source: trunk/klask @ 20

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