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