diff options
author | Willy Tarreau <w@1wt.eu> | 2020-08-28 11:49:31 +0200 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2020-08-28 18:51:36 +0200 |
commit | de70ca5dfd469fc4d06579ac0cce95a50df2257d (patch) | |
tree | fdcaac87cba6ff5c1d6f27477d922efaeeda45f3 | |
parent | 8987e7a8c90caf7b9877424432c36902451ad310 (diff) | |
download | haproxy-de70ca5dfd469fc4d06579ac0cce95a50df2257d.tar.gz |
REORG: tcp: move TCP bind/server keywords from proto_tcp.c to cfgparse-tcp.c
Let's continue the cleanup and get rid of all bind and server keywords
parsers from proto_tcp.c. They're now moved to cfgparse-tcp.c, just as
was done for ssl before 2.2 release. Nothing has changed beyond this.
Now proto_tcp.c is clean and only contains code related to binding and
connecting.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/cfgparse-tcp.c | 347 | ||||
-rw-r--r-- | src/proto_tcp.c | 282 |
3 files changed, 348 insertions, 283 deletions
@@ -819,7 +819,7 @@ OBJS = src/mux_fcgi.o src/mux_h1.o src/mux_h2.o src/backend.o \ src/ebsttree.o src/pipe.o src/hpack-enc.o src/fcgi.o \ src/eb64tree.o src/dict.o src/shctx.o src/ebimtree.o \ src/eb32tree.o src/ebtree.o src/dgram.o src/proto_udp.o \ - src/hpack-huff.o src/base64.o src/version.o + src/hpack-huff.o src/cfgparse-tcp.o src/base64.o src/version.o ifneq ($(TRACE),) OBJS += src/calltrace.o diff --git a/src/cfgparse-tcp.c b/src/cfgparse-tcp.c new file mode 100644 index 000000000..c13674b7c --- /dev/null +++ b/src/cfgparse-tcp.c @@ -0,0 +1,347 @@ +/* + * Configuration parsing for TCP (bind and server keywords) + * + * Copyright 2000-2020 Willy Tarreau <w@1wt.eu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/types.h> + +#include <netinet/tcp.h> +#include <netinet/in.h> + +#include <haproxy/api.h> +#include <haproxy/arg.h> +#include <haproxy/errors.h> +#include <haproxy/list.h> +#include <haproxy/listener.h> +#include <haproxy/namespace.h> +#include <haproxy/proxy-t.h> +#include <haproxy/server.h> +#include <haproxy/tools.h> + + +#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 */ +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_TRANSPARENT +/* parse the "transparent" bind keyword */ +static int bind_parse_transparent(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_INET || l->addr.ss_family == AF_INET6) + l->options |= LI_O_FOREIGN; + } + + return 0; +} +#endif + +#ifdef TCP_DEFER_ACCEPT +/* parse the "defer-accept" bind keyword */ +static int bind_parse_defer_accept(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_INET || l->addr.ss_family == AF_INET6) + l->options |= LI_O_DEF_ACCEPT; + } + + return 0; +} +#endif + +#ifdef TCP_FASTOPEN +/* parse the "tfo" bind keyword */ +static int bind_parse_tfo(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_INET || l->addr.ss_family == AF_INET6) + l->options |= LI_O_TCP_FO; + } + + return 0; +} +#endif + +#ifdef TCP_MAXSEG +/* parse the "mss" bind keyword */ +static int bind_parse_mss(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + struct listener *l; + int mss; + + if (!*args[cur_arg + 1]) { + memprintf(err, "'%s' : missing MSS value", args[cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + + mss = atoi(args[cur_arg + 1]); + if (!mss || abs(mss) > 65535) { + memprintf(err, "'%s' : expects an MSS with and absolute value between 1 and 65535", args[cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + + list_for_each_entry(l, &conf->listeners, by_bind) { + if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6) + l->maxseg = mss; + } + + return 0; +} +#endif + +#ifdef TCP_USER_TIMEOUT +/* parse the "tcp-ut" bind keyword */ +static int bind_parse_tcp_ut(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + const char *ptr = NULL; + struct listener *l; + unsigned int timeout; + + if (!*args[cur_arg + 1]) { + memprintf(err, "'%s' : missing TCP User Timeout value", args[cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + + ptr = parse_time_err(args[cur_arg + 1], &timeout, TIME_UNIT_MS); + if (ptr == PARSE_TIME_OVER) { + memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)", + args[cur_arg+1], args[cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + else if (ptr == PARSE_TIME_UNDER) { + memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)", + args[cur_arg+1], args[cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + else if (ptr) { + memprintf(err, "'%s' : expects a positive delay in milliseconds", args[cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + + list_for_each_entry(l, &conf->listeners, by_bind) { + if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6) + l->tcp_ut = timeout; + } + + return 0; +} +#endif + +#ifdef SO_BINDTODEVICE +/* parse the "interface" bind keyword */ +static int bind_parse_interface(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + struct listener *l; + + if (!*args[cur_arg + 1]) { + memprintf(err, "'%s' : missing interface name", args[cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + + list_for_each_entry(l, &conf->listeners, by_bind) { + if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6) + l->interface = strdup(args[cur_arg + 1]); + } + + return 0; +} +#endif + +#ifdef USE_NS +/* parse the "namespace" bind keyword */ +static int bind_parse_namespace(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) +{ + struct listener *l; + char *namespace = NULL; + + if (!*args[cur_arg + 1]) { + memprintf(err, "'%s' : missing namespace id", args[cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + namespace = args[cur_arg + 1]; + + list_for_each_entry(l, &conf->listeners, by_bind) { + l->netns = netns_store_lookup(namespace, strlen(namespace)); + + if (l->netns == NULL) + l->netns = netns_store_insert(namespace); + + if (l->netns == NULL) { + ha_alert("Cannot open namespace '%s'.\n", args[cur_arg + 1]); + return ERR_ALERT | ERR_FATAL; + } + } + return 0; +} +#endif + +#ifdef TCP_USER_TIMEOUT +/* parse the "tcp-ut" server keyword */ +static int srv_parse_tcp_ut(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err) +{ + const char *ptr = NULL; + unsigned int timeout; + + if (!*args[*cur_arg + 1]) { + memprintf(err, "'%s' : missing TCP User Timeout value", args[*cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + + ptr = parse_time_err(args[*cur_arg + 1], &timeout, TIME_UNIT_MS); + if (ptr == PARSE_TIME_OVER) { + memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)", + args[*cur_arg+1], args[*cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + else if (ptr == PARSE_TIME_UNDER) { + memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)", + args[*cur_arg+1], args[*cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + else if (ptr) { + memprintf(err, "'%s' : expects a positive delay in milliseconds", args[*cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + + if (newsrv->addr.ss_family == AF_INET || newsrv->addr.ss_family == AF_INET6) + newsrv->tcp_ut = timeout; + + return 0; +} +#endif + + +/************************************************************************/ +/* All supported bind keywords must be declared here. */ +/************************************************************************/ + +/* Note: must not be declared <const> as its list will be overwritten. + * Please take care of keeping this list alphabetically sorted, doing so helps + * all code contributors. + * Optional keywords are also declared with a NULL ->parse() function so that + * the config parser can report an appropriate error when a known keyword was + * not enabled. + */ +static struct bind_kw_list bind_kws = { "TCP", { }, { +#ifdef TCP_DEFER_ACCEPT + { "defer-accept", bind_parse_defer_accept, 0 }, /* wait for some data for 1 second max before doing accept */ +#endif +#ifdef SO_BINDTODEVICE + { "interface", bind_parse_interface, 1 }, /* specifically bind to this interface */ +#endif +#ifdef TCP_MAXSEG + { "mss", bind_parse_mss, 1 }, /* set MSS of listening socket */ +#endif +#ifdef TCP_USER_TIMEOUT + { "tcp-ut", bind_parse_tcp_ut, 1 }, /* set User Timeout on listening socket */ +#endif +#ifdef TCP_FASTOPEN + { "tfo", bind_parse_tfo, 0 }, /* enable TCP_FASTOPEN of listening socket */ +#endif +#ifdef CONFIG_HAP_TRANSPARENT + { "transparent", bind_parse_transparent, 0 }, /* transparently bind to the specified addresses */ +#endif +#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 */ +#endif +#ifdef USE_NS + { "namespace", bind_parse_namespace, 1 }, +#endif + /* the versions with the NULL parse function*/ + { "defer-accept", NULL, 0 }, + { "interface", NULL, 1 }, + { "mss", NULL, 1 }, + { "transparent", NULL, 0 }, + { "v4v6", NULL, 0 }, + { "v6only", NULL, 0 }, + { NULL, NULL, 0 }, +}}; + +INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws); + +static struct srv_kw_list srv_kws = { "TCP", { }, { +#ifdef TCP_USER_TIMEOUT + { "tcp-ut", srv_parse_tcp_ut, 1, 1 }, /* set TCP user timeout on server */ +#endif + { NULL, NULL, 0 }, +}}; + +INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws); + + +REGISTER_BUILD_OPTS("Built with transparent proxy support using:" +#if defined(IP_TRANSPARENT) + " IP_TRANSPARENT" +#endif +#if defined(IPV6_TRANSPARENT) + " IPV6_TRANSPARENT" +#endif +#if defined(IP_FREEBIND) + " IP_FREEBIND" +#endif +#if defined(IP_BINDANY) + " IP_BINDANY" +#endif +#if defined(IPV6_BINDANY) + " IPV6_BINDANY" +#endif +#if defined(SO_BINDANY) + " SO_BINDANY" +#endif + ""); + + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */ diff --git a/src/proto_tcp.c b/src/proto_tcp.c index ebe1aad2d..7ab6b50ec 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -39,7 +39,6 @@ #include <haproxy/proto_tcp.h> #include <haproxy/protocol.h> #include <haproxy/proxy-t.h> -#include <haproxy/server.h> #include <haproxy/tools.h> @@ -1196,287 +1195,6 @@ int tcp_pause_listener(struct listener *l) return 1; } -#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 */ -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_TRANSPARENT -/* parse the "transparent" bind keyword */ -static int bind_parse_transparent(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_INET || l->addr.ss_family == AF_INET6) - l->options |= LI_O_FOREIGN; - } - - return 0; -} -#endif - -#ifdef TCP_DEFER_ACCEPT -/* parse the "defer-accept" bind keyword */ -static int bind_parse_defer_accept(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_INET || l->addr.ss_family == AF_INET6) - l->options |= LI_O_DEF_ACCEPT; - } - - return 0; -} -#endif - -#ifdef TCP_FASTOPEN -/* parse the "tfo" bind keyword */ -static int bind_parse_tfo(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_INET || l->addr.ss_family == AF_INET6) - l->options |= LI_O_TCP_FO; - } - - return 0; -} -#endif - -#ifdef TCP_MAXSEG -/* parse the "mss" bind keyword */ -static int bind_parse_mss(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) -{ - struct listener *l; - int mss; - - if (!*args[cur_arg + 1]) { - memprintf(err, "'%s' : missing MSS value", args[cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - - mss = atoi(args[cur_arg + 1]); - if (!mss || abs(mss) > 65535) { - memprintf(err, "'%s' : expects an MSS with and absolute value between 1 and 65535", args[cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - - list_for_each_entry(l, &conf->listeners, by_bind) { - if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6) - l->maxseg = mss; - } - - return 0; -} -#endif - -#ifdef TCP_USER_TIMEOUT -/* parse the "tcp-ut" bind keyword */ -static int bind_parse_tcp_ut(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) -{ - const char *ptr = NULL; - struct listener *l; - unsigned int timeout; - - if (!*args[cur_arg + 1]) { - memprintf(err, "'%s' : missing TCP User Timeout value", args[cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - - ptr = parse_time_err(args[cur_arg + 1], &timeout, TIME_UNIT_MS); - if (ptr == PARSE_TIME_OVER) { - memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)", - args[cur_arg+1], args[cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - else if (ptr == PARSE_TIME_UNDER) { - memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)", - args[cur_arg+1], args[cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - else if (ptr) { - memprintf(err, "'%s' : expects a positive delay in milliseconds", args[cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - - list_for_each_entry(l, &conf->listeners, by_bind) { - if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6) - l->tcp_ut = timeout; - } - - return 0; -} -#endif - -#ifdef SO_BINDTODEVICE -/* parse the "interface" bind keyword */ -static int bind_parse_interface(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) -{ - struct listener *l; - - if (!*args[cur_arg + 1]) { - memprintf(err, "'%s' : missing interface name", args[cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - - list_for_each_entry(l, &conf->listeners, by_bind) { - if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6) - l->interface = strdup(args[cur_arg + 1]); - } - - return 0; -} -#endif - -#ifdef USE_NS -/* parse the "namespace" bind keyword */ -static int bind_parse_namespace(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) -{ - struct listener *l; - char *namespace = NULL; - - if (!*args[cur_arg + 1]) { - memprintf(err, "'%s' : missing namespace id", args[cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - namespace = args[cur_arg + 1]; - - list_for_each_entry(l, &conf->listeners, by_bind) { - l->netns = netns_store_lookup(namespace, strlen(namespace)); - - if (l->netns == NULL) - l->netns = netns_store_insert(namespace); - - if (l->netns == NULL) { - ha_alert("Cannot open namespace '%s'.\n", args[cur_arg + 1]); - return ERR_ALERT | ERR_FATAL; - } - } - return 0; -} -#endif - -#ifdef TCP_USER_TIMEOUT -/* parse the "tcp-ut" server keyword */ -static int srv_parse_tcp_ut(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err) -{ - const char *ptr = NULL; - unsigned int timeout; - - if (!*args[*cur_arg + 1]) { - memprintf(err, "'%s' : missing TCP User Timeout value", args[*cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - - ptr = parse_time_err(args[*cur_arg + 1], &timeout, TIME_UNIT_MS); - if (ptr == PARSE_TIME_OVER) { - memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)", - args[*cur_arg+1], args[*cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - else if (ptr == PARSE_TIME_UNDER) { - memprintf(err, "timer underflow in argument '%s' to '%s' (minimum non-null value is 1 ms)", - args[*cur_arg+1], args[*cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - else if (ptr) { - memprintf(err, "'%s' : expects a positive delay in milliseconds", args[*cur_arg]); - return ERR_ALERT | ERR_FATAL; - } - - if (newsrv->addr.ss_family == AF_INET || newsrv->addr.ss_family == AF_INET6) - newsrv->tcp_ut = timeout; - - return 0; -} -#endif - - -/************************************************************************/ -/* All supported bind keywords must be declared here. */ -/************************************************************************/ - -/* Note: must not be declared <const> as its list will be overwritten. - * Please take care of keeping this list alphabetically sorted, doing so helps - * all code contributors. - * Optional keywords are also declared with a NULL ->parse() function so that - * the config parser can report an appropriate error when a known keyword was - * not enabled. - */ -static struct bind_kw_list bind_kws = { "TCP", { }, { -#ifdef TCP_DEFER_ACCEPT - { "defer-accept", bind_parse_defer_accept, 0 }, /* wait for some data for 1 second max before doing accept */ -#endif -#ifdef SO_BINDTODEVICE - { "interface", bind_parse_interface, 1 }, /* specifically bind to this interface */ -#endif -#ifdef TCP_MAXSEG - { "mss", bind_parse_mss, 1 }, /* set MSS of listening socket */ -#endif -#ifdef TCP_USER_TIMEOUT - { "tcp-ut", bind_parse_tcp_ut, 1 }, /* set User Timeout on listening socket */ -#endif -#ifdef TCP_FASTOPEN - { "tfo", bind_parse_tfo, 0 }, /* enable TCP_FASTOPEN of listening socket */ -#endif -#ifdef CONFIG_HAP_TRANSPARENT - { "transparent", bind_parse_transparent, 0 }, /* transparently bind to the specified addresses */ -#endif -#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 */ -#endif -#ifdef USE_NS - { "namespace", bind_parse_namespace, 1 }, -#endif - /* the versions with the NULL parse function*/ - { "defer-accept", NULL, 0 }, - { "interface", NULL, 1 }, - { "mss", NULL, 1 }, - { "transparent", NULL, 0 }, - { "v4v6", NULL, 0 }, - { "v6only", NULL, 0 }, - { NULL, NULL, 0 }, -}}; - -INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws); - -static struct srv_kw_list srv_kws = { "TCP", { }, { -#ifdef TCP_USER_TIMEOUT - { "tcp-ut", srv_parse_tcp_ut, 1, 1 }, /* set TCP user timeout on server */ -#endif - { NULL, NULL, 0 }, -}}; - -INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws); - - REGISTER_BUILD_OPTS("Built with transparent proxy support using:" #if defined(IP_TRANSPARENT) " IP_TRANSPARENT" |