#!/usr/bin/perl use Net::SNMP; use IO::Handle; use POSIX ":sys_wait_h"; pipe(PARENT,CHILD); CHILD->autoflush(1); sub WalkCAM { my ($ip, $uplinks, $CAM) = @_; #my $sth = $dbh->prepare( "SELECT mark_port_seen( ?, ?, ? )" ); my ( $session, $error ); # Since the script tends to fail every once in a while, retry the command # a bunch of times. for ( my $testCount = 0; $testCount < 10; $testCount++ ) { ($session, $error) = Net::SNMP->session( -hostname => $ip, -community => 'six0csh' ); if ( defined($session) ) { last; } # if we failed, wait ten seconds sleep( 10 ); } if (!defined($session)) { printf("ERROR: %s.\n", $error); exit 1; } my $dot1dBasePortIfIndex = '1.3.6.1.2.1.17.1.4.1.2'; my $ifName = '1.3.6.1.2.1.31.1.1.1.1'; my $dot1dTpFdbPort = '1.3.6.1.2.1.17.4.3.1.2'; $result = $session->get_table( -baseoid => $dot1dBasePortIfIndex ); if (!defined($result)) { printf("ERROR: %s.\n", $session->error); $session->close; exit 1; } %FdbPorts = (); while( ($key, $value) = each %$result ) { $key =~ /.*\.(\d+)$/; $FdbPorts{$1} = $value; #print "$ip\t" . $FdbPorts{$1} . " = " . $value . "\n"; }; $result = $session->get_table( -baseoid => $ifName ); %IfNames = (); while( ( $key, $value ) = each %$result ) { $key =~ /.*\.(\d+)$/; $IfNames{$1} = $value; #print "$ip\t$1 = $value\n"; }; $result = $session->get_table( -baseoid => $dot1dTpFdbPort ); while( ( $key, $value ) = each %$result ) { $key =~ /.*(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)$/; if( $IfNames{$FdbPorts{$value}} ) { $mac = sprintf( "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", $1, $2, $3, $4, $5, $6 ); $port = $IfNames{$FdbPorts{$value}}; ##$sth->execute( $mac, $ip, $port ); #($c) = $sth->fetchrow(); #print( "$mac\t$ip\t$port\t$c\n" ); #$sth->finish(); #print "$ip\tCam: $mac / $ip;$port\n"; if( !$$uplinks{$ip . ';'. $port} ) { $$CAM{$mac} = $ip . ';' . $port; print CHILD "$mac $ip;$port\n"; } } }; $session->close; }; my %uplinks = ( "129.21.61.252;Fa0/13" => 1, "129.21.61.252;Fa0/5" => 1, "129.21.61.251;Fa0/24" => 1, "129.21.61.250;Fa0/24" => 1, "129.21.61.249;Fa0/24" => 1, "129.21.61.248;Fa0/24" => 1, "129.21.61.252;Fa1/1" => 1, "129.21.61.243;Fa0/1" => 1, "129.21.61.241;Fa2/1" => 1, "129.21.61.241;Fa0/16" => 1, "129.21.61.252;Fa0/15" => 1, "129.21.61.241;Fa0/15" => 1, "129.21.61.242;Fa0/23" => 1, "129.21.61.242;Fa0/24" => 1, "129.21.61.252;Fa0/12" => 1, "129.21.61.252;Fa0/14" => 1, ); my %CAM = (); my %pids; for my $i (241..243,248..252) { my $pid; if ($pid = fork()) { #push(@pids, { pid => $pid, ip => "129.21.61.$i" } ); $pids{$pid} = "129.21.61.$i"; } else { #print "Walking 129.21.61.$i\n"; WalkCAM("129.21.61.$i", \%uplinks, \%CAM); close(CHILD); exit(0); } } close(CHILD); $SIG{CHLD} = sub { my $p; $p = waitpid(-1, 0); #print "Child $p (" . $pids{$p} . ") is done\n"; }; #foreach (@pids) { #my $p = $_->{pid}; #my $ip = $_->{ip}; #print "Done reading data from $p\n"; #print "Waiting on $p ($ip) to finish\n"; #waitpid($p, 0); #print "Pid $p ($ip) finished\n"; #} while () { chomp(); split(" ", $_, 2); $CAM{$_[0]} = $_[1]; #print "$_[0] = $_[1]\n"; } if (scalar(@ARGV) > 0) { foreach (@ARGV) { split(":",$_); my $mac = join ':', map { sprintf("%02s", $_) } @_; if (exists($CAM{$mac})) { $CAM{$mac} =~ /^([^\;]+)\;([^\;]+)$/; print( "$mac\t$1\t$2\n" ); } else { print "$mac not found\n"; } } } else { while ( ($mac, $value) = each %CAM ) { $value =~ /^([^\;]+)\;([^\;]+)$/; print( "$mac\t$1\t$2\n" ); } } exit 0;