LCOV - code coverage report
Current view: top level - netinet6 - nd6_nbr.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 592 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13