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

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

1.1       nbrk        1: /*     $NetBSD: ip6_mroute.c,v 1.59 2003/12/10 09:28:38 itojun Exp $   */
                      2: /*     $KAME: ip6_mroute.c,v 1.45 2001/03/25 08:38:51 itojun Exp $     */
                      3:
                      4: /*
                      5:  * Copyright (C) 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: /*     BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp     */
                     34:
                     35: /*
                     36:  * Copyright (c) 1989 Stephen Deering
                     37:  * Copyright (c) 1992, 1993
                     38:  *      The Regents of the University of California.  All rights reserved.
                     39:  *
                     40:  * This code is derived from software contributed to Berkeley by
                     41:  * Stephen Deering of Stanford University.
                     42:  *
                     43:  * Redistribution and use in source and binary forms, with or without
                     44:  * modification, are permitted provided that the following conditions
                     45:  * are met:
                     46:  * 1. Redistributions of source code must retain the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer.
                     48:  * 2. Redistributions in binary form must reproduce the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer in the
                     50:  *    documentation and/or other materials provided with the distribution.
                     51:  * 3. Neither the name of the University nor the names of its contributors
                     52:  *    may be used to endorse or promote products derived from this software
                     53:  *    without specific prior written permission.
                     54:  *
                     55:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     56:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     57:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     58:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     59:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     60:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     61:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     62:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     63:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     64:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     65:  * SUCH DAMAGE.
                     66:  *
                     67:  *      @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93
                     68:  */
                     69:
                     70: /*
                     71:  * IP multicast forwarding procedures
                     72:  *
                     73:  * Written by David Waitzman, BBN Labs, August 1988.
                     74:  * Modified by Steve Deering, Stanford, February 1989.
                     75:  * Modified by Mark J. Steiglitz, Stanford, May, 1991
                     76:  * Modified by Van Jacobson, LBL, January 1993
                     77:  * Modified by Ajit Thyagarajan, PARC, August 1993
                     78:  * Modified by Bill Fenner, PARC, April 1994
                     79:  *
                     80:  * MROUTING Revision: 3.5.1.2 + PIM-SMv2 (pimd) Support
                     81:  */
                     82:
                     83: #ifndef _KERNEL
                     84: # ifdef KERNEL
                     85: #  define _KERNEL
                     86: # endif
                     87: #endif
                     88:
                     89: #include <sys/param.h>
                     90: #include <sys/systm.h>
                     91: #include <sys/timeout.h>
                     92: #include <sys/mbuf.h>
                     93: #include <sys/socket.h>
                     94: #include <sys/socketvar.h>
                     95: #include <sys/sockio.h>
                     96: #include <sys/protosw.h>
                     97: #include <sys/errno.h>
                     98: #include <sys/time.h>
                     99: #include <sys/kernel.h>
                    100: #include <sys/ioctl.h>
                    101: #include <sys/syslog.h>
                    102:
                    103: #include <net/if.h>
                    104: #include <net/route.h>
                    105: #include <net/raw_cb.h>
                    106:
                    107: #include <netinet/in.h>
                    108: #include <netinet/in_var.h>
                    109: #include <netinet/icmp6.h>
                    110:
                    111: #include <netinet/ip6.h>
                    112: #include <netinet6/ip6_var.h>
                    113: #include <netinet6/ip6_mroute.h>
                    114: #include <netinet6/pim6.h>
                    115: #include <netinet6/pim6_var.h>
                    116: #include <netinet6/nd6.h>
                    117:
                    118: static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *);
                    119: static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
                    120:
                    121: static int set_pim6(int *);
                    122: static int get_pim6(struct mbuf *);
                    123: static int socket_send(struct socket *, struct mbuf *,
                    124:                            struct sockaddr_in6 *);
                    125: static int register_send(struct ip6_hdr *, struct mif6 *,
                    126:                              struct mbuf *);
                    127:
                    128: /*
                    129:  * Globals.  All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static,
                    130:  * except for netstat or debugging purposes.
                    131:  */
                    132: struct socket  *ip6_mrouter = NULL;
                    133: int            ip6_mrouter_ver = 0;
                    134: int            ip6_mrtproto = IPPROTO_PIM;    /* for netstat only */
                    135: struct mrt6stat        mrt6stat;
                    136:
                    137: #define NO_RTE_FOUND   0x1
                    138: #define RTE_FOUND      0x2
                    139:
                    140: struct mf6c    *mf6ctable[MF6CTBLSIZ];
                    141: u_char         n6expire[MF6CTBLSIZ];
                    142: struct mif6 mif6table[MAXMIFS];
                    143: #ifdef MRT6DEBUG
                    144: u_int          mrt6debug = 0;    /* debug level        */
                    145: #define                DEBUG_MFC       0x02
                    146: #define                DEBUG_FORWARD   0x04
                    147: #define                DEBUG_EXPIRE    0x08
                    148: #define                DEBUG_XMIT      0x10
                    149: #define         DEBUG_REG       0x20
                    150: #define         DEBUG_PIM       0x40
                    151: #endif
                    152:
                    153: static void    expire_upcalls(void *);
                    154: #define                EXPIRE_TIMEOUT  (hz / 4)        /* 4x / second */
                    155: #define                UPCALL_EXPIRE   6               /* number of timeouts */
                    156:
                    157: #ifdef INET
                    158: #ifdef MROUTING
                    159: extern struct socket *ip_mrouter;
                    160: #endif
                    161: #endif
                    162:
                    163: /*
                    164:  * 'Interfaces' associated with decapsulator (so we can tell
                    165:  * packets that went through it from ones that get reflected
                    166:  * by a broken gateway).  These interfaces are never linked into
                    167:  * the system ifnet list & no routes point to them.  I.e., packets
                    168:  * can't be sent this way.  They only exist as a placeholder for
                    169:  * multicast source verification.
                    170:  */
                    171: struct ifnet multicast_register_if;
                    172:
                    173: #define ENCAP_HOPS 64
                    174:
                    175: /*
                    176:  * Private variables.
                    177:  */
                    178: static mifi_t nummifs = 0;
                    179: static mifi_t reg_mif_num = (mifi_t)-1;
                    180:
                    181: struct pim6stat pim6stat;
                    182: static int pim6;
                    183:
                    184: /*
                    185:  * Hash function for a source, group entry
                    186:  */
                    187: #define MF6CHASH(a, g) MF6CHASHMOD((a).s6_addr32[0] ^ (a).s6_addr32[1] ^ \
                    188:                                   (a).s6_addr32[2] ^ (a).s6_addr32[3] ^ \
                    189:                                   (g).s6_addr32[0] ^ (g).s6_addr32[1] ^ \
                    190:                                   (g).s6_addr32[2] ^ (g).s6_addr32[3])
                    191:
                    192: /*
                    193:  * Find a route for a given origin IPv6 address and Multicast group address.
                    194:  * Quality of service parameter to be added in the future!!!
                    195:  */
                    196:
                    197: #define MF6CFIND(o, g, rt) do { \
                    198:        struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
                    199:        rt = NULL; \
                    200:        mrt6stat.mrt6s_mfc_lookups++; \
                    201:        while (_rt) { \
                    202:                if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \
                    203:                    IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \
                    204:                    (_rt->mf6c_stall == NULL)) { \
                    205:                        rt = _rt; \
                    206:                        break; \
                    207:                } \
                    208:                _rt = _rt->mf6c_next; \
                    209:        } \
                    210:        if (rt == NULL) { \
                    211:                mrt6stat.mrt6s_mfc_misses++; \
                    212:        } \
                    213: } while (0)
                    214:
                    215: /*
                    216:  * Macros to compute elapsed time efficiently
                    217:  * Borrowed from Van Jacobson's scheduling code
                    218:  */
                    219: #define TV_DELTA(a, b, delta) do { \
                    220:            int xxs; \
                    221:                \
                    222:            delta = (a).tv_usec - (b).tv_usec; \
                    223:            if ((xxs = (a).tv_sec - (b).tv_sec)) { \
                    224:               switch (xxs) { \
                    225:                      case 2: \
                    226:                          delta += 1000000; \
                    227:                              /* FALLTHROUGH */ \
                    228:                      case 1: \
                    229:                          delta += 1000000; \
                    230:                          break; \
                    231:                      default: \
                    232:                          delta += (1000000 * xxs); \
                    233:               } \
                    234:            } \
                    235: } while (0)
                    236:
                    237: #define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
                    238:              (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
                    239:
                    240: #ifdef UPCALL_TIMING
                    241: #define UPCALL_MAX     50
                    242: u_long upcall_data[UPCALL_MAX + 1];
                    243: static void collate();
                    244: #endif /* UPCALL_TIMING */
                    245:
                    246: static int get_sg_cnt(struct sioc_sg_req6 *);
                    247: static int get_mif6_cnt(struct sioc_mif_req6 *);
                    248: static int ip6_mrouter_init(struct socket *, int, int);
                    249: static int add_m6if(struct mif6ctl *);
                    250: static int del_m6if(mifi_t *);
                    251: static int add_m6fc(struct mf6cctl *);
                    252: static int del_m6fc(struct mf6cctl *);
                    253:
                    254: static struct timeout expire_upcalls_ch;
                    255:
                    256: /*
                    257:  * Handle MRT setsockopt commands to modify the multicast routing tables.
                    258:  */
                    259: int
                    260: ip6_mrouter_set(cmd, so, m)
                    261:        int cmd;
                    262:        struct socket *so;
                    263:        struct mbuf *m;
                    264: {
                    265:        if (cmd != MRT6_INIT && so != ip6_mrouter)
                    266:                return (EACCES);
                    267:
                    268:        switch (cmd) {
                    269: #ifdef MRT6_OINIT
                    270:        case MRT6_OINIT:
                    271: #endif
                    272:        case MRT6_INIT:
                    273:                if (m == NULL || m->m_len < sizeof(int))
                    274:                        return (EINVAL);
                    275:                return (ip6_mrouter_init(so, *mtod(m, int *), cmd));
                    276:        case MRT6_DONE:
                    277:                return (ip6_mrouter_done());
                    278:        case MRT6_ADD_MIF:
                    279:                if (m == NULL || m->m_len < sizeof(struct mif6ctl))
                    280:                        return (EINVAL);
                    281:                return (add_m6if(mtod(m, struct mif6ctl *)));
                    282:        case MRT6_DEL_MIF:
                    283:                if (m == NULL || m->m_len < sizeof(mifi_t))
                    284:                        return (EINVAL);
                    285:                return (del_m6if(mtod(m, mifi_t *)));
                    286:        case MRT6_ADD_MFC:
                    287:                if (m == NULL || m->m_len < sizeof(struct mf6cctl))
                    288:                        return (EINVAL);
                    289:                return (add_m6fc(mtod(m, struct mf6cctl *)));
                    290:        case MRT6_DEL_MFC:
                    291:                if (m == NULL || m->m_len < sizeof(struct mf6cctl))
                    292:                        return (EINVAL);
                    293:                return (del_m6fc(mtod(m,  struct mf6cctl *)));
                    294:        case MRT6_PIM:
                    295:                if (m == NULL || m->m_len < sizeof(int))
                    296:                        return (EINVAL);
                    297:                return (set_pim6(mtod(m, int *)));
                    298:        default:
                    299:                return (EOPNOTSUPP);
                    300:        }
                    301: }
                    302:
                    303: /*
                    304:  * Handle MRT getsockopt commands
                    305:  */
                    306: int
                    307: ip6_mrouter_get(cmd, so, m)
                    308:        int cmd;
                    309:        struct socket *so;
                    310:        struct mbuf **m;
                    311: {
                    312:        struct mbuf *mb;
                    313:
                    314:        if (so != ip6_mrouter) return EACCES;
                    315:
                    316:        *m = mb = m_get(M_WAIT, MT_SOOPTS);
                    317:
                    318:        switch (cmd) {
                    319:        case MRT6_PIM:
                    320:                return get_pim6(mb);
                    321:        default:
                    322:                m_free(mb);
                    323:                return EOPNOTSUPP;
                    324:        }
                    325: }
                    326:
                    327: /*
                    328:  * Handle ioctl commands to obtain information from the cache
                    329:  */
                    330: int
                    331: mrt6_ioctl(cmd, data)
                    332:        int cmd;
                    333:        caddr_t data;
                    334: {
                    335:
                    336:        switch (cmd) {
                    337:        case SIOCGETSGCNT_IN6:
                    338:                return (get_sg_cnt((struct sioc_sg_req6 *)data));
                    339:        case SIOCGETMIFCNT_IN6:
                    340:                return (get_mif6_cnt((struct sioc_mif_req6 *)data));
                    341:        default:
                    342:                return (EINVAL);
                    343:        }
                    344: }
                    345:
                    346: /*
                    347:  * returns the packet, byte, rpf-failure count for the source group provided
                    348:  */
                    349: static int
                    350: get_sg_cnt(req)
                    351:        struct sioc_sg_req6 *req;
                    352: {
                    353:        struct mf6c *rt;
                    354:        int s;
                    355:
                    356:        s = splsoftnet();
                    357:
                    358:        MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt);
                    359:        splx(s);
                    360:        if (rt != NULL) {
                    361:                req->pktcnt = rt->mf6c_pkt_cnt;
                    362:                req->bytecnt = rt->mf6c_byte_cnt;
                    363:                req->wrong_if = rt->mf6c_wrong_if;
                    364:        } else
                    365:                return (ESRCH);
                    366: #if 0
                    367:                req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
                    368: #endif
                    369:
                    370:        return 0;
                    371: }
                    372:
                    373: /*
                    374:  * returns the input and output packet and byte counts on the mif provided
                    375:  */
                    376: static int
                    377: get_mif6_cnt(req)
                    378:        struct sioc_mif_req6 *req;
                    379: {
                    380:        mifi_t mifi = req->mifi;
                    381:
                    382:        if (mifi >= nummifs)
                    383:                return EINVAL;
                    384:
                    385:        req->icount = mif6table[mifi].m6_pkt_in;
                    386:        req->ocount = mif6table[mifi].m6_pkt_out;
                    387:        req->ibytes = mif6table[mifi].m6_bytes_in;
                    388:        req->obytes = mif6table[mifi].m6_bytes_out;
                    389:
                    390:        return 0;
                    391: }
                    392:
                    393: /*
                    394:  * Get PIM processiong global
                    395:  */
                    396: static int
                    397: get_pim6(m)
                    398:        struct mbuf *m;
                    399: {
                    400:        int *i;
                    401:
                    402:        i = mtod(m, int *);
                    403:
                    404:        *i = pim6;
                    405:
                    406:        return 0;
                    407: }
                    408:
                    409: static int
                    410: set_pim6(i)
                    411:        int *i;
                    412: {
                    413:        if ((*i != 1) && (*i != 0))
                    414:                return EINVAL;
                    415:
                    416:        pim6 = *i;
                    417:
                    418:        return 0;
                    419: }
                    420:
                    421: /*
                    422:  * Enable multicast routing
                    423:  */
                    424: static int
                    425: ip6_mrouter_init(so, v, cmd)
                    426:        struct socket *so;
                    427:        int v;
                    428:        int cmd;
                    429: {
                    430: #ifdef MRT6DEBUG
                    431:        if (mrt6debug)
                    432:                log(LOG_DEBUG,
                    433:                    "ip6_mrouter_init: so_type = %d, pr_protocol = %d\n",
                    434:                    so->so_type, so->so_proto->pr_protocol);
                    435: #endif
                    436:
                    437:        if (so->so_type != SOCK_RAW ||
                    438:            so->so_proto->pr_protocol != IPPROTO_ICMPV6)
                    439:                return (EOPNOTSUPP);
                    440:
                    441:        if (v != 1)
                    442:                return (ENOPROTOOPT);
                    443:
                    444:        if (ip6_mrouter != NULL)
                    445:                return (EADDRINUSE);
                    446:
                    447:        ip6_mrouter = so;
                    448:        ip6_mrouter_ver = cmd;
                    449:
                    450:        bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
                    451:        bzero((caddr_t)n6expire, sizeof(n6expire));
                    452:
                    453:        pim6 = 0;/* used for stubbing out/in pim stuff */
                    454:
                    455:        timeout_set(&expire_upcalls_ch, expire_upcalls, NULL);
                    456:        timeout_add(&expire_upcalls_ch, EXPIRE_TIMEOUT);
                    457:
                    458: #ifdef MRT6DEBUG
                    459:        if (mrt6debug)
                    460:                log(LOG_DEBUG, "ip6_mrouter_init\n");
                    461: #endif
                    462:
                    463:        return 0;
                    464: }
                    465:
                    466: /*
                    467:  * Disable multicast routing
                    468:  */
                    469: int
                    470: ip6_mrouter_done()
                    471: {
                    472:        mifi_t mifi;
                    473:        int i;
                    474:        struct ifnet *ifp;
                    475:        struct in6_ifreq ifr;
                    476:        struct mf6c *rt;
                    477:        struct rtdetq *rte;
                    478:        int s;
                    479:
                    480:        s = splsoftnet();
                    481:
                    482:        /*
                    483:         * For each phyint in use, disable promiscuous reception of all IPv6
                    484:         * multicasts.
                    485:         */
                    486: #ifdef INET
                    487: #ifdef MROUTING
                    488:        /*
                    489:         * If there is still IPv4 multicast routing daemon,
                    490:         * we remain interfaces to receive all muliticasted packets.
                    491:         * XXX: there may be an interface in which the IPv4 multicast
                    492:         * daemon is not interested...
                    493:         */
                    494:        if (!ip_mrouter)
                    495: #endif
                    496: #endif
                    497:        {
                    498:                for (mifi = 0; mifi < nummifs; mifi++) {
                    499:                        if (mif6table[mifi].m6_ifp &&
                    500:                            !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
                    501:                                ifr.ifr_addr.sin6_family = AF_INET6;
                    502:                                ifr.ifr_addr.sin6_addr= in6addr_any;
                    503:                                ifp = mif6table[mifi].m6_ifp;
                    504:                                (*ifp->if_ioctl)(ifp, SIOCDELMULTI,
                    505:                                                 (caddr_t)&ifr);
                    506:                        }
                    507:                }
                    508:        }
                    509: #ifdef notyet
                    510:        bzero((caddr_t)qtable, sizeof(qtable));
                    511:        bzero((caddr_t)tbftable, sizeof(tbftable));
                    512: #endif
                    513:        bzero((caddr_t)mif6table, sizeof(mif6table));
                    514:        nummifs = 0;
                    515:
                    516:        pim6 = 0; /* used to stub out/in pim specific code */
                    517:
                    518:        timeout_del(&expire_upcalls_ch);
                    519:
                    520:        /*
                    521:         * Free all multicast forwarding cache entries.
                    522:         */
                    523:        for (i = 0; i < MF6CTBLSIZ; i++) {
                    524:                rt = mf6ctable[i];
                    525:                while (rt) {
                    526:                        struct mf6c *frt;
                    527:
                    528:                        for (rte = rt->mf6c_stall; rte != NULL; ) {
                    529:                                struct rtdetq *n = rte->next;
                    530:
                    531:                                m_free(rte->m);
                    532:                                free(rte, M_MRTABLE);
                    533:                                rte = n;
                    534:                        }
                    535:                        frt = rt;
                    536:                        rt = rt->mf6c_next;
                    537:                        free(frt, M_MRTABLE);
                    538:                }
                    539:        }
                    540:
                    541:        bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
                    542:
                    543:        /*
                    544:         * Reset de-encapsulation cache
                    545:         */
                    546:        reg_mif_num = -1;
                    547:
                    548:        ip6_mrouter = NULL;
                    549:        ip6_mrouter_ver = 0;
                    550:
                    551:        splx(s);
                    552:
                    553: #ifdef MRT6DEBUG
                    554:        if (mrt6debug)
                    555:                log(LOG_DEBUG, "ip6_mrouter_done\n");
                    556: #endif
                    557:
                    558:        return 0;
                    559: }
                    560:
                    561: void
                    562: ip6_mrouter_detach(ifp)
                    563:        struct ifnet *ifp;
                    564: {
                    565:        struct rtdetq *rte;
                    566:        struct mf6c *mfc;
                    567:        mifi_t mifi;
                    568:        int i;
                    569:
                    570:        /*
                    571:         * Delete a mif which points to ifp.
                    572:         */
                    573:        for (mifi = 0; mifi < nummifs; mifi++)
                    574:                if (mif6table[mifi].m6_ifp == ifp)
                    575:                        del_m6if(&mifi);
                    576:
                    577:        /*
                    578:         * Clear rte->ifp of cache entries received on ifp.
                    579:         */
                    580:        for (i = 0; i < MF6CTBLSIZ; i++) {
                    581:                if (n6expire[i] == 0)
                    582:                        continue;
                    583:
                    584:                for (mfc = mf6ctable[i]; mfc != NULL; mfc = mfc->mf6c_next) {
                    585:                        for (rte = mfc->mf6c_stall; rte != NULL; rte = rte->next) {
                    586:                                if (rte->ifp == ifp)
                    587:                                        rte->ifp = NULL;
                    588:                        }
                    589:                }
                    590:        }
                    591: }
                    592:
                    593: /*
                    594:  * Add a mif to the mif table
                    595:  */
                    596: static int
                    597: add_m6if(mifcp)
                    598:        struct mif6ctl *mifcp;
                    599: {
                    600:        struct mif6 *mifp;
                    601:        struct ifnet *ifp;
                    602:        struct in6_ifreq ifr;
                    603:        int error, s;
                    604: #ifdef notyet
                    605:        struct tbf *m_tbf = tbftable + mifcp->mif6c_mifi;
                    606: #endif
                    607:
                    608:        if (mifcp->mif6c_mifi >= MAXMIFS)
                    609:                return EINVAL;
                    610:        mifp = mif6table + mifcp->mif6c_mifi;
                    611:        if (mifp->m6_ifp)
                    612:                return EADDRINUSE; /* XXX: is it appropriate? */
                    613:        if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi >= if_indexlim)
                    614:                return ENXIO;
                    615:        ifp = ifindex2ifnet[mifcp->mif6c_pifi];
                    616:        if (!ifp)
                    617:                return ENXIO;
                    618:
                    619:        if (mifcp->mif6c_flags & MIFF_REGISTER) {
                    620:                if (reg_mif_num == (mifi_t)-1) {
                    621:                        strlcpy(multicast_register_if.if_xname,
                    622:                            "register_mif",
                    623:                            sizeof multicast_register_if.if_xname); /* XXX */
                    624:                        multicast_register_if.if_flags |= IFF_LOOPBACK;
                    625:                        multicast_register_if.if_index = mifcp->mif6c_mifi;
                    626:                        reg_mif_num = mifcp->mif6c_mifi;
                    627:                }
                    628:
                    629:                ifp = &multicast_register_if;
                    630:
                    631:        } /* if REGISTER */
                    632:        else {
                    633:                /* Make sure the interface supports multicast */
                    634:                if ((ifp->if_flags & IFF_MULTICAST) == 0)
                    635:                        return EOPNOTSUPP;
                    636:
                    637:                s = splsoftnet();
                    638:
                    639:                /*
                    640:                 * Enable promiscuous reception of all IPv6 multicasts
                    641:                 * from the interface.
                    642:                 */
                    643:                ifr.ifr_addr.sin6_family = AF_INET6;
                    644:                ifr.ifr_addr.sin6_addr = in6addr_any;
                    645:                error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
                    646:
                    647:                splx(s);
                    648:                if (error)
                    649:                        return error;
                    650:        }
                    651:
                    652:        s = splsoftnet();
                    653:
                    654:        mifp->m6_flags     = mifcp->mif6c_flags;
                    655:        mifp->m6_ifp       = ifp;
                    656: #ifdef notyet
                    657:        /* scaling up here allows division by 1024 in critical code */
                    658:        mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000;
                    659: #endif
                    660:        /* initialize per mif pkt counters */
                    661:        mifp->m6_pkt_in    = 0;
                    662:        mifp->m6_pkt_out   = 0;
                    663:        mifp->m6_bytes_in  = 0;
                    664:        mifp->m6_bytes_out = 0;
                    665:        splx(s);
                    666:
                    667:        /* Adjust nummifs up if the mifi is higher than nummifs */
                    668:        if (nummifs <= mifcp->mif6c_mifi)
                    669:                nummifs = mifcp->mif6c_mifi + 1;
                    670:
                    671: #ifdef MRT6DEBUG
                    672:        if (mrt6debug)
                    673:                log(LOG_DEBUG,
                    674:                    "add_mif #%d, phyint %s%d\n",
                    675:                    mifcp->mif6c_mifi,
                    676:                    ifp->if_name, ifp->if_unit);
                    677: #endif
                    678:
                    679:        return 0;
                    680: }
                    681:
                    682: /*
                    683:  * Delete a mif from the mif table
                    684:  */
                    685: static int
                    686: del_m6if(mifip)
                    687:        mifi_t *mifip;
                    688: {
                    689:        struct mif6 *mifp = mif6table + *mifip;
                    690:        mifi_t mifi;
                    691:        struct ifnet *ifp;
                    692:        struct in6_ifreq ifr;
                    693:        int s;
                    694:
                    695:        if (*mifip >= nummifs)
                    696:                return EINVAL;
                    697:        if (mifp->m6_ifp == NULL)
                    698:                return EINVAL;
                    699:
                    700:        s = splsoftnet();
                    701:
                    702:        if (!(mifp->m6_flags & MIFF_REGISTER)) {
                    703:                /*
                    704:                 * XXX: what if there is yet IPv4 multicast daemon
                    705:                 *      using the interface?
                    706:                 */
                    707:                ifp = mifp->m6_ifp;
                    708:
                    709:                ifr.ifr_addr.sin6_family = AF_INET6;
                    710:                ifr.ifr_addr.sin6_addr = in6addr_any;
                    711:                (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
                    712:        }
                    713:
                    714: #ifdef notyet
                    715:        bzero((caddr_t)qtable[*mifip], sizeof(qtable[*mifip]));
                    716:        bzero((caddr_t)mifp->m6_tbf, sizeof(*(mifp->m6_tbf)));
                    717: #endif
                    718:        bzero((caddr_t)mifp, sizeof (*mifp));
                    719:
                    720:        /* Adjust nummifs down */
                    721:        for (mifi = nummifs; mifi > 0; mifi--)
                    722:                if (mif6table[mifi - 1].m6_ifp)
                    723:                        break;
                    724:        nummifs = mifi;
                    725:
                    726:        splx(s);
                    727:
                    728: #ifdef MRT6DEBUG
                    729:        if (mrt6debug)
                    730:                log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
                    731: #endif
                    732:
                    733:        return 0;
                    734: }
                    735:
                    736: /*
                    737:  * Add an mfc entry
                    738:  */
                    739: static int
                    740: add_m6fc(mfccp)
                    741:        struct mf6cctl *mfccp;
                    742: {
                    743:        struct mf6c *rt;
                    744:        u_long hash;
                    745:        struct rtdetq *rte;
                    746:        u_short nstl;
                    747:        int s;
                    748:
                    749:        MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
                    750:                 mfccp->mf6cc_mcastgrp.sin6_addr, rt);
                    751:
                    752:        /* If an entry already exists, just update the fields */
                    753:        if (rt) {
                    754: #ifdef MRT6DEBUG
                    755:                if (mrt6debug & DEBUG_MFC)
                    756:                        log(LOG_DEBUG,"add_m6fc update o %s g %s p %x\n",
                    757:                            ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
                    758:                            ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
                    759:                            mfccp->mf6cc_parent);
                    760: #endif
                    761:
                    762:                s = splsoftnet();
                    763:
                    764:                rt->mf6c_parent = mfccp->mf6cc_parent;
                    765:                rt->mf6c_ifset = mfccp->mf6cc_ifset;
                    766:                splx(s);
                    767:                return 0;
                    768:        }
                    769:
                    770:        /*
                    771:         * Find the entry for which the upcall was made and update
                    772:         */
                    773:        s = splsoftnet();
                    774:
                    775:        hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
                    776:                        mfccp->mf6cc_mcastgrp.sin6_addr);
                    777:        for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
                    778:                if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
                    779:                                       &mfccp->mf6cc_origin.sin6_addr) &&
                    780:                    IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
                    781:                                       &mfccp->mf6cc_mcastgrp.sin6_addr) &&
                    782:                    (rt->mf6c_stall != NULL)) {
                    783:
                    784:                        if (nstl++)
                    785:                                log(LOG_ERR,
                    786:                                    "add_m6fc: %s o %s g %s p %x dbx %p\n",
                    787:                                    "multiple kernel entries",
                    788:                                    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
                    789:                                    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
                    790:                                    mfccp->mf6cc_parent, rt->mf6c_stall);
                    791:
                    792: #ifdef MRT6DEBUG
                    793:                        if (mrt6debug & DEBUG_MFC)
                    794:                                log(LOG_DEBUG,
                    795:                                    "add_m6fc o %s g %s p %x dbg %x\n",
                    796:                                    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
                    797:                                    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
                    798:                                    mfccp->mf6cc_parent, rt->mf6c_stall);
                    799: #endif
                    800:
                    801:                        rt->mf6c_origin     = mfccp->mf6cc_origin;
                    802:                        rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;
                    803:                        rt->mf6c_parent     = mfccp->mf6cc_parent;
                    804:                        rt->mf6c_ifset      = mfccp->mf6cc_ifset;
                    805:                        /* initialize pkt counters per src-grp */
                    806:                        rt->mf6c_pkt_cnt    = 0;
                    807:                        rt->mf6c_byte_cnt   = 0;
                    808:                        rt->mf6c_wrong_if   = 0;
                    809:
                    810:                        rt->mf6c_expire = 0;    /* Don't clean this guy up */
                    811:                        n6expire[hash]--;
                    812:
                    813:                        /* free packets Qed at the end of this entry */
                    814:                        for (rte = rt->mf6c_stall; rte != NULL; ) {
                    815:                                struct rtdetq *n = rte->next;
                    816:                                if (rte->ifp) {
                    817:                                        ip6_mdq(rte->m, rte->ifp, rt);
                    818:                                }
                    819:                                m_freem(rte->m);
                    820: #ifdef UPCALL_TIMING
                    821:                                collate(&(rte->t));
                    822: #endif /* UPCALL_TIMING */
                    823:                                free(rte, M_MRTABLE);
                    824:                                rte = n;
                    825:                        }
                    826:                        rt->mf6c_stall = NULL;
                    827:                }
                    828:        }
                    829:
                    830:        /*
                    831:         * It is possible that an entry is being inserted without an upcall
                    832:         */
                    833:        if (nstl == 0) {
                    834: #ifdef MRT6DEBUG
                    835:                if (mrt6debug & DEBUG_MFC)
                    836:                        log(LOG_DEBUG,
                    837:                            "add_m6fc no upcall h %d o %s g %s p %x\n",
                    838:                            hash,
                    839:                            ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
                    840:                            ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
                    841:                            mfccp->mf6cc_parent);
                    842: #endif
                    843:
                    844:                for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
                    845:
                    846:                        if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
                    847:                                               &mfccp->mf6cc_origin.sin6_addr)&&
                    848:                            IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
                    849:                                               &mfccp->mf6cc_mcastgrp.sin6_addr)) {
                    850:
                    851:                                rt->mf6c_origin     = mfccp->mf6cc_origin;
                    852:                                rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;
                    853:                                rt->mf6c_parent     = mfccp->mf6cc_parent;
                    854:                                rt->mf6c_ifset      = mfccp->mf6cc_ifset;
                    855:                                /* initialize pkt counters per src-grp */
                    856:                                rt->mf6c_pkt_cnt    = 0;
                    857:                                rt->mf6c_byte_cnt   = 0;
                    858:                                rt->mf6c_wrong_if   = 0;
                    859:
                    860:                                if (rt->mf6c_expire)
                    861:                                        n6expire[hash]--;
                    862:                                rt->mf6c_expire    = 0;
                    863:                        }
                    864:                }
                    865:                if (rt == NULL) {
                    866:                        /* no upcall, so make a new entry */
                    867:                        rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE,
                    868:                                                  M_NOWAIT);
                    869:                        if (rt == NULL) {
                    870:                                splx(s);
                    871:                                return ENOBUFS;
                    872:                        }
                    873:
                    874:                        /* insert new entry at head of hash chain */
                    875:                        rt->mf6c_origin     = mfccp->mf6cc_origin;
                    876:                        rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;
                    877:                        rt->mf6c_parent     = mfccp->mf6cc_parent;
                    878:                        rt->mf6c_ifset      = mfccp->mf6cc_ifset;
                    879:                        /* initialize pkt counters per src-grp */
                    880:                        rt->mf6c_pkt_cnt    = 0;
                    881:                        rt->mf6c_byte_cnt   = 0;
                    882:                        rt->mf6c_wrong_if   = 0;
                    883:                        rt->mf6c_expire     = 0;
                    884:                        rt->mf6c_stall = NULL;
                    885:
                    886:                        /* link into table */
                    887:                        rt->mf6c_next  = mf6ctable[hash];
                    888:                        mf6ctable[hash] = rt;
                    889:                }
                    890:        }
                    891:        splx(s);
                    892:        return 0;
                    893: }
                    894:
                    895: #ifdef UPCALL_TIMING
                    896: /*
                    897:  * collect delay statistics on the upcalls
                    898:  */
                    899: static void
                    900: collate(t)
                    901:        struct timeval *t;
                    902: {
                    903:        u_long d;
                    904:        struct timeval tp;
                    905:        u_long delta;
                    906:
                    907:        GET_TIME(tp);
                    908:
                    909:        if (TV_LT(*t, tp))
                    910:        {
                    911:                TV_DELTA(tp, *t, delta);
                    912:
                    913:                d = delta >> 10;
                    914:                if (d > UPCALL_MAX)
                    915:                        d = UPCALL_MAX;
                    916:
                    917:                ++upcall_data[d];
                    918:        }
                    919: }
                    920: #endif /* UPCALL_TIMING */
                    921:
                    922: /*
                    923:  * Delete an mfc entry
                    924:  */
                    925: static int
                    926: del_m6fc(mfccp)
                    927:        struct mf6cctl *mfccp;
                    928: {
                    929:        struct sockaddr_in6     origin;
                    930:        struct sockaddr_in6     mcastgrp;
                    931:        struct mf6c             *rt;
                    932:        struct mf6c             **nptr;
                    933:        u_long          hash;
                    934:        int s;
                    935:
                    936:        origin = mfccp->mf6cc_origin;
                    937:        mcastgrp = mfccp->mf6cc_mcastgrp;
                    938:        hash = MF6CHASH(origin.sin6_addr, mcastgrp.sin6_addr);
                    939:
                    940: #ifdef MRT6DEBUG
                    941:        if (mrt6debug & DEBUG_MFC)
                    942:                log(LOG_DEBUG,"del_m6fc orig %s mcastgrp %s\n",
                    943:                    ip6_sprintf(&origin.sin6_addr),
                    944:                    ip6_sprintf(&mcastgrp.sin6_addr));
                    945: #endif
                    946:
                    947:        s = splsoftnet();
                    948:
                    949:        nptr = &mf6ctable[hash];
                    950:        while ((rt = *nptr) != NULL) {
                    951:                if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr,
                    952:                                       &rt->mf6c_origin.sin6_addr) &&
                    953:                    IN6_ARE_ADDR_EQUAL(&mcastgrp.sin6_addr,
                    954:                                       &rt->mf6c_mcastgrp.sin6_addr) &&
                    955:                    rt->mf6c_stall == NULL)
                    956:                        break;
                    957:
                    958:                nptr = &rt->mf6c_next;
                    959:        }
                    960:        if (rt == NULL) {
                    961:                splx(s);
                    962:                return EADDRNOTAVAIL;
                    963:        }
                    964:
                    965:        *nptr = rt->mf6c_next;
                    966:        free(rt, M_MRTABLE);
                    967:
                    968:        splx(s);
                    969:
                    970:        return 0;
                    971: }
                    972:
                    973: static int
                    974: socket_send(s, mm, src)
                    975:        struct socket *s;
                    976:        struct mbuf *mm;
                    977:        struct sockaddr_in6 *src;
                    978: {
                    979:        if (s) {
                    980:                if (sbappendaddr(&s->so_rcv,
                    981:                                 (struct sockaddr *)src,
                    982:                                 mm, (struct mbuf *)0) != 0) {
                    983:                        sorwakeup(s);
                    984:                        return 0;
                    985:                }
                    986:        }
                    987:        m_freem(mm);
                    988:        return -1;
                    989: }
                    990:
                    991: /*
                    992:  * IPv6 multicast forwarding function. This function assumes that the packet
                    993:  * pointed to by "ip6" has arrived on (or is about to be sent to) the interface
                    994:  * pointed to by "ifp", and the packet is to be relayed to other networks
                    995:  * that have members of the packet's destination IPv6 multicast group.
                    996:  *
                    997:  * The packet is returned unscathed to the caller, unless it is
                    998:  * erroneous, in which case a non-zero return value tells the caller to
                    999:  * discard it.
                   1000:  */
                   1001:
                   1002: int
                   1003: ip6_mforward(ip6, ifp, m)
                   1004:        struct ip6_hdr *ip6;
                   1005:        struct ifnet *ifp;
                   1006:        struct mbuf *m;
                   1007: {
                   1008:        struct mf6c *rt;
                   1009:        struct mif6 *mifp;
                   1010:        struct mbuf *mm;
                   1011:        int s;
                   1012:        mifi_t mifi;
                   1013:        struct sockaddr_in6 sin6;
                   1014:
                   1015: #ifdef MRT6DEBUG
                   1016:        if (mrt6debug & DEBUG_FORWARD)
                   1017:                log(LOG_DEBUG, "ip6_mforward: src %s, dst %s, ifindex %d\n",
                   1018:                    ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&ip6->ip6_dst),
                   1019:                    ifp->if_index);
                   1020: #endif
                   1021:
                   1022:        /*
                   1023:         * Don't forward a packet with Hop limit of zero or one,
                   1024:         * or a packet destined to a local-only group.
                   1025:         */
                   1026:        if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
                   1027:            IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
                   1028:                return 0;
                   1029:        ip6->ip6_hlim--;
                   1030:
                   1031:        /*
                   1032:         * Source address check: do not forward packets with unspecified
                   1033:         * source. It was discussed in July 2000, on ipngwg mailing list.
                   1034:         * This is rather more serious than unicast cases, because some
                   1035:         * MLD packets can be sent with the unspecified source address
                   1036:         * (although such packets must normally set 1 to the hop limit field).
                   1037:         */
                   1038:        if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
                   1039:                ip6stat.ip6s_cantforward++;
                   1040:                if (ip6_log_time + ip6_log_interval < time_second) {
                   1041:                        ip6_log_time = time_second;
                   1042:                        log(LOG_DEBUG,
                   1043:                            "cannot forward "
                   1044:                            "from %s to %s nxt %d received on %s\n",
                   1045:                            ip6_sprintf(&ip6->ip6_src),
                   1046:                            ip6_sprintf(&ip6->ip6_dst),
                   1047:                            ip6->ip6_nxt,
                   1048:                            m->m_pkthdr.rcvif->if_xname);
                   1049:                }
                   1050:                return 0;
                   1051:        }
                   1052:
                   1053:        /*
                   1054:         * Determine forwarding mifs from the forwarding cache table
                   1055:         */
                   1056:        s = splsoftnet();
                   1057:        MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt);
                   1058:
                   1059:        /* Entry exists, so forward if necessary */
                   1060:        if (rt) {
                   1061:                splx(s);
                   1062:                return (ip6_mdq(m, ifp, rt));
                   1063:        } else {
                   1064:                /*
                   1065:                 * If we don't have a route for packet's origin,
                   1066:                 * Make a copy of the packet &
                   1067:                 * send message to routing daemon
                   1068:                 */
                   1069:
                   1070:                struct mbuf *mb0;
                   1071:                struct rtdetq *rte;
                   1072:                u_long hash;
                   1073: /*             int i, npkts;*/
                   1074: #ifdef UPCALL_TIMING
                   1075:                struct timeval tp;
                   1076:
                   1077:                GET_TIME(tp);
                   1078: #endif /* UPCALL_TIMING */
                   1079:
                   1080:                mrt6stat.mrt6s_no_route++;
                   1081: #ifdef MRT6DEBUG
                   1082:                if (mrt6debug & (DEBUG_FORWARD | DEBUG_MFC))
                   1083:                        log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n",
                   1084:                            ip6_sprintf(&ip6->ip6_src),
                   1085:                            ip6_sprintf(&ip6->ip6_dst));
                   1086: #endif
                   1087:
                   1088:                /*
                   1089:                 * Allocate mbufs early so that we don't do extra work if we
                   1090:                 * are just going to fail anyway.
                   1091:                 */
                   1092:                rte = (struct rtdetq *)malloc(sizeof(*rte), M_MRTABLE,
                   1093:                                              M_NOWAIT);
                   1094:                if (rte == NULL) {
                   1095:                        splx(s);
                   1096:                        return ENOBUFS;
                   1097:                }
                   1098:                mb0 = m_copy(m, 0, M_COPYALL);
                   1099:                /*
                   1100:                 * Pullup packet header if needed before storing it,
                   1101:                 * as other references may modify it in the meantime.
                   1102:                 */
                   1103:                if (mb0 &&
                   1104:                    (M_READONLY(mb0) || mb0->m_len < sizeof(struct ip6_hdr)))
                   1105:                        mb0 = m_pullup(mb0, sizeof(struct ip6_hdr));
                   1106:                if (mb0 == NULL) {
                   1107:                        free(rte, M_MRTABLE);
                   1108:                        splx(s);
                   1109:                        return ENOBUFS;
                   1110:                }
                   1111:
                   1112:                /* is there an upcall waiting for this packet? */
                   1113:                hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst);
                   1114:                for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
                   1115:                        if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src,
                   1116:                                               &rt->mf6c_origin.sin6_addr) &&
                   1117:                            IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
                   1118:                                               &rt->mf6c_mcastgrp.sin6_addr) &&
                   1119:                            (rt->mf6c_stall != NULL))
                   1120:                                break;
                   1121:                }
                   1122:
                   1123:                if (rt == NULL) {
                   1124:                        struct mrt6msg *im;
                   1125: #ifdef MRT6_OINIT
                   1126:                        struct omrt6msg *oim;
                   1127: #endif
                   1128:
                   1129:                        /* no upcall, so make a new entry */
                   1130:                        rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE,
                   1131:                                                  M_NOWAIT);
                   1132:                        if (rt == NULL) {
                   1133:                                free(rte, M_MRTABLE);
                   1134:                                m_freem(mb0);
                   1135:                                splx(s);
                   1136:                                return ENOBUFS;
                   1137:                        }
                   1138:                        /*
                   1139:                         * Make a copy of the header to send to the user
                   1140:                         * level process
                   1141:                         */
                   1142:                        mm = m_copy(mb0, 0, sizeof(struct ip6_hdr));
                   1143:
                   1144:                        if (mm == NULL) {
                   1145:                                free(rte, M_MRTABLE);
                   1146:                                m_freem(mb0);
                   1147:                                free(rt, M_MRTABLE);
                   1148:                                splx(s);
                   1149:                                return ENOBUFS;
                   1150:                        }
                   1151:
                   1152:                        /*
                   1153:                         * Send message to routing daemon
                   1154:                         */
                   1155:                        (void)memset(&sin6, 0, sizeof(sin6));
                   1156:                        sin6.sin6_len = sizeof(sin6);
                   1157:                        sin6.sin6_family = AF_INET6;
                   1158:                        sin6.sin6_addr = ip6->ip6_src;
                   1159:
                   1160:                        im = NULL;
                   1161: #ifdef MRT6_OINIT
                   1162:                        oim = NULL;
                   1163: #endif
                   1164:                        switch (ip6_mrouter_ver) {
                   1165: #ifdef MRT6_OINIT
                   1166:                        case MRT6_OINIT:
                   1167:                                oim = mtod(mm, struct omrt6msg *);
                   1168:                                oim->im6_msgtype = MRT6MSG_NOCACHE;
                   1169:                                oim->im6_mbz = 0;
                   1170:                                break;
                   1171: #endif
                   1172:                        case MRT6_INIT:
                   1173:                                im = mtod(mm, struct mrt6msg *);
                   1174:                                im->im6_msgtype = MRT6MSG_NOCACHE;
                   1175:                                im->im6_mbz = 0;
                   1176:                                break;
                   1177:                        default:
                   1178:                                free(rte, M_MRTABLE);
                   1179:                                m_freem(mb0);
                   1180:                                free(rt, M_MRTABLE);
                   1181:                                splx(s);
                   1182:                                return EINVAL;
                   1183:                        }
                   1184:
                   1185: #ifdef MRT6DEBUG
                   1186:                        if (mrt6debug & DEBUG_FORWARD)
                   1187:                                log(LOG_DEBUG,
                   1188:                                    "getting the iif info in the kernel\n");
                   1189: #endif
                   1190:
                   1191:                        for (mifp = mif6table, mifi = 0;
                   1192:                             mifi < nummifs && mifp->m6_ifp != ifp;
                   1193:                             mifp++, mifi++)
                   1194:                                ;
                   1195:
                   1196:                        switch (ip6_mrouter_ver) {
                   1197: #ifdef MRT6_OINIT
                   1198:                        case MRT6_OINIT:
                   1199:                                oim->im6_mif = mifi;
                   1200:                                break;
                   1201: #endif
                   1202:                        case MRT6_INIT:
                   1203:                                im->im6_mif = mifi;
                   1204:                                break;
                   1205:                        }
                   1206:
                   1207:                        if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
                   1208:                                log(LOG_WARNING, "ip6_mforward: ip6_mrouter "
                   1209:                                    "socket queue full\n");
                   1210:                                mrt6stat.mrt6s_upq_sockfull++;
                   1211:                                free(rte, M_MRTABLE);
                   1212:                                m_freem(mb0);
                   1213:                                free(rt, M_MRTABLE);
                   1214:                                splx(s);
                   1215:                                return ENOBUFS;
                   1216:                        }
                   1217:
                   1218:                        mrt6stat.mrt6s_upcalls++;
                   1219:
                   1220:                        /* insert new entry at head of hash chain */
                   1221:                        bzero(rt, sizeof(*rt));
                   1222:                        rt->mf6c_origin.sin6_family = AF_INET6;
                   1223:                        rt->mf6c_origin.sin6_len = sizeof(struct sockaddr_in6);
                   1224:                        rt->mf6c_origin.sin6_addr = ip6->ip6_src;
                   1225:                        rt->mf6c_mcastgrp.sin6_family = AF_INET6;
                   1226:                        rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6);
                   1227:                        rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst;
                   1228:                        rt->mf6c_expire = UPCALL_EXPIRE;
                   1229:                        n6expire[hash]++;
                   1230:                        rt->mf6c_parent = MF6C_INCOMPLETE_PARENT;
                   1231:
                   1232:                        /* link into table */
                   1233:                        rt->mf6c_next  = mf6ctable[hash];
                   1234:                        mf6ctable[hash] = rt;
                   1235:                        /* Add this entry to the end of the queue */
                   1236:                        rt->mf6c_stall = rte;
                   1237:                } else {
                   1238:                        /* determine if q has overflowed */
                   1239:                        struct rtdetq **p;
                   1240:                        int npkts = 0;
                   1241:
                   1242:                        for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next)
                   1243:                                if (++npkts > MAX_UPQ6) {
                   1244:                                        mrt6stat.mrt6s_upq_ovflw++;
                   1245:                                        free(rte, M_MRTABLE);
                   1246:                                        m_freem(mb0);
                   1247:                                        splx(s);
                   1248:                                        return 0;
                   1249:                                }
                   1250:
                   1251:                        /* Add this entry to the end of the queue */
                   1252:                        *p = rte;
                   1253:                }
                   1254:
                   1255:                rte->next = NULL;
                   1256:                rte->m = mb0;
                   1257:                rte->ifp = ifp;
                   1258: #ifdef UPCALL_TIMING
                   1259:                rte->t = tp;
                   1260: #endif /* UPCALL_TIMING */
                   1261:
                   1262:                splx(s);
                   1263:
                   1264:                return 0;
                   1265:        }
                   1266: }
                   1267:
                   1268: /*
                   1269:  * Clean up cache entries if upcalls are not serviced
                   1270:  * Call from the Slow Timeout mechanism, every half second.
                   1271:  */
                   1272: static void
                   1273: expire_upcalls(unused)
                   1274:        void *unused;
                   1275: {
                   1276:        struct rtdetq *rte;
                   1277:        struct mf6c *mfc, **nptr;
                   1278:        int i;
                   1279:        int s;
                   1280:
                   1281:        s = splsoftnet();
                   1282:
                   1283:        for (i = 0; i < MF6CTBLSIZ; i++) {
                   1284:                if (n6expire[i] == 0)
                   1285:                        continue;
                   1286:                nptr = &mf6ctable[i];
                   1287:                while ((mfc = *nptr) != NULL) {
                   1288:                        rte = mfc->mf6c_stall;
                   1289:                        /*
                   1290:                         * Skip real cache entries
                   1291:                         * Make sure it wasn't marked to not expire (shouldn't happen)
                   1292:                         * If it expires now
                   1293:                         */
                   1294:                        if (rte != NULL &&
                   1295:                            mfc->mf6c_expire != 0 &&
                   1296:                            --mfc->mf6c_expire == 0) {
                   1297: #ifdef MRT6DEBUG
                   1298:                                if (mrt6debug & DEBUG_EXPIRE)
                   1299:                                        log(LOG_DEBUG, "expire_upcalls: expiring (%s %s)\n",
                   1300:                                            ip6_sprintf(&mfc->mf6c_origin.sin6_addr),
                   1301:                                            ip6_sprintf(&mfc->mf6c_mcastgrp.sin6_addr));
                   1302: #endif
                   1303:                                /*
                   1304:                                 * drop all the packets
                   1305:                                 * free the mbuf with the pkt, if, timing info
                   1306:                                 */
                   1307:                                do {
                   1308:                                        struct rtdetq *n = rte->next;
                   1309:                                        m_freem(rte->m);
                   1310:                                        free(rte, M_MRTABLE);
                   1311:                                        rte = n;
                   1312:                                } while (rte != NULL);
                   1313:                                mrt6stat.mrt6s_cache_cleanups++;
                   1314:                                n6expire[i]--;
                   1315:
                   1316:                                *nptr = mfc->mf6c_next;
                   1317:                                free(mfc, M_MRTABLE);
                   1318:                        } else {
                   1319:                                nptr = &mfc->mf6c_next;
                   1320:                        }
                   1321:                }
                   1322:        }
                   1323:        splx(s);
                   1324:        timeout_set(&expire_upcalls_ch, expire_upcalls, NULL);
                   1325:        timeout_add(&expire_upcalls_ch, EXPIRE_TIMEOUT);
                   1326: }
                   1327:
                   1328: /*
                   1329:  * Packet forwarding routine once entry in the cache is made
                   1330:  */
                   1331: static int
                   1332: ip6_mdq(m, ifp, rt)
                   1333:        struct mbuf *m;
                   1334:        struct ifnet *ifp;
                   1335:        struct mf6c *rt;
                   1336: {
                   1337:        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
                   1338:        mifi_t mifi, iif;
                   1339:        struct mif6 *mifp;
                   1340:        int plen = m->m_pkthdr.len;
                   1341:
                   1342: /*
                   1343:  * Macro to send packet on mif.  Since RSVP packets don't get counted on
                   1344:  * input, they shouldn't get counted on output, so statistics keeping is
                   1345:  * separate.
                   1346:  */
                   1347:
                   1348: #define MC6_SEND(ip6, mifp, m) do {                            \
                   1349:                if ((mifp)->m6_flags & MIFF_REGISTER)           \
                   1350:                    register_send((ip6), (mifp), (m));          \
                   1351:                else                                            \
                   1352:                    phyint_send((ip6), (mifp), (m));            \
                   1353: } while (0)
                   1354:
                   1355:        /*
                   1356:         * Don't forward if it didn't arrive from the parent mif
                   1357:         * for its origin.
                   1358:         */
                   1359:        mifi = rt->mf6c_parent;
                   1360:        if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) {
                   1361:                /* came in the wrong interface */
                   1362: #ifdef MRT6DEBUG
                   1363:                if (mrt6debug & DEBUG_FORWARD)
                   1364:                        log(LOG_DEBUG,
                   1365:                            "wrong if: ifid %d mifi %d mififid %x\n",
                   1366:                            ifp->if_index, mifi,
                   1367:                            mif6table[mifi].m6_ifp ?
                   1368:                            mif6table[mifi].m6_ifp->if_index : -1);
                   1369: #endif
                   1370:                mrt6stat.mrt6s_wrong_if++;
                   1371:                rt->mf6c_wrong_if++;
                   1372:                /*
                   1373:                 * If we are doing PIM processing, and we are forwarding
                   1374:                 * packets on this interface, send a message to the
                   1375:                 * routing daemon.
                   1376:                 */
                   1377:                /* have to make sure this is a valid mif */
                   1378:                if (mifi < nummifs && mif6table[mifi].m6_ifp)
                   1379:                        if (pim6 && (m->m_flags & M_LOOP) == 0) {
                   1380:                                /*
                   1381:                                 * Check the M_LOOP flag to avoid an
                   1382:                                 * unnecessary PIM assert.
                   1383:                                 * XXX: M_LOOP is an ad-hoc hack...
                   1384:                                 */
                   1385:                                struct sockaddr_in6 sin6;
                   1386:
                   1387:                                struct mbuf *mm;
                   1388:                                struct mrt6msg *im;
                   1389: #ifdef MRT6_OINIT
                   1390:                                struct omrt6msg *oim;
                   1391: #endif
                   1392:
                   1393:                                mm = m_copy(m, 0, sizeof(struct ip6_hdr));
                   1394:                                if (mm &&
                   1395:                                    (M_READONLY(mm) ||
                   1396:                                     mm->m_len < sizeof(struct ip6_hdr)))
                   1397:                                        mm = m_pullup(mm, sizeof(struct ip6_hdr));
                   1398:                                if (mm == NULL)
                   1399:                                        return ENOBUFS;
                   1400:
                   1401: #ifdef MRT6_OINIT
                   1402:                                oim = NULL;
                   1403: #endif
                   1404:                                im = NULL;
                   1405:                                switch (ip6_mrouter_ver) {
                   1406: #ifdef MRT6_OINIT
                   1407:                                case MRT6_OINIT:
                   1408:                                        oim = mtod(mm, struct omrt6msg *);
                   1409:                                        oim->im6_msgtype = MRT6MSG_WRONGMIF;
                   1410:                                        oim->im6_mbz = 0;
                   1411:                                        break;
                   1412: #endif
                   1413:                                case MRT6_INIT:
                   1414:                                        im = mtod(mm, struct mrt6msg *);
                   1415:                                        im->im6_msgtype = MRT6MSG_WRONGMIF;
                   1416:                                        im->im6_mbz = 0;
                   1417:                                        break;
                   1418:                                default:
                   1419:                                        m_freem(mm);
                   1420:                                        return EINVAL;
                   1421:                                }
                   1422:
                   1423:                                for (mifp = mif6table, iif = 0;
                   1424:                                     iif < nummifs && mifp &&
                   1425:                                             mifp->m6_ifp != ifp;
                   1426:                                     mifp++, iif++)
                   1427:                                        ;
                   1428:
                   1429:                                (void)memset(&sin6, 0, sizeof(sin6));
                   1430:                                sin6.sin6_len = sizeof(sin6);
                   1431:                                sin6.sin6_family = AF_INET6;
                   1432:                                switch (ip6_mrouter_ver) {
                   1433: #ifdef MRT6_OINIT
                   1434:                                case MRT6_OINIT:
                   1435:                                        oim->im6_mif = iif;
                   1436:                                        sin6.sin6_addr = oim->im6_src;
                   1437:                                        break;
                   1438: #endif
                   1439:                                case MRT6_INIT:
                   1440:                                        im->im6_mif = iif;
                   1441:                                        sin6.sin6_addr = im->im6_src;
                   1442:                                        break;
                   1443:                                }
                   1444:
                   1445:                                mrt6stat.mrt6s_upcalls++;
                   1446:
                   1447:                                if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
                   1448: #ifdef MRT6DEBUG
                   1449:                                        if (mrt6debug)
                   1450:                                                log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
                   1451: #endif
                   1452:                                        ++mrt6stat.mrt6s_upq_sockfull;
                   1453:                                        return ENOBUFS;
                   1454:                                }       /* if socket Q full */
                   1455:                        }               /* if PIM */
                   1456:                return 0;
                   1457:        }                       /* if wrong iif */
                   1458:
                   1459:        /* If I sourced this packet, it counts as output, else it was input. */
                   1460:        if (m->m_pkthdr.rcvif == NULL) {
                   1461:                /* XXX: is rcvif really NULL when output?? */
                   1462:                mif6table[mifi].m6_pkt_out++;
                   1463:                mif6table[mifi].m6_bytes_out += plen;
                   1464:        } else {
                   1465:                mif6table[mifi].m6_pkt_in++;
                   1466:                mif6table[mifi].m6_bytes_in += plen;
                   1467:        }
                   1468:        rt->mf6c_pkt_cnt++;
                   1469:        rt->mf6c_byte_cnt += plen;
                   1470:
                   1471:        /*
                   1472:         * For each mif, forward a copy of the packet if there are group
                   1473:         * members downstream on the interface.
                   1474:         */
                   1475:        for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++)
                   1476:                if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
                   1477:                        if (mif6table[mifi].m6_ifp == NULL)
                   1478:                                continue;
                   1479:
                   1480:                        /*
                   1481:                         * check if the outgoing packet is going to break
                   1482:                         * a scope boundary.
                   1483:                         * XXX For packets through PIM register tunnel
                   1484:                         * interface, we believe a routing daemon.
                   1485:                         */
                   1486:                        if ((mif6table[rt->mf6c_parent].m6_flags &
                   1487:                             MIFF_REGISTER) == 0 &&
                   1488:                            (mif6table[mifi].m6_flags & MIFF_REGISTER) == 0 &&
                   1489:                            (in6_addr2scopeid(ifp, &ip6->ip6_dst) !=
                   1490:                             in6_addr2scopeid(mif6table[mifi].m6_ifp,
                   1491:                                              &ip6->ip6_dst) ||
                   1492:                             in6_addr2scopeid(ifp, &ip6->ip6_src) !=
                   1493:                             in6_addr2scopeid(mif6table[mifi].m6_ifp,
                   1494:                                              &ip6->ip6_src))) {
                   1495:                                ip6stat.ip6s_badscope++;
                   1496:                                continue;
                   1497:                        }
                   1498:
                   1499:                        mifp->m6_pkt_out++;
                   1500:                        mifp->m6_bytes_out += plen;
                   1501:                        MC6_SEND(ip6, mifp, m);
                   1502:                }
                   1503:        return 0;
                   1504: }
                   1505:
                   1506: static void
                   1507: phyint_send(ip6, mifp, m)
                   1508:        struct ip6_hdr *ip6;
                   1509:        struct mif6 *mifp;
                   1510:        struct mbuf *m;
                   1511: {
                   1512:        struct mbuf *mb_copy;
                   1513:        struct ifnet *ifp = mifp->m6_ifp;
                   1514:        int error = 0;
                   1515:        int s = splsoftnet();
                   1516:        static struct route_in6 ro;
                   1517:        struct  in6_multi *in6m;
                   1518:        struct sockaddr_in6 *dst6;
                   1519:        u_long linkmtu;
                   1520:
                   1521:        /*
                   1522:         * Make a new reference to the packet; make sure that
                   1523:         * the IPv6 header is actually copied, not just referenced,
                   1524:         * so that ip6_output() only scribbles on the copy.
                   1525:         */
                   1526:        mb_copy = m_copy(m, 0, M_COPYALL);
                   1527:        if (mb_copy &&
                   1528:            (M_READONLY(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr)))
                   1529:                mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr));
                   1530:        if (mb_copy == NULL) {
                   1531:                splx(s);
                   1532:                return;
                   1533:        }
                   1534:        /* set MCAST flag to the outgoing packet */
                   1535:        mb_copy->m_flags |= M_MCAST;
                   1536:
                   1537:        /*
                   1538:         * If we sourced the packet, call ip6_output since we may devide
                   1539:         * the packet into fragments when the packet is too big for the
                   1540:         * outgoing interface.
                   1541:         * Otherwise, we can simply send the packet to the interface
                   1542:         * sending queue.
                   1543:         */
                   1544:        if (m->m_pkthdr.rcvif == NULL) {
                   1545:                struct ip6_moptions im6o;
                   1546:
                   1547:                im6o.im6o_multicast_ifp = ifp;
                   1548:                /* XXX: ip6_output will override ip6->ip6_hlim */
                   1549:                im6o.im6o_multicast_hlim = ip6->ip6_hlim;
                   1550:                im6o.im6o_multicast_loop = 1;
                   1551:                error = ip6_output(mb_copy, NULL, &ro, IPV6_FORWARDING, &im6o,
                   1552:                    NULL, NULL);
                   1553:
                   1554: #ifdef MRT6DEBUG
                   1555:                if (mrt6debug & DEBUG_XMIT)
                   1556:                        log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
                   1557:                            mifp - mif6table, error);
                   1558: #endif
                   1559:                splx(s);
                   1560:                return;
                   1561:        }
                   1562:
                   1563:        /*
                   1564:         * If we belong to the destination multicast group
                   1565:         * on the outgoing interface, loop back a copy.
                   1566:         */
                   1567:        dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
                   1568:        IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
                   1569:        if (in6m != NULL) {
                   1570:                dst6->sin6_len = sizeof(struct sockaddr_in6);
                   1571:                dst6->sin6_family = AF_INET6;
                   1572:                dst6->sin6_addr = ip6->ip6_dst;
                   1573:                ip6_mloopback(ifp, m, (struct sockaddr_in6 *)&ro.ro_dst);
                   1574:        }
                   1575:        /*
                   1576:         * Put the packet into the sending queue of the outgoing interface
                   1577:         * if it would fit in the MTU of the interface.
                   1578:         */
                   1579:        linkmtu = IN6_LINKMTU(ifp);
                   1580:        if (mb_copy->m_pkthdr.len <= linkmtu || linkmtu < IPV6_MMTU) {
                   1581:                dst6->sin6_len = sizeof(struct sockaddr_in6);
                   1582:                dst6->sin6_family = AF_INET6;
                   1583:                dst6->sin6_addr = ip6->ip6_dst;
                   1584:                /*
                   1585:                 * We just call if_output instead of nd6_output here, since
                   1586:                 * we need no ND for a multicast forwarded packet...right?
                   1587:                 */
                   1588:                error = (*ifp->if_output)(ifp, mb_copy,
                   1589:                    (struct sockaddr *)&ro.ro_dst, NULL);
                   1590: #ifdef MRT6DEBUG
                   1591:                if (mrt6debug & DEBUG_XMIT)
                   1592:                        log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
                   1593:                            mifp - mif6table, error);
                   1594: #endif
                   1595:        } else {
                   1596:                if (ip6_mcast_pmtu)
                   1597:                        icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, linkmtu);
                   1598:                else {
                   1599: #ifdef MRT6DEBUG
                   1600:                        if (mrt6debug & DEBUG_XMIT)
                   1601:                                log(LOG_DEBUG,
                   1602:                                    "phyint_send: packet too big on %s o %s g %s"
                   1603:                                    " size %d(discarded)\n",
                   1604:                                    ifp->if_xname,
                   1605:                                    ip6_sprintf(&ip6->ip6_src),
                   1606:                                    ip6_sprintf(&ip6->ip6_dst),
                   1607:                                    mb_copy->m_pkthdr.len);
                   1608: #endif /* MRT6DEBUG */
                   1609:                        m_freem(mb_copy); /* simply discard the packet */
                   1610:                }
                   1611:        }
                   1612:
                   1613:        splx(s);
                   1614: }
                   1615:
                   1616: static int
                   1617: register_send(ip6, mif, m)
                   1618:        struct ip6_hdr *ip6;
                   1619:        struct mif6 *mif;
                   1620:        struct mbuf *m;
                   1621: {
                   1622:        struct mbuf *mm;
                   1623:        int i, len = m->m_pkthdr.len;
                   1624:        struct sockaddr_in6 sin6;
                   1625:        struct mrt6msg *im6;
                   1626:
                   1627: #ifdef MRT6DEBUG
                   1628:        if (mrt6debug)
                   1629:                log(LOG_DEBUG, "** IPv6 register_send **\n src %s dst %s\n",
                   1630:                    ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&ip6->ip6_dst));
                   1631: #endif
                   1632:        ++pim6stat.pim6s_snd_registers;
                   1633:
                   1634:        /* Make a copy of the packet to send to the user level process */
                   1635:        MGETHDR(mm, M_DONTWAIT, MT_HEADER);
                   1636:        if (mm == NULL)
                   1637:                return ENOBUFS;
                   1638:        mm->m_data += max_linkhdr;
                   1639:        mm->m_len = sizeof(struct ip6_hdr);
                   1640:
                   1641:        if ((mm->m_next = m_copy(m, 0, M_COPYALL)) == NULL) {
                   1642:                m_freem(mm);
                   1643:                return ENOBUFS;
                   1644:        }
                   1645:        i = MHLEN - M_LEADINGSPACE(mm);
                   1646:        if (i > len)
                   1647:                i = len;
                   1648:        mm = m_pullup(mm, i);
                   1649:        if (mm == NULL)
                   1650:                return ENOBUFS;
                   1651: /* TODO: check it! */
                   1652:        mm->m_pkthdr.len = len + sizeof(struct ip6_hdr);
                   1653:
                   1654:        /*
                   1655:         * Send message to routing daemon
                   1656:         */
                   1657:        (void)memset(&sin6, 0, sizeof(sin6));
                   1658:        sin6.sin6_len = sizeof(sin6);
                   1659:        sin6.sin6_family = AF_INET6;
                   1660:        sin6.sin6_addr = ip6->ip6_src;
                   1661:
                   1662:        im6 = mtod(mm, struct mrt6msg *);
                   1663:        im6->im6_msgtype      = MRT6MSG_WHOLEPKT;
                   1664:        im6->im6_mbz          = 0;
                   1665:
                   1666:        im6->im6_mif = mif - mif6table;
                   1667:
                   1668:        /* iif info is not given for reg. encap.n */
                   1669:        mrt6stat.mrt6s_upcalls++;
                   1670:
                   1671:        if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
                   1672: #ifdef MRT6DEBUG
                   1673:                if (mrt6debug)
                   1674:                        log(LOG_WARNING,
                   1675:                            "register_send: ip6_mrouter socket queue full\n");
                   1676: #endif
                   1677:                ++mrt6stat.mrt6s_upq_sockfull;
                   1678:                return ENOBUFS;
                   1679:        }
                   1680:        return 0;
                   1681: }
                   1682:
                   1683: /*
                   1684:  * PIM sparse mode hook
                   1685:  * Receives the pim control messages, and passes them up to the listening
                   1686:  * socket, using rip6_input.
                   1687:  * The only message processed is the REGISTER pim message; the pim header
                   1688:  * is stripped off, and the inner packet is passed to register_mforward.
                   1689:  */
                   1690: int
                   1691: pim6_input(mp, offp, proto)
                   1692:        struct mbuf **mp;
                   1693:        int *offp, proto;
                   1694: {
                   1695:        struct pim *pim; /* pointer to a pim struct */
                   1696:        struct ip6_hdr *ip6;
                   1697:        int pimlen;
                   1698:        struct mbuf *m = *mp;
                   1699:        int minlen;
                   1700:        int off = *offp;
                   1701:
                   1702:        ++pim6stat.pim6s_rcv_total;
                   1703:
                   1704:        ip6 = mtod(m, struct ip6_hdr *);
                   1705:        pimlen = m->m_pkthdr.len - *offp;
                   1706:
                   1707:        /*
                   1708:         * Validate lengths
                   1709:         */
                   1710:        if (pimlen < PIM_MINLEN) {
                   1711:                ++pim6stat.pim6s_rcv_tooshort;
                   1712: #ifdef MRT6DEBUG
                   1713:                if (mrt6debug & DEBUG_PIM)
                   1714:                        log(LOG_DEBUG,"pim6_input: PIM packet too short\n");
                   1715: #endif
                   1716:                m_freem(m);
                   1717:                return (IPPROTO_DONE);
                   1718:        }
                   1719:
                   1720:        /*
                   1721:         * if the packet is at least as big as a REGISTER, go ahead
                   1722:         * and grab the PIM REGISTER header size, to avoid another
                   1723:         * possible m_pullup() later.
                   1724:         *
                   1725:         * PIM_MINLEN       == pimhdr + u_int32 == 8
                   1726:         * PIM6_REG_MINLEN   == pimhdr + reghdr + eip6hdr == 4 + 4 + 40
                   1727:         */
                   1728:        minlen = (pimlen >= PIM6_REG_MINLEN) ? PIM6_REG_MINLEN : PIM_MINLEN;
                   1729:
                   1730:        /*
                   1731:         * Make sure that the IP6 and PIM headers in contiguous memory, and
                   1732:         * possibly the PIM REGISTER header
                   1733:         */
                   1734:        IP6_EXTHDR_GET(pim, struct pim *, m, off, minlen);
                   1735:        if (pim == NULL) {
                   1736:                pim6stat.pim6s_rcv_tooshort++;
                   1737:                return IPPROTO_DONE;
                   1738:        }
                   1739:
                   1740:        /* PIM version check */
                   1741:        if (pim->pim_ver != PIM_VERSION) {
                   1742:                ++pim6stat.pim6s_rcv_badversion;
                   1743: #ifdef MRT6DEBUG
                   1744:                log(LOG_ERR,
                   1745:                    "pim6_input: incorrect version %d, expecting %d\n",
                   1746:                    pim->pim_ver, PIM_VERSION);
                   1747: #endif
                   1748:                m_freem(m);
                   1749:                return (IPPROTO_DONE);
                   1750:        }
                   1751:
                   1752: #define PIM6_CHECKSUM
                   1753: #ifdef PIM6_CHECKSUM
                   1754:        {
                   1755:                int cksumlen;
                   1756:
                   1757:                /*
                   1758:                 * Validate checksum.
                   1759:                 * If PIM REGISTER, exclude the data packet
                   1760:                 */
                   1761:                if (pim->pim_type == PIM_REGISTER)
                   1762:                        cksumlen = PIM_MINLEN;
                   1763:                else
                   1764:                        cksumlen = pimlen;
                   1765:
                   1766:                if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) {
                   1767:                        ++pim6stat.pim6s_rcv_badsum;
                   1768: #ifdef MRT6DEBUG
                   1769:                        if (mrt6debug & DEBUG_PIM)
                   1770:                                log(LOG_DEBUG,
                   1771:                                    "pim6_input: invalid checksum\n");
                   1772: #endif
                   1773:                        m_freem(m);
                   1774:                        return (IPPROTO_DONE);
                   1775:                }
                   1776:        }
                   1777: #endif /* PIM_CHECKSUM */
                   1778:
                   1779:        if (pim->pim_type == PIM_REGISTER) {
                   1780:                /*
                   1781:                 * since this is a REGISTER, we'll make a copy of the register
                   1782:                 * headers ip6+pim+u_int32_t+encap_ip6, to be passed up to the
                   1783:                 * routing daemon.
                   1784:                 */
                   1785:                static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 };
                   1786:
                   1787:                struct mbuf *mcp;
                   1788:                struct ip6_hdr *eip6;
                   1789:                u_int32_t *reghdr;
                   1790:                int rc;
                   1791:
                   1792:                ++pim6stat.pim6s_rcv_registers;
                   1793:
                   1794:                if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) {
                   1795: #ifdef MRT6DEBUG
                   1796:                        if (mrt6debug & DEBUG_PIM)
                   1797:                                log(LOG_DEBUG,
                   1798:                                    "pim6_input: register mif not set: %d\n",
                   1799:                                    reg_mif_num);
                   1800: #endif
                   1801:                        m_freem(m);
                   1802:                        return (IPPROTO_DONE);
                   1803:                }
                   1804:
                   1805:                reghdr = (u_int32_t *)(pim + 1);
                   1806:
                   1807:                if ((ntohl(*reghdr) & PIM_NULL_REGISTER))
                   1808:                        goto pim6_input_to_daemon;
                   1809:
                   1810:                /*
                   1811:                 * Validate length
                   1812:                 */
                   1813:                if (pimlen < PIM6_REG_MINLEN) {
                   1814:                        ++pim6stat.pim6s_rcv_tooshort;
                   1815:                        ++pim6stat.pim6s_rcv_badregisters;
                   1816: #ifdef MRT6DEBUG
                   1817:                        log(LOG_ERR,
                   1818:                            "pim6_input: register packet size too "
                   1819:                            "small %d from %s\n",
                   1820:                            pimlen, ip6_sprintf(&ip6->ip6_src));
                   1821: #endif
                   1822:                        m_freem(m);
                   1823:                        return (IPPROTO_DONE);
                   1824:                }
                   1825:
                   1826:                eip6 = (struct ip6_hdr *) (reghdr + 1);
                   1827: #ifdef MRT6DEBUG
                   1828:                if (mrt6debug & DEBUG_PIM)
                   1829:                        log(LOG_DEBUG,
                   1830:                            "pim6_input[register], eip6: %s -> %s, "
                   1831:                            "eip6 plen %d\n",
                   1832:                            ip6_sprintf(&eip6->ip6_src),
                   1833:                            ip6_sprintf(&eip6->ip6_dst),
                   1834:                            ntohs(eip6->ip6_plen));
                   1835: #endif
                   1836:
                   1837:                /* verify the version number of the inner packet */
                   1838:                if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
                   1839:                        ++pim6stat.pim6s_rcv_badregisters;
                   1840: #ifdef MRT6DEBUG
                   1841:                        log(LOG_DEBUG, "pim6_input: invalid IP version (%d) "
                   1842:                            "of the inner packet\n",
                   1843:                            (eip6->ip6_vfc & IPV6_VERSION));
                   1844: #endif
                   1845:                        m_freem(m);
                   1846:                        return (IPPROTO_NONE);
                   1847:                }
                   1848:
                   1849:                /* verify the inner packet is destined to a mcast group */
                   1850:                if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) {
                   1851:                        ++pim6stat.pim6s_rcv_badregisters;
                   1852: #ifdef MRT6DEBUG
                   1853:                        if (mrt6debug & DEBUG_PIM)
                   1854:                                log(LOG_DEBUG,
                   1855:                                    "pim6_input: inner packet of register "
                   1856:                                    "is not multicast %s\n",
                   1857:                                    ip6_sprintf(&eip6->ip6_dst));
                   1858: #endif
                   1859:                        m_freem(m);
                   1860:                        return (IPPROTO_DONE);
                   1861:                }
                   1862:
                   1863:                /*
                   1864:                 * make a copy of the whole header to pass to the daemon later.
                   1865:                 */
                   1866:                mcp = m_copy(m, 0, off + PIM6_REG_MINLEN);
                   1867:                if (mcp == NULL) {
                   1868: #ifdef MRT6DEBUG
                   1869:                        log(LOG_ERR,
                   1870:                            "pim6_input: pim register: "
                   1871:                            "could not copy register head\n");
                   1872: #endif
                   1873:                        m_freem(m);
                   1874:                        return (IPPROTO_DONE);
                   1875:                }
                   1876:
                   1877:                /*
                   1878:                 * forward the inner ip6 packet; point m_data at the inner ip6.
                   1879:                 */
                   1880:                m_adj(m, off + PIM_MINLEN);
                   1881: #ifdef MRT6DEBUG
                   1882:                if (mrt6debug & DEBUG_PIM) {
                   1883:                        log(LOG_DEBUG,
                   1884:                            "pim6_input: forwarding decapsulated register: "
                   1885:                            "src %s, dst %s, mif %d\n",
                   1886:                            ip6_sprintf(&eip6->ip6_src),
                   1887:                            ip6_sprintf(&eip6->ip6_dst),
                   1888:                            reg_mif_num);
                   1889:                }
                   1890: #endif
                   1891:
                   1892:                rc = looutput(mif6table[reg_mif_num].m6_ifp, m,
                   1893:                              (struct sockaddr *) &dst,
                   1894:                              (struct rtentry *) NULL);
                   1895:
                   1896:                /* prepare the register head to send to the mrouting daemon */
                   1897:                m = mcp;
                   1898:        }
                   1899:
                   1900:        /*
                   1901:         * Pass the PIM message up to the daemon; if it is a register message
                   1902:         * pass the 'head' only up to the daemon. This includes the
                   1903:         * encapsulator ip6 header, pim header, register header and the
                   1904:         * encapsulated ip6 header.
                   1905:         */
                   1906:   pim6_input_to_daemon:
                   1907:        rip6_input(&m, offp, proto);
                   1908:        return (IPPROTO_DONE);
                   1909: }

CVSweb