PATCH: innd: seperate sockets for IPv4 and IPV6

"Miquel van Smoorenburg" list-inn-workers at news.cistron.nl
Mon Mar 24 20:24:07 UTC 2008


In article <2B4C67D6AC2948C9B14CF5FE6DAEF667 at Iulius>,
Julien ÉLIE  <julien at trigofacile.com> wrote:
>Hi Miquel,
>
>> This patch makes innd listen on seperate sockets for IPv4 and IPv6
>> connections if the IPV6_V6ONLY socketoption is available.
>
>Does it look good if I modify bind_ipv6() in backends/innbind.c as follows?
>  [I do not use your condition:
>    if (addr_specified == 0 && addr6_specified == 0)
>  ]
>
>Does anyone have the IPV6_V6ONLY socket option to test if it works?

The code you used actually only tests if the IPV6_V6PONLY socket
option works. It's because I'm not sure if there are OSes
around that define IPV6_V6ONLY in header files but where it doesn't
work at runtime. That would be fatal. It's probably too paranoid.

You have to do the setsockopt on every newly opened socket just before
bind().  I haven't looked at inn-current before, but I think it should
look like this.

Completely untested ofcourse, probably doesn't even compile.

inn-current-bind-ipv4-6-separate.patch

diff -ruN inn-CURRENT-20080324.orig/backends/innbind.c inn-CURRENT-20080324/backends/innbind.c
--- inn-CURRENT-20080324.orig/backends/innbind.c	2008-03-24 10:04:43.000000000 +0100
+++ inn-CURRENT-20080324/backends/innbind.c	2008-03-24 21:01:05.000000000 +0100
@@ -235,6 +235,14 @@
         sysdie("cannot mark socket reusable for %s", spec);
 #endif
 
+    /* Mark it IPV6 only if possible */
+#ifdef IPV6_V6ONLY
+    flag = 1;
+    if (binding->family == AF_INET6 &&
+        setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0)
+        sysdie("cannot mark socket IPv6 only for %s", spec);
+#endif
+
     /* Fill in the struct. */
     binding->fd = fd;
 }
diff -ruN inn-CURRENT-20080324.orig/lib/network.c inn-CURRENT-20080324/lib/network.c
--- inn-CURRENT-20080324.orig/lib/network.c	2008-03-24 10:04:43.000000000 +0100
+++ inn-CURRENT-20080324/lib/network.c	2008-03-24 21:16:15.000000000 +0100
@@ -231,6 +231,9 @@
     int fd, bindfd;
     struct sockaddr_in6 server;
     struct in6_addr addr;
+#ifdef IPV6_V6ONLY
+    int flag;
+#endif
 
     /* Create the socket. */
     fd = socket(PF_INET6, SOCK_STREAM, IPPROTO_IP);
@@ -241,6 +244,12 @@
     }
     network_set_reuseaddr(fd);
 
+#ifdef IPV6_V6ONLY
+    flag = 1;
+    if (setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0)
+        sysdie("cannot set IPv6 socket to v6only");
+#endif
+
     /* Accept "any" or "all" in the bind address to mean 0.0.0.0. */
     if (!strcmp(address, "any") || !strcmp(address, "all"))
         address = "::";
@@ -297,22 +306,39 @@
 
     *count = 0;
 
+    /* Start the fds array at two entries,
+       assuming an IPv6 and IPv4 socket, and grow it by two when necessary. */
+    size = 2;
+    *fds = xmalloc(size * sizeof(int));
+#ifdef IPV6_V6ONLY
+    /* Start with an IPv4 socket. */
+    fd = network_bind_ipv4("0.0.0.0", port);
+    if (fd >= 0) {
+            (*fds)[*count] = fd;
+            (*count)++;
+    }
+#endif
+
     /* Do the query to find all the available addresses. */
     memset(&hints, 0, sizeof(hints));
     hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+#ifdef IPV6_V6ONLY
+    hints.ai_family = AF_INET6;
+#else
     hints.ai_family = AF_UNSPEC;
+#endif
     hints.ai_socktype = SOCK_STREAM;
     snprintf(service, sizeof(service), "%hu", port);
     error = getaddrinfo(NULL, service, &hints, &addrs);
     if (error < 0) {
+#ifdef IPV6_V6ONLY
+	if (error != EAI_ADDRFAMILY && error != EAI_FAMILY)
+#endif
         warn("getaddrinfo failed: %s", gai_strerror(error));
         return;
     }
 
-    /* Now, try to bind each of them.  Start the fds array at two entries,
-       assuming an IPv6 and IPv4 socket, and grow it by two when necessary. */
-    size = 2;
-    *fds = xmalloc(size * sizeof(int));
+    /* Now, try to bind each of them. */
     for (addr = addrs; addr != NULL; addr = addr->ai_next) {
         network_sockaddr_sprint(name, sizeof(name), addr->ai_addr);
         if (addr->ai_family == AF_INET)
-- 
The From: and Reply-To: addresses are internal news2mail gateway addresses.
Reply to the list or to "Miquel van Smoorenburg" <miquels at cistron.nl>


More information about the inn-workers mailing list