diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h index b99df4d00..b735a6e2f 100644 --- a/include/haproxy/connection.h +++ b/include/haproxy/connection.h @@ -357,9 +357,11 @@ static inline void conn_set_private(struct connection *conn) * returns it. If is NULL, the address is always allocated and returned. * if is non-null, an address will only be allocated if it points to a * non-null pointer. In this case the allocated address will be assigned there. - * In both situations the new pointer is returned. + * If is non-null and positive, the address in will be copied + * into the allocated address. In both situations the new pointer is returned. */ -static inline struct sockaddr_storage *sockaddr_alloc(struct sockaddr_storage **sap) +static inline struct sockaddr_storage * +sockaddr_alloc(struct sockaddr_storage **sap, const struct sockaddr_storage *orig, socklen_t len) { struct sockaddr_storage *sa; @@ -367,6 +369,8 @@ static inline struct sockaddr_storage *sockaddr_alloc(struct sockaddr_storage ** return *sap; sa = pool_alloc(pool_head_sockaddr); + if (sa && orig && len > 0) + memcpy(sa, orig, len); if (sap) *sap = sa; return sa; @@ -535,7 +539,7 @@ static inline int conn_get_src(struct connection *conn) if (!conn_ctrl_ready(conn) || !conn->ctrl->fam->get_src) return 0; - if (!sockaddr_alloc(&conn->src)) + if (!sockaddr_alloc(&conn->src, NULL, 0)) return 0; if (conn->ctrl->fam->get_src(conn->handle.fd, (struct sockaddr *)conn->src, @@ -558,7 +562,7 @@ static inline int conn_get_dst(struct connection *conn) if (!conn_ctrl_ready(conn) || !conn->ctrl->fam->get_dst) return 0; - if (!sockaddr_alloc(&conn->dst)) + if (!sockaddr_alloc(&conn->dst, NULL, 0)) return 0; if (conn->ctrl->fam->get_dst(conn->handle.fd, (struct sockaddr *)conn->dst, diff --git a/src/backend.c b/src/backend.c index 99f179d5d..789becee2 100644 --- a/src/backend.c +++ b/src/backend.c @@ -845,7 +845,7 @@ int assign_server_address(struct stream *s) DPRINTF(stderr,"assign_server_address : s=%p\n",s); - if (!sockaddr_alloc(&s->target_addr)) + if (!sockaddr_alloc(&s->target_addr, NULL, 0)) return SRV_STATUS_INTERNAL; if ((s->flags & SF_DIRECT) || (s->be->lbprm.algo & BE_LB_KIND)) { @@ -1056,7 +1056,7 @@ static void assign_tproxy_address(struct stream *s) else return; - if (!sockaddr_alloc(&srv_conn->src)) + if (!sockaddr_alloc(&srv_conn->src, NULL, 0)) return; switch (src->opts & CO_SRC_TPROXY_MASK) { @@ -1411,7 +1411,7 @@ int connect_server(struct stream *s) } } - if (!srv_conn || !sockaddr_alloc(&srv_conn->dst)) { + if (!srv_conn || !sockaddr_alloc(&srv_conn->dst, 0, 0)) { if (srv_conn) conn_free(srv_conn); return SF_ERR_RESOURCE; diff --git a/src/connection.c b/src/connection.c index 1274112d8..dc54b9d63 100644 --- a/src/connection.c +++ b/src/connection.c @@ -501,7 +501,7 @@ 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)) + if (!sockaddr_alloc(&conn->src, NULL, 0) || !sockaddr_alloc(&conn->dst, NULL, 0)) goto fail; if (!fd_recv_ready(conn->handle.fd)) @@ -871,7 +871,7 @@ int conn_recv_netscaler_cip(struct connection *conn, int flag) if (!conn_ctrl_ready(conn)) goto fail; - if (!sockaddr_alloc(&conn->src) || !sockaddr_alloc(&conn->dst)) + if (!sockaddr_alloc(&conn->src, NULL, 0) || !sockaddr_alloc(&conn->dst, NULL, 0)) goto fail; if (!fd_recv_ready(conn->handle.fd)) diff --git a/src/hlua.c b/src/hlua.c index e7cac6547..9616a7518 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -2564,11 +2564,10 @@ __LJMP static int hlua_socket_connect(struct lua_State *L) si = appctx->owner; s = si_strm(si); - if (!sockaddr_alloc(&s->target_addr)) { + if (!sockaddr_alloc(&s->target_addr, addr, sizeof(*addr))) { xref_unlock(&socket->xref, peer); WILL_LJMP(luaL_error(L, "connect: internal error")); } - *s->target_addr = *addr; s->flags |= SF_ADDR_SET; hlua = hlua_gethlua(L); diff --git a/src/http_ana.c b/src/http_ana.c index 142a0bf91..870682ff9 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -754,7 +754,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit) struct htx_sl *sl; struct ist uri, path; - if (!sockaddr_alloc(&s->target_addr)) { + if (!sockaddr_alloc(&s->target_addr, NULL, 0)) { if (!(s->flags & SF_ERR_MASK)) s->flags |= SF_ERR_RESOURCE; goto return_int_err; diff --git a/src/peers.c b/src/peers.c index 1b05dbd84..18df3cd82 100644 --- a/src/peers.c +++ b/src/peers.c @@ -2574,9 +2574,8 @@ static struct appctx *peer_session_create(struct peers *peers, struct peer *peer /* initiate an outgoing connection */ s->target = peer_session_target(peer, s); - if (!sockaddr_alloc(&s->target_addr)) + if (!sockaddr_alloc(&s->target_addr, &peer->addr, sizeof(peer->addr))) goto out_free_strm; - *s->target_addr = peer->addr; s->flags = SF_ASSIGNED|SF_ADDR_SET; s->si[1].flags |= SI_FL_NOLINGER; diff --git a/src/session.c b/src/session.c index da271cf87..f6e4fe438 100644 --- a/src/session.c +++ b/src/session.c @@ -147,11 +147,10 @@ int session_accept_fd(struct listener *l, int cfd, struct sockaddr_storage *addr if (unlikely((cli_conn = conn_new(&l->obj_type)) == NULL)) goto out_close; - if (!sockaddr_alloc(&cli_conn->src)) + if (!sockaddr_alloc(&cli_conn->src, addr, sizeof(*addr))) goto out_free_conn; cli_conn->handle.fd = cfd; - *cli_conn->src = *addr; cli_conn->flags |= CO_FL_ADDR_FROM_SET; cli_conn->proxy_netns = l->rx.settings->netns; diff --git a/src/sink.c b/src/sink.c index 64bac6174..b87ea288c 100644 --- a/src/sink.c +++ b/src/sink.c @@ -649,9 +649,8 @@ static struct appctx *sink_forward_session_create(struct sink *sink, struct sink s->target = &sft->srv->obj_type; - if (!sockaddr_alloc(&s->target_addr)) + if (!sockaddr_alloc(&s->target_addr, &sft->srv->addr, sizeof(sft->srv->addr))) goto out_free_strm; - *s->target_addr = sft->srv->addr; s->flags = SF_ASSIGNED|SF_ADDR_SET; s->si[1].flags |= SI_FL_NOLINGER; diff --git a/src/tcpcheck.c b/src/tcpcheck.c index b9ef3802b..3142e7868 100644 --- a/src/tcpcheck.c +++ b/src/tcpcheck.c @@ -1028,7 +1028,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec check->wait_list.events = 0; /* no client address */ - if (!sockaddr_alloc(&conn->dst)) { + if (!sockaddr_alloc(&conn->dst, NULL, 0)) { status = SF_ERR_RESOURCE; goto fail_check; }