Bug 880698
Summary: | glibc: getaddrinfo() doesn't order results correctly when node is NULL | ||||||||
---|---|---|---|---|---|---|---|---|---|
Product: | Red Hat Enterprise Linux 8 | Reporter: | David Jaša <djasa> | ||||||
Component: | glibc | Assignee: | glibc team <glibc-bugzilla> | ||||||
Status: | CLOSED WONTFIX | QA Contact: | qe-baseos-tools-bugs | ||||||
Severity: | high | Docs Contact: | |||||||
Priority: | unspecified | ||||||||
Version: | 8.2 | CC: | armbru, ashankar, cfergeau, codonell, dj, fweimer, jan.kratochvil, mnewsome, pfrankli | ||||||
Target Milestone: | rc | Keywords: | Triaged | ||||||
Target Release: | 8.0 | ||||||||
Hardware: | Unspecified | ||||||||
OS: | Unspecified | ||||||||
Whiteboard: | |||||||||
Fixed In Version: | Doc Type: | If docs needed, set a value | |||||||
Doc Text: | Story Points: | --- | |||||||
Clone Of: | Environment: | ||||||||
Last Closed: | 2020-06-15 14:00:12 UTC | Type: | Bug | ||||||
Regression: | --- | Mount Type: | --- | ||||||
Documentation: | --- | CRM: | |||||||
Verified Versions: | Category: | --- | |||||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||||
Cloudforms Team: | --- | Target Upstream Version: | |||||||
Embargoed: | |||||||||
Bug Depends On: | |||||||||
Bug Blocks: | 787262, 880347 | ||||||||
Attachments: |
|
Description
David Jaša
2012-11-27 15:57:32 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 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)." 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). sourceware 14211 is duplicate of sw 9981 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 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". 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 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. 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. 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. |