summaryrefslogtreecommitdiff
path: root/sys/netinet6
diff options
context:
space:
mode:
authorPeter Hessler <phessler@cvs.openbsd.org>2023-04-28 14:09:07 +0000
committerPeter Hessler <phessler@cvs.openbsd.org>2023-04-28 14:09:07 +0000
commit964eb88d44adea6add4e2c196ec0eb951b32621a (patch)
tree6536b481fce63d5f95407d620c637148c6a6d489 /sys/netinet6
parent0d03b2d55c45a6392cde55a16be44706f7bf9af6 (diff)
Inbound portion of RFC9131. Routers can create new neighbor cache entries
when receiving a valid Neighbor Advertisement. OK florian@ kn@
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/nd6_nbr.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index f78e2324d85..ab3c122d0f5 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6_nbr.c,v 1.145 2023/04/25 15:41:17 phessler Exp $ */
+/* $OpenBSD: nd6_nbr.c,v 1.146 2023/04/28 14:09:06 phessler Exp $ */
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
/*
@@ -678,11 +678,40 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
goto bad;
}
+ /* Check if we already have this neighbor in our cache. */
+ rt = nd6_lookup(&taddr6, 0, ifp, ifp->if_rdomain);
+
/*
+ * If we are a router, we may create new stale cache entries upon
+ * receiving Unsolicited Neighbor Advertisements.
+ */
+ if (rt == NULL && ip6_forwarding == 1) {
+ rt = nd6_lookup(&taddr6, 1, ifp, ifp->if_rdomain);
+ if (rt == NULL || lladdr == NULL ||
+ ((sdl = satosdl(rt->rt_gateway)) == NULL))
+ goto freeit;
+
+ ln = (struct llinfo_nd6 *)rt->rt_llinfo;
+ sdl->sdl_alen = ifp->if_addrlen;
+ bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
+
+ /*
+ * RFC9131 6.1.1
+ *
+ * Routers SHOULD create a new entry for the target address
+ * with the reachability state set to STALE.
+ */
+ ln->ln_state = ND6_LLINFO_STALE;
+ nd6_llinfo_settimer(ln, nd6_gctimer);
+
+ goto freeit;
+ }
+
+ /*
+ * Host:
* If no neighbor cache entry is found, NA SHOULD silently be
* discarded.
*/
- rt = nd6_lookup(&taddr6, 0, ifp, ifp->if_rdomain);
if ((rt == NULL) ||
((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) ||
((sdl = satosdl(rt->rt_gateway)) == NULL))