tcp: Simplify endpoint validation using flowside information

Now that we store all our endpoints in the flowside structure, use some
inany helpers to make validation of those endpoints simpler.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2024-07-18 15:26:32 +10:00 committed by Stefano Brivio
parent e2ea10e246
commit 528a6517f8
2 changed files with 15 additions and 52 deletions

View file

@ -211,7 +211,6 @@ static inline bool inany_is_multicast(const union inany_addr *a)
* *
* Return: true if @a is specified and a unicast address * Return: true if @a is specified and a unicast address
*/ */
/* cppcheck-suppress unusedFunction */
static inline bool inany_is_unicast(const union inany_addr *a) static inline bool inany_is_unicast(const union inany_addr *a)
{ {
return !inany_is_unspecified(a) && !inany_is_multicast(a); return !inany_is_unspecified(a) && !inany_is_multicast(a);

62
tcp.c
View file

@ -1689,39 +1689,15 @@ static void tcp_conn_from_tap(struct ctx *c, sa_family_t af,
&dstaddr, dstport); &dstaddr, dstport);
conn = FLOW_SET_TYPE(flow, FLOW_TCP, tcp); conn = FLOW_SET_TYPE(flow, FLOW_TCP, tcp);
if (af == AF_INET) { if (!inany_is_unicast(&ini->eaddr) || ini->eport == 0 ||
if (IN4_IS_ADDR_UNSPECIFIED(saddr) || !inany_is_unicast(&ini->faddr) || ini->fport == 0) {
IN4_IS_ADDR_BROADCAST(saddr) || char sstr[INANY_ADDRSTRLEN], dstr[INANY_ADDRSTRLEN];
IN4_IS_ADDR_MULTICAST(saddr) || srcport == 0 ||
IN4_IS_ADDR_UNSPECIFIED(daddr) ||
IN4_IS_ADDR_BROADCAST(daddr) ||
IN4_IS_ADDR_MULTICAST(daddr) || dstport == 0) {
char sstr[INET_ADDRSTRLEN], dstr[INET_ADDRSTRLEN];
debug("Invalid endpoint in TCP SYN: %s:%hu -> %s:%hu", debug("Invalid endpoint in TCP SYN: %s:%hu -> %s:%hu",
inet_ntop(AF_INET, saddr, sstr, sizeof(sstr)), inany_ntop(&ini->eaddr, sstr, sizeof(sstr)), ini->eport,
srcport, inany_ntop(&ini->faddr, dstr, sizeof(dstr)), ini->fport);
inet_ntop(AF_INET, daddr, dstr, sizeof(dstr)),
dstport);
goto cancel; goto cancel;
} }
} else if (af == AF_INET6) {
if (IN6_IS_ADDR_UNSPECIFIED(saddr) ||
IN6_IS_ADDR_MULTICAST(saddr) || srcport == 0 ||
IN6_IS_ADDR_UNSPECIFIED(daddr) ||
IN6_IS_ADDR_MULTICAST(daddr) || dstport == 0) {
char sstr[INET6_ADDRSTRLEN], dstr[INET6_ADDRSTRLEN];
debug("Invalid endpoint in TCP SYN: %s:%hu -> %s:%hu",
inet_ntop(AF_INET6, saddr, sstr, sizeof(sstr)),
srcport,
inet_ntop(AF_INET6, daddr, dstr, sizeof(dstr)),
dstport);
goto cancel;
}
} else {
ASSERT(0);
}
if ((s = tcp_conn_sock(c, af)) < 0) if ((s = tcp_conn_sock(c, af)) < 0)
goto cancel; goto cancel;
@ -2336,7 +2312,7 @@ static void tcp_tap_conn_from_sock(struct ctx *c, in_port_t dstport,
void tcp_listen_handler(struct ctx *c, union epoll_ref ref, void tcp_listen_handler(struct ctx *c, union epoll_ref ref,
const struct timespec *now) const struct timespec *now)
{ {
char sastr[SOCKADDR_STRLEN]; const struct flowside *ini;
union sockaddr_inany sa; union sockaddr_inany sa;
socklen_t sl = sizeof(sa); socklen_t sl = sizeof(sa);
union flow *flow; union flow *flow;
@ -2353,23 +2329,15 @@ void tcp_listen_handler(struct ctx *c, union epoll_ref ref,
/* FIXME: When listening port has a specific bound address, record that /* FIXME: When listening port has a specific bound address, record that
* as the forwarding address */ * as the forwarding address */
flow_initiate_sa(flow, ref.tcp_listen.pif, &sa, ref.tcp_listen.port); ini = flow_initiate_sa(flow, ref.tcp_listen.pif, &sa,
ref.tcp_listen.port);
if (sa.sa_family == AF_INET) { if (!inany_is_unicast(&ini->eaddr) || ini->eport == 0) {
const struct in_addr *addr = &sa.sa4.sin_addr; char sastr[SOCKADDR_STRLEN];
in_port_t port = sa.sa4.sin_port;
if (IN4_IS_ADDR_UNSPECIFIED(addr) || err("Invalid endpoint from TCP accept(): %s",
IN4_IS_ADDR_BROADCAST(addr) || sockaddr_ntop(&sa, sastr, sizeof(sastr)));
IN4_IS_ADDR_MULTICAST(addr) || port == 0) goto cancel;
goto bad_endpoint;
} else if (sa.sa_family == AF_INET6) {
const struct in6_addr *addr = &sa.sa6.sin6_addr;
in_port_t port = sa.sa6.sin6_port;
if (IN6_IS_ADDR_UNSPECIFIED(addr) ||
IN6_IS_ADDR_MULTICAST(addr) || port == 0)
goto bad_endpoint;
} }
if (tcp_splice_conn_from_sock(c, ref.tcp_listen.pif, if (tcp_splice_conn_from_sock(c, ref.tcp_listen.pif,
@ -2379,10 +2347,6 @@ void tcp_listen_handler(struct ctx *c, union epoll_ref ref,
tcp_tap_conn_from_sock(c, ref.tcp_listen.port, flow, s, &sa, now); tcp_tap_conn_from_sock(c, ref.tcp_listen.port, flow, s, &sa, now);
return; return;
bad_endpoint:
err("Invalid endpoint from TCP accept(): %s",
sockaddr_ntop(&sa, sastr, sizeof(sastr)));
cancel: cancel:
flow_alloc_cancel(flow); flow_alloc_cancel(flow);
} }