ip6_input.c
来自「eCos操作系统源码」· C语言 代码 · 共 2,515 行 · 第 1/5 页
C
2,515 行
//==========================================================================//// src/sys/netinet6/ip6_input.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_input.c,v 1.242 2001/12/27 17:40:10 jinmei 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. *//* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 */#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/socketvar.h>#include <sys/errno.h>#include <net/if.h>#include <net/if_types.h>#include <net/if_dl.h>#include <net/route.h>#include <net/netisr.h>#if defined(__FreeBSD__) && __FreeBSD__ >= 4#include <net/intrq.h>#endif#include <netinet/in.h>#include <netinet/in_systm.h>#ifdef INET#include <netinet/ip.h>#include <netinet/ip_icmp.h>#endif /* INET */#include <netinet/ip6.h>#include <netinet6/in6_var.h>#include <netinet6/ip6_var.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#include <netinet/icmp6.h>#include <netinet6/in6_ifattach.h>#include <netinet6/nd6.h>#ifdef __bsdi__#include <netinet6/raw_ip6.h>#endif#ifdef MIP6#include <netinet6/mip6.h>#endif#if defined(IPSEC) && !defined(__OpenBSD__)#include <netinet6/ipsec.h>#endif#if defined(IPV6FIREWALL) || (defined(__FreeBSD__) && __FreeBSD__ >= 4)#include <netinet6/ip6_fw.h>#endif#include <netinet6/ip6protosw.h>/* we need it for NLOOP. */#if NGIF > 0#include <netinet6/in6_gif.h>#endif#ifdef MIP6#include <netinet6/mip6.h>#endif /* MIP6 */#ifdef __OpenBSD__#if NPF > 0#include <net/pfvar.h>#endif#endifextern struct domain inet6domain;extern struct ip6protosw inet6sw[];#ifdef __bsdi__#if _BSDI_VERSION < 199802extern struct ifnet loif;#elseextern struct ifnet *loifp;#endif#endifu_char ip6_protox[IPPROTO_MAX];static int ip6qmaxlen = IFQ_MAXLEN;struct in6_ifaddr *in6_ifaddr;#if !(defined(__FreeBSD__) && __FreeBSD__ >= 4)struct ifqueue ip6intrq;#endif#if defined(__NetBSD__)extern struct ifnet loif[NLOOP];#endif#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)extern struct callout in6_tmpaddrtimer_ch;#elif defined(__OpenBSD__)extern struct timeout in6_tmpaddrtimer_ch;#endifint ip6_forward_srcrt; /* XXX */int ip6_sourcecheck; /* XXX */int ip6_sourcecheck_interval; /* XXX */#if defined(__FreeBSD__) && __FreeBSD__ >= 4const int int6intrq_present = 1;#endif#ifdef MEASURE_PERFORMANCE#define MEASURE_PERFORMANCE_UDPONLY#define IP6_PERFORM_LOGSIZE 10000int ip6_logentry;int ip6_logsize = IP6_PERFORM_LOGSIZE;unsigned long long ip6_performance_log[IP6_PERFORM_LOGSIZE];unsigned long long ip6_performance_log2[IP6_PERFORM_LOGSIZE];struct in6_addr ip6_performance_addrlog[IP6_PERFORM_LOGSIZE];#endif#ifdef MEASURE_PERFORMANCE#define OURS_CHECK_ALG_RTABLE 0#define OURS_CHECK_ALG_LINEAR 1#define OURS_CHECK_ALG_HASH 2#define OURS_CHECK_ALG_LARGEHASH 3#ifdef OURS_CHECK_LINEARint ip6_ours_check_algorithm = OURS_CHECK_ALG_LINEAR;#elif OURS_CHECK_HASHint ip6_ours_check_algorithm = OURS_CHECK_ALG_HASH;#elseint ip6_ours_check_algorithm = OURS_CHECK_ALG_RTABLE;#endif#elseint ip6_ours_check_algorithm;#endif#if defined(IPV6FIREWALL) || (defined(__FreeBSD__) && __FreeBSD__ >= 4)/* firewall hooks */ip6_fw_chk_t *ip6_fw_chk_ptr;ip6_fw_ctl_t *ip6_fw_ctl_ptr;#endif#if defined(__FreeBSD__) && __FreeBSD__ >= 4int ip6_fw_enable = 1;#endifstruct ip6stat ip6stat;static void ip6_init2 __P((void *));static struct mbuf *ip6_setdstifaddr __P((struct mbuf *, struct in6_ifaddr *));static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));#ifdef PULLDOWN_TESTstatic struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int));#endif#ifdef NATPTextern int ip6_protocol_tr;int natpt_in6 __P((struct mbuf *, struct mbuf **));extern void ip_forward __P((struct mbuf *, int));#endif#ifdef MEASURE_PERFORMANCEstatic unsigned long long ctr_beg, ctr_end;static __inline unsigned long long read_tsc __P((void));static __inline void add_performance_log __P((unsigned long long, struct in6_addr *)); #endif#ifdef MEASURE_PERFORMANCEstatic __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_log(val, addr) unsigned long long val; struct in6_addr *addr;{ ip6_logentry = (ip6_logentry + 1) % ip6_logsize; ip6_performance_log[ip6_logentry] = val; ip6_performance_addrlog[ip6_logentry] = *addr;}#endif/* * IP6 initialization: fill in IP6 protocol switch table. * All protocols not implemented in kernel go to raw IP6 protocol handler. */voidip6_init(){ struct ip6protosw *pr; int i;#ifndef __OpenBSD__ struct timeval tv;#endif#ifdef RADIX_ART rt_tables[AF_INET6]->rnh_addrsize = sizeof(struct in6_addr);#endif#ifdef DIAGNOSTIC if (sizeof(struct protosw) != sizeof(struct ip6protosw)) panic("sizeof(protosw) != sizeof(ip6protosw)");#endif pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); if (pr == 0) panic("ip6_init"); for (i = 0; i < IPPROTO_MAX; i++) ip6_protox[i] = pr - inet6sw; for (pr = (struct ip6protosw *)inet6domain.dom_protosw; pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) if (pr->pr_domain->dom_family == PF_INET6 && pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) ip6_protox[pr->pr_protocol] = pr - inet6sw; ip6intrq.ifq_maxlen = ip6qmaxlen;#if (defined(__FreeBSD__) && __FreeBSD__ >= 4) register_netisr(NETISR_IPV6, ip6intr);#endif addrsel_policy_init(); nd6_init(); frag6_init();#if defined(__FreeBSD__) && __FreeBSD__ >= 4#else#ifdef IPV6FIREWALL ip6_fw_init();#endif#endif#ifndef __OpenBSD__ /* * in many cases, random() here does NOT return random number * as initialization during bootstrap time occur in fixed order. */ microtime(&tv); ip6_flow_seq = random() ^ tv.tv_usec; microtime(&tv); ip6_desync_factor = (random() ^ tv.tv_usec) % MAX_TEMP_DESYNC_FACTOR;#else ip6_flow_seq = arc4random(); ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;#endif#ifndef __FreeBSD__ ip6_init2((void *)0);#endif#ifdef MIP6 mip6_init();#endif /* MIP6 */#ifdef MEASURE_PERFORMANCE in6h_hashinit();#endif}static voidip6_init2(dummy) void *dummy;{#if defined(__bsdi__) && _BSDI_VERSION < 199802 struct ifnet *loifp = &loif;#endif /* * to route local address of p2p link to loopback, * assign loopback address first. */#ifdef __bsdi__ in6_ifattach(loifp, NULL);#elif defined(__OpenBSD__) in6_ifattach(lo0ifp, NULL);#else in6_ifattach(&loif[0], NULL);#endif /* nd6_timer_init */#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3) callout_init(&nd6_timer_ch); callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL);#elif defined(__OpenBSD__) bzero(&nd6_timer_ch, sizeof(nd6_timer_ch)); timeout_set(&nd6_timer_ch, nd6_timer, NULL); timeout_add(&nd6_timer_ch, hz);#else timeout(nd6_timer, (caddr_t)0, hz);#endif /* timer for regeneranation of temporary addresses randomize ID */#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3) callout_init(&in6_tmpaddrtimer_ch); callout_reset(&in6_tmpaddrtimer_ch, (ip6_temp_preferred_lifetime - ip6_desync_factor - ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL);#elif defined(__OpenBSD__) timeout_set(&in6_tmpaddrtimer_ch, in6_tmpaddrtimer, NULL); timeout_add(&in6_tmpaddrtimer_ch, (ip6_temp_preferred_lifetime - ip6_desync_factor - ip6_temp_regen_advance) * hz);#else timeout(in6_tmpaddrtimer, (caddr_t)0, (ip6_temp_preferred_lifetime - ip6_desync_factor - ip6_temp_regen_advance) * hz);#endif}SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);/* * IP6 input interrupt handling. Just pass the packet to ip6_input. */voidip6intr(){ int s; struct mbuf *m; for (;;) { s = splimp(); IF_DEQUEUE(&ip6intrq, m); splx(s); if (m == 0) return; ip6_input(m); }}#if (defined(__FreeBSD__) && __FreeBSD__ <= 3)NETISR_SET(NETISR_IPV6, ip6intr);#endif#ifdef NEW_STRUCT_ROUTEextern struct route ip6_forward_rt;#elseextern struct route_in6 ip6_forward_rt;/* NetBSD/OpenBSD requires NEW_STRUCT_ROUTE */#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)#error NEW_STRUCT_ROUTE is required#endif#endifvoidip6_input(m) struct mbuf *m;{ struct ip6_hdr *ip6; int off = sizeof(struct ip6_hdr), nest; u_int32_t plen; u_int32_t rtalert = ~0; int nxt, ours = 0; struct ifnet *deliverifp = NULL;#if 0 struct mbuf *mhist; /* onion peeling history */ caddr_t hist;#endif#if defined(__bsdi__) && _BSDI_VERSION < 199802 struct ifnet *loifp = &loif;#endif#if defined(__NetBSD__) && defined(PFIL_HOOKS) struct packet_filter_hook *pfh; struct mbuf *m0; int rv;#endif /* PFIL_HOOKS */#if defined(IPSEC) && !defined(__OpenBSD__) /* * should the inner packet be considered authentic? * see comment in ah4_input(). */ m->m_flags &= ~M_AUTHIPHDR; m->m_flags &= ~M_AUTHIPDGM;#endif /* * make sure we don't have onion peering information into m_aux. */ ip6_delaux(m); /* * mbuf statistics */ if (m->m_flags & M_EXT) { if (m->m_next) ip6stat.ip6s_mext2m++; else ip6stat.ip6s_mext1++; } else {#define M2MMAX (sizeof(ip6stat.ip6s_m2m)/sizeof(ip6stat.ip6s_m2m[0])) if (m->m_next) { if (m->m_flags & M_LOOP) {#ifdef __bsdi__ ip6stat.ip6s_m2m[loifp->if_index]++; /* XXX */#elif defined(__OpenBSD__) ip6stat.ip6s_m2m[lo0ifp->if_index]++; /* XXX */#else ip6stat.ip6s_m2m[loif[0].if_index]++; /* XXX */#endif } else if (m->m_pkthdr.rcvif->if_index < M2MMAX) ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++; else ip6stat.ip6s_m2m[0]++; } else ip6stat.ip6s_m1++;#undef M2MMAX } in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive); ip6stat.ip6s_total++;#ifndef PULLDOWN_TEST /* * L2 bridge code and some other code can return mbuf chain * that does not conform to KAME requirement. too bad. * XXX: fails to join if interface MTU > MCLBYTES. jumbogram? */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?