Index: libmicrohttpd-0.4.6/src/daemon/daemon.c =================================================================== --- libmicrohttpd-0.4.6.orig/src/daemon/daemon.c 2010-02-20 10:00:01.000000000 +0100 +++ libmicrohttpd-0.4.6/src/daemon/daemon.c 2012-01-15 16:30:54.000000000 +0100 @@ -695,6 +695,25 @@ } #endif +#if HAVE_INET6 + /* If receiving IPv4 connections on an IPv6 socket (dual-stack sockets), + * the operating system will typically report back a so called mapped-v4 + * address, of the form ::ffff:127.0.0.1. Rewrite these to IPv4 addresses, + * since that is what all the other code expects. + */ + if (addrstorage.sin6_family == AF_INET6) { + const uint32_t *addr32 = (const uint32_t *) addrstorage.sin6_addr.s6_addr; + if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) { + uint32_t addr4 = addr32[3]; + uint16_t port = addrstorage.sin6_port; + + struct sockaddr_in *addr_in = (struct sockaddr_in *) &addrstorage; + addr_in->sin_family = AF_INET; + addr_in->sin_addr.s_addr = addr4; + addr_in->sin_port = port; + } + } +#endif #if HAVE_MESSAGES #if DEBUG_CONNECT @@ -1411,6 +1430,7 @@ void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls, va_list ap) { + const int off = 0; const int on = 1; struct MHD_Daemon *retVal; int socket_fd; @@ -1507,20 +1527,57 @@ return NULL; } #endif - if ((options & MHD_USE_IPv6) != 0) -#if HAVE_INET6 - socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0); -#else + + /* MHD_USE_DUALSTACK overrides MHD_USE_IPv6. */ + if ((options & MHD_USE_DUALSTACK) != 0) + options &= ~MHD_USE_IPv6; + +#if HAVE_INET6 && defined(IPV6_V6ONLY) + /* If we have IPv6 support, and support the IPV6_V6ONLY flag from + * RFC3493, we can support IPv4 and IPv6 on the same socket. + * If not, we ignore the flag and open it as IPv4-only. + */ + if ((options & MHD_USE_DUALSTACK) != 0) { + socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0); + if (socket_fd == -1) + { + options &= ~MHD_USE_DUALSTACK; + } + else if (SETSOCKOPT (socket_fd, + IPPROTO_IPV6, + IPV6_V6ONLY, + &off, sizeof (off)) < 0) + { #if HAVE_MESSAGES - fprintf (stderr, "AF_INET6 not supported\n"); + FPRINTF (stderr, "setsockopt(IPV6_V6ONLY) failed: %s\n", STRERROR (errno)); #endif - free (retVal); - return NULL; + CLOSE (socket_fd); + options &= ~MHD_USE_DUALSTACK; + } } #endif - else - socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0); + + /* If MHD_USE_DUALSTACK is set at this point, we have a working socket + * and should not try to create a new one. Otherwise, open one here. + */ + if ((options & MHD_USE_DUALSTACK) == 0) + { + if ((options & MHD_USE_IPv6) != 0) +#if HAVE_INET6 + socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0); +#else + { +#if HAVE_MESSAGES + fprintf (stderr, "AF_INET6 not supported\n"); +#endif + free (retVal); + return NULL; + } +#endif + else + socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0); + } if (socket_fd == -1) { #if HAVE_MESSAGES @@ -1566,7 +1623,7 @@ if (NULL == servaddr) { #if HAVE_INET6 - if ((options & MHD_USE_IPv6) != 0) + if ((options & MHD_USE_IPv6) != 0 || (options & MHD_USE_DUALSTACK) != 0) { memset (&servaddr6, 0, sizeof (struct sockaddr_in6)); servaddr6.sin6_family = AF_INET6; Index: libmicrohttpd-0.4.6/src/include/microhttpd.h =================================================================== --- libmicrohttpd-0.4.6.orig/src/include/microhttpd.h 2010-03-13 09:41:30.000000000 +0100 +++ libmicrohttpd-0.4.6/src/include/microhttpd.h 2012-01-15 14:54:00.000000000 +0100 @@ -299,7 +299,14 @@ * This option only works in conjunction with MHD_USE_THREAD_PER_CONNECTION * (at this point). */ - MHD_USE_POLL = 64 + MHD_USE_POLL = 64, + + /** + * Accept both IPv6 and IPv4 connections if possible; otherwise, + * fall back to IPv4. Will override MHD_USE_IPv6, so if you give this flag, + * you will never get a pure IPv6 socket. + */ + MHD_USE_DUALSTACK = 128, }; /**