odhcp6c: clear the socket buffer after initialising it master
authorLincoln Ramsay <[email protected]>
Mon, 8 Dec 2025 02:55:34 +0000 (10:55 +0800)
committerÁlvaro Fernández Rojas <[email protected]>
Tue, 9 Dec 2025 15:12:21 +0000 (16:12 +0100)
There is a chance that the socket receives packets it should not
process between its initial creation and when ra_init is finished.

Flush these from the buffer by calling recvmsg and throwing away
everything that is received.

This solves a race condition on a multi-interface device, where
several odhcp6c instances are started, and an RA for one interface
ends up in the queue for another interface's odhcp6c socket.

Signed-off-by: Lincoln Ramsay <[email protected]>
Link: https://github.com/openwrt/odhcp6c/pull/133
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
src/ra.c

index a50231cbd1b5a86d75580f06e4d3bc32dbd6f977..47343aaa6b2f22c28058191eda9d38a637f3a7bc 100644 (file)
--- a/src/ra.c
+++ b/src/ra.c
@@ -178,6 +178,31 @@ int ra_init(const char *ifname, const struct in6_addr *ifid,
        if (fcntl(sock, F_SETFL, val | O_ASYNC) < 0)
                goto failure;
 
+       // flush any received messages that may not have had all the options (particularly the bind) applied to them
+       uint8_t buf[1500] _o_aligned(4);
+       union {
+               struct cmsghdr hdr;
+               uint8_t buf[CMSG_SPACE(sizeof(int))];
+       } cmsg_buf;
+
+       while (true) {
+               struct sockaddr_in6 from;
+               struct iovec iov = {buf, sizeof(buf)};
+               struct msghdr msg = {
+                       .msg_name = (void *) &from,
+                       .msg_namelen = sizeof(from),
+                       .msg_iov = &iov,
+                       .msg_iovlen = 1,
+                       .msg_control = cmsg_buf.buf,
+                       .msg_controllen = sizeof(cmsg_buf),
+                       .msg_flags = 0
+               };
+
+               ssize_t len = recvmsg(sock, &msg, MSG_DONTWAIT);
+               if (len <= 0)
+                       break;
+       }
+
        // Send RS
        signal(SIGALRM, ra_send_rs);
        ra_send_rs(SIGALRM);