]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
CLEANUP: proto_tcp: use the same code to bind servers and backends
authorWilly Tarreau <w@1wt.eu>
Sat, 8 Dec 2012 21:49:11 +0000 (22:49 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 9 Dec 2012 09:05:37 +0000 (10:05 +0100)
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.

src/proto_tcp.c

index 83d568c1948c18b9378aec9f0c32d4dd524253f7..eb4444235c9311c6850ecb1da12419556c6d6bd4 100644 (file)
@@ -247,6 +247,7 @@ int tcp_connect_server(struct connection *conn, int data, int delack)
        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 @@ int tcp_connect_server(struct connection *conn, int data, int delack)
         * - 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 @@ int tcp_connect_server(struct connection *conn, int data, int delack)
 
 #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 @@ int tcp_connect_server(struct connection *conn, int data, int delack)
                                        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;