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

Commit 9b6700f added "v6only". As suggested by Vincent Bernat, it is
sometimes useful to have the opposite option to force binding to the
two protocols when the system is configured to bind to v6 only by
default. This option does exactly this. v6only still has precedence.
This commit is contained in:
Willy Tarreau 2012-11-24 15:07:23 +01:00
parent 5e16cbc3bd
commit 77e3af9e6f
3 changed files with 27 additions and 1 deletions

View File

@ -7156,11 +7156,19 @@ transparent
kernel version. Some distribution kernels include backports of the feature, kernel version. Some distribution kernels include backports of the feature,
so check for support with your vendor. so check for support with your vendor.
v4v6
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 both IPv4
and IPv6 when it uses the default address. Doing so is sometimes necessary
on systems which bind to IPv6 only by default. It has no effect on non-IPv6
sockets, and is overriden by the "v6only" option.
v6only v6only
Is an optional keyword which is supported only on most recent systems 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 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 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. system-wide as it is per-listener. It has no effect on non-IPv6 sockets and
has precedence over the "v4v6" option.
uid <uid> uid <uid>
Sets the owner of the UNIX sockets to the designated system uid. It can also Sets the owner of the UNIX sockets to the designated system uid. It can also

View File

@ -91,6 +91,7 @@ enum {
#define LI_O_UNLIMITED 0x0080 /* listener not subject to global limits (peers & stats socket) */ #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_TCP_FO 0x0100 /* enable TCP Fast Open (linux >= 3.6) */
#define LI_O_V6ONLY 0x0200 /* bind to IPv6 only on Linux >= 2.4.21 */ #define LI_O_V6ONLY 0x0200 /* bind to IPv6 only on Linux >= 2.4.21 */
#define LI_O_V4V6 0x0400 /* bind to IPv4/IPv6 on Linux >= 2.4.21 */
/* Note: if a listener uses LI_O_UNLIMITED, it is highly recommended that it adds its own /* 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. * maxconn setting to the global.maxsock value so that its resources are reserved.

View File

@ -703,6 +703,8 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
#if defined(IPV6_V6ONLY) #if defined(IPV6_V6ONLY)
if (listener->options & LI_O_V6ONLY) if (listener->options & LI_O_V6ONLY)
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
else if (listener->options & LI_O_V4V6)
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
#endif #endif
if (bind(fd, (struct sockaddr *)&listener->addr, listener->proto->sock_addrlen) == -1) { if (bind(fd, (struct sockaddr *)&listener->addr, listener->proto->sock_addrlen) == -1) {
@ -1727,6 +1729,19 @@ static int val_payload_lv(struct arg *arg, char **err_msg)
} }
#ifdef IPV6_V6ONLY #ifdef IPV6_V6ONLY
/* parse the "v4v6" bind keyword */
static int bind_parse_v4v6(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_V4V6;
}
return 0;
}
/* parse the "v6only" bind keyword */ /* parse the "v6only" bind keyword */
static int bind_parse_v6only(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) static int bind_parse_v6only(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{ {
@ -1899,6 +1914,7 @@ static struct bind_kw_list bind_kws = { "TCP", { }, {
{ "transparent", bind_parse_transparent, 0 }, /* transparently bind to the specified addresses */ { "transparent", bind_parse_transparent, 0 }, /* transparently bind to the specified addresses */
#endif #endif
#ifdef IPV6_V6ONLY #ifdef IPV6_V6ONLY
{ "v4v6", bind_parse_v4v6, 0 }, /* force socket to bind to IPv4+IPv6 */
{ "v6only", bind_parse_v6only, 0 }, /* force socket to bind to IPv6 only */ { "v6only", bind_parse_v6only, 0 }, /* force socket to bind to IPv6 only */
#endif #endif
/* the versions with the NULL parse function*/ /* the versions with the NULL parse function*/
@ -1906,6 +1922,7 @@ static struct bind_kw_list bind_kws = { "TCP", { }, {
{ "interface", NULL, 1 }, { "interface", NULL, 1 },
{ "mss", NULL, 1 }, { "mss", NULL, 1 },
{ "transparent", NULL, 0 }, { "transparent", NULL, 0 },
{ "v4v6", NULL, 0 },
{ "v6only", NULL, 0 }, { "v6only", NULL, 0 },
{ NULL, NULL, 0 }, { NULL, NULL, 0 },
}}; }};