]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tcp: add support for the "v6only" bind option
authorWilly Tarreau <w@1wt.eu>
Sat, 24 Nov 2012 10:55:28 +0000 (11:55 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 24 Nov 2012 11:20:28 +0000 (12:20 +0100)
This option forces a socket to bind to IPv6 only when it uses the
default address (eg: ":::80").

doc/configuration.txt
include/types/listener.h
src/proto_tcp.c

index f4094079cd74dfc1a8154043791cf3e9d3c168ab..aa2121289b659728d57283f8e98bc3f2411fa7c2 100644 (file)
@@ -7156,6 +7156,12 @@ transparent
   kernel version. Some distribution kernels include backports of the feature,
   so check for support with your vendor.
 
+v6only
+  Is an optional keyword which is supported only on most recent systems
+  including Linux kernels >= 2.4.21. It is used to bind a socket to IPv6 only
+  when it uses the default address. Doing so is sometimes preferred to doing it
+  system-wide as it is per-listener. It has no effect on non-IPv6 sockets.
+
 uid <uid>
   Sets the owner of the UNIX sockets to the designated system uid. It can also
   be set by default in the global section's "unix-bind" statement. Note that
index 0f1698665eac5fd893fa0cf97039bbd99163367a..0bdde76b7b6b624d546db3f3b58751dc705d3f2f 100644 (file)
@@ -90,6 +90,7 @@ enum {
 #define LI_O_ACC_PROXY  0x0040  /* find the proxied address in the first request line */
 #define LI_O_UNLIMITED  0x0080  /* listener not subject to global limits (peers & stats socket) */
 #define LI_O_TCP_FO     0x0100  /* enable TCP Fast Open (linux >= 3.6) */
+#define LI_O_V6ONLY     0x0200  /* bind to IPv6 only on Linux >= 2.4.21 */
 
 /* Note: if a listener uses LI_O_UNLIMITED, it is highly recommended that it adds its own
  * maxconn setting to the global.maxsock value so that its resources are reserved.
index fd9b03d86ddd56799c78d11092a4eaecabf680b0..86073a41fef4132fc165e829521529af3b672e6f 100644 (file)
@@ -700,6 +700,11 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
                }
        }
 #endif
+#if defined(IPV6_V6ONLY)
+       if (listener->options & LI_O_V6ONLY)
+                setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
+#endif
+
        if (bind(fd, (struct sockaddr *)&listener->addr, listener->proto->sock_addrlen) == -1) {
                err |= ERR_RETRYABLE | ERR_ALERT;
                msg = "cannot bind socket";
@@ -1721,6 +1726,21 @@ static int val_payload_lv(struct arg *arg, char **err_msg)
        return 1;
 }
 
+#ifdef IPV6_V6ONLY
+/* parse the "v6only" bind keyword */
+static int bind_parse_v6only(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
+{
+       struct listener *l;
+
+       list_for_each_entry(l, &conf->listeners, by_bind) {
+               if (l->addr.ss_family == AF_INET6)
+                       l->options |= LI_O_V6ONLY;
+       }
+
+       return 0;
+}
+#endif
+
 #ifdef CONFIG_HAP_LINUX_TPROXY
 /* parse the "transparent" bind keyword */
 static int bind_parse_transparent(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
@@ -1877,12 +1897,16 @@ static struct bind_kw_list bind_kws = { "TCP", { }, {
 #endif
 #ifdef CONFIG_HAP_LINUX_TPROXY
        { "transparent",   bind_parse_transparent,  0 }, /* transparently bind to the specified addresses */
+#endif
+#ifdef IPV6_V6ONLY
+       { "v6only",        bind_parse_v6only,       0 }, /* force socket to bind to IPv6 only */
 #endif
        /* the versions with the NULL parse function*/
        { "defer-accept",  NULL,  0 },
        { "interface",     NULL,  1 },
        { "mss",           NULL,  1 },
        { "transparent",   NULL,  0 },
+       { "v6only",        NULL,  0 },
        { NULL, NULL, 0 },
 }};