1 /* tcp_input.c 1.1 81/10/24 */ 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.td_tod = time; 187 tdb.td_tcb = tp; 188 tdb.td_old = nstate; 189 tdb.td_inp = INRECV; 190 tdb.td_tim = 0; 191 tdb.td_sno = n->t_seq; 192 tdb.td_ano = n->t_ackno; 193 tdb.td_wno = n->t_win; 194 tdb.td_lno = n->t_len; 195 tdb.td_flg = n->th_flags; 196 } else 197 tdb.td_tod = 0; 198 #endif 199 switch (tp->t_state) { 200 201 case LISTEN: 202 if (!syn_ok(tp, n) || 203 ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) { 204 nstate = EFAILEC; 205 goto done; 206 } 207 tp->t_fport = n->t_src; 208 rcv_ctldat(tp, n, 1); 209 if (tp->tc_flags&TC_FIN_RCVD) { 210 tp->t_finack = T_2ML; /* 3 */ 211 tp->tc_flags &= ~TC_WAITED_2_ML; 212 nstate = CLOSE_WAIT; 213 } else { 214 tp->t_init = T_INIT / 2; /* 4 */ 215 nstate = L_SYN_RCVD; 216 } 217 goto done; 218 219 case SYN_SENT: 220 if (!syn_ok(tp, n)) { 221 nstate = EFAILEC; 222 goto done; 223 } 224 rcv_ctldat(tp, n, 1); 225 if (tp->tc_flags&TC_FIN_RCVD) { 226 if (n->th_flags&TH_ACK) { 227 if (n->t_ackno > tp->iss) 228 present_data(tp); /* 32 */ 229 } else { 230 tp->t_finack = T_2ML; /* 9 */ 231 tp->tc_flags &= ~TC_WAITED_2_ML; 232 } 233 nstate = CLOSE_WAIT; 234 goto done; 235 } 236 if (n->th_flags&TH_ACK) { 237 present_data(tp); /* 11 */ 238 nstate = ESTAB; 239 } else 240 nstate = SYN_RCVD; /* 8 */ 241 goto done; 242 243 case SYN_RCVD: 244 case L_SYN_RCVD: 245 if ((n->th_flags&TH_ACK) == 0 || 246 (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) { 247 nstate = EFAILEC; 248 goto done; 249 } 250 goto input; 251 252 case ESTAB: 253 case FIN_W1: 254 case FIN_W2: 255 case TIME_WAIT: 256 input: 257 rcv_ctldat(tp, n, 1); /* 39 */ 258 present_data(tp); 259 switch (tp->t_state) { 260 261 case ESTAB: 262 if (tp->tc_flags&TC_FIN_RCVD) 263 nstate = CLOSE_WAIT; 264 break; 265 266 case SYN_RCVD: 267 case L_SYN_RCVD: 268 nstate = (tp->tc_flags&TC_FIN_RCVD) ? 269 CLOSE_WAIT : ESTAB; /* 33:5 */ 270 break; 271 272 case FIN_W1: 273 j = ack_fin(tp, n); 274 if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 275 if (j) 276 nstate = FIN_W2; /* 27 */ 277 break; 278 } 279 tp->t_finack = T_2ML; 280 tp->tc_flags &= ~TC_WAITED_2_ML; 281 nstate = j ? TIME_WAIT : CLOSING1; /* 28:26 */ 282 break; 283 284 case FIN_W2: 285 if (tp->tc_flags&TC_FIN_RCVD) { 286 tp->t_finack = T_2ML; /* 29 */ 287 tp->tc_flags &= ~TC_WAITED_2_ML; 288 nstate = TIME_WAIT; 289 break; 290 } 291 break; 292 } 293 goto done; 294 295 case CLOSE_WAIT: 296 if (n->th_flags&TH_FIN) { 297 if ((n->th_flags&TH_ACK) && 298 n->t_ackno <= tp->seq_fin) { 299 rcv_ctldat(tp, n, 0); /* 30 */ 300 tp->t_finack = T_2ML; 301 tp->tc_flags &= ~TC_WAITED_2_ML; 302 } else 303 send_ctl(tp); /* 31 */ 304 goto done; 305 } 306 goto input; 307 308 case CLOSING1: 309 j = ack_fin(tp, n); 310 if (n->th_flags&TH_FIN) { 311 rcv_ctldat(tp, n, 0); 312 tp->t_finack = T_2ML; 313 tp->tc_flags &= ~TC_WAITED_2_ML; 314 if (j) 315 nstate = TIME_WAIT; /* 23 */ 316 goto done; 317 } 318 if (j) { 319 if (tp->tc_flags&TC_WAITED_2_ML) 320 if (rcv_empty(tp)) { 321 t_close(tp, UCLOSED); /* 15 */ 322 nstate = CLOSED; 323 } else 324 nstate = RCV_WAIT; /* 18 */ 325 else 326 nstate = TIME_WAIT; 327 goto done; 328 } 329 goto input; 330 331 case CLOSING2: 332 if (ack_fin(tp, n)) { 333 if (rcv_empty(tp)) { /* 16 */ 334 t_close(tp, UCLOSED); 335 nstate = CLOSED; 336 } else 337 nstate = RCV_WAIT; /* 19 */ 338 goto done; 339 } 340 if (n->th_flags&TH_FIN) { 341 send_ctl(tp); /* 31 */ 342 goto done; 343 } 344 goto input; 345 346 case RCV_WAIT: 347 if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) && 348 n->t_ackno <= tp->seq_fin) { 349 rcv_ctldat(tp, n, 0); 350 tp->t_finack = T_2ML; 351 tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 352 } 353 goto done; 354 } 355 panic("tcp_input"); 356 done: 357 358 /* 359 * Done with state*input specific processing. 360 * Form trace records, free input if not needed, 361 * and enter new state. 362 */ 363 #ifdef TCPDEBUG 364 if (tdb.td_tod) { 365 tdb.td_new = nstate; 366 tcp_debug[tdbx++ % TDBSIZE] = tdb; 367 if (tcpconsdebug) 368 tcp_prt(&tdb); 369 } 370 #endif 371 switch (nstate) { 372 373 case EFAILEC: 374 m_freem(mp); 375 return; 376 377 default: 378 tp->t_state = nstate; 379 /* fall into ... */ 380 381 case CLOSED: 382 /* IF CLOSED CANT LOOK AT tc_flags */ 383 if ((tp->tc_flags&TC_NET_KEEP) == 0) 384 m_freem(mp); 385 return; 386 } 387 /* NOTREACHED */ 388 389 /* 390 * Unwanted packed; free everything 391 * but the header and return an rst. 392 */ 393 notwanted: 394 m_freem(mp->m_next); 395 mp->m_next = NULL; 396 mp->m_len = sizeof(struct th); 397 #define xchg(a,b) j=a; a=b; b=j 398 xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 399 #undef xchg 400 if (n->th_flags&TH_ACK) 401 n->t_seq = n->t_ackno; 402 else { 403 n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 404 n->t_seq = 0; 405 } 406 n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */ 407 n->th_flags ^= TH_ACK; 408 n->t_len = htons(TCPSIZE); 409 n->t_off = 5; 410 n->t_sum = cksum(mp, sizeof(struct th)); 411 ((struct ip *)n)->ip_len = sizeof(struct th); 412 ip_output(mp); 413 netstat.t_badsegs++; 414 } 415 416 rcv_ctldat(tp, n, dataok) 417 register struct tcb *tp; 418 register struct th *n; 419 { 420 register sent; 421 register struct ucb *up; 422 register struct mbuf *m, *mn; 423 register len; 424 COUNT(RCV_CTLDAT); 425 426 tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 427 /* syn */ 428 if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) { 429 tp->irs = n->t_seq; 430 tp->rcv_nxt = n->t_seq + 1; 431 tp->snd_wl = tp->rcv_urp = tp->irs; 432 tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 433 } 434 /* ack */ 435 if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 436 n->t_ackno > tp->snd_una) { 437 up = tp->t_ucb; 438 439 /* update snd_una and snd_nxt */ 440 tp->snd_una = n->t_ackno; 441 if (tp->snd_una > tp->snd_nxt) 442 tp->snd_nxt = tp->snd_una; 443 444 /* if timed msg acked, set retrans time value */ 445 if ((tp->tc_flags&TC_SYN_ACKED) && 446 tp->snd_una > tp->t_xmt_val) { 447 tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 448 if (tp->t_xmtime > T_REMAX) 449 tp->t_xmtime = T_REMAX; 450 } 451 452 /* remove acked data from send buf */ 453 len = tp->snd_una - tp->snd_off; 454 m = up->uc_sbuf; 455 while (len > 0 && m != NULL) 456 if (m->m_len <= len) { 457 len -= m->m_len; 458 if (m->m_off > MMAXOFF) 459 up->uc_ssize -= NMBPG; 460 MFREE(m, mn); 461 m = mn; 462 up->uc_ssize--; 463 } else { 464 m->m_len -= len; 465 m->m_off += len; 466 break; 467 } 468 up->uc_sbuf = m; 469 tp->snd_off = tp->snd_una; 470 if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 471 (tp->snd_una > tp->iss)) { 472 tp->tc_flags |= TC_SYN_ACKED; 473 tp->t_init = 0; 474 } 475 if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 476 tp->tc_flags &= ~TC_SND_FIN; 477 tp->t_rexmt = 0; 478 tp->t_rexmttl = 0; 479 tp->tc_flags |= TC_CANCELLED; 480 netwakeup(tp->t_ucb); /* wasteful */ 481 } 482 /* win */ 483 if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 484 tp->snd_wl = n->t_seq; 485 tp->snd_wnd = n->t_win; 486 tp->tc_flags |= TC_NEW_WINDOW; 487 tp->t_persist = 0; 488 } 489 if (dataok) { 490 /* text */ 491 if (n->t_len != 0) 492 rcv_text(tp, n); 493 /* urg */ 494 if (n->th_flags&TH_URG) { 495 unsigned urgent; 496 497 urgent = n->t_urp + n->t_seq; 498 if (tp->rcv_nxt < urgent) { 499 if (tp->rcv_urp <= tp->rcv_nxt) 500 to_user(tp->t_ucb, UURGENT); 501 tp->rcv_urp = urgent; 502 } 503 } 504 /* eol */ 505 if ((n->th_flags&TH_EOL) && 506 (tp->tc_flags&TC_DROPPED_TXT) == 0 && 507 tp->t_rcv_prev != (struct th *)tp) { 508 /* mark last mbuf */ 509 m = dtom(tp->t_rcv_prev); 510 if (m != NULL) { 511 while (m->m_next != NULL) 512 m = m->m_next; 513 m->m_act = 514 (struct mbuf *)(m->m_off + m->m_len - 1); 515 } 516 } 517 } 518 /* fin */ 519 if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) { 520 int last; 521 522 if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 523 /* do we really have fin ? */ 524 last = firstempty(tp); 525 if (tp->t_rcv_prev == (struct th *)tp || 526 last == t_end(tp->t_rcv_prev)) { 527 tp->tc_flags |= TC_FIN_RCVD; 528 netwakeup(tp->t_ucb); /* poke */ 529 } 530 if ((tp->tc_flags&TC_FIN_RCVD) && 531 tp->rcv_nxt >= last) { 532 tp->rcv_nxt = last + 1; /* fin seq */ 533 tp->tc_flags |= TC_ACK_DUE; 534 } 535 } else 536 tp->tc_flags |= TC_ACK_DUE; 537 } 538 539 /* respond */ 540 if (tp->tc_flags&TC_ACK_DUE) 541 sent = send_ctl(tp); 542 else if (tp->tc_flags&TC_NEW_WINDOW) 543 sent = send(tp); 544 else 545 sent = 0; 546 547 /* set for retrans */ 548 if (!sent && tp->snd_una < tp->snd_nxt && 549 (tp->tc_flags&TC_CANCELLED)) { 550 tp->t_rexmt = tp->t_xmtime; 551 tp->t_rexmttl = T_REXMTTL; 552 tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 553 tp->tc_flags &= ~TC_CANCELLED; 554 } 555 } 556 557 rcv_text(tp, t) 558 register struct tcb *tp; 559 register struct th *t; 560 { 561 register i; 562 register struct th *p, *q; 563 register struct mbuf *m, *n; 564 struct th *savq; 565 int last, j, k; 566 COUNT(RCV_TEXT); 567 568 /* throw away any data we have already received */ 569 if ((i = tp->rcv_nxt - t->t_seq) > 0) { 570 if (i >= t->t_len) 571 return; 572 t->t_seq += i; 573 t->t_len -= i; 574 m_adj(dtom(t), i); 575 } 576 577 last = t_end(t); /* last seq # in incoming seg */ 578 i = rcv_resource(tp); /* # buffers available to con */ 579 580 /* count buffers in segment */ 581 582 for (m = dtom(t), j = 0; m != NULL; m = m->m_next) 583 if (m->m_len != 0) { 584 j++; 585 if (m->m_off > MMAXOFF) 586 j += NMBPG; 587 } 588 589 /* not enough resources to process segment */ 590 591 if (j > i && netcb.n_bufs < netcb.n_lowat) { 592 593 /* if segment preceeds top of seqeuncing queue, try to take 594 buffers from bottom of queue */ 595 596 q = tp->t_rcv_next; 597 if (q != (struct th *)tp && tp->rcv_nxt < q->t_seq && 598 t->t_seq < q->t_seq) 599 600 for (k=j-i, p = tp->t_rcv_prev; k > 0 && 601 p != (struct th *)tp; k--) { 602 savq = p->t_prev; 603 tcp_deq(p); 604 i += m_freem(dtom(p)); 605 p = savq; 606 } 607 608 /* if still not enough room, drop text from end of segment */ 609 610 if (j > i) { 611 612 for (m = dtom(t); i > 0 && m != NULL; i--) 613 m = m->m_next; 614 615 while (m != NULL) { 616 t->t_len -= m->m_len; 617 last -= m->m_len; 618 m->m_len = 0; 619 m = m->m_next; 620 } 621 tp->tc_flags |= TC_DROPPED_TXT; 622 if (last < t->t_seq) 623 return; 624 } 625 } 626 627 /* merge incoming data into the sequence queue */ 628 629 q = tp->t_rcv_next; /* -> top of sequencing queue */ 630 631 /* skip frags which new doesn't overlap at end */ 632 633 while ((q != (struct th *)tp) && (t->t_seq > t_end(q))) 634 q = q->t_next; 635 636 if (q == (struct th *)tp) { /* frag at end of chain */ 637 638 if (last >= tp->rcv_nxt) { 639 tp->tc_flags |= TC_NET_KEEP; 640 tcp_enq(t, tp->t_rcv_prev); 641 } 642 643 } else { 644 645 /* frag doesn't overlap any on chain */ 646 647 if (last < q->t_seq) { 648 tp->tc_flags |= TC_NET_KEEP; 649 tcp_enq(t, q->t_prev); 650 651 /* new overlaps beginning of next frag only */ 652 653 } else if (last < t_end(q)) { 654 if ((i = last - q->t_seq + 1) < t->t_len) { 655 t->t_len -= i; 656 m_adj(dtom(t), -i); 657 tp->tc_flags |= TC_NET_KEEP; 658 tcp_enq(t, q->t_prev); 659 } 660 661 /* new overlaps end of previous frag */ 662 663 } else { 664 savq = q; 665 if (t->t_seq <= q->t_seq) { /* complete cover */ 666 savq = q->t_prev; 667 tcp_deq(q); 668 m_freem(dtom(q)); 669 670 } else { /* overlap */ 671 if ((i = t_end(q) - t->t_seq + 1) < t->t_len) { 672 t->t_seq += i; 673 t->t_len -= i; 674 m_adj(dtom(t), i); 675 } else 676 t->t_len = 0; 677 } 678 679 /* new overlaps at beginning of successor frags */ 680 681 q = savq->t_next; 682 while ((q != (struct th *)tp) && (t->t_len != 0) && 683 (q->t_seq < last)) 684 685 /* complete cover */ 686 687 if (t_end(q) <= last) { 688 p = q->t_next; 689 tcp_deq(q); 690 m_freem(dtom(q)); 691 q = p; 692 693 } else { /* overlap */ 694 695 if ((i = last - q->t_seq + 1) < t->t_len) { 696 t->t_len -= i; 697 m_adj(dtom(t), -i); 698 } else 699 t->t_len = 0; 700 break; 701 } 702 703 /* enqueue whatever is left of new before successors */ 704 705 if (t->t_len != 0) { 706 tp->tc_flags |= TC_NET_KEEP; 707 tcp_enq(t, savq); 708 } 709 } 710 } 711 712 /* set to ack completed data (no gaps) */ 713 714 tp->rcv_nxt = firstempty(tp); 715 tp->tc_flags |= TC_ACK_DUE; 716 717 #ifdef notdef 718 /* THIS CODE CANT POSSIBLY WORK */ 719 /* if any room remaining in rcv buf, take any unprocessed 720 messages and schedule for later processing */ 721 722 i = rcv_resource(tp); 723 724 while ((m = tp->t_rcv_unack) != NULL && i > 0) { 725 726 /* schedule work request */ 727 728 t = (struct th *)((int)m + m->m_off); 729 j = (t->t_off << 2) + sizeof(struct ip); 730 m->m_off += j; 731 m->m_len -= j; 732 tp->t_rcv_unack = m->m_act; 733 m->m_act = (struct mbuf *)0; 734 netstat.t_unack++; 735 tcp_work(INRECV, 0, tp, t); 736 737 /* remaining buffer space */ 738 739 for (n = m; n != NULL; n = n->m_next) 740 i--; 741 } 742 #endif 743 } 744 745 present_data(tp) 746 register struct tcb *tp; 747 { 748 register struct th *t; 749 register struct ucb *up; 750 register struct mbuf *m, **mp; 751 seq_t ready; 752 COUNT(PRESENT_DATA); 753 754 /* connection must be synced and data available for user */ 755 if (((tp->tc_flags&TC_SYN_ACKED) == 0) || 756 (t = tp->t_rcv_next) == (struct th *)tp) 757 return; 758 up = tp->t_ucb; 759 ready = firstempty(tp); /* seq # of last complete datum */ 760 mp = &up->uc_rbuf; 761 while (*mp) 762 mp = &(*mp)->m_next; 763 while (up->uc_rsize < up->uc_rcv && t != (struct th *) tp && 764 t_end(t) < ready) { 765 tcp_deq(t); 766 m = dtom(t); 767 t = t->t_next; 768 while (m) { 769 if (m->m_len == 0) { 770 m = m_free(m); 771 continue; 772 } 773 up->uc_rsize++; 774 if (m->m_off > MMAXOFF) 775 up->uc_rsize += NMBPG; 776 if (*mp == 0) 777 *mp = m; 778 mp = &m->m_next; 779 m = *mp; 780 } 781 } 782 if (up->uc_rsize != 0) 783 netwakeup(up); 784 /* 785 * Let user know about foreign tcp close if no more data. 786 */ 787 if ((tp->tc_flags&TC_FIN_RCVD) && (tp->tc_flags&TC_USR_CLOSED) == 0 && 788 rcv_empty(tp)) 789 to_user(up, UCLOSED); 790 } 791