KAME people chose to add states to the address descriptors in order
to implement various IPv6 automagic features.  But IN6_IFF_NODAD is
not a real state, it's just a hack for some spaghetti code.

Diff belows get rids of this flag by shuffling some code around and
only using the IN6_IFF_TENTATIVE flag.

Ok?

Index: net/if_spppsubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_spppsubr.c,v
retrieving revision 1.136
diff -u -p -r1.136 if_spppsubr.c
--- net/if_spppsubr.c   18 Jul 2015 15:51:16 -0000      1.136
+++ net/if_spppsubr.c   19 Aug 2015 11:15:01 -0000
@@ -4790,9 +4790,6 @@ sppp_set_ip6_addr(struct sppp *sp, const
         */
        ifra->ifra_prefixmask.sin6_family = AF_UNSPEC;
 
-       /* DAD is redundant after an IPv6CP exchange. */
-       ifra->ifra_flags |= IN6_IFF_NODAD;
-
        task_add(systq, &sp->ipv6cp.set_addr_task);
 }
 
Index: netinet6/in6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6.c,v
retrieving revision 1.164
diff -u -p -r1.164 in6.c
--- netinet6/in6.c      19 Aug 2015 11:09:24 -0000      1.164
+++ netinet6/in6.c      19 Aug 2015 11:15:02 -0000
@@ -468,11 +468,19 @@ in6_control(struct socket *so, u_long cm
                /* reject read-only flags */
                if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 ||
                    (ifra->ifra_flags & IN6_IFF_DETACHED) != 0 ||
-                   (ifra->ifra_flags & IN6_IFF_NODAD) != 0 ||
                    (ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0 ||
                    (ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0) {
                        return (EINVAL);
                }
+
+               /*
+                * Make the address tentative before joining multicast
+                * addresses, so that corresponding MLD responses would
+                * not have a tentative source address.
+                */
+               if ((ia6 == NULL) && in6if_do_dad(ifp))
+                       ifra->ifra_flags |= IN6_IFF_TENTATIVE;
+
                /*
                 * first, make or update the interface address structure,
                 * and link it to the list. try to enable inet6 if there
@@ -497,6 +505,11 @@ in6_control(struct socket *so, u_long cm
                        break;
                }
 
+               /* Perform DAD, if needed. */
+               if (ia6->ia6_flags & IN6_IFF_TENTATIVE)
+                       nd6_dad_start(&ia6->ia_ifa);
+
+
                plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, NULL);
                if (plen == 128) {
                        dohooks(ifp->if_addrhooks, 0);
@@ -753,15 +766,6 @@ in6_update_ifa(struct ifnet *ifp, struct
         * configure address flags.
         */
        ia6->ia6_flags = ifra->ifra_flags;
-       /*
-        * Make the address tentative before joining multicast addresses,
-        * so that corresponding MLD responses would not have a tentative
-        * source address.
-        */
-       ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;  /* safety */
-       if (hostIsNew && in6if_do_dad(ifp) &&
-           (ifra->ifra_flags & IN6_IFF_NODAD) == 0)
-               ia6->ia6_flags |= IN6_IFF_TENTATIVE;
 
        /*
         * We are done if we have simply modified an existing address.
@@ -906,17 +910,6 @@ in6_update_ifa(struct ifnet *ifp, struct
                if (!imm)
                        goto cleanup;
                LIST_INSERT_HEAD(&ia6->ia6_memberships, imm, i6mm_chain);
-       }
-
-       /*
-        * Perform DAD, if needed.
-        * XXX It may be of use, if we can administratively
-        * disable DAD.
-        */
-       if (hostIsNew && in6if_do_dad(ifp) &&
-           (ifra->ifra_flags & IN6_IFF_NODAD) == 0)
-       {
-               nd6_dad_start(&ia6->ia_ifa, NULL);
        }
 
        return (error);
Index: netinet6/in6_ifattach.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6_ifattach.c,v
retrieving revision 1.91
diff -u -p -r1.91 in6_ifattach.c
--- netinet6/in6_ifattach.c     17 Aug 2015 10:57:24 -0000      1.91
+++ netinet6/in6_ifattach.c     19 Aug 2015 11:15:02 -0000
@@ -292,7 +292,6 @@ success:
 int
 in6_ifattach_linklocal(struct ifnet *ifp, struct in6_addr *ifid)
 {
-       struct in6_ifaddr *ia6;
        struct in6_aliasreq ifra;
        int  s, error;
 
@@ -332,12 +331,6 @@ in6_ifattach_linklocal(struct ifnet *ifp
        ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
 
        /*
-        * Do not let in6_update_ifa() do DAD, since we need a random delay
-        * before sending an NS at the first time the interface becomes up.
-        */
-       ifra.ifra_flags |= IN6_IFF_NODAD;
-
-       /*
         * Now call in6_update_ifa() to do a bunch of procedures to configure
         * a link-local address. In the case of CARP, we may be called after
         * one has already been configured, so check if it's already there
@@ -363,21 +356,17 @@ in6_ifattach_linklocal(struct ifnet *ifp
        }
 
        /*
-        * Adjust ia6_flags so that in6_ifattach() will perform DAD.
+        * Perform DAD.
+        *
         * XXX: Some P2P interfaces seem not to send packets just after
         * becoming up, so we skip p2p interfaces for safety.
         */
-       ia6 = in6ifa_ifpforlinklocal(ifp, 0); /* ia6 must not be NULL */
-#ifdef DIAGNOSTIC
-       if (!ia6) {
-               panic("ia6 == NULL in in6_ifattach_linklocal");
-               /* NOTREACHED */
-       }
-#endif
        if (in6if_do_dad(ifp) && ((ifp->if_flags & IFF_POINTOPOINT) ||
            (ifp->if_type == IFT_CARP)) == 0) {
-               ia6->ia6_flags &= ~IN6_IFF_NODAD;
+               struct in6_ifaddr *ia6;
+               ia6 = in6ifa_ifpforlinklocal(ifp, 0);
                ia6->ia6_flags |= IN6_IFF_TENTATIVE;
+               nd6_dad_start(&ia6->ia_ifa);
        }
 
        /*
@@ -423,9 +412,6 @@ in6_ifattach_loopback(struct ifnet *ifp)
        ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
        ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
 
-       /* we don't need to perform DAD on loopback interfaces. */
-       ifra.ifra_flags |= IN6_IFF_NODAD;
-
        /*
         * We are sure that this is a newly assigned address, so we can set
         * NULL to the 3rd arg.
@@ -492,9 +478,6 @@ in6_nigroup(struct ifnet *ifp, const cha
 int
 in6_ifattach(struct ifnet *ifp)
 {
-       struct ifaddr *ifa;
-       int dad_delay = 0;              /* delay ticks before DAD output */
-
        /* some of the interfaces are inherently not IPv6 capable */
        switch (ifp->if_type) {
        case IFT_BRIDGE:
@@ -529,14 +512,6 @@ in6_ifattach(struct ifnet *ifp)
                        return (0);
 
                return (in6_ifattach_loopback(ifp));
-       }
-
-       /* Perform DAD. */
-       TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
-               if (ifa->ifa_addr->sa_family != AF_INET6)
-                       continue;
-               if (ifatoia6(ifa)->ia6_flags & IN6_IFF_TENTATIVE)
-                       nd6_dad_start(ifa, &dad_delay);
        }
 
        if (ifp->if_xflags & IFXF_AUTOCONF6)
Index: netinet6/in6_var.h
===================================================================
RCS file: /cvs/src/sys/netinet6/in6_var.h,v
retrieving revision 1.52
diff -u -p -r1.52 in6_var.h
--- netinet6/in6_var.h  8 Jul 2015 08:48:34 -0000       1.52
+++ netinet6/in6_var.h  19 Aug 2015 11:15:02 -0000
@@ -433,9 +433,6 @@ struct      in6_rrenumreq {
 #define IN6_IFF_DUPLICATED     0x04    /* DAD detected duplicate */
 #define IN6_IFF_DETACHED       0x08    /* may be detached from the link */
 #define IN6_IFF_DEPRECATED     0x10    /* deprecated address */
-#define IN6_IFF_NODAD          0x20    /* don't perform DAD on this address
-                                        * (used only at first SIOC* call)
-                                        */
 #define IN6_IFF_AUTOCONF       0x40    /* autoconfigurable address. */
 #define IN6_IFF_PRIVACY                0x80    /* RFC 4941 temporary address */
 
Index: netinet6/nd6.h
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6.h,v
retrieving revision 1.45
diff -u -p -r1.45 nd6.h
--- netinet6/nd6.h      18 Aug 2015 08:52:25 -0000      1.45
+++ netinet6/nd6.h      19 Aug 2015 11:15:03 -0000
@@ -291,7 +291,7 @@ void nd6_ns_input(struct mbuf *, int, in
 void nd6_ns_output(struct ifnet *, struct in6_addr *,
        struct in6_addr *, struct llinfo_nd6 *, int);
 caddr_t nd6_ifptomac(struct ifnet *);
-void nd6_dad_start(struct ifaddr *, int *);
+void nd6_dad_start(struct ifaddr *);
 void nd6_dad_stop(struct ifaddr *);
 void nd6_ra_input(struct mbuf *, int, int);
 
Index: netinet6/nd6_nbr.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6_nbr.c,v
retrieving revision 1.91
diff -u -p -r1.91 nd6_nbr.c
--- netinet6/nd6_nbr.c  16 Jul 2015 15:28:38 -0000      1.91
+++ netinet6/nd6_nbr.c  19 Aug 2015 11:15:03 -0000
@@ -1128,11 +1128,9 @@ nd6_dad_stoptimer(struct dadq *dp)
 
 /*
  * Start Duplicated Address Detection (DAD) for specified interface address.
- *
- * tick - minimum delay ticks for IFF_UP event
  */
 void
-nd6_dad_start(struct ifaddr *ifa, int *tick)
+nd6_dad_start(struct ifaddr *ifa)
 {
        struct in6_ifaddr *ia6 = ifatoia6(ifa);
        struct dadq *dp;
@@ -1149,31 +1147,15 @@ nd6_dad_start(struct ifaddr *ifa, int *t
         * - DAD is disabled (ip6_dad_count == 0)
         * - the interface address is anycast
         */
-       if (!(ia6->ia6_flags & IN6_IFF_TENTATIVE)) {
-               log(LOG_DEBUG,
-                       "nd6_dad_start: called with non-tentative address "
-                       "%s(%s)\n",
-                       inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr,
-                           addr, sizeof(addr)),
-                       ifa->ifa_ifp ? ifa->ifa_ifp->if_xname : "???");
-               return;
-       }
-       if (ia6->ia6_flags & IN6_IFF_ANYCAST) {
+       KASSERT(ia6->ia6_flags & IN6_IFF_TENTATIVE);
+       if ((ia6->ia6_flags & IN6_IFF_ANYCAST) || (!ip6_dad_count)) {
                ia6->ia6_flags &= ~IN6_IFF_TENTATIVE;
                return;
        }
-       if (!ip6_dad_count) {
-               ia6->ia6_flags &= ~IN6_IFF_TENTATIVE;
-               return;
-       }
-       if (!ifa->ifa_ifp)
-               panic("nd6_dad_start: ifa->ifa_ifp == NULL");
-       if (!(ifa->ifa_ifp->if_flags & IFF_UP))
-               return;
-       if (nd6_dad_find(ifa) != NULL) {
-               /* DAD already in progress */
+
+       /* DAD already in progress */
+       if (nd6_dad_find(ifa) != NULL)
                return;
-       }
 
        dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO);
        if (dp == NULL) {
@@ -1202,21 +1184,9 @@ nd6_dad_start(struct ifaddr *ifa, int *t
        dp->dad_count = ip6_dad_count;
        dp->dad_ns_icount = dp->dad_na_icount = 0;
        dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
-       if (tick == NULL) {
-               nd6_dad_ns_output(dp, ifa);
-               nd6_dad_starttimer(dp,
-                   (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
-       } else {
-               int ntick;
-
-               if (*tick == 0)
-                       ntick = arc4random_uniform(MAX_RTR_SOLICITATION_DELAY *
-                           hz);
-               else
-                       ntick = *tick + arc4random_uniform(hz / 2);
-               *tick = ntick;
-               nd6_dad_starttimer(dp, ntick);
-       }
+       nd6_dad_ns_output(dp, ifa);
+       nd6_dad_starttimer(dp,
+           (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
 }
 
 /*
Index: netinet6/nd6_rtr.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6_rtr.c,v
retrieving revision 1.115
diff -u -p -r1.115 nd6_rtr.c
--- netinet6/nd6_rtr.c  18 Aug 2015 08:52:25 -0000      1.115
+++ netinet6/nd6_rtr.c  19 Aug 2015 11:15:03 -0000
@@ -2084,7 +2084,7 @@ in6_ifadd(struct nd_prefix *pr, int priv
 
        /* XXX: scope zone ID? */
 
-       ifra.ifra_flags |= IN6_IFF_AUTOCONF; /* obey autoconf */
+       ifra.ifra_flags |= IN6_IFF_AUTOCONF|IN6_IFF_TENTATIVE;
 
        /* allocate ifaddr structure, link into chain, etc. */
        s = splsoftnet();
@@ -2103,7 +2103,13 @@ in6_ifadd(struct nd_prefix *pr, int priv
        }
 
        /* this is always non-NULL */
-       return (in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr));
+       ia6 = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
+
+       /* Perform DAD, if needed. */
+       if (ia6->ia6_flags & IN6_IFF_TENTATIVE)
+               nd6_dad_start(&ia6->ia_ifa);
+
+       return (ia6);
 }
 
 int

Reply via email to