raw_ip6.c

来自「eCos操作系统源码」· C语言 代码 · 共 715 行 · 第 1/2 页

C
715
字号
//==========================================================================////      src/sys/netinet6/raw_ip6.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####//==========================================================================/* * 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. * * $FreeBSD: src/sys/netinet6/raw_ip6.c,v 1.7.2.4 2001/07/29 19:32:40 ume Exp $ *//* * 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. * *	@(#)raw_ip.c	8.2 (Berkeley) 1/4/94 */#include <sys/param.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/protosw.h>#include <sys/socketvar.h>#include <sys/errno.h>#include <net/if.h>#include <net/route.h>#include <net/if_types.h>#include <netinet/in.h>#include <netinet/in_var.h>#include <netinet/in_systm.h>#include <netinet/ip6.h>#include <netinet6/ip6_var.h>#include <netinet6/ip6_mroute.h>#include <netinet/icmp6.h>#include <netinet/in_pcb.h>#include <netinet6/in6_pcb.h>#include <netinet6/nd6.h>#include <netinet6/ip6protosw.h>#include <netinet6/scope6_var.h>#include <netinet6/raw_ip6.h>#ifdef IPSEC#include <netinet6/ipsec.h>#endif /*IPSEC*/#define	satosin6(sa)	((struct sockaddr_in6 *)(sa))#define	ifatoia6(ifa)	((struct in6_ifaddr *)(ifa))/* * Raw interface to IP6 protocol. */extern struct	inpcbhead ripcb;extern struct	inpcbinfo ripcbinfo;extern u_long	rip_sendspace;extern u_long	rip_recvspace;struct rip6stat rip6stat;/* * Setup generic address and protocol structures * for raw_input routine, then pass them along with * mbuf chain. */intrip6_input(mp, offp, proto)	struct	mbuf **mp;	int	*offp, proto;{	struct mbuf *m = *mp;	register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);	register struct inpcb *in6p;	struct inpcb *last = 0;	struct ip6_recvpktopts opts;	struct sockaddr_in6 rip6src;	rip6stat.rip6s_ipackets++;#if defined(NFAITH) && 0 < NFAITH	if (faithprefix(&ip6->ip6_dst)) {		/* XXX send icmp6 host/port unreach? */		m_freem(m);		return IPPROTO_DONE;	}#endif	init_sin6(&rip6src, m); /* general init */	bzero(&opts, sizeof(opts));	LIST_FOREACH(in6p, &ripcb, inp_list) {		if ((in6p->in6p_vflag & INP_IPV6) == 0)			continue;		if (in6p->in6p_ip6_nxt &&		    in6p->in6p_ip6_nxt != proto)			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_cksum != -1) {			rip6stat.rip6s_isum++;			if (in6_cksum(m, ip6->ip6_nxt, *offp,			    m->m_pkthdr.len - *offp)) {				rip6stat.rip6s_badsum++;				continue;			}		}		if (last) {			struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);#ifdef IPSEC			/*			 * Check AH/ESP integrity.			 */			if (n && ipsec6_in_reject_so(n, last->inp_socket)) {				m_freem(n);				ipsec6stat.in_polvio++;				/* do not inject data into pcb */			} else#endif /*IPSEC*/			if (n) {				if (last->in6p_flags & IN6P_CONTROLOPTS ||				    last->in6p_socket->so_options & SO_TIMESTAMP)					ip6_savecontrol(last, ip6, n, &opts,							NULL);				/* strip intermediate headers */				m_adj(n, *offp);				if (sbappendaddr(&last->in6p_socket->so_rcv,						(struct sockaddr *)&rip6src,						 n, opts.head) == 0) {					m_freem(n);					if (opts.head)						m_freem(opts.head);					rip6stat.rip6s_fullsock++;				} else					sorwakeup(last->in6p_socket);				bzero(&opts, sizeof(opts));			}		}		last = in6p;	}#ifdef IPSEC	/*	 * Check AH/ESP integrity.	 */	if (last && ipsec6_in_reject_so(m, last->inp_socket)) {		m_freem(m);		ipsec6stat.in_polvio++;		ip6stat.ip6s_delivered--;		/* do not inject data into pcb */	} else#endif /*IPSEC*/	if (last) {		if (last->in6p_flags & IN6P_CONTROLOPTS ||		    last->in6p_socket->so_options & SO_TIMESTAMP)			ip6_savecontrol(last, ip6, m, &opts, NULL);		/* strip intermediate headers */		m_adj(m, *offp);		if (sbappendaddr(&last->in6p_socket->so_rcv,				(struct sockaddr *)&rip6src, m, opts.head) == 0) {			m_freem(m);			if (opts.head)				m_freem(opts.head);			rip6stat.rip6s_fullsock++;		} else			sorwakeup(last->in6p_socket);	} else {		rip6stat.rip6s_nosock++;		if (m->m_flags & M_MCAST)			rip6stat.rip6s_nosockmcast++;		if (proto == IPPROTO_NONE)			m_freem(m);		else {			char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */			icmp6_error(m, ICMP6_PARAM_PROB,				    ICMP6_PARAMPROB_NEXTHEADER,				    prvnxtp - mtod(m, char *));		}		ip6stat.ip6s_delivered--;	}	return IPPROTO_DONE;}voidrip6_ctlinput(cmd, sa, d)	int cmd;	struct sockaddr *sa;	void *d;{	struct ip6_hdr *ip6;	struct mbuf *m;	int off = 0;	struct ip6ctlparam *ip6cp = NULL;	const struct sockaddr_in6 *sa6_src = NULL;	void *cmdarg;	void (*notify) __P((struct inpcb *, int)) = in6_rtchange;	if (sa->sa_family != AF_INET6 ||	    sa->sa_len != sizeof(struct sockaddr_in6))		return;	if ((unsigned)cmd >= PRC_NCMDS)		return;	if (PRC_IS_REDIRECT(cmd))		notify = in6_rtchange, d = NULL;	else if (cmd == PRC_HOSTDEAD)		d = NULL;	else if (inet6ctlerrmap[cmd] == 0)		return;	/* if the parameter is from icmp6, decode it. */	if (d != NULL) {		ip6cp = (struct ip6ctlparam *)d;		m = ip6cp->ip6c_m;		ip6 = ip6cp->ip6c_ip6;		off = ip6cp->ip6c_off;		cmdarg = ip6cp->ip6c_cmdarg;		sa6_src = ip6cp->ip6c_src;	} else {		m = NULL;		ip6 = NULL;		cmdarg = NULL;		sa6_src = &sa6_any;	}	(void) in6_pcbnotify(&ripcb, sa, 0, (struct sockaddr *)sa6_src,			     0, cmd, cmdarg, notify);}/* * Generate IPv6 header and pass packet to ip6_output. * Tack on options user may have setup with control call. */intrip6_output(m, so, dstsock, control)	struct mbuf *m;	struct socket *so;	struct sockaddr_in6 *dstsock;	struct mbuf *control;{	struct in6_addr *dst;	struct ip6_hdr *ip6;	struct inpcb *in6p;	u_int	plen = m->m_pkthdr.len;	int error = 0;	struct ip6_pktopts opt, *stickyopt = NULL;	struct ifnet *oifp = NULL;	int type = 0, code = 0;		/* for ICMPv6 output statistics only */	int priv = 1;	struct in6_addr *in6a;	in6p = sotoin6pcb(so);	stickyopt = in6p->in6p_outputopts;	dst = &dstsock->sin6_addr;	if (control) {		if ((error = ip6_setpktoptions(control, &opt,					       stickyopt, priv, 0)) != 0) {			goto bad;		}		in6p->in6p_outputopts = &opt;	}	/*	 * For an ICMPv6 packet, we should know its type and code	 * to update statistics.	 */	if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {		struct icmp6_hdr *icmp6;		if (m->m_len < sizeof(struct icmp6_hdr) &&		    (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {			error = ENOBUFS;			goto bad;		}		icmp6 = mtod(m, struct icmp6_hdr *);		type = icmp6->icmp6_type;		code = icmp6->icmp6_code;	}	M_PREPEND(m, sizeof(*ip6), M_WAIT);	ip6 = mtod(m, struct ip6_hdr *);	/* Source address selection. */	if ((in6a = in6_selectsrc(dstsock, in6p->in6p_outputopts,

⌨️ 快捷键说明

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