|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1992, 1993 ! 27: * The Regents of the University of California. All rights reserved. ! 28: * ! 29: * Redistribution and use in source and binary forms, with or without ! 30: * modification, are permitted provided that the following conditions ! 31: * are met: ! 32: * 1. Redistributions of source code must retain the above copyright ! 33: * notice, this list of conditions and the following disclaimer. ! 34: * 2. Redistributions in binary form must reproduce the above copyright ! 35: * notice, this list of conditions and the following disclaimer in the ! 36: * documentation and/or other materials provided with the distribution. ! 37: * 3. All advertising materials mentioning features or use of this software ! 38: * must display the following acknowledgement: ! 39: * This product includes software developed by the University of ! 40: * California, Berkeley and its contributors. ! 41: * 4. Neither the name of the University nor the names of its contributors ! 42: * may be used to endorse or promote products derived from this software ! 43: * without specific prior written permission. ! 44: * ! 45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 55: * SUCH DAMAGE. ! 56: * ! 57: * @(#)tuba_usrreq.c 8.1 (Berkeley) 6/10/93 ! 58: */ ! 59: ! 60: #include <sys/param.h> ! 61: #include <sys/systm.h> ! 62: #include <sys/malloc.h> ! 63: #include <sys/mbuf.h> ! 64: #include <sys/socket.h> ! 65: #include <sys/socketvar.h> ! 66: #include <sys/protosw.h> ! 67: #include <sys/errno.h> ! 68: #include <sys/stat.h> ! 69: ! 70: #include <net/if.h> ! 71: #include <net/route.h> ! 72: ! 73: #include <netinet/in.h> ! 74: #include <netinet/in_systm.h> ! 75: #include <netinet/ip.h> ! 76: #include <netinet/in_pcb.h> ! 77: #include <netinet/ip_var.h> ! 78: #include <netinet/tcp.h> ! 79: #include <netinet/tcp_fsm.h> ! 80: #include <netinet/tcp_seq.h> ! 81: #include <netinet/tcp_timer.h> ! 82: #include <netinet/tcp_var.h> ! 83: #include <netinet/tcpip.h> ! 84: #include <netinet/tcp_debug.h> ! 85: ! 86: #include <netiso/argo_debug.h> ! 87: #include <netiso/iso.h> ! 88: #include <netiso/clnp.h> ! 89: #include <netiso/iso_pcb.h> ! 90: #include <netiso/iso_var.h> ! 91: #include <netiso/tuba_table.h> ! 92: /* ! 93: * TCP protocol interface to socket abstraction. ! 94: */ ! 95: extern char *tcpstates[]; ! 96: extern struct inpcb tuba_inpcb; ! 97: extern struct isopcb tuba_isopcb; ! 98: ! 99: /* ! 100: * Process a TCP user request for TCP tb. If this is a send request ! 101: * then m is the mbuf chain of send data. If this is a timer expiration ! 102: * (called from the software clock routine), then timertype tells which timer. ! 103: */ ! 104: /*ARGSUSED*/ ! 105: tuba_usrreq(so, req, m, nam, control) ! 106: struct socket *so; ! 107: int req; ! 108: struct mbuf *m, *nam, *control; ! 109: { ! 110: register struct inpcb *inp; ! 111: register struct isopcb *isop; ! 112: register struct tcpcb *tp; ! 113: int s; ! 114: int error = 0; ! 115: int ostate; ! 116: struct sockaddr_iso *siso; ! 117: ! 118: if (req == PRU_CONTROL) ! 119: return (iso_control(so, (int)m, (caddr_t)nam, ! 120: (struct ifnet *)control)); ! 121: ! 122: s = splnet(); ! 123: inp = sotoinpcb(so); ! 124: /* ! 125: * When a TCP is attached to a socket, then there will be ! 126: * a (struct inpcb) pointed at by the socket, and this ! 127: * structure will point at a subsidary (struct tcpcb). ! 128: */ ! 129: if (inp == 0 && req != PRU_ATTACH) { ! 130: splx(s); ! 131: return (EINVAL); /* XXX */ ! 132: } ! 133: if (inp) { ! 134: tp = intotcpcb(inp); ! 135: if (tp == 0) ! 136: panic("tuba_usrreq"); ! 137: ostate = tp->t_state; ! 138: isop = (struct isopcb *)tp->t_tuba_pcb; ! 139: if (isop == 0) ! 140: panic("tuba_usrreq 2"); ! 141: } else ! 142: ostate = 0; ! 143: switch (req) { ! 144: ! 145: /* ! 146: * TCP attaches to socket via PRU_ATTACH, reserving space, ! 147: * and an internet control block. We also need to ! 148: * allocate an isopcb and separate the control block from ! 149: * tcp/ip ones. ! 150: */ ! 151: case PRU_ATTACH: ! 152: if (error = iso_pcballoc(so, &tuba_isopcb)) ! 153: break; ! 154: isop = (struct isopcb *)so->so_pcb; ! 155: so->so_pcb = 0; ! 156: if (error = tcp_usrreq(so, req, m, nam, control)) { ! 157: isop->isop_socket = 0; ! 158: iso_pcbdetach(isop); ! 159: } else { ! 160: inp = sotoinpcb(so); ! 161: remque(inp); ! 162: insque(inp, &tuba_inpcb); ! 163: inp->inp_head = &tuba_inpcb; ! 164: tp = intotcpcb(inp); ! 165: if (tp == 0) ! 166: panic("tuba_usrreq 3"); ! 167: tp->t_tuba_pcb = (caddr_t) isop; ! 168: } ! 169: goto notrace; ! 170: ! 171: /* ! 172: * PRU_DETACH detaches the TCP protocol from the socket. ! 173: * If the protocol state is non-embryonic, then can't ! 174: * do this directly: have to initiate a PRU_DISCONNECT, ! 175: * which may finish later; embryonic TCB's can just ! 176: * be discarded here. ! 177: */ ! 178: case PRU_DETACH: ! 179: if (tp->t_state > TCPS_LISTEN) ! 180: tp = tcp_disconnect(tp); ! 181: else ! 182: tp = tcp_close(tp); ! 183: if (tp == 0) ! 184: tuba_pcbdetach(isop); ! 185: break; ! 186: ! 187: /* ! 188: * Give the socket an address. ! 189: */ ! 190: case PRU_BIND: ! 191: siso = mtod(nam, struct sockaddr_iso *); ! 192: if (siso->siso_tlen && siso->siso_tlen != 2) { ! 193: error = EINVAL; ! 194: break; ! 195: } ! 196: if ((error = iso_pcbbind(isop, nam)) || ! 197: (siso = isop->isop_laddr) == 0) ! 198: break; ! 199: bcopy(TSEL(siso), &inp->inp_lport, 2); ! 200: if (siso->siso_nlen && ! 201: !(inp->inp_laddr.s_addr = tuba_lookup(siso, M_WAITOK))) ! 202: error = ENOBUFS; ! 203: break; ! 204: ! 205: /* ! 206: * Prepare to accept connections. ! 207: */ ! 208: case PRU_CONNECT: ! 209: case PRU_LISTEN: ! 210: if (inp->inp_lport == 0 && ! 211: (error = iso_pcbbind(isop, (struct mbuf *)0))) ! 212: break; ! 213: bcopy(TSEL(isop->isop_laddr), &inp->inp_lport, 2); ! 214: if (req == PRU_LISTEN) { ! 215: tp->t_state = TCPS_LISTEN; ! 216: break; ! 217: } ! 218: /*FALLTHROUGH*/ ! 219: /* ! 220: * Initiate connection to peer. ! 221: * Create a template for use in transmissions on this connection. ! 222: * Enter SYN_SENT state, and mark socket as connecting. ! 223: * Start keep-alive timer, and seed output sequence space. ! 224: * Send initial segment on connection. ! 225: */ ! 226: /* case PRU_CONNECT: */ ! 227: if (error = iso_pcbconnect(isop, nam)) ! 228: break; ! 229: if ((siso = isop->isop_laddr) && siso->siso_nlen > 1) ! 230: siso->siso_data[siso->siso_nlen - 1] = ISOPROTO_TCP; ! 231: else ! 232: panic("tuba_usrreq: connect"); ! 233: siso = mtod(nam, struct sockaddr_iso *); ! 234: if (!(inp->inp_faddr.s_addr = tuba_lookup(siso, M_WAITOK))) { ! 235: unconnect: ! 236: iso_pcbdisconnect(isop); ! 237: error = ENOBUFS; ! 238: break; ! 239: } ! 240: bcopy(TSEL(isop->isop_faddr), &inp->inp_fport, 2); ! 241: if (inp->inp_laddr.s_addr == 0 && ! 242: (inp->inp_laddr.s_addr = ! 243: tuba_lookup(isop->isop_laddr, M_WAITOK)) == 0) ! 244: goto unconnect; ! 245: if ((tp->t_template = tcp_template(tp)) == 0) ! 246: goto unconnect; ! 247: soisconnecting(so); ! 248: tcpstat.tcps_connattempt++; ! 249: tp->t_state = TCPS_SYN_SENT; ! 250: tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; ! 251: tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; ! 252: tcp_sendseqinit(tp); ! 253: error = tcp_output(tp); ! 254: tuba_refcnt(isop, 1); ! 255: break; ! 256: ! 257: /* ! 258: * Initiate disconnect from peer. ! 259: * If connection never passed embryonic stage, just drop; ! 260: * else if don't need to let data drain, then can just drop anyways, ! 261: * else have to begin TCP shutdown process: mark socket disconnecting, ! 262: * drain unread data, state switch to reflect user close, and ! 263: * send segment (e.g. FIN) to peer. Socket will be really disconnected ! 264: * when peer sends FIN and acks ours. ! 265: * ! 266: * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. ! 267: */ ! 268: case PRU_DISCONNECT: ! 269: if ((tp = tcp_disconnect(tp)) == 0) ! 270: tuba_pcbdetach(isop); ! 271: break; ! 272: ! 273: /* ! 274: * Accept a connection. Essentially all the work is ! 275: * done at higher levels; just return the address ! 276: * of the peer, storing through addr. ! 277: */ ! 278: case PRU_ACCEPT: ! 279: bcopy((caddr_t)isop->isop_faddr, mtod(nam, caddr_t), ! 280: nam->m_len = isop->isop_faddr->siso_len); ! 281: break; ! 282: ! 283: /* ! 284: * Mark the connection as being incapable of further output. ! 285: */ ! 286: case PRU_SHUTDOWN: ! 287: socantsendmore(so); ! 288: tp = tcp_usrclosed(tp); ! 289: if (tp) ! 290: error = tcp_output(tp); ! 291: else ! 292: tuba_pcbdetach(isop); ! 293: break; ! 294: /* ! 295: * Abort the TCP. ! 296: */ ! 297: case PRU_ABORT: ! 298: if ((tp = tcp_drop(tp, ECONNABORTED)) == 0) ! 299: tuba_pcbdetach(isop); ! 300: break; ! 301: ! 302: ! 303: case PRU_SOCKADDR: ! 304: if (isop->isop_laddr) ! 305: bcopy((caddr_t)isop->isop_laddr, mtod(nam, caddr_t), ! 306: nam->m_len = isop->isop_laddr->siso_len); ! 307: break; ! 308: ! 309: case PRU_PEERADDR: ! 310: if (isop->isop_faddr) ! 311: bcopy((caddr_t)isop->isop_faddr, mtod(nam, caddr_t), ! 312: nam->m_len = isop->isop_faddr->siso_len); ! 313: break; ! 314: ! 315: default: ! 316: error = tcp_usrreq(so, req, m, nam, control); ! 317: goto notrace; ! 318: } ! 319: if (tp && (so->so_options & SO_DEBUG)) ! 320: tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req); ! 321: notrace: ! 322: splx(s); ! 323: return(error); ! 324: } ! 325: ! 326: tuba_ctloutput(op, so, level, optname, mp) ! 327: int op; ! 328: struct socket *so; ! 329: int level, optname; ! 330: struct mbuf **mp; ! 331: { ! 332: int clnp_ctloutput(), tcp_ctloutput(); ! 333: ! 334: return ((level != IPPROTO_TCP ? clnp_ctloutput : tcp_ctloutput) ! 335: (op, so, level, optname, mp)); ! 336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.