We rely on AF_INET6 wildcard bind() binding the AF_INET port, too,
i.e. IPV6_V6ONLY off. This should be the default according to RFC
3493 section 5.3, but isn't on Windows and BSD. RFC 4038 recognizes
this fact in section 4.2.
When IPV6_V6ONLY is on, an AF_INET6 wildcard bind only accepts
connections from IPv6 addresses. Thus, IPv4 doesn't work when
getaddrinfo() returns an AF_INET6 address first (which it should do
when the system has an IPv6 address configured).
Switch off IPV6_V6ONLY explicitly instead of relying on the default.
This makes IPv6 work on systems where IPV6_V6ONLY is on by default,
such as Windows and BSD.
Except for OpenBSD, which does not support switching it off. To be
addressed in the next commit.
if (fd < 0)
continue; /* error, try next one */
if (fd < 0)
continue; /* error, try next one */
+#ifdef IPV6_V6ONLY
+ if (ai->ai_family == AF_INET6) {
+ int off = 0;
+
+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off));
+ }
+#endif
+
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(fd, ai->ai_addr, ai->ai_addrlen) == 0)
break; /* success */
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(fd, ai->ai_addr, ai->ai_addrlen) == 0)
break; /* success */