1 /* tcp_input.c 1.6 81/10/29 */ 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 (up->uc_rcc > up->uc_rhiwat && 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 return; 171 } 172 #endif 173 174 /* 175 * Discard ip header, and do tcp input processing. 176 */ 177 hlen += sizeof(struct ip); 178 mp->m_off += hlen; 179 mp->m_len -= hlen; 180 nstate = tp->t_state; 181 tp->tc_flags &= ~TC_NET_KEEP; 182 acounts[tp->t_state][INRECV]++; 183 #ifdef TCPDEBUG 184 if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 185 tdb_setup(tp, n, INRECV, &tdb); 186 } else 187 tdb.td_tod = 0; 188 #endif 189 switch (tp->t_state) { 190 191 case LISTEN: 192 if (!syn_ok(tp, n) || 193 ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) { 194 nstate = EFAILEC; 195 goto done; 196 } 197 tp->t_fport = n->t_src; 198 tp->t_ucb->uc_template = tcp_template(tp); 199 rcv_ctldat(tp, n, 1); 200 if (tp->tc_flags&TC_FIN_RCVD) { 201 tp->t_finack = T_2ML; /* 3 */ 202 tp->tc_flags &= ~TC_WAITED_2_ML; 203 nstate = CLOSE_WAIT; 204 } else { 205 tp->t_init = T_INIT / 2; /* 4 */ 206 nstate = L_SYN_RCVD; 207 } 208 goto done; 209 210 case SYN_SENT: 211 if (!syn_ok(tp, n)) { 212 nstate = EFAILEC; 213 goto done; 214 } 215 rcv_ctldat(tp, n, 1); 216 if (tp->tc_flags&TC_FIN_RCVD) { 217 if (n->th_flags&TH_ACK) { 218 if (n->t_ackno > tp->iss) 219 present_data(tp); /* 32 */ 220 } else { 221 tp->t_finack = T_2ML; /* 9 */ 222 tp->tc_flags &= ~TC_WAITED_2_ML; 223 } 224 nstate = CLOSE_WAIT; 225 goto done; 226 } 227 if (n->th_flags&TH_ACK) { 228 present_data(tp); /* 11 */ 229 nstate = ESTAB; 230 } else 231 nstate = SYN_RCVD; /* 8 */ 232 goto done; 233 234 case SYN_RCVD: 235 case L_SYN_RCVD: 236 if ((n->th_flags&TH_ACK) == 0 || 237 (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) { 238 nstate = EFAILEC; 239 goto done; 240 } 241 goto input; 242 243 case ESTAB: 244 case FIN_W1: 245 case FIN_W2: 246 case TIME_WAIT: 247 input: 248 rcv_ctldat(tp, n, 1); /* 39 */ 249 present_data(tp); 250 switch (tp->t_state) { 251 252 case ESTAB: 253 if (tp->tc_flags&TC_FIN_RCVD) 254 nstate = CLOSE_WAIT; 255 break; 256 257 case SYN_RCVD: 258 case L_SYN_RCVD: 259 nstate = (tp->tc_flags&TC_FIN_RCVD) ? 260 CLOSE_WAIT : ESTAB; /* 33:5 */ 261 break; 262 263 case FIN_W1: 264 j = ack_fin(tp, n); 265 if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 266 if (j) 267 nstate = FIN_W2; /* 27 */ 268 break; 269 } 270 tp->t_finack = T_2ML; 271 tp->tc_flags &= ~TC_WAITED_2_ML; 272 nstate = j ? TIME_WAIT : CLOSING1; /* 28:26 */ 273 break; 274 275 case FIN_W2: 276 if (tp->tc_flags&TC_FIN_RCVD) { 277 tp->t_finack = T_2ML; /* 29 */ 278 tp->tc_flags &= ~TC_WAITED_2_ML; 279 nstate = TIME_WAIT; 280 break; 281 } 282 break; 283 } 284 goto done; 285 286 case CLOSE_WAIT: 287 if (n->th_flags&TH_FIN) { 288 if ((n->th_flags&TH_ACK) && 289 n->t_ackno <= tp->seq_fin) { 290 rcv_ctldat(tp, n, 0); /* 30 */ 291 tp->t_finack = T_2ML; 292 tp->tc_flags &= ~TC_WAITED_2_ML; 293 } else 294 send_ctl(tp); /* 31 */ 295 goto done; 296 } 297 goto input; 298 299 case CLOSING1: 300 j = ack_fin(tp, n); 301 if (n->th_flags&TH_FIN) { 302 rcv_ctldat(tp, n, 0); 303 tp->t_finack = T_2ML; 304 tp->tc_flags &= ~TC_WAITED_2_ML; 305 if (j) 306 nstate = TIME_WAIT; /* 23 */ 307 goto done; 308 } 309 if (j) { 310 if (tp->tc_flags&TC_WAITED_2_ML) 311 if (rcv_empty(tp)) { 312 t_close(tp, UCLOSED); /* 15 */ 313 nstate = CLOSED; 314 } else 315 nstate = RCV_WAIT; /* 18 */ 316 else 317 nstate = TIME_WAIT; 318 goto done; 319 } 320 goto input; 321 322 case CLOSING2: 323 if (ack_fin(tp, n)) { 324 if (rcv_empty(tp)) { /* 16 */ 325 t_close(tp, UCLOSED); 326 nstate = CLOSED; 327 } else 328 nstate = RCV_WAIT; /* 19 */ 329 goto done; 330 } 331 if (n->th_flags&TH_FIN) { 332 send_ctl(tp); /* 31 */ 333 goto done; 334 } 335 goto input; 336 337 case RCV_WAIT: 338 if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) && 339 n->t_ackno <= tp->seq_fin) { 340 rcv_ctldat(tp, n, 0); 341 tp->t_finack = T_2ML; 342 tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 343 } 344 goto done; 345 } 346 panic("tcp_input"); 347 done: 348 349 /* 350 * Done with state*input specific processing. 351 * Form trace records, free input if not needed, 352 * and enter new state. 353 */ 354 #ifdef TCPDEBUG 355 if (tdb.td_tod) 356 tdb_stuff(&tdb, nstate); 357 #endif 358 switch (nstate) { 359 360 case EFAILEC: 361 m_freem(mp); 362 return; 363 364 default: 365 tp->t_state = nstate; 366 /* fall into ... */ 367 368 case CLOSED: 369 /* IF CLOSED CANT LOOK AT tc_flags */ 370 if ((tp->tc_flags&TC_NET_KEEP) == 0) 371 m_freem(mp); 372 return; 373 } 374 /* NOTREACHED */ 375 376 /* 377 * Unwanted packed; free everything 378 * but the header and return an rst. 379 */ 380 notwanted: 381 m_freem(mp->m_next); 382 mp->m_next = NULL; 383 mp->m_len = sizeof(struct th); 384 #define xchg(a,b) j=a; a=b; b=j 385 xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 386 #undef xchg 387 if (n->th_flags&TH_ACK) 388 n->t_seq = n->t_ackno; 389 else { 390 n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 391 n->t_seq = 0; 392 } 393 n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */ 394 n->th_flags ^= TH_ACK; 395 n->t_len = htons(TCPSIZE); 396 n->t_off = 5; 397 n->t_sum = cksum(mp, sizeof(struct th)); 398 ((struct ip *)n)->ip_len = sizeof(struct th); 399 ip_output(mp); 400 netstat.t_badsegs++; 401 } 402 403 rcv_ctldat(tp, n, dataok) 404 register struct tcb *tp; 405 register struct th *n; 406 { 407 register sent; 408 register struct ucb *up; 409 register struct mbuf *m, *mn; 410 register len; 411 COUNT(RCV_CTLDAT); 412 413 tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 414 /* syn */ 415 if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) { 416 tp->irs = n->t_seq; 417 tp->rcv_nxt = n->t_seq + 1; 418 tp->snd_wl = tp->rcv_urp = tp->irs; 419 tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 420 } 421 /* ack */ 422 if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 423 n->t_ackno > tp->snd_una) { 424 up = tp->t_ucb; 425 426 /* update snd_una and snd_nxt */ 427 tp->snd_una = n->t_ackno; 428 if (tp->snd_una > tp->snd_nxt) 429 tp->snd_nxt = tp->snd_una; 430 431 /* if timed msg acked, set retrans time value */ 432 if ((tp->tc_flags&TC_SYN_ACKED) && 433 tp->snd_una > tp->t_xmt_val) { 434 tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 435 if (tp->t_xmtime > T_REMAX) 436 tp->t_xmtime = T_REMAX; 437 } 438 439 /* remove acked data from send buf */ 440 len = tp->snd_una - tp->snd_off; 441 m = up->uc_sbuf; 442 while (len > 0 && m != NULL) 443 if (m->m_len <= len) { 444 len -= m->m_len; 445 if (m->m_off > MMAXOFF) 446 up->uc_ssize -= NMBPG; 447 MFREE(m, mn); 448 m = mn; 449 up->uc_ssize--; 450 } else { 451 m->m_len -= len; 452 m->m_off += len; 453 break; 454 } 455 up->uc_sbuf = m; 456 tp->snd_off = tp->snd_una; 457 if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 458 (tp->snd_una > tp->iss)) { 459 tp->tc_flags |= TC_SYN_ACKED; 460 tp->t_init = 0; 461 } 462 if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 463 tp->tc_flags &= ~TC_SND_FIN; 464 tp->t_rexmt = 0; 465 tp->t_rexmttl = 0; 466 tp->tc_flags |= TC_CANCELLED; 467 netwakeup(tp->t_ucb); /* wasteful */ 468 } 469 /* win */ 470 if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 471 tp->snd_wl = n->t_seq; 472 tp->snd_wnd = n->t_win; 473 tp->tc_flags |= TC_NEW_WINDOW; 474 tp->t_persist = 0; 475 } 476 if (dataok) { 477 /* text */ 478 if (n->t_len != 0) 479 rcv_text(tp, n); 480 /* urg */ 481 if (n->th_flags&TH_URG) { 482 unsigned urgent; 483 484 urgent = n->t_urp + n->t_seq; 485 if (tp->rcv_nxt < urgent) { 486 if (tp->rcv_urp <= tp->rcv_nxt) 487 to_user(tp->t_ucb, UURGENT); 488 tp->rcv_urp = urgent; 489 } 490 } 491 /* eol */ 492 if ((n->th_flags&TH_EOL) && 493 (tp->tc_flags&TC_DROPPED_TXT) == 0 && 494 tp->t_rcv_prev != (struct th *)tp) { 495 /* mark last mbuf */ 496 m = dtom(tp->t_rcv_prev); 497 if (m != NULL) { 498 while (m->m_next != NULL) 499 m = m->m_next; 500 m->m_act = 501 (struct mbuf *)(m->m_off + m->m_len - 1); 502 } 503 } 504 } 505 /* fin */ 506 if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) { 507 int last; 508 509 if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 510 /* do we really have fin ? */ 511 last = firstempty(tp); 512 if (tp->t_rcv_prev == (struct th *)tp || 513 last == t_end(tp->t_rcv_prev)) { 514 tp->tc_flags |= TC_FIN_RCVD; 515 netwakeup(tp->t_ucb); /* poke */ 516 } 517 if ((tp->tc_flags&TC_FIN_RCVD) && 518 tp->rcv_nxt >= last) { 519 tp->rcv_nxt = last + 1; /* fin seq */ 520 tp->tc_flags |= TC_ACK_DUE; 521 } 522 } else 523 tp->tc_flags |= TC_ACK_DUE; 524 } 525 526 /* respond */ 527 if (tp->tc_flags&TC_ACK_DUE) 528 sent = send_ctl(tp); 529 else if (tp->tc_flags&TC_NEW_WINDOW) 530 sent = send(tp); 531 else 532 sent = 0; 533 534 /* set for retrans */ 535 if (!sent && tp->snd_una < tp->snd_nxt && 536 (tp->tc_flags&TC_CANCELLED)) { 537 tp->t_rexmt = tp->t_xmtime; 538 tp->t_rexmttl = T_REXMTTL; 539 tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 540 tp->tc_flags &= ~TC_CANCELLED; 541 } 542 } 543 544 rcv_text(tp, n) 545 register struct tcb *tp; 546 register struct th *n; 547 { 548 register int i; 549 register struct th *p, *q; 550 register struct mbuf *m; 551 int overage; 552 COUNT(RCV_TEXT); 553 554 /* 555 * Discard duplicate data already passed to user. 556 */ 557 if (SEQ_LT(n->t_seq, tp->rcv_nxt)) { 558 i = tp->rcv_nxt - n->t_seq; 559 if (i >= n->t_len) 560 goto dropseg; 561 n->t_seq += i; 562 n->t_len -= i; 563 m_adj(dtom(n), i); 564 } 565 566 /* 567 * Find a segment which begins after this one does. 568 */ 569 for (q = tp->t_rcv_next; q != (struct th *)tp; q = q->t_next) 570 if (SEQ_GT(q->t_seq, n->t_seq)) 571 break; 572 573 /* 574 * If there is a preceding segment, it may provide some of 575 * our data already. If so, drop the data from the incoming 576 * segment. If it provides all of our data, drop us. 577 */ 578 if (q->t_prev != (struct th *)tp) { 579 /* conversion to int (in i) handles seq wraparound */ 580 i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq; 581 if (i > 0) { 582 if (i >= n->t_len) 583 goto dropseg; 584 m_adj(dtom(tp), i); 585 n->t_len -= i; 586 n->t_seq += i; 587 } 588 } 589 590 /* 591 * While we overlap succeeding segments trim them or, 592 * if they are completely covered, dequeue them. 593 */ 594 while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) { 595 i = (n->t_seq + n->t_len) - q->t_seq; 596 if (i < q->t_len) { 597 q->t_len -= i; 598 m_adj(dtom(q), i); 599 break; 600 } 601 q = q->t_next; 602 m_freem(dtom(q->t_prev)); 603 remque(q->t_prev); 604 } 605 606 /* 607 * Stick new segment in its place. 608 */ 609 insque(n, q->t_prev); 610 tp->seqcnt += n->t_len; 611 612 #ifdef notdef 613 /* 614 * Calculate available space and discard segments for 615 * which there is too much. 616 */ 617 q = tp->t_rcv_prev; 618 overage = 619 (tp->t_socket->uc_rcc + tp->rcv_seqcnt) - tp->t_socket->uc_rhiwat; 620 if (overage > 0) 621 for (;;) { 622 i = MIN(q->t_len, overage); 623 overage -= i; 624 q->t_len -= i; 625 m_adj(q, -i); 626 if (q == n) 627 tp->tc_flags |= TC_DROPPED_TXT; 628 if (q->t_len) 629 break; 630 if (q == n) 631 panic("tcp_text dropall"); 632 q = q->t_prev; 633 remque(q->t_next); 634 } 635 #endif 636 637 /* 638 * Advance rcv_next through 639 * newly completed sequence space 640 * and return forcing an ack. 641 */ 642 while (n->t_seq == tp->rcv_nxt) { 643 /* present data belongs here */ 644 tp->rcv_nxt += n->t_len; 645 n = n->t_next; 646 if (n == (struct th *)tp) 647 break; 648 } 649 tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 650 return; 651 652 dropseg: 653 /* don't set TC_NET_KEEP, so that mbuf's will get dropped */ 654 return; 655 } 656 657 #define socket ucb /* ### */ 658 #define t_socket t_ucb /* ### */ 659 660 present_data(tp) 661 register struct tcb *tp; 662 { 663 register struct th *t; 664 register struct socket *up; 665 register struct mbuf *m, **mp; 666 seq_t ready; 667 COUNT(PRESENT_DATA); 668 669 /* connection must be synced and data available for user */ 670 if ((tp->tc_flags&TC_SYN_ACKED) == 0) 671 return; 672 up = tp->t_socket; 673 mp = &up->uc_rbuf; 674 while (*mp) 675 mp = &(*mp)->m_next; 676 t = tp->t_rcv_next; 677 /* SHOULD PACK DATA IN HERE */ 678 while (t != (struct th *)tp && t->t_seq < tp->rcv_nxt) { 679 remque(t); 680 m = dtom(t); 681 up->uc_rcc += t->t_len; 682 tp->seqcnt -= t->t_len; 683 if (tp->seqcnt < 0) panic("present_data"); 684 t = t->t_next; 685 while (m) { 686 if (m->m_len == 0) { 687 m = m_free(m); 688 continue; 689 } 690 *mp = m; 691 mp = &m->m_next; 692 m = *mp; 693 } 694 } 695 if (up->uc_rcc != 0) 696 netwakeup(up); 697 if ((tp->tc_flags&TC_FIN_RCVD) && /* ### */ 698 (tp->tc_flags&TC_USR_CLOSED) == 0 && /* ### */ 699 rcv_empty(tp)) /* ### */ 700 to_user(up, UCLOSED); /* ### */ 701 } 702