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;