raw_ip.c

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

C
695
字号
//==========================================================================////      src/sys/netinet/raw_ip.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) 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.7 (Berkeley) 5/15/95 * $FreeBSD: src/sys/netinet/raw_ip.c,v 1.64.2.8 2001/07/29 19:32:40 ume Exp $ */#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/sysctl.h>#include <net/if.h>#include <net/route.h>#define _IP_VHL#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/in_pcb.h>#include <netinet/in_var.h>#include <netinet/ip_var.h>#include <netinet/ip_mroute.h>#include <netinet/ip_fw.h>#ifdef IPSEC#include <netinet6/ipsec.h>#endif /*IPSEC*/#ifdef DUMMYNET#include <netinet/ip_dummynet.h>#endifstruct	inpcbhead ripcb;struct	inpcbinfo ripcbinfo;/* * Nominal space allocated to a raw ip socket. */#define	RIPSNDQ		8192#define	RIPRCVQ		8192/* * Raw interface to IP protocol. *//* * Initialize raw connection block q. */voidrip_init(){	LIST_INIT(&ripcb);	ripcbinfo.listhead = &ripcb;	/*	 * XXX We don't use the hash list for raw IP, but it's easier	 * to allocate a one entry hash list than it is to check all	 * over the place for hashbase == NULL.	 */	ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);	ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask);	ripcbinfo.ipi_zone = zinit("ripcb", sizeof(struct inpcb),				   maxsockets, ZONE_INTERRUPT, 0);}static struct	sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };/* * Setup generic address and protocol structures * for raw_input routine, then pass them along with * mbuf chain. */voidrip_input(m, off)	struct mbuf *m;	int off;{	register struct ip *ip = mtod(m, struct ip *);	register struct inpcb *inp;	struct inpcb *last = 0;	struct mbuf *opts = 0;	int proto = ip->ip_p;	ripsrc.sin_addr = ip->ip_src;	LIST_FOREACH(inp, &ripcb, inp_list) {#ifdef INET6		if ((inp->inp_vflag & INP_IPV4) == 0)			continue;#endif		if (inp->inp_ip_p && inp->inp_ip_p != proto)			continue;		if (inp->inp_laddr.s_addr &&                  inp->inp_laddr.s_addr != ip->ip_dst.s_addr)			continue;		if (inp->inp_faddr.s_addr &&                  inp->inp_faddr.s_addr != ip->ip_src.s_addr)			continue;		if (last) {			struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);#ifdef IPSEC			/* check AH/ESP integrity. */			if (n && ipsec4_in_reject_so(n, last->inp_socket)) {				m_freem(n);				ipsecstat.in_polvio++;				/* do not inject data to pcb */			} else#endif /*IPSEC*/			if (n) {				if (last->inp_flags & INP_CONTROLOPTS ||				    last->inp_socket->so_options & SO_TIMESTAMP)				    ip_savecontrol(last, &opts, ip, n);				if (sbappendaddr(&last->inp_socket->so_rcv,				    (struct sockaddr *)&ripsrc, n,				    opts) == 0) {					/* should notify about lost packet */					m_freem(n);					if (opts)					    m_freem(opts);				} else					sorwakeup(last->inp_socket);				opts = 0;			}		}		last = inp;	}#ifdef IPSEC	/* check AH/ESP integrity. */	if (last && ipsec4_in_reject_so(m, last->inp_socket)) {		m_freem(m);		ipsecstat.in_polvio++;		ipstat.ips_delivered--;		/* do not inject data to pcb */	} else#endif /*IPSEC*/	if (last) {		if (last->inp_flags & INP_CONTROLOPTS ||		    last->inp_socket->so_options & SO_TIMESTAMP)			ip_savecontrol(last, &opts, ip, m);		if (sbappendaddr(&last->inp_socket->so_rcv,		    (struct sockaddr *)&ripsrc, m, opts) == 0) {			m_freem(m);			if (opts)			    m_freem(opts);		} else			sorwakeup(last->inp_socket);	} else {		m_freem(m);		ipstat.ips_noproto++;		ipstat.ips_delivered--;	}}/* * Generate IP header and pass packet to ip_output. * Tack on options user may have setup with control call. */intrip_output(m, so, dst)	struct mbuf *m;	struct socket *so;	u_long dst;{	register struct ip *ip;	register struct inpcb *inp = sotoinpcb(so);	int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;	/*	 * If the user handed us a complete IP packet, use it.	 * Otherwise, allocate an mbuf for a header and fill it in.	 */	if ((inp->inp_flags & INP_HDRINCL) == 0) {		if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {			m_freem(m);			return(EMSGSIZE);		}		M_PREPEND(m, sizeof(struct ip), M_WAIT);		ip = mtod(m, struct ip *);		ip->ip_tos = inp->inp_ip_tos;		ip->ip_off = 0;		ip->ip_p = inp->inp_ip_p;		ip->ip_len = m->m_pkthdr.len;		ip->ip_src = inp->inp_laddr;		ip->ip_dst.s_addr = dst;		ip->ip_ttl = inp->inp_ip_ttl;	} else {		if (m->m_pkthdr.len > IP_MAXPACKET) {			m_freem(m);			return(EMSGSIZE);		}		ip = mtod(m, struct ip *);		/* don't allow both user specified and setsockopt options,		   and don't allow packet length sizes that will crash */		if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))		     && inp->inp_options)		    || (ip->ip_len > m->m_pkthdr.len)		    || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {			m_freem(m);			return EINVAL;		}		if (ip->ip_id == 0)#ifdef RANDOM_IP_ID			ip->ip_id = ip_randomid();#else			ip->ip_id = htons(ip_id++);#endif		/* XXX prevent ip_output from overwriting header fields */		flags |= IP_RAWOUTPUT;		ipstat.ips_rawout++;	}#ifdef IPSEC	if (ipsec_setsocket(m, so) != 0) {		m_freem(m);		return ENOBUFS;	}#endif /*IPSEC*/	return (ip_output(m, inp->inp_options, &inp->inp_route, flags,			  inp->inp_moptions));}/* * Raw IP socket option processing. */intrip_ctloutput(so, sopt)	struct socket *so;	struct sockopt *sopt;{	struct	inpcb *inp = sotoinpcb(so);	int	error, optval;	if (sopt->sopt_level != IPPROTO_IP)		return (EINVAL);	error = 0;	switch (sopt->sopt_dir) {	case SOPT_GET:		switch (sopt->sopt_name) {		case IP_HDRINCL:			optval = inp->inp_flags & INP_HDRINCL;			error = sooptcopyout(sopt, &optval, sizeof optval);			break;		case IP_FW_ADD:		case IP_FW_GET:			if (ip_fw_ctl_ptr == 0)				error = ENOPROTOOPT;			else				error = ip_fw_ctl_ptr(sopt);			break;#ifdef DUMMYNET		case IP_DUMMYNET_GET:			if (ip_dn_ctl_ptr == NULL)				error = ENOPROTOOPT ;			else				error = ip_dn_ctl_ptr(sopt);			break ;#endif /* DUMMYNET */		case MRT_INIT:		case MRT_DONE:		case MRT_ADD_VIF:		case MRT_DEL_VIF:		case MRT_ADD_MFC:		case MRT_DEL_MFC:		case MRT_VERSION:		case MRT_ASSERT:			error = ip_mrouter_get(so, sopt);			break;		default:			error = ip_ctloutput(so, sopt);			break;		}		break;	case SOPT_SET:		switch (sopt->sopt_name) {		case IP_HDRINCL:			error = sooptcopyin(sopt, &optval, sizeof optval,					    sizeof optval);			if (error)				break;			if (optval)				inp->inp_flags |= INP_HDRINCL;			else				inp->inp_flags &= ~INP_HDRINCL;			break;		case IP_FW_ADD:		case IP_FW_DEL:

⌨️ 快捷键说明

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