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

📄 tcp_input.c

📁 完整的TCP/IP源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* tcp_input.c - TCP input routines *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995 *	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. * *	@(#)tcp_input.c	8.12 (Berkeley) 5/24/95 *//*modification history--------------------01f,09jan98,vin  added LAND attack fix.01e,26sep97,sgv  Removed check for PUSH flag in TCP_REASS macro01d,07jul97,vin  fixed additional bugs. 		 (timestamp echo fix Stevens VolII Sec 26.6 fig 26.20,                 connection timer bug Stevens VolII sec 28.6 fig 28.20,                 simultaneous bug fix Stevens VolII sec 28.8 fig 28.30,                 removed unnecessary code Stevens VolII sec 29.9 fig 29.22)01c,08mar97,vin  added changes to accomodate changes in pcb structure for		 hash look ups.01c,05feb97,rjc  changes for tos routing01b,22nov96,vin  added cluster support replaced m_get(..) with mBufClGet(..).01a,03mar96,vin  created from BSD4.4lite2. integrated some wrs changes from		 02q of tcp_input.c*/#include "vxWorks.h"#include "net/systm.h"#include "net/mbuf.h"#include "net/protosw.h"#include "sys/socket.h"#include "net/socketvar.h"#include "errno.h"#include "net/if.h"#include "net/route.h"#include "netinet/in.h"#include "netinet/in_pcb.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "netinet/ip_var.h"#include "netinet/tcp.h"#include "netinet/tcp_fsm.h"#include "netinet/tcp_seq.h"#include "netinet/tcp_timer.h"#include "netinet/tcp_var.h"#include "netinet/tcpip.h"#ifdef BSDDEBUG#include "netinet/tcp_debug.h"#endif	/* BSDDEBUG */extern u_long sb_max;IMPORT int tcp_keepinit;extern void _remque ();extern void _insque ();/* XXX LAND attack safe remove this after thorough investigation */UCHAR _landAttackSafe = 0;/* *  MIB-II support counts the number of TCP packets sent with the Reset Flag *  set. */long   tcpOutRsts;tcp_seq	tcp_iss;		/* tcp initial send seq # */unsigned tcp_alpha, tcp_beta;	/* retransmission smoothing constants */struct inpcbhead tcb;           /* head of queue of active tcpcb's */struct inpcbinfo tcbinfo;struct 	tcpstat tcpstat;	/* tcp statistics */int	tcprexmtthresh = 3;struct	tcpiphdr tcp_saveti;struct	inpcb *tcp_last_inpcb = NULL;u_long 	tcp_now;			/* for RFC 1323 timestamps */#define TCP_PAWS_IDLE	(24 * 24 * 60 * 60 * PR_SLOWHZ)/* for modulo comparisons of timestamps */#define TSTMP_LT(a,b)	((int)((a)-(b)) < 0)#define TSTMP_GEQ(a,b)	((int)((a)-(b)) >= 0)/* * 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. * Set DELACK for segments received in order, but ack immediately * when segments are out of order (so fast retransmit can work). */#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)->t_flags |= TF_DELACK; \		(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), (m)); \		tp->t_flags |= TF_ACKNOW; \	} \}#ifndef TUBA_INCLUDEinttcp_reass(tp, ti, m)	register struct tcpcb *tp;	register struct tcpiphdr *ti;	struct mbuf *m;{	register struct tcpiphdr *q;	struct socket *so = tp->t_inpcb->inp_socket;	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;				m_freem(m);				return (0);			}			m_adj(m, i);			ti->ti_len -= i;			ti->ti_seq += i;		}		q = (struct tcpiphdr *)(q->ti_next);	}	tcpstat.tcps_rcvoopack++;	tcpstat.tcps_rcvoobyte += ti->ti_len;	REASS_MBUF(ti) = m;		/* XXX */	/*	 * 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(REASS_MBUF(q), i);			break;		}		q = (struct tcpiphdr *)q->ti_next;		m = REASS_MBUF((struct tcpiphdr *)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 = REASS_MBUF(ti);		ti = (struct tcpiphdr *)ti->ti_next;		if (so->so_state & SS_CANTRCVMORE)			m_freem(m);		else			sbappend(&so->so_rcv, m);	} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);	sorwakeup(so);	return (flags);}/* * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */voidtcp_input(m, iphlen)	register struct mbuf *m;	int iphlen;{	register struct tcpiphdr *ti;	register struct inpcb *inp;	u_char *optp = NULL;	int optlen = 0;	int len, tlen, off;	register struct tcpcb *tp = 0;	register int tiflags;	struct socket *so = NULL;	int todrop, acked, ourfinisacked, needoutput = 0;	short ostate = 0;	struct in_addr laddr;	int dropsocket = 0;	int iss = 0;	u_long tiwin, ts_val, ts_ecr;	int ts_present = 0;	tcpstat.tcps_rcvtotal++;	/*	 * Get IP and TCP header together in first mbuf.	 * Note: IP leaves IP header in first mbuf.	 */	ti = mtod(m, struct tcpiphdr *);	if (iphlen > sizeof (struct ip))		ip_stripoptions(m, (struct mbuf *)0);	if (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;	ti->ti_next = ti->ti_prev = 0;	ti->ti_x1 = 0;	ti->ti_len = (u_short)tlen;	HTONS(ti->ti_len);	if ((ti->ti_sum = in_cksum(m, len))) {		tcpstat.tcps_rcvbadsum++;		goto drop;	}#endif /* TUBA_INCLUDE */	/*	 * Check that TCP offset makes sense,	 * pull out TCP options and adjust length.		XXX	 */	off = ti->ti_off << 2;	if (off < sizeof (struct tcphdr) || off > tlen) {		tcpstat.tcps_rcvbadoff++;		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 *);		}		optlen = off - sizeof (struct tcphdr);		optp = mtod(m, u_char *) + sizeof (struct tcpiphdr);		/* 		 * Do quick retrieval of timestamp options ("options		 * prediction?").  If timestamp is the only option and it's		 * formatted as recommended in RFC 1323 appendix A, we		 * quickly get the values now and not bother calling		 * tcp_dooptions(), etc.		 */		if ((optlen == TCPOLEN_TSTAMP_APPA ||		     (optlen > TCPOLEN_TSTAMP_APPA &&			optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) &&		     *(u_long *)optp == htonl(TCPOPT_TSTAMP_HDR) &&		     (ti->ti_flags & TH_SYN) == 0) {			ts_present = 1;			ts_val = ntohl(*(u_long *)(optp + 4));			ts_ecr = ntohl(*(u_long *)(optp + 8));			optp = NULL;	/* we've parsed the options */		}	}	tiflags = ti->ti_flags;	/*	 * Convert TCP protocol specific fields to host format.	 */	NTOHL(ti->ti_seq);	NTOHL(ti->ti_ack);	NTOHS(ti->ti_win);	NTOHS(ti->ti_urp);	/*	 * Locate pcb for segment.	 */findpcb:	inp = tcp_last_inpcb;        if ((inp != NULL) &&            (inp->inp_lport == ti->ti_dport) &&	    (inp->inp_fport == ti->ti_sport) &&	    (inp->inp_faddr.s_addr == ti->ti_src.s_addr) &&            (inp->inp_laddr.s_addr == ti->ti_dst.s_addr))            {            goto pcbMatchFound;            }        else            {            /*             * Search the hash table of pcbs.             */            inp = in_pcblookuphash (&tcbinfo, ti->ti_src, ti->ti_sport,                                    ti->ti_dst, ti->ti_dport, 1);            /*             * ...and if that fails, drop the packet.             */            if (inp == NULL)                {                ++tcpstat.tcps_pcbcachemiss;                /*                 * If the state is CLOSED (i.e., TCB does not exist) then                 * all data in the incoming segment is discarded.                 * If the TCB exists but is in CLOSED state, it is embryonic,                 * but should either do a listen or a connect soon.                 */                goto dropwithreset;                }            }        tcp_last_inpcb = inp;		/* update the cache */pcbMatchFound:	tp = intotcpcb(inp);	if (tp == 0)		goto dropwithreset;	if (tp->t_state == TCPS_CLOSED)		goto drop;		/* Unscale the window into a 32-bit value. */	if ((tiflags & TH_SYN) == 0)		tiwin = ti->ti_win << tp->snd_scale;	else		tiwin = ti->ti_win;	so = inp->inp_socket;	if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {		if (so->so_options & SO_DEBUG) {			ostate = tp->t_state;			tcp_saveti = *ti;		}		if (so->so_options & SO_ACCEPTCONN) {			if ((tiflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) {				/*				 * Note: dropwithreset makes sure we don't				 * send a reset in response to a RST.				 */				if (tiflags & TH_ACK) {					tcpstat.tcps_badsyn++;					goto dropwithreset;				}				goto drop;			}			so = sonewconn(so, 0);			if (so == 0)				goto drop;			/*			 * This is ugly, but ....			 *			 * Mark socket as temporary until we're			 * committed to keeping it.  The code at			 * ``drop'' and ``dropwithreset'' check the			 * flag dropsocket to see if the temporary			 * socket created here should be discarded.			 * We mark the socket as discardable until			 * we're committed to it below in TCPS_LISTEN.			 */			dropsocket++;			inp = (struct inpcb *)so->so_pcb;			inp->inp_laddr = ti->ti_dst;			inp->inp_lport = ti->ti_dport;

⌨️ 快捷键说明

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