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