[c-nsp] Getting ARP table from SNMP

Bill Nash billn at billn.net
Tue Oct 17 12:51:11 EDT 2006


On Tue, 17 Oct 2006, Laurent Geyer wrote:

> Exactly what I'm doing. I don't have the CAM portion of it finished just yet
> but I'm getting there. Too much ops crap to deal with right now to finish
> what I started :(
> 
> Mind sharing what you have?
> 

I sent this to Laurent earlier, but I'll repost here because it's 
interesting. 

Caveats: 
- This code is old. I wrote this about five years ago. It's also 
for CatOS only. If it doesn't work out of the box, well, congratulations, 
you have broken code. I coded for readability over cleverness. Sorry.
- Pasting it into Pine makes it look like Prince Charles. It mostly only 
affects the comments.
- Database inserts are a problem that aren't addressed by this code. I 
officially declare it to be 'your problem.'

This can be modified to work with IOS. For all object fetches besides the 
initial ifDescr poll, you need to instantiate a new session on a per vlan 
basis, which means you'll have to poll a list of vlans from somewhere, or 
glean them from the ifDescr strings with regexp. I don't know why Cisco 
did this, but needless to say, it pisses me off:

my ($vlan_session, $error) = Net::SNMP->session(
                        -timeout        => $seconds,
                        -community      => $snmpRead ."@". $vlanNumber,
                        -hostname       => $hostname,
                );

Cheers.

- billn

------


my($target_oid, $result, %names, %names_rev, %fdbp);
          my ($session, $error) = Net::SNMP->session(
                                  -hostname      => $args{target},
                                  -community     => $args{community}
                               );

          if($session) {
		# Catalyst flavored ifDescr, abstracted in the oids table 
as ifName
                $target_oid = q(.1.3.6.1.2.1.31.1.1.1.1);
                if ( defined($result = $session->get_table(-baseoid => 
$target_oid))) {
                        foreach $oid (keys(%{$result})) {
                                $value = $result->{$oid};
                                $oid =~ s/$target_oid.//;
                                $names{$oid} = $value;
                                $names_rev{$value} = $oid;
                        }
                        print scalar(keys %names) . ' named 
interfaces/vlans found.
';
                }
                else { print qq(Error retrieving ifNames: $error); }

		# dot1dBasePortIfIndex - BRIDGE-MIB
		# The value of the instance of the ifIndex object,
		# defined in MIB-II, for the interface corresponding
		# to this port.
		# billn - We use this part to correlate the bridge 
indexing to the interface ifIndex's
		# note that we're setting the actual value of %fdpb{oid} 
to the MIB2's ifDescr 
                $target_oid = qq(.1.3.6.1.2.1.17.1.4.1.2);
                if ( defined($result = $session->get_table(-baseoid => 
$target_oid))) {
                        foreach $oid (keys(%{$result})) {
                                $value = $result->{$oid};
                                $oid =~ s/$target_oid.//;
                                $fdbp{$oid} = $names{$value};
                        }
                }
                else { print qq(Error retrieving fdbp->ifIndex 
$target_oid: $error
) if ($error); }

		# vtpVlanState - CISCO-VTP-MIB
		# We're polling this mostly just to get an index of vlans
                $target_oid = q(.1.3.6.1.4.1.9.9.46.1.3.1.1.2);
                if ( defined($result = $session->get_table(-baseoid => 
$target_oid))) {
                        foreach $oid (keys(%{$result})) {
                                $value = $result->{$oid};
                                $oid =~ s/$target_oid.1.//;
                                $vlans{$oid}{status} = $value;
                        }
                        print scalar(keys %vlans) . ' vlans found.
';

		# dot1dTpFdbAddress - BRIDGE-MIB
		# A unicast MAC address for which the bridge has
		# forwarding and/or filtering information.

                $target_oid = qq(.1.3.6.1.2.1.17.4.3.1.1);
                	if ( defined($result = 
$session->get_table(-baseoid => $target_oid))) {
       	                	 foreach $oid (keys(%{$result})) {
       	                	         $value = $result->{$oid};
       	                	         $oid =~ s/$target_oid.//;
       		                         $vfdb{$oid} = $value;
       	                         }
                        }
                        else {
                                print qq(Error retrieving vfdb $target_oid 
for vlan $vlan: $error
) if ($error);
                        }
                }
                else { print qq(Error retrieving vtpVlanState: $error); }


		# dot1dTpFdbPort - BRIDGE-MIB
		# Either the value '0', or the port number of the
		# port on which a frame having a source address
		# equal to the value of the corresponding instance
		# of dot1dTpFdbAddress has been seen.
		#
		# billn - This is what ties our correlation together. This 
object returns learned MAC
		# addresses, indexed by bridge port indexes. We mapped 
those to ifMib indexes earlier, 
		# so we assemble the finished product here:
		# [ Port Name ] -> [ IfIndex] -> [ Bridge Port Index ] -> 
[ Learned Mac Addresses ]
		# Note, there can be more than one learned MAC, especially 
if the interface is connected to another
		# bridging device (switch, hub) or is a trunk to a 
router/switch.

                $target_oid = qq(.1.3.6.1.2.1.17.4.3.1.2);
                if ( defined($result = $session->get_table(-baseoid => 
$target_oid))) {
                        foreach $oid (keys(%{$result})) {
                                $value = $result->{$oid};
                                $oid =~ s/$target_oid.//;
                                $ports{ $fdbp{$value} }{ $vfdb{$oid} } = 
$oid;
                                $vfdb{$oid} = $value;
                        }
                }
                else { print qq(Error retrieving fdbp $target_oid: $error
) if ($error); }

                foreach $port (sort keys %ports) {
                	foreach $mac (sort keys %{$ports{$port}}) {
                       		@output = ();
                       		$mac =~ s/^0x//;
                       		@stack = unpack(qq(A2A2A2A2A2A2), $mac);
                       		$mac = join(q(:), @stack);
				push (@{$return[ $names_rev{$value} ]}, 
$mac);
                       	}
                }
          }


More information about the cisco-nsp mailing list