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

📄 icmp6.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		for (ifa = ifp->if_addrlist.tqh_first; ifa;		     ifa = ifa->ifa_list.tqe_next)#endif		{			if (ifa->ifa_addr->sa_family != AF_INET6)				continue;			ifa6 = (struct in6_ifaddr *)ifa;			if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 &&			    IN6_ARE_ADDR_EQUAL(&subj_ip6->sin6_addr,					       &ifa6->ia_addr.sin6_addr))				iffound = 1;			/*			 * IPv4-mapped addresses can only be returned by a			 * Node Information proxy, since they represent			 * addresses of IPv4-only nodes, which perforce do			 * not implement this protocol.			 * [icmp-name-lookups-07, Section 5.4]			 * So we don't support NI_NODEADDR_FLAG_COMPAT in			 * this function at this moment.			 */			/* What do we have to do about ::1? */			switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {			case IPV6_ADDR_SCOPE_LINKLOCAL:				if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)					continue;				break;			case IPV6_ADDR_SCOPE_SITELOCAL:				if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)					continue;				break;			case IPV6_ADDR_SCOPE_GLOBAL:				if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)					continue;				break;			default:				continue;			}			/*			 * check if anycast is okay.			 * XXX: just experimental.  not in the spec.			 */			if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&			    (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)				continue; /* we need only unicast addresses */			if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&			    (icmp6_nodeinfo & 4) == 0) {				continue;			}			addrsofif++; /* count the address */		}		if (iffound) {			*ifpp = ifp;			return(addrsofif);		}		addrs += addrsofif;	}	return(addrs);}static intni6_store_addrs(ni6, nni6, ifp0, resid)	struct icmp6_nodeinfo *ni6, *nni6;	struct ifnet *ifp0;	int resid;{#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	struct ifnet *ifp = ifp0 ? ifp0 : ifnet;#else	struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&ifnet);#endif	struct in6_ifaddr *ifa6;	struct ifaddr *ifa;	struct ifnet *ifp_dep = NULL;	int copied = 0, allow_deprecated = 0;	u_char *cp = (u_char *)(nni6 + 1);	int niflags = ni6->ni_flags;	u_int32_t ltime;#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)	long time_second = time.tv_sec;#endif	if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL))		return(0);	/* needless to copy */  again:#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)	for (; ifp; ifp = ifp->if_next)#else	for (; ifp; ifp = TAILQ_NEXT(ifp, if_list))#endif	{#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)#else		for (ifa = ifp->if_addrlist.tqh_first; ifa;		     ifa = ifa->ifa_list.tqe_next)#endif		{			if (ifa->ifa_addr->sa_family != AF_INET6)				continue;			ifa6 = (struct in6_ifaddr *)ifa;			if (IFA6_IS_DEPRECATED(ifa6) &&			    allow_deprecated == 0) {				/*				 * prefererred address should be put before				 * deprecated addresses.				 */				/* record the interface for later search */				if (ifp_dep == NULL)					ifp_dep = ifp;				continue;			}			else if (!IFA6_IS_DEPRECATED(ifa6) &&				 allow_deprecated != 0)				continue; /* we now collect deprecated addrs */			/* What do we have to do about ::1? */			switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) {			case IPV6_ADDR_SCOPE_LINKLOCAL:				if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0)					continue;				break;			case IPV6_ADDR_SCOPE_SITELOCAL:				if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0)					continue;				break;			case IPV6_ADDR_SCOPE_GLOBAL:				if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0)					continue;				break;			default:				continue;			}			/*			 * check if anycast is okay.			 * XXX: just experimental.  not in the spec.			 */			if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 &&			    (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0)				continue;			if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&			    (icmp6_nodeinfo & 4) == 0) {				continue;			}			/* now we can copy the address */			if (resid < sizeof(struct in6_addr) +			    sizeof(u_int32_t)) {				/*				 * We give up much more copy.				 * Set the truncate flag and return.				 */				nni6->ni_flags |=					NI_NODEADDR_FLAG_TRUNCATE;				return(copied);			}			/*			 * Set the TTL of the address.			 * The TTL value should be one of the following			 * according to the specification:			 *			 * 1. The remaining lifetime of a DHCP lease on the			 *    address, or			 * 2. The remaining Valid Lifetime of a prefix from			 *    which the address was derived through Stateless			 *    Autoconfiguration.			 *			 * Note that we currently do not support stateful			 * address configuration by DHCPv6, so the former			 * case can't happen.			 *			 * TTL must be 2^31 > TTL >= 0.			 */			if (ifa6->ia6_lifetime.ia6t_expire == 0)				ltime = ND6_INFINITE_LIFETIME;			else {				if (ifa6->ia6_lifetime.ia6t_expire >				    time_second) {					ltime = ifa6->ia6_lifetime.ia6t_expire						- time_second;				} else					ltime = 0;			}			if (ltime > 0x7fffffff)				ltime = 0x7fffffff;			ltime = htonl(ltime);						bcopy(&ltime, cp, sizeof(u_int32_t));			cp += sizeof(u_int32_t);			/* copy the address itself */			bcopy(&ifa6->ia_addr.sin6_addr, cp,			      sizeof(struct in6_addr));			/* XXX: KAME link-local hack; remove ifindex */			if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr))				((struct in6_addr *)cp)->s6_addr16[1] = 0;			cp += sizeof(struct in6_addr);						resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));			copied += (sizeof(struct in6_addr) +				   sizeof(u_int32_t));		}		if (ifp0)	/* we need search only on the specified IF */			break;	}	if (allow_deprecated == 0 && ifp_dep != NULL) {		ifp = ifp_dep;		allow_deprecated = 1;		goto again;	}	return(copied);}/* * XXX almost dup'ed code with rip6_input. */static inticmp6_rip6_input(mp, off)	struct	mbuf **mp;	int	off;{	struct mbuf *m = *mp;	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);	struct in6pcb *in6p;	struct in6pcb *last = NULL;	struct sockaddr_in6 rip6src;	struct icmp6_hdr *icmp6;	struct ip6_recvpktopts opts;#ifndef PULLDOWN_TEST	/* this is assumed to be safe. */	icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);#else	IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));	if (icmp6 == NULL) {		/* m is already reclaimed */		return IPPROTO_DONE;	}#endif	bzero(&opts, sizeof(opts));	bzero(&rip6src, sizeof(rip6src));	rip6src.sin6_len = sizeof(struct sockaddr_in6);	rip6src.sin6_family = AF_INET6;	/* KAME hack: recover scopeid */	(void)in6_recoverscope(&rip6src, &ip6->ip6_src, m->m_pkthdr.rcvif);#if defined(__FreeBSD__) && __FreeBSD__ >= 3	LIST_FOREACH(in6p, &ripcb, inp_list)#elif defined(__OpenBSD__)	for (in6p = rawin6pcbtable.inpt_queue.cqh_first;	     in6p != (struct inpcb *)&rawin6pcbtable.inpt_queue;	     in6p = in6p->inp_queue.cqe_next)#else	for (in6p = rawin6pcb.in6p_next;	     in6p != &rawin6pcb; in6p = in6p->in6p_next)#endif	{#if defined(__FreeBSD__) && __FreeBSD__ >= 3		if ((in6p->inp_vflag & INP_IPV6) == 0)			continue;#endif#ifdef HAVE_NRL_INPCB		if (!(in6p->in6p_flags & INP_IPV6))			continue;#endif		if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)			continue;		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&		   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))			continue;		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&		   !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))			continue;		if (in6p->in6p_icmp6filt		    && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type,				 in6p->in6p_icmp6filt))			continue;		if (last) {			struct	mbuf *n;			if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {				if (last->in6p_flags & IN6P_CONTROLOPTS)					ip6_savecontrol(last, ip6, n, &opts,							NULL);				/* strip intermediate headers */				m_adj(n, off);				if (sbappendaddr(&last->in6p_socket->so_rcv,						 (struct sockaddr *)&rip6src,						 n, opts.head) == 0) {					/* should notify about lost packet */					m_freem(n);					if (opts.head) {						m_freem(opts.head);					}				} else					sorwakeup(last->in6p_socket);				bzero(&opts, sizeof(opts));			}		}		last = in6p;	}	if (last) {		if (last->in6p_flags & IN6P_CONTROLOPTS)			ip6_savecontrol(last, ip6, m, &opts, NULL);		/* strip intermediate headers */		m_adj(m, off);		if (sbappendaddr(&last->in6p_socket->so_rcv,				 (struct sockaddr *)&rip6src,				 m, opts.head) == 0) {			m_freem(m);			if (opts.head)				m_freem(opts.head);		} else			sorwakeup(last->in6p_socket);	} else {		m_freem(m);		ip6stat.ip6s_delivered--;	}	return IPPROTO_DONE;}/* * Reflect the ip6 packet back to the source. * OFF points to the icmp6 header, counted from the top of the mbuf. * * Note: RFC 1885 required that an echo reply should be truncated if it * did not fit in with (return) path MTU, and KAME code supported the * behavior.  However, as a clarification after the RFC, this limitation * was removed in a revised version of the spec, RFC 2463.  We had kept the * old behavior, with a (non-default) ifdef block, while the new version of * the spec was an internet-draft status, and even after the new RFC was * published.  But it would rather make sense to clean the obsoleted part * up, and to make the code simpler at this stage. */voidicmp6_reflect(m, off)	struct	mbuf *m;	size_t off;{	struct ip6_hdr *ip6;	struct icmp6_hdr *icmp6;	struct in6_ifaddr *ia;	struct in6_addr t, *src = 0;	int plen;	int type, code;	struct ifnet *outif = NULL;	struct sockaddr_in6 sa6_src, sa6_dst;	/* too short to reflect */	if (off < sizeof(struct ip6_hdr)) {		nd6log((LOG_DEBUG,		    "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",		    (u_long)off, (u_long)sizeof(struct ip6_hdr),		    __FILE__, __LINE__));		goto bad;	}	/*	 * If there are extra headers between IPv6 and ICMPv6, strip	 * off that header first.	 */#ifdef DIAGNOSTIC	if (sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) > MHLEN)		panic("assumption failed in icmp6_reflect");#endif	if (off > sizeof(struct ip6_hdr)) {		size_t l;		struct ip6_hdr nip6;		l = off - sizeof(struct ip6_hdr);		m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);		m_adj(m, l);		l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);		if (m->m_len < l) {			if ((m = m_pullup(m, l)) == NULL)				return;		}		bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6));	} else /* off == sizeof(struct ip6_hdr) */ {		size_t l;		l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);		if (m->m_len < l) {			if ((m = m_pullup(m, l)) == NULL)				return;		}	}	plen = m->m_pkthdr.len - sizeof(struct ip6_hdr);	ip6 = mtod(m, struct ip6_hdr *);	ip6->ip6_nxt = IPPROTO_ICMPV6;	icmp6 = (struct icmp6_hdr *)(ip6 + 1);	type = icmp6->icmp6_type; /* keep type for statistics */	code = icmp6->icmp6_code; /* ditto. */	t = ip6->ip6_dst;	/*	 * ip6_input() drops a packet if its src is multicast.	 * So, the src is never multicast.	 */	ip6->ip6_dst = ip6->ip6_src;	/*	 * XXX: make sure to embed scope zone information, using	 * already embedded IDs or the received interface (if any).	 * Note that rcvif may be NULL.	 * TODO: scoped routing case (XXX).	 */	bzero(&sa6_src, sizeof(sa6_src));	sa6_src.sin6_family = AF_INET6;	sa6_src.sin6_len = sizeof(sa6_src);	sa6_src.sin6_addr = ip6->ip6_dst;	in6_recoverscope(&sa6_src, &ip6->ip6_dst, m->m_pkthdr.rcvif);	in6_embedscope(&sa6_src.sin6_addr, &sa6_src);	ip6->ip6_dst = sa6_src.sin6_addr;	bzero(&sa6_dst, sizeof(sa6_dst));	sa6_dst.sin6_family = AF_INET6;	sa6_dst.sin6_len = sizeof(sa6_dst);	sa6_dst.sin6_addr = t;	in6_recoverscope(&sa6_dst, &t, m->m_pkthdr.rcvif);	in6_embedscope(&t, &sa6_dst);	/*	 * If the incoming packet was addressed directly to us (i.e. unicast),	 * use dst as the src for the reply.	 * The IN6_IFF_NOTREADY case would be VERY rare, but is possible	 * (for example) when we encounter an error while forwarding procedure	 * destined to a duplicated address of ours.	 */	for (ia = in6_ifaddr; ia; ia = ia->ia_next)		if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) &&		    (ia->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0) {			src = &t;			break;		}	if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) && (m->m_flags & M_LOOP)) {		/*		 * This is the case if the dst is our link-local address		 * and the sender is also ourselves.		 */		src = &t;	}	if (src == 0) {		int e;#ifdef NEW_STRUCT_ROUTE		struct route ro;#else		struct route_in6 ro;#endif		/*		 * This case matches to multicasts, our anycast, or unicasts		 * that we do not own.  Select a source address based on the		 * source address of the erroneous packet.		 */		bzero(&ro, sizeof(ro));		src = in6_selectsrc(&sa6_src, NULL, NULL, &ro, NULL, NULL, &e);		if (ro.ro_rt) { /* XXX: see comments in icmp6_mtudisc_update */			RTFREE(ro.ro_rt); /* XXX: we could use this */		}		if (src == NULL) {			nd6log((LOG_DEBUG,			    "icmp6_reflect: source can't be determined: "			    "dst=%s, error=%d\n",			    ip6_sprintf(&sa6_src.sin6_addr), e));			goto bad;		}	}	ip6->ip6_src = *src;	ip6->ip6_flow = 0;	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;	ip6->ip6_vfc |= IPV6_VERSION;	ip6->ip6_nxt = IPPROTO_ICMPV6;	if (m->m_pkthdr.rcvif) {		/* XXX: This may not be the outgoing i

⌨️ 快捷键说明

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