Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/uipc_syscalls.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/kern/uipc_syscalls.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.92.2.9 retrieving revision 1.93 diff -u -p -r1.92.2.9 -r1.93 --- src/sys/kern/uipc_syscalls.c 2008/03/24 09:39:02 1.92.2.9 +++ src/sys/kern/uipc_syscalls.c 2005/09/03 19:44:20 1.93 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_syscalls.c,v 1.92.2.9 2008/03/24 09:39:02 yamt Exp $ */ +/* $NetBSD: uipc_syscalls.c,v 1.93 2005/09/03 19:44:20 martin Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1990, 1993 @@ -32,8 +32,9 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.92.2.9 2008/03/24 09:39:02 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.93 2005/09/03 19:44:20 martin Exp $"); +#include "opt_ktrace.h" #include "opt_pipe.h" #include @@ -49,242 +50,257 @@ __KERNEL_RCSID(0, "$NetBSD: uipc_syscall #include #include #include +#ifdef KTRACE #include +#endif #include #include +#include #include #include +static void adjust_rights(struct mbuf *m, int len, struct proc *p); + /* * System call interface to the socket abstraction. */ extern const struct fileops socketops; int -sys___socket30(struct lwp *l, const struct sys___socket30_args *uap, register_t *retval) +sys_socket(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_socket_args /* { syscallarg(int) domain; syscallarg(int) type; syscallarg(int) protocol; - } */ + } */ *uap = v; + + struct proc *p; + struct filedesc *fdp; + struct socket *so; + struct file *fp; int fd, error; - error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type), - SCARG(uap, protocol), l, &fd); - if (error == 0) + p = l->l_proc; + fdp = p->p_fd; + /* falloc() will use the desciptor for us */ + if ((error = falloc(p, &fp, &fd)) != 0) + return (error); + fp->f_flag = FREAD|FWRITE; + fp->f_type = DTYPE_SOCKET; + fp->f_ops = &socketops; + error = socreate(SCARG(uap, domain), &so, SCARG(uap, type), + SCARG(uap, protocol), p); + if (error) { + FILE_UNUSE(fp, p); + fdremove(fdp, fd); + ffree(fp); + } else { + fp->f_data = (caddr_t)so; + FILE_SET_MATURE(fp); + FILE_UNUSE(fp, p); *retval = fd; - return error; + } + return (error); } /* ARGSUSED */ int -sys_bind(struct lwp *l, const struct sys_bind_args *uap, register_t *retval) +sys_bind(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_bind_args /* { syscallarg(int) s; syscallarg(const struct sockaddr *) name; syscallarg(unsigned int) namelen; - } */ + } */ *uap = v; + struct proc *p; + struct file *fp; struct mbuf *nam; int error; + p = l->l_proc; + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) + return (error); error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), MT_SONAME); - if (error) - return error; - - return do_sys_bind(l, SCARG(uap, s), nam); -} - -int -do_sys_bind(struct lwp *l, int fd, struct mbuf *nam) -{ - struct socket *so; - int error; - - if ((error = fd_getsock(fd, &so)) != 0) { - m_freem(nam); + if (error) { + FILE_UNUSE(fp, p); return (error); } - MCLAIM(nam, so->so_mowner); - error = sobind(so, nam, l); + MCLAIM(nam, ((struct socket *)fp->f_data)->so_mowner); + error = sobind((struct socket *)fp->f_data, nam, p); m_freem(nam); - fd_putfile(fd); - return error; + FILE_UNUSE(fp, p); + return (error); } /* ARGSUSED */ int -sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval) +sys_listen(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_listen_args /* { syscallarg(int) s; syscallarg(int) backlog; - } */ - struct socket *so; + } */ *uap = v; + struct proc *p; + struct file *fp; int error; - if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) + p = l->l_proc; + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) return (error); - error = solisten(so, SCARG(uap, backlog), l); - fd_putfile(SCARG(uap, s)); - return error; + error = solisten((struct socket *)fp->f_data, SCARG(uap, backlog)); + FILE_UNUSE(fp, p); + return (error); } int -do_sys_accept(struct lwp *l, int sock, struct mbuf **name, register_t *new_sock) +sys_accept(struct lwp *l, void *v, register_t *retval) { - file_t *fp, *fp2; + struct sys_accept_args /* { + syscallarg(int) s; + syscallarg(struct sockaddr *) name; + syscallarg(unsigned int *) anamelen; + } */ *uap = v; + struct proc *p; + struct filedesc *fdp; + struct file *fp; struct mbuf *nam; + unsigned int namelen; int error, s, fd; - struct socket *so, *so2; + struct socket *so; + int fflag; - if ((fp = fd_getfile(sock)) == NULL) - return (EBADF); - if (fp->f_type != DTYPE_SOCKET) - return (ENOTSOCK); - if ((error = fd_allocfile(&fp2, &fd)) != 0) + p = l->l_proc; + fdp = p->p_fd; + if (SCARG(uap, name) && (error = copyin(SCARG(uap, anamelen), + &namelen, sizeof(namelen)))) + return (error); + + /* getsock() will use the descriptor for us */ + if ((error = getsock(fdp, SCARG(uap, s), &fp)) != 0) return (error); - nam = m_get(M_WAIT, MT_SONAME); - *new_sock = fd; s = splsoftnet(); - so = fp->f_data; - fd_putfile(sock); /* XXX wrong, socket can disappear */ + so = (struct socket *)fp->f_data; + FILE_UNUSE(fp, p); if (!(so->so_proto->pr_flags & PR_LISTEN)) { - error = EOPNOTSUPP; - goto bad; + splx(s); + return (EOPNOTSUPP); } if ((so->so_options & SO_ACCEPTCONN) == 0) { - error = EINVAL; - goto bad; + splx(s); + return (EINVAL); } - if (so->so_nbio && so->so_qlen == 0) { - error = EWOULDBLOCK; - goto bad; + if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { + splx(s); + return (EWOULDBLOCK); } while (so->so_qlen == 0 && so->so_error == 0) { if (so->so_state & SS_CANTRCVMORE) { so->so_error = ECONNABORTED; break; } - error = tsleep(&so->so_timeo, PSOCK | PCATCH, - netcon, 0); + error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, + netcon, 0); if (error) { - goto bad; + splx(s); + return (error); } } if (so->so_error) { error = so->so_error; so->so_error = 0; - goto bad; + splx(s); + return (error); + } + fflag = fp->f_flag; + /* falloc() will use the descriptor for us */ + if ((error = falloc(p, &fp, &fd)) != 0) { + splx(s); + return (error); } + *retval = fd; + /* connection has been removed from the listen queue */ KNOTE(&so->so_rcv.sb_sel.sel_klist, 0); - so2 = TAILQ_FIRST(&so->so_q); - if (soqremque(so2, 1) == 0) + + { struct socket *aso = TAILQ_FIRST(&so->so_q); + if (soqremque(aso, 1) == 0) panic("accept"); - fp2->f_type = DTYPE_SOCKET; - fp2->f_flag = fp->f_flag; - fp2->f_ops = &socketops; - fp2->f_data = so2; - error = soaccept(so2, nam); - splx(s); + so = aso; + } + fp->f_type = DTYPE_SOCKET; + fp->f_flag = fflag; + fp->f_ops = &socketops; + fp->f_data = (caddr_t)so; + FILE_UNUSE(fp, p); + nam = m_get(M_WAIT, MT_SONAME); + if ((error = soaccept(so, nam)) == 0 && SCARG(uap, name)) { + if (namelen > nam->m_len) + namelen = nam->m_len; + /* SHOULD COPY OUT A CHAIN HERE */ + if ((error = copyout(mtod(nam, caddr_t), + (caddr_t)SCARG(uap, name), namelen)) == 0) + error = copyout((caddr_t)&namelen, + (caddr_t)SCARG(uap, anamelen), + sizeof(*SCARG(uap, anamelen))); + } + /* if an error occurred, free the file descriptor */ if (error) { - /* an error occurred, free the file descriptor and mbuf */ - m_freem(nam); - mutex_enter(&fp2->f_lock); - fp2->f_count++; - mutex_exit(&fp2->f_lock); - closef(fp2); - fd_abort(curproc, NULL, fd); - } else { - fd_affix(curproc, fp2, fd); - *name = nam; + fdremove(fdp, fd); + ffree(fp); } - return (error); - bad: + m_freem(nam); splx(s); - m_freem(nam); - fd_abort(curproc, fp2, fd); - return (error); -} - -int -sys_accept(struct lwp *l, const struct sys_accept_args *uap, register_t *retval) -{ - /* { - syscallarg(int) s; - syscallarg(struct sockaddr *) name; - syscallarg(unsigned int *) anamelen; - } */ - int error, fd; - struct mbuf *name; - - error = do_sys_accept(l, SCARG(uap, s), &name, retval); - if (error != 0) - return error; - error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen), - MSG_LENUSRSPACE, name); - if (name != NULL) - m_free(name); - if (error != 0) { - fd = (int)*retval; - if (fd_getfile(fd) != NULL) - (void)fd_close(fd); - } - return error; + FILE_SET_MATURE(fp); + return (error); } /* ARGSUSED */ int -sys_connect(struct lwp *l, const struct sys_connect_args *uap, register_t *retval) +sys_connect(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_connect_args /* { syscallarg(int) s; syscallarg(const struct sockaddr *) name; syscallarg(unsigned int) namelen; - } */ - int error; - struct mbuf *nam; - - error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), - MT_SONAME); - if (error) - return error; - return do_sys_connect(l, SCARG(uap, s), nam); -} - -int -do_sys_connect(struct lwp *l, int fd, struct mbuf *nam) -{ + } */ *uap = v; + struct proc *p; + struct file *fp; struct socket *so; - int error; + struct mbuf *nam; + int error, s; int interrupted = 0; - int s; - if ((error = fd_getsock(fd, &so)) != 0) { - m_freem(nam); + p = l->l_proc; + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) return (error); - } - MCLAIM(nam, so->so_mowner); + so = (struct socket *)fp->f_data; if (so->so_state & SS_ISCONNECTING) { error = EALREADY; goto out; } - - error = soconnect(so, nam, l); + error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), + MT_SONAME); + if (error) + goto out; + MCLAIM(nam, so->so_mowner); + error = soconnect(so, nam, p); if (error) goto bad; - if (so->so_nbio && (so->so_state & SS_ISCONNECTING)) { + if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { + m_freem(nam); error = EINPROGRESS; goto out; } s = splsoftnet(); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { - error = tsleep(&so->so_timeo, PSOCK | PCATCH, + error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, netcon, 0); if (error) { if (error == EINTR || error == ERESTART) @@ -300,50 +316,53 @@ do_sys_connect(struct lwp *l, int fd, st bad: if (!interrupted) so->so_state &= ~SS_ISCONNECTING; + m_freem(nam); if (error == ERESTART) error = EINTR; out: - fd_putfile(fd); - m_freem(nam); + FILE_UNUSE(fp, p); return (error); } int -sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap, register_t *retval) +sys_socketpair(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_socketpair_args /* { syscallarg(int) domain; syscallarg(int) type; syscallarg(int) protocol; syscallarg(int *) rsv; - } */ - file_t *fp1, *fp2; + } */ *uap = v; + struct proc *p; + struct filedesc *fdp; + struct file *fp1, *fp2; struct socket *so1, *so2; int fd, error, sv[2]; - proc_t *p; - p = curproc; + p = l->l_proc; + fdp = p->p_fd; error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), - SCARG(uap, protocol), l); + SCARG(uap, protocol), p); if (error) return (error); error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), - SCARG(uap, protocol), l); + SCARG(uap, protocol), p); if (error) goto free1; - if ((error = fd_allocfile(&fp1, &fd)) != 0) + /* falloc() will use the descriptor for us */ + if ((error = falloc(p, &fp1, &fd)) != 0) goto free2; sv[0] = fd; fp1->f_flag = FREAD|FWRITE; fp1->f_type = DTYPE_SOCKET; fp1->f_ops = &socketops; - fp1->f_data = so1; - if ((error = fd_allocfile(&fp2, &fd)) != 0) + fp1->f_data = (caddr_t)so1; + if ((error = falloc(p, &fp2, &fd)) != 0) goto free3; fp2->f_flag = FREAD|FWRITE; fp2->f_type = DTYPE_SOCKET; fp2->f_ops = &socketops; - fp2->f_data = so2; + fp2->f_data = (caddr_t)so2; sv[1] = fd; if ((error = soconnect2(so1, so2)) != 0) goto free4; @@ -354,14 +373,21 @@ sys_socketpair(struct lwp *l, const stru if ((error = soconnect2(so2, so1)) != 0) goto free4; } - error = copyout(sv, SCARG(uap, rsv), 2 * sizeof(int)); - fd_affix(p, fp2, sv[1]); - fd_affix(p, fp1, sv[0]); + error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv), + 2 * sizeof(int)); + FILE_SET_MATURE(fp1); + FILE_SET_MATURE(fp2); + FILE_UNUSE(fp1, p); + FILE_UNUSE(fp2, p); return (error); free4: - fd_abort(p, fp2, sv[1]); + FILE_UNUSE(fp2, p); + ffree(fp2); + fdremove(fdp, sv[1]); free3: - fd_abort(p, fp1, sv[0]); + FILE_UNUSE(fp1, p); + ffree(fp1); + fdremove(fdp, sv[0]); free2: (void)soclose(so2); free1: @@ -370,106 +396,105 @@ sys_socketpair(struct lwp *l, const stru } int -sys_sendto(struct lwp *l, const struct sys_sendto_args *uap, register_t *retval) +sys_sendto(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_sendto_args /* { syscallarg(int) s; syscallarg(const void *) buf; syscallarg(size_t) len; syscallarg(int) flags; syscallarg(const struct sockaddr *) to; syscallarg(unsigned int) tolen; - } */ + } */ *uap = v; + struct proc *p; struct msghdr msg; struct iovec aiov; + p = l->l_proc; msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */ msg.msg_namelen = SCARG(uap, tolen); msg.msg_iov = &aiov; msg.msg_iovlen = 1; - msg.msg_control = NULL; + msg.msg_control = 0; msg.msg_flags = 0; aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */ aiov.iov_len = SCARG(uap, len); - return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval); + return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); } int -sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap, register_t *retval) +sys_sendmsg(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_sendmsg_args /* { syscallarg(int) s; syscallarg(const struct msghdr *) msg; syscallarg(int) flags; - } */ + } */ *uap = v; + struct proc *p; struct msghdr msg; + struct iovec aiov[UIO_SMALLIOV], *iov; int error; - error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); + error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg)); if (error) return (error); - - msg.msg_flags = MSG_IOVUSRSPACE; - return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval); + if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) { + if ((unsigned int)msg.msg_iovlen > IOV_MAX) + return (EMSGSIZE); + iov = malloc(sizeof(struct iovec) * msg.msg_iovlen, + M_IOV, M_WAITOK); + } else + iov = aiov; + if ((unsigned int)msg.msg_iovlen > 0) { + error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, + (size_t)(msg.msg_iovlen * sizeof(struct iovec))); + if (error) + goto done; + } + msg.msg_iov = iov; + msg.msg_flags = 0; + p = l->l_proc; + error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); +done: + if (iov != aiov) + free(iov, M_IOV); + return (error); } int -do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags, - register_t *retsize) +sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize) { + struct file *fp; struct uio auio; - int i, len, error, iovlen; + struct iovec *iov; + int i, len, error; struct mbuf *to, *control; struct socket *so; - struct iovec *tiov; - struct iovec aiov[UIO_SMALLIOV], *iov = aiov; - struct iovec *ktriov = NULL; - - ktrkuser("msghdr", mp, sizeof *mp); - - /* If the caller passed us stuff in mbufs, we must free them */ - if (mp->msg_flags & MSG_NAMEMBUF) - to = mp->msg_name; - else - to = NULL; - - if (mp->msg_flags & MSG_CONTROLMBUF) - control = mp->msg_control; - else - control = NULL; - - if (mp->msg_flags & MSG_IOVUSRSPACE) { - if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { - if ((unsigned int)mp->msg_iovlen > IOV_MAX) { - error = EMSGSIZE; - goto bad; - } - iov = malloc(sizeof(struct iovec) * mp->msg_iovlen, - M_IOV, M_WAITOK); - } - if (mp->msg_iovlen != 0) { - error = copyin(mp->msg_iov, iov, - (size_t)(mp->msg_iovlen * sizeof(struct iovec))); - if (error) - goto bad; - } - mp->msg_iov = iov; - } +#ifdef KTRACE + struct iovec *ktriov; +#endif +#ifdef KTRACE + ktriov = NULL; +#endif + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, s, &fp)) != 0) + return (error); + so = (struct socket *)fp->f_data; auio.uio_iov = mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = UIO_WRITE; + auio.uio_procp = p; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; - KASSERT(l == curlwp); - auio.uio_vmspace = l->l_proc->p_vmspace; - - for (i = 0, tiov = mp->msg_iov; i < mp->msg_iovlen; i++, tiov++) { + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++, iov++) { #if 0 /* cannot happen; iov_len is unsigned */ - if (tiov->iov_len < 0) { + if (iov->iov_len < 0) { error = EINVAL; - goto bad; + goto out; } #endif /* @@ -477,304 +502,207 @@ do_sys_sendmsg(struct lwp *l, int s, str * Therefore, we must restrict the length to SSIZE_MAX to * avoid garbage return values. */ - auio.uio_resid += tiov->iov_len; - if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { + auio.uio_resid += iov->iov_len; + if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { error = EINVAL; - goto bad; + goto out; } } - - if (mp->msg_name && to == NULL) { + if (mp->msg_name) { error = sockargs(&to, mp->msg_name, mp->msg_namelen, - MT_SONAME); + MT_SONAME); if (error) - goto bad; - } - + goto out; + MCLAIM(to, so->so_mowner); + } else + to = 0; if (mp->msg_control) { - if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { + if (mp->msg_controllen < sizeof(struct cmsghdr)) { error = EINVAL; goto bad; } - if (control == NULL) { - error = sockargs(&control, mp->msg_control, - mp->msg_controllen, MT_CONTROL); - if (error) - goto bad; - } - } + error = sockargs(&control, mp->msg_control, + mp->msg_controllen, MT_CONTROL); + if (error) + goto bad; + MCLAIM(control, so->so_mowner); + } else + control = 0; +#ifdef KTRACE + if (KTRPOINT(p, KTR_GENIO)) { + int iovlen = auio.uio_iovcnt * sizeof(struct iovec); - if (ktrpoint(KTR_GENIO)) { - iovlen = auio.uio_iovcnt * sizeof(struct iovec); ktriov = malloc(iovlen, M_TEMP, M_WAITOK); - memcpy(ktriov, auio.uio_iov, iovlen); + memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen); } - - if ((error = fd_getsock(s, &so)) != 0) - goto bad; - - if (mp->msg_name) - MCLAIM(to, so->so_mowner); - if (mp->msg_control) - MCLAIM(control, so->so_mowner); - +#endif len = auio.uio_resid; - KERNEL_LOCK(1, NULL); - error = (*so->so_send)(so, to, &auio, NULL, control, flags, l); - KERNEL_UNLOCK_ONE(NULL); - /* Protocol is responsible for freeing 'control' */ - control = NULL; - - fd_putfile(s); - + error = (*so->so_send)(so, to, &auio, NULL, control, flags, p); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; - if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) { - mutex_enter(&proclist_mutex); - psignal(l->l_proc, SIGPIPE); - mutex_exit(&proclist_mutex); - } + if (error == EPIPE) + psignal(p, SIGPIPE); } if (error == 0) *retsize = len - auio.uio_resid; - -bad: +#ifdef KTRACE if (ktriov != NULL) { - ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error); + if (error == 0) + ktrgenio(p, s, UIO_WRITE, ktriov, *retsize, error); free(ktriov, M_TEMP); } - - if (iov != aiov) - free(iov, M_IOV); +#endif + bad: if (to) m_freem(to); - if (control) - m_freem(control); - + out: + FILE_UNUSE(fp, p); return (error); } int -sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, register_t *retval) +sys_recvfrom(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_recvfrom_args /* { syscallarg(int) s; syscallarg(void *) buf; syscallarg(size_t) len; syscallarg(int) flags; syscallarg(struct sockaddr *) from; syscallarg(unsigned int *) fromlenaddr; - } */ + } */ *uap = v; + struct proc *p; struct msghdr msg; struct iovec aiov; int error; - struct mbuf *from; - msg.msg_name = NULL; + if (SCARG(uap, fromlenaddr)) { + error = copyin((caddr_t)SCARG(uap, fromlenaddr), + (caddr_t)&msg.msg_namelen, + sizeof(msg.msg_namelen)); + if (error) + return (error); + } else + msg.msg_namelen = 0; + msg.msg_name = (caddr_t)SCARG(uap, from); msg.msg_iov = &aiov; msg.msg_iovlen = 1; aiov.iov_base = SCARG(uap, buf); aiov.iov_len = SCARG(uap, len); - msg.msg_control = NULL; - msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS; - - error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval); - if (error != 0) - return error; - - error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr), - MSG_LENUSRSPACE, from); - if (from != NULL) - m_free(from); - return error; + msg.msg_control = 0; + msg.msg_flags = SCARG(uap, flags); + p = l->l_proc; + return (recvit(p, SCARG(uap, s), &msg, + (caddr_t)SCARG(uap, fromlenaddr), retval)); } int -sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap, register_t *retval) +sys_recvmsg(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_recvmsg_args /* { syscallarg(int) s; syscallarg(struct msghdr *) msg; syscallarg(int) flags; - } */ + } */ *uap = v; + struct proc *p; struct msghdr msg; + struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; int error; - struct mbuf *from, *control; - error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); + error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg, + sizeof(msg)); if (error) return (error); - - msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; - - error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, - msg.msg_control != NULL ? &control : NULL, retval); - if (error != 0) - return error; - - if (msg.msg_control != NULL) - error = copyout_msg_control(l, &msg, control); - - if (error == 0) - error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0, - from); - if (from != NULL) - m_free(from); - if (error == 0) { - ktrkuser("msghdr", &msg, sizeof msg); - error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); + if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) { + if ((unsigned int)msg.msg_iovlen > IOV_MAX) + return (EMSGSIZE); + iov = malloc(sizeof(struct iovec) * msg.msg_iovlen, + M_IOV, M_WAITOK); + } else + iov = aiov; + if ((unsigned int)msg.msg_iovlen > 0) { + error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, + (size_t)(msg.msg_iovlen * sizeof(struct iovec))); + if (error) + goto done; } - + uiov = msg.msg_iov; + msg.msg_iov = iov; + msg.msg_flags = SCARG(uap, flags); + p = l->l_proc; + if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) { + msg.msg_iov = uiov; + error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg), + sizeof(msg)); + } +done: + if (iov != aiov) + free(iov, M_IOV); return (error); } /* - * Adjust for a truncated SCM_RIGHTS control message. - * This means closing any file descriptors that aren't present - * in the returned buffer. - * m is the mbuf holding the (already externalized) SCM_RIGHTS message. + * Adjust for a truncated SCM_RIGHTS control message. This means + * closing any file descriptors that aren't entirely present in the + * returned buffer. m is the mbuf holding the (already externalized) + * SCM_RIGHTS message; len is the length it is being truncated to. p + * is the affected process. */ static void -free_rights(struct mbuf *m) +adjust_rights(struct mbuf *m, int len, struct proc *p) { int nfd; int i; + int nok; int *fdv; - nfd = m->m_len < CMSG_SPACE(sizeof(int)) ? 0 - : (m->m_len - CMSG_SPACE(sizeof(int))) / sizeof(int) + 1; + nfd = (m->m_len - CMSG_LEN(0)) / sizeof(int); + nok = (len < CMSG_LEN(0)) ? 0 : ((len - CMSG_LEN(0)) / sizeof(int)); fdv = (int *) CMSG_DATA(mtod(m,struct cmsghdr *)); - for (i = 0; i < nfd; i++) { - if (fd_getfile(fdv[i]) != NULL) - (void)fd_close(fdv[i]); - } -} - -void -free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied) -{ - struct mbuf *next; - struct cmsghdr *cmsg; - bool do_free_rights = false; - - while (control != NULL) { - cmsg = mtod(control, struct cmsghdr *); - if (control == uncopied) - do_free_rights = true; - if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET - && cmsg->cmsg_type == SCM_RIGHTS) - free_rights(control); - next = control->m_next; - m_free(control); - control = next; - } -} - -/* Copy socket control/CMSG data to user buffer, frees the mbuf */ -int -copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control) -{ - int i, len, error = 0; - struct cmsghdr *cmsg; - struct mbuf *m; - char *q; - - len = mp->msg_controllen; - if (len <= 0 || control == 0) { - mp->msg_controllen = 0; - free_control_mbuf(l, control, control); - return 0; - } - - q = (char *)mp->msg_control; - - for (m = control; m != NULL; ) { - cmsg = mtod(m, struct cmsghdr *); - i = m->m_len; - if (len < i) { - mp->msg_flags |= MSG_CTRUNC; - if (cmsg->cmsg_level == SOL_SOCKET - && cmsg->cmsg_type == SCM_RIGHTS) - /* Do not truncate me ... */ - break; - i = len; - } - error = copyout(mtod(m, void *), q, i); - ktrkuser("msgcontrol", mtod(m, void *), i); - if (error != 0) { - /* We must free all the SCM_RIGHTS */ - m = control; - break; - } - m = m->m_next; - if (m) - i = ALIGN(i); - q += i; - len -= i; - if (len <= 0) - break; - } - - free_control_mbuf(l, control, m); - - mp->msg_controllen = q - (char *)mp->msg_control; - return error; + for (i = nok; i < nfd; i++) + fdrelease(p,fdv[i]); } int -do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from, - struct mbuf **control, register_t *retsize) +recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp, + register_t *retsize) { + struct file *fp; struct uio auio; - struct iovec aiov[UIO_SMALLIOV], *iov = aiov; - struct iovec *tiov; - int i, len, error, iovlen; + struct iovec *iov; + int i, len, error; + struct mbuf *from, *control; struct socket *so; +#ifdef KTRACE struct iovec *ktriov; +#endif - ktrkuser("msghdr", mp, sizeof *mp); - - *from = NULL; - if (control != NULL) - *control = NULL; + from = 0; + control = 0; +#ifdef KTRACE + ktriov = NULL; +#endif - if ((error = fd_getsock(s, &so)) != 0) + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, s, &fp)) != 0) return (error); - - if (mp->msg_flags & MSG_IOVUSRSPACE) { - if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) { - if ((unsigned int)mp->msg_iovlen > IOV_MAX) { - error = EMSGSIZE; - goto out; - } - iov = malloc(sizeof(struct iovec) * mp->msg_iovlen, - M_IOV, M_WAITOK); - } - if (mp->msg_iovlen != 0) { - error = copyin(mp->msg_iov, iov, - (size_t)(mp->msg_iovlen * sizeof(struct iovec))); - if (error) - goto out; - } - auio.uio_iov = iov; - } else - auio.uio_iov = mp->msg_iov; + so = (struct socket *)fp->f_data; + auio.uio_iov = mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = UIO_READ; + auio.uio_procp = p; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; - KASSERT(l == curlwp); - auio.uio_vmspace = l->l_proc->p_vmspace; - - tiov = auio.uio_iov; - for (i = 0; i < mp->msg_iovlen; i++, tiov++) { + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++, iov++) { #if 0 /* cannot happen iov_len is unsigned */ - if (tiov->iov_len < 0) { + if (iov->iov_len < 0) { error = EINVAL; - goto out; + goto out1; } #endif /* @@ -782,84 +710,138 @@ do_sys_recvmsg(struct lwp *l, int s, str * Therefore we must restrict the length to SSIZE_MAX to * avoid garbage return values. */ - auio.uio_resid += tiov->iov_len; - if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { + auio.uio_resid += iov->iov_len; + if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { error = EINVAL; - goto out; + goto out1; } } +#ifdef KTRACE + if (KTRPOINT(p, KTR_GENIO)) { + int iovlen = auio.uio_iovcnt * sizeof(struct iovec); - ktriov = NULL; - if (ktrpoint(KTR_GENIO)) { - iovlen = auio.uio_iovcnt * sizeof(struct iovec); ktriov = malloc(iovlen, M_TEMP, M_WAITOK); - memcpy(ktriov, auio.uio_iov, iovlen); + memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen); } - +#endif len = auio.uio_resid; - mp->msg_flags &= MSG_USERFLAGS; - KERNEL_LOCK(1, NULL); - error = (*so->so_receive)(so, from, &auio, NULL, control, - &mp->msg_flags); - KERNEL_UNLOCK_ONE(NULL); - len -= auio.uio_resid; - *retsize = len; - if (error != 0 && len != 0 - && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) - /* Some data transferred */ - error = 0; - + error = (*so->so_receive)(so, &from, &auio, NULL, + mp->msg_control ? &control : NULL, &mp->msg_flags); + if (error) { + if (auio.uio_resid != len && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) + error = 0; + } +#ifdef KTRACE if (ktriov != NULL) { - ktrgeniov(s, UIO_READ, ktriov, len, error); + if (error == 0) + ktrgenio(p, s, UIO_READ, ktriov, + len - auio.uio_resid, error); free(ktriov, M_TEMP); } - - if (error != 0) { - m_freem(*from); - *from = NULL; - if (control != NULL) { - free_control_mbuf(l, *control, *control); - *control = NULL; +#endif + if (error) + goto out; + *retsize = len - auio.uio_resid; + if (mp->msg_name) { + len = mp->msg_namelen; + if (len <= 0 || from == 0) + len = 0; + else { + if (len > from->m_len) + len = from->m_len; + /* else if len < from->m_len ??? */ + error = copyout(mtod(from, caddr_t), + (caddr_t)mp->msg_name, (unsigned)len); + if (error) + goto out; + } + mp->msg_namelen = len; + if (namelenp && + (error = copyout((caddr_t)&len, namelenp, sizeof(int)))) + goto out; + } + if (mp->msg_control) { + len = mp->msg_controllen; + if (len <= 0 || control == 0) + len = 0; + else { + struct mbuf *m = control; + caddr_t q = (caddr_t)mp->msg_control; + + do { + i = m->m_len; + if (len < i) { + mp->msg_flags |= MSG_CTRUNC; + i = len; + if (mtod(m, struct cmsghdr *)-> + cmsg_type == SCM_RIGHTS) + adjust_rights(m, len, p); + } + error = copyout(mtod(m, caddr_t), q, + (unsigned)i); + m = m->m_next; + if (m) + i = ALIGN(i); + q += i; + len -= i; + if (error != 0 || len <= 0) + break; + } while (m != NULL); + while (m) { + if (mtod(m, struct cmsghdr *)-> + cmsg_type == SCM_RIGHTS) + adjust_rights(m, 0, p); + m = m->m_next; + } + len = q - (caddr_t)mp->msg_control; } + mp->msg_controllen = len; } out: - if (iov != aiov) - free(iov, M_TEMP); - fd_putfile(s); + if (from) + m_freem(from); + if (control) + m_freem(control); + out1: + FILE_UNUSE(fp, p); return (error); } - /* ARGSUSED */ int -sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval) +sys_shutdown(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_shutdown_args /* { syscallarg(int) s; syscallarg(int) how; - } */ - struct socket *so; + } */ *uap = v; + struct proc *p; + struct file *fp; int error; - if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) + p = l->l_proc; + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) return (error); - error = soshutdown(so, SCARG(uap, how)); - fd_putfile(SCARG(uap, s)); + error = soshutdown((struct socket *)fp->f_data, SCARG(uap, how)); + FILE_UNUSE(fp, p); return (error); } /* ARGSUSED */ int -sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap, register_t *retval) +sys_setsockopt(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_setsockopt_args /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(const void *) val; syscallarg(unsigned int) valsize; - } */ + } */ *uap = v; struct proc *p; + struct file *fp; struct mbuf *m; struct socket *so; int error; @@ -867,18 +849,21 @@ sys_setsockopt(struct lwp *l, const stru p = l->l_proc; m = NULL; - if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) return (error); + so = (struct socket *)fp->f_data; len = SCARG(uap, valsize); if (len > MCLBYTES) { error = EINVAL; goto out; } if (SCARG(uap, val)) { - m = getsombuf(so, MT_SOOPTS); + m = m_get(M_WAIT, MT_SOOPTS); + MCLAIM(m, so->so_mowner); if (len > MLEN) m_clget(m, M_WAIT); - error = copyin(SCARG(uap, val), mtod(m, void *), len); + error = copyin(SCARG(uap, val), mtod(m, caddr_t), len); if (error) { (void) m_free(m); goto out; @@ -887,45 +872,48 @@ sys_setsockopt(struct lwp *l, const stru } error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m); out: - fd_putfile(SCARG(uap, s)); + FILE_UNUSE(fp, p); return (error); } /* ARGSUSED */ int -sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, register_t *retval) +sys_getsockopt(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_getsockopt_args /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(void *) val; syscallarg(unsigned int *) avalsize; - } */ - struct socket *so; + } */ *uap = v; + struct proc *p; + struct file *fp; struct mbuf *m; unsigned int op, i, valsize; int error; - char *val = SCARG(uap, val); + p = l->l_proc; m = NULL; - if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) return (error); - if (val != NULL) { - error = copyin(SCARG(uap, avalsize), - &valsize, sizeof(valsize)); + if (SCARG(uap, val)) { + error = copyin((caddr_t)SCARG(uap, avalsize), + (caddr_t)&valsize, sizeof(valsize)); if (error) goto out; } else valsize = 0; - error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), &m); - if (error == 0 && val != NULL && valsize && m != NULL) { + if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level), + SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize && + m != NULL) { op = 0; while (m && !error && op < valsize) { i = min(m->m_len, (valsize - op)); - error = copyout(mtod(m, void *), val, i); + error = copyout(mtod(m, caddr_t), SCARG(uap, val), i); op += i; - val += i; + SCARG(uap, val) = ((u_int8_t *)SCARG(uap, val)) + i; m = m_free(m); } valsize = op; @@ -936,51 +924,60 @@ sys_getsockopt(struct lwp *l, const stru if (m != NULL) (void) m_freem(m); out: - fd_putfile(SCARG(uap, s)); + FILE_UNUSE(fp, p); return (error); } #ifdef PIPE_SOCKETPAIR /* ARGSUSED */ int -sys_pipe(struct lwp *l, const void *v, register_t *retval) +sys_pipe(struct lwp *l, void *v, register_t *retval) { - file_t *rf, *wf; + struct proc *p; + struct filedesc *fdp; + struct file *rf, *wf; struct socket *rso, *wso; int fd, error; - proc_t *p; - p = curproc; - if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l)) != 0) + p = l->l_proc; + fdp = p->p_fd; + if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, p)) != 0) return (error); - if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l)) != 0) + if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, p)) != 0) goto free1; /* remember this socket pair implements a pipe */ wso->so_state |= SS_ISAPIPE; rso->so_state |= SS_ISAPIPE; - if ((error = fd_allocfile(&rf, &fd)) != 0) + /* falloc() will use the descriptor for us */ + if ((error = falloc(p, &rf, &fd)) != 0) goto free2; retval[0] = fd; rf->f_flag = FREAD; rf->f_type = DTYPE_SOCKET; rf->f_ops = &socketops; - rf->f_data = rso; - if ((error = fd_allocfile(&wf, &fd)) != 0) + rf->f_data = (caddr_t)rso; + if ((error = falloc(p, &wf, &fd)) != 0) goto free3; wf->f_flag = FWRITE; wf->f_type = DTYPE_SOCKET; wf->f_ops = &socketops; - wf->f_data = wso; + wf->f_data = (caddr_t)wso; retval[1] = fd; if ((error = unp_connect2(wso, rso, PRU_CONNECT2)) != 0) goto free4; - fd_affix(p, wf, (int)retval[1]); - fd_affix(p, rf, (int)retval[0]); + FILE_SET_MATURE(rf); + FILE_SET_MATURE(wf); + FILE_UNUSE(rf, p); + FILE_UNUSE(wf, p); return (0); free4: - fd_abort(p, wf, (int)retval[1]); + FILE_UNUSE(wf, p); + ffree(wf); + fdremove(fdp, retval[1]); free3: - fd_abort(p, rf, (int)retval[0]); + FILE_UNUSE(rf, p); + ffree(rf); + fdremove(fdp, retval[0]); free2: (void)soclose(wso); free1: @@ -994,98 +991,45 @@ sys_pipe(struct lwp *l, const void *v, r */ /* ARGSUSED */ int -do_sys_getsockname(struct lwp *l, int fd, int which, struct mbuf **nam) +sys_getsockname(struct lwp *l, void *v, register_t *retval) { + struct sys_getsockname_args /* { + syscallarg(int) fdes; + syscallarg(struct sockaddr *) asa; + syscallarg(unsigned int *) alen; + } */ *uap = v; + struct proc *p; + struct file *fp; struct socket *so; struct mbuf *m; + unsigned int len; int error; - if ((error = fd_getsock(fd, &so)) != 0) - return error; - - if (which == PRU_PEERADDR - && (so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) == 0) { - error = ENOTCONN; - goto bad; - } - + p = l->l_proc; + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) + return (error); + error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len)); + if (error) + goto out; + so = (struct socket *)fp->f_data; m = m_getclr(M_WAIT, MT_SONAME); - *nam = m; MCLAIM(m, so->so_mowner); - error = (*so->so_proto->pr_usrreq)(so, which, (struct mbuf *)0, - m, (struct mbuf *)0, (struct lwp *)0); - if (error != 0) - m_free(m); + error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0, + m, (struct mbuf *)0, (struct proc *)0); + if (error) + goto bad; + if (len > m->m_len) + len = m->m_len; + error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len); + if (error == 0) + error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), + sizeof(len)); bad: - fd_putfile(fd); - return error; -} - -int -copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags, - struct mbuf *addr) -{ - int len; - int error; - - if (asa == NULL) - /* Assume application not interested */ - return 0; - - if (flags & MSG_LENUSRSPACE) { - error = copyin(alen, &len, sizeof(len)); - if (error) - return error; - } else - len = *alen; - if (len < 0) - return EINVAL; - - if (addr == NULL) { - len = 0; - error = 0; - } else { - if (len > addr->m_len) - len = addr->m_len; - /* Maybe this ought to copy a chain ? */ - ktrkuser("sockname", mtod(addr, void *), len); - error = copyout(mtod(addr, void *), asa, len); - } - - if (error == 0) { - if (flags & MSG_LENUSRSPACE) - error = copyout(&len, alen, sizeof(len)); - else - *alen = len; - } - - return error; -} - -/* - * Get socket name. - */ -/* ARGSUSED */ -int -sys_getsockname(struct lwp *l, const struct sys_getsockname_args *uap, register_t *retval) -{ - /* { - syscallarg(int) fdes; - syscallarg(struct sockaddr *) asa; - syscallarg(unsigned int *) alen; - } */ - struct mbuf *m; - int error; - - error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_SOCKADDR, &m); - if (error != 0) - return error; - - error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen), - MSG_LENUSRSPACE, m); - if (m != NULL) - m_free(m); - return error; + m_freem(m); + out: + FILE_UNUSE(fp, p); + return (error); } /* @@ -1093,25 +1037,49 @@ sys_getsockname(struct lwp *l, const str */ /* ARGSUSED */ int -sys_getpeername(struct lwp *l, const struct sys_getpeername_args *uap, register_t *retval) +sys_getpeername(struct lwp *l, void *v, register_t *retval) { - /* { + struct sys_getpeername_args /* { syscallarg(int) fdes; syscallarg(struct sockaddr *) asa; syscallarg(unsigned int *) alen; - } */ + } */ *uap = v; + struct proc *p; + struct file *fp; + struct socket *so; struct mbuf *m; + unsigned int len; int error; - error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_PEERADDR, &m); - if (error != 0) - return error; - - error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen), - MSG_LENUSRSPACE, m); - if (m != NULL) - m_free(m); - return error; + p = l->l_proc; + /* getsock() will use the descriptor for us */ + if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) + return (error); + so = (struct socket *)fp->f_data; + if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { + error = ENOTCONN; + goto out; + } + error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len)); + if (error) + goto out; + m = m_getclr(M_WAIT, MT_SONAME); + MCLAIM(m, so->so_mowner); + error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0, + m, (struct mbuf *)0, (struct proc *)0); + if (error) + goto bad; + if (len > m->m_len) + len = m->m_len; + error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len); + if (error) + goto bad; + error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len)); + bad: + m_freem(m); + out: + FILE_UNUSE(fp, p); + return (error); } /* @@ -1144,12 +1112,11 @@ sockargs(struct mbuf **mp, const void *b MEXTMALLOC(m, buflen, M_WAITOK); } m->m_len = buflen; - error = copyin(bf, mtod(m, void *), buflen); + error = copyin(bf, mtod(m, caddr_t), buflen); if (error) { (void) m_free(m); return (error); } - ktrkuser("sockargs", mtod(m, void *), buflen); *mp = m; if (type == MT_SONAME) { sa = mtod(m, struct sockaddr *); @@ -1167,15 +1134,17 @@ sockargs(struct mbuf **mp, const void *b } int -getsock(int fdes, struct file **fpp) +getsock(struct filedesc *fdp, int fdes, struct file **fpp) { - file_t *fp; + struct file *fp; - if ((fp = fd_getfile(fdes)) == NULL) + if ((fp = fd_getfile(fdp, fdes)) == NULL) return (EBADF); + FILE_USE(fp); + if (fp->f_type != DTYPE_SOCKET) { - fd_putfile(fdes); + FILE_UNUSE(fp, NULL); return (ENOTSOCK); } *fpp = fp;