Last active
April 23, 2020 11:04
-
-
Save artizirk/fb70ff49b9e259f32e3ed7e068838746 to your computer and use it in GitHub Desktop.
Generate systemd nspawn interface MAC aadresses based on the host id and container name https://wiki.wut.ee/sysadmin/systemd-nspawn_containers
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 | |
""" | |
This script implements systemd-nspawn MAC aadress generation algorithm | |
""" | |
import sys | |
import struct | |
from subprocess import run | |
import siphashc # https://pypi.org/project/siphashc/ | |
# from src/nspawn/nspawn-network.c | |
# -n,--network-veth | |
# host side of vb-/ve- interface | |
HOST_HASH_KEY = bytes.fromhex("1a376fc746ec450bada3d53106605db1") | |
# container side of vb-/ve- interface | |
CONTAINER_HASH_KEY = bytes.fromhex("c3c4f919b557b21ce6cf1427039ceea2") | |
# --network-veth-extra | |
VETH_EXTRA_HOST_HASH_KEY = bytes.fromhex("48c7f6b7ea9d4c9eb728d4de91d5bf66") | |
VETH_EXTRA_CONTAINER_HASH_KEY = bytes.fromhex("af501761cef94d35840d2b2054bece59") | |
# --network-macvlan | |
MACVLAN_HASH_KEY = bytes.fromhex("00136dbc66834481bb0cf9511f24a66f") | |
# used when interface name is too long | |
SHORTEN_IFNAME_HASH_KEY = bytes.fromhex("e190a404a8ef4b518cccc33a9f11fca2") | |
# Based on systemd src/nspawn/nspawn-network.c | |
def generate_mac(machine_id, machine_name, hash_key, idx=0): | |
if type(machine_name) == str: | |
machine_name = machine_name.encode() | |
if idx > 0: | |
v = machine_id + struct.pack('<Q', idx) + machine_name | |
else: | |
v = machine_id + machine_name | |
result = siphashc.siphash(hash_key, v).to_bytes(8, byteorder='little') | |
mac = bytearray(result[:6]) | |
mac[0] &= 0xfe; # clear multicast bit | |
mac[0] |= 0x02; # set local assignment bit (IEEE802) | |
return bytes(mac) | |
def format_mac(mac): | |
if type(mac) == bytes: | |
mac = mac.hex() | |
l = [] | |
for idx in range(0, len(mac), 2): | |
l.append(mac[idx:idx+2]) | |
return ":".join(l) | |
if __name__ == "__main__": | |
if len(sys.argv) == 3: | |
machine_id = bytes.fromhex(sys.argv[1]) | |
machine_name = sys.argv[2] | |
elif len(sys.argv) == 2: | |
machine_name = sys.argv[1] | |
machine_id_proc = run(["systemd-id128", "machine-id"], capture_output=True, text=True) | |
machine_id = bytes.fromhex(machine_id_proc.stdout.strip()) | |
else: | |
print("Usage: {} [machine-id] machine-name".format(sys.argv[0]), file=sys.stderr) | |
sys.exit(1) | |
mac = generate_mac(machine_id, machine_name, CONTAINER_HASH_KEY) | |
print(format_mac(mac)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment