ip6_mroute.c
来自「eCos操作系统源码」· C语言 代码 · 共 2,032 行 · 第 1/4 页
C
2,032 行
//==========================================================================//// src/sys/netinet6/ip6_mroute.c////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD, // FreeBSD or other sources, and are covered by the appropriate// copyright disclaimers included herein.//// Portions created by Red Hat are// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================/* $KAME: ip6_mroute.c,v 1.58 2001/12/18 02:36:31 itojun Exp $ *//* * Copyright (C) 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp *//* * IP multicast forwarding procedures * * Written by David Waitzman, BBN Labs, August 1988. * Modified by Steve Deering, Stanford, February 1989. * Modified by Mark J. Steiglitz, Stanford, May, 1991 * Modified by Van Jacobson, LBL, January 1993 * Modified by Ajit Thyagarajan, PARC, August 1993 * Modified by Bill Fenenr, PARC, April 1994 * * MROUTING Revision: 3.5.1.2 + PIM-SMv2 (pimd) Support *//* * XXX it seems that home address option processing should be reverted * before calls to socket_send(). see sys/netinet6/dest6.c for details. */#include <sys/param.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/sockio.h>#include <sys/protosw.h>#include <sys/errno.h>#include <sys/time.h>#include <net/if.h>#include <net/route.h>#include <net/raw_cb.h>#include <netinet/in.h>#include <netinet/in_var.h>#include <netinet/ip6.h>#include <netinet6/ip6_var.h>#include <netinet6/ip6_mroute.h>#include <netinet6/pim6.h>#include <netinet6/pim6_var.h>#define M_HASCL(m) ((m)->m_flags & M_EXT)static int ip6_mdq __P((struct mbuf *, struct ifnet *, struct mf6c *));static void phyint_send __P((struct ip6_hdr *, struct mif6 *, struct mbuf *));static int set_pim6 __P((int *));#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)static int get_pim6 __P((struct mbuf *));#endifstatic int socket_send __P((struct socket *, struct mbuf *, struct sockaddr_in6 *));static int register_send __P((struct ip6_hdr *, struct mif6 *, struct mbuf *));/* * Globals. All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static, * except for netstat or debugging purposes. */struct socket *ip6_mrouter = NULL;int ip6_mrouter_ver = 0;int ip6_mrtproto = IPPROTO_PIM; /* for netstat only */struct mrt6stat mrt6stat;#define NO_RTE_FOUND 0x1#define RTE_FOUND 0x2struct mf6c *mf6ctable[MF6CTBLSIZ];u_char n6expire[MF6CTBLSIZ];#if (defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)) struct mif6 mif6table[MAXMIFS];#elsestatic struct mif6 mif6table[MAXMIFS];#endif#ifdef MRT6DEBUGu_int mrt6debug = 0; /* debug level */#define DEBUG_MFC 0x02#define DEBUG_FORWARD 0x04#define DEBUG_EXPIRE 0x08#define DEBUG_XMIT 0x10#define DEBUG_REG 0x20#define DEBUG_PIM 0x40#endifstatic void expire_upcalls __P((void *));#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */#define UPCALL_EXPIRE 6 /* number of timeouts */#ifdef INET#ifdef MROUTINGextern struct socket *ip_mrouter;#endif#endif/* * 'Interfaces' associated with decapsulator (so we can tell * packets that went through it from ones that get reflected * by a broken gateway). These interfaces are never linked into * the system ifnet list & no routes point to them. I.e., packets * can't be sent this way. They only exist as a placeholder for * multicast source verification. */struct ifnet multicast_register_if;#define ENCAP_HOPS 64/* * Private variables. */static mifi_t nummifs = 0;static mifi_t reg_mif_num = (mifi_t)-1;static struct pim6stat pim6stat;static int pim6;/* * Hash function for a source, group entry */#define MF6CHASH(a, g) MF6CHASHMOD((a).s6_addr32[0] ^ (a).s6_addr32[1] ^ \ (a).s6_addr32[2] ^ (a).s6_addr32[3] ^ \ (g).s6_addr32[0] ^ (g).s6_addr32[1] ^ \ (g).s6_addr32[2] ^ (g).s6_addr32[3])/* * Find a route for a given origin IPv6 address and Multicast group address. * Quality of service parameter to be added in the future!!! */#define MF6CFIND(o, g, rt) do { \ struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \ rt = NULL; \ mrt6stat.mrt6s_mfc_lookups++; \ while (_rt) { \ if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \ IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \ (_rt->mf6c_stall == NULL)) { \ rt = _rt; \ break; \ } \ _rt = _rt->mf6c_next; \ } \ if (rt == NULL) { \ mrt6stat.mrt6s_mfc_misses++; \ } \} while (0)/* * Macros to compute elapsed time efficiently * Borrowed from Van Jacobson's scheduling code */#define TV_DELTA(a, b, delta) do { \ int xxs; \ \ delta = (a).tv_usec - (b).tv_usec; \ if ((xxs = (a).tv_sec - (b).tv_sec)) { \ switch (xxs) { \ case 2: \ delta += 1000000; \ /* fall through */ \ case 1: \ delta += 1000000; \ break; \ default: \ delta += (1000000 * xxs); \ } \ } \} while (0)#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \ (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)#ifdef UPCALL_TIMING#define UPCALL_MAX 50u_long upcall_data[UPCALL_MAX + 1];static void collate();#endif /* UPCALL_TIMING */static int get_sg_cnt __P((struct sioc_sg_req6 *));static int get_mif6_cnt __P((struct sioc_mif_req6 *));static int ip6_mrouter_init __P((struct socket *, struct mbuf *, int));static int add_m6if __P((struct mif6ctl *));static int del_m6if __P((mifi_t *));static int add_m6fc __P((struct mf6cctl *));static int del_m6fc __P((struct mf6cctl *));#ifdef __NetBSD__static struct callout expire_upcalls_ch = CALLOUT_INITIALIZER;#elif (defined(__FreeBSD__) && __FreeBSD__ >= 3)static struct callout expire_upcalls_ch;#elif defined(__OpenBSD__)static struct timeout expire_upcalls_ch;#endif/* * Handle MRT setsockopt commands to modify the multicast routing tables. */#if defined(__FreeBSD__) && __FreeBSD__ >= 3intip6_mrouter_set(so, sopt) struct socket *so; struct sockopt *sopt;{ int error = 0; struct mbuf *m; if (so != ip6_mrouter && sopt->sopt_name != MRT6_INIT) return (EACCES); if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */ return (error); if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */ return (error); switch (sopt->sopt_name) { case MRT6_INIT:#ifdef MRT6_OINIT case MRT6_OINIT:#endif error = ip6_mrouter_init(so, m, sopt->sopt_name); break; case MRT6_DONE: error = ip6_mrouter_done(); break; case MRT6_ADD_MIF: error = add_m6if(mtod(m, struct mif6ctl *)); break; case MRT6_DEL_MIF: error = del_m6if(mtod(m, mifi_t *)); break; case MRT6_ADD_MFC: error = add_m6fc(mtod(m, struct mf6cctl *)); break; case MRT6_DEL_MFC: error = del_m6fc(mtod(m, struct mf6cctl *)); break; case MRT6_PIM: error = set_pim6(mtod(m, int *)); break; default: error = EOPNOTSUPP; break; } (void)m_freem(m); return(error);}#elseintip6_mrouter_set(cmd, so, m) int cmd; struct socket *so; struct mbuf *m;{ if (cmd != MRT6_INIT && so != ip6_mrouter) return EACCES; switch (cmd) {#ifdef MRT6_OINIT case MRT6_OINIT: return ip6_mrouter_init(so, m, cmd);#endif case MRT6_INIT: return ip6_mrouter_init(so, m, cmd); case MRT6_DONE: return ip6_mrouter_done(); case MRT6_ADD_MIF: return add_m6if(mtod(m, struct mif6ctl *)); case MRT6_DEL_MIF: return del_m6if(mtod(m, mifi_t *)); case MRT6_ADD_MFC: return add_m6fc(mtod(m, struct mf6cctl *)); case MRT6_DEL_MFC: return del_m6fc(mtod(m, struct mf6cctl *)); case MRT6_PIM: return set_pim6(mtod(m, int *)); default: return EOPNOTSUPP; }}#endif/* * Handle MRT getsockopt commands */#if defined(__FreeBSD__) && __FreeBSD__ >= 3intip6_mrouter_get(so, sopt) struct socket *so; struct sockopt *sopt;{ int error = 0; if (so != ip6_mrouter) return EACCES; switch (sopt->sopt_name) { case MRT6_PIM: error = sooptcopyout(sopt, &pim6, sizeof(pim6)); break; } return (error);}#elseintip6_mrouter_get(cmd, so, m) int cmd; struct socket *so; struct mbuf **m;{ struct mbuf *mb; if (so != ip6_mrouter) return EACCES; *m = mb = m_get(M_WAIT, MT_SOOPTS); switch (cmd) { case MRT6_PIM: return get_pim6(mb); default: m_free(mb); return EOPNOTSUPP; }}#endif/* * Handle ioctl commands to obtain information from the cache */intmrt6_ioctl(cmd, data) int cmd; caddr_t data;{ int error = 0; switch (cmd) { case SIOCGETSGCNT_IN6: return(get_sg_cnt((struct sioc_sg_req6 *)data)); break; /* for safety */ case SIOCGETMIFCNT_IN6: return(get_mif6_cnt((struct sioc_mif_req6 *)data)); break; /* for safety */ default: return (EINVAL); break; } return error;}/* * returns the packet, byte, rpf-failure count for the source group provided */static intget_sg_cnt(req) struct sioc_sg_req6 *req;{ struct mf6c *rt; int s;#ifdef __NetBSD__ s = splsoftnet();#else s = splnet();#endif MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt); splx(s); if (rt != NULL) { req->pktcnt = rt->mf6c_pkt_cnt; req->bytecnt = rt->mf6c_byte_cnt; req->wrong_if = rt->mf6c_wrong_if; } else return(ESRCH);#if 0 req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;#endif return 0;}/* * returns the input and output packet and byte counts on the mif provided */static intget_mif6_cnt(req) struct sioc_mif_req6 *req;{ mifi_t mifi = req->mifi; if (mifi >= nummifs) return EINVAL; req->icount = mif6table[mifi].m6_pkt_in; req->ocount = mif6table[mifi].m6_pkt_out; req->ibytes = mif6table[mifi].m6_bytes_in; req->obytes = mif6table[mifi].m6_bytes_out; return 0;}#if !(defined(__FreeBSD__) && __FreeBSD__ >=3)/* * Get PIM processiong global */static intget_pim6(m) struct mbuf *m;{ int *i; i = mtod(m, int *); *i = pim6; return 0;}#endifstatic intset_pim6(i) int *i;{ if ((*i != 1) && (*i != 0)) return EINVAL; pim6 = *i; return 0;}/* * Enable multicast routing */static intip6_mrouter_init(so, m, cmd) struct socket *so; struct mbuf *m; int cmd;{ int *v;#ifdef MRT6DEBUG if (mrt6debug) log(LOG_DEBUG, "ip6_mrouter_init: so_type = %d, pr_protocol = %d\n", so->so_type, so->so_proto->pr_protocol);#endif if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_ICMPV6) return EOPNOTSUPP; if (!m || (m->m_len != sizeof(int *))) return ENOPROTOOPT; v = mtod(m, int *); if (*v != 1) return ENOPROTOOPT; if (ip6_mrouter != NULL) return EADDRINUSE; ip6_mrouter = so; ip6_mrouter_ver = cmd; bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?