Author: ed
Date: Wed Mar 22 06:43:10 2017
New Revision: 315700
URL: https://svnweb.freebsd.org/changeset/base/315700

Log:
  Make file descriptor passing work for CloudABI's sendmsg().
  
  Reduce the potential amount of code duplication between cloudabi32 and
  cloudabi64 by creating a cloudabi_sock_recv() utility function. The
  cloudabi32 and cloudabi64 modules will then only contain code to convert
  the iovecs to the native pointer size.
  
  In cloudabi_sock_recv(), we can now construct an SCM_RIGHTS cmsghdr in
  an mbuf and pass that on to kern_sendit().

Modified:
  head/sys/compat/cloudabi/cloudabi_sock.c
  head/sys/compat/cloudabi/cloudabi_util.h
  head/sys/compat/cloudabi32/cloudabi32_sock.c
  head/sys/compat/cloudabi64/cloudabi64_sock.c

Modified: head/sys/compat/cloudabi/cloudabi_sock.c
==============================================================================
--- head/sys/compat/cloudabi/cloudabi_sock.c    Wed Mar 22 05:27:20 2017        
(r315699)
+++ head/sys/compat/cloudabi/cloudabi_sock.c    Wed Mar 22 06:43:10 2017        
(r315700)
@@ -30,7 +30,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/capsicum.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
+#include <sys/mbuf.h>
 #include <sys/mutex.h>
+#include <sys/proc.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
@@ -243,3 +245,51 @@ cloudabi_sys_sock_stat_get(struct thread
        fdrop(fp, td);
        return (copyout(&ss, uap->buf, sizeof(ss)));
 }
+
+int
+cloudabi_sock_send(struct thread *td, cloudabi_fd_t fd, struct iovec *data,
+    size_t datalen, const cloudabi_fd_t *fds, size_t fdslen,
+    cloudabi_msgflags_t flags, size_t *rdatalen)
+{
+       struct msghdr hdr = {
+               .msg_iov = data,
+               .msg_iovlen = datalen,
+       };
+       struct mbuf *control;
+       int error, mflags;
+
+       /* Convert flags. */
+       mflags = MSG_NOSIGNAL;
+       if (flags & CLOUDABI_MSG_EOR)
+               mflags |= MSG_EOR;
+
+       /* Convert file descriptor array to an SCM_RIGHTS message. */
+       if (fdslen > MCLBYTES || CMSG_SPACE(fdslen * sizeof(int)) > MCLBYTES) {
+               return (EINVAL);
+       } else if (fdslen > 0) {
+               struct cmsghdr *chdr;
+
+               control = m_get2(CMSG_SPACE(fdslen * sizeof(int)),
+                   M_WAITOK, MT_CONTROL, 0);
+               control->m_len = CMSG_SPACE(fdslen * sizeof(int));
+
+               chdr = mtod(control, struct cmsghdr *);
+               chdr->cmsg_len = CMSG_LEN(fdslen * sizeof(int));
+               chdr->cmsg_level = SOL_SOCKET;
+               chdr->cmsg_type = SCM_RIGHTS;
+               error = copyin(fds, CMSG_DATA(chdr), fdslen * sizeof(int));
+               if (error != 0) {
+                       m_free(control);
+                       return (error);
+               }
+       } else {
+               control = NULL;
+       }
+
+       error = kern_sendit(td, fd, &hdr, mflags, control, UIO_USERSPACE);
+       if (error != 0)
+               return (error);
+       *rdatalen = td->td_retval[0];
+       td->td_retval[0] = 0;
+       return (0);
+}

Modified: head/sys/compat/cloudabi/cloudabi_util.h
==============================================================================
--- head/sys/compat/cloudabi/cloudabi_util.h    Wed Mar 22 05:27:20 2017        
(r315699)
+++ head/sys/compat/cloudabi/cloudabi_util.h    Wed Mar 22 06:43:10 2017        
(r315700)
@@ -77,6 +77,10 @@ int cloudabi_futex_lock_wrlock(struct th
     cloudabi_scope_t, cloudabi_clockid_t, cloudabi_timestamp_t,
     cloudabi_timestamp_t);
 
+/* Socket operations. */
+int cloudabi_sock_send(struct thread *, cloudabi_fd_t, struct iovec *, size_t,
+    const cloudabi_fd_t *, size_t, cloudabi_msgflags_t, size_t *);
+
 /* vDSO setup and teardown. */
 void cloudabi_vdso_init(struct sysentvec *, char *, char *);
 void cloudabi_vdso_destroy(struct sysentvec *);

Modified: head/sys/compat/cloudabi32/cloudabi32_sock.c
==============================================================================
--- head/sys/compat/cloudabi32/cloudabi32_sock.c        Wed Mar 22 05:27:20 
2017        (r315699)
+++ head/sys/compat/cloudabi32/cloudabi32_sock.c        Wed Mar 22 06:43:10 
2017        (r315700)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ * Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -105,44 +105,37 @@ cloudabi32_sys_sock_send(struct thread *
        cloudabi32_send_in_t si;
        cloudabi32_send_out_t so = {};
        cloudabi32_ciovec_t iovobj;
-       struct msghdr msghdr = {};
+       struct iovec *iov;
        const cloudabi32_ciovec_t *user_iov;
-       size_t i;
-       int error, flags;
+       size_t datalen, i;
+       int error;
 
        error = copyin(uap->in, &si, sizeof(si));
        if (error != 0)
                return (error);
 
-       /* Convert results in cloudabi_send_in_t to struct msghdr. */
+       /* Convert iovecs to native format. */
        if (si.si_data_len > UIO_MAXIOV)
                return (EINVAL);
-       msghdr.msg_iovlen = si.si_data_len;
-       msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec),
+       iov = malloc(si.si_data_len * sizeof(struct iovec),
            M_SOCKET, M_WAITOK);
        user_iov = TO_PTR(si.si_data);
