[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     ! 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