]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tools: make str2sa_range() directly return the protocol
authorWilly Tarreau <w@1wt.eu>
Wed, 16 Sep 2020 16:25:03 +0000 (18:25 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 16 Sep 2020 20:08:08 +0000 (22:08 +0200)
We'll need this so that it can return pointers to stacked protocol in
the future (for QUIC). In addition this removes a lot of tests for
protocol validity in the callers.

Some of them were checked further apart, or after a call to
str2listener() and they were simplified as well.

There's still a trick, we can fail to return a protocol in case the caller
accepts an fqdn for use later. This is what servers do and in this case it
is valid to return no protocol. A typical example is:

   server foo localhost:1111

include/haproxy/tools.h
src/cfgparse-listen.c
src/cfgparse.c
src/check.c
src/cli.c
src/hlua.c
src/log.c
src/server.c
src/tcpcheck.c
src/tools.c

index 25a66f8fd04f9c4f48cbfaa9fb179a31fcc4bf19..4080d7a5d25675a02be16a7be515e7689f609279 100644 (file)
@@ -241,10 +241,9 @@ static inline int is_idchar(char c)
  * If <pfx> is non-null, it is used as a string prefix before any path-based
  * address (typically the path to a unix socket).
  */
-struct sockaddr_storage *str2sa_range(const char *str,
-                                      int *port, int *low, int *high, int *fd,
-                                      char **err, const char *pfx,
-                                      char **fqdn, unsigned int opts);
+struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int *high, int *fd,
+                                      struct protocol **proto, char **err,
+                                      const char *pfx, char **fqdn, unsigned int opts);
 
 /* converts <str> to a struct in_addr containing a network mask. It can be
  * passed in dotted form (255.255.255.0) or in CIDR form (24). It returns 1
index d29505a3ebf085cd51e7f2ba0959e5a234a8ba6f..a2a9911701b61e6081e806ba6951b9ea26959e43 100644 (file)
@@ -2600,7 +2600,7 @@ 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,
+               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);
                if (!sk) {
                        ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
@@ -2608,8 +2608,7 @@ stats_error_parsing:
                        goto out;
                }
 
-               proto = protocol_by_family(sk->ss_family);
-               if (!proto || !proto->connect) {
+               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;
@@ -2859,7 +2858,7 @@ stats_error_parsing:
                curproxy->conn_src.iface_name = NULL;
                curproxy->conn_src.iface_len = 0;
 
-               sk = str2sa_range(args[1], NULL, &port1, &port2, NULL,
+               sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, &proto,
                                  &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM);
                if (!sk) {
                        ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
@@ -2868,8 +2867,7 @@ stats_error_parsing:
                        goto out;
                }
 
-               proto = protocol_by_family(sk->ss_family);
-               if (!proto || !proto->connect) {
+               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;
@@ -2938,7 +2936,7 @@ stats_error_parsing:
                                } else {
                                        struct sockaddr_storage *sk;
 
-                                       sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL,
+                                       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);
                                        if (!sk) {
                                                ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
@@ -2947,8 +2945,7 @@ stats_error_parsing:
                                                goto out;
                                        }
 
-                                       proto = protocol_by_family(sk->ss_family);
-                                       if (!proto || !proto->connect) {
+                                       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;
index c4dd262ff20766b011a37b64b8550fa93e10032e..b876fbd257e7caad07bcf11ed01bf25934b57b6e 100644 (file)
@@ -127,19 +127,13 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
                        *next++ = 0;
                }
 
-               ss2 = str2sa_range(str, NULL, &port, &end, &fd, err,
+               ss2 = str2sa_range(str, NULL, &port, &end, &fd, &proto, err,
                                   curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
                                   NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_PORT_RANGE |
                                          PA_O_SOCKET_FD | PA_O_STREAM | PA_O_XPRT);
                if (!ss2)
                        goto fail;
 
-               proto = protocol_by_family(ss2->ss_family);
-               if (!proto) {
-                       memprintf(err, "unsupported protocol family %d fr address '%s'", ss2->ss_family, str);
-                       goto fail;
-               }
-
                /* OK the address looks correct */
                if (!create_listeners(bind_conf, ss2, port, end, fd, proto, err)) {
                        memprintf(err, "%s for address '%s'.\n", *err, str);
@@ -183,19 +177,13 @@ int str2receiver(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
                        *next++ = 0;
                }
 
-               ss2 = str2sa_range(str, NULL, &port, &end, &fd, err,
+               ss2 = str2sa_range(str, NULL, &port, &end, &fd, &proto, err,
                                   curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
                                   NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_PORT_RANGE |
                                          PA_O_SOCKET_FD | PA_O_DGRAM | PA_O_XPRT);
                if (!ss2)
                        goto fail;
 
-               proto = protocol_by_family(ss2->ss_family);
-               if (!proto) {
-                       memprintf(err, "unsupported protocol family %d fr address '%s'", ss2->ss_family, str);
-                       goto fail;
-               }
-
                /* OK the address looks correct */
                if (!create_listeners(bind_conf, ss2, port, end, fd, proto, err)) {
                        memprintf(err, "%s for address '%s'.\n", *err, str);
@@ -642,7 +630,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
                                }
                        }
                        newpeer->addr = l->rx.addr;
-                       newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
+                       newpeer->proto = l->rx.proto;
                        cur_arg++;
                }
 
