1 /* tcp_input.c 1.41 81/12/19 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mbuf.h" 6 #include "../h/protosw.h" 7 #include "../h/socket.h" 8 #include "../h/socketvar.h" 9 #include "../net/in.h" 10 #include "../net/in_pcb.h" 11 #include "../net/in_systm.h" 12 #include "../net/if.h" 13 #include "../net/ip.h" 14 #include "../net/ip_var.h" 15 #include "../net/tcp.h" 16 #define TCPSTATES 17 #include "../net/tcp_fsm.h" 18 #include "../net/tcp_seq.h" 19 #include "../net/tcp_timer.h" 20 #include "../net/tcp_var.h" 21 #include "../net/tcpip.h" 22 #include "../errno.h" 23 24 int tcpcksum = 1; 25 struct sockaddr_in tcp_in = { AF_INET }; 26 27 /* 28 * TCP input routine, follows pages 65-76 of the 29 * protocol specification dated September, 1981 very closely. 30 */ 31 tcp_input(m0) 32 struct mbuf *m0; 33 { 34 register struct tcpiphdr *ti; 35 struct inpcb *inp; 36 register struct mbuf *m; 37 int len, tlen, off; 38 register struct tcpcb *tp; 39 register int tiflags; 40 struct socket *so; 41 int todrop, acked; 42 43 COUNT(TCP_INPUT); 44 /* 45 * Get IP and TCP header together in first mbuf. 46 * Note: IP leaves IP header in first mbuf. 47 */ 48 m = m0; 49 ti = mtod(m, struct tcpiphdr *); 50 if (((struct ip *)ti)->ip_hl > (sizeof (struct ip) >> 2)) 51 ip_stripoptions((struct ip *)ti, (struct mbuf *)0); 52 if (m->m_len < sizeof (struct tcpiphdr)) { 53 if (m_pullup(m, sizeof (struct tcpiphdr)) == 0) { 54 tcpstat.tcps_hdrops++; 55 goto drop; 56 } 57 ti = mtod(m, struct tcpiphdr *); 58 } 59 60 /* 61 * Checksum extended TCP header and data. 62 */ 63 tlen = ((struct ip *)ti)->ip_len; 64 len = sizeof (struct ip) + tlen; 65 if (tcpcksum) { 66 ti->ti_next = ti->ti_prev = 0; 67 ti->ti_x1 = 0; 68 ti->ti_len = (u_short)tlen; 69 #if vax 70 ti->ti_len = htons(ti->ti_len); 71 #endif 72 if (ti->ti_sum = in_cksum(m, len)) { 73 tcpstat.tcps_badsum++; 74 printf("tcp cksum %x\n", ti->ti_sum); 75 goto drop; 76 } 77 } 78 79 /* 80 * Check that TCP offset makes sense, 81 * process TCP options and adjust length. 82 */ 83 off = ti->ti_off << 2; 84 if (off < sizeof (struct tcphdr) || off > tlen) { 85 tcpstat.tcps_badoff++; 86 goto drop; 87 } 88 ti->ti_len = tlen - off; 89 #if 0 90 if (off > sizeof (struct tcphdr)) 91 tcp_options(ti); 92 #endif 93 tiflags = ti->ti_flags; 94 95 #if vax 96 /* 97 * Convert TCP protocol specific fields to host format. 98 */ 99 ti->ti_seq = ntohl(ti->ti_seq); 100 ti->ti_ack = ntohl(ti->ti_ack); 101 ti->ti_win = ntohs(ti->ti_win); 102 ti->ti_urp = ntohs(ti->ti_urp); 103 #endif 104 105 /* 106 * Locate pcb for segment. 107 */ 108 inp = in_pcblookup 109 (&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport); 110 111 /* 112 * If the state is CLOSED (i.e., TCB does not exist) then 113 * all data in the incoming segment is discarded. 114 */ 115 if (inp == 0) 116 goto dropwithreset; 117 tp = intotcpcb(inp); 118 if (tp == 0) 119 goto dropwithreset; 120 so = inp->inp_socket; 121 122 /* 123 * Segment received on connection. 124 * Reset idle time and keep-alive timer. 125 */ 126 tp->t_idle = 0; 127 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 128 129 /* 130 * Calculate amount of space in receive window, 131 * and then do TCP input processing. 132 */ 133 tp->rcv_wnd = sbspace(&so->so_rcv); 134 if (tp->rcv_wnd < 0) 135 tp->rcv_wnd = 0; 136 137 switch (tp->t_state) { 138 139 /* 140 * If the state is LISTEN then ignore segment if it contains an RST. 141 * If the segment contains an ACK then it is bad and send a RST. 142 * If it does not contain a SYN then it is not interesting; drop it. 143 * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial 144 * tp->iss, and send a segment: 145 * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK> 146 * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. 147 * Fill in remote peer address fields if not previously specified. 148 * Enter SYN_RECEIVED state, and process any other fields of this 149 * segment in this state. 150 */ 151 case TCPS_LISTEN: 152 if (tiflags & TH_RST) 153 goto drop; 154 if (tiflags & TH_ACK) 155 goto dropwithreset; 156 if ((tiflags & TH_SYN) == 0) 157 goto drop; 158 tcp_in.sin_addr = ti->ti_src; 159 tcp_in.sin_port = ti->ti_sport; 160 if (in_pcbconnect(inp, (struct sockaddr *)&tcp_in)) 161 goto drop; 162 tp->t_template = tcp_template(tp); 163 if (tp->t_template == 0) { 164 in_pcbdisconnect(inp); 165 goto drop; 166 } 167 tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; 168 tp->irs = ti->ti_seq; 169 tcp_sendseqinit(tp); 170 tcp_rcvseqinit(tp); 171 tp->t_state = TCPS_SYN_RECEIVED; 172 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 173 goto trimthenstep6; 174 175 /* 176 * If the state is SYN_SENT: 177 * if seg contains an ACK, but not for our SYN, drop the input. 178 * if seg contains a RST, then drop the connection. 179 * if seg does not contain SYN, then drop it. 180 * Otherwise this is an acceptable SYN segment 181 * initialize tp->rcv_nxt and tp->irs 182 * if seg contains ack then advance tp->snd_una 183 * if SYN has been acked change to ESTABLISHED else SYN_RCVD state 184 * arrange for segment to be acked (eventually) 185 * continue processing rest of data/controls, beginning with URG 186 */ 187 case TCPS_SYN_SENT: 188 if ((tiflags & TH_ACK) && 189 (SEQ_LEQ(ti->ti_ack, tp->iss) || 190 SEQ_GT(ti->ti_ack, tp->snd_max))) 191 goto dropwithreset; 192 if (tiflags & TH_RST) { 193 if (tiflags & TH_ACK) 194 tcp_drop(tp, ECONNRESET); 195 goto drop; 196 } 197 if ((tiflags & TH_SYN) == 0) 198 goto drop; 199 tp->snd_una = ti->ti_ack; 200 tp->t_timer[TCPT_REXMT] = 0; 201 tp->irs = ti->ti_seq; 202 tcp_rcvseqinit(tp); 203 tp->t_flags |= TF_ACKNOW; 204 if (SEQ_GT(tp->snd_una, tp->iss)) { 205 so->so_state |= SS_CONNAWAITING; 206 soisconnected(so); 207 tp->t_state = TCPS_ESTABLISHED; 208 (void) tcp_reass(tp, (struct tcpiphdr *)0); 209 } else 210 tp->t_state = TCPS_SYN_RECEIVED; 211 goto trimthenstep6; 212 213 trimthenstep6: 214 /* 215 * Advance ti->ti_seq to correspond to first data byte. 216 * If data, trim to stay within window, 217 * dropping FIN if necessary. 218 */ 219 ti->ti_seq++; 220 if (ti->ti_len > tp->rcv_wnd) { 221 todrop = ti->ti_len - tp->rcv_wnd; 222 m_adj(m, -todrop); 223 ti->ti_len = tp->rcv_wnd; 224 ti->ti_flags &= ~TH_FIN; 225 } 226 tp->snd_wl1 = ti->ti_seq - 1; 227 goto step6; 228 } 229 230 /* 231 * States other than LISTEN or SYN_SENT. 232 * First check that at least some bytes of segment are within 233 * receive window. 234 */ 235 if (tp->rcv_wnd == 0) { 236 /* 237 * If window is closed can only take segments at 238 * window edge, and have to drop data and PUSH from 239 * incoming segments. 240 */ 241 if (tp->rcv_nxt != ti->ti_seq) 242 goto dropafterack; 243 if (ti->ti_len > 0) { 244 ti->ti_len = 0; 245 ti->ti_flags &= ~(TH_PUSH|TH_FIN); 246 } 247 } else { 248 /* 249 * If segment begins before rcv_nxt, drop leading 250 * data (and SYN); if nothing left, just ack. 251 */ 252 if (SEQ_GT(tp->rcv_nxt, ti->ti_seq)) { 253 todrop = tp->rcv_nxt - ti->ti_seq; 254 if (tiflags & TH_SYN) { 255 ti->ti_seq++; 256 if (ti->ti_urp > 1) 257 ti->ti_urp--; 258 else 259 tiflags &= ~TH_URG; 260 todrop--; 261 } 262 if (todrop > ti->ti_len) 263 goto dropafterack; 264 m_adj(m, todrop); 265 ti->ti_seq += todrop; 266 ti->ti_len -= todrop; 267 if (ti->ti_urp > todrop) 268 ti->ti_urp -= todrop; 269 else { 270 tiflags &= ~TH_URG; 271 /* ti->ti_flags &= ~TH_URG; */ 272 /* ti->ti_urp = 0; */ 273 } 274 /* tiflags &= ~TH_SYN; */ 275 /* ti->ti_flags &= ~TH_SYN; */ 276 } 277 /* 278 * If segment ends after window, drop trailing data 279 * (and PUSH and FIN); if nothing left, just ACK. 280 */ 281 if (SEQ_GT(ti->ti_seq+ti->ti_len, tp->rcv_nxt+tp->rcv_wnd)) { 282 todrop = 283 ti->ti_seq+ti->ti_len - (tp->rcv_nxt+tp->rcv_wnd); 284 if (todrop > ti->ti_len) 285 goto dropafterack; 286 m_adj(m, -todrop); 287 ti->ti_len -= todrop; 288 ti->ti_flags &= ~(TH_PUSH|TH_FIN); 289 } 290 } 291 292 /* 293 * If the RST bit is set examine the state: 294 * SYN_RECEIVED STATE: 295 * If passive open, return to LISTEN state. 296 * If active open, inform user that connection was refused. 297 * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: 298 * Inform user that connection was reset, and close tcb. 299 * CLOSING, LAST_ACK, TIME_WAIT STATES 300 * Close the tcb. 301 */ 302 if (tiflags&TH_RST) switch (tp->t_state) { 303 304 case TCPS_SYN_RECEIVED: 305 if (inp->inp_socket->so_options & SO_ACCEPTCONN) { 306 tp->t_state = TCPS_LISTEN; 307 tp->t_timer[TCPT_KEEP] = 0; 308 (void) m_free(dtom(tp->t_template)); 309 tp->t_template = 0; 310 in_pcbdisconnect(inp); 311 goto drop; 312 } 313 tcp_drop(tp, ECONNREFUSED); 314 goto drop; 315 316 case TCPS_ESTABLISHED: 317 case TCPS_FIN_WAIT_1: 318 case TCPS_FIN_WAIT_2: 319 case TCPS_CLOSE_WAIT: 320 tcp_drop(tp, ECONNRESET); 321 goto drop; 322 323 case TCPS_CLOSING: 324 case TCPS_LAST_ACK: 325 case TCPS_TIME_WAIT: 326 tcp_close(tp); 327 goto drop; 328 } 329 330 /* 331 * If a SYN is in the window, then this is an 332 * error and we send an RST and drop the connection. 333 */ 334 if (tiflags & TH_SYN) { 335 tcp_drop(tp, ECONNRESET); 336 goto dropwithreset; 337 } 338 339 /* 340 * If the ACK bit is off we drop the segment and return. 341 */ 342 if ((tiflags & TH_ACK) == 0) 343 goto drop; 344 345 /* 346 * Ack processing. 347 */ 348 switch (tp->t_state) { 349 350 /* 351 * In SYN_RECEIVED state if the ack ACKs our SYN then enter 352 * ESTABLISHED state and continue processing, othewise 353 * send an RST. 354 */ 355 case TCPS_SYN_RECEIVED: 356 if (SEQ_GT(tp->snd_una, ti->ti_ack) || 357 SEQ_GT(ti->ti_ack, tp->snd_max)) 358 goto dropwithreset; 359 tp->snd_una++; /* SYN acked */ 360 tp->t_timer[TCPT_REXMT] = 0; 361 so->so_state |= SS_CONNAWAITING; 362 soisconnected(so); 363 tp->t_state = TCPS_ESTABLISHED; 364 (void) tcp_reass(tp, (struct tcpiphdr *)0); 365 tp->snd_wl1 = ti->ti_seq - 1; 366 /* fall into ... */ 367 368 /* 369 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range 370 * ACKs. If the ack is in the range 371 * tp->snd_una < ti->ti_ack <= tp->snd_max 372 * then advance tp->snd_una to ti->ti_ack and drop 373 * data from the retransmission queue. If this ACK reflects 374 * more up to date window information we update our window information. 375 */ 376 case TCPS_ESTABLISHED: 377 case TCPS_FIN_WAIT_1: 378 case TCPS_FIN_WAIT_2: 379 case TCPS_CLOSE_WAIT: 380 case TCPS_CLOSING: 381 case TCPS_LAST_ACK: 382 case TCPS_TIME_WAIT: 383 #define ourfinisacked (acked > 0) 384 385 if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) 386 break; 387 if (SEQ_GT(ti->ti_ack, tp->snd_max)) 388 goto dropafterack; 389 acked = ti->ti_ack - tp->snd_una; 390 if (acked >= so->so_snd.sb_cc) { 391 acked -= so->so_snd.sb_cc; 392 /* if acked > 0 our FIN is acked */ 393 if (so->so_snd.sb_cc) 394 sbdrop(&so->so_snd, so->so_snd.sb_cc); 395 tp->t_timer[TCPT_REXMT] = 0; 396 } else { 397 if (acked) 398 sbdrop(&so->so_snd, acked); 399 acked = 0; 400 TCPT_RANGESET(tp->t_timer[TCPT_REXMT], 401 tcp_beta * tp->t_srtt, TCPTV_MIN, TCPTV_MAX); 402 } 403 tp->snd_una = ti->ti_ack; 404 405 /* 406 * If transmit timer is running and timed sequence 407 * number was acked, update smoothed round trip time. 408 */ 409 if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) { 410 if (tp->t_srtt == 0) 411 tp->t_srtt = tp->t_rtt; 412 else 413 tp->t_srtt = 414 tcp_alpha * tp->t_srtt + 415 (1 - tcp_alpha) * tp->t_rtt; 416 tp->t_rtt = 0; 417 } 418 419 switch (tp->t_state) { 420 421 /* 422 * In FIN_WAIT_1 STATE in addition to the processing 423 * for the ESTABLISHED state if our FIN is now acknowledged 424 * then enter FIN_WAIT_2. 425 */ 426 case TCPS_FIN_WAIT_1: 427 if (ourfinisacked) 428 tp->t_state = TCPS_FIN_WAIT_2; 429 break; 430 431 /* 432 * In CLOSING STATE in addition to the processing for 433 * the ESTABLISHED state if the ACK acknowledges our FIN 434 * then enter the TIME-WAIT state, otherwise ignore 435 * the segment. 436 */ 437 case TCPS_CLOSING: 438 if (ourfinisacked) { 439 tp->t_state = TCPS_TIME_WAIT; 440 tcp_canceltimers(tp); 441 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 442 soisdisconnected(so); 443 } 444 break; 445 446 /* 447 * The only thing that can arrive in LAST_ACK state 448 * is an acknowledgment of our FIN. If our FIN is now 449 * acknowledged, delete the TCB, enter the closed state 450 * and return. 451 */ 452 case TCPS_LAST_ACK: 453 if (ourfinisacked) 454 tcp_close(tp); 455 goto drop; 456 457 /* 458 * In TIME_WAIT state the only thing that should arrive 459 * is a retransmission of the remote FIN. Acknowledge 460 * it and restart the finack timer. 461 */ 462 case TCPS_TIME_WAIT: 463 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 464 goto dropafterack; 465 } 466 #undef ourfinisacked 467 } 468 469 step6: 470 /* 471 * Update window information. 472 */ 473 if (SEQ_LT(tp->snd_wl1, ti->ti_seq) || 474 tp->snd_wl1==ti->ti_seq && SEQ_LEQ(tp->snd_wl2,ti->ti_seq)) { 475 tp->snd_wnd = ti->ti_win; 476 tp->snd_wl1 = ti->ti_seq; 477 tp->snd_wl2 = ti->ti_ack; 478 if (tp->snd_wnd > 0) 479 tp->t_timer[TCPT_PERSIST] = 0; 480 } 481 482 /* 483 * If an URG bit is set in the segment and is greater than the 484 * current known urgent pointer, then signal the user that the 485 * remote side has out of band data. This should not happen 486 * in CLOSE_WAIT, CLOSING, LAST-ACK or TIME_WAIT STATES since 487 * a FIN has been received from the remote side. In these states 488 * we ignore the URG. 489 */ 490 if ((tiflags & TH_URG) == 0 && TCPS_HAVERCVDFIN(tp->t_state) == 0) 491 if (SEQ_GT(ti->ti_urp, tp->rcv_up)) { 492 tp->rcv_up = ti->ti_urp; 493 #if 0 494 sohasoutofband(so); /* XXX */ 495 #endif 496 } 497 498 /* 499 * Process the segment text, merging it into the TCP sequencing queue, 500 * and arranging for acknowledgment of receipt if necessary. 501 * This process logically involves adjusting tp->rcv_wnd as data 502 * is presented to the user (this happens in tcp_usrreq.c, 503 * case PRU_RCVD). If a FIN has already been received on this 504 * connection then we just ignore the text. 505 */ 506 if ((ti->ti_len || (tiflags&TH_FIN)) && 507 TCPS_HAVERCVDFIN(tp->t_state) == 0) { 508 off += sizeof (struct ip); /* drop IP header */ 509 m->m_off += off; 510 m->m_len -= off; 511 tiflags = tcp_reass(tp, ti); 512 tp->t_flags |= TF_ACKNOW; /* XXX TF_DELACK */ 513 } else { 514 m_freem(m); 515 tiflags &= ~TH_FIN; 516 } 517 518 /* 519 * If FIN is received ACK the FIN and let the user know 520 * that the connection is closing. 521 */ 522 if (tiflags & TH_FIN) { 523 if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { 524 socantrcvmore(so); 525 tp->t_flags |= TF_ACKNOW; 526 tp->rcv_nxt++; 527 } 528 switch (tp->t_state) { 529 530 /* 531 * In SYN_RECEIVED and ESTABLISHED STATES 532 * enter the CLOSE_WAIT state. 533 */ 534 case TCPS_SYN_RECEIVED: 535 case TCPS_ESTABLISHED: 536 tp->t_state = TCPS_CLOSE_WAIT; 537 break; 538 539 /* 540 * If still in FIN_WAIT_1 STATE FIN has not been acked so 541 * enter the CLOSING state. 542 */ 543 case TCPS_FIN_WAIT_1: 544 tp->t_state = TCPS_CLOSING; 545 break; 546 547 /* 548 * In FIN_WAIT_2 state enter the TIME_WAIT state, 549 * starting the time-wait timer, turning off the other 550 * standard timers. 551 */ 552 case TCPS_FIN_WAIT_2: 553 tp->t_state = TCPS_TIME_WAIT; 554 tcp_canceltimers(tp); 555 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 556 soisdisconnected(so); 557 break; 558 559 /* 560 * In TIME_WAIT state restart the 2 MSL time_wait timer. 561 */ 562 case TCPS_TIME_WAIT: 563 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; 564 break; 565 } 566 } 567 568 /* 569 * Return any desired output. 570 */ 571 tcp_output(tp); 572 return; 573 574 dropafterack: 575 /* 576 * Generate an ACK dropping incoming segment. 577 * Make ACK reflect our state. 578 */ 579 if (tiflags & TH_RST) 580 goto drop; 581 tcp_respond(ti, tp->rcv_nxt, tp->snd_nxt, TH_ACK); 582 return; 583 584 dropwithreset: 585 /* 586 * Generate a RST, dropping incoming segment. 587 * Make ACK acceptable to originator of segment. 588 */ 589 if (tiflags & TH_RST) 590 goto drop; 591 if (tiflags & TH_ACK) 592 tcp_respond(ti, (tcp_seq)0, ti->ti_ack, TH_RST); 593 else { 594 if (tiflags & TH_SYN) 595 ti->ti_len++; 596 tcp_respond(ti, ti->ti_seq+ti->ti_len, (tcp_seq)0, TH_RST|TH_ACK); 597 } 598 return; 599 600 drop: 601 /* 602 * Drop space held by incoming segment and return. 603 */ 604 m_freem(m); 605 } 606 607 /* 608 * Insert segment ti into reassembly queue of tcp with 609 * control block tp. Return TH_FIN if reassembly now includes 610 * a segment with FIN. 611 */ 612 tcp_reass(tp, ti) 613 register struct tcpcb *tp; 614 register struct tcpiphdr *ti; 615 { 616 register struct tcpiphdr *q; 617 struct socket *so = tp->t_inpcb->inp_socket; 618 struct mbuf *m; 619 int flags; 620 COUNT(TCP_REASS); 621 622 /* 623 * Call with ti==0 after become established to 624 * force pre-ESTABLISHED data up to user socket. 625 */ 626 if (ti == 0) 627 goto present; 628 629 /* 630 * Find a segment which begins after this one does. 631 */ 632 for (q = tp->seg_next; q != (struct tcpiphdr *)tp; 633 q = (struct tcpiphdr *)q->ti_next) 634 if (SEQ_GT(q->ti_seq, ti->ti_seq)) 635 break; 636 637 /* 638 * If there is a preceding segment, it may provide some of 639 * our data already. If so, drop the data from the incoming 640 * segment. If it provides all of our data, drop us. 641 */ 642 if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { 643 register int i; 644 q = (struct tcpiphdr *)(q->ti_prev); 645 /* conversion to int (in i) handles seq wraparound */ 646 i = q->ti_seq + q->ti_len - ti->ti_seq; 647 if (i > 0) { 648 if (i >= ti->ti_len) 649 goto drop; 650 m_adj(dtom(tp), i); 651 ti->ti_len -= i; 652 ti->ti_seq += i; 653 } 654 q = (struct tcpiphdr *)(q->ti_next); 655 } 656 657 /* 658 * While we overlap succeeding segments trim them or, 659 * if they are completely covered, dequeue them. 660 */ 661 while (q != (struct tcpiphdr *)tp && 662 SEQ_GT(ti->ti_seq + ti->ti_len, q->ti_seq)) { 663 register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; 664 if (i < q->ti_len) { 665 q->ti_len -= i; 666 m_adj(dtom(q), i); 667 break; 668 } 669 q = (struct tcpiphdr *)q->ti_next; 670 m_freem(dtom(q->ti_prev)); 671 remque(q->ti_prev); 672 } 673 674 /* 675 * Stick new segment in its place. 676 */ 677 insque(ti, q->ti_prev); 678 679 present: 680 /* 681 * Present data to user, advancing rcv_nxt through 682 * completed sequence space. 683 */ 684 if (TCPS_HAVERCVDSYN(tp->t_state) == 0) 685 return (0); 686 ti = tp->seg_next; 687 if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) 688 return (0); 689 if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len) 690 return (0); 691 do { 692 tp->rcv_nxt += ti->ti_len; 693 flags = ti->ti_flags & TH_FIN; 694 remque(ti); 695 m = dtom(ti); 696 ti = (struct tcpiphdr *)ti->ti_next; 697 if (so->so_state & SS_CANTRCVMORE) 698 (void) m_freem(m); 699 else 700 sbappend(&so->so_rcv, m); 701 } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); 702 sorwakeup(so); 703 return (flags); 704 drop: 705 m_freem(dtom(ti)); 706 return (0); 707 } 708