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

📄 ip_mroute.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 4 页
字号:
								= INADDR_ANY;	    ifp = viftable[vifi].v_ifp;	    (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);	}    }    bzero((caddr_t)tbftable, sizeof(tbftable));    bzero((caddr_t)viftable, sizeof(viftable));    numvifs = 0;    pim_assert = 0;    untimeout(expire_upcalls, (caddr_t)NULL);    /*     * Free all multicast forwarding cache entries.     */    for (i = 0; i < MFCTBLSIZ; i++) {	mb_rt = mfctable[i];	while (mb_rt) {	    if (mb_rt->m_act != NULL) {		while (mb_rt->m_act) {		    m = mb_rt->m_act;		    mb_rt->m_act = m->m_act;		    rte = mtod(m, struct rtdetq *);		    m_freem(rte->m);		    m_free(m);		}	    }	    mb_rt = m_free(mb_rt);	}    }    bzero((caddr_t)mfctable, sizeof(mfctable));    /*     * Reset de-encapsulation cache     */    last_encap_src = 0;    last_encap_vif = NULL;    have_encap_tunnel = 0;     ip_mrouter = NULL;    splx(s);    if (mrtdebug)	log(LOG_DEBUG, "ip_mrouter_done\n");    return 0;}#ifndef MROUTE_LKMint (*ip_mrouter_done)(void) = X_ip_mrouter_done;#endifstatic intget_version(mb)    struct mbuf *mb;{    int *v;    v = mtod(mb, int *);    *v = 0x0305;	/* XXX !!!! */    mb->m_len = sizeof(int);    return 0;}/* * Set PIM assert processing global */static intset_assert(i)    int *i;{    if ((*i != 1) && (*i != 0))	return EINVAL;    pim_assert = *i;    return 0;}/* * Get PIM assert processing global */static intget_assert(m)    struct mbuf *m;{    int *i;    i = mtod(m, int *);    *i = pim_assert;    return 0;}/* * Add a vif to the vif table */static intadd_vif(vifcp)    register struct vifctl *vifcp;{    register struct vif *vifp = viftable + vifcp->vifc_vifi;    static struct sockaddr_in sin = {sizeof sin, AF_INET};    struct ifaddr *ifa;    struct ifnet *ifp;    struct ifreq ifr;    int error, s;    struct tbf *v_tbf = tbftable + vifcp->vifc_vifi;    if (vifcp->vifc_vifi >= MAXVIFS)  return EINVAL;    if (vifp->v_lcl_addr.s_addr != 0) return EADDRINUSE;    /* Find the interface with an address in AF_INET family */    sin.sin_addr = vifcp->vifc_lcl_addr;    ifa = ifa_ifwithaddr((struct sockaddr *)&sin);    if (ifa == 0) return EADDRNOTAVAIL;    ifp = ifa->ifa_ifp;    if (vifcp->vifc_flags & VIFF_TUNNEL) {	if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) {		/*		 * An encapsulating tunnel is wanted.  Tell ipip_input() to		 * start paying attention to encapsulated packets.		 */		if (have_encap_tunnel == 0) {			have_encap_tunnel = 1;			for (s = 0; s < MAXVIFS; ++s) {				multicast_decap_if[s].if_name = "mdecap";				multicast_decap_if[s].if_unit = s;			}		}		/*		 * Set interface to fake encapsulator interface		 */		ifp = &multicast_decap_if[vifcp->vifc_vifi];		/*		 * Prepare cached route entry		 */		bzero(&vifp->v_route, sizeof(vifp->v_route));	} else {	    log(LOG_ERR, "source routed tunnels not supported\n");	    return EOPNOTSUPP;	}    } else {	/* Make sure the interface supports multicast */	if ((ifp->if_flags & IFF_MULTICAST) == 0)	    return EOPNOTSUPP;	/* Enable promiscuous reception of all IP multicasts from the if */	((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;	((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY;	s = splnet();	error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);	splx(s);	if (error)	    return error;    }    s = splnet();    /* define parameters for the tbf structure */    vifp->v_tbf = v_tbf;    GET_TIME(vifp->v_tbf->tbf_last_pkt_t);    vifp->v_tbf->tbf_n_tok = 0;    vifp->v_tbf->tbf_q_len = 0;    vifp->v_tbf->tbf_max_q_len = MAXQSIZE;    vifp->v_tbf->tbf_q = vifp->v_tbf->tbf_t = NULL;    vifp->v_flags     = vifcp->vifc_flags;    vifp->v_threshold = vifcp->vifc_threshold;    vifp->v_lcl_addr  = vifcp->vifc_lcl_addr;    vifp->v_rmt_addr  = vifcp->vifc_rmt_addr;    vifp->v_ifp       = ifp;    /* scaling up here allows division by 1024 in critical code */    vifp->v_rate_limit= vifcp->vifc_rate_limit * 1024 / 1000;    vifp->v_rsvp_on   = 0;    vifp->v_rsvpd     = NULL;    /* initialize per vif pkt counters */    vifp->v_pkt_in    = 0;    vifp->v_pkt_out   = 0;    vifp->v_bytes_in  = 0;    vifp->v_bytes_out = 0;    splx(s);    /* Adjust numvifs up if the vifi is higher than numvifs */    if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1;    if (mrtdebug)	log(LOG_DEBUG, "add_vif #%d, lcladdr %x, %s %x, thresh %x, rate %d\n",	    vifcp->vifc_vifi, 	    ntohl(vifcp->vifc_lcl_addr.s_addr),	    (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask",	    ntohl(vifcp->vifc_rmt_addr.s_addr),	    vifcp->vifc_threshold,	    vifcp->vifc_rate_limit);        return 0;}/* * Delete a vif from the vif table */static intdel_vif(vifip)    vifi_t *vifip;{    register struct vif *vifp = viftable + *vifip;    register vifi_t vifi;    register struct mbuf *m;    struct ifnet *ifp;    struct ifreq ifr;    int s;    if (*vifip >= numvifs) return EINVAL;    if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL;    s = splnet();    if (!(vifp->v_flags & VIFF_TUNNEL)) {	((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;	((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY;	ifp = vifp->v_ifp;	(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);    }    if (vifp == last_encap_vif) {	last_encap_vif = 0;	last_encap_src = 0;    }    /*     * Free packets queued at the interface     */    while (vifp->v_tbf->tbf_q) {	m = vifp->v_tbf->tbf_q;	vifp->v_tbf->tbf_q = m->m_act;	m_freem(m);    }    bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf)));    bzero((caddr_t)vifp, sizeof (*vifp));    /* Adjust numvifs down */    for (vifi = numvifs; vifi > 0; vifi--)	if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break;    numvifs = vifi;    splx(s);    if (mrtdebug)      log(LOG_DEBUG, "del_vif %d, numvifs %d\n", *vifip, numvifs);    return 0;}/* * Add an mfc entry */static intadd_mfc(mfccp)    struct mfcctl *mfccp;{    struct mfc *rt;    register struct mbuf *mb_rt;    u_long hash;    struct mbuf *mb_ntry;    struct rtdetq *rte;    register u_short nstl;    int s;    int i;    MFCFIND(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr, rt);    /* If an entry already exists, just update the fields */    if (rt) {	if (mrtdebug & DEBUG_MFC)	    log(LOG_DEBUG,"add_mfc update o %x g %x p %x\n",		ntohl(mfccp->mfcc_origin.s_addr),		ntohl(mfccp->mfcc_mcastgrp.s_addr),		mfccp->mfcc_parent);	s = splnet();	rt->mfc_parent = mfccp->mfcc_parent;	for (i = 0; i < numvifs; i++)	    rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];	splx(s);	return 0;    }    /*      * Find the entry for which the upcall was made and update     */    s = splnet();    hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);    for (mb_rt = mfctable[hash], nstl = 0; mb_rt; mb_rt = mb_rt->m_next) {	rt = mtod(mb_rt, struct mfc *);	if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&	    (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) &&	    (mb_rt->m_act != NULL)) {  	    if (nstl++)		log(LOG_ERR, "add_mfc %s o %x g %x p %x dbx %x\n",		    "multiple kernel entries",		    ntohl(mfccp->mfcc_origin.s_addr),		    ntohl(mfccp->mfcc_mcastgrp.s_addr),		    mfccp->mfcc_parent, mb_rt->m_act);	    if (mrtdebug & DEBUG_MFC)		log(LOG_DEBUG,"add_mfc o %x g %x p %x dbg %x\n",		    ntohl(mfccp->mfcc_origin.s_addr),		    ntohl(mfccp->mfcc_mcastgrp.s_addr),		    mfccp->mfcc_parent, mb_rt->m_act);	    rt->mfc_origin     = mfccp->mfcc_origin;	    rt->mfc_mcastgrp   = mfccp->mfcc_mcastgrp;	    rt->mfc_parent     = mfccp->mfcc_parent;	    for (i = 0; i < numvifs; i++)		rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];	    /* initialize pkt counters per src-grp */	    rt->mfc_pkt_cnt    = 0;	    rt->mfc_byte_cnt   = 0;	    rt->mfc_wrong_if   = 0;	    rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;	    rt->mfc_expire = 0;	/* Don't clean this guy up */	    nexpire[hash]--;	    /* free packets Qed at the end of this entry */	    while (mb_rt->m_act) {		mb_ntry = mb_rt->m_act;		rte = mtod(mb_ntry, struct rtdetq *);/* #ifdef RSVP_ISI */		ip_mdq(rte->m, rte->ifp, rt, -1);/* #endif */		mb_rt->m_act = mb_ntry->m_act;		m_freem(rte->m);#ifdef UPCALL_TIMING		collate(&(rte->t));#endif /* UPCALL_TIMING */		m_free(mb_ntry);	    }	}    }    /*     * It is possible that an entry is being inserted without an upcall     */    if (nstl == 0) {	if (mrtdebug & DEBUG_MFC)	    log(LOG_DEBUG,"add_mfc no upcall h %d o %x g %x p %x\n",		hash, ntohl(mfccp->mfcc_origin.s_addr),		ntohl(mfccp->mfcc_mcastgrp.s_addr),		mfccp->mfcc_parent);		for (mb_rt = mfctable[hash]; mb_rt; mb_rt = mb_rt->m_next) {	    	    rt = mtod(mb_rt, struct mfc *);	    if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&		(rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) {		rt->mfc_origin     = mfccp->mfcc_origin;		rt->mfc_mcastgrp   = mfccp->mfcc_mcastgrp;		rt->mfc_parent     = mfccp->mfcc_parent;		for (i = 0; i < numvifs; i++)		    rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];		/* initialize pkt counters per src-grp */		rt->mfc_pkt_cnt    = 0;		rt->mfc_byte_cnt   = 0;		rt->mfc_wrong_if   = 0;		rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;		if (rt->mfc_expire)		    nexpire[hash]--;		rt->mfc_expire	   = 0;	    }	}	if (mb_rt == NULL) {	    /* no upcall, so make a new entry */	    MGET(mb_rt, M_DONTWAIT, MT_MRTABLE);	    if (mb_rt == NULL) {		splx(s);		return ENOBUFS;	    }	    	    rt = mtod(mb_rt, struct mfc *);	    	    /* insert new entry at head of hash chain */	    rt->mfc_origin     = mfccp->mfcc_origin;	    rt->mfc_mcastgrp   = mfccp->mfcc_mcastgrp;	    rt->mfc_parent     = mfccp->mfcc_parent;	    for (i = 0; i < numvifs; i++)		    rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];	    /* initialize pkt counters per src-grp */	    rt->mfc_pkt_cnt    = 0;	    rt->mfc_byte_cnt   = 0;	    rt->mfc_wrong_if   = 0;	    rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;	    rt->mfc_expire     = 0;	    	    /* link into table */	    mb_rt->m_next  = mfctable[hash];	    mfctable[hash] = mb_rt;	    mb_rt->m_act = NULL;	}    }    splx(s);    return 0;}#ifdef UPCALL_TIMING/* * collect delay statistics on the upcalls  */static void collate(t)register struct timeval *t;{    register u_long d;    register struct timeval tp;    register u_long delta;        GET_TIME(tp);        if (TV_LT(*t, tp))    {	TV_DELTA(tp, *t, delta);		d = delta >> 10;	if (d > 50)	    d = 50;		++upcall_data[d];    }}#endif /* UPCALL_TIMING *//* * Delete an mfc entry */static intdel_mfc(mfccp)    struct mfcctl *mfccp;{    struct in_addr 	origin;    struct in_addr 	mcastgrp;    struct mfc 		*rt;    struct mbuf 	*mb_rt;    struct mbuf 	**nptr;    u_long 		hash;    int s;    origin = mfccp->mfcc_origin;    mcastgrp = mfccp->mfcc_mcastgrp;    hash = MFCHASH(origin.s_addr, mcastgrp.s_addr);    if (mrtdebug & DEBUG_MFC)	log(LOG_DEBUG,"del_mfc orig %x mcastgrp %x\n",	    ntohl(origin.s_addr), ntohl(mcastgrp.s_addr));    s = splnet();    nptr = &mfctable[hash];    while ((mb_rt = *nptr) != NULL) {        rt = mtod(mb_rt, struct mfc *);	if (origin.s_addr == rt->mfc_origin.s_addr &&	    mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr &&	    mb_rt->m_act == NULL)	    break;	nptr = &mb_rt->m_next;    }    if (mb_rt == NULL) {	splx(s);	return EADDRNOTAVAIL;    }    MFREE(mb_rt, *nptr);    splx(s);    return 0;}/* * Send a message to mrouted on the multicast routing socket */static intsocket_send(s, mm, src)	struct socket *s;	struct mbuf *mm;	struct sockaddr_in *src;{	if (s) {		if (sbappendaddr(&s->so_rcv,				 (struct sockaddr *)src,				 mm, (struct mbuf *)0) != 0) {			sorwakeup(s);			return 0;		}	}	m_freem(mm);	return -1;}/* * 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(ip, ifp, m, imo)    register struct ip *ip;    struct ifnet *ifp;    struct mbuf *m;    struct ip_moptions *imo;{    register struct mfc *rt;    register u_char *ipoptions;    static struct sockaddr_in 	k_igmpsrc	= { sizeof k_igmpsrc, AF_INET };    static int srctun = 0;    register struct mbuf *mm;    int s;    vifi_t vifi;    struct vif *vifp;    if (mrtdebug & DEBUG_FORWARD)	log(LOG_DEBUG, "ip_mforward: src %x, dst %x, ifp %x\n",	    ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), ifp);    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 {	/*	 * Packet arrived through a source-route tunnel.	 * Source-route tunnels are no longer supported.	 */	if ((srctun++ % 1000) == 0)	    log(LOG_ERR, "ip_mforward: received source-routed packet from %x\n",		ntohl(ip->ip_src.s_addr));	return 1;    }    if ((imo) && ((vifi = imo->imo_multicast_vif) < numvifs)) {	if (ip->ip_ttl < 255)		ip->ip_ttl++;	/* compensate for -1 in *_send routines */	if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {	    vifp = viftable + vifi;	    printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s%d)\n",		ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), vifi,		(vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "",		vifp->v_ifp->if_name, vifp->v_ifp->if_unit);	}	return (ip_mdq(m, ifp, NULL, vifi));    }    if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {	printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n",	    ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr));	if(!imo)		printf("In fact, no options were specified at all\n");

⌨️ 快捷键说明

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