]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet6/nd6_nbr.c
xnu-344.49.tar.gz
[apple/xnu.git] / bsd / netinet6 / nd6_nbr.c
index eca3501f1a20cdc545fe344f46bcb2c4fb47364f..70fbfef80868a992c9e32174533c0286c100f6ad 100644 (file)
@@ -1,4 +1,5 @@
-/*     $KAME: nd6_nbr.c,v 1.32 2000/03/21 11:37:30 itojun Exp $        */
+/*     $FreeBSD: src/sys/netinet6/nd6_nbr.c,v 1.4.2.4 2001/07/06 05:32:25 sumikawa Exp $       */
+/*     $KAME: nd6_nbr.c,v 1.64 2001/05/17 03:48:30 itojun Exp $        */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  * SUCH DAMAGE.
  */
 
-#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
-#include "opt_inet.h"
-#if __NetBSD__ /*XXX*/
-#include "opt_ipsec.h"
-#endif
-#endif
-
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/malloc.h>
@@ -45,9 +39,6 @@
 #include <sys/time.h>
 #include <sys/kernel.h>
 #include <sys/errno.h>
-#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
-#include <sys/ioctl.h>
-#endif
 #include <sys/syslog.h>
 #include <kern/queue.h>
 
 #include <netinet6/nd6.h>
 #include <netinet/icmp6.h>
 
-#ifdef __OpenBSD__     /*don't confuse KAME ipsec with OpenBSD ipsec*/
-#undef IPSEC
-#endif
-
 #if IPSEC
 #include <netinet6/ipsec.h>
+#if INET6
+#include <netinet6/ipsec6.h>
+#endif
+extern int ipsec_bypass;
 #endif
 
 #include <net/net_osdep.h>
 
 struct dadq;
 static struct dadq *nd6_dad_find __P((struct ifaddr *));
+#ifndef __APPLE__
+static void nd6_dad_starttimer __P((struct dadq *, int));
+static void nd6_dad_stoptimer __P((struct dadq *));
+#else
+void nd6_dad_stoptimer __P((struct ifaddr *));
+#endif
 static void nd6_dad_timer __P((struct ifaddr *));
+static void nd6_dad_timer_funnel __P((struct ifaddr *));
 static void nd6_dad_ns_output __P((struct dadq *, struct ifaddr *));
 static void nd6_dad_ns_input __P((struct ifaddr *));
 static void nd6_dad_na_input __P((struct ifaddr *));
@@ -112,10 +110,25 @@ nd6_ns_input(m, off, icmp6len)
        union nd_opts ndopts;
        struct sockaddr_dl *proxydl = NULL;
 
+#ifndef PULLDOWN_TEST
+       IP6_EXTHDR_CHECK(m, off, icmp6len,);
+       nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
+#else
+       IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
+       if (nd_ns == NULL) {
+               icmp6stat.icp6s_tooshort++;
+               return;
+       }
+#endif
+       ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
+       taddr6 = nd_ns->nd_ns_target;
+
        if (ip6->ip6_hlim != 255) {
-               log(LOG_ERR,
-                   "nd6_ns_input: invalid hlim %d\n", ip6->ip6_hlim);
-               goto freeit;
+               nd6log((LOG_ERR,
+                   "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n",
+                   ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
+                   ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
+               goto bad;
        }
 
        if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
@@ -127,26 +140,14 @@ nd6_ns_input(m, off, icmp6len)
                    && daddr6.s6_addr8[12] == 0xff) {
                        ; /*good*/
                } else {
-                       log(LOG_INFO, "nd6_ns_input: bad DAD packet "
-                               "(wrong ip6 dst)\n");
+                       nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
+                               "(wrong ip6 dst)\n"));
                        goto bad;
                }
        }
 
-#ifndef PULLDOWN_TEST
-       IP6_EXTHDR_CHECK(m, off, icmp6len,);
-       nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
-#else
-       IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
-       if (nd_ns == NULL) {
-               icmp6stat.icp6s_tooshort++;
-               return;
-       }
-#endif
-       taddr6 = nd_ns->nd_ns_target;
-
        if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