@@ -1001,7 +989,6 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
        else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
                struct sockaddr_storage *sk;
                int port1, port2;
-               struct protocol *proto;
 
                if (!*args[2]) {
                        ha_alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
@@ -1040,21 +1027,14 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
                newnameserver->conf.line = linenum;
                newnameserver->id = strdup(args[1]);
 
-               sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_DGRAM);
+               sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, NULL,
+                                 &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_DGRAM);
                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;
                }
 
-               proto = protocol_by_family(sk->ss_family);
-               if (!proto) {
-                       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;
-               }
-
                newnameserver->addr = *sk;
        }
        else if (strcmp(args[0], "parse-resolv-conf") == 0) {
@@ -1410,15 +1390,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, &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT);
+               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);
                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;
                }
 
-               proto = protocol_by_family(sk->ss_family);
-               if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
+               if (!proto->connect || 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 40788ae98e2f74548295f27a24f68c999713c36c..be9461e29871d95d5d40f4da60df30f4e7f7cfaa 100644 (file)
@@ -2638,15 +2638,14 @@ 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, errmsg, NULL, NULL,
+       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);
        if (!sk) {
                memprintf(errmsg, "'%s' : %s", args[*cur_arg], *errmsg);
                goto error;
        }
 
-       proto = protocol_by_family(sk->ss_family);
-       if (!proto || !proto->connect) {
+       if (!proto->connect) {
                memprintf(errmsg, "'%s %s' : connect() not supported for this address family.",
                          args[*cur_arg], args[*cur_arg+1]);
                goto error;
index 2892d882f4daea22c0c1c1d51018d5eab9e306b8..f34f9916f2f4a19ed4148bd1d89a1fa6ae690ba7 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -2475,15 +2475,14 @@ int mworker_cli_proxy_create()
                newsrv->conf.line = 0;
 
                memprintf(&msg, "sockpair@%d", child->ipc_fd[0]);
-               if ((sk = str2sa_range(msg, &port, &port1, &port2, NULL,
+               if ((sk = str2sa_range(msg, &port, &port1, &port2, NULL, &proto,
                                       &errmsg, NULL, NULL, PA_O_STREAM)) == 0) {
                        goto error;
                }
                free(msg);
                msg = NULL;
 
-               proto = protocol_by_family(sk->ss_family);
-               if (!proto || !proto->connect) {
+               if (!proto->connect) {
                        goto error;
                }
 
index 5589482b024c34ee9e6266631ffebc1c83eef56a..390191e05f1fbbb7b01edf8a9db63008eb8b8ba4 100644 (file)
@@ -2534,7 +2534,7 @@ __LJMP static int hlua_socket_connect(struct lua_State *L)
        }
 
        /* Parse ip address. */
-       addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, NULL, PA_O_PORT_OK | PA_O_STREAM);
+       addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, NULL, NULL, PA_O_PORT_OK | PA_O_STREAM);
        if (!addr) {
                xref_unlock(&socket->xref, peer);
                WILL_LJMP(luaL_error(L, "connect: cannot parse destination address '%s'", ip));
index ee998705155153b9cac190980fdc2a8e51731f1d..2a4956107583687939c4ab0795228fb6fc8fbb13 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -1019,7 +1019,7 @@ int parse_logsrv(char **args, struct list *logsrvs, int do_del, char **err)
                goto done;
        }
 
-       sk = str2sa_range(args[1], NULL, &port1, &port2, &fd,
+       sk = str2sa_range(args[1], NULL, &port1, &port2, &fd, NULL,
                          err, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_RAW_FD | PA_O_DGRAM);
        if (!sk)
                goto error;
index 84b66f734ca458db5dd96fda43b8a99fd48952a3..6c5f1729906aa795c3e8af0ee787d2e3725bec0f 100644 (file)
@@ -659,15 +659,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,
+       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);
        if (!sk) {
                memprintf(err, "'%s %s' : %s\n", args[*cur_arg], args[*cur_arg + 1], errmsg);
                goto err;
        }
 
-       proto = protocol_by_family(sk->ss_family);
-       if (!proto || !proto->connect) {
+       if (!proto->connect) {
                ha_alert("'%s %s' : connect() not supported for this address family.\n",
                         args[*cur_arg], args[*cur_arg + 1]);
                goto err;
@@ -745,15 +744,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,
+                               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);
                                if (!sk) {
                                        ha_alert("'%s %s' : %s\n", args[*cur_arg], args[*cur_arg + 1], errmsg);
                                        goto err;
                                }
 
-                               proto = protocol_by_family(sk->ss_family);
-                               if (!proto || !proto->connect) {
+                               if (!proto->connect) {
                                        ha_alert("'%s %s' : connect() not supported for this address family.\n",
                                                 args[*cur_arg], args[*cur_arg + 1]);
                                        goto err;
@@ -842,15 +840,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,
+       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);
        if (!sk) {
                memprintf(err, "'%s %s' : %s\n", args[*cur_arg], args[*cur_arg + 1], errmsg);
                goto err;
        }
 
-       proto = protocol_by_family(sk->ss_family);
-       if (!proto || !proto->connect) {
+       if (!proto->connect) {
                ha_alert("'%s %s' : connect() not supported for this address family.\n", args[*cur_arg], args[*cur_arg + 1]);
                goto err;
        }
@@ -2030,7 +2027,7 @@ 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,
+                       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);
                        if (!sk) {
                                ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
@@ -2038,8 +2035,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
                                goto out;
                        }
 
-                       proto = protocol_by_family(sk->ss_family);
-                       if (!fqdn && (!proto || !proto->connect)) {
+                       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;
index 8da89559b832592442e6a3875a88f70692caf039..7d9569c0d37c3a6fb1977c225f661396025920d3 100644 (file)
@@ -2224,15 +2224,14 @@ struct tcpcheck_rule *parse_tcpcheck_connect(char **args, int cur_arg, struct pr
                                goto error;
                        }
 
-                       sk = str2sa_range(args[cur_arg+1], NULL, &port1, &port2, NULL,
+                       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);
                        if (!sk) {
                                memprintf(errmsg, "'%s' : %s.", args[cur_arg], *errmsg);
                                goto error;
                        }
 
-                       proto = protocol_by_family(sk->ss_family);
-                       if (!proto || !proto->connect) {
+                       if (!proto->connect) {
                                memprintf(errmsg, "'%s' : connect() not supported for this address family.\n",
                                          args[cur_arg]);
                                goto error;
index 0f0bbae80a494f7af72fbfa6304007cb21a4db8c..f2553a62a43c341e1672e029f116fcfb4fbd6b74 100644 (file)
@@ -47,6 +47,7 @@
 #include <haproxy/hlua.h>
 #include <haproxy/listener.h>
 #include <haproxy/namespace.h>
+#include <haproxy/protocol.h>
 #include <haproxy/ssl_sock.h>
 #include <haproxy/stream_interface.h>
 #include <haproxy/task.h>
@@ -864,13 +865,18 @@ struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, i
  * the address when cast to sockaddr_in and the address family is
  * AF_CUST_EXISTING_FD.
  *
+ * The matching protocol will be set into <proto> if non-null.
+ *
  * Any known file descriptor is also assigned to <fd> if non-null, otherwise it
  * is forced to -1.
  */
-struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int *high, int *fd, char **err, const char *pfx, char **fqdn, unsigned int opts)
+struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int *high, int *fd,
+                                      struct protocol **proto, char **err,
+                                      const char *pfx, char **fqdn, unsigned int opts)
 {
        static THREAD_LOCAL struct sockaddr_storage ss;
        struct sockaddr_storage *ret = NULL;
+       struct protocol *new_proto = NULL;
        char *back, *str2;
        char *port1, *port2;
        int portl, porth, porta;
@@ -1170,6 +1176,19 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
                        ss.ss_family = AF_CUST_UDP4;
        }
 
+       if (proto) {
+               /* 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
+                * for servers actually).
+                */
+               new_proto = protocol_by_family(ss.ss_family);
+               if (!new_proto && (!fqdn || !*fqdn)) {
+                       memprintf(err, "unsupported protocol family %d for address '%s'", ss.ss_family, str);
+                       goto out;
+               }
+       }
+
        ret = &ss;
  out:
        if (port)
@@ -1180,6 +1199,8 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
                *high = porth;
        if (fd)
                *fd = new_fd;
+       if (proto)
+               *proto = new_proto;
        free(back);
        return ret;
 }