mirror of
https://passt.top/passt
synced 2025-05-24 18:15:36 +02:00

So far for UDP flows (like TCP connections) we didn't record our address (oaddr) in the flow table entry for socket based pifs. That's because we didn't have that information when a flow was initiated by a datagram coming to a "listening" socket with 0.0.0.0 or :: address. Even when we did have the information, we didn't record it, to simplify address matching on lookups. This meant that in some circumstances we could send replies on a UDP flow from a different address than the originating request came to, which is surprising and breaks certain setups. We now have code in udp_peek_addr() which does determine our address for incoming UDP datagrams. We can use that information to properly populate oaddr in the flow table for flow initiated from a socket. In order to be able to consistently match datagrams to flows, we must *always* have a specific oaddr, not an unspecified address (that's how the flow hash table works). So, we also need to fill in oaddr correctly for flows we initiate *to* sockets. Our forwarding logic doesn't specify oaddr here, letting the kernel decide based on the routing table. In this case we need to call getsockname() after connect()ing the socket to find which local address the kernel picked. This adds getsockname() to our seccomp profile for all variants. Link: https://bugs.passt.top/show_bug.cgi?id=99 Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
50 lines
1.5 KiB
C
50 lines
1.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright Red Hat
|
|
* Author: David Gibson <david@gibson.dropbear.id.au>
|
|
*
|
|
* UDP flow tracking data structures
|
|
*/
|
|
#ifndef UDP_FLOW_H
|
|
#define UDP_FLOW_H
|
|
|
|
/**
|
|
* struct udp_flow - Descriptor for a flow of UDP packets
|
|
* @f: Generic flow information
|
|
* @ttl: TTL or hop_limit for both sides
|
|
* @closed: Flow is already closed
|
|
* @flush0: @s[0] may have datagrams queued for other flows
|
|
* @flush1: @s[1] may have datagrams queued for other flows
|
|
* @ts: Activity timestamp
|
|
* @s: Socket fd (or -1) for each side of the flow
|
|
*/
|
|
struct udp_flow {
|
|
/* Must be first element */
|
|
struct flow_common f;
|
|
|
|
uint8_t ttl[SIDES];
|
|
|
|
bool closed :1,
|
|
flush0 :1,
|
|
flush1 :1;
|
|
|
|
time_t ts;
|
|
int s[SIDES];
|
|
};
|
|
|
|
struct udp_flow *udp_at_sidx(flow_sidx_t sidx);
|
|
flow_sidx_t udp_flow_from_sock(const struct ctx *c, uint8_t pif,
|
|
const union inany_addr *dst, in_port_t port,
|
|
const union sockaddr_inany *s_in,
|
|
const struct timespec *now);
|
|
flow_sidx_t udp_flow_from_tap(const struct ctx *c,
|
|
uint8_t pif, sa_family_t af,
|
|
const void *saddr, const void *daddr,
|
|
in_port_t srcport, in_port_t dstport,
|
|
const struct timespec *now);
|
|
void udp_flow_close(const struct ctx *c, struct udp_flow *uflow);
|
|
bool udp_flow_defer(const struct ctx *c, struct udp_flow *uflow,
|
|
const struct timespec *now);
|
|
bool udp_flow_timer(const struct ctx *c, struct udp_flow *uflow,
|
|
const struct timespec *now);
|
|
|
|
#endif /* UDP_FLOW_H */
|