-               log(LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n");
+               nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"));
                goto bad;
        }
 
@@ -156,8 +157,10 @@ nd6_ns_input(m, off, icmp6len)
        icmp6len -= sizeof(*nd_ns);
        nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
        if (nd6_options(&ndopts) < 0) {
-               log(LOG_INFO, "nd6_ns_input: invalid ND option, ignored\n");
-               goto bad;
+               nd6log((LOG_INFO,
+                   "nd6_ns_input: invalid ND option, ignored\n"));
+               /* nd6_options have incremented stats */
+               goto freeit;
        }
 
        if (ndopts.nd_opts_src_lladdr) {
@@ -166,8 +169,8 @@ nd6_ns_input(m, off, icmp6len)
        }
        
        if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) {
-               log(LOG_INFO, "nd6_ns_input: bad DAD packet "
-                       "(link-layer address option)\n");
+               nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
+                   "(link-layer address option)\n"));
                goto bad;
        }
 
@@ -211,11 +214,7 @@ nd6_ns_input(m, off, icmp6len)
                tsin6.sin6_family = AF_INET6;
                tsin6.sin6_addr = taddr6;
 
-               rt = rtalloc1((struct sockaddr *)&tsin6, 0
-#if __FreeBSD__ || defined (__APPLE__)
-                             , 0
-#endif /* __FreeBSD__ */
-                             );
+               rt = rtalloc1((struct sockaddr *)&tsin6, 0, 0);
                if (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
                    rt->rt_gateway->sa_family == AF_LINK) {
                        /*
@@ -233,7 +232,7 @@ nd6_ns_input(m, off, icmp6len)
        }
        if (!ifa) {
                /*
-                * We've got a NS packet, and we don't have that adddress
+                * We've got an NS packet, and we don't have that adddress
                 * assigned for us.  We MUST silently ignore it.
                 * See RFC2461 7.2.3.
                 */
@@ -246,10 +245,11 @@ nd6_ns_input(m, off, icmp6len)
                goto freeit;
 
        if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
-               log(LOG_INFO,
+               nd6log((LOG_INFO,
                    "nd6_ns_input: lladdrlen mismatch for %s "
                    "(if %d, NS packet %d)\n",
-                       ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2);
+                       ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2));
+               goto bad;
        }
 
        if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
@@ -316,9 +316,10 @@ nd6_ns_input(m, off, icmp6len)
        return;
 
  bad:
-       log(LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(&saddr6));
-       log(LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(&daddr6));
-       log(LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(&taddr6));
+       nd6log((LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(&saddr6)));
+       nd6log((LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(&daddr6)));
+       nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(&taddr6)));
+       icmp6stat.icp6s_badns++;
        m_freem(m);
 }
 
@@ -334,7 +335,7 @@ nd6_ns_input(m, off, icmp6len)
 void
 nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
        struct ifnet *ifp;
