]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[BUG] config: report unresolvable host names as errors
authorWilly Tarreau <w@1wt.eu>
Tue, 9 Feb 2010 19:50:45 +0000 (20:50 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 9 Feb 2010 19:50:45 +0000 (20:50 +0100)
When a host name could not be resolved, an alert was emitted but the
service used to start with 0.0.0.0 for the IP address, because the
address parsing functions could not report an error. This is now
changed. This fix must be backported to 1.3 as it was first discovered
there.

src/cfgparse.c
src/standard.c

index 9bdfb3e3d579a03cf09a90e1220b3aeb74fe1d97..90cc9b03bb814827e40038c9980515464292bf98 100644 (file)
@@ -795,11 +795,24 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                }
 
                if (args[1][0] == '/') {
+                       struct sockaddr_un *sk = str2sun(args[1]);
+                       if (!sk) {
+                               Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
+                                     args[1], (int)sizeof(sk->sun_path) - 1);
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
+                       }
+                       logsrv.u.un = *sk;
                        logsrv.u.addr.sa_family = AF_UNIX;
-                       logsrv.u.un = *str2sun(args[1]);
                } else {
+                       struct sockaddr_in *sk = str2sa(args[1]);
+                       if (!sk) {
+                               Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
+                       }
+                       logsrv.u.in = *sk;
                        logsrv.u.addr.sa_family = AF_INET;
-                       logsrv.u.in = *str2sa(args[1]);
                        if (!logsrv.u.in.sin_port)
                                logsrv.u.in.sin_port = htons(SYSLOG_PORT);
                }
@@ -2950,6 +2963,7 @@ stats_error_parsing:
                curproxy->grace = val;
        }
        else if (!strcmp(args[0], "dispatch")) {  /* dispatch address */
+               struct sockaddr_in *sk;
                if (curproxy == &defproxy) {
                        Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
                        err_code |= ERR_ALERT | ERR_FATAL;
@@ -2963,7 +2977,13 @@ stats_error_parsing:
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
-               curproxy->dispatch_addr = *str2sa(args[1]);
+               sk = str2sa(args[1]);
+               if (!sk) {
+                       Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+               curproxy->dispatch_addr = *sk;
        }
        else if (!strcmp(args[0], "balance")) {  /* set balancing with optional algorithm */
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
@@ -3024,6 +3044,8 @@ stats_error_parsing:
                }
 
                if (!defsrv) {
+                       struct sockaddr_in *sk;
+
                        if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
                                Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
                                err_code |= ERR_ALERT | ERR_ABORT;
@@ -3060,9 +3082,15 @@ stats_error_parsing:
                        } else
                                newsrv->state |= SRV_MAPPORTS;
 
-                       newsrv->addr = *str2sa(raddr);
-                       newsrv->addr.sin_port = htons(realport);
+                       sk = str2sa(raddr);
                        free(raddr);
+                       if (!sk) {
+                               Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
+                       }
+                       newsrv->addr = *sk;
+                       newsrv->addr.sin_port = htons(realport);
 
                        newsrv->check_port      = curproxy->defsrv.check_port;
                        newsrv->inter           = curproxy->defsrv.inter;
@@ -3221,7 +3249,13 @@ stats_error_parsing:
                                cur_arg += 2;
                        }
                        else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
-                               newsrv->check_addr = *str2sa(args[cur_arg + 1]);
+                               struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
+                               if (!sk) {
+                                       Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
+                               }
+                               newsrv->check_addr = *sk;
                                cur_arg += 2;
                        }
                        else if (!strcmp(args[cur_arg], "port")) {
@@ -3353,6 +3387,8 @@ stats_error_parsing:
                        }
                        else if (!defsrv && !strcmp(args[cur_arg], "source")) {  /* address to which we bind when connecting */
                                int port_low, port_high;
+                               struct sockaddr_in *sk;
+
                                if (!*args[cur_arg + 1]) {
 #if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
                                        Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
@@ -3365,7 +3401,13 @@ stats_error_parsing:
                                        goto out;
                                }
                                newsrv->state |= SRV_BIND_SRC;
-                               newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
+                               sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
+                               if (!sk) {
+                                       Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
+                               }
+                               newsrv->source_addr = *sk;
 
                                if (port_low != port_high) {
                                        int i;
@@ -3405,8 +3447,14 @@ stats_error_parsing:
                                                } else if (!strcmp(args[cur_arg + 1], "clientip")) {
                                                        newsrv->state |= SRV_TPROXY_CIP;
                                                } else {
+                                                       struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
+                                                       if (!sk) {
+                                                               Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
+                                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                                               goto out;
+                                                       }
+                                                       newsrv->tproxy_addr = *sk;
                                                        newsrv->state |= SRV_TPROXY_ADDR;
-                                                       newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
                                                }
                                                global.last_checks |= LSTCHK_NETADM;
 #if !defined(CONFIG_HAP_LINUX_TPROXY)
@@ -3558,11 +3606,24 @@ stats_error_parsing:
                        }
 
                        if (args[1][0] == '/') {
+                               struct sockaddr_un *sk = str2sun(args[1]);
+                               if (!sk) {
+                                       Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
+                                             args[1], (int)sizeof(sk->sun_path) - 1);
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
+                               }
+                               logsrv.u.un = *sk;
                                logsrv.u.addr.sa_family = AF_UNIX;
