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

📄 nd6.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
//==========================================================================////      src/sys/netinet6/nd6.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: nd6.c,v 1.221 2001/12/18 02:23:45 itojun 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. *//* * XXX * KAME 970409 note: * BSD/OS version heavily modifies this code, related to llinfo. * Since we don't have BSD/OS version of net/route.c in our hand, * I left the code mostly as it was in 970310.  -- itojun */#include <sys/param.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/sockio.h>#include <sys/protosw.h>#include <sys/errno.h>#include <sys/queue.h>#include <sys/sysctl.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_types.h>#include <net/route.h>#include <netinet/in.h>#ifndef __NetBSD__#include <netinet/if_ether.h>#ifdef __bsdi__#include <net/if_fddi.h>#endif#ifdef __OpenBSD__#include <netinet/ip_ipsp.h>#endif#else /* __NetBSD__ */#include <net/if_ether.h>#include <netinet/if_inarp.h>#include <net/if_fddi.h>#endif /* __NetBSD__ */#include <netinet6/in6_var.h>#include <netinet/ip6.h>#include <netinet6/ip6_var.h>#include <netinet6/nd6.h>#include <netinet/icmp6.h>#if defined(__NetBSD__)extern struct ifnet loif[NLOOP];#endif#define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */#define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */#define SIN6(s) ((struct sockaddr_in6 *)s)#define SDL(s) ((struct sockaddr_dl *)s)/* timer values */int	nd6_prune	= 1;	/* walk list every 1 seconds */int	nd6_delay	= 5;	/* delay first probe time 5 second */int	nd6_umaxtries	= 3;	/* maximum unicast query */int	nd6_mmaxtries	= 3;	/* maximum multicast query */int	nd6_useloopback = 1;	/* use loopback interface for local traffic */int	nd6_gctimer	= (60 * 60 * 24); /* 1 day: garbage collection timer *//* preventing too many loops in ND option parsing */int nd6_maxndopt = 10;	/* max # of ND options allowed */int nd6_maxnudhint = 0;	/* max # of subsequent upper layer hints */int nd6_debug = 1;/* for debugging? */static int nd6_inuse, nd6_allocated;struct llinfo_nd6 llinfo_nd6 = {&llinfo_nd6, &llinfo_nd6};static size_t nd_ifinfo_indexlim = 8;struct nd_ifinfo *nd_ifinfo = NULL;struct nd_drhead nd_defrouter;struct nd_prhead nd_prefix = { 0 };int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL;static struct sockaddr_in6 all1_sa;static void nd6_slowtimo __P((void *));static int regen_tmpaddr __P((struct in6_ifaddr *));static struct llinfo_nd6 *nd6_free __P((struct rtentry *, int));#ifdef __NetBSD__struct callout nd6_slowtimo_ch = CALLOUT_INITIALIZER;struct callout nd6_timer_ch = CALLOUT_INITIALIZER;extern struct callout in6_tmpaddrtimer_ch;#elif (defined(__FreeBSD__) && __FreeBSD__ >= 3)struct callout nd6_slowtimo_ch;struct callout nd6_timer_ch;extern struct callout in6_tmpaddrtimer_ch;#elif defined(__OpenBSD__)struct timeout nd6_slowtimo_ch;struct timeout nd6_timer_ch;extern struct timeout in6_tmpaddrtimer_ch;#endifvoidnd6_init(){	static int nd6_init_done = 0;	int i;	if (nd6_init_done) {		log(LOG_NOTICE, "nd6_init called more than once(ignored)\n");		return;	}	all1_sa.sin6_family = AF_INET6;	all1_sa.sin6_len = sizeof(struct sockaddr_in6);	for (i = 0; i < sizeof(all1_sa.sin6_addr); i++)		all1_sa.sin6_addr.s6_addr[i] = 0xff;	/* initialization of the default router list */	TAILQ_INIT(&nd_defrouter);	nd6_init_done = 1;	/* start timer */#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)	callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,	    nd6_slowtimo, NULL);#elif defined(__OpenBSD__)	timeout_set(&nd6_slowtimo_ch, nd6_slowtimo, NULL);	timeout_add(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz);#else	timeout(nd6_slowtimo, (caddr_t)0, ND6_SLOWTIMER_INTERVAL * hz);#endif}voidnd6_ifattach(ifp)	struct ifnet *ifp;{	/*	 * We have some arrays that should be indexed by if_index.	 * since if_index will grow dynamically, they should grow too.	 */	if (nd_ifinfo == NULL || if_index >= nd_ifinfo_indexlim) {		size_t n;		caddr_t q;		while (if_index >= nd_ifinfo_indexlim)			nd_ifinfo_indexlim <<= 1;		/* grow nd_ifinfo */		n = nd_ifinfo_indexlim * sizeof(struct nd_ifinfo);		q = (caddr_t)malloc(n, M_IP6NDP, M_WAITOK);		bzero(q, n);		if (nd_ifinfo) {			bcopy((caddr_t)nd_ifinfo, q, n/2);			free((caddr_t)nd_ifinfo, M_IP6NDP);		}		nd_ifinfo = (struct nd_ifinfo *)q;	}#define ND nd_ifinfo[ifp->if_index]	/*	 * Don't initialize if called twice.	 * XXX: to detect this, we should choose a member that is never set	 * before initialization of the ND structure itself.  We formaly used	 * the linkmtu member, which was not suitable because it could be 	 * initialized via "ifconfig mtu".	 */	if (ND.basereachable)		return;#ifdef DIAGNOSTIC#if defined(__FreeBSD__) && __FreeBSD__ >= 5	if (!ifnet_byindex(ifp->if_index))		panic("nd6_ifattach: ifnet_byindex is NULL");#else	if (!ifindex2ifnet[ifp->if_index])		panic("nd6_ifattach: ifindex2ifnet is NULL");#endif#endif#if defined(__FreeBSD__) && __FreeBSD__ >= 5	ND.linkmtu = ifnet_byindex(ifp->if_index)->if_mtu;#else	ND.linkmtu = ifindex2ifnet[ifp->if_index]->if_mtu;#endif	ND.chlim = IPV6_DEFHLIM;	ND.basereachable = REACHABLE_TIME;	ND.reachable = ND_COMPUTE_RTIME(ND.basereachable);	ND.retrans = RETRANS_TIMER;	ND.receivedra = 0;	/*	 * Note that the default value of ip6_accept_rtadv is 0, which means	 * we won't accept RAs by default even if we set ND6_IFF_ACCEPT_RTADV	 * here.	 */	ND.flags = ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV;	nd6_setmtu(ifp);#undef ND}/* * Reset ND level link MTU. This function is called when the physical MTU * changes, which means we might have to adjust the ND level MTU. */voidnd6_setmtu(ifp)	struct ifnet *ifp;{#ifndef MIN#define MIN(a,b) ((a) < (b) ? (a) : (b))#endif	struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];	u_long oldmaxmtu = ndi->maxmtu;	u_long oldlinkmtu = ndi->linkmtu;	switch (ifp->if_type) {	case IFT_ARCNET:	/* XXX MTU handling needs more work */		ndi->maxmtu = MIN(60480, ifp->if_mtu);		break;	case IFT_ETHER:		ndi->maxmtu = MIN(ETHERMTU, ifp->if_mtu);		break;#if defined(__FreeBSD__) || defined(__bsdi__)	case IFT_FDDI:#if 0 // FIXME#if defined(__bsdi__) && _BSDI_VERSION >= 199802		ndi->maxmtu = MIN(FDDIMTU, ifp->if_mtu);#else		ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu);#endif#endif		break;#endif#if !(defined(__bsdi__) && _BSDI_VERSION >= 199802)	case IFT_ATM:#if 0 // FIXME		ndi->maxmtu = MIN(ATMMTU, ifp->if_mtu);#endif		break;#endif	case IFT_IEEE1394:	/* XXX should be IEEE1394MTU(1500) */		ndi->maxmtu = MIN(ETHERMTU, ifp->if_mtu);		break;#ifdef IFT_IEEE80211	case IFT_IEEE80211:	/* XXX should be IEEE80211MTU(1500) */		ndi->maxmtu = MIN(ETHERMTU, ifp->if_mtu);		break;#endif	default:		ndi->maxmtu = ifp->if_mtu;		break;	}	if (oldmaxmtu != ndi->maxmtu) {		/*		 * If the ND level MTU is not set yet, or if the maxmtu		 * is reset to a smaller value than the ND level MTU,		 * also reset the ND level MTU.		 */		if (ndi->linkmtu == 0 ||		    ndi->maxmtu < ndi->linkmtu) {			ndi->linkmtu = ndi->maxmtu;			/* also adjust in6_maxmtu if necessary. */			if (oldlinkmtu == 0) {				/*				 * XXX: the case analysis is grotty, but				 * it is not efficient to call in6_setmaxmtu()				 * here when we are during the initialization				 * procedure.				 */				if (in6_maxmtu < ndi->linkmtu)					in6_maxmtu = ndi->linkmtu;			} else				in6_setmaxmtu();		}	}#undef MIN}voidnd6_option_init(opt, icmp6len, ndopts)	void *opt;	int icmp6len;	union nd_opts *ndopts;{	bzero(ndopts, sizeof(*ndopts));	ndopts->nd_opts_search = (struct nd_opt_hdr *)opt;	ndopts->nd_opts_last		= (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len);	if (icmp6len == 0) {		ndopts->nd_opts_done = 1;		ndopts->nd_opts_search = NULL;	}}/* * Take one ND option. */struct nd_opt_hdr *nd6_option(ndopts)	union nd_opts *ndopts;{	struct nd_opt_hdr *nd_opt;	int olen;	if (!ndopts)		panic("ndopts == NULL in nd6_option\n");	if (!ndopts->nd_opts_last)		panic("uninitialized ndopts in nd6_option\n");	if (!ndopts->nd_opts_search)		return NULL;	if (ndopts->nd_opts_done)		return NULL;	nd_opt = ndopts->nd_opts_search;	/* make sure nd_opt_len is inside the buffer */	if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) {		bzero(ndopts, sizeof(*ndopts));		return NULL;	}	olen = nd_opt->nd_opt_len << 3;	if (olen == 0) {		/*		 * Message validation requires that all included		 * options have a length that is greater than zero.		 */		bzero(ndopts, sizeof(*ndopts));		return NULL;	}	ndopts->nd_opts_search = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen);	if (ndopts->nd_opts_search > ndopts->nd_opts_last) {		/* option overruns the end of buffer, invalid */		bzero(ndopts, sizeof(*ndopts));		return NULL;	} else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {		/* reached the end of options chain */		ndopts->nd_opts_done = 1;		ndopts->nd_opts_search = NULL;	}	return nd_opt;}/* * Parse multiple ND options. * This function is much easier to use, for ND routines that do not need * multiple options of the same type. */intnd6_options(ndopts)	union nd_opts *ndopts;{	struct nd_opt_hdr *nd_opt;	int i = 0;	if (!ndopts)		panic("ndopts == NULL in nd6_options\n");	if (!ndopts->nd_opts_last)		panic("uninitialized ndopts in nd6_options\n");	if (!ndopts->nd_opts_search)		return 0;	while (1) {		nd_opt = nd6_option(ndopts);		if (!nd_opt && !ndopts->nd_opts_last) {			/*			 * Message validation requires that all included			 * options have a length that is greater than zero.			 */			icmp6stat.icp6s_nd_badopt++;			bzero(ndopts, sizeof(*ndopts));			return -1;		}		if (!nd_opt)			goto skip1;		switch (nd_opt->nd_opt_type) {		case ND_OPT_SOURCE_LINKADDR:		case ND_OPT_TARGET_LINKADDR:		case ND_OPT_MTU:		case ND_OPT_REDIRECTED_HEADER:		case ND_OPT_ADVINTERVAL:		case ND_OPT_SOURCE_ADDRLIST:		case ND_OPT_TARGET_ADDRLIST:			if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {				nd6log((LOG_INFO,				    "duplicated ND6 option found (type=%d)\n",				    nd_opt->nd_opt_type));				/* XXX bark? */			} else {				ndopts->nd_opt_array[nd_opt->nd_opt_type]					= nd_opt;			}			break;		case ND_OPT_PREFIX_INFORMATION:			if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) {				ndopts->nd_opt_array[nd_opt->nd_opt_type]					= nd_opt;			}			ndopts->nd_opts_pi_end =				(struct nd_opt_prefix_info *)nd_opt;			break;		case ND_OPT_HOMEAGENT_INFO:			break;		default:			/*			 * Unknown options must be silently ignored,			 * to accomodate future extension to the protocol.			 */			nd6log((LOG_DEBUG,			    "nd6_options: unsupported option %d - "			    "option ignored\n", nd_opt->nd_opt_type));		}skip1:		i++;		if (i > nd6_maxndopt) {			icmp6stat.icp6s_nd_toomanyopt++;			nd6log((LOG_INFO, "too many loop in nd opt\n"));			break;		}		if (ndopts->nd_opts_done)			break;	}	return 0;}/* * ND6 timer routine to expire default route list and prefix list */voidnd6_timer(ignored_arg)	void	*ignored_arg;{	int s;	struct llinfo_nd6 *ln;	struct nd_defrouter *dr;	struct nd_prefix *pr;#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)	long time_second = time.tv_sec;#endif	struct ifnet *ifp;

⌨️ 快捷键说明

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