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