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