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

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

CVSweb <webmaster@jp.NetBSD.org>