fix getaddrinfo regression with AI_ADDRCONFIG on some configurations
authorRich Felker <dalias@aerifal.cx>
Wed, 19 Sep 2018 22:03:22 +0000 (18:03 -0400)
committerRich Felker <dalias@aerifal.cx>
Wed, 19 Sep 2018 22:03:22 +0000 (18:03 -0400)
despite not being documented to do so in the standard or Linux
documentation, attempts to udp connect to 127.0.0.1 or ::1 generate
EADDRNOTAVAIL when the loopback device is not configured and there is
no default route for IPv6. this caused getaddrinfo with AI_ADDRCONFIG
to fail with EAI_SYSTEM and EADDRNOTAVAIL on some no-IPv6
configurations, rather than the intended behavior of detecting IPv6 as
unsuppported and producing IPv4-only results.

previously, only EAFNOSUPPORT was treated as unavailability of the
address family being probed. instead, treat all errors related to
inability to get an address or route as conclusive that the family
being probed is unsupported, and only fail with EAI_SYSTEM on other
errors.

further improvements may be desirable, such as reporting EAI_AGAIN
instead of EAI_SYSTEM for errors which are expected to be transient,
but this patch should suffice to fix the serious regression.

src/network/getaddrinfo.c

index ba26847a1c02e6be4578898d1b0d6a2dc55a2635..e33bfa28aaaa4d2d2bfd6bb5798ed37fea480ad2 100644 (file)
@@ -76,7 +76,16 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
                                close(s);
                                if (!r) continue;
                        }
-                       if (errno != EAFNOSUPPORT) return EAI_SYSTEM;
+                       switch (errno) {
+                       case EADDRNOTAVAIL:
+                       case EAFNOSUPPORT:
+                       case EHOSTUNREACH:
+                       case ENETDOWN:
+                       case ENETUNREACH:
+                               break;
+                       default:
+                               return EAI_SYSTEM;
+                       }
                        if (family == tf[i]) return EAI_NONAME;
                        family = tf[1-i];
                }