]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: connection: make sure all address producers allocate their address
authorWilly Tarreau <w@1wt.eu>
Wed, 17 Jul 2019 17:04:47 +0000 (19:04 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 19 Jul 2019 11:50:09 +0000 (13:50 +0200)
This commit places calls to sockaddr_alloc() at the places where an address
is needed, and makes sure that the allocation is properly tested. This does
not add too many error paths since connection allocations are already in the
vicinity and share the same error paths. For the two cases where a
clear_addr() was called, instead the address was not allocated.

include/proto/connection.h
src/backend.c
src/checks.c
src/connection.c
src/hlua.c
src/http_ana.c
src/peers.c
src/session.c

index c1ce51d22a7f67620992b1518bfd416d8ab02c8f..6d2e78401a552b50888c62c6921ff404de0e05cd 100644 (file)
@@ -675,6 +675,9 @@ static inline int conn_get_src(struct connection *conn)
        if (!conn_ctrl_ready(conn) || !conn->ctrl->get_src)
                return 0;
 
+       if (!sockaddr_alloc(&conn->src))
+               return 0;
+
        if (conn->ctrl->get_src(conn->handle.fd, (struct sockaddr *)conn->src,
                                sizeof(*conn->src),
                                obj_type(conn->target) != OBJ_TYPE_LISTENER) == -1)
@@ -695,6 +698,9 @@ static inline int conn_get_dst(struct connection *conn)
        if (!conn_ctrl_ready(conn) || !conn->ctrl->get_dst)
                return 0;
 
+       if (!sockaddr_alloc(&conn->dst))
+               return 0;
+
        if (conn->ctrl->get_dst(conn->handle.fd, (struct sockaddr *)conn->dst,
                                sizeof(*conn->dst),
                                obj_type(conn->target) != OBJ_TYPE_LISTENER) == -1)
index 18d249871628bc14894923649a4504dca415e82a..dcf364201b64e929cb271996266e98024b53f581 100644 (file)
@@ -826,7 +826,8 @@ int assign_server_address(struct stream *s, struct connection *srv_conn)
 
        DPRINTF(stderr,"assign_server_address : s=%p\n",s);
 
-       /* FIXME WTA: an address allocation will soon be needed here */
+       if (!sockaddr_alloc(&srv_conn->dst))
+               return SRV_STATUS_INTERNAL;
 
        if ((s->flags & SF_DIRECT) || (s->be->lbprm.algo & BE_LB_KIND)) {
                /* A server is necessarily known for this stream */
@@ -1039,7 +1040,8 @@ static void assign_tproxy_address(struct stream *s)
        else
                return;
 
-       /* FIXME WTA: an address allocation will soon be needed here for src */
+       if (!sockaddr_alloc(&srv_conn->src))
+               return;
 
        switch (src->opts & CO_SRC_TPROXY_MASK) {
        case CO_SRC_TPROXY_ADDR:
index c2fc87c38e64d1486137a709846e4c26bd8c1fe4..61acb17c0f96f4b780dfce75b4032089cb6ea23e 100644 (file)
@@ -1614,7 +1614,9 @@ static int connect_conn_chk(struct task *t)
        /* Maybe there were an older connection we were waiting on */
        check->wait_list.events = 0;
 
-       /* FIXME WTA: we'll have to dynamically allocate the dst address here */
+       if (!sockaddr_alloc(&conn->dst))
+               return SF_ERR_RESOURCE;
+
        if (is_addr(&check->addr)) {
                /* we'll connect to the check addr specified on the server */
                *conn->dst = check->addr;
@@ -1643,10 +1645,6 @@ static int connect_conn_chk(struct task *t)
        }
 
        /* no client address */
-       /* FIXME WTA: we'll have to dynamically allocate the src address here
-        * before clearing it, or better release it and make it null.
-        */
-       clear_addr(conn->src);
 
        conn_prepare(conn, proto, check->xprt);
        if (conn_install_mux(conn, &mux_pt_ops, cs, s->proxy, NULL) < 0)
@@ -2862,12 +2860,12 @@ static int tcpcheck_main(struct check *check)
                        conn->target = s ? &s->obj_type : &proxy->obj_type;
 
                        /* no client address */
-                       /* FIXME WTA: we'll have to dynamically allocate the src address here
-                        * before clearing it, or better release it and make it null.
-                        */
-                       clear_addr(conn->src);
 
-                       /* FIXME WTA: we'll have to dynamically allocate the dst address here */
+                       if (!sockaddr_alloc(&conn->dst)) {
+                               ret = SF_ERR_RESOURCE;
+                               goto fail_check;
+                       }
+
                        if (is_addr(&check->addr)) {
                                /* we'll connect to the check addr specified on the server */
                                *conn->dst = check->addr;
index 0277309aca20be520e8458cdcd50147dbc720c07..602fc79ec48ff88de39c5d48c7724c2ff5849471 100644 (file)
@@ -402,6 +402,9 @@ int conn_recv_proxy(struct connection *conn, int flag)
        if (!conn_ctrl_ready(conn))
                goto fail;
 
+       if (!sockaddr_alloc(&conn->src) || !sockaddr_alloc(&conn->dst))
+               goto fail;
+
        if (!fd_recv_ready(conn->handle.fd))
                goto not_ready;
 
index 150faecb7596a47a5ab5c5763df9c0695f60100e..49f056c3988cc67b80ee0c350988a45cdb07ebae 100644 (file)
@@ -2461,7 +2461,11 @@ __LJMP static int hlua_socket_connect(struct lua_State *L)
                WILL_LJMP(luaL_error(L, "connect: port ranges not supported : address '%s'", ip));
        }
 
-       /* FIXME WTA: dst address allocation needed here! */
+       if (!sockaddr_alloc(&conn->dst)) {
+               xref_unlock(&socket->xref, peer);
+               WILL_LJMP(luaL_error(L, "connect: internal error"));
+       }
+
        memcpy(conn->dst, addr, sizeof(struct sockaddr_storage));
 
        /* Set port. */
index c5c928d1676e26d0875caaf77c8598ae1b430591..782c1689df5e3113a0ec43420453e4a5722117d0 100644 (file)
@@ -741,7 +741,8 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
                struct ist uri, path;
 
                /* Note that for now we don't reuse existing proxy connections */
-               if (unlikely((conn = cs_conn(si_alloc_cs(&s->si[1], NULL))) == NULL)) {
+               if (unlikely((conn = cs_conn(si_alloc_cs(&s->si[1], NULL))) == NULL ||
+                            !sockaddr_alloc(&conn->dst))) {
                        txn->req.err_state = txn->req.msg_state;
                        txn->req.msg_state = HTTP_MSG_ERROR;
                        txn->status = 500;
@@ -759,7 +760,6 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
                uri = htx_sl_req_uri(sl);
                path = http_get_path(uri);
 
-               /* FIXME WTA: below we'll need to dynamically allocate the dst address */
                if (url2sa(uri.ptr, uri.len - path.len, conn->dst, NULL) == -1)
                        goto return_bad_req;
 
index 193ef0e519949504263aa82d2b091b40200df237..8fa6a8e4a71cbe62a795c4bae4ffba35968f680b 100644 (file)
@@ -2539,7 +2539,9 @@ static struct appctx *peer_session_create(struct peers *peers, struct peer *peer
 
        conn->target = s->target = peer_session_target(peer, s);
 
-       /* FIXME WTA: a sockaddr allocation will be needed here */
+       if (!sockaddr_alloc(&conn->dst))
+               goto out_free_cs;
+
        memcpy(conn->dst, &peer->addr, sizeof(*conn->dst));
 
        conn_prepare(conn, peer->proto, peer_xprt(peer));
index 782d4889c4cb24c18b59b99d2cd14d14b4a7b43c..7def387347693fe023763692e88e120353e5a0b8 100644 (file)
@@ -155,8 +155,10 @@ int session_accept_fd(struct listener *l, int cfd, struct sockaddr_storage *addr
        if (unlikely((cli_conn = conn_new()) == NULL))
                goto out_close;
 
+       if (!sockaddr_alloc(&cli_conn->src))
+               goto out_free_conn;
+
        cli_conn->handle.fd = cfd;
-       /* FIXME WTA: an allocation will be needed here. Better steal the original address on success */
        *cli_conn->src = *addr;
        cli_conn->flags |= CO_FL_ADDR_FROM_SET;
        cli_conn->target = &l->obj_type;