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

Cache object: 63ffb56b9426dcf0279a55d78a7b6ee0


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