From ceccdd78a716ec4624a72432308323dcb4744146 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 2 Nov 2016 22:27:10 +0100 Subject: [PATCH] MEDIUM: tools: make str2sa_range() return the FQDN even when not resolving This will be needed to later postpone server address resolution. We need the FQDN even when it doesn't resolve. The caller then needs to check if fqdn was set when resolve is null to detect that the address couldn't be parsed and needs later resolution. --- src/standard.c | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/standard.c b/src/standard.c index fed847777..41c54acfd 100644 --- a/src/standard.c +++ b/src/standard.c @@ -808,7 +808,10 @@ struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, i * that the caller will have to free(), * - NULL if there was an explicit address that doesn't require resolution. * - * Hostnames are only resolved if is non-null. + * Hostnames are only resolved if is non-null. Note that if + * is null, is still honnored so it is possible for the caller to know + * whether a resolution failed by setting to null and checking if + * was filled, indicating the need for a 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. @@ -902,7 +905,6 @@ 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; char *end = str2 + strlen(str2); char *chr; @@ -927,14 +929,6 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char port1 = ""; } - if (str2ip2(str2, &ss, 0) == NULL) { - use_fqdn = 1; - if (!resolve || str2ip2(str2, &ss, 1) == NULL) { - memprintf(err, "invalid address: '%s' in '%s'\n", str2, str); - goto out; - } - } - if (isdigit((int)(unsigned char)*port1)) { /* single port or range */ port2 = strchr(port1, '-'); if (port2) @@ -957,14 +951,34 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char memprintf(err, "invalid character '%c' in port number '%s' in '%s'\n", *port1, port1, str); goto out; } - set_host_port(&ss, porta); - if (use_fqdn && fqdn) { - if (str2 != back) - memmove(back, str2, strlen(str2) + 1); - *fqdn = back; - back = NULL; + /* first try to parse the IP without resolving. If it fails, it + * tells us we need to keep a copy of the FQDN to resolve later + * and to enable DNS. In this case we can proceed if is + * set or if resolve is set, otherwise it's an error. + */ + if (str2ip2(str2, &ss, 0) == NULL) { + if (!resolve && fqdn) { + /* we'll still want to store the port, so let's + * force it to IPv4 for now. + */ + memset(&ss, 0, sizeof(ss)); + ss.ss_family = AF_INET; + } + else if ((!resolve && !fqdn) || + (resolve && str2ip2(str2, &ss, 1) == NULL)) { + memprintf(err, "invalid address: '%s' in '%s'\n", str2, str); + goto out; + } + + if (fqdn) { + if (str2 != back) + memmove(back, str2, strlen(str2) + 1); + *fqdn = back; + back = NULL; + } } + set_host_port(&ss, porta); } ret = &ss;