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