From 96c1a61136e81003ebe119f9bd032f4b5676ef68 Mon Sep 17 00:00:00 2001 From: Dragan Dosen Date: Tue, 19 Dec 2023 12:46:01 +0100 Subject: [PATCH] MEDIUM: udp: allow to retrieve the frontend destination address A new flag RX_F_PASS_PKTINFO is now available, whose purpose is to mark that the destination address is about to be retrieved on some listeners. The address can be retrieved from the first received datagram, and relies on the IP_PKTINFO, IP_RECVDSTADDR and IPV6_RECVPKTINFO support. --- include/haproxy/receiver-t.h | 1 + src/proto_udp.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/haproxy/receiver-t.h b/include/haproxy/receiver-t.h index 0ae441eb9..90f52aae5 100644 --- a/include/haproxy/receiver-t.h +++ b/include/haproxy/receiver-t.h @@ -37,6 +37,7 @@ #define RX_F_MWORKER 0x00000004 /* keep the FD open in the master but close it in the children */ #define RX_F_MUST_DUP 0x00000008 /* this receiver's fd must be dup() from a reference; ignore socket-level ops here */ #define RX_F_NON_SUSPENDABLE 0x00000010 /* this socket cannot be suspended hence must always be unbound */ +#define RX_F_PASS_PKTINFO 0x00000020 /* pass pktinfo in received messages */ /* Bit values for rx_settings->options */ #define RX_O_FOREIGN 0x00000001 /* receives on foreign addresses */ diff --git a/src/proto_udp.c b/src/proto_udp.c index 98559745c..7308e988b 100644 --- a/src/proto_udp.c +++ b/src/proto_udp.c @@ -155,6 +155,26 @@ int udp_bind_listener(struct listener *listener, char *errmsg, int errlen) if (global.tune.frontend_sndbuf) setsockopt(listener->rx.fd, SOL_SOCKET, SO_SNDBUF, &global.tune.frontend_sndbuf, sizeof(global.tune.frontend_sndbuf)); + if (listener->rx.flags & RX_F_PASS_PKTINFO) { + /* set IP_PKTINFO to retrieve destination address on recv */ + switch (listener->rx.addr.ss_family) { + case AF_INET: +#if defined(IP_PKTINFO) + setsockopt(listener->rx.fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); +#elif defined(IP_RECVDSTADDR) + setsockopt(listener->rx.fd, IPPROTO_IP, IP_RECVDSTADDR, &one, sizeof(one)); +#endif /* IP_PKTINFO || IP_RECVDSTADDR */ + break; + case AF_INET6: +#ifdef IPV6_RECVPKTINFO + setsockopt(listener->rx.fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); +#endif + break; + default: + break; + } + } + listener_set_state(listener, LI_LISTEN); udp_return: