#!/usr/bin/perl ################################################################### #@swl3 = ("swcorebb1", "swlat", "lnfgw10" ); @swl3 = ("swcorebb1.lnf.infn.it", "lnfgw10.lnf.infn.it", "swscienza.lnf.infn.it", "swlat.lnf.infn.it", "swkloe.lnf.infn.it", "172.30.0.2"); $sw4vlan = "swcorebb1"; ################################################################### $SNMPWALK = 'snmpwalk -O n -v1 -c'; #port LOW -> port HI 17.1.4.1.2 #port HI -> port name .iso.3.6.1.2.1.31.1.1.1.1 #is in cdp enterprises.9.9.23.1.2.1.1.6 use Socket; use POSIX; $| = 1; ( $switch = $ARGV[0] ) =~ s/\r|\n//g; ( $mac = $ARGV[1] ) =~ s/\r|\n//g; unless ( $switch && $mac ) { ( $scrname = $0 ) =~ s/.+\///g; print ' Usage: '.$scrname.' The hostname or IP of the switch to start from The hostname or IP or mac-address to search '; exit; } foreach ( split ( /\n/, `$SNMPWALK public $sw4vlan .iso.3.6.1.4.1.9.9.46.1.3.1.1.4` ) ) { /^.+\.(\d+) =\sSTRING: \"(.+)\"/; next if $2 eq 'fddi-default' || $2 eq 'token-ring-default' || $2 eq 'fddinet-default' || $2 eq 'trnet-default'; $vlans{$1} = $2; } $community = 'public'; $imac = $mac; $addr = gethostbyname($mac); print "\n"; if ( $addr ) { $addr = join ( '.', unpack('C4',$addr)); $addrname = gethostbyaddr(inet_aton($addr), AF_INET);; print "Host Name: $addrname\n"; print "Host IP: $addr\n"; print "Status: "; `ping -c2 -w5 $addr`; print "UP.\n" if !$?; print "seems DOWN.\n" if $?; foreach ( @swl3 ) { $l3from = $_; $mac = lc(`$SNMPWALK $community $_ .iso.3.6.1.2.1.3.1.1.2 | grep '$addr = Hex-STRING' 2>/dev/null`); last if $mac; } if (!$mac) { print "mac-address of '$imac' not found\n"; exit 1; } print "Layer3 from: $l3from\n"; $mac =~ s/^.+\.(\d+)\.\d+\.$addr =\s+hex-string: (.+)\s*\n$/$2/g; $mac =~ s/\s//g; } else { ( $mac = lc($mac) ) =~ s/[^0-9a-f]//g; if ( length($mac) < 12 ) { print "'$imac' is not hostname or mac-address\n"; exit 1; } ( $macsp = uc($mac) ) =~ s/(.{2})/$1 /g; fe: foreach ( @swl3 ) { $swl32s = $l3from = $_; open ( SNMP, "$SNMPWALK $community $swl32s .iso.3.6.1.2.1.3.1.1.2 | " ); wh: while ( ) { next unless /Hex-STRING: $macsp\s*$/; s/^.+\.(\d+\.\d+\.\d+\.\d+)\s+=\s+.+$/$1/; s/\n|\r//g; $addr = $_; $addrname = gethostbyaddr(inet_aton($addr), AF_INET);; print "Host Name: $addrname\n"; print "Host IP: $addr\n"; print "Layer3 from: $l3from\n"; print "Status: "; `ping -c2 -w5 $addr`; print "UP.\n" if !$?; print "seems DOWN.\n" if $?; } close ( SNMP ); last fe if $addr; } } print "Mac-addr: ".mac_conv($mac)."\n"; #print "Interface: $mvlan\n" if $mvlan; $cmac = cmac(mac_conv($mac)); $neighb = $switch; $vlok = 0; $space = 3; while ( $neighb ne '' ) { if ( !$vlok ) { foreach ( keys(%vlans) ) { $vln = $_; $community = 'public@'.$_ ; $community = 'public' if $_ == 1; #print "looking in $switch (".$vlans{$_}.") $community...\n"; ( $portlo = `$SNMPWALK $community $switch .1.3.6.1.2.1.17.4.3.1.2$cmac` ) =~ s/^.+ = INTEGER: |\n//g; $vlok = 1; last if $portlo; } if ( !$portlo ) { print "port for '$mac' not found\n"; exit 1; } print "Vlan: ".$vlans{$vln}." ( $vln )\n\n"; } else { print " " x (2+ $space); print "|\n"; ( $portlo = `$SNMPWALK $community $switch .1.3.6.1.2.1.17.4.3.1.2$cmac` ) =~ s/^.+ = INTEGER: |\n//g; } print " " x ($space); print "$switch "; ( $porthi = `$SNMPWALK $community $switch .1.3.6.1.2.1.17.1.4.1.2.$portlo 2>/dev/null` ) =~ s/^.+ = INTEGER: |\n//g; if (!$porthi) { print "\n" ; exit; } ( $portname = `$SNMPWALK $community $switch .iso.3.6.1.2.1.31.1.1.1.1.$porthi` ) =~ s/^.+ = STRING: |\n//g; $realportname = ''; unless ( `$SNMPWALK $community $switch .iso.3.6.1.4.1.9.9.98.1.1.1.1.8.$porthi` ) { #print "Port $porthi not exists\n"; $realportapp = `$SNMPWALK $community $switch .iso.3.6.1.4.1.9.9.98.1.1.1.1.8 | grep ' = INTEGER: $porthi'`; foreach ( split (/\n/, $realportapp) ) { s/^.+\.(\d+) =.+$/$1/g; push (@realport, $_); } foreach ( @realport ) { #print "-->$_\n"; ( $realportnameapp = `$SNMPWALK $community $switch .iso.3.6.1.2.1.31.1.1.1.1.$_` ) =~ s/^.+ = STRING: |\n//g; $realportname .= " $realportnameapp" if $realportnameapp; $porthi = $_ } } $portname .= " ($realportname )" if $realportname; print "- $portname\n"; $space += (length($switch)+ ( ceil( length($portname) / 2 ) ) ); ( $neighb = `$SNMPWALK $community $switch .iso.3.6.1.4.1.9.9.23.1.2.1.1.6.$porthi` ) =~ s/^.+ = STRING: |\n//g; last if !$neighb; ( $switch = $neighb ) =~ s/^.+\((.+)\).*$/$1/g; $switch =~ s/\"|\.lnf\.infn\.it//g; } print " " x ( 2 + $space); print "|\n"; print " " x ($space); $addrname =~ s/\..+$//; print "$addrname\n"; sub cmac { my $mac = $_[0]; my $cmac = ''; foreach ( split(/-/, $mac) ) { $cmac .= '.'.hex $_ ; } return $cmac; } sub munge_index { my $fwt = shift; my @cols = split(/\./,$fwt); return join('-',map {sprintf("%02x",$_)} @cols); } sub mac_conv { my $mac = $_[0]; $sep = '-'; $intv = 2; $ret = ''; foreach ( split ( /(\s+)/, lc( $mac ) ) ) { s/[^a-f0-9]//g ; next if length($_) < 12; s/(.{$intv})/$1$sep/g; s/$sep\s*$//; $ret .= "$_" ; } return $ret if length($ret) > 1; }