⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip_mroute.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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.2 1998/08/21 13:04:54 joel Exp $ */#include "opt_mrouting.h"#include <sys/param.h>#include <sys/queue.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/protosw.h>#include <sys/errno.h>#include <sys/time.h>#include <sys/kernel.h>#include <sys/ioctl.h>#include <sys/syslog.h>#include <net/if.h>#include <net/route.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/ip_var.h>#include <netinet/in_pcb.h>#include <netinet/in_var.h>#include <netinet/igmp.h>#include <netinet/igmp_var.h>#include <netinet/ip_mroute.h>#include <netinet/udp.h>#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#ifndef MROUTINGextern u_long	_ip_mcast_src __P((int vifi));extern int	_ip_mforward __P((struct ip *ip, struct ifnet *ifp,				  struct mbuf *m, struct ip_moptions *imo));extern int	_ip_mrouter_done __P((void));extern int	_ip_mrouter_get __P((int cmd, struct socket *so,				     struct mbuf **m));extern int	_ip_mrouter_set __P((int cmd, struct socket *so,				     struct mbuf *m));extern int	_mrt_ioctl __P((int req, caddr_t data, struct proc *p));/* * Dummy routines and globals used when multicast routing is not compiled in. */struct socket  *ip_mrouter  = NULL;/* static u_int		ip_mrtproto = 0; *//* static struct mrtstat	mrtstat; */u_int		rsvpdebug = 0;int_ip_mrouter_set(cmd, so, m)	int cmd;	struct socket *so;	struct mbuf *m;{	return(EOPNOTSUPP);}int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = _ip_mrouter_set;int_ip_mrouter_get(cmd, so, m)	int cmd;	struct socket *so;	struct mbuf **m;{	return(EOPNOTSUPP);}int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = _ip_mrouter_get;int_ip_mrouter_done(){	return(0);}int (*ip_mrouter_done)(void) = _ip_mrouter_done;int_ip_mforward(ip, ifp, m, imo)	struct ip *ip;	struct ifnet *ifp;	struct mbuf *m;	struct ip_moptions *imo;{	return(0);}int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,		   struct ip_moptions *) = _ip_mforward;int_mrt_ioctl(int req, caddr_t data, struct proc *p){	return EOPNOTSUPP;}int (*mrt_ioctl)(int, caddr_t, struct proc *) = _mrt_ioctl;voidrsvp_input(m, iphlen)		/* XXX must fixup manually */	struct mbuf *m;	int iphlen;{    /* Can still get packets with rsvp_on = 0 if there is a local member     * of the group to which the RSVP packet is addressed.  But in this     * case we want to throw the packet away.     */    if (!rsvp_on) {	m_freem(m);	return;    }     if (ip_rsvpd != NULL) {	if (rsvpdebug)	    printf("rsvp_input: Sending packet up old-style socket\n");	rip_input(m, iphlen);	return;    }    /* Drop the packet */    m_freem(m);}void ipip_input(struct mbuf *m, int iphlen) { /* XXX must fixup manually */	rip_input(m, iphlen);}int (*legal_vif_num)(int) = 0;/* * This should never be called, since IP_MULTICAST_VIF should fail, but * just in case it does get called, the code a little lower in ip_output * will assign the packet a local address. */u_long_ip_mcast_src(int vifi) { return INADDR_ANY; }u_long (*ip_mcast_src)(int) = _ip_mcast_src;intip_rsvp_vif_init(so, m)    struct socket *so;    struct mbuf *m;{    return(EINVAL);}intip_rsvp_vif_done(so, m)    struct socket *so;    struct mbuf *m;{    return(EINVAL);}voidip_rsvp_force_done(so)    struct socket *so;{    return;}#else /* MROUTING */#define M_HASCL(m)	((m)->m_flags & M_EXT)#define INSIZ		sizeof(struct in_addr)#define	same(a1, a2) \	(bcmp((caddr_t)(a1), (caddr_t)(a2), INSIZ) == 0)#define MT_MRTABLE MT_RTABLE	/* since nothing else uses it *//* * Globals.  All but ip_mrouter and ip_mrtproto could be static, * except for netstat or debugging purposes. */#ifndef MROUTE_LKMstruct socket  *ip_mrouter  = NULL;struct mrtstat	mrtstat;int		ip_mrtproto = IGMP_DVMRP;    /* for netstat only */#else /* MROUTE_LKM */extern void	X_ipip_input __P((struct mbuf *m, int iphlen));extern struct mrtstat mrtstat;static int ip_mrtproto;#endif#define NO_RTE_FOUND 	0x1#define RTE_FOUND	0x2static struct mbuf    *mfctable[MFCTBLSIZ];static u_char		nexpire[MFCTBLSIZ];static struct vif	viftable[MAXVIFS];static u_int	mrtdebug = 0;	  /* debug level 	*/#define		DEBUG_MFC	0x02#define		DEBUG_FORWARD	0x04#define		DEBUG_EXPIRE	0x08#define		DEBUG_XMIT	0x10static u_int  	tbfdebug = 0;     /* tbf debug level 	*/static u_int	rsvpdebug = 0;	  /* rsvp debug level   */#define		EXPIRE_TIMEOUT	(hz / 4)	/* 4x / second		*/#define		UPCALL_EXPIRE	6		/* number of timeouts	*//* * Define the token bucket filter structures * tbftable -> each vif has one of these for storing info  */static struct tbf tbftable[MAXVIFS];#define		TBF_REPROCESS	(hz / 100)	/* 100x / second *//* * '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];#define ENCAP_TTL 64#define ENCAP_PROTO IPPROTO_IPIP	/* 4 *//* 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 */};/* * 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;static u_long	X_ip_mcast_src __P((int vifi));static int	X_ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo));static int	X_ip_mrouter_done __P((void));static int	X_ip_mrouter_get __P((int cmd, struct socket *so, struct mbuf **m));static int	X_ip_mrouter_set __P((int cmd, struct socket *so, struct mbuf *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 *, struct mbuf *);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 socket_send(struct socket *, struct mbuf *, struct sockaddr_in *);static int get_version(struct mbuf *);static int get_assert(struct mbuf *);static int set_assert(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 *);/* * whether or not special PIM assert processing is enabled. */static int pim_assert;/* * Rate limit for assert notification messages, in usec */#define ASSERT_MSG_TIME		3000000/* * 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) { \	register struct mbuf *_mb_rt = mfctable[MFCHASH(o,g)]; \	register struct mfc *_rt = NULL; \	rt = NULL; \	++mrtstat.mrts_mfc_lookups; \	while (_mb_rt) { \		_rt = mtod(_mb_rt, struct mfc *); \		if ((_rt->mfc_origin.s_addr == o) && \		    (_rt->mfc_mcastgrp.s_addr == g) && \		    (_mb_rt->m_act == NULL)) { \			rt = _rt; \			break; \		} \		_mb_rt = _mb_rt->m_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) { \	    register int xxs; \		\	    delta = (a).tv_usec - (b).tv_usec; \	    if ((xxs = (a).tv_sec - (b).tv_sec)) { \	       switch (xxs) { \		      case 2: \			  delta += 1000000; \			      /* fall through */ \		      case 1: \			  delta += 1000000; \			  break; \		      default: \			  delta += (1000000 * xxs); \	       } \	    } \}#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \	      (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)#ifdef UPCALL_TIMINGu_long upcall_data[51];static void collate(struct timeval *);#endif /* UPCALL_TIMING *//* * Handle MRT setsockopt commands to modify the multicast routing tables. */static intX_ip_mrouter_set(cmd, so, m)    int cmd;    struct socket *so;    struct mbuf *m;{   if (cmd != MRT_INIT && so != ip_mrouter) return EACCES;    switch (cmd) {	case MRT_INIT:     return ip_mrouter_init(so, m);	case MRT_DONE:     return ip_mrouter_done();	case MRT_ADD_VIF:  return add_vif (mtod(m, struct vifctl *));	case MRT_DEL_VIF:  return del_vif (mtod(m, vifi_t *));	case MRT_ADD_MFC:  return add_mfc (mtod(m, struct mfcctl *));	case MRT_DEL_MFC:  return del_mfc (mtod(m, struct mfcctl *));	case MRT_ASSERT:   return set_assert(mtod(m, int *));	default:             return EOPNOTSUPP;    }}#ifndef MROUTE_LKMint (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = X_ip_mrouter_set;#endif/* * Handle MRT getsockopt commands */static intX_ip_mrouter_get(cmd, so, m)    int cmd;    struct socket *so;    struct mbuf **m;{    struct mbuf *mb;    if (so != ip_mrouter) return EACCES;    *m = mb = m_get(M_WAIT, MT_SOOPTS);      switch (cmd) {	case MRT_VERSION:   return get_version(mb);	case MRT_ASSERT:    return get_assert(mb);	default:            return EOPNOTSUPP;    }}#ifndef MROUTE_LKMint (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = X_ip_mrouter_get;#endif/* * Handle ioctl commands to obtain information from the cache */static intX_mrt_ioctl(cmd, data)    int cmd;    caddr_t data;{    int error = 0;    switch (cmd) {	case (SIOCGETVIFCNT):	    return (get_vif_cnt((struct sioc_vif_req *)data));	    break;	case (SIOCGETSGCNT):	    return (get_sg_cnt((struct sioc_sg_req *)data));	    break;	default:	    return (EINVAL);	    break;    }    return error;}#ifndef MROUTE_LKMint (*mrt_ioctl)(int, caddr_t) = X_mrt_ioctl;#endif/* * returns the packet, byte, rpf-failure count for the source group provided */static intget_sg_cnt(req)    register struct sioc_sg_req *req;{    register struct mfc *rt;    int s;    s = splnet();    MFCFIND(req->src.s_addr, req->grp.s_addr, rt);    splx(s);    if (rt != NULL) {	req->pktcnt = rt->mfc_pkt_cnt;	req->bytecnt = rt->mfc_byte_cnt;	req->wrong_if = rt->mfc_wrong_if;    } else	req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;    return 0;}/* * returns the input and output packet and byte counts on the vif provided */static intget_vif_cnt(req)    register struct sioc_vif_req *req;{    register vifi_t vifi = req->vifi;    if (vifi >= numvifs) return EINVAL;    req->icount = viftable[vifi].v_pkt_in;    req->ocount = viftable[vifi].v_pkt_out;    req->ibytes = viftable[vifi].v_bytes_in;    req->obytes = viftable[vifi].v_bytes_out;    return 0;}/* * Enable multicast routing */static intip_mrouter_init(so, m)	struct socket *so;	struct mbuf *m;{    int *v;    if (mrtdebug)	log(LOG_DEBUG,"ip_mrouter_init: so_type = %d, pr_protocol = %d\n",		so->so_type, so->so_proto->pr_protocol);    if (so->so_type != SOCK_RAW ||	so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP;    if (!m || (m->m_len != sizeof(int *)))	return ENOPROTOOPT;    v = mtod(m, int *);    if (*v != 1)	return ENOPROTOOPT;    if (ip_mrouter != NULL) return EADDRINUSE;    ip_mrouter = so;    bzero((caddr_t)mfctable, sizeof(mfctable));    bzero((caddr_t)nexpire, sizeof(nexpire));    pim_assert = 0;    timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);    if (mrtdebug)	log(LOG_DEBUG, "ip_mrouter_init\n");    return 0;}/* * Disable multicast routing */static intX_ip_mrouter_done(){    vifi_t vifi;    int i;    struct ifnet *ifp;    struct ifreq ifr;    struct mbuf *mb_rt;    struct mbuf *m;    struct rtdetq *rte;    int s;    s = splnet();    /*     * For each phyint in use, disable promiscuous reception of all IP     * multicasts.     */    for (vifi = 0; vifi < numvifs; vifi++) {	if (viftable[vifi].v_lcl_addr.s_addr != 0 &&	    !(viftable[vifi].v_flags & VIFF_TUNNEL)) {	    ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;	    ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -