2

I frequently need to convert a raw, byte-encoded IPv6 address into an IPv6Address object from the ipaddr-py project. Byte-encoded IPv6 addresses are not accepted by the initializer as shown here:

>>> import ipaddr   
>>> byte_ip = b'\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'
>>> ipaddr.IPAddress(byte_ip)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "ipaddr.py", line 78, in IPAddress
    address)
ValueError: ' \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' does
 not appear to be an IPv4 or IPv6 address

What is the easiest way to convert the byte-encoding to a format ipaddr-py can understand? I'm using v. 2.1.10 of ipaddr.py.

My only workaround so far is way too long for the simple task:

>>> def bytes_to_ipaddr_string(c):
...     c = c.encode('hex')
...     if len(c) is not 32: raise Exception('invalid IPv6 address')
...     s = ''
...     while c is not '':
...         s = s + ':'
...         s = s + c[:4]
...         c = c[4:]
...     return s[1:]
...
>>> ipaddr.IPAddress(bytes_to_ipaddr_string(byte_ip))
IPv6Address('2000::1')

EDIT: I'm looking for a cross-platform solution. Unix-only won't do.

Anyone got a better solution?

2 Answers 2

2

On Unix IPv6 bin -> string conversion is simple - all you need is socket.inet_ntop:

>>> socket.inet_ntop(socket.AF_INET6, b'\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01')
'2000::1'
Sign up to request clarification or add additional context in comments.

1 Comment

Very clean solution, thanks. Unfortunately I need a cross-platform solution. At least *nix and Win32.
1

Have a look at ipaddr_test.py:

[...]
# Compatibility function to cast str to bytes objects
if issubclass(ipaddr.Bytes, str):
    _cb = ipaddr.Bytes
else:
    _cb = lambda bytestr: bytes(bytestr, 'charmap')
[...]

Then

_cb('\x20\x01\x06\x58\x02\x2a\xca\xfe'
    '\x02\x00\x00\x00\x00\x00\x00\x01')

provides you a Bytes object which is recognized by the module to contain a packed address.

I didn't test it, but it looks as if it is the way it is intended to be...


Meanwhile I tested it. The _cb stuff is presumably for older moule versions which didn't have a Bytes object. So you just can do

import ipaddr
b = ipaddr.Bytes('\x20\x01\x06\x58\x02\x2a\xca\xfe' '\x02\x00\x00\x00\x00\x00\x00\x01')
print ipaddr.IPAddress(b)

which will result in

2001:658:22a:cafe:200::1

which is probably what you need.

1 Comment

Bingo, ipaddr.IPAddress(ipaddr.Bytes(byte_ip)) works like a charm. I think the _cb stuff is for Python3 compatibility.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.