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