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

📄 tcp_input.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
		}	  		  } else {	  	/* didn't get lock on socket.... still back off if referenced*/		smp_unlock(&lk_tcb);		waitcnt = 1000000;		while (so->ref > 0 && waitcnt--) ;		if (owner) 			owner=0;		else 			smp_lock(&lk_tcb,LK_RETRY);		goto findpcb;	  }	  inp_temp = in_pcblookup	    (&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport,	    INPLOOKUP_WILDCARD);	  if (inp != inp_temp) {		freeondrop = 0;		smp_unlock(&so->lk_socket);		/* We are unlocked so don't keep a messy socket pointer		 * around because it could confuse tcp_respond.  */		so = NULL;		if (owner){			smp_unlock(&lk_tcb);			owner = 0;		}		goto dropwithreset;	  }	  if ( owner){		smp_unlock(&lk_tcb);	  }	}	/*	 * 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.	 */	tp = intotcpcb(inp);	if (tp == 0)		goto dropwithreset;#ifdef XTI	PRINTXTID(128, ("tcp_input: tp =%x,tp->t_state = %s\n",tp,tcpstates[tp->t_state]));	if (ti->ti_flags) 	  PRINTXTID(128, ("<"));	if (ti->ti_flags & TH_FIN) 	  PRINTXTID(128, ("FIN "));	if (ti->ti_flags & TH_SYN) 	  PRINTXTID(128, ("SYN "));	if (ti->ti_flags & TH_RST) 	  PRINTXTID(128, ("RST "));	if (ti->ti_flags & TH_PUSH) 	  PRINTXTID(128, ("PSH "));	if (ti->ti_flags & TH_ACK) 	  PRINTXTID(128, ("ACK "));	if (ti->ti_flags & TH_URG) 	  PRINTXTID(128, ("URG "));	if (ti->ti_flags) 	  PRINTXTID(128, (">\n"));#endif XTI	if (tp->t_state == TCPS_CLOSED)		goto drop; 	if (so->so_options & SO_DEBUG) {		ostate = tp->t_state;		tcp_saveti = *ti;	}	/* 	 * Unlock the old and lock the new...	 */	if (so->so_options & SO_ACCEPTCONN) {		so_tmp = sonewconn(so);		if (so_tmp == 0) {			freeondrop = 0;			goto drop;		}		SO_LOCK(so_tmp);		smp_unlock(&so->lk_socket);		so = so_tmp;		/*		 * 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;		inp->inp_options = ip_srcroute();		tp = intotcpcb(inp);		tp->t_state = TCPS_LISTEN;	}	/*	 * Segment received on connection.	 * Reset idle time and keep-alive timer.	 */	tp->t_idle = 0;	tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;	/*	 * Process options if not in LISTEN state,	 * else do it below (after getting remote address).	 */	if (om && tp->t_state != TCPS_LISTEN) {		tcp_dooptions(tp, om, ti);		om = 0;	}	/*	 * Calculate amount of space in receive window,	 * and then do TCP input processing.	 * Receive window is amount of space in rcv queue,	 * but not less than advertised window.	 */	{ int win;		win = sbspace(&so->so_rcv);	if (win < 0)		win = 0;	tp->rcv_wnd = MAX(win, (int)(tp->rcv_adv - tp->rcv_nxt));	}	switch (tp->t_state) {	/*	 * If the state is LISTEN then ignore segment if it contains an RST.	 * If the segment contains an ACK then it is bad and send a RST.	 * If it does not contain a SYN then it is not interesting; drop it.	 * Don't bother responding if the destination was a broadcast.	 * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial	 * tp->iss, and send a segment:	 *     <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>	 * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.	 * Fill in remote peer address fields if not previously specified.	 * Enter SYN_RECEIVED state, and process any other fields of this	 * segment in this state.	 */	case TCPS_LISTEN: {		struct mbuf *am;		register struct sockaddr_in *sin;		if (tiflags & TH_RST){			goto drop;		}		if (tiflags & TH_ACK){			goto dropwithreset;		}		if ((tiflags & TH_SYN) == 0){			goto drop;}		if (in_broadcast(ti->ti_dst)){			goto drop;		}		am = m_get(M_DONTWAIT, MT_SONAME);		if (am == NULL){			goto drop;		}		am->m_len = sizeof (struct sockaddr_in);		sin = mtod(am, struct sockaddr_in *);		sin->sin_family = AF_INET;		sin->sin_addr = ti->ti_src;		sin->sin_port = ti->ti_sport;		laddr = inp->inp_laddr;		if (inp->inp_laddr.s_addr == INADDR_ANY)			inp->inp_laddr = ti->ti_dst;		/* Call in_pcbconnect() with smp lock set */		/* 4.13.89.us Following if/else is brought		 * to you courtesy of the protocol timeout		 * timers.		 */		if (!owner){			if (in_pcbconnect(inp, am)) {				inp->inp_laddr = laddr;				(void) m_free(am);				goto drop;			}		}else{			so->ref = 9;		  	smp_unlock(&so->lk_socket);		  	smp_lock(&lk_tcb, LK_RETRY);			smp_lock(&so->lk_socket, LK_RETRY);			so->ref = 0;			if (in_pcbconnect(inp, am)) {				smp_unlock(&lk_tcb);				inp->inp_laddr = laddr;				(void) m_free(am);				goto drop;			}			smp_unlock(&lk_tcb);		}		(void) m_free(am);		tp->t_template = tcp_template(tp);		if (tp->t_template == 0) {			tp = tcp_drop(tp, ENOBUFS);			dropsocket = 0;			if ( smp && smp_owner(&so->lk_socket) == 0){				dropsocket = 0;				goto drop;			}			goto drop;		}		if (om) {			tcp_dooptions(tp, om, ti);			om = 0;		}		smp_lock(&lk_tcpiss, LK_RETRY);		if (iss)			tp->iss = iss;		else			tp->iss = tcp_iss;		tcp_iss += TCP_ISSINCR/2;		smp_unlock(&lk_tcpiss);		tp->irs = ti->ti_seq;		tcp_sendseqinit(tp);		tcp_rcvseqinit(tp);		tp->t_flags |= TF_ACKNOW;#ifdef XTI		if (tp->t_acceptmode) {		  tp->t_flags &= ~(TF_ACKNOW);		  soisconnected(so);		}		/* bump T_LISTEN count in socket struct field		 * so->so_xticb.xti_evtarray when so->so_xticb.xti_epvalid and		 * *->evtenabled are on.		 */				if (so->so_xticb.xti_epvalid) { /* valid xti endpoint */		  		  /* load tcp options to be read by *_CONOPT */		  tp->xti_inbound_qos.precedence = xti_precedence;		  tp->xti_inbound_qos.timeout = tp->xti_neg_qos.timeout;		  tp->xti_inbound_qos.max_seg_size = tp->t_maxseg;		  tp->xti_inbound_qos.secopt = xti_secopt;		  if (so->so_xticb.xti_evtenabled) {		    so->so_xticb.xti_evtarray[XTI_EVT_T_LISTEN]++;		    PRINTXTID(1, ("T_LISTEN (#1)    \n"));		  }		}#endif XTI		tp->t_state = TCPS_SYN_RECEIVED;		tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;		dropsocket = 0;		/* committed to socket */		TCPSTAT(tcps_accepts++);		goto trimthenstep6;		}	/*	 * If the state is SYN_SENT:	 *	if seg contains an ACK, but not for our SYN, drop the input.	 *	if seg contains a RST, then drop the connection.	 *	if seg does not contain SYN, then drop it.	 * Otherwise this is an acceptable SYN segment	 *	initialize tp->rcv_nxt and tp->irs	 *	if seg contains ack then advance tp->snd_una	 *	if SYN has been acked change to ESTABLISHED else SYN_RCVD state	 *	arrange for segment to be acked (eventually)	 *	continue processing rest of data/controls, beginning with URG	 */	case TCPS_SYN_SENT:		if ((tiflags & TH_ACK) &&		    (SEQ_LEQ(ti->ti_ack, tp->iss) ||		     SEQ_GT(ti->ti_ack, tp->snd_max))) {			goto dropwithreset;		}		if (tiflags & TH_RST) {			if (tiflags & TH_ACK) {				freeondrop = 0;#ifdef XTI	      /* set T_DISCONNECT bit on in socket struct field	       * so->so_xticb.xti_evtarray when so->so_xticb.xti_epvalid and	       * *->evtenabled are on.	       */					      if (so->so_xticb.xti_epvalid) { /* valid xti endpoint */		if (so->so_xticb.xti_evtenabled) {		  so->so_xticb.xti_evtarray[XTI_EVT_T_DISCONNECT]++;		  PRINTXTID(1, ("T_DISCONNECT (#1) \n"));		}	      }#endif XTI				tp = tcp_drop(tp, ECONNREFUSED);				if (smp &&  smp_owner(&so->lk_socket) == 0){				   dropsocket = 0;				   goto drop;				}			}			goto drop;		}		if ((tiflags & TH_SYN) == 0){			goto drop;		}		if (tiflags & TH_ACK) {		tp->snd_una = ti->ti_ack;		if (SEQ_LT(tp->snd_nxt, tp->snd_una))			tp->snd_nxt = tp->snd_una;		}		tp->t_timer[TCPT_REXMT] = 0;		tp->irs = ti->ti_seq;		tcp_rcvseqinit(tp);		tp->t_flags |= TF_ACKNOW;		if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {			TCPSTAT(tcps_connects++);			soisconnected(so);			tp->t_state = TCPS_ESTABLISHED;			tp->t_maxseg = MIN(tp->t_maxseg, tcp_mss(tp));#ifdef XTI			/* set T_CONNECT bit on in socket struct field			 * so->so_xticb.xti_evtarray when so->so_xticb.xti_epvalid and			 * *->xti_evtenabled are on.			 */						if (so->so_xticb.xti_epvalid) { /* valid xti endpoint */			  if (so->so_xticb.xti_evtenabled) {			    so->so_xticb.xti_evtarray[XTI_EVT_T_CONNECT]++; 			    PRINTXTID(1, ("T_CONNECT (#1)   \n"));			  }			  tp->xti_inbound_qos.precedence = xti_precedence;			  tp->xti_inbound_qos.timeout = tp->xti_neg_qos.timeout;			  tp->xti_inbound_qos.max_seg_size = tp->t_maxseg;			  tp->xti_inbound_qos.secopt = xti_secopt;			}#endif XTI			(void) tcp_reass(tp, (struct tcpiphdr *)0);			/*			 * if we didn't have to retransmit the SYN,			 * use its rtt as our initial srtt & rtt var.			 */			if (tp->t_rtt) {				tp->t_srtt = tp->t_rtt << 3;				tp->t_rttvar = tp->t_rtt << 1;				TCPT_RANGESET(tp->t_rxtcur, 				    ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1,				    TCPTV_MIN, TCPTV_REXMTMAX);				tp->t_rtt = 0;			}#ifdef XTI		      } else {			tp->t_state = TCPS_SYN_RECEIVED;			/* set T_LISTEN bit on in socket struct field			 * so->so_xticb.xti_evtarray when so->so_xticb.xti_epvalid and			 * *->xti_evtenabled are on.			 */						if (so->so_xticb.xti_epvalid) { /* valid xti endpoint */			  /* load tcp options to be read by *_CONOPT */			  			  tp->xti_inbound_qos.precedence = xti_precedence;			  tp->xti_inbound_qos.timeout = tp->xti_neg_qos.timeout;			  tp->xti_inbound_qos.max_seg_size = tp->t_maxseg;			  tp->xti_inbound_qos.secopt = xti_secopt;			  			  if (so->so_xticb.xti_evtenabled) {			    so->so_xticb.xti_evtarray[XTI_EVT_T_LISTEN]++; 			    PRINTXTID(1, ("T_LISTEN (#2) \n"));			  }			}		      }#else		} else			tp->t_state = TCPS_SYN_RECEIVED;#endif XTItrimthenstep6:		/*		 * Advance ti->ti_seq to correspond to first data byte.		 * If data, trim to stay within window,		 * dropping FIN if necessary.		 */		ti->ti_seq++;		if (ti->ti_len > tp->rcv_wnd) {			todrop = ti->ti_len - tp->rcv_wnd;			m_adj(m, -todrop);			ti->ti_len = tp->rcv_wnd;			tiflags &= ~TH_FIN;			TCPSTAT(tcps_rcvpackafterwin++);			TCPSTAT(tcps_rcvbyteafterwin += todrop);		}		tp->snd_wl1 = ti->ti_seq - 1;		tp->rcv_up = ti->ti_seq;		goto step6;	}	/*	 * States other than LISTEN or SYN_SENT.	 * First check that at least some bytes of segment are within 	 * receive window.  If segment begins before rcv_nxt,	 * drop leading data (and SYN); if nothing left, just ack.	 */		todrop = tp->rcv_nxt - ti->ti_seq;		if (todrop > 0) {			if (tiflags & TH_SYN) {				tiflags &= ~TH_SYN;				ti->ti_seq++;				if (ti->ti_urp > 1) 					ti->ti_urp--;				else					tiflags &= ~TH_URG;				todrop--;			}			if (todrop > ti->ti_len ||			todrop == ti->ti_len && (tiflags&TH_FIN) == 0) {/* #ifdef TCP_COMPAT_42 */				/*				 * Don't toss RST in response to 4.2-style keepalive.				 */				if (ti->ti_seq == tp->rcv_nxt - 1 && tiflags & TH_RST){					goto do_rst;}/* #endif */				TCPSTAT(tcps_rcvduppack++);				TCPSTAT(tcps_rcvdupbyte += ti->ti_len);				todrop = ti->ti_len;				tiflags &= ~TH_FIN;				tp->t_flags |= TF_ACKNOW;			} else {				TCPSTAT(tcps_rcvpartduppack++);				TCPSTAT(tcps_rcvpartdupbyte += todrop);			}			m_adj(m, todrop);			ti->ti_seq += todrop;			ti->ti_len -= todrop;			if (ti->ti_urp > todrop)				ti->ti_urp -= todrop;			else {				tiflags &= ~TH_URG;				ti->ti_urp = 0;			}		}	/*	 * If new data is received on a connection after the	 * user processes are gone, then RST the other end.	 */	if ((so->so_state & SS_NOFDREF) &&	    tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {		freeondrop = 0;		TCPSTAT(tcps_rcvafterclose++);		tp = tcp_close(tp);		if ( smp && smp_owner(&so->lk_socket) == 0){			dropsocket = 0;			/* The socket has been freed by tcp_close()			 * The above smp_owner check should be removed			 * The following line will prevent the machine			 * from panicing.			 */			so = NULL;			goto dropwithreset;		}		goto dropwithreset;	}	if (tp->rcv_wnd == 0) {		/*		 * If window is closed can only take segments at		 * window edge, and have to drop data and PUSH from		 * incoming segments.		 */		if (tp->rcv_nxt != ti->ti_seq) {			TCPSTAT(tcps_rcvpackafterwin++);			TCPSTAT(tcps_rcvbyteafterwin += ti->ti_len);			goto dropafterack;		}		if (ti->ti_len > 0) {			if (ti->ti_len == 1) 				TCPSTAT(tcps_rcvwinprobe++);			else {				TCPSTAT(tcps_rcvpackafterwin++);				TCPSTAT(tcps_rcvbyteafterwin += ti->ti_len);			}			m_adj(m, ti->ti_len);			ti->ti_len = 0;			tiflags &= ~(TH_PUSH|TH_FIN);		}	} else {		/*		 * If segment ends after window, drop trailing data		 * (and PUSH and FIN); if nothing left, just ACK.		 */		todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);		if (todrop > 0) {			if (todrop >= ti->ti_len) {				/*				 * If a new connection request is received				 * while in TIME_WAIT, drop the old connection				 * and start over if the sequence numbers				 * are above the previous ones.				 */				if (tiflags & TH_SYN &&				    tp->t_state == TCPS_TIME_WAIT &&				    SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {					iss = tp->rcv_nxt + TCP_ISSINCR;					(void) tcp_close(tp);					/* sofree may not really free the					 * socket and will return with the old					 * socket locked.					 */					if (smp && smp_owner(&so->lk_socket))						smp_unlock(&so->lk_socket);					goto findpcb;				}				if (todrop == 1) 					TCPSTAT(tcps_rcvwinprobe++);				else {					TCPSTAT(tcps_rcvpackafterwin++);					TCPSTAT(tcps_rcvbyteafterwin += ti->ti_len);				}				goto dropafterack;			}			TCPSTAT(tcps_rcvpackafterwin++);			TCPSTAT(tcps_rcvbyteafterwin += todrop);			m_adj(m, -todrop);			ti->ti_len -= todrop;			tiflags &= ~(TH_PUSH|TH_FIN);		}	}/* #ifdef TCP_COMPAT_42 */do_rst:/* #endif */	/*	 * If the RST bit is set examine the state:	 *    SYN_RECEIVED STATE:	 *	If passive open, return to LISTEN state.	 *	If active open, inform user that connection was refused.	 *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:	 *	Inform user that connection was reset, and close tcb.	 *    CLOSING, LAST_ACK, TIME_WAIT STATES	 *	Close the tcb.	 */	if (tiflags&TH_RST) switch (tp->t_state) {	case TCPS_SYN_RECEIVED:#ifdef XTI		/* set T_DISCONNECT bit on in socket struct field		 * so->so_xticb.xti_evtarray when so->so_xticb.xti_epvalid and		 * *->xti_evtenabled are on.		 */			if (so->so_xticb.xti_epvalid) { /* valid xti endpoint */		  if (so->so_xticb.xti_evtenabled) {		    so->so_xticb.xti_evtarray[XTI_EVT_T_DISCONNECT]++; 

⌨️ 快捷键说明

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