The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet6/ip6_mroute.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: d98d62c1727930cb0981928ee1609f17


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.