MINOR: tcp: add support for the "v6only" bind option

This option forces a socket to bind to IPv6 only when it uses the
default address (eg: ":::80").
This commit is contained in:
Willy Tarreau 2012-11-24 11:55:28 +01:00
parent e3635edc88
commit 9b6700f673
3 changed files with 31 additions and 0 deletions

View 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

View 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.

View 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 },
}};