Date: Mon, 9 Jul 2018 20:11:48 -0400 From: Christopher Friedt <chrisfriedt@...il.com> To: musl@...ts.openwall.com Subject: Re: getaddrinfo(3) / AI_ADDRCONFIG On Mon, Jul 9, 2018 at 6:38 PM Rich Felker <dalias@...c.org> wrote: > POSIX does not clearly specify how "only if an IPv6 address is > configured on the local system" is determined, but the glibc behavior > of ignoring ::1 on lo seems clearly non-conforming. My assumption a > the time was that ::1 would always be configured and available unless > IPv6 support was omitted from the kernel, so that any test involving > iteration of interfaces would be meaningless; at most probing ::1, or > probably just trying socket(AF_INET6,...) would suffice to determine > what to do. > > It's unclear to me (and I think to everyone) what an application > actually wants when it uses AI_ADDRCONFIG. Neither knowing whether You did point out that glibc is non-conforming, and I assumed that musl would prefer to be more conforming as well. The patch I provided *is* conforming in that it does not assume AI_ADDRCONFIG is present when hints are NULL. Your assumption actually missed the mark a bit though. If IPv6 is initially configured for an interface, even if no routable address is assigned, it will get a link-local address (which is not a loopback address, and so is not skipped by getaddrinfo). So it will not be ::1 that comes back by default but something in the fe80::/10 range. The description of AI_ADDRCONFIG below is also fairly straightforward, and tackles the exact problem I encountered (see the last sentence of the paragraph below). http://man7.org/linux/man-pages/man3/getaddrinfo.3.html If hints.ai_flags includes the AI_ADDRCONFIG flag, then IPv4 addresses are returned in the list pointed to by res only if the local system has at least one IPv4 address configured, and IPv6 addresses are returned only if the local system has at least one IPv6 address configured. The loopback address is not considered for this case as valid as a configured address. This flag is useful on, for example, IPv4-only systems, to ensure that getaddrinfo() does not return IPv6 socket addresses that would always fail in connect(2) or bind(2). At least 4 majorly (ubuquitously?) adopted libc's have implemented AI_ADDRCONFIG this way (glibc, uclibc, Apple libc, BSD libc). My suggestion would be to do what everyone else does until there is better clarification rather than try and be a snowflake. > IPv6 is supported at all on the host, nor whether there happens to be > *some* interface or non-lo interface with an IPv6 address (think: it > might just be a private-network VPN), tells you anything about whether > the IPv6 addresses for the particular hostname you're looking up with IPv6 support does not imply that a network interface needs to be configured with an IPv6 address. The point you are trying to make seems to be addressing glibc's non-conformance as opposed to AI_ADDRCONFIG's intended functionality. Since the patch does not introduce non-conformance, and actually does not negatively alter musl's behaviour. > getaddrinfo is routable. The more likely thing an application might > want is to request whichever result is routable ^^ PRECISELY > want is to request whichever result is routable, but THAT ALREADY > HAPPENS without AI_ADDRCONFIG: the results are sorted such that In fact IT DOES NOT ALREADY HAPPEN. Musl's getaddrinfo does not provide a routable socket at all in the example I provided. In fact, there are exactly zero network interfaces with an IPv6 address in this case, but somehow musl comes back with "::1" for localhost, which is more damaging than useful in this use case. You could almost say that musl is currently also non-conformant in that sense. > routable ones come before non-routable ones, so if you try them in > order, you'll never hit a non-routable address family unless all the > results for the other family fail to be reachable. Want proof? Download the tarball I provided here: https://issues.apache.org/jira/browse/THRIFT-4594 Using a default Docker installation, run it with "docker build -t foo ." (where . is the directory with the Dockerfile). The C++ / c_glib unit tests will work in this case (with the fix) (the python unit tests are currently not compiling). Then, comment-out the line that applies the patch to musl in the Dockerfile. # RUN patch -p1 < musl-1.1.19-getaddrinfo-ai-addrconfig.patch The C++ / c_glib unit tests will break in this case. You can step-through the code yourself, or just trust the instrumentation I've already done detailed at issues.apache.org. So there you have it. A use case with a demonstrated bug and fix that is 100% reproducible. > So at this point my leaning is somewhere between: > > 1. Saying it's 2018 and having a system without IPv6 support (at least > ::1) is an unsupported configuration. That's a slippery-slope argument. Just because a system supports IPv6 does not imply that a network interface needs to be configured with an IPv6 address. As an example, my lame cable ISP does not route IPv6 traffic nor does it provide an IPv6 prefix. They are IPv4-only (you may think I live in the dark ages). Therefore, it does not even make sense for the average customer to configure IPv6 on their LAN. Does my OS support IPv6? Of course. ... Did I bypass them with a 6in4 tunnel - you can be damn sure ;-) But many people wouldn't bother with that. > 2. Implementing AI_ADDRCONFIG as detection for the case where IPv6 has > been completely disabled at the kernel or container level. That's not at all the case here. 3. Where a user's OS supports IPv6 but they have simply opted not to assign an IPv6 address to their network interface or use a link-local address. > I'm not sure what option 2 entails if IPv6 is disabled at the > container level but socket(AF_INET6,...) still succeeds, so we should > perhaps look into that if you or other users feel strongly that > AI_ADDRCONFIG should do something here. But it shouldn't involve any > O(n) iteration of interfaces, allocation, or pulling in other heavy > code. My only emphasis would be to support it to the end that it does what is expected when passed in, and to not make it a default. Review the patch, because AI_ADDRCONFIG is not a default flag. It's O(n) in the worst case. In the best case, it's O(1). In the average case (probabilistically speaking, where network interfaces each have v4 and v6 addresses), it's still O(1). In the default case, the only overhead is the time it takes to perform a mask and compare. C
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.