RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.
Bug 880698 - glibc: getaddrinfo() doesn't order results correctly when node is NULL
Summary: glibc: getaddrinfo() doesn't order results correctly when node is NULL
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Red Hat Enterprise Linux 8
Classification: Red Hat
Component: glibc
Version: 8.2
Hardware: Unspecified
OS: Unspecified
unspecified
high
Target Milestone: rc
: 8.0
Assignee: glibc team
QA Contact: qe-baseos-tools-bugs
URL:
Whiteboard:
Depends On:
Blocks: 787262 880347
TreeView+ depends on / blocked
 
Reported: 2012-11-27 15:57 UTC by David Jaša
Modified: 2023-07-18 14:30 UTC (History)
9 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2020-06-15 14:00:12 UTC
Type: Bug
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
gai_bug.c by Hans Nieser (859 bytes, text/plain)
2012-11-27 15:57 UTC, David Jaša
no flags Details
Uli Drepper's server example code, hacked up slightly by me (2.39 KB, text/x-csrc)
2013-05-15 13:08 UTC, Markus Armbruster
no flags Details


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker RHELPLAN-35280 0 None None None 2021-09-17 12:12:17 UTC
Sourceware 9981 0 P2 ASSIGNED getaddrinfo(NULL) with AI_PASSIVE returns 0.0.0.0 (IPv4-only) and :: (IPv6+IPv4) in this order 2020-10-12 02:57:58 UTC
Sourceware 14211 0 P2 RESOLVED getaddrinfo() doesn't order results correctly when node is NULL 2020-10-12 02:57:47 UTC

Description David Jaša 2012-11-27 15:57:32 UTC
Created attachment 652835 [details]
gai_bug.c by Hans Nieser

This is downstream version of ustream 14211: http://sourceware.org/bugzilla/show_bug.cgi?id=14211

----------------------

if node==NULL when calling getaddrinfo(), the results are not sorted correctly

in the attached test case, you can see:
$ gcc gai_bug.c && ./a.out 4242
this is an IPv4 result
this is an IPv6 result

it should have returned the IPv6 result first


----------------------

This bug essentially breaks apps that do want to listen on ipv4 and ipv6 simultaneously, because with dualstack enabled (default for any current sane system), binding to ipv4 wildcard address first will prevent binding to ipv6 wildcard address.

Comment 1 Jan Kratochvil 2012-11-27 17:45:15 UTC
If you want to bind to both addresses separately you need to set IPV6_V6ONLY to 1 anyway.

The most easy is to just say:
  req.ai_family = AF_INET6;

and bind only the the single address returned.  I tried to disable IPv6 on recent distro and I even failed but if you want to really be backward compatible then fallback to AF_INET4 if that getaddrinfo fails (but then you could be also backward compatible with OSes not supporting getaddrinfo).

I do not see anything about returned values order in:
http://tools.ietf.org/html/rfc3493
6.1 Protocol-Independent Nodename and Service Name Translation

Comment 2 Christophe Fergeau 2012-11-27 17:58:33 UTC
man getaddrinfo has:
"Normally, the application should try using the addresses in the order in which they are returned.  The sorting function used within getaddrinfo() is defined in RFC 3484; the order can be tweaked for a particular system by editing /etc/gai.conf (available since glibc 2.5)."

Comment 3 Pavel Šimerda (pavlix) 2012-11-28 17:45:48 UTC
I set up a detailed description of the problem:

https://fedoraproject.org/wiki/Networking/NameResolution#Binding_to_addresses_using_getaddrinfo.28.29

Looking forward to any comments.