-       struct in6_addr *daddr6, *taddr6;
+       const struct in6_addr *daddr6, *taddr6;
        struct llinfo_nd6 *ln;  /* for source address determination */
        int dad;        /* duplicated address detection */
 {
@@ -355,7 +356,7 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
        maxlen = sizeof(*ip6) + sizeof(*nd_ns);
        maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
        if (max_linkhdr + maxlen >= MCLBYTES) {
-#ifdef DIAGNOSTIC
+#if DIAGNOSTIC
                printf("nd6_ns_output: max_linkhdr + maxlen >= MCLBYTES "
                    "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
 #endif
@@ -372,6 +373,7 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
        }
        if (m == NULL)
                return;
+       m->m_pkthdr.rcvif = NULL;
 
        if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
                m->m_flags |= M_MCAST;
@@ -505,7 +507,8 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
 
 #if IPSEC
        /* Don't lookup socket */
-       ipsec_setsocket(m, NULL);
+       if (ipsec_bypass == 0)
+               (void)ipsec_setsocket(m, NULL);
 #endif
        ip6_output(m, NULL, NULL, dad ? IPV6_DADOUTPUT : 0, &im6o, &outif);
        if (outif) {
@@ -551,9 +554,11 @@ nd6_na_input(m, off, icmp6len)
        union nd_opts ndopts;
 
        if (ip6->ip6_hlim != 255) {
-               log(LOG_ERR,
-                   "nd6_na_input: invalid hlim %d\n", ip6->ip6_hlim);
-               goto freeit;
+               nd6log((LOG_ERR,
+                   "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n",
+                   ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
+                   ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
+               goto bad;
        }
 
 #ifndef PULLDOWN_TEST
@@ -576,22 +581,24 @@ nd6_na_input(m, off, icmp6len)
                taddr6.s6_addr16[1] = htons(ifp->if_index);
 
        if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
-               log(LOG_ERR,
+               nd6log((LOG_ERR,
                    "nd6_na_input: invalid target address %s\n",
-                   ip6_sprintf(&taddr6));
-               goto freeit;
+                   ip6_sprintf(&taddr6)));
+               goto bad;
        }
        if (IN6_IS_ADDR_MULTICAST(&daddr6))
                if (is_solicited) {
-                       log(LOG_ERR,
-                           "nd6_na_input: a solicited adv is multicasted\n");
-                       goto freeit;
+                       nd6log((LOG_ERR,
+                           "nd6_na_input: a solicited adv is multicasted\n"));
+                       goto bad;
                }
 
        icmp6len -= sizeof(*nd_na);
        nd6_option_init(nd_na + 1, icmp6len, &ndopts);
        if (nd6_options(&ndopts) < 0) {
-               log(LOG_INFO, "nd6_na_input: invalid ND option, ignored\n");
+               nd6log((LOG_INFO,
+                   "nd6_na_input: invalid ND option, ignored\n"));
+               /* nd6_options have incremented stats */
                goto freeit;
        }
 
@@ -626,10 +633,11 @@ nd6_na_input(m, off, icmp6len)
        }
 
        if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
-               log(LOG_INFO,
+               nd6log((LOG_INFO,
                    "nd6_na_input: lladdrlen mismatch for %s "
                    "(if %d, NA packet %d)\n",
-                       ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2);
+                       ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2));
+               goto bad;
        }
 
        /*
@@ -656,16 +664,22 @@ nd6_na_input(m, off, icmp6len)
                bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
                if (is_solicited) {
                        ln->ln_state = ND6_LLINFO_REACHABLE;
+                       ln->ln_byhint = 0;
                        if (ln->ln_expire)
-#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__)
-                               ln->ln_expire = time.tv_sec +
-#else
                                ln->ln_expire = time_second +
-#endif
-                                       nd_ifinfo[rt->rt_ifp->if_index].reachable;
-               } else
+                                   nd_ifinfo[rt->rt_ifp->if_index].reachable;
+               } else {
                        ln->ln_state = ND6_LLINFO_STALE;
-               ln->ln_router = is_router;
+                       ln->ln_expire = time_second + nd6_gctimer;
+               }
+               if ((ln->ln_router = is_router) != 0) {
+                       /*
+                        * This means a router's state has changed from
+                        * non-reachable to probably reachable, and might
+                        * affect the status of associated prefixes..
+                        */
+                       pfxlist_onlink_check();
+               }
        } else {
                int llchange;
 
@@ -708,8 +722,10 @@ nd6_na_input(m, off, icmp6len)
                         * If state is REACHABLE, make it STALE.
                         * no other updates should be done.
                         */
-                       if (ln->ln_state == ND6_LLINFO_REACHABLE)
+                       if (ln->ln_state == ND6_LLINFO_REACHABLE) {
                                ln->ln_state = ND6_LLINFO_STALE;
+                               ln->ln_expire = time_second + nd6_gctimer;
+                       }
                        goto freeit;
                } else if (is_override                             /* (2a) */
                        || (!is_override && (lladdr && !llchange)) /* (2b) */
@@ -729,17 +745,16 @@ nd6_na_input(m, off, icmp6len)
                         */
                        if (is_solicited) {
                                ln->ln_state = ND6_LLINFO_REACHABLE;
+                               ln->ln_byhint = 0;
                                if (ln->ln_expire) {
-#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__)
-                                       ln->ln_expire = time.tv_sec +
-#else
                                        ln->ln_expire = time_second +
-#endif
-                                               nd_ifinfo[ifp->if_index].reachable;
+                                           nd_ifinfo[ifp->if_index].reachable;
                                }
                        } else {
-                               if (lladdr && llchange)
+                               if (lladdr && llchange) {
                                        ln->ln_state = ND6_LLINFO_STALE;
+                                       ln->ln_expire = time_second + nd6_gctimer;
+                               }
                        }
                }
 
