xref: /csrg-svn/sys/netinet/tcp_input.c (revision 4803)
1*4803Swnj /* tcp_input.c 1.21 81/11/08 */
24601Swnj 
34601Swnj #include "../h/param.h"
44601Swnj #include "../h/systm.h"
54663Swnj #include "../h/mbuf.h"
64663Swnj #include "../h/socket.h"
7*4803Swnj #include "../h/socketvar.h"
8*4803Swnj #include "../net/inet_cksum.h"
9*4803Swnj #include "../net/inet.h"
10*4803Swnj #include "../net/inet_systm.h"
11*4803Swnj #include "../net/imp.h"
12*4803Swnj #include "../net/inet_host.h"
13*4803Swnj #include "../net/ip.h"
14*4803Swnj #include "../net/tcp.h"
15*4803Swnj #include "../net/tcp_fsm.h"
16*4803Swnj #include "../net/tcp_var.h"
17*4803Swnj #include "/usr/include/errno.h"
184601Swnj 
194679Swnj int	tcpcksum = 1;
204601Swnj 
21*4803Swnj tcp_advise(mp)
22*4803Swnj 	struct mbuf *mp;
23*4803Swnj {
24*4803Swnj 
25*4803Swnj }
26*4803Swnj 
274601Swnj tcp_input(mp)
284601Swnj 	register struct mbuf *mp;
294601Swnj {
304673Swnj 	register struct th *n;		/* known to be r10 */
314697Swnj 	register int j;
324601Swnj 	register struct tcb *tp;
33*4803Swnj 	register int thflags;
344601Swnj 	int nstate;
354601Swnj 	struct mbuf *m;
36*4803Swnj 	struct socket *so;
374673Swnj 	int hlen, tlen;
384601Swnj 	u_short lport, fport;
394601Swnj #ifdef TCPDEBUG
404601Swnj 	struct tcp_debug tdb;
414601Swnj #endif
424601Swnj COUNT(TCP_INPUT);
434601Swnj 
444601Swnj 	/*
454601Swnj 	 * Build extended tcp header
464601Swnj 	 */
47*4803Swnj 	n = mtod(mp, struct th *);
48*4803Swnj 	thflags = n->th_flags;
494601Swnj 	tlen = ((struct ip *)n)->ip_len;
504601Swnj 	n->t_len = htons(tlen);
514601Swnj 	n->t_next = NULL;
524601Swnj 	n->t_prev = NULL;
534601Swnj 	n->t_x1 = 0;
544601Swnj 	lport = ntohs(n->t_dst);
554601Swnj 	fport = ntohs(n->t_src);
564601Swnj 
574601Swnj 	/* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */
584601Swnj 	if ((hlen = n->t_off << 2) > mp->m_len)
594601Swnj 		{ printf("tcp header overflow\n"); m_freem(mp); return; }
604601Swnj 
614679Swnj 	if (tcpcksum) {
624679Swnj 		/*
634679Swnj 		 * Checksum extended header and data
644679Swnj 		 */
654718Swnj 		CKSUM_TCPCHK(mp, n, r10, sizeof (struct ip) + tlen);
664718Swnj 		if (n->t_sum != 0) {
674679Swnj 			netstat.t_badsum++;
684601Swnj 			m_freem(mp);
694601Swnj 			return;
704601Swnj 		}
714601Swnj 	}
724601Swnj 
734601Swnj 	/*
744601Swnj 	 * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!)
754601Swnj 	 */
76*4803Swnj 	tp = tcb.tcb_next;
77*4803Swnj 	for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next)
784601Swnj 		if (tp->t_lport == lport && tp->t_fport == fport &&
79*4803Swnj 		    tp->t_host->h_addr.s_addr == n->t_s.s_addr)
804601Swnj 			goto found;
81*4803Swnj 	tp = tcb.tcb_next;
82*4803Swnj 	for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next)
834601Swnj 		if (tp->t_lport == lport &&
844601Swnj 		    (tp->t_fport==fport || tp->t_fport==0) &&
85*4803Swnj 		    (tp->t_host->h_addr.s_addr == n->t_s.s_addr ||
86*4803Swnj 		     tp->t_host->h_addr.s_addr == 0))
874601Swnj 			goto found;
884601Swnj 	goto notwanted;
894601Swnj found:
904601Swnj 
914601Swnj 	/*
924601Swnj 	 * Byte swap header
934601Swnj 	 */
944601Swnj 	n->t_len = tlen - hlen;
954601Swnj 	n->t_src = fport;
964601Swnj 	n->t_dst = lport;
974601Swnj 	n->t_seq = ntohl(n->t_seq);
984601Swnj 	n->t_ackno = ntohl(n->t_ackno);
994601Swnj 	n->t_win = ntohs(n->t_win);
1004601Swnj 	n->t_urp = ntohs(n->t_urp);
1014601Swnj 
1024601Swnj 	/*
1034601Swnj 	 * Check segment seq # and do rst processing
1044601Swnj 	 */
1054601Swnj 	switch (tp->t_state) {
1064601Swnj 
1074601Swnj 	case LISTEN:
108*4803Swnj 		if ((thflags&TH_ACK) || !syn_ok(tp, n)) {
1094675Swnj 			tcp_sndrst(tp, n);
1104601Swnj 			goto badseg;
1114601Swnj 		}
112*4803Swnj 		if (thflags&TH_RST)
1134601Swnj 			goto badseg;
1144601Swnj 		goto goodseg;
1154601Swnj 
1164601Swnj 	case SYN_SENT:
1174601Swnj 		if (!ack_ok(tp, n) || !syn_ok(tp, n)) {
1184675Swnj 			tcp_sndrst(tp, n);			/* 71,72,75 */
1194601Swnj 			goto badseg;
1204601Swnj 		}
121*4803Swnj 		if (thflags&TH_RST) {
122*4803Swnj 			tcp_error(tp, ENETRESET);
123*4803Swnj 			tcp_detach(tp);				/* 70 */
1244601Swnj 			tp->t_state = CLOSED;
1254601Swnj 			goto badseg;
1264601Swnj 		}
1274601Swnj 		goto goodseg;
1284601Swnj 
1294601Swnj 	default:
130*4803Swnj         	if ((thflags&TH_RST) == 0)
1314601Swnj 			goto common;
1324601Swnj 		if (n->t_seq < tp->rcv_nxt)		/* bad rst */
1334601Swnj 			goto badseg;				/* 69 */
1344601Swnj 		switch (tp->t_state) {
1354601Swnj 
1364601Swnj 		case L_SYN_RCVD:
1374601Swnj 			if (ack_ok(tp, n) == 0)
1384601Swnj 				goto badseg;			/* 69 */
1394601Swnj 			tp->t_rexmt = 0;
1404601Swnj 			tp->t_rexmttl = 0;
1414601Swnj 			tp->t_persist = 0;
142*4803Swnj 			h_free(tp->t_host);
143*4803Swnj 			tp->t_host = 0;
1444601Swnj 			tp->t_state = LISTEN;
1454601Swnj 			goto badseg;
1464601Swnj 
1474601Swnj 		default:
148*4803Swnj 			tcp_error(tp, ENETRESET);
149*4803Swnj 			tcp_detach(tp);				/* 66 */
1504601Swnj 			tp->t_state = CLOSED;
1514601Swnj 			goto badseg;
1524601Swnj 		}
1534601Swnj 		/*NOTREACHED*/
1544601Swnj 
1554601Swnj 	case SYN_RCVD:
1564601Swnj common:
1574601Swnj 		if (ack_ok(tp, n) == 0) {
1584675Swnj 			tcp_sndrst(tp, n);			/* 74 */
1594601Swnj 			goto badseg;
1604601Swnj 		}
1614601Swnj 		if (syn_ok(tp, n) && n->t_seq != tp->irs) {
1624679Swnj 			tcp_sndnull(tp);			/* 74 */
1634601Swnj 			goto badseg;
1644601Swnj 		}
1654601Swnj 		goto goodseg;
1664601Swnj 	}
1674601Swnj badseg:
1684601Swnj 	m_freem(mp);
1694601Swnj 	return;
1704601Swnj 
1714601Swnj goodseg:
1724601Swnj 	/*
1734601Swnj 	 * Defer processing if no buffer space for this connection.
1744601Swnj 	 */
175*4803Swnj 	so = tp->t_socket;
176*4803Swnj 	if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat &&
177*4803Swnj 	     n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) {
178*4803Swnj /*
1794601Swnj 		mp->m_act = (struct mbuf *)0;
180*4803Swnj 		if ((m = tp->seg_unack) != NULL) {
1814601Swnj 			while (m->m_act != NULL)
1824601Swnj 				m = m->m_act;
1834601Swnj 			m->m_act = mp;
1844601Swnj 		} else
185*4803Swnj 			tp->seg_unack = mp;
186*4803Swnj */
187*4803Swnj 		m_freem(mp);
1884601Swnj 		return;
1894601Swnj 	}
1904601Swnj 
1914601Swnj 	/*
1924601Swnj 	 * Discard ip header, and do tcp input processing.
1934601Swnj 	 */
1944601Swnj 	hlen += sizeof(struct ip);
1954601Swnj 	mp->m_off += hlen;
1964601Swnj 	mp->m_len -= hlen;
1974601Swnj 	nstate = tp->t_state;
1984601Swnj 	tp->tc_flags &= ~TC_NET_KEEP;
1994770Swnj #ifdef KPROF
2004601Swnj 	acounts[tp->t_state][INRECV]++;
2014770Swnj #endif
2024601Swnj #ifdef TCPDEBUG
203*4803Swnj 	if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) {
2044604Swnj 		tdb_setup(tp, n, INRECV, &tdb);
2054601Swnj 	} else
2064601Swnj 		tdb.td_tod = 0;
2074601Swnj #endif
2084601Swnj 	switch (tp->t_state) {
2094601Swnj 
2104601Swnj 	case LISTEN:
2114601Swnj 		if (!syn_ok(tp, n) ||
212*4803Swnj 		    ((tp->t_host = h_make(&n->t_s)) == 0)) {
2134601Swnj 			nstate = EFAILEC;
2144601Swnj 			goto done;
2154601Swnj 		}
2164601Swnj 		tp->t_fport = n->t_src;
2174733Swnj 		tp->t_template = tcp_template(tp);
2184675Swnj 		tcp_ctldat(tp, n, 1);
2194601Swnj 		if (tp->tc_flags&TC_FIN_RCVD) {
2204601Swnj 			tp->t_finack = T_2ML;			/* 3 */
2214601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
2224601Swnj 			nstate = CLOSE_WAIT;
2234601Swnj 		} else {
224*4803Swnj /* XXX */		/* tp->t_init = T_INIT / 2; */		/* 4 */
2254601Swnj 			nstate = L_SYN_RCVD;
2264601Swnj 		}
2274601Swnj 		goto done;
2284601Swnj 
2294601Swnj 	case SYN_SENT:
2304601Swnj 		if (!syn_ok(tp, n)) {
2314601Swnj 			nstate = EFAILEC;
2324601Swnj 			goto done;
2334601Swnj 		}
2344675Swnj 		tcp_ctldat(tp, n, 1);
2354601Swnj 		if (tp->tc_flags&TC_FIN_RCVD) {
236*4803Swnj 			if ((thflags&TH_ACK) == 0) {
2374601Swnj 				tp->t_finack = T_2ML;		/* 9 */
2384601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
2394601Swnj 			}
2404601Swnj 			nstate = CLOSE_WAIT;
2414601Swnj 			goto done;
2424601Swnj 		}
243*4803Swnj 		nstate = (thflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */
2444601Swnj 		goto done;
2454601Swnj 
2464601Swnj 	case SYN_RCVD:
2474601Swnj 	case L_SYN_RCVD:
248*4803Swnj 		if ((thflags&TH_ACK) == 0 ||
249*4803Swnj 		    (thflags&TH_ACK) && n->t_ackno <= tp->iss) {
2504601Swnj 			nstate = EFAILEC;
2514601Swnj 			goto done;
2524601Swnj 		}
2534601Swnj 		goto input;
2544601Swnj 
2554601Swnj 	case ESTAB:
2564601Swnj 	case FIN_W1:
2574601Swnj 	case FIN_W2:
2584601Swnj 	case TIME_WAIT:
2594601Swnj input:
2604675Swnj 		tcp_ctldat(tp, n, 1);				/* 39 */
2614601Swnj 		switch (tp->t_state) {
2624601Swnj 
2634601Swnj 		case ESTAB:
2644601Swnj 			if (tp->tc_flags&TC_FIN_RCVD)
2654601Swnj 				nstate = CLOSE_WAIT;
2664601Swnj 			break;
2674601Swnj 
2684601Swnj 		case SYN_RCVD:
2694601Swnj 		case L_SYN_RCVD:
2704601Swnj 			nstate = (tp->tc_flags&TC_FIN_RCVD) ?
2714601Swnj 			    CLOSE_WAIT : ESTAB;			 /* 33:5 */
2724601Swnj 			break;
2734601Swnj 
2744601Swnj 		case FIN_W1:
2754601Swnj 			j = ack_fin(tp, n);
2764601Swnj 			if ((tp->tc_flags & TC_FIN_RCVD) == 0) {
2774601Swnj 				if (j)
2784601Swnj 					nstate = FIN_W2;	/* 27 */
2794601Swnj 				break;
2804601Swnj 			}
2814601Swnj 			tp->t_finack = T_2ML;
2824601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
2834730Swnj 			nstate = j ? TIME_WAIT : CLOSING;	/* 28:26 */
2844601Swnj 			break;
2854601Swnj 
2864601Swnj 		case FIN_W2:
2874601Swnj 			if (tp->tc_flags&TC_FIN_RCVD) {
2884601Swnj 				tp->t_finack = T_2ML;		/* 29 */
2894601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
2904601Swnj 				nstate = TIME_WAIT;
2914601Swnj 				break;
2924601Swnj 			}
2934601Swnj 			break;
2944601Swnj 		}
2954601Swnj 		goto done;
2964601Swnj 
2974601Swnj 	case CLOSE_WAIT:
298*4803Swnj 		if (thflags&TH_FIN) {
299*4803Swnj 			if ((thflags&TH_ACK) &&
3004601Swnj 			    n->t_ackno <= tp->seq_fin) {
3014675Swnj 				tcp_ctldat(tp, n, 0);		/* 30 */
3024601Swnj 				tp->t_finack = T_2ML;
3034601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
3044601Swnj 			} else
3054675Swnj 				tcp_sndctl(tp);			/* 31 */
3064601Swnj 			goto done;
3074601Swnj 		}
3084601Swnj 		goto input;
3094601Swnj 
3104730Swnj 	case CLOSING:
3114601Swnj 		j = ack_fin(tp, n);
312*4803Swnj 		if (thflags&TH_FIN) {
3134675Swnj 			tcp_ctldat(tp, n, 0);
3144601Swnj 			tp->t_finack = T_2ML;
3154601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
3164601Swnj 			if (j)
3174601Swnj 				nstate = TIME_WAIT;		/* 23 */
3184601Swnj 			goto done;
3194601Swnj 		}
3204601Swnj 		if (j) {
3214601Swnj 			if (tp->tc_flags&TC_WAITED_2_ML)
3224601Swnj 				if (rcv_empty(tp)) {
323*4803Swnj 					sowakeup(tp->t_socket); /* ### */
324*4803Swnj 					nstate = CLOSED;	/* 15 */
3254601Swnj 				} else
3264601Swnj 					nstate = RCV_WAIT;	/* 18 */
3274601Swnj 			else
3284601Swnj 				nstate = TIME_WAIT;
3294601Swnj 			goto done;
3304601Swnj 		}
3314601Swnj 		goto input;
3324601Swnj 
3334730Swnj 	case LAST_ACK:
3344601Swnj 		if (ack_fin(tp, n)) {
3354601Swnj 			if (rcv_empty(tp)) {			/* 16 */
336*4803Swnj 				sowakeup(tp->t_socket); /* ### */
337*4803Swnj /* XXX */			/* tcp_close(tp, UCLOSED); */
3384601Swnj 				nstate = CLOSED;
3394601Swnj 			} else
3404601Swnj 				nstate = RCV_WAIT;		/* 19 */
3414601Swnj 			goto done;
3424601Swnj 		}
343*4803Swnj 		if (thflags&TH_FIN) {
3444675Swnj 			tcp_sndctl(tp);				/* 31 */
3454601Swnj 			goto done;
3464601Swnj 		}
3474601Swnj 		goto input;
3484601Swnj 
3494601Swnj 	case RCV_WAIT:
350*4803Swnj 		if ((thflags&TH_FIN) && (thflags&TH_ACK) &&
3514601Swnj 		    n->t_ackno <= tp->seq_fin) {
3524675Swnj 			tcp_ctldat(tp, n, 0);
3534601Swnj 			tp->t_finack = T_2ML;
3544601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;	/* 30 */
3554601Swnj 		}
3564601Swnj 		goto done;
3574601Swnj 	}
3584601Swnj 	panic("tcp_input");
3594601Swnj done:
3604601Swnj 
3614601Swnj 	/*
3624601Swnj 	 * Done with state*input specific processing.
3634601Swnj 	 * Form trace records, free input if not needed,
3644601Swnj 	 * and enter new state.
3654601Swnj 	 */
3664601Swnj #ifdef TCPDEBUG
3674604Swnj 	if (tdb.td_tod)
3684604Swnj 		tdb_stuff(&tdb, nstate);
3694601Swnj #endif
3704601Swnj 	switch (nstate) {
3714601Swnj 
3724601Swnj 	case EFAILEC:
3734601Swnj 		m_freem(mp);
3744601Swnj 		return;
3754601Swnj 
3764601Swnj 	default:
3774601Swnj 		tp->t_state = nstate;
3784601Swnj 		/* fall into ... */
3794601Swnj 
3804601Swnj 	case CLOSED:
3814601Swnj 		/* IF CLOSED CANT LOOK AT tc_flags */
3824601Swnj 		if ((tp->tc_flags&TC_NET_KEEP) == 0)
3834690Swnj 			/* inline expansion of m_freem */
3844690Swnj 			while (mp) {
3854690Swnj 				MFREE(mp, m);
3864690Swnj 				mp = m;
3874690Swnj 			}
3884601Swnj 		return;
3894601Swnj 	}
3904601Swnj 	/* NOTREACHED */
3914601Swnj 
3924601Swnj 	/*
3934601Swnj 	 * Unwanted packed; free everything
3944601Swnj 	 * but the header and return an rst.
3954601Swnj 	 */
3964601Swnj notwanted:
3974601Swnj 	m_freem(mp->m_next);
3984601Swnj 	mp->m_next = NULL;
3994601Swnj 	mp->m_len = sizeof(struct th);
4004601Swnj #define xchg(a,b) j=a; a=b; b=j
4014601Swnj 	xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src);
4024601Swnj #undef xchg
403*4803Swnj 	if (thflags&TH_ACK)
4044601Swnj 		n->t_seq = n->t_ackno;
4054601Swnj 	else {
4064601Swnj 		n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen);
4074601Swnj 		n->t_seq = 0;
4084601Swnj 	}
409*4803Swnj 	n->th_flags = ((thflags & TH_ACK) ? 0 : TH_ACK) | TH_RST;
4104601Swnj 	n->t_len = htons(TCPSIZE);
4114601Swnj 	n->t_off = 5;
4124718Swnj 	n->t_sum = inet_cksum(mp, sizeof(struct th));
4134601Swnj 	((struct ip *)n)->ip_len = sizeof(struct th);
4144601Swnj 	ip_output(mp);
4154601Swnj 	netstat.t_badsegs++;
4164601Swnj }
4174601Swnj 
4184675Swnj tcp_ctldat(tp, n, dataok)
4194601Swnj 	register struct tcb *tp;
4204601Swnj 	register struct th *n;
4214601Swnj {
4224679Swnj 	register struct mbuf *m;
423*4803Swnj 	register int thflags = n->th_flags;
4244679Swnj 	int sent;
4254679Swnj COUNT(TCP_CTLDAT);
4264601Swnj 
4274601Swnj 	tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW);
4284601Swnj /* syn */
429*4803Swnj 	if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (thflags&TH_SYN)) {
4304601Swnj 		tp->irs = n->t_seq;
4314601Swnj 		tp->rcv_nxt = n->t_seq + 1;
4324601Swnj 		tp->snd_wl = tp->rcv_urp = tp->irs;
4334601Swnj 		tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE);
4344601Swnj 	}
4354601Swnj /* ack */
436*4803Swnj 	if ((thflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) &&
4374601Swnj 	    n->t_ackno > tp->snd_una) {
4384679Swnj 		register struct mbuf *mn;
439*4803Swnj 		register struct socket *so;
4404690Swnj 		int len;
4414679Swnj 
442*4803Swnj 		so = tp->t_socket;
4434601Swnj 
4444601Swnj 		/* update snd_una and snd_nxt */
4454601Swnj 		tp->snd_una = n->t_ackno;
4464601Swnj 		if (tp->snd_una > tp->snd_nxt)
4474601Swnj 			tp->snd_nxt = tp->snd_una;
4484601Swnj 		/* if timed msg acked, set retrans time value */
4494601Swnj 		if ((tp->tc_flags&TC_SYN_ACKED) &&
4504601Swnj 		    tp->snd_una > tp->t_xmt_val) {
4514601Swnj 			tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT);
4524601Swnj 			if (tp->t_xmtime > T_REMAX)
4534601Swnj 				tp->t_xmtime = T_REMAX;
4544601Swnj 		}
4554601Swnj 
4564601Swnj 		/* remove acked data from send buf */
4574601Swnj 		len = tp->snd_una - tp->snd_off;
458*4803Swnj 		m = so->so_snd.sb_mb;
4594601Swnj 		while (len > 0 && m != NULL)
4604601Swnj 			if (m->m_len <= len) {
4614601Swnj 				len -= m->m_len;
4624601Swnj 				if (m->m_off > MMAXOFF)
463*4803Swnj 					so->so_snd.sb_mbcnt -= NMBPG;
4644601Swnj 				MFREE(m, mn);
4654601Swnj 				m = mn;
466*4803Swnj 				so->so_snd.sb_mbcnt--;
467*4803Swnj 				if (so->so_snd.sb_mbcnt <= 0)
468*4803Swnj 					panic("tcp_ctldat");
4694601Swnj 			} else {
4704601Swnj 				m->m_len -= len;
4714601Swnj 				m->m_off += len;
4724601Swnj 				break;
4734601Swnj 			}
474*4803Swnj 		so->so_snd.sb_mb = m;
4754601Swnj 		tp->snd_off = tp->snd_una;
4764601Swnj 		if ((tp->tc_flags&TC_SYN_ACKED) == 0 &&
4774601Swnj 		    (tp->snd_una > tp->iss)) {
4784601Swnj 			tp->tc_flags |= TC_SYN_ACKED;
4794601Swnj 			tp->t_init = 0;
4804601Swnj 		}
4814601Swnj 		if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin)
4824601Swnj 			tp->tc_flags &= ~TC_SND_FIN;
4834601Swnj 		tp->t_rexmt = 0;
4844601Swnj 		tp->t_rexmttl = 0;
4854601Swnj 		tp->tc_flags |= TC_CANCELLED;
486*4803Swnj 		sowakeup(tp->t_socket);		/* wasteful */
4874601Swnj 	}
4884601Swnj /* win */
4894601Swnj 	if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) {
4904601Swnj 		tp->snd_wl = n->t_seq;
4914601Swnj 		tp->snd_wnd = n->t_win;
4924601Swnj 		tp->tc_flags |= TC_NEW_WINDOW;
4934601Swnj 		tp->t_persist = 0;
4944601Swnj 	}
4954679Swnj 	if (dataok == 0)
4964679Swnj 		goto ctlonly;
4974601Swnj /* text */
4984679Swnj 	if (n->t_len == 0)
4994679Swnj 		goto notext;
5004679Swnj 	{ register int i;
5014679Swnj 	  register struct th *p, *q;
5024679Swnj 	  register struct mbuf *m;
5034679Swnj 	  int overage;
5044601Swnj 
5054645Swnj 	/*
5064645Swnj 	 * Discard duplicate data already passed to user.
5074645Swnj 	 */
5084648Swnj 	if (SEQ_LT(n->t_seq, tp->rcv_nxt)) {
5094645Swnj 		i = tp->rcv_nxt - n->t_seq;
5104645Swnj 		if (i >= n->t_len)
5114679Swnj 			goto notext;
5124645Swnj 		n->t_seq += i;
5134645Swnj 		n->t_len -= i;
5144645Swnj 		m_adj(dtom(n), i);
5154601Swnj 	}
5164601Swnj 
5174645Swnj 	/*
5184645Swnj 	 * Find a segment which begins after this one does.
5194645Swnj 	 */
520*4803Swnj 	for (q = tp->tcb_hd.seg_next; q != (struct th *)tp; q = q->t_next)
5214648Swnj 		if (SEQ_GT(q->t_seq, n->t_seq))
5224645Swnj 			break;
5234601Swnj 
5244645Swnj 	/*
5254645Swnj 	 * If there is a preceding segment, it may provide some of
5264645Swnj 	 * our data already.  If so, drop the data from the incoming
5274645Swnj 	 * segment.  If it provides all of our data, drop us.
5284645Swnj 	 */
5294645Swnj 	if (q->t_prev != (struct th *)tp) {
5304648Swnj 		/* conversion to int (in i) handles seq wraparound */
5314645Swnj 		i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq;
5324645Swnj 		if (i > 0) {
5334645Swnj 			if (i >= n->t_len)
5344679Swnj 				goto notext;	/* w/o setting TC_NET_KEEP */
5354645Swnj 			m_adj(dtom(tp), i);
5364645Swnj 			n->t_len -= i;
5374645Swnj 			n->t_seq += i;
5384601Swnj 		}
5394601Swnj 	}
5404601Swnj 
5414645Swnj 	/*
5424645Swnj 	 * While we overlap succeeding segments trim them or,
5434645Swnj 	 * if they are completely covered, dequeue them.
5444645Swnj 	 */
5454648Swnj 	while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) {
5464645Swnj 		i = (n->t_seq + n->t_len) - q->t_seq;
5474645Swnj 		if (i < q->t_len) {
5484645Swnj 			q->t_len -= i;
5494645Swnj 			m_adj(dtom(q), i);
5504645Swnj 			break;
5514601Swnj 		}
5524645Swnj 		q = q->t_next;
5534645Swnj 		m_freem(dtom(q->t_prev));
5544645Swnj 		remque(q->t_prev);
5554645Swnj 	}
5564601Swnj 
5574645Swnj 	/*
5584645Swnj 	 * Stick new segment in its place.
5594645Swnj 	 */
5604645Swnj 	insque(n, q->t_prev);
5614656Swnj 	tp->seqcnt += n->t_len;
5624601Swnj 
5634645Swnj 	/*
5644645Swnj 	 * Calculate available space and discard segments for
5654645Swnj 	 * which there is too much.
5664645Swnj 	 */
567*4803Swnj 	q = tp->tcb_hd.seg_prev;
5684648Swnj 	overage =
569*4803Swnj 	    (tp->t_socket->so_rcv.sb_cc /* + tp->rcv_seqcnt XXX */) -
570*4803Swnj 		tp->t_socket->so_rcv.sb_hiwat;
5714645Swnj 	if (overage > 0)
5724645Swnj 		for (;;) {
5734645Swnj 			i = MIN(q->t_len, overage);
5744645Swnj 			overage -= i;
5754645Swnj 			q->t_len -= i;
5764645Swnj 			m_adj(q, -i);
5774645Swnj 			if (q == n)
5784645Swnj 				tp->tc_flags |= TC_DROPPED_TXT;
5794645Swnj 			if (q->t_len)
5804645Swnj 				break;
5814645Swnj 			if (q == n)
5824648Swnj 				panic("tcp_text dropall");
5834645Swnj 			q = q->t_prev;
5844645Swnj 			remque(q->t_next);
5854645Swnj 		}
5864601Swnj 
5874645Swnj 	/*
5884648Swnj 	 * Advance rcv_next through
5894648Swnj 	 * newly completed sequence space
5904648Swnj 	 * and return forcing an ack.
5914645Swnj 	 */
5924645Swnj 	while (n->t_seq == tp->rcv_nxt) {
5934648Swnj 		/* present data belongs here */
5944645Swnj 		tp->rcv_nxt += n->t_len;
5954645Swnj 		n = n->t_next;
5964645Swnj 		if (n == (struct th *)tp)
5974645Swnj 			break;
5984645Swnj 	}
5994645Swnj 	tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP);
6004679Swnj 	}
6014679Swnj notext:
6024679Swnj /* urg */
6034601Swnj 
604*4803Swnj 	if (thflags & (TH_URG|TH_EOL|TH_FIN)) {
605*4803Swnj 		if (thflags&TH_URG) {
606*4803Swnj 			unsigned urgent;
607*4803Swnj 
608*4803Swnj 			urgent = n->t_urp + n->t_seq;
609*4803Swnj 			if (tp->rcv_nxt < urgent) {
610*4803Swnj 				if (tp->rcv_urp <= tp->rcv_nxt) {
611*4803Swnj 					/* DO SOMETHING WITH URGENT!!! ### */
612*4803Swnj 				}
613*4803Swnj 				tp->rcv_urp = urgent;
614*4803Swnj 			}
6154679Swnj 		}
6164679Swnj /* eol */
617*4803Swnj 		if ((thflags&TH_EOL) &&
618*4803Swnj 		    (tp->tc_flags&TC_DROPPED_TXT) == 0 &&
619*4803Swnj 		    tp->tcb_hd.seg_prev != (struct th *)tp) {
620*4803Swnj 			/* mark last mbuf */
621*4803Swnj 			m = dtom(tp->tcb_hd.seg_prev);
622*4803Swnj 			if (m != NULL) {
623*4803Swnj 				while (m->m_next != NULL)
624*4803Swnj 					m = m->m_next;
625*4803Swnj 				m->m_act =
626*4803Swnj 				    (struct mbuf *)(m->m_off + m->m_len - 1);
627*4803Swnj 			}
6284679Swnj 		}
6294679Swnj ctlonly:
6304679Swnj /* fin */
631*4803Swnj 		if ((thflags&TH_FIN) &&
632*4803Swnj 		    (tp->tc_flags&TC_DROPPED_TXT) == 0) {
633*4803Swnj 			seq_t last;
6344679Swnj 
635*4803Swnj 			if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
636*4803Swnj 				/* do we really have fin ? */
637*4803Swnj 				last = firstempty(tp);
638*4803Swnj 				if (tp->tcb_hd.seg_prev == (struct th *)tp ||
639*4803Swnj 				    last == t_end(tp->tcb_hd.seg_prev)) {
640*4803Swnj 					tp->tc_flags |= TC_FIN_RCVD;
641*4803Swnj 					sowakeup(tp->t_socket); /* ### */
642*4803Swnj 				}
643*4803Swnj 				if ((tp->tc_flags&TC_FIN_RCVD) &&
644*4803Swnj 				    tp->rcv_nxt >= last) {
645*4803Swnj 					tp->rcv_nxt = last + 1;
646*4803Swnj 					tp->tc_flags |= TC_ACK_DUE;
647*4803Swnj 				}
648*4803Swnj 			} else
6494679Swnj 				tp->tc_flags |= TC_ACK_DUE;
650*4803Swnj 		}
6514679Swnj 	}
6524679Swnj /* respond */
6534679Swnj 	sent = 0;
6544679Swnj 	if (tp->tc_flags&TC_ACK_DUE)
6554679Swnj 		sent = tcp_sndctl(tp);
656*4803Swnj 	else if ((tp->tc_flags&TC_NEW_WINDOW))
657*4803Swnj 		if (tp->snd_nxt <= tp->snd_off + tp->t_socket->so_snd.sb_cc ||
658*4803Swnj 		    (tp->tc_flags&TC_SND_FIN))
6594679Swnj 			sent = tcp_send(tp);
6604679Swnj 
6614679Swnj /* set for retrans */
6624679Swnj 	if (!sent && tp->snd_una < tp->snd_nxt &&
6634679Swnj 	    (tp->tc_flags&TC_CANCELLED)) {
6644679Swnj 		tp->t_rexmt = tp->t_xmtime;
6654679Swnj 		tp->t_rexmttl = T_REXMTTL;
6664679Swnj 		tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst;
6674679Swnj 		tp->tc_flags &= ~TC_CANCELLED;
6684679Swnj 	}
6694690Swnj /* present data to user */
6704690Swnj 	{ register struct mbuf **mp;
671*4803Swnj 	  register struct socket *so = tp->t_socket;
6724690Swnj 	  seq_t ready;
6734601Swnj 
6744601Swnj 	/* connection must be synced and data available for user */
6754656Swnj 	if ((tp->tc_flags&TC_SYN_ACKED) == 0)
6764601Swnj 		return;
677*4803Swnj 	so = tp->t_socket;
678*4803Swnj 	mp = &so->so_rcv.sb_mb;
6794601Swnj 	while (*mp)
6804601Swnj 		mp = &(*mp)->m_next;
681*4803Swnj 	n = tp->tcb_hd.seg_next;
6824656Swnj 	/* SHOULD PACK DATA IN HERE */
6834690Swnj 	while (n != (struct th *)tp && n->t_seq < tp->rcv_nxt) {
6844690Swnj 		remque(n);
6854690Swnj 		m = dtom(n);
686*4803Swnj 		so->so_rcv.sb_cc += n->t_len;
6874690Swnj 		tp->seqcnt -= n->t_len;
6884656Swnj 		if (tp->seqcnt < 0) panic("present_data");
6894690Swnj 		n = n->t_next;
6904601Swnj 		while (m) {
6914601Swnj 			if (m->m_len == 0) {
6924692Swnj 				MFREE(m, *mp);
6934692Swnj 			} else {
6944692Swnj 				*mp = m;
6954692Swnj 				mp = &m->m_next;
6964601Swnj 			}
6974601Swnj 			m = *mp;
6984601Swnj 		}
6994601Swnj 	}
700*4803Swnj 	sowakeup(so);		/* should be macro/conditional */
7014690Swnj 	}
7024601Swnj }
703*4803Swnj 
704*4803Swnj tcp_drain()
705*4803Swnj {
706*4803Swnj 
707*4803Swnj }
708