(In reply to comment #1)
> If you want to bind to both addresses separately you need to set IPV6_V6ONLY
> to 1 anyway.
> 
> The most easy is to just say:
>   req.ai_family = AF_INET6;
> 
> and bind only the the single address returned.  I tried to disable IPv6 on
> recent distro and I even failed but if you want to really be backward
> compatible then fallback to AF_INET4 if that getaddrinfo fails (but then you
> could be also backward compatible with OSes not supporting getaddrinfo).
> 
> I do not see anything about returned values order in:
> http://tools.ietf.org/html/rfc3493
> 6.1 Protocol-Independent Nodename and Service Name Translation

This is true but...

(from the above resource)

The addresses are obviously returned in different order than usual (IPv4 first) and that should probably be fixed in glibc. But even if it's fixed, it only changes the order of the actions:

sock1 = socket(AF_INET6, SOCK_STREAM, SOL_TCP)
bind(sock1, in6addr_any, sizeof (in6addr_any))
...
sock2 = socket(AF_INET, SOCK_STREAM, SOL_TCP)
bind(sock2, INADDR_ANY, sizeof (INADDR_ANY))
...

The first socket succeeds and binds to both addresses. The second one fails. If the application ignores (or only warns about) the second failure, it would work without problem. 

(In reply to comment #1)
> I do not see anything about returned values order in:
> http://tools.ietf.org/html/rfc3493
> 6.1 Protocol-Independent Nodename and Service Name Translation

If you read the whole:

https://fedoraproject.org/wiki/Networking/NameResolution

You will realize that we can no longer use INFORMATIONAL RFCs as a source of information about how getaddrinfo() should work but we should rather fix it and then post updates for the RFC.

(In reply to comment #2)
> man getaddrinfo has:
> "Normally, the application should try using the addresses in the order in
> which they are returned.  The sorting function used within getaddrinfo() is
> defined in RFC 3484; the order can be tweaked for a particular system by
> editing /etc/gai.conf (available since glibc 2.5)."

RFC 3484 is alread obsoleted.

From RFC 6724:

  The application might also specify a source
  address with bind(), but often the source address is left
  unspecified.

This is either not true (bind requires an address) or vague and improper wording for a standard (it doesn't define what 'left unspecified' means
nor does it refer to such a definition).

Comment 4 David Jaša 2013-01-22 15:13:04 UTC
sourceware 14211 is duplicate of sw 9981

Comment 5 Markus Armbruster 2013-05-15 13:05:30 UTC
This is a regression.

RHEL-5 puts "::" before "0.0.0.0".  So do the various BSDs.

RHEL-6 and current Fedora put "0.0.0.0" before "::".  This breaks
programs that used to work just fine.  One of them is the server
example code from Uli Drepper's well-known "Userlevel IPv6 Programming
Introduction".

http://www.akkadia.org/drepper/userapi-ipv6.html

Comment 6 Markus Armbruster 2013-05-15 13:08:24 UTC
Created attachment 748281 [details]
Uli Drepper's server example code, hacked up slightly by me

You can find the original at
http://www.akkadia.org/drepper/userapi-ipv6.html
in section "Example Server Code".

Comment 7 Markus Armbruster 2013-05-15 13:12:44 UTC
Re comment#1:

} If you want to bind to both addresses separately you need to set
} IPV6_V6ONLY to 1 anyway.

Setting IPV6_V6ONLY and then binding all results of getaddrinfo() is
perhaps the sanest way to dual-stack bind.

However, older programs often bind in one of the following two ways,
and both ways worked just fine until we changed getaddrinfo(), and
they still do on the various BSDs (except for OpenBSD, but that's
"special", as usual):

1. Leave IPV6_V6ONLY off, and bind all results, ignoring EADDRINUSE.
This is how Uli Drepper's server and many other programs work.

2. Leave IPV6_V6ONLY off, try binding results in order until one
works.  Many older programs work that way.  RFC 3484 encouraged this
technique:

   Well-behaved applications SHOULD iterate through the list of
   addresses returned from getaddrinfo() until they find a working
   address.

Yes, RFC 3484 is obsolete, and newer RFCs (e.g. RFC 4038) encourage
binding all results, with IPV6_V6ONLY off.  Doesn't mean we can go
ahead and break old programs cavalierly.

} The most easy is to just say:
}   req.ai_family = AF_INET6;
}
} and bind only the the single address returned.  I tried to disable
} IPv6 on recent distro and I even failed but if you want to really be
} backward compatible then fallback to AF_INET4 if that getaddrinfo
} fails (but then you could be also backward compatible with OSes not
} supporting getaddrinfo).

This is bad advice.  By asking getaddrinfo() first for AF_INET6 and
then for AF_INET, you second-guess the proper ordering of results.
That's getaddrinfo()'s job, not the application's!  The RFCs
consistently tell us to stick to getaddrinfo() order.  Comment#2 is
right.

Re comment#3:

} The first socket succeeds and binds to both addresses. The second
} one fails. If the application ignores (or only warns about) the
} second failure, it would work without problem.

Yes, but that's not new.

The old-fashioned way to cope with this problem is to ignore
EADDRINUSE, like Uli Drepper's example code does.

The modern way to cope is setting IPV6_V6ONLY.


[*] http://www.akkadia.org/drepper/userapi-ipv6.html

Comment 11 Carlos O'Donell 2015-01-14 21:46:38 UTC
This issue isn't decided upstream, and until it is it won't get fixed in RHEL. We need a compatible solution to all the other distributions. We'll get this fixed upstream first and then backport. Unfortunately I think RHEL6 is going to have to stay as it is with applications working around the problem. I'm moving this to RHEL 7.2 to track the fix there.

Comment 18 Carlos O'Donell 2019-06-07 19:44:07 UTC
Given that we have no progress on this work upstream, and that RHEL 7 is entering Maintenance Phase 1 in 2019, I'm going to move this request to RHEL 8, where we will again have a chance to make broader changes.

Comment 19 Carlos O'Donell 2020-06-15 14:00:12 UTC
Changing the existing behaviour for the API during the lifetime of Red Hat Enterprise Linux is risky since it impacts so many existing deployed applications.

We are going to track this issue upstream in the glibc bug 9981:
https://sourceware.org/bugzilla/show_bug.cgi?id=9981

We are closing this bug as CLOSED / WONTIFX since we will not make this change in RHEL 8, but instead we will target the next major release of RHEL with this functional change.

It still isn't clear that this change is something we want to make, and the technical direction of the change will be decided by the upstream community which will review the semantic change.


Note You need to log in before you can comment on or make changes to this bug.