Justin Azoff

Hi! Random things are here :-)

normalizing ipv6 addresses

One of the first steps in groking ipv6 is getting a handle on ipv6 addresses.

The ‘dotted quad’ notation for ipv4 is fairly simple, and other than possible zero padding issues, they all look the same. ipv6 addresses are a bit different. Rather than a dotted quad they are 8 hex groups, and there are a lot of rules for displaying the addresses. For working with ipv6 addresses there are two options:

  • Convert them to a 16 byte string
  • Normalize them

There are some very nice libraries for working with ip addreses, but the low level socket functions can be used to convert and normalize:

>>> import socket
>>> bytes=socket.inet_pton(socket.AF_INET6, "2001:4860:800f:0:0:0:0:0063")
>>> bytes
' \x01H`\x80\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00c'
>>> 'we can see that the data is the same:'
>>> binascii.hexlify(bytes)
'20014860800f00000000000000000063'
>>> print socket.inet_ntop(socket.AF_INET6, bytes)
2001:4860:800f::63

We can make a simple fuction to do that:

def normalize(ip):
    bytes=socket.inet_pton(socket.AF_INET6, ip)
    return socket.inet_ntop(socket.AF_INET6, bytes)

You can see some of the weird normalization rules in action:

>>> print normalize("2001:4860:800f:0:0:0:0:0063")
2001:4860:800f::63
>>> print normalize("::ffff:c000:280")
::ffff:192.0.2.128
>>> print normalize("ff02:0:0:0:0:0:0:1")
ff02::1