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