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