source: trunk/klask @ 22

Last change on this file since 22 was 22, checked in by g7moreau, 16 years ago
  • Human Readable Port depend now on the switch model. No anymore hardcore switch hostname !
  • Switch port inter-connection are now add to Portignore in command updatedb. No need to add the portignore directive for each switch in the config file anymore.
  • Property svn:executable set to *
File size: 41.2 KB
Line 
1#!/usr/bin/perl -w
2
3use strict;
4use warnings;
5
6use Net::SNMP;
7use YAML qw(:all);
8use Net::Netmask;
9use Net::CIDR::Lite;
10use NetAddr::IP;
11use Getopt::Long;
12
13# apt-get install snmp fping libnet-cidr-lite-perl libnet-netmask-perl libnet-snmp-perl libnetaddr-ip-perl libyaml-perl
14# libcrypt-des-perl libcrypt-hcesha-perl   libdigest-hmac-perl
15
16my $KLASK_DB_FILE  = '/var/cache/klask/klaskdb';
17my $KLASK_SW_FILE  = '/var/cache/klask/switchdb';
18my $KLASK_CFG_FILE = '/etc/klask.conf';
19
20my $KLASK_CFG = YAML::LoadFile("$KLASK_CFG_FILE");
21
22my %DEFAULT = %{$KLASK_CFG->{default}};
23my @SWITCH  = @{$KLASK_CFG->{switch}};
24
25my %switch_level = ();
26LEVEL_OF_EACH_SWITCH:
27for my $sw (@SWITCH){
28   $switch_level{$sw->{hostname}} = $sw->{level} || $DEFAULT{switch_level}  || 2;
29   }
30@SWITCH = sort { $switch_level{$b->{hostname}} <=> $switch_level{$a->{hostname}} } @{$KLASK_CFG->{switch}}; 
31
32my %SWITCH_PORT_COUNT = ();
33
34my %CMD_DB = (
35   help       => \&cmd_help,
36   exportdb   => \&cmd_exportdb,
37   updatedb   => \&cmd_updatedb,
38   searchdb   => \&cmd_searchdb,
39   removedb   => \&cmd_removedb,
40   search     => \&cmd_search,
41   enable     => \&cmd_enable,
42   disable    => \&cmd_disable,
43   status     => \&cmd_status,
44   updatesw   => \&cmd_updatesw,
45   exportsw   => \&cmd_exportsw,
46   dotsw      => \&cmd_exportsw_dot,
47   iplocation => \&cmd_iplocation,
48   );
49
50my %INTERNAL_PORT_MAP = (
51   0 => 'A',
52   1 => 'B',
53   2 => 'C',
54   3 => 'D',
55   4 => 'E',
56   5 => 'F',
57   6 => 'G',
58   7 => 'H',
59   );
60my %INTERNAL_PORT_MAP_REV = reverse %INTERNAL_PORT_MAP;
61
62my %SWITCH_KIND = (
63   J3299A => { model => 'HP224M',     match => 'HP J3299A ProCurve Switch 224M'  },
64   J4120A => { model => 'HP1600M',    match => 'HP J4120A ProCurve Switch 1600M' },
65   J4093A => { model => 'HP2424M',    match => 'HP J4093A ProCurve Switch 2424M' },
66   J4813A => { model => 'HP2524',     match => 'HP J4813A ProCurve Switch 2524'  },
67   J4900A => { model => 'HP2626A',    match => 'HP J4900A ProCurve Switch 2626'  },
68   J4900B => { model => 'HP2626B',    match => 'HP J4900B ProCurve Switch 2626'  },
69   J9021A => { model => 'HP2810-24G', match => 'ProCurve J9021A Switch 2810-24G' },
70   J4903A => { model => 'HP2824',     match => 'J4903A.+?Switch 2824,'           },
71   J4110A => { model => 'HP8000M',    match => 'HP J4110A ProCurve Switch 8000M' },
72   BS350T => { model => 'BS350T',     match => 'BayStack 350T HW'                },
73   );
74 
75my %OID_NUMBER = (
76   sysDescr    => '1.3.6.1.2.1.1.1.0',
77   sysName     => '1.3.6.1.2.1.1.5.0',
78   sysContact  => '1.3.6.1.2.1.1.4.0',
79   sysLocation => '1.3.6.1.2.1.1.6.0',
80   );
81
82################
83# principal
84################
85
86my $cmd = shift @ARGV || 'help';
87if (defined $CMD_DB{$cmd}) {
88   $CMD_DB{$cmd}->(@ARGV);
89   }
90else {
91   print STDERR "klask: command $cmd not found\n\n";
92   $CMD_DB{help}->();
93   exit 1;
94   }
95
96exit;
97
98###
99# fast ping dont l'objectif est de remplir la table arp de la machine
100sub fastping {
101   system "fping -c 1 @_ >/dev/null 2>&1";
102   }
103
104###
105# donne l'@ ip, dns, arp en fonction du dns OU de l'ip
106sub resolve_ip_arp_host {
107   my $param_ip_or_host = shift;
108   my $interface = shift || '*';
109   my $type      = shift || 'fast';
110
111   my %ret = (
112      hostname_fq  => 'unknow',
113      ipv4_address => '0.0.0.0',
114      mac_address  => 'unknow',
115      );
116
117#   my $cmdarping  = `arping -c 1 -w 1 -rR $param 2>/dev/null`;
118
119   # controler que arpwatch tourne !
120   # resultat de la commande arpwatch
121   # /var/lib/arpwatch/arp.dat
122   # 0:13:d3:e1:92:d0        192.168.24.109  1163681980      theo8sv109
123   #my $cmd = "grep  -e '".'\b'."$param_ip_or_host".'\b'."' /var/lib/arpwatch/arp.dat | sort +2rn | head -1";
124#   my $cmd = "grep  -he '".'\b'."$param_ip_or_host".'\b'."' /var/lib/arpwatch/*.dat | sort +2rn | head -1";
125   my $cmd = "grep  -he '".'\b'."$param_ip_or_host".'\b'."' /var/lib/arpwatch/$interface.dat | sort +2rn | head -1";
126   my $cmd_arpwatch = `$cmd`;
127   chomp $cmd_arpwatch;
128   my ($arp, $ip, $timestamp, $host) = split /\s+/, $cmd_arpwatch;
129#print "OOO $cmd\n";
130#print "TTT arp $arp -> $ip pour host $host\n";
131   $ret{ipv4_address} = $ip        if $ip;
132   $ret{mac_address}  = $arp       if $arp;
133   $ret{timestamp}    = $timestamp if $timestamp;
134
135   my $nowtimestamp = time();
136
137   if ( $type eq 'fast' and ( not defined $timestamp or $timestamp < ( $nowtimestamp - 3 * 3600 ) ) ) {
138      $ret{mac_address} = 'unknow';
139      return %ret;
140      }
141
142  # resultat de la commande arp
143   # tech7meylan.hmg.inpg.fr (194.254.66.240) at 00:14:22:45:28:A9 [ether] on eth0
144   my $cmd_arp  = `arp -a $param_ip_or_host 2>/dev/null`;
145   chomp $cmd_arp;
146   $cmd_arp =~ /(\S*)\s\(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\)\sat\s([0-9,A-Z]{2}:[0-9,A-Z]{2}:[0-9,A-Z]{2}:[0-9,A-Z]{2}:[0-9,A-Z]{2}:[0-9,A-Z]{2})/;
147   $ret{hostname_fq}  = $1 if(defined($1));
148   $ret{ipv4_address} = $2 if(defined($2));
149   $ret{mac_address}  = $3 if(defined($3));
150
151#   if ($ret{ipv4_address} eq '0.0.0.0' and $ret{mac_address} eq 'unknow'and $ret{hostname_fq} eq 'unknow') {
152      # resultat de la commande host si le parametre est ip
153      # 250.66.254.194.in-addr.arpa domain name pointer legihp2100.hmg.inpg.fr.
154      my $cmd_host = `host $param_ip_or_host 2>/dev/null`;
155      chomp $cmd_host;
156      $cmd_host =~ m/domain\sname\spointer\s(\S+)\.$/;
157      $ret{hostname_fq} = $1 if defined $1;
158
159      # resultat de la commande host si parametre est hostname
160      # tech7meylan.hmg.inpg.fr has address 194.254.66.240
161      $cmd_host =~ m/\shas\saddress\s([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$/;
162      $ret{ipv4_address} = $1 if defined $1;
163
164      $cmd_host =~ m/\b([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.in-addr\.arpa\s/;
165      $ret{ipv4_address} = "$4.$3.$2.$1"     if defined $1 and  defined $2 and  defined $3 and  defined $4;
166      $ret{hostname_fq}  = $param_ip_or_host if not defined $1 and $ret{hostname_fq} eq 'unknow';
167#      }
168
169   unless ($ret{mac_address} eq 'unknow') {
170      my @paquets = ();
171      foreach ( split(/:/, $ret{mac_address}) ) {
172         my @chars = split //, uc("00$_");
173         push @paquets, "$chars[-2]$chars[-1]";
174         }
175      $ret{mac_address} = join ':', @paquets;
176      }
177
178   return %ret;
179   }
180
181# Find Surname of a switch
182sub get_switch_model {
183   my $sw_snmp_description = shift || 'unknow';
184   
185   for my $sw_kind (keys %SWITCH_KIND) {
186      next if not $sw_snmp_description =~ m/$SWITCH_KIND{$sw_kind}->{match}/;
187     
188      return $SWITCH_KIND{$sw_kind}->{model};
189      }
190     
191   return $sw_snmp_description;
192   }
193
194###
195# va rechercher le nom des switchs pour savoir qui est qui
196sub init_switch_names {
197   my $verbose = shift;
198   
199   printf "%-25s                %-25s %s\n",'Switch','Description','Type';
200#   print "Switch description\n" if $verbose;
201   print "-------------------------------------------------------------------------\n" if $verbose;
202
203   INIT_EACH_SWITCH:
204   for my $sw (@SWITCH) {
205      my %session = ( -hostname   => $sw->{hostname} );
206         $session{-version} = $sw->{version}   || 1;
207         $session{-port}    = $sw->{snmpport}  || $DEFAULT{snmpport}  || 161;
208         if (exists $sw->{version} and $sw->{version} eq 3) {
209            $session{-username} = $sw->{username} || 'snmpadmin';
210            }
211         else {
212            $session{-community} = $sw->{community} || $DEFAULT{community} || 'public';
213            }
214
215      $sw->{local_session} = \%session;
216
217      my ($session, $error) = Net::SNMP->session( %{$sw->{local_session}} );
218      print "$error \n" if $error;
219
220      my $result = $session->get_request(
221         -varbindlist => [
222            $OID_NUMBER{sysDescr},
223            $OID_NUMBER{sysName},
224            $OID_NUMBER{sysContact},
225            $OID_NUMBER{sysLocation},
226            ]
227         );
228      $sw->{description} = $result->{$OID_NUMBER{sysName}} || $sw->{hostname};
229      $sw->{model} = get_switch_model( $result->{$OID_NUMBER{sysDescr}});
230      #$sw->{location} = $result->{"1.3.6.1.2.1.1.6.0"} || $sw->{hostname};
231      #$sw->{contact} = $result->{"1.3.6.1.2.1.1.4.0"} || $sw->{hostname};
232      $session->close;
233
234      # Ligne à virer car on récupère maintenant le modèle du switch
235      my ($desc, $type) = split ':', $sw->{description}, 2;
236#      printf "%-25s 0--------->>>> %-25s %s\n", $sw->{hostname}, $desc, uc($type)."**" if $verbose;
237      printf "%-25s 0--------->>>> %-25s %s\n", $sw->{hostname}, $desc, $sw->{model} if $verbose;
238      }
239
240   print "\n" if $verbose;
241   }
242
243###
244# convertit l'hexa (uniquement 2 chiffres) en decimal
245sub hex_to_dec {
246   #00:0F:1F:43:E4:2B
247   my $car = '00' . uc(shift);
248
249   return '00' if $car eq '00UNKNOW';
250   my %table = (
251      "0"=>"0",  "1"=>"1",  "2"=>"2",  "3"=>"3",  "4"=>"4",  "5"=>"5", "6"=>"6", "7"=>"7", "8"=>"8", "9"=>"9",
252      "A"=>"10", "B"=>"11", "C"=>"12", "D"=>"13", "E"=>"14", "F"=>"15"
253      );
254   my @chars = split(//, $car);
255   return $table{$chars[-2]}*16 + $table{$chars[-1]};
256   }
257
258###
259# convertit l'@ arp en decimal
260sub arp_hex_to_dec {
261   #00:0F:1F:43:E4:2B
262   my $arp = shift;
263
264   my @paquets = split /:/, $arp;
265   my $return = '';
266   foreach(@paquets) {
267      $return .= ".".hex_to_dec($_);
268      }
269   return $return;
270   }
271
272###
273# va rechercher le port et le switch sur lequel est la machine
274sub find_switch_port {
275   my $arp = shift;
276   my $switch_proposal = shift || '';
277   
278   my %ret;
279   $ret{switch_description} = "unknow";
280   $ret{switch_port} = "0";
281
282   return %ret if $arp eq 'unknow';;
283
284   my @switch_search = @SWITCH;
285   if ($switch_proposal ne '') {
286      for my $sw (@SWITCH) {
287         next if $sw->{hostname} ne $switch_proposal;
288         unshift @switch_search, $sw;
289         last;
290         }
291      }
292
293   my $research = "1.3.6.1.2.1.17.4.3.1.2".arp_hex_to_dec($arp);
294   
295   LOOP_ON_SWITCH:
296   for my $sw (@switch_search) {
297      my ($session, $error) = Net::SNMP->session( %{$sw->{local_session}} );
298      print "$error \n" if $error;
299
300      my $result = $session->get_request(
301         -varbindlist => [$research]
302         );
303      if (not defined($result) or $result->{$research} eq 'noSuchInstance') {
304         $session->close;
305         next LOOP_ON_SWITCH;
306         }
307
308         my $swport = $result->{$research};
309         $session->close;
310
311         # IMPORTANT !!
312         # ceci empeche la detection sur certains port ...
313         # en effet les switch sont relies entre eux par un cable reseau et du coup
314         # tous les arp de toutes les machines sont presentes sur ces ports (ceux choisis ici sont les miens)
315         # cette partie est a ameliore, voir a configurer dans l'entete
316         # 21->24 45->48
317#         my $flag = 0;
318         SWITCH_PORT_IGNORE:
319         foreach my $p (@{$sw->{portignore}}) {
320            next SWITCH_PORT_IGNORE if $swport ne get_numerical_port($sw->{model},$p);
321#            $flag = 1;
322            next LOOP_ON_SWITCH;
323            }
324#         if ($flag == 0) {
325            $ret{switch_hostname}    = $sw->{hostname};
326            $ret{switch_description} = $sw->{description};
327            $ret{switch_port}        = get_human_readable_port($sw->{model}, $swport); # $swport;
328           
329            last LOOP_ON_SWITCH;
330#            }
331#         }
332#      $session->close;
333      }
334   return %ret;
335   }
336
337###
338# va rechercher les port et les switch sur lequel est la machine
339sub find_all_switch_port {
340   my $arp = shift;
341
342   my $ret = {};
343
344   return $ret if $arp eq 'unknow';
345
346   for my $sw (@SWITCH) {
347      $SWITCH_PORT_COUNT{$sw->{hostname}} = {} if not exists $SWITCH_PORT_COUNT{$sw->{hostname}};
348      }
349
350   my $research = "1.3.6.1.2.1.17.4.3.1.2".arp_hex_to_dec($arp);
351   LOOP_ON_ALL_SWITCH:
352   for my $sw (@SWITCH) {
353      my ($session, $error) = Net::SNMP->session( %{$sw->{local_session}} );
354      print "$error \n" if $error;
355
356      my $result = $session->get_request(
357         -varbindlist => [$research]
358         );
359
360      if(defined($result) and $result->{$research} ne 'noSuchInstance'){
361         my $swport = $result->{$research};
362
363         $ret->{$sw->{hostname}} = {};
364         $ret->{$sw->{hostname}}{hostname}    = $sw->{hostname};
365         $ret->{$sw->{hostname}}{description} = $sw->{description};
366         $ret->{$sw->{hostname}}{port}        = get_human_readable_port($sw->{model}, $swport);
367
368         $SWITCH_PORT_COUNT{$sw->{hostname}}->{$swport}++;
369         }
370
371      $session->close;
372      }
373   return $ret;
374   }
375
376sub get_list_network {
377
378   return keys %{$KLASK_CFG->{network}};
379   }
380
381sub get_current_interface {
382   my $network = shift;
383
384   return $KLASK_CFG->{network}{$network}{interface};
385   }
386 
387###
388# liste l'ensemble des adresses ip d'un réseau
389sub get_list_ip {
390   my @network = @_;
391
392   my $cidrlist = Net::CIDR::Lite->new;
393
394   for my $net (@network) {
395      my @line  = @{$KLASK_CFG->{network}{$net}{'ip-subnet'}};
396      for my $cmd (@line) {
397         for my $method (keys %$cmd){
398            $cidrlist->add_any($cmd->{$method}) if $method eq 'add';
399            }
400         }
401      }
402
403   my @res = ();
404
405   for my $cidr ($cidrlist->list()) {
406      my $net = new NetAddr::IP $cidr;
407      for my $ip (@$net) {
408         $ip =~ s#/32##;
409         push @res,  $ip;
410         }
411      }
412
413   return @res;
414   }
415
416# liste l'ensemble des routeurs du réseau
417sub get_list_main_router {
418   my @network = @_;
419
420   my @res = ();
421
422   for my $net (@network) {
423      push @res, $KLASK_CFG->{network}{$net}{'main-router'};
424      }
425
426   return @res;
427   }
428
429sub get_human_readable_port {
430   my $sw_model = shift;
431   my $sw_port  = shift;
432   
433   return $sw_port if not $sw_model eq 'HP8000M';
434   
435   my $reste = (($sw_port - 1) % 8) + 1;
436   my $major = int( ($sw_port - 1) / 8 );
437
438   return "$INTERNAL_PORT_MAP{$major}$reste";
439   }
440
441sub get_numerical_port {
442   my $sw_model = shift;
443   my $sw_port  = shift;
444   
445   return $sw_port if not $sw_model eq 'HP8000';
446
447   my $letter = substr($sw_port, 0, 1);
448   
449#   return $port if $letter =~ m/\d/;
450   
451   my $reste =  substr($sw_port, 1);
452   
453   return $INTERNAL_PORT_MAP_REV{$letter} * 8 + $reste;
454   }
455
456################
457# Les commandes
458################
459
460sub cmd_help {
461
462print <<END;
463klask - ports manager and finder for switch
464
465 klask updatedb
466 klask exportdf
467
468 klask searchdb computer
469 klask search   computer
470
471 klask enable  switch port
472 klask disable switch port
473 klask status  switch port
474END
475   }
476
477sub cmd_search {
478   my @computer = @_;
479   
480   init_switch_names();    #nomme les switchs
481   fastping(@computer);
482   for my $clientname (@computer) {
483      my %resol_arp = resolve_ip_arp_host($clientname);          #resolution arp
484      my %where     = find_switch_port($resol_arp{mac_address}); #retrouve l'emplacement
485      printf "%-22s %2i %-30s %-15s %18s", $where{switch_description}, $where{switch_port}, $resol_arp{hostname_fq}, $resol_arp{ipv4_address}, $resol_arp{mac_address}."\n"
486         unless $where{switch_description} eq 'unknow' and $resol_arp{hostname_fq} eq 'unknow' and $resol_arp{mac_address} eq 'unknow';
487      }
488   }
489
490sub cmd_searchdb {
491   my @computer = @_;
492
493   fastping(@computer);
494   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
495   
496   LOOP_ON_COMPUTER:
497   for my $clientname (@computer) {
498      my %resol_arp = resolve_ip_arp_host($clientname);      #resolution arp
499      my $ip = $resol_arp{ipv4_address};
500     
501      next LOOP_ON_COMPUTER unless exists $computerdb->{$ip};
502     
503      my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($computerdb->{$ip}{timestamp});
504      $year += 1900;
505      $mon++;
506      my $date = sprintf "%04i-%02i-%02i %02i:%02i", $year,$mon,$mday,$hour,$min;
507
508      printf "%-22s %2s %-30s %-15s %-18s %s\n",
509         $computerdb->{$ip}{switch_name},
510         $computerdb->{$ip}{switch_port},
511         $computerdb->{$ip}{hostname_fq},
512         $ip,
513         $computerdb->{$ip}{mac_address},
514         $date;
515      }
516   }
517
518sub cmd_updatedb {
519   my @network = @_;
520      @network = get_list_network() if not @network;
521
522   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
523   my $timestamp = time;
524
525   my %computer_not_detected = ();
526   my $timestamp_last_week = $timestamp - (3600 * 24 * 7);
527
528   my $number_of_computer = get_list_ip(@network); # + 1;
529   my $size_of_database   = keys %$computerdb;
530   my $i = 0;
531   my $detected_computer = 0;
532
533   init_switch_names('yes');    #nomme les switchs
534
535   { # Remplis le champs portignore des ports d'inter-connection pour chaque switch
536   my $switch_connection = YAML::LoadFile("$KLASK_SW_FILE");
537   my %db_switch_output_port       = %{$switch_connection->{output_port}};
538   my %db_switch_connected_on_port = %{$switch_connection->{connected_on_port}};
539   my %db_switch_chained_port = ();
540   for my $swport (keys %db_switch_connected_on_port) {       
541      my ($sw_connect,$port_connect) = split ':', $swport;
542      $db_switch_chained_port{$sw_connect} .= "$port_connect:";
543      }
544   for my $sw (@SWITCH){
545      push @{$sw->{portignore}}, $db_switch_output_port{$sw->{hostname}}  if exists $db_switch_output_port{$sw->{hostname}};
546      if ( exists $db_switch_chained_port{$sw->{hostname}} ) {
547         chop $db_switch_chained_port{$sw->{hostname}};
548         push @{$sw->{portignore}}, split(':',$db_switch_chained_port{$sw->{hostname}});
549         }
550#      print "$sw->{hostname} ++ @{$sw->{portignore}}\n";
551      }
552   }
553
554   my %router_mac_ip = ();
555   DETECT_ALL_ROUTER:
556#   for my $one_router ('194.254.66.254') {
557   for my $one_router ( get_list_main_router(@network) ) {
558      my %resol_arp = resolve_ip_arp_host($one_router);
559      $router_mac_ip{ $resol_arp{mac_address} } = $resol_arp{ipv4_address};
560      }
561
562   ALL_NETWORK:
563   for my $net (@network) {
564
565      my @computer = get_list_ip($net);
566      my $current_interface = get_current_interface($net);
567
568      fastping(@computer);
569
570      LOOP_ON_COMPUTER:
571      for my $one_computer (@computer) {
572         $i++;
573         
574         my $total_percent = int(($i*100)/$number_of_computer);
575
576         my $localtime = time - $timestamp;
577         my ($sec,$min) = localtime($localtime);
578
579         my $time_elapse = 0;
580            $time_elapse = $localtime * ( 100 - $total_percent) / $total_percent if $total_percent != 0;
581         my ($sec_elapse,$min_elapse) = localtime($time_elapse);
582
583         printf "\rComputer scanned: %4i/%i (%2i%%)",  $i,                 $number_of_computer, $total_percent;
584#         printf ", Computer detected: %4i/%i (%2i%%)", $detected_computer, $size_of_database,   int(($detected_computer*100)/$size_of_database);
585         printf ", detected: %4i/%i (%2i%%)", $detected_computer, $size_of_database,   int(($detected_computer*100)/$size_of_database);
586         printf " [Time: %02i:%02i / %02i:%02i]", int($localtime/60), $localtime % 60, int($time_elapse/60), $time_elapse % 60;
587#         printf "  [%02i:%02i/%02i:%02i]", int($localtime/60), $localtime % 60, int($time_elapse/60), $time_elapse % 60;
588         printf " %-14s", $one_computer;
589
590         my %resol_arp = resolve_ip_arp_host($one_computer,$current_interface);
591         
592         # do not search on router connection (why ?)
593         if ( exists $router_mac_ip{$resol_arp{mac_address}}) {
594            $computer_not_detected{$one_computer} = $current_interface;
595            next LOOP_ON_COMPUTER;
596            }
597
598         # do not search on switch inter-connection
599         if (exists $switch_level{$resol_arp{hostname_fq}}) {
600            $computer_not_detected{$one_computer} = $current_interface;
601            next LOOP_ON_COMPUTER;
602            }
603
604         my $switch_proposal = '';
605         if (exists $computerdb->{$resol_arp{ipv4_address}} and exists $computerdb->{$resol_arp{ipv4_address}}{switch_hostname}) {
606            $switch_proposal = $computerdb->{$resol_arp{ipv4_address}}{switch_hostname};
607            }
608
609         # do not have a mac address
610         if ($resol_arp{mac_address} eq 'unknow' or (exists $resol_arp{timestamps} and $resol_arp{timestamps} < ($timestamp - 3 * 3600))) {
611            $computer_not_detected{$one_computer} = $current_interface;
612            next LOOP_ON_COMPUTER;
613            }
614
615         my %where = find_switch_port($resol_arp{mac_address},$switch_proposal);
616
617         #192.168.24.156:
618         #  arp: 00:0B:DB:D5:F6:65
619         #  hostname: pcroyon.hmg.priv
620         #  port: 5
621         #  switch: sw-batH-legi:hp2524
622         #  timestamp: 1164355525
623
624         # do not have a mac address
625#         if ($resol_arp{mac_address} eq 'unknow') {
626#            $computer_not_detected{$one_computer} = $current_interface;
627#            next LOOP_ON_COMPUTER;
628#            }
629
630         # detected on a switch
631         if ($where{switch_description} ne 'unknow') {
632            $detected_computer++;
633            $computerdb->{$resol_arp{ipv4_address}} = {
634               hostname_fq        => $resol_arp{hostname_fq},
635               mac_address        => $resol_arp{mac_address},
636               switch_hostname    => $where{switch_hostname},
637               switch_description => $where{switch_description},
638               switch_port        => $where{switch_port},
639               timestamp          => $timestamp,
640               };
641            next LOOP_ON_COMPUTER;
642            }
643
644         # new in the database but where it is ?
645         if (not exists $computerdb->{$resol_arp{ipv4_address}}) {
646            $detected_computer++;
647            $computerdb->{$resol_arp{ipv4_address}} = {
648               hostname_fq        => $resol_arp{hostname_fq},
649               mac_address        => $resol_arp{mac_address},
650               switch_hostname    => $where{switch_hostname},
651               switch_description => $where{switch_description},
652               switch_port        => $where{switch_port},
653               timestamp          => $resol_arp{timestamp},
654               };
655            }
656
657         # mise a jour du nom de la machine si modification dans le dns
658         $computerdb->{$resol_arp{ipv4_address}}{hostname_fq} = $resol_arp{hostname_fq};
659       
660         # mise à jour de la date de détection si détection plus récente par arpwatch
661         $computerdb->{$resol_arp{ipv4_address}}{timestamp}   = $resol_arp{timestamp} if exists $resol_arp{timestamp} and $computerdb->{$resol_arp{ipv4_address}}{timestamp} < $resol_arp{timestamp};
662
663         # provisoire car changement de nom des attributs
664#         $computerdb->{$resol_arp{ipv4_address}}{mac_address}        = $computerdb->{$resol_arp{ipv4_address}}{arp};
665#         $computerdb->{$resol_arp{ipv4_address}}{switch_description} = $computerdb->{$resol_arp{ipv4_address}}{switch};
666#         $computerdb->{$resol_arp{ipv4_address}}{switch_port}        = $computerdb->{$resol_arp{ipv4_address}}{port};
667       
668         # relance un arping sur la machine si celle-ci n'a pas été détectée depuis plus d'une semaine
669#         push @computer_not_detected, $resol_arp{ipv4_address} if $computerdb->{$resol_arp{ipv4_address}}{timestamp} < $timestamp_last_week;
670         $computer_not_detected{$resol_arp{ipv4_address}} = $current_interface if $computerdb->{$resol_arp{ipv4_address}}{timestamp} < $timestamp_last_week;
671       
672         }
673      }
674
675   # final end of line at the end of the loop
676   printf "\n";
677
678   my $dirdb = $KLASK_DB_FILE;
679      $dirdb =~ s#/[^/]*$##;
680   mkdir "$dirdb", 0755 unless -d "$dirdb";
681   YAML::DumpFile("$KLASK_DB_FILE", $computerdb);
682
683   for my $one_computer (keys %computer_not_detected) {
684      my $interface = $computer_not_detected{$one_computer};
685      system "arping -c 1 -w 1 -rR -i $interface $one_computer &>/dev/null";
686#      print  "arping -c 1 -w 1 -rR -i $interface $one_computer 2>/dev/null\n";
687      }
688   }
689
690sub cmd_removedb {
691   my @computer = @_;
692   
693   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
694
695   LOOP_ON_COMPUTER:
696   for my $one_computer (@computer) {
697
698      my %resol_arp = resolve_ip_arp_host($one_computer);
699
700      delete $computerdb->{$resol_arp{ipv4_address}} if exists $computerdb->{$resol_arp{ipv4_address}};
701      }
702
703   my $dirdb = $KLASK_DB_FILE;
704      $dirdb =~ s#/[^/]*$##;
705   mkdir "$dirdb", 0755 unless -d "$dirdb";
706   YAML::DumpFile("$KLASK_DB_FILE", $computerdb);
707   }
708
709sub cmd_exportdb {
710   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
711
712   printf "%-24s %-4s            %-30s %-15s %-18s %-s\n", qw(Switch Port Hostname IPv4-Address MAC-Address Date);
713   print "---------------------------------------------------------------------------------------------------------------------------\n";
714
715   LOOP_ON_IP_ADDRESS:
716   foreach my $ip (Net::Netmask::sort_by_ip_address(keys %$computerdb)) {
717   
718#      next LOOP_ON_IP_ADDRESS if $computerdb->{$ip}{hostname_fq} eq 'unknow';
719
720      # to be improve in the future
721      next LOOP_ON_IP_ADDRESS if $computerdb->{$ip}{hostname_fq} eq ($computerdb->{$ip}{switch_hostname} || $computerdb->{$ip}{switch_description}); # switch on himself !
722
723# dans le futur
724#      next if $computerdb->{$ip}{hostname_fq} eq 'unknow';
725     
726      my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($computerdb->{$ip}{timestamp});
727      $year += 1900;
728      $mon++;
729      my $date = sprintf "%04i-%02i-%02i %02i:%02i", $year,$mon,$mday,$hour,$min;
730
731      printf "%-25s  %2s  <-------  %-30s %-15s %-18s %s\n",
732         $computerdb->{$ip}{switch_hostname} || $computerdb->{$ip}{switch_description},
733         $computerdb->{$ip}{switch_port},
734         $computerdb->{$ip}{hostname_fq},
735         $ip,
736         $computerdb->{$ip}{mac_address},
737         $date;
738      }
739   }
740
741sub cmd_iplocation {
742   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
743
744   LOOP_ON_IP_ADDRESS:
745   foreach my $ip (Net::Netmask::sort_by_ip_address(keys %$computerdb)) {
746
747      next LOOP_ON_IP_ADDRESS if $computerdb->{$ip}{hostname_fq} eq ($computerdb->{$ip}{switch_hostname} || $computerdb->{$ip}{switch_description}); # switch on himself !
748
749      my $sw_hostname = $computerdb->{$ip}{switch_hostname} || '';
750      next if $sw_hostname eq 'unknow';
751 
752      my $sw_location = '';
753      for my $sw (@SWITCH) {
754         next if $sw_hostname ne $sw->{hostname};
755         $sw_location = $sw->{location};
756         last;
757         }
758
759      printf "%s: \"%s\"\n", $ip, $sw_location if not $sw_location eq '';
760      }
761   }
762
763sub cmd_enable {
764   my $switch = shift;
765   my $port   = shift;
766   
767   #snmpset -v 1 -c community X.X.X.X 1.3.6.1.2.1.2.2.1.7.NoPort = 1 (up)
768   #snmpset -v 1 -c community X.X.X.X 1.3.6.1.2.1.2.2.1.7.NoPort = 2 (down)
769   system "snmpset -v 1 -c public $switch 1.3.6.1.2.1.2.2.1.7.$port = 1";
770   }
771
772sub cmd_disable {
773   my $switch = shift;
774   my $port   = shift;
775   
776   system "snmpset -v 1 -c public $switch 1.3.6.1.2.1.2.2.1.7.$port = 2";
777   }
778
779sub cmd_status {
780   my $switch = shift;
781   my $port   = shift;
782   
783   system "snmpget -v 1 -c public $switch 1.3.6.1.2.1.2.2.1.7.$port";
784   }
785
786
787sub cmd_updatesw {
788
789   init_switch_names('yes');    #nomme les switchs
790   print "\n";
791
792   my %where = ();
793   my %db_switch_output_port = ();
794   my %db_switch_ip_hostname = ();
795
796   DETECT_ALL_ROUTER:
797#   for my $one_computer ('194.254.66.254') {
798   for my $one_router ( get_list_main_router(get_list_network()) ) {
799      my %resol_arp = resolve_ip_arp_host($one_router,'*','low');            # resolution arp
800      next DETECT_ALL_ROUTER if $resol_arp{mac_address} eq 'unknow';
801     
802      $where{$resol_arp{ipv4_address}} = find_all_switch_port($resol_arp{mac_address}); # retrouve les emplacements des routeurs
803      }
804
805   ALL_ROUTER_IP_ADDRESS:
806   for my $ip (Net::Netmask::sort_by_ip_address(keys %where)) { # '194.254.66.254')) {
807   
808      next ALL_ROUTER_IP_ADDRESS if not exists $where{$ip}; # /a priori/ idiot car ne sers à rien...
809
810      ALL_SWITCH_CONNECTED:
811      for my $switch_detected ( keys %{$where{$ip}} ) {
812
813         my $switch = $where{$ip}->{$switch_detected};
814
815         next ALL_SWITCH_CONNECTED if $switch->{port} eq '0';
816         
817         $db_switch_output_port{$switch->{hostname}} = $switch->{port};
818         }
819      }   
820
821#   print "Switch output port\n"; 
822#   print "------------------\n";
823#   for my $sw (sort keys %db_switch_output_port) {
824#      printf "%-25s %2s\n", $sw, $db_switch_output_port{$sw};
825#      }
826#   print "\n";
827
828
829   my %db_switch_link_with = ();
830
831   my @list_switch_ip = ();
832   my @list_switch_ipv4 = ();
833   for my $sw (@SWITCH){
834      push @list_switch_ip, $sw->{hostname};
835      }
836
837   ALL_SWITCH:
838   for my $one_computer (@list_switch_ip) {
839      my %resol_arp = resolve_ip_arp_host($one_computer,'*','low'); # arp resolution
840      next ALL_SWITCH if $resol_arp{mac_address} eq 'unknow';
841     
842      push @list_switch_ipv4,$resol_arp{ipv4_address};
843     
844      $where{$resol_arp{ipv4_address}} = find_all_switch_port($resol_arp{mac_address}); # find port on all switch
845
846      $db_switch_ip_hostname{$resol_arp{ipv4_address}} = $resol_arp{hostname_fq};
847      }
848     
849   ALL_SWITCH_IP_ADDRESS:
850   for my $ip (Net::Netmask::sort_by_ip_address(@list_switch_ipv4)) {
851   
852      next ALL_SWITCH_IP_ADDRESS if not exists $where{$ip};
853
854      DETECTED_SWITCH:
855      for my $switch_detected ( keys %{$where{$ip}} ) {
856
857         next DETECTED_SWITCH if not exists $SWITCH_PORT_COUNT{ $db_switch_ip_hostname{$ip}};
858
859         my $switch = $where{$ip}->{$switch_detected};
860
861         next if $switch->{port}     eq '0';
862         next if $switch->{port}     eq $db_switch_output_port{$switch->{hostname}};
863         next if $switch->{hostname} eq $db_switch_ip_hostname{$ip}; # $computerdb->{$ip}{hostname};
864
865         $db_switch_link_with{ $db_switch_ip_hostname{$ip} } ||= {};
866         $db_switch_link_with{ $db_switch_ip_hostname{$ip} }->{ $switch->{hostname} } = $switch->{port};
867         }
868
869      }
870   
871   my %db_switch_connected_on_port = ();
872   my $maybe_more_than_one_switch_connected = 'yes';
873   
874   while ($maybe_more_than_one_switch_connected eq 'yes') {
875      for my $sw (keys %db_switch_link_with) {
876         for my $connect (keys %{$db_switch_link_with{$sw}}) {
877         
878            my $port = $db_switch_link_with{$sw}->{$connect};
879         
880            $db_switch_connected_on_port{"$connect:$port"} ||= {};
881            $db_switch_connected_on_port{"$connect:$port"}->{$sw}++; # Just to define the key
882            }
883         }
884
885      $maybe_more_than_one_switch_connected  = 'no';
886
887      SWITCH_AND_PORT:
888      for my $swport (keys %db_switch_connected_on_port) {
889         
890         next if keys %{$db_switch_connected_on_port{$swport}} == 1;
891         
892         $maybe_more_than_one_switch_connected = 'yes';
893
894         my ($sw_connect,$port_connect) = split ':', $swport;
895         my @sw_on_same_port = keys %{$db_switch_connected_on_port{$swport}};
896
897         CONNECTED:
898         for my $sw_connected (@sw_on_same_port) {
899           
900            next CONNECTED if not keys %{$db_switch_link_with{$sw_connected}} == 1;
901           
902            $db_switch_connected_on_port{$swport} = {$sw_connected => 1};
903           
904            for my $other_sw (@sw_on_same_port) {
905               next if $other_sw eq $sw_connected;
906               
907               delete $db_switch_link_with{$other_sw}->{$sw_connect};
908               }
909           
910            # We can not do better for this switch for this loop
911            next SWITCH_AND_PORT;
912            }
913         }
914      }
915
916   my %db_switch_parent =();
917
918   for my $sw (keys %db_switch_link_with) {
919      for my $connect (keys %{$db_switch_link_with{$sw}}) {
920     
921         my $port = $db_switch_link_with{$sw}->{$connect};
922     
923         $db_switch_connected_on_port{"$connect:$port"} ||= {};
924         $db_switch_connected_on_port{"$connect:$port"}->{$sw} = $port;
925       
926         $db_switch_parent{$sw} = {switch => $connect, port => $port};
927         }
928      }
929
930   print "Switch output port and parent port connection\n"; 
931   print "---------------------------------------------\n";
932   for my $sw (sort keys %db_switch_output_port) {
933      if (exists $db_switch_parent{$sw}) {
934         printf "%-25s  %2s  +-->  %2s  %-25s\n", $sw, $db_switch_output_port{$sw}, $db_switch_parent{$sw}->{port}, $db_switch_parent{$sw}->{switch};
935         }
936      else {
937         printf "%-25s  %2s  +-->  router\n", $sw, $db_switch_output_port{$sw};
938         }
939      }
940   print "\n";
941
942   print "Switch parent and children port inter-connection\n";
943   print "------------------------------------------------\n";
944   for my $swport (sort keys %db_switch_connected_on_port) {       
945      my ($sw_connect,$port_connect) = split ':', $swport;
946      for my $sw (keys %{$db_switch_connected_on_port{$swport}}) {
947         if (exists $db_switch_output_port{$sw}) {
948            printf "%-25s  %2s  <--+  %2s  %-25s\n", $sw_connect, $port_connect, $db_switch_output_port{$sw}, $sw;
949            }
950         else {
951            printf "%-25s  %2s  <--+      %-25s\n", $sw_connect, $port_connect, $sw;
952            }
953         }
954      }
955
956   my $switch_connection = {
957      output_port       => \%db_switch_output_port,
958      parent            => \%db_switch_parent,
959      connected_on_port => \%db_switch_connected_on_port,
960      link_with         => \%db_switch_link_with,
961      };
962     
963   YAML::DumpFile("$KLASK_SW_FILE", $switch_connection);
964   }
965
966sub cmd_exportsw {
967   my @ARGV   = @_;
968
969   my $format = 'txt';
970
971   my $ret = GetOptions(
972      'format|f=s'  => \$format,
973      );
974
975   my %possible_format = (
976      txt => \&cmd_exportsw_txt,
977      dot => \&cmd_exportsw_dot,
978      );
979
980   $format = 'txt' if not defined $possible_format{$format};
981   
982   $possible_format{$format}->(@ARGV);
983   }
984
985sub cmd_exportsw_txt {
986
987   my $switch_connection = YAML::LoadFile("$KLASK_SW_FILE");
988
989   my %db_switch_output_port       = %{$switch_connection->{output_port}};
990   my %db_switch_parent            = %{$switch_connection->{parent}};
991   my %db_switch_connected_on_port = %{$switch_connection->{connected_on_port}};
992
993   print "Switch output port and parent port connection\n"; 
994   print "---------------------------------------------\n";
995   for my $sw (sort keys %db_switch_output_port) {
996      if (exists $db_switch_parent{$sw}) {
997         printf "%-25s  %2s  +-->  %2s  %-25s\n", $sw, $db_switch_output_port{$sw}, $db_switch_parent{$sw}->{port}, $db_switch_parent{$sw}->{switch};
998         }
999      else {
1000         printf "%-25s  %2s  +-->  router\n", $sw, $db_switch_output_port{$sw};
1001         }
1002      }
1003   print "\n";
1004
1005   print "Switch parent and children port inter-connection\n";
1006   print "------------------------------------------------\n";
1007   for my $swport (sort keys %db_switch_connected_on_port) {       
1008      my ($sw_connect,$port_connect) = split ':', $swport;
1009      for my $sw (keys %{$db_switch_connected_on_port{$swport}}) {
1010         if (exists $db_switch_output_port{$sw}) {
1011            printf "%-25s  %2s  <--+  %2s  %-25s\n", $sw_connect, $port_connect, $db_switch_output_port{$sw}, $sw;
1012            }
1013         else {
1014            printf "%-25s  %2s  <--+      %-25s\n", $sw_connect, $port_connect, $sw;
1015            }
1016         }
1017      }
1018   }
1019
1020sub cmd_exportsw_dot {
1021
1022   my $switch_connection = YAML::LoadFile("$KLASK_SW_FILE");
1023   
1024   my %db_switch_output_port       = %{$switch_connection->{output_port}};
1025   my %db_switch_parent            = %{$switch_connection->{parent}};
1026   my %db_switch_connected_on_port = %{$switch_connection->{connected_on_port}};
1027   my %db_switch_link_with         = %{$switch_connection->{link_with}};
1028     
1029   my %db_building= ();
1030   for my $sw (@SWITCH) {
1031      my ($building, $location) = split /\//, $sw->{location}, 2;
1032      $db_building{$building} ||= {};
1033      $db_building{$building}->{$location} ||= {};
1034      $db_building{$building}->{$location}{ $sw->{hostname} } = 'y';
1035      }
1036 
1037 
1038   print "digraph G {\n";
1039
1040   print "site [label = \"site\", color = black, fillcolor = gold, shape = invhouse, style = filled];\n";
1041   print "internet [label = \"internet\", color = black, fillcolor = cyan, shape = house, style = filled];\n";
1042
1043   my $b=0;
1044   for my $building (keys %db_building) {
1045      $b++;
1046     
1047      print "\"building$b\" [label = \"$building\", color = black, fillcolor = gold, style = filled];\n";
1048      print "site -> \"building$b\" [len = 2, color = firebrick];\n";
1049
1050      my $l = 0;
1051      for my $loc (keys %{$db_building{$building}}) {
1052         $l++;
1053 
1054         print "\"location$b-$l\" [label = \"$building / $loc\", color = black, fillcolor = orange, style = filled];\n";
1055         print "\"building$b\" -> \"location$b-$l\" [len = 2, color = firebrick]\n";
1056
1057         for my $sw (keys %{$db_building{$building}->{$loc}}) {
1058
1059            print "\"$sw:$db_switch_output_port{$sw}\" [label = $db_switch_output_port{$sw}, color = black, fillcolor = lightblue,  peripheries = 2, style = filled];\n";
1060
1061            print "\"$sw\" [label = \"$sw\", color = black, fillcolor = palegreen, shape = rect, style = filled];\n";
1062            print "\"location$b-$l\" -> \"$sw\" [len = 2, color = firebrick, arrowtail = dot]\n";
1063            print "\"$sw\" -> \"$sw:$db_switch_output_port{$sw}\" [len=2, style=bold, arrowhead = normal, arrowtail = invdot]\n";
1064
1065
1066            for my $swport (keys %db_switch_connected_on_port) {
1067               my ($sw_connect,$port_connect) = split ':', $swport;
1068               next if not $sw_connect eq $sw;
1069               next if $port_connect eq $db_switch_output_port{$sw};
1070               print "\"$sw:$port_connect\" [label = $port_connect, color = black, fillcolor = plum,  peripheries = 1, style = filled];\n";
1071               print "\"$sw:$port_connect\" -> \"$sw\" [len=2, style=bold, arrowhead= normal, arrowtail = inv]\n";
1072              }
1073            }
1074         }
1075      }
1076
1077#   print "Switch output port and parent port connection\n"; 
1078#   print "---------------------------------------------\n";
1079   for my $sw (sort keys %db_switch_output_port) {
1080      if (exists $db_switch_parent{$sw}) {
1081#         printf "   \"%s:%s\" -> \"%s:%s\"\n", $sw, $db_switch_output_port{$sw}, $db_switch_parent{$sw}->{switch}, $db_switch_parent{$sw}->{port};
1082         }
1083      else {
1084         printf "   \"%s:%s\" -> internet\n", $sw, $db_switch_output_port{$sw};
1085         }
1086      }
1087   print "\n";
1088
1089#   print "Switch parent and children port inter-connection\n";
1090#   print "------------------------------------------------\n";
1091   for my $swport (sort keys %db_switch_connected_on_port) {       
1092      my ($sw_connect,$port_connect) = split ':', $swport;
1093      for my $sw (keys %{$db_switch_connected_on_port{$swport}}) {
1094         if (exists $db_switch_output_port{$sw}) {
1095            printf "   \"%s:%s\" -> \"%s:%s\" [color = navyblue]\n", $sw, $db_switch_output_port{$sw}, $sw_connect, $port_connect;
1096            }
1097         else {
1098            printf "   \"%s\"   -> \"%s%s\"\n", $sw, $sw_connect, $port_connect;
1099            }
1100         }
1101      }
1102
1103print "}\n";
1104   }
1105
1106
1107__END__
1108
1109
1110=head1 NAME
1111
1112klask - ports manager and finder for switch
1113
1114
1115=head1 SYNOPSIS
1116
1117 klask updatedb
1118 klask exportdb
1119
1120 klask updatesw
1121 klask exportsw --format [txt|dot]
1122
1123 klask searchdb computer
1124 klask search   computer
1125
1126 klask enable  switch port
1127 klask disable swith port
1128 klask status  swith port
1129
1130
1131=head1 DESCRIPTION
1132
1133klask is a small tool to find where is a host in a big network. klask mean search in brittany.
1134
1135Klask has now a web site dedicated for it !
1136
1137 http://servforge.legi.inpg.fr/projects/klask
1138
1139
1140=head1 COMMANDS
1141
1142
1143=head2 search
1144
1145This command takes one or more computer in argument. It search a computer on the network and give the port and the switch on which the computer is connected.
1146
1147
1148=head2 enable
1149
1150This command activate a port on a switch by snmp. So you need to give the switch and the port number on the command line.
1151
1152
1153=head2 disable
1154
1155This command deactivate a port on a switch by snmp. So you need to give the switch and the port number on the command line.
1156
1157
1158=head2 status
1159
1160This command return the status of a port number on a switch by snmp. So you need to give the switch name and the port number on the command line.
1161
1162
1163=head2 updatedb
1164
1165This command will scan networks and update a database. To know which are the cmputer scan, you have to configure the file /etc/klask.conf This file is easy to read and write because klask use YAML format and not XML.
1166
1167
1168=head2 exportdb
1169
1170This command print the content of the database. There is actually only one format. It's very easy to have more format, it's just need times...
1171
1172
1173=head2 updatesw
1174
1175This command build a map of your manageable switch on your network. The list of the switch must be given in the file /etc/klask.conf.
1176
1177
1178=head2 exportsw --format [txt|dot]
1179
1180This command print the content of the switch database. There is actually two format. One is just txt for terminal and the other is the dot format from the graphviz environnement.
1181
1182 klask exportsw --format dot > /tmp/map.dot
1183 dot -Tpng /tmp/map.dot > /tmp/map.png
1184
1185
1186
1187=head1 CONFIGURATION
1188
1189Because klask need many parameters, it's not possible actually to use command line parameters. The configuration is done in a /etc/klask.conf YAML file. This format have many advantage over XML, it's easier to read and to write !
1190
1191Here an example, be aware with indent, it's important in YAML, do not use tabulation !
1192
1193 default:
1194   community: public
1195   snmpport: 161
1196
1197 network:
1198   labnet:
1199     ip-subnet:
1200       - add: 192.168.1.0/24
1201       - add: 192.168.2.0/24
1202     interface: eth0
1203     main-router: gw1.labnet.local
1204
1205   schoolnet:
1206     ip-subnet:
1207       - add: 192.168.6.0/24
1208       - add: 192.168.7.0/24
1209     interface: eth0.38
1210     main-router: gw2.schoolnet.local
1211
1212 switch:
1213   - hostname: sw1.klask.local
1214     portignore:
1215       - 1
1216       - 2
1217
1218   - hostname: sw2.klask.local
1219     location: BatK / 2 / K203
1220     type: HP2424
1221     portignore:
1222       - 1
1223       - 2
1224
1225I think it's pretty easy to understand. The default section can be overide in any section, if parameter mean something in theses sections. Network to be scan are define in the network section. You must put a add by network. Maybe i will make a delete line to suppress specific computers. The switch section define your switch. You have to write the port number to ignore, this is important if your switchs are cascade. Juste put the ports numbers between switch.
1226
1227
1228=head1 FILES
1229
1230 /etc/klask.conf
1231 /var/cache/klask/klaskdb
1232 /var/cache/klask/switchdb
1233
1234=head1 SEE ALSO
1235
1236Net::SNMP, Net::Netmask, Net::CIDR::Lite, NetAddr::IP, YAML
1237
1238
1239=head1 VERSION
1240
12410.4
1242
1243
1244=head1 AUTHOR
1245
1246Written by Gabriel Moreau, Grenoble - France
1247
1248
1249=head1 COPYRIGHT
1250       
1251Copyright (C) 2005-2008 Gabriel Moreau.
1252
1253
1254=head1 LICENCE
1255
1256GPL version 2 or later and Perl equivalent
Note: See TracBrowser for help on using the repository browser.