[BACK]Return to ip6_mroute.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet6

Annotation of src/sys/netinet6/ip6_mroute.c, Revision 1.2

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

CVSweb <webmaster@jp.NetBSD.org>