1 /* tcp_usrreq.c 1.22 81/10/31 */ 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 COUNT(TCP_TIMEO); 23 24 /* 25 * Search through tcb's and update active timers. 26 */ 27 for (tp = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->tcb_next) { 28 if (tp->t_init != 0 && --tp->t_init == 0) 29 tcp_usrreq(ISTIMER, TINIT, tp, 0); 30 if (tp->t_rexmt != 0 && --tp->t_rexmt == 0) 31 tcp_usrreq(ISTIMER, TREXMT, tp, 0); 32 if (tp->t_rexmttl != 0 && --tp->t_rexmttl == 0) 33 tcp_usrreq(ISTIMER, TREXMTTL, tp, 0); 34 if (tp->t_persist != 0 && --tp->t_persist == 0) 35 tcp_usrreq(ISTIMER, TPERSIST, tp, 0); 36 if (tp->t_finack != 0 && --tp->t_finack == 0) 37 tcp_usrreq(ISTIMER, TFINACK, tp, 0); 38 tp->t_xmt++; 39 } 40 tcp_iss += ISSINCR; /* increment iss */ 41 timeout(tcp_timeo, 0, hz); /* reschedule every second */ 42 splx(s); 43 } 44 45 tcp_usrreq(input, timertype, tp, mp) 46 int input, timertype; 47 register struct tcb *tp; 48 struct mbuf *mp; 49 { 50 int s = splnet(); 51 register int nstate; 52 #ifdef TCPDEBUG 53 struct tcp_debug tdb; 54 #endif 55 COUNT(TCP_USRREQ); 56 57 nstate = tp->t_state; 58 tp->tc_flags &= ~TC_NET_KEEP; 59 acounts[nstate][input]++; 60 #ifdef TCPDEBUG 61 if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 62 tdb_setup(tp, (struct th *)0, input, &tdb); 63 tdb.td_tim = timertype; 64 } else 65 tdb.td_tod = 0; 66 #endif 67 switch (tcp_fstab[nstate][input]) { 68 69 default: 70 printf("tcp: bad state: tcb=%x state=%d input=%d\n", 71 tp, tp->t_state, input); 72 nstate = EFAILEC; 73 break; 74 75 case LIS_CLS: /* 1 */ 76 tcp_open(tp, PASSIVE); 77 nstate = LISTEN; 78 break; 79 80 case SYS_CLS: /* 2 */ 81 tcp_open(tp, ACTIVE); 82 tcp_sndctl(tp); 83 nstate = SYN_SENT; 84 break; 85 86 case CLS_OPN: /* 10 */ 87 tcp_close(tp, UCLOSED); 88 nstate = CLOSED; 89 break; 90 91 case CL2_CLW: /* 10 */ 92 tp->tc_flags |= TC_SND_FIN; 93 tcp_sndctl(tp); 94 tp->tc_flags |= TC_USR_CLOSED; 95 nstate = CLOSING2; 96 break; 97 98 case TIMERS: /* 14,17,34,35,36,37,38 */ 99 nstate = tcp_timers(tp, timertype); 100 break; 101 102 case CLS_RWT: /* 20 */ 103 if ((tp->tc_flags&TC_FIN_RCVD) && 104 (tp->tc_flags&TC_USR_CLOSED) == 0 && 105 rcv_empty(tp)) 106 to_user(tp, UCLOSED); 107 if (rcv_empty(tp)) { 108 tcp_close(tp, UCLOSED); 109 nstate = CLOSED; 110 } else 111 nstate = RCV_WAIT; 112 break; 113 114 case FW1_SYR: /* 24,25 */ 115 tp->tc_flags |= TC_SND_FIN; 116 tcp_sndctl(tp); 117 tp->tc_flags |= TC_USR_CLOSED; 118 nstate = FIN_W1; 119 break; 120 121 case SSS_SND: /* 40,41 */ 122 nstate = tcp_usrsend(tp, mp); 123 break; 124 125 case SSS_RCV: /* 42 */ 126 tcp_sndwin(tp); /* send new window */ 127 if ((tp->tc_flags&TC_FIN_RCVD) && 128 (tp->tc_flags&TC_USR_CLOSED) == 0 && 129 rcv_empty(tp)) 130 to_user(tp, UCLOSED); 131 break; 132 133 case CLS_NSY: /* 44 */ 134 tcp_close(tp, UABORT); 135 nstate = CLOSED; 136 break; 137 138 case CLS_SYN: /* 45 */ 139 tp->tc_flags |= TC_SND_RST; 140 tcp_sndnull(tp); 141 tcp_close(tp, UABORT); 142 nstate = CLOSED; 143 break; 144 145 case CLS_ACT: /* 47 */ 146 tcp_close(tp, UNETDWN); 147 nstate = CLOSED; 148 break; 149 150 case NOP: 151 break; 152 153 case CLS_ERR: 154 to_user(tp->t_ucb, UCLSERR); 155 break; 156 } 157 #ifdef TCPDEBUG 158 if (tdb.td_tod) 159 tdb_stuff(&tdb, nstate); 160 #endif 161 /* YECH */ 162 switch (nstate) { 163 164 case CLOSED: 165 case SAME: 166 break; 167 168 case EFAILEC: 169 if (mp) 170 m_freem(dtom(mp)); 171 break; 172 173 default: 174 tp->t_state = nstate; 175 break; 176 } 177 splx(s); 178 } 179 180 /* 181 * Open routine, called to initialize newly created tcb fields. 182 */ 183 tcp_open(tp, mode) 184 register struct tcb *tp; 185 int mode; 186 { 187 register struct ucb *up = tp->t_ucb; 188 COUNT(TCP_OPEN); 189 190 /* 191 * Link in tcb queue and make 192 * initialize empty reassembly queue. 193 */ 194 tp->tcb_next = tcb.tcb_next; 195 tcb.tcb_next->tcb_prev = tp; 196 tp->tcb_prev = (struct tcb *)&tcb; 197 tcb.tcb_next = tp; 198 tp->t_rcv_next = tp->t_rcv_prev = (struct th *)tp; 199 200 /* 201 * Initialize sequence numbers and 202 * round trip retransmit timer. 203 * (Other fields were init'd to zero when tcb allocated.) 204 */ 205 tp->t_xmtime = T_REXMT; 206 tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una = 207 tp->iss = tcp_iss; 208 tp->snd_off = tp->iss + 1; 209 tcp_iss += (ISSINCR >> 1) + 1; 210 211 /* 212 * Set timeout for open. 213 * SHOULD THIS BE A HIGHER LEVEL FUNCTION!?! THINK SO. 214 */ 215 if (up->uc_timeo) 216 tp->t_init = up->uc_timeo; 217 else if (mode == ACTIVE) 218 tp->t_init = T_INIT; 219 /* else 220 tp->t_init = 0; */ 221 up->uc_timeo = 0; /* ### */ 222 } 223 224 /* 225 * Internal close of a connection, shutting down the tcb. 226 */ 227 tcp_close(tp, state) 228 register struct tcb *tp; 229 short state; 230 { 231 register struct ucb *up = tp->t_ucb; 232 register struct th *t; 233 register struct mbuf *m; 234 COUNT(TCP_CLOSE); 235 236 /* 237 * Cancel all timers. 238 * SHOULD LOOP HERE !?! 239 */ 240 tp->t_init = tp->t_rexmt = tp->t_rexmttl = tp->t_persist = 241 tp->t_finack = 0; 242 243 /* 244 * Remque the tcb 245 */ 246 tp->tcb_prev->tcb_next = tp->tcb_next; 247 tp->tcb_next->tcb_prev = tp->tcb_prev; 248 249 /* 250 * Discard all buffers... 251 * 252 * SHOULD COUNT EACH RESOURCE TO 0 AND PANIC IF CONFUSED 253 */ 254 for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next) 255 m_freem(dtom(t)); 256 if (up->uc_rbuf != NULL) { 257 m_freem(up->uc_rbuf); 258 up->uc_rbuf = NULL; 259 } 260 up->uc_rcc = 0; 261 if (up->uc_sbuf != NULL) { 262 m_freem(up->uc_sbuf); 263 up->uc_sbuf = NULL; 264 } 265 up->uc_ssize = 0; 266 for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) { 267 m_freem(m); 268 tp->t_rcv_unack = NULL; 269 } 270 271 /* 272 * Free tcp send template. 273 */ 274 if (up->uc_template) { 275 m_free(dtom(up->uc_template)); 276 up->uc_template = 0; 277 } 278 279 /* 280 * Free the tcb 281 * WOULD THIS BETTER BE DONE AT USER CLOSE? 282 */ 283 wmemfree((caddr_t)tp, 1024); 284 up->uc_tcb = NULL; 285 286 /* 287 * Lower buffer allocation. 288 * SHOULD BE A M_ROUTINE CALL. 289 */ 290 mbstat.m_lowat -= up->uc_snd + (up->uc_rhiwat/MSIZE) + 2; 291 mbstat.m_hiwat = 2 * mbstat.m_lowat; 292 293 /* 294 * Free routing table entry. 295 */ 296 if (up->uc_host != NULL) { 297 h_free(up->uc_host); 298 up->uc_host = NULL; 299 } 300 301 /* 302 * If user has initiated close (via close call), delete ucb 303 * entry, otherwise just wakeup so user can issue close call 304 */ 305 if (tp->tc_flags&TC_USR_ABORT) 306 up->uc_proc = NULL; 307 else 308 to_user(up, state); /* ### */ 309 } 310 311 /* 312 * User routine to send data queue headed by m0 into the protocol. 313 */ 314 tcp_usrsend(tp, m0) 315 register struct tcb *tp; 316 struct mbuf *m0; 317 { 318 register struct mbuf *m, *n; 319 register struct ucb *up = tp->t_ucb; 320 register off; 321 seq_t last; 322 COUNT(TCP_USRSEND); 323 324 last = tp->snd_off; 325 for (m = n = m0; m != NULL; m = m->m_next) { 326 up->uc_ssize++; 327 if (m->m_off > MMAXOFF) 328 up->uc_ssize += NMBPG; 329 last += m->m_len; 330 } 331 if ((m = up->uc_sbuf) == NULL) 332 up->uc_sbuf = n; 333 else { 334 while (m->m_next != NULL) { 335 m = m->m_next; 336 last += m->m_len; 337 } 338 if (m->m_off <= MMAXOFF) { 339 last += m->m_len; 340 off = m->m_off + m->m_len; 341 while (n && n->m_off <= MMAXOFF && 342 (MMAXOFF - off) >= n->m_len) { 343 bcopy((caddr_t)((int)n + n->m_off), 344 (caddr_t)((int)m + off), n->m_len); 345 m->m_len += n->m_len; 346 off += n->m_len; 347 up->uc_ssize--; 348 n = m_free(n); 349 } 350 } 351 m->m_next = n; 352 } 353 if (up->uc_flags & UEOL) 354 tp->snd_end = last; 355 if (up->uc_flags & UURG) { 356 tp->snd_urp = last+1; 357 tp->tc_flags |= TC_SND_URG; 358 } 359 tcp_send(tp); 360 return (SAME); 361 } 362 363 /* 364 * TCP timer went off processing. 365 */ 366 tcp_timers(tp, timertype) 367 register struct tcb *tp; 368 int timertype; 369 { 370 371 COUNT(TCP_TIMERS); 372 switch (timertype) { 373 374 case TINIT: /* initialization timer */ 375 if ((tp->tc_flags&TC_SYN_ACKED) == 0) { /* 35 */ 376 tcp_close(tp, UINTIMO); 377 return (CLOSED); 378 } 379 return (SAME); 380 381 case TFINACK: /* fin-ack timer */ 382 switch (tp->t_state) { 383 384 case TIME_WAIT: 385 /* 386 * We can be sure our ACK of foreign FIN was rcvd, 387 * and can close if no data left for user. 388 */ 389 if (rcv_empty(tp)) { 390 tcp_close(tp, UCLOSED); /* 14 */ 391 return (CLOSED); 392 } 393 return (RCV_WAIT); /* 17 */ 394 395 case CLOSING1: 396 tp->tc_flags |= TC_WAITED_2_ML; 397 return (SAME); 398 399 default: 400 return (SAME); 401 } 402 403 case TREXMT: /* retransmission timer */ 404 if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ 405 /* 406 * Set up for a retransmission, increase rexmt time 407 * in case of multiple retransmissions. 408 */ 409 tp->snd_nxt = tp->snd_una; 410 tp->tc_flags |= TC_REXMT; 411 tp->t_xmtime = tp->t_xmtime << 1; 412 if (tp->t_xmtime > T_REMAX) 413 tp->t_xmtime = T_REMAX; 414 tcp_send(tp); 415 } 416 return (SAME); 417 418 case TREXMTTL: /* retransmit too long */ 419 if (tp->t_rtl_val > tp->snd_una) /* 36 */ 420 to_user(tp->t_ucb, URXTIMO); 421 /* 422 * If user has already closed, abort the connection. 423 */ 424 if (tp->tc_flags & TC_USR_CLOSED) { 425 tcp_close(tp, URXTIMO); 426 return (CLOSED); 427 } 428 return (SAME); 429 430 case TPERSIST: /* persist timer */ 431 /* 432 * Force a byte send through closed window. 433 */ 434 tp->tc_flags |= TC_FORCE_ONE; 435 tcp_send(tp); 436 return (SAME); 437 } 438 panic("tcp_timers"); 439 } 440 441 /* THIS ROUTINE IS A CROCK */ 442 to_user(up, state) 443 register struct ucb *up; 444 register short state; 445 { 446 COUNT(TO_USER); 447 448 up->uc_state |= state; 449 netwakeup(up); 450 if (state == UURGENT) 451 psignal(up->uc_proc, SIGURG); 452 } 453 454 #ifdef TCPDEBUG 455 /* 456 * TCP debugging utility subroutines. 457 * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID. 458 */ 459 tdb_setup(tp, n, input, tdp) 460 struct tcb *tp; 461 register struct th *n; 462 int input; 463 register struct tcp_debug *tdp; 464 { 465 466 COUNT(TDB_SETUP); 467 tdp->td_tod = time; 468 tdp->td_tcb = tp; 469 tdp->td_old = tp->t_state; 470 tdp->td_inp = input; 471 tdp->td_tim = 0; 472 tdp->td_new = -1; 473 if (n) { 474 tdp->td_sno = n->t_seq; 475 tdp->td_ano = n->t_ackno; 476 tdp->td_wno = n->t_win; 477 tdp->td_lno = n->t_len; 478 tdp->td_flg = n->th_flags; 479 } else 480 tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno = 481 tdp->td_flg = 0; 482 } 483 484 tdb_stuff(tdp, nstate) 485 struct tcp_debug *tdp; 486 int nstate; 487 { 488 COUNT(TDB_STUFF); 489 490 tdp->td_new = nstate; 491 tcp_debug[tdbx++ % TDBSIZE] = *tdp; 492 if (tcpconsdebug & 2) 493 tcp_prt(tdp); 494 } 495 496 tcp_prt(tdp) 497 register struct tcp_debug *tdp; 498 { 499 COUNT(TCP_PRT); 500 501 printf("%x ", ((int)tdp->td_tcb)&0xffffff); 502 if (tdp->td_inp == INSEND) { 503 printf("SEND #%x", tdp->td_sno); 504 tdp->td_lno = ntohs(tdp->td_lno); 505 tdp->td_wno = ntohs(tdp->td_wno); 506 } else { 507 if (tdp->td_inp == INRECV) 508 printf("RCV #%x ", tdp->td_sno); 509 printf("%s.%s", 510 tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]); 511 if (tdp->td_inp == ISTIMER) 512 printf("(%s)", tcptimers[tdp->td_tim]); 513 printf(" -> %s", 514 tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]); 515 if (tdp->td_new == -1) 516 printf(" (FAILED)"); 517 } 518 /* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */ 519 if (tdp->td_lno) 520 printf(" len=%d", tdp->td_lno); 521 if (tdp->td_wno) 522 printf(" win=%d", tdp->td_wno); 523 if (tdp->td_flg & TH_FIN) printf(" FIN"); 524 if (tdp->td_flg & TH_SYN) printf(" SYN"); 525 if (tdp->td_flg & TH_RST) printf(" RST"); 526 if (tdp->td_flg & TH_EOL) printf(" EOL"); 527 if (tdp->td_flg & TH_ACK) printf(" ACK %x", tdp->td_ano); 528 if (tdp->td_flg & TH_URG) printf(" URG"); 529 printf("\n"); 530 } 531 #endif 532