[BACK]Return to nd6_nbr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet6

Annotation of src/sys/netinet6/nd6_nbr.c, Revision 1.97

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

CVSweb <webmaster@jp.NetBSD.org>