source: trunk/klask @ 31

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