MEDIUM: connection: Assign session addresses when PROXY line is received

When PROXY protocol line is received, the retrieved client source and
destination addresses are set at the session level. This leaves those at the
connection level intact.
This commit is contained in:
Christopher Faulet 2021-10-25 08:17:11 +02:00
parent a8e95fed43
commit c105c9213f

View File

@ -757,6 +757,7 @@ static inline size_t get_tlv_length(const struct tlv *src)
*/
int conn_recv_proxy(struct connection *conn, int flag)
{
struct session *sess = conn->owner;
char *line, *end;
struct proxy_hdr_v2 *hdr_v2;
const char v2sig[] = PP2_SIGNATURE;
@ -767,9 +768,6 @@ int conn_recv_proxy(struct connection *conn, int flag)
if (!conn_ctrl_ready(conn))
goto fail;
if (!sockaddr_alloc(&conn->src, NULL, 0) || !sockaddr_alloc(&conn->dst, NULL, 0))
goto fail;
if (!fd_recv_ready(conn->handle.fd))
goto not_ready;
@ -841,15 +839,18 @@ int conn_recv_proxy(struct connection *conn, int flag)
if (*line++ != '\n')
goto bad_header;
/* update the session's addresses and mark them set */
((struct sockaddr_in *)conn->src)->sin_family = AF_INET;
((struct sockaddr_in *)conn->src)->sin_addr.s_addr = htonl(src3);
((struct sockaddr_in *)conn->src)->sin_port = htons(sport);
if (!sess || !sockaddr_alloc(&sess->src, NULL, 0) || !sockaddr_alloc(&sess->dst, NULL, 0))
goto fail;
((struct sockaddr_in *)conn->dst)->sin_family = AF_INET;
((struct sockaddr_in *)conn->dst)->sin_addr.s_addr = htonl(dst3);
((struct sockaddr_in *)conn->dst)->sin_port = htons(dport);
conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
/* update the session's addresses and mark them set */
((struct sockaddr_in *)sess->src)->sin_family = AF_INET;
((struct sockaddr_in *)sess->src)->sin_addr.s_addr = htonl(src3);
((struct sockaddr_in *)sess->src)->sin_port = htons(sport);
((struct sockaddr_in *)sess->dst)->sin_family = AF_INET;
((struct sockaddr_in *)sess->dst)->sin_addr.s_addr = htonl(dst3);
((struct sockaddr_in *)sess->dst)->sin_port = htons(dport);
sess->flags |= SESS_FL_ADDR_FROM_SET | SESS_FL_ADDR_TO_SET;
}
else if (memcmp(line, "TCP6 ", 5) == 0) {
u32 sport, dport;
@ -902,15 +903,18 @@ int conn_recv_proxy(struct connection *conn, int flag)
if (inet_pton(AF_INET6, dst_s, (void *)&dst3) != 1)
goto bad_header;
/* update the session's addresses and mark them set */
((struct sockaddr_in6 *)conn->src)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)conn->src)->sin6_addr, &src3, sizeof(struct in6_addr));
((struct sockaddr_in6 *)conn->src)->sin6_port = htons(sport);
if (!sess || !sockaddr_alloc(&sess->src, NULL, 0) || !sockaddr_alloc(&sess->dst, NULL, 0))
goto fail;
((struct sockaddr_in6 *)conn->dst)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)conn->dst)->sin6_addr, &dst3, sizeof(struct in6_addr));
((struct sockaddr_in6 *)conn->dst)->sin6_port = htons(dport);
conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
/* update the session's addresses and mark them set */
((struct sockaddr_in6 *)sess->src)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)sess->src)->sin6_addr, &src3, sizeof(struct in6_addr));
((struct sockaddr_in6 *)sess->src)->sin6_port = htons(sport);
((struct sockaddr_in6 *)sess->dst)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)sess->dst)->sin6_addr, &dst3, sizeof(struct in6_addr));
((struct sockaddr_in6 *)sess->dst)->sin6_port = htons(dport);
sess->flags |= SESS_FL_ADDR_FROM_SET | SESS_FL_ADDR_TO_SET;
}
else if (memcmp(line, "UNKNOWN\r\n", 9) == 0) {
/* This can be a UNIX socket forwarded by an haproxy upstream */
@ -949,26 +953,32 @@ int conn_recv_proxy(struct connection *conn, int flag)
if (ntohs(hdr_v2->len) < PP2_ADDR_LEN_INET)
goto bad_header;
((struct sockaddr_in *)conn->src)->sin_family = AF_INET;
((struct sockaddr_in *)conn->src)->sin_addr.s_addr = hdr_v2->addr.ip4.src_addr;
((struct sockaddr_in *)conn->src)->sin_port = hdr_v2->addr.ip4.src_port;
((struct sockaddr_in *)conn->dst)->sin_family = AF_INET;
((struct sockaddr_in *)conn->dst)->sin_addr.s_addr = hdr_v2->addr.ip4.dst_addr;
((struct sockaddr_in *)conn->dst)->sin_port = hdr_v2->addr.ip4.dst_port;
conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
if (!sess || !sockaddr_alloc(&sess->src, NULL, 0) || !sockaddr_alloc(&sess->dst, NULL, 0))
goto fail;
((struct sockaddr_in *)sess->src)->sin_family = AF_INET;
((struct sockaddr_in *)sess->src)->sin_addr.s_addr = hdr_v2->addr.ip4.src_addr;
((struct sockaddr_in *)sess->src)->sin_port = hdr_v2->addr.ip4.src_port;
((struct sockaddr_in *)sess->dst)->sin_family = AF_INET;
((struct sockaddr_in *)sess->dst)->sin_addr.s_addr = hdr_v2->addr.ip4.dst_addr;
((struct sockaddr_in *)sess->dst)->sin_port = hdr_v2->addr.ip4.dst_port;
sess->flags |= SESS_FL_ADDR_FROM_SET | SESS_FL_ADDR_TO_SET;
tlv_offset = PP2_HEADER_LEN + PP2_ADDR_LEN_INET;
break;
case 0x21: /* TCPv6 */
if (ntohs(hdr_v2->len) < PP2_ADDR_LEN_INET6)
goto bad_header;
((struct sockaddr_in6 *)conn->src)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)conn->src)->sin6_addr, hdr_v2->addr.ip6.src_addr, 16);
((struct sockaddr_in6 *)conn->src)->sin6_port = hdr_v2->addr.ip6.src_port;
((struct sockaddr_in6 *)conn->dst)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)conn->dst)->sin6_addr, hdr_v2->addr.ip6.dst_addr, 16);
((struct sockaddr_in6 *)conn->dst)->sin6_port = hdr_v2->addr.ip6.dst_port;
conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
if (!sess || !sockaddr_alloc(&sess->src, NULL, 0) || !sockaddr_alloc(&sess->dst, NULL, 0))
goto fail;
((struct sockaddr_in6 *)sess->src)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)sess->src)->sin6_addr, hdr_v2->addr.ip6.src_addr, 16);
((struct sockaddr_in6 *)sess->src)->sin6_port = hdr_v2->addr.ip6.src_port;
((struct sockaddr_in6 *)sess->dst)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)sess->dst)->sin6_addr, hdr_v2->addr.ip6.dst_addr, 16);
((struct sockaddr_in6 *)sess->dst)->sin6_port = hdr_v2->addr.ip6.dst_port;
sess->flags |= SESS_FL_ADDR_FROM_SET | SESS_FL_ADDR_TO_SET;
tlv_offset = PP2_HEADER_LEN + PP2_ADDR_LEN_INET6;
break;
}