[BACK]Return to uipc_syscalls.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/uipc_syscalls.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: uipc_syscalls.c,v 1.66 2006/10/23 07:13:56 henning Exp $      */
                      2: /*     $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 1982, 1986, 1989, 1990, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of the University nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  *
                     32:  *     @(#)uipc_syscalls.c     8.4 (Berkeley) 2/21/94
                     33:  */
                     34:
                     35: #include <sys/param.h>
                     36: #include <sys/systm.h>
                     37: #include <sys/filedesc.h>
                     38: #include <sys/proc.h>
                     39: #include <sys/file.h>
                     40: #include <sys/buf.h>
                     41: #include <sys/malloc.h>
                     42: #include <sys/event.h>
                     43: #include <sys/mbuf.h>
                     44: #include <sys/protosw.h>
                     45: #include <sys/socket.h>
                     46: #include <sys/socketvar.h>
                     47: #include <sys/signalvar.h>
                     48: #include <sys/unpcb.h>
                     49: #include <sys/un.h>
                     50: #ifdef KTRACE
                     51: #include <sys/ktrace.h>
                     52: #endif
                     53:
                     54: #include <sys/mount.h>
                     55: #include <sys/syscallargs.h>
                     56:
                     57: /*
                     58:  * System call interface to the socket abstraction.
                     59:  */
                     60: extern struct fileops socketops;
                     61:
                     62: int
                     63: sys_socket(struct proc *p, void *v, register_t *retval)
                     64: {
                     65:        struct sys_socket_args /* {
                     66:                syscallarg(int) domain;
                     67:                syscallarg(int) type;
                     68:                syscallarg(int) protocol;
                     69:        } */ *uap = v;
                     70:        struct filedesc *fdp = p->p_fd;
                     71:        struct socket *so;
                     72:        struct file *fp;
                     73:        int fd, error;
                     74:
                     75:        fdplock(fdp);
                     76:
                     77:        if ((error = falloc(p, &fp, &fd)) != 0)
                     78:                goto out;
                     79:        fp->f_flag = FREAD|FWRITE;
                     80:        fp->f_type = DTYPE_SOCKET;
                     81:        fp->f_ops = &socketops;
                     82:        error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
                     83:                         SCARG(uap, protocol));
                     84:        if (error) {
                     85:                fdremove(fdp, fd);
                     86:                closef(fp, p);
                     87:        } else {
                     88:                fp->f_data = so;
                     89:                FILE_SET_MATURE(fp);
                     90:                *retval = fd;
                     91:        }
                     92: out:
                     93:        fdpunlock(fdp);
                     94:        return (error);
                     95: }
                     96:
                     97: /* ARGSUSED */
                     98: int
                     99: sys_bind(struct proc *p, void *v, register_t *retval)
                    100: {
                    101:        struct sys_bind_args /* {
                    102:                syscallarg(int) s;
                    103:                syscallarg(const struct sockaddr *) name;
                    104:                syscallarg(socklen_t) namelen;
                    105:        } */ *uap = v;
                    106:        struct file *fp;
                    107:        struct mbuf *nam;
                    108:        int error;
                    109:
                    110:        if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
                    111:                return (error);
                    112:        error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
                    113:                         MT_SONAME);
                    114:        if (error == 0) {
                    115:                error = sobind(fp->f_data, nam);
                    116:                m_freem(nam);
                    117:        }
                    118:        FRELE(fp);
                    119:        return (error);
                    120: }
                    121:
                    122: /* ARGSUSED */
                    123: int
                    124: sys_listen(struct proc *p, void *v, register_t *retval)
                    125: {
                    126:        struct sys_listen_args /* {
                    127:                syscallarg(int) s;
                    128:                syscallarg(int) backlog;
                    129:        } */ *uap = v;
                    130:        struct file *fp;
                    131:        int error;
                    132:
                    133:        if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
                    134:                return (error);
                    135:        error = solisten(fp->f_data, SCARG(uap, backlog));
                    136:        FRELE(fp);
                    137:        return (error);
                    138: }
                    139:
                    140: int
                    141: sys_accept(struct proc *p, void *v, register_t *retval)
                    142: {
                    143:        struct sys_accept_args /* {
                    144:                syscallarg(int) s;
                    145:                syscallarg(struct sockaddr *) name;
                    146:                syscallarg(socklen_t *) anamelen;
                    147:        } */ *uap = v;
                    148:        struct file *fp, *headfp;
                    149:        struct mbuf *nam;
                    150:        socklen_t namelen;
                    151:        int error, s, tmpfd;
                    152:        struct socket *head, *so;
                    153:        int nflag;
                    154:
                    155:        if (SCARG(uap, name) && (error = copyin(SCARG(uap, anamelen),
                    156:            &namelen, sizeof (namelen))))
                    157:                return (error);
                    158:        if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
                    159:                return (error);
                    160:        headfp = fp;
                    161:        s = splsoftnet();
                    162:        head = fp->f_data;
                    163:        if ((head->so_options & SO_ACCEPTCONN) == 0) {
                    164:                error = EINVAL;
                    165:                goto bad;
                    166:        }
                    167:        if ((head->so_state & SS_NBIO) && head->so_qlen == 0) {
                    168:                if (head->so_state & SS_CANTRCVMORE)
                    169:                        error = ECONNABORTED;
                    170:                else
                    171:                        error = EWOULDBLOCK;
                    172:                goto bad;
                    173:        }
                    174:        while (head->so_qlen == 0 && head->so_error == 0) {
                    175:                if (head->so_state & SS_CANTRCVMORE) {
                    176:                        head->so_error = ECONNABORTED;
                    177:                        break;
                    178:                }
                    179:                error = tsleep(&head->so_timeo, PSOCK | PCATCH, netcon, 0);
                    180:                if (error) {
                    181:                        goto bad;
                    182:                }
                    183:        }
                    184:        if (head->so_error) {
                    185:                error = head->so_error;
                    186:                head->so_error = 0;
                    187:                goto bad;
                    188:        }
                    189:
                    190:        /*
                    191:         * At this point we know that there is at least one connection
                    192:         * ready to be accepted. Remove it from the queue prior to
                    193:         * allocating the file descriptor for it since falloc() may
                    194:         * block allowing another process to accept the connection
                    195:         * instead.
                    196:         */
                    197:        so = TAILQ_FIRST(&head->so_q);
                    198:        if (soqremque(so, 1) == 0)
                    199:                panic("accept");
                    200:
                    201:        /* Take note if socket was non-blocking. */
                    202:        nflag = (fp->f_flag & FNONBLOCK);
                    203:
                    204:        fdplock(p->p_fd);
                    205:        if ((error = falloc(p, &fp, &tmpfd)) != 0) {
                    206:                /*
                    207:                 * Probably ran out of file descriptors. Put the
                    208:                 * unaccepted connection back onto the queue and
                    209:                 * do another wakeup so some other process might
                    210:                 * have a chance at it.
                    211:                 */
                    212:                so->so_head = head;
                    213:                head->so_qlen++;
                    214:                so->so_onq = &head->so_q;
                    215:                TAILQ_INSERT_HEAD(so->so_onq, so, so_qe);
                    216:                wakeup_one(&head->so_timeo);
                    217:                goto bad;
                    218:        }
                    219:        *retval = tmpfd;
                    220:
                    221:        /* connection has been removed from the listen queue */
                    222:        KNOTE(&head->so_rcv.sb_sel.si_note, 0);
                    223:
                    224:        fp->f_type = DTYPE_SOCKET;
                    225:        fp->f_flag = FREAD | FWRITE | nflag;
                    226:        fp->f_ops = &socketops;
                    227:        fp->f_data = so;
                    228:        nam = m_get(M_WAIT, MT_SONAME);
                    229:        error = soaccept(so, nam);
                    230:        if (!error && SCARG(uap, name)) {
                    231:                if (namelen > nam->m_len)
                    232:                        namelen = nam->m_len;
                    233:                /* SHOULD COPY OUT A CHAIN HERE */
                    234:                if ((error = copyout(mtod(nam, caddr_t),
                    235:                    SCARG(uap, name), namelen)) == 0)
                    236:                        error = copyout(&namelen, SCARG(uap, anamelen),
                    237:                            sizeof (*SCARG(uap, anamelen)));
                    238:        }
                    239:        /* if an error occurred, free the file descriptor */
                    240:        if (error) {
                    241:                fdremove(p->p_fd, tmpfd);
                    242:                closef(fp, p);
                    243:        } else {
                    244:                FILE_SET_MATURE(fp);
                    245:        }
                    246:        m_freem(nam);
                    247: bad:
                    248:        fdpunlock(p->p_fd);
                    249:        splx(s);
                    250:        FRELE(headfp);
                    251:        return (error);
                    252: }
                    253:
                    254: /* ARGSUSED */
                    255: int
                    256: sys_connect(struct proc *p, void *v, register_t *retval)
                    257: {
                    258:        struct sys_connect_args /* {
                    259:                syscallarg(int) s;
                    260:                syscallarg(const struct sockaddr *) name;
                    261:                syscallarg(socklen_t) namelen;
                    262:        } */ *uap = v;
                    263:        struct file *fp;
                    264:        struct socket *so;
                    265:        struct mbuf *nam = NULL;
                    266:        int error, s;
                    267:
                    268:        if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
                    269:                return (error);
                    270:        so = fp->f_data;
                    271:        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
                    272:                FRELE(fp);
                    273:                return (EALREADY);
                    274:        }
                    275:        error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
                    276:                         MT_SONAME);
                    277:        if (error)
                    278:                goto bad;
                    279:        error = soconnect(so, nam);
                    280:        if (error)
                    281:                goto bad;
                    282:        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
                    283:                FRELE(fp);
                    284:                m_freem(nam);
                    285:                return (EINPROGRESS);
                    286:        }
                    287:        s = splsoftnet();
                    288:        while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
                    289:                error = tsleep(&so->so_timeo, PSOCK | PCATCH,
                    290:                    netcon, 0);
                    291:                if (error)
                    292:                        break;
                    293:        }
                    294:        if (error == 0) {
                    295:                error = so->so_error;
                    296:                so->so_error = 0;
                    297:        }
                    298:        splx(s);
                    299: bad:
                    300:        so->so_state &= ~SS_ISCONNECTING;
                    301:        FRELE(fp);
                    302:        if (nam)
                    303:                m_freem(nam);
                    304:        if (error == ERESTART)
                    305:                error = EINTR;
                    306:        return (error);
                    307: }
                    308:
                    309: int
                    310: sys_socketpair(struct proc *p, void *v, register_t *retval)
                    311: {
                    312:        struct sys_socketpair_args /* {
                    313:                syscallarg(int) domain;
                    314:                syscallarg(int) type;
                    315:                syscallarg(int) protocol;
                    316:                syscallarg(int *) rsv;
                    317:        } */ *uap = v;
                    318:        struct filedesc *fdp = p->p_fd;
                    319:        struct file *fp1, *fp2;
                    320:        struct socket *so1, *so2;
                    321:        int fd, error, sv[2];
                    322:
                    323:        error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
                    324:                         SCARG(uap, protocol));
                    325:        if (error)
                    326:                return (error);
                    327:        error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
                    328:                         SCARG(uap, protocol));
                    329:        if (error)
                    330:                goto free1;
                    331:
                    332:        fdplock(fdp);
                    333:        if ((error = falloc(p, &fp1, &fd)) != 0)
                    334:                goto free2;
                    335:        sv[0] = fd;
                    336:        fp1->f_flag = FREAD|FWRITE;
                    337:        fp1->f_type = DTYPE_SOCKET;
                    338:        fp1->f_ops = &socketops;
                    339:        fp1->f_data = so1;
                    340:        if ((error = falloc(p, &fp2, &fd)) != 0)
                    341:                goto free3;
                    342:        fp2->f_flag = FREAD|FWRITE;
                    343:        fp2->f_type = DTYPE_SOCKET;
                    344:        fp2->f_ops = &socketops;
                    345:        fp2->f_data = so2;
                    346:        sv[1] = fd;
                    347:        if ((error = soconnect2(so1, so2)) != 0)
                    348:                goto free4;
                    349:        if (SCARG(uap, type) == SOCK_DGRAM) {
                    350:                /*
                    351:                 * Datagram socket connection is asymmetric.
                    352:                 */
                    353:                 if ((error = soconnect2(so2, so1)) != 0)
                    354:                        goto free4;
                    355:        }
                    356:        error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int));
                    357:        if (error == 0) {
                    358:                FILE_SET_MATURE(fp1);
                    359:                FILE_SET_MATURE(fp2);
                    360:                fdpunlock(fdp);
                    361:                return (0);
                    362:        }
                    363: free4:
                    364:        fdremove(fdp, sv[1]);
                    365:        closef(fp2, p);
                    366:        so2 = NULL;
                    367: free3:
                    368:        fdremove(fdp, sv[0]);
                    369:        closef(fp1, p);
                    370:        so1 = NULL;
                    371: free2:
                    372:        if (so2 != NULL)
                    373:                (void)soclose(so2);
                    374:        fdpunlock(fdp);
                    375: free1:
                    376:        if (so1 != NULL)
                    377:                (void)soclose(so1);
                    378:        return (error);
                    379: }
                    380:
                    381: int
                    382: sys_sendto(struct proc *p, void *v, register_t *retval)
                    383: {
                    384:        struct sys_sendto_args /* {
                    385:                syscallarg(int) s;
                    386:                syscallarg(const void *) buf;
                    387:                syscallarg(size_t) len;
                    388:                syscallarg(int) flags;
                    389:                syscallarg(const struct sockaddr *) to;
                    390:                syscallarg(socklen_t) tolen;
                    391:        } */ *uap = v;
                    392:        struct msghdr msg;
                    393:        struct iovec aiov;
                    394:
                    395:        msg.msg_name = (caddr_t)SCARG(uap, to);
                    396:        msg.msg_namelen = SCARG(uap, tolen);
                    397:        msg.msg_iov = &aiov;
                    398:        msg.msg_iovlen = 1;
                    399:        msg.msg_control = 0;
                    400: #ifdef COMPAT_OLDSOCK
                    401:        msg.msg_flags = 0;
                    402: #endif
                    403:        aiov.iov_base = (char *)SCARG(uap, buf);
                    404:        aiov.iov_len = SCARG(uap, len);
                    405:        return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
                    406: }
                    407:
                    408: int
                    409: sys_sendmsg(struct proc *p, void *v, register_t *retval)
                    410: {
                    411:        struct sys_sendmsg_args /* {
                    412:                syscallarg(int) s;
                    413:                syscallarg(const struct msghdr *) msg;
                    414:                syscallarg(int) flags;
                    415:        } */ *uap = v;
                    416:        struct msghdr msg;
                    417:        struct iovec aiov[UIO_SMALLIOV], *iov;
                    418:        int error;
                    419:
                    420:        error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
                    421:        if (error)
                    422:                return (error);
                    423:        if (msg.msg_iovlen > IOV_MAX)
                    424:                return (EMSGSIZE);
                    425:        if (msg.msg_iovlen > UIO_SMALLIOV)
                    426:                iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
                    427:                    M_IOV, M_WAITOK);
                    428:        else
                    429:                iov = aiov;
                    430:        if (msg.msg_iovlen &&
                    431:            (error = copyin(msg.msg_iov, iov,
                    432:                    (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
                    433:                goto done;
                    434:        msg.msg_iov = iov;
                    435: #ifdef COMPAT_OLDSOCK
                    436:        msg.msg_flags = 0;
                    437: #endif
                    438:        error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
                    439: done:
                    440:        if (iov != aiov)
                    441:                free(iov, M_IOV);
                    442:        return (error);
                    443: }
                    444:
                    445: int
                    446: sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
                    447: {
                    448:        struct file *fp;
                    449:        struct uio auio;
                    450:        struct iovec *iov;
                    451:        int i;
                    452:        struct mbuf *to, *control;
                    453:        int len, error;
                    454: #ifdef KTRACE
                    455:        struct iovec *ktriov = NULL;
                    456: #endif
                    457:
                    458:        to = NULL;
                    459:
                    460:        if ((error = getsock(p->p_fd, s, &fp)) != 0)
                    461:                return (error);
                    462:        auio.uio_iov = mp->msg_iov;
                    463:        auio.uio_iovcnt = mp->msg_iovlen;
                    464:        auio.uio_segflg = UIO_USERSPACE;
                    465:        auio.uio_rw = UIO_WRITE;
                    466:        auio.uio_procp = p;
                    467:        auio.uio_offset = 0;                    /* XXX */
                    468:        auio.uio_resid = 0;
                    469:        iov = mp->msg_iov;
                    470:        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
                    471:                /* Don't allow sum > SSIZE_MAX */
                    472:                if (iov->iov_len > SSIZE_MAX ||
                    473:                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
                    474:                        error = EINVAL;
                    475:                        goto bad;
                    476:                }
                    477:        }
                    478:        if (mp->msg_name) {
                    479:                error = sockargs(&to, mp->msg_name, mp->msg_namelen,
                    480:                                 MT_SONAME);
                    481:                if (error)
                    482:                        goto bad;
                    483:        }
                    484:        if (mp->msg_control) {
                    485:                if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))
                    486: #ifdef COMPAT_OLDSOCK
                    487:                    && mp->msg_flags != MSG_COMPAT
                    488: #endif
                    489:                ) {
                    490:                        error = EINVAL;
                    491:                        goto bad;
                    492:                }
                    493:                error = sockargs(&control, mp->msg_control,
                    494:                                 mp->msg_controllen, MT_CONTROL);
                    495:                if (error)
                    496:                        goto bad;
                    497: #ifdef COMPAT_OLDSOCK
                    498:                if (mp->msg_flags == MSG_COMPAT) {
                    499:                        struct cmsghdr *cm;
                    500:
                    501:                        M_PREPEND(control, sizeof(*cm), M_WAIT);
                    502:                        cm = mtod(control, struct cmsghdr *);
                    503:                        cm->cmsg_len = control->m_len;
                    504:                        cm->cmsg_level = SOL_SOCKET;
                    505:                        cm->cmsg_type = SCM_RIGHTS;
                    506:                }
                    507: #endif
                    508:        } else
                    509:                control = 0;
                    510: #ifdef KTRACE
                    511:        if (KTRPOINT(p, KTR_GENIO)) {
                    512:                int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
                    513:
                    514:                ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
                    515:                bcopy(auio.uio_iov, ktriov, iovlen);
                    516:        }
                    517: #endif
                    518:        len = auio.uio_resid;
                    519:        error = sosend(fp->f_data, to, &auio, NULL, control, flags);
                    520:        if (error) {
                    521:                if (auio.uio_resid != len && (error == ERESTART ||
                    522:                    error == EINTR || error == EWOULDBLOCK))
                    523:                        error = 0;
                    524:                if (error == EPIPE)
                    525:                        psignal(p, SIGPIPE);
                    526:        }
                    527:        if (error == 0) {
                    528:                *retsize = len - auio.uio_resid;
                    529:                fp->f_wxfer++;
                    530:                fp->f_wbytes += *retsize;
                    531:        }
                    532: #ifdef KTRACE
                    533:        if (ktriov != NULL) {
                    534:                if (error == 0)
                    535:                        ktrgenio(p, s, UIO_WRITE, ktriov, *retsize, error);
                    536:                free(ktriov, M_TEMP);
                    537:        }
                    538: #endif
                    539: bad:
                    540:        FRELE(fp);
                    541:        if (to)
                    542:                m_freem(to);
                    543:        return (error);
                    544: }
                    545:
                    546: int
                    547: sys_recvfrom(struct proc *p, void *v, register_t *retval)
                    548: {
                    549:        struct sys_recvfrom_args /* {
                    550:                syscallarg(int) s;
                    551:                syscallarg(void *) buf;
                    552:                syscallarg(size_t) len;
                    553:                syscallarg(int) flags;
                    554:                syscallarg(struct sockaddr *) from;
                    555:                syscallarg(socklen_t *) fromlenaddr;
                    556:        } */ *uap = v;
                    557:        struct msghdr msg;
                    558:        struct iovec aiov;
                    559:        int error;
                    560:
                    561:        if (SCARG(uap, fromlenaddr)) {
                    562:                error = copyin(SCARG(uap, fromlenaddr),
                    563:                    &msg.msg_namelen, sizeof (msg.msg_namelen));
                    564:                if (error)
                    565:                        return (error);
                    566:        } else
                    567:                msg.msg_namelen = 0;
                    568:        msg.msg_name = (caddr_t)SCARG(uap, from);
                    569:        msg.msg_iov = &aiov;
                    570:        msg.msg_iovlen = 1;
                    571:        aiov.iov_base = SCARG(uap, buf);
                    572:        aiov.iov_len = SCARG(uap, len);
                    573:        msg.msg_control = 0;
                    574:        msg.msg_flags = SCARG(uap, flags);
                    575:        return (recvit(p, SCARG(uap, s), &msg,
                    576:            (caddr_t)SCARG(uap, fromlenaddr), retval));
                    577: }
                    578:
                    579: int
                    580: sys_recvmsg(struct proc *p, void *v, register_t *retval)
                    581: {
                    582:        struct sys_recvmsg_args /* {
                    583:                syscallarg(int) s;
                    584:                syscallarg(struct msghdr *) msg;
                    585:                syscallarg(int) flags;
                    586:        } */ *uap = v;
                    587:        struct msghdr msg;
                    588:        struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
                    589:        int error;
                    590:
                    591:        error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
                    592:        if (error)
                    593:                return (error);
                    594:        if (msg.msg_iovlen > IOV_MAX)
                    595:                return (EMSGSIZE);
                    596:        if (msg.msg_iovlen > UIO_SMALLIOV)
                    597:                iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
                    598:                    M_IOV, M_WAITOK);
                    599:        else
                    600:                iov = aiov;
                    601: #ifdef COMPAT_OLDSOCK
                    602:        msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
                    603: #else
                    604:        msg.msg_flags = SCARG(uap, flags);
                    605: #endif
                    606:        if (msg.msg_iovlen > 0) {
                    607:                error = copyin(msg.msg_iov, iov,
                    608:                    (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
                    609:                if (error)
                    610:                        goto done;
                    611:        }
                    612:        uiov = msg.msg_iov;
                    613:        msg.msg_iov = iov;
                    614:        if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) {
                    615:                msg.msg_iov = uiov;
                    616:                error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
                    617:        }
                    618: done:
                    619:        if (iov != aiov)
                    620:                free(iov, M_IOV);
                    621:        return (error);
                    622: }
                    623:
                    624: int
                    625: recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
                    626:     register_t *retsize)
                    627: {
                    628:        struct file *fp;
                    629:        struct uio auio;
                    630:        struct iovec *iov;
                    631:        int i;
                    632:        size_t len;
                    633:        int error;
                    634:        struct mbuf *from = NULL, *control = NULL;
                    635: #ifdef KTRACE
                    636:        struct iovec *ktriov = NULL;
                    637: #endif
                    638:
                    639:        if ((error = getsock(p->p_fd, s, &fp)) != 0)
                    640:                return (error);
                    641:        auio.uio_iov = mp->msg_iov;
                    642:        auio.uio_iovcnt = mp->msg_iovlen;
                    643:        auio.uio_segflg = UIO_USERSPACE;
                    644:        auio.uio_rw = UIO_READ;
                    645:        auio.uio_procp = p;
                    646:        auio.uio_offset = 0;                    /* XXX */
                    647:        auio.uio_resid = 0;
                    648:        iov = mp->msg_iov;
                    649:        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
                    650:                /* Don't allow sum > SSIZE_MAX */
                    651:                if (iov->iov_len > SSIZE_MAX ||
                    652:                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
                    653:                        error = EINVAL;
                    654:                        goto out;
                    655:                }
                    656:        }
                    657: #ifdef KTRACE
                    658:        if (KTRPOINT(p, KTR_GENIO)) {
                    659:                int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
                    660:
                    661:                ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
                    662:                bcopy(auio.uio_iov, ktriov, iovlen);
                    663:        }
                    664: #endif
                    665:        len = auio.uio_resid;
                    666:        error = soreceive(fp->f_data, &from, &auio, NULL,
                    667:                          mp->msg_control ? &control : NULL,
                    668:                          &mp->msg_flags);
                    669:        if (error) {
                    670:                if (auio.uio_resid != len && (error == ERESTART ||
                    671:                    error == EINTR || error == EWOULDBLOCK))
                    672:                        error = 0;
                    673:        }
                    674: #ifdef KTRACE
                    675:        if (ktriov != NULL) {
                    676:                if (error == 0)
                    677:                        ktrgenio(p, s, UIO_READ,
                    678:                                ktriov, len - auio.uio_resid, error);
                    679:                free(ktriov, M_TEMP);
                    680:        }
                    681: #endif
                    682:        if (error)
                    683:                goto out;
                    684:        *retsize = len - auio.uio_resid;
                    685:        if (mp->msg_name) {
                    686:                socklen_t alen;
                    687:
                    688:                if (from == NULL)
                    689:                        alen = 0;
                    690:                else {
                    691:                        /* save sa_len before it is destroyed by MSG_COMPAT */
                    692:                        alen = mp->msg_namelen;
                    693:                        if (alen > from->m_len)
                    694:                                alen = from->m_len;
                    695:                        /* else if alen < from->m_len ??? */
                    696: #ifdef COMPAT_OLDSOCK
                    697:                        if (mp->msg_flags & MSG_COMPAT)
                    698:                                mtod(from, struct osockaddr *)->sa_family =
                    699:                                    mtod(from, struct sockaddr *)->sa_family;
                    700: #endif
                    701:                        error = copyout(mtod(from, caddr_t), mp->msg_name, alen);
                    702:                        if (error)
                    703:                                goto out;
                    704:                }
                    705:                mp->msg_namelen = alen;
                    706:                if (namelenp &&
                    707:                    (error = copyout(&alen, namelenp, sizeof(alen)))) {
                    708: #ifdef COMPAT_OLDSOCK
                    709:                        if (mp->msg_flags & MSG_COMPAT)
                    710:                                error = 0;      /* old recvfrom didn't check */
                    711:                        else
                    712: #endif
                    713:                        goto out;
                    714:                }
                    715:        }
                    716:        if (mp->msg_control) {
                    717: #ifdef COMPAT_OLDSOCK
                    718:                /*
                    719:                 * We assume that old recvmsg calls won't receive access
                    720:                 * rights and other control info, esp. as control info
                    721:                 * is always optional and those options didn't exist in 4.3.
                    722:                 * If we receive rights, trim the cmsghdr; anything else
                    723:                 * is tossed.
                    724:                 */
                    725:                if (control && mp->msg_flags & MSG_COMPAT) {
                    726:                        if (mtod(control, struct cmsghdr *)->cmsg_level !=
                    727:                            SOL_SOCKET ||
                    728:                            mtod(control, struct cmsghdr *)->cmsg_type !=
                    729:                            SCM_RIGHTS) {
                    730:                                mp->msg_controllen = 0;
                    731:                                goto out;
                    732:                        }
                    733:                        control->m_len -= sizeof (struct cmsghdr);
                    734:                        control->m_data += sizeof (struct cmsghdr);
                    735:                }
                    736: #endif
                    737:                len = mp->msg_controllen;
                    738:                if (len <= 0 || control == NULL)
                    739:                        len = 0;
                    740:                else {
                    741:                        struct mbuf *m = control;
                    742:                        caddr_t p = mp->msg_control;
                    743:
                    744:                        do {
                    745:                                i = m->m_len;
                    746:                                if (len < i) {
                    747:                                        mp->msg_flags |= MSG_CTRUNC;
                    748:                                        i = len;
                    749:                                }
                    750:                                error = copyout(mtod(m, caddr_t), p,
                    751:                                    (unsigned)i);
                    752:                                if (m->m_next)
                    753:                                        i = ALIGN(i);
                    754:                                p += i;
                    755:                                len -= i;
                    756:                                if (error != 0 || len <= 0)
                    757:                                        break;
                    758:                        } while ((m = m->m_next) != NULL);
                    759:                        len = p - (caddr_t)mp->msg_control;
                    760:                }
                    761:                mp->msg_controllen = len;
                    762:        }
                    763:        if (!error) {
                    764:                fp->f_rxfer++;
                    765:                fp->f_rbytes += *retsize;
                    766:        }
                    767: out:
                    768:        FRELE(fp);
                    769:        if (from)
                    770:                m_freem(from);
                    771:        if (control)
                    772:                m_freem(control);
                    773:        return (error);
                    774: }
                    775:
                    776: /* ARGSUSED */
                    777: int
                    778: sys_shutdown(struct proc *p, void *v, register_t *retval)
                    779: {
                    780:        struct sys_shutdown_args /* {
                    781:                syscallarg(int) s;
                    782:                syscallarg(int) how;
                    783:        } */ *uap = v;
                    784:        struct file *fp;
                    785:        int error;
                    786:
                    787:        if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
                    788:                return (error);
                    789:        error = soshutdown(fp->f_data, SCARG(uap, how));
                    790:        FRELE(fp);
                    791:        return (error);
                    792: }
                    793:
                    794: /* ARGSUSED */
                    795: int
                    796: sys_setsockopt(struct proc *p, void *v, register_t *retval)
                    797: {
                    798:        struct sys_setsockopt_args /* {
                    799:                syscallarg(int) s;
                    800:                syscallarg(int) level;
                    801:                syscallarg(int) name;
                    802:                syscallarg(const void *) val;
                    803:                syscallarg(socklen_t) valsize;
                    804:        } */ *uap = v;
                    805:        struct file *fp;
                    806:        struct mbuf *m = NULL;
                    807:        int error;
                    808:
                    809:        if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
                    810:                return (error);
                    811:        if (SCARG(uap, valsize) > MCLBYTES) {
                    812:                error = EINVAL;
                    813:                goto bad;
                    814:        }
                    815:        if (SCARG(uap, val)) {
                    816:                m = m_get(M_WAIT, MT_SOOPTS);
                    817:                if (SCARG(uap, valsize) > MLEN) {
                    818:                        MCLGET(m, M_DONTWAIT);
                    819:                        if ((m->m_flags & M_EXT) == 0) {
                    820:                                error = ENOBUFS;
                    821:                                goto bad;
                    822:                        }
                    823:                }
                    824:                if (m == NULL) {
                    825:                        error = ENOBUFS;
                    826:                        goto bad;
                    827:                }
                    828:                error = copyin(SCARG(uap, val), mtod(m, caddr_t),
                    829:                    SCARG(uap, valsize));
                    830:                if (error) {
                    831:                        goto bad;
                    832:                }
                    833:                m->m_len = SCARG(uap, valsize);
                    834:        }
                    835:        error = sosetopt(fp->f_data, SCARG(uap, level),
                    836:                         SCARG(uap, name), m);
                    837:        m = NULL;
                    838: bad:
                    839:        if (m)
                    840:                m_freem(m);
                    841:        FRELE(fp);
                    842:        return (error);
                    843: }
                    844:
                    845: /* ARGSUSED */
                    846: int
                    847: sys_getsockopt(struct proc *p, void *v, register_t *retval)
                    848: {
                    849:        struct sys_getsockopt_args /* {
                    850:                syscallarg(int) s;
                    851:                syscallarg(int) level;
                    852:                syscallarg(int) name;
                    853:                syscallarg(void *) val;
                    854:                syscallarg(socklen_t *) avalsize;
                    855:        } */ *uap = v;
                    856:        struct file *fp;
                    857:        struct mbuf *m = NULL;
                    858:        socklen_t valsize;
                    859:        int error;
                    860:
                    861:        if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
                    862:                return (error);
                    863:        if (SCARG(uap, val)) {
                    864:                error = copyin(SCARG(uap, avalsize),
                    865:                    &valsize, sizeof (valsize));
                    866:                if (error)
                    867:                        goto out;
                    868:        } else
                    869:                valsize = 0;
                    870:        if ((error = sogetopt(fp->f_data, SCARG(uap, level),
                    871:            SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
                    872:            m != NULL) {
                    873:                if (valsize > m->m_len)
                    874:                        valsize = m->m_len;
                    875:                error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
                    876:                if (error == 0)
                    877:                        error = copyout(&valsize,
                    878:                            SCARG(uap, avalsize), sizeof (valsize));
                    879:        }
                    880: out:
                    881:        FRELE(fp);
                    882:        if (m != NULL)
                    883:                (void)m_free(m);
                    884:        return (error);
                    885: }
                    886:
                    887: int
                    888: sys_pipe(struct proc *p, void *v, register_t *retval)
                    889: {
                    890:        struct sys_pipe_args /* {
                    891:                syscallarg(int *) fdp;
                    892:        } */ *uap = v;
                    893:        int error, fds[2];
                    894:        register_t rval[2];
                    895:
                    896:        if ((error = sys_opipe(p, v, rval)) != 0)
                    897:                return (error);
                    898:
                    899:        fds[0] = rval[0];
                    900:        fds[1] = rval[1];
                    901:        error = copyout(fds, SCARG(uap, fdp), 2 * sizeof (int));
                    902:        if (error) {
                    903:                fdplock(p->p_fd);
                    904:                fdrelease(p, fds[0]);
                    905:                fdrelease(p, fds[1]);
                    906:                fdpunlock(p->p_fd);
                    907:        }
                    908:        return (error);
                    909: }
                    910:
                    911: /*
                    912:  * Get socket name.
                    913:  */
                    914: /* ARGSUSED */
                    915: int
                    916: sys_getsockname(struct proc *p, void *v, register_t *retval)
                    917: {
                    918:        struct sys_getsockname_args /* {
                    919:                syscallarg(int) fdes;
                    920:                syscallarg(struct sockaddr *) asa;
                    921:                syscallarg(socklen_t *) alen;
                    922:        } */ *uap = v;
                    923:        struct file *fp;
                    924:        struct socket *so;
                    925:        struct mbuf *m = NULL;
                    926:        socklen_t len;
                    927:        int error;
                    928:
                    929:        if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
                    930:                return (error);
                    931:        error = copyin(SCARG(uap, alen), &len, sizeof (len));
                    932:        if (error)
                    933:                goto bad;
                    934:        so = fp->f_data;
                    935:        m = m_getclr(M_WAIT, MT_SONAME);
                    936:        error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
                    937:        if (error)
                    938:                goto bad;
                    939:        if (len > m->m_len)
                    940:                len = m->m_len;
                    941:        error = copyout(mtod(m, caddr_t), SCARG(uap, asa), len);
                    942:        if (error == 0)
                    943:                error = copyout(&len, SCARG(uap, alen), sizeof (len));
                    944: bad:
                    945:        FRELE(fp);
                    946:        if (m)
                    947:                m_freem(m);
                    948:        return (error);
                    949: }
                    950:
                    951: /*
                    952:  * Get name of peer for connected socket.
                    953:  */
                    954: /* ARGSUSED */
                    955: int
                    956: sys_getpeername(struct proc *p, void *v, register_t *retval)
                    957: {
                    958:        struct sys_getpeername_args /* {
                    959:                syscallarg(int) fdes;
                    960:                syscallarg(struct sockaddr *) asa;
                    961:                syscallarg(socklen_t *) alen;
                    962:        } */ *uap = v;
                    963:        struct file *fp;
                    964:        struct socket *so;
                    965:        struct mbuf *m = NULL;
                    966:        socklen_t len;
                    967:        int error;
                    968:
                    969:        if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
                    970:                return (error);
                    971:        so = fp->f_data;
                    972:        if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
                    973:                FRELE(fp);
                    974:                return (ENOTCONN);
                    975:        }
                    976:        error = copyin(SCARG(uap, alen), &len, sizeof (len));
                    977:        if (error)
                    978:                goto bad;
                    979:        m = m_getclr(M_WAIT, MT_SONAME);
                    980:        error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
                    981:        if (error)
                    982:                goto bad;
                    983:        if (len > m->m_len)
                    984:                len = m->m_len;
                    985:        error = copyout(mtod(m, caddr_t), SCARG(uap, asa), len);
                    986:        if (error == 0)
                    987:                error = copyout(&len, SCARG(uap, alen), sizeof (len));
                    988: bad:
                    989:        FRELE(fp);
                    990:        m_freem(m);
                    991:        return (error);
                    992: }
                    993:
                    994: /*
                    995:  * Get eid of peer for connected socket.
                    996:  */
                    997: /* ARGSUSED */
                    998: int
                    999: sys_getpeereid(struct proc *p, void *v, register_t *retval)
                   1000: {
                   1001:        struct sys_getpeereid_args /* {
                   1002:                syscallarg(int) fdes;
                   1003:                syscallarg(uid_t *) euid;
                   1004:                syscallarg(gid_t *) egid;
                   1005:        } */ *uap = v;
                   1006:        struct file *fp;
                   1007:        struct socket *so;
                   1008:        struct mbuf *m = NULL;
                   1009:        struct unpcbid *id;
                   1010:        int error;
                   1011:
                   1012:        if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
                   1013:                return (error);
                   1014:        so = fp->f_data;
                   1015:        if (so->so_proto != pffindtype(AF_LOCAL, SOCK_STREAM)) {
                   1016:                FRELE(fp);
                   1017:                return (EOPNOTSUPP);
                   1018:        }
                   1019:        m = m_getclr(M_WAIT, MT_SONAME);
                   1020:        if (m == NULL) {
                   1021:                error = ENOBUFS;
                   1022:                goto bad;
                   1023:        }
                   1024:        error = (*so->so_proto->pr_usrreq)(so, PRU_PEEREID, 0, m, 0);
                   1025:        if (!error && m->m_len != sizeof(struct unpcbid))
                   1026:                error = EOPNOTSUPP;
                   1027:        if (error)
                   1028:                goto bad;
                   1029:        id = mtod(m, struct unpcbid *);
                   1030:        error = copyout(&(id->unp_euid), SCARG(uap, euid), sizeof(uid_t));
                   1031:        if (error == 0)
                   1032:                error = copyout(&(id->unp_egid), SCARG(uap, egid), sizeof(gid_t));
                   1033: bad:
                   1034:        FRELE(fp);
                   1035:        m_freem(m);
                   1036:        return (error);
                   1037: }
                   1038:
                   1039: int
                   1040: sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
                   1041: {
                   1042:        struct sockaddr *sa;
                   1043:        struct mbuf *m;
                   1044:        int error;
                   1045:
                   1046:        /*
                   1047:         * We can't allow socket names > UCHAR_MAX in length, since that
                   1048:         * will overflow sa_len. Also, control data more than MCLBYTES in
                   1049:         * length is just too much.
                   1050:         */
                   1051:        if (buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES))
                   1052:                return (EINVAL);
                   1053:
                   1054:        /* Allocate an mbuf to hold the arguments. */
                   1055:        m = m_get(M_WAIT, type);
                   1056:        if ((u_int)buflen > MLEN) {
                   1057:                MCLGET(m, M_WAITOK);
                   1058:                if ((m->m_flags & M_EXT) == 0) {
                   1059:                        m_free(m);
                   1060:                        return ENOBUFS;
                   1061:                }
                   1062:        }
                   1063:        m->m_len = buflen;
                   1064:        error = copyin(buf, mtod(m, caddr_t), buflen);
                   1065:        if (error) {
                   1066:                (void) m_free(m);
                   1067:                return (error);
                   1068:        }
                   1069:        *mp = m;
                   1070:        if (type == MT_SONAME) {
                   1071:                sa = mtod(m, struct sockaddr *);
                   1072: #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
                   1073:                if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
                   1074:                        sa->sa_family = sa->sa_len;
                   1075: #endif
                   1076:                sa->sa_len = buflen;
                   1077:        }
                   1078:        return (0);
                   1079: }
                   1080:
                   1081: int
                   1082: getsock(struct filedesc *fdp, int fdes, struct file **fpp)
                   1083: {
                   1084:        struct file *fp;
                   1085:
                   1086:        if ((fp = fd_getfile(fdp, fdes)) == NULL)
                   1087:                return (EBADF);
                   1088:        if (fp->f_type != DTYPE_SOCKET)
                   1089:                return (ENOTSOCK);
                   1090:        *fpp = fp;
                   1091:        FREF(fp);
                   1092:
                   1093:        return (0);
                   1094: }

CVSweb