1 /* tcp_usrreq.c 1.13 81/10/29 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../bbnnet/net.h" 6 #include "../bbnnet/mbuf.h" 7 #include "../bbnnet/tcp.h" 8 #include "../bbnnet/ip.h" 9 #include "../bbnnet/imp.h" 10 #include "../bbnnet/ucb.h" 11 #define TCPFSTAB 12 #ifdef TCPDEBUG 13 #define TCPSTATES 14 #endif 15 #include "../bbnnet/fsm.h" 16 17 tcp_timeo() 18 { 19 register struct tcb *tp; 20 int s = splnet(); 21 COUNT(TCP_TIMEO); 22 23 /* 24 * Search through tcb's and update active timers. 25 */ 26 for (tp = netcb.n_tcb_head; tp != NULL; tp = tp->t_tcb_next) { 27 if (tp->t_init != 0 && --tp->t_init == 0) 28 tcp_usrreq(ISTIMER, TINIT, tp, 0); 29 if (tp->t_rexmt != 0 && --tp->t_rexmt == 0) 30 tcp_usrreq(ISTIMER, TREXMT, tp, 0); 31 if (tp->t_rexmttl != 0 && --tp->t_rexmttl == 0) 32 tcp_usrreq(ISTIMER, TREXMTTL, tp, 0); 33 if (tp->t_persist != 0 && --tp->t_persist == 0) 34 tcp_usrreq(ISTIMER, TPERSIST, tp, 0); 35 if (tp->t_finack != 0 && --tp->t_finack == 0) 36 tcp_usrreq(ISTIMER, TFINACK, tp, 0); 37 tp->t_xmt++; 38 } 39 netcb.n_iss += ISSINCR; /* increment iss */ 40 timeout(tcp_timeo, 0, hz); /* reschedule every second */ 41 splx(s); 42 } 43 44 tcp_usrreq(input, timertype, tp, mp) 45 int input, timertype; 46 register struct tcb *tp; 47 struct mbuf *mp; 48 { 49 int s = splnet(); 50 register int nstate; 51 #ifdef TCPDEBUG 52 struct tcp_debug tdb; 53 #endif 54 COUNT(TCP_USRREQ); 55 56 nstate = tp->t_state; 57 tp->tc_flags &= ~TC_NET_KEEP; 58 acounts[nstate][input]++; 59 #ifdef TCPDEBUG 60 if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 61 tdb_setup(tp, (struct th *)0, input, &tdb); 62 tdb.td_tim = timertype; 63 } else 64 tdb.td_tod = 0; 65 #endif 66 switch (tcp_fstab[nstate][input]) { 67 68 default: 69 printf("tcp: bad state: tcb=%x state=%d input=%d\n", 70 tp, tp->t_state, input); 71 nstate = EFAILEC; 72 break; 73 74 case LIS_CLS: /* 1 */ 75 t_open(tp, PASSIVE); 76 nstate = LISTEN; 77 break; 78 79 case SYS_CLS: /* 2 */ 80 t_open(tp, ACTIVE); 81 send_ctl(tp); 82 nstate = SYN_SENT; 83 break; 84 85 case CLS_OPN: /* 10 */ 86 t_close(tp, UCLOSED); 87 nstate = CLOSED; 88 break; 89 90 case CL2_CLW: /* 10 */ 91 tp->tc_flags |= TC_SND_FIN; 92 send_ctl(tp); 93 tp->tc_flags |= TC_USR_CLOSED; 94 nstate = CLOSING2; 95 break; 96 97 case TIMERS: /* 14,17,34,35,36,37,38 */ 98 nstate = tcp_timers(tp, timertype); 99 break; 100 101 case CLS_RWT: /* 20 */ 102 present_data(tp); 103 if (rcv_empty(tp)) { 104 t_close(tp, UCLOSED); 105 nstate = CLOSED; 106 } else 107 nstate = RCV_WAIT; 108 break; 109 110 case FW1_SYR: /* 24,25 */ 111 tp->tc_flags |= TC_SND_FIN; 112 send_ctl(tp); 113 tp->tc_flags |= TC_USR_CLOSED; 114 nstate = FIN_W1; 115 break; 116 117 case SSS_SND: /* 40,41 */ 118 nstate = sss_send(tp, mp); 119 break; 120 121 case SSS_RCV: /* 42 */ 122 send_ctl(tp); /* send new window */ 123 present_data(tp); 124 break; 125 126 case CLS_NSY: /* 44 */ 127 t_close(tp, UABORT); 128 nstate = CLOSED; 129 break; 130 131 case CLS_SYN: /* 45 */ 132 tp->tc_flags |= TC_SND_RST; 133 send_null(tp); 134 t_close(tp, UABORT); 135 nstate = CLOSED; 136 break; 137 138 case CLS_ACT: /* 47 */ 139 t_close(tp, UNETDWN); 140 nstate = CLOSED; 141 break; 142 143 case NOP: 144 break; 145 146 case CLS_ERR: 147 to_user(tp->t_ucb, UCLSERR); 148 break; 149 } 150 #ifdef TCPDEBUG 151 if (tdb.td_tod) 152 tdb_stuff(&tdb, nstate); 153 #endif 154 /* YECH */ 155 switch (nstate) { 156 157 case CLOSED: 158 case SAME: 159 break; 160 161 case EFAILEC: 162 if (mp) 163 m_freem(dtom(mp)); 164 break; 165 166 default: 167 tp->t_state = nstate; 168 break; 169 } 170 splx(s); 171 } 172 173 t_open(tp, mode) /* set up a tcb for a connection */ 174 register struct tcb *tp; 175 int mode; 176 { 177 register struct ucb *up; 178 COUNT(T_OPEN); 179 180 /* enqueue the tcb */ 181 182 if (netcb.n_tcb_head == NULL) { 183 netcb.n_tcb_head = tp; 184 netcb.n_tcb_tail = tp; 185 } else { 186 tp->t_tcb_next = netcb.n_tcb_head; 187 netcb.n_tcb_head->t_tcb_prev = tp; 188 netcb.n_tcb_head = tp; 189 } 190 191 /* initialize non-zero tcb fields */ 192 193 tp->t_rcv_next = (struct th *)tp; 194 tp->t_rcv_prev = (struct th *)tp; 195 tp->t_xmtime = T_REXMT; 196 tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = 197 tp->snd_una = tp->iss = netcb.n_iss; 198 tp->snd_off = tp->iss + 1; 199 netcb.n_iss += (ISSINCR >> 1) + 1; 200 201 /* set timeout for open */ 202 203 up = tp->t_ucb; 204 tp->t_init = (up->uc_timeo != 0 ? up->uc_timeo : 205 (mode == ACTIVE ? T_INIT : 0)); 206 up->uc_timeo = 0; /* overlays uc_ssize */ 207 } 208 209 t_close(tp, state) 210 register struct tcb *tp; 211 short state; 212 { 213 register struct ucb *up; 214 register struct th *t; 215 register struct mbuf *m; 216 COUNT(T_CLOSE); 217 218 up = tp->t_ucb; 219 220 tp->t_init = tp->t_rexmt = tp->t_rexmttl = tp->t_persist = 221 tp->t_finack = 0; 222 223 /* delete tcb */ 224 225 if (tp->t_tcb_prev == NULL) 226 netcb.n_tcb_head = tp->t_tcb_next; 227 else 228 tp->t_tcb_prev->t_tcb_next = tp->t_tcb_next; 229 if (tp->t_tcb_next == NULL) 230 netcb.n_tcb_tail = tp->t_tcb_prev; 231 else 232 tp->t_tcb_next->t_tcb_prev = tp->t_tcb_prev; 233 234 /* free all data on receive and send buffers */ 235 236 for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next) 237 m_freem(dtom(t)); 238 239 if (up->uc_rbuf != NULL) { 240 m_freem(up->uc_rbuf); 241 up->uc_rbuf = NULL; 242 } 243 up->uc_rcc = 0; 244 if (up->uc_sbuf != NULL) { 245 m_freem(up->uc_sbuf); 246 up->uc_sbuf = NULL; 247 } 248 up->uc_ssize = 0; 249 for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) { 250 m_freem(m); 251 tp->t_rcv_unack = NULL; 252 } 253 m = dtom(tp); 254 m->m_off = 0; 255 m_free(m); 256 up->uc_tcb = NULL; 257 258 /* lower buffer allocation and decrement host entry */ 259 260 netcb.n_lowat -= up->uc_snd + (up->uc_rhiwat/MSIZE) + 2; 261 netcb.n_hiwat = 2 * netcb.n_lowat; 262 if (up->uc_host != NULL) { 263 h_free(up->uc_host); 264 up->uc_host = NULL; 265 } 266 267 /* if user has initiated close (via close call), delete ucb 268 entry, otherwise just wakeup so user can issue close call */ 269 270 if (tp->tc_flags&TC_USR_ABORT) 271 up->uc_proc = NULL; 272 else 273 to_user(up, state); 274 } 275 276 sss_send(tp, m0) 277 register struct tcb *tp; 278 struct mbuf *m0; 279 { 280 register struct mbuf *m, *n; 281 register struct ucb *up = tp->t_ucb; 282 register off; 283 seq_t last; 284 COUNT(SSS_SEND); 285 286 last = tp->snd_off; 287 for (m = n = m0; m != NULL; m = m->m_next) { 288 up->uc_ssize++; 289 if (m->m_off > MMAXOFF) 290 up->uc_ssize += NMBPG; 291 last += m->m_len; 292 } 293 if ((m = up->uc_sbuf) == NULL) 294 up->uc_sbuf = n; 295 else { 296 while (m->m_next != NULL) { 297 m = m->m_next; 298 last += m->m_len; 299 } 300 if (m->m_off <= MMAXOFF) { 301 last += m->m_len; 302 off = m->m_off + m->m_len; 303 while (n && n->m_off <= MMAXOFF && 304 (MMAXOFF - off) >= n->m_len) { 305 bcopy((caddr_t)((int)n + n->m_off), 306 (caddr_t)((int)m + off), n->m_len); 307 m->m_len += n->m_len; 308 off += n->m_len; 309 up->uc_ssize--; 310 n = m_free(n); 311 } 312 } 313 m->m_next = n; 314 } 315 if (up->uc_flags & UEOL) 316 tp->snd_end = last; 317 if (up->uc_flags & UURG) { 318 tp->snd_urp = last+1; 319 tp->tc_flags |= TC_SND_URG; 320 } 321 send(tp); 322 return (SAME); 323 } 324 325 tcp_timers(tp, timertype) 326 register struct tcb *tp; 327 int timertype; 328 { 329 330 COUNT(TCP_TIMERS); 331 switch (timertype) { 332 333 case TINIT: /* initialization timer */ 334 if ((tp->tc_flags&TC_SYN_ACKED) == 0) { /* 35 */ 335 t_close(tp, UINTIMO); 336 return (CLOSED); 337 } 338 return (SAME); 339 340 case TFINACK: /* fin-ack timer */ 341 switch (tp->t_state) { 342 343 case TIME_WAIT: 344 /* 345 * We can be sure our ACK of foreign FIN was rcvd, 346 * and can close if no data left for user. 347 */ 348 if (rcv_empty(tp)) { 349 t_close(tp, UCLOSED); /* 14 */ 350 return (CLOSED); 351 } 352 return (RCV_WAIT); /* 17 */ 353 354 case CLOSING1: 355 tp->tc_flags |= TC_WAITED_2_ML; 356 return (SAME); 357 358 default: 359 return (SAME); 360 } 361 362 case TREXMT: /* retransmission timer */ 363 if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ 364 /* 365 * Set up for a retransmission, increase rexmt time 366 * in case of multiple retransmissions. 367 */ 368 tp->snd_nxt = tp->snd_una; 369 tp->tc_flags |= TC_REXMT; 370 tp->t_xmtime = tp->t_xmtime << 1; 371 if (tp->t_xmtime > T_REMAX) 372 tp->t_xmtime = T_REMAX; 373 send(tp); 374 } 375 return (SAME); 376 377 case TREXMTTL: /* retransmit too long */ 378 if (tp->t_rtl_val > tp->snd_una) /* 36 */ 379 to_user(tp->t_ucb, URXTIMO); 380 /* 381 * If user has already closed, abort the connection. 382 */ 383 if (tp->tc_flags & TC_USR_CLOSED) { 384 t_close(tp, URXTIMO); 385 return (CLOSED); 386 } 387 return (SAME); 388 389 case TPERSIST: /* persist timer */ 390 /* 391 * Force a byte send through closed window. 392 */ 393 tp->tc_flags |= TC_FORCE_ONE; 394 send(tp); 395 return (SAME); 396 } 397 panic("tcp_timers"); 398 } 399 400 /* THIS ROUTINE IS A CROCK */ 401 to_user(up, state) 402 register struct ucb *up; 403 register short state; 404 { 405 COUNT(TO_USER); 406 407 up->uc_state |= state; 408 netwakeup(up); 409 if (state == UURGENT) 410 psignal(up->uc_proc, SIGURG); 411 } 412 413 #ifdef TCPDEBUG 414 tcp_prt(tdp) 415 register struct tcp_debug *tdp; 416 { 417 COUNT(TCP_PRT); 418 419 printf("TCP(%x) %s x %s", 420 tdp->td_tcb, tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]); 421 if (tdp->td_inp == ISTIMER) 422 printf("(%s)", tcptimers[tdp->td_tim]); 423 printf(" --> %s", 424 tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]); 425 /* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */ 426 if (tdp->td_new < 0) 427 printf(" (FAILED)"); 428 if (tdp->td_sno) { 429 printf(" sno %x ano %x win %d len %d flags %x", 430 tdp->td_sno, tdp->td_ano, tdp->td_wno, tdp->td_lno, tdp->td_flg); 431 } 432 printf("\n"); 433 } 434 #endif 435