How to replace host part of IPv6 address using Python
In our previous post Bitwise operation with IPv6 addresses and networks in Python we showed how to perform bitwise operations in Python using the ipaddress
module. In this post we will use this previous work to replace just the host part of an IPv6 address, leaving the network part as-is - in other words, we will combine two IPv6 addresses together using a configurable network prefix length.
import ipaddress
def bitwise_and_ipv6(addr1, addr2):
result_int = int.from_bytes(addr1.packed, byteorder="big") & int.from_bytes(addr2.packed, byteorder="big")
return ipaddress.IPv6Address(result_int.to_bytes(16, byteorder="big"))
def bitwise_or_ipv6(addr1, addr2):
result_int = int.from_bytes(addr1.packed, byteorder="big") | int.from_bytes(addr2.packed, byteorder="big")
return ipaddress.IPv6Address(result_int.to_bytes(16, byteorder="big"))
def bitwise_xor_ipv6(addr1, addr2):
result_int = int.from_bytes(addr1.packed, byteorder="big") ^ int.from_bytes(addr2.packed, byteorder="big")
return ipaddress.IPv6Address(result_int.to_bytes(16, byteorder="big"))
def replace_ipv6_host_part(net_addr, host_addr, netmask_length=64):
# Compute bitmasks
prefix_network = ipaddress.IPv6Network(f"::/{netmask_length}")
hostmask = prefix_network.hostmask # ffff:ffff:ffff:ffff:: for /64
netmask = prefix_network.netmask # ::ffff:ffff:ffff:ffff for /64
# Compute address
net_part = bitwise_and_ipv6(net_addr, netmask)
host_part = bitwise_and_ipv6(host_addr, hostmask)
# Put together resulting IP
return bitwise_or_ipv6(net_part, host_part)
# Usage example:
# IP address from which we take the network part ("prefix")
net_addr = ipaddress.IPv6Address("2a01:c22:6f71:9f00:8ce6:2eff:fe60:cc69")
# IP address from which we take the host part (suffix)
host_addr = ipaddress.IPv6Address("::dead:babe:cafe:0000")
print(replace_ipv6_host_part(net_addr, host_addr))
This prints
IPv6Address('2a01:c22:6f71:9f00:dead:babe:cafe:0')