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

Cache object: 4d3ca03001af7d4a7d5b743cdc976f71


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