1
0
Fork 0
mirror of https://passt.top/passt synced 2025-06-06 16:06:19 +02:00

udp: support traceroute in direction tap-socket

Now that ICMP pass-through from socket-to-tap is in place, it is
easy to support UDP based traceroute functionality in direction
tap-to-socket.

We fix that in this commit.

Link: https://bugs.passt.top/show_bug.cgi?id=64
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
Jon Maloy 2025-04-05 15:21:26 -04:00 committed by Stefano Brivio
parent 06784d7fc6
commit a7775e9550
5 changed files with 40 additions and 7 deletions

17
tap.c
View file

@ -559,6 +559,7 @@ PACKET_POOL_DECL(pool_l4, UIO_MAXIOV, pkt_buf);
* struct l4_seq4_t - Message sequence for one protocol handler call, IPv4 * struct l4_seq4_t - Message sequence for one protocol handler call, IPv4
* @msgs: Count of messages in sequence * @msgs: Count of messages in sequence
* @protocol: Protocol number * @protocol: Protocol number
* @ttl: Time to live
* @source: Source port * @source: Source port
* @dest: Destination port * @dest: Destination port
* @saddr: Source address * @saddr: Source address
@ -567,6 +568,7 @@ PACKET_POOL_DECL(pool_l4, UIO_MAXIOV, pkt_buf);
*/ */
static struct tap4_l4_t { static struct tap4_l4_t {
uint8_t protocol; uint8_t protocol;
uint8_t ttl;
uint16_t source; uint16_t source;
uint16_t dest; uint16_t dest;
@ -586,6 +588,7 @@ static struct tap4_l4_t {
* @dest: Destination port * @dest: Destination port
* @saddr: Source address * @saddr: Source address
* @daddr: Destination address * @daddr: Destination address
* @hop_limit: Hop limit
* @msg: Array of messages that can be handled in a single call * @msg: Array of messages that can be handled in a single call
*/ */
static struct tap6_l4_t { static struct tap6_l4_t {
@ -598,6 +601,8 @@ static struct tap6_l4_t {
struct in6_addr saddr; struct in6_addr saddr;
struct in6_addr daddr; struct in6_addr daddr;
uint8_t hop_limit;
struct pool_l4_t p; struct pool_l4_t p;
} tap6_l4[TAP_SEQS /* Arbitrary: TAP_MSGS in theory, so limit in users */]; } tap6_l4[TAP_SEQS /* Arbitrary: TAP_MSGS in theory, so limit in users */];
@ -786,7 +791,8 @@ resume:
#define L4_MATCH(iph, uh, seq) \ #define L4_MATCH(iph, uh, seq) \
((seq)->protocol == (iph)->protocol && \ ((seq)->protocol == (iph)->protocol && \
(seq)->source == (uh)->source && (seq)->dest == (uh)->dest && \ (seq)->source == (uh)->source && (seq)->dest == (uh)->dest && \
(seq)->saddr.s_addr == (iph)->saddr && (seq)->daddr.s_addr == (iph)->daddr) (seq)->saddr.s_addr == (iph)->saddr && \
(seq)->daddr.s_addr == (iph)->daddr && (seq)->ttl == (iph)->ttl)
#define L4_SET(iph, uh, seq) \ #define L4_SET(iph, uh, seq) \
do { \ do { \
@ -795,6 +801,7 @@ resume:
(seq)->dest = (uh)->dest; \ (seq)->dest = (uh)->dest; \
(seq)->saddr.s_addr = (iph)->saddr; \ (seq)->saddr.s_addr = (iph)->saddr; \
(seq)->daddr.s_addr = (iph)->daddr; \ (seq)->daddr.s_addr = (iph)->daddr; \
(seq)->ttl = (iph)->ttl; \
} while (0) } while (0)
if (seq && L4_MATCH(iph, uh, seq) && seq->p.count < UIO_MAXIOV) if (seq && L4_MATCH(iph, uh, seq) && seq->p.count < UIO_MAXIOV)
@ -843,7 +850,7 @@ append:
for (k = 0; k < p->count; ) for (k = 0; k < p->count; )
k += udp_tap_handler(c, PIF_TAP, AF_INET, k += udp_tap_handler(c, PIF_TAP, AF_INET,
&seq->saddr, &seq->daddr, &seq->saddr, &seq->daddr,
p, k, now); seq->ttl, p, k, now);
} }
} }
@ -966,7 +973,8 @@ resume:
(seq)->dest == (uh)->dest && \ (seq)->dest == (uh)->dest && \
(seq)->flow_lbl == ip6_get_flow_lbl(ip6h) && \ (seq)->flow_lbl == ip6_get_flow_lbl(ip6h) && \
IN6_ARE_ADDR_EQUAL(&(seq)->saddr, saddr) && \ IN6_ARE_ADDR_EQUAL(&(seq)->saddr, saddr) && \
IN6_ARE_ADDR_EQUAL(&(seq)->daddr, daddr)) IN6_ARE_ADDR_EQUAL(&(seq)->daddr, daddr) && \
(seq)->hop_limit == (ip6h)->hop_limit)
#define L4_SET(ip6h, proto, uh, seq) \ #define L4_SET(ip6h, proto, uh, seq) \
do { \ do { \
@ -976,6 +984,7 @@ resume:
(seq)->flow_lbl = ip6_get_flow_lbl(ip6h); \ (seq)->flow_lbl = ip6_get_flow_lbl(ip6h); \
(seq)->saddr = *saddr; \ (seq)->saddr = *saddr; \
(seq)->daddr = *daddr; \ (seq)->daddr = *daddr; \
(seq)->hop_limit = (ip6h)->hop_limit; \
} while (0) } while (0)
if (seq && L4_MATCH(ip6h, proto, uh, seq) && if (seq && L4_MATCH(ip6h, proto, uh, seq) &&
@ -1026,7 +1035,7 @@ append:
for (k = 0; k < p->count; ) for (k = 0; k < p->count; )
k += udp_tap_handler(c, PIF_TAP, AF_INET6, k += udp_tap_handler(c, PIF_TAP, AF_INET6,
&seq->saddr, &seq->daddr, &seq->saddr, &seq->daddr,
p, k, now); seq->hop_limit, p, k, now);
} }
} }

