[PATCH 11/11] batctl: icmp_helper: attach socket filter before packets can arrive
Sven Eckelmann <[email protected]> Tue, 07 Jul 2026 20:46:53 +0200
| Newsgroups | org.open-mesh.lists.batman |
|---|---|
| Message-ID | <[email protected]> |
The raw packet socket is created with ETH_P_ALL as protocol, which
registers the ethernet packet hook immediately. Frames from every interface
start queuing the moment the socket exists. The BPF filter that restricts
the socket to batman-adv ICMP packets with our uid is only attached after
bind(). Frames received in the window between socket() and SO_ATTACH_FILTER
are therefore queued unfiltered.
Delay the start of the capture by:
* create the socket with protocol 0 (no capture)
* attach the filter while the queue is guaranteed empty
* then bind() with sll_protocol = htons(ETH_P_ALL)
Only after the bind, packets will be captured.
Fixes: 4bd751eed4dc ("batctl: Implement non-routing batadv_icmp in userspace")
Signed-off-by: Sven Eckelmann <[email protected]>
---
icmp_helper.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/icmp_helper.c b/icmp_helper.c
index 52ac22d..570f0b3 100644
--- a/icmp_helper.c
+++ b/icmp_helper.c
@@ -176,7 +176,12 @@ static int icmp_interface_add(const char *ifname, const uint8_t mac[ETH_ALEN])
strncpy(iface->name, ifname, IFNAMSIZ);
iface->name[sizeof(iface->name) - 1] = '\0';
- iface->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ /* create the socket with protocol 0 so the kernel does not start
+ * capturing yet - otherwise frames would queue unfiltered between
+ * socket() and SO_ATTACH_FILTER. Delivery only starts at bind() below,
+ * by which time the filter is already installed.
+ */
+ iface->sock = socket(PF_PACKET, SOCK_RAW, 0);
if (iface->sock < 0) {
perror("Error - can't create raw socket");
ret = -errno;
@@ -194,6 +199,12 @@ static int icmp_interface_add(const char *ifname, const uint8_t mac[ETH_ALEN])
goto close_sock;
}
+ ret = icmp_interface_filter(iface->sock, uid);
+ if (ret < 0) {
+ fprintf(stderr, "Error - can't add filter to raw socket: %s\n", strerror(-ret));
+ goto close_sock;
+ }
+
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(ETH_P_ALL);
@@ -207,12 +218,6 @@ static int icmp_interface_add(const char *ifname, const uint8_t mac[ETH_ALEN])
goto close_sock;
}
- ret = icmp_interface_filter(iface->sock, uid);
- if (ret < 0) {
- fprintf(stderr, "Error - can't add filter to raw socket: %s\n", strerror(-ret));
- goto close_sock;
- }
-
list_add(&iface->list, &interface_list);
return 0;
--
2.47.3