source: trunk/klask @ 28

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