source: trunk/klask @ 34

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