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;