]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tools: make str2sa_range() return the FQDN even when not resolving
authorWilly Tarreau <w@1wt.eu>
Wed, 2 Nov 2016 21:27:10 +0000 (22:27 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 9 Nov 2016 13:24:20 +0000 (14:24 +0100)
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

index fed847777fe93716901b9e518756975abe399fa7..41c54acfd2757e9711974e0744552a70d723aa89 100644 (file)
@@ -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 <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 @@ 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 <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 (fqdn) {
+                               if (str2 != back)
+                                       memmove(back, str2, strlen(str2) + 1);
+                               *fqdn = back;
+                               back = NULL;
+                       }
                }
+               set_host_port(&ss, porta);
        }
 
        ret = &ss;