ip6_mroute.c

来自「eCos操作系统源码」· C语言 代码 · 共 2,032 行 · 第 1/4 页

C
2,032
字号
	bzero((caddr_t)n6expire, sizeof(n6expire));	pim6 = 0;/* used for stubbing out/in pim stuff */#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)	callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,	    expire_upcalls, NULL);#elif defined(__OpenBSD__)	timeout_set(&expire_upcalls_ch, expire_upcalls, NULL);	timeout_add(&expire_upcalls_ch, EXPIRE_TIMEOUT);#else	timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);#endif#ifdef MRT6DEBUG	if (mrt6debug)		log(LOG_DEBUG, "ip6_mrouter_init\n");#endif	return 0;}/* * Disable multicast routing */intip6_mrouter_done(){	mifi_t mifi;	int i;	struct ifnet *ifp;	struct in6_ifreq ifr;	struct mf6c *rt;	struct rtdetq *rte;	int s;#ifdef __NetBSD__	s = splsoftnet();#else	s = splnet();#endif	/*	 * For each phyint in use, disable promiscuous reception of all IPv6	 * multicasts.	 */#ifdef INET#ifdef MROUTING	/*	 * If there is still IPv4 multicast routing daemon,	 * we remain interfaces to receive all muliticasted packets.	 * XXX: there may be an interface in which the IPv4 multicast	 * daemon is not interested...	 */	if (!ip_mrouter)#endif#endif	{		for (mifi = 0; mifi < nummifs; mifi++) {			if (mif6table[mifi].m6_ifp &&			    !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {				ifr.ifr_addr.sin6_family = AF_INET6;				ifr.ifr_addr.sin6_addr= in6addr_any;				ifp = mif6table[mifi].m6_ifp;				(*ifp->if_ioctl)(ifp, SIOCDELMULTI,						 (caddr_t)&ifr);			}		}	}#ifdef notyet	bzero((caddr_t)qtable, sizeof(qtable));	bzero((caddr_t)tbftable, sizeof(tbftable));#endif	bzero((caddr_t)mif6table, sizeof(mif6table));	nummifs = 0;	pim6 = 0; /* used to stub out/in pim specific code */#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)	callout_stop(&expire_upcalls_ch);#elif defined(__OpenBSD__)	timeout_del(&expire_upcalls_ch);#else	untimeout(expire_upcalls, (caddr_t)NULL);#endif	/*	 * Free all multicast forwarding cache entries.	 */	for (i = 0; i < MF6CTBLSIZ; i++) {		rt = mf6ctable[i];		while (rt) {			struct mf6c *frt;			for (rte = rt->mf6c_stall; rte != NULL; ) {				struct rtdetq *n = rte->next;				m_free(rte->m);				free(rte, M_MRTABLE);				rte = n;			}			frt = rt;			rt = rt->mf6c_next;			free(frt, M_MRTABLE);		}	}	bzero((caddr_t)mf6ctable, sizeof(mf6ctable));	/*	 * Reset de-encapsulation cache	 */	reg_mif_num = -1;	ip6_mrouter = NULL;	ip6_mrouter_ver = 0;	splx(s);#ifdef MRT6DEBUG	if (mrt6debug)		log(LOG_DEBUG, "ip6_mrouter_done\n");#endif	return 0;}static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };/* * Add a mif to the mif table */static intadd_m6if(mifcp)	struct mif6ctl *mifcp;{	struct mif6 *mifp;	struct ifnet *ifp;#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)	struct in6_ifreq ifr;#endif	int error, s;#ifdef notyet	struct tbf *m_tbf = tbftable + mifcp->mif6c_mifi;#endif	if (mifcp->mif6c_mifi >= MAXMIFS)		return EINVAL;	mifp = mif6table + mifcp->mif6c_mifi;	if (mifp->m6_ifp)		return EADDRINUSE; /* XXX: is it appropriate? */	if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > if_index)		return ENXIO;	/*	 * XXX: some OSes can remove ifp and clear ifindex2ifnet[id]	 * even for id between 0 and if_index.	 */#if defined(__FreeBSD__) && __FreeBSD__ >= 5	ifp = ifnet_byindex(mifcp->mif6c_pifi);#else	ifp = ifindex2ifnet[mifcp->mif6c_pifi];#endif	if (ifp == NULL)		return ENXIO;	if (mifcp->mif6c_flags & MIFF_REGISTER) {		if (reg_mif_num == (mifi_t)-1) {#if defined(__NetBSD__) || defined(__OpenBSD__)			strcpy(multicast_register_if.if_xname,			       "register_mif"); /* XXX */#else			multicast_register_if.if_name = "register_mif";#endif			multicast_register_if.if_flags |= IFF_LOOPBACK;			multicast_register_if.if_index = mifcp->mif6c_mifi;			reg_mif_num = mifcp->mif6c_mifi;		}		ifp = &multicast_register_if;	} /* if REGISTER */	else {		/* Make sure the interface supports multicast */		if ((ifp->if_flags & IFF_MULTICAST) == 0)			return EOPNOTSUPP;#ifdef __NetBSD__		s = splsoftnet();#else		s = splnet();#endif#if (defined(__FreeBSD__) && __FreeBSD__ >= 3)		error = if_allmulti(ifp, 1);#else		/*		 * Enable promiscuous reception of all IPv6 multicasts		 * from the interface.		 */		ifr.ifr_addr.sin6_family = AF_INET6;		ifr.ifr_addr.sin6_addr = in6addr_any;		error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);#endif		splx(s);		if (error)			return error;	}#ifdef __NetBSD__	s = splsoftnet();#else	s = splnet();#endif	mifp->m6_flags     = mifcp->mif6c_flags;	mifp->m6_ifp       = ifp;#ifdef notyet	/* scaling up here allows division by 1024 in critical code */	mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000;#endif	/* initialize per mif pkt counters */	mifp->m6_pkt_in    = 0;	mifp->m6_pkt_out   = 0;	mifp->m6_bytes_in  = 0;	mifp->m6_bytes_out = 0;	splx(s);	/* Adjust nummifs up if the mifi is higher than nummifs */	if (nummifs <= mifcp->mif6c_mifi)		nummifs = mifcp->mif6c_mifi + 1;#ifdef MRT6DEBUG	if (mrt6debug)		log(LOG_DEBUG,		    "add_mif #%d, phyint %s%d\n",		    mifcp->mif6c_mifi,		    ifp->if_name, ifp->if_unit);#endif	return 0;}/* * Delete a mif from the mif table */static intdel_m6if(mifip)	mifi_t *mifip;{	struct mif6 *mifp = mif6table + *mifip;	mifi_t mifi;	struct ifnet *ifp;#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)	struct in6_ifreq ifr;#endif	int s;	if (*mifip >= nummifs)		return EINVAL;	if (mifp->m6_ifp == NULL)		return EINVAL;#ifdef __NetBSD__	s = splsoftnet();#else	s = splnet();#endif	if (!(mifp->m6_flags & MIFF_REGISTER)) {		/*		 * XXX: what if there is yet IPv4 multicast daemon		 *      using the interface?		 */		ifp = mifp->m6_ifp;#if (defined(__FreeBSD__) && __FreeBSD__ >= 3)		if_allmulti(ifp, 0);#else		ifr.ifr_addr.sin6_family = AF_INET6;		ifr.ifr_addr.sin6_addr = in6addr_any;		(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);#endif	}#ifdef notyet	bzero((caddr_t)qtable[*mifip], sizeof(qtable[*mifip]));	bzero((caddr_t)mifp->m6_tbf, sizeof(*(mifp->m6_tbf)));#endif	bzero((caddr_t)mifp, sizeof (*mifp));	/* Adjust nummifs down */	for (mifi = nummifs; mifi > 0; mifi--)		if (mif6table[mifi - 1].m6_ifp)			break;	nummifs = mifi;	splx(s);#ifdef MRT6DEBUG	if (mrt6debug)		log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);#endif	return 0;}/* * Add an mfc entry */static intadd_m6fc(mfccp)	struct mf6cctl *mfccp;{	struct mf6c *rt;	u_long hash;	struct rtdetq *rte;	u_short nstl;	int s;	MF6CFIND(mfccp->mf6cc_origin.sin6_addr,		 mfccp->mf6cc_mcastgrp.sin6_addr, rt);	/* If an entry already exists, just update the fields */	if (rt) {#ifdef MRT6DEBUG		if (mrt6debug & DEBUG_MFC)			log(LOG_DEBUG,"add_m6fc update o %s g %s p %x\n",			    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),			    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),			    mfccp->mf6cc_parent);#endif#ifdef __NetBSD__		s = splsoftnet();#else		s = splnet();#endif		rt->mf6c_parent = mfccp->mf6cc_parent;		rt->mf6c_ifset = mfccp->mf6cc_ifset;		splx(s);		return 0;	}	/*	 * Find the entry for which the upcall was made and update	 */#ifdef __NetBSD__	s = splsoftnet();#else	s = splnet();#endif	hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,			mfccp->mf6cc_mcastgrp.sin6_addr);	for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {		if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,				       &mfccp->mf6cc_origin.sin6_addr) &&		    IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,				       &mfccp->mf6cc_mcastgrp.sin6_addr) &&		    (rt->mf6c_stall != NULL)) {			if (nstl++)				log(LOG_ERR,				    "add_m6fc: %s o %s g %s p %x dbx %p\n",				    "multiple kernel entries",				    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),				    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),				    mfccp->mf6cc_parent, rt->mf6c_stall);#ifdef MRT6DEBUG			if (mrt6debug & DEBUG_MFC)				log(LOG_DEBUG,				    "add_m6fc o %s g %s p %x dbg %x\n",				    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),				    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),				    mfccp->mf6cc_parent, rt->mf6c_stall);#endif			rt->mf6c_origin     = mfccp->mf6cc_origin;			rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;			rt->mf6c_parent     = mfccp->mf6cc_parent;			rt->mf6c_ifset	    = mfccp->mf6cc_ifset;			/* initialize pkt counters per src-grp */			rt->mf6c_pkt_cnt    = 0;			rt->mf6c_byte_cnt   = 0;			rt->mf6c_wrong_if   = 0;			rt->mf6c_expire = 0;	/* Don't clean this guy up */			n6expire[hash]--;			/* free packets Qed at the end of this entry */			for (rte = rt->mf6c_stall; rte != NULL; ) {				struct rtdetq *n = rte->next;				ip6_mdq(rte->m, rte->ifp, rt);				m_freem(rte->m);#ifdef UPCALL_TIMING				collate(&(rte->t));#endif /* UPCALL_TIMING */				free(rte, M_MRTABLE);				rte = n;			}			rt->mf6c_stall = NULL;		}	}	/*	 * It is possible that an entry is being inserted without an upcall	 */	if (nstl == 0) {#ifdef MRT6DEBUG		if (mrt6debug & DEBUG_MFC)			log(LOG_DEBUG,			    "add_m6fc no upcall h %d o %s g %s p %x\n",			    hash,			    ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),			    ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),			    mfccp->mf6cc_parent);#endif		for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {				if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,					       &mfccp->mf6cc_origin.sin6_addr)&&			    IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,					       &mfccp->mf6cc_mcastgrp.sin6_addr)) {				rt->mf6c_origin     = mfccp->mf6cc_origin;				rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;				rt->mf6c_parent     = mfccp->mf6cc_parent;				rt->mf6c_ifset	    = mfccp->mf6cc_ifset;				/* initialize pkt counters per src-grp */				rt->mf6c_pkt_cnt    = 0;				rt->mf6c_byte_cnt   = 0;				rt->mf6c_wrong_if   = 0;				if (rt->mf6c_expire)					n6expire[hash]--;				rt->mf6c_expire	   = 0;			}		}		if (rt == NULL) {			/* no upcall, so make a new entry */			rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE,						  M_NOWAIT);			if (rt == NULL) {				splx(s);				return ENOBUFS;			}				/* insert new entry at head of hash chain */			rt->mf6c_origin     = mfccp->mf6cc_origin;			rt->mf6c_mcastgrp   = mfccp->mf6cc_mcastgrp;			rt->mf6c_parent     = mfccp->mf6cc_parent;			rt->mf6c_ifset	    = mfccp->mf6cc_ifset;			/* initialize pkt counters per src-grp */			rt->mf6c_pkt_cnt    = 0;			rt->mf6c_byte_cnt   = 0;			rt->mf6c_wrong_if   = 0;			rt->mf6c_expire     = 0;			rt->mf6c_stall = NULL;				/* link into table */			rt->mf6c_next  = mf6ctable[hash];			mf6ctable[hash] = rt;		}	}	splx(s);	return 0;}#ifdef UPCALL_TIMING/* * collect delay statistics on the upcalls */static voidcollate(t)	struct timeval *t;{	u_long d;	struct timeval tp;	u_long delta;	GET_TIME(tp);	if (TV_LT(*t, tp))	{		TV_DELTA(tp, *t, delta);			d = delta >> 10;		if (d > UPCALL_MAX)			d = UPCALL_MAX;			++upcall_data[d];	}}#endif /* UPCALL_TIMING *//* * Delete an mfc entry */static intdel_m6fc(mfccp)	struct mf6cctl *mfccp;{	struct sockaddr_in6 	origin;	struct sockaddr_in6 	mcastgrp;	struct mf6c 		*rt;	struct mf6c	 	**nptr;	u_long 		hash;	int s;

⌨️ 快捷键说明

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