1 /* tcp_usrreq.c 1.14 81/10/29 */ 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_head; tp != NULL; tp = tp->t_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 t_open(tp, PASSIVE); 77 nstate = LISTEN; 78 break; 79 80 case SYS_CLS: /* 2 */ 81 t_open(tp, ACTIVE); 82 send_ctl(tp); 83 nstate = SYN_SENT; 84 break; 85 86 case CLS_OPN: /* 10 */ 87 t_close(tp, UCLOSED); 88 nstate = CLOSED; 89 break; 90 91 case CL2_CLW: /* 10 */ 92 tp->tc_flags |= TC_SND_FIN; 93 send_ctl(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 t_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 send_ctl(tp); 114 tp->tc_flags |= TC_USR_CLOSED; 115 nstate = FIN_W1; 116 break; 117 118 case SSS_SND: /* 40,41 */ 119 nstate = sss_send(tp, mp); 120 break; 121 122 case SSS_RCV: /* 42 */ 123 send_ctl(tp); /* send new window */ 124 present_data(tp); 125 break; 126 127 case CLS_NSY: /* 44 */ 128 t_close(tp, UABORT); 129 nstate = CLOSED; 130 break; 131 132 case CLS_SYN: /* 45 */ 133 tp->tc_flags |= TC_SND_RST; 134 send_null(tp); 135 t_close(tp, UABORT); 136 nstate = CLOSED; 137 break; 138 139 case CLS_ACT: /* 47 */ 140 t_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 t_open(tp, mode) /* set up a tcb for a connection */ 175 register struct tcb *tp; 176 int mode; 177 { 178 register struct ucb *up; 179 COUNT(T_OPEN); 180 181 /* enqueue the tcb */ 182 183 if (tcb_head == NULL) { 184 tcb_head = tp; 185 tcb_tail = tp; 186 } else { 187 tp->t_tcb_next = tcb_head; 188 tcb_head->t_tcb_prev = tp; 189 tcb_head = tp; 190 } 191 192 /* initialize non-zero tcb fields */ 193 194 tp->t_rcv_next = (struct th *)tp; 195 tp->t_rcv_prev = (struct th *)tp; 196 tp->t_xmtime = T_REXMT; 197 tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = 198 tp->snd_una = tp->iss = tcp_iss; 199 tp->snd_off = tp->iss + 1; 200 tcp_iss += (ISSINCR >> 1) + 1; 201 202 /* set timeout for open */ 203 204 up = tp->t_ucb; 205 tp->t_init = (up->uc_timeo != 0 ? up->uc_timeo : 206 (mode == ACTIVE ? T_INIT : 0)); 207 up->uc_timeo = 0; /* overlays uc_ssize */ 208 } 209 210 t_close(tp, state) 211 register struct tcb *tp; 212 short state; 213 { 214 register struct ucb *up; 215 register struct th *t; 216 register struct mbuf *m; 217 COUNT(T_CLOSE); 218 219 up = tp->t_ucb; 220 221 tp->t_init = tp->t_rexmt = tp->t_rexmttl = tp->t_persist = 222 tp->t_finack = 0; 223 224 /* delete tcb */ 225 226 if (tp->t_tcb_prev == NULL) 227 tcb_head = tp->t_tcb_next; 228 else 229 tp->t_tcb_prev->t_tcb_next = tp->t_tcb_next; 230 if (tp->t_tcb_next == NULL) 231 tcb_tail = tp->t_tcb_prev; 232 else 233 tp->t_tcb_next->t_tcb_prev = tp->t_tcb_prev; 234 235 /* free all data on receive and send buffers */ 236 237 for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next) 238 m_freem(dtom(t)); 239 240 if (up->uc_rbuf != NULL) { 241 m_freem(up->uc_rbuf); 242 up->uc_rbuf = NULL; 243 } 244 up->uc_rcc = 0; 245 if (up->uc_sbuf != NULL) { 246 m_freem(up->uc_sbuf); 247 up->uc_sbuf = NULL; 248 } 249 up->uc_ssize = 0; 250 for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) { 251 m_freem(m); 252 tp->t_rcv_unack = NULL; 253 } 254 if (up->uc_template) { 255 m_free(dtom(up->uc_template)); 256 up->uc_template = 0; 257 } 258 m = dtom(tp); 259 m->m_off = 0; 260 m_free(m); 261 up->uc_tcb = NULL; 262 263 /* lower buffer allocation and decrement host entry */ 264 265 mbstat.m_lowat -= up->uc_snd + (up->uc_rhiwat/MSIZE) + 2; 266 mbstat.m_hiwat = 2 * mbstat.m_lowat; 267 if (up->uc_host != NULL) { 268 h_free(up->uc_host); 269 up->uc_host = NULL; 270 } 271 272 /* if user has initiated close (via close call), delete ucb 273 entry, otherwise just wakeup so user can issue close call */ 274 275 if (tp->tc_flags&TC_USR_ABORT) 276 up->uc_proc = NULL; 277 else 278 to_user(up, state); 279 } 280 281 sss_send(tp, m0) 282 register struct tcb *tp; 283 struct mbuf *m0; 284 { 285 register struct mbuf *m, *n; 286 register struct ucb *up = tp->t_ucb; 287 register off; 288 seq_t last; 289 COUNT(SSS_SEND); 290 291 last = tp->snd_off; 292 for (m = n = m0; m != NULL; m = m->m_next) { 293 up->uc_ssize++; 294 if (m->m_off > MMAXOFF) 295 up->uc_ssize += NMBPG; 296 last += m->m_len; 297 } 298 if ((m = up->uc_sbuf) == NULL) 299 up->uc_sbuf = n; 300 else { 301 while (m->m_next != NULL) { 302 m = m->m_next; 303 last += m->m_len; 304 } 305 if (m->m_off <= MMAXOFF) { 306 last += m->m_len; 307 off = m->m_off + m->m_len; 308 while (n && n->m_off <= MMAXOFF && 309 (MMAXOFF - off) >= n->m_len) { 310 bcopy((caddr_t)((int)n + n->m_off), 311 (caddr_t)((int)m + off), n->m_len); 312 m->m_len += n->m_len; 313 off += n->m_len; 314 up->uc_ssize--; 315 n = m_free(n); 316 } 317 } 318 m->m_next = n; 319 } 320 if (up->uc_flags & UEOL) 321 tp->snd_end = last; 322 if (up->uc_flags & UURG) { 323 tp->snd_urp = last+1; 324 tp->tc_flags |= TC_SND_URG; 325 } 326 send(tp); 327 return (SAME); 328 } 329 330 tcp_timers(tp, timertype) 331 register struct tcb *tp; 332 int timertype; 333 { 334 335 COUNT(TCP_TIMERS); 336 switch (timertype) { 337 338 case TINIT: /* initialization timer */ 339 if ((tp->tc_flags&TC_SYN_ACKED) == 0) { /* 35 */ 340 t_close(tp, UINTIMO); 341 return (CLOSED); 342 } 343 return (SAME); 344 345 case TFINACK: /* fin-ack timer */ 346 switch (tp->t_state) { 347 348 case TIME_WAIT: 349 /* 350 * We can be sure our ACK of foreign FIN was rcvd, 351 * and can close if no data left for user. 352 */ 353 if (rcv_empty(tp)) { 354 t_close(tp, UCLOSED); /* 14 */ 355 return (CLOSED); 356 } 357 return (RCV_WAIT); /* 17 */ 358 359 case CLOSING1: 360 tp->tc_flags |= TC_WAITED_2_ML; 361 return (SAME); 362 363 default: 364 return (SAME); 365 } 366 367 case TREXMT: /* retransmission timer */ 368 if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ 369 /* 370 * Set up for a retransmission, increase rexmt time 371 * in case of multiple retransmissions. 372 */ 373 tp->snd_nxt = tp->snd_una; 374 tp->tc_flags |= TC_REXMT; 375 tp->t_xmtime = tp->t_xmtime << 1; 376 if (tp->t_xmtime > T_REMAX) 377 tp->t_xmtime = T_REMAX; 378 send(tp); 379 } 380 return (SAME); 381 382 case TREXMTTL: /* retransmit too long */ 383 if (tp->t_rtl_val > tp->snd_una) /* 36 */ 384 to_user(tp->t_ucb, URXTIMO); 385 /* 386 * If user has already closed, abort the connection. 387 */ 388 if (tp->tc_flags & TC_USR_CLOSED) { 389 t_close(tp, URXTIMO); 390 return (CLOSED); 391 } 392 return (SAME); 393 394 case TPERSIST: /* persist timer */ 395 /* 396 * Force a byte send through closed window. 397 */ 398 tp->tc_flags |= TC_FORCE_ONE; 399 send(tp); 400 return (SAME); 401 } 402 panic("tcp_timers"); 403 } 404 405 /* THIS ROUTINE IS A CROCK */ 406 to_user(up, state) 407 register struct ucb *up; 408 register short state; 409 { 410 COUNT(TO_USER); 411 412 up->uc_state |= state; 413 netwakeup(up); 414 if (state == UURGENT) 415 psignal(up->uc_proc, SIGURG); 416 } 417 418 #ifdef TCPDEBUG 419 tcp_prt(tdp) 420 register struct tcp_debug *tdp; 421 { 422 COUNT(TCP_PRT); 423 424 printf("TCP(%x) %s x %s", 425 tdp->td_tcb, tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]); 426 if (tdp->td_inp == ISTIMER) 427 printf("(%s)", tcptimers[tdp->td_tim]); 428 printf(" --> %s", 429 tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]); 430 /* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */ 431 if (tdp->td_new < 0) 432 printf(" (FAILED)"); 433 if (tdp->td_sno) { 434 printf(" sno %x ano %x win %d len %d flags %x", 435 tdp->td_sno, tdp->td_ano, tdp->td_wno, tdp->td_lno, tdp->td_flg); 436 } 437 printf("\n"); 438 } 439 #endif 440