Annotation of XNU/bsd/netiso/tuba_usrreq.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.