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