From: Willy Tarreau Date: Tue, 15 Sep 2020 12:01:16 +0000 (+0200) Subject: MINOR: tools: make str2sa_range() optionally return the fd X-Git-Tag: v2.3-dev5~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a93e5c7fae9ec624ef9fa779c6b875238c60542a;p=thirdparty%2Fhaproxy.git MINOR: tools: make str2sa_range() optionally return the fd If a file descriptor was passed, we can optionally return it. This will be useful for listening sockets which are both a pre-bound FD and a ready socket. --- diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index 095485f4d4..25a66f8fd0 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -242,7 +242,7 @@ 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 *port, int *low, int *high, int *fd, char **err, const char *pfx, char **fqdn, unsigned int opts); diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index 2819ad9e3c..d29505a3eb 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -2600,7 +2600,8 @@ 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, &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, + &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); err_code |= ERR_ALERT | ERR_FATAL; @@ -2858,7 +2859,8 @@ stats_error_parsing: curproxy->conn_src.iface_name = NULL; curproxy->conn_src.iface_len = 0; - sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); + sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, + &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); if (!sk) { ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); @@ -2936,7 +2938,8 @@ stats_error_parsing: } else { struct sockaddr_storage *sk; - sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); + sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL, + &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); if (!sk) { ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[cur_arg], args[cur_arg+1], errmsg); diff --git a/src/cfgparse.c b/src/cfgparse.c index 1ff555c359..59827f4581 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -126,7 +126,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, *next++ = 0; } - ss2 = str2sa_range(str, NULL, &port, &end, err, + ss2 = str2sa_range(str, NULL, &port, &end, &fd, 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_STREAM | PA_O_XPRT); @@ -1009,7 +1009,7 @@ 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, &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, &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; @@ -1385,7 +1385,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, &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, &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; diff --git a/src/check.c b/src/check.c index 21978da509..40788ae98e 100644 --- a/src/check.c +++ b/src/check.c @@ -2638,7 +2638,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, errmsg, NULL, NULL, + sk = str2sa_range(args[*cur_arg+1], NULL, &port1, &port2, NULL, errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); if (!sk) { memprintf(errmsg, "'%s' : %s", args[*cur_arg], *errmsg); diff --git a/src/cli.c b/src/cli.c index 55d2a034af..2892d882f4 100644 --- a/src/cli.c +++ b/src/cli.c @@ -2475,7 +2475,8 @@ 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, &errmsg, NULL, NULL, PA_O_STREAM)) == 0) { + if ((sk = str2sa_range(msg, &port, &port1, &port2, NULL, + &errmsg, NULL, NULL, PA_O_STREAM)) == 0) { goto error; } free(msg); diff --git a/src/hlua.c b/src/hlua.c index b3b93e8d0a..5589482b02 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -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, PA_O_PORT_OK | PA_O_STREAM); + addr = str2sa_range(ip, NULL, &low, &high, 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/log.c b/src/log.c index e31d85b700..fcb16f6be2 100644 --- a/src/log.c +++ b/src/log.c @@ -1021,7 +1021,8 @@ int parse_logsrv(char **args, struct list *logsrvs, int do_del, char **err) if (strncmp(args[1], "fd@", 3) == 0) logsrv->type = LOG_TARGET_FD; - sk = str2sa_range(args[1], NULL, &port1, &port2, err, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_RAW_FD | PA_O_DGRAM); + sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, + err, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_RAW_FD | PA_O_DGRAM); if (!sk) goto error; logsrv->addr = *sk; diff --git a/src/server.c b/src/server.c index 5c457186f4..84b66f734c 100644 --- a/src/server.c +++ b/src/server.c @@ -659,7 +659,8 @@ 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, &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, + &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; @@ -744,7 +745,8 @@ 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, &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); + sk = str2sa_range(args[*cur_arg + 1], NULL, &port1, &port2, NULL, + &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; @@ -840,7 +842,8 @@ 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, &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, + &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; @@ -2027,7 +2030,8 @@ 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, &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, + &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); err_code |= ERR_ALERT | ERR_FATAL; diff --git a/src/tcpcheck.c b/src/tcpcheck.c index abd92cf15c..8da89559b8 100644 --- a/src/tcpcheck.c +++ b/src/tcpcheck.c @@ -2224,7 +2224,8 @@ 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, errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM); + sk = str2sa_range(args[cur_arg+1], NULL, &port1, &port2, NULL, + 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; diff --git a/src/tools.c b/src/tools.c index 4f61ae2562..9fffc70299 100644 --- a/src/tools.c +++ b/src/tools.c @@ -863,8 +863,11 @@ struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, i * When a file descriptor is passed, its value is put into the s_addr part of * the address when cast to sockaddr_in and the address family is * AF_CUST_EXISTING_FD. + * + * 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, 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, char **err, const char *pfx, char **fqdn, unsigned int opts) { static THREAD_LOCAL struct sockaddr_storage ss; struct sockaddr_storage *ret = NULL; @@ -873,6 +876,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int int portl, porth, porta; int abstract = 0; int is_udp = 0; + int new_fd = -1; portl = porth = porta = 0; if (fqdn) @@ -941,24 +945,26 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int if (ss.ss_family == AF_CUST_SOCKPAIR) { char *endptr; - ((struct sockaddr_in *)&ss)->sin_addr.s_addr = strtol(str2, &endptr, 10); - ((struct sockaddr_in *)&ss)->sin_port = 0; - - if (!*str2 || *endptr) { + new_fd = strtol(str2, &endptr, 10); + if (!*str2 || new_fd < 0 || *endptr) { memprintf(err, "file descriptor '%s' is not a valid integer in '%s'\n", str2, str); goto out; } + + ((struct sockaddr_in *)&ss)->sin_addr.s_addr = new_fd; + ((struct sockaddr_in *)&ss)->sin_port = 0; } else if (ss.ss_family == AF_CUST_EXISTING_FD) { char *endptr; - ((struct sockaddr_in *)&ss)->sin_addr.s_addr = strtol(str2, &endptr, 10); - ((struct sockaddr_in *)&ss)->sin_port = 0; - - if (!*str2 || *endptr) { + new_fd = strtol(str2, &endptr, 10); + if (!*str2 || new_fd < 0 || *endptr) { memprintf(err, "file descriptor '%s' is not a valid integer in '%s'\n", str2, str); goto out; } + + ((struct sockaddr_in *)&ss)->sin_addr.s_addr = new_fd; + ((struct sockaddr_in *)&ss)->sin_port = 0; } else if (ss.ss_family == AF_UNIX) { struct sockaddr_un *un = (struct sockaddr_un *)&ss; @@ -1111,6 +1117,8 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int *low = portl; if (high) *high = porth; + if (fd) + *fd = new_fd; free(back); return ret; }