s3:lib/util_sock: listen on IPv6 addresses with IPV6_ONLY (bug #7383)
authorStefan Metzmacher <metze@samba.org>
Sat, 23 Apr 2011 09:29:51 +0000 (11:29 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 25 Apr 2011 15:42:03 +0000 (17:42 +0200)
This avoids getting IPv4 addresses as mapped IPv6 addresses
(e.g. ::ffff:192.168.0.1).

Before the bahavior was inconsistent between operating system
and distributions. Some system have IPV6_ONLY as default.

Now we consistently get AF_INET for IPv4 addresses and AF_INET6
for IPv6 addresses.

It also makes it possible to listen only on IPv6 now
as "::" doesn't imply "0.0.0.0" anymore. Which also
avoids confusing log messages that we were not able to
bind to "0.0.0.0".

metze

source3/lib/util_sock.c

index 71f6a8f29c91d676a4f1287a714846920cf335a8..eb74b75960023517ae630d4bf3bf511729404b5e 100644 (file)
@@ -787,6 +787,32 @@ int open_socket_in(int type,
 #endif /* SO_REUSEPORT */
        }
 
+#ifdef HAVE_IPV6
+       /*
+        * As IPV6_V6ONLY is the default on some systems,
+        * we better try to be consistent and always use it.
+        *
+        * This also avoids using IPv4 via AF_INET6 sockets
+        * and makes sure %I never resolves to a '::ffff:192.168.0.1'
+        * string.
+        */
+       if (sock.ss_family == AF_INET6) {
+               int val = 1;
+               int ret;
+
+               ret = setsockopt(res, IPPROTO_IPV6, IPV6_V6ONLY,
+                                (const void *)&val, sizeof(val));
+               if (ret == -1) {
+                       if(DEBUGLVL(0)) {
+                               dbgtext("open_socket_in(): IPV6_ONLY failed: ");
+                               dbgtext("%s\n", strerror(errno));
+                       }
+                       close(res);
+                       return -1;
+               }
+       }
+#endif
+
        /* now we've got a socket - we need to bind it */
        if (bind(res, (struct sockaddr *)&sock, slen) == -1 ) {
                if( DEBUGLVL(dlevel) && (port == SMB_PORT1 ||