The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet6/nd6_nbr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $FreeBSD: releng/5.2/sys/netinet6/nd6_nbr.c 122062 2003-11-04 16:02:05Z ume $   */
    2 /*      $KAME: nd6_nbr.c,v 1.86 2002/01/21 02:33:04 jinmei Exp $        */
    3 
    4 /*
    5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include "opt_inet.h"
   34 #include "opt_inet6.h"
   35 #include "opt_ipsec.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/socket.h>
   42 #include <sys/sockio.h>
   43 #include <sys/time.h>
   44 #include <sys/kernel.h>
   45 #include <sys/errno.h>
   46 #include <sys/syslog.h>
   47 #include <sys/queue.h>
   48 #include <sys/callout.h>
   49 
   50 #include <net/if.h>
   51 #include <net/if_types.h>
   52 #include <net/if_dl.h>
   53 #include <net/route.h>
   54 
   55 #include <netinet/in.h>
   56 #include <netinet/in_var.h>
   57 #include <netinet6/in6_var.h>
   58 #include <netinet/ip6.h>
   59 #include <netinet6/ip6_var.h>
   60 #include <netinet6/nd6.h>
   61 #include <netinet/icmp6.h>
   62 
   63 #ifdef IPSEC
   64 #include <netinet6/ipsec.h>
   65 #ifdef INET6
   66 #include <netinet6/ipsec6.h>
   67 #endif
   68 #endif
   69 
   70 #include <net/net_osdep.h>
   71 
   72 #define SDL(s) ((struct sockaddr_dl *)s)
   73 
   74 struct dadq;
   75 static struct dadq *nd6_dad_find __P((struct ifaddr *));
   76 static void nd6_dad_starttimer __P((struct dadq *, int));
   77 static void nd6_dad_stoptimer __P((struct dadq *));
   78 static void nd6_dad_timer __P((struct ifaddr *));
   79 static void nd6_dad_ns_output __P((struct dadq *, struct ifaddr *));
   80 static void nd6_dad_ns_input __P((struct ifaddr *));
   81 static void nd6_dad_na_input __P((struct ifaddr *));
   82 
   83 static int dad_ignore_ns = 0;   /* ignore NS in DAD - specwise incorrect*/
   84 static int dad_maxtry = 15;     /* max # of *tries* to transmit DAD packet */
   85 
   86 /*
   87  * Input a Neighbor Solicitation Message.
   88  *
   89  * Based on RFC 2461
   90  * Based on RFC 2462 (duplicated address detection)
   91  */
   92 void
   93 nd6_ns_input(m, off, icmp6len)
   94         struct mbuf *m;
   95         int off, icmp6len;
   96 {
   97         struct ifnet *ifp = m->m_pkthdr.rcvif;
   98         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
   99         struct nd_neighbor_solicit *nd_ns;
  100         struct in6_addr saddr6 = ip6->ip6_src;
  101         struct in6_addr daddr6 = ip6->ip6_dst;
  102         struct in6_addr taddr6;
  103         struct in6_addr myaddr6;
  104         char *lladdr = NULL;
  105         struct ifaddr *ifa;
  106         int lladdrlen = 0;
  107         int anycast = 0, proxy = 0, tentative = 0;
  108         int tlladdr;
  109         union nd_opts ndopts;
  110         struct sockaddr_dl *proxydl = NULL;
  111 
  112 #ifndef PULLDOWN_TEST
  113         IP6_EXTHDR_CHECK(m, off, icmp6len,);
  114         nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
  115 #else
  116         IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
  117         if (nd_ns == NULL) {
  118                 icmp6stat.icp6s_tooshort++;
  119                 return;
  120         }
  121 #endif
  122         ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
  123         taddr6 = nd_ns->nd_ns_target;
  124 
  125         if (ip6->ip6_hlim != 255) {
  126                 nd6log((LOG_ERR,
  127                     "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n",
  128                     ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
  129                     ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
  130                 goto bad;
  131         }
  132 
  133         if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
  134                 /* dst has to be solicited node multicast address. */
  135                 if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL &&
  136                     /* don't check ifindex portion */
  137                     daddr6.s6_addr32[1] == 0 &&
  138                     daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE &&
  139                     daddr6.s6_addr8[12] == 0xff) {
  140                         ; /* good */
  141                 } else {
  142                         nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
  143                             "(wrong ip6 dst)\n"));
  144                         goto bad;
  145                 }
  146         }
  147 
  148         if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
  149                 nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"));
  150                 goto bad;
  151         }
  152 
  153         if (IN6_IS_SCOPE_LINKLOCAL(&taddr6))
  154                 taddr6.s6_addr16[1] = htons(ifp->if_index);
  155 
  156         icmp6len -= sizeof(*nd_ns);
  157         nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
  158         if (nd6_options(&ndopts) < 0) {
  159                 nd6log((LOG_INFO,
  160                     "nd6_ns_input: invalid ND option, ignored\n"));
  161                 /* nd6_options have incremented stats */
  162                 goto freeit;
  163         }
  164 
  165         if (ndopts.nd_opts_src_lladdr) {
  166                 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
  167                 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
  168         }
  169 
  170         if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) {
  171                 nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
  172                     "(link-layer address option)\n"));
  173                 goto bad;
  174         }
  175 
  176         /*
  177          * Attaching target link-layer address to the NA?
  178          * (RFC 2461 7.2.4)
  179          *
  180          * NS IP dst is unicast/anycast                 MUST NOT add
  181          * NS IP dst is solicited-node multicast        MUST add
  182          *
  183          * In implementation, we add target link-layer address by default.
  184          * We do not add one in MUST NOT cases.
  185          */
  186 #if 0 /* too much! */
  187         ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &daddr6);
  188         if (ifa && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST))
  189                 tlladdr = 0;
  190         else
  191 #endif
  192         if (!IN6_IS_ADDR_MULTICAST(&daddr6))
  193                 tlladdr = 0;
  194         else
  195                 tlladdr = 1;
  196 
  197         /*
  198          * Target address (taddr6) must be either:
  199          * (1) Valid unicast/anycast address for my receiving interface,
  200          * (2) Unicast address for which I'm offering proxy service, or
  201          * (3) "tentative" address on which DAD is being performed.
  202          */
  203         /* (1) and (3) check. */
  204         ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
  205 
  206         /* (2) check. */
  207         if (!ifa) {
  208                 struct rtentry *rt;
  209                 struct sockaddr_in6 tsin6;
  210                 int need_proxy;
  211 
  212                 bzero(&tsin6, sizeof tsin6);            
  213                 tsin6.sin6_len = sizeof(struct sockaddr_in6);
  214                 tsin6.sin6_family = AF_INET6;
  215                 tsin6.sin6_addr = taddr6;
  216 
  217                 rt = rtalloc1((struct sockaddr *)&tsin6, 0, 0);
  218                 need_proxy = (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
  219                     rt->rt_gateway->sa_family == AF_LINK);
  220                 if (rt)
  221                         rtfree(rt);
  222                 if (need_proxy) {
  223                         /*
  224                          * proxy NDP for single entry
  225                          */
  226                         ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
  227                                 IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
  228                         if (ifa) {
  229                                 proxy = 1;
  230                                 proxydl = SDL(rt->rt_gateway);
  231                         }
  232                 }
  233         }
  234         if (!ifa) {
  235                 /*
  236                  * We've got an NS packet, and we don't have that adddress
  237                  * assigned for us.  We MUST silently ignore it.
  238                  * See RFC2461 7.2.3.
  239                  */
  240                 goto freeit;
  241         }
  242         myaddr6 = *IFA_IN6(ifa);
  243         anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
  244         tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE;
  245         if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
  246                 goto freeit;
  247 
  248         if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
  249                 nd6log((LOG_INFO, "nd6_ns_input: lladdrlen mismatch for %s "
  250                     "(if %d, NS packet %d)\n",
  251                     ip6_sprintf(&taddr6),
  252                     ifp->if_addrlen, lladdrlen - 2));
  253                 goto bad;
  254         }
  255 
  256         if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
  257                 nd6log((LOG_INFO, "nd6_ns_input: duplicate IP6 address %s\n",
  258                     ip6_sprintf(&saddr6)));
  259                 goto freeit;
  260         }
  261 
  262         /*
  263          * We have neighbor solicitation packet, with target address equals to
  264          * one of my tentative address.
  265          *
  266          * src addr     how to process?
  267          * ---          ---
  268          * multicast    of course, invalid (rejected in ip6_input)
  269          * unicast      somebody is doing address resolution -> ignore
  270          * unspec       dup address detection
  271          *
  272          * The processing is defined in RFC 2462.
  273          */
  274         if (tentative) {
  275                 /*
  276                  * If source address is unspecified address, it is for
  277                  * duplicated address detection.
  278                  *
  279                  * If not, the packet is for addess resolution;
  280                  * silently ignore it.
  281                  */
  282                 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
  283                         nd6_dad_ns_input(ifa);
  284 
  285                 goto freeit;
  286         }
  287 
  288         /*
  289          * If the source address is unspecified address, entries must not
  290          * be created or updated.
  291          * It looks that sender is performing DAD.  Output NA toward
  292          * all-node multicast address, to tell the sender that I'm using
  293          * the address.
  294          * S bit ("solicited") must be zero.
  295          */
  296         if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
  297                 saddr6 = in6addr_linklocal_allnodes;
  298                 saddr6.s6_addr16[1] = htons(ifp->if_index);
  299                 nd6_na_output(ifp, &saddr6, &taddr6,
  300                     ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
  301                     (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0),
  302                     tlladdr, (struct sockaddr *)proxydl);
  303                 goto freeit;
  304         }
  305 
  306         nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen,
  307             ND_NEIGHBOR_SOLICIT, 0);
  308 
  309         nd6_na_output(ifp, &saddr6, &taddr6,
  310             ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
  311             (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
  312             tlladdr, (struct sockaddr *)proxydl);
  313  freeit:
  314         m_freem(m);
  315         return;
  316 
  317  bad:
  318         nd6log((LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(&saddr6)));
  319         nd6log((LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(&daddr6)));
  320         nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(&taddr6)));
  321         icmp6stat.icp6s_badns++;
  322         m_freem(m);
  323 }
  324 
  325 /*
  326  * Output a Neighbor Solicitation Message. Caller specifies:
  327  *      - ICMP6 header source IP6 address
  328  *      - ND6 header target IP6 address
  329  *      - ND6 header source datalink address
  330  *
  331  * Based on RFC 2461
  332  * Based on RFC 2462 (duplicated address detection)
  333  */
  334 void
  335 nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
  336         struct ifnet *ifp;
  337         const struct in6_addr *daddr6, *taddr6;
  338         struct llinfo_nd6 *ln;  /* for source address determination */
  339         int dad;        /* duplicated address detection */
  340 {
  341         struct mbuf *m;
  342         struct ip6_hdr *ip6;
  343         struct nd_neighbor_solicit *nd_ns;
  344         struct in6_ifaddr *ia = NULL;
  345         struct ip6_moptions im6o;
  346         int icmp6len;
  347         int maxlen;
  348         caddr_t mac;
  349         struct ifnet *outif = NULL;
  350 
  351         if (IN6_IS_ADDR_MULTICAST(taddr6))
  352                 return;
  353 
  354         /* estimate the size of message */
  355         maxlen = sizeof(*ip6) + sizeof(*nd_ns);
  356         maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
  357         if (max_linkhdr + maxlen >= MCLBYTES) {
  358 #ifdef DIAGNOSTIC
  359                 printf("nd6_ns_output: max_linkhdr + maxlen >= MCLBYTES "
  360                     "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
  361 #endif
  362                 return;
  363         }
  364 
  365         MGETHDR(m, M_DONTWAIT, MT_DATA);
  366         if (m && max_linkhdr + maxlen >= MHLEN) {
  367                 MCLGET(m, M_DONTWAIT);
  368                 if ((m->m_flags & M_EXT) == 0) {
  369                         m_free(m);
  370                         m = NULL;
  371                 }
  372         }
  373         if (m == NULL)
  374                 return;
  375         m->m_pkthdr.rcvif = NULL;
  376 
  377         if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
  378                 m->m_flags |= M_MCAST;
  379                 im6o.im6o_multicast_ifp = ifp;
  380                 im6o.im6o_multicast_hlim = 255;
  381                 im6o.im6o_multicast_loop = 0;
  382         }
  383 
  384         icmp6len = sizeof(*nd_ns);
  385         m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len;
  386         m->m_data += max_linkhdr;       /* or MH_ALIGN() equivalent? */
  387 
  388         /* fill neighbor solicitation packet */
  389         ip6 = mtod(m, struct ip6_hdr *);
  390         ip6->ip6_flow = 0;
  391         ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
  392         ip6->ip6_vfc |= IPV6_VERSION;
  393         /* ip6->ip6_plen will be set later */
  394         ip6->ip6_nxt = IPPROTO_ICMPV6;
  395         ip6->ip6_hlim = 255;
  396         if (daddr6)
  397                 ip6->ip6_dst = *daddr6;
  398         else {
  399                 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
  400                 ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index);
  401                 ip6->ip6_dst.s6_addr32[1] = 0;
  402                 ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
  403                 ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3];
  404                 ip6->ip6_dst.s6_addr8[12] = 0xff;
  405         }
  406         if (!dad) {
  407                 /*
  408                  * RFC2461 7.2.2:
  409                  * "If the source address of the packet prompting the
  410                  * solicitation is the same as one of the addresses assigned
  411                  * to the outgoing interface, that address SHOULD be placed
  412                  * in the IP Source Address of the outgoing solicitation.
  413                  * Otherwise, any one of the addresses assigned to the
  414                  * interface should be used."
  415                  *
  416                  * We use the source address for the prompting packet
  417                  * (saddr6), if:
  418                  * - saddr6 is given from the caller (by giving "ln"), and
  419                  * - saddr6 belongs to the outgoing interface.
  420                  * Otherwise, we perform a scope-wise match.
  421                  */
  422                 struct ip6_hdr *hip6;           /* hold ip6 */
  423                 struct in6_addr *saddr6;
  424 
  425                 if (ln && ln->ln_hold) {
  426                         hip6 = mtod(ln->ln_hold, struct ip6_hdr *);
  427                         /* XXX pullup? */
  428                         if (sizeof(*hip6) < ln->ln_hold->m_len)
  429                                 saddr6 = &hip6->ip6_src;
  430                         else
  431                                 saddr6 = NULL;
  432                 } else
  433                         saddr6 = NULL;
  434                 if (saddr6 && in6ifa_ifpwithaddr(ifp, saddr6))
  435                         bcopy(saddr6, &ip6->ip6_src, sizeof(*saddr6));
  436                 else {
  437                         ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
  438                         if (ia == NULL) {
  439                                 m_freem(m);
  440                                 return;
  441                         }
  442                         ip6->ip6_src = ia->ia_addr.sin6_addr;
  443                 }
  444         } else {
  445                 /*
  446                  * Source address for DAD packet must always be IPv6
  447                  * unspecified address. (0::0)
  448                  */
  449                 bzero(&ip6->ip6_src, sizeof(ip6->ip6_src));
  450         }
  451         nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1);
  452         nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
  453         nd_ns->nd_ns_code = 0;
  454         nd_ns->nd_ns_reserved = 0;
  455         nd_ns->nd_ns_target = *taddr6;
  456         in6_clearscope(&nd_ns->nd_ns_target); /* XXX */
  457 
  458         /*
  459          * Add source link-layer address option.
  460          *
  461          *                              spec            implementation
  462          *                              ---             ---
  463          * DAD packet                   MUST NOT        do not add the option
  464          * there's no link layer address:
  465          *                              impossible      do not add the option
  466          * there's link layer address:
  467          *      Multicast NS            MUST add one    add the option
  468          *      Unicast NS              SHOULD add one  add the option
  469          */
  470         if (!dad && (mac = nd6_ifptomac(ifp))) {
  471                 int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
  472                 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
  473                 /* 8 byte alignments... */
  474                 optlen = (optlen + 7) & ~7;
  475 
  476                 m->m_pkthdr.len += optlen;
  477                 m->m_len += optlen;
  478                 icmp6len += optlen;
  479                 bzero((caddr_t)nd_opt, optlen);
  480                 nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
  481                 nd_opt->nd_opt_len = optlen >> 3;
  482                 bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
  483         }
  484 
  485         ip6->ip6_plen = htons((u_short)icmp6len);
  486         nd_ns->nd_ns_cksum = 0;
  487         nd_ns->nd_ns_cksum =
  488             in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
  489 
  490 #ifdef IPSEC
  491         /* Don't lookup socket */
  492         (void)ipsec_setsocket(m, NULL);
  493 #endif
  494         ip6_output(m, NULL, NULL, dad ? IPV6_DADOUTPUT : 0, &im6o, &outif, NULL);
  495         if (outif) {
  496                 icmp6_ifstat_inc(outif, ifs6_out_msg);
  497                 icmp6_ifstat_inc(outif, ifs6_out_neighborsolicit);
  498         }
  499         icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++;
  500 }
  501 
  502 /*
  503  * Neighbor advertisement input handling.
  504  *
  505  * Based on RFC 2461
  506  * Based on RFC 2462 (duplicated address detection)
  507  *
  508  * the following items are not implemented yet:
  509  * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
  510  * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
  511  */
  512 void
  513 nd6_na_input(m, off, icmp6len)
  514         struct mbuf *m;
  515         int off, icmp6len;
  516 {
  517         struct ifnet *ifp = m->m_pkthdr.rcvif;
  518         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
  519         struct nd_neighbor_advert *nd_na;
  520         struct in6_addr daddr6 = ip6->ip6_dst;
  521         struct in6_addr taddr6;
  522         int flags;
  523         int is_router;
  524         int is_solicited;
  525         int is_override;
  526         char *lladdr = NULL;
  527         int lladdrlen = 0;
  528         struct ifaddr *ifa;
  529         struct llinfo_nd6 *ln;
  530         struct rtentry *rt;
  531         struct sockaddr_dl *sdl;
  532         union nd_opts ndopts;
  533 
  534         if (ip6->ip6_hlim != 255) {
  535                 nd6log((LOG_ERR,
  536                     "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n",
  537                     ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
  538                     ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
  539                 goto bad;
  540         }
  541 
  542 #ifndef PULLDOWN_TEST
  543         IP6_EXTHDR_CHECK(m, off, icmp6len,);
  544         nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
  545 #else
  546         IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len);
  547         if (nd_na == NULL) {
  548                 icmp6stat.icp6s_tooshort++;
  549                 return;
  550         }
  551 #endif
  552         taddr6 = nd_na->nd_na_target;
  553         flags = nd_na->nd_na_flags_reserved;
  554         is_router = ((flags & ND_NA_FLAG_ROUTER) != 0);
  555         is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0);
  556         is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
  557 
  558         if (IN6_IS_SCOPE_LINKLOCAL(&taddr6))
  559                 taddr6.s6_addr16[1] = htons(ifp->if_index);
  560 
  561         if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
  562                 nd6log((LOG_ERR,
  563                     "nd6_na_input: invalid target address %s\n",
  564                     ip6_sprintf(&taddr6)));
  565                 goto bad;
  566         }
  567         if (IN6_IS_ADDR_MULTICAST(&daddr6))
  568                 if (is_solicited) {
  569                         nd6log((LOG_ERR,
  570                             "nd6_na_input: a solicited adv is multicasted\n"));
  571                         goto bad;
  572                 }
  573 
  574         icmp6len -= sizeof(*nd_na);
  575         nd6_option_init(nd_na + 1, icmp6len, &ndopts);
  576         if (nd6_options(&ndopts) < 0) {
  577                 nd6log((LOG_INFO,
  578                     "nd6_na_input: invalid ND option, ignored\n"));
  579                 /* nd6_options have incremented stats */
  580                 goto freeit;
  581         }
  582 
  583         if (ndopts.nd_opts_tgt_lladdr) {
  584                 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
  585                 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
  586         }
  587 
  588         ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
  589 
  590         /*
  591          * Target address matches one of my interface address.
  592          *
  593          * If my address is tentative, this means that there's somebody
  594          * already using the same address as mine.  This indicates DAD failure.
  595          * This is defined in RFC 2462.
  596          *
  597          * Otherwise, process as defined in RFC 2461.
  598          */
  599         if (ifa
  600          && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
  601                 nd6_dad_na_input(ifa);
  602                 goto freeit;
  603         }
  604 
  605         /* Just for safety, maybe unnecessary. */
  606         if (ifa) {
  607                 log(LOG_ERR,
  608                     "nd6_na_input: duplicate IP6 address %s\n",
  609                     ip6_sprintf(&taddr6));
  610                 goto freeit;
  611         }
  612 
  613         if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
  614                 nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s "
  615                     "(if %d, NA packet %d)\n", ip6_sprintf(&taddr6),
  616                     ifp->if_addrlen, lladdrlen - 2));
  617                 goto bad;
  618         }
  619 
  620         /*
  621          * If no neighbor cache entry is found, NA SHOULD silently be
  622          * discarded.
  623          */
  624         rt = nd6_lookup(&taddr6, 0, ifp);
  625         if ((rt == NULL) ||
  626            ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) ||
  627            ((sdl = SDL(rt->rt_gateway)) == NULL))
  628                 goto freeit;
  629 
  630         if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
  631                 /*
  632                  * If the link-layer has address, and no lladdr option came,
  633                  * discard the packet.
  634                  */
  635                 if (ifp->if_addrlen && !lladdr)
  636                         goto freeit;
  637 
  638                 /*
  639                  * Record link-layer address, and update the state.
  640                  */
  641                 sdl->sdl_alen = ifp->if_addrlen;
  642                 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
  643                 if (is_solicited) {
  644                         ln->ln_state = ND6_LLINFO_REACHABLE;
  645                         ln->ln_byhint = 0;
  646                         if (ln->ln_expire) {
  647                                 ln->ln_expire = time_second +
  648                                     ND_IFINFO(rt->rt_ifp)->reachable;
  649                         }
  650                 } else {
  651                         ln->ln_state = ND6_LLINFO_STALE;
  652                         ln->ln_expire = time_second + nd6_gctimer;
  653                 }
  654                 if ((ln->ln_router = is_router) != 0) {
  655                         /*
  656                          * This means a router's state has changed from
  657                          * non-reachable to probably reachable, and might
  658                          * affect the status of associated prefixes..
  659                          */
  660                         pfxlist_onlink_check();
  661                 }
  662         } else {
  663                 int llchange;
  664 
  665                 /*
  666                  * Check if the link-layer address has changed or not.
  667                  */
  668                 if (!lladdr)
  669                         llchange = 0;
  670                 else {
  671                         if (sdl->sdl_alen) {
  672                                 if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
  673                                         llchange = 1;
  674                                 else
  675                                         llchange = 0;
  676                         } else
  677                                 llchange = 1;
  678                 }
  679 
  680                 /*
  681                  * This is VERY complex.  Look at it with care.
  682                  *
  683                  * override solicit lladdr llchange     action
  684                  *                                      (L: record lladdr)
  685                  *
  686                  *      0       0       n       --      (2c)
  687                  *      0       0       y       n       (2b) L
  688                  *      0       0       y       y       (1)    REACHABLE->STALE
  689                  *      0       1       n       --      (2c)   *->REACHABLE
  690                  *      0       1       y       n       (2b) L *->REACHABLE
  691                  *      0       1       y       y       (1)    REACHABLE->STALE
  692                  *      1       0       n       --      (2a)
  693                  *      1       0       y       n       (2a) L
  694                  *      1       0       y       y       (2a) L *->STALE
  695                  *      1       1       n       --      (2a)   *->REACHABLE
  696                  *      1       1       y       n       (2a) L *->REACHABLE
  697                  *      1       1       y       y       (2a) L *->REACHABLE
  698                  */
  699                 if (!is_override && (lladdr && llchange)) {        /* (1) */
  700                         /*
  701                          * If state is REACHABLE, make it STALE.
  702                          * no other updates should be done.
  703                          */
  704                         if (ln->ln_state == ND6_LLINFO_REACHABLE) {
  705                                 ln->ln_state = ND6_LLINFO_STALE;
  706                                 ln->ln_expire = time_second + nd6_gctimer;
  707                         }
  708                         goto freeit;
  709                 } else if (is_override                             /* (2a) */
  710                         || (!is_override && (lladdr && !llchange)) /* (2b) */
  711                         || !lladdr) {                              /* (2c) */
  712                         /*
  713                          * Update link-local address, if any.
  714                          */
  715                         if (lladdr) {
  716                                 sdl->sdl_alen = ifp->if_addrlen;
  717                                 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
  718                         }
  719 
  720                         /*
  721                          * If solicited, make the state REACHABLE.
  722                          * If not solicited and the link-layer address was
  723                          * changed, make it STALE.
  724                          */
  725                         if (is_solicited) {
  726                                 ln->ln_state = ND6_LLINFO_REACHABLE;
  727                                 ln->ln_byhint = 0;
  728                                 if (ln->ln_expire) {
  729                                         ln->ln_expire = time_second +
  730                                             ND_IFINFO(ifp)->reachable;
  731                                 }
  732                         } else {
  733                                 if (lladdr && llchange) {
  734                                         ln->ln_state = ND6_LLINFO_STALE;
  735                                         ln->ln_expire = time_second + nd6_gctimer;
  736                                 }
  737                         }
  738                 }
  739 
  740                 if (ln->ln_router && !is_router) {
  741                         /*
  742                          * The peer dropped the router flag.
  743                          * Remove the sender from the Default Router List and
  744                          * update the Destination Cache entries.
  745                          */
  746                         struct nd_defrouter *dr;
  747                         struct in6_addr *in6;
  748                         int s;
  749 
  750                         in6 = &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
  751 
  752                         /*
  753                          * Lock to protect the default router list.
  754                          * XXX: this might be unnecessary, since this function
  755                          * is only called under the network software interrupt
  756                          * context.  However, we keep it just for safety.
  757                          */
  758                         s = splnet();
  759                         dr = defrouter_lookup(in6, rt->rt_ifp);
  760                         if (dr)
  761                                 defrtrlist_del(dr);
  762                         else if (!ip6_forwarding && ip6_accept_rtadv) {
  763                                 /*
  764                                  * Even if the neighbor is not in the default
  765                                  * router list, the neighbor may be used
  766                                  * as a next hop for some destinations
  767                                  * (e.g. redirect case). So we must
  768                                  * call rt6_flush explicitly.
  769                                  */
  770                                 rt6_flush(&ip6->ip6_src, rt->rt_ifp);
  771                         }
  772                         splx(s);
  773                 }
  774                 ln->ln_router = is_router;
  775         }
  776         rt->rt_flags &= ~RTF_REJECT;
  777         ln->ln_asked = 0;
  778         if (ln->ln_hold) {
  779                 /*
  780                  * we assume ifp is not a loopback here, so just set the 2nd
  781                  * argument as the 1st one.
  782                  */
  783                 nd6_output(ifp, ifp, ln->ln_hold,
  784                            (struct sockaddr_in6 *)rt_key(rt), rt);
  785                 ln->ln_hold = NULL;
  786         }
  787 
  788  freeit:
  789         m_freem(m);
  790         return;
  791 
  792  bad:
  793         icmp6stat.icp6s_badna++;
  794         m_freem(m);
  795 }
  796 
  797 /*
  798  * Neighbor advertisement output handling.
  799  *
  800  * Based on RFC 2461
  801  *
  802  * the following items are not implemented yet:
  803  * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
  804  * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
  805  */
  806 void
  807 nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
  808         struct ifnet *ifp;
  809         const struct in6_addr *daddr6, *taddr6;
  810         u_long flags;
  811         int tlladdr;            /* 1 if include target link-layer address */
  812         struct sockaddr *sdl0;  /* sockaddr_dl (= proxy NA) or NULL */
  813 {
  814         struct mbuf *m;
  815         struct ip6_hdr *ip6;
  816         struct nd_neighbor_advert *nd_na;
  817         struct in6_ifaddr *ia = NULL;
  818         struct ip6_moptions im6o;
  819         int icmp6len;
  820         int maxlen;
  821         caddr_t mac = NULL;
  822         struct ifnet *outif = NULL;
  823 
  824         /* estimate the size of message */
  825         maxlen = sizeof(*ip6) + sizeof(*nd_na);
  826         maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
  827         if (max_linkhdr + maxlen >= MCLBYTES) {
  828 #ifdef DIAGNOSTIC
  829                 printf("nd6_na_output: max_linkhdr + maxlen >= MCLBYTES "
  830                     "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
  831 #endif
  832                 return;
  833         }
  834 
  835         MGETHDR(m, M_DONTWAIT, MT_DATA);
  836         if (m && max_linkhdr + maxlen >= MHLEN) {
  837                 MCLGET(m, M_DONTWAIT);
  838                 if ((m->m_flags & M_EXT) == 0) {
  839                         m_free(m);
  840                         m = NULL;
  841                 }
  842         }
  843         if (m == NULL)
  844                 return;
  845         m->m_pkthdr.rcvif = NULL;
  846 
  847         if (IN6_IS_ADDR_MULTICAST(daddr6)) {
  848                 m->m_flags |= M_MCAST;
  849                 im6o.im6o_multicast_ifp = ifp;
  850                 im6o.im6o_multicast_hlim = 255;
  851                 im6o.im6o_multicast_loop = 0;
  852         }
  853 
  854         icmp6len = sizeof(*nd_na);
  855         m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len;
  856         m->m_data += max_linkhdr;       /* or MH_ALIGN() equivalent? */
  857 
  858         /* fill neighbor advertisement packet */
  859         ip6 = mtod(m, struct ip6_hdr *);
  860         ip6->ip6_flow = 0;
  861         ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
  862         ip6->ip6_vfc |= IPV6_VERSION;
  863         ip6->ip6_nxt = IPPROTO_ICMPV6;
  864         ip6->ip6_hlim = 255;
  865         if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) {
  866                 /* reply to DAD */
  867                 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
  868                 ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index);
  869                 ip6->ip6_dst.s6_addr32[1] = 0;
  870                 ip6->ip6_dst.s6_addr32[2] = 0;
  871                 ip6->ip6_dst.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
  872                 flags &= ~ND_NA_FLAG_SOLICITED;
  873         } else
  874                 ip6->ip6_dst = *daddr6;
  875 
  876         /*
  877          * Select a source whose scope is the same as that of the dest.
  878          */
  879         ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
  880         if (ia == NULL) {
  881                 m_freem(m);
  882                 return;
  883         }
  884         ip6->ip6_src = ia->ia_addr.sin6_addr;
  885         nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
  886         nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
  887         nd_na->nd_na_code = 0;
  888         nd_na->nd_na_target = *taddr6;
  889         in6_clearscope(&nd_na->nd_na_target); /* XXX */
  890 
  891         /*
  892          * "tlladdr" indicates NS's condition for adding tlladdr or not.
  893          * see nd6_ns_input() for details.
  894          * Basically, if NS packet is sent to unicast/anycast addr,
  895          * target lladdr option SHOULD NOT be included.
  896          */
  897         if (tlladdr) {
  898                 /*
  899                  * sdl0 != NULL indicates proxy NA.  If we do proxy, use
  900                  * lladdr in sdl0.  If we are not proxying (sending NA for
  901                  * my address) use lladdr configured for the interface.
  902                  */
  903                 if (sdl0 == NULL)
  904                         mac = nd6_ifptomac(ifp);
  905                 else if (sdl0->sa_family == AF_LINK) {
  906                         struct sockaddr_dl *sdl;
  907                         sdl = (struct sockaddr_dl *)sdl0;
  908                         if (sdl->sdl_alen == ifp->if_addrlen)
  909                                 mac = LLADDR(sdl);
  910                 }
  911         }
  912         if (tlladdr && mac) {
  913                 int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
  914                 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
  915 
  916                 /* roundup to 8 bytes alignment! */
  917                 optlen = (optlen + 7) & ~7;
  918 
  919                 m->m_pkthdr.len += optlen;
  920                 m->m_len += optlen;
  921                 icmp6len += optlen;
  922                 bzero((caddr_t)nd_opt, optlen);
  923                 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
  924                 nd_opt->nd_opt_len = optlen >> 3;
  925                 bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
  926         } else
  927                 flags &= ~ND_NA_FLAG_OVERRIDE;
  928 
  929         ip6->ip6_plen = htons((u_short)icmp6len);
  930         nd_na->nd_na_flags_reserved = flags;
  931         nd_na->nd_na_cksum = 0;
  932         nd_na->nd_na_cksum =
  933             in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
  934 
  935 #ifdef IPSEC
  936         /* Don't lookup socket */
  937         (void)ipsec_setsocket(m, NULL);
  938 #endif
  939         ip6_output(m, NULL, NULL, 0, &im6o, &outif, NULL);
  940         if (outif) {
  941                 icmp6_ifstat_inc(outif, ifs6_out_msg);
  942                 icmp6_ifstat_inc(outif, ifs6_out_neighboradvert);
  943         }
  944         icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++;
  945 }
  946 
  947 caddr_t
  948 nd6_ifptomac(ifp)
  949         struct ifnet *ifp;
  950 {
  951         switch (ifp->if_type) {
  952         case IFT_ARCNET:
  953         case IFT_ETHER:
  954         case IFT_FDDI:
  955         case IFT_IEEE1394:
  956 #ifdef IFT_L2VLAN
  957         case IFT_L2VLAN:
  958 #endif
  959 #ifdef IFT_IEEE80211
  960         case IFT_IEEE80211:
  961 #endif
  962         case IFT_ISO88025:
  963                 return ((caddr_t)(ifp + 1));
  964         default:
  965                 return NULL;
  966         }
  967 }
  968 
  969 TAILQ_HEAD(dadq_head, dadq);
  970 struct dadq {
  971         TAILQ_ENTRY(dadq) dad_list;
  972         struct ifaddr *dad_ifa;
  973         int dad_count;          /* max NS to send */
  974         int dad_ns_tcount;      /* # of trials to send NS */
  975         int dad_ns_ocount;      /* NS sent so far */
  976         int dad_ns_icount;
  977         int dad_na_icount;
  978         struct callout dad_timer_ch;
  979 };
  980 
  981 static struct dadq_head dadq;
  982 static int dad_init = 0;
  983 
  984 static struct dadq *
  985 nd6_dad_find(ifa)
  986         struct ifaddr *ifa;
  987 {
  988         struct dadq *dp;
  989 
  990         for (dp = dadq.tqh_first; dp; dp = dp->dad_list.tqe_next) {
  991                 if (dp->dad_ifa == ifa)
  992                         return dp;
  993         }
  994         return NULL;
  995 }
  996 
  997 static void
  998 nd6_dad_starttimer(dp, ticks)
  999         struct dadq *dp;
 1000         int ticks;
 1001 {
 1002 
 1003         callout_reset(&dp->dad_timer_ch, ticks,
 1004             (void (*) __P((void *)))nd6_dad_timer, (void *)dp->dad_ifa);
 1005 }
 1006 
 1007 static void
 1008 nd6_dad_stoptimer(dp)
 1009         struct dadq *dp;
 1010 {
 1011 
 1012         callout_stop(&dp->dad_timer_ch);
 1013 }
 1014 
 1015 /*
 1016  * Start Duplicated Address Detection (DAD) for specified interface address.
 1017  */
 1018 void
 1019 nd6_dad_start(ifa, tick)
 1020         struct ifaddr *ifa;
 1021         int *tick;      /* minimum delay ticks for IFF_UP event */
 1022 {
 1023         struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
 1024         struct dadq *dp;
 1025 
 1026         if (!dad_init) {
 1027                 TAILQ_INIT(&dadq);
 1028                 dad_init++;
 1029         }
 1030 
 1031         /*
 1032          * If we don't need DAD, don't do it.
 1033          * There are several cases:
 1034          * - DAD is disabled (ip6_dad_count == 0)
 1035          * - the interface address is anycast
 1036          */
 1037         if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) {
 1038                 log(LOG_DEBUG,
 1039                         "nd6_dad_start: called with non-tentative address "
 1040                         "%s(%s)\n",
 1041                         ip6_sprintf(&ia->ia_addr.sin6_addr),
 1042                         ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
 1043                 return;
 1044         }
 1045         if (ia->ia6_flags & IN6_IFF_ANYCAST) {
 1046                 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
 1047                 return;
 1048         }
 1049         if (!ip6_dad_count) {
 1050                 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
 1051                 return;
 1052         }
 1053         if (!ifa->ifa_ifp)
 1054                 panic("nd6_dad_start: ifa->ifa_ifp == NULL");
 1055         if (!(ifa->ifa_ifp->if_flags & IFF_UP)) {
 1056                 return;
 1057         }
 1058         if (nd6_dad_find(ifa) != NULL) {
 1059                 /* DAD already in progress */
 1060                 return;
 1061         }
 1062 
 1063         dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT);
 1064         if (dp == NULL) {
 1065                 log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
 1066                         "%s(%s)\n",
 1067                         ip6_sprintf(&ia->ia_addr.sin6_addr),
 1068                         ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
 1069                 return;
 1070         }
 1071         bzero(dp, sizeof(*dp));
 1072         callout_init(&dp->dad_timer_ch, 0);
 1073         TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list);
 1074 
 1075         nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
 1076             ip6_sprintf(&ia->ia_addr.sin6_addr)));
 1077 
 1078         /*
 1079          * Send NS packet for DAD, ip6_dad_count times.
 1080          * Note that we must delay the first transmission, if this is the
 1081          * first packet to be sent from the interface after interface
 1082          * (re)initialization.
 1083          */
 1084         dp->dad_ifa = ifa;
 1085         IFAREF(ifa);    /* just for safety */
 1086         dp->dad_count = ip6_dad_count;
 1087         dp->dad_ns_icount = dp->dad_na_icount = 0;
 1088         dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
 1089         if (tick == NULL) {
 1090                 nd6_dad_ns_output(dp, ifa);
 1091                 nd6_dad_starttimer(dp,
 1092                     ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
 1093         } else {
 1094                 int ntick;
 1095 
 1096                 if (*tick == 0)
 1097                         ntick = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
 1098                 else
 1099                         ntick = *tick + arc4random() % (hz / 2);
 1100                 *tick = ntick;
 1101                 nd6_dad_starttimer(dp, ntick);
 1102         }
 1103 }
 1104 
 1105 /*
 1106  * terminate DAD unconditionally.  used for address removals.
 1107  */
 1108 void
 1109 nd6_dad_stop(ifa)
 1110         struct ifaddr *ifa;
 1111 {
 1112         struct dadq *dp;
 1113 
 1114         if (!dad_init)
 1115                 return;
 1116         dp = nd6_dad_find(ifa);
 1117         if (!dp) {
 1118                 /* DAD wasn't started yet */
 1119                 return;
 1120         }
 1121 
 1122         nd6_dad_stoptimer(dp);
 1123 
 1124         TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
 1125         free(dp, M_IP6NDP);
 1126         dp = NULL;
 1127         IFAFREE(ifa);
 1128 }
 1129 
 1130 static void
 1131 nd6_dad_timer(ifa)
 1132         struct ifaddr *ifa;
 1133 {
 1134         int s;
 1135         struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
 1136         struct dadq *dp;
 1137 
 1138         s = splnet();           /* XXX */
 1139 
 1140         /* Sanity check */
 1141         if (ia == NULL) {
 1142                 log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
 1143                 goto done;
 1144         }
 1145         dp = nd6_dad_find(ifa);
 1146         if (dp == NULL) {
 1147                 log(LOG_ERR, "nd6_dad_timer: DAD structure not found\n");
 1148                 goto done;
 1149         }
 1150         if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
 1151                 log(LOG_ERR, "nd6_dad_timer: called with duplicated address "
 1152                         "%s(%s)\n",
 1153                         ip6_sprintf(&ia->ia_addr.sin6_addr),
 1154                         ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
 1155                 goto done;
 1156         }
 1157         if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
 1158                 log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
 1159                         "%s(%s)\n",
 1160                         ip6_sprintf(&ia->ia_addr.sin6_addr),
 1161                         ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
 1162                 goto done;
 1163         }
 1164 
 1165         /* timeouted with IFF_{RUNNING,UP} check */
 1166         if (dp->dad_ns_tcount > dad_maxtry) {
 1167                 nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n",
 1168                     if_name(ifa->ifa_ifp)));
 1169 
 1170                 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
 1171                 free(dp, M_IP6NDP);
 1172                 dp = NULL;
 1173                 IFAFREE(ifa);
 1174                 goto done;
 1175         }
 1176 
 1177         /* Need more checks? */
 1178         if (dp->dad_ns_ocount < dp->dad_count) {
 1179                 /*
 1180                  * We have more NS to go.  Send NS packet for DAD.
 1181                  */
 1182                 nd6_dad_ns_output(dp, ifa);
 1183                 nd6_dad_starttimer(dp,
 1184                     ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
 1185         } else {
 1186                 /*
 1187                  * We have transmitted sufficient number of DAD packets.
 1188                  * See what we've got.
 1189                  */
 1190                 int duplicate;
 1191 
 1192                 duplicate = 0;
 1193 
 1194                 if (dp->dad_na_icount) {
 1195                         /*
 1196                          * the check is in nd6_dad_na_input(),
 1197                          * but just in case
 1198                          */
 1199                         duplicate++;
 1200                 }
 1201 
 1202                 if (dp->dad_ns_icount) {
 1203 #if 0 /* heuristics */
 1204                         /*
 1205                          * if
 1206                          * - we have sent many(?) DAD NS, and
 1207                          * - the number of NS we sent equals to the
 1208                          *   number of NS we've got, and
 1209                          * - we've got no NA
 1210                          * we may have a faulty network card/driver which
 1211                          * loops back multicasts to myself.
 1212                          */
 1213                         if (3 < dp->dad_count
 1214                          && dp->dad_ns_icount == dp->dad_count
 1215                          && dp->dad_na_icount == 0) {
 1216                                 log(LOG_INFO, "DAD questionable for %s(%s): "
 1217                                     "network card loops back multicast?\n",
 1218                                     ip6_sprintf(&ia->ia_addr.sin6_addr),
 1219                                     if_name(ifa->ifa_ifp));
 1220                                 /* XXX consider it a duplicate or not? */
 1221                                 /* duplicate++; */
 1222                         } else {
 1223                                 /* We've seen NS, means DAD has failed. */
 1224                                 duplicate++;
 1225                         }
 1226 #else
 1227                         /* We've seen NS, means DAD has failed. */
 1228                         duplicate++;
 1229 #endif
 1230                 }
 1231 
 1232                 if (duplicate) {
 1233                         /* (*dp) will be freed in nd6_dad_duplicated() */
 1234                         dp = NULL;
 1235                         nd6_dad_duplicated(ifa);
 1236                 } else {
 1237                         /*
 1238                          * We are done with DAD.  No NA came, no NS came.
 1239                          * duplicated address found.
 1240                          */
 1241                         ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
 1242 
 1243                         nd6log((LOG_DEBUG,
 1244                             "%s: DAD complete for %s - no duplicates found\n",
 1245                             if_name(ifa->ifa_ifp),
 1246                             ip6_sprintf(&ia->ia_addr.sin6_addr)));
 1247 
 1248                         TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
 1249                         free(dp, M_IP6NDP);
 1250                         dp = NULL;
 1251                         IFAFREE(ifa);
 1252                 }
 1253         }
 1254 
 1255 done:
 1256         splx(s);
 1257 }
 1258 
 1259 void
 1260 nd6_dad_duplicated(ifa)
 1261         struct ifaddr *ifa;
 1262 {
 1263         struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
 1264         struct dadq *dp;
 1265 
 1266         dp = nd6_dad_find(ifa);
 1267         if (dp == NULL) {
 1268                 log(LOG_ERR, "nd6_dad_duplicated: DAD structure not found\n");
 1269                 return;
 1270         }
 1271 
 1272         log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "
 1273             "NS in/out=%d/%d, NA in=%d\n",
 1274             if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr),
 1275             dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_na_icount);
 1276 
 1277         ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
 1278         ia->ia6_flags |= IN6_IFF_DUPLICATED;
 1279 
 1280         /* We are done with DAD, with duplicated address found. (failure) */
 1281         nd6_dad_stoptimer(dp);
 1282 
 1283         log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
 1284             if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));
 1285         log(LOG_ERR, "%s: manual intervention required\n",
 1286             if_name(ifa->ifa_ifp));
 1287 
 1288         TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
 1289         free(dp, M_IP6NDP);
 1290         dp = NULL;
 1291         IFAFREE(ifa);
 1292 }
 1293 
 1294 static void
 1295 nd6_dad_ns_output(dp, ifa)
 1296         struct dadq *dp;
 1297         struct ifaddr *ifa;
 1298 {
 1299         struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
 1300         struct ifnet *ifp = ifa->ifa_ifp;
 1301 
 1302         dp->dad_ns_tcount++;
 1303         if ((ifp->if_flags & IFF_UP) == 0) {
 1304 #if 0
 1305                 printf("%s: interface down?\n", if_name(ifp));
 1306 #endif
 1307                 return;
 1308         }
 1309         if ((ifp->if_flags & IFF_RUNNING) == 0) {
 1310 #if 0
 1311                 printf("%s: interface not running?\n", if_name(ifp));
 1312 #endif
 1313                 return;
 1314         }
 1315 
 1316         dp->dad_ns_ocount++;
 1317         nd6_ns_output(ifp, NULL, &ia->ia_addr.sin6_addr, NULL, 1);
 1318 }
 1319 
 1320 static void
 1321 nd6_dad_ns_input(ifa)
 1322         struct ifaddr *ifa;
 1323 {
 1324         struct in6_ifaddr *ia;
 1325         struct ifnet *ifp;
 1326         const struct in6_addr *taddr6;
 1327         struct dadq *dp;
 1328         int duplicate;
 1329 
 1330         if (!ifa)
 1331                 panic("ifa == NULL in nd6_dad_ns_input");
 1332 
 1333         ia = (struct in6_ifaddr *)ifa;
 1334         ifp = ifa->ifa_ifp;
 1335         taddr6 = &ia->ia_addr.sin6_addr;
 1336         duplicate = 0;
 1337         dp = nd6_dad_find(ifa);
 1338 
 1339         /* Quickhack - completely ignore DAD NS packets */
 1340         if (dad_ignore_ns) {
 1341                 nd6log((LOG_INFO,
 1342                     "nd6_dad_ns_input: ignoring DAD NS packet for "
 1343                     "address %s(%s)\n", ip6_sprintf(taddr6),
 1344                     if_name(ifa->ifa_ifp)));
 1345                 return;
 1346         }
 1347 
 1348         /*
 1349          * if I'm yet to start DAD, someone else started using this address
 1350          * first.  I have a duplicate and you win.
 1351          */
 1352         if (!dp || dp->dad_ns_ocount == 0)
 1353                 duplicate++;
 1354 
 1355         /* XXX more checks for loopback situation - see nd6_dad_timer too */
 1356 
 1357         if (duplicate) {
 1358                 dp = NULL;      /* will be freed in nd6_dad_duplicated() */
 1359                 nd6_dad_duplicated(ifa);
 1360         } else {
 1361                 /*
 1362                  * not sure if I got a duplicate.
 1363                  * increment ns count and see what happens.
 1364                  */
 1365                 if (dp)
 1366                         dp->dad_ns_icount++;
 1367         }
 1368 }
 1369 
 1370 static void
 1371 nd6_dad_na_input(ifa)
 1372         struct ifaddr *ifa;
 1373 {
 1374         struct dadq *dp;
 1375 
 1376         if (!ifa)
 1377                 panic("ifa == NULL in nd6_dad_na_input");
 1378 
 1379         dp = nd6_dad_find(ifa);
 1380         if (dp)
 1381                 dp->dad_na_icount++;
 1382 
 1383         /* remove the address. */
 1384         nd6_dad_duplicated(ifa);
 1385 }

Cache object: 2224a65ca5ceadc2f0ee95344ef40b41


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.