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

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

CVSweb <webmaster@jp.NetBSD.org>