1 /* tcp_usrreq.c 1.24 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.h" 8 #include "../inet/inet_systm.h" 9 #include "../inet/imp.h" 10 #include "../inet/ip.h" 11 #include "../inet/tcp.h" 12 #define TCPFSTAB 13 #ifdef TCPDEBUG 14 #define TCPSTATES 15 #endif 16 #include "../inet/tcp_fsm.h" 17 18 /* 19 * Tcp finite state machine entries for timer and user generated 20 * requests. These routines raise the ipl to that of the network 21 * to prevent reentry. In particluar, this requires that the software 22 * clock interrupt have lower priority than the network so that 23 * we can enter the network from timeout routines without improperly 24 * nesting the interrupt stack. 25 */ 26 27 /* 28 * Tcp protocol timeout routine called once per second. 29 * Updates the timers in all active tcb's and 30 * causes finite state machine actions if timers expire. 31 */ 32 tcp_timeo() 33 { 34 register struct tcb *tp; 35 int s = splnet(); 36 register u_char *tmp; 37 register int i; 38 COUNT(TCP_TIMEO); 39 40 /* 41 * Search through tcb's and update active timers. 42 */ 43 for (tp = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->tcb_next) { 44 tmp = &tp->t_init; 45 for (i = 0; i < TNTIMERS; i++) 46 if (*tmp && --*tmp == 0) 47 tcp_usrreq(ISTIMER, i, tp, 0); 48 tp->t_xmt++; 49 } 50 tcp_iss += ISSINCR; /* increment iss */ 51 timeout(tcp_timeo, 0, hz); /* reschedule every second */ 52 splx(s); 53 } 54 55 /* 56 * Cancel all timers for tcp tp. 57 */ 58 tcp_tcancel(tp) 59 struct tcb *tp; 60 { 61 register u_char *tmp = &tp->t_init; 62 register int i; 63 64 for (i = 0; i < TNTIMERS; i++) 65 *tmp++ = 0; 66 } 67 68 /* 69 * Process a TCP user request for tcp tb. If this is a send request 70 * then m is the mbuf chain of send data. If this is a timer expiration 71 * (called from the software clock routine), then timertype tells which timer. 72 */ 73 tcp_usrreq(input, timertype, tp, m) 74 int input, timertype; 75 register struct tcb *tp; 76 struct mbuf *m; 77 { 78 int s = splnet(); 79 register int nstate; 80 #ifdef TCPDEBUG 81 struct tcp_debug tdb; 82 #endif 83 COUNT(TCP_USRREQ); 84 85 nstate = tp->t_state; 86 tp->tc_flags &= ~TC_NET_KEEP; 87 #ifdef KPROF 88 acounts[nstate][input]++; 89 #endif 90 #ifdef TCPDEBUG 91 if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 92 tdb_setup(tp, (struct th *)0, input, &tdb); 93 tdb.td_tim = timertype; 94 } else 95 tdb.td_tod = 0; 96 #endif 97 switch (input) { 98 99 /* 100 * Passive open. Create a tcp control block 101 * and enter listen state. 102 */ 103 case IUOPENA: 104 if (nstate != 0 && nstate != CLOSED) 105 goto bad; 106 tcp_open(tp, PASSIVE); 107 nstate = LISTEN; 108 break; 109 110 /* 111 * Active open. Create a tcp control block, 112 * send a SYN and enter SYN_SENT state. 113 */ 114 case IUOPENR: 115 if (nstate != 0 && nstate != CLOSED) 116 goto bad; 117 tcp_open(tp, ACTIVE); 118 tcp_sndctl(tp); 119 nstate = SYN_SENT; 120 break; 121 122 /* 123 * Tcp close call. Can be generated by a user ioctl (half-close), 124 * or when higher level close occurs, if a close hasn't happened 125 * already. 126 */ 127 case IUCLOSE: 128 switch (nstate) { 129 130 /* 131 * If we are aborting out of a listener or a active 132 * connection which has not yet completed we can just 133 * delete the tcb. 134 */ 135 case LISTEN: 136 case SYN_SENT: 137 tcp_close(tp, UCLOSED); 138 nstate = CLOSED; 139 break; 140 141 /* 142 * If we have gotten as far as receiving a syn from 143 * our foreign peer, we must be sure to send a FIN. 144 * If we have gotten a FIN from the foreign peer already 145 * (CLOSE_WAIT state), then all that remains is to wait 146 * for his ack of the FIN (LAST_ACK state). If we have 147 * not gotten a FIN from the foreign peer then we need 148 * to either: 149 * 1. rcv ack of our FIN (to FIN_W2) and then 150 * send an ACK (to TIME_WAIT) and timeout at 2*MSL. 151 * or 2. receive hist FIN (to CLOSING), send an ACK 152 * (to TIME_WAIT), and then timeout. 153 * In any case this starts with a transition to FIN_W1 here. 154 */ 155 case SYN_RCVD: 156 case L_SYN_RCVD: 157 case ESTAB: 158 case CLOSE_WAIT: 159 tp->tc_flags |= TC_SND_FIN; 160 tcp_sndctl(tp); 161 tp->tc_flags |= TC_USR_CLOSED; 162 nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK; 163 break; 164 165 /* 166 * In these states the user has already closed; 167 * trying to close again is an error. 168 */ 169 case FIN_W1: 170 case FIN_W2: 171 case TIME_WAIT: 172 case CLOSING: 173 case LAST_ACK: 174 case RCV_WAIT: 175 to_user(tp->t_ucb, UCLSERR); 176 break; 177 178 default: 179 goto bad; 180 } 181 break; 182 183 /* 184 * TCP Timer processing. 185 * Timers should expire only on open connections 186 * not in LISTEN state. 187 */ 188 case ISTIMER: 189 switch (nstate) { 190 191 case 0: 192 case CLOSED: 193 case LISTEN: 194 goto bad; 195 196 default: 197 nstate = tcp_timers(tp, timertype); 198 } 199 break; 200 201 /* 202 * User notification of more window availability after 203 * reading out data. This should not happen before a connection 204 * is established or after it is closed. 205 * If the foreign peer has closed and the local entity 206 * has not, inform him of the FIN (give end of file). 207 * If the local entity is in RCV_WAIT state (draining data 208 * out of the TCP buffers after foreign close) and there 209 * is no more data, institute a close. 210 */ 211 case IURECV: 212 if (nstate < ESTAB || nstate == CLOSED) 213 goto bad; 214 tcp_sndwin(tp); 215 if ((tp->tc_flags&TC_FIN_RCVD) && 216 (tp->tc_flags&TC_USR_CLOSED) == 0 && 217 rcv_empty(tp)) 218 to_user(tp, UCLOSED); 219 if (nstate == RCV_WAIT && rcv_empty(tp)) { 220 tcp_close(tp, UCLOSED); 221 nstate = CLOSED; 222 } 223 break; 224 225 /* 226 * Send request on open connection. 227 * Should not happen if the connection is not yet established. 228 * Allowed only on ESTAB connection and after FIN from 229 * foreign peer. 230 */ 231 case IUSEND: 232 switch (nstate) { 233 234 case ESTAB: 235 case CLOSE_WAIT: 236 nstate = tcp_usrsend(tp, m); 237 break; 238 239 default: 240 if (nstate < ESTAB) 241 goto bad; 242 to_user(tp, UCLSERR); 243 break; 244 } 245 break; 246 247 /* 248 * User abort of connection. 249 * If a SYN has been received, but we have not exchanged FINs 250 * then we need to send an RST. In any case we then 251 * enter closed state. 252 */ 253 case IUABORT: 254 if (nstate == 0 || nstate == CLOSED) 255 break; 256 switch (nstate) { 257 258 case 0: 259 case CLOSED: 260 break; 261 262 case SYN_RCVD: 263 case ESTAB: 264 case FIN_W1: 265 case FIN_W2: 266 case CLOSE_WAIT: 267 tp->tc_flags |= TC_SND_RST; 268 tcp_sndnull(tp); 269 /* fall into ... */ 270 271 default: 272 tcp_close(tp, UABORT); 273 nstate = CLOSED; 274 } 275 break; 276 277 /* 278 * Network down entry. Discard the tcb and force 279 * the state to be closed, ungracefully. 280 */ 281 case INCLEAR: 282 if (nstate == 0 || nstate == CLOSED) 283 break; 284 tcp_close(tp, UNETDWN); 285 nstate = CLOSED; 286 break; 287 288 default: 289 panic("tcp_usrreq"); 290 bad: 291 printf("tcp: bad state: tcb=%x state=%d input=%d\n", 292 tp, tp->t_state, input); 293 nstate = EFAILEC; 294 break; 295 } 296 #ifdef TCPDEBUG 297 if (tdb.td_tod) 298 tdb_stuff(&tdb, nstate); 299 #endif 300 /* YECH */ 301 switch (nstate) { 302 303 case CLOSED: 304 case SAME: 305 break; 306 307 case EFAILEC: 308 if (m) 309 m_freem(dtom(m)); 310 break; 311 312 default: 313 tp->t_state = nstate; 314 break; 315 } 316 splx(s); 317 } 318 319 /* 320 * Open routine, called to initialize newly created tcb fields. 321 */ 322 tcp_open(tp, mode) 323 register struct tcb *tp; 324 int mode; 325 { 326 register struct ucb *up = tp->t_ucb; 327 COUNT(TCP_OPEN); 328 329 /* 330 * Link in tcb queue and make 331 * initialize empty reassembly queue. 332 */ 333 tp->tcb_next = tcb.tcb_next; 334 tcb.tcb_next->tcb_prev = tp; 335 tp->tcb_prev = (struct tcb *)&tcb; 336 tcb.tcb_next = tp; 337 tp->t_rcv_next = tp->t_rcv_prev = (struct th *)tp; 338 339 /* 340 * Initialize sequence numbers and 341 * round trip retransmit timer. 342 * (Other fields were init'd to zero when tcb allocated.) 343 */ 344 tp->t_xmtime = T_REXMT; 345 tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una = 346 tp->iss = tcp_iss; 347 tp->snd_off = tp->iss + 1; 348 tcp_iss += (ISSINCR >> 1) + 1; 349 350 /* 351 * Set timeout for open. 352 * SHOULD THIS BE A HIGHER LEVEL FUNCTION!?! THINK SO. 353 */ 354 if (up->uc_timeo) 355 tp->t_init = up->uc_timeo; 356 else if (mode == ACTIVE) 357 tp->t_init = T_INIT; 358 /* else 359 tp->t_init = 0; */ 360 up->uc_timeo = 0; /* ### */ 361 } 362 363 /* 364 * Internal close of a connection, shutting down the tcb. 365 */ 366 tcp_close(tp, state) 367 register struct tcb *tp; 368 short state; 369 { 370 register struct ucb *up = tp->t_ucb; 371 register struct th *t; 372 register struct mbuf *m; 373 COUNT(TCP_CLOSE); 374 375 /* 376 * Remove from tcb queue and cancel timers. 377 */ 378 tp->tcb_prev->tcb_next = tp->tcb_next; 379 tp->tcb_next->tcb_prev = tp->tcb_prev; 380 tcp_tcancel(tp); 381 382 /* 383 * Discard all buffers. 384 */ 385 for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next) 386 m_freem(dtom(t)); 387 if (up->uc_rbuf) { 388 m_freem(up->uc_rbuf); 389 up->uc_rbuf = NULL; 390 } 391 up->uc_rcc = 0; 392 if (up->uc_sbuf) { 393 m_freem(up->uc_sbuf); 394 up->uc_sbuf = NULL; 395 } 396 up->uc_ssize = 0; 397 for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) { 398 m_freem(m); 399 tp->t_rcv_unack = NULL; 400 } 401 402 /* 403 * Free tcp send template, the tcb itself, 404 * the routing table entry, and the space we had reserved 405 * in the meory pool. 406 */ 407 if (tp->t_template) { 408 m_free(dtom(tp->t_template)); 409 tp->t_template = 0; 410 } 411 wmemfree((caddr_t)tp, 1024); 412 up->uc_pcb = 0; 413 if (up->uc_host) { 414 h_free(up->uc_host); 415 up->uc_host = 0; 416 } 417 m_release(up->uc_snd + (up->uc_rhiwat/MSIZE) + 2); 418 419 /* 420 * If user has initiated close (via close call), delete ucb 421 * entry, otherwise just wakeup so user can issue close call 422 */ 423 if (tp->tc_flags&TC_USR_ABORT) /* ### */ 424 up->uc_proc = NULL; /* ### */ 425 else /* ### */ 426 to_user(up, state); /* ### */ 427 } 428 429 /* 430 * Send data queue headed by m0 into the protocol. 431 */ 432 tcp_usrsend(tp, m0) 433 register struct tcb *tp; 434 struct mbuf *m0; 435 { 436 register struct mbuf *m, *n; 437 register struct ucb *up = tp->t_ucb; 438 register off; 439 seq_t last; 440 COUNT(TCP_USRSEND); 441 442 last = tp->snd_off; 443 for (m = n = m0; m != NULL; m = m->m_next) { 444 up->uc_ssize++; 445 if (m->m_off > MMAXOFF) 446 up->uc_ssize += NMBPG; 447 last += m->m_len; 448 } 449 if ((m = up->uc_sbuf) == NULL) 450 up->uc_sbuf = n; 451 else { 452 while (m->m_next != NULL) { 453 m = m->m_next; 454 last += m->m_len; 455 } 456 if (m->m_off <= MMAXOFF) { 457 last += m->m_len; 458 off = m->m_off + m->m_len; 459 while (n && n->m_off <= MMAXOFF && 460 (MMAXOFF - off) >= n->m_len) { 461 bcopy((caddr_t)((int)n + n->m_off), 462 (caddr_t)((int)m + off), n->m_len); 463 m->m_len += n->m_len; 464 off += n->m_len; 465 up->uc_ssize--; 466 n = m_free(n); 467 } 468 } 469 m->m_next = n; 470 } 471 if (up->uc_flags & UEOL) 472 tp->snd_end = last; 473 if (up->uc_flags & UURG) { 474 tp->snd_urp = last+1; 475 tp->tc_flags |= TC_SND_URG; 476 } 477 tcp_send(tp); 478 return (SAME); 479 } 480 481 /* 482 * TCP timer went off processing. 483 */ 484 tcp_timers(tp, timertype) 485 register struct tcb *tp; 486 int timertype; 487 { 488 489 COUNT(TCP_TIMERS); 490 switch (timertype) { 491 492 case TINIT: /* initialization timer */ 493 if ((tp->tc_flags&TC_SYN_ACKED) == 0) { /* 35 */ 494 tcp_close(tp, UINTIMO); 495 return (CLOSED); 496 } 497 return (SAME); 498 499 case TFINACK: /* fin-ack timer */ 500 switch (tp->t_state) { 501 502 case TIME_WAIT: 503 /* 504 * We can be sure our ACK of foreign FIN was rcvd, 505 * and can close if no data left for user. 506 */ 507 if (rcv_empty(tp)) { 508 tcp_close(tp, UCLOSED); /* 14 */ 509 return (CLOSED); 510 } 511 return (RCV_WAIT); /* 17 */ 512 513 case CLOSING: 514 tp->tc_flags |= TC_WAITED_2_ML; 515 return (SAME); 516 517 default: 518 return (SAME); 519 } 520 521 case TREXMT: /* retransmission timer */ 522 if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ 523 /* 524 * Set up for a retransmission, increase rexmt time 525 * in case of multiple retransmissions. 526 */ 527 tp->snd_nxt = tp->snd_una; 528 tp->tc_flags |= TC_REXMT; 529 tp->t_xmtime = tp->t_xmtime << 1; 530 if (tp->t_xmtime > T_REMAX) 531 tp->t_xmtime = T_REMAX; 532 tcp_send(tp); 533 } 534 return (SAME); 535 536 case TREXMTTL: /* retransmit too long */ 537 if (tp->t_rtl_val > tp->snd_una) /* 36 */ 538 to_user(tp->t_ucb, URXTIMO); 539 /* 540 * If user has already closed, abort the connection. 541 */ 542 if (tp->tc_flags & TC_USR_CLOSED) { 543 tcp_close(tp, URXTIMO); 544 return (CLOSED); 545 } 546 return (SAME); 547 548 case TPERSIST: /* persist timer */ 549 /* 550 * Force a byte send through closed window. 551 */ 552 tp->tc_flags |= TC_FORCE_ONE; 553 tcp_send(tp); 554 return (SAME); 555 } 556 panic("tcp_timers"); 557 } 558 559 /* THIS ROUTINE IS A CROCK */ 560 to_user(up, state) 561 register struct ucb *up; 562 register short state; 563 { 564 COUNT(TO_USER); 565 566 up->uc_state |= state; 567 netwakeup(up); 568 if (state == UURGENT) 569 psignal(up->uc_proc, SIGURG); 570 } 571 572 #ifdef TCPDEBUG 573 /* 574 * TCP debugging utility subroutines. 575 * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID. 576 */ 577 tdb_setup(tp, n, input, tdp) 578 struct tcb *tp; 579 register struct th *n; 580 int input; 581 register struct tcp_debug *tdp; 582 { 583 584 COUNT(TDB_SETUP); 585 tdp->td_tod = time; 586 tdp->td_tcb = tp; 587 tdp->td_old = tp->t_state; 588 tdp->td_inp = input; 589 tdp->td_tim = 0; 590 tdp->td_new = -1; 591 if (n) { 592 tdp->td_sno = n->t_seq; 593 tdp->td_ano = n->t_ackno; 594 tdp->td_wno = n->t_win; 595 tdp->td_lno = n->t_len; 596 tdp->td_flg = n->th_flags; 597 } else 598 tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno = 599 tdp->td_flg = 0; 600 } 601 602 tdb_stuff(tdp, nstate) 603 struct tcp_debug *tdp; 604 int nstate; 605 { 606 COUNT(TDB_STUFF); 607 608 tdp->td_new = nstate; 609 tcp_debug[tdbx++ % TDBSIZE] = *tdp; 610 if (tcpconsdebug & 2) 611 tcp_prt(tdp); 612 } 613 614 tcp_prt(tdp) 615 register struct tcp_debug *tdp; 616 { 617 COUNT(TCP_PRT); 618 619 printf("%x ", ((int)tdp->td_tcb)&0xffffff); 620 if (tdp->td_inp == INSEND) { 621 printf("SEND #%x", tdp->td_sno); 622 tdp->td_lno = ntohs(tdp->td_lno); 623 tdp->td_wno = ntohs(tdp->td_wno); 624 } else { 625 if (tdp->td_inp == INRECV) 626 printf("RCV #%x ", tdp->td_sno); 627 printf("%s.%s", 628 tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]); 629 if (tdp->td_inp == ISTIMER) 630 printf("(%s)", tcptimers[tdp->td_tim]); 631 printf(" -> %s", 632 tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]); 633 if (tdp->td_new == -1) 634 printf(" (FAILED)"); 635 } 636 /* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */ 637 if (tdp->td_lno) 638 printf(" len=%d", tdp->td_lno); 639 if (tdp->td_wno) 640 printf(" win=%d", tdp->td_wno); 641 if (tdp->td_flg & TH_FIN) printf(" FIN"); 642 if (tdp->td_flg & TH_SYN) printf(" SYN"); 643 if (tdp->td_flg & TH_RST) printf(" RST"); 644 if (tdp->td_flg & TH_EOL) printf(" EOL"); 645 if (tdp->td_flg & TH_ACK) printf(" ACK %x", tdp->td_ano); 646 if (tdp->td_flg & TH_URG) printf(" URG"); 647 printf("\n"); 648 } 649 #endif 650