[BACK]Return to uipc_syscalls.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/uipc_syscalls.c, Revision 1.54

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

CVSweb <webmaster@jp.NetBSD.org>