pythonstruct

Ipv6 address format from struct.unpack


What would be the way to unpack and map to ipv6 address. I'm currently doing the following

In [3]: struct.unpack("!h",'*\x00')
Out[3]: (10752,)

In [5]: ipaddress.IPv6Address(10752)
Out[5]: IPv6Address(u'::2a00')

but of course the end result i wish for is 2a00:: , i was expecting IPv6Address to return it but i'm missing something.

What i'm currently doing is unpacking as sting then to hex and append :: .

In [14]: struct.unpack("!2s",'*\x00')
Out[14]: ('*\x00',)

In [15]: '*\x00'.encode("hex")
Out[15]: '2a00'

then append to hex and append 

In [16]: '*\x00'.encode("hex")+'::'
Out[16]: '2a00::'

Solution

  • The IP adress converts what we could see as a binary number into a 128-bit representation with hexadecimal numbers (and some other logic to compress zero sequenes).

    The number 10752 is equivalent to:

    00        00        00        00        00        00        00  (hex)
    00        00        00        00        00        2a        00
    
    00000000  00000000  00000000  00000000  00000000  00000000  00000000  (bin)
    00000000  00000000  00000000  00000000  00000000  00101010  00000000
    

    or thus with colons in between:

    0000:0000:0000:0000:0000:0000:0000:2a00
    

    and this is actually what you get. IPv6 addresses use double colons to strip of sequences of zero.

    If we shift the value however 112 places up (128-16), we thus get:

    2a        00        00        00        00        00        00  (hex)
    00        00        00        00        00        00        00
    
    00101010  00000000  00000000  00000000  00000000  00000000  00000000  (bin)
    00000000  00000000  00000000  00000000  00000000  00000000  00000000
    

    which is thus:

    2a00:0000:0000:0000:0000:0000:0000:0000
    

    so we can obtain the desired output with:

    >>> ipaddress.IPv6Address(10752<<112)
    IPv6Address('2a00::')
    

    Note that the above however will only work if the data is less than 216=65'536, since otherwise it takes more than 16 bits, and then the value is too large to get represented by an IPv6 address.