Bitwise operation with IPv6 addresses and networks in Python
Python3 features the easy-to-use ipaddress library providing many calculations. However, bitwise boolean operators are not available for addresses.
This post shows you how to perform bitwise operations with IPv6Address()
objects. We’ll use the following strategy:
- Use
.packed
to get a binary bytes() instance of the IP address - Use
int.from_bytes()
to acquire an integer representing the binary address - Perform bitwise operations with said integer
- Use
result.to_bytes(16, ...)
to convert back the integer to abytes()
array in the correct byte order - Construct an
IPv6Address()
object from the resulting byte array.
Python code:
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"))
Example usage:
a = ipaddress.IPv6Address('2001:16b8:2703:8835:9ec7:a6ff:febe:96b1')
b = ipaddress.IPv6Address('2001:16b8:2703:4241:9ec7:a6ff:febe:96b1')
print(bitwise_and_ipv6(a, b)) # IPv6Address('2001:16b8:2703:1:9ec7:a6ff:febe:96b1')
print(bitwise_or_ipv6(a, b)) # IPv6Address('2001:16b8:2703:ca75:9ec7:a6ff:febe:96b1')
print(bitwise_xor_ipv6(a, b)) # IPv6Address('0:0:0:ca74::')
Similarly, you can use the code in order to manipulate IPv6Network()
instances:
a = ipaddress.IPv6Network('2001:16b8:2703:8835:9ec7:a6ff:febe::/112')
b = ipaddress.IPv6Network('2001:16b8:2703:4241:9ec7:a6ff:febe::/112')
print(bitwise_and_ipv6(a.network_address, b.network_address)) # IPv6Address('2001:16b8:2703:1:9ec7:a6ff:febe:0')
print(bitwise_or_ipv6(a.network_address, b.network_address)) # IPv6Address('2001:16b8:2703:ca75:9ec7:a6ff:febe:0')
print(bitwise_xor_ipv6(a.network_address, b.network_address)) # IPv6Address('0:0:0:ca74::')
Note that the return type will always be IPv6Address()
and never IPv6Network()
since the result of the bitwise operation doesn’t have any netmask associated with it.
Besides .network_address
you can also use other properties of IPv6Address()
instances like .broadcast_address
or .hostmask
or .netmask
.