-                               logsrv.u.un = *str2sun(args[1]);
                        } else {
+                               struct sockaddr_in *sk = str2sa(args[1]);
+                               if (!sk) {
+                                       Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
+                               }
+                               logsrv.u.in = *sk;
                                logsrv.u.addr.sa_family = AF_INET;
-                               logsrv.u.in = *str2sa(args[1]);
                                if (!logsrv.u.in.sin_port) {
                                        logsrv.u.in.sin_port =
                                                htons(SYSLOG_PORT);
@@ -3596,6 +3657,7 @@ stats_error_parsing:
        }
        else if (!strcmp(args[0], "source")) {  /* address to which we bind when connecting */
                int cur_arg;
+               struct sockaddr_in *sk;
 
                if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
                        err_code |= ERR_WARN;
@@ -3613,7 +3675,13 @@ stats_error_parsing:
                curproxy->iface_name = NULL;
                curproxy->iface_len = 0;
 
-               curproxy->source_addr = *str2sa(args[1]);
+               sk = str2sa(args[1]);
+               if (!sk) {
+                       Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+               curproxy->source_addr = *sk;
                curproxy->options |= PR_O_BIND_SRC;
 
                cur_arg = 2;
@@ -3640,8 +3708,14 @@ stats_error_parsing:
                                } else if (!strcmp(args[cur_arg + 1], "clientip")) {
                                        curproxy->options |= PR_O_TPXY_CIP;
                                } else {
+                                       struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
+                                       if (!sk) {
+                                               Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
+                                       }
+                                       curproxy->tproxy_addr = *sk;
                                        curproxy->options |= PR_O_TPXY_ADDR;
-                                       curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
                                }
                                global.last_checks |= LSTCHK_NETADM;
 #if !defined(CONFIG_HAP_LINUX_TPROXY)
index e9be0f97f5b4c847af56a8bb40bd9a91cf2a8c4f..2e68936545ae47757bc724822cadd6884b67102a 100644 (file)
@@ -119,6 +119,7 @@ const char *limit_r(unsigned long n, char *buffer, int size, const char *alt)
 /*
  * converts <str> to a struct sockaddr_un* which is locally allocated.
  * The format is "/path", where "/path" is a path to a UNIX domain socket.
+ * NULL is returned if the socket path is invalid (too long).
  */
 struct sockaddr_un *str2sun(const char *str)
 {
@@ -128,8 +129,7 @@ struct sockaddr_un *str2sun(const char *str)
        memset(&su, 0, sizeof(su));
        strsz = strlen(str) + 1;
        if (strsz > sizeof(su.sun_path)) {
-               Alert("Socket path '%s' too long (max %d)\n",
-                     str, (int)sizeof(su.sun_path) - 1);
+               return NULL;
        } else {
                su.sun_family = AF_UNIX;
                memcpy(su.sun_path, str, strsz);
@@ -216,18 +216,20 @@ const char *invalid_domainchar(const char *name) {
 /*
  * converts <str> to a struct sockaddr_in* which is locally allocated.
  * The format is "addr:port", where "addr" can be a dotted IPv4 address,
- * a host name, or empty or "*" to indicate INADDR_ANY.
+ * a host name, or empty or "*" to indicate INADDR_ANY. NULL is returned
+ * if the host part cannot be resolved.
  */
 struct sockaddr_in *str2sa(char *str)
 {
        static struct sockaddr_in sa;
+       struct sockaddr_in *ret = NULL;
        char *c;
        int port;
 
        memset(&sa, 0, sizeof(sa));
        str = strdup(str);
        if (str == NULL)
-               goto out_nofree;
+               goto out;
 
        if ((c = strrchr(str,':')) != NULL) {
                *c++ = '\0';
@@ -240,20 +242,17 @@ struct sockaddr_in *str2sa(char *str)
                sa.sin_addr.s_addr = INADDR_ANY;
        }
        else if (!inet_pton(AF_INET, str, &sa.sin_addr)) {
-               struct hostent *he;
-
-               if ((he = gethostbyname(str)) == NULL) {
-                       Alert("Invalid server name: '%s'\n", str);
-               }
-               else
-                       sa.sin_addr = *(struct in_addr *) *(he->h_addr_list);
+               struct hostent *he = gethostbyname(str);
+               if (!he)
+                       goto out;
+               sa.sin_addr = *(struct in_addr *) *(he->h_addr_list);
        }
        sa.sin_port   = htons(port);
        sa.sin_family = AF_INET;
-
+       ret = &sa;
+ out:
        free(str);
- out_nofree:
-       return &sa;
+       return ret;
 }
 
 /*
@@ -263,18 +262,20 @@ struct sockaddr_in *str2sa(char *str)
  * port is set in the sockaddr_in. Thus, it is enough to check the size of the
  * returned range to know if an array must be allocated or not. The format is
  * "addr[:port[-port]]", where "addr" can be a dotted IPv4 address, a host
- * name, or empty or "*" to indicate INADDR_ANY.
+ * name, or empty or "*" to indicate INADDR_ANY. NULL is returned if the host
+ * part cannot be resolved.
  */
 struct sockaddr_in *str2sa_range(char *str, int *low, int *high)
 {
        static struct sockaddr_in sa;
+       struct sockaddr_in *ret = NULL;
        char *c;
        int portl, porth;
 
        memset(&sa, 0, sizeof(sa));
        str = strdup(str);
        if (str == NULL)
-               goto out_nofree;
+               goto out;
 
        if ((c = strrchr(str,':')) != NULL) {
                char *sep;
@@ -296,23 +297,21 @@ struct sockaddr_in *str2sa_range(char *str, int *low, int *high)
                sa.sin_addr.s_addr = INADDR_ANY;
        }
        else if (!inet_pton(AF_INET, str, &sa.sin_addr)) {
-               struct hostent *he;
-
-               if ((he = gethostbyname(str)) == NULL) {
-                       Alert("Invalid server name: '%s'\n", str);
-               }
-               else
-                       sa.sin_addr = *(struct in_addr *) *(he->h_addr_list);
+               struct hostent *he = gethostbyname(str);
+               if (!he)
+                       goto out;
+               sa.sin_addr = *(struct in_addr *) *(he->h_addr_list);
        }
        sa.sin_port   = htons(portl);
        sa.sin_family = AF_INET;
+       ret = &sa;
 
        *low = portl;
        *high = porth;
 
+ out:
        free(str);
- out_nofree:
-       return &sa;
+       return ret;
 }
 
 /* converts <str> to a struct in_addr containing a network mask. It can be