@@ -754,11 +769,7 @@ nd6_na_input(m, off, icmp6len)
                        int s;
 
                        in6 = &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
-#if __NetBSD__
-                       s = splsoftnet();
-#else
                        s = splnet();
-#endif
                        dr = defrouter_lookup(in6, rt->rt_ifp);
                        if (dr)
                                defrtrlist_del(dr);
@@ -779,17 +790,22 @@ nd6_na_input(m, off, icmp6len)
        rt->rt_flags &= ~RTF_REJECT;
        ln->ln_asked = 0;
        if (ln->ln_hold) {
-#if OLDIP6OUTPUT
-               (*ifp->if_output)(ifp, ln->ln_hold, rt_key(rt), rt);
-#else
-               nd6_output(ifp, ln->ln_hold,
+               /*
+                * we assume ifp is not a p2p here, so just set the 2nd
+                * argument as the 1st one.
+                */
+               nd6_output(ifp, ifp, ln->ln_hold,
                           (struct sockaddr_in6 *)rt_key(rt), rt);
-#endif
                ln->ln_hold = 0;
        }
 
  freeit:
        m_freem(m);
+       return;
+
+ bad:
+       icmp6stat.icp6s_badna++;
+       m_freem(m);
 }
 
 /*
@@ -804,7 +820,7 @@ nd6_na_input(m, off, icmp6len)
 void
 nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
        struct ifnet *ifp;
-       struct in6_addr *daddr6, *taddr6;
+       const struct in6_addr *daddr6, *taddr6;
        u_long flags;
        int tlladdr;            /* 1 if include target link-layer address */
        struct sockaddr *sdl0;  /* sockaddr_dl (= proxy NA) or NULL */
@@ -823,7 +839,7 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
        maxlen = sizeof(*ip6) + sizeof(*nd_na);
        maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
        if (max_linkhdr + maxlen >= MCLBYTES) {
-#ifdef DIAGNOSTIC
+#if DIAGNOSTIC
                printf("nd6_na_output: max_linkhdr + maxlen >= MCLBYTES "
                    "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
 #endif
@@ -840,6 +856,7 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
        }
        if (m == NULL)
                return;
+       m->m_pkthdr.rcvif = NULL;
 
        if (IN6_IS_ADDR_MULTICAST(daddr6)) {
                m->m_flags |= M_MCAST;
@@ -933,7 +950,8 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
 
 #if IPSEC
        /* Don't lookup socket */
-       ipsec_setsocket(m, NULL);
+       if (ipsec_bypass == 0)
+               (void)ipsec_setsocket(m, NULL);
 #endif
        ip6_output(m, NULL, NULL, 0, &im6o, &outif);
        if (outif) {
@@ -951,11 +969,14 @@ nd6_ifptomac(ifp)
        case IFT_ARCNET:
        case IFT_ETHER:
        case IFT_FDDI:
-#if __NetBSD__
-               return LLADDR(ifp->if_sadl);
-#else
-               return ((caddr_t)(ifp + 1));
+       case IFT_IEEE1394:
+#if IFT_L2VLAN
+       case IFT_L2VLAN:
 #endif
+#if IFT_IEEE80211
+       case IFT_IEEE80211:
+#endif
+               return ((caddr_t)(ifp + 1));
                break;
        default:
                return NULL;
@@ -977,6 +998,7 @@ struct dadq {
 };
 
 static struct dadq_head dadq;
+static int dad_init = 0;
 
 static struct dadq *
 nd6_dad_find(ifa)
@@ -991,6 +1013,33 @@ nd6_dad_find(ifa)
        return NULL;
 }
 
+#ifdef  __APPLE__
+void
+nd6_dad_stoptimer(ifa)
+       struct ifaddr *ifa;
+{
+
+       untimeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa);
+}
+#else
+static void
+nd6_dad_starttimer(dp, ticks)
+       struct dadq *dp;
+       int ticks;
+{
+
+       callout_reset(&dp->dad_timer_ch, ticks,
+           (void (*) __P((void *)))nd6_dad_timer, (void *)dp->dad_ifa);
+}
+static void
+nd6_dad_stoptimer(dp)
+       struct dadq *dp;
+{
+
+       callout_stop(&dp->dad_timer_ch);
+}
+#endif
+
 /*
  * Start Duplicated Address Detection (DAD) for specified interface address.
  */
@@ -1001,7 +1050,6 @@ nd6_dad_start(ifa, tick)
 {
        struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
        struct dadq *dp;
-       static int dad_init = 0;
 
        if (!dad_init) {
                TAILQ_INIT(&dadq);
@@ -1048,12 +1096,13 @@ nd6_dad_start(ifa, tick)
                return;
        }
        bzero(dp, sizeof(*dp));
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+       callout_init(&dp->dad_timer_ch);
+#endif
        TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list);
 
-#if ND6_DEBUG
-       log(LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
-           ip6_sprintf(&ia->ia_addr.sin6_addr));
-#endif
+       nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
+           ip6_sprintf(&ia->ia_addr.sin6_addr)));
 
        /*
         * Send NS packet for DAD, ip6_dad_count times.
@@ -1062,7 +1111,7 @@ nd6_dad_start(ifa, tick)
         * (re)initialization.
         */
        dp->dad_ifa = ifa;
-       ifa->ifa_refcnt++;      /*just for safety*/
+       ifaref(ifa);    /*just for safety*/
        dp->dad_count = ip6_dad_count;
        dp->dad_ns_icount = dp->dad_na_icount = 0;
        dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
@@ -1071,7 +1120,7 @@ nd6_dad_start(ifa, tick)
 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
                dp->dad_timer =
 #endif
-               timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa,
+               timeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa,
                        nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
        } else {
                int ntick;
@@ -1084,11 +1133,53 @@ nd6_dad_start(ifa, tick)
 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
                dp->dad_timer =
 #endif
-               timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa,
+               timeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa,
                        ntick);
        }
 }
 
+/*
+ * terminate DAD unconditionally.  used for address removals.
+ */
+void
+nd6_dad_stop(ifa)
+       struct ifaddr *ifa;
+{
+       struct dadq *dp;
+
+       if (!dad_init)
+               return;
+       dp = nd6_dad_find(ifa);
+       if (!dp) {
+               /* DAD wasn't started yet */
+               return;
+       }
+
+       untimeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa);
+
+       TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
+       FREE(dp, M_IP6NDP);
+       dp = NULL;
+       ifafree(ifa);
+}
+
+
+static void     
+nd6_dad_timer_funnel(ifa)
+       struct ifaddr *ifa;
+{
+                
+#ifdef __APPLE__
+        boolean_t       funnel_state;
+        funnel_state = thread_funnel_set(network_flock, TRUE);
+#endif 
+       nd6_dad_timer(ifa);
+#ifdef __APPLE__
+        (void) thread_funnel_set(network_flock, FALSE);
+#endif
+
+} 
+
 static void
 nd6_dad_timer(ifa)
        struct ifaddr *ifa;
@@ -1097,15 +1188,7 @@ nd6_dad_timer(ifa)
        struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
        struct dadq *dp;
 
-#ifdef __APPLE__
-       boolean_t   funnel_state;
-       funnel_state = thread_set_funneled(TRUE);
-#endif
-#if __NetBSD__
-       s = splsoftnet();       /*XXX*/
-#else
        s = splnet();           /*XXX*/
