Call nd6_ns_output() without kernel lock from nd6_resolve().
authorbluhm <bluhm@openbsd.org>
Tue, 2 May 2023 06:06:13 +0000 (06:06 +0000)
committerbluhm <bluhm@openbsd.org>
Tue, 2 May 2023 06:06:13 +0000 (06:06 +0000)
OK kn@

sys/netinet6/nd6.c
sys/netinet6/nd6.h
sys/netinet6/nd6_nbr.c

index 5e4d00e..a670963 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nd6.c,v 1.272 2023/04/05 23:01:03 kn Exp $    */
+/*     $OpenBSD: nd6.c,v 1.273 2023/05/02 06:06:13 bluhm Exp $ */
 /*     $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $   */
 
 /*
@@ -303,7 +303,8 @@ nd6_llinfo_timer(struct rtentry *rt)
                if (ln->ln_asked < nd6_mmaxtries) {
                        ln->ln_asked++;
                        nd6_llinfo_settimer(ln, RETRANS_TIMER / 1000);
-                       nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
+                       nd6_ns_output(ifp, NULL, &dst->sin6_addr,
+                           &ln->ln_saddr6, 0);
                } else {
                        struct mbuf_list ml;
                        struct mbuf *m;
@@ -336,6 +337,7 @@ nd6_llinfo_timer(struct rtentry *rt)
                        ln = NULL;
                }
                break;
+
        case ND6_LLINFO_REACHABLE:
                if (!ND6_LLINFO_PERMANENT(ln)) {
                        ln->ln_state = ND6_LLINFO_STALE;
@@ -357,14 +359,16 @@ nd6_llinfo_timer(struct rtentry *rt)
                ln->ln_asked = 1;
                ln->ln_state = ND6_LLINFO_PROBE;
                nd6_llinfo_settimer(ln, RETRANS_TIMER / 1000);
-               nd6_ns_output(ifp, &dst->sin6_addr, &dst->sin6_addr, ln, 0);
+               nd6_ns_output(ifp, &dst->sin6_addr, &dst->sin6_addr,
+                   &ln->ln_saddr6, 0);
                break;
+
        case ND6_LLINFO_PROBE:
                if (ln->ln_asked < nd6_umaxtries) {
                        ln->ln_asked++;
                        nd6_llinfo_settimer(ln, RETRANS_TIMER / 1000);
-                       nd6_ns_output(ifp, &dst->sin6_addr,
-                           &dst->sin6_addr, ln, 0);
+                       nd6_ns_output(ifp, &dst->sin6_addr, &dst->sin6_addr,
+                           &ln->ln_saddr6, 0);
                } else {
                        nd6_free(rt);
                        ln = NULL;
@@ -1247,7 +1251,9 @@ nd6_resolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
        struct sockaddr_dl *sdl;
        struct rtentry *rt;
        struct llinfo_nd6 *ln = NULL;
+       struct in6_addr saddr6;
        time_t uptime;
+       int solicit = 0;
 
        if (m->m_flags & M_MCAST) {
                ETHER_MAP_IPV6_MULTICAST(&satosin6(dst)->sin6_addr, desten);
@@ -1357,9 +1363,13 @@ nd6_resolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
        if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) {
                ln->ln_asked++;
                nd6_llinfo_settimer(ln, RETRANS_TIMER / 1000);
-               nd6_ns_output(ifp, NULL, &satosin6(dst)->sin6_addr, ln, 0);
+               saddr6 = ln->ln_saddr6;
+               solicit = 1;
        }
        KERNEL_UNLOCK();
+
+       if (solicit)
+               nd6_ns_output(ifp, NULL, &satosin6(dst)->sin6_addr, &saddr6, 0);
        return (EAGAIN);
 
 bad:
index 8e6a722..e9dc93e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nd6.h,v 1.97 2023/04/05 21:51:47 bluhm Exp $  */
+/*     $OpenBSD: nd6.h,v 1.98 2023/05/02 06:06:13 bluhm Exp $  */
 /*     $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $    */
 
 /*
@@ -141,7 +141,7 @@ void nd6_na_output(struct ifnet *, const struct in6_addr *,
        const struct in6_addr *, u_long, int, struct sockaddr *);
 void nd6_ns_input(struct mbuf *, int, int);
 void nd6_ns_output(struct ifnet *, const struct in6_addr *,
-       const struct in6_addr *, const struct llinfo_nd6 *, int);
+       const struct in6_addr *, const struct in6_addr *, int);
 caddr_t nd6_ifptomac(struct ifnet *);
 void nd6_dad_start(struct ifaddr *);
 void nd6_dad_stop(struct ifaddr *);
index ab3c122..2636718 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nd6_nbr.c,v 1.146 2023/04/28 14:09:06 phessler Exp $  */
+/*     $OpenBSD: nd6_nbr.c,v 1.147 2023/05/02 06:06:13 bluhm Exp $     */
 /*     $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $        */
 
 /*
@@ -360,7 +360,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
  */
 void
 nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
-    const struct in6_addr *taddr6, const struct llinfo_nd6 *ln, int dad)
+    const struct in6_addr *taddr6, const struct in6_addr *saddr6, int dad)
 {
        struct mbuf *m;
        struct ip6_hdr *ip6;
@@ -423,7 +423,7 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
        bzero(&dst_sa, sizeof(dst_sa));
        src_sa.sin6_family = dst_sa.sin6_family = AF_INET6;
        src_sa.sin6_len = dst_sa.sin6_len = sizeof(struct sockaddr_in6);
-       if (daddr6)
+       if (daddr6 != NULL)
                dst_sa.sin6_addr = *daddr6;
        else {
                dst_sa.sin6_addr.s6_addr16[0] = __IPV6_ADDR_INT16_MLL;
@@ -451,14 +451,13 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
                 * - if taddr is link local saddr6 must be link local as well
                 * Otherwise, we perform the source address selection as usual.
                 */
-               if (ln != NULL)
-                       src_sa.sin6_addr = ln->ln_saddr6;
+               if (saddr6 != NULL)
+                       src_sa.sin6_addr = *saddr6;
 
                if (!IN6_IS_ADDR_LINKLOCAL(taddr6) ||
                    IN6_IS_ADDR_UNSPECIFIED(&src_sa.sin6_addr) ||
                    IN6_IS_ADDR_LINKLOCAL(&src_sa.sin6_addr) ||
                    !in6ifa_ifpwithaddr(ifp, &src_sa.sin6_addr)) {
-
                        struct rtentry *rt;
 
                        rt = rtalloc(sin6tosa(&dst_sa), RT_RESOLVE,