1 /* tcp_input.c 1.3 81/10/25 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../bbnnet/net.h" 6 #include "../bbnnet/mbuf.h" 7 #include "../bbnnet/host.h" 8 #include "../bbnnet/imp.h" 9 #include "../bbnnet/ucb.h" 10 #include "../bbnnet/tcp.h" 11 #include "../bbnnet/ip.h" 12 #include "../h/dir.h" 13 #include "../h/user.h" 14 #include "../h/inode.h" 15 #include "../bbnnet/fsm.h" 16 17 extern int nosum; 18 19 tcp_input(mp) 20 register struct mbuf *mp; 21 { 22 register struct tcb *tp; 23 register struct th *n; 24 int nstate; 25 struct mbuf *m; 26 struct ucb *up; 27 int hlen, tlen, j; 28 u_short lport, fport; 29 #ifdef TCPDEBUG 30 struct tcp_debug tdb; 31 #endif 32 COUNT(TCP_INPUT); 33 34 /* 35 * Build extended tcp header 36 */ 37 n = (struct th *)((int)mp + mp->m_off); 38 tlen = ((struct ip *)n)->ip_len; 39 n->t_len = htons(tlen); 40 n->t_next = NULL; 41 n->t_prev = NULL; 42 n->t_x1 = 0; 43 lport = ntohs(n->t_dst); 44 fport = ntohs(n->t_src); 45 46 /* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */ 47 if ((hlen = n->t_off << 2) > mp->m_len) 48 { printf("tcp header overflow\n"); m_freem(mp); return; } 49 50 /* 51 * Checksum extended header and data 52 */ 53 j = n->t_sum; n->t_sum = 0; 54 if (j != cksum(mp, sizeof (struct ip) + tlen)) { 55 netstat.t_badsum++; 56 if (nosum == 0) { 57 m_freem(mp); 58 return; 59 } 60 } 61 62 /* 63 * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!) 64 */ 65 for (tp = netcb.n_tcb_head; tp != 0; tp = tp->t_tcb_next) 66 if (tp->t_lport == lport && tp->t_fport == fport && 67 tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr) 68 goto found; 69 for (tp = netcb.n_tcb_head; tp != 0; tp = tp->t_tcb_next) 70 if (tp->t_lport == lport && 71 (tp->t_fport==fport || tp->t_fport==0) && 72 (tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr || 73 tp->t_ucb->uc_host->h_addr.s_addr == 0)) 74 goto found; 75 goto notwanted; 76 found: 77 78 /* 79 * Byte swap header 80 */ 81 n->t_len = tlen - hlen; 82 n->t_src = fport; 83 n->t_dst = lport; 84 n->t_seq = ntohl(n->t_seq); 85 n->t_ackno = ntohl(n->t_ackno); 86 n->t_win = ntohs(n->t_win); 87 n->t_urp = ntohs(n->t_urp); 88 89 /* 90 * Check segment seq # and do rst processing 91 */ 92 switch (tp->t_state) { 93 94 case LISTEN: 95 if ((n->th_flags&TH_ACK) || !syn_ok(tp, n)) { 96 send_rst(tp, n); 97 goto badseg; 98 } 99 if (n->th_flags&TH_RST) 100 goto badseg; 101 goto goodseg; 102 103 case SYN_SENT: 104 if (!ack_ok(tp, n) || !syn_ok(tp, n)) { 105 send_rst(tp, n); /* 71,72,75 */ 106 goto badseg; 107 } 108 if (n->th_flags&TH_RST) { 109 t_close(tp, URESET); /* 70 */ 110 tp->t_state = CLOSED; 111 goto badseg; 112 } 113 goto goodseg; 114 115 default: 116 if ((n->th_flags&TH_RST) == 0) 117 goto common; 118 if (n->t_seq < tp->rcv_nxt) /* bad rst */ 119 goto badseg; /* 69 */ 120 switch (tp->t_state) { 121 122 case L_SYN_RCVD: 123 if (ack_ok(tp, n) == 0) 124 goto badseg; /* 69 */ 125 tp->t_rexmt = 0; 126 tp->t_rexmttl = 0; 127 tp->t_persist = 0; 128 h_free(tp->t_ucb->uc_host); 129 tp->t_state = LISTEN; 130 goto badseg; 131 132 default: 133 t_close(tp, URESET); /* 66 */ 134 tp->t_state = CLOSED; 135 goto badseg; 136 } 137 /*NOTREACHED*/ 138 139 case SYN_RCVD: 140 common: 141 if (ack_ok(tp, n) == 0) { 142 send_rst(tp, n); /* 74 */ 143 goto badseg; 144 } 145 if (syn_ok(tp, n) && n->t_seq != tp->irs) { 146 send_null(tp); /* 74 */ 147 goto badseg; 148 } 149 goto goodseg; 150 } 151 badseg: 152 m_freem(mp); 153 return; 154 155 goodseg: 156 #ifdef notdef 157 /* 158 * Defer processing if no buffer space for this connection. 159 */ 160 up = tp->t_ucb; 161 if ((int)up->uc_rcv - (int)up->uc_rsize <= 0 162 && n->t_len != 0 && netcb.n_bufs < netcb.n_lowat) { 163 mp->m_act = (struct mbuf *)0; 164 if ((m = tp->t_rcv_unack) != NULL) { 165 while (m->m_act != NULL) 166 m = m->m_act; 167 m->m_act = mp; 168 } else 169 tp->t_rcv_unack = mp; 170 171 return; 172 } 173 #endif 174 175 /* 176 * Discard ip header, and do tcp input processing. 177 */ 178 hlen += sizeof(struct ip); 179 mp->m_off += hlen; 180 mp->m_len -= hlen; 181 nstate = tp->t_state; 182 tp->tc_flags &= ~TC_NET_KEEP; 183 acounts[tp->t_state][INRECV]++; 184 #ifdef TCPDEBUG 185 if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 186 tdb_setup(tp, n, INRECV, &tdb); 187 } else 188 tdb.td_tod = 0; 189 #endif 190 switch (tp->t_state) { 191 192 case LISTEN: 193 if (!syn_ok(tp, n) || 194 ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) { 195 nstate = EFAILEC; 196 goto done; 197 } 198 tp->t_fport = n->t_src; 199 tp->t_ucb->uc_template = tcp_template(tp); 200 rcv_ctldat(tp, n, 1); 201 if (tp->tc_flags&TC_FIN_RCVD) { 202 tp->t_finack = T_2ML; /* 3 */ 203 tp->tc_flags &= ~TC_WAITED_2_ML; 204 nstate = CLOSE_WAIT; 205 } else { 206 tp->t_init = T_INIT / 2; /* 4 */ 207 nstate = L_SYN_RCVD; 208 } 209 goto done; 210 211 case SYN_SENT: 212 if (!syn_ok(tp, n)) { 213 nstate = EFAILEC; 214 goto done; 215 } 216 rcv_ctldat(tp, n, 1); 217 if (tp->tc_flags&TC_FIN_RCVD) { 218 if (n->th_flags&TH_ACK) { 219 if (n->t_ackno > tp->iss) 220 present_data(tp); /* 32 */ 221 } else { 222 tp->t_finack = T_2ML; /* 9 */ 223 tp->tc_flags &= ~TC_WAITED_2_ML; 224 } 225 nstate = CLOSE_WAIT; 226 goto done; 227 } 228 if (n->th_flags&TH_ACK) { 229 present_data(tp); /* 11 */ 230 nstate = ESTAB; 231 } else 232 nstate = SYN_RCVD; /* 8 */ 233 goto done; 234 235 case SYN_RCVD: 236 case L_SYN_RCVD: 237 if ((n->th_flags&TH_ACK) == 0 || 238 (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) { 239 nstate = EFAILEC; 240 goto done; 241 } 242 goto input; 243 244 case ESTAB: 245 case FIN_W1: 246 case FIN_W2: 247 case TIME_WAIT: 248 input: 249 rcv_ctldat(tp, n, 1); /* 39 */ 250 present_data(tp); 251 switch (tp->t_state) { 252 253 case ESTAB: 254 if (tp->tc_flags&TC_FIN_RCVD) 255 nstate = CLOSE_WAIT; 256 break; 257 258 case SYN_RCVD: 259 case L_SYN_RCVD: 260 nstate = (tp->tc_flags&TC_FIN_RCVD) ? 261 CLOSE_WAIT : ESTAB; /* 33:5 */ 262 break; 263 264 case FIN_W1: 265 j = ack_fin(tp, n); 266 if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 267 if (j) 268 nstate = FIN_W2; /* 27 */ 269 break; 270 } 271 tp->t_finack = T_2ML; 272 tp->tc_flags &= ~TC_WAITED_2_ML; 273 nstate = j ? TIME_WAIT : CLOSING1; /* 28:26 */ 274 break; 275 276 case FIN_W2: 277 if (tp->tc_flags&TC_FIN_RCVD) { 278 tp->t_finack = T_2ML; /* 29 */ 279 tp->tc_flags &= ~TC_WAITED_2_ML; 280 nstate = TIME_WAIT; 281 break; 282 } 283 break; 284 } 285 goto done; 286 287 case CLOSE_WAIT: 288 if (n->th_flags&TH_FIN) { 289 if ((n->th_flags&TH_ACK) && 290 n->t_ackno <= tp->seq_fin) { 291 rcv_ctldat(tp, n, 0); /* 30 */ 292 tp->t_finack = T_2ML; 293 tp->tc_flags &= ~TC_WAITED_2_ML; 294 } else 295 send_ctl(tp); /* 31 */ 296 goto done; 297 } 298 goto input; 299 300 case CLOSING1: 301 j = ack_fin(tp, n); 302 if (n->th_flags&TH_FIN) { 303 rcv_ctldat(tp, n, 0); 304 tp->t_finack = T_2ML; 305 tp->tc_flags &= ~TC_WAITED_2_ML; 306 if (j) 307 nstate = TIME_WAIT; /* 23 */ 308 goto done; 309 } 310 if (j) { 311 if (tp->tc_flags&TC_WAITED_2_ML) 312 if (rcv_empty(tp)) { 313 t_close(tp, UCLOSED); /* 15 */ 314 nstate = CLOSED; 315 } else 316 nstate = RCV_WAIT; /* 18 */ 317 else 318 nstate = TIME_WAIT; 319 goto done; 320 } 321 goto input; 322 323 case CLOSING2: 324 if (ack_fin(tp, n)) { 325 if (rcv_empty(tp)) { /* 16 */ 326 t_close(tp, UCLOSED); 327 nstate = CLOSED; 328 } else 329 nstate = RCV_WAIT; /* 19 */ 330 goto done; 331 } 332 if (n->th_flags&TH_FIN) { 333 send_ctl(tp); /* 31 */ 334 goto done; 335 } 336 goto input; 337 338 case RCV_WAIT: 339 if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) && 340 n->t_ackno <= tp->seq_fin) { 341 rcv_ctldat(tp, n, 0); 342 tp->t_finack = T_2ML; 343 tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 344 } 345 goto done; 346 } 347 panic("tcp_input"); 348 done: 349 350 /* 351 * Done with state*input specific processing. 352 * Form trace records, free input if not needed, 353 * and enter new state. 354 */ 355 #ifdef TCPDEBUG 356 if (tdb.td_tod) 357 tdb_stuff(&tdb, nstate); 358 #endif 359 switch (nstate) { 360 361 case EFAILEC: 362 m_freem(mp); 363 return; 364 365 default: 366 tp->t_state = nstate; 367 /* fall into ... */ 368 369 case CLOSED: 370 /* IF CLOSED CANT LOOK AT tc_flags */ 371 if ((tp->tc_flags&TC_NET_KEEP) == 0) 372 m_freem(mp); 373 return; 374 } 375 /* NOTREACHED */ 376 377 /* 378 * Unwanted packed; free everything 379 * but the header and return an rst. 380 */ 381 notwanted: 382 m_freem(mp->m_next); 383 mp->m_next = NULL; 384 mp->m_len = sizeof(struct th); 385 #define xchg(a,b) j=a; a=b; b=j 386 xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 387 #undef xchg 388 if (n->th_flags&TH_ACK) 389 n->t_seq = n->t_ackno; 390 else { 391 n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 392 n->t_seq = 0; 393 } 394 n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */ 395 n->th_flags ^= TH_ACK; 396 n->t_len = htons(TCPSIZE); 397 n->t_off = 5; 398 n->t_sum = cksum(mp, sizeof(struct th)); 399 ((struct ip *)n)->ip_len = sizeof(struct th); 400 ip_output(mp); 401 netstat.t_badsegs++; 402 } 403 404 rcv_ctldat(tp, n, dataok) 405 register struct tcb *tp; 406 register struct th *n; 407 { 408 register sent; 409 register struct ucb *up; 410 register struct mbuf *m, *mn; 411 register len; 412 COUNT(RCV_CTLDAT); 413 414 tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 415 /* syn */ 416 if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) { 417 tp->irs = n->t_seq; 418 tp->rcv_nxt = n->t_seq + 1; 419 tp->snd_wl = tp->rcv_urp = tp->irs; 420 tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 421 } 422 /* ack */ 423 if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 424 n->t_ackno > tp->snd_una) { 425 up = tp->t_ucb; 426 427 /* update snd_una and snd_nxt */ 428 tp->snd_una = n->t_ackno; 429 if (tp->snd_una > tp->snd_nxt) 430 tp->snd_nxt = tp->snd_una; 431 432 /* if timed msg acked, set retrans time value */ 433 if ((tp->tc_flags&TC_SYN_ACKED) && 434 tp->snd_una > tp->t_xmt_val) { 435 tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 436 if (tp->t_xmtime > T_REMAX) 437 tp->t_xmtime = T_REMAX; 438 } 439 440 /* remove acked data from send buf */ 441 len = tp->snd_una - tp->snd_off; 442 m = up->uc_sbuf; 443 while (len > 0 && m != NULL) 444 if (m->m_len <= len) { 445 len -= m->m_len; 446 if (m->m_off > MMAXOFF) 447 up->uc_ssize -= NMBPG; 448 MFREE(m, mn); 449 m = mn; 450 up->uc_ssize--; 451 } else { 452 m->m_len -= len; 453 m->m_off += len; 454 break; 455 } 456 up->uc_sbuf = m; 457 tp->snd_off = tp->snd_una; 458 if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 459 (tp->snd_una > tp->iss)) { 460 tp->tc_flags |= TC_SYN_ACKED; 461 tp->t_init = 0; 462 } 463 if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 464 tp->tc_flags &= ~TC_SND_FIN; 465 tp->t_rexmt = 0; 466 tp->t_rexmttl = 0; 467 tp->tc_flags |= TC_CANCELLED; 468 netwakeup(tp->t_ucb); /* wasteful */ 469 } 470 /* win */ 471 if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 472 tp->snd_wl = n->t_seq; 473 tp->snd_wnd = n->t_win; 474 tp->tc_flags |= TC_NEW_WINDOW; 475 tp->t_persist = 0; 476 } 477 if (dataok) { 478 /* text */ 479 if (n->t_len != 0) 480 rcv_text(tp, n); 481 /* urg */ 482 if (n->th_flags&TH_URG) { 483 unsigned urgent; 484 485 urgent = n->t_urp + n->t_seq; 486 if (tp->rcv_nxt < urgent) { 487 if (tp->rcv_urp <= tp->rcv_nxt) 488 to_user(tp->t_ucb, UURGENT); 489 tp->rcv_urp = urgent; 490 } 491 } 492 /* eol */ 493 if ((n->th_flags&TH_EOL) && 494 (tp->tc_flags&TC_DROPPED_TXT) == 0 && 495 tp->t_rcv_prev != (struct th *)tp) { 496 /* mark last mbuf */ 497 m = dtom(tp->t_rcv_prev); 498 if (m != NULL) { 499 while (m->m_next != NULL) 500 m = m->m_next; 501 m->m_act = 502 (struct mbuf *)(m->m_off + m->m_len - 1); 503 } 504 } 505 } 506 /* fin */ 507 if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) { 508 int last; 509 510 if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 511 /* do we really have fin ? */ 512 last = firstempty(tp); 513 if (tp->t_rcv_prev == (struct th *)tp || 514 last == t_end(tp->t_rcv_prev)) { 515 tp->tc_flags |= TC_FIN_RCVD; 516 netwakeup(tp->t_ucb); /* poke */ 517 } 518 if ((tp->tc_flags&TC_FIN_RCVD) && 519 tp->rcv_nxt >= last) { 520 tp->rcv_nxt = last + 1; /* fin seq */ 521 tp->tc_flags |= TC_ACK_DUE; 522 } 523 } else 524 tp->tc_flags |= TC_ACK_DUE; 525 } 526 527 /* respond */ 528 if (tp->tc_flags&TC_ACK_DUE) 529 sent = send_ctl(tp); 530 else if (tp->tc_flags&TC_NEW_WINDOW) 531 sent = send(tp); 532 else 533 sent = 0; 534 535 /* set for retrans */ 536 if (!sent && tp->snd_una < tp->snd_nxt && 537 (tp->tc_flags&TC_CANCELLED)) { 538 tp->t_rexmt = tp->t_xmtime; 539 tp->t_rexmttl = T_REXMTTL; 540 tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 541 tp->tc_flags &= ~TC_CANCELLED; 542 } 543 } 544 545 rcv_text(tp, t) 546 register struct tcb *tp; 547 register struct th *t; 548 { 549 register i; 550 register struct th *p, *q; 551 register struct mbuf *m, *n; 552 struct th *savq; 553 int last, j, k; 554 COUNT(RCV_TEXT); 555 556 /* throw away any data we have already received */ 557 if ((i = tp->rcv_nxt - t->t_seq) > 0) { 558 if (i >= t->t_len) 559 return; 560 t->t_seq += i; 561 t->t_len -= i; 562 m_adj(dtom(t), i); 563 } 564 565 last = t_end(t); /* last seq # in incoming seg */ 566 i = rcv_resource(tp); /* # buffers available to con */ 567 568 /* count buffers in segment */ 569 570 for (m = dtom(t), j = 0; m != NULL; m = m->m_next) 571 if (m->m_len != 0) { 572 j++; 573 if (m->m_off > MMAXOFF) 574 j += NMBPG; 575 } 576 577 /* not enough resources to process segment */ 578 579 if (j > i && netcb.n_bufs < netcb.n_lowat) { 580 581 /* if segment preceeds top of seqeuncing queue, try to take 582 buffers from bottom of queue */ 583 584 q = tp->t_rcv_next; 585 if (q != (struct th *)tp && tp->rcv_nxt < q->t_seq && 586 t->t_seq < q->t_seq) 587 588 for (k=j-i, p = tp->t_rcv_prev; k > 0 && 589 p != (struct th *)tp; k--) { 590 savq = p->t_prev; 591 tcp_deq(p); 592 i += m_freem(dtom(p)); 593 p = savq; 594 } 595 596 /* if still not enough room, drop text from end of segment */ 597 598 if (j > i) { 599 600 for (m = dtom(t); i > 0 && m != NULL; i--) 601 m = m->m_next; 602 603 while (m != NULL) { 604 t->t_len -= m->m_len; 605 last -= m->m_len; 606 m->m_len = 0; 607 m = m->m_next; 608 } 609 tp->tc_flags |= TC_DROPPED_TXT; 610 if (last < t->t_seq) 611 return; 612 } 613 } 614 615 /* merge incoming data into the sequence queue */ 616 617 q = tp->t_rcv_next; /* -> top of sequencing queue */ 618 619 /* skip frags which new doesn't overlap at end */ 620 621 while ((q != (struct th *)tp) && (t->t_seq > t_end(q))) 622 q = q->t_next; 623 624 if (q == (struct th *)tp) { /* frag at end of chain */ 625 626 if (last >= tp->rcv_nxt) { 627 tp->tc_flags |= TC_NET_KEEP; 628 tcp_enq(t, tp->t_rcv_prev); 629 } 630 631 } else { 632 633 /* frag doesn't overlap any on chain */ 634 635 if (last < q->t_seq) { 636 tp->tc_flags |= TC_NET_KEEP; 637 tcp_enq(t, q->t_prev); 638 639 /* new overlaps beginning of next frag only */ 640 641 } else if (last < t_end(q)) { 642 if ((i = last - q->t_seq + 1) < t->t_len) { 643 t->t_len -= i; 644 m_adj(dtom(t), -i); 645 tp->tc_flags |= TC_NET_KEEP; 646 tcp_enq(t, q->t_prev); 647 } 648 649 /* new overlaps end of previous frag */ 650 651 } else { 652 savq = q; 653 if (t->t_seq <= q->t_seq) { /* complete cover */ 654 savq = q->t_prev; 655 tcp_deq(q); 656 m_freem(dtom(q)); 657 658 } else { /* overlap */ 659 if ((i = t_end(q) - t->t_seq + 1) < t->t_len) { 660 t->t_seq += i; 661 t->t_len -= i; 662 m_adj(dtom(t), i); 663 } else 664 t->t_len = 0; 665 } 666 667 /* new overlaps at beginning of successor frags */ 668 669 q = savq->t_next; 670 while ((q != (struct th *)tp) && (t->t_len != 0) && 671 (q->t_seq < last)) 672 673 /* complete cover */ 674 675 if (t_end(q) <= last) { 676 p = q->t_next; 677 tcp_deq(q); 678 m_freem(dtom(q)); 679 q = p; 680 681 } else { /* overlap */ 682 683 if ((i = last - q->t_seq + 1) < t->t_len) { 684 t->t_len -= i; 685 m_adj(dtom(t), -i); 686 } else 687 t->t_len = 0; 688 break; 689 } 690 691 /* enqueue whatever is left of new before successors */ 692 693 if (t->t_len != 0) { 694 tp->tc_flags |= TC_NET_KEEP; 695 tcp_enq(t, savq); 696 } 697 } 698 } 699 700 /* set to ack completed data (no gaps) */ 701 702 tp->rcv_nxt = firstempty(tp); 703 tp->tc_flags |= TC_ACK_DUE; 704 705 #ifdef notdef 706 /* THIS CODE CANT POSSIBLY WORK */ 707 /* if any room remaining in rcv buf, take any unprocessed 708 messages and schedule for later processing */ 709 710 i = rcv_resource(tp); 711 712 while ((m = tp->t_rcv_unack) != NULL && i > 0) { 713 714 /* schedule work request */ 715 716 t = (struct th *)((int)m + m->m_off); 717 j = (t->t_off << 2) + sizeof(struct ip); 718 m->m_off += j; 719 m->m_len -= j; 720 tp->t_rcv_unack = m->m_act; 721 m->m_act = (struct mbuf *)0; 722 netstat.t_unack++; 723 tcp_work(INRECV, 0, tp, t); 724 725 /* remaining buffer space */ 726 727 for (n = m; n != NULL; n = n->m_next) 728 i--; 729 } 730 #endif 731 } 732 733 present_data(tp) 734 register struct tcb *tp; 735 { 736 register struct th *t; 737 register struct ucb *up; 738 register struct mbuf *m, **mp; 739 seq_t ready; 740 COUNT(PRESENT_DATA); 741 742 /* connection must be synced and data available for user */ 743 if (((tp->tc_flags&TC_SYN_ACKED) == 0) || 744 (t = tp->t_rcv_next) == (struct th *)tp) 745 return; 746 up = tp->t_ucb; 747 ready = firstempty(tp); /* seq # of last complete datum */ 748 mp = &up->uc_rbuf; 749 while (*mp) 750 mp = &(*mp)->m_next; 751 while (up->uc_rsize < up->uc_rcv && t != (struct th *) tp && 752 t_end(t) < ready) { 753 tcp_deq(t); 754 m = dtom(t); 755 t = t->t_next; 756 while (m) { 757 if (m->m_len == 0) { 758 m = m_free(m); 759 continue; 760 } 761 up->uc_rsize++; 762 if (m->m_off > MMAXOFF) 763 up->uc_rsize += NMBPG; 764 if (*mp == 0) 765 *mp = m; 766 mp = &m->m_next; 767 m = *mp; 768 } 769 } 770 if (up->uc_rsize != 0) 771 netwakeup(up); 772 /* 773 * Let user know about foreign tcp close if no more data. 774 */ 775 if ((tp->tc_flags&TC_FIN_RCVD) && (tp->tc_flags&TC_USR_CLOSED) == 0 && 776 rcv_empty(tp)) 777 to_user(up, UCLOSED); 778 } 779 780 #ifdef TCPDEBUG 781 tdb_setup(tp, n, input, tdp) 782 struct tcb *tp; 783 register struct th *n; 784 int input; 785 register struct tcp_debug *tdp; 786 { 787 788 tdp->td_tod = time; 789 tdp->td_tcb = tp; 790 tdp->td_old = tp->t_state; 791 tdp->td_inp = input; 792 tdp->td_tim = 0; 793 tdp->td_new = -1; 794 if (n) { 795 tdp->td_sno = n->t_seq; 796 tdp->td_ano = n->t_ackno; 797 tdp->td_wno = n->t_win; 798 tdp->td_lno = n->t_len; 799 tdp->td_flg = n->th_flags; 800 } else 801 tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno = 802 tdp->td_flg = 0; 803 } 804 805 tdb_stuff(tdp, nstate) 806 struct tcp_debug *tdp; 807 int nstate; 808 { 809 810 tdp->td_new = nstate; 811 tcp_debug[tdbx++ % TDBSIZE] = *tdp; 812 if (tcpconsdebug & 2) 813 tcp_prt(tdp); 814 } 815 #endif 816