Bug 614526: Pass AI_ADDRCONFIG to getaddrinfo if PR_AI_ADDRCONFIG is set. Filter the various localhost names to work around a AI_ADDRCONFIG problem with loopback addresses in some implementations. r=wtc. a1.9.2.17=dveditz.
--- a/nsprpub/pr/src/misc/prnetdb.c
+++ b/nsprpub/pr/src/misc/prnetdb.c
@@ -2034,17 +2034,42 @@ PR_IMPLEMENT(PRAddrInfo *) PR_GetAddrInf
/*
* we assume a RFC 2553 compliant getaddrinfo. this may at some
* point need to be customized as platforms begin to adopt the
* RFC 3493.
*/
memset(&hints, 0, sizeof(hints));
- hints.ai_flags = (flags & PR_AI_NOCANONNAME) ? 0: AI_CANONNAME;
+ if (flags & PR_AI_NOCANONNAME)
+ hints.ai_flags |= AI_CANONNAME;
+#ifdef AI_ADDRCONFIG
+ /*
+ * Propagate AI_ADDRCONFIG to the GETADDRINFO call if PR_AI_ADDRCONFIG
+ * is set.
+ *
+ * Need a workaround for loopback host addresses:
+ * The problem is that in glibc and Windows, AI_ADDRCONFIG applies the
+ * existence of an outgoing network interface to IP addresses of the
+ * loopback interface, due to a strict interpretation of the
+ * specification. For example, if a computer does not have any
+ * outgoing IPv6 network interface, but its loopback network interface
+ * supports IPv6, a getaddrinfo call on "localhost" with AI_ADDRCONFIG
+ * won't return the IPv6 loopback address "::1", because getaddrinfo
+ * thinks the computer cannot connect to any IPv6 destination,
+ * ignoring the remote vs. local/loopback distinction.
+ */
+ if ((flags & PR_AI_ADDRCONFIG) &&
+ strcmp(hostname, "localhost") != 0 &&
+ strcmp(hostname, "localhost.localdomain") != 0 &&
+ strcmp(hostname, "localhost6") != 0 &&
+ strcmp(hostname, "localhost6.localdomain6") != 0) {
+ hints.ai_flags |= AI_ADDRCONFIG;
+ }
+#endif
hints.ai_family = (af == PR_AF_INET) ? AF_INET : AF_UNSPEC;
/*
* it is important to select a socket type in the hints, otherwise we
* will get back repetitive entries: one for each socket type. since
* we do not expose ai_socktype through our API, it is okay to do this
* here. the application may still choose to create a socket of some
* other type.