source: rtems/cpukit/libnetworking/netinet/ip_mroute.c @ b3f8c9e1

4.104.11
Last change on this file since b3f8c9e1 was b3f8c9e1, checked in by Ralf Corsepius <ralf.corsepius@…>, on Dec 22, 2008 at 7:47:28 AM

Include <errno.h> (POSIX,C99) instead of <sys/errno.h> (BSD'ism).

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