getaddrinfo and AI_PASSIVE is broken for net.ipv6.bindv6only=0

Bug #673708 reported by Jason Gunthorpe on 2010-11-10
This bug affects 3 people
Affects Status Importance Assigned to Milestone
eglibc (Ubuntu)

Bug Description

When calling getaddrinfo and specifying AF_UNSPEC and AI_PASSIVE it returns both IPv4 and IPv6 addresses when the sysctl net.ipv6.bindv6only = 0. Proper app behavior for AI_PASSIVE should be to bind and listen to all returned addresses, but the kernel does not allow binding to a V4 and V6 address with the same port. In this case getaddrinfo should return only a IPv4 or only a IPv6 address.

Illustrated with python because I'm lazy:

>>> resx = socket.getaddrinfo(None,'1234',0,socket.SOCK_STREAM,0,socket.AI_PASSIVE)
>>> print resx
[(2, 1, 6, '', ('', 1234)), (10, 1, 6, '', ('::', 1234, 0, 0))]

>>> res = resx[0]
>>> fd = socket.socket(res[0],res[1],res[2])
>>> fd.bind(res[4]);

>>> res = resx[1]
>>> fd2 = socket.socket(res[0],res[1],res[2])
>>> fd2.bind(res[4]);
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in bind
socket.error: [Errno 98] Address already in use

At least in earlier Ubuntu releases this case returned the IPv6 address first, so most apps which don't properly use all addresses 'worked' but it was still wrong to return both addresses. The new behavior breaks IPv6 in various cases, with no possible app work-around!

Apps should not be expected to 'sense' if the system is bindv6only. getaddrinfo AF_UNSPEC/AI_PASSIVE should return v6 only for an IPv6 enabled bindv6only = 0 host and both IPv6 and IPv4 (in any order) for an IPv6 enabled bindv6only= host.

At a minimum the old sorting behavior of putting v6 first should be restored! Real apps depend on this!

I've noted various other bugs in this same theme:

So here is one for Ubuntu with a bit more clarity on the exact problem.

ProblemType: Bug
DistroRelease: Ubuntu 10.10
Package: libc6 2.12.1-0ubuntu8
ProcVersionSignature: Ubuntu 2.6.35-22.35-generic
Uname: Linux 2.6.35-22-generic x86_64
Architecture: amd64
Date: Wed Nov 10 12:52:08 2010
InstallationMedia: Ubuntu 10.10 "Maverick Meerkat" - Release amd64 (20101007)
 PATH=(custom, no user)
SourcePackage: eglibc

Jason Gunthorpe (jgunthorpe) wrote :
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in eglibc (Ubuntu):
status: New → Confirmed
ruff (rufferson) wrote :

Here's the root cause

will never be fixed as it is a consequence of poorly written but properly implemented RFC3484

ruff (rufferson) wrote :

Actually Ubuntu can place a workaround by pre-configuring gai.conf.
Easy fix will be to create separate label for IPv4 loopback address
label ::ffff:0f00:1/96 8

ANY4->ANY4 connect yields to ->
ANY6->ANY6 connect results ::1 -> ::
both and are label 4
while ::1 and :: are labels 0 and 3
adding specific label for v4-lo equals sorting by removing 'equal lable' case match.

ruff (rufferson) wrote :

* of course
label ::ffff:0f00:1/128 8

ruff (rufferson) wrote :

On the second thought RFC doesn't say anything about implementing validation of addresses with connect(), so we can argue it is really GLIBC defect. In any case upstream fix proposal submitted.

Craig McQueen (cmcqueen1975) wrote :

Should that be ::ffff:7f00:1 instead of ::ffff:0f00:1?

Craig McQueen (cmcqueen1975) wrote :

Please can we fix this before everyone ends up putting work-arounds in their apps.

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.