Skip to content

Instantly share code, notes, and snippets.

@ezr
Created July 11, 2020 06:19
Show Gist options
  • Save ezr/e76060f969b5c2817395e524b5cbdad2 to your computer and use it in GitHub Desktop.
Save ezr/e76060f969b5c2817395e524b5cbdad2 to your computer and use it in GitHub Desktop.
Converts an IPv6 link-local address to a MAC address
#!/usr/bin/env python3
'''
thanks https://ben.akrin.com/?p=1347
To convert from an IPv6 link-local address to a MAC address:
- the 1st 64 bits go away (the fe80:: part)
- bit 71 gets flipped (after fe80:: is gone this would be the 7th bit)
- bits 89 through 112 go away (the ff:fe)
'''
import re
from sys import argv
def run_tests():
test("fe80::5074:f2ff:feb1:a87f", "52:74:f2:b1:a8:7f")
test("fe80::12c3:7bff:fef1:be70", "10:c3:7b:f1:be:70")
test("fe80::8286:88ff:fe3e:7313", "80:86:88:3e:73:13")
test("FE80::5074:F2FF:FEB1:A87F", "52:74:f2:b1:a8:7f")
test("fe80::5074:f2ff:feb1:f", "52:74:f2:b1:00:0f")
test("fe80::200:ff:fe00:0", "00:00:00:00:00:00")
test("fe80::0:ff:fe00:0", "02:00:00:00:00:00")
test("fe80::ff:fe00:0", "02:00:00:00:00:00")
def test(addr, expected):
print("testing input", addr, "expecting", expected)
result = addr_to_mac(addr)
if result == expected:
print("PASS\n")
else:
print("FAIL", result, "\n")
def addr_to_mac(addr):
# make a list like: ['5074', 'f2ff', 'feb1', '7f']
arr = addr.split(":")[-4:]
# fill in omitted zeros:
arr = list(map(lambda s: s.zfill(4), arr))
# flip the 7th bit of the 1st octect
flipped = hex(int(arr[0][:2], 16) ^ 2)[2:].zfill(2)
arr[0] = flipped + arr[0][2:]
# now arr is like : ['5274', 'f2ff', 'feb1', '007f']
# get rid of the fffe in the middle:
arr[1] = arr[1][:2]
arr[2] = arr[2][2:]
# now arr is like : ['5274', 'f2', 'fe', '007f']
mac = "".join(arr)
return ':'.join([mac[i:i+2] for i in range(0, len(mac), 2)]).lower()
if __name__ == "__main__":
if len(argv) < 2:
print("Usage: %s ADDRESS" % argv[0])
exit(1)
if argv[1] == "test":
run_tests()
exit(0)
addr = argv[1][:argv[1].rfind("/")]
if not re.match("fe80:(:[a-f0-9]{1,4}){3,4}$", addr, re.IGNORECASE):
print("Error, expected input in a format like \"fe80::5074:f2ff:feb1:a87f\"")
exit(1)
mac = addr_to_mac(addr)
print(mac)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment