source: trunk/klask @ 26

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