-       for (i = 0; i < msghdr.msg_iovlen; i++) {
+       for (i = 0; i < si.si_data_len; i++) {
                error = copyin(&user_iov[i], &iovobj, sizeof(iovobj));
                if (error != 0) {
-                       free(msghdr.msg_iov, M_SOCKET);
+                       free(iov, M_SOCKET);
                        return (error);
                }
-               msghdr.msg_iov[i].iov_base = TO_PTR(iovobj.buf);
-               msghdr.msg_iov[i].iov_len = iovobj.buf_len;
+               iov[i].iov_base = TO_PTR(iovobj.buf);
+               iov[i].iov_len = iovobj.buf_len;
        }
 
-       flags = MSG_NOSIGNAL;
-       if (si.si_flags & CLOUDABI_MSG_EOR)
-               flags |= MSG_EOR;
-
-       /* TODO(ed): Add file descriptor passing. */
-       error = kern_sendit(td, uap->sock, &msghdr, flags, NULL, UIO_USERSPACE);
-       free(msghdr.msg_iov, M_SOCKET);
+       error = cloudabi_sock_send(td, uap->sock, iov, si.si_data_len,
+           TO_PTR(si.si_fds), si.si_fds_len, si.si_flags, &datalen);
+       free(iov, M_SOCKET);
        if (error != 0)
                return (error);
 
-       /* Convert results in msghdr to cloudabi_send_out_t. */
-       so.so_datalen = td->td_retval[0];
-       td->td_retval[0] = 0;
+       so.so_datalen = datalen;
        return (copyout(&so, uap->out, sizeof(so)));
 }

Modified: head/sys/compat/cloudabi64/cloudabi64_sock.c
==============================================================================
--- head/sys/compat/cloudabi64/cloudabi64_sock.c        Wed Mar 22 05:27:20 
2017        (r315699)
+++ head/sys/compat/cloudabi64/cloudabi64_sock.c        Wed Mar 22 06:43:10 
2017        (r315700)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ * Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -105,44 +105,37 @@ cloudabi64_sys_sock_send(struct thread *
        cloudabi64_send_in_t si;
        cloudabi64_send_out_t so = {};
        cloudabi64_ciovec_t iovobj;
-       struct msghdr msghdr = {};
+       struct iovec *iov;
        const cloudabi64_ciovec_t *user_iov;
-       size_t i;
-       int error, flags;
+       size_t datalen, i;
+       int error;
 
        error = copyin(uap->in, &si, sizeof(si));
        if (error != 0)
                return (error);
 
-       /* Convert results in cloudabi_send_in_t to struct msghdr. */
+       /* Convert iovecs to native format. */
        if (si.si_data_len > UIO_MAXIOV)
                return (EINVAL);
-       msghdr.msg_iovlen = si.si_data_len;
-       msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec),
+       iov = malloc(si.si_data_len * sizeof(struct iovec),
            M_SOCKET, M_WAITOK);
        user_iov = TO_PTR(si.si_data);
-       for (i = 0; i < msghdr.msg_iovlen; i++) {
+       for (i = 0; i < si.si_data_len; i++) {
                error = copyin(&user_iov[i], &iovobj, sizeof(iovobj));
                if (error != 0) {
-                       free(msghdr.msg_iov, M_SOCKET);
+                       free(iov, M_SOCKET);
                        return (error);
                }
-               msghdr.msg_iov[i].iov_base = TO_PTR(iovobj.buf);
-               msghdr.msg_iov[i].iov_len = iovobj.buf_len;
+               iov[i].iov_base = TO_PTR(iovobj.buf);
+               iov[i].iov_len = iovobj.buf_len;
        }
 
-       flags = MSG_NOSIGNAL;
-       if (si.si_flags & CLOUDABI_MSG_EOR)
-               flags |= MSG_EOR;
-
-       /* TODO(ed): Add file descriptor passing. */
-       error = kern_sendit(td, uap->sock, &msghdr, flags, NULL, UIO_USERSPACE);
-       free(msghdr.msg_iov, M_SOCKET);
+       error = cloudabi_sock_send(td, uap->sock, iov, si.si_data_len,
+           TO_PTR(si.si_fds), si.si_fds_len, si.si_flags, &datalen);
+       free(iov, M_SOCKET);
        if (error != 0)
                return (error);
 
-       /* Convert results in msghdr to cloudabi_send_out_t. */
-       so.so_datalen = td->td_retval[0];
-       td->td_retval[0] = 0;
+       so.so_datalen = datalen;
        return (copyout(&so, uap->out, sizeof(so)));
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to