Skip to content

Instantly share code, notes, and snippets.

@rbenigno
Last active July 31, 2022 16:32
Show Gist options
  • Save rbenigno/b78aef90d124bec65858 to your computer and use it in GitHub Desktop.
Save rbenigno/b78aef90d124bec65858 to your computer and use it in GitHub Desktop.
Use SNMP to dump mac address to port mappings from a switch
#!/usr/bin/perl
#
# Purpose: Dump mac address to port mappings from a switch
#
# Usage: ./dump_mac_table.pl <switch ip/hostname> [community]
#
# Requires:
# - CPAN SNMP::Info module (hint: cpan SNMP::Info)
# - Cisco SNMP MIBs
# ftp://ftp.cisco.com/pub/mibs/v1/v1.tar.gz
# ftp://ftp.cisco.com/pub/mibs/v2/v2.tar.gz
# hint: use "net-snmp-config --default-mibdirs" to find the MIB search paths
#
use SNMP::Info;
# Gather and check command line argeuments
my ($switch, $community) = @ARGV;
die "Usage: $0 <switch ip/hostname> [community]\n" if $#ARGV < 0;
# If no community passed, assume public
$community = "public" if !defined $community;
# Connect to switch via SNMP v2 - die if no data is retrieved
my $switchinfo = new SNMP::Info (
AutoSpecify => 1,
Debug => 0,
DestHost => $switch,
Community => $community,
Version => 2
);
die "No data retrieved from \"$switch\" using community \"$community\"\n" if !defined $switchinfo;
# use Data::Dumper qw(Dumper);
# print Dumper \$switchinfo;
# my $class = $switchinfo->class();
# print "Using device sub class : $class\n";
# Get switch name
my $switchname = $switchinfo->name();
# Get VLANs
my $vlans = $switchinfo->v_index();
# Tables must be retrieved on a per VLAN basis, so we loop through all vlans,
# using the SNMP community for VLAN targeting
foreach my $entry (keys %$vlans) {
my $vlan_id = $vlans->{$entry};
# Skip unsup vlans
if ($vlan_id ~~ [ 1002, 1003, 1004, 1005]) {next;}
# Connect to switch / VLAN via SNMP v2 - warn if no data is retrieved
my $switchinfo = new SNMP::Info (
AutoSpecify => 1,
Debug => 0,
DestHost => $switch,
Community => "$community\@$vlan_id",
Version => 2
);
if (!defined $switchinfo) {
warn "No data retrieved from \"$switch\" using community \"$community\@$vlan_id\"\n";
next;
}
# Get the info we need to build user friendly mac>port output
my $fw_mac = $switchinfo->fw_mac(); # dot1dTpFdbAddress - hash of forwarding table macs
my $fw_port = $switchinfo->fw_port(); # dot1dTpFdbPort - hash of forwarding table port iid
my $bp_index = $switchinfo->bp_index(); # dot1dBasePortEntry - hash of bridge port table entries map back to iid
my $interfaces = $switchinfo->interfaces(); # Map of iids to friendly port names
# Loop through forwarding table and print out the mac, switch name and port
foreach my $fw_index (keys %$fw_mac){
my $mac = $fw_mac->{$fw_index};
my $bp_id = $fw_port->{$fw_index};
my $iid = $bp_index->{$bp_id};
my $port = $interfaces->{$iid};
if ($port) {print "$mac\t$switchname\t$port\n";}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment