BUG/MEDIUM: tcp: transparent bind to the source only when address is set

Thomas Heil reported that health checks did not work anymore when a backend
or server has "usesrc clientip". This is because the source address is not
set and tcp_bind_socket() tries to bind to that address anyway.

The solution consists in explicitly clearing the source address in the checks
and to make tcp_bind_socket() avoid binding when the address is not set. This
also has an indirect benefit that a useless bind() syscall will be avoided
when using "source 0.0.0.0 usesrc clientip" in health checks.
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index d0424d9..b94f9b2 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -170,14 +170,18 @@
 
 	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
 	if (foreign_ok) {
-		ret = bind(fd, (struct sockaddr *)&bind_addr, get_addr_len(&bind_addr));
-		if (ret < 0)
-			return 2;
+		if (is_addr(&bind_addr)) {
+			ret = bind(fd, (struct sockaddr *)&bind_addr, get_addr_len(&bind_addr));
+			if (ret < 0)
+				return 2;
+		}
 	}
 	else {
-		ret = bind(fd, (struct sockaddr *)local, get_addr_len(local));
-		if (ret < 0)
-			return 1;
+		if (is_addr(local)) {
+			ret = bind(fd, (struct sockaddr *)local, get_addr_len(local));
+			if (ret < 0)
+				return 1;
+		}
 	}
 
 	if (!flags)
@@ -295,15 +299,17 @@
 	if (srv != NULL && srv->state & SRV_BIND_SRC) {
 		int ret, flags = 0;
 
-		switch (srv->state & SRV_TPROXY_MASK) {
-		case SRV_TPROXY_ADDR:
-		case SRV_TPROXY_CLI:
-			flags = 3;
-			break;
-		case SRV_TPROXY_CIP:
-		case SRV_TPROXY_DYN:
-			flags = 1;
-			break;
+		if (is_addr(&conn->addr.from)) {
+			switch (srv->state & SRV_TPROXY_MASK) {
+			case SRV_TPROXY_ADDR:
+			case SRV_TPROXY_CLI:
+				flags = 3;
+				break;
+			case SRV_TPROXY_CIP:
+			case SRV_TPROXY_DYN:
+				flags = 1;
+				break;
+			}
 		}
 
 #ifdef SO_BINDTODEVICE
@@ -368,15 +374,17 @@
 	else if (be->options & PR_O_BIND_SRC) {
 		int ret, flags = 0;
 
-		switch (be->options & PR_O_TPXY_MASK) {
-		case PR_O_TPXY_ADDR:
-		case PR_O_TPXY_CLI:
-			flags = 3;
-			break;
-		case PR_O_TPXY_CIP:
-		case PR_O_TPXY_DYN:
-			flags = 1;
-			break;
+		if (is_addr(&conn->addr.from)) {
+			switch (be->options & PR_O_TPXY_MASK) {
+			case PR_O_TPXY_ADDR:
+			case PR_O_TPXY_CLI:
+				flags = 3;
+				break;
+			case PR_O_TPXY_CIP:
+			case PR_O_TPXY_DYN:
+				flags = 1;
+				break;
+			}
 		}
 
 #ifdef SO_BINDTODEVICE