⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icmp6.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
//==========================================================================////      src/sys/netinet6/icmp6.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: icmp6.c,v 1.269 2001/12/18 02:19:16 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_icmp.c	8.2 (Berkeley) 1/4/94 */#include <sys/param.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/domain.h>#include <net/if.h>#include <net/route.h>#include <net/if_dl.h>#include <net/if_types.h>#include <netinet/in.h>#include <netinet/in_var.h>#if defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)#include <netinet/in_systm.h>#include <netinet/ip.h>#endif#include <netinet/ip6.h>#include <netinet6/ip6_var.h>#include <netinet/icmp6.h>#include <netinet6/mld6_var.h>#if defined(__FreeBSD__) && __FreeBSD__ >= 3#include <netinet/in_pcb.h>#include <netinet6/in6_pcb.h>#elif defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)#include <netinet/in_pcb.h>#else#include <netinet6/in6_pcb.h>#endif#include <netinet6/nd6.h>#include <netinet6/in6_ifattach.h>#include <netinet6/ip6protosw.h>#ifdef __OpenBSD__ /* KAME IPSEC */#undef IPSEC#endif#ifdef IPSEC#include <netinet6/ipsec.h>#include <netkey/key.h>#endif#ifdef MIP6#include <netinet6/mip6.h>#endif#ifdef HAVE_NRL_INPCB/* inpcb members */#define in6pcb		inpcb#define in6p_laddr	inp_laddr6#define in6p_faddr	inp_faddr6#define in6p_icmp6filt	inp_icmp6filt#define in6p_route	inp_route#define in6p_socket	inp_socket#define in6p_flags	inp_flags#define in6p_moptions	inp_moptions6#define in6p_outputopts	inp_outputopts6#define in6p_ip6	inp_ipv6#define in6p_flowinfo	inp_flowinfo#define in6p_sp		inp_sp#define in6p_next	inp_next#define in6p_prev	inp_prev/* * for KAME src sync over BSD*'s.  XXX: FreeBSD (>=3) are VERY different from * others... */#define in6p_ip6_nxt	inp_ipv6.ip6_nxt#endifextern struct domain inet6domain;extern struct ip6protosw inet6sw[];extern u_char ip6_protox[];struct icmp6stat icmp6stat;#if defined (__OpenBSD__)extern struct inpcbtable rawin6pcbtable;#elif !(defined(__FreeBSD__) && __FreeBSD__ >= 3)extern struct in6pcb rawin6pcb;#elseextern struct inpcbhead ripcb;#endifextern int icmp6errppslim;static int icmp6errpps_count = 0;static struct timeval icmp6errppslim_last;extern int icmp6_nodeinfo;#if defined(__NetBSD__) || defined(__OpenBSD__)/* * List of callbacks to notify when Path MTU changes are made. */struct icmp6_mtudisc_callback {	LIST_ENTRY(icmp6_mtudisc_callback) mc_list;	void (*mc_func) __P((struct in6_addr *));};LIST_HEAD(, icmp6_mtudisc_callback) icmp6_mtudisc_callbacks =    LIST_HEAD_INITIALIZER(&icmp6_mtudisc_callbacks);static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL;extern int pmtu_expire;/* XXX do these values make any sense? */static int icmp6_mtudisc_hiwat = 1280;static int icmp6_mtudisc_lowat = 256;/* * keep track of # of redirect routes. */static struct rttimer_queue *icmp6_redirect_timeout_q = NULL;/* XXX do these values make any sense? */static int icmp6_redirect_hiwat = 1280;static int icmp6_redirect_lowat = 1024;#endifstatic void icmp6_errcount __P((struct icmp6errstat *, int, int));static int icmp6_rip6_input __P((struct mbuf **, int));static int icmp6_ratelimit __P((const struct in6_addr *, const int, const int));static const char *icmp6_redirect_diag __P((struct in6_addr *,	struct in6_addr *, struct in6_addr *));#ifndef HAVE_PPSRATECHECKstatic int ppsratecheck __P((struct timeval *, int *, int));#endifstatic struct mbuf *ni6_input __P((struct mbuf *, int));static struct mbuf *ni6_nametodns __P((const char *, int, int));static int ni6_dnsmatch __P((const char *, int, const char *, int));static int ni6_addrs __P((struct icmp6_nodeinfo *, struct mbuf *,			  struct ifnet **, char *));static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,				struct ifnet *, int));static int icmp6_notify_error __P((struct mbuf *, int, int, int));static int icmp6_recover_src __P((struct mbuf *));#if defined(__NetBSD__) || defined(__OpenBSD__)static struct rtentry *icmp6_mtudisc_clone __P((struct sockaddr *));static void icmp6_mtudisc_timeout __P((struct rtentry *, struct rttimer *));static void icmp6_redirect_timeout __P((struct rtentry *, struct rttimer *));#endifvoidicmp6_init(){	mld6_init();#if defined(__NetBSD__) || defined(__OpenBSD__)	icmp6_mtudisc_timeout_q = rt_timer_queue_create(pmtu_expire);	icmp6_redirect_timeout_q = rt_timer_queue_create(icmp6_redirtimeout);#endif}static voidicmp6_errcount(stat, type, code)	struct icmp6errstat *stat;	int type, code;{	switch (type) {	case ICMP6_DST_UNREACH:		switch (code) {		case ICMP6_DST_UNREACH_NOROUTE:			stat->icp6errs_dst_unreach_noroute++;			return;		case ICMP6_DST_UNREACH_ADMIN:			stat->icp6errs_dst_unreach_admin++;			return;		case ICMP6_DST_UNREACH_BEYONDSCOPE:			stat->icp6errs_dst_unreach_beyondscope++;			return;		case ICMP6_DST_UNREACH_ADDR:			stat->icp6errs_dst_unreach_addr++;			return;		case ICMP6_DST_UNREACH_NOPORT:			stat->icp6errs_dst_unreach_noport++;			return;		}		break;	case ICMP6_PACKET_TOO_BIG:		stat->icp6errs_packet_too_big++;		return;	case ICMP6_TIME_EXCEEDED:		switch (code) {		case ICMP6_TIME_EXCEED_TRANSIT:			stat->icp6errs_time_exceed_transit++;			return;		case ICMP6_TIME_EXCEED_REASSEMBLY:			stat->icp6errs_time_exceed_reassembly++;			return;		}		break;	case ICMP6_PARAM_PROB:		switch (code) {		case ICMP6_PARAMPROB_HEADER:			stat->icp6errs_paramprob_header++;			return;		case ICMP6_PARAMPROB_NEXTHEADER:			stat->icp6errs_paramprob_nextheader++;			return;		case ICMP6_PARAMPROB_OPTION:			stat->icp6errs_paramprob_option++;			return;		}		break;	case ND_REDIRECT:		stat->icp6errs_redirect++;		return;	}	stat->icp6errs_unknown++;}#if defined(__NetBSD__) || defined(__OpenBSD__)/* * Register a Path MTU Discovery callback. */voidicmp6_mtudisc_callback_register(func)	void (*func) __P((struct in6_addr *));{	struct icmp6_mtudisc_callback *mc;	for (mc = LIST_FIRST(&icmp6_mtudisc_callbacks); mc != NULL;	     mc = LIST_NEXT(mc, mc_list)) {		if (mc->mc_func == func)			return;	}	mc = malloc(sizeof(*mc), M_PCB, M_NOWAIT);	if (mc == NULL)		panic("icmp6_mtudisc_callback_register");	mc->mc_func = func;	LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks, mc, mc_list);}#endif/* * Generate an error packet of type error in response to bad IP6 packet. */voidicmp6_error(m, type, code, param)	struct mbuf *m;	int type, code, param;{	struct ip6_hdr *oip6, *nip6;	struct icmp6_hdr *icmp6;	struct mbuf *n;	struct ip6aux *ip6a;	struct in6_addr nip6_src, *nip6_srcp;	u_int preplen;	int off;	int nxt;	icmp6stat.icp6s_error++;	/* count per-type-code statistics */	icmp6_errcount(&icmp6stat.icp6s_outerrhist, type, code);#ifdef M_DECRYPTED	/* not openbsd */	if (m->m_flags & M_DECRYPTED) {		icmp6stat.icp6s_canterror++;		goto freeit;	}#endif#ifndef PULLDOWN_TEST	IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), );#else	if (m->m_len < sizeof(struct ip6_hdr)) {		m = m_pullup(m, sizeof(struct ip6_hdr));		if (m == NULL)			return;	}#endif	oip6 = mtod(m, struct ip6_hdr *);	/*	 * If the destination address of the erroneous packet is a multicast	 * address, or the packet was sent using link-layer multicast,	 * we should basically suppress sending an error (RFC 2463, Section	 * 2.4).	 * We have two exceptions (the item e.2 in that section):	 * - the Pakcet Too Big message can be sent for path MTU discovery.	 * - the Parameter Problem Message that can be allowed an icmp6 error	 *   in the option type field.  This check has been done in	 *   ip6_unknown_opt(), so we can just check the type and code.	 */	if ((m->m_flags & (M_BCAST|M_MCAST) ||	     IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) &&	    (type != ICMP6_PACKET_TOO_BIG &&	     (type != ICMP6_PARAM_PROB ||	      code != ICMP6_PARAMPROB_OPTION)))		goto freeit;	/*	 * RFC 2463, 2.4 (e.5): source address check.	 * XXX: the case of anycast source?	 */	if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) ||	    IN6_IS_ADDR_MULTICAST(&oip6->ip6_src))		goto freeit;	/*	 * If we are about to send ICMPv6 against ICMPv6 error/redirect,	 * don't do it.	 */	nxt = -1;	off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);	if (off >= 0 && nxt == IPPROTO_ICMPV6) {		struct icmp6_hdr *icp;#ifndef PULLDOWN_TEST		IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), );		icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);#else		IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,			sizeof(*icp));		if (icp == NULL) {			icmp6stat.icp6s_tooshort++;			return;		}#endif		if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||		    icp->icmp6_type == ND_REDIRECT) {			/*			 * ICMPv6 error			 * Special case: for redirect (which is			 * informational) we must not send icmp6 error.			 */			icmp6stat.icp6s_canterror++;			goto freeit;		} else {			/* ICMPv6 informational - send the error */		}	}#if 0 /* controversial */	else if (off >= 0 && nxt == IPPROTO_ESP) {		/*		 * It could be ICMPv6 error inside ESP.  Take a safer side,		 * don't respond.		 */		icmp6stat.icp6s_canterror++;		goto freeit;	}#endif	else {		/* non-ICMPv6 - send the error */	}	oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */	/* Finally, do rate limitation check. */	if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {		icmp6stat.icp6s_toofreq++;		goto freeit;	}	/*	 * OK, ICMP6 can be generated.	 */	/*	 * Recover the original ip6_src if the src and the homeaddr	 * have been swapped while dest6 processing (see dest6.c).  To	 * avoid m_pulldown, we had better to swap addresses before	 * m_prepend below.	 *	 * XXX: We should consider the other candidate to keep the	 * icmp6 error packet correct that not swapping ip6_src and	 * homeaddr in the dest6 processing.	 */	nip6_srcp = &oip6->ip6_src;	n = ip6_findaux(m);	if (n != NULL) {		ip6a = mtod(n, struct ip6aux *);		if ((ip6a->ip6a_flags & IP6A_HASEEN) != 0 &&		    (ip6a->ip6a_flags & IP6A_SWAP) != 0) {			nip6_src = oip6->ip6_src;			nip6_srcp = &nip6_src;			if (icmp6_recover_src(m)) {				/* mbuf is freed in icmp6_recover_src */				return;			}			oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */		}	}	if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN)		m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);	preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);	M_PREPEND(m, preplen, M_DONTWAIT);	if (m && m->m_len < preplen)		m = m_pullup(m, preplen);	if (m == NULL) {		nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__));		return;	}	nip6 = mtod(m, struct ip6_hdr *);	nip6->ip6_src  = *nip6_srcp;	nip6->ip6_dst  = oip6->ip6_dst;	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))		oip6->ip6_src.s6_addr16[1] = 0;	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))		oip6->ip6_dst.s6_addr16[1] = 0;	icmp6 = (struct icmp6_hdr *)(nip6 + 1);

⌨️ 快捷键说明

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