Source-Changes-HG archive

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

[src/trunk]: src/sys/netinet Implement RFC 5227 2.4 Ongoing Conflict Detectio...



details:   https://anonhg.NetBSD.org/src/rev/689ccf915c9a
branches:  trunk
changeset: 818384:689ccf915c9a
user:      roy <roy%NetBSD.org@localhost>
date:      Tue Oct 11 13:59:30 2016 +0000

description:
Implement RFC 5227 2.4 Ongoing Conflict Detection and Address Defence.

If ip_dad_count is 0, then the conflict is just logged and the address
is not marked as duplicated.

diffstat:

 sys/netinet/if_arp.c |  83 +++++++++++++++++++++++----------------------------
 sys/netinet/in_var.h |   3 +-
 2 files changed, 40 insertions(+), 46 deletions(-)

diffs (153 lines):

diff -r a24c2885f321 -r 689ccf915c9a sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c      Tue Oct 11 13:39:34 2016 +0000
+++ b/sys/netinet/if_arp.c      Tue Oct 11 13:59:30 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_arp.c,v 1.229 2016/10/11 12:32:30 roy Exp $ */
+/*     $NetBSD: if_arp.c,v 1.230 2016/10/11 13:59:30 roy Exp $ */
 
 /*-
  * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.229 2016/10/11 12:32:30 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.230 2016/10/11 13:59:30 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -178,7 +178,7 @@
 static void arp_dad_timer(struct ifaddr *);
 static void arp_dad_start(struct ifaddr *);
 static void arp_dad_stop(struct ifaddr *);
-static void arp_dad_duplicated(struct ifaddr *);
+static void arp_dad_duplicated(struct ifaddr *, const char *);
 
 static void arp_init_llentry(struct ifnet *, struct llentry *);
 #if NTOKEN > 0
@@ -1133,16 +1133,13 @@
        if (in_nullhost(itaddr))
                ARP_STATINC(ARP_STAT_RCVZEROTPA);
 
-       /* DAD check, RFC 5227 2.1.1, Probe Details */
+       /* DAD check, RFC 5227 */
        if (in_hosteq(isaddr, myaddr) ||
            (in_nullhost(isaddr) && in_hosteq(itaddr, myaddr)))
        {
-               /* If our address is tentative, mark it as duplicated */
-               if (ia->ia4_flags & IN_IFF_TENTATIVE)
-                       arp_dad_duplicated((struct ifaddr *)ia);
-               /* If our address is unuseable, don't reply */
-               if (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED))
-                       goto out;
+               arp_dad_duplicated((struct ifaddr *)ia,
+                   lla_snprintf(ar_sha(ah), ah->ar_hln));
+               goto out;
        }
 
        /*
@@ -1156,14 +1153,6 @@
        if (in_nullhost(isaddr))
                goto reply;
 
-       if (in_hosteq(isaddr, myaddr)) {
-               log(LOG_ERR,
-                  "duplicate IP address %s sent from link address %s\n",
-                  in_fmtaddr(isaddr), lla_snprintf(ar_sha(ah), ah->ar_hln));
-               itaddr = myaddr;
-               goto reply;
-       }
-
        if (in_hosteq(itaddr, myaddr))
                la = arpcreate(ifp, m, &isaddr, NULL, 1);
        else
@@ -1774,41 +1763,45 @@
 }
 
 static void
-arp_dad_duplicated(struct ifaddr *ifa)
+arp_dad_duplicated(struct ifaddr *ifa, const char *sha)
 {
        struct in_ifaddr *ia = (struct in_ifaddr *)ifa;
-       struct ifnet *ifp;
-       struct dadq *dp;
+       struct ifnet *ifp = ifa->ifa_ifp;
+       const char *iastr = in_fmtaddr(ia->ia_addr.sin_addr);
 
-       mutex_enter(&arp_dad_lock);
-       dp = arp_dad_find(ifa);
-       if (dp == NULL) {
-               mutex_exit(&arp_dad_lock);
-               /* DAD seems to be stopping, so do nothing. */
+       if (ia->ia4_flags & (IN_IFF_TENTATIVE|IN_IFF_DUPLICATED)) {
+               log(LOG_ERR,
+                   "%s: DAD duplicate address %s from %s\n",
+                   if_name(ifp), iastr, sha);
+       } else if (ia->ia_dad_defended == 0 ||
+                  ia->ia_dad_defended < time_uptime - DEFEND_INTERVAL) {
+               ia->ia_dad_defended = time_uptime;
+               arpannounce1(ifa);
+               log(LOG_ERR,
+                   "%s: DAD defended address %s from %s\n",
+                   if_name(ifp), iastr, sha);
                return;
+       } else {
+               /* If DAD is disabled, just report the duplicate. */
+               if (ip_dad_count == 0) {
+                       log(LOG_ERR,
+                           "%s: DAD ignoring duplicate address %s from %s\n",
+                           if_name(ifp), iastr, sha);
+                       return;
+               }
+               log(LOG_ERR,
+                   "%s: DAD defence failed for %s from %s\n",
+                   if_name(ifp), iastr, sha);
        }
 
-       ifp = ifa->ifa_ifp;
-       log(LOG_ERR,
-           "%s: DAD detected duplicate IPv4 address %s: ARP out=%d\n",
-           if_name(ifp), in_fmtaddr(ia->ia_addr.sin_addr),
-           dp->dad_arp_ocount);
+       arp_dad_stop(ifa);
 
        ia->ia4_flags &= ~IN_IFF_TENTATIVE;
-       ia->ia4_flags |= IN_IFF_DUPLICATED;
-
-       /* We are done with DAD, with duplicated address found. (failure) */
-       arp_dad_stoptimer(dp);
-
-       /* Inform the routing socket that DAD has completed */
-       rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
-
-       TAILQ_REMOVE(&dadq, dp, dad_list);
-       mutex_exit(&arp_dad_lock);
-
-       free(dp, M_IPARP);
-       dp = NULL;
-       ifafree(ifa);
+       if ((ia->ia4_flags & IN_IFF_DUPLICATED) == 0) {
+               ia->ia4_flags |= IN_IFF_DUPLICATED;
+               /* Inform the routing socket of the duplicate address */
+               rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
+       }
 }
 
 /*
diff -r a24c2885f321 -r 689ccf915c9a sys/netinet/in_var.h
--- a/sys/netinet/in_var.h      Tue Oct 11 13:39:34 2016 +0000
+++ b/sys/netinet/in_var.h      Tue Oct 11 13:59:30 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in_var.h,v 1.87 2016/09/29 15:18:18 roy Exp $  */
+/*     $NetBSD: in_var.h,v 1.88 2016/10/11 13:59:30 roy Exp $  */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -107,6 +107,7 @@
        int     ia4_flags;              /* address flags */
        void    (*ia_dad_start) (struct ifaddr *);      /* DAD start function */
        void    (*ia_dad_stop) (struct ifaddr *);       /* DAD stop function */
+       time_t  ia_dad_defended;        /* last time of DAD defence */
 
 #ifdef _KERNEL
        struct pslist_entry     ia_hash_pslist_entry;



Home | Main Index | Thread Index | Old Index