source: trunk/klask @ 25

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