[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