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:
parent
e2ea10e246
commit
528a6517f8
2 changed files with 15 additions and 52 deletions
1
inany.h
1
inany.h
|
@ -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);
|
||||||
|
|
66
tcp.c
66
tcp.c
|
@ -1689,38 +1689,14 @@ 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)),
|
goto cancel;
|
||||||
dstport);
|
|
||||||
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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue