]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tools: make str2sa_range() directly return type hints
authorAurelien DARRAGON <adarragon@haproxy.com>
Thu, 9 Nov 2023 10:19:24 +0000 (11:19 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 10 Nov 2023 16:49:57 +0000 (17:49 +0100)
str2sa_range() already allows the caller to provide <proto> in order to
get a pointer on the protocol matching with the string input thanks to
5fc9328a ("MINOR: tools: make str2sa_range() directly return the protocol")

However, as stated into the commit message, there is 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"

In this case, we're unable to return protocol because the protocol lookup
depends on both the [proto type + xprt type] and the [family type] to be
known.

While family type might not be directly resolved when fqdn is involved
(because family type might be discovered using DNS queries), proto type
and xprt type are already known. As such, the caller might be interested
in knowing those address related hints even if the address family type is
not yet resolved and thus the matching protocol cannot be looked up.

Thus in this patch we add the optional net_addr_type (custom type)
argument to str2sa_range to enable the caller to check the protocol type
and transport type when the function succeeds.

13 files changed:
include/haproxy/tools-t.h
include/haproxy/tools.h
src/cfgparse-listen.c
src/cfgparse.c
src/check.c
src/cli.c
src/hlua.c
src/http_client.c
src/log.c
src/resolvers.c
src/server.c
src/tcpcheck.c
src/tools.c

index 805ade6a3fcec0fad34895594f541f45a0ab8e3f..32d8193fe9a7e27d1e0e561919dfa271fac24648 100644 (file)
@@ -157,4 +157,10 @@ struct net_addr {
        } addr;
 };
 
+/* holds socket and xprt types for a given address */
+struct net_addr_type {
+       int proto_type; // socket layer
+       int xprt_type;  // transport layer
+};
+
 #endif /* _HAPROXY_TOOLS_T_H */
index 2fc92bb902e9efbdf0df65488746a46fe3da2a16..e3b847905faf7d5c2ec697034beabfb3174535d6 100644 (file)
@@ -284,8 +284,8 @@ static inline int is_idchar(char c)
  * address (typically the path to a unix socket).
  */
 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);
+                                      struct protocol **proto, struct net_addr_type *sa_type,
+                                      char **err, const char *pfx, char **fqdn, unsigned int opts);
 
 
 /* converts <addr> and <port> into a string representation of the address and port. This is sort
index 0b6f7fa07572fe5bde4105174d222d61e8169216..6c7cc6382adf9602519ee1a2c8fb58c274b96351 100644 (file)
@@ -2518,7 +2518,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, NULL,
+               sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, 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) {
@@ -2852,7 +2852,7 @@ stats_error_parsing:
                ha_free(&curproxy->conn_src.iface_name);
                curproxy->conn_src.iface_len = 0;
 
-               sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, NULL,
+               sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, 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",
@@ -2926,7 +2926,7 @@ stats_error_parsing:
                                } else {
                                        struct sockaddr_storage *sk;
 
-                                       sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL, NULL,
+                                       sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL, 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",
index 11d262455dd24e2825edcfb4a7ca2a09acf36561..312b1d7096de6d1e6f7eb21dcc59c3dba399e94a 100644 (file)
@@ -155,7 +155,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
                        *next++ = 0;
                }
 
-               ss2 = str2sa_range(str, NULL, &port, &end, &fd, &proto, err,
+               ss2 = str2sa_range(str, NULL, &port, &end, &fd, &proto, NULL, err,
                                   (curproxy == global.cli_fe || curproxy == mworker_proxy) ? 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);
@@ -241,7 +241,7 @@ int str2receiver(char *str, struct proxy *curproxy, struct bind_conf *bind_conf,
                        *next++ = 0;
                }
 
-               ss2 = str2sa_range(str, NULL, &port, &end, &fd, &proto, err,
+               ss2 = str2sa_range(str, NULL, &port, &end, &fd, &proto, NULL, err,
                                   curproxy == global.cli_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);
@@ -1178,7 +1178,7 @@ 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,
+               sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, &proto, 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) {
index 91fdbcb8c2f5b798f629487a9e7ce739b08080f4..51c028189b2b21a7a70acbc766f9f5166939db90 100644 (file)
@@ -2033,7 +2033,7 @@ 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, NULL, errmsg, NULL, NULL,
+       sk = str2sa_range(args[*cur_arg+1], NULL, &port1, &port2, NULL, 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);
index 0a78ed7807338cbe90da8872a4a92be51426cecf..b176d523251c81f2569c7dbb3f54b84d73b06476 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -3052,7 +3052,7 @@ 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, &proto,
+               if ((sk = str2sa_range(msg, &port, &port1, &port2, NULL, &proto, NULL,
                                       &errmsg, NULL, NULL, PA_O_STREAM)) == 0) {
                        goto error;
                }
index 7e0580d3596d807f2763dd0270541f2c6584aaef..c5a1c615bd06dbb69e4d49b6b7fda37d2b50af7c 100644 (file)
@@ -3228,7 +3228,7 @@ __LJMP static int hlua_socket_connect(struct lua_State *L)
                csk_ctx->srv = socket_tcp;
 
        /* Parse ip address. */
