]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tools: make str2sa_range() check that the protocol has ->connect()
authorWilly Tarreau <w@1wt.eu>
Wed, 16 Sep 2020 17:17:08 +0000 (19:17 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 16 Sep 2020 20:08:08 +0000 (22:08 +0200)
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.

include/haproxy/tools-t.h
src/cfgparse-listen.c
src/cfgparse.c
src/check.c
src/server.c
src/tcpcheck.c
src/tools.c

index 3c8091b59ac1e935813874ee9d5f575b02b27944..b1e72494f44604ed6aa172528ca2e584e3a4116a 100644 (file)
@@ -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
index a2a9911701b61e6081e806ba6951b9ea26959e43..bbdf69934351a259f5d8997df787718425349ffc 100644 (file)
@@ -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;
                                }
index b876fbd257e7caad07bcf11ed01bf25934b57b6e..9d8ef65ad5c05558a4c94c7fd4b1487ef6cfcf5d 100644 (file)
@@ -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;
index be9461e29871d95d5d40f4da60df30f4e7f7cfaa..8d3cd6f93610140da680bf7d859924c7b4b7c5ff 100644 (file)
@@ -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;
index 6c5f1729906aa795c3e8af0ee787d2e3725bec0f..b1656d5ce4caa0e28d488aa08ca7b43c9400501a 100644 (file)
@@ -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;
index 7d9569c0d37c3a6fb1977c225f661396025920d3..5bd237ad6f558b4fd94ac09d30aa56b3f02eaa44 100644 (file)
@@ -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 <ipv4|ipv6> 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) {
index f2553a62a43c341e1672e029f116fcfb4fbd6b74..c4bc821fabeed9ca53627077015c685fd93e93e3 100644 (file)
@@ -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;