This is a small tool using Tinyscript for finding the organization associated with a given OUI or MAC address.
$ pip install tinyscript
$ tsm install oui
This is a small tool using Tinyscript for finding the organization associated with a given OUI or MAC address.
$ pip install tinyscript
$ tsm install oui
| #!/usr/bin/python3 | |
| from tinyscript import * | |
| from tinyscript.helpers import Path, TempPath | |
| __script__ = "OUI/MAC Organization Finder" | |
| __author__ = "Alexandre D'Hondt" | |
| __email__ = "[email protected]" | |
| __version__ = "1.3" | |
| __copyright__ = ("A. D'Hondt", 2021) | |
| __license__ = "gpl-3.0" | |
| __doc__ = """ | |
| This tool returns the organization name associated to an input OUI or MAC address. | |
| """ | |
| __examples__ = ["50:e0:85:01:23:45", "9C-3E-53-01-23-45 -u", "-a ab:cd:ef=\"Curious Device\""] | |
| PATH_OUI_DB = Path(__file__).dirname.joinpath("oui.tsv") | |
| PATH_XTRA_OUI_DB = Path(__file__).dirname.joinpath("oui-extra.tsv") | |
| TEMP_OUI_DB = TempPath().tempfile() | |
| URL_OUI_DB = "https://standards-oui.ieee.org/" | |
| def add_extra_oui(entry): | |
| new_oui, new_org = list(map(lambda x: x.strip(), entry.split("=", 1))) | |
| new_oui = re.sub(r"[-_:]", "", new_oui.upper())[:6] | |
| with PATH_XTRA_OUI_DB.open('a+') as f: | |
| f.seek(0) | |
| for l in f: | |
| oui, org = l.strip().split("\t", 1) | |
| if new_oui == oui: | |
| logger.warning("OUI '%s' already exists (%s)" % (oui, org)) | |
| return | |
| f.write("%s\t%s\n" % (new_oui, new_org)) | |
| logger.info("OUI '%s' added (%s)" % (new_oui, new_org)) | |
| def eui_or_oui(oui): | |
| if re.match("(?i)[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", oui) or \ | |
| re.match("(?i)[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2})$", oui): | |
| oui = re.sub(r"[-_:]", "", oui.upper())[:6] | |
| logger.debug(f"Target OUI: {oui}") | |
| org = open_db().get(oui) | |
| if org: | |
| print(org) | |
| else: | |
| logger.failure("OUI not found") | |
| return | |
| raise ValueError("Not an OUI or MAC address") | |
| def open_db(): | |
| if not PATH_OUI_DB.exists(): | |
| update_db(True) | |
| logger.debug("Opening OUI database...") | |
| db = {} | |
| with PATH_OUI_DB.open('rt') as f: | |
| for l in f: | |
| oui, org = l.split("\t", 1) | |
| db[oui] = org.rstrip("\n") | |
| if PATH_XTRA_OUI_DB.exists(): | |
| with PATH_XTRA_OUI_DB.open('rt') as f: | |
| for l in f: | |
| if l.strip().startswith("#") or l.strip() == "": | |
| continue | |
| oui, org = l.split("\t", 1) | |
| db[oui] = org.rstrip("\n") | |
| return db | |
| def search_ouis(pattern): | |
| ouis = [] | |
| for oui, org in open_db().items(): | |
| if re.search(pattern, org, re.I): | |
| ouis.append((oui, org)) | |
| for oui in sorted(ouis): | |
| print("%s\t%s" % oui) | |
| def update_db(new=False): | |
| logger.debug("%s OUI database..." % ["Updating", "Downloading"][new]) | |
| data = "" | |
| with requests.get(URL_OUI_DB, headers={'User-Agent': "OUI Lookup Tool"}, stream=True) as resp: | |
| resp.raise_for_status() | |
| with TEMP_OUI_DB.open('wb') as f: | |
| for chunk in resp.iter_content(chunk_size=8192): | |
| f.write(chunk) | |
| with TEMP_OUI_DB.open('rt') as f: | |
| for l in f: | |
| l = l.strip() | |
| m = re.match(r"([0-9A-F]{6})\s+\(base 16\)\t+(.*)$", l) | |
| if m: | |
| data += "%s\t%s\n" % (m.group(1), m.group(2)) | |
| with PATH_OUI_DB.open('wt') as f: | |
| f.write(data.rstrip("\n")) | |
| if __name__ == '__main__': | |
| parser.add_argument("oui", nargs="?", type=eui_or_oui, help="OUI or complete MAC address") | |
| parser.add_argument("-a", "--add", type=add_extra_oui, help="add a custom OUI with its organization name", | |
| note="format is \"XXXXXX=orgname\" (with XXXXXX the OUI without separator)") | |
| parser.add_argument("-s", "--search", type=search_ouis, help="search for OUIs given a pattern of organization") | |
| parser.add_argument("-u", "--update", dest="update", action="store_true", help="update the OUI database", | |
| note="DB source is %s" % URL_OUI_DB) | |
| initialize(noargs_action="usage") | |
| if args.update is True: | |
| update_db() |