📄 ip_mroute.c
字号:
/* ip_mroute.c - internet multicast routing routines *//* Copyright 1984-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * IP multicast forwarding procedures * * Written by David Waitzman, BBN Labs, August 1988. * Modified by Steve Deering, Stanford, February 1989. * Modified by Mark J. Steiglitz, Stanford, May, 1991 * Modified by Van Jacobson, LBL, January 1993 * Modified by Ajit Thyagarajan, PARC, August 1993 * Modified by Bill Fenner, PARC, April 1995 * * MROUTING Revision: 3.5 * $Id: ip_mroute.c,v 1.53 1999/01/18 02:06:57 fenner Exp $ *//*modification history--------------------01i,16jul02,gls removed include of igmpRouterLib.h01h,25oct01,rae _mCastRouteFwdHook must be IMPORT01g,12oct01,rae merge from truestack ver 01x, base 01e (SPRs 70325, 69594, 69643, upgrade to MROUTE 3.5, etc).01f,24sep01,gls removed definition and use of __P() macro (SPR #28330)01e,21aug98,n_s fixed add_lgrp () call to MALLOC(). spr20595.01d,08apr97,vin added mCastRouteFwdHook deleted ip_mrouter.01c,05dec96,vin changed malloc(..) to MALLOC(..) to use only network buffers, changed free(..) to FREE(..).01b,22nov96,vin added cluster support replaced m_gethdr(..) with mHdrClGet(..)01a,03mar96,vin created from BSD4.4 stuff.*/#include "vxWorks.h"/* mandatory vxWorks header */#include "errno.h"#include "timers.h"#include "net/mbuf.h"#include "sys/socket.h"#include "sys/times.h"#include "net/socketvar.h"#include "net/protosw.h"#include "sys/times.h"#include "net/route.h"#include "net/mbuf.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "netinet/ip_var.h"#include "netinet/in_var.h"#include "netinet/igmp.h"#include "netinet/igmp_var.h"#include "memPartLib.h"#include "tickLib.h"#include "wdLib.h"#include "sockLib.h"#include "timers.h"#include "net/mbuf.h"#include "wdLib.h"#include "netinet/ip_mroute.h"#include "netinet/udp.h"#include "netLib.h"#include "net/systm.h"#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET#include "wvNetLib.h"#endif#endif#ifdef VIRTUAL_STACK#include "netinet/vsLib.h"#include "netinet/vsIgmp.h"#include "netinet/vsMcast.h"#endif /* VIRTUAL_STACK */#ifndef NTOHL#if BYTE_ORDER != BIG_ENDIAN#define NTOHL(d) ((d) = ntohl((d)))#define NTOHS(d) ((d) = ntohs((u_short)(d)))#define HTONL(d) ((d) = htonl((d)))#define HTONS(d) ((d) = htons((u_short)(d)))#else#define NTOHL(d)#define NTOHS(d)#define HTONL(d)#define HTONS(d)#endif#endif/* * Macros for handling bitmaps with one bit per virtual interface. */#define ALL_VIFS (vifi_t)-1#define VIFM_SET(n, m) ((m) |= (1 << (n)))#define VIFM_CLR(n, m) ((m) &= ~(1 << (n)))#define VIFM_ISSET(n, m) ((m) & (1 << (n)))#define VIFM_CLRALL(m) ((m) = 0x00000000)#define VIFM_COPY(mfrom, mto) ((mto) = (mfrom))#define VIFM_SAME(m1, m2) ((m1) == (m2))/* * Globals. All but ip_mrouter and ip_mrtproto could be static, * except for netstat or debugging purposes. */#ifndef VIRTUAL_STACKextern USHORT ip_id;struct socket * ip_mrouter = 0;IMPORT FUNCPTR _mCastRouteFwdHook;FUNCPTR _pimCacheMissSendHook;static struct mrtstat mrtstat;/* table of mfc entries */static struct mfc *mfctable[MFCTBLSIZ];static u_char nexpire[MFCTBLSIZ];/* table of virtual interfaces */static struct vif viftable[MAXVIFS];static u_int mrtdebug = 0; /* debug level */static u_int tbfdebug = 0; /* tbf debug level */struct mroute_timer_struct* expire_upcalls_ch;/* * Define the token bucket filter structures * tbftable -> each vif has one of these for storing info */static struct tbf tbftable[MAXVIFS];/* * 'Interfaces' associated with decapsulator (so we can tell * packets that went through it from ones that get reflected * by a broken gateway). These interfaces are never linked into * the system ifnet list & no routes point to them. I.e., packets * can't be sent this way. They only exist as a placeholder for * multicast source verification. */static struct ifnet multicast_decap_if[MAXVIFS];/* * Private variables. */static vifi_t numvifs = 0;static int have_encap_tunnel = 0;/* * one-back cache used by ipip_input to locate a tunnel's vif * given a datagram's src ip address. */static u_long last_encap_src;static struct vif *last_encap_vif;int pim_assert;#endif /* VIRTUAL_STACK */#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* Set common fields of event identifiers for this module. */LOCAL UCHAR wvNetModuleId = WV_NET_IPMROUTE_MODULE; /* Value for ip_mroute.c */LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE; /* Available event filter */LOCAL ULONG wvNetEventId; /* Event identifier: see wvNetLib.h */#endif /* INCLUDE_WVNET */#endif/* prototype IP hdr for encapsulated packets */static struct ip multicast_encap_iphdr = {#if BYTE_ORDER == LITTLE_ENDIAN sizeof(struct ip) >> 2, IPVERSION,#else IPVERSION, sizeof(struct ip) >> 2,#endif 0, /* tos */ sizeof(struct ip), /* total length */ 0, /* id */ 0, /* frag offset */ ENCAP_TTL, ENCAP_PROTO, 0, /* checksum */};/* * The timer is a wrapper for watchdog timers... functionality from the net/3 release of the bsd code. */enum sopt_dir { SOPT_GET, SOPT_SET };struct sockopt { enum sopt_dir sopt_dir; /* is this a get or a set? */ int sopt_level; /* second arg of [gs]etsockopt */ int sopt_name; /* third arg of [gs]etsockopt */ void *sopt_val; /* fourth arg of [gs]etsockopt */ size_t sopt_valsize; /* (almost) fifth arg of [gs]etsockopt */ struct proc *sopt_p; /* calling process or null if kernel */};/* timer struct here enables */typedef struct mroute_timer_struct{ WDOG_ID watchdog_id; VOIDFUNCPTR expire_routine; void* argument;} MROUTE_TIMER_STRUCT;static u_long X_ip_mcast_src __P((int vifi));static int X_ip_mforward __P(( struct mbuf *m, struct ifnet *ifp, struct ip *ip, struct ip_moptions *imo) );static int X_ip_mrouter_done __P((void));static int X_ip_mrouter_get __P((struct socket *so, struct sockopt *m));static int X_ip_mrouter_set __P((struct socket *so, struct sockopt *m));static int X_legal_vif_num __P((int vif));static int X_mrt_ioctl __P((int cmd, caddr_t data));static int get_sg_cnt(struct sioc_sg_req *);static int get_vif_cnt(struct sioc_vif_req *);static int ip_mrouter_init(struct socket *, int);static int add_vif(struct vifctl *);static int del_vif(vifi_t);static int add_mfc(struct mfcctl *);static int del_mfc(struct mfcctl *);static int set_assert(FUNCPTR);static int setDebug(int);static void expire_upcalls(void *);static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t);static void phyint_send(struct ip *, struct vif *, struct mbuf *);static void encap_send(struct ip *, struct vif *, struct mbuf *);static void tbf_control(struct vif *, struct mbuf *, struct ip *, u_long);static void tbf_queue(struct vif *, struct mbuf *);static void tbf_process_q(struct vif *);static void tbf_reprocess_q(void *);static int tbf_dq_sel(struct vif *, struct ip *);static void tbf_send_packet(struct vif *, struct mbuf *);static void tbf_update_tokens(struct vif *);static int priority(struct vif *, struct ip *);void multiencap_decap(struct mbuf *);static void mRouteDumpMfctable();static BOOL oifListIsEmpty(struct mfc* rt);static int mRouteOifsAdd(struct mfc* rt, int oif, int ttl);static int mRouteOifsRemove(struct mfc* rt, int oif);static int mRouteGroupLoopRemove(struct mfc* rt, struct mfc* root);int (*ip_mrouter_done)(void) = X_ip_mrouter_done;u_long (*ip_mcast_src)(int) = X_ip_mcast_src;/* From other BSD code that has yet to be ported */static intsooptcopyin(struct sockopt *, void *, size_t, size_t);static intsooptcopyout(struct sockopt *, void *, size_t);static intif_allmulti(struct ifnet *, int);/* wrappers for timers in mroute */static void mRouteNetJobAdd(MROUTE_TIMER_STRUCT* p_timer_struct_object);static MROUTE_TIMER_STRUCT* mRouteTimeout(VOIDFUNCPTR expire_routine, void* argument, int number_of_ticks);static void mRouteUntimeOut(MROUTE_TIMER_STRUCT* p_timer_struct);#define timeout mRouteTimeout#define untimeout mRouteUntimeOut/* vxWorks wrapper for tickGet */#define GET_TIME(t) t = tickGet(); #ifdef _WRS_VXWORKS_5_X#define mRouteNameToPort(ignore, both) 1#else#define mRouteNameToPort igmpNameToPort#endif#ifndef MRT_ALLOC#define MRT_ALLOC KHEAP_ALLOC#endif#ifndef MRT_FREE #define MRT_FREE KHEAP_FREE#endif/* wrapper for header length */#define MLEN (MSIZE - sizeof(M_BLK_HDR)) /* normal data len */#define MHLEN (MLEN - sizeof(M_PKT_HDR)) /* data len w/pkthdr */#define MRTDEBUG(printThis, string, param1, param2, param3, param4, param5, param6) \ {\ if ( (_func_logMsg != NULL) && (printThis) )\ (* _func_logMsg) (string, param1, param2, param3, param4, param5, param6);\ }/* bsd function wrapper */#define MGETHDR(m, how, type) {\ m = mHdrClGet(M_DONTWAIT, MT_DATA, sizeof(*m), TRUE);\ }/* * Hash function for a source, group entry */#define MFCHASH(a, g) MFCHASHMOD(((a) >> 20) ^ ((a) >> 10) ^ (a) ^ \ ((g) >> 20) ^ ((g) >> 10) ^ (g))/* * Find a route for a given origin IP address and Multicast group address * Type of service parameter to be added in the future!!! */#define MFCFIND(o, g, rt) { \ struct mfc *_rt = mfctable[MFCHASH(o,g)]; \ rt = NULL; \ ++mrtstat.mrts_mfc_lookups; \ while (_rt) { \ if ((_rt->mfc_origin.s_addr == o) && \ (_rt->mfc_mcastgrp.s_addr == g) && \ (_rt->mfc_stall == NULL)) { \ rt = _rt; \ break; \ } \ _rt = _rt->mfc_next; \ } \ if (rt == NULL) { \ ++mrtstat.mrts_mfc_misses; \ } \}/* * Macros to compute elapsed time efficiently * Borrowed from Van Jacobson's scheduling code */#define TV_DELTA(a, b, delta) delta = (a) - (b);#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \ (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)/* The net/3 code uses the X_ip_mrouter_set command to handle socket options in * a slightly different format. X_ip_mrouter_cmd reformats the parameters */int X_ip_mrouter_cmd(cmd, so, m)int cmd;struct socket* so;struct mbuf* m;{ struct sockopt socket_option; int result; socket_option.sopt_name = cmd; if (m == NULL) { return (ERROR); } else { socket_option.sopt_val = m->m_data; socket_option.sopt_valsize = m->mBlkHdr.mLen; } result = X_ip_mrouter_set(so, &socket_option); return (0);}int ip_mrouter_cmd (int cmd, struct socket* so, struct mbuf* m) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 10, 12, WV_NETEVENT_IPMRT_START, so->so_fd, cmd)#endif /* INCLUDE_WVNET */#endif return X_ip_mrouter_cmd(cmd, so, m);}/* * Handle MRT setsockopt commands to modify the multicast routing tables. */static intX_ip_mrouter_set(so, sopt) struct socket *so; struct sockopt *sopt;{ int error, optval; vifi_t vifi; struct vifctl vifc; struct mfcctl mfc; error = 0; optval = 0; switch (sopt->sopt_name) { case MRT_INIT: error = sooptcopyin(sopt, &optval, sizeof (optval), sizeof (optval) ); optval = (int)(sopt->sopt_val); if (error) break; MRTDEBUG ( (mrtdebug &DEBUG_MFC), "MROUTE: IP_MROUTER received ip_mrouter init so=%p, optval=%i.\n", (int)so, optval,3,4,5,6 ); error = ip_mrouter_init(so, optval); break; case MRT_DONE: MRTDEBUG ( (mrtdebug &DEBUG_MFC), "MROUTE: IP_MROUTER received MRT_DONE.\n", 1,2,3,4,5,6 ); error = ip_mrouter_done(); break; case MRT_ADD_VIF: MRTDEBUG ( (mrtdebug &DEBUG_MFC), "MROUTE: IP_MROUTER received MRT_ADD_VIF.\n", 1,2,3,4,5,6 ); error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc); if (error) break; error = add_vif(&vifc); break; case MRT_DEL_VIF: MRTDEBUG ( (mrtdebug &DEBUG_MFC), "MROUTE: IP_MROUTER received MRT_DEL_VIF.\n", 1,2,3,4,5,6 ); error = sooptcopyin(sopt, &vifi, sizeof (vifi), sizeof (vifi)); if (error) break; error = del_vif(vifi); break; case MRT_ADD_MFC: case MRT_DEL_MFC: MRTDEBUG ( (mrtdebug &DEBUG_MFC), "MROUTE: IP_MROUTER received MRT_ADD/DEL_MFC.\n", 1,2,3,4,5,6 ); error = sooptcopyin(sopt, &mfc, sizeof mfc, sizeof mfc); if (error){ MRTDEBUG(mrtdebug,"MROUTE: I am not dqing... sooptcopyin error.\n",1,2,3,4,5,6); break; } if (sopt->sopt_name == MRT_ADD_MFC) error = add_mfc(&mfc); else error = del_mfc(&mfc); break; case MRT_ASSERT: MRTDEBUG ( (mrtdebug &DEBUG_MFC), "MROUTE: IP_MROUTER received MRT_ASSERT.\n", 1,2,3,4,5,6 ); error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); if (error) break; set_assert( (FUNCPTR) optval); break; case MRT_DEBUG: MRTDEBUG ( (mrtdebug &DEBUG_MFC), "MROUTE: IP_MROUTER received MRT_DEBUG.\n", 1,2,3,4,5,6 ); error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); if (error) break; setDebug(optval); break; default:#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 23, 3, WV_NETEVENT_IPMRT_BADCMD, sopt->sopt_name)#endif /* INCLUDE_WVNET */#endif error = EOPNOTSUPP; break; } return (error);}int (*ip_mrouter_set)(struct socket *, struct sockopt *) = X_ip_mrouter_set;/* * Handle MRT getsockopt commands */static intX_ip_mrouter_get(so, sopt) struct socket *so; struct sockopt *sopt;{ int error; static int version = 0x0305; /* !!! why is this here? XXX */ switch (sopt->sopt_name) { case MRT_VERSION: error = sooptcopyout(sopt, &version, sizeof version); break; case MRT_ASSERT: error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert); break; default: error = EOPNOTSUPP; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -