Every vendor has their favourite format for MAC addresses and it is common to need to create strings to pass as CLI commands. This post shows to check the string is a valid address and how to convert between formats.
If you run HPE/Aruba switches the discussion on custom formats will be useful.
The python library netaddr manipulates IP and MAC addresses. The code below uses it together with some validation to show how you can get a different format of MAC address from an input. The input here is via a prompt to demonstrate the code but this could easily be a variable. You can easily imagine, given a MAC address in a variable, that the CLI command needed for both a cisco and HP switch could be created.
There is a validation in the netaddr library through the valid_mac function which does validate to an extent but with results that I didn’t like. For example it would validate as true a string of 11 characters (e.g. 12345678901):
print (valid_mac(input("mac?"))) user@net-ansible:$ python macfind2.py mac?12345678901 True
The netaddr library doesn’t validate for regular functions such as when you change format and so you could in theory enter a MAC address “0123” at it be interpreted as “00-00-00-00-00-7B”
The CheckMac function in my code checks that the number of characters is 12 and that there are no non-hex characters. This might help in rare cases to ensure the input is truly correct rather than mathematically correct.
The main function (printMacs) validates the input string and then prints each of the formats, including the two custom ones. It then prints the OUI details if an entry in the database is found. This is a crude way to work out the manufacturer of a NIC card and might be a useful clue if providing info to a user.
from netaddr import * class mac_comware(mac_cisco): pass mac_comware.word_sep = '-' mac_comware.word_size = 16 class mac_procurve(mac_pgsql): pass mac_procurve.word_sep = '-' mac_procurve.word_size = 24 hexChars = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"] def CheckMac(mac1): #returns false if valid badMac=False mac2=mac1.translate(str.maketrans('', '', '-:_')) #strips normal chars if len(mac2) < 12: badMac=True for i in mac2.lower(): if i not in hexChars : badMac=True return badMac def printMacs(mac1): if CheckMac(mac1) == True: print(mac1 + " is NOT a valid MAC") else: print ("original: " + str(mac1)) print ("mac_cisco: " + str(EUI(mac1, dialect = mac_cisco))) print ("mac_unix_expanded: " + str(EUI(mac1, dialect = mac_unix_expanded))) print ("mac_bare: " + str(EUI(mac1, dialect = mac_bare))) print ("mac_pgsql: " + str(EUI(mac1, dialect = mac_pgsql))) print ("mac_unix: " + str(EUI(mac1, dialect = mac_unix))) print ("mac_eui: " + str(EUI(mac1))) print ("mac_comware: " + str(EUI(mac1, dialect = mac_comware))) print ("mac_procurve: " + str(EUI(mac1, dialect = mac_procurve))) try: #needed because easy to get an exception when a MAC isn't registered in OUI db print (EUI(mac1).oui.registration().org) except Exception: pass print ("can't find MAC in database") printMacs(input("mac?"))
You can create your own dialects as per the two examples in my code. These use two other dialects and alter (in this case changing the character between blocks of the MAC address). A little documentation is found here.
A couple of example outputs below:
user@net-ansible:$ python macfind2.py mac?005000112233 original: 005000112233 mac_cisco: 0050.0011.2233 mac_unix_expanded: 00:50:00:11:22:33 mac_bare: 005000112233 mac_pgsql: 005000:112233 mac_unix: 0:50:0:11:22:33 mac_eui: 00-50-00-11-22-33 mac_comware: 0050-0011-2233 mac_procurve: 005000-112233 NEXO COMMUNICATIONS, INC. mac?123456789123 original: 123456789123 mac_cisco: 1234.5678.9123 mac_unix_expanded: 12:34:56:78:91:23 mac_bare: 123456789123 mac_pgsql: 123456:789123 mac_unix: 12:34:56:78:91:23 mac_eui: 12-34-56-78-91-23 mac_comware: 1234-5678-9123 mac_procurve: 123456-789123 can't find MAC in database mac?12345678901 12345678901 is NOT a valid MAC mac?000000000000t 000000000000t is NOT a valid MAC