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

Cache object: b05c19ae06b7faa981859861633803ee


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