[BACK]Return to icmp6.c CVS log [TXT][DIR] Up to [local] / sys / netinet6

Annotation of sys/netinet6/icmp6.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: icmp6.c,v 1.94 2007/06/01 00:52:38 henning Exp $      */
                      2: /*     $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of the project nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
                     33: /*
                     34:  * Copyright (c) 1982, 1986, 1988, 1993
                     35:  *     The Regents of the University of California.  All rights reserved.
                     36:  *
                     37:  * Redistribution and use in source and binary forms, with or without
                     38:  * modification, are permitted provided that the following conditions
                     39:  * are met:
                     40:  * 1. Redistributions of source code must retain the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer.
                     42:  * 2. Redistributions in binary form must reproduce the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer in the
                     44:  *    documentation and/or other materials provided with the distribution.
                     45:  * 3. Neither the name of the University nor the names of its contributors
                     46:  *    may be used to endorse or promote products derived from this software
                     47:  *    without specific prior written permission.
                     48:  *
                     49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     59:  * SUCH DAMAGE.
                     60:  *
                     61:  *     @(#)ip_icmp.c   8.2 (Berkeley) 1/4/94
                     62:  */
                     63:
                     64: #include "faith.h"
                     65: #include "carp.h"
                     66:
                     67: #include <sys/param.h>
                     68: #include <sys/systm.h>
                     69: #include <sys/malloc.h>
                     70: #include <sys/mbuf.h>
                     71: #include <sys/protosw.h>
                     72: #include <sys/socket.h>
                     73: #include <sys/socketvar.h>
                     74: #include <sys/time.h>
                     75: #include <sys/kernel.h>
                     76: #include <sys/syslog.h>
                     77: #include <sys/domain.h>
                     78:
                     79: #include <net/if.h>
                     80: #include <net/route.h>
                     81: #include <net/if_dl.h>
                     82: #include <net/if_types.h>
                     83:
                     84: #include <netinet/in.h>
                     85: #include <netinet/in_var.h>
                     86: #include <netinet/in_systm.h>
                     87: #include <netinet/ip.h>
                     88: #include <netinet/ip6.h>
                     89: #include <netinet6/ip6_var.h>
                     90: #include <netinet/icmp6.h>
                     91: #include <netinet6/mld6_var.h>
                     92: #include <netinet/in_pcb.h>
                     93: #include <netinet6/nd6.h>
                     94: #include <netinet6/in6_ifattach.h>
                     95: #include <netinet6/ip6protosw.h>
                     96:
                     97: #if NCARP > 0
                     98: #include <netinet/ip_carp.h>
                     99: #endif
                    100:
                    101: /* inpcb members */
                    102: #define in6pcb         inpcb
                    103: #define in6p_laddr     inp_laddr6
                    104: #define in6p_faddr     inp_faddr6
                    105: #define in6p_icmp6filt inp_icmp6filt
                    106: #define in6p_route     inp_route
                    107: #define in6p_socket    inp_socket
                    108: #define in6p_flags     inp_flags
                    109: #define in6p_moptions  inp_moptions6
                    110: #define in6p_outputopts        inp_outputopts6
                    111: #define in6p_ip6       inp_ipv6
                    112: #define in6p_flowinfo  inp_flowinfo
                    113: #define in6p_sp                inp_sp
                    114: #define in6p_next      inp_next
                    115: #define in6p_prev      inp_prev
                    116: /* macro names */
                    117: #define sotoin6pcb     sotoinpcb
                    118: /* function names */
                    119: #define in6_pcbdetach  in_pcbdetach
                    120: #define in6_rtchange   in_rtchange
                    121:
                    122: /*
                    123:  * for KAME src sync over BSD*'s.  XXX: FreeBSD (>=3) are VERY different from
                    124:  * others...
                    125:  */
                    126: #define in6p_ip6_nxt   inp_ipv6.ip6_nxt
                    127:
                    128: extern struct domain inet6domain;
                    129: extern struct ip6protosw inet6sw[];
                    130: extern u_char ip6_protox[];
                    131:
                    132: struct icmp6stat icmp6stat;
                    133:
                    134: extern struct inpcbtable rawin6pcbtable;
                    135: extern int icmp6errppslim;
                    136: static int icmp6errpps_count = 0;
                    137: static struct timeval icmp6errppslim_last;
                    138: extern int icmp6_nodeinfo;
                    139:
                    140: /*
                    141:  * List of callbacks to notify when Path MTU changes are made.
                    142:  */
                    143: struct icmp6_mtudisc_callback {
                    144:        LIST_ENTRY(icmp6_mtudisc_callback) mc_list;
                    145:        void (*mc_func)(struct in6_addr *);
                    146: };
                    147:
                    148: LIST_HEAD(, icmp6_mtudisc_callback) icmp6_mtudisc_callbacks =
                    149:     LIST_HEAD_INITIALIZER(&icmp6_mtudisc_callbacks);
                    150:
                    151: static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL;
                    152: extern int pmtu_expire;
                    153:
                    154: /* XXX do these values make any sense? */
                    155: static int icmp6_mtudisc_hiwat = 1280;
                    156: static int icmp6_mtudisc_lowat = 256;
                    157:
                    158: /*
                    159:  * keep track of # of redirect routes.
                    160:  */
                    161: static struct rttimer_queue *icmp6_redirect_timeout_q = NULL;
                    162:
                    163: /* XXX experimental, turned off */
                    164: static int icmp6_redirect_hiwat = -1;
                    165: static int icmp6_redirect_lowat = -1;
                    166:
                    167: static void icmp6_errcount(struct icmp6errstat *, int, int);
                    168: static int icmp6_rip6_input(struct mbuf **, int);
                    169: static int icmp6_ratelimit(const struct in6_addr *, const int, const int);
                    170: static const char *icmp6_redirect_diag(struct in6_addr *,
                    171:        struct in6_addr *, struct in6_addr *);
                    172: static struct mbuf *ni6_input(struct mbuf *, int);
                    173: static struct mbuf *ni6_nametodns(const char *, int, int);
                    174: static int ni6_dnsmatch(const char *, int, const char *, int);
                    175: static int ni6_addrs(struct icmp6_nodeinfo *, struct mbuf *,
                    176:                          struct ifnet **, char *);
                    177: static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
                    178:                                struct ifnet *, int);
                    179: static int icmp6_notify_error(struct mbuf *, int, int, int);
                    180: static struct rtentry *icmp6_mtudisc_clone(struct sockaddr *);
                    181: static void icmp6_mtudisc_timeout(struct rtentry *, struct rttimer *);
                    182: static void icmp6_redirect_timeout(struct rtentry *, struct rttimer *);
                    183:
                    184: void
                    185: icmp6_init()
                    186: {
                    187:        mld6_init();
                    188:        icmp6_mtudisc_timeout_q = rt_timer_queue_create(pmtu_expire);
                    189:        icmp6_redirect_timeout_q = rt_timer_queue_create(icmp6_redirtimeout);
                    190: }
                    191:
                    192: static void
                    193: icmp6_errcount(stat, type, code)
                    194:        struct icmp6errstat *stat;
                    195:        int type, code;
                    196: {
                    197:        switch (type) {
                    198:        case ICMP6_DST_UNREACH:
                    199:                switch (code) {
                    200:                case ICMP6_DST_UNREACH_NOROUTE:
                    201:                        stat->icp6errs_dst_unreach_noroute++;
                    202:                        return;
                    203:                case ICMP6_DST_UNREACH_ADMIN:
                    204:                        stat->icp6errs_dst_unreach_admin++;
                    205:                        return;
                    206:                case ICMP6_DST_UNREACH_BEYONDSCOPE:
                    207:                        stat->icp6errs_dst_unreach_beyondscope++;
                    208:                        return;
                    209:                case ICMP6_DST_UNREACH_ADDR:
                    210:                        stat->icp6errs_dst_unreach_addr++;
                    211:                        return;
                    212:                case ICMP6_DST_UNREACH_NOPORT:
                    213:                        stat->icp6errs_dst_unreach_noport++;
                    214:                        return;
                    215:                }
                    216:                break;
                    217:        case ICMP6_PACKET_TOO_BIG:
                    218:                stat->icp6errs_packet_too_big++;
                    219:                return;
                    220:        case ICMP6_TIME_EXCEEDED:
                    221:                switch (code) {
                    222:                case ICMP6_TIME_EXCEED_TRANSIT:
                    223:                        stat->icp6errs_time_exceed_transit++;
                    224:                        return;
                    225:                case ICMP6_TIME_EXCEED_REASSEMBLY:
                    226:                        stat->icp6errs_time_exceed_reassembly++;
                    227:                        return;
                    228:                }
                    229:                break;
                    230:        case ICMP6_PARAM_PROB:
                    231:                switch (code) {
                    232:                case ICMP6_PARAMPROB_HEADER:
                    233:                        stat->icp6errs_paramprob_header++;
                    234:                        return;
                    235:                case ICMP6_PARAMPROB_NEXTHEADER:
                    236:                        stat->icp6errs_paramprob_nextheader++;
                    237:                        return;
                    238:                case ICMP6_PARAMPROB_OPTION:
                    239:                        stat->icp6errs_paramprob_option++;
                    240:                        return;
                    241:                }
                    242:                break;
                    243:        case ND_REDIRECT:
                    244:                stat->icp6errs_redirect++;
                    245:                return;
                    246:        }
                    247:        stat->icp6errs_unknown++;
                    248: }
                    249:
                    250: /*
                    251:  * Register a Path MTU Discovery callback.
                    252:  */
                    253: void
                    254: icmp6_mtudisc_callback_register(func)
                    255:        void (*func)(struct in6_addr *);
                    256: {
                    257:        struct icmp6_mtudisc_callback *mc;
                    258:
                    259:        for (mc = LIST_FIRST(&icmp6_mtudisc_callbacks); mc != NULL;
                    260:             mc = LIST_NEXT(mc, mc_list)) {
                    261:                if (mc->mc_func == func)
                    262:                        return;
                    263:        }
                    264:
                    265:        mc = malloc(sizeof(*mc), M_PCB, M_NOWAIT);
                    266:        if (mc == NULL)
                    267:                panic("icmp6_mtudisc_callback_register");
                    268:
                    269:        mc->mc_func = func;
                    270:        LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks, mc, mc_list);
                    271: }
                    272:
                    273: /*
                    274:  * Generate an error packet of type error in response to bad IP6 packet.
                    275:  */
                    276: void
                    277: icmp6_error(m, type, code, param)
                    278:        struct mbuf *m;
                    279:        int type, code, param;
                    280: {
                    281:        struct ip6_hdr *oip6, *nip6;
                    282:        struct icmp6_hdr *icmp6;
                    283:        u_int preplen;
                    284:        int off;
                    285:        int nxt;
                    286:
                    287:        icmp6stat.icp6s_error++;
                    288:
                    289:        /* count per-type-code statistics */
                    290:        icmp6_errcount(&icmp6stat.icp6s_outerrhist, type, code);
                    291:
                    292:        if (m->m_len < sizeof(struct ip6_hdr)) {
                    293:                m = m_pullup(m, sizeof(struct ip6_hdr));
                    294:                if (m == NULL)
                    295:                        return;
                    296:        }
                    297:        oip6 = mtod(m, struct ip6_hdr *);
                    298:
                    299:        /*
                    300:         * If the destination address of the erroneous packet is a multicast
                    301:         * address, or the packet was sent using link-layer multicast,
                    302:         * we should basically suppress sending an error (RFC 2463, Section
                    303:         * 2.4).
                    304:         * We have two exceptions (the item e.2 in that section):
                    305:         * - the Pakcet Too Big message can be sent for path MTU discovery.
                    306:         * - the Parameter Problem Message that can be allowed an icmp6 error
                    307:         *   in the option type field.  This check has been done in
                    308:         *   ip6_unknown_opt(), so we can just check the type and code.
                    309:         */
                    310:        if ((m->m_flags & (M_BCAST|M_MCAST) ||
                    311:             IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) &&
                    312:            (type != ICMP6_PACKET_TOO_BIG &&
                    313:             (type != ICMP6_PARAM_PROB ||
                    314:              code != ICMP6_PARAMPROB_OPTION)))
                    315:                goto freeit;
                    316:
                    317:        /*
                    318:         * RFC 2463, 2.4 (e.5): source address check.
                    319:         * XXX: the case of anycast source?
                    320:         */
                    321:        if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) ||
                    322:            IN6_IS_ADDR_MULTICAST(&oip6->ip6_src))
                    323:                goto freeit;
                    324:
                    325:        /*
                    326:         * If we are about to send ICMPv6 against ICMPv6 error/redirect,
                    327:         * don't do it.
                    328:         */
                    329:        nxt = -1;
                    330:        off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
                    331:        if (off >= 0 && nxt == IPPROTO_ICMPV6) {
                    332:                struct icmp6_hdr *icp;
                    333:
                    334:                IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
                    335:                        sizeof(*icp));
                    336:                if (icp == NULL) {
                    337:                        icmp6stat.icp6s_tooshort++;
                    338:                        return;
                    339:                }
                    340:                if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
                    341:                    icp->icmp6_type == ND_REDIRECT) {
                    342:                        /*
                    343:                         * ICMPv6 error
                    344:                         * Special case: for redirect (which is
                    345:                         * informational) we must not send icmp6 error.
                    346:                         */
                    347:                        icmp6stat.icp6s_canterror++;
                    348:                        goto freeit;
                    349:                } else {
                    350:                        /* ICMPv6 informational - send the error */
                    351:                }
                    352:        }
                    353:        else {
                    354:                /* non-ICMPv6 - send the error */
                    355:        }
                    356:
                    357:        oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */
                    358:
                    359:        /* Finally, do rate limitation check. */
                    360:        if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {
                    361:                icmp6stat.icp6s_toofreq++;
                    362:                goto freeit;
                    363:        }
                    364:
                    365:        /*
                    366:         * OK, ICMP6 can be generated.
                    367:         */
                    368:
                    369:        if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)
                    370:                m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
                    371:
                    372:        preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
                    373:        M_PREPEND(m, preplen, M_DONTWAIT);
                    374:        if (m && m->m_len < preplen)
                    375:                m = m_pullup(m, preplen);
                    376:        if (m == NULL) {
                    377:                nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__));
                    378:                return;
                    379:        }
                    380:
                    381:        nip6 = mtod(m, struct ip6_hdr *);
                    382:        nip6->ip6_src  = oip6->ip6_src;
                    383:        nip6->ip6_dst  = oip6->ip6_dst;
                    384:
                    385:        if (IN6_IS_SCOPE_EMBED(&oip6->ip6_src))
                    386:                oip6->ip6_src.s6_addr16[1] = 0;
                    387:        if (IN6_IS_SCOPE_EMBED(&oip6->ip6_dst))
                    388:                oip6->ip6_dst.s6_addr16[1] = 0;
                    389:
                    390:        icmp6 = (struct icmp6_hdr *)(nip6 + 1);
                    391:        icmp6->icmp6_type = type;
                    392:        icmp6->icmp6_code = code;
                    393:        icmp6->icmp6_pptr = htonl((u_int32_t)param);
                    394:
                    395:        /*
                    396:         * icmp6_reflect() is designed to be in the input path.
                    397:         * icmp6_error() can be called from both input and outut path,
                    398:         * and if we are in output path rcvif could contain bogus value.
                    399:         * clear m->m_pkthdr.rcvif for safety, we should have enough scope
                    400:         * information in ip header (nip6).
                    401:         */
                    402:        m->m_pkthdr.rcvif = NULL;
                    403:
                    404:        icmp6stat.icp6s_outhist[type]++;
                    405:        icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
                    406:
                    407:        return;
                    408:
                    409:   freeit:
                    410:        /*
                    411:         * If we can't tell wheter or not we can generate ICMP6, free it.
                    412:         */
                    413:        m_freem(m);
                    414: }
                    415:
                    416: /*
                    417:  * Process a received ICMP6 message.
                    418:  */
                    419: int
                    420: icmp6_input(mp, offp, proto)
                    421:        struct mbuf **mp;
                    422:        int *offp, proto;
                    423: {
                    424:        struct mbuf *m = *mp, *n;
                    425:        struct ip6_hdr *ip6, *nip6;
                    426:        struct icmp6_hdr *icmp6, *nicmp6;
                    427:        int off = *offp;
                    428:        int icmp6len = m->m_pkthdr.len - *offp;
                    429:        int code, sum, noff;
                    430:
                    431:        icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg);
                    432:
                    433:        /*
                    434:         * Locate icmp6 structure in mbuf, and check
                    435:         * that not corrupted and of at least minimum length
                    436:         */
                    437:
                    438:        ip6 = mtod(m, struct ip6_hdr *);
                    439:        if (icmp6len < sizeof(struct icmp6_hdr)) {
                    440:                icmp6stat.icp6s_tooshort++;
                    441:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
                    442:                goto freeit;
                    443:        }
                    444:
                    445:        /*
                    446:         * calculate the checksum
                    447:         */
                    448:        IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
                    449:        if (icmp6 == NULL) {
                    450:                icmp6stat.icp6s_tooshort++;
                    451:                return IPPROTO_DONE;
                    452:        }
                    453:        code = icmp6->icmp6_code;
                    454:
                    455:        if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
                    456:                nd6log((LOG_ERR,
                    457:                    "ICMP6 checksum error(%d|%x) %s\n",
                    458:                    icmp6->icmp6_type, sum, ip6_sprintf(&ip6->ip6_src)));
                    459:                icmp6stat.icp6s_checksum++;
                    460:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
                    461:                goto freeit;
                    462:        }
                    463:
                    464: #if defined(NFAITH) && 0 < NFAITH
                    465:        if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
                    466:                /*
                    467:                 * Deliver very specific ICMP6 type only.
                    468:                 * This is important to deliver TOOBIG.  Otherwise PMTUD
                    469:                 * will not work.
                    470:                 */
                    471:                switch (icmp6->icmp6_type) {
                    472:                case ICMP6_DST_UNREACH:
                    473:                case ICMP6_PACKET_TOO_BIG:
                    474:                case ICMP6_TIME_EXCEEDED:
                    475:                        break;
                    476:                default:
                    477:                        goto freeit;
                    478:                }
                    479:        }
                    480: #endif
                    481:
                    482: #if NCARP > 0
                    483:        if (m->m_pkthdr.rcvif->if_type == IFT_CARP &&
                    484:            m->m_pkthdr.rcvif->if_flags & IFF_LINK0 &&
                    485:            icmp6->icmp6_type == ICMP6_ECHO_REQUEST &&
                    486:            carp_lsdrop(m, AF_INET6, ip6->ip6_src.s6_addr32,
                    487:            ip6->ip6_dst.s6_addr32))
                    488:                goto freeit;
                    489: #endif
                    490:        icmp6stat.icp6s_inhist[icmp6->icmp6_type]++;
                    491:
                    492:        switch (icmp6->icmp6_type) {
                    493:        case ICMP6_DST_UNREACH:
                    494:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach);
                    495:                switch (code) {
                    496:                case ICMP6_DST_UNREACH_NOROUTE:
                    497:                        code = PRC_UNREACH_NET;
                    498:                        break;
                    499:                case ICMP6_DST_UNREACH_ADMIN:
                    500:                        icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_adminprohib);
                    501:                        code = PRC_UNREACH_PROTOCOL; /* is this a good code? */
                    502:                        break;
                    503:                case ICMP6_DST_UNREACH_ADDR:
                    504:                        code = PRC_HOSTDEAD;
                    505:                        break;
                    506: #ifdef COMPAT_RFC1885
                    507:                case ICMP6_DST_UNREACH_NOTNEIGHBOR:
                    508:                        code = PRC_UNREACH_SRCFAIL;
                    509:                        break;
                    510: #else
                    511:                case ICMP6_DST_UNREACH_BEYONDSCOPE:
                    512:                        /* I mean "source address was incorrect." */
                    513:                        code = PRC_PARAMPROB;
                    514:                        break;
                    515: #endif
                    516:                case ICMP6_DST_UNREACH_NOPORT:
                    517:                        code = PRC_UNREACH_PORT;
                    518:                        break;
                    519:                default:
                    520:                        goto badcode;
                    521:                }
                    522:                goto deliver;
                    523:
                    524:        case ICMP6_PACKET_TOO_BIG:
                    525:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig);
                    526:
                    527:                code = PRC_MSGSIZE;
                    528:
                    529:                /*
                    530:                 * Updating the path MTU will be done after examining
                    531:                 * intermediate extension headers.
                    532:                 */
                    533:                goto deliver;
                    534:
                    535:        case ICMP6_TIME_EXCEEDED:
                    536:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed);
                    537:                switch (code) {
                    538:                case ICMP6_TIME_EXCEED_TRANSIT:
                    539:                        code = PRC_TIMXCEED_INTRANS;
                    540:                        break;
                    541:                case ICMP6_TIME_EXCEED_REASSEMBLY:
                    542:                        code = PRC_TIMXCEED_REASS;
                    543:                        break;
                    544:                default:
                    545:                        goto badcode;
                    546:                }
                    547:                goto deliver;
                    548:
                    549:        case ICMP6_PARAM_PROB:
                    550:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob);
                    551:                switch (code) {
                    552:                case ICMP6_PARAMPROB_NEXTHEADER:
                    553:                        code = PRC_UNREACH_PROTOCOL;
                    554:                        break;
                    555:                case ICMP6_PARAMPROB_HEADER:
                    556:                case ICMP6_PARAMPROB_OPTION:
                    557:                        code = PRC_PARAMPROB;
                    558:                        break;
                    559:                default:
                    560:                        goto badcode;
                    561:                }
                    562:                goto deliver;
                    563:
                    564:        case ICMP6_ECHO_REQUEST:
                    565:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo);
                    566:                if (code != 0)
                    567:                        goto badcode;
                    568:                /*
                    569:                 * Copy mbuf to send to two data paths: userland socket(s),
                    570:                 * and to the querier (echo reply).
                    571:                 * m: a copy for socket, n: a copy for querier
                    572:                 */
                    573:                if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
                    574:                        /* Give up local */
                    575:                        n = m;
                    576:                        m = NULL;
                    577:                        goto deliverecho;
                    578:                }
                    579:                /*
                    580:                 * If the first mbuf is shared, or the first mbuf is too short,
                    581:                 * copy the first part of the data into a fresh mbuf.
                    582:                 * Otherwise, we will wrongly overwrite both copies.
                    583:                 */
                    584:                if ((n->m_flags & M_EXT) != 0 ||
                    585:                    n->m_len < off + sizeof(struct icmp6_hdr)) {
                    586:                        struct mbuf *n0 = n;
                    587:                        const int maxlen = sizeof(*nip6) + sizeof(*nicmp6);
                    588:
                    589:                        /*
                    590:                         * Prepare an internal mbuf.  m_pullup() doesn't
                    591:                         * always copy the length we specified.
                    592:                         */
                    593:                        if (maxlen >= MCLBYTES) {
                    594:                                /* Give up remote */
                    595:                                m_freem(n0);
                    596:                                break;
                    597:                        }
                    598:                        MGETHDR(n, M_DONTWAIT, n0->m_type);
                    599:                        if (n && maxlen >= MHLEN) {
                    600:                                MCLGET(n, M_DONTWAIT);
                    601:                                if ((n->m_flags & M_EXT) == 0) {
                    602:                                        m_free(n);
                    603:                                        n = NULL;
                    604:                                }
                    605:                        }
                    606:                        if (n == NULL) {
                    607:                                /* Give up local */
                    608:                                m_freem(n0);
                    609:                                n = m;
                    610:                                m = NULL;
                    611:                                goto deliverecho;
                    612:                        }
                    613:                        M_MOVE_PKTHDR(n, n0);
                    614:                        /*
                    615:                         * Copy IPv6 and ICMPv6 only.
                    616:                         */
                    617:                        nip6 = mtod(n, struct ip6_hdr *);
                    618:                        bcopy(ip6, nip6, sizeof(struct ip6_hdr));
                    619:                        nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
                    620:                        bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
                    621:                        noff = sizeof(struct ip6_hdr);
                    622:                        n->m_len = noff + sizeof(struct icmp6_hdr);
                    623:                        /*
                    624:                         * Adjust mbuf.  ip6_plen will be adjusted in
                    625:                         * ip6_output().
                    626:                         * n->m_pkthdr.len == n0->m_pkthdr.len at this point.
                    627:                         */
                    628:                        n->m_pkthdr.len += noff + sizeof(struct icmp6_hdr);
                    629:                        n->m_pkthdr.len -= (off + sizeof(struct icmp6_hdr));
                    630:                        m_adj(n0, off + sizeof(struct icmp6_hdr));
                    631:                        n->m_next = n0;
                    632:                } else {
                    633:         deliverecho:
                    634:                        nip6 = mtod(n, struct ip6_hdr *);
                    635:                        IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off,
                    636:                            sizeof(*nicmp6));
                    637:                        noff = off;
                    638:                }
                    639:                nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
                    640:                nicmp6->icmp6_code = 0;
                    641:                if (n) {
                    642:                        icmp6stat.icp6s_reflect++;
                    643:                        icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++;
                    644:                        icmp6_reflect(n, noff);
                    645:                }
                    646:                if (!m)
                    647:                        goto freeit;
                    648:                break;
                    649:
                    650:        case ICMP6_ECHO_REPLY:
                    651:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply);
                    652:                if (code != 0)
                    653:                        goto badcode;
                    654:                break;
                    655:
                    656:        case MLD_LISTENER_QUERY:
                    657:        case MLD_LISTENER_REPORT:
                    658:                if (icmp6len < sizeof(struct mld_hdr))
                    659:                        goto badlen;
                    660:                if (icmp6->icmp6_type == MLD_LISTENER_QUERY) /* XXX: ugly... */
                    661:                        icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldquery);
                    662:                else
                    663:                        icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldreport);
                    664:                if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
                    665:                        /* give up local */
                    666:                        mld6_input(m, off);
                    667:                        m = NULL;
                    668:                        goto freeit;
                    669:                }
                    670:                mld6_input(n, off);
                    671:                /* m stays. */
                    672:                break;
                    673:
                    674:        case MLD_LISTENER_DONE:
                    675:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mlddone);
                    676:                if (icmp6len < sizeof(struct mld_hdr))  /* necessary? */
                    677:                        goto badlen;
                    678:                break;          /* nothing to be done in kernel */
                    679:
                    680:        case MLD_MTRACE_RESP:
                    681:        case MLD_MTRACE:
                    682:                /* XXX: these two are experimental.  not officially defined. */
                    683:                /* XXX: per-interface statistics? */
                    684:                break;          /* just pass it to applications */
                    685:
                    686:        case ICMP6_WRUREQUEST:  /* ICMP6_FQDN_QUERY */
                    687:            {
                    688:                enum { WRU, FQDN } mode;
                    689:
                    690:                if (!icmp6_nodeinfo)
                    691:                        break;
                    692:
                    693:                if (icmp6len == sizeof(struct icmp6_hdr) + 4)
                    694:                        mode = WRU;
                    695:                else if (icmp6len >= sizeof(struct icmp6_nodeinfo))
                    696:                        mode = FQDN;
                    697:                else
                    698:                        goto badlen;
                    699:
                    700:                if (mode == FQDN) {
                    701:                        n = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
                    702:                        if (n)
                    703:                                n = ni6_input(n, off);
                    704:                        /* XXX meaningless if n == NULL */
                    705:                        noff = sizeof(struct ip6_hdr);
                    706:                } else {
                    707:                        u_char *p;
                    708:                        int maxlen, maxhlen;
                    709:
                    710:                        if ((icmp6_nodeinfo & 1) == 0)
                    711:                                break;
                    712:
                    713:                        if (code != 0)
                    714:                                goto badcode;
                    715:                        maxlen = sizeof(*nip6) + sizeof(*nicmp6) + 4;
                    716:                        if (maxlen >= MCLBYTES) {
                    717:                                /* Give up remote */
                    718:                                break;
                    719:                        }
                    720:                        MGETHDR(n, M_DONTWAIT, m->m_type);
                    721:                        if (n && maxlen > MHLEN) {
                    722:                                MCLGET(n, M_DONTWAIT);
                    723:                                if ((n->m_flags & M_EXT) == 0) {
                    724:                                        m_free(n);
                    725:                                        n = NULL;
                    726:                                }
                    727:                        }
                    728:                        if (n == NULL) {
                    729:                                /* Give up remote */
                    730:                                break;
                    731:                        }
                    732:                        n->m_pkthdr.rcvif = NULL;
                    733:                        n->m_len = 0;
                    734:                        maxhlen = M_TRAILINGSPACE(n) - maxlen;
                    735:                        if (maxhlen > hostnamelen)
                    736:                                maxhlen = hostnamelen;
                    737:                        /*
                    738:                         * Copy IPv6 and ICMPv6 only.
                    739:                         */
                    740:                        nip6 = mtod(n, struct ip6_hdr *);
                    741:                        bcopy(ip6, nip6, sizeof(struct ip6_hdr));
                    742:                        nicmp6 = (struct icmp6_hdr *)(nip6 + 1);
                    743:                        bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr));
                    744:                        p = (u_char *)(nicmp6 + 1);
                    745:                        bzero(p, 4);
                    746:                        bcopy(hostname, p + 4, maxhlen); /* meaningless TTL */
                    747:                        noff = sizeof(struct ip6_hdr);
                    748:                        M_DUP_PKTHDR(n, m); /* just for rcvif */
                    749:                        n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
                    750:                                sizeof(struct icmp6_hdr) + 4 + maxhlen;
                    751:                        nicmp6->icmp6_type = ICMP6_WRUREPLY;
                    752:                        nicmp6->icmp6_code = 0;
                    753:                }
                    754: #undef hostnamelen
                    755:                if (n) {
                    756:                        icmp6stat.icp6s_reflect++;
                    757:                        icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++;
                    758:                        icmp6_reflect(n, noff);
                    759:                }
                    760:                break;
                    761:            }
                    762:
                    763:        case ICMP6_WRUREPLY:
                    764:                if (code != 0)
                    765:                        goto badcode;
                    766:                break;
                    767:
                    768:        case ND_ROUTER_SOLICIT:
                    769:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit);
                    770:                if (code != 0)
                    771:                        goto badcode;
                    772:                if (icmp6len < sizeof(struct nd_router_solicit))
                    773:                        goto badlen;
                    774:                if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
                    775:                        /* give up local */
                    776:                        nd6_rs_input(m, off, icmp6len);
                    777:                        m = NULL;
                    778:                        goto freeit;
                    779:                }
                    780:                nd6_rs_input(n, off, icmp6len);
                    781:                /* m stays. */
                    782:                break;
                    783:
                    784:        case ND_ROUTER_ADVERT:
                    785:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert);
                    786:                if (code != 0)
                    787:                        goto badcode;
                    788:                if (icmp6len < sizeof(struct nd_router_advert))
                    789:                        goto badlen;
                    790:                if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
                    791:                        /* give up local */
                    792:                        nd6_ra_input(m, off, icmp6len);
                    793:                        m = NULL;
                    794:                        goto freeit;
                    795:                }
                    796:                nd6_ra_input(n, off, icmp6len);
                    797:                /* m stays. */
                    798:                break;
                    799:
                    800:        case ND_NEIGHBOR_SOLICIT:
                    801:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit);
                    802:                if (code != 0)
                    803:                        goto badcode;
                    804:                if (icmp6len < sizeof(struct nd_neighbor_solicit))
                    805:                        goto badlen;
                    806:                if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
                    807:                        /* give up local */
                    808:                        nd6_ns_input(m, off, icmp6len);
                    809:                        m = NULL;
                    810:                        goto freeit;
                    811:                }
                    812:                nd6_ns_input(n, off, icmp6len);
                    813:                /* m stays. */
                    814:                break;
                    815:
                    816:        case ND_NEIGHBOR_ADVERT:
                    817:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert);
                    818:                if (code != 0)
                    819:                        goto badcode;
                    820:                if (icmp6len < sizeof(struct nd_neighbor_advert))
                    821:                        goto badlen;
                    822:                if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
                    823:                        /* give up local */
                    824:                        nd6_na_input(m, off, icmp6len);
                    825:                        m = NULL;
                    826:                        goto freeit;
                    827:                }
                    828:                nd6_na_input(n, off, icmp6len);
                    829:                /* m stays. */
                    830:                break;
                    831:
                    832:        case ND_REDIRECT:
                    833:                icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect);
                    834:                if (code != 0)
                    835:                        goto badcode;
                    836:                if (icmp6len < sizeof(struct nd_redirect))
                    837:                        goto badlen;
                    838:                if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
                    839:                        /* give up local */
                    840:                        icmp6_redirect_input(m, off);
                    841:                        m = NULL;
                    842:                        goto freeit;
                    843:                }
                    844:                icmp6_redirect_input(n, off);
                    845:                /* m stays. */
                    846:                break;
                    847:
                    848:        case ICMP6_ROUTER_RENUMBERING:
                    849:                if (code != ICMP6_ROUTER_RENUMBERING_COMMAND &&
                    850:                    code != ICMP6_ROUTER_RENUMBERING_RESULT)
                    851:                        goto badcode;
                    852:                if (icmp6len < sizeof(struct icmp6_router_renum))
                    853:                        goto badlen;
                    854:                break;
                    855:
                    856:        default:
                    857:                nd6log((LOG_DEBUG,
                    858:                    "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
                    859:                    icmp6->icmp6_type, ip6_sprintf(&ip6->ip6_src),
                    860:                    ip6_sprintf(&ip6->ip6_dst),
                    861:                    m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0));
                    862:                if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) {
                    863:                        /* ICMPv6 error: MUST deliver it by spec... */
                    864:                        code = PRC_NCMDS;
                    865:                        /* deliver */
                    866:                } else {
                    867:                        /* ICMPv6 informational: MUST not deliver */
                    868:                        break;
                    869:                }
                    870:        deliver:
                    871:                if (icmp6_notify_error(m, off, icmp6len, code)) {
                    872:                        /* In this case, m should've been freed. */
                    873:                        return (IPPROTO_DONE);
                    874:                }
                    875:                break;
                    876:
                    877:        badcode:
                    878:                icmp6stat.icp6s_badcode++;
                    879:                break;
                    880:
                    881:        badlen:
                    882:                icmp6stat.icp6s_badlen++;
                    883:                break;
                    884:        }
                    885:
                    886:        /* deliver the packet to appropriate sockets */
                    887:        icmp6_rip6_input(&m, *offp);
                    888:
                    889:        return IPPROTO_DONE;
                    890:
                    891:  freeit:
                    892:        m_freem(m);
                    893:        return IPPROTO_DONE;
                    894: }
                    895:
                    896: static int
                    897: icmp6_notify_error(m, off, icmp6len, code)
                    898:        struct mbuf *m;
                    899:        int off, icmp6len, code;
                    900: {
                    901:        struct icmp6_hdr *icmp6;
                    902:        struct ip6_hdr *eip6;
                    903:        u_int32_t notifymtu;
                    904:        struct sockaddr_in6 icmp6src, icmp6dst;
                    905:
                    906:        if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
                    907:                icmp6stat.icp6s_tooshort++;
                    908:                goto freeit;
                    909:        }
                    910:        IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
                    911:                       sizeof(*icmp6) + sizeof(struct ip6_hdr));
                    912:        if (icmp6 == NULL) {
                    913:                icmp6stat.icp6s_tooshort++;
                    914:                return (-1);
                    915:        }
                    916:        eip6 = (struct ip6_hdr *)(icmp6 + 1);
                    917:
                    918:        /* Detect the upper level protocol */
                    919:        {
                    920:                void (*ctlfunc)(int, struct sockaddr *, void *);
                    921:                u_int8_t nxt = eip6->ip6_nxt;
                    922:                int eoff = off + sizeof(struct icmp6_hdr) +
                    923:                        sizeof(struct ip6_hdr);
                    924:                struct ip6ctlparam ip6cp;
                    925:                struct in6_addr *finaldst = NULL;
                    926:                int icmp6type = icmp6->icmp6_type;
                    927:                struct ip6_frag *fh;
                    928:                struct ip6_rthdr *rth;
                    929:                struct ip6_rthdr0 *rth0;
                    930:                int rthlen;
                    931:
                    932:                while (1) { /* XXX: should avoid infinite loop explicitly? */
                    933:                        struct ip6_ext *eh;
                    934:
                    935:                        switch (nxt) {
                    936:                        case IPPROTO_HOPOPTS:
                    937:                        case IPPROTO_DSTOPTS:
                    938:                        case IPPROTO_AH:
                    939:                                IP6_EXTHDR_GET(eh, struct ip6_ext *, m,
                    940:                                               eoff, sizeof(*eh));
                    941:                                if (eh == NULL) {
                    942:                                        icmp6stat.icp6s_tooshort++;
                    943:                                        return (-1);
                    944:                                }
                    945:
                    946:                                if (nxt == IPPROTO_AH)
                    947:                                        eoff += (eh->ip6e_len + 2) << 2;
                    948:                                else
                    949:                                        eoff += (eh->ip6e_len + 1) << 3;
                    950:                                nxt = eh->ip6e_nxt;
                    951:                                break;
                    952:                        case IPPROTO_ROUTING:
                    953:                                /*
                    954:                                 * When the erroneous packet contains a
                    955:                                 * routing header, we should examine the
                    956:                                 * header to determine the final destination.
                    957:                                 * Otherwise, we can't properly update
                    958:                                 * information that depends on the final
                    959:                                 * destination (e.g. path MTU).
                    960:                                 */
                    961:                                IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m,
                    962:                                               eoff, sizeof(*rth));
                    963:                                if (rth == NULL) {
                    964:                                        icmp6stat.icp6s_tooshort++;
                    965:                                        return (-1);
                    966:                                }
                    967:                                rthlen = (rth->ip6r_len + 1) << 3;
                    968:                                /*
                    969:                                 * XXX: currently there is no
                    970:                                 * officially defined type other
                    971:                                 * than type-0.
                    972:                                 * Note that if the segment left field
                    973:                                 * is 0, all intermediate hops must
                    974:                                 * have been passed.
                    975:                                 */
                    976:                                if (rth->ip6r_segleft &&
                    977:                                    rth->ip6r_type == IPV6_RTHDR_TYPE_0) {
                    978:                                        int hops;
                    979:
                    980:                                        IP6_EXTHDR_GET(rth0,
                    981:                                                       struct ip6_rthdr0 *, m,
                    982:                                                       eoff, rthlen);
                    983:                                        if (rth0 == NULL) {
                    984:                                                icmp6stat.icp6s_tooshort++;
                    985:                                                return (-1);
                    986:                                        }
                    987:                                        /* just ignore a bogus header */
                    988:                                        if ((rth0->ip6r0_len % 2) == 0 &&
                    989:                                            (hops = rth0->ip6r0_len/2))
                    990:                                                finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1);
                    991:                                }
                    992:                                eoff += rthlen;
                    993:                                nxt = rth->ip6r_nxt;
                    994:                                break;
                    995:                        case IPPROTO_FRAGMENT:
                    996:                                IP6_EXTHDR_GET(fh, struct ip6_frag *, m,
                    997:                                               eoff, sizeof(*fh));
                    998:                                if (fh == NULL) {
                    999:                                        icmp6stat.icp6s_tooshort++;
                   1000:                                        return (-1);
                   1001:                                }
                   1002:                                /*
                   1003:                                 * Data after a fragment header is meaningless
                   1004:                                 * unless it is the first fragment, but
                   1005:                                 * we'll go to the notify label for path MTU
                   1006:                                 * discovery.
                   1007:                                 */
                   1008:                                if (fh->ip6f_offlg & IP6F_OFF_MASK)
                   1009:                                        goto notify;
                   1010:
                   1011:                                eoff += sizeof(struct ip6_frag);
                   1012:                                nxt = fh->ip6f_nxt;
                   1013:                                break;
                   1014:                        default:
                   1015:                                /*
                   1016:                                 * This case includes ESP and the No Next
                   1017:                                 * Header.  In such cases going to the notify
                   1018:                                 * label does not have any meaning
                   1019:                                 * (i.e. ctlfunc will be NULL), but we go
                   1020:                                 * anyway since we might have to update
                   1021:                                 * path MTU information.
                   1022:                                 */
                   1023:                                goto notify;
                   1024:                        }
                   1025:                }
                   1026:          notify:
                   1027:                IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
                   1028:                               sizeof(*icmp6) + sizeof(struct ip6_hdr));
                   1029:                if (icmp6 == NULL) {
                   1030:                        icmp6stat.icp6s_tooshort++;
                   1031:                        return (-1);
                   1032:                }
                   1033:
                   1034:                eip6 = (struct ip6_hdr *)(icmp6 + 1);
                   1035:                bzero(&icmp6dst, sizeof(icmp6dst));
                   1036:                icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
                   1037:                icmp6dst.sin6_family = AF_INET6;
                   1038:                if (finaldst == NULL)
                   1039:                        icmp6dst.sin6_addr = eip6->ip6_dst;
                   1040:                else
                   1041:                        icmp6dst.sin6_addr = *finaldst;
                   1042:                icmp6dst.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
                   1043:                                                          &icmp6dst.sin6_addr);
                   1044:                if (in6_embedscope(&icmp6dst.sin6_addr, &icmp6dst,
                   1045:                                   NULL, NULL)) {
                   1046:                        /* should be impossbile */
                   1047:                        nd6log((LOG_DEBUG,
                   1048:                            "icmp6_notify_error: in6_embedscope failed\n"));
                   1049:                        goto freeit;
                   1050:                }
                   1051:
                   1052:                /*
                   1053:                 * retrieve parameters from the inner IPv6 header, and convert
                   1054:                 * them into sockaddr structures.
                   1055:                 */
                   1056:                bzero(&icmp6src, sizeof(icmp6src));
                   1057:                icmp6src.sin6_len = sizeof(struct sockaddr_in6);
                   1058:                icmp6src.sin6_family = AF_INET6;
                   1059:                icmp6src.sin6_addr = eip6->ip6_src;
                   1060:                icmp6src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
                   1061:                                                          &icmp6src.sin6_addr);
                   1062:                if (in6_embedscope(&icmp6src.sin6_addr, &icmp6src,
                   1063:                                   NULL, NULL)) {
                   1064:                        /* should be impossbile */
                   1065:                        nd6log((LOG_DEBUG,
                   1066:                            "icmp6_notify_error: in6_embedscope failed\n"));
                   1067:                        goto freeit;
                   1068:                }
                   1069:                icmp6src.sin6_flowinfo =
                   1070:                    (eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
                   1071:
                   1072:                if (finaldst == NULL)
                   1073:                        finaldst = &eip6->ip6_dst;
                   1074:                ip6cp.ip6c_m = m;
                   1075:                ip6cp.ip6c_icmp6 = icmp6;
                   1076:                ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
                   1077:                ip6cp.ip6c_off = eoff;
                   1078:                ip6cp.ip6c_finaldst = finaldst;
                   1079:                ip6cp.ip6c_src = &icmp6src;
                   1080:                ip6cp.ip6c_nxt = nxt;
                   1081:
                   1082:                if (icmp6type == ICMP6_PACKET_TOO_BIG) {
                   1083:                        notifymtu = ntohl(icmp6->icmp6_mtu);
                   1084:                        ip6cp.ip6c_cmdarg = (void *)&notifymtu;
                   1085:                }
                   1086:
                   1087:                ctlfunc = (void (*)(int, struct sockaddr *, void *))
                   1088:                        (inet6sw[ip6_protox[nxt]].pr_ctlinput);
                   1089:                if (ctlfunc) {
                   1090:                        (void) (*ctlfunc)(code, (struct sockaddr *)&icmp6dst,
                   1091:                                          &ip6cp);
                   1092:                }
                   1093:        }
                   1094:        return (0);
                   1095:
                   1096:   freeit:
                   1097:        m_freem(m);
                   1098:        return (-1);
                   1099: }
                   1100:
                   1101: void
                   1102: icmp6_mtudisc_update(ip6cp, validated)
                   1103:        struct ip6ctlparam *ip6cp;
                   1104:        int validated;
                   1105: {
                   1106:        unsigned long rtcount;
                   1107:        struct icmp6_mtudisc_callback *mc;
                   1108:        struct in6_addr *dst = ip6cp->ip6c_finaldst;
                   1109:        struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6;
                   1110:        struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */
                   1111:        u_int mtu = ntohl(icmp6->icmp6_mtu);
                   1112:        struct rtentry *rt = NULL;
                   1113:        struct sockaddr_in6 sin6;
                   1114:
                   1115:        /*
                   1116:         * allow non-validated cases if memory is plenty, to make traffic
                   1117:         * from non-connected pcb happy.
                   1118:         */
                   1119:        rtcount = rt_timer_count(icmp6_mtudisc_timeout_q);
                   1120:        if (validated) {
                   1121:                if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat)
                   1122:                        return;
                   1123:                else if (0 <= icmp6_mtudisc_lowat &&
                   1124:                    rtcount > icmp6_mtudisc_lowat) {
                   1125:                        /*
                   1126:                         * XXX nuke a victim, install the new one.
                   1127:                         */
                   1128:                }
                   1129:        } else {
                   1130:                if (0 <= icmp6_mtudisc_lowat && rtcount > icmp6_mtudisc_lowat)
                   1131:                        return;
                   1132:        }
                   1133:
                   1134:        bzero(&sin6, sizeof(sin6));
                   1135:        sin6.sin6_family = PF_INET6;
                   1136:        sin6.sin6_len = sizeof(struct sockaddr_in6);
                   1137:        sin6.sin6_addr = *dst;
                   1138:        /* XXX normally, this won't happen */
                   1139:        if (IN6_IS_ADDR_LINKLOCAL(dst)) {
                   1140:                sin6.sin6_addr.s6_addr16[1] =
                   1141:                    htons(m->m_pkthdr.rcvif->if_index);
                   1142:        }
                   1143:        /* sin6.sin6_scope_id = XXX: should be set if DST is a scoped addr */
                   1144:        rt = icmp6_mtudisc_clone((struct sockaddr *)&sin6);
                   1145:
                   1146:        if (rt && (rt->rt_flags & RTF_HOST) &&
                   1147:            !(rt->rt_rmx.rmx_locks & RTV_MTU) &&
                   1148:            (rt->rt_rmx.rmx_mtu > mtu || rt->rt_rmx.rmx_mtu == 0)) {
                   1149:                if (mtu < IN6_LINKMTU(rt->rt_ifp)) {
                   1150:                        icmp6stat.icp6s_pmtuchg++;
                   1151:                        rt->rt_rmx.rmx_mtu = mtu;
                   1152:                }
                   1153:        }
                   1154:        if (rt) { /* XXX: need braces to avoid conflict with else in RTFREE. */
                   1155:                RTFREE(rt);
                   1156:        }
                   1157:
                   1158:        /*
                   1159:         * Notify protocols that the MTU for this destination
                   1160:         * has changed.
                   1161:         */
                   1162:        for (mc = LIST_FIRST(&icmp6_mtudisc_callbacks); mc != NULL;
                   1163:             mc = LIST_NEXT(mc, mc_list))
                   1164:                (*mc->mc_func)(&sin6.sin6_addr);
                   1165: }
                   1166:
                   1167: /*
                   1168:  * Process a Node Information Query packet, based on
                   1169:  * draft-ietf-ipngwg-icmp-name-lookups-07.
                   1170:  *
                   1171:  * Spec incompatibilities:
                   1172:  * - IPv6 Subject address handling
                   1173:  * - IPv4 Subject address handling support missing
                   1174:  * - Proxy reply (answer even if it's not for me)
                   1175:  * - joins NI group address at in6_ifattach() time only, does not cope
                   1176:  *   with hostname changes by sethostname(3)
                   1177:  */
                   1178: #ifndef offsetof               /* XXX */
                   1179: #define        offsetof(type, member)  ((size_t)(&((type *)0)->member))
                   1180: #endif
                   1181: static struct mbuf *
                   1182: ni6_input(m, off)
                   1183:        struct mbuf *m;
                   1184:        int off;
                   1185: {
                   1186:        struct icmp6_nodeinfo *ni6, *nni6;
                   1187:        struct mbuf *n = NULL;
                   1188:        u_int16_t qtype;
                   1189:        int subjlen;
                   1190:        int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
                   1191:        struct ni_reply_fqdn *fqdn;
                   1192:        int addrs;              /* for NI_QTYPE_NODEADDR */
                   1193:        struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */
                   1194:        struct sockaddr_in6 sin6; /* double meaning; ip6_dst and subjectaddr */
                   1195:        struct ip6_hdr *ip6;
                   1196:        int oldfqdn = 0;        /* if 1, return pascal string (03 draft) */
                   1197:        char *subj = NULL;
                   1198:
                   1199:        ip6 = mtod(m, struct ip6_hdr *);
                   1200:        IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6));
                   1201:        if (ni6 == NULL) {
                   1202:                /* m is already reclaimed */
                   1203:                return NULL;
                   1204:        }
                   1205:
                   1206:        /*
                   1207:         * Validate IPv6 destination address.
                   1208:         *
                   1209:         * The Responder must discard the Query without further processing
                   1210:         * unless it is one of the Responder's unicast or anycast addresses, or
                   1211:         * a link-local scope multicast address which the Responder has joined.
                   1212:         * [icmp-name-lookups-07, Section 4.]
                   1213:         */
                   1214:        bzero(&sin6, sizeof(sin6));
                   1215:        sin6.sin6_family = AF_INET6;
                   1216:        sin6.sin6_len = sizeof(struct sockaddr_in6);
                   1217:        bcopy(&ip6->ip6_dst, &sin6.sin6_addr, sizeof(sin6.sin6_addr));
                   1218:        /* XXX scopeid */
                   1219:        if (ifa_ifwithaddr((struct sockaddr *)&sin6))
                   1220:                ; /* unicast/anycast, fine */
                   1221:        else if (IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr))
                   1222:                ; /* link-local multicast, fine */
                   1223:        else
                   1224:                goto bad;
                   1225:
                   1226:        /* validate query Subject field. */
                   1227:        qtype = ntohs(ni6->ni_qtype);
                   1228:        subjlen = m->m_pkthdr.len - off - sizeof(struct icmp6_nodeinfo);
                   1229:        switch (qtype) {
                   1230:        case NI_QTYPE_NOOP:
                   1231:        case NI_QTYPE_SUPTYPES:
                   1232:                /* 07 draft */
                   1233:                if (ni6->ni_code == ICMP6_NI_SUBJ_FQDN && subjlen == 0)
                   1234:                        break;
                   1235:                /* FALLTHROUGH */
                   1236:        case NI_QTYPE_FQDN:
                   1237:        case NI_QTYPE_NODEADDR:
                   1238:                switch (ni6->ni_code) {
                   1239:                case ICMP6_NI_SUBJ_IPV6:
                   1240: #if ICMP6_NI_SUBJ_IPV6 != 0
                   1241:                case 0:
                   1242: #endif
                   1243:                        /*
                   1244:                         * backward compatibility - try to accept 03 draft
                   1245:                         * format, where no Subject is present.
                   1246:                         */
                   1247:                        if (qtype == NI_QTYPE_FQDN && ni6->ni_code == 0 &&
                   1248:                            subjlen == 0) {
                   1249:                                oldfqdn++;
                   1250:                                break;
                   1251:                        }
                   1252: #if ICMP6_NI_SUBJ_IPV6 != 0
                   1253:                        if (ni6->ni_code != ICMP6_NI_SUBJ_IPV6)
                   1254:                                goto bad;
                   1255: #endif
                   1256:
                   1257:                        if (subjlen != sizeof(sin6.sin6_addr))
                   1258:                                goto bad;
                   1259:
                   1260:                        /*
                   1261:                         * Validate Subject address.
                   1262:                         *
                   1263:                         * Not sure what exactly "address belongs to the node"
                   1264:                         * means in the spec, is it just unicast, or what?
                   1265:                         *
                   1266:                         * At this moment we consider Subject address as
                   1267:                         * "belong to the node" if the Subject address equals
                   1268:                         * to the IPv6 destination address; validation for
                   1269:                         * IPv6 destination address should have done enough
                   1270:                         * check for us.
                   1271:                         *
                   1272:                         * We do not do proxy at this moment.
                   1273:                         */
                   1274:                        /* m_pulldown instead of copy? */
                   1275:                        m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
                   1276:                            subjlen, (caddr_t)&sin6.sin6_addr);
                   1277:                        /* XXX kame scope hack */
                   1278:                        if (IN6_IS_SCOPE_EMBED(&sin6.sin6_addr)) {
                   1279:                                if ((m->m_flags & M_PKTHDR) != 0 &&
                   1280:                                    m->m_pkthdr.rcvif) {
                   1281:                                        sin6.sin6_addr.s6_addr16[1] =
                   1282:                                            htons(m->m_pkthdr.rcvif->if_index);
                   1283:                                }
                   1284:                        }
                   1285:                        subj = (char *)&sin6;
                   1286:                        if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &sin6.sin6_addr))
                   1287:                                break;
                   1288:
                   1289:                        /*
                   1290:                         * XXX if we are to allow other cases, we should really
                   1291:                         * be careful about scope here.
                   1292:                         * basically, we should disallow queries toward IPv6
                   1293:                         * destination X with subject Y, if scope(X) > scope(Y).
                   1294:                         * if we allow scope(X) > scope(Y), it will result in
                   1295:                         * information leakage across scope boundary.
                   1296:                         */
                   1297:                        goto bad;
                   1298:
                   1299:                case ICMP6_NI_SUBJ_FQDN:
                   1300:                        /*
                   1301:                         * Validate Subject name with gethostname(3).
                   1302:                         *
                   1303:                         * The behavior may need some debate, since:
                   1304:                         * - we are not sure if the node has FQDN as
                   1305:                         *   hostname (returned by gethostname(3)).
                   1306:                         * - the code does wildcard match for truncated names.
                   1307:                         *   however, we are not sure if we want to perform
                   1308:                         *   wildcard match, if gethostname(3) side has
                   1309:                         *   truncated hostname.
                   1310:                         */
                   1311:                        n = ni6_nametodns(hostname, hostnamelen, 0);
                   1312:                        if (!n || n->m_next || n->m_len == 0)
                   1313:                                goto bad;
                   1314:                        IP6_EXTHDR_GET(subj, char *, m,
                   1315:                            off + sizeof(struct icmp6_nodeinfo), subjlen);
                   1316:                        if (subj == NULL)
                   1317:                                goto bad;
                   1318:                        if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *),
                   1319:                                        n->m_len)) {
                   1320:                                goto bad;
                   1321:                        }
                   1322:                        m_freem(n);
                   1323:                        n = NULL;
                   1324:                        break;
                   1325:
                   1326:                case ICMP6_NI_SUBJ_IPV4:        /* XXX: to be implemented? */
                   1327:                default:
                   1328:                        goto bad;
                   1329:                }
                   1330:                break;
                   1331:        }
                   1332:
                   1333:        /* refuse based on configuration.  XXX ICMP6_NI_REFUSED? */
                   1334:        switch (qtype) {
                   1335:        case NI_QTYPE_FQDN:
                   1336:                if ((icmp6_nodeinfo & 1) == 0)
                   1337:                        goto bad;
                   1338:                break;
                   1339:        case NI_QTYPE_NODEADDR:
                   1340:                if ((icmp6_nodeinfo & 2) == 0)
                   1341:                        goto bad;
                   1342:                break;
                   1343:        }
                   1344:
                   1345:        /* guess reply length */
                   1346:        switch (qtype) {
                   1347:        case NI_QTYPE_NOOP:
                   1348:                break;          /* no reply data */
                   1349:        case NI_QTYPE_SUPTYPES:
                   1350:                replylen += sizeof(u_int32_t);
                   1351:                break;
                   1352:        case NI_QTYPE_FQDN:
                   1353:                /* XXX will append an mbuf */
                   1354:                replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
                   1355:                break;
                   1356:        case NI_QTYPE_NODEADDR:
                   1357:                addrs = ni6_addrs(ni6, m, &ifp, subj);
                   1358:                if ((replylen += addrs * (sizeof(struct in6_addr) +
                   1359:                                          sizeof(u_int32_t))) > MCLBYTES)
                   1360:                        replylen = MCLBYTES; /* XXX: will truncate pkt later */
                   1361:                break;
                   1362:        default:
                   1363:                /*
                   1364:                 * XXX: We must return a reply with the ICMP6 code
                   1365:                 * `unknown Qtype' in this case.  However we regard the case
                   1366:                 * as an FQDN query for backward compatibility.
                   1367:                 * Older versions set a random value to this field,
                   1368:                 * so it rarely varies in the defined qtypes.
                   1369:                 * But the mechanism is not reliable...
                   1370:                 * maybe we should obsolete older versions.
                   1371:                 */
                   1372:                qtype = NI_QTYPE_FQDN;
                   1373:                /* XXX will append an mbuf */
                   1374:                replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
                   1375:                oldfqdn++;
                   1376:                break;
                   1377:        }
                   1378:
                   1379:        /* allocate an mbuf to reply. */
                   1380:        MGETHDR(n, M_DONTWAIT, m->m_type);
                   1381:        if (n == NULL) {
                   1382:                m_freem(m);
                   1383:                return (NULL);
                   1384:        }
                   1385:        M_DUP_PKTHDR(n, m); /* just for rcvif */
                   1386:        if (replylen > MHLEN) {
                   1387:                if (replylen > MCLBYTES) {
                   1388:                        /*
                   1389:                         * XXX: should we try to allocate more? But MCLBYTES
                   1390:                         * is probably much larger than IPV6_MMTU...
                   1391:                         */
                   1392:                        goto bad;
                   1393:                }
                   1394:                MCLGET(n, M_DONTWAIT);
                   1395:                if ((n->m_flags & M_EXT) == 0) {
                   1396:                        goto bad;
                   1397:                }
                   1398:        }
                   1399:        n->m_pkthdr.len = n->m_len = replylen;
                   1400:
                   1401:        /* copy mbuf header and IPv6 + Node Information base headers */
                   1402:        bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr));
                   1403:        nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1);
                   1404:        bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo));
                   1405:
                   1406:        /* qtype dependent procedure */
                   1407:        switch (qtype) {
                   1408:        case NI_QTYPE_NOOP:
                   1409:                nni6->ni_code = ICMP6_NI_SUCCESS;
                   1410:                nni6->ni_flags = 0;
                   1411:                break;
                   1412:        case NI_QTYPE_SUPTYPES:
                   1413:        {
                   1414:                u_int32_t v;
                   1415:                nni6->ni_code = ICMP6_NI_SUCCESS;
                   1416:                nni6->ni_flags = htons(0x0000); /* raw bitmap */
                   1417:                /* supports NOOP, SUPTYPES, FQDN, and NODEADDR */
                   1418:                v = (u_int32_t)htonl(0x0000000f);
                   1419:                bcopy(&v, nni6 + 1, sizeof(u_int32_t));
                   1420:                break;
                   1421:        }
                   1422:        case NI_QTYPE_FQDN:
                   1423:                nni6->ni_code = ICMP6_NI_SUCCESS;
                   1424:                fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) +
                   1425:                                                sizeof(struct ip6_hdr) +
                   1426:                                                sizeof(struct icmp6_nodeinfo));
                   1427:                nni6->ni_flags = 0; /* XXX: meaningless TTL */
                   1428:                fqdn->ni_fqdn_ttl = 0;  /* ditto. */
                   1429:                /*
                   1430:                 * XXX do we really have FQDN in variable "hostname"?
                   1431:                 */
                   1432:                n->m_next = ni6_nametodns(hostname, hostnamelen, oldfqdn);
                   1433:                if (n->m_next == NULL)
                   1434:                        goto bad;
                   1435:                /* XXX we assume that n->m_next is not a chain */
                   1436:                if (n->m_next->m_next != NULL)
                   1437:                        goto bad;
                   1438:                n->m_pkthdr.len += n->m_next->m_len;
                   1439:                break;
                   1440:        case NI_QTYPE_NODEADDR:
                   1441:        {
                   1442:                int lenlim, copied;
                   1443:
                   1444:                nni6->ni_code = ICMP6_NI_SUCCESS;
                   1445:                n->m_pkthdr.len = n->m_len =
                   1446:                    sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
                   1447:                lenlim = M_TRAILINGSPACE(n);
                   1448:                copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
                   1449:                /* XXX: reset mbuf length */
                   1450:                n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
                   1451:                        sizeof(struct icmp6_nodeinfo) + copied;
                   1452:                break;
                   1453:        }
                   1454:        default:
                   1455:                break;          /* XXX impossible! */
                   1456:        }
                   1457:
                   1458:        nni6->ni_type = ICMP6_NI_REPLY;
                   1459:        m_freem(m);
                   1460:        return (n);
                   1461:
                   1462:   bad:
                   1463:        m_freem(m);
                   1464:        if (n)
                   1465:                m_freem(n);
                   1466:        return (NULL);
                   1467: }
                   1468: #undef hostnamelen
                   1469:
                   1470: #define isupper(x) ('A' <= (x) && (x) <= 'Z')
                   1471: #define isalpha(x) (('A' <= (x) && (x) <= 'Z') || ('a' <= (x) && (x) <= 'z'))
                   1472: #define isalnum(x) (isalpha(x) || ('0' <= (x) && (x) <= '9'))
                   1473: #define tolower(x) (isupper(x) ? (x) + 'a' - 'A' : (x))
                   1474:
                   1475: /*
                   1476:  * make a mbuf with DNS-encoded string.  no compression support.
                   1477:  *
                   1478:  * XXX names with less than 2 dots (like "foo" or "foo.section") will be
                   1479:  * treated as truncated name (two \0 at the end).  this is a wild guess.
                   1480:  */
                   1481: static struct mbuf *
                   1482: ni6_nametodns(name, namelen, old)
                   1483:        const char *name;
                   1484:        int namelen;
                   1485:        int old;        /* return pascal string if non-zero */
                   1486: {
                   1487:        struct mbuf *m;
                   1488:        char *cp, *ep;
                   1489:        const char *p, *q;
                   1490:        int i, len, nterm;
                   1491:
                   1492:        if (old)
                   1493:                len = namelen + 1;
                   1494:        else
                   1495:                len = MCLBYTES;
                   1496:
                   1497:        /* because MAXHOSTNAMELEN is usually 256, we use cluster mbuf */
                   1498:        MGET(m, M_DONTWAIT, MT_DATA);
                   1499:        if (m && len > MLEN) {
                   1500:                MCLGET(m, M_DONTWAIT);
                   1501:                if ((m->m_flags & M_EXT) == 0)
                   1502:                        goto fail;
                   1503:        }
                   1504:        if (!m)
                   1505:                goto fail;
                   1506:        m->m_next = NULL;
                   1507:
                   1508:        if (old) {
                   1509:                m->m_len = len;
                   1510:                *mtod(m, char *) = namelen;
                   1511:                bcopy(name, mtod(m, char *) + 1, namelen);
                   1512:                return m;
                   1513:        } else {
                   1514:                m->m_len = 0;
                   1515:                cp = mtod(m, char *);
                   1516:                ep = mtod(m, char *) + M_TRAILINGSPACE(m);
                   1517:
                   1518:                /* if not certain about my name, return empty buffer */
                   1519:                if (namelen == 0)
                   1520:                        return m;
                   1521:
                   1522:                /*
                   1523:                 * guess if it looks like shortened hostname, or FQDN.
                   1524:                 * shortened hostname needs two trailing "\0".
                   1525:                 */
                   1526:                i = 0;
                   1527:                for (p = name; p < name + namelen; p++) {
                   1528:                        if (*p && *p == '.')
                   1529:                                i++;
                   1530:                }
                   1531:                if (i < 2)
                   1532:                        nterm = 2;
                   1533:                else
                   1534:                        nterm = 1;
                   1535:
                   1536:                p = name;
                   1537:                while (cp < ep && p < name + namelen) {
                   1538:                        i = 0;
                   1539:                        for (q = p; q < name + namelen && *q && *q != '.'; q++)
                   1540:                                i++;
                   1541:                        /* result does not fit into mbuf */
                   1542:                        if (cp + i + 1 >= ep)
                   1543:                                goto fail;
                   1544:                        /*
                   1545:                         * DNS label length restriction, RFC1035 page 8.
                   1546:                         * "i == 0" case is included here to avoid returning
                   1547:                         * 0-length label on "foo..bar".
                   1548:                         */
                   1549:                        if (i <= 0 || i >= 64)
                   1550:                                goto fail;
                   1551:                        *cp++ = i;
                   1552:                        if (!isalpha(p[0]) || !isalnum(p[i - 1]))
                   1553:                                goto fail;
                   1554:                        while (i > 0) {
                   1555:                                if (!isalnum(*p) && *p != '-')
                   1556:                                        goto fail;
                   1557:                                if (isupper(*p)) {
                   1558:                                        *cp++ = tolower(*p);
                   1559:                                        p++;
                   1560:                                } else
                   1561:                                        *cp++ = *p++;
                   1562:                                i--;
                   1563:                        }
                   1564:                        p = q;
                   1565:                        if (p < name + namelen && *p == '.')
                   1566:                                p++;
                   1567:                }
                   1568:                /* termination */
                   1569:                if (cp + nterm >= ep)
                   1570:                        goto fail;
                   1571:                while (nterm-- > 0)
                   1572:                        *cp++ = '\0';
                   1573:                m->m_len = cp - mtod(m, char *);
                   1574:                return m;
                   1575:        }
                   1576:
                   1577:        panic("should not reach here");
                   1578:        /* NOTREACHED */
                   1579:
                   1580:  fail:
                   1581:        if (m)
                   1582:                m_freem(m);
                   1583:        return NULL;
                   1584: }
                   1585:
                   1586: /*
                   1587:  * check if two DNS-encoded string matches.  takes care of truncated
                   1588:  * form (with \0\0 at the end).  no compression support.
                   1589:  * XXX upper/lowercase match (see RFC2065)
                   1590:  */
                   1591: static int
                   1592: ni6_dnsmatch(a, alen, b, blen)
                   1593:        const char *a;
                   1594:        int alen;
                   1595:        const char *b;
                   1596:        int blen;
                   1597: {
                   1598:        const char *a0, *b0;
                   1599:        int l;
                   1600:
                   1601:        /* simplest case - need validation? */
                   1602:        if (alen == blen && bcmp(a, b, alen) == 0)
                   1603:                return 1;
                   1604:
                   1605:        a0 = a;
                   1606:        b0 = b;
                   1607:
                   1608:        /* termination is mandatory */
                   1609:        if (alen < 2 || blen < 2)
                   1610:                return 0;
                   1611:        if (a0[alen - 1] != '\0' || b0[blen - 1] != '\0')
                   1612:                return 0;
                   1613:        alen--;
                   1614:        blen--;
                   1615:
                   1616:        while (a - a0 < alen && b - b0 < blen) {
                   1617:                if (a - a0 + 1 > alen || b - b0 + 1 > blen)
                   1618:                        return 0;
                   1619:
                   1620:                if ((signed char)a[0] < 0 || (signed char)b[0] < 0)
                   1621:                        return 0;
                   1622:                /* we don't support compression yet */
                   1623:                if (a[0] >= 64 || b[0] >= 64)
                   1624:                        return 0;
                   1625:
                   1626:                /* truncated case */
                   1627:                if (a[0] == 0 && a - a0 == alen - 1)
                   1628:                        return 1;
                   1629:                if (b[0] == 0 && b - b0 == blen - 1)
                   1630:                        return 1;
                   1631:                if (a[0] == 0 || b[0] == 0)
                   1632:                        return 0;
                   1633:
                   1634:                if (a[0] != b[0])
                   1635:                        return 0;
                   1636:                l = a[0];
                   1637:                if (a - a0 + 1 + l > alen || b - b0 + 1 + l > blen)
                   1638:                        return 0;
                   1639:                if (bcmp(a + 1, b + 1, l) != 0)
                   1640:                        return 0;
                   1641:
                   1642:                a += 1 + l;
                   1643:                b += 1 + l;
                   1644:        }
                   1645:
                   1646:        if (a - a0 == alen && b - b0 == blen)
                   1647:                return 1;
                   1648:        else
                   1649:                return 0;
                   1650: }
                   1651:
                   1652: /*
                   1653:  * calculate the number of addresses to be returned in the node info reply.
                   1654:  */
                   1655: static int
                   1656: ni6_addrs(ni6, m, ifpp, subj)
                   1657:        struct icmp6_nodeinfo *ni6;
                   1658:        struct mbuf *m;
                   1659:        struct ifnet **ifpp;
                   1660:        char *subj;
                   1661: {
                   1662:        struct ifnet *ifp;
                   1663:        struct in6_ifaddr *ifa6;
                   1664:        struct ifaddr *ifa;
                   1665:        struct sockaddr_in6 *subj_ip6 = NULL; /* XXX pedant */
                   1666:        int addrs = 0, addrsofif, iffound = 0;
                   1667:        int niflags = ni6->ni_flags;
                   1668:
                   1669:        if ((niflags & NI_NODEADDR_FLAG_ALL) == 0) {
                   1670:                switch (ni6->ni_code) {
                   1671:                case ICMP6_NI_SUBJ_IPV6:
                   1672:                        if (subj == NULL) /* must be impossible... */
                   1673:                                return (0);
                   1674:                        subj_ip6 = (struct sockaddr_in6 *)subj;
                   1675:                        break;
                   1676:                default:
                   1677:                        /*
                   1678:                         * XXX: we only support IPv6 subject address for
                   1679:                         * this Qtype.
                   1680:                         */
                   1681:                        return (0);
                   1682:                }
                   1683:        }
                   1684:
                   1685:        TAILQ_FOREACH(ifp, &ifnet, if_list) {
                   1686:                addrsofif = 0;
                   1687:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   1688:                        if (ifa->ifa_addr->sa_family != AF_INET6)
                   1689:                                continue;
                   1690:                        ifa6 = (struct in6_ifaddr *)ifa;
                   1691:
                   1692:                        if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 &&
                   1693:                            IN6_ARE_ADDR_EQUAL(&subj_ip6->sin6_addr,
                   1694:                                               &ifa6->ia_addr.sin6_addr))
                   1695:                                iffound = 1;
                   1696:
                   1697:                        /*
                   1698:                         * IPv4-mapped addresses can only be returned by a
                   1699:                         * Node Information proxy, since they represent
                   1700:                         * addresses of IPv4-only nodes, which perforce do
                   1701:                         * not implement this protocol.
                   1702:                         * [icmp-name-lookups-07, Section 5.4]
                   1703:                         * So we don't support NI_NODEADDR_FLAG_COMPAT in
                   1704:                         * this function at this moment.
                   1705:                         */
                   1706:
                   1707:                        /* What do we have to do about ::1? */
                   1708:                        switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
                   1709:                        case IPV6_ADDR_SCOPE_LINKLOCAL:
                   1710:                                if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)
                   1711:                                        continue;
                   1712:                                break;
                   1713:                        case IPV6_ADDR_SCOPE_SITELOCAL:
                   1714:                                if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)
                   1715:                                        continue;
                   1716:                                break;
                   1717:                        case IPV6_ADDR_SCOPE_GLOBAL:
                   1718:                                if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)
                   1719:                                        continue;
                   1720:                                break;
                   1721:                        default:
                   1722:                                continue;
                   1723:                        }
                   1724:
                   1725:                        /*
                   1726:                         * check if anycast is okay.
                   1727:                         * XXX: just experimental.  not in the spec.
                   1728:                         */
                   1729:                        if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
                   1730:                            (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
                   1731:                                continue; /* we need only unicast addresses */
                   1732:
                   1733:                        addrsofif++; /* count the address */
                   1734:                }
                   1735:                if (iffound) {
                   1736:                        *ifpp = ifp;
                   1737:                        return (addrsofif);
                   1738:                }
                   1739:
                   1740:                addrs += addrsofif;
                   1741:        }
                   1742:
                   1743:        return (addrs);
                   1744: }
                   1745:
                   1746: static int
                   1747: ni6_store_addrs(ni6, nni6, ifp0, resid)
                   1748:        struct icmp6_nodeinfo *ni6, *nni6;
                   1749:        struct ifnet *ifp0;
                   1750:        int resid;
                   1751: {
                   1752:        struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&ifnet);
                   1753:        struct in6_ifaddr *ifa6;
                   1754:        struct ifaddr *ifa;
                   1755:        struct ifnet *ifp_dep = NULL;
                   1756:        int copied = 0, allow_deprecated = 0;
                   1757:        u_char *cp = (u_char *)(nni6 + 1);
                   1758:        int niflags = ni6->ni_flags;
                   1759:        u_int32_t ltime;
                   1760:
                   1761:        if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL))
                   1762:                return (0);     /* needless to copy */
                   1763:
                   1764:   again:
                   1765:
                   1766:        for (; ifp != TAILQ_END(&ifnet); ifp = TAILQ_NEXT(ifp, if_list)) {
                   1767:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   1768:                        if (ifa->ifa_addr->sa_family != AF_INET6)
                   1769:                                continue;
                   1770:                        ifa6 = (struct in6_ifaddr *)ifa;
                   1771:
                   1772:                        if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) != 0 &&
                   1773:                            allow_deprecated == 0) {
                   1774:                                /*
                   1775:                                 * prefererred address should be put before
                   1776:                                 * deprecated addresses.
                   1777:                                 */
                   1778:
                   1779:                                /* record the interface for later search */
                   1780:                                if (ifp_dep == NULL)
                   1781:                                        ifp_dep = ifp;
                   1782:
                   1783:                                continue;
                   1784:                        }
                   1785:                        else if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) == 0 &&
                   1786:                                 allow_deprecated != 0)
                   1787:                                continue; /* we now collect deprecated addrs */
                   1788:
                   1789:                        /* What do we have to do about ::1? */
                   1790:                        switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {
                   1791:                        case IPV6_ADDR_SCOPE_LINKLOCAL:
                   1792:                                if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)
                   1793:                                        continue;
                   1794:                                break;
                   1795:                        case IPV6_ADDR_SCOPE_SITELOCAL:
                   1796:                                if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)
                   1797:                                        continue;
                   1798:                                break;
                   1799:                        case IPV6_ADDR_SCOPE_GLOBAL:
                   1800:                                if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)
                   1801:                                        continue;
                   1802:                                break;
                   1803:                        default:
                   1804:                                continue;
                   1805:                        }
                   1806:
                   1807:                        /*
                   1808:                         * check if anycast is okay.
                   1809:                         * XXX: just experimental.  not in the spec.
                   1810:                         */
                   1811:                        if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&
                   1812:                            (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)
                   1813:                                continue;
                   1814:
                   1815:                        /* now we can copy the address */
                   1816:                        if (resid < sizeof(struct in6_addr) +
                   1817:                            sizeof(u_int32_t)) {
                   1818:                                /*
                   1819:                                 * We give up much more copy.
                   1820:                                 * Set the truncate flag and return.
                   1821:                                 */
                   1822:                                nni6->ni_flags |=
                   1823:                                        NI_NODEADDR_FLAG_TRUNCATE;
                   1824:                                return (copied);
                   1825:                        }
                   1826:
                   1827:                        /*
                   1828:                         * Set the TTL of the address.
                   1829:                         * The TTL value should be one of the following
                   1830:                         * according to the specification:
                   1831:                         *
                   1832:                         * 1. The remaining lifetime of a DHCP lease on the
                   1833:                         *    address, or
                   1834:                         * 2. The remaining Valid Lifetime of a prefix from
                   1835:                         *    which the address was derived through Stateless
                   1836:                         *    Autoconfiguration.
                   1837:                         *
                   1838:                         * Note that we currently do not support stateful
                   1839:                         * address configuration by DHCPv6, so the former
                   1840:                         * case can't happen.
                   1841:                         *
                   1842:                         * TTL must be 2^31 > TTL >= 0.
                   1843:                         */
                   1844:                        if (ifa6->ia6_lifetime.ia6t_expire == 0)
                   1845:                                ltime = ND6_INFINITE_LIFETIME;
                   1846:                        else {
                   1847:                                if (ifa6->ia6_lifetime.ia6t_expire >
                   1848:                                    time_second)
                   1849:                                        ltime = htonl(ifa6->ia6_lifetime.ia6t_expire - time_second);
                   1850:                                else
                   1851:                                        ltime = 0;
                   1852:                        }
                   1853:
                   1854:                        bcopy(&ltime, cp, sizeof(u_int32_t));
                   1855:                        cp += sizeof(u_int32_t);
                   1856:
                   1857:                        /* copy the address itself */
                   1858:                        bcopy(&ifa6->ia_addr.sin6_addr, cp,
                   1859:                              sizeof(struct in6_addr));
                   1860:                        /* XXX: KAME link-local hack; remove ifindex */
                   1861:                        if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr))
                   1862:                                ((struct in6_addr *)cp)->s6_addr16[1] = 0;
                   1863:                        cp += sizeof(struct in6_addr);
                   1864:
                   1865:                        resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
                   1866:                        copied += (sizeof(struct in6_addr) +
                   1867:                                   sizeof(u_int32_t));
                   1868:                }
                   1869:                if (ifp0)       /* we need search only on the specified IF */
                   1870:                        break;
                   1871:        }
                   1872:
                   1873:        if (allow_deprecated == 0 && ifp_dep != NULL) {
                   1874:                ifp = ifp_dep;
                   1875:                allow_deprecated = 1;
                   1876:
                   1877:                goto again;
                   1878:        }
                   1879:
                   1880:        return (copied);
                   1881: }
                   1882:
                   1883: /*
                   1884:  * XXX almost dup'ed code with rip6_input.
                   1885:  */
                   1886: static int
                   1887: icmp6_rip6_input(mp, off)
                   1888:        struct  mbuf **mp;
                   1889:        int     off;
                   1890: {
                   1891:        struct mbuf *m = *mp;
                   1892:        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
                   1893:        struct in6pcb *in6p;
                   1894:        struct in6pcb *last = NULL;
                   1895:        struct sockaddr_in6 rip6src;
                   1896:        struct icmp6_hdr *icmp6;
                   1897:        struct mbuf *opts = NULL;
                   1898:
                   1899:        IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
                   1900:        if (icmp6 == NULL) {
                   1901:                /* m is already reclaimed */
                   1902:                return IPPROTO_DONE;
                   1903:        }
                   1904:
                   1905:        bzero(&rip6src, sizeof(rip6src));
                   1906:        rip6src.sin6_len = sizeof(struct sockaddr_in6);
                   1907:        rip6src.sin6_family = AF_INET6;
                   1908:        /* KAME hack: recover scopeid */
                   1909:        (void)in6_recoverscope(&rip6src, &ip6->ip6_src, m->m_pkthdr.rcvif);
                   1910:
                   1911:        CIRCLEQ_FOREACH(in6p, &rawin6pcbtable.inpt_queue, inp_queue) {
                   1912:                if (!(in6p->in6p_flags & INP_IPV6))
                   1913:                        continue;
                   1914:                if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)
                   1915:                        continue;
                   1916:                if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
                   1917:                   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
                   1918:                        continue;
                   1919:                if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
                   1920:                   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
                   1921:                        continue;
                   1922:                if (in6p->in6p_icmp6filt
                   1923:                    && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,
                   1924:                                 in6p->in6p_icmp6filt))
                   1925:                        continue;
                   1926:                if (last) {
                   1927:                        struct  mbuf *n;
                   1928:                        if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
                   1929:                                if (last->in6p_flags & IN6P_CONTROLOPTS)
                   1930:                                        ip6_savecontrol(last, n, &opts);
                   1931:                                /* strip intermediate headers */
                   1932:                                m_adj(n, off);
                   1933:                                if (sbappendaddr(&last->in6p_socket->so_rcv,
                   1934:                                                 (struct sockaddr *)&rip6src,
                   1935:                                                 n, opts) == 0) {
                   1936:                                        /* should notify about lost packet */
                   1937:                                        m_freem(n);
                   1938:                                        if (opts)
                   1939:                                                m_freem(opts);
                   1940:                                } else
                   1941:                                        sorwakeup(last->in6p_socket);
                   1942:                                opts = NULL;
                   1943:                        }
                   1944:                }
                   1945:                last = in6p;
                   1946:        }
                   1947:        if (last) {
                   1948:                if (last->in6p_flags & IN6P_CONTROLOPTS)
                   1949:                        ip6_savecontrol(last, m, &opts);
                   1950:                /* strip intermediate headers */
                   1951:                m_adj(m, off);
                   1952:                if (sbappendaddr(&last->in6p_socket->so_rcv,
                   1953:                                 (struct sockaddr *)&rip6src,
                   1954:                                 m, opts) == 0) {
                   1955:                        m_freem(m);
                   1956:                        if (opts)
                   1957:                                m_freem(opts);
                   1958:                } else
                   1959:                        sorwakeup(last->in6p_socket);
                   1960:        } else {
                   1961:                m_freem(m);
                   1962:                ip6stat.ip6s_delivered--;
                   1963:        }
                   1964:        return IPPROTO_DONE;
                   1965: }
                   1966:
                   1967: /*
                   1968:  * Reflect the ip6 packet back to the source.
                   1969:  * OFF points to the icmp6 header, counted from the top of the mbuf.
                   1970:  *
                   1971:  * Note: RFC 1885 required that an echo reply should be truncated if it
                   1972:  * did not fit in with (return) path MTU, and KAME code supported the
                   1973:  * behavior.  However, as a clarification after the RFC, this limitation
                   1974:  * was removed in a revised version of the spec, RFC 2463.  We had kept the
                   1975:  * old behavior, with a (non-default) ifdef block, while the new version of
                   1976:  * the spec was an internet-draft status, and even after the new RFC was
                   1977:  * published.  But it would rather make sense to clean the obsoleted part
                   1978:  * up, and to make the code simpler at this stage.
                   1979:  */
                   1980: void
                   1981: icmp6_reflect(m, off)
                   1982:        struct  mbuf *m;
                   1983:        size_t off;
                   1984: {
                   1985:        struct ip6_hdr *ip6;
                   1986:        struct icmp6_hdr *icmp6;
                   1987:        struct in6_ifaddr *ia;
                   1988:        struct in6_addr t, *src = 0;
                   1989:        int plen;
                   1990:        int type, code;
                   1991:        struct ifnet *outif = NULL;
                   1992:        struct sockaddr_in6 sa6_src, sa6_dst;
                   1993:
                   1994:        /* too short to reflect */
                   1995:        if (off < sizeof(struct ip6_hdr)) {
                   1996:                nd6log((LOG_DEBUG,
                   1997:                    "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
                   1998:                    (u_long)off, (u_long)sizeof(struct ip6_hdr),
                   1999:                    __FILE__, __LINE__));
                   2000:                goto bad;
                   2001:        }
                   2002:
                   2003:        /*
                   2004:         * If there are extra headers between IPv6 and ICMPv6, strip
                   2005:         * off that header first.
                   2006:         */
                   2007: #ifdef DIAGNOSTIC
                   2008:        if (sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) > MHLEN)
                   2009:                panic("assumption failed in icmp6_reflect");
                   2010: #endif
                   2011:        if (off > sizeof(struct ip6_hdr)) {
                   2012:                size_t l;
                   2013:                struct ip6_hdr nip6;
                   2014:
                   2015:                l = off - sizeof(struct ip6_hdr);
                   2016:                m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
                   2017:                m_adj(m, l);
                   2018:                l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
                   2019:                if (m->m_len < l) {
                   2020:                        if ((m = m_pullup(m, l)) == NULL)
                   2021:                                return;
                   2022:                }
                   2023:                bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));
                   2024:        } else /* off == sizeof(struct ip6_hdr) */ {
                   2025:                size_t l;
                   2026:                l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
                   2027:                if (m->m_len < l) {
                   2028:                        if ((m = m_pullup(m, l)) == NULL)
                   2029:                                return;
                   2030:                }
                   2031:        }
                   2032:        plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);
                   2033:        ip6 = mtod(m, struct ip6_hdr *);
                   2034:        ip6->ip6_nxt = IPPROTO_ICMPV6;
                   2035:        icmp6 = (struct icmp6_hdr *)(ip6 + 1);
                   2036:        type = icmp6->icmp6_type; /* keep type for statistics */
                   2037:        code = icmp6->icmp6_code; /* ditto. */
                   2038:
                   2039:        t = ip6->ip6_dst;
                   2040:        /*
                   2041:         * ip6_input() drops a packet if its src is multicast.
                   2042:         * So, the src is never multicast.
                   2043:         */
                   2044:        ip6->ip6_dst = ip6->ip6_src;
                   2045:
                   2046:        /*
                   2047:         * XXX: make sure to embed scope zone information, using
                   2048:         * already embedded IDs or the received interface (if any).
                   2049:         * Note that rcvif may be NULL.
                   2050:         * TODO: scoped routing case (XXX).
                   2051:         */
                   2052:        bzero(&sa6_src, sizeof(sa6_src));
                   2053:        sa6_src.sin6_family = AF_INET6;
                   2054:        sa6_src.sin6_len = sizeof(sa6_src);
                   2055:        sa6_src.sin6_addr = ip6->ip6_dst;
                   2056:        in6_recoverscope(&sa6_src, &ip6->ip6_dst, m->m_pkthdr.rcvif);
                   2057:        in6_embedscope(&ip6->ip6_dst, &sa6_src, NULL, NULL);
                   2058:        bzero(&sa6_dst, sizeof(sa6_dst));
                   2059:        sa6_dst.sin6_family = AF_INET6;
                   2060:        sa6_dst.sin6_len = sizeof(sa6_dst);
                   2061:        sa6_dst.sin6_addr = t;
                   2062:        in6_recoverscope(&sa6_dst, &t, m->m_pkthdr.rcvif);
                   2063:        in6_embedscope(&t, &sa6_dst, NULL, NULL);
                   2064:
                   2065:        /*
                   2066:         * If the incoming packet was addressed directly to us (i.e. unicast),
                   2067:         * use dst as the src for the reply.
                   2068:         * The IN6_IFF_NOTREADY case would be VERY rare, but is possible
                   2069:         * (for example) when we encounter an error while forwarding procedure
                   2070:         * destined to a duplicated address of ours.
                   2071:         */
                   2072:        for (ia = in6_ifaddr; ia; ia = ia->ia_next)
                   2073:                if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) &&
                   2074:                    (ia->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0) {
                   2075:                        src = &t;
                   2076:                        break;
                   2077:                }
                   2078:        if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) && (m->m_flags & M_LOOP)) {
                   2079:                /*
                   2080:                 * This is the case if the dst is our link-local address
                   2081:                 * and the sender is also ourselves.
                   2082:                 */
                   2083:                src = &t;
                   2084:        }
                   2085:
                   2086:        if (src == 0) {
                   2087:                int e;
                   2088:                struct route_in6 ro;
                   2089:
                   2090:                /*
                   2091:                 * This case matches to multicasts, our anycast, or unicasts
                   2092:                 * that we do not own.  Select a source address based on the
                   2093:                 * source address of the erroneous packet.
                   2094:                 */
                   2095:                bzero(&ro, sizeof(ro));
                   2096:                src = in6_selectsrc(&sa6_src, NULL, NULL, &ro, NULL, &e);
                   2097:                if (ro.ro_rt) { /* XXX: see comments in icmp6_mtudisc_update */
                   2098:                        RTFREE(ro.ro_rt); /* XXX: we could use this */
                   2099:                }
                   2100:                if (src == NULL) {
                   2101:                        nd6log((LOG_DEBUG,
                   2102:                            "icmp6_reflect: source can't be determined: "
                   2103:                            "dst=%s, error=%d\n",
                   2104:                            ip6_sprintf(&sa6_src.sin6_addr), e));
                   2105:                        goto bad;
                   2106:                }
                   2107:        }
                   2108:
                   2109:        ip6->ip6_src = *src;
                   2110:
                   2111:        ip6->ip6_flow = 0;
                   2112:        ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
                   2113:        ip6->ip6_vfc |= IPV6_VERSION;
                   2114:        ip6->ip6_nxt = IPPROTO_ICMPV6;
                   2115:        if (m->m_pkthdr.rcvif) {
                   2116:                /* XXX: This may not be the outgoing interface */
                   2117:                ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
                   2118:        } else
                   2119:                ip6->ip6_hlim = ip6_defhlim;
                   2120:
                   2121:        icmp6->icmp6_cksum = 0;
                   2122:        icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
                   2123:                                        sizeof(struct ip6_hdr), plen);
                   2124:
                   2125:        /*
                   2126:         * XXX option handling
                   2127:         */
                   2128:
                   2129:        m->m_flags &= ~(M_BCAST|M_MCAST);
                   2130:
                   2131:        /*
                   2132:         * To avoid a "too big" situation at an intermediate router
                   2133:         * and the path MTU discovery process, specify the IPV6_MINMTU flag.
                   2134:         * Note that only echo and node information replies are affected,
                   2135:         * since the length of ICMP6 errors is limited to the minimum MTU.
                   2136:         */
                   2137:        if (ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, &outif, NULL) != 0 &&
                   2138:            outif)
                   2139:                icmp6_ifstat_inc(outif, ifs6_out_error);
                   2140:
                   2141:        if (outif)
                   2142:                icmp6_ifoutstat_inc(outif, type, code);
                   2143:
                   2144:        return;
                   2145:
                   2146:  bad:
                   2147:        m_freem(m);
                   2148:        return;
                   2149: }
                   2150:
                   2151: void
                   2152: icmp6_fasttimo()
                   2153: {
                   2154:
                   2155:        mld6_fasttimeo();
                   2156: }
                   2157:
                   2158: static const char *
                   2159: icmp6_redirect_diag(src6, dst6, tgt6)
                   2160:        struct in6_addr *src6;
                   2161:        struct in6_addr *dst6;
                   2162:        struct in6_addr *tgt6;
                   2163: {
                   2164:        static char buf[1024];
                   2165:        snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)",
                   2166:                 ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6));
                   2167:        return buf;
                   2168: }
                   2169:
                   2170: void
                   2171: icmp6_redirect_input(m, off)
                   2172:        struct mbuf *m;
                   2173:        int off;
                   2174: {
                   2175:        struct ifnet *ifp = m->m_pkthdr.rcvif;
                   2176:        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
                   2177:        struct nd_redirect *nd_rd;
                   2178:        int icmp6len = ntohs(ip6->ip6_plen);
                   2179:        char *lladdr = NULL;
                   2180:        int lladdrlen = 0;
                   2181:        u_char *redirhdr = NULL;
                   2182:        int redirhdrlen = 0;
                   2183:        struct rtentry *rt = NULL;
                   2184:        int is_router;
                   2185:        int is_onlink;
                   2186:        struct in6_addr src6 = ip6->ip6_src;
                   2187:        struct in6_addr redtgt6;
                   2188:        struct in6_addr reddst6;
                   2189:        union nd_opts ndopts;
                   2190:
                   2191:        if (!ifp)
                   2192:                return;
                   2193:
                   2194:        /* XXX if we are router, we don't update route by icmp6 redirect */
                   2195:        if (ip6_forwarding)
                   2196:                goto freeit;
                   2197:        if (!icmp6_rediraccept)
                   2198:                goto freeit;
                   2199:
                   2200:        IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
                   2201:        if (nd_rd == NULL) {
                   2202:                icmp6stat.icp6s_tooshort++;
                   2203:                return;
                   2204:        }
                   2205:        redtgt6 = nd_rd->nd_rd_target;
                   2206:        reddst6 = nd_rd->nd_rd_dst;
                   2207:
                   2208:        if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
                   2209:                redtgt6.s6_addr16[1] = htons(ifp->if_index);
                   2210:        if (IN6_IS_ADDR_LINKLOCAL(&reddst6))
                   2211:                reddst6.s6_addr16[1] = htons(ifp->if_index);
                   2212:
                   2213:        /* validation */
                   2214:        if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
                   2215:                nd6log((LOG_ERR,
                   2216:                        "ICMP6 redirect sent from %s rejected; "
                   2217:                        "must be from linklocal\n", ip6_sprintf(&src6)));
                   2218:                goto bad;
                   2219:        }
                   2220:        if (ip6->ip6_hlim != 255) {
                   2221:                nd6log((LOG_ERR,
                   2222:                        "ICMP6 redirect sent from %s rejected; "
                   2223:                        "hlim=%d (must be 255)\n",
                   2224:                        ip6_sprintf(&src6), ip6->ip6_hlim));
                   2225:                goto bad;
                   2226:        }
                   2227:     {
                   2228:        /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */
                   2229:        struct sockaddr_in6 sin6;
                   2230:        struct in6_addr *gw6;
                   2231:
                   2232:        bzero(&sin6, sizeof(sin6));
                   2233:        sin6.sin6_family = AF_INET6;
                   2234:        sin6.sin6_len = sizeof(struct sockaddr_in6);
                   2235:        bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6));
                   2236:        rt = rtalloc1((struct sockaddr *)&sin6, 0, 0);
                   2237:        if (rt) {
                   2238:                if (rt->rt_gateway == NULL ||
                   2239:                    rt->rt_gateway->sa_family != AF_INET6) {
                   2240:                        nd6log((LOG_ERR,
                   2241:                            "ICMP6 redirect rejected; no route "
                   2242:                            "with inet6 gateway found for redirect dst: %s\n",
                   2243:                            icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
                   2244:                        RTFREE(rt);
                   2245:                        goto bad;
                   2246:                }
                   2247:
                   2248:                gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr);
                   2249:                if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
                   2250:                        nd6log((LOG_ERR,
                   2251:                                "ICMP6 redirect rejected; "
                   2252:                                "not equal to gw-for-src=%s (must be same): "
                   2253:                                "%s\n",
                   2254:                                ip6_sprintf(gw6),
                   2255:                                icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
                   2256:                        RTFREE(rt);
                   2257:                        goto bad;
                   2258:                }
                   2259:        } else {
                   2260:                nd6log((LOG_ERR,
                   2261:                        "ICMP6 redirect rejected; "
                   2262:                        "no route found for redirect dst: %s\n",
                   2263:                        icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
                   2264:                goto bad;
                   2265:        }
                   2266:        RTFREE(rt);
                   2267:        rt = NULL;
                   2268:     }
                   2269:        if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
                   2270:                nd6log((LOG_ERR,
                   2271:                        "ICMP6 redirect rejected; "
                   2272:                        "redirect dst must be unicast: %s\n",
                   2273:                        icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
                   2274:                goto bad;
                   2275:        }
                   2276:
                   2277:        is_router = is_onlink = 0;
                   2278:        if (IN6_IS_ADDR_LINKLOCAL(&redtgt6))
                   2279:                is_router = 1;  /* router case */
                   2280:        if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0)
                   2281:                is_onlink = 1;  /* on-link destination case */
                   2282:        if (!is_router && !is_onlink) {
                   2283:                nd6log((LOG_ERR,
                   2284:                        "ICMP6 redirect rejected; "
                   2285:                        "neither router case nor onlink case: %s\n",
                   2286:                        icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
                   2287:                goto bad;
                   2288:        }
                   2289:        /* validation passed */
                   2290:
                   2291:        icmp6len -= sizeof(*nd_rd);
                   2292:        nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
                   2293:        if (nd6_options(&ndopts) < 0) {
                   2294:                nd6log((LOG_INFO, "icmp6_redirect_input: "
                   2295:                        "invalid ND option, rejected: %s\n",
                   2296:                        icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
                   2297:                /* nd6_options have incremented stats */
                   2298:                goto freeit;
                   2299:        }
                   2300:
                   2301:        if (ndopts.nd_opts_tgt_lladdr) {
                   2302:                lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
                   2303:                lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
                   2304:        }
                   2305:
                   2306:        if (ndopts.nd_opts_rh) {
                   2307:                redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len;
                   2308:                redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */
                   2309:        }
                   2310:
                   2311:        if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
                   2312:                nd6log((LOG_INFO,
                   2313:                        "icmp6_redirect_input: lladdrlen mismatch for %s "
                   2314:                        "(if %d, icmp6 packet %d): %s\n",
                   2315:                        ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2,
                   2316:                        icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
                   2317:                goto bad;
                   2318:        }
                   2319:
                   2320:        /* RFC 2461 8.3 */
                   2321:        nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
                   2322:                         is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
                   2323:
                   2324:        if (!is_onlink) {       /* better router case.  perform rtredirect. */
                   2325:                /* perform rtredirect */
                   2326:                struct sockaddr_in6 sdst;
                   2327:                struct sockaddr_in6 sgw;
                   2328:                struct sockaddr_in6 ssrc;
                   2329:                unsigned long rtcount;
                   2330:                struct rtentry *newrt = NULL;
                   2331:
                   2332:                /*
                   2333:                 * do not install redirect route, if the number of entries
                   2334:                 * is too much (> hiwat).  note that, the node (= host) will
                   2335:                 * work just fine even if we do not install redirect route
                   2336:                 * (there will be additional hops, though).
                   2337:                 */
                   2338:                rtcount = rt_timer_count(icmp6_redirect_timeout_q);
                   2339:                if (0 <= icmp6_redirect_hiwat && rtcount > icmp6_redirect_hiwat)
                   2340:                        return;
                   2341:                else if (0 <= icmp6_redirect_lowat &&
                   2342:                    rtcount > icmp6_redirect_lowat) {
                   2343:                        /*
                   2344:                         * XXX nuke a victim, install the new one.
                   2345:                         */
                   2346:                }
                   2347:
                   2348:                bzero(&sdst, sizeof(sdst));
                   2349:                bzero(&sgw, sizeof(sgw));
                   2350:                bzero(&ssrc, sizeof(ssrc));
                   2351:                sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6;
                   2352:                sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len =
                   2353:                        sizeof(struct sockaddr_in6);
                   2354:                bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr));
                   2355:                bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
                   2356:                bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
                   2357:                rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw,
                   2358:                           (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST,
                   2359:                           (struct sockaddr *)&ssrc,
                   2360:                           &newrt);
                   2361:
                   2362:                if (newrt) {
                   2363:                        (void)rt_timer_add(newrt, icmp6_redirect_timeout,
                   2364:                            icmp6_redirect_timeout_q);
                   2365:                        rtfree(newrt);
                   2366:                }
                   2367:        }
                   2368:        /* finally update cached route in each socket via pfctlinput */
                   2369:        {
                   2370:                struct sockaddr_in6 sdst;
                   2371:
                   2372:                bzero(&sdst, sizeof(sdst));
                   2373:                sdst.sin6_family = AF_INET6;
                   2374:                sdst.sin6_len = sizeof(struct sockaddr_in6);
                   2375:                bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
                   2376:                pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
                   2377:        }
                   2378:
                   2379:  freeit:
                   2380:        m_freem(m);
                   2381:        return;
                   2382:
                   2383:  bad:
                   2384:        icmp6stat.icp6s_badredirect++;
                   2385:        m_freem(m);
                   2386: }
                   2387:
                   2388: void
                   2389: icmp6_redirect_output(m0, rt)
                   2390:        struct mbuf *m0;
                   2391:        struct rtentry *rt;
                   2392: {
                   2393:        struct ifnet *ifp;      /* my outgoing interface */
                   2394:        struct in6_addr *ifp_ll6;
                   2395:        struct in6_addr *nexthop;
                   2396:        struct ip6_hdr *sip6;   /* m0 as struct ip6_hdr */
                   2397:        struct mbuf *m = NULL;  /* newly allocated one */
                   2398:        struct ip6_hdr *ip6;    /* m as struct ip6_hdr */
                   2399:        struct nd_redirect *nd_rd;
                   2400:        size_t maxlen;
                   2401:        u_char *p;
                   2402:        struct sockaddr_in6 src_sa;
                   2403:
                   2404:        icmp6_errcount(&icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0);
                   2405:
                   2406:        /* if we are not router, we don't send icmp6 redirect */
                   2407:        if (!ip6_forwarding)
                   2408:                goto fail;
                   2409:
                   2410:        /* sanity check */
                   2411:        if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp))
                   2412:                goto fail;
                   2413:
                   2414:        /*
                   2415:         * Address check:
                   2416:         *  the source address must identify a neighbor, and
                   2417:         *  the destination address must not be a multicast address
                   2418:         *  [RFC 2461, sec 8.2]
                   2419:         */
                   2420:        sip6 = mtod(m0, struct ip6_hdr *);
                   2421:        bzero(&src_sa, sizeof(src_sa));
                   2422:        src_sa.sin6_family = AF_INET6;
                   2423:        src_sa.sin6_len = sizeof(src_sa);
                   2424:        src_sa.sin6_addr = sip6->ip6_src;
                   2425:        /* we don't currently use sin6_scope_id, but eventually use it */
                   2426:        src_sa.sin6_scope_id = in6_addr2scopeid(ifp, &sip6->ip6_src);
                   2427:        if (nd6_is_addr_neighbor(&src_sa, ifp) == 0)
                   2428:                goto fail;
                   2429:        if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst))
                   2430:                goto fail;      /* what should we do here? */
                   2431:
                   2432:        /* rate limit */
                   2433:        if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0))
                   2434:                goto fail;
                   2435:
                   2436:        /*
                   2437:         * Since we are going to append up to 1280 bytes (= IPV6_MMTU),
                   2438:         * we almost always ask for an mbuf cluster for simplicity.
                   2439:         * (MHLEN < IPV6_MMTU is almost always true)
                   2440:         */
                   2441: #if IPV6_MMTU >= MCLBYTES
                   2442: # error assumption failed about IPV6_MMTU and MCLBYTES
                   2443: #endif
                   2444:        MGETHDR(m, M_DONTWAIT, MT_HEADER);
                   2445:        if (m && IPV6_MMTU >= MHLEN)
                   2446:                MCLGET(m, M_DONTWAIT);
                   2447:        if (!m)
                   2448:                goto fail;
                   2449:        m->m_pkthdr.rcvif = NULL;
                   2450:        m->m_len = 0;
                   2451:        maxlen = M_TRAILINGSPACE(m);
                   2452:        maxlen = min(IPV6_MMTU, maxlen);
                   2453:        /* just for safety */
                   2454:        if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
                   2455:            ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
                   2456:                goto fail;
                   2457:        }
                   2458:
                   2459:        {
                   2460:                /* get ip6 linklocal address for ifp(my outgoing interface). */
                   2461:                struct in6_ifaddr *ia;
                   2462:                if ((ia = in6ifa_ifpforlinklocal(ifp,
                   2463:                                                 IN6_IFF_NOTREADY|
                   2464:                                                 IN6_IFF_ANYCAST)) == NULL)
                   2465:                        goto fail;
                   2466:                ifp_ll6 = &ia->ia_addr.sin6_addr;
                   2467:        }
                   2468:
                   2469:        /* get ip6 linklocal address for the router. */
                   2470:        if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) {
                   2471:                struct sockaddr_in6 *sin6;
                   2472:                sin6 = (struct sockaddr_in6 *)rt->rt_gateway;
                   2473:                nexthop = &sin6->sin6_addr;
                   2474:                if (!IN6_IS_ADDR_LINKLOCAL(nexthop))
                   2475:                        nexthop = NULL;
                   2476:        } else
                   2477:                nexthop = NULL;
                   2478:
                   2479:        /* ip6 */
                   2480:        ip6 = mtod(m, struct ip6_hdr *);
                   2481:        ip6->ip6_flow = 0;
                   2482:        ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
                   2483:        ip6->ip6_vfc |= IPV6_VERSION;
                   2484:        /* ip6->ip6_plen will be set later */
                   2485:        ip6->ip6_nxt = IPPROTO_ICMPV6;
                   2486:        ip6->ip6_hlim = 255;
                   2487:        /* ip6->ip6_src must be linklocal addr for my outgoing if. */
                   2488:        bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
                   2489:        bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
                   2490:
                   2491:        /* ND Redirect */
                   2492:        nd_rd = (struct nd_redirect *)(ip6 + 1);
                   2493:        nd_rd->nd_rd_type = ND_REDIRECT;
                   2494:        nd_rd->nd_rd_code = 0;
                   2495:        nd_rd->nd_rd_reserved = 0;
                   2496:        if (rt->rt_flags & RTF_GATEWAY) {
                   2497:                /*
                   2498:                 * nd_rd->nd_rd_target must be a link-local address in
                   2499:                 * better router cases.
                   2500:                 */
                   2501:                if (!nexthop)
                   2502:                        goto fail;
                   2503:                bcopy(nexthop, &nd_rd->nd_rd_target,
                   2504:                      sizeof(nd_rd->nd_rd_target));
                   2505:                bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
                   2506:                      sizeof(nd_rd->nd_rd_dst));
                   2507:        } else {
                   2508:                /* make sure redtgt == reddst */
                   2509:                nexthop = &sip6->ip6_dst;
                   2510:                bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target,
                   2511:                      sizeof(nd_rd->nd_rd_target));
                   2512:                bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst,
                   2513:                      sizeof(nd_rd->nd_rd_dst));
                   2514:        }
                   2515:
                   2516:        p = (u_char *)(nd_rd + 1);
                   2517:
                   2518:        {
                   2519:                /* target lladdr option */
                   2520:                struct rtentry *rt_nexthop = NULL;
                   2521:                int len;
                   2522:                struct sockaddr_dl *sdl;
                   2523:                struct nd_opt_hdr *nd_opt;
                   2524:                char *lladdr;
                   2525:
                   2526:                rt_nexthop = nd6_lookup(nexthop, 0, ifp);
                   2527:                if (!rt_nexthop)
                   2528:                        goto nolladdropt;
                   2529:                len = sizeof(*nd_opt) + ifp->if_addrlen;
                   2530:                len = (len + 7) & ~7;   /* round by 8 */
                   2531:                /* safety check */
                   2532:                if (len + (p - (u_char *)ip6) > maxlen)
                   2533:                        goto nolladdropt;
                   2534:                if (!(rt_nexthop->rt_flags & RTF_GATEWAY) &&
                   2535:                    (rt_nexthop->rt_flags & RTF_LLINFO) &&
                   2536:                    (rt_nexthop->rt_gateway->sa_family == AF_LINK) &&
                   2537:                    (sdl = (struct sockaddr_dl *)rt_nexthop->rt_gateway) &&
                   2538:                    sdl->sdl_alen) {
                   2539:                        nd_opt = (struct nd_opt_hdr *)p;
                   2540:                        nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
                   2541:                        nd_opt->nd_opt_len = len >> 3;
                   2542:                        lladdr = (char *)(nd_opt + 1);
                   2543:                        bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen);
                   2544:                        p += len;
                   2545:                }
                   2546:        }
                   2547:   nolladdropt:;
                   2548:
                   2549:        m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
                   2550:
                   2551:        /* just to be safe */
                   2552:        if (p - (u_char *)ip6 > maxlen)
                   2553:                goto noredhdropt;
                   2554:
                   2555:        {
                   2556:                /* redirected header option */
                   2557:                int len;
                   2558:                struct nd_opt_rd_hdr *nd_opt_rh;
                   2559:
                   2560:                /*
                   2561:                 * compute the maximum size for icmp6 redirect header option.
                   2562:                 * XXX room for auth header?
                   2563:                 */
                   2564:                len = maxlen - (p - (u_char *)ip6);
                   2565:                len &= ~7;
                   2566:
                   2567:                /*
                   2568:                 * Redirected header option spec (RFC2461 4.6.3) talks nothing
                   2569:                 * about padding/truncate rule for the original IP packet.
                   2570:                 * From the discussion on IPv6imp in Feb 1999,
                   2571:                 * the consensus was:
                   2572:                 * - "attach as much as possible" is the goal
                   2573:                 * - pad if not aligned (original size can be guessed by
                   2574:                 *   original ip6 header)
                   2575:                 * Following code adds the padding if it is simple enough,
                   2576:                 * and truncates if not.
                   2577:                 */
                   2578:                if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
                   2579:                        /* not enough room, truncate */
                   2580:                        m_adj(m0, (len - sizeof(*nd_opt_rh)) -
                   2581:                            m0->m_pkthdr.len);
                   2582:                } else {
                   2583:                        /*
                   2584:                         * enough room, truncate if not aligned.
                   2585:                         * we don't pad here for simplicity.
                   2586:                         */
                   2587:                        size_t extra;
                   2588:
                   2589:                        extra = m0->m_pkthdr.len % 8;
                   2590:                        if (extra) {
                   2591:                                /* truncate */
                   2592:                                m_adj(m0, -extra);
                   2593:                        }
                   2594:                        len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
                   2595:                }
                   2596:
                   2597:                nd_opt_rh = (struct nd_opt_rd_hdr *)p;
                   2598:                bzero(nd_opt_rh, sizeof(*nd_opt_rh));
                   2599:                nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
                   2600:                nd_opt_rh->nd_opt_rh_len = len >> 3;
                   2601:                p += sizeof(*nd_opt_rh);
                   2602:                m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
                   2603:
                   2604:                /* connect m0 to m */
                   2605:                m->m_pkthdr.len += m0->m_pkthdr.len;
                   2606:                m_cat(m, m0);
                   2607:                m0 = NULL;
                   2608:        }
                   2609: noredhdropt:
                   2610:        if (m0) {
                   2611:                m_freem(m0);
                   2612:                m0 = NULL;
                   2613:        }
                   2614:
                   2615:        sip6 = mtod(m, struct ip6_hdr *);
                   2616:        if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src))
                   2617:                sip6->ip6_src.s6_addr16[1] = 0;
                   2618:        if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst))
                   2619:                sip6->ip6_dst.s6_addr16[1] = 0;
                   2620: #if 0
                   2621:        if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src))
                   2622:                ip6->ip6_src.s6_addr16[1] = 0;
                   2623:        if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
                   2624:                ip6->ip6_dst.s6_addr16[1] = 0;
                   2625: #endif
                   2626:        if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target))
                   2627:                nd_rd->nd_rd_target.s6_addr16[1] = 0;
                   2628:        if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst))
                   2629:                nd_rd->nd_rd_dst.s6_addr16[1] = 0;
                   2630:
                   2631:        ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
                   2632:
                   2633:        nd_rd->nd_rd_cksum = 0;
                   2634:        nd_rd->nd_rd_cksum
                   2635:                = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen));
                   2636:
                   2637:        /* send the packet to outside... */
                   2638:        if (ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL) != 0)
                   2639:                icmp6_ifstat_inc(ifp, ifs6_out_error);
                   2640:
                   2641:        icmp6_ifstat_inc(ifp, ifs6_out_msg);
                   2642:        icmp6_ifstat_inc(ifp, ifs6_out_redirect);
                   2643:        icmp6stat.icp6s_outhist[ND_REDIRECT]++;
                   2644:
                   2645:        return;
                   2646:
                   2647: fail:
                   2648:        if (m)
                   2649:                m_freem(m);
                   2650:        if (m0)
                   2651:                m_freem(m0);
                   2652: }
                   2653:
                   2654: /* NRL PCB */
                   2655: #define sotoin6pcb     sotoinpcb
                   2656: #define in6pcb         inpcb
                   2657: #define in6p_icmp6filt inp_icmp6filt
                   2658:
                   2659: /*
                   2660:  * ICMPv6 socket option processing.
                   2661:  */
                   2662: int
                   2663: icmp6_ctloutput(op, so, level, optname, mp)
                   2664:        int op;
                   2665:        struct socket *so;
                   2666:        int level, optname;
                   2667:        struct mbuf **mp;
                   2668: {
                   2669:        int error = 0;
                   2670:        int optlen;
                   2671:        struct in6pcb *in6p = sotoin6pcb(so);
                   2672:        struct mbuf *m = *mp;
                   2673:
                   2674:        optlen = m ? m->m_len : 0;
                   2675:
                   2676:        if (level != IPPROTO_ICMPV6) {
                   2677:                if (op == PRCO_SETOPT && m)
                   2678:                        (void)m_free(m);
                   2679:                return EINVAL;
                   2680:        }
                   2681:
                   2682:        switch (op) {
                   2683:        case PRCO_SETOPT:
                   2684:                switch (optname) {
                   2685:                case ICMP6_FILTER:
                   2686:                    {
                   2687:                        struct icmp6_filter *p;
                   2688:
                   2689:                        if (optlen != sizeof(*p)) {
                   2690:                                error = EMSGSIZE;
                   2691:                                break;
                   2692:                        }
                   2693:                        p = mtod(m, struct icmp6_filter *);
                   2694:                        if (!p || !in6p->in6p_icmp6filt) {
                   2695:                                error = EINVAL;
                   2696:                                break;
                   2697:                        }
                   2698:                        bcopy(p, in6p->in6p_icmp6filt,
                   2699:                                sizeof(struct icmp6_filter));
                   2700:                        error = 0;
                   2701:                        break;
                   2702:                    }
                   2703:
                   2704:                default:
                   2705:                        error = ENOPROTOOPT;
                   2706:                        break;
                   2707:                }
                   2708:                if (m)
                   2709:                        (void)m_freem(m);
                   2710:                break;
                   2711:
                   2712:        case PRCO_GETOPT:
                   2713:                switch (optname) {
                   2714:                case ICMP6_FILTER:
                   2715:                    {
                   2716:                        struct icmp6_filter *p;
                   2717:
                   2718:                        if (!in6p->in6p_icmp6filt) {
                   2719:                                error = EINVAL;
                   2720:                                break;
                   2721:                        }
                   2722:                        *mp = m = m_get(M_WAIT, MT_SOOPTS);
                   2723:                        m->m_len = sizeof(struct icmp6_filter);
                   2724:                        p = mtod(m, struct icmp6_filter *);
                   2725:                        bcopy(in6p->in6p_icmp6filt, p,
                   2726:                                sizeof(struct icmp6_filter));
                   2727:                        error = 0;
                   2728:                        break;
                   2729:                    }
                   2730:
                   2731:                default:
                   2732:                        error = ENOPROTOOPT;
                   2733:                        break;
                   2734:                }
                   2735:                break;
                   2736:        }
                   2737:
                   2738:        return (error);
                   2739: }
                   2740:
                   2741: /* NRL PCB */
                   2742: #undef sotoin6pcb
                   2743: #undef in6pcb
                   2744: #undef in6p_icmp6filt
                   2745:
                   2746: /*
                   2747:  * Perform rate limit check.
                   2748:  * Returns 0 if it is okay to send the icmp6 packet.
                   2749:  * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate
                   2750:  * limitation.
                   2751:  *
                   2752:  * XXX per-destination/type check necessary?
                   2753:  */
                   2754: static int
                   2755: icmp6_ratelimit(dst, type, code)
                   2756:        const struct in6_addr *dst;     /* not used at this moment */
                   2757:        const int type;                 /* not used at this moment */
                   2758:        const int code;                 /* not used at this moment */
                   2759: {
                   2760:        int ret;
                   2761:
                   2762:        ret = 0;        /* okay to send */
                   2763:
                   2764:        /* PPS limit */
                   2765:        if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count,
                   2766:            icmp6errppslim)) {
                   2767:                /* The packet is subject to rate limit */
                   2768:                ret++;
                   2769:        }
                   2770:
                   2771:        return ret;
                   2772: }
                   2773:
                   2774: static struct rtentry *
                   2775: icmp6_mtudisc_clone(dst)
                   2776:        struct sockaddr *dst;
                   2777: {
                   2778:        struct rtentry *rt;
                   2779:        int    error;
                   2780:
                   2781:        rt = rtalloc1(dst, 1, 0);
                   2782:        if (rt == 0)
                   2783:                return NULL;
                   2784:
                   2785:        /* If we didn't get a host route, allocate one */
                   2786:        if ((rt->rt_flags & RTF_HOST) == 0) {
                   2787:                struct rtentry *nrt;
                   2788:
                   2789:                error = rtrequest((int) RTM_ADD, dst,
                   2790:                    (struct sockaddr *) rt->rt_gateway,
                   2791:                    (struct sockaddr *) 0,
                   2792:                    RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt, 0);
                   2793:                if (error) {
                   2794:                        rtfree(rt);
                   2795:                        return NULL;
                   2796:                }
                   2797:                nrt->rt_rmx = rt->rt_rmx;
                   2798:                rtfree(rt);
                   2799:                rt = nrt;
                   2800:        }
                   2801:        error = rt_timer_add(rt, icmp6_mtudisc_timeout,
                   2802:                        icmp6_mtudisc_timeout_q);
                   2803:        if (error) {
                   2804:                rtfree(rt);
                   2805:                return NULL;
                   2806:        }
                   2807:
                   2808:        return rt;      /* caller need to call rtfree() */
                   2809: }
                   2810:
                   2811: static void
                   2812: icmp6_mtudisc_timeout(rt, r)
                   2813:        struct rtentry *rt;
                   2814:        struct rttimer *r;
                   2815: {
                   2816:        if (rt == NULL)
                   2817:                panic("icmp6_mtudisc_timeout: bad route to timeout");
                   2818:        if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
                   2819:            (RTF_DYNAMIC | RTF_HOST)) {
                   2820:                rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt),
                   2821:                    rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0, 0);
                   2822:        } else {
                   2823:                if (!(rt->rt_rmx.rmx_locks & RTV_MTU))
                   2824:                        rt->rt_rmx.rmx_mtu = 0;
                   2825:        }
                   2826: }
                   2827:
                   2828: static void
                   2829: icmp6_redirect_timeout(rt, r)
                   2830:        struct rtentry *rt;
                   2831:        struct rttimer *r;
                   2832: {
                   2833:        if (rt == NULL)
                   2834:                panic("icmp6_redirect_timeout: bad route to timeout");
                   2835:        if ((rt->rt_flags & (RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) ==
                   2836:            (RTF_GATEWAY | RTF_DYNAMIC | RTF_HOST)) {
                   2837:                rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt),
                   2838:                    rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0, 0);
                   2839:        }
                   2840: }
                   2841:
                   2842: #include <uvm/uvm_extern.h>
                   2843: #include <sys/sysctl.h>
                   2844:
                   2845: int *icmpv6ctl_vars[ICMPV6CTL_MAXID] = ICMPV6CTL_VARS;
                   2846:
                   2847: int
                   2848: icmp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
                   2849:        int *name;
                   2850:        u_int namelen;
                   2851:        void *oldp;
                   2852:        size_t *oldlenp;
                   2853:        void *newp;
                   2854:        size_t newlen;
                   2855: {
                   2856:
                   2857:        /* All sysctl names at this level are terminal. */
                   2858:        if (namelen != 1)
                   2859:                return ENOTDIR;
                   2860:
                   2861:        switch (name[0]) {
                   2862:
                   2863:        case ICMPV6CTL_STATS:
                   2864:                return sysctl_rdstruct(oldp, oldlenp, newp,
                   2865:                                &icmp6stat, sizeof(icmp6stat));
                   2866:        case ICMPV6CTL_ND6_DRLIST:
                   2867:        case ICMPV6CTL_ND6_PRLIST:
                   2868:                return nd6_sysctl(name[0], oldp, oldlenp, newp, newlen);
                   2869:        default:
                   2870:                if (name[0] < ICMPV6CTL_MAXID)
                   2871:                        return (sysctl_int_arr(icmpv6ctl_vars, name, namelen,
                   2872:                            oldp, oldlenp, newp, newlen));
                   2873:                return ENOPROTOOPT;
                   2874:        }
                   2875:        /* NOTREACHED */
                   2876: }

CVSweb