1: /* 2: * Copyright (c) 1982, 1986 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that this notice is preserved and that due credit is given 7: * to the University of California at Berkeley. The name of the University 8: * may not be used to endorse or promote products derived from this 9: * software without specific prior written permission. This software 10: * is provided ``as is'' without express or implied warranty. 11: * 12: * @(#)tcp_usrreq.c 7.7.1.2 (Berkeley) 3/16/88 13: */ 14: 15: #include "param.h" 16: #include "systm.h" 17: #include "mbuf.h" 18: #include "socket.h" 19: #include "socketvar.h" 20: #include "protosw.h" 21: #include "errno.h" 22: #include "stat.h" 23: 24: #include "../net/if.h" 25: #include "../net/route.h" 26: 27: #include "domain.h" 28: #include "in.h" 29: #include "in_pcb.h" 30: #include "in_systm.h" 31: #include "ip.h" 32: #include "ip_var.h" 33: #include "tcp.h" 34: #include "tcp_fsm.h" 35: #include "tcp_seq.h" 36: #include "tcp_timer.h" 37: #include "tcp_var.h" 38: #include "tcpip.h" 39: #include "tcp_debug.h" 40: 41: /* 42: * TCP protocol interface to socket abstraction. 43: */ 44: extern char *tcpstates[]; 45: struct tcpcb *tcp_newtcpcb(); 46: 47: /* 48: * Process a TCP user request for TCP tb. If this is a send request 49: * then m is the mbuf chain of send data. If this is a timer expiration 50: * (called from the software clock routine), then timertype tells which timer. 51: */ 52: /*ARGSUSED*/ 53: tcp_usrreq(so, req, m, nam, rights) 54: struct socket *so; 55: int req; 56: struct mbuf *m, *nam, *rights; 57: { 58: register struct inpcb *inp; 59: register struct tcpcb *tp; 60: int s; 61: int error = 0; 62: int ostate; 63: 64: #if BSD>=43 65: if (req == PRU_CONTROL) 66: return (in_control(so, (int)m, (caddr_t)nam, 67: (struct ifnet *)rights)); 68: #else 69: if (req == PRU_CONTROL) 70: return(EOPNOTSUPP); 71: #endif 72: if (rights && rights->m_len) 73: return (EINVAL); 74: 75: s = splnet(); 76: inp = sotoinpcb(so); 77: /* 78: * When a TCP is attached to a socket, then there will be 79: * a (struct inpcb) pointed at by the socket, and this 80: * structure will point at a subsidary (struct tcpcb). 81: */ 82: if (inp == 0 && req != PRU_ATTACH) { 83: splx(s); 84: return (EINVAL); /* XXX */ 85: } 86: if (inp) { 87: tp = intotcpcb(inp); 88: /* WHAT IF TP IS 0? */ 89: #ifdef KPROF 90: tcp_acounts[tp->t_state][req]++; 91: #endif 92: ostate = tp->t_state; 93: } else 94: ostate = 0; 95: switch (req) { 96: 97: /* 98: * TCP attaches to socket via PRU_ATTACH, reserving space, 99: * and an internet control block. 100: */ 101: case PRU_ATTACH: 102: if (inp) { 103: error = EISCONN; 104: break; 105: } 106: error = tcp_attach(so); 107: if (error) 108: break; 109: if ((so->so_options & SO_LINGER) && so->so_linger == 0) 110: so->so_linger = TCP_LINGERTIME; 111: tp = sototcpcb(so); 112: break; 113: 114: /* 115: * PRU_DETACH detaches the TCP protocol from the socket. 116: * If the protocol state is non-embryonic, then can't 117: * do this directly: have to initiate a PRU_DISCONNECT, 118: * which may finish later; embryonic TCB's can just 119: * be discarded here. 120: */ 121: case PRU_DETACH: 122: if (tp->t_state > TCPS_LISTEN) 123: tp = tcp_disconnect(tp); 124: else 125: tp = tcp_close(tp); 126: break; 127: 128: /* 129: * Give the socket an address. 130: */ 131: case PRU_BIND: 132: error = in_pcbbind(inp, nam); 133: if (error) 134: break; 135: break; 136: 137: /* 138: * Prepare to accept connections. 139: */ 140: case PRU_LISTEN: 141: if (inp->inp_lport == 0) 142: error = in_pcbbind(inp, (struct mbuf *)0); 143: if (error == 0) 144: tp->t_state = TCPS_LISTEN; 145: break; 146: 147: /* 148: * Initiate connection to peer. 149: * Create a template for use in transmissions on this connection. 150: * Enter SYN_SENT state, and mark socket as connecting. 151: * Start keep-alive timer, and seed output sequence space. 152: * Send initial segment on connection. 153: */ 154: case PRU_CONNECT: 155: if (inp->inp_lport == 0) { 156: error = in_pcbbind(inp, (struct mbuf *)0); 157: if (error) 158: break; 159: } 160: error = in_pcbconnect(inp, nam); 161: if (error) 162: break; 163: tp->t_template = tcp_template(tp); 164: if (tp->t_template == 0) { 165: in_pcbdisconnect(inp); 166: error = ENOBUFS; 167: break; 168: } 169: soisconnecting(so); 170: tcpstat.tcps_connattempt++; 171: tp->t_state = TCPS_SYN_SENT; 172: tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; 173: tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; 174: tcp_sendseqinit(tp); 175: error = tcp_output(tp); 176: break; 177: 178: /* 179: * Create a TCP connection between two sockets. 180: */ 181: case PRU_CONNECT2: 182: error = EOPNOTSUPP; 183: break; 184: 185: /* 186: * Initiate disconnect from peer. 187: * If connection never passed embryonic stage, just drop; 188: * else if don't need to let data drain, then can just drop anyways, 189: * else have to begin TCP shutdown process: mark socket disconnecting, 190: * drain unread data, state switch to reflect user close, and 191: * send segment (e.g. FIN) to peer. Socket will be really disconnected 192: * when peer sends FIN and acks ours. 193: * 194: * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. 195: */ 196: case PRU_DISCONNECT: 197: tp = tcp_disconnect(tp); 198: break; 199: 200: /* 201: * Accept a connection. Essentially all the work is 202: * done at higher levels; just return the address 203: * of the peer, storing through addr. 204: */ 205: case PRU_ACCEPT: { 206: struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); 207: 208: nam->m_len = sizeof (struct sockaddr_in); 209: sin->sin_family = AF_INET; 210: sin->sin_port = inp->inp_fport; 211: sin->sin_addr = inp->inp_faddr; 212: break; 213: } 214: 215: /* 216: * Mark the connection as being incapable of further output. 217: */ 218: case PRU_SHUTDOWN: 219: socantsendmore(so); 220: tp = tcp_usrclosed(tp); 221: if (tp) 222: error = tcp_output(tp); 223: break; 224: 225: /* 226: * After a receive, possibly send window update to peer. 227: */ 228: case PRU_RCVD: 229: (void) tcp_output(tp); 230: break; 231: 232: /* 233: * Do a send by putting data in output queue and updating urgent 234: * marker if URG set. Possibly send more data. 235: */ 236: case PRU_SEND: 237: sbappend(&so->so_snd, m); 238: error = tcp_output(tp); 239: break; 240: 241: /* 242: * Abort the TCP. 243: */ 244: case PRU_ABORT: 245: tp = tcp_drop(tp, ECONNABORTED); 246: break; 247: 248: case PRU_SENSE: 249: ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; 250: (void) splx(s); 251: return (0); 252: 253: case PRU_RCVOOB: 254: if ((so->so_oobmark == 0 && 255: (so->so_state & SS_RCVATMARK) == 0) || 256: #ifdef SO_OOBINLINE 257: so->so_options & SO_OOBINLINE || 258: #endif 259: tp->t_oobflags & TCPOOB_HADDATA) { 260: error = EINVAL; 261: break; 262: } 263: if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { 264: error = EWOULDBLOCK; 265: break; 266: } 267: m->m_len = 1; 268: *mtod(m, caddr_t) = tp->t_iobc; 269: if (((int)nam & MSG_PEEK) == 0) 270: tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); 271: break; 272: 273: case PRU_SENDOOB: 274: if (sbspace(&so->so_snd) < -512) { 275: m_freem(m); 276: error = ENOBUFS; 277: break; 278: } 279: /* 280: * According to RFC961 (Assigned Protocols), 281: * the urgent pointer points to the last octet 282: * of urgent data. We continue, however, 283: * to consider it to indicate the first octet 284: * of data past the urgent section. 285: * Otherwise, snd_up should be one lower. 286: */ 287: sbappend(&so->so_snd, m); 288: tp->snd_up = tp->snd_una + so->so_snd.sb_cc; 289: tp->t_force = 1; 290: error = tcp_output(tp); 291: tp->t_force = 0; 292: break; 293: 294: case PRU_SOCKADDR: 295: in_setsockaddr(inp, nam); 296: break; 297: 298: case PRU_PEERADDR: 299: in_setpeeraddr(inp, nam); 300: break; 301: 302: /* 303: * TCP slow timer went off; going through this 304: * routine for tracing's sake. 305: */ 306: case PRU_SLOWTIMO: 307: tp = tcp_timers(tp, (int)nam); 308: req |= (int)nam << 8; /* for debug's sake */ 309: break; 310: 311: default: 312: panic("tcp_usrreq"); 313: } 314: if (tp && (so->so_options & SO_DEBUG)) 315: tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req); 316: splx(s); 317: return (error); 318: } 319: 320: #if BSD>=43 321: tcp_ctloutput(op, so, level, optname, mp) 322: int op; 323: struct socket *so; 324: int level, optname; 325: struct mbuf **mp; 326: { 327: int error = 0; 328: struct inpcb *inp = sotoinpcb(so); 329: register struct tcpcb *tp = intotcpcb(inp); 330: register struct mbuf *m; 331: 332: if (level != IPPROTO_TCP) 333: return (ip_ctloutput(op, so, level, optname, mp)); 334: 335: switch (op) { 336: 337: case PRCO_SETOPT: 338: m = *mp; 339: switch (optname) { 340: 341: case TCP_NODELAY: 342: if (m == NULL || m->m_len < sizeof (int)) 343: error = EINVAL; 344: else if (*mtod(m, int *)) 345: tp->t_flags |= TF_NODELAY; 346: else 347: tp->t_flags &= ~TF_NODELAY; 348: break; 349: 350: case TCP_MAXSEG: /* not yet */ 351: default: 352: error = EINVAL; 353: break; 354: } 355: if (m) 356: (void) m_free(m); 357: break; 358: 359: case PRCO_GETOPT: 360: *mp = m = m_get(M_WAIT, MT_SOOPTS); 361: m->m_len = sizeof(int); 362: 363: switch (optname) { 364: case TCP_NODELAY: 365: *mtod(m, int *) = tp->t_flags & TF_NODELAY; 366: break; 367: case TCP_MAXSEG: 368: *mtod(m, int *) = tp->t_maxseg; 369: break; 370: default: 371: error = EINVAL; 372: break; 373: } 374: break; 375: } 376: return (error); 377: } 378: #endif 379: 380: int tcp_sendspace = 1024*4; 381: int tcp_recvspace = 1024*4; 382: /* 383: * Attach TCP protocol to socket, allocating 384: * internet protocol control block, tcp control block, 385: * bufer space, and entering LISTEN state if to accept connections. 386: */ 387: tcp_attach(so) 388: struct socket *so; 389: { 390: register struct tcpcb *tp; 391: struct inpcb *inp; 392: int error; 393: 394: error = soreserve(so, tcp_sendspace, tcp_recvspace); 395: if (error) 396: return (error); 397: error = in_pcballoc(so, &tcb); 398: if (error) 399: return (error); 400: inp = sotoinpcb(so); 401: tp = tcp_newtcpcb(inp); 402: if (tp == 0) { 403: int nofd = so->so_state & SS_NOFDREF; /* XXX */ 404: 405: so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ 406: in_pcbdetach(inp); 407: so->so_state |= nofd; 408: return (ENOBUFS); 409: } 410: tp->t_state = TCPS_CLOSED; 411: return (0); 412: } 413: 414: /* 415: * Initiate (or continue) disconnect. 416: * If embryonic state, just send reset (once). 417: * If in ``let data drain'' option and linger null, just drop. 418: * Otherwise (hard), mark socket disconnecting and drop 419: * current input data; switch states based on user close, and 420: * send segment to peer (with FIN). 421: */ 422: struct tcpcb * 423: tcp_disconnect(tp) 424: register struct tcpcb *tp; 425: { 426: struct socket *so = tp->t_inpcb->inp_socket; 427: 428: if (tp->t_state < TCPS_ESTABLISHED) 429: tp = tcp_close(tp); 430: else if ((so->so_options & SO_LINGER) && so->so_linger == 0) 431: tp = tcp_drop(tp, 0); 432: else { 433: soisdisconnecting(so); 434: sbflush(&so->so_rcv); 435: tp = tcp_usrclosed(tp); 436: if (tp) 437: (void) tcp_output(tp); 438: } 439: return (tp); 440: } 441: 442: /* 443: * User issued close, and wish to trail through shutdown states: 444: * if never received SYN, just forget it. If got a SYN from peer, 445: * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. 446: * If already got a FIN from peer, then almost done; go to LAST_ACK 447: * state. In all other cases, have already sent FIN to peer (e.g. 448: * after PRU_SHUTDOWN), and just have to play tedious game waiting 449: * for peer to send FIN or not respond to keep-alives, etc. 450: * We can let the user exit from the close as soon as the FIN is acked. 451: */ 452: struct tcpcb * 453: tcp_usrclosed(tp) 454: register struct tcpcb *tp; 455: { 456: 457: switch (tp->t_state) { 458: 459: case TCPS_CLOSED: 460: case TCPS_LISTEN: 461: case TCPS_SYN_SENT: 462: tp->t_state = TCPS_CLOSED; 463: tp = tcp_close(tp); 464: break; 465: 466: case TCPS_SYN_RECEIVED: 467: case TCPS_ESTABLISHED: 468: tp->t_state = TCPS_FIN_WAIT_1; 469: break; 470: 471: case TCPS_CLOSE_WAIT: 472: tp->t_state = TCPS_LAST_ACK; 473: break; 474: } 475: if (tp && tp->t_state >= TCPS_FIN_WAIT_2) 476: soisdisconnected(tp->t_inpcb->inp_socket); 477: return (tp); 478: }