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