ebpf: obtain udp source ip in more cases

Sometimes the source IP of an outbound UDP connection is specified
via ancillary messages, by using IP_PKTINFO or IPV6_PKTINFO.

In these cases the source IP of the sock struct is empty (0.0.0.0,
sk->__sk_common.skc_rcv_saddr).

Now in udp_sendmsg(), if sk->sk_rcv_saddr is empty, we'll try to
extract it from the ancillary message. IPv4 only for now.
This commit is contained in:
Gustavo Iñiguez Goia 2025-01-17 20:26:11 +01:00
parent f44d3e896b
commit 20a03e11fe
Failed to generate hash of commit

View file

@ -255,6 +255,17 @@ int kprobe__udp_sendmsg(struct pt_regs *ctx)
bpf_probe_read(&udp_key.sport, sizeof(udp_key.sport), &sk->__sk_common.skc_num);
bpf_probe_read(&udp_key.saddr, sizeof(udp_key.saddr), &sk->__sk_common.skc_rcv_saddr);
// TODO: armhf
#if !defined(__arm__)
// extract from the ancillary message the source IP.
if (udp_key.saddr == 0){
u64 cmsg=0;
bpf_probe_read(&cmsg, sizeof(cmsg), &msg->msg_control);
struct in_pktinfo *inpkt = (struct in_pktinfo *)CMSG_DATA(cmsg);
bpf_probe_read(&udp_key.saddr, sizeof(udp_key.saddr), &inpkt->ipi_spec_dst.s_addr);
}
#endif
u32 zero_key = 0;
__builtin_memset(&zero_key, 0, sizeof(zero_key));
struct udp_value_t *lookedupValue = bpf_map_lookup_elem(&udpMap, &udp_key);
@ -302,6 +313,11 @@ int kprobe__udpv6_sendmsg(struct pt_regs *ctx)
bpf_probe_read(&udpv6_key.sport, sizeof(udpv6_key.sport), &sk->__sk_common.skc_num);
bpf_probe_read(&udpv6_key.saddr, sizeof(udpv6_key.saddr), &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
// TODO: obtain IPs from ancillary messages if daddr == 0 || saddr == 0
// https://elixir.bootlin.com/linux/v4.4.60/source/net/ipv4/ip_sockglue.c#L224
//
// IPV6_PKTINFO, in6_pktinfo
#if defined(__i386__)
struct sock_on_x86_32_t sock;