-       addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, NULL, NULL, PA_O_PORT_OK | PA_O_STREAM);
+       addr = str2sa_range(ip, NULL, &low, &high, NULL, 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 e8fdf42a1f71912881a775cd5ea96c1f61c90bf7..fca13a29761c4554d0937440846df966b15b3586 100644 (file)
@@ -455,7 +455,7 @@ int httpclient_set_dst(struct httpclient *hc, const char *dst)
 
        sockaddr_free(&hc->dst);
        /* 'sk' is statically allocated (no need to be freed). */
-       sk = str2sa_range(dst, NULL, NULL, NULL, NULL, NULL,
+       sk = str2sa_range(dst, NULL, NULL, NULL, NULL, NULL, NULL,
                          &errmsg, NULL, NULL,
                          PA_O_PORT_OK | PA_O_STREAM | PA_O_XPRT | PA_O_CONNECT);
        if (!sk) {
index 3458f93f934b0dc010c25fbf28817109b0b845ed..5efc08b3aeaddfa9f128f496ba97615373daad50 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -1123,7 +1123,7 @@ static int parse_log_target(char *raw, struct log_target *target, char **err)
        target->type = LOG_TARGET_DGRAM; // default type
 
        /* parse the target address */
-       sk = str2sa_range(raw, NULL, &port1, &port2, &fd, &proto,
+       sk = str2sa_range(raw, NULL, &port1, &port2, &fd, &proto, NULL,
                          err, NULL, NULL,
                          PA_O_RESOLVE | PA_O_PORT_OK | PA_O_RAW_FD | PA_O_DGRAM | PA_O_STREAM | PA_O_DEFAULT_DGRAM);
        if (!sk)
index c820d9cfb00faebbf82e4705b76ab876906a0e08..4ef55b913523652c7c4ea3faa5e01547bb071220 100644 (file)
@@ -3521,7 +3521,7 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
                        }
                }
 
-               sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, &proto,
+               sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, &proto, NULL,
                                  &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_DGRAM | PA_O_STREAM | PA_O_DEFAULT_DGRAM);
                if (!sk) {
                        ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
index ca48f2875f956eca338edf301bd605cd5554dd03..80e26ab94f829e5c1357f9d7bacc8ca51db4a569 100644 (file)
@@ -1432,7 +1432,7 @@ 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, NULL,
+       sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL, NULL, NULL,
                          &errmsg, NULL, NULL,
                          PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_RANGE | PA_O_STREAM | PA_O_CONNECT);
        if (!sk) {
@@ -1520,7 +1520,7 @@ 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, NULL,
+                               sk = str2sa_range(args[*cur_arg + 1], NULL, &port1, &port2, NULL, NULL, NULL,
                                                  &errmsg, NULL, NULL,
                                                  PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM | PA_O_CONNECT);
                                if (!sk) {
@@ -1610,7 +1610,7 @@ 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, NULL,
+       sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL, NULL, NULL,
                          &errmsg, NULL, NULL,
                          PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_CONNECT);
        if (!sk) {
@@ -3006,7 +3006,7 @@ static int _srv_parse_init(struct server **srv, char **args, int *cur_arg,
                if (!(parse_flags & SRV_PARSE_PARSE_ADDR))
                        goto skip_addr;
 
-               sk = str2sa_range(args[*cur_arg], &port, &port1, &port2, NULL, &newsrv->addr_proto,
+               sk = str2sa_range(args[*cur_arg], &port, &port1, &port2, NULL, &newsrv->addr_proto, NULL,
                                  &errmsg, NULL, &fqdn,
                                  (parse_flags & SRV_PARSE_INITIAL_RESOLVE ? PA_O_RESOLVE : 0) | PA_O_PORT_OK |
                                  (parse_flags & SRV_PARSE_IN_PEER_SECTION ? PA_O_PORT_MAND : PA_O_PORT_OFS) |
index c00c47fede86f5eba7cfae645fe5dcbf7f73bc22..d30ecb57ec12656364c13992208b3dbb33b464cb 100644 (file)
@@ -2413,7 +2413,7 @@ 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, NULL,
+                       sk = str2sa_range(args[cur_arg+1], NULL, &port1, &port2, NULL, 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);
index 45f519ab8cd9d09744c553ca3c4bba7460c6bc96..d67356f8ee827952c22b17d2f9ccbe7e235d904c 100644 (file)
@@ -947,13 +947,15 @@ struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, i
  * AF_CUST_EXISTING_FD.
  *
  * The matching protocol will be set into <proto> if non-null.
+ * The address protocol and transport types hints which are directly resolved
+ * will be set into <sa_type> if not 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,
-                                      struct protocol **proto, char **err,
-                                      const char *pfx, char **fqdn, unsigned int opts)
+                                      struct protocol **proto, struct net_addr_type *sa_type,
+                                      char **err, const char *pfx, char **fqdn, unsigned int opts)
 {
        static THREAD_LOCAL struct sockaddr_storage ss;
        struct sockaddr_storage *ret = NULL;
@@ -963,8 +965,8 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
        int portl, porth, porta;
        int abstract = 0;
        int new_fd = -1;
-       enum proto_type proto_type;
-       int ctrl_type;
+       enum proto_type proto_type = 0; // to shut gcc warning
+       int ctrl_type = 0; // to shut gcc warning
 
        portl = porth = porta = 0;
        if (fqdn)
@@ -1383,6 +1385,10 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
                *fd = new_fd;
        if (proto)
                *proto = new_proto;
+       if (sa_type) {
+               sa_type->proto_type = proto_type;
+               sa_type->xprt_type = (ctrl_type == SOCK_DGRAM) ? PROTO_TYPE_DGRAM : PROTO_TYPE_STREAM;
+       }
        free(back);
        return ret;
 }
@@ -6018,7 +6024,7 @@ const char *hash_ipanon(uint32_t scramble, char *ipstring, int hasport)
                        sa = &ss;
                }
                else {
-                       sa = str2sa_range(ipstring, NULL, NULL, NULL, NULL, NULL, &errmsg, NULL, NULL,
+                       sa = str2sa_range(ipstring, NULL, NULL, NULL, NULL, NULL, NULL, &errmsg, NULL, NULL,
                                          PA_O_PORT_OK | PA_O_STREAM | PA_O_DGRAM | PA_O_XPRT | PA_O_CONNECT |
                                          PA_O_PORT_RANGE | PA_O_PORT_OFS | PA_O_RESOLVE);
                        if (sa == NULL) {