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

📄 ip_mroute.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        if (               (pIp == NULL)            ||(pMbuf == NULL)            ||(pRt == NULL)            ||(pIfnet == NULL)           )        {            return (ERROR);        }		GET_TIME(now);	    MRTDEBUG        (            (mrtdebug),			"MROUTE: pimNotify calling overlying routing protocol.\n",            1,2,3,4,5,6        );				pMbufCopy = m_copy(pMbuf, 0, M_COPYALL);		if (pMbufCopy == NULL) 		{			return ENOBUFS;		}		hlen = pIp->ip_hl << 2;		if (pMbufCopy && (M_HASCL(pMbufCopy) || pMbufCopy->m_len < hlen))			pMbufCopy = m_pullup(pMbufCopy, hlen);		pRt->mfc_last_assert = now;/* It looks like they're overlaying the igmpmsg structure on top of the ip structure.  This will allow us to access the im_src member (which in IP corresponds to the ip_src member of struct ip.  Note that both members are offset by 12 bytes.  struct igmpmsg {    u_long	    unused1;    u_long	    unused2;    u_char	    im_msgtype;#define IGMPMSG_NOCACHE		1#define IGMPMSG_WRONGVIF	2    u_char	    im_mbz;	    u_char	    im_vif;	    u_char	    unused3;    struct in_addr  im_src, im_dst;};  struct ip {#if _BYTE_ORDER == _LITTLE_ENDIAN	u_int	ip_hl:4,				ip_v:4,			#endif#if _BYTE_ORDER == _BIG_ENDIAN	u_int	ip_v:4,				ip_hl:4,		#endif		ip_tos:8,				ip_len:16;			u_short	ip_id;			short	ip_off;		#define	IP_DF 0x4000	#define	IP_MF 0x2000	#define	IP_OFFMASK 0x1fff		u_char	ip_ttl;				u_char	ip_p;				u_short	ip_sum;				struct	in_addr ip_src,ip_dst;	};*/		pIGMPMessage = mtod(pMbufCopy, struct igmpmsg *);        if (pIGMPMessage == NULL)        {            return (ERROR);        }		k_igmpsrc.sin_addr = pIGMPMessage->im_src;		/* The kernel stores these values in host order, pim requires net order*/		pIpNew = mtod (pMbufCopy, struct ip*);        if (pIpNew == NULL)        {            return (ERROR);        }        pIpNew->ip_len = htons(pIpNew->ip_len);		pIpNew->ip_off = htons(pIpNew->ip_off);        /* these values are in the wrong order for PIM*/    	MRTDEBUG        (            (mrtdebug),			"MROUTE: pimNotify calling pim=%p.\n",            (int)_pimCacheMissSendHook,2,3,4,5,6        );				if ( _pimCacheMissSendHook != 0)			{			_pimCacheMissSendHook (pMbufCopy, pIfnet, &k_igmpsrc);		}		return (OK);}/* * IP multicast forwarding function. This function assumes that the packet * pointed to by "ip" has arrived on (or is about to be sent to) the interface * pointed to by "ifp", and the packet is to be relayed to other networks * that have members of the packet's destination IP multicast group. * * The packet is returned unscathed to the caller, unless it is * erroneous, in which case a non-zero return value tells the caller to * discard it. */#define IP_HDR_LEN  20	/* # bytes of fixed IP header (excluding options) */#define TUNNEL_LEN  12  /* # bytes of IP option for tunnel encapsulation  */static intX_ip_mforward(m, ifp, ip, imo )    struct mbuf *m;    struct ifnet *ifp;    struct ip *ip;    struct ip_moptions *imo;{        struct mfc *rt;    struct mfc *root_rt;    u_char *ipoptions;    static struct sockaddr_in 	k_igmpsrc	= { sizeof k_igmpsrc, AF_INET };    static int srctun = 0;    int s;	BOOL null_list;    vifi_t vifi = -1;    MRTDEBUG    (        (mrtdebug & DEBUG_FORWARD),		"ip_mforward: src %lx, dst %lx, if=%p, %s%i\n",        (u_long)ntohl(ip->ip_src.s_addr),         (u_long)ntohl(ip->ip_dst.s_addr),		(int)ifp,         (int)ifp->if_name,         ifp->if_unit,        6    );    if ( (mrtdebug & DEBUG_TABLE) != 0)        mRouteDumpMfctable();    if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 ||	(ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) {	/*	 * Packet arrived via a physical interface or	 * an encapsulated tunnel.	 */    } else {    MRTDEBUG    (        (mrtdebug & DEBUG_FORWARD),		"MROUTE: Packet arrived through a source-route tunnel.  \        Source-route tunnels are no longer supported.\n",        1,2,3,4,5,6    );	/*	 * Packet arrived through a source-route tunnel.	 * Source-route tunnels are no longer supported.	 */	if ((srctun++ % 1000) == 0)	{        MRTDEBUG        (            (mrtdebug),		    "MROUTE: ip_mforward: received source-routed packet from %lx\n",            (u_long)ntohl(ip->ip_src.s_addr),            2,3,4,5,6        );	}	return 1;    }	if ( (imo) && (vifi < numvifs) ) 	{ 		if (ip->ip_ttl < 255)			ip->ip_ttl++;	/* compensate for -1 in *_send routines */		vifi = -1;		return (ip_mdq(m, ifp, NULL, vifi));/* this is for a specific forwarding scenario...  		explicitly chosen vif.  we no longer support this */    }    /*     * Don't forward a packet with time-to-live of zero or one,     * or a packet destined to a local-only group.     */    if (ip->ip_ttl <= 1 ||	 (ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP) )	{			return 0;	}    /*     * Determine forwarding vifs from the forwarding cache table     */    s = splnet();    MFCFIND(ip->ip_src.s_addr, ip->ip_dst.s_addr, rt);    /* Entry exists, so forward if necessary */    if (rt != NULL) 	{		null_list = oifListIsEmpty(rt);		splx(s);		if (             (			    (null_list)			 && (pim_assert )			 && (ifp->if_flags & IFF_BROADCAST) 			)			|| 			(                rt->mfc_notify != 0            )		   )		{			rt->mfc_notify = 1;			pimNotify(ip, m, rt, vifi, ifp);			/* tell pim about new packet for old group.  			 * Pim will be responsible for forwarding*/			if (null_list )			{				return (OK);			}		}		return (ip_mdq(m, ifp, rt, -1));    } 	else 	{	/*	 * If we don't have a route for packet's origin,	 * Make a copy of the packet &	 * send message to routing daemon	 */	struct mbuf *mb0;	struct rtdetq *rte;	u_long hash;	int hlen = ip->ip_hl << 2;    mrtstat.mrts_no_route++;    MRTDEBUG    (        (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)),        "MROUTE: ip_mforward: origin unknown no rte s %lx g %lx\n",		(u_long)ntohl(ip->ip_src.s_addr),		(u_long)ntohl(ip->ip_dst.s_addr),        3,4,5,6    );	/*	 * Allocate mbufs early so that we don't do extra work if we are	 * just going to fail anyway.  Make sure to pullup the header so	 * that other people can't step on it.	 */	rte = MRT_ALLOC (sizeof (struct rtdetq ) );	if (rte == NULL) {	    splx(s);	    return ENOBUFS;	}	rte->m = 0;	mb0 = m_copy(m, 0, M_COPYALL);	if (mb0 && (M_HASCL(mb0) || mb0->m_len < hlen))	    mb0 = m_pullup(mb0, hlen);	if (mb0 == NULL) {	    MRT_FREE((char*) rte);	    splx(s);	    return ENOBUFS;	}	/* is there an upcall waiting for this packet? */	hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr);	for (rt = mfctable[hash]; rt; rt = rt->mfc_next) 	{	    if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) &&			(ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) &&			(rt->mfc_stall != NULL)			)		break;	}	if (rt == NULL) 	{	    int i;	    /* no upcall, so make a new entry */		rt = MRT_ALLOC(sizeof(struct mfc));		if (rt == NULL) 		{			MRT_FREE((char*) rte);			m_freem(mb0);			splx(s);			return ENOBUFS;		}	    /* Make a copy of the header to send to the user level process */		rt->mfc_notify = 0;	    /* 	     * Send message to routing daemon to install 	     * a route into the kernel table	     */	    k_igmpsrc.sin_addr = ip->ip_src;	    	    mrtstat.mrts_upcalls++;	    rt->mfc_origin.s_addr     = ip->ip_src.s_addr;	    rt->mfc_mcastgrp.s_addr   = ip->ip_dst.s_addr;	    rt->mfc_expire	      = UPCALL_EXPIRE;	    nexpire[hash]++;		/* find the root route */		MFCFIND(0, rt->mfc_mcastgrp.s_addr, root_rt);		if (root_rt != NULL)		{/* it exists, do nothing */		}		else if (root_rt == NULL)		{/* create one */			root_rt = MRT_ALLOC(sizeof(struct mfc));			if (root_rt == NULL) 			{				MRT_FREE((char*) rt);				splx(s);				return ENOBUFS;			}			root_rt->mfc_notify = 0;			/* inset NULL entry at head of hash chain */			root_rt->mfc_origin.s_addr     = 0;			root_rt->mfc_mcastgrp   = rt->mfc_mcastgrp;			root_rt->mfc_parent     = 0;			for (i = 0; i < numvifs; i++)				root_rt->mfc_ttls[i] = 0;			/* initialize pkt counters per src-grp */			root_rt->mfc_pkt_cnt    = 0;			root_rt->mfc_byte_cnt   = 0;			root_rt->mfc_wrong_if   = 0;            rt->mfc_last_assert = 0;			root_rt->mfc_last_assert = 0;			root_rt->mfc_expire     = 0;			root_rt->mfc_stall      = NULL;			/* link into table */			root_rt->mfc_next = mfctable[MFCHASH(root_rt->mfc_origin.s_addr, root_rt->mfc_mcastgrp.s_addr) ];			mfctable[MFCHASH(root_rt->mfc_origin.s_addr, root_rt->mfc_mcastgrp.s_addr) ]= root_rt;			root_rt->mfc_next_g = root_rt;	/* next group in same chain */			root_rt->mfc_root_rt = root_rt;	/* 0,g entry in hash table, itself in this case*/		}	    rt->mfc_parent = mRouteNameToPort(ifp->if_name, ifp->if_unit);		rt->mfc_root_rt = root_rt;/* set root_rt*/		rt->mfc_next_g = root_rt->mfc_next_g;	/* insert into from of group chain*/		for (i = 0; i < numvifs; i++)			rt->mfc_ttls[i] = root_rt->mfc_ttls[i];		root_rt->mfc_next_g = rt;	/* insert new entry at head of hash chain */	    /* link into table */	    rt->mfc_next   = mfctable[hash];	    mfctable[hash] = rt;	    rt->mfc_stall = rte;		if (rte->m == 0)		{			rte->m 			= mb0;			rte->ifp 		= ifp;			rte->next		= NULL;		}		if (pim_assert == 0)		{/* new route automatically inherits *,g entries */			if (mRouteGroupAdd( ifp, ip->ip_src, ip->ip_dst ) < 0) 			{		        MRTDEBUG                    (                    (mrtdebug),					"MROUTE: ip_mforward: ip_mrouter socket queue full, mRouteGroupAdd failed\n",                    1,2,3,4,5,6                );				++mrtstat.mrts_upq_sockfull;				MRT_FREE((char*) rte);				m_freem(mb0);				MRT_FREE((char*) rt);				splx(s);				return ENOBUFS;			}		}		else if (pim_assert 			&& (ifp->if_flags & IFF_BROADCAST) 			)		{			pimNotify(ip, m, rt, vifi, ifp);/* tell pim about new group */		}	} else {	    /* determine if q has overflowed */	    int npkts = 0;	    struct rtdetq **p;	    for (p = &rt->mfc_stall; *p != NULL; p = &(*p)->next)		npkts++;	    if (npkts > MAX_UPQ) {		mrtstat.mrts_upq_ovflw++;		MRT_FREE((char*) rte);		m_freem(mb0);		splx(s);		return 0;	    }	    /* Add this entry to the end of the queue */	    *p = rte;	}	if (rte->m == 0)	{	rte->m 			= mb0;	rte->ifp 		= ifp;	rte->next		= NULL;	}	splx(s);	return 0;    }		}int ip_mforward (struct mbuf * m, struct ifnet * ifp, struct ip *ip, struct ip_moptions *imo){	return(X_ip_mforward(m, ifp, ip, imo));};/* * Clean up the cache entry if upcall is not serviced */static voidexpire_upcalls(void *unused){    struct rtdetq *rte;    struct mfc *mfc, **nptr;    int i;    int s;    s = splnet();    for (i = 0; i < MFCTBLSIZ; i++) 	{		if (nexpire[i] == 0)			continue;		nptr = &mfctable[i];		for (mfc = *nptr; mfc != NULL; mfc = *nptr) 		{			/*			 * Skip real cache entries			 * Make sure it wasn't marked to not expire (shouldn't happen)			 * If it expires now			 */			if (mfc->mfc_stall != NULL &&				mfc->mfc_expire != 0 &&			--mfc->mfc_expire == 0) 			{				MRTDEBUG                (                    (mrtdebug & DEBUG_EXPIRE),					"MROUTE: expire_upcalls: expiring (%lx %lx)\n",                    (u_long)ntohl(mfc->mfc_origin.s_addr),					(u_long)ntohl(mfc->mfc_mcastgrp.s_addr),                    3,4,5,6                );				/*				 * drop all the packets				 * free the mbuf with the pkt, if, timing info				 */				for (rte = mfc->mfc_stall; rte; ) 				{					struct rtdetq *n = rte->next;					m_freem(rte->m);					MRT_FREE((char*) rte);					rte = n;				}				++mrtstat.mrts_cache_cleanups;				nexpire[i]--;				*nptr = mfc->mfc_next;				MRT_FREE((char*) mfc);			} 			else 			{				nptr = &mfc->mfc_next;			}		}    }    splx(s);    expire_upcalls_ch = timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);	}/* * Packet forwarding routine once entry in the cache is made */static intip_mdq(m, ifp, rt, xmt_vif)    struct mbuf *m;    struct ifnet *ifp;    struct mfc *rt;    vifi_t xmt_vif;{    struct ip  *ip = mtod(m, struct ip *);    vifi_t vifi;	vifi_t vifi_original;    struct vif *vifp;	USHORT old_len;	int port;        int plen = ip->ip_len;	int forwarded = 0;/* * Macro to send packet on vif.  Since RSVP packets don't get counted on * input, they shouldn't get counted on output, so statistics keeping is * seperate. */#define MC_SEND(ip,vifp,m) {                             \                if ((vifp)->v_flags & VIFF_TUNNEL)  	 \                    encap_send((ip), (vifp), (m));       \                else                                     \                    phyint_send((ip), (vifp), (m));      \}    /*     * If xmt_vif is not -1, send on only the requested vif.     *     * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.)     */	port = mRouteNameToPort(ifp->if_name, ifp->if_unit);    MRTDEBUG    (        (mrtdebug),		"MROUTE:  MDQ found VIF=%i, parent=%i.\n",

⌨️ 快捷键说明

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