From: Willy Tarreau Date: Wed, 16 Sep 2020 17:17:08 +0000 (+0200) Subject: MEDIUM: tools: make str2sa_range() check that the protocol has ->connect() X-Git-Tag: v2.3-dev5~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=65ec4e3ff7e9b5b1ce9a52a0e2d8c732f071460a;p=thirdparty%2Fhaproxy.git MEDIUM: tools: make str2sa_range() check that the protocol has ->connect() Most callers of str2sa_range() need the protocol only to check that it provides a ->connect() method. It used to be used to verify that it's a stream protocol, but it might be a bit early to get rid of it. Let's keep the test for now but move it to str2sa_range() when the new flag PA_O_CONNECT is present. This way almost all call places could be cleaned from this. There's a strange test in the server address parsing code that rechecks the family from the socket which seems to be a duplicate of the previously removed tests. It will have to be rechecked. --- diff --git a/include/haproxy/tools-t.h b/include/haproxy/tools-t.h index 3c8091b59a..b1e72494f4 100644 --- a/include/haproxy/tools-t.h +++ b/include/haproxy/tools-t.h @@ -96,6 +96,7 @@ #define PA_O_DGRAM 0x00000080 /* the address will be used for a datagram socket (in or out) */ #define PA_O_STREAM 0x00000100 /* the address will be used for streams (in or out) */ #define PA_O_XPRT 0x00000200 /* transport protocols may be specified */ +#define PA_O_CONNECT 0x00000400 /* the protocol must have a ->connect method */ /* UTF-8 decoder status */ #define UTF8_CODE_OK 0x00 diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index a2a9911701..bbdf699343 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -2590,7 +2590,6 @@ stats_error_parsing: else if (!strcmp(args[0], "dispatch")) { /* dispatch address */ struct sockaddr_storage *sk; int port1, port2; - struct protocol *proto; if (curproxy == &defproxy) { ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); @@ -2600,21 +2599,15 @@ stats_error_parsing: else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) err_code |= ERR_WARN; - sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, &proto, - &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT); + sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, NULL, + &errmsg, NULL, NULL, + PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT | PA_O_CONNECT); if (!sk) { ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg); err_code |= ERR_ALERT | ERR_FATAL; goto out; } - if (!proto->connect) { - ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n", - file, linenum, args[0], args[1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - if (alertif_too_many_args(1, file, linenum, args, &err_code)) goto out; @@ -2840,7 +2833,6 @@ stats_error_parsing: int cur_arg; int port1, port2; struct sockaddr_storage *sk; - struct protocol *proto; if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) err_code |= ERR_WARN; @@ -2858,8 +2850,8 @@ stats_error_parsing: curproxy->conn_src.iface_name = NULL; curproxy->conn_src.iface_len = 0; - sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, &proto, - &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); + sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, NULL, + &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT); if (!sk) { ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); @@ -2867,13 +2859,6 @@ stats_error_parsing: goto out; } - if (!proto->connect) { - ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n", - file, linenum, args[0], args[1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - curproxy->conn_src.source_addr = *sk; curproxy->conn_src.opts |= CO_SRC_BIND; @@ -2936,8 +2921,8 @@ stats_error_parsing: } else { struct sockaddr_storage *sk; - sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL, &proto, - &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); + sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL, NULL, + &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT); if (!sk) { ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[cur_arg], args[cur_arg+1], errmsg); @@ -2945,13 +2930,6 @@ stats_error_parsing: goto out; } - if (!proto->connect) { - ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n", - file, linenum, args[cur_arg], args[cur_arg+1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - curproxy->conn_src.tproxy_addr = *sk; curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR; } diff --git a/src/cfgparse.c b/src/cfgparse.c index b876fbd257..9d8ef65ad5 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1391,14 +1391,15 @@ int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm) newmailer->id = strdup(args[1]); sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, &proto, - &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT); + &errmsg, NULL, NULL, + PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT | PA_O_CONNECT); if (!sk) { ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); err_code |= ERR_ALERT | ERR_FATAL; goto out; } - if (!proto->connect || proto->sock_prot != IPPROTO_TCP) { + if (proto->sock_prot != IPPROTO_TCP) { ha_alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n", file, linenum, args[0], args[1]); err_code |= ERR_ALERT | ERR_FATAL; diff --git a/src/check.c b/src/check.c index be9461e298..8d3cd6f936 100644 --- a/src/check.c +++ b/src/check.c @@ -2629,7 +2629,6 @@ static int srv_parse_addr(char **args, int *cur_arg, struct proxy *curpx, struct char **errmsg) { struct sockaddr_storage *sk; - struct protocol *proto; int port1, port2, err_code = 0; @@ -2638,19 +2637,13 @@ static int srv_parse_addr(char **args, int *cur_arg, struct proxy *curpx, struct goto error; } - sk = str2sa_range(args[*cur_arg+1], NULL, &port1, &port2, NULL, &proto, errmsg, NULL, NULL, - PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); + sk = str2sa_range(args[*cur_arg+1], NULL, &port1, &port2, NULL, NULL, errmsg, NULL, NULL, + PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT); if (!sk) { memprintf(errmsg, "'%s' : %s", args[*cur_arg], *errmsg); goto error; } - if (!proto->connect) { - memprintf(errmsg, "'%s %s' : connect() not supported for this address family.", - args[*cur_arg], args[*cur_arg+1]); - goto error; - } - srv->check.addr = srv->agent.addr = *sk; srv->flags |= SRV_F_CHECKADDR; srv->flags |= SRV_F_AGENTADDR; diff --git a/src/server.c b/src/server.c index 6c5f172990..b1656d5ce4 100644 --- a/src/server.c +++ b/src/server.c @@ -648,7 +648,6 @@ static int srv_parse_source(char **args, int *cur_arg, char *errmsg; int port_low, port_high; struct sockaddr_storage *sk; - struct protocol *proto; errmsg = NULL; @@ -659,19 +658,14 @@ static int srv_parse_source(char **args, int *cur_arg, } /* 'sk' is statically allocated (no need to be freed). */ - sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL, &proto, - &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_RANGE | PA_O_STREAM); + sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL, NULL, + &errmsg, NULL, NULL, + PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_RANGE | PA_O_STREAM | PA_O_CONNECT); if (!sk) { memprintf(err, "'%s %s' : %s\n", args[*cur_arg], args[*cur_arg + 1], errmsg); goto err; } - if (!proto->connect) { - ha_alert("'%s %s' : connect() not supported for this address family.\n", - args[*cur_arg], args[*cur_arg + 1]); - goto err; - } - newsrv->conn_src.opts |= CO_SRC_BIND; newsrv->conn_src.source_addr = *sk; @@ -744,19 +738,14 @@ static int srv_parse_source(char **args, int *cur_arg, int port1, port2; /* 'sk' is statically allocated (no need to be freed). */ - sk = str2sa_range(args[*cur_arg + 1], NULL, &port1, &port2, NULL, &proto, - &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); + sk = str2sa_range(args[*cur_arg + 1], NULL, &port1, &port2, NULL, NULL, + &errmsg, NULL, NULL, + PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT); if (!sk) { ha_alert("'%s %s' : %s\n", args[*cur_arg], args[*cur_arg + 1], errmsg); goto err; } - if (!proto->connect) { - ha_alert("'%s %s' : connect() not supported for this address family.\n", - args[*cur_arg], args[*cur_arg + 1]); - goto err; - } - newsrv->conn_src.tproxy_addr = *sk; newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR; } @@ -830,7 +819,6 @@ static int srv_parse_socks4(char **args, int *cur_arg, char *errmsg; int port_low, port_high; struct sockaddr_storage *sk; - struct protocol *proto; errmsg = NULL; @@ -840,18 +828,14 @@ static int srv_parse_socks4(char **args, int *cur_arg, } /* 'sk' is statically allocated (no need to be freed). */ - sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL, &proto, - &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM); + sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL, NULL, + &errmsg, NULL, NULL, + PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_CONNECT); if (!sk) { memprintf(err, "'%s %s' : %s\n", args[*cur_arg], args[*cur_arg + 1], errmsg); goto err; } - if (!proto->connect) { - ha_alert("'%s %s' : connect() not supported for this address family.\n", args[*cur_arg], args[*cur_arg + 1]); - goto err; - } - newsrv->flags |= SRV_F_SOCKS4_PROXY; newsrv->socks4_addr = *sk; @@ -1989,7 +1973,6 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr if (!defsrv) { struct sockaddr_storage *sk; int port1, port2, port; - struct protocol *proto; newsrv = new_server(curproxy); if (!newsrv) { @@ -2027,21 +2010,15 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr if (!parse_addr) goto skip_addr; - sk = str2sa_range(args[cur_arg], &port, &port1, &port2, NULL, &proto, - &errmsg, NULL, &fqdn, (initial_resolve ? PA_O_RESOLVE : 0) | PA_O_PORT_OK | PA_O_PORT_OFS | PA_O_STREAM | PA_O_XPRT); + sk = str2sa_range(args[cur_arg], &port, &port1, &port2, NULL, NULL, + &errmsg, NULL, &fqdn, + (initial_resolve ? PA_O_RESOLVE : 0) | PA_O_PORT_OK | PA_O_PORT_OFS | PA_O_STREAM | PA_O_XPRT | PA_O_CONNECT); if (!sk) { ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); err_code |= ERR_ALERT | ERR_FATAL; goto out; } - if (!fqdn && !proto->connect) { - ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n", - file, linenum, args[0], args[1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - if (!port1 || !port2) { /* no port specified, +offset, -offset */ newsrv->flags |= SRV_F_MAPPORTS; diff --git a/src/tcpcheck.c b/src/tcpcheck.c index 7d9569c0d3..5bd237ad6f 100644 --- a/src/tcpcheck.c +++ b/src/tcpcheck.c @@ -2217,26 +2217,19 @@ struct tcpcheck_rule *parse_tcpcheck_connect(char **args, int cur_arg, struct pr conn_opts |= TCPCHK_OPT_DEFAULT_CONNECT; else if (strcmp(args[cur_arg], "addr") == 0) { int port1, port2; - struct protocol *proto; if (!*(args[cur_arg+1])) { memprintf(errmsg, "'%s' expects as argument.", args[cur_arg]); goto error; } - sk = str2sa_range(args[cur_arg+1], NULL, &port1, &port2, NULL, &proto, - errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); + sk = str2sa_range(args[cur_arg+1], NULL, &port1, &port2, NULL, NULL, + errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT); if (!sk) { memprintf(errmsg, "'%s' : %s.", args[cur_arg], *errmsg); goto error; } - if (!proto->connect) { - memprintf(errmsg, "'%s' : connect() not supported for this address family.\n", - args[cur_arg]); - goto error; - } - cur_arg++; } else if (strcmp(args[cur_arg], "port") == 0) { diff --git a/src/tools.c b/src/tools.c index f2553a62a4..c4bc821fab 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1176,7 +1176,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int ss.ss_family = AF_CUST_UDP4; } - if (proto) { + if (proto || (opts & PA_O_CONNECT)) { /* Note: if the caller asks for a proto, we must find one, * except if we return with an fqdn that will resolve later, * in which case the address is not known yet (this is only @@ -1187,6 +1187,11 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int memprintf(err, "unsupported protocol family %d for address '%s'", ss.ss_family, str); goto out; } + + if ((opts & PA_O_CONNECT) && new_proto && !new_proto->connect) { + memprintf(err, "connect() not supported for this protocol family %d used by address '%s'", ss.ss_family, str); + goto out; + } } ret = &ss;