no flipping of sport/dport
[unix-history] / usr / src / sys / netinet / tcp_input.c
CommitLineData
77b2c695 1/* tcp_input.c 1.28 81/11/23 */
87e78f19
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
dad64fdf
BJ
5#include "../h/mbuf.h"
6#include "../h/socket.h"
d52566dd 7#include "../h/socketvar.h"
d52566dd 8#include "../net/inet.h"
53a5409e 9#include "../net/inet_pcb.h"
d52566dd
BJ
10#include "../net/inet_systm.h"
11#include "../net/imp.h"
d52566dd 12#include "../net/ip.h"
eb44bfb2 13#include "../net/ip_var.h"
d52566dd
BJ
14#include "../net/tcp.h"
15#include "../net/tcp_fsm.h"
16#include "../net/tcp_var.h"
17#include "/usr/include/errno.h"
87e78f19 18
60b16fa9 19int tcpcksum = 1;
87e78f19 20
53a5409e
BJ
21tcp_drain()
22{
23 register struct inpcb *ip;
24
4ad99bae 25COUNT(TCP_DRAIN);
53a5409e
BJ
26 for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next)
27 tcp_drainunack(intotcpcb(ip));
28}
29
30tcp_drainunack(tp)
31 register struct tcpcb *tp;
32{
33 register struct mbuf *m;
34
4ad99bae 35COUNT(TCP_DRAINUNACK);
53a5409e
BJ
36 for (m = tp->seg_unack; m; m = m->m_act)
37 m_freem(m);
38 tp->seg_unack = 0;
39}
40
41tcp_ctlinput(m)
42 struct mbuf *m;
d52566dd
BJ
43{
44
4ad99bae 45COUNT(TCP_CTLINPUT);
53a5409e 46 m_freem(m);
d52566dd
BJ
47}
48
4ad99bae
BJ
49struct sockaddr_in tcp_sockaddr = { AF_INET };
50
2b4b57cd
BJ
51tcp_input(m0)
52 struct mbuf *m0;
87e78f19 53{
2b4b57cd 54 register struct tcpiphdr *ti;
53a5409e 55 struct inpcb *inp;
2b4b57cd
BJ
56 register struct mbuf *m;
57 int len, tlen, off;
58
59 register struct tcpcb *tp;
60 register int j;
61 register int tiflags;
87e78f19 62 int nstate;
d52566dd 63 struct socket *so;
87e78f19
BJ
64#ifdef TCPDEBUG
65 struct tcp_debug tdb;
66#endif
87e78f19 67
2b4b57cd 68COUNT(TCP_INPUT);
87e78f19 69 /*
2b4b57cd 70 * Get ip and tcp header together in first mbuf.
87e78f19 71 */
2b4b57cd 72 m = m0;
2b4b57cd
BJ
73 if (m->m_len < sizeof (struct tcpiphdr) &&
74 m_pullup(m, sizeof (struct tcpiphdr)) == 0) {
75 tcpstat.tcps_hdrops++;
76 goto bad;
77 }
20790db4
BJ
78 ti = mtod(m, struct tcpiphdr *);
79 if (ti->ti_len > sizeof (struct ip))
80 ip_stripoptions((struct ip *)ti, (char *)0);
87e78f19 81
2b4b57cd
BJ
82 /*
83 * Checksum extended tcp header and data.
84 */
85 tlen = ((struct ip *)ti)->ip_len;
86 len = sizeof (struct ip) + tlen;
60b16fa9 87 if (tcpcksum) {
2b4b57cd
BJ
88 ti->ti_next = ti->ti_prev = 0;
89 ti->ti_x1 = 0;
4ad99bae 90 ti->ti_len = htons((u_short)tlen);
77b2c695 91 if ((ti->ti_sum = inet_cksum(m, len)) != 0xffff) {
2b4b57cd
BJ
92 tcpstat.tcps_badsum++;
93 printf("tcp cksum %x\ti", ti->ti_sum);
94 goto bad;
87e78f19
BJ
95 }
96 }
97
98 /*
2b4b57cd
BJ
99 * Check that tcp offset makes sense,
100 * process tcp options and adjust length.
87e78f19 101 */
2b4b57cd
BJ
102 off = ti->ti_off << 2;
103 if (off < sizeof (struct tcphdr) || off > ti->ti_len) {
104 tcpstat.tcps_badoff++;
105 goto bad;
106 }
107 ti->ti_len = tlen - off;
108 /* PROCESS OPTIONS */
109
110 /*
2b4b57cd
BJ
111 * Locate pcb for segment.
112 */
4ad99bae 113 inp = in_pcblookup(&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport);
53a5409e
BJ
114 if (inp == 0)
115 goto notwanted;
2b4b57cd
BJ
116 tp = intotcpcb(inp); /* ??? */
117 if (tp == 0) /* ??? */
118 goto notwanted; /* ??? */
87e78f19
BJ
119
120 /*
2b4b57cd 121 * Convert tcp protocol specific fields to host format.
87e78f19 122 */
2b4b57cd
BJ
123 ti->ti_seq = ntohl(ti->ti_seq);
124 ti->ti_ackno = ntohl((n_long)ti->ti_ackno);
125 ti->ti_win = ntohs(ti->ti_win);
126 ti->ti_urp = ntohs(ti->ti_urp);
87e78f19
BJ
127
128 /*
129 * Check segment seq # and do rst processing
130 */
2b4b57cd 131 tiflags = ti->ti_flags;
87e78f19
BJ
132 switch (tp->t_state) {
133
134 case LISTEN:
2b4b57cd
BJ
135 if ((tiflags&TH_ACK) || (tiflags&TH_SYN) == 0) {
136 tcp_sndrst(tp, ti);
137 goto bad;
87e78f19 138 }
2b4b57cd
BJ
139 if (tiflags&TH_RST)
140 goto bad;
141 goto good;
87e78f19
BJ
142
143 case SYN_SENT:
2b4b57cd
BJ
144 if (!ack_ok(tp, ti) || (tiflags&TH_SYN) == 0) {
145 tcp_sndrst(tp, ti); /* 71,72,75 */
146 goto bad;
87e78f19 147 }
2b4b57cd 148 if (tiflags&TH_RST) {
d52566dd
BJ
149 tcp_error(tp, ENETRESET);
150 tcp_detach(tp); /* 70 */
87e78f19 151 tp->t_state = CLOSED;
2b4b57cd 152 goto bad;
87e78f19 153 }
2b4b57cd 154 goto good;
87e78f19
BJ
155
156 default:
2b4b57cd 157 if ((tiflags&TH_RST) == 0)
87e78f19 158 goto common;
2b4b57cd
BJ
159 if (ti->ti_seq < tp->rcv_nxt) /* bad rst */
160 goto bad; /* 69 */
87e78f19
BJ
161 switch (tp->t_state) {
162
163 case L_SYN_RCVD:
2b4b57cd
BJ
164 if (ack_ok(tp, ti) == 0)
165 goto bad; /* 69 */
87e78f19
BJ
166 tp->t_rexmt = 0;
167 tp->t_rexmttl = 0;
168 tp->t_persist = 0;
4ad99bae 169 inp->inp_faddr.s_addr = 0;
87e78f19 170 tp->t_state = LISTEN;
2b4b57cd 171 goto bad;
87e78f19
BJ
172
173 default:
d52566dd
BJ
174 tcp_error(tp, ENETRESET);
175 tcp_detach(tp); /* 66 */
87e78f19 176 tp->t_state = CLOSED;
2b4b57cd 177 goto bad;
87e78f19
BJ
178 }
179 /*NOTREACHED*/
180
181 case SYN_RCVD:
182common:
2b4b57cd
BJ
183 if (ack_ok(tp, ti) == 0) {
184 tcp_sndrst(tp, ti); /* 74 */
185 goto bad;
87e78f19 186 }
2b4b57cd 187 if ((tiflags&TH_SYN) == 0 && ti->ti_seq != tp->irs) {
60b16fa9 188 tcp_sndnull(tp); /* 74 */
2b4b57cd 189 goto bad;
87e78f19 190 }
2b4b57cd 191 goto good;
87e78f19 192 }
2b4b57cd
BJ
193bad:
194 m_freem(m);
87e78f19
BJ
195 return;
196
2b4b57cd 197good:
87e78f19
BJ
198 /*
199 * Defer processing if no buffer space for this connection.
200 */
53a5409e 201 so = inp->inp_socket;
d52566dd 202 if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat &&
2b4b57cd 203 ti->ti_len != 0 && mbstat.m_bufs < mbstat.m_lowat) {
d52566dd 204/*
2b4b57cd 205 m->m_act = (struct mbuf *)0;
d52566dd 206 if ((m = tp->seg_unack) != NULL) {
87e78f19
BJ
207 while (m->m_act != NULL)
208 m = m->m_act;
2b4b57cd 209 m->m_act = m0;
87e78f19 210 } else
2b4b57cd 211 tp->seg_unack = m0;
d52566dd 212*/
2b4b57cd 213 m_freem(m0);
87e78f19
BJ
214 return;
215 }
87e78f19
BJ
216
217 /*
218 * Discard ip header, and do tcp input processing.
219 */
2b4b57cd
BJ
220 off += sizeof (struct ip);
221 m->m_off += off;
222 m->m_len -= off;
87e78f19
BJ
223 nstate = tp->t_state;
224 tp->tc_flags &= ~TC_NET_KEEP;
a1de2d92 225#ifdef KPROF
87e78f19 226 acounts[tp->t_state][INRECV]++;
a1de2d92 227#endif
87e78f19 228#ifdef TCPDEBUG
d52566dd 229 if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) {
2b4b57cd 230 tdb_setup(tp, ti, INRECV, &tdb);
87e78f19
BJ
231 } else
232 tdb.td_tod = 0;
233#endif
234 switch (tp->t_state) {
235
236 case LISTEN:
4ad99bae
BJ
237 tcp_sockaddr.sin_addr = ti->ti_src;
238 tcp_sockaddr.sin_port = ti->ti_sport;
239 if ((tiflags&TH_SYN) == 0 || in_pcbsetpeer(inp, &tcp_sockaddr)) {
87e78f19
BJ
240 nstate = EFAILEC;
241 goto done;
242 }
e1506033 243 tp->t_template = tcp_template(tp);
2b4b57cd 244 tcp_ctldat(tp, ti, 1);
87e78f19
BJ
245 if (tp->tc_flags&TC_FIN_RCVD) {
246 tp->t_finack = T_2ML; /* 3 */
247 tp->tc_flags &= ~TC_WAITED_2_ML;
248 nstate = CLOSE_WAIT;
249 } else {
53a5409e 250 tp->t_init = T_INIT / 2; /* 4 */
87e78f19
BJ
251 nstate = L_SYN_RCVD;
252 }
253 goto done;
254
255 case SYN_SENT:
2b4b57cd 256 if (!syn_ok(tp, ti)) {
87e78f19
BJ
257 nstate = EFAILEC;
258 goto done;
259 }
2b4b57cd 260 tcp_ctldat(tp, ti, 1);
87e78f19 261 if (tp->tc_flags&TC_FIN_RCVD) {
2b4b57cd 262 if ((tiflags&TH_ACK) == 0) {
87e78f19
BJ
263 tp->t_finack = T_2ML; /* 9 */
264 tp->tc_flags &= ~TC_WAITED_2_ML;
265 }
266 nstate = CLOSE_WAIT;
267 goto done;
268 }
2b4b57cd 269 nstate = (tiflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */
87e78f19
BJ
270 goto done;
271
272 case SYN_RCVD:
273 case L_SYN_RCVD:
2b4b57cd
BJ
274 if ((tiflags&TH_ACK) == 0 ||
275 (tiflags&TH_ACK) && ti->ti_ackno <= tp->iss) {
87e78f19
BJ
276 nstate = EFAILEC;
277 goto done;
278 }
279 goto input;
280
281 case ESTAB:
282 case FIN_W1:
283 case FIN_W2:
284 case TIME_WAIT:
285input:
2b4b57cd 286 tcp_ctldat(tp, ti, 1); /* 39 */
87e78f19
BJ
287 switch (tp->t_state) {
288
289 case ESTAB:
290 if (tp->tc_flags&TC_FIN_RCVD)
291 nstate = CLOSE_WAIT;
292 break;
293
294 case SYN_RCVD:
295 case L_SYN_RCVD:
296 nstate = (tp->tc_flags&TC_FIN_RCVD) ?
297 CLOSE_WAIT : ESTAB; /* 33:5 */
298 break;
299
300 case FIN_W1:
2b4b57cd 301 j = ack_fin(tp, ti);
87e78f19
BJ
302 if ((tp->tc_flags & TC_FIN_RCVD) == 0) {
303 if (j)
304 nstate = FIN_W2; /* 27 */
305 break;
306 }
307 tp->t_finack = T_2ML;
308 tp->tc_flags &= ~TC_WAITED_2_ML;
9c5022e3 309 nstate = j ? TIME_WAIT : CLOSING; /* 28:26 */
87e78f19
BJ
310 break;
311
312 case FIN_W2:
313 if (tp->tc_flags&TC_FIN_RCVD) {
314 tp->t_finack = T_2ML; /* 29 */
315 tp->tc_flags &= ~TC_WAITED_2_ML;
316 nstate = TIME_WAIT;
317 break;
318 }
319 break;
320 }
321 goto done;
322
323 case CLOSE_WAIT:
2b4b57cd
BJ
324 if (tiflags&TH_FIN) {
325 if ((tiflags&TH_ACK) &&
326 ti->ti_ackno <= tp->seq_fin) {
327 tcp_ctldat(tp, ti, 0); /* 30 */
87e78f19
BJ
328 tp->t_finack = T_2ML;
329 tp->tc_flags &= ~TC_WAITED_2_ML;
330 } else
cdad2eb1 331 (void) tcp_sndctl(tp); /* 31 */
87e78f19
BJ
332 goto done;
333 }
334 goto input;
335
9c5022e3 336 case CLOSING:
2b4b57cd
BJ
337 j = ack_fin(tp, ti);
338 if (tiflags&TH_FIN) {
339 tcp_ctldat(tp, ti, 0);
87e78f19
BJ
340 tp->t_finack = T_2ML;
341 tp->tc_flags &= ~TC_WAITED_2_ML;
342 if (j)
343 nstate = TIME_WAIT; /* 23 */
344 goto done;
345 }
346 if (j) {
347 if (tp->tc_flags&TC_WAITED_2_ML)
348 if (rcv_empty(tp)) {
53a5409e 349 sorwakeup(inp->inp_socket);
d52566dd 350 nstate = CLOSED; /* 15 */
87e78f19
BJ
351 } else
352 nstate = RCV_WAIT; /* 18 */
353 else
354 nstate = TIME_WAIT;
355 goto done;
356 }
357 goto input;
358
9c5022e3 359 case LAST_ACK:
2b4b57cd 360 if (ack_fin(tp, ti)) {
53a5409e
BJ
361 if (rcv_empty(tp)) { /* 16 */
362 sorwakeup(inp->inp_socket);
87e78f19
BJ
363 nstate = CLOSED;
364 } else
365 nstate = RCV_WAIT; /* 19 */
366 goto done;
367 }
2b4b57cd 368 if (tiflags&TH_FIN) {
cdad2eb1 369 (void) tcp_sndctl(tp); /* 31 */
87e78f19
BJ
370 goto done;
371 }
372 goto input;
373
374 case RCV_WAIT:
2b4b57cd
BJ
375 if ((tiflags&TH_FIN) && (tiflags&TH_ACK) &&
376 ti->ti_ackno <= tp->seq_fin) {
377 tcp_ctldat(tp, ti, 0);
87e78f19
BJ
378 tp->t_finack = T_2ML;
379 tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */
380 }
381 goto done;
382 }
383 panic("tcp_input");
384done:
385
386 /*
387 * Done with state*input specific processing.
388 * Form trace records, free input if not needed,
389 * and enter new state.
390 */
391#ifdef TCPDEBUG
8f5a3361
BJ
392 if (tdb.td_tod)
393 tdb_stuff(&tdb, nstate);
87e78f19
BJ
394#endif
395 switch (nstate) {
396
397 case EFAILEC:
2b4b57cd 398 m_freem(m);
87e78f19
BJ
399 return;
400
401 default:
402 tp->t_state = nstate;
403 /* fall into ... */
404
405 case CLOSED:
406 /* IF CLOSED CANT LOOK AT tc_flags */
2b4b57cd
BJ
407 if ((tp->tc_flags&TC_NET_KEEP) == 0) {
408 register struct mbuf *n;
2a4921ab 409 /* inline expansion of m_freem */
2b4b57cd 410 while (m) {
4ad99bae 411 MFREE(m, n);
2b4b57cd 412 m = n;
2a4921ab 413 }
2b4b57cd 414 }
87e78f19
BJ
415 return;
416 }
417 /* NOTREACHED */
418
419 /*
420 * Unwanted packed; free everything
421 * but the header and return an rst.
422 */
423notwanted:
2b4b57cd
BJ
424 m_freem(m->m_next);
425 m->m_next = NULL;
426 m->m_len = sizeof(struct tcpiphdr);
87e78f19 427#define xchg(a,b) j=a; a=b; b=j
2b4b57cd
BJ
428 xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr);
429 xchg(ti->ti_dport, ti->ti_sport);
87e78f19 430#undef xchg
2b4b57cd
BJ
431 if (tiflags&TH_ACK)
432 ti->ti_seq = ti->ti_ackno;
87e78f19 433 else {
4ad99bae 434 ti->ti_ackno = htonl((unsigned)(ntohl(ti->ti_seq) + ti->ti_len));
2b4b57cd 435 ti->ti_seq = 0;
87e78f19 436 }
2b4b57cd
BJ
437 ti->ti_flags = ((tiflags & TH_ACK) ? 0 : TH_ACK) | TH_RST;
438 ti->ti_len = htons(TCPSIZE);
439 ti->ti_off = 5;
440 ti->ti_sum = inet_cksum(m, sizeof(struct tcpiphdr));
441 ((struct ip *)ti)->ip_len = sizeof(struct tcpiphdr);
77b2c695 442 ((struct ip *)ti)->ip_ttl = MAXTTL;
2b4b57cd
BJ
443 ip_output(m);
444 tcpstat.tcps_badsegs++;
87e78f19
BJ
445}
446
53a5409e
BJ
447tcp_ctldat(tp, n0, dataok)
448 register struct tcpcb *tp;
449 struct tcpiphdr *n0;
450 int dataok;
87e78f19 451{
2b4b57cd
BJ
452 register struct tcpiphdr *ti = n0;
453 register int tiflags = ti->ti_flags;
53a5409e 454 struct socket *so = tp->t_inpcb->inp_socket;
2b4b57cd 455 seq_t past = ti->ti_seq + ti->ti_len;
53a5409e 456 seq_t urgent;
60b16fa9
BJ
457 int sent;
458COUNT(TCP_CTLDAT);
87e78f19 459
2b4b57cd
BJ
460 if (tiflags & TH_URG)
461 urgent = ti->ti_seq + ti->ti_urp;
53a5409e 462 tp->tc_flags &= ~(TC_ACK_DUE|TC_NEW_WINDOW);
87e78f19 463/* syn */
2b4b57cd
BJ
464 if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (tiflags&TH_SYN)) {
465 tp->irs = ti->ti_seq;
466 tp->rcv_nxt = ti->ti_seq + 1;
87e78f19
BJ
467 tp->snd_wl = tp->rcv_urp = tp->irs;
468 tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE);
469 }
470/* ack */
2b4b57cd
BJ
471 if ((tiflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) &&
472 ti->ti_ackno > tp->snd_una) {
53a5409e
BJ
473 /*
474 * Reflect newly acknowledged data.
475 */
2b4b57cd 476 tp->snd_una = ti->ti_ackno;
87e78f19
BJ
477 if (tp->snd_una > tp->snd_nxt)
478 tp->snd_nxt = tp->snd_una;
53a5409e
BJ
479
480 /*
481 * If timed msg acked, update retransmit time value.
482 */
87e78f19
BJ
483 if ((tp->tc_flags&TC_SYN_ACKED) &&
484 tp->snd_una > tp->t_xmt_val) {
53a5409e 485 /* NEED SMOOTHING HERE */
87e78f19
BJ
486 tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT);
487 if (tp->t_xmtime > T_REMAX)
488 tp->t_xmtime = T_REMAX;
489 }
490
53a5409e
BJ
491 /*
492 * Remove acked data from send buf
493 */
cdad2eb1 494 sbdrop(&so->so_snd, (int)(tp->snd_una - tp->snd_off));
87e78f19
BJ
495 tp->snd_off = tp->snd_una;
496 if ((tp->tc_flags&TC_SYN_ACKED) == 0 &&
497 (tp->snd_una > tp->iss)) {
498 tp->tc_flags |= TC_SYN_ACKED;
499 tp->t_init = 0;
500 }
501 if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin)
502 tp->tc_flags &= ~TC_SND_FIN;
503 tp->t_rexmt = 0;
504 tp->t_rexmttl = 0;
505 tp->tc_flags |= TC_CANCELLED;
53a5409e 506 sowwakeup(tp->t_inpcb->inp_socket);
87e78f19
BJ
507 }
508/* win */
2b4b57cd
BJ
509 if ((tp->tc_flags & TC_SYN_RCVD) && ti->ti_seq >= tp->snd_wl) {
510 tp->snd_wl = ti->ti_seq;
511 tp->snd_wnd = ti->ti_win;
87e78f19
BJ
512 tp->tc_flags |= TC_NEW_WINDOW;
513 tp->t_persist = 0;
514 }
87e78f19 515/* text */
2b4b57cd 516 if (dataok && ti->ti_len) {
cdad2eb1 517 register struct tcpiphdr *q;
53a5409e 518 int overage;
87e78f19 519
53a5409e 520/* eol */
2b4b57cd 521 if ((tiflags&TH_EOL)) {
53a5409e 522 register struct mbuf *m;
2b4b57cd 523 for (m = dtom(ti); m->m_next; m = m->m_next)
53a5409e
BJ
524 ;
525 m->m_act = (struct mbuf *)(mtod(m, caddr_t) - 1);
526 }
87e78f19 527
53a5409e
BJ
528/* text */
529 /*
530 * Discard duplicate data already passed to user.
531 */
2b4b57cd
BJ
532 if (SEQ_LT(ti->ti_seq, tp->rcv_nxt)) {
533 register int i = tp->rcv_nxt - ti->ti_seq;
534 if (i >= ti->ti_len)
53a5409e 535 goto notext;
2b4b57cd
BJ
536 ti->ti_seq += i;
537 ti->ti_len -= i;
538 m_adj(dtom(ti), i);
87e78f19 539 }
87e78f19 540
53a5409e
BJ
541 /*
542 * Find a segment which begins after this one does.
543 */
544 for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
eb44bfb2 545 q = (struct tcpiphdr *)q->ti_next)
2b4b57cd 546 if (SEQ_GT(q->ti_seq, ti->ti_seq))
53a5409e 547 break;
87e78f19 548
53a5409e
BJ
549 /*
550 * If there is a preceding segment, it may provide some of
551 * our data already. If so, drop the data from the incoming
552 * segment. If it provides all of our data, drop us.
553 */
eb44bfb2
BJ
554 if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
555 register int i;
556 q = (struct tcpiphdr *)(q->ti_prev);
53a5409e 557 /* conversion to int (in i) handles seq wraparound */
2b4b57cd 558 i = q->ti_seq + q->ti_len - ti->ti_seq;
53a5409e 559 if (i > 0) {
2b4b57cd 560 if (i >= ti->ti_len)
53a5409e
BJ
561 goto notext;
562 /* w/o setting TC_NET_KEEP */
563 m_adj(dtom(tp), i);
2b4b57cd
BJ
564 ti->ti_len -= i;
565 ti->ti_seq += i;
53a5409e 566 }
eb44bfb2 567 q = (struct tcpiphdr *)(q->ti_next);
53a5409e 568 }
87e78f19 569
53a5409e
BJ
570 /*
571 * While we overlap succeeding segments trim them or,
572 * if they are completely covered, dequeue them.
573 */
574 while (q != (struct tcpiphdr *)tp &&
2b4b57cd
BJ
575 SEQ_GT(ti->ti_seq + ti->ti_len, q->ti_seq)) {
576 register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
eb44bfb2
BJ
577 if (i < q->ti_len) {
578 q->ti_len -= i;
53a5409e 579 m_adj(dtom(q), i);
ac5e71a1 580 break;
53a5409e 581 }
eb44bfb2
BJ
582 q = (struct tcpiphdr *)q->ti_next;
583 m_freem(dtom(q->ti_prev));
584 remque(q->ti_prev);
ac5e71a1 585 }
87e78f19 586
53a5409e
BJ
587 /*
588 * Stick new segment in its place.
589 */
2b4b57cd
BJ
590 insque(ti, q->ti_prev);
591 tp->seqcnt += ti->ti_len;
d52566dd 592
53a5409e
BJ
593 /*
594 * Calculate available space and discard segments for
595 * which there is too much.
596 */
597 overage =
598 (so->so_rcv.sb_cc /*XXX+tp->rcv_seqcnt*/) - so->so_rcv.sb_hiwat;
599 if (overage > 0) {
600 q = tp->seg_prev;
601 for (;;) {
eb44bfb2 602 register int i = MIN(q->ti_len, overage);
53a5409e 603 overage -= i;
eb44bfb2 604 q->ti_len -= i;
cdad2eb1 605 m_adj(dtom(q), -i);
eb44bfb2 606 if (q->ti_len)
53a5409e 607 break;
2b4b57cd 608 if (q == ti)
53a5409e 609 panic("tcp_text dropall");
eb44bfb2
BJ
610 q = (struct tcpiphdr *)q->ti_prev;
611 remque(q->ti_next);
d52566dd 612 }
60b16fa9 613 }
53a5409e
BJ
614
615 /*
616 * Advance rcv_next through newly completed sequence space.
617 */
2b4b57cd
BJ
618 while (ti->ti_seq == tp->rcv_nxt) {
619 tp->rcv_nxt += ti->ti_len;
620 ti = (struct tcpiphdr *)ti->ti_next;
621 if (ti == (struct tcpiphdr *)tp)
53a5409e
BJ
622 break;
623 }
624/* urg */
2b4b57cd 625 if (tiflags&TH_URG) {
53a5409e
BJ
626 /* ... */
627 if (SEQ_GT(urgent, tp->rcv_urp))
628 tp->rcv_urp = urgent;
60b16fa9 629 }
53a5409e
BJ
630 tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP);
631 }
632notext:
60b16fa9 633/* fin */
2b4b57cd 634 if ((tiflags&TH_FIN) && past == tp->rcv_nxt) {
53a5409e
BJ
635 if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
636 tp->tc_flags |= TC_FIN_RCVD;
637 sorwakeup(so);
638 tp->rcv_nxt++;
d52566dd 639 }
53a5409e 640 tp->tc_flags |= TC_ACK_DUE;
60b16fa9 641 }
60b16fa9
BJ
642/* respond */
643 sent = 0;
644 if (tp->tc_flags&TC_ACK_DUE)
645 sent = tcp_sndctl(tp);
d52566dd 646 else if ((tp->tc_flags&TC_NEW_WINDOW))
53a5409e 647 if (tp->snd_nxt <= tp->snd_off + so->so_snd.sb_cc ||
d52566dd 648 (tp->tc_flags&TC_SND_FIN))
60b16fa9 649 sent = tcp_send(tp);
60b16fa9
BJ
650
651/* set for retrans */
652 if (!sent && tp->snd_una < tp->snd_nxt &&
653 (tp->tc_flags&TC_CANCELLED)) {
654 tp->t_rexmt = tp->t_xmtime;
655 tp->t_rexmttl = T_REXMTTL;
656 tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst;
657 tp->tc_flags &= ~TC_CANCELLED;
658 }
2a4921ab 659/* present data to user */
2de49286 660 if ((tp->tc_flags&TC_SYN_ACKED) == 0)
87e78f19 661 return;
2b4b57cd
BJ
662 ti = tp->seg_next;
663 while (ti != (struct tcpiphdr *)tp && ti->ti_seq < tp->rcv_nxt) {
664 remque(ti);
665 sbappend(&so->so_rcv, dtom(ti));
666 tp->seqcnt -= ti->ti_len;
53a5409e
BJ
667 if (tp->seqcnt < 0)
668 panic("tcp_input present");
2b4b57cd 669 ti = (struct tcpiphdr *)ti->ti_next;
2a4921ab 670 }
53a5409e 671 sorwakeup(so);
d52566dd 672}