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/netinet/ip_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: ip_mroute.c,v 1.82 2003/11/19 18:39:34 jonathan Exp $  */
    2 
    3 /*
    4  * Copyright (c) 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Stephen Deering of Stanford University.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93
   35  */
   36 
   37 /*
   38  * Copyright (c) 1989 Stephen Deering
   39  *
   40  * This code is derived from software contributed to Berkeley by
   41  * Stephen Deering of Stanford University.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  * 3. All advertising materials mentioning features or use of this software
   52  *    must display the following acknowledgement:
   53  *      This product includes software developed by the University of
   54  *      California, Berkeley and its contributors.
   55  * 4. Neither the name of the University nor the names of its contributors
   56  *    may be used to endorse or promote products derived from this software
   57  *    without specific prior written permission.
   58  *
   59  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   60  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   61  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   62  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   63  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   64  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   65  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   66  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   67  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   68  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   69  * SUCH DAMAGE.
   70  *
   71  *      @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93
   72  */
   73 
   74 /*
   75  * IP multicast forwarding procedures
   76  *
   77  * Written by David Waitzman, BBN Labs, August 1988.
   78  * Modified by Steve Deering, Stanford, February 1989.
   79  * Modified by Mark J. Steiglitz, Stanford, May, 1991
   80  * Modified by Van Jacobson, LBL, January 1993
   81  * Modified by Ajit Thyagarajan, PARC, August 1993
   82  * Modified by Bill Fenner, PARC, April 1994
   83  * Modified by Charles M. Hannum, NetBSD, May 1995.
   84  *
   85  * MROUTING Revision: 1.2
   86  */
   87 
   88 #include <sys/cdefs.h>
   89 __KERNEL_RCSID(0, "$NetBSD: ip_mroute.c,v 1.82 2003/11/19 18:39:34 jonathan Exp $");
   90 
   91 #include "opt_inet.h"
   92 #include "opt_ipsec.h"
   93 
   94 #include <sys/param.h>
   95 #include <sys/systm.h>
   96 #include <sys/callout.h>
   97 #include <sys/mbuf.h>
   98 #include <sys/socket.h>
   99 #include <sys/socketvar.h>
  100 #include <sys/protosw.h>
  101 #include <sys/errno.h>
  102 #include <sys/time.h>
  103 #include <sys/kernel.h>
  104 #include <sys/ioctl.h>
  105 #include <sys/syslog.h>
  106 #include <net/if.h>
  107 #include <net/route.h>
  108 #include <net/raw_cb.h>
  109 #include <netinet/in.h>
  110 #include <netinet/in_var.h>
  111 #include <netinet/in_systm.h>
  112 #include <netinet/ip.h>
  113 #include <netinet/ip_var.h>
  114 #include <netinet/in_pcb.h>
  115 #include <netinet/udp.h>
  116 #include <netinet/igmp.h>
  117 #include <netinet/igmp_var.h>
  118 #include <netinet/ip_mroute.h>
  119 #include <netinet/ip_encap.h>
  120 
  121 #ifdef IPSEC
  122 #include <netinet6/ipsec.h>
  123 #include <netkey/key.h>
  124 #endif
  125 
  126 #ifdef FAST_IPSEC
  127 #include <netipsec/ipsec.h>
  128 #include <netipsec/key.h>
  129 #endif
  130 
  131 #include <machine/stdarg.h>
  132 
  133 #define IP_MULTICASTOPTS 0
  134 #define M_PULLUP(m, len) \
  135         do { \
  136                 if ((m) && ((m)->m_flags & M_EXT || (m)->m_len < (len))) \
  137                         (m) = m_pullup((m), (len)); \
  138         } while (/*CONSTCOND*/ 0)
  139 
  140 /*
  141  * Globals.  All but ip_mrouter and ip_mrtproto could be static,
  142  * except for netstat or debugging purposes.
  143  */
  144 struct socket  *ip_mrouter  = 0;
  145 int             ip_mrtproto = IGMP_DVMRP;    /* for netstat only */
  146 
  147 #define NO_RTE_FOUND    0x1
  148 #define RTE_FOUND       0x2
  149 
  150 #define MFCHASH(a, g) \
  151         ((((a).s_addr >> 20) ^ ((a).s_addr >> 10) ^ (a).s_addr ^ \
  152           ((g).s_addr >> 20) ^ ((g).s_addr >> 10) ^ (g).s_addr) & mfchash)
  153 LIST_HEAD(mfchashhdr, mfc) *mfchashtbl;
  154 u_long  mfchash;
  155 
  156 u_char          nexpire[MFCTBLSIZ];
  157 struct vif      viftable[MAXVIFS];
  158 struct mrtstat  mrtstat;
  159 u_int           mrtdebug = 0;     /* debug level        */
  160 #define         DEBUG_MFC       0x02
  161 #define         DEBUG_FORWARD   0x04
  162 #define         DEBUG_EXPIRE    0x08
  163 #define         DEBUG_XMIT      0x10
  164 u_int           tbfdebug = 0;     /* tbf debug level    */
  165 #ifdef RSVP_ISI
  166 u_int           rsvpdebug = 0;    /* rsvp debug level   */
  167 extern struct socket *ip_rsvpd;
  168 extern int rsvp_on;
  169 #endif /* RSVP_ISI */
  170 
  171 /* vif attachment using sys/netinet/ip_encap.c */
  172 extern struct domain inetdomain;
  173 static void vif_input __P((struct mbuf *, ...));
  174 static int vif_encapcheck __P((const struct mbuf *, int, int, void *));
  175 static struct protosw vif_protosw =
  176 { SOCK_RAW,     &inetdomain,    IPPROTO_IPV4,   PR_ATOMIC|PR_ADDR,
  177   vif_input,    rip_output,     0,              rip_ctloutput,
  178   rip_usrreq,
  179   0,            0,              0,              0,
  180 };
  181 
  182 #define         EXPIRE_TIMEOUT  (hz / 4)        /* 4x / second */
  183 #define         UPCALL_EXPIRE   6               /* number of timeouts */
  184 
  185 /*
  186  * Define the token bucket filter structures
  187  */
  188 
  189 #define         TBF_REPROCESS   (hz / 100)      /* 100x / second */
  190 
  191 static int get_sg_cnt __P((struct sioc_sg_req *));
  192 static int get_vif_cnt __P((struct sioc_vif_req *));
  193 static int ip_mrouter_init __P((struct socket *, struct mbuf *));
  194 static int get_version __P((struct mbuf *));
  195 static int set_assert __P((struct mbuf *));
  196 static int get_assert __P((struct mbuf *));
  197 static int add_vif __P((struct mbuf *));
  198 static int del_vif __P((struct mbuf *));
  199 static void update_mfc __P((struct mfcctl *, struct mfc *));
  200 static void expire_mfc __P((struct mfc *));
  201 static int add_mfc __P((struct mbuf *));
  202 #ifdef UPCALL_TIMING
  203 static void collate __P((struct timeval *));
  204 #endif
  205 static int del_mfc __P((struct mbuf *));
  206 static int socket_send __P((struct socket *, struct mbuf *,
  207                             struct sockaddr_in *));
  208 static void expire_upcalls __P((void *));
  209 #ifdef RSVP_ISI
  210 static int ip_mdq __P((struct mbuf *, struct ifnet *, struct mfc *, vifi_t));
  211 #else
  212 static int ip_mdq __P((struct mbuf *, struct ifnet *, struct mfc *));
  213 #endif
  214 static void phyint_send __P((struct ip *, struct vif *, struct mbuf *));
  215 static void encap_send __P((struct ip *, struct vif *, struct mbuf *));
  216 static void tbf_control __P((struct vif *, struct mbuf *, struct ip *,
  217                              u_int32_t));
  218 static void tbf_queue __P((struct vif *, struct mbuf *));
  219 static void tbf_process_q __P((struct vif *));
  220 static void tbf_reprocess_q __P((void *));
  221 static int tbf_dq_sel __P((struct vif *, struct ip *));
  222 static void tbf_send_packet __P((struct vif *, struct mbuf *));
  223 static void tbf_update_tokens __P((struct vif *));
  224 static int priority __P((struct vif *, struct ip *));
  225 
  226 /*
  227  * 'Interfaces' associated with decapsulator (so we can tell
  228  * packets that went through it from ones that get reflected
  229  * by a broken gateway).  These interfaces are never linked into
  230  * the system ifnet list & no routes point to them.  I.e., packets
  231  * can't be sent this way.  They only exist as a placeholder for
  232  * multicast source verification.
  233  */
  234 #if 0
  235 struct ifnet multicast_decap_if[MAXVIFS];
  236 #endif
  237 
  238 #define ENCAP_TTL       64
  239 #define ENCAP_PROTO     IPPROTO_IPIP    /* 4 */
  240 
  241 /* prototype IP hdr for encapsulated packets */
  242 struct ip multicast_encap_iphdr = {
  243 #if BYTE_ORDER == LITTLE_ENDIAN
  244         sizeof(struct ip) >> 2, IPVERSION,
  245 #else
  246         IPVERSION, sizeof(struct ip) >> 2,
  247 #endif
  248         0,                              /* tos */
  249         sizeof(struct ip),              /* total length */
  250         0,                              /* id */
  251         0,                              /* frag offset */
  252         ENCAP_TTL, ENCAP_PROTO,
  253         0,                              /* checksum */
  254 };
  255 
  256 /*
  257  * Private variables.
  258  */
  259 static vifi_t      numvifs = 0;
  260 
  261 static struct callout expire_upcalls_ch;
  262 
  263 /*
  264  * one-back cache used by vif_encapcheck to locate a tunnel's vif
  265  * given a datagram's src ip address.
  266  */
  267 static struct in_addr last_encap_src;
  268 static struct vif *last_encap_vif;
  269 
  270 /*
  271  * whether or not special PIM assert processing is enabled.
  272  */
  273 static int pim_assert;
  274 /*
  275  * Rate limit for assert notification messages, in usec
  276  */
  277 #define ASSERT_MSG_TIME         3000000
  278 
  279 /*
  280  * Find a route for a given origin IP address and Multicast group address
  281  * Type of service parameter to be added in the future!!!
  282  */
  283 
  284 #define MFCFIND(o, g, rt) do { \
  285         struct mfc *_rt; \
  286         (rt) = 0; \
  287         ++mrtstat.mrts_mfc_lookups; \
  288         LIST_FOREACH(_rt, &mfchashtbl[MFCHASH(o, g)], mfc_hash) { \
  289                 if (in_hosteq(_rt->mfc_origin, (o)) && \
  290                     in_hosteq(_rt->mfc_mcastgrp, (g)) && \
  291                     _rt->mfc_stall == 0) { \
  292                         (rt) = _rt; \
  293                         break; \
  294                 } \
  295         } \
  296         if ((rt) == 0) \
  297                 ++mrtstat.mrts_mfc_misses; \
  298 } while (/*CONSTCOND*/ 0)
  299 
  300 /*
  301  * Macros to compute elapsed time efficiently
  302  * Borrowed from Van Jacobson's scheduling code
  303  */
  304 #define TV_DELTA(a, b, delta) do { \
  305         int xxs; \
  306         delta = (a).tv_usec - (b).tv_usec; \
  307         xxs = (a).tv_sec - (b).tv_sec; \
  308         switch (xxs) { \
  309         case 2: \
  310                 delta += 1000000; \
  311                 /* fall through */ \
  312         case 1: \
  313                 delta += 1000000; \
  314                 /* fall through */ \
  315         case 0: \
  316                 break; \
  317         default: \
  318                 delta += (1000000 * xxs); \
  319                 break; \
  320         } \
  321 } while (/*CONSTCOND*/ 0)
  322 
  323 #ifdef UPCALL_TIMING
  324 u_int32_t upcall_data[51];
  325 #endif /* UPCALL_TIMING */
  326 
  327 /*
  328  * Handle MRT setsockopt commands to modify the multicast routing tables.
  329  */
  330 int
  331 ip_mrouter_set(so, optname, m)
  332         struct socket *so;
  333         int optname;
  334         struct mbuf **m;
  335 {
  336         int error;
  337 
  338         if (optname != MRT_INIT && so != ip_mrouter)
  339                 error = ENOPROTOOPT;
  340         else
  341                 switch (optname) {
  342                 case MRT_INIT:
  343                         error = ip_mrouter_init(so, *m);
  344                         break;
  345                 case MRT_DONE:
  346                         error = ip_mrouter_done();
  347                         break;
  348                 case MRT_ADD_VIF:
  349                         error = add_vif(*m);
  350                         break;
  351                 case MRT_DEL_VIF:
  352                         error = del_vif(*m);
  353                         break;
  354                 case MRT_ADD_MFC:
  355                         error = add_mfc(*m);
  356                         break;
  357                 case MRT_DEL_MFC:
  358                         error = del_mfc(*m);
  359                         break;
  360                 case MRT_ASSERT:
  361                         error = set_assert(*m);
  362                         break;
  363                 default:
  364                         error = ENOPROTOOPT;
  365                         break;
  366                 }
  367 
  368         if (*m)
  369                 m_free(*m);
  370         return (error);
  371 }
  372 
  373 /*
  374  * Handle MRT getsockopt commands
  375  */
  376 int
  377 ip_mrouter_get(so, optname, m)
  378         struct socket *so;
  379         int optname;
  380         struct mbuf **m;
  381 {
  382         int error;
  383 
  384         if (so != ip_mrouter)
  385                 error = ENOPROTOOPT;
  386         else {
  387                 *m = m_get(M_WAIT, MT_SOOPTS);
  388                 MCLAIM(*m, so->so_mowner);
  389 
  390                 switch (optname) {
  391                 case MRT_VERSION:
  392                         error = get_version(*m);
  393                         break;
  394                 case MRT_ASSERT:
  395                         error = get_assert(*m);
  396                         break;
  397                 default:
  398                         error = ENOPROTOOPT;
  399                         break;
  400                 }
  401 
  402                 if (error)
  403                         m_free(*m);
  404         }
  405 
  406         return (error);
  407 }
  408 
  409 /*
  410  * Handle ioctl commands to obtain information from the cache
  411  */
  412 int
  413 mrt_ioctl(so, cmd, data)
  414         struct socket *so;
  415         u_long cmd;
  416         caddr_t data;
  417 {
  418         int error;
  419 
  420         if (so != ip_mrouter)
  421                 error = EINVAL;
  422         else
  423                 switch (cmd) {
  424                 case SIOCGETVIFCNT:
  425                         error = get_vif_cnt((struct sioc_vif_req *)data);
  426                         break;
  427                 case SIOCGETSGCNT:
  428                         error = get_sg_cnt((struct sioc_sg_req *)data);
  429                         break;
  430                 default:
  431                         error = EINVAL;
  432                         break;
  433                 }
  434 
  435         return (error);
  436 }
  437 
  438 /*
  439  * returns the packet, byte, rpf-failure count for the source group provided
  440  */
  441 static int
  442 get_sg_cnt(req)
  443         struct sioc_sg_req *req;
  444 {
  445         struct mfc *rt;
  446         int s;
  447 
  448         s = splsoftnet();
  449         MFCFIND(req->src, req->grp, rt);
  450         splx(s);
  451         if (rt != 0) {
  452                 req->pktcnt = rt->mfc_pkt_cnt;
  453                 req->bytecnt = rt->mfc_byte_cnt;
  454                 req->wrong_if = rt->mfc_wrong_if;
  455         } else
  456                 req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
  457 
  458         return (0);
  459 }
  460 
  461 /*
  462  * returns the input and output packet and byte counts on the vif provided
  463  */
  464 static int
  465 get_vif_cnt(req)
  466         struct sioc_vif_req *req;
  467 {
  468         vifi_t vifi = req->vifi;
  469 
  470         if (vifi >= numvifs)
  471                 return (EINVAL);
  472 
  473         req->icount = viftable[vifi].v_pkt_in;
  474         req->ocount = viftable[vifi].v_pkt_out;
  475         req->ibytes = viftable[vifi].v_bytes_in;
  476         req->obytes = viftable[vifi].v_bytes_out;
  477 
  478         return (0);
  479 }
  480 
  481 /*
  482  * Enable multicast routing
  483  */
  484 static int
  485 ip_mrouter_init(so, m)
  486         struct socket *so;
  487         struct mbuf *m;
  488 {
  489         int *v;
  490 
  491         if (mrtdebug)
  492                 log(LOG_DEBUG,
  493                     "ip_mrouter_init: so_type = %d, pr_protocol = %d\n",
  494                     so->so_type, so->so_proto->pr_protocol);
  495 
  496         if (so->so_type != SOCK_RAW ||
  497             so->so_proto->pr_protocol != IPPROTO_IGMP)
  498                 return (EOPNOTSUPP);
  499 
  500         if (m == 0 || m->m_len < sizeof(int))
  501                 return (EINVAL);
  502 
  503         v = mtod(m, int *);
  504         if (*v != 1)
  505                 return (EINVAL);
  506 
  507         if (ip_mrouter != 0)
  508                 return (EADDRINUSE);
  509 
  510         ip_mrouter = so;
  511 
  512         mfchashtbl =
  513             hashinit(MFCTBLSIZ, HASH_LIST, M_MRTABLE, M_WAITOK, &mfchash);
  514         bzero((caddr_t)nexpire, sizeof(nexpire));
  515 
  516         pim_assert = 0;
  517 
  518         callout_init(&expire_upcalls_ch);
  519         callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
  520             expire_upcalls, NULL);
  521 
  522         if (mrtdebug)
  523                 log(LOG_DEBUG, "ip_mrouter_init\n");
  524 
  525         return (0);
  526 }
  527 
  528 /*
  529  * Disable multicast routing
  530  */
  531 int
  532 ip_mrouter_done()
  533 {
  534         vifi_t vifi;
  535         struct vif *vifp;
  536         int i;
  537         int s;
  538 
  539         s = splsoftnet();
  540 
  541         /* Clear out all the vifs currently in use. */
  542         for (vifi = 0; vifi < numvifs; vifi++) {
  543                 vifp = &viftable[vifi];
  544                 if (!in_nullhost(vifp->v_lcl_addr))
  545                         reset_vif(vifp);
  546         }
  547 
  548         numvifs = 0;
  549         pim_assert = 0;
  550 
  551         callout_stop(&expire_upcalls_ch);
  552 
  553         /*
  554          * Free all multicast forwarding cache entries.
  555          */
  556         for (i = 0; i < MFCTBLSIZ; i++) {
  557                 struct mfc *rt, *nrt;
  558 
  559                 for (rt = LIST_FIRST(&mfchashtbl[i]); rt; rt = nrt) {
  560                         nrt = LIST_NEXT(rt, mfc_hash);
  561 
  562                         expire_mfc(rt);
  563                 }
  564         }
  565 
  566         free(mfchashtbl, M_MRTABLE);
  567         mfchashtbl = 0;
  568 
  569         /* Reset de-encapsulation cache. */
  570 
  571         ip_mrouter = 0;
  572 
  573         splx(s);
  574 
  575         if (mrtdebug)
  576                 log(LOG_DEBUG, "ip_mrouter_done\n");
  577 
  578         return (0);
  579 }
  580 
  581 void
  582 ip_mrouter_detach(ifp)
  583         struct ifnet *ifp;
  584 {
  585         int vifi, i;
  586         struct vif *vifp;
  587         struct mfc *rt;
  588         struct rtdetq *rte;
  589 
  590         /* XXX not sure about sideeffect to userland routing daemon */
  591         for (vifi = 0; vifi < numvifs; vifi++) {
  592                 vifp = &viftable[vifi];
  593                 if (vifp->v_ifp == ifp)
  594                         reset_vif(vifp);
  595         }
  596         for (i = 0; i < MFCTBLSIZ; i++) {
  597                 if (nexpire[i] == 0)
  598                         continue;
  599                 LIST_FOREACH(rt, &mfchashtbl[i], mfc_hash) {
  600                         for (rte = rt->mfc_stall; rte; rte = rte->next) {
  601                                 if (rte->ifp == ifp)
  602                                         rte->ifp = NULL;
  603                         }
  604                 }
  605         }
  606 }
  607 
  608 static int
  609 get_version(m)
  610         struct mbuf *m;
  611 {
  612         int *v = mtod(m, int *);
  613 
  614         *v = 0x0305;    /* XXX !!!! */
  615         m->m_len = sizeof(int);
  616         return (0);
  617 }
  618 
  619 /*
  620  * Set PIM assert processing global
  621  */
  622 static int
  623 set_assert(m)
  624         struct mbuf *m;
  625 {
  626         int *i;
  627 
  628         if (m == 0 || m->m_len < sizeof(int))
  629                 return (EINVAL);
  630 
  631         i = mtod(m, int *);
  632         pim_assert = !!*i;
  633         return (0);
  634 }
  635 
  636 /*
  637  * Get PIM assert processing global
  638  */
  639 static int
  640 get_assert(m)
  641         struct mbuf *m;
  642 {
  643         int *i = mtod(m, int *);
  644 
  645         *i = pim_assert;
  646         m->m_len = sizeof(int);
  647         return (0);
  648 }
  649 
  650 static struct sockaddr_in sin = { sizeof(sin), AF_INET };
  651 
  652 /*
  653  * Add a vif to the vif table
  654  */
  655 static int
  656 add_vif(m)
  657         struct mbuf *m;
  658 {
  659         struct vifctl *vifcp;
  660         struct vif *vifp;
  661         struct ifaddr *ifa;
  662         struct ifnet *ifp;
  663         struct ifreq ifr;
  664         int error, s;
  665 
  666         if (m == 0 || m->m_len < sizeof(struct vifctl))
  667                 return (EINVAL);
  668 
  669         vifcp = mtod(m, struct vifctl *);
  670         if (vifcp->vifc_vifi >= MAXVIFS)
  671                 return (EINVAL);
  672 
  673         vifp = &viftable[vifcp->vifc_vifi];
  674         if (!in_nullhost(vifp->v_lcl_addr))
  675                 return (EADDRINUSE);
  676 
  677         /* Find the interface with an address in AF_INET family. */
  678         sin.sin_addr = vifcp->vifc_lcl_addr;
  679         ifa = ifa_ifwithaddr(sintosa(&sin));
  680         if (ifa == 0)
  681                 return (EADDRNOTAVAIL);
  682 
  683         if (vifcp->vifc_flags & VIFF_TUNNEL) {
  684                 if (vifcp->vifc_flags & VIFF_SRCRT) {
  685                         log(LOG_ERR, "Source routed tunnels not supported\n");
  686                         return (EOPNOTSUPP);
  687                 }
  688 
  689                 /* attach this vif to decapsulator dispatch table */
  690                 vifp->v_encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV4,
  691                     vif_encapcheck, &vif_protosw, vifp);
  692                 if (!vifp->v_encap_cookie)
  693                         return (EINVAL);
  694 
  695                 /* Create a fake encapsulation interface. */
  696                 ifp = (struct ifnet *)malloc(sizeof(*ifp), M_MRTABLE, M_WAITOK);
  697                 bzero(ifp, sizeof(*ifp));
  698                 sprintf(ifp->if_xname, "mdecap%d", vifcp->vifc_vifi);
  699 
  700                 /* Prepare cached route entry. */
  701                 bzero(&vifp->v_route, sizeof(vifp->v_route));
  702         } else {
  703                 /* Use the physical interface associated with the address. */
  704                 ifp = ifa->ifa_ifp;
  705 
  706                 /* Make sure the interface supports multicast. */
  707                 if ((ifp->if_flags & IFF_MULTICAST) == 0)
  708                         return (EOPNOTSUPP);
  709 
  710                 /* Enable promiscuous reception of all IP multicasts. */
  711                 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
  712                 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
  713                 satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
  714                 error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
  715                 if (error)
  716                         return (error);
  717         }
  718 
  719         s = splsoftnet();
  720 
  721         /* Define parameters for the tbf structure. */
  722         vifp->tbf_q = 0;
  723         vifp->tbf_t = &vifp->tbf_q;
  724         microtime(&vifp->tbf_last_pkt_t);
  725         vifp->tbf_n_tok = 0;
  726         vifp->tbf_q_len = 0;
  727         vifp->tbf_max_q_len = MAXQSIZE;
  728 
  729         vifp->v_flags = vifcp->vifc_flags;
  730         vifp->v_threshold = vifcp->vifc_threshold;
  731         /* scaling up here allows division by 1024 in critical code */
  732         vifp->v_rate_limit = vifcp->vifc_rate_limit * 1024 / 1000;
  733         vifp->v_lcl_addr = vifcp->vifc_lcl_addr;
  734         vifp->v_rmt_addr = vifcp->vifc_rmt_addr;
  735         vifp->v_ifp = ifp;
  736         /* Initialize per vif pkt counters. */
  737         vifp->v_pkt_in = 0;
  738         vifp->v_pkt_out = 0;
  739         vifp->v_bytes_in = 0;
  740         vifp->v_bytes_out = 0;
  741 
  742         callout_init(&vifp->v_repq_ch);
  743 
  744 #ifdef RSVP_ISI
  745         vifp->v_rsvp_on = 0;
  746         vifp->v_rsvpd = 0;
  747 #endif /* RSVP_ISI */
  748 
  749         splx(s);
  750 
  751         /* Adjust numvifs up if the vifi is higher than numvifs. */
  752         if (numvifs <= vifcp->vifc_vifi)
  753                 numvifs = vifcp->vifc_vifi + 1;
  754 
  755         if (mrtdebug)
  756                 log(LOG_DEBUG, "add_vif #%d, lcladdr %x, %s %x, thresh %x, rate %d\n",
  757                     vifcp->vifc_vifi,
  758                     ntohl(vifcp->vifc_lcl_addr.s_addr),
  759                     (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask",
  760                     ntohl(vifcp->vifc_rmt_addr.s_addr),
  761                     vifcp->vifc_threshold,
  762                     vifcp->vifc_rate_limit);
  763 
  764         return (0);
  765 }
  766 
  767 void
  768 reset_vif(vifp)
  769         struct vif *vifp;
  770 {
  771         struct mbuf *m, *n;
  772         struct ifnet *ifp;
  773         struct ifreq ifr;
  774 
  775         callout_stop(&vifp->v_repq_ch);
  776 
  777         /* detach this vif from decapsulator dispatch table */
  778         encap_detach(vifp->v_encap_cookie);
  779         vifp->v_encap_cookie = NULL;
  780 
  781         for (m = vifp->tbf_q; m != 0; m = n) {
  782                 n = m->m_nextpkt;
  783                 m_freem(m);
  784         }
  785 
  786         if (vifp->v_flags & VIFF_TUNNEL) {
  787                 free(vifp->v_ifp, M_MRTABLE);
  788                 if (vifp == last_encap_vif) {
  789                         last_encap_vif = 0;
  790                         last_encap_src = zeroin_addr;
  791                 }
  792         } else {
  793                 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
  794                 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
  795                 satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
  796                 ifp = vifp->v_ifp;
  797                 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
  798         }
  799         bzero((caddr_t)vifp, sizeof(*vifp));
  800 }
  801 
  802 /*
  803  * Delete a vif from the vif table
  804  */
  805 static int
  806 del_vif(m)
  807         struct mbuf *m;
  808 {
  809         vifi_t *vifip;
  810         struct vif *vifp;
  811         vifi_t vifi;
  812         int s;
  813 
  814         if (m == 0 || m->m_len < sizeof(vifi_t))
  815                 return (EINVAL);
  816 
  817         vifip = mtod(m, vifi_t *);
  818         if (*vifip >= numvifs)
  819                 return (EINVAL);
  820 
  821         vifp = &viftable[*vifip];
  822         if (in_nullhost(vifp->v_lcl_addr))
  823                 return (EADDRNOTAVAIL);
  824 
  825         s = splsoftnet();
  826 
  827         reset_vif(vifp);
  828 
  829         /* Adjust numvifs down */
  830         for (vifi = numvifs; vifi > 0; vifi--)
  831                 if (!in_nullhost(viftable[vifi-1].v_lcl_addr))
  832                         break;
  833         numvifs = vifi;
  834 
  835         splx(s);
  836 
  837         if (mrtdebug)
  838                 log(LOG_DEBUG, "del_vif %d, numvifs %d\n", *vifip, numvifs);
  839 
  840         return (0);
  841 }
  842 
  843 static void
  844 update_mfc(mfccp, rt)
  845         struct mfcctl *mfccp;
  846         struct mfc *rt;
  847 {
  848         vifi_t vifi;
  849 
  850         rt->mfc_parent = mfccp->mfcc_parent;
  851         for (vifi = 0; vifi < numvifs; vifi++)
  852                 rt->mfc_ttls[vifi] = mfccp->mfcc_ttls[vifi];
  853         rt->mfc_expire = 0;
  854         rt->mfc_stall = 0;
  855 }
  856 
  857 static void
  858 expire_mfc(rt)
  859         struct mfc *rt;
  860 {
  861         struct rtdetq *rte, *nrte;
  862 
  863         for (rte = rt->mfc_stall; rte != 0; rte = nrte) {
  864                 nrte = rte->next;
  865                 m_freem(rte->m);
  866                 free(rte, M_MRTABLE);
  867         }
  868 
  869         LIST_REMOVE(rt, mfc_hash);
  870         free(rt, M_MRTABLE);
  871 }
  872 
  873 /*
  874  * Add an mfc entry
  875  */
  876 static int
  877 add_mfc(m)
  878         struct mbuf *m;
  879 {
  880         struct mfcctl *mfccp;
  881         struct mfc *rt;
  882         u_int32_t hash = 0;
  883         struct rtdetq *rte, *nrte;
  884         u_short nstl;
  885         int s;
  886 
  887         if (m == 0 || m->m_len < sizeof(struct mfcctl))
  888                 return (EINVAL);
  889 
  890         mfccp = mtod(m, struct mfcctl *);
  891 
  892         s = splsoftnet();
  893         MFCFIND(mfccp->mfcc_origin, mfccp->mfcc_mcastgrp, rt);
  894 
  895         /* If an entry already exists, just update the fields */
  896         if (rt) {
  897                 if (mrtdebug & DEBUG_MFC)
  898                         log(LOG_DEBUG, "add_mfc update o %x g %x p %x\n",
  899                             ntohl(mfccp->mfcc_origin.s_addr),
  900                             ntohl(mfccp->mfcc_mcastgrp.s_addr),
  901                             mfccp->mfcc_parent);
  902 
  903                 if (rt->mfc_expire)
  904                         nexpire[hash]--;
  905 
  906                 update_mfc(mfccp, rt);
  907 
  908                 splx(s);
  909                 return (0);
  910         }
  911 
  912         /*
  913          * Find the entry for which the upcall was made and update
  914          */
  915         nstl = 0;
  916         hash = MFCHASH(mfccp->mfcc_origin, mfccp->mfcc_mcastgrp);
  917         LIST_FOREACH(rt, &mfchashtbl[hash], mfc_hash) {
  918                 if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) &&
  919                     in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp) &&
  920                     rt->mfc_stall != 0) {
  921                         if (nstl++)
  922                                 log(LOG_ERR, "add_mfc %s o %x g %x p %x dbx %p\n",
  923                                     "multiple kernel entries",
  924                                     ntohl(mfccp->mfcc_origin.s_addr),
  925                                     ntohl(mfccp->mfcc_mcastgrp.s_addr),
  926                                     mfccp->mfcc_parent, rt->mfc_stall);
  927 
  928                         if (mrtdebug & DEBUG_MFC)
  929                                 log(LOG_DEBUG, "add_mfc o %x g %x p %x dbg %p\n",
  930                                     ntohl(mfccp->mfcc_origin.s_addr),
  931                                     ntohl(mfccp->mfcc_mcastgrp.s_addr),
  932                                     mfccp->mfcc_parent, rt->mfc_stall);
  933 
  934                         if (rt->mfc_expire)
  935                                 nexpire[hash]--;
  936 
  937                         rte = rt->mfc_stall;
  938                         update_mfc(mfccp, rt);
  939 
  940                         /* free packets Qed at the end of this entry */
  941                         for (; rte != 0; rte = nrte) {
  942                                 nrte = rte->next;
  943                                 if (rte->ifp) {
  944 #ifdef RSVP_ISI
  945                                         ip_mdq(rte->m, rte->ifp, rt, -1);
  946 #else
  947                                         ip_mdq(rte->m, rte->ifp, rt);
  948 #endif /* RSVP_ISI */
  949                                 }
  950                                 m_freem(rte->m);
  951 #ifdef UPCALL_TIMING
  952                                 collate(&rte->t);
  953 #endif /* UPCALL_TIMING */
  954                                 free(rte, M_MRTABLE);
  955                         }
  956                 }
  957         }
  958 
  959         if (nstl == 0) {
  960                 /*
  961                  * No mfc; make a new one
  962                  */
  963                 if (mrtdebug & DEBUG_MFC)
  964                         log(LOG_DEBUG, "add_mfc no upcall o %x g %x p %x\n",
  965                             ntohl(mfccp->mfcc_origin.s_addr),
  966                             ntohl(mfccp->mfcc_mcastgrp.s_addr),
  967                             mfccp->mfcc_parent);
  968 
  969                 rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
  970                 if (rt == 0) {
  971                         splx(s);
  972                         return (ENOBUFS);
  973                 }
  974 
  975                 rt->mfc_origin = mfccp->mfcc_origin;
  976                 rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp;
  977                 /* initialize pkt counters per src-grp */
  978                 rt->mfc_pkt_cnt = 0;
  979                 rt->mfc_byte_cnt = 0;
  980                 rt->mfc_wrong_if = 0;
  981                 timerclear(&rt->mfc_last_assert);
  982                 update_mfc(mfccp, rt);
  983 
  984                 /* insert new entry at head of hash chain */
  985                 LIST_INSERT_HEAD(&mfchashtbl[hash], rt, mfc_hash);
  986         }
  987 
  988         splx(s);
  989         return (0);
  990 }
  991 
  992 #ifdef UPCALL_TIMING
  993 /*
  994  * collect delay statistics on the upcalls
  995  */
  996 static void collate(t)
  997         struct timeval *t;
  998 {
  999         u_int32_t d;
 1000         struct timeval tp;
 1001         u_int32_t delta;
 1002 
 1003         microtime(&tp);
 1004 
 1005         if (timercmp(t, &tp, <)) {
 1006                 TV_DELTA(tp, *t, delta);
 1007 
 1008                 d = delta >> 10;
 1009                 if (d > 50)
 1010                         d = 50;
 1011 
 1012                 ++upcall_data[d];
 1013         }
 1014 }
 1015 #endif /* UPCALL_TIMING */
 1016 
 1017 /*
 1018  * Delete an mfc entry
 1019  */
 1020 static int
 1021 del_mfc(m)
 1022         struct mbuf *m;
 1023 {
 1024         struct mfcctl *mfccp;
 1025         struct mfc *rt;
 1026         int s;
 1027 
 1028         if (m == 0 || m->m_len < sizeof(struct mfcctl))
 1029                 return (EINVAL);
 1030 
 1031         mfccp = mtod(m, struct mfcctl *);
 1032 
 1033         if (mrtdebug & DEBUG_MFC)
 1034                 log(LOG_DEBUG, "del_mfc origin %x mcastgrp %x\n",
 1035                     ntohl(mfccp->mfcc_origin.s_addr),
 1036                     ntohl(mfccp->mfcc_mcastgrp.s_addr));
 1037 
 1038         s = splsoftnet();
 1039 
 1040         MFCFIND(mfccp->mfcc_origin, mfccp->mfcc_mcastgrp, rt);
 1041         if (rt == 0) {
 1042                 splx(s);
 1043                 return (EADDRNOTAVAIL);
 1044         }
 1045 
 1046         LIST_REMOVE(rt, mfc_hash);
 1047         free(rt, M_MRTABLE);
 1048 
 1049         splx(s);
 1050         return (0);
 1051 }
 1052 
 1053 static int
 1054 socket_send(s, mm, src)
 1055         struct socket *s;
 1056         struct mbuf *mm;
 1057         struct sockaddr_in *src;
 1058 {
 1059         if (s) {
 1060                 if (sbappendaddr(&s->so_rcv, sintosa(src), mm,
 1061                     (struct mbuf *)0) != 0) {
 1062                         sorwakeup(s);
 1063                         return (0);
 1064                 }
 1065         }
 1066         m_freem(mm);
 1067         return (-1);
 1068 }
 1069 
 1070 /*
 1071  * IP multicast forwarding function. This function assumes that the packet
 1072  * pointed to by "ip" has arrived on (or is about to be sent to) the interface
 1073  * pointed to by "ifp", and the packet is to be relayed to other networks
 1074  * that have members of the packet's destination IP multicast group.
 1075  *
 1076  * The packet is returned unscathed to the caller, unless it is
 1077  * erroneous, in which case a non-zero return value tells the caller to
 1078  * discard it.
 1079  */
 1080 
 1081 #define IP_HDR_LEN  20  /* # bytes of fixed IP header (excluding options) */
 1082 #define TUNNEL_LEN  12  /* # bytes of IP option for tunnel encapsulation  */
 1083 
 1084 int
 1085 #ifdef RSVP_ISI
 1086 ip_mforward(m, ifp, imo)
 1087 #else
 1088 ip_mforward(m, ifp)
 1089 #endif /* RSVP_ISI */
 1090         struct mbuf *m;
 1091         struct ifnet *ifp;
 1092 #ifdef RSVP_ISI
 1093         struct ip_moptions *imo;
 1094 #endif /* RSVP_ISI */
 1095 {
 1096         struct ip *ip = mtod(m, struct ip *);
 1097         struct mfc *rt;
 1098         static int srctun = 0;
 1099         struct mbuf *mm;
 1100         int s;
 1101 #ifdef RSVP_ISI
 1102         struct vif *vifp;
 1103         vifi_t vifi;
 1104 #endif /* RSVP_ISI */
 1105 
 1106         /*
 1107          * Clear any in-bound checksum flags for this packet.
 1108          */
 1109         m->m_pkthdr.csum_flags = 0;
 1110 
 1111         if (mrtdebug & DEBUG_FORWARD)
 1112                 log(LOG_DEBUG, "ip_mforward: src %x, dst %x, ifp %p\n",
 1113                     ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), ifp);
 1114 
 1115         if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 ||
 1116             ((u_char *)(ip + 1))[1] != IPOPT_LSRR) {
 1117                 /*
 1118                  * Packet arrived via a physical interface or
 1119                  * an encapuslated tunnel.
 1120                  */
 1121         } else {
 1122                 /*
 1123                  * Packet arrived through a source-route tunnel.
 1124                  * Source-route tunnels are no longer supported.
 1125                  */
 1126                 if ((srctun++ % 1000) == 0)
 1127                         log(LOG_ERR,
 1128                             "ip_mforward: received source-routed packet from %x\n",
 1129                             ntohl(ip->ip_src.s_addr));
 1130 
 1131                 return (1);
 1132         }
 1133 
 1134 #ifdef RSVP_ISI
 1135         if (imo && ((vifi = imo->imo_multicast_vif) < numvifs)) {
 1136                 if (ip->ip_ttl < 255)
 1137                         ip->ip_ttl++; /* compensate for -1 in *_send routines */
 1138                 if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
 1139                         vifp = viftable + vifi;
 1140                         printf("Sending IPPROTO_RSVP from %x to %x on vif %d (%s%s)\n",
 1141                             ntohl(ip->ip_src), ntohl(ip->ip_dst), vifi,
 1142                             (vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "",
 1143                             vifp->v_ifp->if_xname);
 1144                 }
 1145                 return (ip_mdq(m, ifp, (struct mfc *)0, vifi));
 1146         }
 1147         if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
 1148                 printf("Warning: IPPROTO_RSVP from %x to %x without vif option\n",
 1149                     ntohl(ip->ip_src), ntohl(ip->ip_dst));
 1150         }
 1151 #endif /* RSVP_ISI */
 1152 
 1153         /*
 1154          * Don't forward a packet with time-to-live of zero or one,
 1155          * or a packet destined to a local-only group.
 1156          */
 1157         if (ip->ip_ttl <= 1 || IN_LOCAL_GROUP(ip->ip_dst.s_addr))
 1158                 return (0);
 1159 
 1160         /*
 1161          * Determine forwarding vifs from the forwarding cache table
 1162          */
 1163         s = splsoftnet();
 1164         MFCFIND(ip->ip_src, ip->ip_dst, rt);
 1165 
 1166         /* Entry exists, so forward if necessary */
 1167         if (rt != 0) {
 1168                 splx(s);
 1169 #ifdef RSVP_ISI
 1170                 return (ip_mdq(m, ifp, rt, -1));
 1171 #else
 1172                 return (ip_mdq(m, ifp, rt));
 1173 #endif /* RSVP_ISI */
 1174         } else {
 1175                 /*
 1176                  * If we don't have a route for packet's origin,
 1177                  * Make a copy of the packet &
 1178                  * send message to routing daemon
 1179                  */
 1180 
 1181                 struct mbuf *mb0;
 1182                 struct rtdetq *rte;
 1183                 u_int32_t hash;
 1184                 int hlen = ip->ip_hl << 2;
 1185 #ifdef UPCALL_TIMING
 1186                 struct timeval tp;
 1187 
 1188                 microtime(&tp);
 1189 #endif /* UPCALL_TIMING */
 1190 
 1191                 mrtstat.mrts_no_route++;
 1192                 if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC))
 1193                         log(LOG_DEBUG, "ip_mforward: no rte s %x g %x\n",
 1194                             ntohl(ip->ip_src.s_addr),
 1195                             ntohl(ip->ip_dst.s_addr));
 1196 
 1197                 /*
 1198                  * Allocate mbufs early so that we don't do extra work if we are
 1199                  * just going to fail anyway.  Make sure to pullup the header so
 1200                  * that other people can't step on it.
 1201                  */
 1202                 rte = (struct rtdetq *)malloc(sizeof(*rte), M_MRTABLE,
 1203                     M_NOWAIT);
 1204                 if (rte == 0) {
 1205                         splx(s);
 1206                         return (ENOBUFS);
 1207                 }
 1208                 mb0 = m_copy(m, 0, M_COPYALL);
 1209                 M_PULLUP(mb0, hlen);
 1210                 if (mb0 == 0) {
 1211                         free(rte, M_MRTABLE);
 1212                         splx(s);
 1213                         return (ENOBUFS);
 1214                 }
 1215 
 1216                 /* is there an upcall waiting for this packet? */
 1217                 hash = MFCHASH(ip->ip_src, ip->ip_dst);
 1218                 LIST_FOREACH(rt, &mfchashtbl[hash], mfc_hash) {
 1219                         if (in_hosteq(ip->ip_src, rt->mfc_origin) &&
 1220                             in_hosteq(ip->ip_dst, rt->mfc_mcastgrp) &&
 1221                             rt->mfc_stall != 0)
 1222                                 break;
 1223                 }
 1224 
 1225                 if (rt == 0) {
 1226                         int i;
 1227                         struct igmpmsg *im;
 1228 
 1229                         /* no upcall, so make a new entry */
 1230                         rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE,
 1231                             M_NOWAIT);
 1232                         if (rt == 0) {
 1233                                 free(rte, M_MRTABLE);
 1234                                 m_freem(mb0);
 1235                                 splx(s);
 1236                                 return (ENOBUFS);
 1237                         }
 1238                         /*
 1239                          * Make a copy of the header to send to the user level
 1240                          * process
 1241                          */
 1242                         mm = m_copy(m, 0, hlen);
 1243                         M_PULLUP(mm, hlen);
 1244                         if (mm == 0) {
 1245                                 free(rte, M_MRTABLE);
 1246                                 m_freem(mb0);
 1247                                 free(rt, M_MRTABLE);
 1248                                 splx(s);
 1249                                 return (ENOBUFS);
 1250                         }
 1251 
 1252                         /*
 1253                          * Send message to routing daemon to install
 1254                          * a route into the kernel table
 1255                          */
 1256                         sin.sin_addr = ip->ip_src;
 1257 
 1258                         im = mtod(mm, struct igmpmsg *);
 1259                         im->im_msgtype = IGMPMSG_NOCACHE;
 1260                         im->im_mbz = 0;
 1261 
 1262                         mrtstat.mrts_upcalls++;
 1263 
 1264                         if (socket_send(ip_mrouter, mm, &sin) < 0) {
 1265                                 log(LOG_WARNING,
 1266                                     "ip_mforward: ip_mrouter socket queue full\n");
 1267                                 ++mrtstat.mrts_upq_sockfull;
 1268                                 free(rte, M_MRTABLE);
 1269                                 m_freem(mb0);
 1270                                 free(rt, M_MRTABLE);
 1271                                 splx(s);
 1272                                 return (ENOBUFS);
 1273                         }
 1274 
 1275                         /* insert new entry at head of hash chain */
 1276                         rt->mfc_origin = ip->ip_src;
 1277                         rt->mfc_mcastgrp = ip->ip_dst;
 1278                         rt->mfc_pkt_cnt = 0;
 1279                         rt->mfc_byte_cnt = 0;
 1280                         rt->mfc_wrong_if = 0;
 1281                         rt->mfc_expire = UPCALL_EXPIRE;
 1282                         nexpire[hash]++;
 1283                         for (i = 0; i < numvifs; i++)
 1284                                 rt->mfc_ttls[i] = 0;
 1285                         rt->mfc_parent = -1;
 1286 
 1287                         /* link into table */
 1288                         LIST_INSERT_HEAD(&mfchashtbl[hash], rt, mfc_hash);
 1289                         /* Add this entry to the end of the queue */
 1290                         rt->mfc_stall = rte;
 1291                 } else {
 1292                         /* determine if q has overflowed */
 1293                         struct rtdetq **p;
 1294                         int npkts = 0;
 1295 
 1296                         for (p = &rt->mfc_stall; *p != 0; p = &(*p)->next)
 1297                                 if (++npkts > MAX_UPQ) {
 1298                                         mrtstat.mrts_upq_ovflw++;
 1299                                         free(rte, M_MRTABLE);
 1300                                         m_freem(mb0);
 1301                                         splx(s);
 1302                                         return (0);
 1303                                 }
 1304 
 1305                         /* Add this entry to the end of the queue */
 1306                         *p = rte;
 1307                 }
 1308 
 1309                 rte->next = 0;
 1310                 rte->m = mb0;
 1311                 rte->ifp = ifp;
 1312 #ifdef UPCALL_TIMING
 1313                 rte->t = tp;
 1314 #endif /* UPCALL_TIMING */
 1315 
 1316                 splx(s);
 1317 
 1318                 return (0);
 1319         }
 1320 }
 1321 
 1322 
 1323 /*ARGSUSED*/
 1324 static void
 1325 expire_upcalls(v)
 1326         void *v;
 1327 {
 1328         int i;
 1329         int s;
 1330 
 1331         s = splsoftnet();
 1332 
 1333         for (i = 0; i < MFCTBLSIZ; i++) {
 1334                 struct mfc *rt, *nrt;
 1335 
 1336                 if (nexpire[i] == 0)
 1337                         continue;
 1338 
 1339                 for (rt = LIST_FIRST(&mfchashtbl[i]); rt; rt = nrt) {
 1340                         nrt = LIST_NEXT(rt, mfc_hash);
 1341 
 1342                         if (rt->mfc_expire == 0 || --rt->mfc_expire > 0)
 1343                                 continue;
 1344                         nexpire[i]--;
 1345 
 1346                         ++mrtstat.mrts_cache_cleanups;
 1347                         if (mrtdebug & DEBUG_EXPIRE)
 1348                                 log(LOG_DEBUG,
 1349                                     "expire_upcalls: expiring (%x %x)\n",
 1350                                     ntohl(rt->mfc_origin.s_addr),
 1351                                     ntohl(rt->mfc_mcastgrp.s_addr));
 1352 
 1353                         expire_mfc(rt);
 1354                 }
 1355         }
 1356 
 1357         splx(s);
 1358         callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
 1359             expire_upcalls, NULL);
 1360 }
 1361 
 1362 /*
 1363  * Packet forwarding routine once entry in the cache is made
 1364  */
 1365 static int
 1366 #ifdef RSVP_ISI
 1367 ip_mdq(m, ifp, rt, xmt_vif)
 1368 #else
 1369 ip_mdq(m, ifp, rt)
 1370 #endif /* RSVP_ISI */
 1371         struct mbuf *m;
 1372         struct ifnet *ifp;
 1373         struct mfc *rt;
 1374 #ifdef RSVP_ISI
 1375         vifi_t xmt_vif;
 1376 #endif /* RSVP_ISI */
 1377 {
 1378         struct ip  *ip = mtod(m, struct ip *);
 1379         vifi_t vifi;
 1380         struct vif *vifp;
 1381         int plen = ntohs(ip->ip_len) - (ip->ip_hl << 2);
 1382 
 1383 /*
 1384  * Macro to send packet on vif.  Since RSVP packets don't get counted on
 1385  * input, they shouldn't get counted on output, so statistics keeping is
 1386  * separate.
 1387  */
 1388 #define MC_SEND(ip, vifp, m) do {                       \
 1389         if ((vifp)->v_flags & VIFF_TUNNEL)              \
 1390                 encap_send((ip), (vifp), (m));          \
 1391         else                                            \
 1392                 phyint_send((ip), (vifp), (m));         \
 1393 } while (/*CONSTCOND*/ 0)
 1394 
 1395 #ifdef RSVP_ISI
 1396         /*
 1397          * If xmt_vif is not -1, send on only the requested vif.
 1398          *
 1399          * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.
 1400          */
 1401         if (xmt_vif < numvifs) {
 1402                 MC_SEND(ip, viftable + xmt_vif, m);
 1403                 return (1);
 1404         }
 1405 #endif /* RSVP_ISI */
 1406 
 1407         /*
 1408          * Don't forward if it didn't arrive from the parent vif for its origin.
 1409          */
 1410         vifi = rt->mfc_parent;
 1411         if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) {
 1412                 /* came in the wrong interface */
 1413                 if (mrtdebug & DEBUG_FORWARD)
 1414                         log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n",
 1415                             ifp, vifi,
 1416                             vifi >= numvifs ? 0 : viftable[vifi].v_ifp);
 1417                 ++mrtstat.mrts_wrong_if;
 1418                 ++rt->mfc_wrong_if;
 1419                 /*
 1420                  * If we are doing PIM assert processing, and we are forwarding
 1421                  * packets on this interface, and it is a broadcast medium
 1422                  * interface (and not a tunnel), send a message to the routing
 1423                  * daemon.
 1424                  */
 1425                 if (pim_assert && rt->mfc_ttls[vifi] &&
 1426                     (ifp->if_flags & IFF_BROADCAST) &&
 1427                     !(viftable[vifi].v_flags & VIFF_TUNNEL)) {
 1428                         struct mbuf *mm;
 1429                         struct igmpmsg *im;
 1430                         int hlen = ip->ip_hl << 2;
 1431                         struct timeval now;
 1432                         u_int32_t delta;
 1433 
 1434                         microtime(&now);
 1435 
 1436                         TV_DELTA(rt->mfc_last_assert, now, delta);
 1437 
 1438                         if (delta > ASSERT_MSG_TIME) {
 1439                                 mm = m_copy(m, 0, hlen);
 1440                                 M_PULLUP(mm, hlen);
 1441                                 if (mm == 0) {
 1442                                         return (ENOBUFS);
 1443                                 }
 1444 
 1445                                 rt->mfc_last_assert = now;
 1446 
 1447                                 im = mtod(mm, struct igmpmsg *);
 1448                                 im->im_msgtype  = IGMPMSG_WRONGVIF;
 1449                                 im->im_mbz      = 0;
 1450                                 im->im_vif      = vifi;
 1451 
 1452                                 sin.sin_addr = im->im_src;
 1453 
 1454                                 socket_send(ip_mrouter, mm, &sin);
 1455                         }
 1456                 }
 1457                 return (0);
 1458         }
 1459 
 1460         /* If I sourced this packet, it counts as output, else it was input. */
 1461         if (in_hosteq(ip->ip_src, viftable[vifi].v_lcl_addr)) {
 1462                 viftable[vifi].v_pkt_out++;
 1463                 viftable[vifi].v_bytes_out += plen;
 1464         } else {
 1465                 viftable[vifi].v_pkt_in++;
 1466                 viftable[vifi].v_bytes_in += plen;
 1467         }
 1468         rt->mfc_pkt_cnt++;
 1469         rt->mfc_byte_cnt += plen;
 1470 
 1471         /*
 1472          * For each vif, decide if a copy of the packet should be forwarded.
 1473          * Forward if:
 1474          *              - the ttl exceeds the vif's threshold
 1475          *              - there are group members downstream on interface
 1476          */
 1477         for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++)
 1478                 if ((rt->mfc_ttls[vifi] > 0) &&
 1479                     (ip->ip_ttl > rt->mfc_ttls[vifi])) {
 1480                         vifp->v_pkt_out++;
 1481                         vifp->v_bytes_out += plen;
 1482                         MC_SEND(ip, vifp, m);
 1483                 }
 1484 
 1485         return (0);
 1486 }
 1487 
 1488 #ifdef RSVP_ISI
 1489 /*
 1490  * check if a vif number is legal/ok. This is used by ip_output, to export
 1491  * numvifs there,
 1492  */
 1493 int
 1494 legal_vif_num(vif)
 1495         int vif;
 1496 {
 1497         if (vif >= 0 && vif < numvifs)
 1498                 return (1);
 1499         else
 1500                 return (0);
 1501 }
 1502 #endif /* RSVP_ISI */
 1503 
 1504 static void
 1505 phyint_send(ip, vifp, m)
 1506         struct ip *ip;
 1507         struct vif *vifp;
 1508         struct mbuf *m;
 1509 {
 1510         struct mbuf *mb_copy;
 1511         int hlen = ip->ip_hl << 2;
 1512 
 1513         /*
 1514          * Make a new reference to the packet; make sure that
 1515          * the IP header is actually copied, not just referenced,
 1516          * so that ip_output() only scribbles on the copy.
 1517          */
 1518         mb_copy = m_copy(m, 0, M_COPYALL);
 1519         M_PULLUP(mb_copy, hlen);
 1520         if (mb_copy == 0)
 1521                 return;
 1522 
 1523         if (vifp->v_rate_limit <= 0)
 1524                 tbf_send_packet(vifp, mb_copy);
 1525         else
 1526                 tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *),
 1527                     ntohs(ip->ip_len));
 1528 }
 1529 
 1530 static void
 1531 encap_send(ip, vifp, m)
 1532         struct ip *ip;
 1533         struct vif *vifp;
 1534         struct mbuf *m;
 1535 {
 1536         struct mbuf *mb_copy;
 1537         struct ip *ip_copy;
 1538         int i, len = ntohs(ip->ip_len) + sizeof(multicast_encap_iphdr);
 1539 
 1540         /*
 1541          * copy the old packet & pullup it's IP header into the
 1542          * new mbuf so we can modify it.  Try to fill the new
 1543          * mbuf since if we don't the ethernet driver will.
 1544          */
 1545         MGETHDR(mb_copy, M_DONTWAIT, MT_DATA);
 1546         if (mb_copy == 0)
 1547                 return;
 1548         mb_copy->m_data += max_linkhdr;
 1549         mb_copy->m_pkthdr.len = len;
 1550         mb_copy->m_len = sizeof(multicast_encap_iphdr);
 1551 
 1552         if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == 0) {
 1553                 m_freem(mb_copy);
 1554                 return;
 1555         }
 1556         i = MHLEN - max_linkhdr;
 1557         if (i > len)
 1558                 i = len;
 1559         mb_copy = m_pullup(mb_copy, i);
 1560         if (mb_copy == 0)
 1561                 return;
 1562 
 1563         /*
 1564          * fill in the encapsulating IP header.
 1565          */
 1566         ip_copy = mtod(mb_copy, struct ip *);
 1567         *ip_copy = multicast_encap_iphdr;
 1568         ip_copy->ip_id = ip_newid();
 1569         ip_copy->ip_len = htons(len);
 1570         ip_copy->ip_src = vifp->v_lcl_addr;
 1571         ip_copy->ip_dst = vifp->v_rmt_addr;
 1572 
 1573         /*
 1574          * turn the encapsulated IP header back into a valid one.
 1575          */
 1576         ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr));
 1577         --ip->ip_ttl;
 1578         ip->ip_sum = 0;
 1579         mb_copy->m_data += sizeof(multicast_encap_iphdr);
 1580         ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
 1581         mb_copy->m_data -= sizeof(multicast_encap_iphdr);
 1582 
 1583         if (vifp->v_rate_limit <= 0)
 1584                 tbf_send_packet(vifp, mb_copy);
 1585         else
 1586                 tbf_control(vifp, mb_copy, ip, ntohs(ip_copy->ip_len));
 1587 }
 1588 
 1589 /*
 1590  * De-encapsulate a packet and feed it back through ip input.
 1591  */
 1592 static void
 1593 #if __STDC__
 1594 vif_input(struct mbuf *m, ...)
 1595 #else
 1596 vif_input(m, va_alist)
 1597         struct mbuf *m;
 1598         va_dcl
 1599 #endif
 1600 {
 1601         int off, proto;
 1602         va_list ap;
 1603         struct vif *vifp;
 1604         int s;
 1605         struct ifqueue *ifq;
 1606 
 1607         va_start(ap, m);
 1608         off = va_arg(ap, int);
 1609         proto = va_arg(ap, int);
 1610         va_end(ap);
 1611 
 1612         vifp = (struct vif *)encap_getarg(m);
 1613         if (!vifp || proto != AF_INET) {
 1614                 m_freem(m);
 1615                 mrtstat.mrts_bad_tunnel++;
 1616                 return;
 1617         }
 1618 
 1619         m_adj(m, off);
 1620         m->m_pkthdr.rcvif = vifp->v_ifp;
 1621         ifq = &ipintrq;
 1622         s = splnet();
 1623         if (IF_QFULL(ifq)) {
 1624                 IF_DROP(ifq);
 1625                 m_freem(m);
 1626         } else {
 1627                 IF_ENQUEUE(ifq, m);
 1628                 /*
 1629                  * normally we would need a "schednetisr(NETISR_IP)"
 1630                  * here but we were called by ip_input and it is going
 1631                  * to loop back & try to dequeue the packet we just
 1632                  * queued as soon as we return so we avoid the
 1633                  * unnecessary software interrrupt.
 1634                  */
 1635         }
 1636         splx(s);
 1637 }
 1638 
 1639 /*
 1640  * Check if the packet should be grabbed by us.
 1641  */
 1642 static int
 1643 vif_encapcheck(m, off, proto, arg)
 1644         const struct mbuf *m;
 1645         int off;
 1646         int proto;
 1647         void *arg;
 1648 {
 1649         struct vif *vifp;
 1650         struct ip ip;
 1651 
 1652 #ifdef DIAGNOSTIC
 1653         if (!arg || proto != IPPROTO_IPV4)
 1654                 panic("unexpected arg in vif_encapcheck");
 1655 #endif
 1656 
 1657         /*
 1658          * do not grab the packet if it's not to a multicast destination or if
 1659          * we don't have an encapsulating tunnel with the source.
 1660          * Note:  This code assumes that the remote site IP address
 1661          * uniquely identifies the tunnel (i.e., that this site has
 1662          * at most one tunnel with the remote site).
 1663          */
 1664 
 1665         /* LINTED const cast */
 1666         m_copydata((struct mbuf *)m, off, sizeof(ip), (caddr_t)&ip);
 1667         if (!IN_MULTICAST(ip.ip_dst.s_addr))
 1668                 return 0;
 1669 
 1670         /* LINTED const cast */
 1671         m_copydata((struct mbuf *)m, 0, sizeof(ip), (caddr_t)&ip);
 1672         if (!in_hosteq(ip.ip_src, last_encap_src)) {
 1673                 vifp = (struct vif *)arg;
 1674                 if (vifp->v_flags & VIFF_TUNNEL &&
 1675                     in_hosteq(vifp->v_rmt_addr, ip.ip_src))
 1676                         ;
 1677                 else
 1678                         return 0;
 1679                 last_encap_vif = vifp;
 1680                 last_encap_src = ip.ip_src;
 1681         } else
 1682                 vifp = last_encap_vif;
 1683 
 1684         /* 32bit match, since we have checked ip_src only */
 1685         return 32;
 1686 }
 1687 
 1688 /*
 1689  * Token bucket filter module
 1690  */
 1691 static void
 1692 tbf_control(vifp, m, ip, len)
 1693         struct vif *vifp;
 1694         struct mbuf *m;
 1695         struct ip *ip;
 1696         u_int32_t len;
 1697 {
 1698 
 1699         if (len > MAX_BKT_SIZE) {
 1700                 /* drop if packet is too large */
 1701                 mrtstat.mrts_pkt2large++;
 1702                 m_freem(m);
 1703                 return;
 1704         }
 1705 
 1706         tbf_update_tokens(vifp);
 1707 
 1708         /*
 1709          * If there are enough tokens, and the queue is empty, send this packet
 1710          * out immediately.  Otherwise, try to insert it on this vif's queue.
 1711          */
 1712         if (vifp->tbf_q_len == 0) {
 1713                 if (len <= vifp->tbf_n_tok) {
 1714                         vifp->tbf_n_tok -= len;
 1715                         tbf_send_packet(vifp, m);
 1716                 } else {
 1717                         /* queue packet and timeout till later */
 1718                         tbf_queue(vifp, m);
 1719                         callout_reset(&vifp->v_repq_ch, TBF_REPROCESS,
 1720                             tbf_reprocess_q, vifp);
 1721                 }
 1722         } else {
 1723                 if (vifp->tbf_q_len >= vifp->tbf_max_q_len &&
 1724                     !tbf_dq_sel(vifp, ip)) {
 1725                         /* queue length too much, and couldn't make room */
 1726                         mrtstat.mrts_q_overflow++;
 1727                         m_freem(m);
 1728                 } else {
 1729                         /* queue length low enough, or made room */
 1730                         tbf_queue(vifp, m);
 1731                         tbf_process_q(vifp);
 1732                 }
 1733         }
 1734 }
 1735 
 1736 /*
 1737  * adds a packet to the queue at the interface
 1738  */
 1739 static void
 1740 tbf_queue(vifp, m)
 1741         struct vif *vifp;
 1742         struct mbuf *m;
 1743 {
 1744         int s = splsoftnet();
 1745 
 1746         /* insert at tail */
 1747         *vifp->tbf_t = m;
 1748         vifp->tbf_t = &m->m_nextpkt;
 1749         vifp->tbf_q_len++;
 1750 
 1751         splx(s);
 1752 }
 1753 
 1754 
 1755 /*
 1756  * processes the queue at the interface
 1757  */
 1758 static void
 1759 tbf_process_q(vifp)
 1760         struct vif *vifp;
 1761 {
 1762         struct mbuf *m;
 1763         int len;
 1764         int s = splsoftnet();
 1765 
 1766         /*
 1767          * Loop through the queue at the interface and send as many packets
 1768          * as possible.
 1769          */
 1770         for (m = vifp->tbf_q; m != 0; m = vifp->tbf_q) {
 1771                 len = ntohs(mtod(m, struct ip *)->ip_len);
 1772 
 1773                 /* determine if the packet can be sent */
 1774                 if (len <= vifp->tbf_n_tok) {
 1775                         /* if so,
 1776                          * reduce no of tokens, dequeue the packet,
 1777                          * send the packet.
 1778                          */
 1779                         if ((vifp->tbf_q = m->m_nextpkt) == 0)
 1780                                 vifp->tbf_t = &vifp->tbf_q;
 1781                         --vifp->tbf_q_len;
 1782 
 1783                         m->m_nextpkt = 0;
 1784                         vifp->tbf_n_tok -= len;
 1785                         tbf_send_packet(vifp, m);
 1786                 } else
 1787                         break;
 1788         }
 1789         splx(s);
 1790 }
 1791 
 1792 static void
 1793 tbf_reprocess_q(arg)
 1794         void *arg;
 1795 {
 1796         struct vif *vifp = arg;
 1797 
 1798         if (ip_mrouter == 0)
 1799                 return;
 1800 
 1801         tbf_update_tokens(vifp);
 1802         tbf_process_q(vifp);
 1803 
 1804         if (vifp->tbf_q_len != 0)
 1805                 callout_reset(&vifp->v_repq_ch, TBF_REPROCESS,
 1806                     tbf_reprocess_q, vifp);
 1807 }
 1808 
 1809 /* function that will selectively discard a member of the queue
 1810  * based on the precedence value and the priority
 1811  */
 1812 static int
 1813 tbf_dq_sel(vifp, ip)
 1814         struct vif *vifp;
 1815         struct ip *ip;
 1816 {
 1817         u_int p;
 1818         struct mbuf **mp, *m;
 1819         int s = splsoftnet();
 1820 
 1821         p = priority(vifp, ip);
 1822 
 1823         for (mp = &vifp->tbf_q, m = *mp;
 1824             m != 0;
 1825             mp = &m->m_nextpkt, m = *mp) {
 1826                 if (p > priority(vifp, mtod(m, struct ip *))) {
 1827                         if ((*mp = m->m_nextpkt) == 0)
 1828                                 vifp->tbf_t = mp;
 1829                         --vifp->tbf_q_len;
 1830 
 1831                         m_freem(m);
 1832                         mrtstat.mrts_drop_sel++;
 1833                         splx(s);
 1834                         return (1);
 1835                 }
 1836         }
 1837         splx(s);
 1838         return (0);
 1839 }
 1840 
 1841 static void
 1842 tbf_send_packet(vifp, m)
 1843         struct vif *vifp;
 1844         struct mbuf *m;
 1845 {
 1846         int error;
 1847         int s = splsoftnet();
 1848 
 1849         if (vifp->v_flags & VIFF_TUNNEL) {
 1850                 /* If tunnel options */
 1851                 ip_output(m, (struct mbuf *)0, &vifp->v_route,
 1852                     IP_FORWARDING, (struct ip_moptions *)NULL,
 1853                     (struct socket *)NULL);
 1854         } else {
 1855                 /* if physical interface option, extract the options and then send */
 1856                 struct ip_moptions imo;
 1857 
 1858                 imo.imo_multicast_ifp = vifp->v_ifp;
 1859                 imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
 1860                 imo.imo_multicast_loop = 1;
 1861 #ifdef RSVP_ISI
 1862                 imo.imo_multicast_vif = -1;
 1863 #endif
 1864 
 1865                 error = ip_output(m, (struct mbuf *)0, (struct route *)0,
 1866                     IP_FORWARDING|IP_MULTICASTOPTS, &imo,
 1867                     (struct socket *)NULL);
 1868 
 1869                 if (mrtdebug & DEBUG_XMIT)
 1870                         log(LOG_DEBUG, "phyint_send on vif %ld err %d\n",
 1871                             (long)(vifp - viftable), error);
 1872         }
 1873         splx(s);
 1874 }
 1875 
 1876 /* determine the current time and then
 1877  * the elapsed time (between the last time and time now)
 1878  * in milliseconds & update the no. of tokens in the bucket
 1879  */
 1880 static void
 1881 tbf_update_tokens(vifp)
 1882         struct vif *vifp;
 1883 {
 1884         struct timeval tp;
 1885         u_int32_t tm;
 1886         int s = splsoftnet();
 1887 
 1888         microtime(&tp);
 1889 
 1890         TV_DELTA(tp, vifp->tbf_last_pkt_t, tm);
 1891 
 1892         /*
 1893          * This formula is actually
 1894          * "time in seconds" * "bytes/second".
 1895          *
 1896          * (tm / 1000000) * (v_rate_limit * 1000 * (1000/1024) / 8)
 1897          *
 1898          * The (1000/1024) was introduced in add_vif to optimize
 1899          * this divide into a shift.
 1900          */
 1901         vifp->tbf_n_tok += tm * vifp->v_rate_limit / 8192;
 1902         vifp->tbf_last_pkt_t = tp;
 1903 
 1904         if (vifp->tbf_n_tok > MAX_BKT_SIZE)
 1905                 vifp->tbf_n_tok = MAX_BKT_SIZE;
 1906 
 1907         splx(s);
 1908 }
 1909 
 1910 static int
 1911 priority(vifp, ip)
 1912         struct vif *vifp;
 1913         struct ip *ip;
 1914 {
 1915         int prio;
 1916 
 1917         /* temporary hack; may add general packet classifier some day */
 1918 
 1919         /*
 1920          * The UDP port space is divided up into four priority ranges:
 1921          * [0, 16384)     : unclassified - lowest priority
 1922          * [16384, 32768) : audio - highest priority
 1923          * [32768, 49152) : whiteboard - medium priority
 1924          * [49152, 65536) : video - low priority
 1925          */
 1926         if (ip->ip_p == IPPROTO_UDP) {
 1927                 struct udphdr *udp = (struct udphdr *)(((char *)ip) + (ip->ip_hl << 2));
 1928 
 1929                 switch (ntohs(udp->uh_dport) & 0xc000) {
 1930                 case 0x4000:
 1931                         prio = 70;
 1932                         break;
 1933                 case 0x8000:
 1934                         prio = 60;
 1935                         break;
 1936                 case 0xc000:
 1937                         prio = 55;
 1938                         break;
 1939                 default:
 1940                         prio = 50;
 1941                         break;
 1942                 }
 1943 
 1944                 if (tbfdebug > 1)
 1945                         log(LOG_DEBUG, "port %x prio %d\n",
 1946                             ntohs(udp->uh_dport), prio);
 1947         } else
 1948                 prio = 50;
 1949 
 1950         return (prio);
 1951 }
 1952 
 1953 /*
 1954  * End of token bucket filter modifications
 1955  */
 1956 #ifdef RSVP_ISI
 1957 int
 1958 ip_rsvp_vif_init(so, m)
 1959         struct socket *so;
 1960         struct mbuf *m;
 1961 {
 1962         int i;
 1963         int s;
 1964 
 1965         if (rsvpdebug)
 1966                 printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n",
 1967                     so->so_type, so->so_proto->pr_protocol);
 1968 
 1969         if (so->so_type != SOCK_RAW ||
 1970             so->so_proto->pr_protocol != IPPROTO_RSVP)
 1971                 return (EOPNOTSUPP);
 1972 
 1973         /* Check mbuf. */
 1974         if (m == 0 || m->m_len != sizeof(int)) {
 1975                 return (EINVAL);
 1976         }
 1977         i = *(mtod(m, int *));
 1978 
 1979         if (rsvpdebug)
 1980                 printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n", i, rsvp_on);
 1981 
 1982         s = splsoftnet();
 1983 
 1984         /* Check vif. */
 1985         if (!legal_vif_num(i)) {
 1986                 splx(s);
 1987                 return (EADDRNOTAVAIL);
 1988         }
 1989 
 1990         /* Check if socket is available. */
 1991         if (viftable[i].v_rsvpd != 0) {
 1992                 splx(s);
 1993                 return (EADDRINUSE);
 1994         }
 1995 
 1996         viftable[i].v_rsvpd = so;
 1997         /*
 1998          * This may seem silly, but we need to be sure we don't over-increment
 1999          * the RSVP counter, in case something slips up.
 2000          */
 2001         if (!viftable[i].v_rsvp_on) {
 2002                 viftable[i].v_rsvp_on = 1;
 2003                 rsvp_on++;
 2004         }
 2005 
 2006         splx(s);
 2007         return (0);
 2008 }
 2009 
 2010 int
 2011 ip_rsvp_vif_done(so, m)
 2012         struct socket *so;
 2013         struct mbuf *m;
 2014 {
 2015         int i;
 2016         int s;
 2017 
 2018         if (rsvpdebug)
 2019                 printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n",
 2020                     so->so_type, so->so_proto->pr_protocol);
 2021 
 2022         if (so->so_type != SOCK_RAW ||
 2023             so->so_proto->pr_protocol != IPPROTO_RSVP)
 2024                 return (EOPNOTSUPP);
 2025 
 2026         /* Check mbuf. */
 2027         if (m == 0 || m->m_len != sizeof(int)) {
 2028                 return (EINVAL);
 2029         }
 2030         i = *(mtod(m, int *));
 2031 
 2032         s = splsoftnet();
 2033 
 2034         /* Check vif. */
 2035         if (!legal_vif_num(i)) {
 2036                 splx(s);
 2037                 return (EADDRNOTAVAIL);
 2038         }
 2039 
 2040         if (rsvpdebug)
 2041                 printf("ip_rsvp_vif_done: v_rsvpd = %x so = %x\n",
 2042                     viftable[i].v_rsvpd, so);
 2043 
 2044         viftable[i].v_rsvpd = 0;
 2045         /*
 2046          * This may seem silly, but we need to be sure we don't over-decrement
 2047          * the RSVP counter, in case something slips up.
 2048          */
 2049         if (viftable[i].v_rsvp_on) {
 2050                 viftable[i].v_rsvp_on = 0;
 2051                 rsvp_on--;
 2052         }
 2053 
 2054         splx(s);
 2055         return (0);
 2056 }
 2057 
 2058 void
 2059 ip_rsvp_force_done(so)
 2060         struct socket *so;
 2061 {
 2062         int vifi;
 2063         int s;
 2064 
 2065         /* Don't bother if it is not the right type of socket. */
 2066         if (so->so_type != SOCK_RAW ||
 2067             so->so_proto->pr_protocol != IPPROTO_RSVP)
 2068                 return;
 2069 
 2070         s = splsoftnet();
 2071 
 2072         /*
 2073          * The socket may be attached to more than one vif...this
 2074          * is perfectly legal.
 2075          */
 2076         for (vifi = 0; vifi < numvifs; vifi++) {
 2077                 if (viftable[vifi].v_rsvpd == so) {
 2078                         viftable[vifi].v_rsvpd = 0;
 2079                         /*
 2080                          * This may seem silly, but we need to be sure we don't
 2081                          * over-decrement the RSVP counter, in case something
 2082                          * slips up.
 2083                          */
 2084                         if (viftable[vifi].v_rsvp_on) {
 2085                                 viftable[vifi].v_rsvp_on = 0;
 2086                                 rsvp_on--;
 2087                         }
 2088                 }
 2089         }
 2090 
 2091         splx(s);
 2092         return;
 2093 }
 2094 
 2095 void
 2096 rsvp_input(m, ifp)
 2097         struct mbuf *m;
 2098         struct ifnet *ifp;
 2099 {
 2100         int vifi;
 2101         struct ip *ip = mtod(m, struct ip *);
 2102         static struct sockaddr_in rsvp_src = { sizeof(sin), AF_INET };
 2103         int s;
 2104 
 2105         if (rsvpdebug)
 2106                 printf("rsvp_input: rsvp_on %d\n", rsvp_on);
 2107 
 2108         /*
 2109          * Can still get packets with rsvp_on = 0 if there is a local member
 2110          * of the group to which the RSVP packet is addressed.  But in this
 2111          * case we want to throw the packet away.
 2112          */
 2113         if (!rsvp_on) {
 2114                 m_freem(m);
 2115                 return;
 2116         }
 2117 
 2118         /*
 2119          * If the old-style non-vif-associated socket is set, then use
 2120          * it and ignore the new ones.
 2121          */
 2122         if (ip_rsvpd != 0) {
 2123                 if (rsvpdebug)
 2124                         printf("rsvp_input: "
 2125                             "Sending packet up old-style socket\n");
 2126                 rip_input(m);   /*XXX*/
 2127                 return;
 2128         }
 2129 
 2130         s = splsoftnet();
 2131 
 2132         if (rsvpdebug)
 2133                 printf("rsvp_input: check vifs\n");
 2134 
 2135         /* Find which vif the packet arrived on. */
 2136         for (vifi = 0; vifi < numvifs; vifi++) {
 2137                 if (viftable[vifi].v_ifp == ifp)
 2138                         break;
 2139         }
 2140 
 2141         if (vifi == numvifs) {
 2142                 /* Can't find vif packet arrived on. Drop packet. */
 2143                 if (rsvpdebug)
 2144                         printf("rsvp_input: "
 2145                             "Can't find vif for packet...dropping it.\n");
 2146                 m_freem(m);
 2147                 splx(s);
 2148                 return;
 2149         }
 2150 
 2151         if (rsvpdebug)
 2152                 printf("rsvp_input: check socket\n");
 2153 
 2154         if (viftable[vifi].v_rsvpd == 0) {
 2155                 /*
 2156                  * drop packet, since there is no specific socket for this
 2157                  * interface
 2158                  */
 2159                 if (rsvpdebug)
 2160                         printf("rsvp_input: No socket defined for vif %d\n",
 2161                             vifi);
 2162                 m_freem(m);
 2163                 splx(s);
 2164                 return;
 2165         }
 2166 
 2167         rsvp_src.sin_addr = ip->ip_src;
 2168 
 2169         if (rsvpdebug && m)
 2170                 printf("rsvp_input: m->m_len = %d, sbspace() = %d\n",
 2171                     m->m_len, sbspace(&viftable[vifi].v_rsvpd->so_rcv));
 2172 
 2173         if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0)
 2174                 if (rsvpdebug)
 2175                         printf("rsvp_input: Failed to append to socket\n");
 2176         else
 2177                 if (rsvpdebug)
 2178                         printf("rsvp_input: send packet up\n");
 2179 
 2180         splx(s);
 2181 }
 2182 #endif /* RSVP_ISI */

Cache object: 5e57226f717c1a16591d0a9ae3cc8092


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