CLEANUP: proto_tcp: use the same code to bind servers and backends

The tproxy and source binding code has now be factored out for
servers and backends. A nice effect is that the code now supports
having backends use source port ranges, though the config does not
support it yet. This change has reduced the executable by around
700 bytes.
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 83d568c..eb44442 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -247,6 +247,7 @@
 	int fd;
 	struct server *srv;
 	struct proxy *be;
+	struct conn_src *src;
 
 	switch (obj_type(conn->target)) {
 	case OBJ_TYPE_PROXY:
@@ -303,11 +304,18 @@
 	 * - server-specific at first
 	 * - proxy-specific next
 	 */
-	if (srv != NULL && srv->conn_src.opts & CO_SRC_BIND) {
+	if (srv && srv->conn_src.opts & CO_SRC_BIND)
+		src = &srv->conn_src;
+	else if (be->conn_src.opts & CO_SRC_BIND)
+		src = &be->conn_src;
+	else
+		src = NULL;
+
+	if (src) {
 		int ret, flags = 0;
 
 		if (is_addr(&conn->addr.from)) {
-			switch (srv->conn_src.opts & CO_SRC_TPROXY_MASK) {
+			switch (src->opts & CO_SRC_TPROXY_MASK) {
 			case CO_SRC_TPROXY_ADDR:
 			case CO_SRC_TPROXY_CLI:
 				flags = 3;
@@ -321,16 +329,16 @@
 
 #ifdef SO_BINDTODEVICE
 		/* Note: this might fail if not CAP_NET_RAW */
-		if (srv->conn_src.iface_name)
-			setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, srv->conn_src.iface_name, srv->conn_src.iface_len + 1);
+		if (src->iface_name)
+			setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, src->iface_name, src->iface_len + 1);
 #endif
 
-		if (srv->conn_src.sport_range) {
+		if (src->sport_range) {
 			int attempts = 10; /* should be more than enough to find a spare port */
-			struct sockaddr_storage src;
+			struct sockaddr_storage sa;
 
 			ret = 1;
-			src = srv->conn_src.source_addr;
+			sa = src->source_addr;
 
 			do {
 				/* note: in case of retry, we may have to release a previously
@@ -343,76 +351,36 @@
 					break;
 				attempts--;
 
-				fdinfo[fd].local_port = port_range_alloc_port(srv->conn_src.sport_range);
+				fdinfo[fd].local_port = port_range_alloc_port(src->sport_range);
 				if (!fdinfo[fd].local_port)
 					break;
 
-				fdinfo[fd].port_range = srv->conn_src.sport_range;
-				set_host_port(&src, fdinfo[fd].local_port);
+				fdinfo[fd].port_range = src->sport_range;
+				set_host_port(&sa, fdinfo[fd].local_port);
 
-				ret = tcp_bind_socket(fd, flags, &src, &conn->addr.from);
+				ret = tcp_bind_socket(fd, flags, &sa, &conn->addr.from);
 			} while (ret != 0); /* binding NOK */
 		}
 		else {
-			ret = tcp_bind_socket(fd, flags, &srv->conn_src.source_addr, &conn->addr.from);
+			ret = tcp_bind_socket(fd, flags, &src->source_addr, &conn->addr.from);
 		}
 
-		if (ret) {
+		if (unlikely(ret != 0)) {
 			port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
 			fdinfo[fd].port_range = NULL;
 			close(fd);
 
-			if (ret == 1) {
-				Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
-				      be->id, srv->id);
-				send_log(be, LOG_EMERG,
-					 "Cannot bind to source address before connect() for server %s/%s.\n",
-					 be->id, srv->id);
-			} else {
-				Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
-				      be->id, srv->id);
-				send_log(be, LOG_EMERG,
-					 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
-					 be->id, srv->id);
-			}
-			return SN_ERR_RESOURCE;
-		}
-	}
-	else if (be->conn_src.opts & CO_SRC_BIND) {
-		int ret, flags = 0;
-
-		if (is_addr(&conn->addr.from)) {
-			switch (be->conn_src.opts & CO_SRC_BIND) {
-			case CO_SRC_TPROXY_ADDR:
-			case CO_SRC_TPROXY_CLI:
-				flags = 3;
-				break;
-			case CO_SRC_TPROXY_CIP:
-			case CO_SRC_TPROXY_DYN:
-				flags = 1;
-				break;
-			}
-		}
-
-#ifdef SO_BINDTODEVICE
-		/* Note: this might fail if not CAP_NET_RAW */
-		if (be->conn_src.iface_name)
-			setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, be->conn_src.iface_name, be->conn_src.iface_len + 1);
-#endif
-		ret = tcp_bind_socket(fd, flags, &be->conn_src.source_addr, &conn->addr.from);
-		if (ret) {
-			close(fd);
 			if (ret == 1) {
-				Alert("Cannot bind to source address before connect() for proxy %s. Aborting.\n",
+				Alert("Cannot bind to source address before connect() for backend %s. Aborting.\n",
 				      be->id);
 				send_log(be, LOG_EMERG,
-					 "Cannot bind to source address before connect() for proxy %s.\n",
+					 "Cannot bind to source address before connect() for backend %s.\n",
 					 be->id);
 			} else {
-				Alert("Cannot bind to tproxy source address before connect() for proxy %s. Aborting.\n",
+				Alert("Cannot bind to tproxy source address before connect() for backend %s. Aborting.\n",
 				      be->id);
 				send_log(be, LOG_EMERG,
-					 "Cannot bind to tproxy source address before connect() for proxy %s.\n",
+					 "Cannot bind to tproxy source address before connect() for backend %s.\n",
 					 be->id);
 			}
 			return SN_ERR_RESOURCE;