While I don’t like going down to Layer 2 , recently I had to do it – I didn’t know IP address of the Cisco router I wanted to connect to but I had access to the Cisco router sitting in the same network. That would be pretty easy to do #show arp on this router and then search on Google to whom belongs each MAC if it wasn’t the subnet mask of /26. Copy pasting each entry of the ARP table into Google didn’t look like a lot of fun. So I wrote a python script that reads MAC addresses in bulk from command line and using downloaded beforehand database of MAC-vendor translations prints vendor for each MAC address. It works for #show arp on CIsco,#show mac-address-table on CIsco switches, #arp -en on Linux (means including Checkpoint), #arp -a on Freebsd ,#show arp of Junos from Juniper, #get sys arp on Fortigate.
Below is the script.
Here:
mac-database.txt – file containing MAC-vendor translation in format <MAC 6 hex digits as a sequence> <VENDOR>, I used standards.ieee.org/regauth/oui/oui.txt as the source with a bit of sed, but if you want ready to use file I recommend nmap-mac-prefixes from nmap source-code distribution http://nmap.org/svn/nmap-mac-prefixes
Download script (to make sure formatting is preserved, an important thing for Python)
http://yurisk.info/scripts/mac-finder.py
Script AND mac database from nmap project – http://yurisk.info/scripts/mac.tar.gz
#!/usr/bin/python
#This script accepts MAC addresses from the command line and
#prints vendor for each mac address
# Author:Yuri, yurisk@yurisk.info,06.2010
import sys
import re
#This function removes from MACs colon or dot and returns MAC as a sequence of HEX chars
def dotreplace(matchobj):
if matchobj.group(0) == '.':
return ''
elif matchobj.group(0) == ':':
return ''
#open file with MAC addresses and vendors database,it has form xxxx <Vendor>
macs=open('mac-database.txt','r')
macs_lines=macs.readlines()
#Read from stdinput
data = sys.stdin.readlines()
for ppp in data:
popa=re.search('.*([a-f0-9]{4}\.[a-f0-9]{4}\.[a-f0-9]{4}).*',ppp,re.IGNORECASE)
if popa:
newpopa=re.sub('\.', dotreplace,popa.group(1))[0:6]
newpopa_re=re.compile(newpopa,re.IGNORECASE)
for mac_db in macs_lines:
vendor=re.search(newpopa_re,mac_db)
if vendor:
print ppp.strip(),mac_db[7:]
popalinux = re.search('.*([a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}).*',ppp,re.IGNORECASE)
if popalinux:
newpopalinux=re.sub(':',dotreplace,popalinux.group(1))[0:6]
newpopalinux_re=re.compile(newpopalinux,re.IGNORECASE)
for mac_db in macs_lines:
vendor=re.search(newpopalinux_re,mac_db)
if vendor:
print ppp.strip(),mac_db[7:]
popadash = re.search('.*([a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}-[a-f0-9]{2}).*',ppp,re.IGNORECASE)
if popadash:
newpopadash=re.sub('-',dotreplace,popadash.group(1))[0:6]
newpopadash_re=re.compile(newpopadash,re.IGNORECASE)
for mac_db in macs_lines:
vendor=re.search(newpopadash_re,mac_db)
if vendor:
print ppp.strip(),mac_db[7:]
Running it:
[root@darkstar ]# ./mac-finder.py
<now I copy paste output from arp -a in BSD>
$ arp -a
(10.99.99.150) at 00:50:56:95:74:72 on em0 [ethernet]
(10.99.99.254) at 00:09:0f:31:c8:24 on em0 [ethernet]
<Hit CTRL+D to signal the end of input>
(10.99.99.150) at 00:50:56:95:74:72 on em0 [ethernet] VMware, Inc.
(10.99.99.254) at 00:09:0f:31:c8:24 on em0 [ethernet] Fortinet Inc.