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

📄 tcp_input.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 5 页
字号:
		/*		 * If no out of band data is expected,		 * pull receive urgent pointer along		 * with the receive window.		 */		if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))			tp->rcv_up = tp->rcv_nxt;dodata:							/* XXX */	/*	 * Process the segment text, merging it into the TCP sequencing queue,	 * and arranging for acknowledgment of receipt if necessary.	 * This process logically involves adjusting tp->rcv_wnd as data	 * is presented to the user (this happens in tcp_usrreq.c,	 * case PRU_RCVD).  If a FIN has already been received on this	 * connection then we just ignore the text.	 */	if ((tlen || (tiflags & TH_FIN)) &&	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {		if (th->th_seq == tp->rcv_nxt && tp->segq.lh_first == NULL &&		    tp->t_state == TCPS_ESTABLISHED) {			if (th->th_flags & TH_PUSH)				tp->t_flags |= TF_ACKNOW;			else				tp->t_flags |= TF_DELACK;			tp->rcv_nxt += tlen;			tiflags = th->th_flags & TH_FIN;			tcpstat.tcps_rcvpack++;			tcpstat.tcps_rcvbyte += tlen;			ND6_HINT(tp);			m_adj(m, hdroptlen);			sbappend(&so->so_rcv, m);			sorwakeup(so);		} else {			m_adj(m, hdroptlen);			tiflags = tcp_reass(tp, th, m, &tlen);			tp->t_flags |= TF_ACKNOW;		}#ifdef TCP_SACK		if (!tp->sack_disable)			tcp_update_sack_list(tp); #endif 		/* 		 * variable len never referenced again in modern BSD,		 * so why bother computing it ??		 */#if 0		/*		 * Note the amount of data that peer has sent into		 * our window, in order to estimate the sender's		 * buffer size.		 */		len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt);#endif /* 0 */	} else {		m_freem(m);		tiflags &= ~TH_FIN;	}	/*	 * If FIN is received ACK the FIN and let the user know	 * that the connection is closing.  Ignore a FIN received before	 * the connection is fully established.	 */	if ((tiflags & TH_FIN) && TCPS_HAVEESTABLISHED(tp->t_state)) {		if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {			socantrcvmore(so);			tp->t_flags |= TF_ACKNOW;			tp->rcv_nxt++;		}		switch (tp->t_state) {		/*		 * In ESTABLISHED STATE enter the CLOSE_WAIT state.		 */		case TCPS_ESTABLISHED:			tp->t_state = TCPS_CLOSE_WAIT;			break;		/*		 * If still in FIN_WAIT_1 STATE FIN has not been acked so		 * enter the CLOSING state.		 */		case TCPS_FIN_WAIT_1:			tp->t_state = TCPS_CLOSING;			break;		/*		 * In FIN_WAIT_2 state enter the TIME_WAIT state,		 * starting the time-wait timer, turning off the other 		 * standard timers.		 */		case TCPS_FIN_WAIT_2:			tp->t_state = TCPS_TIME_WAIT;			tcp_canceltimers(tp);			tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;			soisdisconnected(so);			break;		/*		 * In TIME_WAIT state restart the 2 MSL time_wait timer.		 */		case TCPS_TIME_WAIT:			tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;			break;		}	}	if (so->so_options & SO_DEBUG) {#ifdef INET6		if (tp->pf == PF_INET6)			tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen);		else#endif /* INET6 */			tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen);	}	/*	 * Return any desired output.	 */	if (needoutput || (tp->t_flags & TF_ACKNOW)) {		(void) tcp_output(tp);	}	return;dropafterack:	/*	 * Generate an ACK dropping incoming segment if it occupies	 * sequence space, where the ACK reflects our state.	 */	if (tiflags & TH_RST)		goto drop;	m_freem(m);	tp->t_flags |= TF_ACKNOW;	(void) tcp_output(tp);	return;dropwithreset:	/*	 * Generate a RST, dropping incoming segment.	 * Make ACK acceptable to originator of segment.	 * Don't bother to respond if destination was broadcast/multicast.	 */	if ((tiflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST))	  goto drop;#ifdef INET6	if (is_ipv6) {	  /* For following calls to tcp_respond */	  ti = mtod(m, struct tcpiphdr *);	  if (IN6_IS_ADDR_MULTICAST(&ipv6->ip6_dst))	    goto drop;	} else {#endif /* INET6 */	    if (IN_MULTICAST(ti->ti_dst.s_addr))	      goto drop;#ifdef INET6	}#endif /* INET6 */	if (tiflags & TH_ACK)		tcp_respond(tp, (caddr_t) ti, m, (tcp_seq)0, th->th_ack, TH_RST);	else {		if (tiflags & TH_SYN)			tlen++;		tcp_respond(tp, (caddr_t) ti, m, th->th_seq+tlen, (tcp_seq)0,		    TH_RST|TH_ACK);	}	/* destroy temporarily created socket */	if (dropsocket)		(void) soabort(so);	return;drop:	/*	 * Drop space held by incoming segment and return.	 */	if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {#ifdef INET6	  if (tp->pf == PF_INET6)	    tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen);	  else#endif /* INET6 */	    tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen);	}	m_freem(m);	/* destroy temporarily created socket */	if (dropsocket)		(void) soabort(so);	return;#ifndef TUBA_INCLUDE}voidtcp_dooptions(tp, cp, cnt, th, ts_present, ts_val, ts_ecr)	struct tcpcb *tp;	u_char *cp;	int cnt;	struct tcphdr *th;	int *ts_present;	u_int32_t *ts_val, *ts_ecr;{	u_int16_t mss = 0;	int opt, optlen;	for (; cnt > 0; cnt -= optlen, cp += optlen) {		opt = cp[0];		if (opt == TCPOPT_EOL)			break;		if (opt == TCPOPT_NOP)			optlen = 1;		else {			optlen = cp[1];			if (optlen <= 0)				break;		}		switch (opt) {		default:			continue;		case TCPOPT_MAXSEG:			if (optlen != TCPOLEN_MAXSEG)				continue;			if (!(th->th_flags & TH_SYN))				continue;			bcopy((char *) cp + 2, (char *) &mss, sizeof(mss));			NTOHS(mss);			break;		case TCPOPT_WINDOW:			if (optlen != TCPOLEN_WINDOW)				continue;			if (!(th->th_flags & TH_SYN))				continue;			tp->t_flags |= TF_RCVD_SCALE;			tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT);			break;		case TCPOPT_TIMESTAMP:			if (optlen != TCPOLEN_TIMESTAMP)				continue;			*ts_present = 1;			bcopy((char *)cp + 2, (char *) ts_val, sizeof(*ts_val));			NTOHL(*ts_val);			bcopy((char *)cp + 6, (char *) ts_ecr, sizeof(*ts_ecr));			NTOHL(*ts_ecr);			/* 			 * A timestamp received in a SYN makes			 * it ok to send timestamp requests and replies.			 */			if (th->th_flags & TH_SYN) {				tp->t_flags |= TF_RCVD_TSTMP;				tp->ts_recent = *ts_val;				tp->ts_recent_age = tcp_now;			}			break;		#ifdef TCP_SACK 		case TCPOPT_SACK_PERMITTED:			if (tp->sack_disable || optlen!=TCPOLEN_SACK_PERMITTED)				continue;			if (th->th_flags & TH_SYN)				/* MUST only be set on SYN */				tp->t_flags |= TF_SACK_PERMIT;			break;		case TCPOPT_SACK:			if (tcp_sack_option(tp, th, cp, optlen))				continue;			break;#endif          		}	}	/* Update t_maxopd and t_maxseg after all options are processed */	if (th->th_flags & TH_SYN)		(void) tcp_mss(tp, mss);	/* sets t_maxseg */}#if defined(TCP_SACK)u_long tcp_seq_subtract(a, b)	u_long a, b;{ 	return ((long)(a - b)); }#endif#ifdef TCP_SACK /* * This function is called upon receipt of new valid data (while not in header * prediction mode), and it updates the ordered list of sacks.  */void tcp_update_sack_list(tp)	struct tcpcb *tp; {    	/* 	 * First reported block MUST be the most recent one.  Subsequent	 * blocks SHOULD be in the order in which they arrived at the	 * receiver.  These two conditions make the implementation fully	 * compliant with RFC 2018.	 */     	int i, j = 0, count = 0, lastpos = -1;	struct sackblk sack, firstsack, temp[MAX_SACK_BLKS];    	/* First clean up current list of sacks */	for (i = 0; i < tp->rcv_numsacks; i++) {		sack = tp->sackblks[i];		if (sack.start == 0 && sack.end == 0) {			count++; /* count = number of blocks to be discarded */			continue;		}		if (SEQ_LEQ(sack.end, tp->rcv_nxt)) {			tp->sackblks[i].start = tp->sackblks[i].end = 0;			count++;		} else { 			temp[j].start = tp->sackblks[i].start;			temp[j++].end = tp->sackblks[i].end;		}	}   	tp->rcv_numsacks -= count;	if (tp->rcv_numsacks == 0) { /* no sack blocks currently (fast path) */		tcp_clean_sackreport(tp);		if (SEQ_LT(tp->rcv_nxt, tp->rcv_laststart)) {			/* ==> need first sack block */			tp->sackblks[0].start = tp->rcv_laststart;			tp->sackblks[0].end = tp->rcv_lastend;			tp->rcv_numsacks = 1;		}		return;	}	/* Otherwise, sack blocks are already present. */	for (i = 0; i < tp->rcv_numsacks; i++)		tp->sackblks[i] = temp[i]; /* first copy back sack list */	if (SEQ_GEQ(tp->rcv_nxt, tp->rcv_lastend)) 		return;     /* sack list remains unchanged */	/* 	 * From here, segment just received should be (part of) the 1st sack.	 * Go through list, possibly coalescing sack block entries.	 */	firstsack.start = tp->rcv_laststart;	firstsack.end = tp->rcv_lastend;	for (i = 0; i < tp->rcv_numsacks; i++) {		sack = tp->sackblks[i];		if (SEQ_LT(sack.end, firstsack.start) ||		    SEQ_GT(sack.start, firstsack.end))			continue; /* no overlap */		if (sack.start == firstsack.start && sack.end == firstsack.end){			/* 			 * identical block; delete it here since we will			 * move it to the front of the list.			 */			tp->sackblks[i].start = tp->sackblks[i].end = 0;			lastpos = i;    /* last posn with a zero entry */			continue;		}		if (SEQ_LEQ(sack.start, firstsack.start))			firstsack.start = sack.start; /* merge blocks */		if (SEQ_GEQ(sack.end, firstsack.end))			firstsack.end = sack.end;     /* merge blocks */		tp->sackblks[i].start = tp->sackblks[i].end = 0;		lastpos = i;    /* last posn with a zero entry */	}	if (lastpos != -1) {    /* at least one merge */		for (i = 0, j = 1; i < tp->rcv_numsacks; i++) {			sack = tp->sackblks[i];			if (sack.start == 0 && sack.end == 0)				continue;			temp[j++] = sack;		}		tp->rcv_numsacks = j; /* including first blk (added later) */		for (i = 1; i < tp->rcv_numsacks; i++) /* now copy back */			tp->sackblks[i] = temp[i];	} else {        /* no merges -- shift sacks by 1 */		if (tp->rcv_numsacks < MAX_SACK_BLKS)			tp->rcv_numsacks++;		for (i = tp->rcv_numsacks-1; i > 0; i--)			tp->sackblks[i] = tp->sackblks[i-1];	}	tp->sackblks[0] = firstsack;	return;}  /* * Process the TCP SACK option.  Returns 1 if tcp_dooptions() should continue, * and 0 otherwise, if the option was fine.  tp->snd_holes is an ordered list * of holes (oldest to newest, in terms of the sequence space).   */             inttcp_sack_option(tp, th, cp, optlen)	struct tcpcb *tp;	struct tcphdr *th;	u_char *cp;	int    optlen;{       	int tmp_olen;	u_char *tmp_cp;	struct sackhole *cur, *p, *temp;   	if (tp->sack_disable)		return 1;           	/* Note: TCPOLEN_SACK must be 2*sizeof(tcp_seq) */	if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0)		return 1;	tmp_cp = cp + 2;	tmp_olen = optlen - 2;	if (tp->snd_numholes < 0)		tp->snd_numholes = 0;	if (tp->t_maxseg == 0)		panic("tcp_sack_option"); /* Should never happen */	while (tmp_olen > 0) {		struct sackblk sack;            		bcopy((char *) tmp_cp, (char *) &(sack.start), sizeof(tcp_seq));		NTOHL(sack.start); 		bcopy((char *) tmp_cp + sizeof(tcp_seq),		    (char *) &(sack.end), sizeof(tcp_seq));		NTOHL(sack.end);		tmp_olen -= TCPOLEN_SACK;		tmp_cp += TCPOLEN_SACK;		if (SEQ_LEQ(sack.end, sack.start))			continue; /* bad SACK fields */		if (SEQ_LEQ(sack.end, tp->snd_una)) 			continue; /* old block */#if defined(TCP_SACK) && defined(TCP_FACK)		/* Updates snd_fack.  */		if (SEQ_GEQ(sack.end, tp->snd_fack))			tp->snd_fack = sack.end;#endif /* TCP_FACK */		if (SEQ_GT(th->th_ack, tp->snd_una)) {			if (SEQ_LT(sack.start, th->th_ack))				continue;		} else {			if (SEQ_LT(sack.start, tp->snd_una))				continue;		}		if (SEQ_GT(sack.end, tp->snd_max))			continue;		if (tp->snd_holes == 0) { /* first hole */			tp->snd_holes = (struct sackhole *)			    malloc(sizeof(struct sackhole), M_PCB, M_NOWAIT);			if (tp->snd_holes == NULL) {				/* ENOBUFS, so ignore SACKed block for now*/				continue;  			}			cur = tp->snd_holes;			cur->start = th->th_ack;			cur->end = sack.start;			cur->rxmit = cur->start;			cur->next = 0;			tp->snd_numholes = 1;			tp->rcv_lastsack = sack.end;			/* 			 * dups is at least one.  If more data has been 			 * SACKed, it can be greater than one.			 */			cur->dups = min(tcprexmtthresh, 			    ((sack.end - cur->end)/tp->t_maxseg));			if (cur->dups < 1)				cur->dups = 1;			continue; /* with next sack block */		}		/* Go thru list of holes:  p = previous,  cur = current */		p = cur = tp->snd_holes;		while (cur) {			if (SEQ_LEQ(sack.end, cur->start)) 				/* SACKs data before the current hole */ 				break; /* no use going through more holes */			if (SEQ_GEQ(sack.start, cur->end)) {				/* SACKs data beyond the current hole */				cur->dups++;				if (

⌨️ 快捷键说明

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