Created
July 11, 2020 06:19
-
-
Save ezr/e76060f969b5c2817395e524b5cbdad2 to your computer and use it in GitHub Desktop.
Converts an IPv6 link-local address to a MAC address
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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