-#endif
 
        /* Sanity check */
        if (ia == NULL) {
@@ -1134,13 +1217,13 @@ nd6_dad_timer(ifa)
 
        /* timeouted with IFF_{RUNNING,UP} check */
        if (dp->dad_ns_tcount > dad_maxtry) {
-               log(LOG_ERR, "%s: could not run DAD, driver problem?\n",
-                   if_name(ifa->ifa_ifp));
+               nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n",
+                       if_name(ifa->ifa_ifp)));
 
                TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
-               _FREE(dp, M_IP6NDP);
+               FREE(dp, M_IP6NDP);
                dp = NULL;
-               IFAFREE(ifa);
+               ifafree(ifa);
                goto done;
        }
 
@@ -1153,7 +1236,7 @@ nd6_dad_timer(ifa)
 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
                dp->dad_timer =
 #endif
-               timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa,
+               timeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa,
                        nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
        } else {
                /*
@@ -1213,25 +1296,20 @@ nd6_dad_timer(ifa)
                         */
                        ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
 
-#if ND6_DEBUG
-                       log(LOG_INFO,
+                       nd6log((LOG_DEBUG,
                            "%s: DAD complete for %s - no duplicates found\n",
                            if_name(ifa->ifa_ifp),
-                           ip6_sprintf(&ia->ia_addr.sin6_addr));
-#endif
+                           ip6_sprintf(&ia->ia_addr.sin6_addr)));
 
                        TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
-                       _FREE(dp, M_IP6NDP);
+                       FREE(dp, M_IP6NDP);
                        dp = NULL;
-                       IFAFREE(ifa);
+                       ifafree(ifa);
                }
        }
 
 done:
        splx(s);
-#ifdef __APPLE__
-       (void) thread_set_funneled(funnel_state);
-#endif
 }
 
 void
@@ -1247,20 +1325,17 @@ nd6_dad_duplicated(ifa)
                return;
        }
 
-       log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: %d NS, "
-           "%d NA\n", if_name(ifa->ifa_ifp),
-           ip6_sprintf(&ia->ia_addr.sin6_addr),
-           dp->dad_ns_icount, dp->dad_na_icount);
+       log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "
+           "NS in/out=%d/%d, NA in=%d\n",
+           if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr),
+           dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_na_icount);
 
        ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
        ia->ia6_flags |= IN6_IFF_DUPLICATED;
 
        /* We are done with DAD, with duplicated address found. (failure) */
-       untimeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
-               , dp->dad_timer
-#endif
-               );
+       untimeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa);
+
 
        log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
            if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));
@@ -1268,9 +1343,9 @@ nd6_dad_duplicated(ifa)
            if_name(ifa->ifa_ifp));
 
        TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
-       _FREE(dp, M_IP6NDP);
+       FREE(dp, M_IP6NDP);
        dp = NULL;
-       IFAFREE(ifa);
+       ifafree(ifa);
 }
 
 static void
@@ -1305,7 +1380,7 @@ nd6_dad_ns_input(ifa)
 {
        struct in6_ifaddr *ia;
        struct ifnet *ifp;
-       struct in6_addr *taddr6;
+       const struct in6_addr *taddr6;
        struct dadq *dp;
        int duplicate;
 
@@ -1318,17 +1393,12 @@ nd6_dad_ns_input(ifa)
        duplicate = 0;
        dp = nd6_dad_find(ifa);
 
-       /*
-        * If it is from myself, ignore this.
-        */
-       if (ifp && (ifp->if_flags & IFF_LOOPBACK))
-               return;
-
        /* Quickhack - completely ignore DAD NS packets */
        if (dad_ignore_ns) {
-               log(LOG_INFO, "nd6_dad_ns_input: ignoring DAD NS packet for "
+               nd6log((LOG_INFO,
+                   "nd6_dad_ns_input: ignoring DAD NS packet for "
                    "address %s(%s)\n", ip6_sprintf(taddr6),
-                   if_name(ifa->ifa_ifp));
+                   if_name(ifa->ifa_ifp)));
                return;
        }