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