22
udp.c
View file

@ -844,6 +844,7 @@ fail:
* @af: Address family, AF_INET or AF_INET6 * @af: Address family, AF_INET or AF_INET6
* @saddr: Source address * @saddr: Source address
* @daddr: Destination address * @daddr: Destination address
* @ttl: TTL or hop limit for packets to be sent in this call
* @p: Pool of UDP packets, with UDP headers * @p: Pool of UDP packets, with UDP headers
* @idx: Index of first packet to process * @idx: Index of first packet to process
* @now: Current timestamp * @now: Current timestamp
@ -854,7 +855,8 @@ fail:
*/ */
int udp_tap_handler(const struct ctx *c, uint8_t pif, int udp_tap_handler(const struct ctx *c, uint8_t pif,
sa_family_t af, const void *saddr, const void *daddr, sa_family_t af, const void *saddr, const void *daddr,
const struct pool *p, int idx, const struct timespec *now) uint8_t ttl, const struct pool *p, int idx,
const struct timespec *now)
{ {
const struct flowside *toside; const struct flowside *toside;
struct mmsghdr mm[UIO_MAXIOV]; struct mmsghdr mm[UIO_MAXIOV];
@ -933,6 +935,24 @@ int udp_tap_handler(const struct ctx *c, uint8_t pif,
mm[i].msg_hdr.msg_controllen = 0; mm[i].msg_hdr.msg_controllen = 0;
mm[i].msg_hdr.msg_flags = 0; mm[i].msg_hdr.msg_flags = 0;
if (ttl != uflow->ttl[tosidx.sidei]) {
uflow->ttl[tosidx.sidei] = ttl;
if (af == AF_INET) {
if (setsockopt(s, IPPROTO_IP, IP_TTL,
&ttl, sizeof(ttl)) < 0)
flow_perror(uflow,
"setsockopt IP_TTL");
} else {
/* IPv6 hop_limit cannot be only 1 byte */
int hop_limit = ttl;
if (setsockopt(s, SOL_IPV6, IPV6_UNICAST_HOPS,
&hop_limit, sizeof(hop_limit)) < 0)
flow_perror(uflow,
"setsockopt IPV6_UNICAST_HOPS");
}
}
count++; count++;
} }

3
udp.h
View file

@ -15,7 +15,8 @@ void udp_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
uint32_t events, const struct timespec *now); uint32_t events, const struct timespec *now);
int udp_tap_handler(const struct ctx *c, uint8_t pif, int udp_tap_handler(const struct ctx *c, uint8_t pif,
sa_family_t af, const void *saddr, const void *daddr, sa_family_t af, const void *saddr, const void *daddr,
const struct pool *p, int idx, const struct timespec *now); uint8_t ttl, const struct pool *p, int idx,
const struct timespec *now);
int udp_sock_init(const struct ctx *c, int ns, const union inany_addr *addr, int udp_sock_init(const struct ctx *c, int ns, const union inany_addr *addr,
const char *ifname, in_port_t port); const char *ifname, in_port_t port);
int udp_init(struct ctx *c); int udp_init(struct ctx *c);

View file

@ -137,6 +137,7 @@ static flow_sidx_t udp_flow_new(const struct ctx *c, union flow *flow,
uflow = FLOW_SET_TYPE(flow, FLOW_UDP, udp); uflow = FLOW_SET_TYPE(flow, FLOW_UDP, udp);
uflow->ts = now->tv_sec; uflow->ts = now->tv_sec;
uflow->s[INISIDE] = uflow->s[TGTSIDE] = -1; uflow->s[INISIDE] = uflow->s[TGTSIDE] = -1;
uflow->ttl[INISIDE] = uflow->ttl[TGTSIDE] = 0;
if (s_ini >= 0) { if (s_ini >= 0) {
/* When using auto port-scanning the listening port could go /* When using auto port-scanning the listening port could go

View file

@ -8,11 +8,12 @@
#define UDP_FLOW_H #define UDP_FLOW_H
/** /**
* struct udp - Descriptor for a flow of UDP packets * struct udp_flow - Descriptor for a flow of UDP packets
* @f: Generic flow information * @f: Generic flow information
* @closed: Flow is already closed * @closed: Flow is already closed
* @ts: Activity timestamp * @ts: Activity timestamp
* @s: Socket fd (or -1) for each side of the flow * @s: Socket fd (or -1) for each side of the flow
* @ttl: TTL or hop_limit for both sides
*/ */
struct udp_flow { struct udp_flow {
/* Must be first element */ /* Must be first element */
@ -21,6 +22,7 @@ struct udp_flow {
bool closed :1; bool closed :1;
time_t ts; time_t ts;
int s[SIDES]; int s[SIDES];
uint8_t ttl[SIDES];
}; };
struct udp_flow *udp_at_sidx(flow_sidx_t sidx); struct udp_flow *udp_at_sidx(flow_sidx_t sidx);