From: Aurelien DARRAGON Date: Thu, 9 Nov 2023 10:19:24 +0000 (+0100) Subject: MINOR: tools: make str2sa_range() directly return type hints X-Git-Tag: v2.9-dev10~99 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12582eb8e50a88cd9d27b12ed6c97dada227b980;p=thirdparty%2Fhaproxy.git MINOR: tools: make str2sa_range() directly return type hints str2sa_range() already allows the caller to provide 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. --- diff --git a/include/haproxy/tools-t.h b/include/haproxy/tools-t.h index 805ade6a3f..32d8193fe9 100644 --- a/include/haproxy/tools-t.h +++ b/include/haproxy/tools-t.h @@ -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 */ diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index 2fc92bb902..e3b847905f 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -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 and into a string representation of the address and port. This is sort diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index 0b6f7fa075..6c7cc6382a 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -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", diff --git a/src/cfgparse.c b/src/cfgparse.c index 11d262455d..312b1d7096 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -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) { diff --git a/src/check.c b/src/check.c index 91fdbcb8c2..51c028189b 100644 --- a/src/check.c +++ b/src/check.c @@ -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); diff --git a/src/cli.c b/src/cli.c index 0a78ed7807..b176d52325 100644 --- 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; } diff --git a/src/hlua.c b/src/hlua.c index 7e0580d359..c5a1c615bd 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -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)); diff --git a/src/http_client.c b/src/http_client.c index e8fdf42a1f..fca13a2976 100644 --- a/src/http_client.c +++ b/src/http_client.c @@ -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) { diff --git a/src/log.c b/src/log.c index 3458f93f93..5efc08b3ae 100644 --- 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) diff --git a/src/resolvers.c b/src/resolvers.c index c820d9cfb0..4ef55b9135 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -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); diff --git a/src/server.c b/src/server.c index ca48f2875f..80e26ab94f 100644 --- a/src/server.c +++ b/src/server.c @@ -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) | diff --git a/src/tcpcheck.c b/src/tcpcheck.c index c00c47fede..d30ecb57ec 100644 --- a/src/tcpcheck.c +++ b/src/tcpcheck.c @@ -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); diff --git a/src/tools.c b/src/tools.c index 45f519ab8c..d67356f8ee 100644 --- a/src/tools.c +++ b/src/tools.c @@ -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 if non-null. + * The address protocol and transport types hints which are directly resolved + * will be set into if not NULL. * * Any known file descriptor is also assigned to 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) {