source: trunk/klask @ 32

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