1 /* tcp_usrreq.c 1.28 81/11/15 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mbuf.h" 6 #include "../h/socket.h" 7 #include "../h/socketvar.h" 8 #include "../h/protosw.h" 9 #include "../net/inet.h" 10 #include "../net/inet_host.h" 11 #include "../net/inet_pcb.h" 12 #include "../net/inet_systm.h" 13 #include "../net/imp.h" 14 #include "../net/ip.h" 15 #include "../net/ip_var.h" 16 #include "../net/tcp.h" 17 #define TCPFSTAB 18 #ifdef TCPDEBUG 19 #define TCPSTATES 20 #endif 21 #include "../net/tcp_fsm.h" 22 #include "../net/tcp_var.h" 23 #include "/usr/include/errno.h" 24 25 /* 26 * Tcp initialization 27 */ 28 tcp_init() 29 { 30 31 tcp_iss = 1; /* wrong */ 32 tcb.inp_next = tcb.inp_prev = &tcb; 33 } 34 35 /* 36 * Tcp finite state machine entries for timer and user generated 37 * requests. These routines raise the ipl to that of the network 38 * to prevent reentry. In particluar, this requires that the software 39 * clock interrupt have lower priority than the network so that 40 * we can enter the network from timeout routines without improperly 41 * nesting the interrupt stack. 42 */ 43 44 /* 45 * Tcp protocol timeout routine called every 500 ms. 46 * Updates the timers in all active tcb's and 47 * causes finite state machine actions if timers expire. 48 */ 49 tcp_slowtimo() 50 { 51 register struct inpcb *ip; 52 register struct tcpcb *tp; 53 int s = splnet(); 54 register short *tmp; 55 register int i; 56 COUNT(TCP_TIMEO); 57 58 /* 59 * Search through tcb's and update active timers. 60 */ 61 for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) { 62 tp = intotcpcb(ip); 63 tmp = &tp->t_init; 64 for (i = 0; i < TNTIMERS; i++) { 65 if (*tmp && --*tmp == 0) 66 tcp_usrreq(tp->t_inpcb->inp_socket, 67 PRU_SLOWTIMO, 0, i); 68 tmp++; 69 } 70 tp->t_xmt++; 71 } 72 tcp_iss += ISSINCR/2; /* increment iss */ 73 splx(s); 74 } 75 76 /* 77 * Cancel all timers for tcp tp. 78 */ 79 tcp_tcancel(tp) 80 struct tcpcb *tp; 81 { 82 register short *tmp = &tp->t_init; 83 register int i; 84 85 for (i = 0; i < TNTIMERS; i++) 86 *tmp++ = 0; 87 } 88 89 /* 90 * Process a TCP user request for tcp tb. If this is a send request 91 * then m is the mbuf chain of send data. If this is a timer expiration 92 * (called from the software clock routine), then timertype tells which timer. 93 */ 94 tcp_usrreq(so, req, m, addr) 95 struct socket *so; 96 int req; 97 struct mbuf *m; 98 caddr_t addr; 99 { 100 register struct inpcb *inp = sotoinpcb(so); 101 register struct tcpcb *tp = intotcpcb(inp); 102 int s = splnet(); 103 register int nstate; 104 #ifdef TCPDEBUG 105 struct tcp_debug tdb; 106 #endif 107 int error = 0; 108 COUNT(TCP_USRREQ); 109 110 /* 111 * Make sure attached. If not, 112 * only PRU_ATTACH is valid. 113 */ 114 if (tp) { 115 nstate = tp->t_state; 116 tp->tc_flags &= ~TC_NET_KEEP; 117 } else 118 if (req != PRU_ATTACH) { 119 splx(s); 120 return (EINVAL); 121 } 122 123 /* 124 * Do tracing and accounting. 125 */ 126 #ifdef KPROF 127 acounts[nstate][req]++; 128 #endif 129 #ifdef TCPDEBUG 130 if (tp && ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug)) { 131 tdb_setup(tp, (struct tcpiphdr *)0, req, &tdb); 132 tdb.td_tim = timertype; 133 } else 134 tdb.td_tod = 0; 135 #endif 136 switch (req) { 137 138 case PRU_ATTACH: 139 if (tp) 140 error = EISCONN; 141 else { 142 tcp_attach(so); 143 tp = sototcpcb(so); 144 } 145 if (so->so_options & SO_ACCEPTCONN) { 146 inp->inp_lhost = in_hmake(&n_lhost); 147 in_pcbgenport(&tcb, inp); 148 nstate = LISTEN; 149 } else 150 nstate = CLOSED; 151 break; 152 153 case PRU_DETACH: 154 tcp_detach(so); 155 break; 156 157 case PRU_CONNECT: 158 if (tp->t_state != 0 && tp->t_state != CLOSED) 159 goto bad; 160 inp->inp_fhost = in_hmake((struct in_addr *)addr, &error); 161 if (inp->inp_fhost == 0) 162 break; 163 tcp_sndctl(tp); 164 nstate = SYN_SENT; 165 soisconnecting(so); 166 break; 167 168 case PRU_DISCONNECT: 169 if ((tp->tc_flags & TC_FIN_RCVD) == 0) 170 goto abort; 171 if (nstate < ESTAB) 172 tcp_disconnect(so); 173 else { 174 tp->tc_flags |= TC_SND_FIN; 175 tcp_sendctl(tp); 176 tp->tc_flags |= TC_USR_CLOSED; 177 soisdisconnecting(so); 178 } 179 break; 180 181 case PRU_SHUTDOWN: 182 switch (nstate) { 183 184 case LISTEN: 185 case SYN_SENT: 186 nstate = CLOSED; 187 break; 188 189 case SYN_RCVD: 190 case L_SYN_RCVD: 191 case ESTAB: 192 case CLOSE_WAIT: 193 tp->tc_flags |= TC_SND_FIN; 194 tcp_sndctl(tp); 195 tp->tc_flags |= TC_USR_CLOSED; 196 nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK; 197 break; 198 199 case FIN_W1: 200 case FIN_W2: 201 case TIME_WAIT: 202 case CLOSING: 203 case LAST_ACK: 204 case RCV_WAIT: 205 break; 206 207 default: 208 goto bad; 209 } 210 break; 211 212 case PRU_RCVD: 213 if (nstate < ESTAB || nstate == CLOSED) 214 goto bad; 215 tcp_sndwin(tp); 216 if ((tp->tc_flags&TC_FIN_RCVD) && 217 (tp->tc_flags&TC_USR_CLOSED) == 0 && 218 rcv_empty(tp)) 219 error = ESHUTDOWN; 220 if (nstate == RCV_WAIT && rcv_empty(tp)) 221 nstate = CLOSED; 222 break; 223 224 case PRU_SEND: 225 switch (nstate) { 226 227 case ESTAB: 228 case CLOSE_WAIT: 229 tcp_usrsend(tp, m); 230 break; 231 232 default: 233 if (nstate < ESTAB) 234 goto bad; 235 m_freem(m); 236 error = ENOTCONN; 237 break; 238 } 239 break; 240 241 abort: 242 case PRU_ABORT: 243 tcp_abort(tp); 244 nstate = CLOSED; 245 break; 246 247 case PRU_CONTROL: 248 error = EOPNOTSUPP; 249 break; 250 251 case PRU_SLOWTIMO: 252 switch (nstate) { 253 254 case 0: 255 case CLOSED: 256 case LISTEN: 257 goto bad; 258 259 default: 260 nstate = tcp_timers(tp, (int)addr); 261 } 262 break; 263 264 default: 265 panic("tcp_usrreq"); 266 bad: 267 printf("tcp: bad state: tcb=%x state=%d input=%d\n", 268 tp, tp->t_state, req); 269 nstate = EFAILEC; 270 break; 271 } 272 #ifdef TCPDEBUG 273 if (tdb.td_tod) 274 tdb_stuff(&tdb, nstate); 275 #endif 276 switch (nstate) { 277 278 case CLOSED: 279 case SAME: 280 break; 281 282 case EFAILEC: 283 if (m) 284 m_freem(dtom(m)); 285 break; 286 287 default: 288 tp->t_state = nstate; 289 break; 290 } 291 splx(s); 292 return (error); 293 } 294 295 tcp_attach(so) 296 register struct socket *so; 297 { 298 register struct tcpcb *tp; 299 COUNT(TCP_ATTACH); 300 301 /* 302 * Make empty reassembly queue. 303 */ 304 tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; 305 306 /* 307 * Initialize sequence numbers and round trip retransmit timer. 308 */ 309 tp->t_xmtime = T_REXMT; 310 tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una = 311 tp->iss = tcp_iss; 312 tp->snd_off = tp->iss + 1; 313 tcp_iss += (ISSINCR >> 1) + 1; 314 } 315 316 tcp_detach(so) 317 register struct socket *so; 318 { 319 register struct tcpcb *tp = (struct tcpcb *)so->so_pcb; 320 register struct tcpiphdr *t; 321 register struct mbuf *m; 322 COUNT(TCP_DETACH); 323 324 wmemfree((caddr_t)tp, 1024); 325 m_release(so->so_rcv.sb_hiwat + so->so_snd.sb_hiwat + 2 * MSIZE); 326 } 327 328 tcp_disconnect(tp) 329 register struct tcpcb *tp; 330 { 331 register struct tcpiphdr *t; 332 register struct mbuf *m; 333 register struct socket *so; 334 335 tcp_tcancel(tp); 336 t = tp->seg_next; 337 for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next) 338 m_freem(dtom(t)); 339 tcp_drainunack(tp); 340 if (tp->t_template) { 341 m_free(dtom(tp->t_template)); 342 tp->t_template = 0; 343 } 344 in_pcbfree(tp->t_inpcb); 345 } 346 347 tcp_abort(so) 348 register struct socket *so; 349 { 350 register struct tcpcb *tp = sototcpcb(so); 351 352 switch (tp->t_state) { 353 354 case SYN_RCVD: 355 case ESTAB: 356 case FIN_W1: 357 case FIN_W2: 358 case CLOSE_WAIT: 359 tp->tc_flags |= TC_SND_RST; 360 tcp_sndnull(tp); 361 } 362 if (so) 363 soisdisconnected(so); 364 } 365 366 /* 367 * Send data queue headed by m0 into the protocol. 368 */ 369 tcp_usrsend(tp, m0) 370 register struct tcpcb *tp; 371 struct mbuf *m0; 372 { 373 register struct mbuf *m, *n; 374 register struct socket *so = tp->t_inpcb->inp_socket; 375 register off; 376 seq_t last; 377 COUNT(TCP_USRSEND); 378 379 sbappend(&so->so_snd, m0); 380 if (tp->t_options & TO_EOL) 381 tp->snd_end = tp->snd_off + so->so_snd.sb_cc; 382 if (tp->t_options & TO_URG) { 383 tp->snd_urp = tp->snd_off + so->so_snd.sb_cc + 1; 384 tp->tc_flags |= TC_SND_URG; 385 } 386 tcp_send(tp); 387 } 388 389 /* 390 * TCP timer went off processing. 391 */ 392 tcp_timers(tp, timertype) 393 register struct tcpcb *tp; 394 int timertype; 395 { 396 397 COUNT(TCP_TIMERS); 398 switch (timertype) { 399 400 case TFINACK: /* fin-ack timer */ 401 switch (tp->t_state) { 402 403 case TIME_WAIT: 404 /* 405 * We can be sure our ACK of foreign FIN was rcvd, 406 * and can close if no data left for user. 407 */ 408 if (rcv_empty(tp)) { 409 tcp_disconnect(tp); 410 return (CLOSED); 411 } 412 return (RCV_WAIT); /* 17 */ 413 414 case CLOSING: 415 tp->tc_flags |= TC_WAITED_2_ML; 416 return (SAME); 417 418 default: 419 return (SAME); 420 } 421 422 case TREXMT: /* retransmission timer */ 423 if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ 424 /* 425 * Set so for a retransmission, increase rexmt time 426 * in case of multiple retransmissions. 427 */ 428 tp->snd_nxt = tp->snd_una; 429 tp->tc_flags |= TC_REXMT; 430 tp->t_xmtime = tp->t_xmtime << 1; 431 if (tp->t_xmtime > T_REMAX) 432 tp->t_xmtime = T_REMAX; 433 tcp_send(tp); 434 } 435 return (SAME); 436 437 case TREXMTTL: /* retransmit too long */ 438 if (tp->t_rtl_val > tp->snd_una) /* 36 */ 439 tcp_error(EIO); /* URXTIMO !?! */ 440 /* 441 * If user has already closed, abort the connection. 442 */ 443 if (tp->tc_flags & TC_USR_CLOSED) { 444 tcp_abort(tp); 445 return (CLOSED); 446 } 447 return (SAME); 448 449 case TPERSIST: /* persist timer */ 450 /* 451 * Force a byte send through closed window. 452 */ 453 tp->tc_flags |= TC_FORCE_ONE; 454 tcp_send(tp); 455 return (SAME); 456 } 457 panic("tcp_timers"); 458 } 459 460 tcp_sense(m) 461 struct mbuf *m; 462 { 463 464 return (EOPNOTSUPP); 465 } 466 467 tcp_error(so, errno) 468 struct socket *so; 469 int errno; 470 { 471 COUNT(TO_USER); 472 473 so->so_error = errno; 474 sorwakeup(so); 475 sowwakeup(so); 476 } 477 478 #ifdef TCPDEBUG 479 /* 480 * TCP debugging utility subroutines. 481 * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID. 482 */ 483 tdb_setup(tp, n, input, tdp) 484 struct tcpcb *tp; 485 register struct tcpiphdr *n; 486 int input; 487 register struct tcp_debug *tdp; 488 { 489 490 COUNT(TDB_SETUP); 491 tdp->td_tod = time; 492 tdp->td_tcb = tp; 493 tdp->td_old = tp->t_state; 494 tdp->td_inp = input; 495 tdp->td_tim = 0; 496 tdp->td_new = -1; 497 if (n) { 498 tdp->td_sno = n->ti_seq; 499 tdp->td_ano = n->ti_ackno; 500 tdp->td_wno = n->t_win; 501 tdp->td_lno = n->ti_len; 502 tdp->td_flg = n->ti_flags; 503 } else 504 tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno = 505 tdp->td_flg = 0; 506 } 507 508 tdb_stuff(tdp, nstate) 509 struct tcp_debug *tdp; 510 int nstate; 511 { 512 COUNT(TDB_STUFF); 513 514 tdp->td_new = nstate; 515 tcp_debug[tdbx++ % TDBSIZE] = *tdp; 516 if (tcpconsdebug & 2) 517 tcp_prt(tdp); 518 } 519 520 tcp_prt(tdp) 521 register struct tcp_debug *tdp; 522 { 523 COUNT(TCP_PRT); 524 525 printf("%x ", ((int)tdp->td_tcb)&0xffffff); 526 if (tdp->td_inp == INSEND) { 527 printf("SEND #%x", tdp->td_sno); 528 tdp->td_lno = ntohs(tdp->td_lno); 529 tdp->td_wno = ntohs(tdp->td_wno); 530 } else { 531 if (tdp->td_inp == INRECV) 532 printf("RCV #%x ", tdp->td_sno); 533 printf("%s.%s", 534 tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]); 535 if (tdp->td_inp == ISTIMER) 536 printf("(%s)", tcptimers[tdp->td_tim]); 537 printf(" -> %s", 538 tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]); 539 if (tdp->td_new == -1) 540 printf(" (FAILED)"); 541 } 542 /* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */ 543 if (tdp->td_lno) 544 printf(" len=%d", tdp->td_lno); 545 if (tdp->td_wno) 546 printf(" win=%d", tdp->td_wno); 547 if (tdp->td_flg & TH_FIN) printf(" FIN"); 548 if (tdp->td_flg & TH_SYN) printf(" SYN"); 549 if (tdp->td_flg & TH_RST) printf(" RST"); 550 if (tdp->td_flg & TH_EOL) printf(" EOL"); 551 if (tdp->td_flg & TH_ACK) printf(" ACK %x", tdp->td_ano); 552 if (tdp->td_flg & TH_URG) printf(" URG"); 553 printf("\n"); 554 } 555 #endif 556