Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet6 nd6: restore a missing reachability confirmation



details:   https://anonhg.NetBSD.org/src/rev/25b651a29f25
branches:  trunk
changeset: 452332:25b651a29f25
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Fri Jun 28 06:45:16 2019 +0000

description:
nd6: restore a missing reachability confirmation

On sending a packet over a STALE cache, the cache should be tried a reachability
confirmation, which is described in RFC 2461/4861 7.3.3.  On the fast path in
nd6_resolve, however, the treatment for STALE caches has been skipped
accidentally.  So STALE caches never be back to the REACHABLE state.

To fix the issue, branch to the fast path only when the cache entry is the
REACHABLE state and leave other caches to the slow path that includes the
treatment.  To this end we need to allow to return a link-layer address if a
valid address is available on the slow path too, which is the same behavior as
FreeBSD and OpenBSD.

diffstat:

 sys/netinet6/nd6.c |  20 ++++++++++++++++----
 1 files changed, 16 insertions(+), 4 deletions(-)

diffs (48 lines):

diff -r d3fdd9abbfd0 -r 25b651a29f25 sys/netinet6/nd6.c
--- a/sys/netinet6/nd6.c        Fri Jun 28 01:57:43 2019 +0000
+++ b/sys/netinet6/nd6.c        Fri Jun 28 06:45:16 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nd6.c,v 1.254 2019/05/13 02:03:07 christos Exp $       */
+/*     $NetBSD: nd6.c,v 1.255 2019/06/28 06:45:16 ozaki-r Exp $        */
 /*     $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $   */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.254 2019/05/13 02:03:07 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.255 2019/06/28 06:45:16 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -2319,8 +2319,8 @@
        /* Look up the neighbor cache for the nexthop */
        ln = nd6_lookup(&dst->sin6_addr, ifp, false);
 
-       if (ln != NULL && (ln->la_flags & LLE_VALID) != 0) {
-               KASSERT(ln->ln_state > ND6_LLINFO_INCOMPLETE);
+       if (ln != NULL && (ln->la_flags & LLE_VALID) != 0 &&
+           ln->ln_state == ND6_LLINFO_REACHABLE) {
                /* Fast path */
                memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen));
                LLE_RUNLOCK(ln);
@@ -2383,6 +2383,18 @@
        }
 
        /*
+        * If the neighbor cache entry has a state other than INCOMPLETE
+        * (i.e. its link-layer address is already resolved), just
+        * send the packet.
+        */
+       if (ln->ln_state > ND6_LLINFO_INCOMPLETE) {
+               KASSERT((ln->la_flags & LLE_VALID) != 0);
+               memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen));
+               LLE_WUNLOCK(ln);
+               return 0;
+       }
+
+       /*
         * There is a neighbor cache entry, but no ethernet address
         * response yet.  Append this latest packet to the end of the
         * packet queue in the mbuf, unless the number of the packet



Home | Main Index | Thread Index | Old Index