MAC finder script


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 http://standards-oui.ieee.org/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) https://yurisk.info/scripts/mac-finder.py
Script AND mac database from nmap project - https://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.