Wednesday, August 19, 2009

Retrieve ARP table from Cisco router, parse, spew

I had a colleague in need of an automated way to retrieve the ARP table from a lot of Cisco routers and format the output in a spreadsheet. Another colleague suggested using an Expect script, which is definitely cool because I love using Expect (seriously, it's a Swiss Army knife), but I wanted to take it a different direction. I looked up the SNMP MIB to retrieve the ARP table and then parsed the input to provide a two-column output consisting of the IP address and MAC address, one pair per line.

Here is the script:

snmpwalk -t 60 -v 1 -c MYCOMMSTRING routerhostname .1.3.6.1.2.1.4.22.1.2 | \
while read line; do \
IP_ADDR=`echo ${line} | \
awk '{print $1;}' | \
sed -e 's/^IP-MIB::ipNetToMediaPhysAddress.[0-9]*\.//'`; \
MAC_ADDR=`echo ${line} | \
awk '{print $4;}' | \
sed -e 's/^\([0-9a-f]\)/0\1/' \
-e 's/:\([0-9a-f]\):/:0\1:/g' \
-e 's/:\([0-9a-f]\):/:0\1:/g' \
-e 's/:\([0-9a-f]\)$/:0\1/' | \
tr '[:lower:]' '[:upper:]'`; \
echo "${IP_ADDR} ${MAC_ADDR}"; \
done


Notice that there are two mid-string sed matches, each with a 'g' matching command. The reason that this command needs to be listed twice is that a single iteration of 'g' doesn't mean global, it means to match up to two addresses within the stream. Since some of the MAC addresses I was dealing with were beyond that, such as "0:d:ed:c:7:5e", just using a single mid-string pattern with 'g' left me with "00:0d:ed:0c:7:5e" (note the :7: instead of the desired :07:). Adding the second iteration of mid-string matching fixed this issue by enabling matching of a third and fourth mid-string single-digit. I learned something new about sed, and learning something new is a good thing.

1 comment:

GB Hoyt said...

hmmm, I just realized you could put most of that on a single line. thanks for breaking it up!
very readable.