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

Cache object: bb409c06ed0ded2531f6e0e1636bce6a


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