From 5212a1019d75db47a03c95c12e385e4625dda3d0 Mon Sep 17 00:00:00 2001 From: Lincoln Ramsay Date: Mon, 8 Dec 2025 10:55:34 +0800 Subject: [PATCH] odhcp6c: clear the socket buffer after initialising it MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Link: https://github.com/openwrt/odhcp6c/pull/133 Signed-off-by: Álvaro Fernández Rojas --- src/ra.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/ra.c b/src/ra.c index a50231c..47343aa 100644 --- 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); -- 2.30.2