Annotation of XNU/bsd/kern/sys_socket.c, revision 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) 1982, 1986, 1990, 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:  *     @(#)sys_socket.c        8.1 (Berkeley) 6/10/93
        !            55:  */
        !            56: 
        !            57: #include <sys/param.h>
        !            58: #include <sys/systm.h>
        !            59: #include <sys/file.h>
        !            60: #include <sys/protosw.h>
        !            61: #include <sys/socket.h>
        !            62: #include <sys/socketvar.h>
        !            63: #include <sys/filio.h>                 /* XXX */
        !            64: #include <sys/sockio.h>
        !            65: #include <sys/stat.h>
        !            66: #include <sys/uio.h>
        !            67: #include <sys/filedesc.h>
        !            68: 
        !            69: #include <net/if.h>
        !            70: #include <net/route.h>
        !            71: 
        !            72: int soo_read __P((struct file *fp, struct uio *uio, 
        !            73:                struct ucred *cred));
        !            74: int soo_write __P((struct file *fp, struct uio *uio, 
        !            75:                struct ucred *cred));
        !            76: int soo_close __P((struct file *fp, struct proc *p));
        !            77: 
        !            78: int soo_select __P((struct file *fp, int which, struct proc *p));
        !            79: 
        !            80: struct fileops socketops =
        !            81:     { soo_read, soo_write, soo_ioctl, soo_select, soo_close };
        !            82: 
        !            83: /* ARGSUSED */
        !            84: int
        !            85: soo_read(fp, uio, cred)
        !            86:        struct file *fp;
        !            87:        struct uio *uio;
        !            88:        struct ucred *cred;
        !            89: {
        !            90:        struct socket *so = (struct socket *)fp->f_data;
        !            91:        struct kextcb *kp;
        !            92:        int (*fsoreceive) __P((struct socket *so, 
        !            93:                               struct sockaddr **paddr,
        !            94:                               struct uio *uio, struct mbuf **mp0,
        !            95:                               struct mbuf **controlp, int *flagsp));
        !            96: 
        !            97:        fsoreceive = so->so_proto->pr_usrreqs->pru_soreceive;
        !            98:        if (fsoreceive != soreceive)
        !            99:        {       kp = sotokextcb(so);
        !           100:                while (kp)
        !           101:                {       if (kp->e_soif && kp->e_soif->sf_soreceive)
        !           102:                                (*kp->e_soif->sf_soreceive)(so, 0, &uio,
        !           103:                                                            0, 0, 0, kp);
        !           104:                        kp = kp->e_next;
        !           105:                }
        !           106: 
        !           107:        }
        !           108:        return (*fsoreceive)(so, 0, uio, 0, 0, 0);
        !           109: }
        !           110: 
        !           111: /* ARGSUSED */
        !           112: int
        !           113: soo_write(fp, uio, cred)
        !           114:        struct file *fp;
        !           115:        struct uio *uio;
        !           116:        struct ucred *cred;
        !           117: {
        !           118:        struct socket *so = (struct socket *)fp->f_data;
        !           119:        int     (*fsosend) __P((struct socket *so, struct sockaddr *addr,
        !           120:                                struct uio *uio, struct mbuf *top,
        !           121:                                struct mbuf *control, int flags));
        !           122:        struct kextcb *kp;
        !           123: 
        !           124:        fsosend = so->so_proto->pr_usrreqs->pru_sosend;
        !           125:        if (fsosend != sosend)
        !           126:        {       kp = sotokextcb(so);
        !           127:                while (kp)
        !           128:                {       if (kp->e_soif && kp->e_soif->sf_sosend)
        !           129:                        (*kp->e_soif->sf_sosend)(so, 0, &uio,
        !           130:                                                 0, 0, 0, kp);
        !           131:                        kp = kp->e_next;
        !           132:                }
        !           133:        }
        !           134: 
        !           135:        return (*fsosend)(so, 0, uio, 0, 0, 0);
        !           136: }
        !           137: 
        !           138: int
        !           139: soo_ioctl(fp, cmd, data, p)
        !           140:        struct file *fp;
        !           141:        u_long cmd;
        !           142:        register caddr_t data;
        !           143:        struct proc *p;
        !           144: {
        !           145:        register struct socket *so = (struct socket *)fp->f_data;
        !           146: 
        !           147:        struct sockopt sopt;
        !           148:        struct kextcb *kp;
        !           149: 
        !           150:        kp = sotokextcb(so);
        !           151:        sopt.sopt_level = cmd;
        !           152:        sopt.sopt_name = (int)data;
        !           153:        sopt.sopt_p = p;
        !           154:        while (kp)
        !           155:        {       if (kp->e_soif && kp->e_soif->sf_socontrol)
        !           156:                        (*kp->e_soif->sf_socontrol)(so, &sopt, kp);
        !           157:                kp = kp->e_next;
        !           158:        }
        !           159: 
        !           160:        switch (cmd) {
        !           161: 
        !           162:        case FIONBIO:
        !           163:                if (*(int *)data)
        !           164:                        so->so_state |= SS_NBIO;
        !           165:                else
        !           166:                        so->so_state &= ~SS_NBIO;
        !           167:                return (0);
        !           168: 
        !           169:        case FIOASYNC:
        !           170:                if (*(int *)data) {
        !           171:                        so->so_state |= SS_ASYNC;
        !           172:                        so->so_rcv.sb_flags |= SB_ASYNC;
        !           173:                        so->so_snd.sb_flags |= SB_ASYNC;
        !           174:                } else {
        !           175:                        so->so_state &= ~SS_ASYNC;
        !           176:                        so->so_rcv.sb_flags &= ~SB_ASYNC;
        !           177:                        so->so_snd.sb_flags &= ~SB_ASYNC;
        !           178:                }
        !           179:                return (0);
        !           180: 
        !           181:        case FIONREAD:
        !           182:                *(int *)data = so->so_rcv.sb_cc;
        !           183:                return (0);
        !           184: 
        !           185:        case SIOCSPGRP:
        !           186:                so->so_pgid = *(int *)data;
        !           187:                return (0);
        !           188: 
        !           189:        case SIOCGPGRP:
        !           190:                *(int *)data = so->so_pgid;
        !           191:                return (0);
        !           192: 
        !           193:        case SIOCATMARK:
        !           194:                *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
        !           195:                return (0);
        !           196:     case SIOCSETOT: {
        !           197:         /*
        !           198:          * Set socket level options here and then call protocol
        !           199:          * specific routine.
        !           200:          */
        !           201:         struct socket  *cloned_so = NULL;
        !           202:         int                            cloned_fd = *(int *)data;
        !           203:         int                            error = 0;
        !           204: 
        !           205:         /* let's make sure it's either -1 or a valid file descriptor */
        !           206:         if (cloned_fd != -1) {
        !           207:             struct file     *cloned_fp;
        !           208:             error = getsock(p->p_fd, cloned_fd, &cloned_fp);
        !           209:             if (error)
        !           210:                 return (error);
        !           211:             cloned_so = (struct socket *)cloned_fp->f_data;
        !           212:         }
        !           213: 
        !           214:         /* Always set socket non-blocking for OT */
        !           215:         so->so_state |= SS_NBIO;
        !           216:         so->so_options |= SO_DONTTRUNC | SO_WANTMORE;
        !           217: 
        !           218:         if (cloned_so && so != cloned_so) {
        !           219:             /* Flags options */
        !           220:             so->so_options |= cloned_so->so_options;
        !           221: 
        !           222:             /* SO_LINGER */
        !           223:             if (so->so_options & SO_LINGER)
        !           224:                 so->so_linger = cloned_so->so_linger;
        !           225: 
        !           226:             /* SO_SNDBUF, SO_RCVBUF */
        !           227:             if (sbreserve(&so->so_snd, cloned_so->so_snd.sb_hiwat) == 0) {
        !           228:                 error = ENOBUFS;
        !           229:                 return (error);
        !           230:             }
        !           231:             if (sbreserve(&so->so_rcv, cloned_so->so_rcv.sb_hiwat) == 0) {
        !           232:                 error = ENOBUFS;
        !           233:                 return (error);
        !           234:             }
        !           235: 
        !           236:             /* SO_SNDLOWAT, SO_RCVLOWAT */
        !           237:             so->so_snd.sb_lowat =
        !           238:                 (cloned_so->so_snd.sb_lowat > so->so_snd.sb_hiwat) ?
        !           239:                 so->so_snd.sb_hiwat : cloned_so->so_snd.sb_lowat;
        !           240:             so->so_rcv.sb_lowat =
        !           241:                 (cloned_so->so_rcv.sb_lowat > so->so_rcv.sb_hiwat) ?
        !           242:                 so->so_rcv.sb_hiwat : cloned_so->so_rcv.sb_lowat;
        !           243: 
        !           244:             /* SO_SNDTIMEO, SO_RCVTIMEO */
        !           245:             so->so_snd.sb_timeo = cloned_so->so_snd.sb_timeo;
        !           246:             so->so_rcv.sb_timeo = cloned_so->so_rcv.sb_timeo;
        !           247:         }
        !           248: 
        !           249:         error = (*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, p);
        !           250:         /* Just ignore protocols that do not understand it */
        !           251:         if (error == EOPNOTSUPP)
        !           252:             error = 0;
        !           253:         return (error);
        !           254:         }
        !           255:        }
        !           256:        /*
        !           257:         * Interface/routing/protocol specific ioctls:
        !           258:         * interface and routing ioctls should have a
        !           259:         * different entry since a socket's unnecessary
        !           260:         */
        !           261:        if (IOCGROUP(cmd) == 'i')
        !           262:                return (ifioctl(so, cmd, data, p));
        !           263:        if (IOCGROUP(cmd) == 'r')
        !           264:                return (rtioctl(cmd, data, p));
        !           265:        return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, p));
        !           266: }
        !           267: 
        !           268: int
        !           269: soo_select(fp, which, p)
        !           270:        struct file *fp;
        !           271:        int which;
        !           272:        struct proc *p;
        !           273: {
        !           274:        register struct socket *so = (struct socket *)fp->f_data;
        !           275:        register int s = splnet();
        !           276: 
        !           277:        switch (which) {
        !           278: 
        !           279:        case FREAD:
        !           280:                if (soreadable(so)) {
        !           281:                        splx(s);
        !           282:                        return (1);
        !           283:                }
        !           284:                selrecord(p, &so->so_rcv.sb_sel);
        !           285:                so->so_rcv.sb_flags |= SB_SEL;
        !           286:                break;
        !           287: 
        !           288:        case FWRITE:
        !           289:                if (sowriteable(so)) {
        !           290:                        splx(s);
        !           291:                        return (1);
        !           292:                }
        !           293:                selrecord(p, &so->so_snd.sb_sel);
        !           294:                so->so_snd.sb_flags |= SB_SEL;
        !           295:                break;
        !           296: 
        !           297:        case 0:
        !           298:                if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
        !           299:                        splx(s);
        !           300:                        return (1);
        !           301:                }
        !           302:                selrecord(p, &so->so_rcv.sb_sel);
        !           303:                so->so_rcv.sb_flags |= SB_SEL;
        !           304:                break;
        !           305:        }
        !           306:        splx(s);
        !           307:        return (0);
        !           308: }
        !           309: 
        !           310: 
        !           311: int
        !           312: soo_stat(so, ub)
        !           313:        register struct socket *so;
        !           314:        register struct stat *ub;
        !           315: {
        !           316: 
        !           317:        bzero((caddr_t)ub, sizeof (*ub));
        !           318:        ub->st_mode = S_IFSOCK;
        !           319:        return ((*so->so_proto->pr_usrreqs->pru_sense)(so, ub));
        !           320: }
        !           321: 
        !           322: /* ARGSUSED */
        !           323: int
        !           324: soo_close(fp, p)
        !           325:        struct file *fp;
        !           326:        struct proc *p;
        !           327: {
        !           328:        int error = 0;
        !           329: 
        !           330:        if (fp->f_data)
        !           331:                error = soclose((struct socket *)fp->f_data);
        !           332:        fp->f_data = 0;
        !           333:        return (error);
        !           334: }

unix.superglobalmegacorp.com

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