[BUG] config: report unresolvable host names as errors

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.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 9bdfb3e..90cc9b0 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -795,11 +795,24 @@
 		}
 
 		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 @@
 		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 @@
 			err_code |= ERR_ALERT | ERR_FATAL;
 			goto out;
 		}
+		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 = *str2sa(args[1]);
+		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 @@
 		}
 
 		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 @@
 			} 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 @@
 				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 @@
 			}
 			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 @@
 					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 @@
 						} 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 @@
 			}
 
 			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 @@
 	}
 	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 @@
 		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 @@
 				} 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)
diff --git a/src/standard.c b/src/standard.c
index e9be0f9..2e68936 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -119,6 +119,7 @@
 /*
  * 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 @@
 	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 @@
 /*
  * 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 @@
 		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 @@
  * 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 @@
 		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