diff --git a/include/common/standard.h b/include/common/standard.h index fc044fb6a..a8e1b9952 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -277,7 +277,7 @@ extern const char *invalid_domainchar(const char *name); * If 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 *low, int *high, char **err, const char *pfx); +struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char **err, const char *pfx, char **fqdn); /* converts 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 diff --git a/src/cfgparse.c b/src/cfgparse.c index 6e2bcd72e..71d3fea23 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -239,7 +239,8 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, } ss2 = str2sa_range(str, &port, &end, err, - curproxy == global.stats_fe ? NULL : global.unix_bind.prefix); + curproxy == global.stats_fe ? NULL : global.unix_bind.prefix, + NULL); if (!ss2) goto fail; @@ -1597,7 +1598,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm) } } - sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg); err_code |= ERR_ALERT | ERR_FATAL; @@ -2027,7 +2028,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) newpeer->last_change = now.tv_sec; newpeer->id = strdup(args[1]); - sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); err_code |= ERR_ALERT | ERR_FATAL; @@ -2227,7 +2228,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], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); err_code |= ERR_ALERT | ERR_FATAL; @@ -2411,7 +2412,7 @@ int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm) newmailer->id = strdup(args[1]); - sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); err_code |= ERR_ALERT | ERR_FATAL; @@ -5545,7 +5546,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], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg); err_code |= ERR_ALERT | ERR_FATAL; @@ -5817,7 +5818,7 @@ stats_error_parsing: } } - sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg); err_code |= ERR_ALERT | ERR_FATAL; @@ -5869,7 +5870,7 @@ stats_error_parsing: curproxy->conn_src.iface_name = NULL; curproxy->conn_src.iface_len = 0; - sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); @@ -5954,7 +5955,7 @@ stats_error_parsing: } else { struct sockaddr_storage *sk; - sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[cur_arg], args[cur_arg+1], errmsg); diff --git a/src/server.c b/src/server.c index 340a31050..0e5c07999 100644 --- a/src/server.c +++ b/src/server.c @@ -904,7 +904,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr * - IP:+N => port=+N, relative * - IP:-N => port=-N, relative */ - sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); err_code |= ERR_ALERT | ERR_FATAL; @@ -1189,7 +1189,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr int port1, port2; struct protocol *proto; - sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[cur_arg], errmsg); @@ -1397,7 +1397,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr } newsrv->conn_src.opts |= CO_SRC_BIND; - sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL); + sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[cur_arg], args[cur_arg+1], errmsg); @@ -1497,7 +1497,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr struct sockaddr_storage *sk; int port1, port2; - sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL); + sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL); if (!sk) { Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[cur_arg], args[cur_arg+1], errmsg); diff --git a/src/standard.c b/src/standard.c index 464173937..58cc5deb4 100644 --- a/src/standard.c +++ b/src/standard.c @@ -755,10 +755,15 @@ struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, i * If is non-null, it is used as a string prefix before any path-based * address (typically the path to a unix socket). * + * if is non-null, it will be filled with : + * - a pointer to the FQDN of the server name to resolve if there's one, and + * that the caller will have to free(), + * - NULL if there was an explicit address that doesn't require resolution. + * * 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_UNSPEC. */ -struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char **err, const char *pfx) +struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char **err, const char *pfx, char **fqdn) { static struct sockaddr_storage ss; struct sockaddr_storage *ret = NULL; @@ -768,6 +773,8 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char int abstract = 0; portl = porth = porta = 0; + if (fqdn) + *fqdn = NULL; str2 = back = env_expand(strdup(str)); if (str2 == NULL) { @@ -840,15 +847,20 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char memcpy(((struct sockaddr_un *)&ss)->sun_path + prefix_path_len + abstract, str2, adr_len + 1 - abstract); } else { /* IPv4 and IPv6 */ + int use_fqdn = 0; + port1 = strrchr(str2, ':'); if (port1) *port1++ = '\0'; else port1 = ""; - if (str2ip(str2, &ss) == NULL) { - memprintf(err, "invalid address: '%s' in '%s'\n", str2, str); - goto out; + if (str2ip2(str2, &ss, 0) == NULL) { + use_fqdn = 1; + if (str2ip(str2, &ss) == NULL) { + memprintf(err, "invalid address: '%s' in '%s'\n", str2, str); + goto out; + } } if (isdigit((int)(unsigned char)*port1)) { /* single port or range */ @@ -874,6 +886,13 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char goto out; } set_host_port(&ss, porta); + + if (use_fqdn && fqdn) { + if (str2 != back) + memmove(back, str2, strlen(str2) + 1); + *fqdn = back; + back = NULL; + } } ret = &ss;