1 /* tcp_input.c 1.20 81/11/07 */ 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_cksum.h" 8 #include "../inet/inet.h" 9 #include "../inet/inet_systm.h" 10 #include "../inet/imp.h" 11 #include "../inet/inet_host.h" 12 #include "../inet/ip.h" 13 #include "../inet/tcp.h" 14 #include "../inet/tcp_fsm.h" 15 16 int tcpcksum = 1; 17 18 tcp_input(mp) 19 register struct mbuf *mp; 20 { 21 register struct th *n; /* known to be r10 */ 22 register int j; 23 register struct tcb *tp; 24 int nstate; 25 struct mbuf *m; 26 struct ucb *up; 27 int hlen, tlen; 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 if (tcpcksum) { 51 /* 52 * Checksum extended header and data 53 */ 54 CKSUM_TCPCHK(mp, n, r10, sizeof (struct ip) + tlen); 55 if (n->t_sum != 0) { 56 netstat.t_badsum++; 57 m_freem(mp); 58 return; 59 } 60 } 61 62 /* 63 * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!) 64 */ 65 for (tp = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->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 = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->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 tcp_sndrst(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 tcp_sndrst(tp, n); /* 71,72,75 */ 106 goto badseg; 107 } 108 if (n->th_flags&TH_RST) { 109 tcp_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 tcp_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 tcp_sndrst(tp, n); /* 74 */ 143 goto badseg; 144 } 145 if (syn_ok(tp, n) && n->t_seq != tp->irs) { 146 tcp_sndnull(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 /* DO SOMETHING ABOUT UNACK!!! */ 158 /* 159 * Defer processing if no buffer space for this connection. 160 */ 161 up = tp->t_ucb; 162 if (up->uc_rcc > up->uc_rhiwat && 163 && n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 164 mp->m_act = (struct mbuf *)0; 165 if ((m = tp->t_rcv_unack) != NULL) { 166 while (m->m_act != NULL) 167 m = m->m_act; 168 m->m_act = mp; 169 } else 170 tp->t_rcv_unack = mp; 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 #ifdef KPROF 184 acounts[tp->t_state][INRECV]++; 185 #endif 186 #ifdef TCPDEBUG 187 if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 188 tdb_setup(tp, n, INRECV, &tdb); 189 } else 190 tdb.td_tod = 0; 191 #endif 192 switch (tp->t_state) { 193 194 case LISTEN: 195 if (!syn_ok(tp, n) || 196 ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) { 197 nstate = EFAILEC; 198 goto done; 199 } 200 tp->t_fport = n->t_src; 201 tp->t_template = tcp_template(tp); 202 tcp_ctldat(tp, n, 1); 203 if (tp->tc_flags&TC_FIN_RCVD) { 204 tp->t_finack = T_2ML; /* 3 */ 205 tp->tc_flags &= ~TC_WAITED_2_ML; 206 nstate = CLOSE_WAIT; 207 } else { 208 tp->t_init = T_INIT / 2; /* 4 */ 209 nstate = L_SYN_RCVD; 210 } 211 goto done; 212 213 case SYN_SENT: 214 if (!syn_ok(tp, n)) { 215 nstate = EFAILEC; 216 goto done; 217 } 218 tcp_ctldat(tp, n, 1); 219 if (tp->tc_flags&TC_FIN_RCVD) { 220 if ((n->th_flags&TH_ACK) == 0) { 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 nstate = (n->th_flags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */ 228 goto done; 229 230 case SYN_RCVD: 231 case L_SYN_RCVD: 232 if ((n->th_flags&TH_ACK) == 0 || 233 (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) { 234 nstate = EFAILEC; 235 goto done; 236 } 237 goto input; 238 239 case ESTAB: 240 case FIN_W1: 241 case FIN_W2: 242 case TIME_WAIT: 243 input: 244 tcp_ctldat(tp, n, 1); /* 39 */ 245 switch (tp->t_state) { 246 247 case ESTAB: 248 if (tp->tc_flags&TC_FIN_RCVD) 249 nstate = CLOSE_WAIT; 250 break; 251 252 case SYN_RCVD: 253 case L_SYN_RCVD: 254 nstate = (tp->tc_flags&TC_FIN_RCVD) ? 255 CLOSE_WAIT : ESTAB; /* 33:5 */ 256 break; 257 258 case FIN_W1: 259 j = ack_fin(tp, n); 260 if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 261 if (j) 262 nstate = FIN_W2; /* 27 */ 263 break; 264 } 265 tp->t_finack = T_2ML; 266 tp->tc_flags &= ~TC_WAITED_2_ML; 267 nstate = j ? TIME_WAIT : CLOSING; /* 28:26 */ 268 break; 269 270 case FIN_W2: 271 if (tp->tc_flags&TC_FIN_RCVD) { 272 tp->t_finack = T_2ML; /* 29 */ 273 tp->tc_flags &= ~TC_WAITED_2_ML; 274 nstate = TIME_WAIT; 275 break; 276 } 277 break; 278 } 279 goto done; 280 281 case CLOSE_WAIT: 282 if (n->th_flags&TH_FIN) { 283 if ((n->th_flags&TH_ACK) && 284 n->t_ackno <= tp->seq_fin) { 285 tcp_ctldat(tp, n, 0); /* 30 */ 286 tp->t_finack = T_2ML; 287 tp->tc_flags &= ~TC_WAITED_2_ML; 288 } else 289 tcp_sndctl(tp); /* 31 */ 290 goto done; 291 } 292 goto input; 293 294 case CLOSING: 295 j = ack_fin(tp, n); 296 if (n->th_flags&TH_FIN) { 297 tcp_ctldat(tp, n, 0); 298 tp->t_finack = T_2ML; 299 tp->tc_flags &= ~TC_WAITED_2_ML; 300 if (j) 301 nstate = TIME_WAIT; /* 23 */ 302 goto done; 303 } 304 if (j) { 305 if (tp->tc_flags&TC_WAITED_2_ML) 306 if (rcv_empty(tp)) { 307 tcp_close(tp, UCLOSED); /* 15 */ 308 nstate = CLOSED; 309 } else 310 nstate = RCV_WAIT; /* 18 */ 311 else 312 nstate = TIME_WAIT; 313 goto done; 314 } 315 goto input; 316 317 case LAST_ACK: 318 if (ack_fin(tp, n)) { 319 if (rcv_empty(tp)) { /* 16 */ 320 tcp_close(tp, UCLOSED); 321 nstate = CLOSED; 322 } else 323 nstate = RCV_WAIT; /* 19 */ 324 goto done; 325 } 326 if (n->th_flags&TH_FIN) { 327 tcp_sndctl(tp); /* 31 */ 328 goto done; 329 } 330 goto input; 331 332 case RCV_WAIT: 333 if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) && 334 n->t_ackno <= tp->seq_fin) { 335 tcp_ctldat(tp, n, 0); 336 tp->t_finack = T_2ML; 337 tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 338 } 339 goto done; 340 } 341 panic("tcp_input"); 342 done: 343 344 /* 345 * Done with state*input specific processing. 346 * Form trace records, free input if not needed, 347 * and enter new state. 348 */ 349 #ifdef TCPDEBUG 350 if (tdb.td_tod) 351 tdb_stuff(&tdb, nstate); 352 #endif 353 switch (nstate) { 354 355 case EFAILEC: 356 m_freem(mp); 357 return; 358 359 default: 360 tp->t_state = nstate; 361 /* fall into ... */ 362 363 case CLOSED: 364 /* IF CLOSED CANT LOOK AT tc_flags */ 365 if ((tp->tc_flags&TC_NET_KEEP) == 0) 366 /* inline expansion of m_freem */ 367 while (mp) { 368 MFREE(mp, m); 369 mp = m; 370 } 371 return; 372 } 373 /* NOTREACHED */ 374 375 /* 376 * Unwanted packed; free everything 377 * but the header and return an rst. 378 */ 379 notwanted: 380 m_freem(mp->m_next); 381 mp->m_next = NULL; 382 mp->m_len = sizeof(struct th); 383 #define xchg(a,b) j=a; a=b; b=j 384 xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 385 #undef xchg 386 if (n->th_flags&TH_ACK) 387 n->t_seq = n->t_ackno; 388 else { 389 n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 390 n->t_seq = 0; 391 } 392 n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */ 393 n->th_flags ^= TH_ACK; 394 n->t_len = htons(TCPSIZE); 395 n->t_off = 5; 396 n->t_sum = inet_cksum(mp, sizeof(struct th)); 397 ((struct ip *)n)->ip_len = sizeof(struct th); 398 ip_output(mp); 399 netstat.t_badsegs++; 400 } 401 402 tcp_ctldat(tp, n, dataok) 403 register struct tcb *tp; 404 register struct th *n; 405 { 406 register struct mbuf *m; 407 int sent; 408 COUNT(TCP_CTLDAT); 409 410 tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 411 /* syn */ 412 if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) { 413 tp->irs = n->t_seq; 414 tp->rcv_nxt = n->t_seq + 1; 415 tp->snd_wl = tp->rcv_urp = tp->irs; 416 tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 417 } 418 /* ack */ 419 if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 420 n->t_ackno > tp->snd_una) { 421 register struct mbuf *mn; 422 register struct ucb *up; 423 int len; 424 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 /* 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 == 0) 477 goto ctlonly; 478 /* text */ 479 if (n->t_len == 0) 480 goto notext; 481 { register int i; 482 register struct th *p, *q; 483 register struct mbuf *m; 484 int overage; 485 486 /* 487 * Discard duplicate data already passed to user. 488 */ 489 if (SEQ_LT(n->t_seq, tp->rcv_nxt)) { 490 i = tp->rcv_nxt - n->t_seq; 491 if (i >= n->t_len) 492 goto notext; 493 n->t_seq += i; 494 n->t_len -= i; 495 m_adj(dtom(n), i); 496 } 497 498 /* 499 * Find a segment which begins after this one does. 500 */ 501 for (q = tp->t_rcv_next; q != (struct th *)tp; q = q->t_next) 502 if (SEQ_GT(q->t_seq, n->t_seq)) 503 break; 504 505 /* 506 * If there is a preceding segment, it may provide some of 507 * our data already. If so, drop the data from the incoming 508 * segment. If it provides all of our data, drop us. 509 */ 510 if (q->t_prev != (struct th *)tp) { 511 /* conversion to int (in i) handles seq wraparound */ 512 i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq; 513 if (i > 0) { 514 if (i >= n->t_len) 515 goto notext; /* w/o setting TC_NET_KEEP */ 516 m_adj(dtom(tp), i); 517 n->t_len -= i; 518 n->t_seq += i; 519 } 520 } 521 522 /* 523 * While we overlap succeeding segments trim them or, 524 * if they are completely covered, dequeue them. 525 */ 526 while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) { 527 i = (n->t_seq + n->t_len) - q->t_seq; 528 if (i < q->t_len) { 529 q->t_len -= i; 530 m_adj(dtom(q), i); 531 break; 532 } 533 q = q->t_next; 534 m_freem(dtom(q->t_prev)); 535 remque(q->t_prev); 536 } 537 538 /* 539 * Stick new segment in its place. 540 */ 541 insque(n, q->t_prev); 542 tp->seqcnt += n->t_len; 543 544 #ifdef notdef 545 /* 546 * Calculate available space and discard segments for 547 * which there is too much. 548 */ 549 q = tp->t_rcv_prev; 550 overage = 551 (tp->t_ucb->uc_rcc + tp->rcv_seqcnt) - tp->t_ucb->uc_rhiwat; 552 if (overage > 0) 553 for (;;) { 554 i = MIN(q->t_len, overage); 555 overage -= i; 556 q->t_len -= i; 557 m_adj(q, -i); 558 if (q == n) 559 tp->tc_flags |= TC_DROPPED_TXT; 560 if (q->t_len) 561 break; 562 if (q == n) 563 panic("tcp_text dropall"); 564 q = q->t_prev; 565 remque(q->t_next); 566 } 567 #endif 568 569 /* 570 * Advance rcv_next through 571 * newly completed sequence space 572 * and return forcing an ack. 573 */ 574 while (n->t_seq == tp->rcv_nxt) { 575 /* present data belongs here */ 576 tp->rcv_nxt += n->t_len; 577 n = n->t_next; 578 if (n == (struct th *)tp) 579 break; 580 } 581 tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 582 } 583 notext: 584 urgeolfin: 585 /* urg */ 586 if (n->th_flags&TH_URG) { 587 unsigned urgent; 588 589 urgent = n->t_urp + n->t_seq; 590 if (tp->rcv_nxt < urgent) { 591 if (tp->rcv_urp <= tp->rcv_nxt) 592 to_user(tp->t_ucb, UURGENT); 593 tp->rcv_urp = urgent; 594 } 595 } 596 /* eol */ 597 if ((n->th_flags&TH_EOL) && 598 (tp->tc_flags&TC_DROPPED_TXT) == 0 && 599 tp->t_rcv_prev != (struct th *)tp) { 600 /* mark last mbuf */ 601 m = dtom(tp->t_rcv_prev); 602 if (m != NULL) { 603 while (m->m_next != NULL) 604 m = m->m_next; 605 m->m_act = 606 (struct mbuf *)(m->m_off + m->m_len - 1); 607 } 608 } 609 ctlonly: 610 /* fin */ 611 if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) { 612 seq_t last; 613 614 if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 615 /* do we really have fin ? */ 616 last = firstempty(tp); 617 if (tp->t_rcv_prev == (struct th *)tp || 618 last == t_end(tp->t_rcv_prev)) { 619 tp->tc_flags |= TC_FIN_RCVD; 620 netwakeup(tp->t_ucb); /* poke */ 621 } 622 if ((tp->tc_flags&TC_FIN_RCVD) && 623 tp->rcv_nxt >= last) { 624 tp->rcv_nxt = last + 1; /* fin seq */ 625 tp->tc_flags |= TC_ACK_DUE; 626 } 627 } else 628 tp->tc_flags |= TC_ACK_DUE; 629 } 630 631 /* respond */ 632 sent = 0; 633 if (tp->tc_flags&TC_ACK_DUE) 634 sent = tcp_sndctl(tp); 635 else if (tp->tc_flags&TC_NEW_WINDOW) { 636 seq_t last = tp->snd_off; 637 for (m = tp->t_ucb->uc_sbuf; m != NULL; m = m->m_next) /*###*/ 638 last += m->m_len; /*###*/ 639 if (tp->snd_nxt <= last || (tp->tc_flags&TC_SND_FIN)) 640 sent = tcp_send(tp); 641 } 642 643 /* set for retrans */ 644 if (!sent && tp->snd_una < tp->snd_nxt && 645 (tp->tc_flags&TC_CANCELLED)) { 646 tp->t_rexmt = tp->t_xmtime; 647 tp->t_rexmttl = T_REXMTTL; 648 tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 649 tp->tc_flags &= ~TC_CANCELLED; 650 } 651 /* present data to user */ 652 { register struct mbuf **mp; 653 register struct ucb *up = tp->t_ucb; 654 seq_t ready; 655 656 /* connection must be synced and data available for user */ 657 if ((tp->tc_flags&TC_SYN_ACKED) == 0) 658 return; 659 up = tp->t_ucb; 660 mp = &up->uc_rbuf; 661 while (*mp) 662 mp = &(*mp)->m_next; 663 n = tp->t_rcv_next; 664 /* SHOULD PACK DATA IN HERE */ 665 while (n != (struct th *)tp && n->t_seq < tp->rcv_nxt) { 666 remque(n); 667 m = dtom(n); 668 up->uc_rcc += n->t_len; 669 tp->seqcnt -= n->t_len; 670 if (tp->seqcnt < 0) panic("present_data"); 671 n = n->t_next; 672 while (m) { 673 if (m->m_len == 0) { 674 MFREE(m, *mp); 675 } else { 676 *mp = m; 677 mp = &m->m_next; 678 } 679 m = *mp; 680 } 681 } 682 if (up->uc_rcc != 0) 683 netwakeup(up); 684 if ((tp->tc_flags&TC_FIN_RCVD) && /* ### */ 685 (tp->tc_flags&TC_USR_CLOSED) == 0 && /* ### */ 686 rcv_empty(tp)) /* ### */ 687 to_user(up, UCLOSED); /* ### */ 688 } 689 } 690