#!/usr/local/bin/perl # # Try to build configuration files for all the routers in the WAN, # by recursively scanning them. Can take a long time to run! # call with parameter '-h' for syntax help. ########################################################################## # # buildwan.pl # # THIS IS RELEASED IN THE PUBLIC DOMAIN: # Do what you want with it, how you want. You are free to modify, # distribute or even sell this script. # ########################################################################## use strict; use Net::SNMP; use FileHandle; use vars qw($opt_L $opt_h $opt_s $opt_c $opt_D $opt_w $opt_N $opt_A $opt_p); use Getopt::Std; my( $conffile, %config,@cfgfiles, $pathsep ); my($SHDESC ) = "1.3.6.1.2.1.2.2.1.2"; my($DESC ) = "1.3.6.1.2.1.31.1.1.1.18"; my($SYSDESC) = "1.3.6.1.2.1.1.1.0"; my($IFINDEX) = "1.3.6.1.2.1.2.2.1.1"; my($IFDESCR) = "1.3.6.1.2.1.2.2.1.2"; my($IFSPEED) = "1.3.6.1.2.1.2.2.1.5"; my($IFADMINSTATUS) = "1.3.6.1.2.1.2.2.1.7"; my($IFOPERSTATUS) = "1.3.6.1.2.1.2.2.1.8"; my($IFINOCTETS) = "1.3.6.1.2.1.2.2.1.10"; my($IPIFINDEX) = "1.3.6.1.2.1.4.20.1.2"; my($IPROUTEGW) = "1.3.6.1.2.1.4.21.1.7"; my($CPUOID) = "1.3.6.1.4.1.9.2.1.58.0"; my($FNDRYCPUOID) = "1.3.6.1.4.1.1991.1.1.2.1.35.0"; my($MEMOID) = "1.3.6.1.4.1.9.9.48.1.1.1.5.1"; # have to find out my($FNDRYMEMOID) = "1.3.6.1.4.1.1991.1.1.2.1.55.0"; my($FNDRYMAXMEMOID) = "1.3.6.1.4.1.1991.1.1.2.1.54.0"; my($FNDRYBGPOID) = "1.3.6.1.4.1.1991.1.2.11.1.27.0"; my($FNDRYTEMPOID) = "1.3.6.1.4.1.1991.1.1.1.1.18.0"; # Cisco 7200 Series Temperature my($CISCOTEMP) = "1.3.6.1.4.1.9.9.13.1.3.1"; my( $includelans ) = 0; my( $includealllan ) = 0; my( $router, $routerip, $routerhostname, $routerdesc, $routeraddr ); my( $showall ) = 0; my( $fname ); my( $script ) = "/cgi-bin/routers2.cgi"; my( $pathsep ) = "/"; my( $domain ) = "...\.adsw\.com"; my( @community ) = ( "public" ); my( $community ); my( $workdir ) = "/var/db/rrdtool"; my( $pathadd ) = "/usr/local/bin"; my( @queue ) = ( ); my( $subdir ) = ""; my( @filelist ) = (); my( %routers, %done ); ########################################################################## my($spinindex) = 0; sub spin($) { print "\r".(substr "\\|/-",$spinindex,1)." ".$_[0]." \r"; $spinindex += 1; $spinindex = 0 if($spinindex > 3); } sub escape($) { my($rv); $rv = $_[0]; $rv =~ s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg; return $rv; } # $interfaces{ifno} = \{ desc=>"", shdesc=>"", ip=>"" } my( %interfaces ) = (); sub process_rtr($) { my($snmp, $resp, $snmperr, $k); my($n,$v,$ip); my($cpuok,$memok,$bgpok,$tempok); my($rcomm) = ""; my($fndrymaxmem); $router = $_[0]; $cpuok = $memok = ""; if(defined $done{$router} ) { print "No need to do $router again (".$done{$router}[0].") \r"; return; } %interfaces = (); foreach $community ( @community ) { print "\r**** Let's check $community\@$router **** "; ($snmp, $snmperr) = Net::SNMP->session( -hostname=>$router, -community=>$community, -timeout=>4 ); if($snmperr) { print "Error: ".$snmperr."\n"; $done{$router} =[ "Error","",""]; return; } $rcomm = $community; # get the interfaces list $resp = $snmp->get_next_request( $IFINDEX ); last if($resp); } print "\n"; if(!defined $resp ) { print "Error: ". $snmp->error()."\n"; $snmp->close(); $done{$router} = ["Error","",""]; return; } print "If: "; while( defined $resp ) { $n = (keys %$resp)[0]; foreach $k ( keys %$resp ) { $v = $resp->{$k}; last if ( $v !~ /^\d+$/ ); spin "If $v"; $interfaces{$v}{ifno} = $v ; } last if ( $v !~ /^\d+$/ ); $resp = $snmp->get_next_request( $n ); } # Get IP interface list print "\rIP: \r"; $resp = $snmp->get_next_request( $IPIFINDEX ); if(!defined $resp ) { print "\nError: ". $snmp->error()."\n"; $done{$router} = ["Error","",""]; $snmp->close(); return; } while( defined $resp ) { $n = (keys %$resp)[0]; foreach $k ( keys %$resp ) { $v = $resp->{$k}; last if ( $v !~ /^\d+$/ ); if( $k =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)$/ and defined $interfaces{$v} ) { $ip = "$1.$2.$3.$4"; $interfaces{$v}{ip} = $ip if(($ip =~ /^10/) or !$interfaces{$v}{ip}); spin "IP ".$interfaces{$v}{ip}; if($done{$interfaces{$v}{ip}} and $done{$interfaces{$v}{ip}}[0] !~ /Error/i) { print "\rOops, done this one before (" .$interfaces{$v}{ip}.")(" .$done{$interfaces{$v}{ip}}[0].")\n"; $done{$router} = [ @{$done{$interfaces{$v}{ip}}} ]; return; } } } last if ( $v !~ /^\d+$/ ); $resp = $snmp->get_next_request( $n ); } # get their descriptions and activity print "\rDt: \r"; foreach $k ( keys %interfaces ) { $resp = $snmp->get_request( "$IFDESCR.$k", "$IFADMINSTATUS.$k", "$IFOPERSTATUS.$k", "$IFSPEED.$k", "$IFINOCTETS.$k" ); # XXX: ici a faire :) if ($includealllan) { if( $resp->{"$IFDESCR.$k"} =~ /^lo/i or $resp->{"$IFDESCR.$k"} =~ /^nul/i or $resp->{"$IFDESCR.$k"} =~ /^Nul.*/i or $resp->{"$IFDESCR.$k"} =~ /^VLAN.*/i ) { $interfaces{$k}{state} = "X"; delete $interfaces{$k} unless($showall); spin "$k X"; } else { spin "$k ."; $interfaces{$k}{state} = " "; $interfaces{$k}{descr} = $resp->{"$IFDESCR.$k"}; $interfaces{$k}{ifinoctets} = $resp->{"$IFINOCTETS.$k"}; $interfaces{$k}{speed} = $resp->{"$IFSPEED.$k"}; } } else { if( $resp->{"$IFDESCR.$k"} =~ /^lo/i or $resp->{"$IFDESCR.$k"} =~ /^nul/i or $resp->{"$IFDESCR.$k"} =~ /^Nul.*/i or $resp->{"$IFDESCR.$k"} =~ /^VLAN.*/i or $resp->{"$IFADMINSTATUS.$k"} != 1 or $resp->{"$IFOPERSTATUS.$k"} != 1 ) { $interfaces{$k}{state} = "X"; delete $interfaces{$k} unless($showall); spin "$k X"; } else { spin "$k ."; $interfaces{$k}{state} = " "; $interfaces{$k}{descr} = $resp->{"$IFDESCR.$k"}; $interfaces{$k}{ifinoctets} = $resp->{"$IFINOCTETS.$k"}; $interfaces{$k}{speed} = $resp->{"$IFSPEED.$k"}; } } } $routerip = "$router"; $routerhostname = ""; my($hn, $a,$b,$c,$d); foreach $k ( keys %interfaces ) { if($done{$interfaces{$k}{ip}} and $done{$interfaces{$k}{ip}}[0] !~ /Error/i) { print "\rOops, done this one before (".$interfaces{$k}{ip}.")(" .$done{$interfaces{$k}{ip}}[0].")\n"; $done{$router} = [ @{$done{$interfaces{$k}{ip}}} ]; $snmp->close; return; } if($interfaces{$k}{ip} =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/) { ($a,$b,$c,$d) = ($1,$2,$3,$4); if( $routerip !~ /^10\./ and $a eq "10") { $routerip = $interfaces{$k}{ip}; next; } if(!$routeraddr or !$routerhostname or $a eq "10") { $routeraddr = pack 'C4',$a,$b,$c,$d; $hn = gethostbyaddr($routeraddr,2); if($hn) { $routerip = $interfaces{$k}{ip}; $routerhostname = $hn; } } } } if(!$routerhostname) { $routerip =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/; $routeraddr = pack 'C4',$1,$2,$3,$4; $routerhostname = gethostbyaddr($routeraddr,2); } $routerdesc = $routerhostname; $routerdesc = $routerip if(!$routerdesc); $routerdesc =~ s/\.$domain//o; $routerdesc =~ s/^router\.//; $routerdesc =~ s/\.uk$//; $routerdesc =~ s/^router(\d+)\.(.*)/\2 \1/; # $routerdesc = ucfirst $routerdesc if( $routerdesc !~ /\./ ); if( $router ne $routerip and $done{$routerip} and $done{$routerip}!~/Error/i ) { print "\rOops, done this one before ($routerip)(".$done{$routerip}[0].")\n"; $snmp->close; $done{$router} = [ @{$done{$routerip}} ]; return; } $routerhostname = $routerip if(!$routerhostname); # now check to see if the router has an OID for CPU and mem $resp = $snmp->get_request( $MEMOID ); if( $resp ) { $memok = $MEMOID if( $resp->{$MEMOID} ); } else { $resp = $snmp->get_request( $FNDRYMEMOID ); if( $resp ) { $memok = $FNDRYMEMOID if( $resp->{$FNDRYMEMOID} ); $resp = $snmp->get_request( $FNDRYMAXMEMOID ); if( $resp ) { $fndrymaxmem = $resp->{$FNDRYMAXMEMOID} if( $resp->{$FNDRYMAXMEMOID} ); } } } # Try $CPUOID, if this doesn't work, try Foundry one $resp = $snmp->get_request( $CPUOID ); if( $resp ) { $cpuok = $CPUOID if( $resp->{$CPUOID} ); } else { $resp = $snmp->get_request( $FNDRYCPUOID ); if( $resp ) { $cpuok = $FNDRYCPUOID if( $resp->{$FNDRYCPUOID} ); } } # Try to check if BGP routes exists $resp = $snmp->get_request( $FNDRYBGPOID ); if( $resp ) { $bgpok = $FNDRYBGPOID if( $resp->{$FNDRYBGPOID} ); } # Try to check if router has temp sensors (currently only foundry !) $resp = $snmp->get_request( $FNDRYTEMPOID ); if( $resp ) { $tempok = $FNDRYTEMPOID if( $resp->{$FNDRYTEMPOID} ); } $routers{$router} = { interfaces=>{%interfaces}, name=>$routerdesc, ip=>$routerip, hostname=>$routerhostname, community=>$rcomm, cpu=>$cpuok, mem=>$memok, fndrymaxmem=>$fndrymaxmem, bgp=>$bgpok, temp=>$tempok }; print "\rFinished router $routerhostname at address $routerip\n"; $done{$router} = [ $routerdesc, (lc $routerdesc).".cfg", "" ]; my($nextip, $t); foreach $k ( keys %interfaces ) { next if(!$interfaces{$k}{ip}); $t = $routerhostname.".".$interfaces{$k}{descr}; $t =~ s/[\[\]#\/\\\s]+/./g; $t =~ s/\.+/./g; $t = lc $t; $done{$interfaces{$k}{ip}} = [ $routerdesc, (lc $routerdesc).".cfg", $t ]; } # check routing table and queue each agteway for next scan $resp = $snmp->get_next_request( $IPROUTEGW ); if(!defined $resp ) { print "\nError: ". $snmp->error()."\n"; $snmp->close(); return; } if(!$opt_N) { print "\rChecking routing table ..... \r"; while( defined $resp ) { $n = (keys %$resp)[0]; last if( $n !~ /^$IPROUTEGW/ ); $nextip = $resp->{$n}; spin "Route $nextip "; if(!defined $done{$nextip} and $nextip =~ /[123456789]\d*\.\d+\.\d+\.\d+/ ) { push @queue, $nextip ; print "Queueing $nextip (route) \r"; } $resp = $snmp->get_next_request( $n ); } $snmp->close; writefile($router); print "\n"; } else { print "\rRouting table is ignored....\n"; } } ########################################################################## # pass hostname, comm, a hash ref for the interfaces sub print_if($$$$) { my($h,$c,$n,$ifp) = @_; my($k,$nextip,$icon); my($t,$d,$f); my($mb,$pfx); my $descr; $n = ucfirst $n if($n !~ /\./); foreach $k ( keys %$ifp ) { my $descr; $descr = $ifp->{$k}->{descr}; $descr =~ s/\n//g; $icon = "interface-sm.gif"; $pfx = ""; $d = ""; $t = $h.".".$k; #$t = $h.".".$ifp->{$k}->{descr} if($ifp->{$k}->{descr}); $t = $h.".".$descr if($descr); $t =~ s/[\[\]#\/\\\s]+/./g; $t =~ s/\.+/./g; $t = lc $t; # print it out if(!$ifp->{$k}->{speed} or !$c or !$h) { $pfx = "# "; } if(!$includelans and $descr =~ /(ether|token)/i) { $pfx = "# "; } # print "$k".$ifp->{$k}{state}.": ".$ifp->{$k}{descr} # ." [".$ifp->{$k}{ip}."] " # .($ifp->{$k}{speed}/8)."bytes/s " # .$ifp->{$k}{ifinoctets}."\n"; # print "ifp=$ifp k=$k ifp->{k}=".$ifp->{$k}."\n"; # print "ifp->{k}->{ip}=".$ifp->{$k}->{ip}."\n"; if( $ifp->{$k}->{ip} ) { print CFG $pfx."Target[".$t."]: /".$ifp->{$k}->{ip}.":$c\@$h\n"; } else { print CFG $pfx."Target[".$t."]: $k:$c\@$h\n"; } if(!$ifp->{$k}->{speed}) { print CFG $pfx."#MaxBytes[".$t."]: unknown (Defaulting to 1G)\n"; print CFG $pfx."MaxBytes[".$t."]: 12500000\n"; } else { $mb = $ifp->{$k}->{speed} / 8; print CFG $pfx."MaxBytes[".$t."]: $mb\n"; } if($ifp->{$k}->{destination}[0]) { $d = " (To ".(ucfirst $ifp->{$k}{destination}[0]).")" if($ifp->{$k}{destination}[0] !~ /Error/i); } else { $ifp->{$k}->{ip} =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)$/; $nextip = "$1.$2.$3.".($4^3); if(defined $done{$nextip}) { $ifp->{$k}->{destination} = $done{$nextip}; $d = " (To ".(ucfirst $done{$nextip}[0]).")" if($done{$nextip}[0] !~ /Error/i); # } else { # print CFG "# unable to find info for $nextip\n"; } } $icon = "interface2-sm.gif" if($d); print CFG $pfx."Title[".$t."]: $n"; print CFG " (".$ifp->{$k}->{ip}.")" if($ifp->{$k}->{ip}); print CFG ": ".$descr." $d\n"; print CFG $pfx."PageTop[".$t."]: