intermediate version, still in debugging phase
[unix-history] / usr / src / sys / netinet / tcp_input.c
CommitLineData
27d029ad 1/* tcp_input.c 1.90 83/03/25 */
87e78f19
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
dad64fdf 5#include "../h/mbuf.h"
8a13b737 6#include "../h/protosw.h"
dad64fdf 7#include "../h/socket.h"
d52566dd 8#include "../h/socketvar.h"
f4d55810
SL
9#include "../h/errno.h"
10
11#include "../net/if.h"
c124e997 12#include "../net/route.h"
f4d55810
SL
13
14#include "../netinet/in.h"
fcfe450e
BJ
15#include "../netinet/in_pcb.h"
16#include "../netinet/in_systm.h"
fcfe450e
BJ
17#include "../netinet/ip.h"
18#include "../netinet/ip_var.h"
19#include "../netinet/tcp.h"
20#include "../netinet/tcp_fsm.h"
21#include "../netinet/tcp_seq.h"
22#include "../netinet/tcp_timer.h"
23#include "../netinet/tcp_var.h"
24#include "../netinet/tcpip.h"
25#include "../netinet/tcp_debug.h"
87e78f19 26
22856bb8 27int tcpprintfs = 0;
60b16fa9 28int tcpcksum = 1;
4b935108 29struct tcpiphdr tcp_saveti;
8b5a83bb 30extern tcpnodelack;
87e78f19 31
4b935108 32struct tcpcb *tcp_newtcpcb();
2ff61f9d
BJ
33/*
34 * TCP input routine, follows pages 65-76 of the
35 * protocol specification dated September, 1981 very closely.
36 */
2b4b57cd
BJ
37tcp_input(m0)
38 struct mbuf *m0;
87e78f19 39{
2b4b57cd 40 register struct tcpiphdr *ti;
53a5409e 41 struct inpcb *inp;
2b4b57cd 42 register struct mbuf *m;
8b5a83bb 43 struct mbuf *om = 0;
2b4b57cd 44 int len, tlen, off;
8e65fd66 45 register struct tcpcb *tp = 0;
2b4b57cd 46 register int tiflags;
d52566dd 47 struct socket *so;
f1b2fa5b 48 int todrop, acked;
4b935108 49 short ostate;
ebcadd38 50 struct in_addr laddr;
7aa16f99 51 int dropsocket = 0;
87e78f19
BJ
52
53 /*
4aed14e3
BJ
54 * Get IP and TCP header together in first mbuf.
55 * Note: IP leaves IP header in first mbuf.
87e78f19 56 */
2b4b57cd 57 m = m0;
20790db4 58 ti = mtod(m, struct tcpiphdr *);
4aed14e3 59 if (((struct ip *)ti)->ip_hl > (sizeof (struct ip) >> 2))
d63599ac 60 ip_stripoptions((struct ip *)ti, (struct mbuf *)0);
6703c41f
BJ
61 if (m->m_off > MMAXOFF || m->m_len < sizeof (struct tcpiphdr)) {
62 if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) {
8a13b737 63 tcpstat.tcps_hdrops++;
6703c41f 64 return;
8a13b737
BJ
65 }
66 ti = mtod(m, struct tcpiphdr *);
67 }
87e78f19 68
2b4b57cd 69 /*
4aed14e3 70 * Checksum extended TCP header and data.
2b4b57cd
BJ
71 */
72 tlen = ((struct ip *)ti)->ip_len;
73 len = sizeof (struct ip) + tlen;
60b16fa9 74 if (tcpcksum) {
2b4b57cd
BJ
75 ti->ti_next = ti->ti_prev = 0;
76 ti->ti_x1 = 0;
ac83b17a 77 ti->ti_len = (u_short)tlen;
668cc26d 78 ti->ti_len = htons((u_short)ti->ti_len);
4b6b94ca 79 if (ti->ti_sum = in_cksum(m, len)) {
2b4b57cd 80 tcpstat.tcps_badsum++;
1e977657
BJ
81 if (tcpprintfs)
82 printf("tcp cksum %x\n", ti->ti_sum);
8a13b737 83 goto drop;
87e78f19
BJ
84 }
85 }
86
87 /*
4aed14e3 88 * Check that TCP offset makes sense,
8b5a83bb 89 * pull out TCP options and adjust length.
87e78f19 90 */
2b4b57cd 91 off = ti->ti_off << 2;
4b6b94ca 92 if (off < sizeof (struct tcphdr) || off > tlen) {
2b4b57cd 93 tcpstat.tcps_badoff++;
8a13b737 94 goto drop;
2b4b57cd 95 }
1e977657
BJ
96 tlen -= off;
97 ti->ti_len = tlen;
8b5a83bb
BJ
98 if (off > sizeof (struct tcphdr)) {
99 if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) {
100 tcpstat.tcps_hdrops++;
101 goto drop;
102 }
103 ti = mtod(m, struct tcpiphdr *);
cce93e4b 104 om = m_get(M_DONTWAIT, MT_DATA);
8b5a83bb
BJ
105 if (om == 0)
106 goto drop;
8b5a83bb
BJ
107 om->m_len = off - sizeof (struct tcphdr);
108 { caddr_t op = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
668cc26d 109 bcopy(op, mtod(om, caddr_t), (unsigned)om->m_len);
8b5a83bb 110 m->m_len -= om->m_len;
668cc26d
SL
111 bcopy(op+om->m_len, op,
112 (unsigned)(m->m_len-sizeof (struct tcpiphdr)));
8b5a83bb
BJ
113 }
114 }
2ff61f9d 115 tiflags = ti->ti_flags;
2b4b57cd 116
795e0416 117 /*
1e977657 118 * Drop TCP and IP headers.
795e0416
BJ
119 */
120 off += sizeof (struct ip);
121 m->m_off += off;
122 m->m_len -= off;
123
8a13b737 124 /*
4aed14e3 125 * Convert TCP protocol specific fields to host format.
8a13b737
BJ
126 */
127 ti->ti_seq = ntohl(ti->ti_seq);
128 ti->ti_ack = ntohl(ti->ti_ack);
129 ti->ti_win = ntohs(ti->ti_win);
130 ti->ti_urp = ntohs(ti->ti_urp);
131
2b4b57cd 132 /*
8075bb0e 133 * Locate pcb for segment.
2b4b57cd 134 */
2ff61f9d 135 inp = in_pcblookup
ebcadd38
BJ
136 (&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport,
137 INPLOOKUP_WILDCARD);
2ff61f9d
BJ
138
139 /*
140 * If the state is CLOSED (i.e., TCB does not exist) then
4aed14e3 141 * all data in the incoming segment is discarded.
2ff61f9d 142 */
22856bb8 143 if (inp == 0)
8a13b737 144 goto dropwithreset;
2ff61f9d 145 tp = intotcpcb(inp);
22856bb8 146 if (tp == 0)
8a13b737 147 goto dropwithreset;
f1b2fa5b 148 so = inp->inp_socket;
4b935108
BJ
149 if (so->so_options & SO_DEBUG) {
150 ostate = tp->t_state;
151 tcp_saveti = *ti;
152 }
ebf42a75
BJ
153 if (so->so_options & SO_ACCEPTCONN) {
154 so = sonewconn(so);
155 if (so == 0)
156 goto drop;
7aa16f99
SL
157 /*
158 * This is ugly, but ....
159 *
160 * Mark socket as temporary until we're
161 * committed to keeping it. The code at
162 * ``drop'' and ``dropwithreset'' check the
163 * flag dropsocket to see if the temporary
164 * socket created here should be discarded.
165 * We mark the socket as discardable until
166 * we're committed to it below in TCPS_LISTEN.
167 */
168 dropsocket++;
ebf42a75
BJ
169 inp = (struct inpcb *)so->so_pcb;
170 inp->inp_laddr = ti->ti_dst;
171 inp->inp_lport = ti->ti_dport;
172 tp = intotcpcb(inp);
173 tp->t_state = TCPS_LISTEN;
174 }
87e78f19 175
405c9168
BJ
176 /*
177 * Segment received on connection.
178 * Reset idle time and keep-alive timer.
179 */
180 tp->t_idle = 0;
181 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
182
8b5a83bb
BJ
183 /*
184 * Process options.
185 */
186 if (om) {
187 tcp_dooptions(tp, om);
188 om = 0;
189 }
190
87e78f19 191 /*
8a13b737
BJ
192 * Calculate amount of space in receive window,
193 * and then do TCP input processing.
87e78f19 194 */
8a13b737 195 tp->rcv_wnd = sbspace(&so->so_rcv);
4b6b94ca
BJ
196 if (tp->rcv_wnd < 0)
197 tp->rcv_wnd = 0;
2ff61f9d 198
87e78f19
BJ
199 switch (tp->t_state) {
200
2ff61f9d
BJ
201 /*
202 * If the state is LISTEN then ignore segment if it contains an RST.
203 * If the segment contains an ACK then it is bad and send a RST.
204 * If it does not contain a SYN then it is not interesting; drop it.
8a13b737 205 * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial
2ff61f9d 206 * tp->iss, and send a segment:
8a13b737 207 * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>
2ff61f9d
BJ
208 * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.
209 * Fill in remote peer address fields if not previously specified.
210 * Enter SYN_RECEIVED state, and process any other fields of this
4aed14e3 211 * segment in this state.
2ff61f9d 212 */
8075bb0e 213 case TCPS_LISTEN: {
789d2a39 214 struct mbuf *am;
8075bb0e
BJ
215 register struct sockaddr_in *sin;
216
2ff61f9d
BJ
217 if (tiflags & TH_RST)
218 goto drop;
22856bb8 219 if (tiflags & TH_ACK)
8a13b737 220 goto dropwithreset;
22856bb8 221 if ((tiflags & TH_SYN) == 0)
2ff61f9d 222 goto drop;
789d2a39
SL
223 am = m_get(M_DONTWAIT, MT_SONAME);
224 if (am == NULL)
225 goto drop;
226 am->m_len = sizeof (struct sockaddr_in);
a8d3bf7f 227 sin = mtod(am, struct sockaddr_in *);
8075bb0e
BJ
228 sin->sin_family = AF_INET;
229 sin->sin_addr = ti->ti_src;
230 sin->sin_port = ti->ti_sport;
ebcadd38 231 laddr = inp->inp_laddr;
789d2a39 232 if (inp->inp_laddr.s_addr == INADDR_ANY)
ebcadd38 233 inp->inp_laddr = ti->ti_dst;
a8d3bf7f 234 if (in_pcbconnect(inp, am)) {
ebcadd38 235 inp->inp_laddr = laddr;
5a1f132a 236 (void) m_free(am);
4aed14e3 237 goto drop;
ebcadd38 238 }
5a1f132a 239 (void) m_free(am);
4aed14e3
BJ
240 tp->t_template = tcp_template(tp);
241 if (tp->t_template == 0) {
242 in_pcbdisconnect(inp);
ebcadd38 243 inp->inp_laddr = laddr;
93f92b1d 244 tp = 0;
4aed14e3
BJ
245 goto drop;
246 }
8a13b737 247 tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
2ff61f9d 248 tp->irs = ti->ti_seq;
8a13b737
BJ
249 tcp_sendseqinit(tp);
250 tcp_rcvseqinit(tp);
2ff61f9d 251 tp->t_state = TCPS_SYN_RECEIVED;
4aed14e3 252 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
7aa16f99 253 dropsocket = 0; /* committed to socket */
8a13b737 254 goto trimthenstep6;
8075bb0e 255 }
87e78f19 256
2ff61f9d
BJ
257 /*
258 * If the state is SYN_SENT:
259 * if seg contains an ACK, but not for our SYN, drop the input.
260 * if seg contains a RST, then drop the connection.
261 * if seg does not contain SYN, then drop it.
262 * Otherwise this is an acceptable SYN segment
263 * initialize tp->rcv_nxt and tp->irs
264 * if seg contains ack then advance tp->snd_una
265 * if SYN has been acked change to ESTABLISHED else SYN_RCVD state
266 * arrange for segment to be acked (eventually)
267 * continue processing rest of data/controls, beginning with URG
268 */
269 case TCPS_SYN_SENT:
270 if ((tiflags & TH_ACK) &&
22856bb8
BJ
271/* this should be SEQ_LT; is SEQ_LEQ for BBN vax TCP only */
272 (SEQ_LT(ti->ti_ack, tp->iss) ||
4b6b94ca 273 SEQ_GT(ti->ti_ack, tp->snd_max)))
8a13b737 274 goto dropwithreset;
2ff61f9d 275 if (tiflags & TH_RST) {
0e3936fa
SL
276 if (tiflags & TH_ACK)
277 tp = tcp_drop(tp, ECONNREFUSED);
2ff61f9d 278 goto drop;
87e78f19 279 }
2ff61f9d
BJ
280 if ((tiflags & TH_SYN) == 0)
281 goto drop;
4b6b94ca 282 tp->snd_una = ti->ti_ack;
b8977237
BJ
283 if (SEQ_LT(tp->snd_nxt, tp->snd_una))
284 tp->snd_nxt = tp->snd_una;
4aed14e3 285 tp->t_timer[TCPT_REXMT] = 0;
2ff61f9d 286 tp->irs = ti->ti_seq;
8a13b737
BJ
287 tcp_rcvseqinit(tp);
288 tp->t_flags |= TF_ACKNOW;
405c9168 289 if (SEQ_GT(tp->snd_una, tp->iss)) {
4aed14e3 290 soisconnected(so);
2ff61f9d 291 tp->t_state = TCPS_ESTABLISHED;
405c9168
BJ
292 (void) tcp_reass(tp, (struct tcpiphdr *)0);
293 } else
8a13b737
BJ
294 tp->t_state = TCPS_SYN_RECEIVED;
295 goto trimthenstep6;
296
297trimthenstep6:
298 /*
4b6b94ca 299 * Advance ti->ti_seq to correspond to first data byte.
8a13b737
BJ
300 * If data, trim to stay within window,
301 * dropping FIN if necessary.
302 */
4b6b94ca 303 ti->ti_seq++;
8a13b737
BJ
304 if (ti->ti_len > tp->rcv_wnd) {
305 todrop = ti->ti_len - tp->rcv_wnd;
306 m_adj(m, -todrop);
307 ti->ti_len = tp->rcv_wnd;
308 ti->ti_flags &= ~TH_FIN;
87e78f19 309 }
e832edbc 310 tp->snd_wl1 = ti->ti_seq - 1;
8a13b737 311 goto step6;
2ff61f9d 312 }
87e78f19 313
2ff61f9d
BJ
314 /*
315 * States other than LISTEN or SYN_SENT.
316 * First check that at least some bytes of segment are within
317 * receive window.
318 */
319 if (tp->rcv_wnd == 0) {
320 /*
321 * If window is closed can only take segments at
4b6b94ca 322 * window edge, and have to drop data and PUSH from
2ff61f9d
BJ
323 * incoming segments.
324 */
22856bb8 325 if (tp->rcv_nxt != ti->ti_seq)
2ff61f9d 326 goto dropafterack;
8a13b737 327 if (ti->ti_len > 0) {
fd5dc5f0 328 m_adj(m, ti->ti_len);
8a13b737
BJ
329 ti->ti_len = 0;
330 ti->ti_flags &= ~(TH_PUSH|TH_FIN);
87e78f19 331 }
2ff61f9d
BJ
332 } else {
333 /*
4b6b94ca 334 * If segment begins before rcv_nxt, drop leading
2ff61f9d
BJ
335 * data (and SYN); if nothing left, just ack.
336 */
fd5dc5f0
BJ
337 todrop = tp->rcv_nxt - ti->ti_seq;
338 if (todrop > 0) {
8a13b737 339 if (tiflags & TH_SYN) {
22856bb8 340 tiflags &= ~TH_SYN;
fd5dc5f0 341 ti->ti_flags &= ~TH_SYN;
8a13b737
BJ
342 ti->ti_seq++;
343 if (ti->ti_urp > 1)
344 ti->ti_urp--;
345 else
346 tiflags &= ~TH_URG;
347 todrop--;
348 }
1e977657
BJ
349 if (todrop > ti->ti_len ||
350 todrop == ti->ti_len && (tiflags&TH_FIN) == 0)
2ff61f9d
BJ
351 goto dropafterack;
352 m_adj(m, todrop);
353 ti->ti_seq += todrop;
354 ti->ti_len -= todrop;
8a13b737
BJ
355 if (ti->ti_urp > todrop)
356 ti->ti_urp -= todrop;
357 else {
358 tiflags &= ~TH_URG;
fd5dc5f0
BJ
359 ti->ti_flags &= ~TH_URG;
360 ti->ti_urp = 0;
8a13b737 361 }
2ff61f9d
BJ
362 }
363 /*
364 * If segment ends after window, drop trailing data
8a13b737 365 * (and PUSH and FIN); if nothing left, just ACK.
2ff61f9d 366 */
fd5dc5f0
BJ
367 todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
368 if (todrop > 0) {
1e977657 369 if (todrop >= ti->ti_len)
2ff61f9d
BJ
370 goto dropafterack;
371 m_adj(m, -todrop);
372 ti->ti_len -= todrop;
8a13b737 373 ti->ti_flags &= ~(TH_PUSH|TH_FIN);
87e78f19 374 }
87e78f19 375 }
87e78f19 376
dd020fc8 377 /*
6fed2989 378 * If data is received on a connection after the
dd020fc8
BJ
379 * user processes are gone, then RST the other end.
380 */
0e3936fa 381 if ((so->so_state & SS_NOFDREF) && tp->t_state > TCPS_CLOSE_WAIT &&
c9f1e449 382 ti->ti_len) {
0e3936fa 383 tp = tcp_close(tp);
dd020fc8
BJ
384 goto dropwithreset;
385 }
386
87e78f19 387 /*
2ff61f9d
BJ
388 * If the RST bit is set examine the state:
389 * SYN_RECEIVED STATE:
390 * If passive open, return to LISTEN state.
391 * If active open, inform user that connection was refused.
392 * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
393 * Inform user that connection was reset, and close tcb.
394 * CLOSING, LAST_ACK, TIME_WAIT STATES
395 * Close the tcb.
87e78f19 396 */
2ff61f9d 397 if (tiflags&TH_RST) switch (tp->t_state) {
4b935108 398
2ff61f9d 399 case TCPS_SYN_RECEIVED:
0e3936fa 400 tp = tcp_drop(tp, ECONNREFUSED);
2ff61f9d
BJ
401 goto drop;
402
403 case TCPS_ESTABLISHED:
404 case TCPS_FIN_WAIT_1:
405 case TCPS_FIN_WAIT_2:
406 case TCPS_CLOSE_WAIT:
0e3936fa 407 tp = tcp_drop(tp, ECONNRESET);
2ff61f9d
BJ
408 goto drop;
409
410 case TCPS_CLOSING:
411 case TCPS_LAST_ACK:
412 case TCPS_TIME_WAIT:
0e3936fa 413 tp = tcp_close(tp);
2ff61f9d 414 goto drop;
87e78f19 415 }
87e78f19
BJ
416
417 /*
2ff61f9d
BJ
418 * If a SYN is in the window, then this is an
419 * error and we send an RST and drop the connection.
420 */
421 if (tiflags & TH_SYN) {
0e3936fa 422 tp = tcp_drop(tp, ECONNRESET);
8a13b737 423 goto dropwithreset;
2ff61f9d
BJ
424 }
425
426 /*
427 * If the ACK bit is off we drop the segment and return.
428 */
8a13b737 429 if ((tiflags & TH_ACK) == 0)
2ff61f9d
BJ
430 goto drop;
431
432 /*
433 * Ack processing.
87e78f19 434 */
87e78f19
BJ
435 switch (tp->t_state) {
436
2ff61f9d
BJ
437 /*
438 * In SYN_RECEIVED state if the ack ACKs our SYN then enter
439 * ESTABLISHED state and continue processing, othewise
440 * send an RST.
441 */
442 case TCPS_SYN_RECEIVED:
8a13b737 443 if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
4b6b94ca 444 SEQ_GT(ti->ti_ack, tp->snd_max))
8a13b737 445 goto dropwithreset;
4aed14e3 446 tp->snd_una++; /* SYN acked */
b8977237
BJ
447 if (SEQ_LT(tp->snd_nxt, tp->snd_una))
448 tp->snd_nxt = tp->snd_una;
4aed14e3 449 tp->t_timer[TCPT_REXMT] = 0;
8a13b737
BJ
450 soisconnected(so);
451 tp->t_state = TCPS_ESTABLISHED;
405c9168 452 (void) tcp_reass(tp, (struct tcpiphdr *)0);
4aed14e3 453 tp->snd_wl1 = ti->ti_seq - 1;
8a13b737 454 /* fall into ... */
87e78f19 455
2ff61f9d
BJ
456 /*
457 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
458 * ACKs. If the ack is in the range
4b6b94ca 459 * tp->snd_una < ti->ti_ack <= tp->snd_max
2ff61f9d
BJ
460 * then advance tp->snd_una to ti->ti_ack and drop
461 * data from the retransmission queue. If this ACK reflects
462 * more up to date window information we update our window information.
463 */
464 case TCPS_ESTABLISHED:
465 case TCPS_FIN_WAIT_1:
466 case TCPS_FIN_WAIT_2:
467 case TCPS_CLOSE_WAIT:
468 case TCPS_CLOSING:
4aed14e3
BJ
469 case TCPS_LAST_ACK:
470 case TCPS_TIME_WAIT:
8a13b737
BJ
471#define ourfinisacked (acked > 0)
472
4aed14e3 473 if (SEQ_LEQ(ti->ti_ack, tp->snd_una))
2ff61f9d 474 break;
22856bb8 475 if (SEQ_GT(ti->ti_ack, tp->snd_max))
2ff61f9d 476 goto dropafterack;
8a13b737 477 acked = ti->ti_ack - tp->snd_una;
dd020fc8
BJ
478
479 /*
480 * If transmit timer is running and timed sequence
481 * number was acked, update smoothed round trip time.
482 */
483 if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) {
484 if (tp->t_srtt == 0)
485 tp->t_srtt = tp->t_rtt;
486 else
487 tp->t_srtt =
488 tcp_alpha * tp->t_srtt +
489 (1 - tcp_alpha) * tp->t_rtt;
dd020fc8
BJ
490 tp->t_rtt = 0;
491 }
492
6703c41f 493 if (ti->ti_ack == tp->snd_max)
4aed14e3 494 tp->t_timer[TCPT_REXMT] = 0;
6703c41f 495 else {
4aed14e3
BJ
496 TCPT_RANGESET(tp->t_timer[TCPT_REXMT],
497 tcp_beta * tp->t_srtt, TCPTV_MIN, TCPTV_MAX);
dd020fc8 498 tp->t_rtt = 1;
22856bb8 499 tp->t_rxtshift = 0;
8a13b737 500 }
6703c41f
BJ
501 if (acked > so->so_snd.sb_cc) {
502 sbdrop(&so->so_snd, so->so_snd.sb_cc);
503 tp->snd_wnd -= so->so_snd.sb_cc;
504 } else {
668cc26d 505 sbdrop(&so->so_snd, acked);
6703c41f
BJ
506 tp->snd_wnd -= acked;
507 acked = 0;
508 }
5744ed2b 509 if ((so->so_snd.sb_flags & SB_WAIT) || so->so_snd.sb_sel)
22856bb8 510 sowwakeup(so);
4b6b94ca 511 tp->snd_una = ti->ti_ack;
b8977237
BJ
512 if (SEQ_LT(tp->snd_nxt, tp->snd_una))
513 tp->snd_nxt = tp->snd_una;
405c9168 514
87e78f19
BJ
515 switch (tp->t_state) {
516
2ff61f9d
BJ
517 /*
518 * In FIN_WAIT_1 STATE in addition to the processing
519 * for the ESTABLISHED state if our FIN is now acknowledged
8a13b737 520 * then enter FIN_WAIT_2.
2ff61f9d
BJ
521 */
522 case TCPS_FIN_WAIT_1:
fdae4427
BJ
523 if (ourfinisacked) {
524 /*
525 * If we can't receive any more
526 * data, then closing user can proceed.
527 */
528 if (so->so_state & SS_CANTRCVMORE)
529 soisdisconnected(so);
8a13b737 530 tp->t_state = TCPS_FIN_WAIT_2;
fdae4427 531 }
87e78f19
BJ
532 break;
533
2ff61f9d
BJ
534 /*
535 * In CLOSING STATE in addition to the processing for
536 * the ESTABLISHED state if the ACK acknowledges our FIN
537 * then enter the TIME-WAIT state, otherwise ignore
538 * the segment.
539 */
540 case TCPS_CLOSING:
4aed14e3 541 if (ourfinisacked) {
2ff61f9d 542 tp->t_state = TCPS_TIME_WAIT;
4aed14e3
BJ
543 tcp_canceltimers(tp);
544 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
545 soisdisconnected(so);
546 }
547 break;
87e78f19 548
2ff61f9d 549 /*
8a13b737
BJ
550 * The only thing that can arrive in LAST_ACK state
551 * is an acknowledgment of our FIN. If our FIN is now
552 * acknowledged, delete the TCB, enter the closed state
553 * and return.
2ff61f9d
BJ
554 */
555 case TCPS_LAST_ACK:
0e3936fa
SL
556 if (ourfinisacked)
557 tp = tcp_close(tp);
2ff61f9d 558 goto drop;
87e78f19 559
2ff61f9d
BJ
560 /*
561 * In TIME_WAIT state the only thing that should arrive
562 * is a retransmission of the remote FIN. Acknowledge
563 * it and restart the finack timer.
564 */
565 case TCPS_TIME_WAIT:
405c9168 566 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
2ff61f9d 567 goto dropafterack;
87e78f19 568 }
8a13b737
BJ
569#undef ourfinisacked
570 }
87e78f19 571
2ff61f9d 572step6:
4aed14e3
BJ
573 /*
574 * Update window information.
575 */
22856bb8 576 if (SEQ_LT(tp->snd_wl1, ti->ti_seq) || tp->snd_wl1 == ti->ti_seq &&
8e65fd66 577 (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
22856bb8 578 tp->snd_wl2 == ti->ti_ack && ti->ti_win > tp->snd_wnd)) {
4aed14e3
BJ
579 tp->snd_wnd = ti->ti_win;
580 tp->snd_wl1 = ti->ti_seq;
581 tp->snd_wl2 = ti->ti_ack;
a8d3bf7f 582 if (tp->snd_wnd != 0)
4aed14e3
BJ
583 tp->t_timer[TCPT_PERSIST] = 0;
584 }
4aed14e3 585
2ff61f9d 586 /*
b2db9217 587 * Process segments with URG.
2ff61f9d 588 */
9c811062
BJ
589 if ((tiflags & TH_URG) && ti->ti_urp &&
590 TCPS_HAVERCVDFIN(tp->t_state) == 0) {
b2db9217
BJ
591 /*
592 * If this segment advances the known urgent pointer,
593 * then mark the data stream. This should not happen
594 * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
595 * a FIN has been received from the remote side.
596 * In these states we ignore the URG.
597 */
598 if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {
599 tp->rcv_up = ti->ti_seq + ti->ti_urp;
600 so->so_oobmark = so->so_rcv.sb_cc +
601 (tp->rcv_up - tp->rcv_nxt) - 1;
602 if (so->so_oobmark == 0)
603 so->so_state |= SS_RCVATMARK;
77a4e3ca 604 sohasoutofband(so);
b2db9217
BJ
605 tp->t_oobflags &= ~TCPOOB_HAVEDATA;
606 }
607 /*
608 * Remove out of band data so doesn't get presented to user.
609 * This can happen independent of advancing the URG pointer,
610 * but if two URG's are pending at once, some out-of-band
611 * data may creep in... ick.
612 */
ebf42a75 613 if (ti->ti_urp <= ti->ti_len)
b2db9217 614 tcp_pulloutofband(so, ti);
5e74df82 615 }
87e78f19
BJ
616
617 /*
2ff61f9d
BJ
618 * Process the segment text, merging it into the TCP sequencing queue,
619 * and arranging for acknowledgment of receipt if necessary.
620 * This process logically involves adjusting tp->rcv_wnd as data
621 * is presented to the user (this happens in tcp_usrreq.c,
622 * case PRU_RCVD). If a FIN has already been received on this
623 * connection then we just ignore the text.
87e78f19 624 */
e832edbc
BJ
625 if ((ti->ti_len || (tiflags&TH_FIN)) &&
626 TCPS_HAVERCVDFIN(tp->t_state) == 0) {
2ff61f9d 627 tiflags = tcp_reass(tp, ti);
8b5a83bb
BJ
628 if (tcpnodelack == 0)
629 tp->t_flags |= TF_DELACK;
630 else
631 tp->t_flags |= TF_ACKNOW;
4aed14e3 632 } else {
2b4b57cd 633 m_freem(m);
e832edbc 634 tiflags &= ~TH_FIN;
4aed14e3 635 }
87e78f19
BJ
636
637 /*
e832edbc
BJ
638 * If FIN is received ACK the FIN and let the user know
639 * that the connection is closing.
87e78f19 640 */
e832edbc 641 if (tiflags & TH_FIN) {
4aed14e3
BJ
642 if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {
643 socantrcvmore(so);
644 tp->t_flags |= TF_ACKNOW;
645 tp->rcv_nxt++;
646 }
2ff61f9d 647 switch (tp->t_state) {
87e78f19 648
2ff61f9d
BJ
649 /*
650 * In SYN_RECEIVED and ESTABLISHED STATES
651 * enter the CLOSE_WAIT state.
53a5409e 652 */
2ff61f9d
BJ
653 case TCPS_SYN_RECEIVED:
654 case TCPS_ESTABLISHED:
655 tp->t_state = TCPS_CLOSE_WAIT;
656 break;
53a5409e 657
2ff61f9d 658 /*
8a13b737
BJ
659 * If still in FIN_WAIT_1 STATE FIN has not been acked so
660 * enter the CLOSING state.
53a5409e 661 */
2ff61f9d 662 case TCPS_FIN_WAIT_1:
8a13b737 663 tp->t_state = TCPS_CLOSING;
2ff61f9d 664 break;
87e78f19 665
2ff61f9d
BJ
666 /*
667 * In FIN_WAIT_2 state enter the TIME_WAIT state,
668 * starting the time-wait timer, turning off the other
669 * standard timers.
670 */
671 case TCPS_FIN_WAIT_2:
4aed14e3 672 tp->t_state = TCPS_TIME_WAIT;
a6503abf 673 tcp_canceltimers(tp);
405c9168 674 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
4aed14e3 675 soisdisconnected(so);
2ff61f9d
BJ
676 break;
677
53a5409e 678 /*
2ff61f9d 679 * In TIME_WAIT state restart the 2 MSL time_wait timer.
53a5409e 680 */
2ff61f9d 681 case TCPS_TIME_WAIT:
405c9168 682 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
2ff61f9d 683 break;
8a13b737 684 }
87e78f19 685 }
4b935108
BJ
686 if (so->so_options & SO_DEBUG)
687 tcp_trace(TA_INPUT, ostate, tp, &tcp_saveti, 0);
8a13b737
BJ
688
689 /*
690 * Return any desired output.
691 */
668cc26d 692 (void) tcp_output(tp);
2ff61f9d 693 return;
8a13b737 694
2ff61f9d 695dropafterack:
8a13b737 696 /*
1e977657
BJ
697 * Generate an ACK dropping incoming segment if it occupies
698 * sequence space, where the ACK reflects our state.
8a13b737 699 */
1e977657
BJ
700 if ((tiflags&TH_RST) ||
701 tlen == 0 && (tiflags&(TH_SYN|TH_FIN)) == 0)
8a13b737 702 goto drop;
f3cdd721
BJ
703 if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
704 tcp_trace(TA_RESPOND, ostate, tp, &tcp_saveti, 0);
8e65fd66 705 tcp_respond(tp, ti, tp->rcv_nxt, tp->snd_nxt, TH_ACK);
4b6b94ca 706 return;
8a13b737
BJ
707
708dropwithreset:
8b5a83bb 709 if (om)
668cc26d 710 (void) m_free(om);
8a13b737 711 /*
4aed14e3 712 * Generate a RST, dropping incoming segment.
8a13b737
BJ
713 * Make ACK acceptable to originator of segment.
714 */
715 if (tiflags & TH_RST)
716 goto drop;
717 if (tiflags & TH_ACK)
8e65fd66 718 tcp_respond(tp, ti, (tcp_seq)0, ti->ti_ack, TH_RST);
8a13b737
BJ
719 else {
720 if (tiflags & TH_SYN)
721 ti->ti_len++;
1e977657
BJ
722 tcp_respond(tp, ti, ti->ti_seq+ti->ti_len, (tcp_seq)0,
723 TH_RST|TH_ACK);
8a13b737 724 }
7aa16f99
SL
725 /* destroy temporarily created socket */
726 if (dropsocket)
727 (void) soabort(so);
4b6b94ca 728 return;
8a13b737 729
2ff61f9d 730drop:
8a13b737
BJ
731 /*
732 * Drop space held by incoming segment and return.
733 */
f3cdd721
BJ
734 if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
735 tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0);
2ff61f9d 736 m_freem(m);
7aa16f99
SL
737 /* destroy temporarily created socket */
738 if (dropsocket)
739 (void) soabort(so);
4b935108 740 return;
2ff61f9d
BJ
741}
742
8b5a83bb
BJ
743tcp_dooptions(tp, om)
744 struct tcpcb *tp;
745 struct mbuf *om;
5e74df82 746{
8b5a83bb
BJ
747 register u_char *cp;
748 int opt, optlen, cnt;
749
750 cp = mtod(om, u_char *);
751 cnt = om->m_len;
752 for (; cnt > 0; cnt -= optlen, cp += optlen) {
753 opt = cp[0];
754 if (opt == TCPOPT_EOL)
755 break;
756 if (opt == TCPOPT_NOP)
757 optlen = 1;
758 else
759 optlen = cp[1];
760 switch (opt) {
761
762 default:
763 break;
764
765 case TCPOPT_MAXSEG:
766 if (optlen != 4)
767 continue;
768 tp->t_maxseg = *(u_short *)(cp + 2);
668cc26d 769 tp->t_maxseg = ntohs((u_short)tp->t_maxseg);
8b5a83bb 770 break;
8b5a83bb 771 }
5e74df82 772 }
668cc26d 773 (void) m_free(om);
5e74df82
BJ
774}
775
b2db9217
BJ
776/*
777 * Pull out of band byte out of a segment so
778 * it doesn't appear in the user's data queue.
779 * It is still reflected in the segment length for
780 * sequencing purposes.
781 */
782tcp_pulloutofband(so, ti)
783 struct socket *so;
784 struct tcpiphdr *ti;
785{
786 register struct mbuf *m;
1acff8ec 787 int cnt = ti->ti_urp - 1;
b2db9217
BJ
788
789 m = dtom(ti);
790 while (cnt >= 0) {
791 if (m->m_len > cnt) {
792 char *cp = mtod(m, caddr_t) + cnt;
793 struct tcpcb *tp = sototcpcb(so);
794
795 tp->t_iobc = *cp;
796 tp->t_oobflags |= TCPOOB_HAVEDATA;
668cc26d 797 bcopy(cp+1, cp, (unsigned)(m->m_len - cnt - 1));
b2db9217
BJ
798 m->m_len--;
799 return;
800 }
801 cnt -= m->m_len;
802 m = m->m_next;
803 if (m == 0)
804 break;
805 }
806 panic("tcp_pulloutofband");
807}
808
2ff61f9d
BJ
809/*
810 * Insert segment ti into reassembly queue of tcp with
811 * control block tp. Return TH_FIN if reassembly now includes
812 * a segment with FIN.
813 */
f1b2fa5b 814tcp_reass(tp, ti)
2ff61f9d
BJ
815 register struct tcpcb *tp;
816 register struct tcpiphdr *ti;
2ff61f9d
BJ
817{
818 register struct tcpiphdr *q;
8a13b737 819 struct socket *so = tp->t_inpcb->inp_socket;
e832edbc
BJ
820 struct mbuf *m;
821 int flags;
2ff61f9d
BJ
822
823 /*
405c9168
BJ
824 * Call with ti==0 after become established to
825 * force pre-ESTABLISHED data up to user socket.
2ff61f9d 826 */
405c9168 827 if (ti == 0)
2ff61f9d 828 goto present;
87e78f19 829
2ff61f9d
BJ
830 /*
831 * Find a segment which begins after this one does.
832 */
833 for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
834 q = (struct tcpiphdr *)q->ti_next)
835 if (SEQ_GT(q->ti_seq, ti->ti_seq))
836 break;
837
838 /*
839 * If there is a preceding segment, it may provide some of
840 * our data already. If so, drop the data from the incoming
841 * segment. If it provides all of our data, drop us.
842 */
843 if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
844 register int i;
fd5dc5f0 845 q = (struct tcpiphdr *)q->ti_prev;
2ff61f9d
BJ
846 /* conversion to int (in i) handles seq wraparound */
847 i = q->ti_seq + q->ti_len - ti->ti_seq;
848 if (i > 0) {
2b4b57cd 849 if (i >= ti->ti_len)
2ff61f9d 850 goto drop;
4ab1a5c3 851 m_adj(dtom(ti), i);
2b4b57cd 852 ti->ti_len -= i;
2ff61f9d 853 ti->ti_seq += i;
53a5409e 854 }
2ff61f9d
BJ
855 q = (struct tcpiphdr *)(q->ti_next);
856 }
87e78f19 857
2ff61f9d
BJ
858 /*
859 * While we overlap succeeding segments trim them or,
860 * if they are completely covered, dequeue them.
861 */
fd5dc5f0 862 while (q != (struct tcpiphdr *)tp) {
2ff61f9d 863 register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
fd5dc5f0
BJ
864 if (i <= 0)
865 break;
2ff61f9d 866 if (i < q->ti_len) {
fd5dc5f0 867 q->ti_seq += i;
2ff61f9d
BJ
868 q->ti_len -= i;
869 m_adj(dtom(q), i);
870 break;
ac5e71a1 871 }
2ff61f9d 872 q = (struct tcpiphdr *)q->ti_next;
473a17a5 873 m = dtom(q->ti_prev);
2ff61f9d 874 remque(q->ti_prev);
473a17a5 875 m_freem(m);
2ff61f9d 876 }
87e78f19 877
2ff61f9d
BJ
878 /*
879 * Stick new segment in its place.
880 */
881 insque(ti, q->ti_prev);
2ff61f9d 882
2ff61f9d
BJ
883present:
884 /*
4aed14e3
BJ
885 * Present data to user, advancing rcv_nxt through
886 * completed sequence space.
2ff61f9d 887 */
e832edbc 888 if (TCPS_HAVERCVDSYN(tp->t_state) == 0)
4aed14e3 889 return (0);
2b4b57cd 890 ti = tp->seg_next;
e832edbc
BJ
891 if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
892 return (0);
893 if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)
894 return (0);
895 do {
4aed14e3
BJ
896 tp->rcv_nxt += ti->ti_len;
897 flags = ti->ti_flags & TH_FIN;
2b4b57cd 898 remque(ti);
e832edbc 899 m = dtom(ti);
2b4b57cd 900 ti = (struct tcpiphdr *)ti->ti_next;
e832edbc 901 if (so->so_state & SS_CANTRCVMORE)
668cc26d 902 m_freem(m);
789d2a39 903 else
e832edbc
BJ
904 sbappend(&so->so_rcv, m);
905 } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
906 sorwakeup(so);
2ff61f9d
BJ
907 return (flags);
908drop:
909 m_freem(dtom(ti));
e832edbc 910 return (0);
d52566dd 911}