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

📄 tcp_input.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifndef lintstatic  char    *sccsid = "@(#)tcp_input.c	4.9	(ULTRIX)	3/8/91";#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				* * *      03-Mar-91 - Michael G. Mc Menemy *      Fix oob code to handle both XTI and Berkeley style oob data. * *      03-Mar-91 - Michael G. Mc Menemy *      Fix rexmt when all outstanding packets have been acked. *  *      03-Mar-91 - Michael G. Mc Menemy *      Fix unaligned access panic in oob code. *  *	16-Jan-91 - U. Sinkewicz *	Fix to stack overwrite panic in LOOPBACK mode from tcp_output() *	and tcp_input() thrashing. * *	09-oct-90 - jaw *	merge in mm fix for deadlock caused by bug in tcp_input. * *	17-Jul-90  - jsd *	remove so->ref panic since it's optimized out for single-cpu * *	16-July-90 - lp *	Leave trailers for machines that use them (IFF_NOTRAILERS). * *	18-June-90 -  lp *	Remove trailers in max seg calculation for FDDI. Note that * 	ethernet will now no longer do trailers encapsulation. * *	14-May-90 - R. Bhanukitsiri *	Fix "m_free has bad m_cltype" panic by not freeing up old *	out-of-band data when a new out-of-band data arrives. * *	26-Jan-90 - gmm *	Make socket pointer in tcp_input() volatile * *	3-Jan-90  - U. Sinkewicz *	Performance enhancements to uniprocessor kernel. * *	2-Dec-89  - jsd *	Panic during so->ref check for single-cpu so we don't hang * *	9-Nov-89  - Ursula Sinkewicz *	Fix to the case when we have a SYN in the window and are *	responding with an RST. * *	30-May-89 - Ursula Sinkewicz *	Added so->ref field which is used in conjunction with SO_LOCK *	to fix smp hole caused by unlocking the socket and locking it *	again.  Problem is that the socket may have changed or been *	freed while unlocked.  The unlocking is necessary to accommodate *	the lock heirarchy and sleeps. * *      05-05-89 - Michael G. Mc Menemy *              Add XTI support. * *	27-2-89 - Ursula Sinkewicz *		Lowered ipl on lk_rtentry, lk_ifnet, lk_in_ifaddr; *		replace tcpstatictics with a macro, as per lp changes  *		from 3/16/89. * *	3-3-89 - Ursula Sinkewicz *		Added support for new directory layout to smp file. * *	2-23-89 - Ursula Sinkewicz *		Spool dangling reference info to error logger.  Added * 		change to eleminate willbefreed flag which coincides *		with uipc_socket.c changes. * *	12-5-88	- Ursula Sinkewicz *		SMP - release memory for socket/pcb on close/shutdown/ *		abort.	 * *	15-Jan-88	lp *		Merge of final 43BSD changes. *									* *	6/25/87 - Ursula Sinkewicz					* *		Major cleanup of freeondrop flag.			* * *	04/27/87 - Larry Cohen *		Send response to everything except a reset.  Code  *		effected is right after "dropafterack:" *									 *	01/28/87 - Larry Cohen *		Look for resets before checking to see if input is *		within acceptable range.  This is because a response *		to KEEPALIVE messages is not within an acceptable range. *		If the response to our KEEPALIVE message is a reset *		(which is the case if the remote side has crashed and  *		come up again soon) we would otherwise drop the RST  *		message and leave local processes hanging. * *	01/28/87 - Larry Cohen *		update max_sndwnd * 	12/16/86 - lp 							* *		Start timer on FIN_WAIT_2 state if CANTRECVMORE 	* *	Larry Cohen  -	09/16/85					* * 		Add 43bsd alpha tape changes for subnet routing		* *									* ************************************************************************//* * 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. * *	tcp_input.c	7.13 (Berkeley) 11/13/87 */#include "../h/param.h"#include "../h/systm.h"#include "../h/smp_lock.h"#include "../h/mbuf.h"#include "../h/protosw.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../h/errno.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/ip.h"#include "../net/netinet/ip_var.h"#include "../net/netinet/tcp.h"#include "../net/netinet/tcp_fsm.h"#include "../net/netinet/tcp_seq.h"#include "../net/netinet/tcp_timer.h"#include "../net/netinet/tcp_var.h"#include "../net/netinet/tcpip.h"#include "../net/netinet/tcp_debug.h"#ifdef XTIextern	char *tcpstates[];extern  int xti_debug; /* general debug */#define PRINTXTID(level, msg)   \  /*                            \   * level:                     \   * 0x01 = generate events;    \   * 0x04 = acceptchk/abort support;  \   * 0x08 = peek events;        \   * 0x10 = tpdu T_MORE support; \   * 0x20 = oob mark;           \   * 0x40 = option neg.         \   * 0x80 = protocol;           \   */                           \  if (xti_debug & (level))      \     cprintf((msg))#else#define PRINTXTID(level, msg)#endif XTIint	tcpprintfs = 0;int	tcpcksum = 1;int	tcprexmtthresh = 3;struct	tcpiphdr tcp_saveti;extern	tcpnodelack;struct	tcpcb *tcp_newtcpcb();/* * Insert segment ti into reassembly queue of tcp with * control block tp.  Return TH_FIN if reassembly now includes * a segment with FIN.  The macro form does the common case inline * (segment is the next to be received on an established connection, * and the queue is empty), avoiding linkage into and removal * from the queue and repetition of various conversions. */#ifdef XTI#define	TCP_REASS(tp, ti, m, so, flags) { \	if ((ti)->ti_seq == (tp)->rcv_nxt && \	    (tp)->seg_next == (struct tcpiphdr *)(tp) && \	    (tp)->t_state == TCPS_ESTABLISHED) { \		(tp)->rcv_nxt += (ti)->ti_len; \		flags = (ti)->ti_flags & TH_FIN; \		TCPSTAT(tcps_rcvpack++);\		TCPSTAT(tcps_rcvbyte += (ti)->ti_len);\/*#ifdef XTI */\	          if ((so)->so_xticb.xti_epvalid) { \                    if ((so)->so_xticb.xti_evtenabled) { \                      if (mbuf_any_len((m)) > 0) { \		      (so)->so_xticb.xti_evtarray[XTI_EVT_T_DATA]++; \		      PRINTXTID(1, ("T_DATA (#1) 1 event generated\n")); \		      }}} \/*#endif XTI */\		sbappend(&(so)->so_rcv, (m)); \		sorwakeup(so); \	} else \		(flags) = tcp_reass((tp), (ti)); \}#else#define	TCP_REASS(tp, ti, m, so, flags) { \	if ((ti)->ti_seq == (tp)->rcv_nxt && \	    (tp)->seg_next == (struct tcpiphdr *)(tp) && \	    (tp)->t_state == TCPS_ESTABLISHED) { \		(tp)->rcv_nxt += (ti)->ti_len; \		flags = (ti)->ti_flags & TH_FIN; \		TCPSTAT(tcps_rcvpack++);\		TCPSTAT(tcps_rcvbyte += (ti)->ti_len);\		sbappend(&(so)->so_rcv, (m)); \		sorwakeup(so); \	} else \		(flags) = tcp_reass((tp), (ti)); \}#endif XTItcp_reass(tp, ti)	register struct tcpcb *tp;	register struct tcpiphdr *ti;{	register struct tcpiphdr *q;	struct socket *so = tp->t_inpcb->inp_socket;	struct mbuf *m;	int flags;	/*	 * Call with ti==0 after become established to	 * force pre-ESTABLISHED data up to user socket.	 */	if (ti == 0)		goto present;	/*	 * Find a segment which begins after this one does.	 */	for (q = tp->seg_next; q != (struct tcpiphdr *)tp;	    q = (struct tcpiphdr *)q->ti_next)		if (SEQ_GT(q->ti_seq, ti->ti_seq))			break;	/*	 * If there is a preceding segment, it may provide some of	 * our data already.  If so, drop the data from the incoming	 * segment.  If it provides all of our data, drop us.	 */	if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {		register int i;		q = (struct tcpiphdr *)q->ti_prev;		/* conversion to int (in i) handles seq wraparound */		i = q->ti_seq + q->ti_len - ti->ti_seq;		if (i > 0) {			if (i >= ti->ti_len) {				TCPSTAT(tcps_rcvduppack++);				TCPSTAT(tcps_rcvdupbyte += ti->ti_len);				goto drop;			}			m_adj(dtom(ti), i);			ti->ti_len -= i;			ti->ti_seq += i;		}		q = (struct tcpiphdr *)(q->ti_next);	}	TCPSTAT(tcps_rcvoopack++);	TCPSTAT(tcps_rcvoobyte += ti->ti_len);	/*	 * While we overlap succeeding segments trim them or,	 * if they are completely covered, dequeue them.	 */	while (q != (struct tcpiphdr *)tp) {		register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;		if (i <= 0)			break;		if (i < q->ti_len) {			q->ti_seq += i;			q->ti_len -= i;			m_adj(dtom(q), i);			break;		}		q = (struct tcpiphdr *)q->ti_next;		m = dtom(q->ti_prev);		remque(q->ti_prev);		m_freem(m);	}	/*	 * Stick new segment in its place.	 */	insque(ti, q->ti_prev);present:	/*	 * Present data to user, advancing rcv_nxt through	 * completed sequence space.	 */	if (TCPS_HAVERCVDSYN(tp->t_state) == 0)		return (0);	ti = tp->seg_next;	if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)		return (0);	if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)		return (0);	do {		tp->rcv_nxt += ti->ti_len;		flags = ti->ti_flags & TH_FIN;		remque(ti);		m = dtom(ti);		ti = (struct tcpiphdr *)ti->ti_next;		if (so->so_state & SS_CANTRCVMORE){			m_freem(m);		}#ifdef XTI		else {		  sbappend(&so->so_rcv, m);		  if (so->so_xticb.xti_epvalid)  		    if (so->so_xticb.xti_evtenabled) {		      if (ti->ti_len) {			so->so_xticb.xti_evtarray[XTI_EVT_T_DATA] ++;			PRINTXTID(1, ("T_DATA (#2) 1 event generated\n"));		      }		    }		}#else		else			sbappend(&so->so_rcv, m);#endif XTI	} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);	sorwakeup(so);	return (flags);drop:	m_freem(dtom(ti));return (0);}/* * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. *//* * SMP: enter without socket lock set.  Come into the routine only * through the interrupt handler and in LOOPBACK mode. */tcp_input(m0)	struct mbuf *m0;{	register struct tcpiphdr *ti;	struct inpcb *inp;	struct inpcb *inp_temp;	register struct mbuf *m;	struct mbuf *om = 0;	int len, tlen, off;	register struct tcpcb *tp = 0;	register int tiflags;	int todrop, acked, ourfinisacked, needoutput = 0;	volatile struct socket *so = NULL;  /* SMP */	short ostate;	struct in_addr laddr;	int dropsocket = 0;	int iss = 0;	int freeondrop = 1; 		/* SMP */	struct socket *so_tmp; 		/* SMP */	int status = 0;			/* SMP */	struct socket *so_addr = NULL;	/* SMP */	int owner = 0;			/* SMP */	int error = 0;	int waitcnt; /*SMP*/#ifdef XTI	short xti_precedence;	struct secoptions xti_secopt;#endif XTI	TCPSTAT(tcps_rcvtotal++);	/*	 * Get IP and TCP header together in first mbuf.	 * Note: IP leaves IP header in first mbuf.	 */	m = m0;	ti = mtod(m, struct tcpiphdr *);#ifdef XTI	/* get precedence from IP header */	xti_precedence = (((struct ip *)ti)->ip_tos & (0x07));	/* get IP Security options */	if (xti_ip_dooptions(((struct ip *) ti), &xti_secopt)) {	  xti_secopt.security = T_UNUSED;	  xti_secopt.compartment = T_UNUSED;	  xti_secopt.handling = T_UNUSED;	  xti_secopt.tcc = T_UNUSED;	}#endif XTI	if (((struct ip *)ti)->ip_hl > (sizeof (struct ip) >> 2))		ip_stripoptions((struct ip *)ti, (struct mbuf *)0);	if (m->m_off > MMAXOFF || m->m_len < sizeof (struct tcpiphdr)) {		if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) {			TCPSTAT(tcps_rcvshort++);			return;		}		ti = mtod(m, struct tcpiphdr *);	}	/*	 * Checksum extended TCP header and data.	 */	tlen = ((struct ip *)ti)->ip_len;	len = sizeof (struct ip) + tlen;#ifdef TCPLOOPBACK	if (tcpcksum && (ti->ti_src.s_addr != ti->ti_dst.s_addr)) {#else	if (tcpcksum) {#endif TCPLOOPBACK		ti->ti_next = ti->ti_prev = 0;		ti->ti_x1 = 0;		ti->ti_len = (u_short)tlen;		ti->ti_len = htons((u_short)ti->ti_len);		if (ti->ti_sum = in_cksum(m, len)) {			if (tcpprintfs)				printf("tcp sum: src %x\n", ti->ti_src);			TCPSTAT(tcps_rcvbadsum++);			freeondrop = 0;			goto drop;		}	}	/*	 * Check that TCP offset makes sense,	 * pull out TCP options and adjust length.	 */	off = ti->ti_off << 2;	if (off < sizeof (struct tcphdr) || off > tlen) {		if (tcpprintfs)			printf("tcp off: src %x off %d\n", ti->ti_src, off);		TCPSTAT(tcps_rcvbadoff++);		freeondrop = 0;		goto drop;	}	tlen -= off;	ti->ti_len = tlen;	if (off > sizeof (struct tcphdr)) {		if (m->m_len < sizeof(struct ip) + off) {			if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) {				TCPSTAT(tcps_rcvshort++);				return;			}			ti = mtod(m, struct tcpiphdr *);		}		om = m_get(M_DONTWAIT, MT_DATA);		if (om == 0) {			freeondrop = 0;			goto drop;		}		om->m_len = off - sizeof (struct tcphdr);		{ caddr_t op = mtod(m, caddr_t) + sizeof (struct tcpiphdr);		  bcopy(op, mtod(om, caddr_t), (unsigned)om->m_len);		  m->m_len -= om->m_len;		  bcopy(op+om->m_len, op,		   (unsigned)(m->m_len-sizeof (struct tcpiphdr)));		}	}	tiflags = ti->ti_flags;	/*	 * Drop TCP and IP headers; TCP options were dropped above.	 */	m->m_off += sizeof(struct tcpiphdr);	m->m_len -= sizeof(struct tcpiphdr);	/*	 * Convert TCP protocol specific fields to host format.	 */	ti->ti_seq = ntohl(ti->ti_seq);	ti->ti_ack = ntohl(ti->ti_ack);	ti->ti_win = ntohs(ti->ti_win);	ti->ti_urp = ntohs(ti->ti_urp);	/*	 * Locate pcb for segment.	 */	/* 4.13.89.us  You need to start with an owner check on	 * the tcb because there is an obscure path here from	 * the slow timers which set lk_tcb.	 */findpcb:	if ( smp && !(smp_owner(&lk_tcb)) ){		owner = 1;		smp_lock(&lk_tcb, LK_RETRY);	}	else 		owner = 0;	inp = in_pcblookup		(&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport,		INPLOOKUP_WILDCARD);loop1:	if (inp == 0) {		freeondrop = 0;		tp = 0;		so = NULL;	/* This is for tcp_respond() locking.  */		if ( owner){			smp_unlock(&lk_tcb);			owner = 0;		}		goto dropwithreset;	}	so = inp->inp_socket;	if (smp){	  /* try only once to avoid DEADLOCK.  we have lk_tcb and need to 	     get it released as soon as possible. */	  if (smp_lock(&so->lk_socket, LK_ONCE) || 	      smp_lock(&so->lk_socket, LK_ONCE)) {	  	if (so->ref > 0){	/* if some one owns it then backoff */			smp_unlock(&so->lk_socket);			smp_unlock(&lk_tcb);			waitcnt = 1000000; /* need some limit to wait */			while (so->ref > 0 && waitcnt--) 				;			if (owner) 				owner=0;			else 				smp_lock(&lk_tcb,LK_RETRY);			goto findpcb;		

⌨️ 快捷键说明

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