[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.86.2.1.2.2

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

CVSweb <webmaster@jp.NetBSD.org>