ip_mroute.c revision 85658
11541Srgrimes/* 22531Swollman * IP multicast forwarding procedures 31541Srgrimes * 41541Srgrimes * Written by David Waitzman, BBN Labs, August 1988. 51541Srgrimes * Modified by Steve Deering, Stanford, February 1989. 62531Swollman * Modified by Mark J. Steiglitz, Stanford, May, 1991 72531Swollman * Modified by Van Jacobson, LBL, January 1993 82531Swollman * Modified by Ajit Thyagarajan, PARC, August 1993 99209Swollman * Modified by Bill Fenner, PARC, April 1995 101541Srgrimes * 119209Swollman * MROUTING Revision: 3.5 1250477Speter * $FreeBSD: head/sys/netinet/ip_mroute.c 85658 2001-10-29 02:19:19Z dillon $ 131541Srgrimes */ 141541Srgrimes 1514328Speter#include "opt_mrouting.h" 1677574Skris#include "opt_random_ip_id.h" 171541Srgrimes 181541Srgrimes#include <sys/param.h> 191549Srgrimes#include <sys/systm.h> 2042777Sfenner#include <sys/malloc.h> 211541Srgrimes#include <sys/mbuf.h> 221541Srgrimes#include <sys/socket.h> 231541Srgrimes#include <sys/socketvar.h> 242531Swollman#include <sys/protosw.h> 251541Srgrimes#include <sys/time.h> 269209Swollman#include <sys/kernel.h> 2780354Sfenner#include <sys/sysctl.h> 2824204Sbde#include <sys/sockio.h> 292531Swollman#include <sys/syslog.h> 301541Srgrimes#include <net/if.h> 311541Srgrimes#include <net/route.h> 321541Srgrimes#include <netinet/in.h> 331541Srgrimes#include <netinet/in_systm.h> 341541Srgrimes#include <netinet/ip.h> 352531Swollman#include <netinet/ip_var.h> 361541Srgrimes#include <netinet/in_var.h> 371541Srgrimes#include <netinet/igmp.h> 3880354Sfenner#include <netinet/ip_encap.h> 391541Srgrimes#include <netinet/ip_mroute.h> 409209Swollman#include <netinet/udp.h> 4160214Sken#include <machine/in_cksum.h> 421541Srgrimes 432531Swollman#ifndef MROUTING 4412579Sbdeextern u_long _ip_mcast_src __P((int vifi)); 4512579Sbdeextern int _ip_mforward __P((struct ip *ip, struct ifnet *ifp, 4612579Sbde struct mbuf *m, struct ip_moptions *imo)); 4712579Sbdeextern int _ip_mrouter_done __P((void)); 4838482Swollmanextern int _ip_mrouter_get __P((struct socket *so, struct sockopt *sopt)); 4938482Swollmanextern int _ip_mrouter_set __P((struct socket *so, struct sockopt *sopt)); 5080354Sfennerextern int _mrt_ioctl __P((int req, caddr_t data)); 5112579Sbde 522531Swollman/* 532531Swollman * Dummy routines and globals used when multicast routing is not compiled in. 542531Swollman */ 551541Srgrimes 569209Swollmanstruct socket *ip_mrouter = NULL; 579209Swollmanu_int rsvpdebug = 0; 582531Swollman 592531Swollmanint 6038482Swollman_ip_mrouter_set(so, sopt) 612531Swollman struct socket *so; 6238482Swollman struct sockopt *sopt; 632531Swollman{ 642531Swollman return(EOPNOTSUPP); 652531Swollman} 662531Swollman 6738482Swollmanint (*ip_mrouter_set)(struct socket *, struct sockopt *) = _ip_mrouter_set; 682754Swollman 699209Swollman 702531Swollmanint 7138482Swollman_ip_mrouter_get(so, sopt) 729209Swollman struct socket *so; 7338482Swollman struct sockopt *sopt; 749209Swollman{ 759209Swollman return(EOPNOTSUPP); 769209Swollman} 779209Swollman 7838482Swollmanint (*ip_mrouter_get)(struct socket *, struct sockopt *) = _ip_mrouter_get; 799209Swollman 809209Swollmanint 812754Swollman_ip_mrouter_done() 822531Swollman{ 832531Swollman return(0); 842531Swollman} 852531Swollman 862754Swollmanint (*ip_mrouter_done)(void) = _ip_mrouter_done; 872754Swollman 882531Swollmanint 892754Swollman_ip_mforward(ip, ifp, m, imo) 902531Swollman struct ip *ip; 912531Swollman struct ifnet *ifp; 922531Swollman struct mbuf *m; 932754Swollman struct ip_moptions *imo; 942531Swollman{ 952531Swollman return(0); 962531Swollman} 972754Swollman 982754Swollmanint (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, 992754Swollman struct ip_moptions *) = _ip_mforward; 1002754Swollman 1012754Swollmanint 10280354Sfenner_mrt_ioctl(int req, caddr_t data) 1032754Swollman{ 1042754Swollman return EOPNOTSUPP; 1052754Swollman} 1062754Swollman 10780354Sfennerint (*mrt_ioctl)(int, caddr_t) = _mrt_ioctl; 1082754Swollman 1099209Swollmanvoid 11082884Sjulianrsvp_input(m, off) /* XXX must fixup manually */ 1119209Swollman struct mbuf *m; 11255009Sshin int off; 1139209Swollman{ 1149209Swollman /* Can still get packets with rsvp_on = 0 if there is a local member 1159209Swollman * of the group to which the RSVP packet is addressed. But in this 1169209Swollman * case we want to throw the packet away. 1179209Swollman */ 1189209Swollman if (!rsvp_on) { 1199209Swollman m_freem(m); 1209209Swollman return; 1219209Swollman } 1229209Swollman 1239209Swollman if (ip_rsvpd != NULL) { 1249209Swollman if (rsvpdebug) 1259209Swollman printf("rsvp_input: Sending packet up old-style socket\n"); 12682884Sjulian rip_input(m, off); 1279209Swollman return; 1289209Swollman } 1299209Swollman /* Drop the packet */ 1309209Swollman m_freem(m); 1312754Swollman} 1322754Swollman 1332754Swollmanint (*legal_vif_num)(int) = 0; 1342754Swollman 1359209Swollman/* 1369209Swollman * This should never be called, since IP_MULTICAST_VIF should fail, but 1379209Swollman * just in case it does get called, the code a little lower in ip_output 1389209Swollman * will assign the packet a local address. 1399209Swollman */ 1409209Swollmanu_long 1419209Swollman_ip_mcast_src(int vifi) { return INADDR_ANY; } 1429209Swollmanu_long (*ip_mcast_src)(int) = _ip_mcast_src; 1439209Swollman 1449209Swollmanint 14538482Swollmanip_rsvp_vif_init(so, sopt) 1469209Swollman struct socket *so; 14738482Swollman struct sockopt *sopt; 1489209Swollman{ 1499209Swollman return(EINVAL); 1509209Swollman} 1519209Swollman 1529209Swollmanint 15338482Swollmanip_rsvp_vif_done(so, sopt) 1549209Swollman struct socket *so; 15538482Swollman struct sockopt *sopt; 1569209Swollman{ 1579209Swollman return(EINVAL); 1589209Swollman} 1599209Swollman 1609209Swollmanvoid 1619209Swollmanip_rsvp_force_done(so) 1629209Swollman struct socket *so; 1639209Swollman{ 1649209Swollman return; 1659209Swollman} 1669209Swollman 1677083Swollman#else /* MROUTING */ 1682531Swollman 1699209Swollman#define M_HASCL(m) ((m)->m_flags & M_EXT) 1709209Swollman 17142777Sfennerstatic MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast routing tables"); 1722531Swollman 17380354Sfenner#ifndef MROUTE_KLD 17480354Sfenner/* The socket used to communicate with the multicast routing daemon. */ 1752531Swollmanstruct socket *ip_mrouter = NULL; 17680354Sfenner#endif 17780354Sfenner 17880354Sfenner#if defined(MROUTING) || defined(MROUTE_KLD) 17933181Seivindstatic struct mrtstat mrtstat; 18080354SfennerSYSCTL_STRUCT(_net_inet_ip, OID_AUTO, mrtstat, CTLFLAG_RW, 18180354Sfenner &mrtstat, mrtstat, "Multicast Routing Statistics (struct mrtstat, netinet/ip_mroute.h)"); 1822763Swollman#endif 1831541Srgrimes 18442777Sfennerstatic struct mfc *mfctable[MFCTBLSIZ]; 18512820Sphkstatic u_char nexpire[MFCTBLSIZ]; 18612820Sphkstatic struct vif viftable[MAXVIFS]; 18712296Sphkstatic u_int mrtdebug = 0; /* debug level */ 1889209Swollman#define DEBUG_MFC 0x02 1899209Swollman#define DEBUG_FORWARD 0x04 1909209Swollman#define DEBUG_EXPIRE 0x08 1919209Swollman#define DEBUG_XMIT 0x10 19212296Sphkstatic u_int tbfdebug = 0; /* tbf debug level */ 19312296Sphkstatic u_int rsvpdebug = 0; /* rsvp debug level */ 1942531Swollman 19529681Sgibbsstatic struct callout_handle expire_upcalls_ch; 19629681Sgibbs 1979209Swollman#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ 1989209Swollman#define UPCALL_EXPIRE 6 /* number of timeouts */ 1992531Swollman 2001541Srgrimes/* 2012531Swollman * Define the token bucket filter structures 2029209Swollman * tbftable -> each vif has one of these for storing info 2032531Swollman */ 2042531Swollman 20512820Sphkstatic struct tbf tbftable[MAXVIFS]; 20610203Swollman#define TBF_REPROCESS (hz / 100) /* 100x / second */ 2072531Swollman 2082531Swollman/* 2092531Swollman * 'Interfaces' associated with decapsulator (so we can tell 2102531Swollman * packets that went through it from ones that get reflected 2112531Swollman * by a broken gateway). These interfaces are never linked into 2122531Swollman * the system ifnet list & no routes point to them. I.e., packets 2132531Swollman * can't be sent this way. They only exist as a placeholder for 2142531Swollman * multicast source verification. 2152531Swollman */ 21612820Sphkstatic struct ifnet multicast_decap_if[MAXVIFS]; 2172531Swollman 2182531Swollman#define ENCAP_TTL 64 2199209Swollman#define ENCAP_PROTO IPPROTO_IPIP /* 4 */ 2202531Swollman 2212531Swollman/* prototype IP hdr for encapsulated packets */ 22212296Sphkstatic struct ip multicast_encap_iphdr = { 2232754Swollman#if BYTE_ORDER == LITTLE_ENDIAN 2242531Swollman sizeof(struct ip) >> 2, IPVERSION, 2252531Swollman#else 2262531Swollman IPVERSION, sizeof(struct ip) >> 2, 2272531Swollman#endif 2282531Swollman 0, /* tos */ 2292531Swollman sizeof(struct ip), /* total length */ 2302531Swollman 0, /* id */ 2312531Swollman 0, /* frag offset */ 2329209Swollman ENCAP_TTL, ENCAP_PROTO, 2332531Swollman 0, /* checksum */ 2342531Swollman}; 2352531Swollman 2362531Swollman/* 2371541Srgrimes * Private variables. 2381541Srgrimes */ 2392531Swollmanstatic vifi_t numvifs = 0; 24080354Sfennerstatic const struct encaptab *encap_cookie = NULL; 2411541Srgrimes 2421541Srgrimes/* 24383708Ssumikawa * one-back cache used by mroute_encapcheck to locate a tunnel's vif 2442531Swollman * given a datagram's src ip address. 2452531Swollman */ 2462531Swollmanstatic u_long last_encap_src; 2472531Swollmanstatic struct vif *last_encap_vif; 2482531Swollman 24912579Sbdestatic u_long X_ip_mcast_src __P((int vifi)); 25012579Sbdestatic int X_ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo)); 25112579Sbdestatic int X_ip_mrouter_done __P((void)); 25238482Swollmanstatic int X_ip_mrouter_get __P((struct socket *so, struct sockopt *m)); 25338482Swollmanstatic int X_ip_mrouter_set __P((struct socket *so, struct sockopt *m)); 25412579Sbdestatic int X_legal_vif_num __P((int vif)); 25512579Sbdestatic int X_mrt_ioctl __P((int cmd, caddr_t data)); 25612579Sbde 2579209Swollmanstatic int get_sg_cnt(struct sioc_sg_req *); 2589209Swollmanstatic int get_vif_cnt(struct sioc_vif_req *); 25938482Swollmanstatic int ip_mrouter_init(struct socket *, int); 2602531Swollmanstatic int add_vif(struct vifctl *); 26138482Swollmanstatic int del_vif(vifi_t); 2622531Swollmanstatic int add_mfc(struct mfcctl *); 2639209Swollmanstatic int del_mfc(struct mfcctl *); 26412579Sbdestatic int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *); 26538482Swollmanstatic int set_assert(int); 2669209Swollmanstatic void expire_upcalls(void *); 2679209Swollmanstatic int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, 2689209Swollman vifi_t); 2692531Swollmanstatic void phyint_send(struct ip *, struct vif *, struct mbuf *); 2702531Swollmanstatic void encap_send(struct ip *, struct vif *, struct mbuf *); 27110203Swollmanstatic void tbf_control(struct vif *, struct mbuf *, struct ip *, u_long); 27210203Swollmanstatic void tbf_queue(struct vif *, struct mbuf *); 2739209Swollmanstatic void tbf_process_q(struct vif *); 2749209Swollmanstatic void tbf_reprocess_q(void *); 2759209Swollmanstatic int tbf_dq_sel(struct vif *, struct ip *); 27610203Swollmanstatic void tbf_send_packet(struct vif *, struct mbuf *); 2779209Swollmanstatic void tbf_update_tokens(struct vif *); 2782531Swollmanstatic int priority(struct vif *, struct ip *); 2792531Swollman 2802531Swollman/* 2819209Swollman * whether or not special PIM assert processing is enabled. 2828876Srgrimes */ 2839209Swollmanstatic int pim_assert; 2849209Swollman/* 2859209Swollman * Rate limit for assert notification messages, in usec 2869209Swollman */ 2879209Swollman#define ASSERT_MSG_TIME 3000000 2882531Swollman 2892531Swollman/* 2909209Swollman * Hash function for a source, group entry 2912531Swollman */ 2929209Swollman#define MFCHASH(a, g) MFCHASHMOD(((a) >> 20) ^ ((a) >> 10) ^ (a) ^ \ 2939209Swollman ((g) >> 20) ^ ((g) >> 10) ^ (g)) 2942531Swollman 2952531Swollman/* 2962531Swollman * Find a route for a given origin IP address and Multicast group address 2972531Swollman * Type of service parameter to be added in the future!!! 2982531Swollman */ 2999209Swollman 3002531Swollman#define MFCFIND(o, g, rt) { \ 30142777Sfenner register struct mfc *_rt = mfctable[MFCHASH(o,g)]; \ 3029209Swollman rt = NULL; \ 3032531Swollman ++mrtstat.mrts_mfc_lookups; \ 30442777Sfenner while (_rt) { \ 3059209Swollman if ((_rt->mfc_origin.s_addr == o) && \ 3069209Swollman (_rt->mfc_mcastgrp.s_addr == g) && \ 30742777Sfenner (_rt->mfc_stall == NULL)) { \ 3089209Swollman rt = _rt; \ 3099209Swollman break; \ 3109209Swollman } \ 31142777Sfenner _rt = _rt->mfc_next; \ 3129209Swollman } \ 3139209Swollman if (rt == NULL) { \ 3149209Swollman ++mrtstat.mrts_mfc_misses; \ 3159209Swollman } \ 3162531Swollman} 3172531Swollman 3182531Swollman 3192531Swollman/* 3202531Swollman * Macros to compute elapsed time efficiently 3212531Swollman * Borrowed from Van Jacobson's scheduling code 3222531Swollman */ 3232531Swollman#define TV_DELTA(a, b, delta) { \ 3242531Swollman register int xxs; \ 3252531Swollman \ 3262531Swollman delta = (a).tv_usec - (b).tv_usec; \ 3272531Swollman if ((xxs = (a).tv_sec - (b).tv_sec)) { \ 3282531Swollman switch (xxs) { \ 3292531Swollman case 2: \ 3302531Swollman delta += 1000000; \ 3312531Swollman /* fall through */ \ 3322531Swollman case 1: \ 3332531Swollman delta += 1000000; \ 3342531Swollman break; \ 3352531Swollman default: \ 3362531Swollman delta += (1000000 * xxs); \ 3372531Swollman } \ 3382531Swollman } \ 3392531Swollman} 3402531Swollman 3412531Swollman#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \ 3422531Swollman (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec) 3432531Swollman 3449209Swollman#ifdef UPCALL_TIMING 3459209Swollmanu_long upcall_data[51]; 3469209Swollmanstatic void collate(struct timeval *); 3479209Swollman#endif /* UPCALL_TIMING */ 3489209Swollman 3499209Swollman 3502531Swollman/* 3519209Swollman * Handle MRT setsockopt commands to modify the multicast routing tables. 3521541Srgrimes */ 35312296Sphkstatic int 35438482SwollmanX_ip_mrouter_set(so, sopt) 35538482Swollman struct socket *so; 35638482Swollman struct sockopt *sopt; 3571541Srgrimes{ 35838482Swollman int error, optval; 35938482Swollman vifi_t vifi; 36038482Swollman struct vifctl vifc; 36138482Swollman struct mfcctl mfc; 3621541Srgrimes 36338482Swollman if (so != ip_mrouter && sopt->sopt_name != MRT_INIT) 36438482Swollman return (EPERM); 36538482Swollman 36638482Swollman error = 0; 36738482Swollman switch (sopt->sopt_name) { 36838482Swollman case MRT_INIT: 36938482Swollman error = sooptcopyin(sopt, &optval, sizeof optval, 37038482Swollman sizeof optval); 37138482Swollman if (error) 37238482Swollman break; 37338482Swollman error = ip_mrouter_init(so, optval); 37438482Swollman break; 37538482Swollman 37638482Swollman case MRT_DONE: 37738482Swollman error = ip_mrouter_done(); 37838482Swollman break; 37938482Swollman 38038482Swollman case MRT_ADD_VIF: 38138482Swollman error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc); 38238482Swollman if (error) 38338482Swollman break; 38438482Swollman error = add_vif(&vifc); 38538482Swollman break; 38638482Swollman 38738482Swollman case MRT_DEL_VIF: 38838482Swollman error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi); 38938482Swollman if (error) 39038482Swollman break; 39138482Swollman error = del_vif(vifi); 39238482Swollman break; 39338482Swollman 39438482Swollman case MRT_ADD_MFC: 39538482Swollman case MRT_DEL_MFC: 39638482Swollman error = sooptcopyin(sopt, &mfc, sizeof mfc, sizeof mfc); 39738482Swollman if (error) 39838482Swollman break; 39938482Swollman if (sopt->sopt_name == MRT_ADD_MFC) 40038482Swollman error = add_mfc(&mfc); 40138482Swollman else 40238482Swollman error = del_mfc(&mfc); 40341878Sfenner break; 40438482Swollman 40538482Swollman case MRT_ASSERT: 40638482Swollman error = sooptcopyin(sopt, &optval, sizeof optval, 40738482Swollman sizeof optval); 40838482Swollman if (error) 40938482Swollman break; 41038482Swollman set_assert(optval); 41141878Sfenner break; 41238482Swollman 41338482Swollman default: 41438482Swollman error = EOPNOTSUPP; 41538482Swollman break; 41638482Swollman } 41738482Swollman return (error); 4182531Swollman} 4191541Srgrimes 42080354Sfenner#ifndef MROUTE_KLD 42138482Swollmanint (*ip_mrouter_set)(struct socket *, struct sockopt *) = X_ip_mrouter_set; 4222763Swollman#endif 4231541Srgrimes 4242531Swollman/* 4259209Swollman * Handle MRT getsockopt commands 4269209Swollman */ 42712296Sphkstatic int 42838482SwollmanX_ip_mrouter_get(so, sopt) 42938482Swollman struct socket *so; 43038482Swollman struct sockopt *sopt; 4319209Swollman{ 43238482Swollman int error; 43338482Swollman static int version = 0x0305; /* !!! why is this here? XXX */ 4349209Swollman 43538482Swollman switch (sopt->sopt_name) { 43638482Swollman case MRT_VERSION: 43738482Swollman error = sooptcopyout(sopt, &version, sizeof version); 43838482Swollman break; 4399209Swollman 44038482Swollman case MRT_ASSERT: 44138482Swollman error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert); 44238482Swollman break; 44338482Swollman default: 44438482Swollman error = EOPNOTSUPP; 44538482Swollman break; 44638482Swollman } 44738482Swollman return (error); 4489209Swollman} 4499209Swollman 45080354Sfenner#ifndef MROUTE_KLD 45138482Swollmanint (*ip_mrouter_get)(struct socket *, struct sockopt *) = X_ip_mrouter_get; 4529209Swollman#endif 4539209Swollman 4549209Swollman/* 4552531Swollman * Handle ioctl commands to obtain information from the cache 4562531Swollman */ 45712296Sphkstatic int 4582763SwollmanX_mrt_ioctl(cmd, data) 4592531Swollman int cmd; 4602531Swollman caddr_t data; 4612531Swollman{ 4622531Swollman int error = 0; 4631541Srgrimes 4642531Swollman switch (cmd) { 4659209Swollman case (SIOCGETVIFCNT): 4669209Swollman return (get_vif_cnt((struct sioc_vif_req *)data)); 4679209Swollman break; 4689209Swollman case (SIOCGETSGCNT): 4699209Swollman return (get_sg_cnt((struct sioc_sg_req *)data)); 4709209Swollman break; 4712531Swollman default: 4729209Swollman return (EINVAL); 4739209Swollman break; 4742531Swollman } 4752531Swollman return error; 4762531Swollman} 4771541Srgrimes 47880354Sfenner#ifndef MROUTE_KLD 47912579Sbdeint (*mrt_ioctl)(int, caddr_t) = X_mrt_ioctl; 4802763Swollman#endif 4812754Swollman 4822531Swollman/* 4839209Swollman * returns the packet, byte, rpf-failure count for the source group provided 4842531Swollman */ 4859209Swollmanstatic int 4862531Swollmanget_sg_cnt(req) 4872531Swollman register struct sioc_sg_req *req; 4882531Swollman{ 4892531Swollman register struct mfc *rt; 4902531Swollman int s; 4911541Srgrimes 4922531Swollman s = splnet(); 4932531Swollman MFCFIND(req->src.s_addr, req->grp.s_addr, rt); 4942531Swollman splx(s); 4959209Swollman if (rt != NULL) { 4969209Swollman req->pktcnt = rt->mfc_pkt_cnt; 4979209Swollman req->bytecnt = rt->mfc_byte_cnt; 4989209Swollman req->wrong_if = rt->mfc_wrong_if; 4999209Swollman } else 5009209Swollman req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff; 5011541Srgrimes 5022531Swollman return 0; 5032531Swollman} 5041541Srgrimes 5052531Swollman/* 5069209Swollman * returns the input and output packet and byte counts on the vif provided 5072531Swollman */ 5089209Swollmanstatic int 5092531Swollmanget_vif_cnt(req) 5102531Swollman register struct sioc_vif_req *req; 5112531Swollman{ 5122531Swollman register vifi_t vifi = req->vifi; 5131541Srgrimes 5149209Swollman if (vifi >= numvifs) return EINVAL; 5159209Swollman 5162531Swollman req->icount = viftable[vifi].v_pkt_in; 5172531Swollman req->ocount = viftable[vifi].v_pkt_out; 5189209Swollman req->ibytes = viftable[vifi].v_bytes_in; 5199209Swollman req->obytes = viftable[vifi].v_bytes_out; 5201541Srgrimes 5212531Swollman return 0; 5222531Swollman} 5232531Swollman 5241541Srgrimes/* 5251541Srgrimes * Enable multicast routing 5261541Srgrimes */ 52712296Sphkstatic int 52838482Swollmanip_mrouter_init(so, version) 5292531Swollman struct socket *so; 53038482Swollman int version; 5311541Srgrimes{ 5329209Swollman if (mrtdebug) 53311284Swollman log(LOG_DEBUG,"ip_mrouter_init: so_type = %d, pr_protocol = %d\n", 5349209Swollman so->so_type, so->so_proto->pr_protocol); 5359209Swollman 5362531Swollman if (so->so_type != SOCK_RAW || 5372531Swollman so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP; 5381541Srgrimes 53938482Swollman if (version != 1) 5409209Swollman return ENOPROTOOPT; 5419209Swollman 5422531Swollman if (ip_mrouter != NULL) return EADDRINUSE; 5431541Srgrimes 5442531Swollman ip_mrouter = so; 5451541Srgrimes 5469209Swollman bzero((caddr_t)mfctable, sizeof(mfctable)); 5479209Swollman bzero((caddr_t)nexpire, sizeof(nexpire)); 5489209Swollman 5499209Swollman pim_assert = 0; 5509209Swollman 55129681Sgibbs expire_upcalls_ch = timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT); 5529209Swollman 5532531Swollman if (mrtdebug) 55411284Swollman log(LOG_DEBUG, "ip_mrouter_init\n"); 5552531Swollman 5562531Swollman return 0; 5571541Srgrimes} 5581541Srgrimes 5591541Srgrimes/* 5601541Srgrimes * Disable multicast routing 5611541Srgrimes */ 56212296Sphkstatic int 5632763SwollmanX_ip_mrouter_done() 5641541Srgrimes{ 5652531Swollman vifi_t vifi; 5662531Swollman int i; 5672531Swollman struct ifnet *ifp; 5682531Swollman struct ifreq ifr; 56942777Sfenner struct mfc *rt; 5702531Swollman struct rtdetq *rte; 5712531Swollman int s; 5721541Srgrimes 5732531Swollman s = splnet(); 5741541Srgrimes 5752531Swollman /* 5762531Swollman * For each phyint in use, disable promiscuous reception of all IP 5772531Swollman * multicasts. 5782531Swollman */ 5792531Swollman for (vifi = 0; vifi < numvifs; vifi++) { 5802531Swollman if (viftable[vifi].v_lcl_addr.s_addr != 0 && 5812531Swollman !(viftable[vifi].v_flags & VIFF_TUNNEL)) { 5822531Swollman ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; 5832531Swollman ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr 5842531Swollman = INADDR_ANY; 5852531Swollman ifp = viftable[vifi].v_ifp; 58621666Swollman if_allmulti(ifp, 0); 5872531Swollman } 5882531Swollman } 5892531Swollman bzero((caddr_t)tbftable, sizeof(tbftable)); 5902531Swollman bzero((caddr_t)viftable, sizeof(viftable)); 5912531Swollman numvifs = 0; 5929209Swollman pim_assert = 0; 5932531Swollman 59429681Sgibbs untimeout(expire_upcalls, (caddr_t)NULL, expire_upcalls_ch); 5959209Swollman 5962531Swollman /* 5979209Swollman * Free all multicast forwarding cache entries. 5982531Swollman */ 5999209Swollman for (i = 0; i < MFCTBLSIZ; i++) { 60042777Sfenner for (rt = mfctable[i]; rt != NULL; ) { 60142777Sfenner struct mfc *nr = rt->mfc_next; 60242777Sfenner 60342777Sfenner for (rte = rt->mfc_stall; rte != NULL; ) { 60442777Sfenner struct rtdetq *n = rte->next; 60542777Sfenner 60642777Sfenner m_freem(rte->m); 60742777Sfenner free(rte, M_MRTABLE); 60842777Sfenner rte = n; 6092531Swollman } 61042777Sfenner free(rt, M_MRTABLE); 61142777Sfenner rt = nr; 6121541Srgrimes } 6139209Swollman } 6141541Srgrimes 6152531Swollman bzero((caddr_t)mfctable, sizeof(mfctable)); 6161541Srgrimes 6172531Swollman /* 6182531Swollman * Reset de-encapsulation cache 6192531Swollman */ 62017108Sbde last_encap_src = 0; 6212531Swollman last_encap_vif = NULL; 62280354Sfenner if (encap_cookie) { 62380354Sfenner encap_detach(encap_cookie); 62480354Sfenner encap_cookie = NULL; 62580354Sfenner } 6269209Swollman 6272531Swollman ip_mrouter = NULL; 6282531Swollman 6292531Swollman splx(s); 6302531Swollman 6312531Swollman if (mrtdebug) 63211284Swollman log(LOG_DEBUG, "ip_mrouter_done\n"); 6332531Swollman 6342531Swollman return 0; 6351541Srgrimes} 6361541Srgrimes 63780354Sfenner#ifndef MROUTE_KLD 6382763Swollmanint (*ip_mrouter_done)(void) = X_ip_mrouter_done; 6392763Swollman#endif 6402754Swollman 6411541Srgrimes/* 6429209Swollman * Set PIM assert processing global 6439209Swollman */ 6449209Swollmanstatic int 6459209Swollmanset_assert(i) 64638482Swollman int i; 6479209Swollman{ 64838482Swollman if ((i != 1) && (i != 0)) 6499209Swollman return EINVAL; 6509209Swollman 65138482Swollman pim_assert = i; 6529209Swollman 6539209Swollman return 0; 6549209Swollman} 6559209Swollman 6569209Swollman/* 65780354Sfenner * Decide if a packet is from a tunnelled peer. 65880354Sfenner * Return 0 if not, 64 if so. 65980354Sfenner */ 66080354Sfennerstatic int 66180354Sfennermroute_encapcheck(const struct mbuf *m, int off, int proto, void *arg) 66280354Sfenner{ 66380354Sfenner struct ip *ip = mtod(m, struct ip *); 66480354Sfenner int hlen = ip->ip_hl << 2; 66580354Sfenner register struct vif *vifp; 66680354Sfenner 66780354Sfenner /* 66880354Sfenner * don't claim the packet if it's not to a multicast destination or if 66980354Sfenner * we don't have an encapsulating tunnel with the source. 67080354Sfenner * Note: This code assumes that the remote site IP address 67180354Sfenner * uniquely identifies the tunnel (i.e., that this site has 67280354Sfenner * at most one tunnel with the remote site). 67380354Sfenner */ 67480354Sfenner if (! IN_MULTICAST(ntohl(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr))) { 67580354Sfenner return 0; 67680354Sfenner } 67780354Sfenner if (ip->ip_src.s_addr != last_encap_src) { 67880354Sfenner register struct vif *vife; 67980354Sfenner 68080354Sfenner vifp = viftable; 68180354Sfenner vife = vifp + numvifs; 68280354Sfenner last_encap_src = ip->ip_src.s_addr; 68380354Sfenner last_encap_vif = 0; 68480354Sfenner for ( ; vifp < vife; ++vifp) 68580354Sfenner if (vifp->v_rmt_addr.s_addr == ip->ip_src.s_addr) { 68680354Sfenner if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT)) 68780354Sfenner == VIFF_TUNNEL) 68880354Sfenner last_encap_vif = vifp; 68980354Sfenner break; 69080354Sfenner } 69180354Sfenner } 69280354Sfenner if ((vifp = last_encap_vif) == 0) { 69380354Sfenner last_encap_src = 0; 69480354Sfenner return 0; 69580354Sfenner } 69680354Sfenner return 64; 69780354Sfenner} 69880354Sfenner 69980354Sfenner/* 70080354Sfenner * De-encapsulate a packet and feed it back through ip input (this 70180354Sfenner * routine is called whenever IP gets a packet that mroute_encap_func() 70280354Sfenner * claimed). 70380354Sfenner */ 70480354Sfennerstatic void 70582884Sjulianmroute_encap_input(struct mbuf *m, int off) 70680354Sfenner{ 70780354Sfenner struct ip *ip = mtod(m, struct ip *); 70880354Sfenner int hlen = ip->ip_hl << 2; 70980354Sfenner 71080354Sfenner if (hlen > sizeof(struct ip)) 71180354Sfenner ip_stripoptions(m, (struct mbuf *) 0); 71280354Sfenner m->m_data += sizeof(struct ip); 71380354Sfenner m->m_len -= sizeof(struct ip); 71480354Sfenner m->m_pkthdr.len -= sizeof(struct ip); 71580354Sfenner 71680354Sfenner m->m_pkthdr.rcvif = last_encap_vif->v_ifp; 71780354Sfenner 71880354Sfenner (void) IF_HANDOFF(&ipintrq, m, NULL); 71980354Sfenner /* 72080354Sfenner * normally we would need a "schednetisr(NETISR_IP)" 72180354Sfenner * here but we were called by ip_input and it is going 72280354Sfenner * to loop back & try to dequeue the packet we just 72380354Sfenner * queued as soon as we return so we avoid the 72480354Sfenner * unnecessary software interrrupt. 72580354Sfenner */ 72680354Sfenner} 72780354Sfenner 72880354Sfennerextern struct domain inetdomain; 72982884Sjulianstatic struct protosw mroute_encap_protosw = 73080354Sfenner{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR, 73180354Sfenner mroute_encap_input, 0, 0, rip_ctloutput, 73280354Sfenner 0, 73380354Sfenner 0, 0, 0, 0, 73480354Sfenner &rip_usrreqs 73580354Sfenner}; 73680354Sfenner 73780354Sfenner/* 7381541Srgrimes * Add a vif to the vif table 7391541Srgrimes */ 7401541Srgrimesstatic int 7411541Srgrimesadd_vif(vifcp) 7422531Swollman register struct vifctl *vifcp; 7431541Srgrimes{ 7442531Swollman register struct vif *vifp = viftable + vifcp->vifc_vifi; 7453747Swollman static struct sockaddr_in sin = {sizeof sin, AF_INET}; 7462531Swollman struct ifaddr *ifa; 7472531Swollman struct ifnet *ifp; 7482531Swollman int error, s; 7492531Swollman struct tbf *v_tbf = tbftable + vifcp->vifc_vifi; 7501541Srgrimes 7512531Swollman if (vifcp->vifc_vifi >= MAXVIFS) return EINVAL; 7522531Swollman if (vifp->v_lcl_addr.s_addr != 0) return EADDRINUSE; 7531541Srgrimes 7542531Swollman /* Find the interface with an address in AF_INET family */ 7552531Swollman sin.sin_addr = vifcp->vifc_lcl_addr; 7562531Swollman ifa = ifa_ifwithaddr((struct sockaddr *)&sin); 7572531Swollman if (ifa == 0) return EADDRNOTAVAIL; 7582531Swollman ifp = ifa->ifa_ifp; 7591541Srgrimes 7602531Swollman if (vifcp->vifc_flags & VIFF_TUNNEL) { 7612531Swollman if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) { 7629209Swollman /* 76380354Sfenner * An encapsulating tunnel is wanted. Tell 76480354Sfenner * mroute_encap_input() to start paying attention 76580354Sfenner * to encapsulated packets. 7669209Swollman */ 76780354Sfenner if (encap_cookie == NULL) { 76880354Sfenner encap_cookie = encap_attach_func(AF_INET, -1, 76980354Sfenner mroute_encapcheck, 77080354Sfenner (struct protosw *)&mroute_encap_protosw, NULL); 77180354Sfenner 77280354Sfenner if (encap_cookie == NULL) { 77380354Sfenner printf("ip_mroute: unable to attach encap\n"); 77480354Sfenner return (EIO); /* XXX */ 77580354Sfenner } 7769209Swollman for (s = 0; s < MAXVIFS; ++s) { 7779209Swollman multicast_decap_if[s].if_name = "mdecap"; 7789209Swollman multicast_decap_if[s].if_unit = s; 7799209Swollman } 7801541Srgrimes } 7819209Swollman /* 7829209Swollman * Set interface to fake encapsulator interface 7839209Swollman */ 7849209Swollman ifp = &multicast_decap_if[vifcp->vifc_vifi]; 7859209Swollman /* 7869209Swollman * Prepare cached route entry 7879209Swollman */ 7889209Swollman bzero(&vifp->v_route, sizeof(vifp->v_route)); 7892531Swollman } else { 79011284Swollman log(LOG_ERR, "source routed tunnels not supported\n"); 7919209Swollman return EOPNOTSUPP; 7921541Srgrimes } 7932531Swollman } else { 7942531Swollman /* Make sure the interface supports multicast */ 7952531Swollman if ((ifp->if_flags & IFF_MULTICAST) == 0) 7962531Swollman return EOPNOTSUPP; 7971541Srgrimes 7982531Swollman /* Enable promiscuous reception of all IP multicasts from the if */ 7992531Swollman s = splnet(); 80022967Swollman error = if_allmulti(ifp, 1); 8012531Swollman splx(s); 8022531Swollman if (error) 8032531Swollman return error; 8042531Swollman } 8051541Srgrimes 8062531Swollman s = splnet(); 8072531Swollman /* define parameters for the tbf structure */ 8082531Swollman vifp->v_tbf = v_tbf; 80910203Swollman GET_TIME(vifp->v_tbf->tbf_last_pkt_t); 81010203Swollman vifp->v_tbf->tbf_n_tok = 0; 81110203Swollman vifp->v_tbf->tbf_q_len = 0; 81210203Swollman vifp->v_tbf->tbf_max_q_len = MAXQSIZE; 81310203Swollman vifp->v_tbf->tbf_q = vifp->v_tbf->tbf_t = NULL; 8141541Srgrimes 8152531Swollman vifp->v_flags = vifcp->vifc_flags; 8162531Swollman vifp->v_threshold = vifcp->vifc_threshold; 8172531Swollman vifp->v_lcl_addr = vifcp->vifc_lcl_addr; 8182531Swollman vifp->v_rmt_addr = vifcp->vifc_rmt_addr; 8192531Swollman vifp->v_ifp = ifp; 82010203Swollman /* scaling up here allows division by 1024 in critical code */ 82110203Swollman vifp->v_rate_limit= vifcp->vifc_rate_limit * 1024 / 1000; 8229209Swollman vifp->v_rsvp_on = 0; 8239209Swollman vifp->v_rsvpd = NULL; 8242531Swollman /* initialize per vif pkt counters */ 8252531Swollman vifp->v_pkt_in = 0; 8262531Swollman vifp->v_pkt_out = 0; 8279209Swollman vifp->v_bytes_in = 0; 8289209Swollman vifp->v_bytes_out = 0; 8292531Swollman splx(s); 8302531Swollman 8312531Swollman /* Adjust numvifs up if the vifi is higher than numvifs */ 8322531Swollman if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1; 8332531Swollman 8342531Swollman if (mrtdebug) 83538373Sbde log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x, rate %d\n", 8369209Swollman vifcp->vifc_vifi, 83738373Sbde (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr), 8382531Swollman (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask", 83938373Sbde (u_long)ntohl(vifcp->vifc_rmt_addr.s_addr), 8402531Swollman vifcp->vifc_threshold, 8419209Swollman vifcp->vifc_rate_limit); 8422531Swollman 8432531Swollman return 0; 8441541Srgrimes} 8451541Srgrimes 8461541Srgrimes/* 8471541Srgrimes * Delete a vif from the vif table 8481541Srgrimes */ 8491541Srgrimesstatic int 85038482Swollmandel_vif(vifi) 85138482Swollman vifi_t vifi; 8521541Srgrimes{ 85338482Swollman register struct vif *vifp = &viftable[vifi]; 85410203Swollman register struct mbuf *m; 8552531Swollman struct ifnet *ifp; 8562531Swollman struct ifreq ifr; 8572531Swollman int s; 8581541Srgrimes 85938482Swollman if (vifi >= numvifs) return EINVAL; 8602531Swollman if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL; 8611541Srgrimes 8622531Swollman s = splnet(); 8631541Srgrimes 8642531Swollman if (!(vifp->v_flags & VIFF_TUNNEL)) { 8652531Swollman ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; 8662531Swollman ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; 8672531Swollman ifp = vifp->v_ifp; 86821666Swollman if_allmulti(ifp, 0); 8692531Swollman } 8701541Srgrimes 8712531Swollman if (vifp == last_encap_vif) { 8722531Swollman last_encap_vif = 0; 8732531Swollman last_encap_src = 0; 8742531Swollman } 8751541Srgrimes 87610203Swollman /* 87710203Swollman * Free packets queued at the interface 87810203Swollman */ 87910203Swollman while (vifp->v_tbf->tbf_q) { 88010203Swollman m = vifp->v_tbf->tbf_q; 88110203Swollman vifp->v_tbf->tbf_q = m->m_act; 88210203Swollman m_freem(m); 88310203Swollman } 88410203Swollman 8852531Swollman bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf))); 8862531Swollman bzero((caddr_t)vifp, sizeof (*vifp)); 8871541Srgrimes 88838482Swollman if (mrtdebug) 88938482Swollman log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs); 89038482Swollman 8912531Swollman /* Adjust numvifs down */ 8922531Swollman for (vifi = numvifs; vifi > 0; vifi--) 8932531Swollman if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break; 8942531Swollman numvifs = vifi; 8952531Swollman 8962531Swollman splx(s); 8972531Swollman 8982531Swollman return 0; 8991541Srgrimes} 9001541Srgrimes 9011541Srgrimes/* 9022531Swollman * Add an mfc entry 9031541Srgrimes */ 9041541Srgrimesstatic int 9052531Swollmanadd_mfc(mfccp) 9062531Swollman struct mfcctl *mfccp; 9071541Srgrimes{ 9082531Swollman struct mfc *rt; 9092531Swollman u_long hash; 9102531Swollman struct rtdetq *rte; 9112531Swollman register u_short nstl; 9122531Swollman int s; 9132531Swollman int i; 9141541Srgrimes 9159209Swollman MFCFIND(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr, rt); 9161541Srgrimes 9172531Swollman /* If an entry already exists, just update the fields */ 9182531Swollman if (rt) { 9199209Swollman if (mrtdebug & DEBUG_MFC) 92038373Sbde log(LOG_DEBUG,"add_mfc update o %lx g %lx p %x\n", 92138373Sbde (u_long)ntohl(mfccp->mfcc_origin.s_addr), 92238373Sbde (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), 9232531Swollman mfccp->mfcc_parent); 9241541Srgrimes 9251541Srgrimes s = splnet(); 9262531Swollman rt->mfc_parent = mfccp->mfcc_parent; 9272531Swollman for (i = 0; i < numvifs; i++) 9289209Swollman rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; 9292531Swollman splx(s); 9302531Swollman return 0; 9312531Swollman } 9321541Srgrimes 9339209Swollman /* 9342531Swollman * Find the entry for which the upcall was made and update 9352531Swollman */ 9362531Swollman s = splnet(); 9379209Swollman hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr); 93842777Sfenner for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) { 9391541Srgrimes 9409209Swollman if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && 9412531Swollman (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) && 94242777Sfenner (rt->mfc_stall != NULL)) { 9439209Swollman 9449209Swollman if (nstl++) 94538373Sbde log(LOG_ERR, "add_mfc %s o %lx g %lx p %x dbx %p\n", 9469209Swollman "multiple kernel entries", 94738373Sbde (u_long)ntohl(mfccp->mfcc_origin.s_addr), 94838373Sbde (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), 94942777Sfenner mfccp->mfcc_parent, (void *)rt->mfc_stall); 9501541Srgrimes 9519209Swollman if (mrtdebug & DEBUG_MFC) 95238373Sbde log(LOG_DEBUG,"add_mfc o %lx g %lx p %x dbg %p\n", 95338373Sbde (u_long)ntohl(mfccp->mfcc_origin.s_addr), 95438373Sbde (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), 95542777Sfenner mfccp->mfcc_parent, (void *)rt->mfc_stall); 9561541Srgrimes 9579209Swollman rt->mfc_origin = mfccp->mfcc_origin; 9589209Swollman rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; 9599209Swollman rt->mfc_parent = mfccp->mfcc_parent; 9609209Swollman for (i = 0; i < numvifs; i++) 9619209Swollman rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; 9629209Swollman /* initialize pkt counters per src-grp */ 9639209Swollman rt->mfc_pkt_cnt = 0; 9649209Swollman rt->mfc_byte_cnt = 0; 9659209Swollman rt->mfc_wrong_if = 0; 9669209Swollman rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; 9672531Swollman 9689209Swollman rt->mfc_expire = 0; /* Don't clean this guy up */ 9699209Swollman nexpire[hash]--; 9702531Swollman 9712531Swollman /* free packets Qed at the end of this entry */ 97242777Sfenner for (rte = rt->mfc_stall; rte != NULL; ) { 97342777Sfenner struct rtdetq *n = rte->next; 97442777Sfenner 9759209Swollman ip_mdq(rte->m, rte->ifp, rt, -1); 9762531Swollman m_freem(rte->m); 9779209Swollman#ifdef UPCALL_TIMING 9789209Swollman collate(&(rte->t)); 9799209Swollman#endif /* UPCALL_TIMING */ 98042777Sfenner free(rte, M_MRTABLE); 98142777Sfenner rte = n; 9822531Swollman } 98342777Sfenner rt->mfc_stall = NULL; 9841541Srgrimes } 9852531Swollman } 9861541Srgrimes 9872531Swollman /* 9882531Swollman * It is possible that an entry is being inserted without an upcall 9892531Swollman */ 9902531Swollman if (nstl == 0) { 9919209Swollman if (mrtdebug & DEBUG_MFC) 99238373Sbde log(LOG_DEBUG,"add_mfc no upcall h %lu o %lx g %lx p %x\n", 99338373Sbde hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr), 99438373Sbde (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), 9952531Swollman mfccp->mfcc_parent); 9969209Swollman 99742777Sfenner for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) { 9989209Swollman 9999209Swollman if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && 10002531Swollman (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) { 10011541Srgrimes 10022531Swollman rt->mfc_origin = mfccp->mfcc_origin; 10032531Swollman rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; 10042531Swollman rt->mfc_parent = mfccp->mfcc_parent; 10052531Swollman for (i = 0; i < numvifs; i++) 10069209Swollman rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; 10072531Swollman /* initialize pkt counters per src-grp */ 10082531Swollman rt->mfc_pkt_cnt = 0; 10099209Swollman rt->mfc_byte_cnt = 0; 10109209Swollman rt->mfc_wrong_if = 0; 10119209Swollman rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; 10129209Swollman if (rt->mfc_expire) 10139209Swollman nexpire[hash]--; 10149209Swollman rt->mfc_expire = 0; 10152531Swollman } 10162531Swollman } 101742777Sfenner if (rt == NULL) { 10182531Swollman /* no upcall, so make a new entry */ 101942777Sfenner rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT); 102042777Sfenner if (rt == NULL) { 10212531Swollman splx(s); 10222531Swollman return ENOBUFS; 10232531Swollman } 10249209Swollman 10252531Swollman /* insert new entry at head of hash chain */ 10262531Swollman rt->mfc_origin = mfccp->mfcc_origin; 10272531Swollman rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; 10282531Swollman rt->mfc_parent = mfccp->mfcc_parent; 10292531Swollman for (i = 0; i < numvifs; i++) 10309209Swollman rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; 10312531Swollman /* initialize pkt counters per src-grp */ 10322531Swollman rt->mfc_pkt_cnt = 0; 10339209Swollman rt->mfc_byte_cnt = 0; 10349209Swollman rt->mfc_wrong_if = 0; 10359209Swollman rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; 10369209Swollman rt->mfc_expire = 0; 103742777Sfenner rt->mfc_stall = NULL; 10389209Swollman 10392531Swollman /* link into table */ 104042777Sfenner rt->mfc_next = mfctable[hash]; 104142777Sfenner mfctable[hash] = rt; 10422531Swollman } 10432531Swollman } 10442531Swollman splx(s); 10452531Swollman return 0; 10461541Srgrimes} 10471541Srgrimes 10489209Swollman#ifdef UPCALL_TIMING 10491541Srgrimes/* 10509209Swollman * collect delay statistics on the upcalls 10519209Swollman */ 10529209Swollmanstatic void collate(t) 10539209Swollmanregister struct timeval *t; 10549209Swollman{ 10559209Swollman register u_long d; 10569209Swollman register struct timeval tp; 10579209Swollman register u_long delta; 10589209Swollman 10599209Swollman GET_TIME(tp); 10609209Swollman 10619209Swollman if (TV_LT(*t, tp)) 10629209Swollman { 10639209Swollman TV_DELTA(tp, *t, delta); 10649209Swollman 10659209Swollman d = delta >> 10; 10669209Swollman if (d > 50) 10679209Swollman d = 50; 10689209Swollman 10699209Swollman ++upcall_data[d]; 10709209Swollman } 10719209Swollman} 10729209Swollman#endif /* UPCALL_TIMING */ 10739209Swollman 10749209Swollman/* 10752531Swollman * Delete an mfc entry 10761541Srgrimes */ 10771541Srgrimesstatic int 10782531Swollmandel_mfc(mfccp) 10799209Swollman struct mfcctl *mfccp; 10801541Srgrimes{ 10812531Swollman struct in_addr origin; 10822531Swollman struct in_addr mcastgrp; 10832531Swollman struct mfc *rt; 108442777Sfenner struct mfc **nptr; 10852531Swollman u_long hash; 108611921Sphk int s; 10871541Srgrimes 10882531Swollman origin = mfccp->mfcc_origin; 10892531Swollman mcastgrp = mfccp->mfcc_mcastgrp; 10909209Swollman hash = MFCHASH(origin.s_addr, mcastgrp.s_addr); 10911541Srgrimes 10929209Swollman if (mrtdebug & DEBUG_MFC) 109338373Sbde log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n", 109438373Sbde (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr)); 10951541Srgrimes 10969209Swollman s = splnet(); 10979209Swollman 10989209Swollman nptr = &mfctable[hash]; 109942777Sfenner while ((rt = *nptr) != NULL) { 11002531Swollman if (origin.s_addr == rt->mfc_origin.s_addr && 11012531Swollman mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr && 110242777Sfenner rt->mfc_stall == NULL) 11032531Swollman break; 11049209Swollman 110542777Sfenner nptr = &rt->mfc_next; 11062531Swollman } 110742777Sfenner if (rt == NULL) { 11089209Swollman splx(s); 11099209Swollman return EADDRNOTAVAIL; 11102531Swollman } 11111541Srgrimes 111242777Sfenner *nptr = rt->mfc_next; 111342777Sfenner free(rt, M_MRTABLE); 11141541Srgrimes 11152531Swollman splx(s); 11162531Swollman 11172531Swollman return 0; 11181541Srgrimes} 11191541Srgrimes 11201541Srgrimes/* 11219209Swollman * Send a message to mrouted on the multicast routing socket 11229209Swollman */ 11239209Swollmanstatic int 11249209Swollmansocket_send(s, mm, src) 11259209Swollman struct socket *s; 11269209Swollman struct mbuf *mm; 11279209Swollman struct sockaddr_in *src; 11289209Swollman{ 11299209Swollman if (s) { 11309209Swollman if (sbappendaddr(&s->so_rcv, 11319209Swollman (struct sockaddr *)src, 11329209Swollman mm, (struct mbuf *)0) != 0) { 11339209Swollman sorwakeup(s); 11349209Swollman return 0; 11359209Swollman } 11369209Swollman } 11379209Swollman m_freem(mm); 11389209Swollman return -1; 11399209Swollman} 11409209Swollman 11419209Swollman/* 11422531Swollman * IP multicast forwarding function. This function assumes that the packet 11432531Swollman * pointed to by "ip" has arrived on (or is about to be sent to) the interface 11442531Swollman * pointed to by "ifp", and the packet is to be relayed to other networks 11452531Swollman * that have members of the packet's destination IP multicast group. 11462531Swollman * 11479209Swollman * The packet is returned unscathed to the caller, unless it is 11489209Swollman * erroneous, in which case a non-zero return value tells the caller to 11492531Swollman * discard it. 11501541Srgrimes */ 11512531Swollman 11522531Swollman#define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */ 11532531Swollman 115412296Sphkstatic int 11552763SwollmanX_ip_mforward(ip, ifp, m, imo) 11562531Swollman register struct ip *ip; 11572531Swollman struct ifnet *ifp; 11582754Swollman struct mbuf *m; 11592531Swollman struct ip_moptions *imo; 11601541Srgrimes{ 116114549Sfenner register struct mfc *rt; 11622531Swollman register u_char *ipoptions; 11633747Swollman static struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET }; 11649209Swollman static int srctun = 0; 11652531Swollman register struct mbuf *mm; 11662531Swollman int s; 11679209Swollman vifi_t vifi; 11689209Swollman struct vif *vifp; 11691541Srgrimes 11709209Swollman if (mrtdebug & DEBUG_FORWARD) 117138373Sbde log(LOG_DEBUG, "ip_mforward: src %lx, dst %lx, ifp %p\n", 117238373Sbde (u_long)ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr), 117338373Sbde (void *)ifp); 11741541Srgrimes 117580354Sfenner if (ip->ip_hl < (sizeof(struct ip) + TUNNEL_LEN) >> 2 || 11762531Swollman (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) { 11772531Swollman /* 11789209Swollman * Packet arrived via a physical interface or 11799209Swollman * an encapsulated tunnel. 11802531Swollman */ 11812531Swollman } else { 11822531Swollman /* 11832531Swollman * Packet arrived through a source-route tunnel. 11849209Swollman * Source-route tunnels are no longer supported. 11852531Swollman */ 11869209Swollman if ((srctun++ % 1000) == 0) 118738373Sbde log(LOG_ERR, 118838373Sbde "ip_mforward: received source-routed packet from %lx\n", 118938373Sbde (u_long)ntohl(ip->ip_src.s_addr)); 11908876Srgrimes 11919209Swollman return 1; 11929209Swollman } 11939209Swollman 11949209Swollman if ((imo) && ((vifi = imo->imo_multicast_vif) < numvifs)) { 11959209Swollman if (ip->ip_ttl < 255) 11969209Swollman ip->ip_ttl++; /* compensate for -1 in *_send routines */ 11979209Swollman if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { 11989209Swollman vifp = viftable + vifi; 119912296Sphk printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s%d)\n", 120085658Sdillon (long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr), 120185658Sdillon vifi, 12029209Swollman (vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "", 12039209Swollman vifp->v_ifp->if_name, vifp->v_ifp->if_unit); 12042531Swollman } 120514549Sfenner return (ip_mdq(m, ifp, NULL, vifi)); 12062531Swollman } 12079209Swollman if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { 120812296Sphk printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n", 120985658Sdillon (long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr)); 12109728Swollman if(!imo) 12119728Swollman printf("In fact, no options were specified at all\n"); 12129209Swollman } 12132531Swollman 12142531Swollman /* 12152531Swollman * Don't forward a packet with time-to-live of zero or one, 12162531Swollman * or a packet destined to a local-only group. 12172531Swollman */ 12182531Swollman if (ip->ip_ttl <= 1 || 12192531Swollman ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP) 12209209Swollman return 0; 12212531Swollman 12222531Swollman /* 12232531Swollman * Determine forwarding vifs from the forwarding cache table 12242531Swollman */ 12252531Swollman s = splnet(); 12262531Swollman MFCFIND(ip->ip_src.s_addr, ip->ip_dst.s_addr, rt); 12272531Swollman 12282531Swollman /* Entry exists, so forward if necessary */ 12292531Swollman if (rt != NULL) { 12301541Srgrimes splx(s); 12319209Swollman return (ip_mdq(m, ifp, rt, -1)); 12329209Swollman } else { 12332531Swollman /* 12342531Swollman * If we don't have a route for packet's origin, 12352531Swollman * Make a copy of the packet & 12362531Swollman * send message to routing daemon 12372531Swollman */ 12382531Swollman 12392531Swollman register struct mbuf *mb0; 12402531Swollman register struct rtdetq *rte; 12412531Swollman register u_long hash; 124214549Sfenner int hlen = ip->ip_hl << 2; 12439209Swollman#ifdef UPCALL_TIMING 12449209Swollman struct timeval tp; 12452531Swollman 12469209Swollman GET_TIME(tp); 12479209Swollman#endif 12489209Swollman 12492531Swollman mrtstat.mrts_no_route++; 12509209Swollman if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)) 125138373Sbde log(LOG_DEBUG, "ip_mforward: no rte s %lx g %lx\n", 125238373Sbde (u_long)ntohl(ip->ip_src.s_addr), 125338373Sbde (u_long)ntohl(ip->ip_dst.s_addr)); 12542531Swollman 12559209Swollman /* 12569209Swollman * Allocate mbufs early so that we don't do extra work if we are 125714549Sfenner * just going to fail anyway. Make sure to pullup the header so 125814549Sfenner * that other people can't step on it. 12599209Swollman */ 126042777Sfenner rte = (struct rtdetq *)malloc((sizeof *rte), M_MRTABLE, M_NOWAIT); 126142777Sfenner if (rte == NULL) { 12629209Swollman splx(s); 12639209Swollman return ENOBUFS; 12649209Swollman } 12659209Swollman mb0 = m_copy(m, 0, M_COPYALL); 126614549Sfenner if (mb0 && (M_HASCL(mb0) || mb0->m_len < hlen)) 126714549Sfenner mb0 = m_pullup(mb0, hlen); 12689209Swollman if (mb0 == NULL) { 126942777Sfenner free(rte, M_MRTABLE); 12709209Swollman splx(s); 12719209Swollman return ENOBUFS; 12729209Swollman } 12739209Swollman 12742531Swollman /* is there an upcall waiting for this packet? */ 12759209Swollman hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr); 127642777Sfenner for (rt = mfctable[hash]; rt; rt = rt->mfc_next) { 12779209Swollman if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) && 12782531Swollman (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) && 127942777Sfenner (rt->mfc_stall != NULL)) 12802531Swollman break; 12812531Swollman } 12822531Swollman 128342777Sfenner if (rt == NULL) { 12849209Swollman int i; 12859209Swollman struct igmpmsg *im; 12869209Swollman 12872531Swollman /* no upcall, so make a new entry */ 128842777Sfenner rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT); 128942777Sfenner if (rt == NULL) { 129042777Sfenner free(rte, M_MRTABLE); 12919266Swollman m_freem(mb0); 12922531Swollman splx(s); 12932531Swollman return ENOBUFS; 12942531Swollman } 12959209Swollman /* Make a copy of the header to send to the user level process */ 129617137Sfenner mm = m_copy(mb0, 0, hlen); 12979209Swollman if (mm == NULL) { 129842777Sfenner free(rte, M_MRTABLE); 12999266Swollman m_freem(mb0); 130042777Sfenner free(rt, M_MRTABLE); 13019209Swollman splx(s); 13029209Swollman return ENOBUFS; 13039209Swollman } 13042531Swollman 13059209Swollman /* 13069209Swollman * Send message to routing daemon to install 13079209Swollman * a route into the kernel table 13089209Swollman */ 13099209Swollman k_igmpsrc.sin_addr = ip->ip_src; 13109209Swollman 13119209Swollman im = mtod(mm, struct igmpmsg *); 13129209Swollman im->im_msgtype = IGMPMSG_NOCACHE; 13139209Swollman im->im_mbz = 0; 13149209Swollman 13159209Swollman mrtstat.mrts_upcalls++; 13169209Swollman 13179209Swollman if (socket_send(ip_mrouter, mm, &k_igmpsrc) < 0) { 131811284Swollman log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n"); 13199209Swollman ++mrtstat.mrts_upq_sockfull; 132042777Sfenner free(rte, M_MRTABLE); 13219266Swollman m_freem(mb0); 132242777Sfenner free(rt, M_MRTABLE); 13239209Swollman splx(s); 13249209Swollman return ENOBUFS; 13259209Swollman } 13269209Swollman 13272531Swollman /* insert new entry at head of hash chain */ 13282531Swollman rt->mfc_origin.s_addr = ip->ip_src.s_addr; 13292531Swollman rt->mfc_mcastgrp.s_addr = ip->ip_dst.s_addr; 13309209Swollman rt->mfc_expire = UPCALL_EXPIRE; 13319209Swollman nexpire[hash]++; 13329209Swollman for (i = 0; i < numvifs; i++) 13339209Swollman rt->mfc_ttls[i] = 0; 13349209Swollman rt->mfc_parent = -1; 13352531Swollman 13362531Swollman /* link into table */ 133742777Sfenner rt->mfc_next = mfctable[hash]; 133842777Sfenner mfctable[hash] = rt; 133942777Sfenner rt->mfc_stall = rte; 13402531Swollman 13419209Swollman } else { 13429209Swollman /* determine if q has overflowed */ 134342777Sfenner int npkts = 0; 134442777Sfenner struct rtdetq **p; 134542777Sfenner 134642777Sfenner for (p = &rt->mfc_stall; *p != NULL; p = &(*p)->next) 13479209Swollman npkts++; 13482531Swollman 13499209Swollman if (npkts > MAX_UPQ) { 13509209Swollman mrtstat.mrts_upq_ovflw++; 135142777Sfenner free(rte, M_MRTABLE); 13529266Swollman m_freem(mb0); 13539209Swollman splx(s); 13549209Swollman return 0; 13559209Swollman } 135642777Sfenner 135742777Sfenner /* Add this entry to the end of the queue */ 135842777Sfenner *p = rte; 13592531Swollman } 13602531Swollman 13612531Swollman rte->m = mb0; 13622531Swollman rte->ifp = ifp; 13639209Swollman#ifdef UPCALL_TIMING 13649209Swollman rte->t = tp; 13659209Swollman#endif 136642777Sfenner rte->next = NULL; 13672531Swollman 13682531Swollman splx(s); 13692531Swollman 13702531Swollman return 0; 13719209Swollman } 13721541Srgrimes} 13731541Srgrimes 137480354Sfenner#ifndef MROUTE_KLD 13752754Swollmanint (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, 13762763Swollman struct ip_moptions *) = X_ip_mforward; 13772763Swollman#endif 13782754Swollman 13791541Srgrimes/* 13802531Swollman * Clean up the cache entry if upcall is not serviced 13811541Srgrimes */ 13822531Swollmanstatic void 13839209Swollmanexpire_upcalls(void *unused) 13841541Srgrimes{ 13852531Swollman struct rtdetq *rte; 138642777Sfenner struct mfc *mfc, **nptr; 13879209Swollman int i; 13882531Swollman int s; 13891541Srgrimes 13902531Swollman s = splnet(); 13919209Swollman for (i = 0; i < MFCTBLSIZ; i++) { 13929209Swollman if (nexpire[i] == 0) 13939209Swollman continue; 13949209Swollman nptr = &mfctable[i]; 139542777Sfenner for (mfc = *nptr; mfc != NULL; mfc = *nptr) { 13969209Swollman /* 13979209Swollman * Skip real cache entries 13989209Swollman * Make sure it wasn't marked to not expire (shouldn't happen) 13999209Swollman * If it expires now 14009209Swollman */ 140142777Sfenner if (mfc->mfc_stall != NULL && 14029209Swollman mfc->mfc_expire != 0 && 14039209Swollman --mfc->mfc_expire == 0) { 14049209Swollman if (mrtdebug & DEBUG_EXPIRE) 140538373Sbde log(LOG_DEBUG, "expire_upcalls: expiring (%lx %lx)\n", 140638373Sbde (u_long)ntohl(mfc->mfc_origin.s_addr), 140738373Sbde (u_long)ntohl(mfc->mfc_mcastgrp.s_addr)); 14089209Swollman /* 14099209Swollman * drop all the packets 14109209Swollman * free the mbuf with the pkt, if, timing info 14119209Swollman */ 141242777Sfenner for (rte = mfc->mfc_stall; rte; ) { 141342777Sfenner struct rtdetq *n = rte->next; 141442777Sfenner 14159209Swollman m_freem(rte->m); 141642777Sfenner free(rte, M_MRTABLE); 141742777Sfenner rte = n; 14189209Swollman } 14199209Swollman ++mrtstat.mrts_cache_cleanups; 14209209Swollman nexpire[i]--; 14212531Swollman 142242777Sfenner *nptr = mfc->mfc_next; 142342777Sfenner free(mfc, M_MRTABLE); 14249209Swollman } else { 142542777Sfenner nptr = &mfc->mfc_next; 14269209Swollman } 14279209Swollman } 14282531Swollman } 14292531Swollman splx(s); 143029681Sgibbs expire_upcalls_ch = timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT); 14311541Srgrimes} 14321541Srgrimes 14331541Srgrimes/* 14342531Swollman * Packet forwarding routine once entry in the cache is made 14351541Srgrimes */ 14361541Srgrimesstatic int 14379209Swollmanip_mdq(m, ifp, rt, xmt_vif) 14382531Swollman register struct mbuf *m; 14392531Swollman register struct ifnet *ifp; 14402531Swollman register struct mfc *rt; 14419209Swollman register vifi_t xmt_vif; 14421541Srgrimes{ 14432531Swollman register struct ip *ip = mtod(m, struct ip *); 14442531Swollman register vifi_t vifi; 14452531Swollman register struct vif *vifp; 144637288Sphk register int plen = ip->ip_len; 14471541Srgrimes 14489209Swollman/* 14499209Swollman * Macro to send packet on vif. Since RSVP packets don't get counted on 14509209Swollman * input, they shouldn't get counted on output, so statistics keeping is 145172091Sasmodai * separate. 14529209Swollman */ 14539209Swollman#define MC_SEND(ip,vifp,m) { \ 14549209Swollman if ((vifp)->v_flags & VIFF_TUNNEL) \ 14559209Swollman encap_send((ip), (vifp), (m)); \ 14569209Swollman else \ 14579209Swollman phyint_send((ip), (vifp), (m)); \ 14589209Swollman} 14599209Swollman 14602531Swollman /* 14619209Swollman * If xmt_vif is not -1, send on only the requested vif. 14629209Swollman * 14639209Swollman * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.) 14649209Swollman */ 14659209Swollman if (xmt_vif < numvifs) { 14669209Swollman MC_SEND(ip, viftable + xmt_vif, m); 14679209Swollman return 1; 14689209Swollman } 14699209Swollman 14709209Swollman /* 14712531Swollman * Don't forward if it didn't arrive from the parent vif for its origin. 14722531Swollman */ 14732531Swollman vifi = rt->mfc_parent; 14749209Swollman if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) { 14752531Swollman /* came in the wrong interface */ 14769209Swollman if (mrtdebug & DEBUG_FORWARD) 147738373Sbde log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n", 147838373Sbde (void *)ifp, vifi, (void *)viftable[vifi].v_ifp); 14792531Swollman ++mrtstat.mrts_wrong_if; 14809209Swollman ++rt->mfc_wrong_if; 14819209Swollman /* 14829209Swollman * If we are doing PIM assert processing, and we are forwarding 14839209Swollman * packets on this interface, and it is a broadcast medium 14849209Swollman * interface (and not a tunnel), send a message to the routing daemon. 14859209Swollman */ 14869209Swollman if (pim_assert && rt->mfc_ttls[vifi] && 14879209Swollman (ifp->if_flags & IFF_BROADCAST) && 14889209Swollman !(viftable[vifi].v_flags & VIFF_TUNNEL)) { 14899209Swollman struct sockaddr_in k_igmpsrc; 14909209Swollman struct mbuf *mm; 14919209Swollman struct igmpmsg *im; 14929209Swollman int hlen = ip->ip_hl << 2; 14939209Swollman struct timeval now; 14949209Swollman register u_long delta; 14959209Swollman 14969209Swollman GET_TIME(now); 14979209Swollman 14989209Swollman TV_DELTA(rt->mfc_last_assert, now, delta); 14999209Swollman 15009209Swollman if (delta > ASSERT_MSG_TIME) { 15019209Swollman mm = m_copy(m, 0, hlen); 15029209Swollman if (mm && (M_HASCL(mm) || mm->m_len < hlen)) 15039209Swollman mm = m_pullup(mm, hlen); 15049209Swollman if (mm == NULL) { 15059209Swollman return ENOBUFS; 15069209Swollman } 15079209Swollman 15089209Swollman rt->mfc_last_assert = now; 15099209Swollman 15109209Swollman im = mtod(mm, struct igmpmsg *); 15119209Swollman im->im_msgtype = IGMPMSG_WRONGVIF; 15129209Swollman im->im_mbz = 0; 15139209Swollman im->im_vif = vifi; 15149209Swollman 15159209Swollman k_igmpsrc.sin_addr = im->im_src; 15169209Swollman 15179334Swollman socket_send(ip_mrouter, mm, &k_igmpsrc); 15189209Swollman } 15199209Swollman } 15209209Swollman return 0; 15212531Swollman } 15221541Srgrimes 15239209Swollman /* If I sourced this packet, it counts as output, else it was input. */ 15249209Swollman if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) { 15259209Swollman viftable[vifi].v_pkt_out++; 15269209Swollman viftable[vifi].v_bytes_out += plen; 15279209Swollman } else { 15289209Swollman viftable[vifi].v_pkt_in++; 15299209Swollman viftable[vifi].v_bytes_in += plen; 15309209Swollman } 15312531Swollman rt->mfc_pkt_cnt++; 15329209Swollman rt->mfc_byte_cnt += plen; 15331541Srgrimes 15342531Swollman /* 15352531Swollman * For each vif, decide if a copy of the packet should be forwarded. 15362531Swollman * Forward if: 15372531Swollman * - the ttl exceeds the vif's threshold 15382531Swollman * - there are group members downstream on interface 15392531Swollman */ 15402531Swollman for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++) 15412531Swollman if ((rt->mfc_ttls[vifi] > 0) && 15429209Swollman (ip->ip_ttl > rt->mfc_ttls[vifi])) { 15439209Swollman vifp->v_pkt_out++; 15449209Swollman vifp->v_bytes_out += plen; 15452531Swollman MC_SEND(ip, vifp, m); 15469209Swollman } 15472531Swollman 15482531Swollman return 0; 15491541Srgrimes} 15501541Srgrimes 15519209Swollman/* 15529209Swollman * check if a vif number is legal/ok. This is used by ip_output, to export 15539209Swollman * numvifs there, 15541541Srgrimes */ 155512296Sphkstatic int 15562763SwollmanX_legal_vif_num(vif) 15572531Swollman int vif; 15589209Swollman{ 15599209Swollman if (vif >= 0 && vif < numvifs) 15602531Swollman return(1); 15612531Swollman else 15622531Swollman return(0); 15632531Swollman} 15642531Swollman 156580354Sfenner#ifndef MROUTE_KLD 15662763Swollmanint (*legal_vif_num)(int) = X_legal_vif_num; 15672763Swollman#endif 15682754Swollman 15699209Swollman/* 15709209Swollman * Return the local address used by this vif 15719209Swollman */ 157212296Sphkstatic u_long 15739209SwollmanX_ip_mcast_src(vifi) 15749209Swollman int vifi; 15759209Swollman{ 15769209Swollman if (vifi >= 0 && vifi < numvifs) 15779209Swollman return viftable[vifi].v_lcl_addr.s_addr; 15789209Swollman else 15799209Swollman return INADDR_ANY; 15809209Swollman} 15819209Swollman 158280354Sfenner#ifndef MROUTE_KLD 15839209Swollmanu_long (*ip_mcast_src)(int) = X_ip_mcast_src; 15849209Swollman#endif 15859209Swollman 15862531Swollmanstatic void 15872531Swollmanphyint_send(ip, vifp, m) 15882531Swollman struct ip *ip; 15892531Swollman struct vif *vifp; 15902531Swollman struct mbuf *m; 15911541Srgrimes{ 15922531Swollman register struct mbuf *mb_copy; 15939209Swollman register int hlen = ip->ip_hl << 2; 15941541Srgrimes 15953571Swollman /* 15969209Swollman * Make a new reference to the packet; make sure that 15979209Swollman * the IP header is actually copied, not just referenced, 15989209Swollman * so that ip_output() only scribbles on the copy. 15993571Swollman */ 16009209Swollman mb_copy = m_copy(m, 0, M_COPYALL); 16019209Swollman if (mb_copy && (M_HASCL(mb_copy) || mb_copy->m_len < hlen)) 16029209Swollman mb_copy = m_pullup(mb_copy, hlen); 16033571Swollman if (mb_copy == NULL) 16049209Swollman return; 16053571Swollman 160642777Sfenner if (vifp->v_rate_limit == 0) 160710203Swollman tbf_send_packet(vifp, mb_copy); 16082531Swollman else 160910203Swollman tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len); 16102531Swollman} 16111541Srgrimes 16122531Swollmanstatic void 16132531Swollmanencap_send(ip, vifp, m) 16142531Swollman register struct ip *ip; 16152531Swollman register struct vif *vifp; 16162531Swollman register struct mbuf *m; 16171541Srgrimes{ 16182531Swollman register struct mbuf *mb_copy; 16192531Swollman register struct ip *ip_copy; 16202531Swollman register int i, len = ip->ip_len; 16211541Srgrimes 16222531Swollman /* 162335256Sdes * copy the old packet & pullup its IP header into the 16242531Swollman * new mbuf so we can modify it. Try to fill the new 16252531Swollman * mbuf since if we don't the ethernet driver will. 16262531Swollman */ 162719940Sfenner MGETHDR(mb_copy, M_DONTWAIT, MT_HEADER); 16282531Swollman if (mb_copy == NULL) 16292531Swollman return; 163019940Sfenner mb_copy->m_data += max_linkhdr; 16312531Swollman mb_copy->m_len = sizeof(multicast_encap_iphdr); 16321541Srgrimes 16332531Swollman if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == NULL) { 16342531Swollman m_freem(mb_copy); 16352531Swollman return; 16362531Swollman } 16372531Swollman i = MHLEN - M_LEADINGSPACE(mb_copy); 16382531Swollman if (i > len) 16392531Swollman i = len; 16402531Swollman mb_copy = m_pullup(mb_copy, i); 16412531Swollman if (mb_copy == NULL) 16422531Swollman return; 16433571Swollman mb_copy->m_pkthdr.len = len + sizeof(multicast_encap_iphdr); 16441541Srgrimes 16452531Swollman /* 16462531Swollman * fill in the encapsulating IP header. 16472531Swollman */ 16482531Swollman ip_copy = mtod(mb_copy, struct ip *); 16492531Swollman *ip_copy = multicast_encap_iphdr; 165077574Skris#ifdef RANDOM_IP_ID 165177574Skris ip_copy->ip_id = ip_randomid(); 165277574Skris#else 165365837Sru ip_copy->ip_id = htons(ip_id++); 165477574Skris#endif 16552531Swollman ip_copy->ip_len += len; 16562531Swollman ip_copy->ip_src = vifp->v_lcl_addr; 16572531Swollman ip_copy->ip_dst = vifp->v_rmt_addr; 16581541Srgrimes 16592531Swollman /* 16602531Swollman * turn the encapsulated IP header back into a valid one. 16612531Swollman */ 16622531Swollman ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr)); 16632531Swollman --ip->ip_ttl; 16642531Swollman HTONS(ip->ip_len); 16652531Swollman HTONS(ip->ip_off); 16662531Swollman ip->ip_sum = 0; 16672531Swollman mb_copy->m_data += sizeof(multicast_encap_iphdr); 16682531Swollman ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2); 16692531Swollman mb_copy->m_data -= sizeof(multicast_encap_iphdr); 16702531Swollman 167142777Sfenner if (vifp->v_rate_limit == 0) 167210203Swollman tbf_send_packet(vifp, mb_copy); 16732531Swollman else 167410203Swollman tbf_control(vifp, mb_copy, ip, ip_copy->ip_len); 16751541Srgrimes} 16761541Srgrimes 16771541Srgrimes/* 16782531Swollman * Token bucket filter module 16792531Swollman */ 168010203Swollman 16819209Swollmanstatic void 168210203Swollmantbf_control(vifp, m, ip, p_len) 16832531Swollman register struct vif *vifp; 16841541Srgrimes register struct mbuf *m; 16852531Swollman register struct ip *ip; 16862531Swollman register u_long p_len; 16871541Srgrimes{ 168810203Swollman register struct tbf *t = vifp->v_tbf; 168910203Swollman 169010203Swollman if (p_len > MAX_BKT_SIZE) { 169110203Swollman /* drop if packet is too large */ 169210203Swollman mrtstat.mrts_pkt2large++; 169310203Swollman m_freem(m); 169410203Swollman return; 169510203Swollman } 169610203Swollman 16972531Swollman tbf_update_tokens(vifp); 16981541Srgrimes 16999209Swollman /* if there are enough tokens, 17002531Swollman * and the queue is empty, 17012531Swollman * send this packet out 17022531Swollman */ 17032531Swollman 170410203Swollman if (t->tbf_q_len == 0) { 170510203Swollman /* queue empty, send packet if enough tokens */ 170610203Swollman if (p_len <= t->tbf_n_tok) { 170710203Swollman t->tbf_n_tok -= p_len; 170810203Swollman tbf_send_packet(vifp, m); 17091541Srgrimes } else { 17102531Swollman /* queue packet and timeout till later */ 171110203Swollman tbf_queue(vifp, m); 171210203Swollman timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS); 17132531Swollman } 171410203Swollman } else if (t->tbf_q_len < t->tbf_max_q_len) { 17152531Swollman /* finite queue length, so queue pkts and process queue */ 171610203Swollman tbf_queue(vifp, m); 17172531Swollman tbf_process_q(vifp); 17182531Swollman } else { 17192531Swollman /* queue length too much, try to dq and queue and process */ 17202531Swollman if (!tbf_dq_sel(vifp, ip)) { 17212531Swollman mrtstat.mrts_q_overflow++; 17222531Swollman m_freem(m); 17232531Swollman return; 17242531Swollman } else { 172510203Swollman tbf_queue(vifp, m); 17262531Swollman tbf_process_q(vifp); 17272531Swollman } 17282531Swollman } 17292531Swollman return; 17302531Swollman} 17311541Srgrimes 17329209Swollman/* 17332531Swollman * adds a packet to the queue at the interface 17342531Swollman */ 17359209Swollmanstatic void 173610203Swollmantbf_queue(vifp, m) 17372531Swollman register struct vif *vifp; 17382531Swollman register struct mbuf *m; 17392531Swollman{ 17402531Swollman register int s = splnet(); 174110203Swollman register struct tbf *t = vifp->v_tbf; 17421541Srgrimes 174310203Swollman if (t->tbf_t == NULL) { 174410203Swollman /* Queue was empty */ 174510203Swollman t->tbf_q = m; 174610203Swollman } else { 174710203Swollman /* Insert at tail */ 174810203Swollman t->tbf_t->m_act = m; 174910203Swollman } 17501541Srgrimes 175110203Swollman /* Set new tail pointer */ 175210203Swollman t->tbf_t = m; 17531541Srgrimes 175410203Swollman#ifdef DIAGNOSTIC 175510203Swollman /* Make sure we didn't get fed a bogus mbuf */ 175610203Swollman if (m->m_act) 175710203Swollman panic("tbf_queue: m_act"); 175810203Swollman#endif 175910203Swollman m->m_act = NULL; 176010203Swollman 176110203Swollman t->tbf_q_len++; 176210203Swollman 17632531Swollman splx(s); 17642531Swollman} 17651541Srgrimes 17661541Srgrimes 17679209Swollman/* 17682531Swollman * processes the queue at the interface 17692531Swollman */ 17709209Swollmanstatic void 17712531Swollmantbf_process_q(vifp) 17722531Swollman register struct vif *vifp; 17732531Swollman{ 177410203Swollman register struct mbuf *m; 177510203Swollman register int len; 17762531Swollman register int s = splnet(); 177710203Swollman register struct tbf *t = vifp->v_tbf; 17781541Srgrimes 17792531Swollman /* loop through the queue at the interface and send as many packets 17802531Swollman * as possible 17812531Swollman */ 178210203Swollman while (t->tbf_q_len > 0) { 178310203Swollman m = t->tbf_q; 17842531Swollman 178510203Swollman len = mtod(m, struct ip *)->ip_len; 178610203Swollman 17872531Swollman /* determine if the packet can be sent */ 178810203Swollman if (len <= t->tbf_n_tok) { 17892531Swollman /* if so, 179010203Swollman * reduce no of tokens, dequeue the packet, 17912531Swollman * send the packet. 17922531Swollman */ 179310203Swollman t->tbf_n_tok -= len; 17942531Swollman 179510203Swollman t->tbf_q = m->m_act; 179610203Swollman if (--t->tbf_q_len == 0) 179710203Swollman t->tbf_t = NULL; 17982531Swollman 179910203Swollman m->m_act = NULL; 180010203Swollman tbf_send_packet(vifp, m); 18012531Swollman 18022531Swollman } else break; 18032531Swollman } 18042531Swollman splx(s); 18051541Srgrimes} 18061541Srgrimes 18079209Swollmanstatic void 18082531Swollmantbf_reprocess_q(xvifp) 18092531Swollman void *xvifp; 18101541Srgrimes{ 18112531Swollman register struct vif *vifp = xvifp; 18129209Swollman if (ip_mrouter == NULL) 18132531Swollman return; 18141541Srgrimes 18152531Swollman tbf_update_tokens(vifp); 18161541Srgrimes 18172531Swollman tbf_process_q(vifp); 18182531Swollman 181910203Swollman if (vifp->v_tbf->tbf_q_len) 182010203Swollman timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS); 18212531Swollman} 18222531Swollman 18232531Swollman/* function that will selectively discard a member of the queue 182410203Swollman * based on the precedence value and the priority 18252531Swollman */ 18269209Swollmanstatic int 18272531Swollmantbf_dq_sel(vifp, ip) 18282531Swollman register struct vif *vifp; 18292531Swollman register struct ip *ip; 18302531Swollman{ 18312531Swollman register int s = splnet(); 18322531Swollman register u_int p; 183310203Swollman register struct mbuf *m, *last; 183410203Swollman register struct mbuf **np; 183510203Swollman register struct tbf *t = vifp->v_tbf; 18362531Swollman 18372531Swollman p = priority(vifp, ip); 18382531Swollman 183910203Swollman np = &t->tbf_q; 184010203Swollman last = NULL; 184110203Swollman while ((m = *np) != NULL) { 184210203Swollman if (p > priority(vifp, mtod(m, struct ip *))) { 184310203Swollman *np = m->m_act; 184410203Swollman /* If we're removing the last packet, fix the tail pointer */ 184510203Swollman if (m == t->tbf_t) 184610203Swollman t->tbf_t = last; 184710203Swollman m_freem(m); 184810203Swollman /* it's impossible for the queue to be empty, but 184910203Swollman * we check anyway. */ 185010203Swollman if (--t->tbf_q_len == 0) 185110203Swollman t->tbf_t = NULL; 18522531Swollman splx(s); 18532531Swollman mrtstat.mrts_drop_sel++; 18542531Swollman return(1); 18551541Srgrimes } 185610203Swollman np = &m->m_act; 185710203Swollman last = m; 18582531Swollman } 18592531Swollman splx(s); 18602531Swollman return(0); 18612531Swollman} 18621541Srgrimes 18639209Swollmanstatic void 186410203Swollmantbf_send_packet(vifp, m) 18652531Swollman register struct vif *vifp; 18662531Swollman register struct mbuf *m; 18672531Swollman{ 186810203Swollman struct ip_moptions imo; 18692531Swollman int error; 187015292Swollman static struct route ro; 18712531Swollman int s = splnet(); 18721541Srgrimes 18739209Swollman if (vifp->v_flags & VIFF_TUNNEL) { 18742531Swollman /* If tunnel options */ 187515292Swollman ip_output(m, (struct mbuf *)0, &vifp->v_route, 187610203Swollman IP_FORWARDING, (struct ip_moptions *)0); 18772531Swollman } else { 187810203Swollman imo.imo_multicast_ifp = vifp->v_ifp; 187910203Swollman imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1; 188010203Swollman imo.imo_multicast_loop = 1; 188110203Swollman imo.imo_multicast_vif = -1; 188210203Swollman 188315292Swollman /* 188415292Swollman * Re-entrancy should not be a problem here, because 188515292Swollman * the packets that we send out and are looped back at us 188615292Swollman * should get rejected because they appear to come from 188715292Swollman * the loopback interface, thus preventing looping. 188815292Swollman */ 188915292Swollman error = ip_output(m, (struct mbuf *)0, &ro, 189010203Swollman IP_FORWARDING, &imo); 18912531Swollman 18929209Swollman if (mrtdebug & DEBUG_XMIT) 189311284Swollman log(LOG_DEBUG, "phyint_send on vif %d err %d\n", 189411284Swollman vifp - viftable, error); 18952531Swollman } 18962531Swollman splx(s); 18971541Srgrimes} 18982531Swollman 18992531Swollman/* determine the current time and then 19002531Swollman * the elapsed time (between the last time and time now) 19012531Swollman * in milliseconds & update the no. of tokens in the bucket 19022531Swollman */ 19039209Swollmanstatic void 19042531Swollmantbf_update_tokens(vifp) 19052531Swollman register struct vif *vifp; 19062531Swollman{ 19072531Swollman struct timeval tp; 190810203Swollman register u_long tm; 19092531Swollman register int s = splnet(); 191010203Swollman register struct tbf *t = vifp->v_tbf; 19112531Swollman 19122531Swollman GET_TIME(tp); 19132531Swollman 191410203Swollman TV_DELTA(tp, t->tbf_last_pkt_t, tm); 19152531Swollman 191610203Swollman /* 191710203Swollman * This formula is actually 191810203Swollman * "time in seconds" * "bytes/second". 191910203Swollman * 192010203Swollman * (tm / 1000000) * (v_rate_limit * 1000 * (1000/1024) / 8) 192110203Swollman * 192210203Swollman * The (1000/1024) was introduced in add_vif to optimize 192310203Swollman * this divide into a shift. 192410203Swollman */ 192510203Swollman t->tbf_n_tok += tm * vifp->v_rate_limit / 1024 / 8; 192610203Swollman t->tbf_last_pkt_t = tp; 19272531Swollman 192810203Swollman if (t->tbf_n_tok > MAX_BKT_SIZE) 192910203Swollman t->tbf_n_tok = MAX_BKT_SIZE; 19302531Swollman 19312531Swollman splx(s); 19322531Swollman} 19332531Swollman 19342531Swollmanstatic int 19352531Swollmanpriority(vifp, ip) 19362531Swollman register struct vif *vifp; 19372531Swollman register struct ip *ip; 19382531Swollman{ 19392531Swollman register int prio; 19402531Swollman 19419209Swollman /* temporary hack; may add general packet classifier some day */ 19422531Swollman 19439209Swollman /* 19449209Swollman * The UDP port space is divided up into four priority ranges: 19459209Swollman * [0, 16384) : unclassified - lowest priority 19469209Swollman * [16384, 32768) : audio - highest priority 19479209Swollman * [32768, 49152) : whiteboard - medium priority 19489209Swollman * [49152, 65536) : video - low priority 19499209Swollman */ 19509209Swollman if (ip->ip_p == IPPROTO_UDP) { 19519209Swollman struct udphdr *udp = (struct udphdr *)(((char *)ip) + (ip->ip_hl << 2)); 19529209Swollman switch (ntohs(udp->uh_dport) & 0xc000) { 19539209Swollman case 0x4000: 19549209Swollman prio = 70; 19559209Swollman break; 19569209Swollman case 0x8000: 19579209Swollman prio = 60; 19589209Swollman break; 19599209Swollman case 0xc000: 19609209Swollman prio = 55; 19619209Swollman break; 19629209Swollman default: 19639209Swollman prio = 50; 19649209Swollman break; 19659209Swollman } 19669209Swollman if (tbfdebug > 1) 196711284Swollman log(LOG_DEBUG, "port %x prio%d\n", ntohs(udp->uh_dport), prio); 19689209Swollman } else { 19699209Swollman prio = 50; 19709209Swollman } 19719209Swollman return prio; 19729209Swollman} 19738876Srgrimes 19749209Swollman/* 19759209Swollman * End of token bucket filter modifications 19769209Swollman */ 19772531Swollman 19789209Swollmanint 197938482Swollmanip_rsvp_vif_init(so, sopt) 198038482Swollman struct socket *so; 198138482Swollman struct sockopt *sopt; 19829209Swollman{ 198338482Swollman int error, i, s; 19849209Swollman 19859209Swollman if (rsvpdebug) 19869209Swollman printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n", 19879209Swollman so->so_type, so->so_proto->pr_protocol); 19889209Swollman 19899209Swollman if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) 19909209Swollman return EOPNOTSUPP; 19919209Swollman 19929209Swollman /* Check mbuf. */ 199338482Swollman error = sooptcopyin(sopt, &i, sizeof i, sizeof i); 199438482Swollman if (error) 199538482Swollman return (error); 19969209Swollman 19979209Swollman if (rsvpdebug) 199838482Swollman printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n", i, rsvp_on); 19999209Swollman 20009209Swollman s = splnet(); 20012531Swollman 20029209Swollman /* Check vif. */ 20039209Swollman if (!legal_vif_num(i)) { 20049209Swollman splx(s); 20059209Swollman return EADDRNOTAVAIL; 20069209Swollman } 20072531Swollman 20089209Swollman /* Check if socket is available. */ 20099209Swollman if (viftable[i].v_rsvpd != NULL) { 20109209Swollman splx(s); 20119209Swollman return EADDRINUSE; 20129209Swollman } 20139209Swollman 20149209Swollman viftable[i].v_rsvpd = so; 20159209Swollman /* This may seem silly, but we need to be sure we don't over-increment 20169209Swollman * the RSVP counter, in case something slips up. 20179209Swollman */ 20189209Swollman if (!viftable[i].v_rsvp_on) { 20199209Swollman viftable[i].v_rsvp_on = 1; 20209209Swollman rsvp_on++; 20219209Swollman } 20229209Swollman 20239209Swollman splx(s); 20249209Swollman return 0; 20252531Swollman} 20262531Swollman 20279209Swollmanint 202838482Swollmanip_rsvp_vif_done(so, sopt) 202938482Swollman struct socket *so; 203038482Swollman struct sockopt *sopt; 20319209Swollman{ 203238482Swollman int error, i, s; 20339209Swollman 203438482Swollman if (rsvpdebug) 203538482Swollman printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n", 203638482Swollman so->so_type, so->so_proto->pr_protocol); 20379209Swollman 203838482Swollman if (so->so_type != SOCK_RAW || 203938482Swollman so->so_proto->pr_protocol != IPPROTO_RSVP) 204038482Swollman return EOPNOTSUPP; 20419209Swollman 204238482Swollman error = sooptcopyin(sopt, &i, sizeof i, sizeof i); 204338482Swollman if (error) 204438482Swollman return (error); 20459209Swollman 204638482Swollman s = splnet(); 20479209Swollman 204838482Swollman /* Check vif. */ 204938482Swollman if (!legal_vif_num(i)) { 205038482Swollman splx(s); 205138482Swollman return EADDRNOTAVAIL; 205238482Swollman } 20532531Swollman 205438482Swollman if (rsvpdebug) 205538482Swollman printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n", 205638482Swollman viftable[i].v_rsvpd, so); 20579209Swollman 205838482Swollman viftable[i].v_rsvpd = NULL; 205938482Swollman /* 206038482Swollman * This may seem silly, but we need to be sure we don't over-decrement 206138482Swollman * the RSVP counter, in case something slips up. 206238482Swollman */ 206338482Swollman if (viftable[i].v_rsvp_on) { 206438482Swollman viftable[i].v_rsvp_on = 0; 206538482Swollman rsvp_on--; 206638482Swollman } 20679209Swollman 206838482Swollman splx(s); 206938482Swollman return 0; 20709209Swollman} 20719209Swollman 20729209Swollmanvoid 20739209Swollmanip_rsvp_force_done(so) 20749209Swollman struct socket *so; 20759209Swollman{ 20769209Swollman int vifi; 20779209Swollman register int s; 20789209Swollman 20799209Swollman /* Don't bother if it is not the right type of socket. */ 20809209Swollman if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) 20819209Swollman return; 20829209Swollman 20839209Swollman s = splnet(); 20849209Swollman 20859209Swollman /* The socket may be attached to more than one vif...this 20869209Swollman * is perfectly legal. 20879209Swollman */ 20889209Swollman for (vifi = 0; vifi < numvifs; vifi++) { 20899209Swollman if (viftable[vifi].v_rsvpd == so) { 20909209Swollman viftable[vifi].v_rsvpd = NULL; 20919209Swollman /* This may seem silly, but we need to be sure we don't 20929209Swollman * over-decrement the RSVP counter, in case something slips up. 20939209Swollman */ 20949209Swollman if (viftable[vifi].v_rsvp_on) { 20959209Swollman viftable[vifi].v_rsvp_on = 0; 20969209Swollman rsvp_on--; 20979209Swollman } 20989209Swollman } 20999209Swollman } 21009209Swollman 21019209Swollman splx(s); 21029209Swollman return; 21039209Swollman} 21049209Swollman 21059209Swollmanvoid 210682884Sjulianrsvp_input(m, off) 21079682Swollman struct mbuf *m; 210855009Sshin int off; 21099209Swollman{ 21109209Swollman int vifi; 21119209Swollman register struct ip *ip = mtod(m, struct ip *); 21129682Swollman static struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET }; 21139209Swollman register int s; 21149682Swollman struct ifnet *ifp; 21159209Swollman 21169209Swollman if (rsvpdebug) 21179209Swollman printf("rsvp_input: rsvp_on %d\n",rsvp_on); 21189209Swollman 21199209Swollman /* Can still get packets with rsvp_on = 0 if there is a local member 21209209Swollman * of the group to which the RSVP packet is addressed. But in this 21219209Swollman * case we want to throw the packet away. 21229209Swollman */ 21239209Swollman if (!rsvp_on) { 21249209Swollman m_freem(m); 21259209Swollman return; 21269209Swollman } 21279209Swollman 21289209Swollman s = splnet(); 21299209Swollman 21309209Swollman if (rsvpdebug) 21319209Swollman printf("rsvp_input: check vifs\n"); 21329209Swollman 21339682Swollman#ifdef DIAGNOSTIC 21349682Swollman if (!(m->m_flags & M_PKTHDR)) 21359682Swollman panic("rsvp_input no hdr"); 21369682Swollman#endif 21379682Swollman 21389682Swollman ifp = m->m_pkthdr.rcvif; 21399209Swollman /* Find which vif the packet arrived on. */ 214065986Skjc for (vifi = 0; vifi < numvifs; vifi++) 21419209Swollman if (viftable[vifi].v_ifp == ifp) 214265986Skjc break; 21439209Swollman 214465986Skjc if (vifi == numvifs || viftable[vifi].v_rsvpd == NULL) { 214565986Skjc /* 214665986Skjc * If the old-style non-vif-associated socket is set, 214765986Skjc * then use it. Otherwise, drop packet since there 214865986Skjc * is no specific socket for this vif. 214965986Skjc */ 215065986Skjc if (ip_rsvpd != NULL) { 21519209Swollman if (rsvpdebug) 215265986Skjc printf("rsvp_input: Sending packet up old-style socket\n"); 215382884Sjulian rip_input(m, off); /* xxx */ 215465986Skjc } else { 215565986Skjc if (rsvpdebug && vifi == numvifs) 215665986Skjc printf("rsvp_input: Can't find vif for packet.\n"); 215765986Skjc else if (rsvpdebug && viftable[vifi].v_rsvpd == NULL) 215865986Skjc printf("rsvp_input: No socket defined for vif %d\n",vifi); 21599209Swollman m_freem(m); 216065986Skjc } 216165986Skjc splx(s); 216265986Skjc return; 21639209Swollman } 21649209Swollman rsvp_src.sin_addr = ip->ip_src; 21659209Swollman 21669209Swollman if (rsvpdebug && m) 216712296Sphk printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n", 21689209Swollman m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv))); 21699209Swollman 217046568Speter if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) { 21719209Swollman if (rsvpdebug) 21729209Swollman printf("rsvp_input: Failed to append to socket\n"); 217346568Speter } else { 21749209Swollman if (rsvpdebug) 21759209Swollman printf("rsvp_input: send packet up\n"); 217646568Speter } 217746568Speter 21789209Swollman splx(s); 21799209Swollman} 21809209Swollman 218180354Sfenner#ifdef MROUTE_KLD 21822531Swollman 21832763Swollmanstatic int 218480354Sfennerip_mroute_modevent(module_t mod, int type, void *unused) 21852763Swollman{ 218680354Sfenner int s; 21872763Swollman 218880354Sfenner switch (type) { 218980354Sfenner static u_long (*old_ip_mcast_src)(int); 219080354Sfenner static int (*old_ip_mrouter_set)(struct socket *, 219180354Sfenner struct sockopt *); 219280354Sfenner static int (*old_ip_mrouter_get)(struct socket *, 219380354Sfenner struct sockopt *); 219480354Sfenner static int (*old_ip_mrouter_done)(void); 219580354Sfenner static int (*old_ip_mforward)(struct ip *, struct ifnet *, 219680354Sfenner struct mbuf *, struct ip_moptions *); 219780354Sfenner static int (*old_mrt_ioctl)(int, caddr_t); 219880354Sfenner static int (*old_legal_vif_num)(int); 21992763Swollman 220080354Sfenner case MOD_LOAD: 220180354Sfenner s = splnet(); 220280354Sfenner /* XXX Protect against multiple loading */ 220380354Sfenner old_ip_mcast_src = ip_mcast_src; 220480354Sfenner ip_mcast_src = X_ip_mcast_src; 220580354Sfenner old_ip_mrouter_get = ip_mrouter_get; 220680354Sfenner ip_mrouter_get = X_ip_mrouter_get; 220780354Sfenner old_ip_mrouter_set = ip_mrouter_set; 220880354Sfenner ip_mrouter_set = X_ip_mrouter_set; 22092763Swollman old_ip_mrouter_done = ip_mrouter_done; 22102763Swollman ip_mrouter_done = X_ip_mrouter_done; 22112763Swollman old_ip_mforward = ip_mforward; 22122763Swollman ip_mforward = X_ip_mforward; 22132763Swollman old_mrt_ioctl = mrt_ioctl; 22142763Swollman mrt_ioctl = X_mrt_ioctl; 22152763Swollman old_legal_vif_num = legal_vif_num; 22162763Swollman legal_vif_num = X_legal_vif_num; 22172763Swollman 221880354Sfenner splx(s); 221980354Sfenner return 0; 22202763Swollman 222180354Sfenner case MOD_UNLOAD: 22222763Swollman if (ip_mrouter) 22232763Swollman return EINVAL; 22242763Swollman 222580354Sfenner s = splnet(); 222680354Sfenner ip_mrouter_get = old_ip_mrouter_get; 222780354Sfenner ip_mrouter_set = old_ip_mrouter_set; 22282763Swollman ip_mrouter_done = old_ip_mrouter_done; 22292763Swollman ip_mforward = old_ip_mforward; 22302763Swollman mrt_ioctl = old_mrt_ioctl; 22312763Swollman legal_vif_num = old_legal_vif_num; 223280354Sfenner splx(s); 223380354Sfenner return 0; 22342763Swollman 22352763Swollman default: 22362763Swollman break; 22372763Swollman } 223880354Sfenner return 0; 22392763Swollman} 22402763Swollman 224180354Sfennerstatic moduledata_t ip_mroutemod = { 224280354Sfenner "ip_mroute", 224380354Sfenner ip_mroute_modevent, 224480354Sfenner 0 224580354Sfenner}; 224680354SfennerDECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY); 22472763Swollman 224880354Sfenner#endif /* MROUTE_KLD */ 22492763Swollman#endif /* MROUTING */ 2250