Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/netinet6 inet6: match NS nonce to any interface
details: https://anonhg.NetBSD.org/src/rev/f123474a0945
branches: trunk
changeset: 995105:f123474a0945
user: roy <roy%NetBSD.org@localhost>
date: Fri Dec 07 14:47:24 2018 +0000
description:
inet6: match NS nonce to any interface
This allows the same address to exist on many interfaces on the same
prefix, matching the inet behaviour.
diffstat:
sys/netinet6/nd6_nbr.c | 53 +++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 46 insertions(+), 7 deletions(-)
diffs (109 lines):
diff -r 924316f5f765 -r f123474a0945 sys/netinet6/nd6_nbr.c
--- a/sys/netinet6/nd6_nbr.c Fri Dec 07 09:36:26 2018 +0000
+++ b/sys/netinet6/nd6_nbr.c Fri Dec 07 14:47:24 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6_nbr.c,v 1.161 2018/12/04 21:16:54 roy Exp $ */
+/* $NetBSD: nd6_nbr.c,v 1.162 2018/12/07 14:47:24 roy Exp $ */
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.161 2018/12/04 21:16:54 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.162 2018/12/07 14:47:24 roy Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -77,6 +77,7 @@
struct dadq;
static struct dadq *nd6_dad_find(struct ifaddr *, struct nd_opt_nonce *, bool *);
+static bool nd6_dad_ownnonce(struct ifaddr *, struct nd_opt_nonce *nonce);
static void nd6_dad_starttimer(struct dadq *, int);
static void nd6_dad_destroytimer(struct dadq *);
static void nd6_dad_timer(struct dadq *);
@@ -309,6 +310,16 @@
goto freeit;
}
+ /*
+ * It looks that sender is performing DAD.
+ * Check that the nonce is not being used by the same address
+ * on another interface.
+ */
+ if (IN6_IS_ADDR_UNSPECIFIED(&saddr6) && ndopts.nd_opts_nonce != NULL) {
+ if (nd6_dad_ownnonce(ifa, ndopts.nd_opts_nonce))
+ goto freeit;
+ }
+
ifa_release(ifa, &psref_ia);
ifa = NULL;
@@ -1088,17 +1099,33 @@
static struct dadq *
nd6_dad_find(struct ifaddr *ifa, struct nd_opt_nonce *nonce, bool *found_nonce)
{
+ struct in6_addr *myaddr6, *dadaddr6;
+ bool match_ifa;
struct dadq *dp;
int i, nonce_max;
KASSERT(mutex_owned(&nd6_dad_lock));
+ KASSERT(ifa != NULL);
+
+ myaddr6 = IFA_IN6(ifa);
+ if (nonce != NULL &&
+ nonce->nd_opt_nonce_len != (ND_OPT_NONCE_LEN + 2) / 8)
+ nonce = NULL;
+ match_ifa = nonce == NULL || found_nonce == NULL || *found_nonce == false;
+ if (found_nonce != NULL)
+ *found_nonce = false;
TAILQ_FOREACH(dp, &dadq, dad_list) {
- if (dp->dad_ifa != ifa)
- continue;
+ if (match_ifa) {
+ if (dp->dad_ifa != ifa)
+ continue;
+ } else {
+ dadaddr6 = IFA_IN6(dp->dad_ifa);
+ if (!IN6_ARE_ADDR_EQUAL(myaddr6, dadaddr6))
+ continue;
+ }
- if (nonce == NULL ||
- nonce->nd_opt_nonce_len != (ND_OPT_NONCE_LEN + 2) / 8)
+ if (nonce == NULL)
break;
nonce_max = MIN(dp->dad_ns_ocount, ND_OPT_NONCE_STORE);
@@ -1115,7 +1142,7 @@
log(LOG_DEBUG,
"%s: detected a looped back NS message for %s\n",
ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???",
- IN6_PRINT(ip6buf, IFA_IN6(ifa)));
+ IN6_PRINT(ip6buf, myaddr6));
dp->dad_ns_lcount++;
continue;
}
@@ -1125,6 +1152,18 @@
return dp;
}
+static bool
+nd6_dad_ownnonce(struct ifaddr *ifa, struct nd_opt_nonce *nonce)
+{
+ bool found_nonce = true;
+
+ mutex_enter(&nd6_dad_lock);
+ nd6_dad_find(ifa, nonce, &found_nonce);
+ mutex_exit(&nd6_dad_lock);
+
+ return found_nonce;
+}
+
static void
nd6_dad_starttimer(struct dadq *dp, int ticks)
{
Home |
Main Index |
Thread Index |
Old Index