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.
diff --git a/src/standard.c b/src/standard.c
index fed8477..41c54ac 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -808,7 +808,10 @@
  *     that the caller will have to free(),
  *   - NULL if there was an explicit address that doesn't require resolution.
  *
- * Hostnames are only resolved if <resolve> is non-null.
+ * Hostnames are only resolved if <resolve> is non-null. Note that if <resolve>
+ * is null, <fqdn> is still honnored so it is possible for the caller to know
+ * whether a resolution failed by setting <resolve> to null and checking if
+ * <fqdn> 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 @@
 		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 @@
 			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 @@
 			memprintf(err, "invalid character '%c' in port number '%s' in '%s'\n", *port1, port1, str);
 			goto out;
 		}
-		set_host_port(&ss, porta);
+
+		/* 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 <fqdn> 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 (use_fqdn && fqdn) {
-			if (str2 != back)
-				memmove(back, str2, strlen(str2) + 1);
-			*fqdn = back;
-			back = NULL;
+			if (fqdn) {
+				if (str2 != back)
+					memmove(back, str2, strlen(str2) + 1);
+				*fqdn = back;
+				back = NULL;
+			}
 		}
+		set_host_port(&ss, porta);
 	}
 
 	ret = &ss;