[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.105

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

CVSweb <webmaster@jp.NetBSD.org>