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

📄 ip_input.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifndef lintstatic char *sccsid = "@(#)ip_input.c	4.4	(ULTRIX)	9/11/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1985 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//************************************************************************ *			Modification History				* * *	31-Jul-90	jsd *		fixes for killer packets with IP options LSR and SRR * *	24-Jul-90	jaw *		submitted bug fix for locking problem in ipintr.... * *	16-July-90	U. Sinkewicz *		Fix to locking around ip_reass(). * *	7-Jul-90	lp *		FDDI performance changes. * *	14-11-89	Ursula Sinkewicz *		Removed lk_ifnet and lk_in_ifaddr to coincide with *		slip changes. * *	17-Oct-89	Uttam Shikarpur					* *		Added counter to track the number of bad options for    * *		network management. (ips_badoptions)		   	* *									* *	27-Mar-89	Ursula Sinkewicz *		Lowered ipl in lk_rtentry, lk_ifnet, lk_in_ifaddr, exchanged *		ip statistics locking for a macro, as per lp changes  *		made 3/16/89. * *	3-Mar-89	Ursula Sinkewicz *		Added support for new directory layout; added pmax *		support. * *	13-Feb-89	Ursula Sinkewicz *		SMP: Added lk_in_ifaddr and lk_ifnet. *	 *	15-Jan-88	lp *		Merge of final 43BSD changes. Use new memory allocation *	scheme for mbufs. * *	Larry Cohen  -	09/16/85					* * 		Add 43bsd alpha tape changes for subnet routing		* *									* *	Larry Cohen  -  01/17/86					* *		- will now accept broadcast of ones or zeros   		* *									* *	Marc Teitelbaum and Fred Templin - 08/21/86			* *		Added 4.3bsd beta tape enhancements. "ipintr()" now	* *		handles subet broadcasts and packet forwarding properly.* *		(Packets are only forwarded by hosts configured with	* *		"GATEWAY" option).					* ************************************************************************//* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * *	@(#)ip_input.c	7.7 (Berkeley) 10/31/87 */#include "../h/param.h"#include "../h/systm.h"#include "../h/mbuf.h"#include "../h/domain.h"#include "../h/protosw.h"#include "../h/socket.h"#include "../h/errno.h"#include "../h/time.h"#include "../h/kernel.h"#include "../h/smp_lock.h"#include "../net/net/if.h"#include "../net/net/route.h"#include "../net/netinet/in.h"#include "../net/netinet/in_pcb.h"#include "../net/netinet/in_systm.h"#include "../net/netinet/in_var.h"#include "../net/netinet/ip.h"#include "../net/netinet/ip_var.h"#include "../net/netinet/ip_icmp.h"#include "../net/netinet/tcp.h"u_char	ip_protox[IPPROTO_MAX];int	ipqmaxlen = IFQ_MAXLEN;struct	in_ifaddr *in_ifaddr;			/* first inet address */struct	lock_t	lk_ipstat;	/* SMP: ipstat lock, see ip_var.h */struct	lock_t  lk_ipq;		/* SMP: ip reassembly queue lock *//* * We need to save the IP options in case a protocol wants to respond * to an incoming packet over the same route if the packet got here * using IP source routing.  This allows connection establishment and * maintenance when the remote end is on a network that is not known * to us. */int	ip_nhops = 0;static	struct ip_srcrt {	char	nop;				/* one NOP to align */	char	srcopt[IPOPT_OFFSET + 1];	/* OPTVAL, OLEN and OFFSET */	struct	in_addr route[MAX_IPOPTLEN];} ip_srcrt;extern struct lock_t lk_arptab;/* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */ip_init(){	register struct protosw *pr;	register int i;	pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);	if (pr == 0)		panic("ip_init");	for (i = 0; i < IPPROTO_MAX; i++)		ip_protox[i] = pr - inetsw;	for (pr = inetdomain.dom_protosw;	    pr < inetdomain.dom_protoswNPROTOSW; pr++)		if (pr->pr_domain->dom_family == PF_INET &&		    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)			ip_protox[pr->pr_protocol] = pr - inetsw;	/* SMP: Initailize locks here - ipstat, ipq, and ipintrq.  4.22.87.us */	lockinit(&lk_ipq, &lock_ipq_d);	lockinit(&lk_ipstat, &lock_ipstat_d);	ipq.next = ipq.prev = &ipq;	ip_id = time.tv_sec & 0xffff;	ipintrq.ifq_maxlen = ipqmaxlen;	lockinit(&ipintrq.lk_ifqueue, &lock_ifqueue_d);	lockinit(&lk_arptab, &lock_arptab_d);}u_char	ipcksum = 1;struct	ip *ip_reass();struct	sockaddr_in ipaddr = { AF_INET };struct 	route ipforward_rt;/* * Ip input routine.  Checksum and byte swap header.  If fragmented * try to reassamble.  If complete and fragment queue exists, discard. * Process options.  Pass to next level. */ipintr(){	register struct ip *ip;	register struct mbuf *m;	struct mbuf *m0;	register int i;	register struct ipq *fp;	register struct in_ifaddr *ia;	struct ifnet *ifp;	int hlen, s;        /*          * This is to keep these long aligned         */        struct in_addr dst;        struct in_addr src;next:	/*	 * Get next datagram off input queue and get IP header	 * in first mbuf.	 */	s = splimp();	/* SMP: Lock element taken off ipintrq along with	 * next/prev pointers in the queue.  4.22.87.us	 */	smp_lock(&ipintrq.lk_ifqueue, LK_RETRY);	IF_DEQUEUEIF(&ipintrq, m, ifp);	smp_unlock(&ipintrq.lk_ifqueue);	splx(s);	if (m == 0)		return;	/*	 * If no IP addresses have been set yet but the interfaces	 * are receiving, can't do anything with incoming packets yet. 	 */	if (in_ifaddr == NULL){		goto bad;	}	IPSTAT(ips_total++);	if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct ip)) &&	    (m = m_pullup(m, sizeof (struct ip))) == 0) {		IPSTAT(ips_toosmall++);		goto next;	}	ip = mtod(m, struct ip *);	hlen = ip->ip_hl << 2;	if (hlen < sizeof(struct ip)) {	/* minimum header length */		IPSTAT(ips_badhlen++);		goto bad;	}	if (hlen > m->m_len) {		if ((m = m_pullup(m, hlen)) == 0) {			IPSTAT(ips_badhlen++);			goto next;		}		ip = mtod(m, struct ip *);	}	if (ipcksum)		if (ip->ip_sum = in_cksum(m, hlen)) {			IPSTAT(ips_badsum++);			goto bad;		}	/*	 * Convert fields to host representation.	 */	ip->ip_len = ntohs((u_short)ip->ip_len);	if (ip->ip_len < hlen) {		IPSTAT(ips_badlen++);		goto bad;	}	ip->ip_id = ntohs(ip->ip_id);	ip->ip_off = ntohs((u_short)ip->ip_off);	/*	 * Check that the amount of data in the buffers	 * is as at least much as the IP header would have us expect.	 * Trim mbufs if longer than we expect.	 * Drop packet if shorter than we expect.	 */	i = -(u_short)ip->ip_len;	m0 = m;	for (;;) {		i += m->m_len;		if (m->m_next == 0)			break;		m = m->m_next;	}	if (i != 0) {		if (i < 0) {			IPSTAT(ips_tooshort++);			m = m0;			goto bad;		}		if (i <= m->m_len)			m->m_len -= i;		else			m_adj(m0, -i);	}	m = m0;	/*	 * Process options and, if not destined for us,	 * ship it on.  ip_dooptions returns 1 when an	 * error was detected (causing an icmp message	 * to be sent and the original packet to be freed).	 */	ip_nhops = 0;		/* for source routed packets */	if (hlen > sizeof (struct ip) && ip_dooptions(ip, ifp))		goto next;	/*	 * Check our list of addresses, to see if the packet is for us.	 */        bcopy(&ip->ip_dst, &dst, sizeof(struct in_addr));	for (ia = in_ifaddr; ia; ia = ia->ia_next) {#define	satosin(sa)	((struct sockaddr_in *)(sa))		if (IA_SIN(ia)->sin_addr.s_addr == dst.s_addr) {			goto ours;		}		if (#ifdef DIRECTED_BROADCAST			ia->ia_ifp == ifp &&#endif DIRECTED_BROADCAST			(ia->ia_ifp->if_flags & IFF_BROADCAST)) {		    u_long t;		    if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==			dst.s_addr) {			    goto ours;		    }		    if (dst.s_addr == ia->ia_netbroadcast.s_addr) {			    goto ours;		    }		    /*		     * Look for all-0's host part (old broadcast addr),		     * either for subnet or net.		     */		    t = ntohl(dst.s_addr);		    if (t == ia->ia_subnet) {			    goto ours;		    }		    if (t == ia->ia_net) {			    goto ours;		    }		}	}	if (dst.s_addr == (u_long)INADDR_BROADCAST)		goto ours;	if (dst.s_addr == INADDR_ANY)		goto ours;	/*	 * Not for us; forward if possible and desirable.	 */	ip_forwardscreen(ip, ifp);	goto next;ours:	/*	 * Look for queue of fragments	 * of this datagram.	 */	smp_lock(&lk_ipq, LK_RETRY);	if(ipq.next != &ipq) {        	bcopy(&ip->ip_src, &src, sizeof(struct in_addr));		for (fp = ipq.next; fp != &ipq; fp = fp->next)			if (ip->ip_id == fp->ipq_id &&		    	src.s_addr == fp->ipq_src.s_addr &&		    	dst.s_addr == fp->ipq_dst.s_addr &&		    	ip->ip_p == fp->ipq_p) {				goto found;		    	}	}	fp = 0;found:	/*	 * Adjust ip_len to not reflect header,	 * set ip_mff if more fragments are expected,	 * convert offset of this to bytes.	 */	ip->ip_len -= hlen;	((struct ipasfrag *)ip)->ipf_mff = 0;	if (ip->ip_off & IP_MF)		((struct ipasfrag *)ip)->ipf_mff = 1;	ip->ip_off <<= 3;	/*	 * If datagram marked as having more fragments	 * or if this is not the first fragment,	 * attempt reassembly; if it succeeds, proceed.  	 */	if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) {		IPSTAT(ips_fragments++);#ifdef mips                /*                 * if the ip header is not aligned properly, copy the                 * mbuf to avoid lots of bcopy's later when reassembling                 * fragments due to placement of fragment pointers within                 * ip header.                   */                if (((u_int)ip & 0x3) != 0) {                        register struct mbuf *mnew;                        mnew = m_copy(m, 0, m->m_len);                        mnew->m_next = m_free(m);                        m = mnew;                        ip = mtod(m, struct ip *);                }#endif mips		ip = ip_reass((struct ipasfrag *)ip, fp);        	smp_unlock(&lk_ipq);		if (ip == 0)			goto next;		m = dtom(ip);	} else{		if (fp) {			ip_freef(fp);		}        	smp_unlock(&lk_ipq);	}	/*	 * Switch out to protocol's input routine.	 */

⌨️ 快捷键说明

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