ip6_forward.c

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

C
751
字号
//==========================================================================////      src/sys/netinet6/ip6_forward.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_forward.c,v 1.87 2001/12/18 01:30:43 keiichi Exp $	*//* * Copyright (C) 1995, 1996, 1997, and 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. */#include <sys/param.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/domain.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/errno.h>#include <net/if.h>#include <net/route.h>#include <netinet/in.h>#include <netinet/in_var.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/ip_var.h>#include <netinet6/in6_var.h>#include <netinet/ip6.h>#include <netinet6/ip6_var.h>#include <netinet/icmp6.h>#include <netinet6/nd6.h>#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)#include <netinet/in_pcb.h>#endif#if !((defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802))#include <netinet6/in6_pcb.h>#endif#ifdef __OpenBSD__#if NPF > 0#include <net/pfvar.h>#endif#endif#ifdef __OpenBSD__ /* KAME IPSEC */#undef IPSEC#endif#ifdef IPSEC#include <netinet6/ipsec.h>#include <netkey/key.h>#endif /* IPSEC */#if defined(IPV6FIREWALL) || (defined(__FreeBSD__) && __FreeBSD__ >= 4)#include <netinet6/ip6_fw.h>#endif#if defined(__NetBSD__) && defined(PFIL_HOOKS)#include <net/pfil.h>#endif#ifdef MIP6#include <netinet6/mip6.h>extern struct mip6_bc_list mip6_bc_list;#endif /* MIP6 *///#include <net/net_osdep.h>#ifdef NEW_STRUCT_ROUTEstruct	route ip6_forward_rt;#elsestruct	route_in6 ip6_forward_rt;#endif#ifdef MEASURE_PERFORMANCE#define OURS_CHECK_ALG_RTABLE 0	/* XXX: duplicated def. */extern int ip6_logentry;extern int ip6_logsize;extern unsigned long long ip6_performance_log[];extern long long ip6_performance_log2[];extern int ip6_ours_check_algorithm;int ip6_forward_cache_miss;static unsigned long long ctr_beg, ctr_end;static __inline unsigned long long read_tsc __P((void));static __inline void add_performance_log2 __P((unsigned long long)); /* XXX: duplicated code */static __inline unsigned long long read_tsc(void){     unsigned int h,l;     /* read Pentium counter */     __asm__(".byte 0x0f,0x31" :"=a" (l), "=d" (h));     return ((unsigned long long)h<<32) | l;}static __inline voidadd_performance_log2(val)	unsigned long long val;{	ip6_performance_log[ip6_logentry] += val;	ip6_performance_log2[ip6_logentry] = val;}#endif/* * Forward a packet.  If some error occurs return the sender * an icmp packet.  Note we can't always generate a meaningful * icmp message because icmp doesn't have a large enough repertoire * of codes and types. * * If not forwarding, just drop the packet.  This could be confusing * if ipforwarding was zero but some routing protocol was advancing * us as a gateway to somewhere.  However, we must let the routing * protocol deal with that. * */voidip6_forward(m, srcrt)	struct mbuf *m;	int srcrt;{	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);	struct sockaddr_in6 *dst;	struct rtentry *rt;	int error, type = 0, code = 0;	struct mbuf *mcopy = NULL;	struct ifnet *origifp;	/* maybe unnecessary */	int64_t srczone, dstzone;#ifdef IPSEC	struct secpolicy *sp = NULL;#endif#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)	long time_second = time.tv_sec;#endif#ifdef IPSEC	/*	 * Check AH/ESP integrity.	 */	/*	 * Don't increment ip6s_cantforward because this is the check	 * before forwarding packet actually.	 */	if (ipsec6_in_reject(m, NULL)) {		ipsec6stat.in_polvio++;		m_freem(m);		return;	}#endif /* IPSEC */	/*	 * Do not forward packets to multicast destination (should be handled	 * by ip6_mforward().	 * Do not forward packets with unspecified source.  It was discussed	 * in July 2000, on ipngwg mailing list.	 */	if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||	    IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {		ip6stat.ip6s_cantforward++;		/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */		if (ip6_log_time + ip6_log_interval < time_second) {			ip6_log_time = time_second;			log(LOG_DEBUG,			    "cannot forward "			    "from %s to %s nxt %d received on %s\n",			    ip6_sprintf(&ip6->ip6_src),			    ip6_sprintf(&ip6->ip6_dst),			    ip6->ip6_nxt,			    if_name(m->m_pkthdr.rcvif));		}		m_freem(m);		return;	}	if (ip6->ip6_hlim <= IPV6_HLIMDEC) {		/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */		icmp6_error(m, ICMP6_TIME_EXCEEDED,				ICMP6_TIME_EXCEED_TRANSIT, 0);		return;	}	ip6->ip6_hlim -= IPV6_HLIMDEC;	/*	 * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU -	 * size of IPv6 + ICMPv6 headers) bytes of the packet in case	 * we need to generate an ICMP6 message to the src.	 * Thanks to M_EXT, in most cases copy will not occur.	 *	 * It is important to save it before IPsec processing as IPsec	 * processing may modify the mbuf.	 */	mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));#ifdef IPSEC	/* get a security policy for this packet */	sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING,	    &error);	if (sp == NULL) {		ipsec6stat.out_inval++;		ip6stat.ip6s_cantforward++;		if (mcopy) {#if 0			/* XXX: what icmp ? */#else			m_freem(mcopy);#endif		}		m_freem(m);		return;	}	error = 0;	/* check policy */	switch (sp->policy) {	case IPSEC_POLICY_DISCARD:		/*		 * This packet is just discarded.		 */		ipsec6stat.out_polvio++;		ip6stat.ip6s_cantforward++;		key_freesp(sp);		if (mcopy) {#if 0			/* XXX: what icmp ? */#else			m_freem(mcopy);#endif		}		m_freem(m);		return;	case IPSEC_POLICY_BYPASS:	case IPSEC_POLICY_NONE:		/* no need to do IPsec. */		key_freesp(sp);		goto skip_ipsec;	case IPSEC_POLICY_IPSEC:		if (sp->req == NULL) {			/* XXX should be panic ? */			printf("ip6_forward: No IPsec request specified.\n");			ip6stat.ip6s_cantforward++;			key_freesp(sp);			if (mcopy) {#if 0				/* XXX: what icmp ? */#else				m_freem(mcopy);#endif			}			m_freem(m);			return;		}		/* do IPsec */		break;	case IPSEC_POLICY_ENTRUST:	default:		/* should be panic ?? */		printf("ip6_forward: Invalid policy found. %d\n", sp->policy);		key_freesp(sp);		goto skip_ipsec;	}    {	struct ipsec_output_state state;	/*	 * All the extension headers will become inaccessible	 * (since they can be encrypted).	 * Don't panic, we need no more updates to extension headers	 * on inner IPv6 packet (since they are now encapsulated).	 *	 * IPv6 [ESP|AH] IPv6 [extension headers] payload	 */	bzero(&state, sizeof(state));	state.m = m;	state.ro = NULL;	/* update at ipsec6_output_tunnel() */	state.dst = NULL;	/* update at ipsec6_output_tunnel() */	error = ipsec6_output_tunnel(&state, sp, 0);	m = state.m;	key_freesp(sp);	if (error) {		/* mbuf is already reclaimed in ipsec6_output_tunnel. */		switch (error) {		case EHOSTUNREACH:		case ENETUNREACH:		case EMSGSIZE:		case ENOBUFS:		case ENOMEM:			break;		default:			printf("ip6_output (ipsec): error code %d\n", error);			/* fall through */		case ENOENT:			/* don't show these error codes to the user */			break;		}		ip6stat.ip6s_cantforward++;		if (mcopy) {#if 0			/* XXX: what icmp ? */#else			m_freem(mcopy);#endif		}		m_freem(m);		return;	}    }    skip_ipsec:#endif /* IPSEC */#ifdef MIP6	{		/*		 * intercept and tunnel packets for home addresses		 * which we are acting as a home agent for.		 */		struct mip6_bc *mbc;		mbc = mip6_bc_list_find_withphaddr(&mip6_bc_list,						   &ip6->ip6_dst);

⌨️ 快捷键说明

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