Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPV6 address stringification different between Mac and Linux #82

Open
rconradharris opened this issue Jan 9, 2015 · 9 comments
Open
Milestone

Comments

@rconradharris
Copy link

The IPv6 stringification on both and Mac and Linux is done by way of ``socket.inet_ntop`. Unfortunately, the implementations aren't exactly the same, so they produce slightly different results:

Linux
>>> import netaddr; print netaddr.IPAddress(42540766411282592891252304891381481473)
2001:db8:0:1:dcad:beff:feef:1

Mac
>>> import netaddr; print netaddr.IPAddress(42540766411282592891252304891381481473)
2001:db8::1:dcad:beff:feef:1

Notice the Mac version compacts out the extra '0'.

The reason this is a problem is that downstream projects like openstack/nova use this as part of a test suite and will encounter different results depending on whether it's run on a Mac or a Linux box. The consequence for us us, is right now our unit-tests fail on a Mac.

Ideally, it'd be great if netaddr provided a completely machine agnostic representation of the IPAddress.

It looks like these functions are present in the fbsocket module, they're just not used when system versions already exists.

So the question is, should we use the fbsocket version across all OS's for compatibility's sake?

Lower-level failing test

from struct import pack
from socket import inet_ntop, AF_INET6
print inet_ntop(AF_INET6, pack('>4I', 536939960, 1, 3702374143, 4277075969)) 
@kk7ds
Copy link

kk7ds commented Feb 10, 2015

Also of note, the RFC says that a single 16-bit zero field should never be compacted. I have no idea why that is, but:

http://tools.ietf.org/html/rfc5952#section-4.2.2

openstack-gerrit pushed a commit to openstack/nova that referenced this issue Feb 10, 2015
Some network tests would fail on a Mac because the IPv6 addressed returned
wasn't an exact match due to a difference in the `socket.inet_ntop` function
that `netaddr` uses.

On a Mac 0 parts of the IPv6 are compressed away to '::' whereas on Linux they
remain ':0:'.

Ultimately, the fix should be in the upstream `netaddr` library which already
has an issue logged for it: netaddr/netaddr#82

Until that's fixed, the solution is to skip the offending tests.

Co-Authored-By: Johannes Erdfelt <johannes@erdfelt.com>
Change-Id: I7a8a49f4105079a686e553b4d002f04a26b93d0f
Closes-Bug: 1409135
openstack-gerrit pushed a commit to openstack/openstack that referenced this issue Feb 10, 2015
Project: openstack/nova  713767660ba44421ea5e0406d121ea868ad178ac

network: Fix IPv6 tests for Mac

Some network tests would fail on a Mac because the IPv6 addressed returned
wasn't an exact match due to a difference in the `socket.inet_ntop` function
that `netaddr` uses.

On a Mac 0 parts of the IPv6 are compressed away to '::' whereas on Linux they
remain ':0:'.

Ultimately, the fix should be in the upstream `netaddr` library which already
has an issue logged for it: netaddr/netaddr#82

Until that's fixed, the solution is to skip the offending tests.

Co-Authored-By: Johannes Erdfelt <johannes@erdfelt.com>
Change-Id: I7a8a49f4105079a686e553b4d002f04a26b93d0f
Closes-Bug: 1409135
@snordhausen
Copy link
Contributor

Using fbsocket everywhere does not sound like a good idea, because performance would be very poor. However, it might be a good idea to use dialect objects, just as we already do for EUI objects.

The default dialect would be native (=use the local inet_ntop) to maintain current behavior and performance. We could also offer an RFC 5952 dialect and maybe a dialect that never compacts anything.
And once we are doing this, dialects would also become available for IPv4 addresses. This would allow to output zero-padded IPs like 010.123.042.001 which are sometimes used (see e.g. issue #83).
What do you think about this approach?

@rconradharris
Copy link
Author

@snordhausen Sounds like a good idea. I wonder if the warning module should be used to let Mac users know that their IPv6 addresses may not be RFC compliant.

@yamt
Copy link

yamt commented Sep 14, 2015

there's a similar issue with ipv4-compat addresses.

Linux:
>>> netaddr.IPAddress("::2")
IPAddress('::2')
>>>

OSX:
>>> netaddr.IPAddress("::2")
IPAddress('::0.0.0.2')
>>>

see https://bugs.launchpad.net/neutron/+bug/1484837

@drkjam
Copy link
Collaborator

drkjam commented Sep 18, 2016

Seems like a big change so I'll have a look at addressing this as part of 0.8.0 if possible.

@pyoungmeister
Copy link

pyoungmeister commented Oct 3, 2016

Additionally, there are difference between OSX and Linux when it comes to the validity of zoned ipv6 link local addresses. Example:

OSX:

>>> netaddr.IPAddress('fe80::%vlan100')
IPAddress('fe80::')

Linux:

>>> netaddr.IPAddress('fe80::%vlan100')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/py/virtualenvs/ansibly/local/lib/python2.7/site-packages/netaddr/ip/__init__.py", line 306, in __init__
    'address from %r' % addr)
netaddr.core.AddrFormatError: failed to detect a valid IP address from 'fe80::%vlan100'

@Akasurde
Copy link

Linux :

>>> netaddr.IPNetwork('::1/120').broadcast
IPAddress('::ff')

OSX:

>>> netaddr.IPNetwork('::1/120').broadcast
IPAddress('::0.0.0.255')

@jstasiak
Copy link
Contributor

Some more data points:

On Mac OS 10.14 socket.inet_ntop(socket.AF_INET6, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff') returns ::0.0.255.255, but on 10.15 it returns ::ffff which is consistent with inet_ntop regarding IPv4-compatible IPv6 addresses on Linux

On Windows inet_ntop mostly matches the behaviour of Mac and Linux regarding IPv4-mapped IPv6 addresses except in case of Python 3 or PyPy, because then it renders ::ffff:0:0 instead of
::ffff:0.0.0.0 (tested on Windows Server 2019, CPython 2.7.18 and 3.8.3, PyPy2 implementing 2.7.13 and PyPy3 implementing 3.6.9).

@jstasiak
Copy link
Contributor

The differences may be disappearing now. Tests on macOS 13.4, CPython 3.11.7:


In [6]: IPAddress(42540766411282592891252304891381481473)
Out[6]: IPAddress('2001:db8:0:1:dcad:beff:feef:1')

In [7]: IPAddress('::0.0.0.255')
Out[7]: IPAddress('::ff')

In [8]: IPAddress('::0.0.0.2')
Out[8]: IPAddress('::2')

The issue of zoned IPv6 addresses remains.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants