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 + -
显示快捷键?