From: Haoyi Ci Date: Thu, 2 Oct 2025 08:14:05 +0000 (+0800) Subject: ndp: Allow NS loopback for master iface X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=f0d855358b86a36efbfeb5a9de5a1d2a4d9d80fe;p=project%2Fodhcpd.git ndp: Allow NS loopback for master iface This commit modifies handle_solicit() in ndp.c to correct IPv6 relay handling of Neighbor Solicitation (NS) requests when no upstream solicitation is received. Background: In IPv6 relay mode, odhcpd discovers local devices only upon receiving upstream NS packets. If no upstream NS arrives (e.g. because the upstream router’s neighbor cache is still valid or no solicitation was ever sent), OpenWrt may attempt neighbor resolution via the master (WAN) interface instead of the LAN, leaving local devices undiscoverable and breaking connectivity. - When an NS packet is sent by the host's master interface, do not immediately return; instead continue searching slave interfaces for the target neighbor. - When odhcpd responds to NS packets, add a check to prevent replying to NS packets that were sent by the host itself. Signed-off-by: Haoyi Ci cihaoyi@outlook.com Link: https://github.com/openwrt/odhcpd/pull/240 Signed-off-by: Álvaro Fernández Rojas --- diff --git a/src/ndp.c b/src/ndp.c index 0ec6fed..0feb814 100644 --- a/src/ndp.c +++ b/src/ndp.c @@ -332,6 +332,7 @@ static void handle_solicit(void *addr, void *data, size_t len, struct interface *c; char ipbuf[INET6_ADDRSTRLEN]; uint8_t mac[6]; + bool is_self_sent; /* Solicitation is for duplicate address detection */ bool ns_is_dad = IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src); @@ -354,7 +355,8 @@ static void handle_solicit(void *addr, void *data, size_t len, syslog(LOG_DEBUG, "Got a NS for %s on %s", ipbuf, iface->name); odhcpd_get_mac(iface, mac); - if (!memcmp(ll->sll_addr, mac, sizeof(mac))) + is_self_sent = !memcmp(ll->sll_addr, mac, sizeof(mac)); + if (is_self_sent && !iface->master) return; /* Looped back */ avl_for_each_element(&interfaces, c, avl) { @@ -366,7 +368,7 @@ static void handle_solicit(void *addr, void *data, size_t len, /* Catch global-addressed NS and answer them manually. * The kernel won't answer these and cannot route them either. */ if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && - IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) { + IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src) && !is_self_sent) { bool is_proxy_neigh = netlink_get_interface_proxy_neigh(iface->ifindex, &req->nd_ns_target) == 1;