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

📄 ip_mroute.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        port,        rt->mfc_parent,        3,4,5,6    );      if ( (xmt_vif < numvifs) || (rt == NULL) ) {/* rt== NULL makes up for missing xmit vif in x_ip_mforward */	MRTDEBUG    (        (mrtdebug),		"MROUTE:  MDQ sending packet on VIF, xmt_vif=%i, numvifs=%i.\n",         xmt_vif,         numvifs,        3,4,5,6    );	MC_SEND(ip, viftable + xmt_vif, m);	forwarded ++;	return 1;    }    /*     * Don't forward if it didn't arrive from the parent vif for its origin.     */    vifi = rt->mfc_parent;    if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) 	{	/* came in the wrong interface */		MRTDEBUG        (            (mrtdebug),			"MROUTE: wrong if: ifp %p vifi %d vififp %p\n",            (int)ifp,             vifi,             (int)viftable[vifi].v_ifp,            4,5,6        ); 		++mrtstat.mrts_wrong_if;		++rt->mfc_wrong_if;		/*		 * If we are doing PIM assert processing, and we are forwarding		 * packets on this interface, and it is a broadcast medium		 * interface (and not a tunnel), send a message to the routing daemon.		 */		if (pim_assert && rt->mfc_ttls[port] &&			(ifp->if_flags & IFF_BROADCAST) &&			!(viftable[vifi].v_flags & VIFF_TUNNEL)) 		{			pimNotify(ip, m, rt, vifi, ifp);		}		return 0;    }	vifi_original = vifi;    /* If I sourced this packet, it counts as output, else it was input. */    if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) 	{		viftable[vifi].v_pkt_out++;		viftable[vifi].v_bytes_out += plen;    } 	else 	{		viftable[vifi].v_pkt_in++;		viftable[vifi].v_bytes_in += plen;    }    rt->mfc_pkt_cnt++;    rt->mfc_byte_cnt += plen;    /*     * For each vif, decide if a copy of the packet should be forwarded.     * Forward if:     *		- the ttl exceeds the vif's threshold     *		- there are group members downstream on interface     */    MRTDEBUG    (        (mrtdebug),		"MROUTE:  MDQ iterating through vifs to find oifs.\n",        1,2,3,4,5,6    );     for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++)    {        MRTDEBUG        (            (mrtdebug),			"MROUTE: mdq vif %i has forward threshold %i.  ip->ttl=%i, parent=%i.\n",            vifi,             rt->mfc_ttls[vifi],            ip->ip_ttl,            rt->mfc_parent,            5,6        ); 	    if (		    (rt->mfc_ttls[vifi] > 0) 		     &&(ip->ip_ttl > rt->mfc_ttls[vifi])		     &&(vifi != rt->mfc_parent)		     )		    {			    vifp->v_pkt_out++;			    vifp->v_bytes_out += plen;			    MRTDEBUG                (                    (mrtdebug),                    "MROUTE:  sending packet out vif %i name %s , ifp=%p.\n",                    vifi,                     (int)vifp->v_ifp->if_name,                     (int)ifp,                    4,5,6                ); 			    old_len = ip->ip_len;			    MC_SEND(ip, vifp, m);			    if (old_len != ip->ip_len)			    {				    HTONS(ip->ip_len);/* the kernel sometimes changes 									    the byte ordering, 									    so we have to change it back */				    HTONS(ip->ip_off);			    }                ip->ip_ttl ++;  /* compensate for -1 in send routine */			    forwarded ++;		    }    }    MRTDEBUG    (        (mrtdebug),		"MROUTE:  MDQ forwarded %i times.\n", forwarded,        2,3,4,5,6    );     return 0;}/* * check if a vif number is legal/ok. This is used by ip_output, to export * numvifs there,  */static intX_legal_vif_num(vif)    int vif;{    if (vif >= 0 && vif < numvifs)       return(1);    else       return(0);}int (*legal_vif_num)(int) = X_legal_vif_num;/* * Return the local address used by this vif */static u_longX_ip_mcast_src(vifi)    int vifi;{    if (vifi >= 0 && vifi < numvifs)	return viftable[vifi].v_lcl_addr.s_addr;    else	return INADDR_ANY;}static voidphyint_send(ip, vifp, m)    struct ip *ip;    struct vif *vifp;    struct mbuf *m;{    struct mbuf *mb_copy;    int hlen = ip->ip_hl << 2;    /*     * Make a new reference to the packet; make sure that     * the IP header is actually copied, not just referenced,     * so that ip_output() only scribbles on the copy.     */    mb_copy = m_copy(m, 0, M_COPYALL);    if (mb_copy && (M_HASCL(mb_copy) || mb_copy->m_len < hlen))	mb_copy = m_pullup(mb_copy, hlen);    if (mb_copy == NULL)	return;    if (vifp->v_rate_limit == 0)	tbf_send_packet(vifp, mb_copy);    else	tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len);}static voidencap_send(ip, vifp, m)    struct ip *ip;    struct vif *vifp;    struct mbuf *m;{    struct mbuf *mb_copy;    struct ip *ip_copy;    int i, len = ip->ip_len;    /*     * copy the old packet & pullup its IP header into the     * new mbuf so we can modify it.  Try to fill the new     * mbuf since if we don't the ethernet driver will.     */    MGETHDR(mb_copy, M_DONTWAIT, MT_HEADER);    if (mb_copy == NULL)	return;    mb_copy->m_data += max_linkhdr;    mb_copy->m_len = sizeof(multicast_encap_iphdr);    if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == NULL) {	m_freem(mb_copy);	return;    }    i = MHLEN - M_LEADINGSPACE(mb_copy);    if (i > len)	i = len;    mb_copy = m_pullup(mb_copy, i);    if (mb_copy == NULL)	return;    mb_copy->m_pkthdr.len = len + sizeof(multicast_encap_iphdr);    /*     * fill in the encapsulating IP header.     */    ip_copy = mtod(mb_copy, struct ip *);    *ip_copy = multicast_encap_iphdr;#ifndef VIRTUAL_STACK    ip_copy->ip_id = htons(ip_id++);#else    ip_copy->ip_id = htons(_ip_id++);#endif    ip_copy->ip_len += len;    ip_copy->ip_src = vifp->v_lcl_addr;    ip_copy->ip_dst = vifp->v_rmt_addr;    /*     * turn the encapsulated IP header back into a valid one.     */    ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr));    --ip->ip_ttl;    HTONS(ip->ip_len);    HTONS(ip->ip_off);    ip->ip_sum = 0;    mb_copy->m_data += sizeof(multicast_encap_iphdr);    ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);    mb_copy->m_data -= sizeof(multicast_encap_iphdr);    if (vifp->v_rate_limit == 0)	tbf_send_packet(vifp, mb_copy);    else	tbf_control(vifp, mb_copy, ip, ip_copy->ip_len);}/* * De-encapsulate a packet and feed it back through ip input (this * routine is called whenever IP gets a packet with proto type * ENCAP_PROTO and a local destination address). */voidipip_input(m, iphlen)	struct mbuf *m;	int iphlen;{    struct ifnet *ifp = m->m_pkthdr.rcvif;    struct ip *ip = mtod(m, struct ip *);    int hlen = ip->ip_hl << 2;    int s;    struct ifqueue *ifq;    struct vif *vifp;    if (!have_encap_tunnel) 	{	    rip_input(m);	    return;    }    /*     * dump the packet if it's not to a multicast destination or if     * we don't have an encapsulating tunnel with the source.     * Note:  This code assumes that the remote site IP address     * uniquely identifies the tunnel (i.e., that this site has     * at most one tunnel with the remote site).     */    if (! IN_MULTICAST(ntohl(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr))) 	{		++mrtstat.mrts_bad_tunnel;		m_freem(m);		return;    }    if (ip->ip_src.s_addr != last_encap_src) 	{		struct vif *vife;				vifp = viftable;		vife = vifp + numvifs;		last_encap_src = ip->ip_src.s_addr;		last_encap_vif = 0;		for ( ; vifp < vife; ++vifp)			if (vifp->v_rmt_addr.s_addr == ip->ip_src.s_addr) 			{				if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT))					== VIFF_TUNNEL)				last_encap_vif = vifp;				break;			}    }    if ((vifp = last_encap_vif) == 0) 	{		last_encap_src = 0;		mrtstat.mrts_cant_tunnel++; /*XXX*/		m_freem(m);		MRTDEBUG        (            (mrtdebug),		    "MROUTE: ip_mforward: no tunnel with %lx\n",            (u_long)ntohl(ip->ip_src.s_addr),            2,3,4,5,6        );		return;    }    ifp = vifp->v_ifp;    if (hlen > IP_HDR_LEN)      ip_stripoptions(m, (struct mbuf *) 0);    m->m_data += IP_HDR_LEN;    m->m_len -= IP_HDR_LEN;    m->m_pkthdr.len -= IP_HDR_LEN;    m->m_pkthdr.rcvif = ifp;    ifq = &ipintrq;    s = splimp();    if (IF_QFULL(ifq)) 	{		IF_DROP(ifq);		m_freem(m);    } else 	{		IF_ENQUEUE(ifq, m);		/*		 * normally we would need a "schednetisr(NETISR_IP)"		 * here but we were called by ip_input and it is going		 * to loop back & try to dequeue the packet we just		 * queued as soon as we return so we avoid the		 * unnecessary software interrrupt.		 */    }    splx(s);}static BOOL oifListIsEmpty    (    struct mfc* rt    )  {	int i;	int j = 0;	if (rt == NULL) return (TRUE);    for (i=0;i<numvifs; i++)	{		j+=rt->mfc_ttls[i];	}    if (j == 0)		return (TRUE);	return(FALSE);}static void mRouteDumpMfctable(){	int i;	int j;	struct mfc* rt;	vifi_t vifi;    struct vif *vifp;	MRTDEBUG    (        (1),		"MROUTE: IP_MROUTE dumping mfctable.\n",        1,2,3,4,5,6    );	for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++)	{		MRTDEBUG        (            (1),			"MROUTE:  vif %i is named %s%i.\n",             vifi,             (int)vifp->v_ifp->if_name, vifp->v_ifp->if_index,            4,5,6        ); 	}	for (i=0;i<MFCTBLSIZ; i++)	{		if (mfctable[i] != NULL)		{			MRTDEBUG            (                (1),                "MROUTE:  mfctable postion %i.\n", i,                2,3,4,5,6            );			for (rt = mfctable[i]; rt != NULL; rt = rt->mfc_next) 			{				MRTDEBUG                (                    (1),                    "MROUTE: \tEntry g=%p, s=%p.\n", 					ntohl(rt->mfc_mcastgrp.s_addr), 					ntohl(rt->mfc_origin.s_addr),                    3,4,5,6                );				MRTDEBUG                (                       (1),                    "MROUTE: \t\t OIFLIST=",1,2,3,4,5,6                );				for (j=0;j<=numvifs; j++)					MRTDEBUG                    (                        (1),                        "vif %i ttl=%i,",j,(int)rt->mfc_ttls[j],3,4,5,6                    );				MRTDEBUG                (                    (1),                    "MROUTE: \n.",                    1,2,3,4,5,6                );			}		}	}}/* * Token bucket filter module */static voidtbf_control(vifp, m, ip, p_len)	struct vif *vifp;	struct mbuf *m;	struct ip *ip;	u_long p_len;{    struct tbf *t = vifp->v_tbf;    if (p_len > MAX_BKT_SIZE) {	/* drop if packet is too large */	mrtstat.mrts_pkt2large++;	m_freem(m);	return;    }    tbf_update_tokens(vifp);    /* if there are enough tokens,      * and the queue is empty,     * send this packet out     */    if (t->tbf_q_len == 0) {	/* queue empty, send packet if enough tokens */	if (p_len <= t->tbf_n_tok) {	    t->tbf_n_tok -= p_len;	    tbf_send_packet(vifp, m);	} else {	    /* queue packet and timeout till later */	    tbf_queue(vifp, m);		timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS);	}    } else if (t->tbf_q_len < t->tbf_max_q_len) {	/* finite queue length, so queue pkts and process queue */	tbf_queue(vifp, m);	tbf_process_q(vifp);    } else {	/* queue length too much, try to dq and queue and process */	if (!tbf_dq_sel(vifp, ip)) {	    mrtstat.mrts_q_overflow++;	    m_freem(m);	    return;	} else {	    tbf_queue(vifp, m);	    tbf_process_q(vifp);	}    }    return;}/*  * adds a packet to the queue at the interface */static voidtbf_queue(vifp, m) 	struct vif *vifp;	struct mbuf *m;{    int s = splnet();    struct tbf *t = vifp->v_tbf;    if (t->tbf_t == NULL) {	/* Queue was empty */	t->tbf_q = m;    } else {	/* Insert at tail */	t->tbf_t->m_act = m;    }    /* Set new tail pointer */    t->tbf_t = m;#ifdef DIAGNOSTIC    /* Make sure we didn't get fed a bogus mbuf */    if (m->m_act)	panic("tbf_queue: m_act");#endif    m->m_act = NULL;    t->tbf_q_len++;    splx(s);}/*  * processes the queue at the interface */static voidtbf_process_q(vifp)    struct vif *vifp;{    struct mbuf *m;    int len;    int s = splnet();    struct tbf *t = vifp->v_tbf;    /* loop through the queue at the interface and send as many packets     * as possible     *

⌨️ 快捷键说明

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