1/*- 2 * Copyright (c) 2015 Nuxi, https://nuxi.nl/ 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: releng/11.0/sys/compat/cloudabi64/cloudabi64_sock.c 297247 2016-03-24 21:47:15Z ed $"); 28 29#include <sys/param.h> 30#include <sys/kernel.h> 31#include <sys/malloc.h> 32#include <sys/proc.h> 33#include <sys/socket.h> 34#include <sys/syscallsubr.h> 35#include <sys/systm.h> 36#include <sys/uio.h> 37 38#include <contrib/cloudabi/cloudabi64_types.h> 39 40#include <compat/cloudabi/cloudabi_util.h> 41 42#include <compat/cloudabi64/cloudabi64_proto.h> 43 44static MALLOC_DEFINE(M_SOCKET, "socket", "CloudABI socket"); 45 46int 47cloudabi64_sys_sock_recv(struct thread *td, 48 struct cloudabi64_sys_sock_recv_args *uap) 49{ 50 struct sockaddr_storage ss; 51 cloudabi64_recv_in_t ri; 52 cloudabi64_recv_out_t ro = {}; 53 cloudabi64_iovec_t iovobj; 54 struct msghdr msghdr = {}; 55 size_t i; 56 int error; 57 58 error = copyin(uap->in, &ri, sizeof(ri)); 59 if (error != 0) 60 return (error); 61 62 /* Convert results in cloudabi_recv_in_t to struct msghdr. */ 63 if (ri.ri_datalen > UIO_MAXIOV) 64 return (EINVAL); 65 msghdr.msg_iovlen = ri.ri_datalen; 66 msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec), 67 M_SOCKET, M_WAITOK); 68 for (i = 0; i < msghdr.msg_iovlen; i++) { 69 error = copyin(&((cloudabi64_iovec_t *)ri.ri_data)[i], &iovobj, 70 sizeof(iovobj)); 71 if (error != 0) { 72 free(msghdr.msg_iov, M_SOCKET); 73 return (error); 74 } 75 msghdr.msg_iov[i].iov_base = (void *)iovobj.iov_base; 76 msghdr.msg_iov[i].iov_len = iovobj.iov_len; 77 } 78 msghdr.msg_name = &ss; 79 msghdr.msg_namelen = sizeof(ss); 80 if (ri.ri_flags & CLOUDABI_MSG_PEEK) 81 msghdr.msg_flags |= MSG_PEEK; 82 if (ri.ri_flags & CLOUDABI_MSG_WAITALL) 83 msghdr.msg_flags |= MSG_WAITALL; 84 85 /* TODO(ed): Add file descriptor passing. */ 86 error = kern_recvit(td, uap->sock, &msghdr, UIO_SYSSPACE, NULL); 87 free(msghdr.msg_iov, M_SOCKET); 88 if (error != 0) 89 return (error); 90 91 /* Convert results in msghdr to cloudabi_recv_out_t. */ 92 ro.ro_datalen = td->td_retval[0]; 93 cloudabi_convert_sockaddr((struct sockaddr *)&ss, 94 MIN(msghdr.msg_namelen, sizeof(ss)), &ro.ro_peername); 95 td->td_retval[0] = 0; 96 return (copyout(&ro, uap->out, sizeof(ro))); 97} 98 99int 100cloudabi64_sys_sock_send(struct thread *td, 101 struct cloudabi64_sys_sock_send_args *uap) 102{ 103 cloudabi64_send_in_t si; 104 cloudabi64_send_out_t so = {}; 105 cloudabi64_ciovec_t iovobj; 106 struct msghdr msghdr = {}; 107 size_t i; 108 int error, flags; 109 110 error = copyin(uap->in, &si, sizeof(si)); 111 if (error != 0) 112 return (error); 113 114 /* Convert results in cloudabi_send_in_t to struct msghdr. */ 115 if (si.si_datalen > UIO_MAXIOV) 116 return (EINVAL); 117 msghdr.msg_iovlen = si.si_datalen; 118 msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec), 119 M_SOCKET, M_WAITOK); 120 for (i = 0; i < msghdr.msg_iovlen; i++) { 121 error = copyin(&((cloudabi64_ciovec_t *)si.si_data)[i], &iovobj, 122 sizeof(iovobj)); 123 if (error != 0) { 124 free(msghdr.msg_iov, M_SOCKET); 125 return (error); 126 } 127 msghdr.msg_iov[i].iov_base = (void *)iovobj.iov_base; 128 msghdr.msg_iov[i].iov_len = iovobj.iov_len; 129 } 130 131 flags = MSG_NOSIGNAL; 132 if (si.si_flags & CLOUDABI_MSG_EOR) 133 flags |= MSG_EOR; 134 135 /* TODO(ed): Add file descriptor passing. */ 136 error = kern_sendit(td, uap->sock, &msghdr, flags, NULL, UIO_USERSPACE); 137 free(msghdr.msg_iov, M_SOCKET); 138 if (error != 0) 139 return (error); 140 141 /* Convert results in msghdr to cloudabi_send_out_t. */ 142 so.so_datalen = td->td_retval[0]; 143 td->td_retval[0] = 0; 144 return (copyout(&so, uap->out, sizeof(so))); 145} 146