Hi, As the nd6 mutex protects the lifetime of struct llinfo_nd6 ln, nd6_mtx must be held longer in nd6_rtrequest() case RTM_RESOLVE.
ok? bluhm Index: netinet6/nd6.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/nd6.c,v retrieving revision 1.275 diff -u -p -r1.275 nd6.c --- netinet6/nd6.c 4 May 2023 06:56:56 -0000 1.275 +++ netinet6/nd6.c 6 May 2023 22:38:34 -0000 @@ -845,6 +845,8 @@ nd6_rtrequest(struct ifnet *ifp, int req mq_init(&ln->ln_mq, LN_HOLD_QUEUE, IPL_SOFTNET); rt->rt_llinfo = (caddr_t)ln; ln->ln_rt = rt; + rt->rt_flags |= RTF_LLINFO; + TAILQ_INSERT_HEAD(&nd6_list, ln, ln_list); /* this is required for "ndp" command. - shin */ if (req == RTM_ADD) { /* @@ -862,9 +864,6 @@ nd6_rtrequest(struct ifnet *ifp, int req ln->ln_state = ND6_LLINFO_NOSTATE; nd6_llinfo_settimer(ln, 0); } - rt->rt_flags |= RTF_LLINFO; - TAILQ_INSERT_HEAD(&nd6_list, ln, ln_list); - mtx_leave(&nd6_mtx); /* * If we have too many cache entries, initiate immediate @@ -877,7 +876,6 @@ nd6_rtrequest(struct ifnet *ifp, int req nd6_inuse >= ip6_neighborgcthresh) { int i; - mtx_enter(&nd6_mtx); for (i = 0; i < 10; i++) { struct llinfo_nd6 *ln_end; @@ -898,7 +896,6 @@ nd6_rtrequest(struct ifnet *ifp, int req ln_end->ln_state = ND6_LLINFO_PURGE; nd6_llinfo_settimer(ln_end, 0); } - mtx_leave(&nd6_mtx); } /* @@ -908,39 +905,38 @@ nd6_rtrequest(struct ifnet *ifp, int req ifa6 = in6ifa_ifpwithaddr(ifp, &satosin6(rt_key(rt))->sin6_addr); ifa = ifa6 ? &ifa6->ia_ifa : NULL; - if (ifa) { - ln->ln_state = ND6_LLINFO_REACHABLE; - ln->ln_byhint = 0; - rt->rt_expire = 0; - KASSERT(ifa == rt->rt_ifa); - } else if (rt->rt_flags & RTF_ANNOUNCE) { + if (ifa != NULL || + (rt->rt_flags & RTF_ANNOUNCE)) { ln->ln_state = ND6_LLINFO_REACHABLE; ln->ln_byhint = 0; rt->rt_expire = 0; + } + mtx_leave(&nd6_mtx); - /* join solicited node multicast for proxy ND */ - if (ifp->if_flags & IFF_MULTICAST) { - struct in6_addr llsol; - int error; - - llsol = satosin6(rt_key(rt))->sin6_addr; - llsol.s6_addr16[0] = htons(0xff02); - llsol.s6_addr16[1] = htons(ifp->if_index); - llsol.s6_addr32[1] = 0; - llsol.s6_addr32[2] = htonl(1); - llsol.s6_addr8[12] = 0xff; - - KERNEL_LOCK(); - if (in6_addmulti(&llsol, ifp, &error)) { - char addr[INET6_ADDRSTRLEN]; - nd6log((LOG_ERR, "%s: failed to join " - "%s (errno=%d)\n", ifp->if_xname, - inet_ntop(AF_INET6, &llsol, - addr, sizeof(addr)), - error)); - } - KERNEL_UNLOCK(); + /* join solicited node multicast for proxy ND */ + if (ifa == NULL && + (rt->rt_flags & RTF_ANNOUNCE) && + (ifp->if_flags & IFF_MULTICAST)) { + struct in6_addr llsol; + int error; + + llsol = satosin6(rt_key(rt))->sin6_addr; + llsol.s6_addr16[0] = htons(0xff02); + llsol.s6_addr16[1] = htons(ifp->if_index); + llsol.s6_addr32[1] = 0; + llsol.s6_addr32[2] = htonl(1); + llsol.s6_addr8[12] = 0xff; + + KERNEL_LOCK(); + if (in6_addmulti(&llsol, ifp, &error)) { + char addr[INET6_ADDRSTRLEN]; + nd6log((LOG_ERR, "%s: failed to join " + "%s (errno=%d)\n", ifp->if_xname, + inet_ntop(AF_INET6, &llsol, + addr, sizeof(addr)), + error)); } + KERNEL_UNLOCK(); } break;