source: trunk/klask @ 21

Last change on this file since 21 was 21, checked in by g7moreau, 16 years ago
  • Separate switch HP 2626 model A and B in two distinct model
  • Property svn:executable set to *
File size: 40.5 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_description = shift || '?';
184   
185   for my $sw_kind (keys %SWITCH_KIND) {
186      next if not $sw_description =~ m/$SWITCH_KIND{$sw_kind}->{match}/;
187     
188      return $SWITCH_KIND{$sw_kind}->{model};
189      }
190     
191   return $sw_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      my ($desc, $type) = split ':', $sw->{description}, 2;
235#      printf "%-25s 0--------->>>> %-25s %s\n", $sw->{hostname}, $desc, uc($type)."**" if $verbose;
236      printf "%-25s 0--------->>>> %-25s %s\n", $sw->{hostname}, $desc, $sw->{model} if $verbose;
237      }
238
239   print "\n" if $verbose;
240   }
241
242###
243# convertit l'hexa (uniquement 2 chiffres) en decimal
244sub hex_to_dec {
245   #00:0F:1F:43:E4:2B
246   my $car = '00' . uc(shift);
247
248   return '00' if $car eq '00UNKNOW';
249   my %table = (
250      "0"=>"0",  "1"=>"1",  "2"=>"2",  "3"=>"3",  "4"=>"4",  "5"=>"5", "6"=>"6", "7"=>"7", "8"=>"8", "9"=>"9",
251      "A"=>"10", "B"=>"11", "C"=>"12", "D"=>"13", "E"=>"14", "F"=>"15"
252      );
253   my @chars = split(//, $car);
254   return $table{$chars[-2]}*16 + $table{$chars[-1]};
255   }
256
257###
258# convertit l'@ arp en decimal
259sub arp_hex_to_dec {
260   #00:0F:1F:43:E4:2B
261   my $arp = shift;
262
263   my @paquets = split /:/, $arp;
264   my $return = '';
265   foreach(@paquets) {
266      $return .= ".".hex_to_dec($_);
267      }
268   return $return;
269   }
270
271###
272# va rechercher le port et le switch sur lequel est la machine
273sub find_switch_port {
274   my $arp = shift;
275   my $switch_proposal = shift || '';
276   
277   my %ret;
278   $ret{switch_description} = "unknow";
279   $ret{switch_port} = "0";
280
281   return %ret if $arp eq 'unknow';;
282
283   my @SWITCH_search = @SWITCH;
284   if ($switch_proposal ne '') {
285      for my $sw (@SWITCH) {
286         next if $sw->{hostname} ne $switch_proposal;
287         unshift @SWITCH_search, $sw;
288         last;
289         }
290      }
291
292   my $research = "1.3.6.1.2.1.17.4.3.1.2".arp_hex_to_dec($arp);
293   
294   LOOP_ON_SWITCH:
295   for my $sw (@SWITCH_search) {
296      my ($session, $error) = Net::SNMP->session( %{$sw->{local_session}} );
297print "$error \n" if $error;
298#         -hostname   => $sw->{hostname},
299#         -community  => $sw->{community} || $DEFAULT{community} || 'public',
300#         -port       => $sw->{snmpport}  || $DEFAULT{snmpport}  || 161
301#         );
302#print "$sw->{hostname} --  $research \n";
303      my $result = $session->get_request(
304         -varbindlist => [$research]
305         );
306#      if(defined($result)) {
307      if (not defined($result) or $result->{$research} eq 'noSuchInstance') {
308#print "$sw->{hostname} --  $research --".$session->error()."\n";
309         $session->close;
310         next LOOP_ON_SWITCH;
311         }
312
313         my $swport = $result->{$research};
314         $session->close;
315
316         # IMPORTANT !!
317         # ceci empeche la detection sur certains port ...
318         # en effet les switch sont relies entre eux par un cable reseau et du coup
319         # tous les arp de toutes les machines sont presentes sur ces ports (ceux choisis ici sont les miens)
320         # cette partie est a ameliore, voir a configurer dans l'entete
321         # 21->24 45->48
322#         my $flag = 0;
323         SWITCH_PORT_IGNORE:
324         foreach my $p (@{$sw->{portignore}}) {
325            next SWITCH_PORT_IGNORE if $swport ne get_numerical_port($sw->{hostname},$p);
326#            $flag = 1;
327            next LOOP_ON_SWITCH;
328            }
329#         if ($flag == 0) {
330            $ret{switch_hostname}    = $sw->{hostname};
331            $ret{switch_description} = $sw->{description};
332            $ret{switch_port}        = get_human_readable_port($sw->{hostname}, $swport); # $swport;
333           
334            last LOOP_ON_SWITCH;
335#            }
336#         }
337#      $session->close;
338      }
339   return %ret;
340   }
341
342###
343# va rechercher les port et les switch sur lequel est la machine
344sub find_all_switch_port {
345   my $arp = shift;
346
347   my $ret = {};
348
349   return $ret if $arp eq 'unknow';
350
351   for my $sw (@SWITCH) {
352      $SWITCH_PORT_COUNT{$sw->{hostname}} = {} if not exists $SWITCH_PORT_COUNT{$sw->{hostname}};
353      }
354
355   my $research = "1.3.6.1.2.1.17.4.3.1.2".arp_hex_to_dec($arp);
356   LOOP_ON_ALL_SWITCH:
357   for my $sw (@SWITCH) {
358      my ($session, $error) = Net::SNMP->session( %{$sw->{local_session}} );
359      print "$error \n" if $error;
360
361      my $result = $session->get_request(
362         -varbindlist => [$research]
363         );
364
365      if(defined($result) and $result->{$research} ne 'noSuchInstance'){
366         my $swport = $result->{$research};
367
368         $ret->{$sw->{hostname}} = {};
369         $ret->{$sw->{hostname}}{hostname}    = $sw->{hostname};
370         $ret->{$sw->{hostname}}{description} = $sw->{description};
371         $ret->{$sw->{hostname}}{port}        = get_human_readable_port($sw->{hostname}, $swport);
372
373         $SWITCH_PORT_COUNT{$sw->{hostname}}->{$swport}++;
374         }
375
376      $session->close;
377      }
378   return $ret;
379   }
380
381sub get_list_network {
382
383   return keys %{$KLASK_CFG->{network}};
384   }
385
386sub get_current_interface {
387   my $network = shift;
388
389   return $KLASK_CFG->{network}{$network}{interface};
390   }
391 
392###
393# liste l'ensemble des adresses ip d'un réseau
394sub get_list_ip {
395   my @network = @_;
396
397   my $cidrlist = Net::CIDR::Lite->new;
398
399   for my $net (@network) {
400      my @line  = @{$KLASK_CFG->{network}{$net}{'ip-subnet'}};
401      for my $cmd (@line) {
402         for my $method (keys %$cmd){
403            $cidrlist->add_any($cmd->{$method}) if $method eq 'add';
404            }
405         }
406      }
407
408   my @res = ();
409
410   for my $cidr ($cidrlist->list()) {
411      my $net = new NetAddr::IP $cidr;
412      for my $ip (@$net) {
413         $ip =~ s#/32##;
414         push @res,  $ip;
415         }
416      }
417
418   return @res;
419   }
420
421# liste l'ensemble des routeurs du réseau
422sub get_list_main_router {
423   my @network = @_;
424
425   my @res = ();
426
427   for my $net (@network) {
428      push @res, $KLASK_CFG->{network}{$net}{'main-router'};
429      }
430
431   return @res;
432   }
433
434sub get_human_readable_port {
435   my $sw = shift;
436   my $port = shift;
437   
438   return $port if not $sw eq 'sw8000-batA.hmg.priv';
439   
440   my $reste = (($port - 1) % 8) + 1;
441   my $major = int( ($port - 1) / 8 );
442
443   return "$INTERNAL_PORT_MAP{$major}$reste";
444   }
445
446sub get_numerical_port {
447   my $sw   = shift;
448   my $port = shift;
449   
450   return $port if not $sw eq 'sw8000-batA.hmg.priv';
451
452   my $letter = substr($port, 0, 1);
453   
454#   return $port if $letter =~ m/\d/;
455   
456   my $reste =  substr($port, 1);
457   
458   return $INTERNAL_PORT_MAP_REV{$letter} * 8 + $reste;
459   }
460
461################
462# Les commandes
463################
464
465sub cmd_help {
466
467print <<END;
468klask - ports manager and finder for switch
469
470 klask updatedb
471 klask exportdf
472
473 klask searchdb computer
474 klask search   computer
475
476 klask enable  switch port
477 klask disable switch port
478 klask status  switch port
479END
480   }
481
482sub cmd_search {
483   my @computer = @_;
484   
485   init_switch_names();    #nomme les switchs
486   fastping(@computer);
487   for my $clientname (@computer) {
488      my %resol_arp = resolve_ip_arp_host($clientname);          #resolution arp
489      my %where     = find_switch_port($resol_arp{mac_address}); #retrouve l'emplacement
490      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"
491         unless $where{switch_description} eq 'unknow' and $resol_arp{hostname_fq} eq 'unknow' and $resol_arp{mac_address} eq 'unknow';
492      }
493   }
494
495sub cmd_searchdb {
496   my @computer = @_;
497
498   fastping(@computer);
499   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
500   
501   LOOP_ON_COMPUTER:
502   for my $clientname (@computer) {
503      my %resol_arp = resolve_ip_arp_host($clientname);      #resolution arp
504      my $ip = $resol_arp{ipv4_address};
505     
506      next LOOP_ON_COMPUTER unless exists $computerdb->{$ip};
507     
508      my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($computerdb->{$ip}{timestamp});
509      $year += 1900;
510      $mon++;
511      my $date = sprintf "%04i-%02i-%02i %02i:%02i", $year,$mon,$mday,$hour,$min;
512
513      printf "%-22s %2s %-30s %-15s %-18s %s\n",
514         $computerdb->{$ip}{switch_name},
515         $computerdb->{$ip}{switch_port},
516         $computerdb->{$ip}{hostname_fq},
517         $ip,
518         $computerdb->{$ip}{mac_address},
519         $date;
520      }
521   }
522
523sub cmd_updatedb {
524   my @network = @_;
525      @network = get_list_network() if not @network;
526
527   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
528   my $timestamp = time;
529   
530   my %computer_not_detected = ();
531   my $timestamp_last_week = $timestamp - (3600 * 24 * 7);
532
533   my $number_of_computer = get_list_ip(@network); # + 1;
534   my $size_of_database   = keys %$computerdb;
535   my $i = 0;
536   my $detected_computer = 0;
537   
538   init_switch_names('yes');    #nomme les switchs
539
540   my %router_mac_ip = ();
541   DETECT_ALL_ROUTER:
542#   for my $one_router ('194.254.66.254') {
543   for my $one_router ( get_list_main_router(@network) ) {
544      my %resol_arp = resolve_ip_arp_host($one_router);
545      $router_mac_ip{ $resol_arp{mac_address} } = $resol_arp{ipv4_address};
546      }
547
548   ALL_NETWORK:
549   for my $net (@network) {
550
551      my @computer = get_list_ip($net);
552      my $current_interface = get_current_interface($net);
553
554      fastping(@computer);
555
556      LOOP_ON_COMPUTER:
557      for my $one_computer (@computer) {
558         $i++;
559         
560         my $total_percent = int(($i*100)/$number_of_computer);
561
562         my $localtime = time - $timestamp;
563         my ($sec,$min) = localtime($localtime);
564
565         my $time_elapse = 0;
566            $time_elapse = $localtime * ( 100 - $total_percent) / $total_percent if $total_percent != 0;
567         my ($sec_elapse,$min_elapse) = localtime($time_elapse);
568
569         printf "\rComputer scanned: %4i/%i (%2i%%)",  $i,                 $number_of_computer, $total_percent;
570#         printf ", Computer detected: %4i/%i (%2i%%)", $detected_computer, $size_of_database,   int(($detected_computer*100)/$size_of_database);
571         printf ", detected: %4i/%i (%2i%%)", $detected_computer, $size_of_database,   int(($detected_computer*100)/$size_of_database);
572         printf " [Time: %02i:%02i / %02i:%02i]", int($localtime/60), $localtime % 60, int($time_elapse/60), $time_elapse % 60;
573#         printf "  [%02i:%02i/%02i:%02i]", int($localtime/60), $localtime % 60, int($time_elapse/60), $time_elapse % 60;
574         printf " %-14s", $one_computer;
575
576         my %resol_arp = resolve_ip_arp_host($one_computer,$current_interface);
577         
578         # do not search on router connection (why ?)
579         if ( exists $router_mac_ip{$resol_arp{mac_address}}) {
580            $computer_not_detected{$one_computer} = $current_interface;
581            next LOOP_ON_COMPUTER;
582            }
583
584         # do not search on switch inter-connection
585         if (exists $switch_level{$resol_arp{hostname_fq}}) {
586            $computer_not_detected{$one_computer} = $current_interface;
587            next LOOP_ON_COMPUTER;
588            }
589
590         my $switch_proposal = '';
591         if (exists $computerdb->{$resol_arp{ipv4_address}} and exists $computerdb->{$resol_arp{ipv4_address}}{switch_hostname}) {
592            $switch_proposal = $computerdb->{$resol_arp{ipv4_address}}{switch_hostname};
593            }
594
595         # do not have a mac address
596         if ($resol_arp{mac_address} eq 'unknow' or (exists $resol_arp{timestamps} and $resol_arp{timestamps} < ($timestamp - 3 * 3600))) {
597            $computer_not_detected{$one_computer} = $current_interface;
598            next LOOP_ON_COMPUTER;
599            }
600
601         my %where = find_switch_port($resol_arp{mac_address},$switch_proposal);
602
603         #192.168.24.156:
604         #  arp: 00:0B:DB:D5:F6:65
605         #  hostname: pcroyon.hmg.priv
606         #  port: 5
607         #  switch: sw-batH-legi:hp2524
608         #  timestamp: 1164355525
609
610         # do not have a mac address
611#         if ($resol_arp{mac_address} eq 'unknow') {
612#            $computer_not_detected{$one_computer} = $current_interface;
613#            next LOOP_ON_COMPUTER;
614#            }
615
616         # detected on a switch
617         if ($where{switch_description} ne 'unknow') {
618            $detected_computer++;
619            $computerdb->{$resol_arp{ipv4_address}} = {
620               hostname_fq        => $resol_arp{hostname_fq},
621               mac_address        => $resol_arp{mac_address},
622               switch_hostname    => $where{switch_hostname},
623               switch_description => $where{switch_description},
624               switch_port        => $where{switch_port},
625               timestamp          => $timestamp,
626               };
627            next LOOP_ON_COMPUTER;
628            }
629
630         # new in the database but where it is ?
631         if (not exists $computerdb->{$resol_arp{ipv4_address}}) {
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          => $resol_arp{timestamp},
640               };
641            }
642
643         # mise a jour du nom de la machine si modification dans le dns
644         $computerdb->{$resol_arp{ipv4_address}}{hostname_fq} = $resol_arp{hostname_fq};
645       
646         # mise à jour de la date de détection si détection plus récente par arpwatch
647         $computerdb->{$resol_arp{ipv4_address}}{timestamp}   = $resol_arp{timestamp} if exists $resol_arp{timestamp} and $computerdb->{$resol_arp{ipv4_address}}{timestamp} < $resol_arp{timestamp};
648
649         # provisoire car changement de nom des attributs
650#         $computerdb->{$resol_arp{ipv4_address}}{mac_address}        = $computerdb->{$resol_arp{ipv4_address}}{arp};
651#         $computerdb->{$resol_arp{ipv4_address}}{switch_description} = $computerdb->{$resol_arp{ipv4_address}}{switch};
652#         $computerdb->{$resol_arp{ipv4_address}}{switch_port}        = $computerdb->{$resol_arp{ipv4_address}}{port};
653       
654         # relance un arping sur la machine si celle-ci n'a pas été détectée depuis plus d'une semaine
655#         push @computer_not_detected, $resol_arp{ipv4_address} if $computerdb->{$resol_arp{ipv4_address}}{timestamp} < $timestamp_last_week;
656         $computer_not_detected{$resol_arp{ipv4_address}} = $current_interface if $computerdb->{$resol_arp{ipv4_address}}{timestamp} < $timestamp_last_week;
657       
658         }
659      }
660
661   # final end of line at the end of the loop
662   printf "\n";
663
664   my $dirdb = $KLASK_DB_FILE;
665      $dirdb =~ s#/[^/]*$##;
666   mkdir "$dirdb", 0755 unless -d "$dirdb";
667   YAML::DumpFile("$KLASK_DB_FILE", $computerdb);
668
669   for my $one_computer (keys %computer_not_detected) {
670      my $interface = $computer_not_detected{$one_computer};
671      system "arping -c 1 -w 1 -rR -i $interface $one_computer &>/dev/null";
672#      print  "arping -c 1 -w 1 -rR -i $interface $one_computer 2>/dev/null\n";
673      }
674   }
675
676sub cmd_removedb {
677   my @computer = @_;
678   
679   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
680
681   LOOP_ON_COMPUTER:
682   for my $one_computer (@computer) {
683
684      my %resol_arp = resolve_ip_arp_host($one_computer);
685
686      delete $computerdb->{$resol_arp{ipv4_address}} if exists $computerdb->{$resol_arp{ipv4_address}};
687      }
688
689   my $dirdb = $KLASK_DB_FILE;
690      $dirdb =~ s#/[^/]*$##;
691   mkdir "$dirdb", 0755 unless -d "$dirdb";
692   YAML::DumpFile("$KLASK_DB_FILE", $computerdb);
693   }
694
695sub cmd_exportdb {
696   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
697
698   printf "%-24s %-4s            %-30s %-15s %-18s %-s\n", qw(Switch Port Hostname IPv4-Address MAC-Address Date);
699   print "---------------------------------------------------------------------------------------------------------------------------\n";
700
701   LOOP_ON_IP_ADDRESS:
702   foreach my $ip (Net::Netmask::sort_by_ip_address(keys %$computerdb)) {
703   
704#      next LOOP_ON_IP_ADDRESS if $computerdb->{$ip}{hostname_fq} eq 'unknow';
705
706      # to be improve in the future
707      next LOOP_ON_IP_ADDRESS if $computerdb->{$ip}{hostname_fq} eq ($computerdb->{$ip}{switch_hostname} || $computerdb->{$ip}{switch_description}); # switch on himself !
708
709# dans le futur
710#      next if $computerdb->{$ip}{hostname_fq} eq 'unknow';
711     
712      my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($computerdb->{$ip}{timestamp});
713      $year += 1900;
714      $mon++;
715      my $date = sprintf "%04i-%02i-%02i %02i:%02i", $year,$mon,$mday,$hour,$min;
716
717      printf "%-25s  %2s  <-------  %-30s %-15s %-18s %s\n",
718         $computerdb->{$ip}{switch_hostname} || $computerdb->{$ip}{switch_description},
719         $computerdb->{$ip}{switch_port},
720         $computerdb->{$ip}{hostname_fq},
721         $ip,
722         $computerdb->{$ip}{mac_address},
723         $date;
724      }
725   }
726
727sub cmd_iplocation {
728   my $computerdb = YAML::LoadFile("$KLASK_DB_FILE");
729
730   LOOP_ON_IP_ADDRESS:
731   foreach my $ip (Net::Netmask::sort_by_ip_address(keys %$computerdb)) {
732
733      next LOOP_ON_IP_ADDRESS if $computerdb->{$ip}{hostname_fq} eq ($computerdb->{$ip}{switch_hostname} || $computerdb->{$ip}{switch_description}); # switch on himself !
734
735      my $sw_hostname = $computerdb->{$ip}{switch_hostname} || '';
736      next if $sw_hostname eq 'unknow';
737 
738      my $sw_location = '';
739      for my $sw (@SWITCH) {
740         next if $sw_hostname ne $sw->{hostname};
741         $sw_location = $sw->{location};
742         last;
743         }
744
745      printf "%s: \"%s\"\n", $ip, $sw_location if not $sw_location eq '';
746      }
747   }
748
749sub cmd_enable {
750   my $switch = shift;
751   my $port   = shift;
752   
753   #snmpset -v 1 -c community X.X.X.X 1.3.6.1.2.1.2.2.1.7.NoPort = 1 (up)
754   #snmpset -v 1 -c community X.X.X.X 1.3.6.1.2.1.2.2.1.7.NoPort = 2 (down)
755   system "snmpset -v 1 -c public $switch 1.3.6.1.2.1.2.2.1.7.$port = 1";
756   }
757
758sub cmd_disable {
759   my $switch = shift;
760   my $port   = shift;
761   
762   system "snmpset -v 1 -c public $switch 1.3.6.1.2.1.2.2.1.7.$port = 2";
763   }
764
765sub cmd_status {
766   my $switch = shift;
767   my $port   = shift;
768   
769   system "snmpget -v 1 -c public $switch 1.3.6.1.2.1.2.2.1.7.$port";
770   }
771
772
773sub cmd_updatesw {
774
775   init_switch_names('yes');    #nomme les switchs
776   print "\n";
777
778   my %where = ();
779   my %db_switch_output_port = ();
780   my %db_switch_ip_hostname = ();
781
782   DETECT_ALL_ROUTER:
783#   for my $one_computer ('194.254.66.254') {
784   for my $one_router ( get_list_main_router(get_list_network()) ) {
785      my %resol_arp = resolve_ip_arp_host($one_router,'*','low');            # resolution arp
786      next DETECT_ALL_ROUTER if $resol_arp{mac_address} eq 'unknow';
787     
788      $where{$resol_arp{ipv4_address}} = find_all_switch_port($resol_arp{mac_address}); # retrouve les emplacements des routeurs
789      }
790
791   ALL_ROUTER_IP_ADDRESS:
792   for my $ip (Net::Netmask::sort_by_ip_address(keys %where)) { # '194.254.66.254')) {
793   
794      next ALL_ROUTER_IP_ADDRESS if not exists $where{$ip}; # /a priori/ idiot car ne sers à rien...
795
796      ALL_SWITCH_CONNECTED:
797      for my $switch_detected ( keys %{$where{$ip}} ) {
798
799         my $switch = $where{$ip}->{$switch_detected};
800
801         next ALL_SWITCH_CONNECTED if $switch->{port} eq '0';
802         
803         $db_switch_output_port{$switch->{hostname}} = $switch->{port};
804         }
805      }   
806
807#   print "Switch output port\n"; 
808#   print "------------------\n";
809#   for my $sw (sort keys %db_switch_output_port) {
810#      printf "%-25s %2s\n", $sw, $db_switch_output_port{$sw};
811#      }
812#   print "\n";
813
814
815   my %db_switch_link_with = ();
816
817   my @list_switch_ip = ();
818   my @list_switch_ipv4 = ();
819   for my $sw (@SWITCH){
820      push @list_switch_ip, $sw->{hostname};
821      }
822
823   ALL_SWITCH:
824   for my $one_computer (@list_switch_ip) {
825      my %resol_arp = resolve_ip_arp_host($one_computer,'*','low'); # arp resolution
826      next ALL_SWITCH if $resol_arp{mac_address} eq 'unknow';
827     
828      push @list_switch_ipv4,$resol_arp{ipv4_address};
829     
830      $where{$resol_arp{ipv4_address}} = find_all_switch_port($resol_arp{mac_address}); # find port on all switch
831
832      $db_switch_ip_hostname{$resol_arp{ipv4_address}} = $resol_arp{hostname_fq};
833      }
834     
835   ALL_SWITCH_IP_ADDRESS:
836   for my $ip (Net::Netmask::sort_by_ip_address(@list_switch_ipv4)) {
837   
838      next ALL_SWITCH_IP_ADDRESS if not exists $where{$ip};
839
840      DETECTED_SWITCH:
841      for my $switch_detected ( keys %{$where{$ip}} ) {
842
843         next DETECTED_SWITCH if not exists $SWITCH_PORT_COUNT{ $db_switch_ip_hostname{$ip}};
844
845         my $switch = $where{$ip}->{$switch_detected};
846
847         next if $switch->{port}     eq '0';
848         next if $switch->{port}     eq $db_switch_output_port{$switch->{hostname}};
849         next if $switch->{hostname} eq $db_switch_ip_hostname{$ip}; # $computerdb->{$ip}{hostname};
850
851         $db_switch_link_with{ $db_switch_ip_hostname{$ip} } ||= {};
852         $db_switch_link_with{ $db_switch_ip_hostname{$ip} }->{ $switch->{hostname} } = $switch->{port};
853         }
854
855      }
856   
857   my %db_switch_connected_on_port = ();
858   my $maybe_more_than_one_switch_connected = 'yes';
859   
860   while ($maybe_more_than_one_switch_connected eq 'yes') {
861      for my $sw (keys %db_switch_link_with) {
862         for my $connect (keys %{$db_switch_link_with{$sw}}) {
863         
864            my $port = $db_switch_link_with{$sw}->{$connect};
865         
866            $db_switch_connected_on_port{"$connect:$port"} ||= {};
867            $db_switch_connected_on_port{"$connect:$port"}->{$sw}++; # Just to define the key
868            }
869         }
870
871      $maybe_more_than_one_switch_connected  = 'no';
872
873      SWITCH_AND_PORT:
874      for my $swport (keys %db_switch_connected_on_port) {
875         
876         next if keys %{$db_switch_connected_on_port{$swport}} == 1;
877         
878         $maybe_more_than_one_switch_connected = 'yes';
879
880         my ($sw_connect,$port_connect) = split ':', $swport;
881         my @sw_on_same_port = keys %{$db_switch_connected_on_port{$swport}};
882
883         CONNECTED:
884         for my $sw_connected (@sw_on_same_port) {
885           
886            next CONNECTED if not keys %{$db_switch_link_with{$sw_connected}} == 1;
887           
888            $db_switch_connected_on_port{$swport} = {$sw_connected => 1};
889           
890            for my $other_sw (@sw_on_same_port) {
891               next if $other_sw eq $sw_connected;
892               
893               delete $db_switch_link_with{$other_sw}->{$sw_connect};
894               }
895           
896            # We can not do better for this switch for this loop
897            next SWITCH_AND_PORT;
898            }
899         }
900      }
901
902   my %db_switch_parent =();
903
904   for my $sw (keys %db_switch_link_with) {
905      for my $connect (keys %{$db_switch_link_with{$sw}}) {
906     
907         my $port = $db_switch_link_with{$sw}->{$connect};
908     
909         $db_switch_connected_on_port{"$connect:$port"} ||= {};
910         $db_switch_connected_on_port{"$connect:$port"}->{$sw} = $port;
911       
912         $db_switch_parent{$sw} = {switch => $connect, port => $port};
913         }
914      }
915
916   print "Switch output port and parent port connection\n"; 
917   print "---------------------------------------------\n";
918   for my $sw (sort keys %db_switch_output_port) {
919      if (exists $db_switch_parent{$sw}) {
920         printf "%-25s  %2s  +-->  %2s  %-25s\n", $sw, $db_switch_output_port{$sw}, $db_switch_parent{$sw}->{port}, $db_switch_parent{$sw}->{switch};
921         }
922      else {
923         printf "%-25s  %2s  +-->  router\n", $sw, $db_switch_output_port{$sw};
924         }
925      }
926   print "\n";
927
928   print "Switch parent and children port inter-connection\n";
929   print "------------------------------------------------\n";
930   for my $swport (sort keys %db_switch_connected_on_port) {       
931      my ($sw_connect,$port_connect) = split ':', $swport;
932      for my $sw (keys %{$db_switch_connected_on_port{$swport}}) {
933         if (exists $db_switch_output_port{$sw}) {
934            printf "%-25s  %2s  <--+  %2s  %-25s\n", $sw_connect, $port_connect, $db_switch_output_port{$sw}, $sw;
935            }
936         else {
937            printf "%-25s  %2s  <--+      %-25s\n", $sw_connect, $port_connect, $sw;
938            }
939         }
940      }
941
942   my $switch_connection = {
943      output_port       => \%db_switch_output_port,
944      parent            => \%db_switch_parent,
945      connected_on_port => \%db_switch_connected_on_port,
946      link_with         => \%db_switch_link_with,
947      };
948     
949   YAML::DumpFile("$KLASK_SW_FILE", $switch_connection);
950   }
951
952sub cmd_exportsw {
953   my @ARGV   = @_;
954
955   my $format = 'txt';
956
957   my $ret = GetOptions(
958      'format|f=s'  => \$format,
959      );
960
961   my %possible_format = (
962      txt => \&cmd_exportsw_txt,
963      dot => \&cmd_exportsw_dot,
964      );
965
966   $format = 'txt' if not defined $possible_format{$format};
967   
968   $possible_format{$format}->(@ARGV);
969   }
970
971sub cmd_exportsw_txt {
972
973   my $switch_connection = YAML::LoadFile("$KLASK_SW_FILE");
974
975   my %db_switch_output_port       = %{$switch_connection->{output_port}};
976   my %db_switch_parent            = %{$switch_connection->{parent}};
977   my %db_switch_connected_on_port = %{$switch_connection->{connected_on_port}};
978
979   print "Switch output port and parent port connection\n"; 
980   print "---------------------------------------------\n";
981   for my $sw (sort keys %db_switch_output_port) {
982      if (exists $db_switch_parent{$sw}) {
983         printf "%-25s  %2s  +-->  %2s  %-25s\n", $sw, $db_switch_output_port{$sw}, $db_switch_parent{$sw}->{port}, $db_switch_parent{$sw}->{switch};
984         }
985      else {
986         printf "%-25s  %2s  +-->  router\n", $sw, $db_switch_output_port{$sw};
987         }
988      }
989   print "\n";
990
991   print "Switch parent and children port inter-connection\n";
992   print "------------------------------------------------\n";
993   for my $swport (sort keys %db_switch_connected_on_port) {       
994      my ($sw_connect,$port_connect) = split ':', $swport;
995      for my $sw (keys %{$db_switch_connected_on_port{$swport}}) {
996         if (exists $db_switch_output_port{$sw}) {
997            printf "%-25s  %2s  <--+  %2s  %-25s\n", $sw_connect, $port_connect, $db_switch_output_port{$sw}, $sw;
998            }
999         else {
1000            printf "%-25s  %2s  <--+      %-25s\n", $sw_connect, $port_connect, $sw;
1001            }
1002         }
1003      }
1004   }
1005
1006sub cmd_exportsw_dot {
1007
1008   my $switch_connection = YAML::LoadFile("$KLASK_SW_FILE");
1009   
1010   my %db_switch_output_port       = %{$switch_connection->{output_port}};
1011   my %db_switch_parent            = %{$switch_connection->{parent}};
1012   my %db_switch_connected_on_port = %{$switch_connection->{connected_on_port}};
1013   my %db_switch_link_with         = %{$switch_connection->{link_with}};
1014     
1015   my %db_building= ();
1016   for my $sw (@SWITCH) {
1017      my ($building, $location) = split /\//, $sw->{location}, 2;
1018      $db_building{$building} ||= {};
1019      $db_building{$building}->{$location} ||= {};
1020      $db_building{$building}->{$location}{ $sw->{hostname} } = 'y';
1021      }
1022 
1023 
1024   print "digraph G {\n";
1025
1026   print "site [label = \"site\", color = black, fillcolor = gold, shape = invhouse, style = filled];\n";
1027   print "internet [label = \"internet\", color = black, fillcolor = cyan, shape = house, style = filled];\n";
1028
1029   my $b=0;
1030   for my $building (keys %db_building) {
1031      $b++;
1032     
1033      print "\"building$b\" [label = \"$building\", color = black, fillcolor = gold, style = filled];\n";
1034      print "site -> \"building$b\" [len = 2, color = firebrick];\n";
1035
1036      my $l = 0;
1037      for my $loc (keys %{$db_building{$building}}) {
1038         $l++;
1039 
1040         print "\"location$b-$l\" [label = \"$building / $loc\", color = black, fillcolor = orange, style = filled];\n";
1041         print "\"building$b\" -> \"location$b-$l\" [len = 2, color = firebrick]\n";
1042
1043         for my $sw (keys %{$db_building{$building}->{$loc}}) {
1044
1045            print "\"$sw:$db_switch_output_port{$sw}\" [label = $db_switch_output_port{$sw}, color = black, fillcolor = lightblue,  peripheries = 2, style = filled];\n";
1046
1047            print "\"$sw\" [label = \"$sw\", color = black, fillcolor = palegreen, shape = rect, style = filled];\n";
1048            print "\"location$b-$l\" -> \"$sw\" [len = 2, color = firebrick, arrowtail = dot]\n";
1049            print "\"$sw\" -> \"$sw:$db_switch_output_port{$sw}\" [len=2, style=bold, arrowhead = normal, arrowtail = invdot]\n";
1050
1051
1052            for my $swport (keys %db_switch_connected_on_port) {
1053               my ($sw_connect,$port_connect) = split ':', $swport;
1054               next if not $sw_connect eq $sw;
1055               next if $port_connect eq $db_switch_output_port{$sw};
1056               print "\"$sw:$port_connect\" [label = $port_connect, color = black, fillcolor = plum,  peripheries = 1, style = filled];\n";
1057               print "\"$sw:$port_connect\" -> \"$sw\" [len=2, style=bold, arrowhead= normal, arrowtail = inv]\n";
1058              }
1059            }
1060         }
1061      }
1062
1063#   print "Switch output port and parent port connection\n"; 
1064#   print "---------------------------------------------\n";
1065   for my $sw (sort keys %db_switch_output_port) {
1066      if (exists $db_switch_parent{$sw}) {
1067#         printf "   \"%s:%s\" -> \"%s:%s\"\n", $sw, $db_switch_output_port{$sw}, $db_switch_parent{$sw}->{switch}, $db_switch_parent{$sw}->{port};
1068         }
1069      else {
1070         printf "   \"%s:%s\" -> internet\n", $sw, $db_switch_output_port{$sw};
1071         }
1072      }
1073   print "\n";
1074
1075#   print "Switch parent and children port inter-connection\n";
1076#   print "------------------------------------------------\n";
1077   for my $swport (sort keys %db_switch_connected_on_port) {       
1078      my ($sw_connect,$port_connect) = split ':', $swport;
1079      for my $sw (keys %{$db_switch_connected_on_port{$swport}}) {
1080         if (exists $db_switch_output_port{$sw}) {
1081            printf "   \"%s:%s\" -> \"%s:%s\" [color = navyblue]\n", $sw, $db_switch_output_port{$sw}, $sw_connect, $port_connect;
1082            }
1083         else {
1084            printf "   \"%s\"   -> \"%s%s\"\n", $sw, $sw_connect, $port_connect;
1085            }
1086         }
1087      }
1088
1089print "}\n";
1090   }
1091
1092
1093__END__
1094
1095
1096=head1 NAME
1097
1098klask - ports manager and finder for switch
1099
1100
1101=head1 SYNOPSIS
1102
1103 klask updatedb
1104 klask exportdb
1105
1106 klask updatesw
1107 klask exportsw --format [txt|dot]
1108
1109 klask searchdb computer
1110 klask search   computer
1111
1112 klask enable  switch port
1113 klask disable swith port
1114 klask status  swith port
1115
1116
1117=head1 DESCRIPTION
1118
1119klask is a small tool to find where is a host in a big network. klask mean search in brittany.
1120
1121Klask has now a web site dedicated for it !
1122
1123 http://servforge.legi.inpg.fr/projects/klask
1124
1125
1126=head1 COMMANDS
1127
1128
1129=head2 search
1130
1131This 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.
1132
1133
1134=head2 enable
1135
1136This command activate a port on a switch by snmp. So you need to give the switch and the port number on the command line.
1137
1138
1139=head2 disable
1140
1141This command deactivate a port on a switch by snmp. So you need to give the switch and the port number on the command line.
1142
1143
1144=head2 status
1145
1146This 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.
1147
1148
1149=head2 updatedb
1150
1151This 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.
1152
1153
1154=head2 exportdb
1155
1156This 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...
1157
1158
1159=head2 updatesw
1160
1161This 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.
1162
1163
1164=head2 exportsw --format [txt|dot]
1165
1166This 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.
1167
1168 klask exportsw --format dot > /tmp/map.dot
1169 dot -Tpng /tmp/map.dot > /tmp/map.png
1170
1171
1172
1173=head1 CONFIGURATION
1174
1175Because 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 !
1176
1177Here an example, be aware with indent, it's important in YAML, do not use tabulation !
1178
1179 default:
1180   community: public
1181   snmpport: 161
1182
1183 network:
1184   labnet:
1185     ip-subnet:
1186       - add: 192.168.1.0/24
1187       - add: 192.168.2.0/24
1188     interface: eth0
1189     main-router: gw1.labnet.local
1190
1191   schoolnet:
1192     ip-subnet:
1193       - add: 192.168.6.0/24
1194       - add: 192.168.7.0/24
1195     interface: eth0.38
1196     main-router: gw2.schoolnet.local
1197
1198 switch:
1199   - hostname: sw1.klask.local
1200     portignore:
1201       - 1
1202       - 2
1203
1204   - hostname: sw2.klask.local
1205     location: BatK / 2 / K203
1206     type: HP2424
1207     portignore:
1208       - 1
1209       - 2
1210
1211I 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.
1212
1213
1214=head1 FILES
1215
1216 /etc/klask.conf
1217 /var/cache/klask/klaskdb
1218 /var/cache/klask/switchdb
1219
1220=head1 SEE ALSO
1221
1222Net::SNMP, Net::Netmask, Net::CIDR::Lite, NetAddr::IP, YAML
1223
1224
1225=head1 VERSION
1226
12270.4
1228
1229
1230=head1 AUTHOR
1231
1232Written by Gabriel Moreau, Grenoble - France
1233
1234
1235=head1 COPYRIGHT
1236       
1237Copyright (C) 2005-2008 Gabriel Moreau.
1238
1239
1240=head1 LICENCE
1241
1242GPL version 2 or later and Perl equivalent
Note: See TracBrowser for help on using the repository browser.