ip_mroute.c revision 50477
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 50477 1999-08-28 01:08:13Z peter $ 131541Srgrimes */ 141541Srgrimes 1514328Speter#include "opt_mrouting.h" 161541Srgrimes 171541Srgrimes#include <sys/param.h> 181549Srgrimes#include <sys/systm.h> 1942777Sfenner#include <sys/malloc.h> 201541Srgrimes#include <sys/mbuf.h> 211541Srgrimes#include <sys/socket.h> 221541Srgrimes#include <sys/socketvar.h> 232531Swollman#include <sys/protosw.h> 241541Srgrimes#include <sys/time.h> 259209Swollman#include <sys/kernel.h> 2624204Sbde#include <sys/sockio.h> 272531Swollman#include <sys/syslog.h> 281541Srgrimes#include <net/if.h> 291541Srgrimes#include <net/route.h> 301541Srgrimes#include <netinet/in.h> 311541Srgrimes#include <netinet/in_systm.h> 321541Srgrimes#include <netinet/ip.h> 332531Swollman#include <netinet/ip_var.h> 341541Srgrimes#include <netinet/in_var.h> 351541Srgrimes#include <netinet/igmp.h> 361541Srgrimes#include <netinet/ip_mroute.h> 379209Swollman#include <netinet/udp.h> 381541Srgrimes 392531Swollman#ifndef NTOHL 402531Swollman#if BYTE_ORDER != BIG_ENDIAN 412531Swollman#define NTOHL(d) ((d) = ntohl((d))) 422531Swollman#define NTOHS(d) ((d) = ntohs((u_short)(d))) 432531Swollman#define HTONL(d) ((d) = htonl((d))) 442531Swollman#define HTONS(d) ((d) = htons((u_short)(d))) 452531Swollman#else 462531Swollman#define NTOHL(d) 472531Swollman#define NTOHS(d) 482531Swollman#define HTONL(d) 492531Swollman#define HTONS(d) 502531Swollman#endif 512531Swollman#endif 521541Srgrimes 532531Swollman#ifndef MROUTING 5412579Sbdeextern u_long _ip_mcast_src __P((int vifi)); 5512579Sbdeextern int _ip_mforward __P((struct ip *ip, struct ifnet *ifp, 5612579Sbde struct mbuf *m, struct ip_moptions *imo)); 5712579Sbdeextern int _ip_mrouter_done __P((void)); 5838482Swollmanextern int _ip_mrouter_get __P((struct socket *so, struct sockopt *sopt)); 5938482Swollmanextern int _ip_mrouter_set __P((struct socket *so, struct sockopt *sopt)); 6012579Sbdeextern int _mrt_ioctl __P((int req, caddr_t data, struct proc *p)); 6112579Sbde 622531Swollman/* 632531Swollman * Dummy routines and globals used when multicast routing is not compiled in. 642531Swollman */ 651541Srgrimes 669209Swollmanstruct socket *ip_mrouter = NULL; 679209Swollmanu_int rsvpdebug = 0; 682531Swollman 692531Swollmanint 7038482Swollman_ip_mrouter_set(so, sopt) 712531Swollman struct socket *so; 7238482Swollman struct sockopt *sopt; 732531Swollman{ 742531Swollman return(EOPNOTSUPP); 752531Swollman} 762531Swollman 7738482Swollmanint (*ip_mrouter_set)(struct socket *, struct sockopt *) = _ip_mrouter_set; 782754Swollman 799209Swollman 802531Swollmanint 8138482Swollman_ip_mrouter_get(so, sopt) 829209Swollman struct socket *so; 8338482Swollman struct sockopt *sopt; 849209Swollman{ 859209Swollman return(EOPNOTSUPP); 869209Swollman} 879209Swollman 8838482Swollmanint (*ip_mrouter_get)(struct socket *, struct sockopt *) = _ip_mrouter_get; 899209Swollman 909209Swollmanint 912754Swollman_ip_mrouter_done() 922531Swollman{ 932531Swollman return(0); 942531Swollman} 952531Swollman 962754Swollmanint (*ip_mrouter_done)(void) = _ip_mrouter_done; 972754Swollman 982531Swollmanint 992754Swollman_ip_mforward(ip, ifp, m, imo) 1002531Swollman struct ip *ip; 1012531Swollman struct ifnet *ifp; 1022531Swollman struct mbuf *m; 1032754Swollman struct ip_moptions *imo; 1042531Swollman{ 1052531Swollman return(0); 1062531Swollman} 1072754Swollman 1082754Swollmanint (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, 1092754Swollman struct ip_moptions *) = _ip_mforward; 1102754Swollman 1112754Swollmanint 1122754Swollman_mrt_ioctl(int req, caddr_t data, struct proc *p) 1132754Swollman{ 1142754Swollman return EOPNOTSUPP; 1152754Swollman} 1162754Swollman 1172754Swollmanint (*mrt_ioctl)(int, caddr_t, struct proc *) = _mrt_ioctl; 1182754Swollman 1199209Swollmanvoid 1209209Swollmanrsvp_input(m, iphlen) /* XXX must fixup manually */ 1219209Swollman struct mbuf *m; 1229209Swollman int iphlen; 1239209Swollman{ 1249209Swollman /* Can still get packets with rsvp_on = 0 if there is a local member 1259209Swollman * of the group to which the RSVP packet is addressed. But in this 1269209Swollman * case we want to throw the packet away. 1279209Swollman */ 1289209Swollman if (!rsvp_on) { 1299209Swollman m_freem(m); 1309209Swollman return; 1319209Swollman } 1329209Swollman 1339209Swollman if (ip_rsvpd != NULL) { 1349209Swollman if (rsvpdebug) 1359209Swollman printf("rsvp_input: Sending packet up old-style socket\n"); 13614824Sfenner rip_input(m, iphlen); 1379209Swollman return; 1389209Swollman } 1399209Swollman /* Drop the packet */ 1409209Swollman m_freem(m); 1412754Swollman} 1422754Swollman 14314824Sfennervoid ipip_input(struct mbuf *m, int iphlen) { /* XXX must fixup manually */ 14414824Sfenner rip_input(m, iphlen); 1459209Swollman} 1469209Swollman 1472754Swollmanint (*legal_vif_num)(int) = 0; 1482754Swollman 1499209Swollman/* 1509209Swollman * This should never be called, since IP_MULTICAST_VIF should fail, but 1519209Swollman * just in case it does get called, the code a little lower in ip_output 1529209Swollman * will assign the packet a local address. 1539209Swollman */ 1549209Swollmanu_long 1559209Swollman_ip_mcast_src(int vifi) { return INADDR_ANY; } 1569209Swollmanu_long (*ip_mcast_src)(int) = _ip_mcast_src; 1579209Swollman 1589209Swollmanint 15938482Swollmanip_rsvp_vif_init(so, sopt) 1609209Swollman struct socket *so; 16138482Swollman struct sockopt *sopt; 1629209Swollman{ 1639209Swollman return(EINVAL); 1649209Swollman} 1659209Swollman 1669209Swollmanint 16738482Swollmanip_rsvp_vif_done(so, sopt) 1689209Swollman struct socket *so; 16938482Swollman struct sockopt *sopt; 1709209Swollman{ 1719209Swollman return(EINVAL); 1729209Swollman} 1739209Swollman 1749209Swollmanvoid 1759209Swollmanip_rsvp_force_done(so) 1769209Swollman struct socket *so; 1779209Swollman{ 1789209Swollman return; 1799209Swollman} 1809209Swollman 1817083Swollman#else /* MROUTING */ 1822531Swollman 1839209Swollman#define M_HASCL(m) ((m)->m_flags & M_EXT) 1849209Swollman 1852531Swollman#define INSIZ sizeof(struct in_addr) 1862531Swollman#define same(a1, a2) \ 1872531Swollman (bcmp((caddr_t)(a1), (caddr_t)(a2), INSIZ) == 0) 1882531Swollman 18942777Sfennerstatic MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast routing tables"); 1902531Swollman 1911541Srgrimes/* 1921541Srgrimes * Globals. All but ip_mrouter and ip_mrtproto could be static, 1931541Srgrimes * except for netstat or debugging purposes. 1941541Srgrimes */ 1952763Swollman#ifndef MROUTE_LKM 1962531Swollmanstruct socket *ip_mrouter = NULL; 19733181Seivindstatic struct mrtstat mrtstat; 1987083Swollman#else /* MROUTE_LKM */ 19914824Sfennerextern void X_ipip_input __P((struct mbuf *m, int iphlen)); 2002763Swollmanextern struct mrtstat mrtstat; 20112296Sphkstatic int ip_mrtproto; 2022763Swollman#endif 2031541Srgrimes 2042531Swollman#define NO_RTE_FOUND 0x1 2052531Swollman#define RTE_FOUND 0x2 2061541Srgrimes 20742777Sfennerstatic struct mfc *mfctable[MFCTBLSIZ]; 20812820Sphkstatic u_char nexpire[MFCTBLSIZ]; 20912820Sphkstatic struct vif viftable[MAXVIFS]; 21012296Sphkstatic u_int mrtdebug = 0; /* debug level */ 2119209Swollman#define DEBUG_MFC 0x02 2129209Swollman#define DEBUG_FORWARD 0x04 2139209Swollman#define DEBUG_EXPIRE 0x08 2149209Swollman#define DEBUG_XMIT 0x10 21512296Sphkstatic u_int tbfdebug = 0; /* tbf debug level */ 21612296Sphkstatic u_int rsvpdebug = 0; /* rsvp debug level */ 2172531Swollman 21829681Sgibbsstatic struct callout_handle expire_upcalls_ch; 21929681Sgibbs 2209209Swollman#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ 2219209Swollman#define UPCALL_EXPIRE 6 /* number of timeouts */ 2222531Swollman 2231541Srgrimes/* 2242531Swollman * Define the token bucket filter structures 2259209Swollman * tbftable -> each vif has one of these for storing info 2262531Swollman */ 2272531Swollman 22812820Sphkstatic struct tbf tbftable[MAXVIFS]; 22910203Swollman#define TBF_REPROCESS (hz / 100) /* 100x / second */ 2302531Swollman 2312531Swollman/* 2322531Swollman * 'Interfaces' associated with decapsulator (so we can tell 2332531Swollman * packets that went through it from ones that get reflected 2342531Swollman * by a broken gateway). These interfaces are never linked into 2352531Swollman * the system ifnet list & no routes point to them. I.e., packets 2362531Swollman * can't be sent this way. They only exist as a placeholder for 2372531Swollman * multicast source verification. 2382531Swollman */ 23912820Sphkstatic struct ifnet multicast_decap_if[MAXVIFS]; 2402531Swollman 2412531Swollman#define ENCAP_TTL 64 2429209Swollman#define ENCAP_PROTO IPPROTO_IPIP /* 4 */ 2432531Swollman 2442531Swollman/* prototype IP hdr for encapsulated packets */ 24512296Sphkstatic struct ip multicast_encap_iphdr = { 2462754Swollman#if BYTE_ORDER == LITTLE_ENDIAN 2472531Swollman sizeof(struct ip) >> 2, IPVERSION, 2482531Swollman#else 2492531Swollman IPVERSION, sizeof(struct ip) >> 2, 2502531Swollman#endif 2512531Swollman 0, /* tos */ 2522531Swollman sizeof(struct ip), /* total length */ 2532531Swollman 0, /* id */ 2542531Swollman 0, /* frag offset */ 2559209Swollman ENCAP_TTL, ENCAP_PROTO, 2562531Swollman 0, /* checksum */ 2572531Swollman}; 2582531Swollman 2592531Swollman/* 2601541Srgrimes * Private variables. 2611541Srgrimes */ 2622531Swollmanstatic vifi_t numvifs = 0; 2639209Swollmanstatic int have_encap_tunnel = 0; 2641541Srgrimes 2651541Srgrimes/* 2669209Swollman * one-back cache used by ipip_input to locate a tunnel's vif 2672531Swollman * given a datagram's src ip address. 2682531Swollman */ 2692531Swollmanstatic u_long last_encap_src; 2702531Swollmanstatic struct vif *last_encap_vif; 2712531Swollman 27212579Sbdestatic u_long X_ip_mcast_src __P((int vifi)); 27312579Sbdestatic int X_ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo)); 27412579Sbdestatic int X_ip_mrouter_done __P((void)); 27538482Swollmanstatic int X_ip_mrouter_get __P((struct socket *so, struct sockopt *m)); 27638482Swollmanstatic int X_ip_mrouter_set __P((struct socket *so, struct sockopt *m)); 27712579Sbdestatic int X_legal_vif_num __P((int vif)); 27812579Sbdestatic int X_mrt_ioctl __P((int cmd, caddr_t data)); 27912579Sbde 2809209Swollmanstatic int get_sg_cnt(struct sioc_sg_req *); 2819209Swollmanstatic int get_vif_cnt(struct sioc_vif_req *); 28238482Swollmanstatic int ip_mrouter_init(struct socket *, int); 2832531Swollmanstatic int add_vif(struct vifctl *); 28438482Swollmanstatic int del_vif(vifi_t); 2852531Swollmanstatic int add_mfc(struct mfcctl *); 2869209Swollmanstatic int del_mfc(struct mfcctl *); 28712579Sbdestatic int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *); 28838482Swollmanstatic int set_assert(int); 2899209Swollmanstatic void expire_upcalls(void *); 2909209Swollmanstatic int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, 2919209Swollman vifi_t); 2922531Swollmanstatic void phyint_send(struct ip *, struct vif *, struct mbuf *); 2932531Swollmanstatic void encap_send(struct ip *, struct vif *, struct mbuf *); 29410203Swollmanstatic void tbf_control(struct vif *, struct mbuf *, struct ip *, u_long); 29510203Swollmanstatic void tbf_queue(struct vif *, struct mbuf *); 2969209Swollmanstatic void tbf_process_q(struct vif *); 2979209Swollmanstatic void tbf_reprocess_q(void *); 2989209Swollmanstatic int tbf_dq_sel(struct vif *, struct ip *); 29910203Swollmanstatic void tbf_send_packet(struct vif *, struct mbuf *); 3009209Swollmanstatic void tbf_update_tokens(struct vif *); 3012531Swollmanstatic int priority(struct vif *, struct ip *); 3029209Swollmanvoid multiencap_decap(struct mbuf *); 3032531Swollman 3042531Swollman/* 3059209Swollman * whether or not special PIM assert processing is enabled. 3068876Srgrimes */ 3079209Swollmanstatic int pim_assert; 3089209Swollman/* 3099209Swollman * Rate limit for assert notification messages, in usec 3109209Swollman */ 3119209Swollman#define ASSERT_MSG_TIME 3000000 3122531Swollman 3132531Swollman/* 3149209Swollman * Hash function for a source, group entry 3152531Swollman */ 3169209Swollman#define MFCHASH(a, g) MFCHASHMOD(((a) >> 20) ^ ((a) >> 10) ^ (a) ^ \ 3179209Swollman ((g) >> 20) ^ ((g) >> 10) ^ (g)) 3182531Swollman 3192531Swollman/* 3202531Swollman * Find a route for a given origin IP address and Multicast group address 3212531Swollman * Type of service parameter to be added in the future!!! 3222531Swollman */ 3239209Swollman 3242531Swollman#define MFCFIND(o, g, rt) { \ 32542777Sfenner register struct mfc *_rt = mfctable[MFCHASH(o,g)]; \ 3269209Swollman rt = NULL; \ 3272531Swollman ++mrtstat.mrts_mfc_lookups; \ 32842777Sfenner while (_rt) { \ 3299209Swollman if ((_rt->mfc_origin.s_addr == o) && \ 3309209Swollman (_rt->mfc_mcastgrp.s_addr == g) && \ 33142777Sfenner (_rt->mfc_stall == NULL)) { \ 3329209Swollman rt = _rt; \ 3339209Swollman break; \ 3349209Swollman } \ 33542777Sfenner _rt = _rt->mfc_next; \ 3369209Swollman } \ 3379209Swollman if (rt == NULL) { \ 3389209Swollman ++mrtstat.mrts_mfc_misses; \ 3399209Swollman } \ 3402531Swollman} 3412531Swollman 3422531Swollman 3432531Swollman/* 3442531Swollman * Macros to compute elapsed time efficiently 3452531Swollman * Borrowed from Van Jacobson's scheduling code 3462531Swollman */ 3472531Swollman#define TV_DELTA(a, b, delta) { \ 3482531Swollman register int xxs; \ 3492531Swollman \ 3502531Swollman delta = (a).tv_usec - (b).tv_usec; \ 3512531Swollman if ((xxs = (a).tv_sec - (b).tv_sec)) { \ 3522531Swollman switch (xxs) { \ 3532531Swollman case 2: \ 3542531Swollman delta += 1000000; \ 3552531Swollman /* fall through */ \ 3562531Swollman case 1: \ 3572531Swollman delta += 1000000; \ 3582531Swollman break; \ 3592531Swollman default: \ 3602531Swollman delta += (1000000 * xxs); \ 3612531Swollman } \ 3622531Swollman } \ 3632531Swollman} 3642531Swollman 3652531Swollman#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \ 3662531Swollman (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec) 3672531Swollman 3689209Swollman#ifdef UPCALL_TIMING 3699209Swollmanu_long upcall_data[51]; 3709209Swollmanstatic void collate(struct timeval *); 3719209Swollman#endif /* UPCALL_TIMING */ 3729209Swollman 3739209Swollman 3742531Swollman/* 3759209Swollman * Handle MRT setsockopt commands to modify the multicast routing tables. 3761541Srgrimes */ 37712296Sphkstatic int 37838482SwollmanX_ip_mrouter_set(so, sopt) 37938482Swollman struct socket *so; 38038482Swollman struct sockopt *sopt; 3811541Srgrimes{ 38238482Swollman int error, optval; 38338482Swollman vifi_t vifi; 38438482Swollman struct vifctl vifc; 38538482Swollman struct mfcctl mfc; 3861541Srgrimes 38738482Swollman if (so != ip_mrouter && sopt->sopt_name != MRT_INIT) 38838482Swollman return (EPERM); 38938482Swollman 39038482Swollman error = 0; 39138482Swollman switch (sopt->sopt_name) { 39238482Swollman case MRT_INIT: 39338482Swollman error = sooptcopyin(sopt, &optval, sizeof optval, 39438482Swollman sizeof optval); 39538482Swollman if (error) 39638482Swollman break; 39738482Swollman error = ip_mrouter_init(so, optval); 39838482Swollman break; 39938482Swollman 40038482Swollman case MRT_DONE: 40138482Swollman error = ip_mrouter_done(); 40238482Swollman break; 40338482Swollman 40438482Swollman case MRT_ADD_VIF: 40538482Swollman error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc); 40638482Swollman if (error) 40738482Swollman break; 40838482Swollman error = add_vif(&vifc); 40938482Swollman break; 41038482Swollman 41138482Swollman case MRT_DEL_VIF: 41238482Swollman error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi); 41338482Swollman if (error) 41438482Swollman break; 41538482Swollman error = del_vif(vifi); 41638482Swollman break; 41738482Swollman 41838482Swollman case MRT_ADD_MFC: 41938482Swollman case MRT_DEL_MFC: 42038482Swollman error = sooptcopyin(sopt, &mfc, sizeof mfc, sizeof mfc); 42138482Swollman if (error) 42238482Swollman break; 42338482Swollman if (sopt->sopt_name == MRT_ADD_MFC) 42438482Swollman error = add_mfc(&mfc); 42538482Swollman else 42638482Swollman error = del_mfc(&mfc); 42741878Sfenner break; 42838482Swollman 42938482Swollman case MRT_ASSERT: 43038482Swollman error = sooptcopyin(sopt, &optval, sizeof optval, 43138482Swollman sizeof optval); 43238482Swollman if (error) 43338482Swollman break; 43438482Swollman set_assert(optval); 43541878Sfenner break; 43638482Swollman 43738482Swollman default: 43838482Swollman error = EOPNOTSUPP; 43938482Swollman break; 44038482Swollman } 44138482Swollman return (error); 4422531Swollman} 4431541Srgrimes 4442763Swollman#ifndef MROUTE_LKM 44538482Swollmanint (*ip_mrouter_set)(struct socket *, struct sockopt *) = X_ip_mrouter_set; 4462763Swollman#endif 4471541Srgrimes 4482531Swollman/* 4499209Swollman * Handle MRT getsockopt commands 4509209Swollman */ 45112296Sphkstatic int 45238482SwollmanX_ip_mrouter_get(so, sopt) 45338482Swollman struct socket *so; 45438482Swollman struct sockopt *sopt; 4559209Swollman{ 45638482Swollman int error; 45738482Swollman static int version = 0x0305; /* !!! why is this here? XXX */ 4589209Swollman 45938482Swollman switch (sopt->sopt_name) { 46038482Swollman case MRT_VERSION: 46138482Swollman error = sooptcopyout(sopt, &version, sizeof version); 46238482Swollman break; 4639209Swollman 46438482Swollman case MRT_ASSERT: 46538482Swollman error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert); 46638482Swollman break; 46738482Swollman default: 46838482Swollman error = EOPNOTSUPP; 46938482Swollman break; 47038482Swollman } 47138482Swollman return (error); 4729209Swollman} 4739209Swollman 4749209Swollman#ifndef MROUTE_LKM 47538482Swollmanint (*ip_mrouter_get)(struct socket *, struct sockopt *) = X_ip_mrouter_get; 4769209Swollman#endif 4779209Swollman 4789209Swollman/* 4792531Swollman * Handle ioctl commands to obtain information from the cache 4802531Swollman */ 48112296Sphkstatic int 4822763SwollmanX_mrt_ioctl(cmd, data) 4832531Swollman int cmd; 4842531Swollman caddr_t data; 4852531Swollman{ 4862531Swollman int error = 0; 4871541Srgrimes 4882531Swollman switch (cmd) { 4899209Swollman case (SIOCGETVIFCNT): 4909209Swollman return (get_vif_cnt((struct sioc_vif_req *)data)); 4919209Swollman break; 4929209Swollman case (SIOCGETSGCNT): 4939209Swollman return (get_sg_cnt((struct sioc_sg_req *)data)); 4949209Swollman break; 4952531Swollman default: 4969209Swollman return (EINVAL); 4979209Swollman break; 4982531Swollman } 4992531Swollman return error; 5002531Swollman} 5011541Srgrimes 5022763Swollman#ifndef MROUTE_LKM 50312579Sbdeint (*mrt_ioctl)(int, caddr_t) = X_mrt_ioctl; 5042763Swollman#endif 5052754Swollman 5062531Swollman/* 5079209Swollman * returns the packet, byte, rpf-failure count for the source group provided 5082531Swollman */ 5099209Swollmanstatic int 5102531Swollmanget_sg_cnt(req) 5112531Swollman register struct sioc_sg_req *req; 5122531Swollman{ 5132531Swollman register struct mfc *rt; 5142531Swollman int s; 5151541Srgrimes 5162531Swollman s = splnet(); 5172531Swollman MFCFIND(req->src.s_addr, req->grp.s_addr, rt); 5182531Swollman splx(s); 5199209Swollman if (rt != NULL) { 5209209Swollman req->pktcnt = rt->mfc_pkt_cnt; 5219209Swollman req->bytecnt = rt->mfc_byte_cnt; 5229209Swollman req->wrong_if = rt->mfc_wrong_if; 5239209Swollman } else 5249209Swollman req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff; 5251541Srgrimes 5262531Swollman return 0; 5272531Swollman} 5281541Srgrimes 5292531Swollman/* 5309209Swollman * returns the input and output packet and byte counts on the vif provided 5312531Swollman */ 5329209Swollmanstatic int 5332531Swollmanget_vif_cnt(req) 5342531Swollman register struct sioc_vif_req *req; 5352531Swollman{ 5362531Swollman register vifi_t vifi = req->vifi; 5371541Srgrimes 5389209Swollman if (vifi >= numvifs) return EINVAL; 5399209Swollman 5402531Swollman req->icount = viftable[vifi].v_pkt_in; 5412531Swollman req->ocount = viftable[vifi].v_pkt_out; 5429209Swollman req->ibytes = viftable[vifi].v_bytes_in; 5439209Swollman req->obytes = viftable[vifi].v_bytes_out; 5441541Srgrimes 5452531Swollman return 0; 5462531Swollman} 5472531Swollman 5481541Srgrimes/* 5491541Srgrimes * Enable multicast routing 5501541Srgrimes */ 55112296Sphkstatic int 55238482Swollmanip_mrouter_init(so, version) 5532531Swollman struct socket *so; 55438482Swollman int version; 5551541Srgrimes{ 5569209Swollman if (mrtdebug) 55711284Swollman log(LOG_DEBUG,"ip_mrouter_init: so_type = %d, pr_protocol = %d\n", 5589209Swollman so->so_type, so->so_proto->pr_protocol); 5599209Swollman 5602531Swollman if (so->so_type != SOCK_RAW || 5612531Swollman so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP; 5621541Srgrimes 56338482Swollman if (version != 1) 5649209Swollman return ENOPROTOOPT; 5659209Swollman 5662531Swollman if (ip_mrouter != NULL) return EADDRINUSE; 5671541Srgrimes 5682531Swollman ip_mrouter = so; 5691541Srgrimes 5709209Swollman bzero((caddr_t)mfctable, sizeof(mfctable)); 5719209Swollman bzero((caddr_t)nexpire, sizeof(nexpire)); 5729209Swollman 5739209Swollman pim_assert = 0; 5749209Swollman 57529681Sgibbs expire_upcalls_ch = timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT); 5769209Swollman 5772531Swollman if (mrtdebug) 57811284Swollman log(LOG_DEBUG, "ip_mrouter_init\n"); 5792531Swollman 5802531Swollman return 0; 5811541Srgrimes} 5821541Srgrimes 5831541Srgrimes/* 5841541Srgrimes * Disable multicast routing 5851541Srgrimes */ 58612296Sphkstatic int 5872763SwollmanX_ip_mrouter_done() 5881541Srgrimes{ 5892531Swollman vifi_t vifi; 5902531Swollman int i; 5912531Swollman struct ifnet *ifp; 5922531Swollman struct ifreq ifr; 59342777Sfenner struct mfc *rt; 5942531Swollman struct rtdetq *rte; 5952531Swollman int s; 5961541Srgrimes 5972531Swollman s = splnet(); 5981541Srgrimes 5992531Swollman /* 6002531Swollman * For each phyint in use, disable promiscuous reception of all IP 6012531Swollman * multicasts. 6022531Swollman */ 6032531Swollman for (vifi = 0; vifi < numvifs; vifi++) { 6042531Swollman if (viftable[vifi].v_lcl_addr.s_addr != 0 && 6052531Swollman !(viftable[vifi].v_flags & VIFF_TUNNEL)) { 6062531Swollman ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; 6072531Swollman ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr 6082531Swollman = INADDR_ANY; 6092531Swollman ifp = viftable[vifi].v_ifp; 61021666Swollman if_allmulti(ifp, 0); 6112531Swollman } 6122531Swollman } 6132531Swollman bzero((caddr_t)tbftable, sizeof(tbftable)); 6142531Swollman bzero((caddr_t)viftable, sizeof(viftable)); 6152531Swollman numvifs = 0; 6169209Swollman pim_assert = 0; 6172531Swollman 61829681Sgibbs untimeout(expire_upcalls, (caddr_t)NULL, expire_upcalls_ch); 6199209Swollman 6202531Swollman /* 6219209Swollman * Free all multicast forwarding cache entries. 6222531Swollman */ 6239209Swollman for (i = 0; i < MFCTBLSIZ; i++) { 62442777Sfenner for (rt = mfctable[i]; rt != NULL; ) { 62542777Sfenner struct mfc *nr = rt->mfc_next; 62642777Sfenner 62742777Sfenner for (rte = rt->mfc_stall; rte != NULL; ) { 62842777Sfenner struct rtdetq *n = rte->next; 62942777Sfenner 63042777Sfenner m_freem(rte->m); 63142777Sfenner free(rte, M_MRTABLE); 63242777Sfenner rte = n; 6332531Swollman } 63442777Sfenner free(rt, M_MRTABLE); 63542777Sfenner rt = nr; 6361541Srgrimes } 6379209Swollman } 6381541Srgrimes 6392531Swollman bzero((caddr_t)mfctable, sizeof(mfctable)); 6401541Srgrimes 6412531Swollman /* 6422531Swollman * Reset de-encapsulation cache 6432531Swollman */ 64417108Sbde last_encap_src = 0; 6452531Swollman last_encap_vif = NULL; 6469209Swollman have_encap_tunnel = 0; 6479209Swollman 6482531Swollman ip_mrouter = NULL; 6492531Swollman 6502531Swollman splx(s); 6512531Swollman 6522531Swollman if (mrtdebug) 65311284Swollman log(LOG_DEBUG, "ip_mrouter_done\n"); 6542531Swollman 6552531Swollman return 0; 6561541Srgrimes} 6571541Srgrimes 6582763Swollman#ifndef MROUTE_LKM 6592763Swollmanint (*ip_mrouter_done)(void) = X_ip_mrouter_done; 6602763Swollman#endif 6612754Swollman 6621541Srgrimes/* 6639209Swollman * Set PIM assert processing global 6649209Swollman */ 6659209Swollmanstatic int 6669209Swollmanset_assert(i) 66738482Swollman int i; 6689209Swollman{ 66938482Swollman if ((i != 1) && (i != 0)) 6709209Swollman return EINVAL; 6719209Swollman 67238482Swollman pim_assert = i; 6739209Swollman 6749209Swollman return 0; 6759209Swollman} 6769209Swollman 6779209Swollman/* 6781541Srgrimes * Add a vif to the vif table 6791541Srgrimes */ 6801541Srgrimesstatic int 6811541Srgrimesadd_vif(vifcp) 6822531Swollman register struct vifctl *vifcp; 6831541Srgrimes{ 6842531Swollman register struct vif *vifp = viftable + vifcp->vifc_vifi; 6853747Swollman static struct sockaddr_in sin = {sizeof sin, AF_INET}; 6862531Swollman struct ifaddr *ifa; 6872531Swollman struct ifnet *ifp; 6882531Swollman int error, s; 6892531Swollman struct tbf *v_tbf = tbftable + vifcp->vifc_vifi; 6901541Srgrimes 6912531Swollman if (vifcp->vifc_vifi >= MAXVIFS) return EINVAL; 6922531Swollman if (vifp->v_lcl_addr.s_addr != 0) return EADDRINUSE; 6931541Srgrimes 6942531Swollman /* Find the interface with an address in AF_INET family */ 6952531Swollman sin.sin_addr = vifcp->vifc_lcl_addr; 6962531Swollman ifa = ifa_ifwithaddr((struct sockaddr *)&sin); 6972531Swollman if (ifa == 0) return EADDRNOTAVAIL; 6982531Swollman ifp = ifa->ifa_ifp; 6991541Srgrimes 7002531Swollman if (vifcp->vifc_flags & VIFF_TUNNEL) { 7012531Swollman if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) { 7029209Swollman /* 7039209Swollman * An encapsulating tunnel is wanted. Tell ipip_input() to 7049209Swollman * start paying attention to encapsulated packets. 7059209Swollman */ 7069209Swollman if (have_encap_tunnel == 0) { 7079209Swollman have_encap_tunnel = 1; 7089209Swollman for (s = 0; s < MAXVIFS; ++s) { 7099209Swollman multicast_decap_if[s].if_name = "mdecap"; 7109209Swollman multicast_decap_if[s].if_unit = s; 7119209Swollman } 7121541Srgrimes } 7139209Swollman /* 7149209Swollman * Set interface to fake encapsulator interface 7159209Swollman */ 7169209Swollman ifp = &multicast_decap_if[vifcp->vifc_vifi]; 7179209Swollman /* 7189209Swollman * Prepare cached route entry 7199209Swollman */ 7209209Swollman bzero(&vifp->v_route, sizeof(vifp->v_route)); 7212531Swollman } else { 72211284Swollman log(LOG_ERR, "source routed tunnels not supported\n"); 7239209Swollman return EOPNOTSUPP; 7241541Srgrimes } 7252531Swollman } else { 7262531Swollman /* Make sure the interface supports multicast */ 7272531Swollman if ((ifp->if_flags & IFF_MULTICAST) == 0) 7282531Swollman return EOPNOTSUPP; 7291541Srgrimes 7302531Swollman /* Enable promiscuous reception of all IP multicasts from the if */ 7312531Swollman s = splnet(); 73222967Swollman error = if_allmulti(ifp, 1); 7332531Swollman splx(s); 7342531Swollman if (error) 7352531Swollman return error; 7362531Swollman } 7371541Srgrimes 7382531Swollman s = splnet(); 7392531Swollman /* define parameters for the tbf structure */ 7402531Swollman vifp->v_tbf = v_tbf; 74110203Swollman GET_TIME(vifp->v_tbf->tbf_last_pkt_t); 74210203Swollman vifp->v_tbf->tbf_n_tok = 0; 74310203Swollman vifp->v_tbf->tbf_q_len = 0; 74410203Swollman vifp->v_tbf->tbf_max_q_len = MAXQSIZE; 74510203Swollman vifp->v_tbf->tbf_q = vifp->v_tbf->tbf_t = NULL; 7461541Srgrimes 7472531Swollman vifp->v_flags = vifcp->vifc_flags; 7482531Swollman vifp->v_threshold = vifcp->vifc_threshold; 7492531Swollman vifp->v_lcl_addr = vifcp->vifc_lcl_addr; 7502531Swollman vifp->v_rmt_addr = vifcp->vifc_rmt_addr; 7512531Swollman vifp->v_ifp = ifp; 75210203Swollman /* scaling up here allows division by 1024 in critical code */ 75310203Swollman vifp->v_rate_limit= vifcp->vifc_rate_limit * 1024 / 1000; 7549209Swollman vifp->v_rsvp_on = 0; 7559209Swollman vifp->v_rsvpd = NULL; 7562531Swollman /* initialize per vif pkt counters */ 7572531Swollman vifp->v_pkt_in = 0; 7582531Swollman vifp->v_pkt_out = 0; 7599209Swollman vifp->v_bytes_in = 0; 7609209Swollman vifp->v_bytes_out = 0; 7612531Swollman splx(s); 7622531Swollman 7632531Swollman /* Adjust numvifs up if the vifi is higher than numvifs */ 7642531Swollman if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1; 7652531Swollman 7662531Swollman if (mrtdebug) 76738373Sbde log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x, rate %d\n", 7689209Swollman vifcp->vifc_vifi, 76938373Sbde (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr), 7702531Swollman (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask", 77138373Sbde (u_long)ntohl(vifcp->vifc_rmt_addr.s_addr), 7722531Swollman vifcp->vifc_threshold, 7739209Swollman vifcp->vifc_rate_limit); 7742531Swollman 7752531Swollman return 0; 7761541Srgrimes} 7771541Srgrimes 7781541Srgrimes/* 7791541Srgrimes * Delete a vif from the vif table 7801541Srgrimes */ 7811541Srgrimesstatic int 78238482Swollmandel_vif(vifi) 78338482Swollman vifi_t vifi; 7841541Srgrimes{ 78538482Swollman register struct vif *vifp = &viftable[vifi]; 78610203Swollman register struct mbuf *m; 7872531Swollman struct ifnet *ifp; 7882531Swollman struct ifreq ifr; 7892531Swollman int s; 7901541Srgrimes 79138482Swollman if (vifi >= numvifs) return EINVAL; 7922531Swollman if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL; 7931541Srgrimes 7942531Swollman s = splnet(); 7951541Srgrimes 7962531Swollman if (!(vifp->v_flags & VIFF_TUNNEL)) { 7972531Swollman ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; 7982531Swollman ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; 7992531Swollman ifp = vifp->v_ifp; 80021666Swollman if_allmulti(ifp, 0); 8012531Swollman } 8021541Srgrimes 8032531Swollman if (vifp == last_encap_vif) { 8042531Swollman last_encap_vif = 0; 8052531Swollman last_encap_src = 0; 8062531Swollman } 8071541Srgrimes 80810203Swollman /* 80910203Swollman * Free packets queued at the interface 81010203Swollman */ 81110203Swollman while (vifp->v_tbf->tbf_q) { 81210203Swollman m = vifp->v_tbf->tbf_q; 81310203Swollman vifp->v_tbf->tbf_q = m->m_act; 81410203Swollman m_freem(m); 81510203Swollman } 81610203Swollman 8172531Swollman bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf))); 8182531Swollman bzero((caddr_t)vifp, sizeof (*vifp)); 8191541Srgrimes 82038482Swollman if (mrtdebug) 82138482Swollman log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs); 82238482Swollman 8232531Swollman /* Adjust numvifs down */ 8242531Swollman for (vifi = numvifs; vifi > 0; vifi--) 8252531Swollman if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break; 8262531Swollman numvifs = vifi; 8272531Swollman 8282531Swollman splx(s); 8292531Swollman 8302531Swollman return 0; 8311541Srgrimes} 8321541Srgrimes 8331541Srgrimes/* 8342531Swollman * Add an mfc entry 8351541Srgrimes */ 8361541Srgrimesstatic int 8372531Swollmanadd_mfc(mfccp) 8382531Swollman struct mfcctl *mfccp; 8391541Srgrimes{ 8402531Swollman struct mfc *rt; 8412531Swollman u_long hash; 8422531Swollman struct rtdetq *rte; 8432531Swollman register u_short nstl; 8442531Swollman int s; 8452531Swollman int i; 8461541Srgrimes 8479209Swollman MFCFIND(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr, rt); 8481541Srgrimes 8492531Swollman /* If an entry already exists, just update the fields */ 8502531Swollman if (rt) { 8519209Swollman if (mrtdebug & DEBUG_MFC) 85238373Sbde log(LOG_DEBUG,"add_mfc update o %lx g %lx p %x\n", 85338373Sbde (u_long)ntohl(mfccp->mfcc_origin.s_addr), 85438373Sbde (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), 8552531Swollman mfccp->mfcc_parent); 8561541Srgrimes 8571541Srgrimes s = splnet(); 8582531Swollman rt->mfc_parent = mfccp->mfcc_parent; 8592531Swollman for (i = 0; i < numvifs; i++) 8609209Swollman rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; 8612531Swollman splx(s); 8622531Swollman return 0; 8632531Swollman } 8641541Srgrimes 8659209Swollman /* 8662531Swollman * Find the entry for which the upcall was made and update 8672531Swollman */ 8682531Swollman s = splnet(); 8699209Swollman hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr); 87042777Sfenner for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) { 8711541Srgrimes 8729209Swollman if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && 8732531Swollman (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) && 87442777Sfenner (rt->mfc_stall != NULL)) { 8759209Swollman 8769209Swollman if (nstl++) 87738373Sbde log(LOG_ERR, "add_mfc %s o %lx g %lx p %x dbx %p\n", 8789209Swollman "multiple kernel entries", 87938373Sbde (u_long)ntohl(mfccp->mfcc_origin.s_addr), 88038373Sbde (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), 88142777Sfenner mfccp->mfcc_parent, (void *)rt->mfc_stall); 8821541Srgrimes 8839209Swollman if (mrtdebug & DEBUG_MFC) 88438373Sbde log(LOG_DEBUG,"add_mfc o %lx g %lx p %x dbg %p\n", 88538373Sbde (u_long)ntohl(mfccp->mfcc_origin.s_addr), 88638373Sbde (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), 88742777Sfenner mfccp->mfcc_parent, (void *)rt->mfc_stall); 8881541Srgrimes 8899209Swollman rt->mfc_origin = mfccp->mfcc_origin; 8909209Swollman rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; 8919209Swollman rt->mfc_parent = mfccp->mfcc_parent; 8929209Swollman for (i = 0; i < numvifs; i++) 8939209Swollman rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; 8949209Swollman /* initialize pkt counters per src-grp */ 8959209Swollman rt->mfc_pkt_cnt = 0; 8969209Swollman rt->mfc_byte_cnt = 0; 8979209Swollman rt->mfc_wrong_if = 0; 8989209Swollman rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; 8992531Swollman 9009209Swollman rt->mfc_expire = 0; /* Don't clean this guy up */ 9019209Swollman nexpire[hash]--; 9022531Swollman 9032531Swollman /* free packets Qed at the end of this entry */ 90442777Sfenner for (rte = rt->mfc_stall; rte != NULL; ) { 90542777Sfenner struct rtdetq *n = rte->next; 90642777Sfenner 9079209Swollman ip_mdq(rte->m, rte->ifp, rt, -1); 9082531Swollman m_freem(rte->m); 9099209Swollman#ifdef UPCALL_TIMING 9109209Swollman collate(&(rte->t)); 9119209Swollman#endif /* UPCALL_TIMING */ 91242777Sfenner free(rte, M_MRTABLE); 91342777Sfenner rte = n; 9142531Swollman } 91542777Sfenner rt->mfc_stall = NULL; 9161541Srgrimes } 9172531Swollman } 9181541Srgrimes 9192531Swollman /* 9202531Swollman * It is possible that an entry is being inserted without an upcall 9212531Swollman */ 9222531Swollman if (nstl == 0) { 9239209Swollman if (mrtdebug & DEBUG_MFC) 92438373Sbde log(LOG_DEBUG,"add_mfc no upcall h %lu o %lx g %lx p %x\n", 92538373Sbde hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr), 92638373Sbde (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), 9272531Swollman mfccp->mfcc_parent); 9289209Swollman 92942777Sfenner for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) { 9309209Swollman 9319209Swollman if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && 9322531Swollman (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) { 9331541Srgrimes 9342531Swollman rt->mfc_origin = mfccp->mfcc_origin; 9352531Swollman rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; 9362531Swollman rt->mfc_parent = mfccp->mfcc_parent; 9372531Swollman for (i = 0; i < numvifs; i++) 9389209Swollman rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; 9392531Swollman /* initialize pkt counters per src-grp */ 9402531Swollman rt->mfc_pkt_cnt = 0; 9419209Swollman rt->mfc_byte_cnt = 0; 9429209Swollman rt->mfc_wrong_if = 0; 9439209Swollman rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; 9449209Swollman if (rt->mfc_expire) 9459209Swollman nexpire[hash]--; 9469209Swollman rt->mfc_expire = 0; 9472531Swollman } 9482531Swollman } 94942777Sfenner if (rt == NULL) { 9502531Swollman /* no upcall, so make a new entry */ 95142777Sfenner rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT); 95242777Sfenner if (rt == NULL) { 9532531Swollman splx(s); 9542531Swollman return ENOBUFS; 9552531Swollman } 9569209Swollman 9572531Swollman /* insert new entry at head of hash chain */ 9582531Swollman rt->mfc_origin = mfccp->mfcc_origin; 9592531Swollman rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp; 9602531Swollman rt->mfc_parent = mfccp->mfcc_parent; 9612531Swollman for (i = 0; i < numvifs; i++) 9629209Swollman rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; 9632531Swollman /* initialize pkt counters per src-grp */ 9642531Swollman rt->mfc_pkt_cnt = 0; 9659209Swollman rt->mfc_byte_cnt = 0; 9669209Swollman rt->mfc_wrong_if = 0; 9679209Swollman rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0; 9689209Swollman rt->mfc_expire = 0; 96942777Sfenner rt->mfc_stall = NULL; 9709209Swollman 9712531Swollman /* link into table */ 97242777Sfenner rt->mfc_next = mfctable[hash]; 97342777Sfenner mfctable[hash] = rt; 9742531Swollman } 9752531Swollman } 9762531Swollman splx(s); 9772531Swollman return 0; 9781541Srgrimes} 9791541Srgrimes 9809209Swollman#ifdef UPCALL_TIMING 9811541Srgrimes/* 9829209Swollman * collect delay statistics on the upcalls 9839209Swollman */ 9849209Swollmanstatic void collate(t) 9859209Swollmanregister struct timeval *t; 9869209Swollman{ 9879209Swollman register u_long d; 9889209Swollman register struct timeval tp; 9899209Swollman register u_long delta; 9909209Swollman 9919209Swollman GET_TIME(tp); 9929209Swollman 9939209Swollman if (TV_LT(*t, tp)) 9949209Swollman { 9959209Swollman TV_DELTA(tp, *t, delta); 9969209Swollman 9979209Swollman d = delta >> 10; 9989209Swollman if (d > 50) 9999209Swollman d = 50; 10009209Swollman 10019209Swollman ++upcall_data[d]; 10029209Swollman } 10039209Swollman} 10049209Swollman#endif /* UPCALL_TIMING */ 10059209Swollman 10069209Swollman/* 10072531Swollman * Delete an mfc entry 10081541Srgrimes */ 10091541Srgrimesstatic int 10102531Swollmandel_mfc(mfccp) 10119209Swollman struct mfcctl *mfccp; 10121541Srgrimes{ 10132531Swollman struct in_addr origin; 10142531Swollman struct in_addr mcastgrp; 10152531Swollman struct mfc *rt; 101642777Sfenner struct mfc **nptr; 10172531Swollman u_long hash; 101811921Sphk int s; 10191541Srgrimes 10202531Swollman origin = mfccp->mfcc_origin; 10212531Swollman mcastgrp = mfccp->mfcc_mcastgrp; 10229209Swollman hash = MFCHASH(origin.s_addr, mcastgrp.s_addr); 10231541Srgrimes 10249209Swollman if (mrtdebug & DEBUG_MFC) 102538373Sbde log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n", 102638373Sbde (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr)); 10271541Srgrimes 10289209Swollman s = splnet(); 10299209Swollman 10309209Swollman nptr = &mfctable[hash]; 103142777Sfenner while ((rt = *nptr) != NULL) { 10322531Swollman if (origin.s_addr == rt->mfc_origin.s_addr && 10332531Swollman mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr && 103442777Sfenner rt->mfc_stall == NULL) 10352531Swollman break; 10369209Swollman 103742777Sfenner nptr = &rt->mfc_next; 10382531Swollman } 103942777Sfenner if (rt == NULL) { 10409209Swollman splx(s); 10419209Swollman return EADDRNOTAVAIL; 10422531Swollman } 10431541Srgrimes 104442777Sfenner *nptr = rt->mfc_next; 104542777Sfenner free(rt, M_MRTABLE); 10461541Srgrimes 10472531Swollman splx(s); 10482531Swollman 10492531Swollman return 0; 10501541Srgrimes} 10511541Srgrimes 10521541Srgrimes/* 10539209Swollman * Send a message to mrouted on the multicast routing socket 10549209Swollman */ 10559209Swollmanstatic int 10569209Swollmansocket_send(s, mm, src) 10579209Swollman struct socket *s; 10589209Swollman struct mbuf *mm; 10599209Swollman struct sockaddr_in *src; 10609209Swollman{ 10619209Swollman if (s) { 10629209Swollman if (sbappendaddr(&s->so_rcv, 10639209Swollman (struct sockaddr *)src, 10649209Swollman mm, (struct mbuf *)0) != 0) { 10659209Swollman sorwakeup(s); 10669209Swollman return 0; 10679209Swollman } 10689209Swollman } 10699209Swollman m_freem(mm); 10709209Swollman return -1; 10719209Swollman} 10729209Swollman 10739209Swollman/* 10742531Swollman * IP multicast forwarding function. This function assumes that the packet 10752531Swollman * pointed to by "ip" has arrived on (or is about to be sent to) the interface 10762531Swollman * pointed to by "ifp", and the packet is to be relayed to other networks 10772531Swollman * that have members of the packet's destination IP multicast group. 10782531Swollman * 10799209Swollman * The packet is returned unscathed to the caller, unless it is 10809209Swollman * erroneous, in which case a non-zero return value tells the caller to 10812531Swollman * discard it. 10821541Srgrimes */ 10832531Swollman 10842531Swollman#define IP_HDR_LEN 20 /* # bytes of fixed IP header (excluding options) */ 10852531Swollman#define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */ 10862531Swollman 108712296Sphkstatic int 10882763SwollmanX_ip_mforward(ip, ifp, m, imo) 10892531Swollman register struct ip *ip; 10902531Swollman struct ifnet *ifp; 10912754Swollman struct mbuf *m; 10922531Swollman struct ip_moptions *imo; 10931541Srgrimes{ 109414549Sfenner register struct mfc *rt; 10952531Swollman register u_char *ipoptions; 10963747Swollman static struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET }; 10979209Swollman static int srctun = 0; 10982531Swollman register struct mbuf *mm; 10992531Swollman int s; 11009209Swollman vifi_t vifi; 11019209Swollman struct vif *vifp; 11021541Srgrimes 11039209Swollman if (mrtdebug & DEBUG_FORWARD) 110438373Sbde log(LOG_DEBUG, "ip_mforward: src %lx, dst %lx, ifp %p\n", 110538373Sbde (u_long)ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr), 110638373Sbde (void *)ifp); 11071541Srgrimes 11082531Swollman if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 || 11092531Swollman (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) { 11102531Swollman /* 11119209Swollman * Packet arrived via a physical interface or 11129209Swollman * an encapsulated tunnel. 11132531Swollman */ 11142531Swollman } else { 11152531Swollman /* 11162531Swollman * Packet arrived through a source-route tunnel. 11179209Swollman * Source-route tunnels are no longer supported. 11182531Swollman */ 11199209Swollman if ((srctun++ % 1000) == 0) 112038373Sbde log(LOG_ERR, 112138373Sbde "ip_mforward: received source-routed packet from %lx\n", 112238373Sbde (u_long)ntohl(ip->ip_src.s_addr)); 11238876Srgrimes 11249209Swollman return 1; 11259209Swollman } 11269209Swollman 11279209Swollman if ((imo) && ((vifi = imo->imo_multicast_vif) < numvifs)) { 11289209Swollman if (ip->ip_ttl < 255) 11299209Swollman ip->ip_ttl++; /* compensate for -1 in *_send routines */ 11309209Swollman if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { 11319209Swollman vifp = viftable + vifi; 113212296Sphk printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s%d)\n", 11339209Swollman ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), vifi, 11349209Swollman (vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "", 11359209Swollman vifp->v_ifp->if_name, vifp->v_ifp->if_unit); 11362531Swollman } 113714549Sfenner return (ip_mdq(m, ifp, NULL, vifi)); 11382531Swollman } 11399209Swollman if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { 114012296Sphk printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n", 11419209Swollman ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr)); 11429728Swollman if(!imo) 11439728Swollman printf("In fact, no options were specified at all\n"); 11449209Swollman } 11452531Swollman 11462531Swollman /* 11472531Swollman * Don't forward a packet with time-to-live of zero or one, 11482531Swollman * or a packet destined to a local-only group. 11492531Swollman */ 11502531Swollman if (ip->ip_ttl <= 1 || 11512531Swollman ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP) 11529209Swollman return 0; 11532531Swollman 11542531Swollman /* 11552531Swollman * Determine forwarding vifs from the forwarding cache table 11562531Swollman */ 11572531Swollman s = splnet(); 11582531Swollman MFCFIND(ip->ip_src.s_addr, ip->ip_dst.s_addr, rt); 11592531Swollman 11602531Swollman /* Entry exists, so forward if necessary */ 11612531Swollman if (rt != NULL) { 11621541Srgrimes splx(s); 11639209Swollman return (ip_mdq(m, ifp, rt, -1)); 11649209Swollman } else { 11652531Swollman /* 11662531Swollman * If we don't have a route for packet's origin, 11672531Swollman * Make a copy of the packet & 11682531Swollman * send message to routing daemon 11692531Swollman */ 11702531Swollman 11712531Swollman register struct mbuf *mb0; 11722531Swollman register struct rtdetq *rte; 11732531Swollman register u_long hash; 117414549Sfenner int hlen = ip->ip_hl << 2; 11759209Swollman#ifdef UPCALL_TIMING 11769209Swollman struct timeval tp; 11772531Swollman 11789209Swollman GET_TIME(tp); 11799209Swollman#endif 11809209Swollman 11812531Swollman mrtstat.mrts_no_route++; 11829209Swollman if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)) 118338373Sbde log(LOG_DEBUG, "ip_mforward: no rte s %lx g %lx\n", 118438373Sbde (u_long)ntohl(ip->ip_src.s_addr), 118538373Sbde (u_long)ntohl(ip->ip_dst.s_addr)); 11862531Swollman 11879209Swollman /* 11889209Swollman * Allocate mbufs early so that we don't do extra work if we are 118914549Sfenner * just going to fail anyway. Make sure to pullup the header so 119014549Sfenner * that other people can't step on it. 11919209Swollman */ 119242777Sfenner rte = (struct rtdetq *)malloc((sizeof *rte), M_MRTABLE, M_NOWAIT); 119342777Sfenner if (rte == NULL) { 11949209Swollman splx(s); 11959209Swollman return ENOBUFS; 11969209Swollman } 11979209Swollman mb0 = m_copy(m, 0, M_COPYALL); 119814549Sfenner if (mb0 && (M_HASCL(mb0) || mb0->m_len < hlen)) 119914549Sfenner mb0 = m_pullup(mb0, hlen); 12009209Swollman if (mb0 == NULL) { 120142777Sfenner free(rte, M_MRTABLE); 12029209Swollman splx(s); 12039209Swollman return ENOBUFS; 12049209Swollman } 12059209Swollman 12062531Swollman /* is there an upcall waiting for this packet? */ 12079209Swollman hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr); 120842777Sfenner for (rt = mfctable[hash]; rt; rt = rt->mfc_next) { 12099209Swollman if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) && 12102531Swollman (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) && 121142777Sfenner (rt->mfc_stall != NULL)) 12122531Swollman break; 12132531Swollman } 12142531Swollman 121542777Sfenner if (rt == NULL) { 12169209Swollman int i; 12179209Swollman struct igmpmsg *im; 12189209Swollman 12192531Swollman /* no upcall, so make a new entry */ 122042777Sfenner rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT); 122142777Sfenner if (rt == NULL) { 122242777Sfenner free(rte, M_MRTABLE); 12239266Swollman m_freem(mb0); 12242531Swollman splx(s); 12252531Swollman return ENOBUFS; 12262531Swollman } 12279209Swollman /* Make a copy of the header to send to the user level process */ 122817137Sfenner mm = m_copy(mb0, 0, hlen); 12299209Swollman if (mm == NULL) { 123042777Sfenner free(rte, M_MRTABLE); 12319266Swollman m_freem(mb0); 123242777Sfenner free(rt, M_MRTABLE); 12339209Swollman splx(s); 12349209Swollman return ENOBUFS; 12359209Swollman } 12362531Swollman 12379209Swollman /* 12389209Swollman * Send message to routing daemon to install 12399209Swollman * a route into the kernel table 12409209Swollman */ 12419209Swollman k_igmpsrc.sin_addr = ip->ip_src; 12429209Swollman 12439209Swollman im = mtod(mm, struct igmpmsg *); 12449209Swollman im->im_msgtype = IGMPMSG_NOCACHE; 12459209Swollman im->im_mbz = 0; 12469209Swollman 12479209Swollman mrtstat.mrts_upcalls++; 12489209Swollman 12499209Swollman if (socket_send(ip_mrouter, mm, &k_igmpsrc) < 0) { 125011284Swollman log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n"); 12519209Swollman ++mrtstat.mrts_upq_sockfull; 125242777Sfenner free(rte, M_MRTABLE); 12539266Swollman m_freem(mb0); 125442777Sfenner free(rt, M_MRTABLE); 12559209Swollman splx(s); 12569209Swollman return ENOBUFS; 12579209Swollman } 12589209Swollman 12592531Swollman /* insert new entry at head of hash chain */ 12602531Swollman rt->mfc_origin.s_addr = ip->ip_src.s_addr; 12612531Swollman rt->mfc_mcastgrp.s_addr = ip->ip_dst.s_addr; 12629209Swollman rt->mfc_expire = UPCALL_EXPIRE; 12639209Swollman nexpire[hash]++; 12649209Swollman for (i = 0; i < numvifs; i++) 12659209Swollman rt->mfc_ttls[i] = 0; 12669209Swollman rt->mfc_parent = -1; 12672531Swollman 12682531Swollman /* link into table */ 126942777Sfenner rt->mfc_next = mfctable[hash]; 127042777Sfenner mfctable[hash] = rt; 127142777Sfenner rt->mfc_stall = rte; 12722531Swollman 12739209Swollman } else { 12749209Swollman /* determine if q has overflowed */ 127542777Sfenner int npkts = 0; 127642777Sfenner struct rtdetq **p; 127742777Sfenner 127842777Sfenner for (p = &rt->mfc_stall; *p != NULL; p = &(*p)->next) 12799209Swollman npkts++; 12802531Swollman 12819209Swollman if (npkts > MAX_UPQ) { 12829209Swollman mrtstat.mrts_upq_ovflw++; 128342777Sfenner free(rte, M_MRTABLE); 12849266Swollman m_freem(mb0); 12859209Swollman splx(s); 12869209Swollman return 0; 12879209Swollman } 128842777Sfenner 128942777Sfenner /* Add this entry to the end of the queue */ 129042777Sfenner *p = rte; 12912531Swollman } 12922531Swollman 12932531Swollman rte->m = mb0; 12942531Swollman rte->ifp = ifp; 12959209Swollman#ifdef UPCALL_TIMING 12969209Swollman rte->t = tp; 12979209Swollman#endif 129842777Sfenner rte->next = NULL; 12992531Swollman 13002531Swollman splx(s); 13012531Swollman 13022531Swollman return 0; 13039209Swollman } 13041541Srgrimes} 13051541Srgrimes 13062763Swollman#ifndef MROUTE_LKM 13072754Swollmanint (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, 13082763Swollman struct ip_moptions *) = X_ip_mforward; 13092763Swollman#endif 13102754Swollman 13111541Srgrimes/* 13122531Swollman * Clean up the cache entry if upcall is not serviced 13131541Srgrimes */ 13142531Swollmanstatic void 13159209Swollmanexpire_upcalls(void *unused) 13161541Srgrimes{ 13172531Swollman struct rtdetq *rte; 131842777Sfenner struct mfc *mfc, **nptr; 13199209Swollman int i; 13202531Swollman int s; 13211541Srgrimes 13222531Swollman s = splnet(); 13239209Swollman for (i = 0; i < MFCTBLSIZ; i++) { 13249209Swollman if (nexpire[i] == 0) 13259209Swollman continue; 13269209Swollman nptr = &mfctable[i]; 132742777Sfenner for (mfc = *nptr; mfc != NULL; mfc = *nptr) { 13289209Swollman /* 13299209Swollman * Skip real cache entries 13309209Swollman * Make sure it wasn't marked to not expire (shouldn't happen) 13319209Swollman * If it expires now 13329209Swollman */ 133342777Sfenner if (mfc->mfc_stall != NULL && 13349209Swollman mfc->mfc_expire != 0 && 13359209Swollman --mfc->mfc_expire == 0) { 13369209Swollman if (mrtdebug & DEBUG_EXPIRE) 133738373Sbde log(LOG_DEBUG, "expire_upcalls: expiring (%lx %lx)\n", 133838373Sbde (u_long)ntohl(mfc->mfc_origin.s_addr), 133938373Sbde (u_long)ntohl(mfc->mfc_mcastgrp.s_addr)); 13409209Swollman /* 13419209Swollman * drop all the packets 13429209Swollman * free the mbuf with the pkt, if, timing info 13439209Swollman */ 134442777Sfenner for (rte = mfc->mfc_stall; rte; ) { 134542777Sfenner struct rtdetq *n = rte->next; 134642777Sfenner 13479209Swollman m_freem(rte->m); 134842777Sfenner free(rte, M_MRTABLE); 134942777Sfenner rte = n; 13509209Swollman } 13519209Swollman ++mrtstat.mrts_cache_cleanups; 13529209Swollman nexpire[i]--; 13532531Swollman 135442777Sfenner *nptr = mfc->mfc_next; 135542777Sfenner free(mfc, M_MRTABLE); 13569209Swollman } else { 135742777Sfenner nptr = &mfc->mfc_next; 13589209Swollman } 13599209Swollman } 13602531Swollman } 13612531Swollman splx(s); 136229681Sgibbs expire_upcalls_ch = timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT); 13631541Srgrimes} 13641541Srgrimes 13651541Srgrimes/* 13662531Swollman * Packet forwarding routine once entry in the cache is made 13671541Srgrimes */ 13681541Srgrimesstatic int 13699209Swollmanip_mdq(m, ifp, rt, xmt_vif) 13702531Swollman register struct mbuf *m; 13712531Swollman register struct ifnet *ifp; 13722531Swollman register struct mfc *rt; 13739209Swollman register vifi_t xmt_vif; 13741541Srgrimes{ 13752531Swollman register struct ip *ip = mtod(m, struct ip *); 13762531Swollman register vifi_t vifi; 13772531Swollman register struct vif *vifp; 137837288Sphk register int plen = ip->ip_len; 13791541Srgrimes 13809209Swollman/* 13819209Swollman * Macro to send packet on vif. Since RSVP packets don't get counted on 13829209Swollman * input, they shouldn't get counted on output, so statistics keeping is 13839209Swollman * seperate. 13849209Swollman */ 13859209Swollman#define MC_SEND(ip,vifp,m) { \ 13869209Swollman if ((vifp)->v_flags & VIFF_TUNNEL) \ 13879209Swollman encap_send((ip), (vifp), (m)); \ 13889209Swollman else \ 13899209Swollman phyint_send((ip), (vifp), (m)); \ 13909209Swollman} 13919209Swollman 13922531Swollman /* 13939209Swollman * If xmt_vif is not -1, send on only the requested vif. 13949209Swollman * 13959209Swollman * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.) 13969209Swollman */ 13979209Swollman if (xmt_vif < numvifs) { 13989209Swollman MC_SEND(ip, viftable + xmt_vif, m); 13999209Swollman return 1; 14009209Swollman } 14019209Swollman 14029209Swollman /* 14032531Swollman * Don't forward if it didn't arrive from the parent vif for its origin. 14042531Swollman */ 14052531Swollman vifi = rt->mfc_parent; 14069209Swollman if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) { 14072531Swollman /* came in the wrong interface */ 14089209Swollman if (mrtdebug & DEBUG_FORWARD) 140938373Sbde log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n", 141038373Sbde (void *)ifp, vifi, (void *)viftable[vifi].v_ifp); 14112531Swollman ++mrtstat.mrts_wrong_if; 14129209Swollman ++rt->mfc_wrong_if; 14139209Swollman /* 14149209Swollman * If we are doing PIM assert processing, and we are forwarding 14159209Swollman * packets on this interface, and it is a broadcast medium 14169209Swollman * interface (and not a tunnel), send a message to the routing daemon. 14179209Swollman */ 14189209Swollman if (pim_assert && rt->mfc_ttls[vifi] && 14199209Swollman (ifp->if_flags & IFF_BROADCAST) && 14209209Swollman !(viftable[vifi].v_flags & VIFF_TUNNEL)) { 14219209Swollman struct sockaddr_in k_igmpsrc; 14229209Swollman struct mbuf *mm; 14239209Swollman struct igmpmsg *im; 14249209Swollman int hlen = ip->ip_hl << 2; 14259209Swollman struct timeval now; 14269209Swollman register u_long delta; 14279209Swollman 14289209Swollman GET_TIME(now); 14299209Swollman 14309209Swollman TV_DELTA(rt->mfc_last_assert, now, delta); 14319209Swollman 14329209Swollman if (delta > ASSERT_MSG_TIME) { 14339209Swollman mm = m_copy(m, 0, hlen); 14349209Swollman if (mm && (M_HASCL(mm) || mm->m_len < hlen)) 14359209Swollman mm = m_pullup(mm, hlen); 14369209Swollman if (mm == NULL) { 14379209Swollman return ENOBUFS; 14389209Swollman } 14399209Swollman 14409209Swollman rt->mfc_last_assert = now; 14419209Swollman 14429209Swollman im = mtod(mm, struct igmpmsg *); 14439209Swollman im->im_msgtype = IGMPMSG_WRONGVIF; 14449209Swollman im->im_mbz = 0; 14459209Swollman im->im_vif = vifi; 14469209Swollman 14479209Swollman k_igmpsrc.sin_addr = im->im_src; 14489209Swollman 14499334Swollman socket_send(ip_mrouter, mm, &k_igmpsrc); 14509209Swollman } 14519209Swollman } 14529209Swollman return 0; 14532531Swollman } 14541541Srgrimes 14559209Swollman /* If I sourced this packet, it counts as output, else it was input. */ 14569209Swollman if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) { 14579209Swollman viftable[vifi].v_pkt_out++; 14589209Swollman viftable[vifi].v_bytes_out += plen; 14599209Swollman } else { 14609209Swollman viftable[vifi].v_pkt_in++; 14619209Swollman viftable[vifi].v_bytes_in += plen; 14629209Swollman } 14632531Swollman rt->mfc_pkt_cnt++; 14649209Swollman rt->mfc_byte_cnt += plen; 14651541Srgrimes 14662531Swollman /* 14672531Swollman * For each vif, decide if a copy of the packet should be forwarded. 14682531Swollman * Forward if: 14692531Swollman * - the ttl exceeds the vif's threshold 14702531Swollman * - there are group members downstream on interface 14712531Swollman */ 14722531Swollman for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++) 14732531Swollman if ((rt->mfc_ttls[vifi] > 0) && 14749209Swollman (ip->ip_ttl > rt->mfc_ttls[vifi])) { 14759209Swollman vifp->v_pkt_out++; 14769209Swollman vifp->v_bytes_out += plen; 14772531Swollman MC_SEND(ip, vifp, m); 14789209Swollman } 14792531Swollman 14802531Swollman return 0; 14811541Srgrimes} 14821541Srgrimes 14839209Swollman/* 14849209Swollman * check if a vif number is legal/ok. This is used by ip_output, to export 14859209Swollman * numvifs there, 14861541Srgrimes */ 148712296Sphkstatic int 14882763SwollmanX_legal_vif_num(vif) 14892531Swollman int vif; 14909209Swollman{ 14919209Swollman if (vif >= 0 && vif < numvifs) 14922531Swollman return(1); 14932531Swollman else 14942531Swollman return(0); 14952531Swollman} 14962531Swollman 14972763Swollman#ifndef MROUTE_LKM 14982763Swollmanint (*legal_vif_num)(int) = X_legal_vif_num; 14992763Swollman#endif 15002754Swollman 15019209Swollman/* 15029209Swollman * Return the local address used by this vif 15039209Swollman */ 150412296Sphkstatic u_long 15059209SwollmanX_ip_mcast_src(vifi) 15069209Swollman int vifi; 15079209Swollman{ 15089209Swollman if (vifi >= 0 && vifi < numvifs) 15099209Swollman return viftable[vifi].v_lcl_addr.s_addr; 15109209Swollman else 15119209Swollman return INADDR_ANY; 15129209Swollman} 15139209Swollman 15149209Swollman#ifndef MROUTE_LKM 15159209Swollmanu_long (*ip_mcast_src)(int) = X_ip_mcast_src; 15169209Swollman#endif 15179209Swollman 15182531Swollmanstatic void 15192531Swollmanphyint_send(ip, vifp, m) 15202531Swollman struct ip *ip; 15212531Swollman struct vif *vifp; 15222531Swollman struct mbuf *m; 15231541Srgrimes{ 15242531Swollman register struct mbuf *mb_copy; 15259209Swollman register int hlen = ip->ip_hl << 2; 15261541Srgrimes 15273571Swollman /* 15289209Swollman * Make a new reference to the packet; make sure that 15299209Swollman * the IP header is actually copied, not just referenced, 15309209Swollman * so that ip_output() only scribbles on the copy. 15313571Swollman */ 15329209Swollman mb_copy = m_copy(m, 0, M_COPYALL); 15339209Swollman if (mb_copy && (M_HASCL(mb_copy) || mb_copy->m_len < hlen)) 15349209Swollman mb_copy = m_pullup(mb_copy, hlen); 15353571Swollman if (mb_copy == NULL) 15369209Swollman return; 15373571Swollman 153842777Sfenner if (vifp->v_rate_limit == 0) 153910203Swollman tbf_send_packet(vifp, mb_copy); 15402531Swollman else 154110203Swollman tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len); 15422531Swollman} 15431541Srgrimes 15442531Swollmanstatic void 15452531Swollmanencap_send(ip, vifp, m) 15462531Swollman register struct ip *ip; 15472531Swollman register struct vif *vifp; 15482531Swollman register struct mbuf *m; 15491541Srgrimes{ 15502531Swollman register struct mbuf *mb_copy; 15512531Swollman register struct ip *ip_copy; 15522531Swollman register int i, len = ip->ip_len; 15531541Srgrimes 15542531Swollman /* 155535256Sdes * copy the old packet & pullup its IP header into the 15562531Swollman * new mbuf so we can modify it. Try to fill the new 15572531Swollman * mbuf since if we don't the ethernet driver will. 15582531Swollman */ 155919940Sfenner MGETHDR(mb_copy, M_DONTWAIT, MT_HEADER); 15602531Swollman if (mb_copy == NULL) 15612531Swollman return; 156219940Sfenner mb_copy->m_data += max_linkhdr; 15632531Swollman mb_copy->m_len = sizeof(multicast_encap_iphdr); 15641541Srgrimes 15652531Swollman if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == NULL) { 15662531Swollman m_freem(mb_copy); 15672531Swollman return; 15682531Swollman } 15692531Swollman i = MHLEN - M_LEADINGSPACE(mb_copy); 15702531Swollman if (i > len) 15712531Swollman i = len; 15722531Swollman mb_copy = m_pullup(mb_copy, i); 15732531Swollman if (mb_copy == NULL) 15742531Swollman return; 15753571Swollman mb_copy->m_pkthdr.len = len + sizeof(multicast_encap_iphdr); 15761541Srgrimes 15772531Swollman /* 15782531Swollman * fill in the encapsulating IP header. 15792531Swollman */ 15802531Swollman ip_copy = mtod(mb_copy, struct ip *); 15812531Swollman *ip_copy = multicast_encap_iphdr; 15822531Swollman ip_copy->ip_id = htons(ip_id++); 15832531Swollman ip_copy->ip_len += len; 15842531Swollman ip_copy->ip_src = vifp->v_lcl_addr; 15852531Swollman ip_copy->ip_dst = vifp->v_rmt_addr; 15861541Srgrimes 15872531Swollman /* 15882531Swollman * turn the encapsulated IP header back into a valid one. 15892531Swollman */ 15902531Swollman ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr)); 15912531Swollman --ip->ip_ttl; 15922531Swollman HTONS(ip->ip_len); 15932531Swollman HTONS(ip->ip_off); 15942531Swollman ip->ip_sum = 0; 15952531Swollman mb_copy->m_data += sizeof(multicast_encap_iphdr); 15962531Swollman ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2); 15972531Swollman mb_copy->m_data -= sizeof(multicast_encap_iphdr); 15982531Swollman 159942777Sfenner if (vifp->v_rate_limit == 0) 160010203Swollman tbf_send_packet(vifp, mb_copy); 16012531Swollman else 160210203Swollman tbf_control(vifp, mb_copy, ip, ip_copy->ip_len); 16031541Srgrimes} 16041541Srgrimes 16051541Srgrimes/* 16062531Swollman * De-encapsulate a packet and feed it back through ip input (this 16072531Swollman * routine is called whenever IP gets a packet with proto type 16082531Swollman * ENCAP_PROTO and a local destination address). 16091541Srgrimes */ 16102531Swollmanvoid 16112763Swollman#ifdef MROUTE_LKM 161214824SfennerX_ipip_input(m, iphlen) 16132763Swollman#else 16149209Swollmanipip_input(m, iphlen) 16152763Swollman#endif 16169209Swollman register struct mbuf *m; 16179209Swollman int iphlen; 16182531Swollman{ 16192531Swollman struct ifnet *ifp = m->m_pkthdr.rcvif; 16202531Swollman register struct ip *ip = mtod(m, struct ip *); 16212531Swollman register int hlen = ip->ip_hl << 2; 16222531Swollman register int s; 16232531Swollman register struct ifqueue *ifq; 16242531Swollman register struct vif *vifp; 16251541Srgrimes 16269209Swollman if (!have_encap_tunnel) { 162714824Sfenner rip_input(m, iphlen); 16289209Swollman return; 16292531Swollman } 16302531Swollman /* 16312531Swollman * dump the packet if it's not to a multicast destination or if 16322531Swollman * we don't have an encapsulating tunnel with the source. 16332531Swollman * Note: This code assumes that the remote site IP address 16342531Swollman * uniquely identifies the tunnel (i.e., that this site has 16352531Swollman * at most one tunnel with the remote site). 16362531Swollman */ 16372531Swollman if (! IN_MULTICAST(ntohl(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr))) { 16382531Swollman ++mrtstat.mrts_bad_tunnel; 16392531Swollman m_freem(m); 16402531Swollman return; 16412531Swollman } 16422531Swollman if (ip->ip_src.s_addr != last_encap_src) { 16432531Swollman register struct vif *vife; 16449209Swollman 16452531Swollman vifp = viftable; 16462531Swollman vife = vifp + numvifs; 16472531Swollman last_encap_src = ip->ip_src.s_addr; 16482531Swollman last_encap_vif = 0; 16492531Swollman for ( ; vifp < vife; ++vifp) 16502531Swollman if (vifp->v_rmt_addr.s_addr == ip->ip_src.s_addr) { 16512531Swollman if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT)) 16522531Swollman == VIFF_TUNNEL) 16532531Swollman last_encap_vif = vifp; 16542531Swollman break; 16552531Swollman } 16562531Swollman } 16572531Swollman if ((vifp = last_encap_vif) == 0) { 16582531Swollman last_encap_src = 0; 16592531Swollman mrtstat.mrts_cant_tunnel++; /*XXX*/ 16602531Swollman m_freem(m); 16612531Swollman if (mrtdebug) 166238373Sbde log(LOG_DEBUG, "ip_mforward: no tunnel with %lx\n", 166338373Sbde (u_long)ntohl(ip->ip_src.s_addr)); 16642531Swollman return; 16652531Swollman } 16662531Swollman ifp = vifp->v_ifp; 16677083Swollman 16687083Swollman if (hlen > IP_HDR_LEN) 16697083Swollman ip_stripoptions(m, (struct mbuf *) 0); 16707083Swollman m->m_data += IP_HDR_LEN; 16717083Swollman m->m_len -= IP_HDR_LEN; 16727083Swollman m->m_pkthdr.len -= IP_HDR_LEN; 16737083Swollman m->m_pkthdr.rcvif = ifp; 16747083Swollman 16752531Swollman ifq = &ipintrq; 16762531Swollman s = splimp(); 16772531Swollman if (IF_QFULL(ifq)) { 16782531Swollman IF_DROP(ifq); 16792531Swollman m_freem(m); 16802531Swollman } else { 16812531Swollman IF_ENQUEUE(ifq, m); 16822531Swollman /* 16832531Swollman * normally we would need a "schednetisr(NETISR_IP)" 16842531Swollman * here but we were called by ip_input and it is going 16852531Swollman * to loop back & try to dequeue the packet we just 16862531Swollman * queued as soon as we return so we avoid the 16872531Swollman * unnecessary software interrrupt. 16882531Swollman */ 16892531Swollman } 16902531Swollman splx(s); 16912531Swollman} 16921541Srgrimes 16932531Swollman/* 16942531Swollman * Token bucket filter module 16952531Swollman */ 169610203Swollman 16979209Swollmanstatic void 169810203Swollmantbf_control(vifp, m, ip, p_len) 16992531Swollman register struct vif *vifp; 17001541Srgrimes register struct mbuf *m; 17012531Swollman register struct ip *ip; 17022531Swollman register u_long p_len; 17031541Srgrimes{ 170410203Swollman register struct tbf *t = vifp->v_tbf; 170510203Swollman 170610203Swollman if (p_len > MAX_BKT_SIZE) { 170710203Swollman /* drop if packet is too large */ 170810203Swollman mrtstat.mrts_pkt2large++; 170910203Swollman m_freem(m); 171010203Swollman return; 171110203Swollman } 171210203Swollman 17132531Swollman tbf_update_tokens(vifp); 17141541Srgrimes 17159209Swollman /* if there are enough tokens, 17162531Swollman * and the queue is empty, 17172531Swollman * send this packet out 17182531Swollman */ 17192531Swollman 172010203Swollman if (t->tbf_q_len == 0) { 172110203Swollman /* queue empty, send packet if enough tokens */ 172210203Swollman if (p_len <= t->tbf_n_tok) { 172310203Swollman t->tbf_n_tok -= p_len; 172410203Swollman tbf_send_packet(vifp, m); 17251541Srgrimes } else { 17262531Swollman /* queue packet and timeout till later */ 172710203Swollman tbf_queue(vifp, m); 172810203Swollman timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS); 17292531Swollman } 173010203Swollman } else if (t->tbf_q_len < t->tbf_max_q_len) { 17312531Swollman /* finite queue length, so queue pkts and process queue */ 173210203Swollman tbf_queue(vifp, m); 17332531Swollman tbf_process_q(vifp); 17342531Swollman } else { 17352531Swollman /* queue length too much, try to dq and queue and process */ 17362531Swollman if (!tbf_dq_sel(vifp, ip)) { 17372531Swollman mrtstat.mrts_q_overflow++; 17382531Swollman m_freem(m); 17392531Swollman return; 17402531Swollman } else { 174110203Swollman tbf_queue(vifp, m); 17422531Swollman tbf_process_q(vifp); 17432531Swollman } 17442531Swollman } 17452531Swollman return; 17462531Swollman} 17471541Srgrimes 17489209Swollman/* 17492531Swollman * adds a packet to the queue at the interface 17502531Swollman */ 17519209Swollmanstatic void 175210203Swollmantbf_queue(vifp, m) 17532531Swollman register struct vif *vifp; 17542531Swollman register struct mbuf *m; 17552531Swollman{ 17562531Swollman register int s = splnet(); 175710203Swollman register struct tbf *t = vifp->v_tbf; 17581541Srgrimes 175910203Swollman if (t->tbf_t == NULL) { 176010203Swollman /* Queue was empty */ 176110203Swollman t->tbf_q = m; 176210203Swollman } else { 176310203Swollman /* Insert at tail */ 176410203Swollman t->tbf_t->m_act = m; 176510203Swollman } 17661541Srgrimes 176710203Swollman /* Set new tail pointer */ 176810203Swollman t->tbf_t = m; 17691541Srgrimes 177010203Swollman#ifdef DIAGNOSTIC 177110203Swollman /* Make sure we didn't get fed a bogus mbuf */ 177210203Swollman if (m->m_act) 177310203Swollman panic("tbf_queue: m_act"); 177410203Swollman#endif 177510203Swollman m->m_act = NULL; 177610203Swollman 177710203Swollman t->tbf_q_len++; 177810203Swollman 17792531Swollman splx(s); 17802531Swollman} 17811541Srgrimes 17821541Srgrimes 17839209Swollman/* 17842531Swollman * processes the queue at the interface 17852531Swollman */ 17869209Swollmanstatic void 17872531Swollmantbf_process_q(vifp) 17882531Swollman register struct vif *vifp; 17892531Swollman{ 179010203Swollman register struct mbuf *m; 179110203Swollman register int len; 17922531Swollman register int s = splnet(); 179310203Swollman register struct tbf *t = vifp->v_tbf; 17941541Srgrimes 17952531Swollman /* loop through the queue at the interface and send as many packets 17962531Swollman * as possible 17972531Swollman */ 179810203Swollman while (t->tbf_q_len > 0) { 179910203Swollman m = t->tbf_q; 18002531Swollman 180110203Swollman len = mtod(m, struct ip *)->ip_len; 180210203Swollman 18032531Swollman /* determine if the packet can be sent */ 180410203Swollman if (len <= t->tbf_n_tok) { 18052531Swollman /* if so, 180610203Swollman * reduce no of tokens, dequeue the packet, 18072531Swollman * send the packet. 18082531Swollman */ 180910203Swollman t->tbf_n_tok -= len; 18102531Swollman 181110203Swollman t->tbf_q = m->m_act; 181210203Swollman if (--t->tbf_q_len == 0) 181310203Swollman t->tbf_t = NULL; 18142531Swollman 181510203Swollman m->m_act = NULL; 181610203Swollman tbf_send_packet(vifp, m); 18172531Swollman 18182531Swollman } else break; 18192531Swollman } 18202531Swollman splx(s); 18211541Srgrimes} 18221541Srgrimes 18239209Swollmanstatic void 18242531Swollmantbf_reprocess_q(xvifp) 18252531Swollman void *xvifp; 18261541Srgrimes{ 18272531Swollman register struct vif *vifp = xvifp; 18289209Swollman if (ip_mrouter == NULL) 18292531Swollman return; 18301541Srgrimes 18312531Swollman tbf_update_tokens(vifp); 18321541Srgrimes 18332531Swollman tbf_process_q(vifp); 18342531Swollman 183510203Swollman if (vifp->v_tbf->tbf_q_len) 183610203Swollman timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS); 18372531Swollman} 18382531Swollman 18392531Swollman/* function that will selectively discard a member of the queue 184010203Swollman * based on the precedence value and the priority 18412531Swollman */ 18429209Swollmanstatic int 18432531Swollmantbf_dq_sel(vifp, ip) 18442531Swollman register struct vif *vifp; 18452531Swollman register struct ip *ip; 18462531Swollman{ 18472531Swollman register int s = splnet(); 18482531Swollman register u_int p; 184910203Swollman register struct mbuf *m, *last; 185010203Swollman register struct mbuf **np; 185110203Swollman register struct tbf *t = vifp->v_tbf; 18522531Swollman 18532531Swollman p = priority(vifp, ip); 18542531Swollman 185510203Swollman np = &t->tbf_q; 185610203Swollman last = NULL; 185710203Swollman while ((m = *np) != NULL) { 185810203Swollman if (p > priority(vifp, mtod(m, struct ip *))) { 185910203Swollman *np = m->m_act; 186010203Swollman /* If we're removing the last packet, fix the tail pointer */ 186110203Swollman if (m == t->tbf_t) 186210203Swollman t->tbf_t = last; 186310203Swollman m_freem(m); 186410203Swollman /* it's impossible for the queue to be empty, but 186510203Swollman * we check anyway. */ 186610203Swollman if (--t->tbf_q_len == 0) 186710203Swollman t->tbf_t = NULL; 18682531Swollman splx(s); 18692531Swollman mrtstat.mrts_drop_sel++; 18702531Swollman return(1); 18711541Srgrimes } 187210203Swollman np = &m->m_act; 187310203Swollman last = m; 18742531Swollman } 18752531Swollman splx(s); 18762531Swollman return(0); 18772531Swollman} 18781541Srgrimes 18799209Swollmanstatic void 188010203Swollmantbf_send_packet(vifp, m) 18812531Swollman register struct vif *vifp; 18822531Swollman register struct mbuf *m; 18832531Swollman{ 188410203Swollman struct ip_moptions imo; 18852531Swollman int error; 188615292Swollman static struct route ro; 18872531Swollman int s = splnet(); 18881541Srgrimes 18899209Swollman if (vifp->v_flags & VIFF_TUNNEL) { 18902531Swollman /* If tunnel options */ 189115292Swollman ip_output(m, (struct mbuf *)0, &vifp->v_route, 189210203Swollman IP_FORWARDING, (struct ip_moptions *)0); 18932531Swollman } else { 189410203Swollman imo.imo_multicast_ifp = vifp->v_ifp; 189510203Swollman imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1; 189610203Swollman imo.imo_multicast_loop = 1; 189710203Swollman imo.imo_multicast_vif = -1; 189810203Swollman 189915292Swollman /* 190015292Swollman * Re-entrancy should not be a problem here, because 190115292Swollman * the packets that we send out and are looped back at us 190215292Swollman * should get rejected because they appear to come from 190315292Swollman * the loopback interface, thus preventing looping. 190415292Swollman */ 190515292Swollman error = ip_output(m, (struct mbuf *)0, &ro, 190610203Swollman IP_FORWARDING, &imo); 19072531Swollman 19089209Swollman if (mrtdebug & DEBUG_XMIT) 190911284Swollman log(LOG_DEBUG, "phyint_send on vif %d err %d\n", 191011284Swollman vifp - viftable, error); 19112531Swollman } 19122531Swollman splx(s); 19131541Srgrimes} 19142531Swollman 19152531Swollman/* determine the current time and then 19162531Swollman * the elapsed time (between the last time and time now) 19172531Swollman * in milliseconds & update the no. of tokens in the bucket 19182531Swollman */ 19199209Swollmanstatic void 19202531Swollmantbf_update_tokens(vifp) 19212531Swollman register struct vif *vifp; 19222531Swollman{ 19232531Swollman struct timeval tp; 192410203Swollman register u_long tm; 19252531Swollman register int s = splnet(); 192610203Swollman register struct tbf *t = vifp->v_tbf; 19272531Swollman 19282531Swollman GET_TIME(tp); 19292531Swollman 193010203Swollman TV_DELTA(tp, t->tbf_last_pkt_t, tm); 19312531Swollman 193210203Swollman /* 193310203Swollman * This formula is actually 193410203Swollman * "time in seconds" * "bytes/second". 193510203Swollman * 193610203Swollman * (tm / 1000000) * (v_rate_limit * 1000 * (1000/1024) / 8) 193710203Swollman * 193810203Swollman * The (1000/1024) was introduced in add_vif to optimize 193910203Swollman * this divide into a shift. 194010203Swollman */ 194110203Swollman t->tbf_n_tok += tm * vifp->v_rate_limit / 1024 / 8; 194210203Swollman t->tbf_last_pkt_t = tp; 19432531Swollman 194410203Swollman if (t->tbf_n_tok > MAX_BKT_SIZE) 194510203Swollman t->tbf_n_tok = MAX_BKT_SIZE; 19462531Swollman 19472531Swollman splx(s); 19482531Swollman} 19492531Swollman 19502531Swollmanstatic int 19512531Swollmanpriority(vifp, ip) 19522531Swollman register struct vif *vifp; 19532531Swollman register struct ip *ip; 19542531Swollman{ 19552531Swollman register int prio; 19562531Swollman 19579209Swollman /* temporary hack; may add general packet classifier some day */ 19582531Swollman 19599209Swollman /* 19609209Swollman * The UDP port space is divided up into four priority ranges: 19619209Swollman * [0, 16384) : unclassified - lowest priority 19629209Swollman * [16384, 32768) : audio - highest priority 19639209Swollman * [32768, 49152) : whiteboard - medium priority 19649209Swollman * [49152, 65536) : video - low priority 19659209Swollman */ 19669209Swollman if (ip->ip_p == IPPROTO_UDP) { 19679209Swollman struct udphdr *udp = (struct udphdr *)(((char *)ip) + (ip->ip_hl << 2)); 19689209Swollman switch (ntohs(udp->uh_dport) & 0xc000) { 19699209Swollman case 0x4000: 19709209Swollman prio = 70; 19719209Swollman break; 19729209Swollman case 0x8000: 19739209Swollman prio = 60; 19749209Swollman break; 19759209Swollman case 0xc000: 19769209Swollman prio = 55; 19779209Swollman break; 19789209Swollman default: 19799209Swollman prio = 50; 19809209Swollman break; 19819209Swollman } 19829209Swollman if (tbfdebug > 1) 198311284Swollman log(LOG_DEBUG, "port %x prio%d\n", ntohs(udp->uh_dport), prio); 19849209Swollman } else { 19859209Swollman prio = 50; 19869209Swollman } 19879209Swollman return prio; 19889209Swollman} 19898876Srgrimes 19909209Swollman/* 19919209Swollman * End of token bucket filter modifications 19929209Swollman */ 19932531Swollman 19949209Swollmanint 199538482Swollmanip_rsvp_vif_init(so, sopt) 199638482Swollman struct socket *so; 199738482Swollman struct sockopt *sopt; 19989209Swollman{ 199938482Swollman int error, i, s; 20009209Swollman 20019209Swollman if (rsvpdebug) 20029209Swollman printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n", 20039209Swollman so->so_type, so->so_proto->pr_protocol); 20049209Swollman 20059209Swollman if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) 20069209Swollman return EOPNOTSUPP; 20079209Swollman 20089209Swollman /* Check mbuf. */ 200938482Swollman error = sooptcopyin(sopt, &i, sizeof i, sizeof i); 201038482Swollman if (error) 201138482Swollman return (error); 20129209Swollman 20139209Swollman if (rsvpdebug) 201438482Swollman printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n", i, rsvp_on); 20159209Swollman 20169209Swollman s = splnet(); 20172531Swollman 20189209Swollman /* Check vif. */ 20199209Swollman if (!legal_vif_num(i)) { 20209209Swollman splx(s); 20219209Swollman return EADDRNOTAVAIL; 20229209Swollman } 20232531Swollman 20249209Swollman /* Check if socket is available. */ 20259209Swollman if (viftable[i].v_rsvpd != NULL) { 20269209Swollman splx(s); 20279209Swollman return EADDRINUSE; 20289209Swollman } 20299209Swollman 20309209Swollman viftable[i].v_rsvpd = so; 20319209Swollman /* This may seem silly, but we need to be sure we don't over-increment 20329209Swollman * the RSVP counter, in case something slips up. 20339209Swollman */ 20349209Swollman if (!viftable[i].v_rsvp_on) { 20359209Swollman viftable[i].v_rsvp_on = 1; 20369209Swollman rsvp_on++; 20379209Swollman } 20389209Swollman 20399209Swollman splx(s); 20409209Swollman return 0; 20412531Swollman} 20422531Swollman 20439209Swollmanint 204438482Swollmanip_rsvp_vif_done(so, sopt) 204538482Swollman struct socket *so; 204638482Swollman struct sockopt *sopt; 20479209Swollman{ 204838482Swollman int error, i, s; 20499209Swollman 205038482Swollman if (rsvpdebug) 205138482Swollman printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n", 205238482Swollman so->so_type, so->so_proto->pr_protocol); 20539209Swollman 205438482Swollman if (so->so_type != SOCK_RAW || 205538482Swollman so->so_proto->pr_protocol != IPPROTO_RSVP) 205638482Swollman return EOPNOTSUPP; 20579209Swollman 205838482Swollman error = sooptcopyin(sopt, &i, sizeof i, sizeof i); 205938482Swollman if (error) 206038482Swollman return (error); 20619209Swollman 206238482Swollman s = splnet(); 20639209Swollman 206438482Swollman /* Check vif. */ 206538482Swollman if (!legal_vif_num(i)) { 206638482Swollman splx(s); 206738482Swollman return EADDRNOTAVAIL; 206838482Swollman } 20692531Swollman 207038482Swollman if (rsvpdebug) 207138482Swollman printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n", 207238482Swollman viftable[i].v_rsvpd, so); 20739209Swollman 207438482Swollman viftable[i].v_rsvpd = NULL; 207538482Swollman /* 207638482Swollman * This may seem silly, but we need to be sure we don't over-decrement 207738482Swollman * the RSVP counter, in case something slips up. 207838482Swollman */ 207938482Swollman if (viftable[i].v_rsvp_on) { 208038482Swollman viftable[i].v_rsvp_on = 0; 208138482Swollman rsvp_on--; 208238482Swollman } 20839209Swollman 208438482Swollman splx(s); 208538482Swollman return 0; 20869209Swollman} 20879209Swollman 20889209Swollmanvoid 20899209Swollmanip_rsvp_force_done(so) 20909209Swollman struct socket *so; 20919209Swollman{ 20929209Swollman int vifi; 20939209Swollman register int s; 20949209Swollman 20959209Swollman /* Don't bother if it is not the right type of socket. */ 20969209Swollman if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) 20979209Swollman return; 20989209Swollman 20999209Swollman s = splnet(); 21009209Swollman 21019209Swollman /* The socket may be attached to more than one vif...this 21029209Swollman * is perfectly legal. 21039209Swollman */ 21049209Swollman for (vifi = 0; vifi < numvifs; vifi++) { 21059209Swollman if (viftable[vifi].v_rsvpd == so) { 21069209Swollman viftable[vifi].v_rsvpd = NULL; 21079209Swollman /* This may seem silly, but we need to be sure we don't 21089209Swollman * over-decrement the RSVP counter, in case something slips up. 21099209Swollman */ 21109209Swollman if (viftable[vifi].v_rsvp_on) { 21119209Swollman viftable[vifi].v_rsvp_on = 0; 21129209Swollman rsvp_on--; 21139209Swollman } 21149209Swollman } 21159209Swollman } 21169209Swollman 21179209Swollman splx(s); 21189209Swollman return; 21199209Swollman} 21209209Swollman 21219209Swollmanvoid 21229682Swollmanrsvp_input(m, iphlen) 21239682Swollman struct mbuf *m; 21249682Swollman int iphlen; 21259209Swollman{ 21269209Swollman int vifi; 21279209Swollman register struct ip *ip = mtod(m, struct ip *); 21289682Swollman static struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET }; 21299209Swollman register int s; 21309682Swollman struct ifnet *ifp; 21319209Swollman 21329209Swollman if (rsvpdebug) 21339209Swollman printf("rsvp_input: rsvp_on %d\n",rsvp_on); 21349209Swollman 21359209Swollman /* Can still get packets with rsvp_on = 0 if there is a local member 21369209Swollman * of the group to which the RSVP packet is addressed. But in this 21379209Swollman * case we want to throw the packet away. 21389209Swollman */ 21399209Swollman if (!rsvp_on) { 21409209Swollman m_freem(m); 21419209Swollman return; 21429209Swollman } 21439209Swollman 21449209Swollman /* If the old-style non-vif-associated socket is set, then use 21459209Swollman * it and ignore the new ones. 21469209Swollman */ 21479209Swollman if (ip_rsvpd != NULL) { 21489209Swollman if (rsvpdebug) 21499209Swollman printf("rsvp_input: Sending packet up old-style socket\n"); 215014824Sfenner rip_input(m, iphlen); 21519209Swollman return; 21529209Swollman } 21539209Swollman 21549209Swollman s = splnet(); 21559209Swollman 21569209Swollman if (rsvpdebug) 21579209Swollman printf("rsvp_input: check vifs\n"); 21589209Swollman 21599682Swollman#ifdef DIAGNOSTIC 21609682Swollman if (!(m->m_flags & M_PKTHDR)) 21619682Swollman panic("rsvp_input no hdr"); 21629682Swollman#endif 21639682Swollman 21649682Swollman ifp = m->m_pkthdr.rcvif; 21659209Swollman /* Find which vif the packet arrived on. */ 21669209Swollman for (vifi = 0; vifi < numvifs; vifi++) { 21679209Swollman if (viftable[vifi].v_ifp == ifp) 21689209Swollman break; 21699209Swollman } 21709209Swollman 21719209Swollman if (vifi == numvifs) { 21729209Swollman /* Can't find vif packet arrived on. Drop packet. */ 21739209Swollman if (rsvpdebug) 21749209Swollman printf("rsvp_input: Can't find vif for packet...dropping it.\n"); 21759209Swollman m_freem(m); 21769209Swollman splx(s); 21779209Swollman return; 21789209Swollman } 21799209Swollman 21809209Swollman if (rsvpdebug) 21819209Swollman printf("rsvp_input: check socket\n"); 21829209Swollman 21839209Swollman if (viftable[vifi].v_rsvpd == NULL) { 21849209Swollman /* drop packet, since there is no specific socket for this 21859209Swollman * interface */ 21869209Swollman if (rsvpdebug) 21879209Swollman printf("rsvp_input: No socket defined for vif %d\n",vifi); 21889209Swollman m_freem(m); 21899209Swollman splx(s); 21909209Swollman return; 21919209Swollman } 21929209Swollman rsvp_src.sin_addr = ip->ip_src; 21939209Swollman 21949209Swollman if (rsvpdebug && m) 219512296Sphk printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n", 21969209Swollman m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv))); 21979209Swollman 219846568Speter if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) { 21999209Swollman if (rsvpdebug) 22009209Swollman printf("rsvp_input: Failed to append to socket\n"); 220146568Speter } else { 22029209Swollman if (rsvpdebug) 22039209Swollman printf("rsvp_input: send packet up\n"); 220446568Speter } 220546568Speter 22069209Swollman splx(s); 22079209Swollman} 22089209Swollman 22092763Swollman#ifdef MROUTE_LKM 22102763Swollman#include <sys/conf.h> 22112763Swollman#include <sys/exec.h> 22122763Swollman#include <sys/sysent.h> 22132763Swollman#include <sys/lkm.h> 22142531Swollman 22152763SwollmanMOD_MISC("ip_mroute_mod") 22162763Swollman 22172763Swollmanstatic int 22182763Swollmanip_mroute_mod_handle(struct lkm_table *lkmtp, int cmd) 22192763Swollman{ 22202763Swollman int i; 22212763Swollman struct lkm_misc *args = lkmtp->private.lkm_misc; 22222763Swollman int err = 0; 22232763Swollman 22242763Swollman switch(cmd) { 22252763Swollman static int (*old_ip_mrouter_cmd)(); 22262763Swollman static int (*old_ip_mrouter_done)(); 22272763Swollman static int (*old_ip_mforward)(); 22282763Swollman static int (*old_mrt_ioctl)(); 22296616Sbde static void (*old_proto4_input)(); 22302763Swollman static int (*old_legal_vif_num)(); 22312763Swollman extern struct protosw inetsw[]; 22322763Swollman 22332763Swollman case LKM_E_LOAD: 22342763Swollman if(lkmexists(lkmtp) || ip_mrtproto) 22352763Swollman return(EEXIST); 22362763Swollman old_ip_mrouter_cmd = ip_mrouter_cmd; 22372763Swollman ip_mrouter_cmd = X_ip_mrouter_cmd; 22382763Swollman old_ip_mrouter_done = ip_mrouter_done; 22392763Swollman ip_mrouter_done = X_ip_mrouter_done; 22402763Swollman old_ip_mforward = ip_mforward; 22412763Swollman ip_mforward = X_ip_mforward; 22422763Swollman old_mrt_ioctl = mrt_ioctl; 22432763Swollman mrt_ioctl = X_mrt_ioctl; 22447083Swollman old_proto4_input = inetsw[ip_protox[ENCAP_PROTO]].pr_input; 22459209Swollman inetsw[ip_protox[ENCAP_PROTO]].pr_input = X_ipip_input; 22462763Swollman old_legal_vif_num = legal_vif_num; 22472763Swollman legal_vif_num = X_legal_vif_num; 22482763Swollman ip_mrtproto = IGMP_DVMRP; 22492763Swollman 22502763Swollman printf("\nIP multicast routing loaded\n"); 22512763Swollman break; 22522763Swollman 22532763Swollman case LKM_E_UNLOAD: 22542763Swollman if (ip_mrouter) 22552763Swollman return EINVAL; 22562763Swollman 22572763Swollman ip_mrouter_cmd = old_ip_mrouter_cmd; 22582763Swollman ip_mrouter_done = old_ip_mrouter_done; 22592763Swollman ip_mforward = old_ip_mforward; 22602763Swollman mrt_ioctl = old_mrt_ioctl; 22617083Swollman inetsw[ip_protox[ENCAP_PROTO]].pr_input = old_proto4_input; 22622763Swollman legal_vif_num = old_legal_vif_num; 22632763Swollman ip_mrtproto = 0; 22642763Swollman break; 22652763Swollman 22662763Swollman default: 22672763Swollman err = EINVAL; 22682763Swollman break; 22692763Swollman } 22702763Swollman 22712763Swollman return(err); 22722763Swollman} 22732763Swollman 22742763Swollmanint 22752763Swollmanip_mroute_mod(struct lkm_table *lkmtp, int cmd, int ver) { 22762763Swollman DISPATCH(lkmtp, cmd, ver, ip_mroute_mod_handle, ip_mroute_mod_handle, 22772763Swollman nosys); 22782763Swollman} 22792763Swollman 22802763Swollman#endif /* MROUTE_LKM */ 22812763Swollman#endif /* MROUTING */ 2282