Skip to content

Instantly share code, notes, and snippets.

@jk
Created April 22, 2024 09:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jk/8059901cb79a75a1b33e0b6965d89e5a to your computer and use it in GitHub Desktop.
Save jk/8059901cb79a75a1b33e0b6965d89e5a to your computer and use it in GitHub Desktop.
Generate IPv6 address from IPv6 prefix and interface's MAC address

Generate IPv6 address from IPv6 prefix and interface's MAC address

More or less like what SLAAC is doing, but without relying on the router advertisment.

Installation

pip install netifaces

Usage

python ./generate-ipv6.py "eth0" "2001:db8:abcd"
import netifaces as ni
import re
import argparse
import ipaddress
def get_mac_address(interface):
try:
interface_details = ni.ifaddresses(interface)
mac_address = interface_details[ni.AF_LINK][0]['addr']
return mac_address
except (ValueError, KeyError):
raise ValueError(f"No MAC address found for interface {interface}")
def mac_to_eui64(mac, ipv6_network):
# Remove any non-hexadecimal characters from MAC
mac = re.sub(r'[^0-9a-fA-F]', '', mac)
mac_bytes = bytes.fromhex(mac)
# Flip the universal/local bit of the MAC address
mac_bytes = bytearray(mac_bytes)
mac_bytes[0] ^= 0b00000010
# Insert ff:fe in the middle of the MAC to form EUI-64
eui64 = mac_bytes[:3] + b'\xff\xfe' + mac_bytes[3:]
eui64 = int.from_bytes(eui64, byteorder='big')
# Calculate full IPv6 address within the network
full_ipv6_address = ipaddress.IPv6Address(ipv6_network.network_address + eui64)
return full_ipv6_address
def main():
parser = argparse.ArgumentParser(description="Generate an IPv6 address from a network device MAC address and an IPv6 prefix with a network mask.")
parser.add_argument("interface_name", type=str, help="Network interface name")
parser.add_argument("ipv6_network", type=str, help="IPv6 network with prefix, e.g., xxxx:xxxx:xxxx::/xx")
args = parser.parse_args()
try:
ipv6_network = ipaddress.IPv6Network(args.ipv6_network, strict=False)
mac_address = get_mac_address(args.interface_name)
ipv6_address = mac_to_eui64(mac_address, ipv6_network)
print(f"Generated IPv6 Address: {ipv6_address} from MAC Address: {mac_address}")
except ValueError as e:
print(e)
except ipaddress.AddressValueError as ave:
print("Error: Invalid IPv6 network format.")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment