1285307Sed/*- 2285307Sed * Copyright (c) 2015 Nuxi, https://nuxi.nl/ 3285307Sed * 4285307Sed * Redistribution and use in source and binary forms, with or without 5285307Sed * modification, are permitted provided that the following conditions 6285307Sed * are met: 7285307Sed * 1. Redistributions of source code must retain the above copyright 8285307Sed * notice, this list of conditions and the following disclaimer. 9285307Sed * 2. Redistributions in binary form must reproduce the above copyright 10285307Sed * notice, this list of conditions and the following disclaimer in the 11285307Sed * documentation and/or other materials provided with the distribution. 12285307Sed * 13285307Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14285307Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15285307Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16285307Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17285307Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18285307Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19285307Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20285307Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21285307Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22285307Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23285307Sed * SUCH DAMAGE. 24285307Sed */ 25285307Sed 26285307Sed#include <sys/cdefs.h> 27285307Sed__FBSDID("$FreeBSD: releng/11.0/sys/compat/cloudabi64/cloudabi64_sock.c 297247 2016-03-24 21:47:15Z ed $"); 28285307Sed 29286680Sed#include <sys/param.h> 30286680Sed#include <sys/kernel.h> 31286680Sed#include <sys/malloc.h> 32286680Sed#include <sys/proc.h> 33286680Sed#include <sys/socket.h> 34286680Sed#include <sys/syscallsubr.h> 35286680Sed#include <sys/systm.h> 36286680Sed#include <sys/uio.h> 37286680Sed 38297247Sed#include <contrib/cloudabi/cloudabi64_types.h> 39297247Sed 40286680Sed#include <compat/cloudabi/cloudabi_util.h> 41286680Sed 42285307Sed#include <compat/cloudabi64/cloudabi64_proto.h> 43285307Sed 44286680Sedstatic MALLOC_DEFINE(M_SOCKET, "socket", "CloudABI socket"); 45286680Sed 46285307Sedint 47285307Sedcloudabi64_sys_sock_recv(struct thread *td, 48285307Sed struct cloudabi64_sys_sock_recv_args *uap) 49285307Sed{ 50286680Sed struct sockaddr_storage ss; 51286680Sed cloudabi64_recv_in_t ri; 52286680Sed cloudabi64_recv_out_t ro = {}; 53286680Sed cloudabi64_iovec_t iovobj; 54286680Sed struct msghdr msghdr = {}; 55286680Sed size_t i; 56286680Sed int error; 57285307Sed 58286680Sed error = copyin(uap->in, &ri, sizeof(ri)); 59286680Sed if (error != 0) 60286680Sed return (error); 61286680Sed 62286680Sed /* Convert results in cloudabi_recv_in_t to struct msghdr. */ 63286680Sed if (ri.ri_datalen > UIO_MAXIOV) 64286680Sed return (EINVAL); 65286680Sed msghdr.msg_iovlen = ri.ri_datalen; 66286680Sed msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec), 67286680Sed M_SOCKET, M_WAITOK); 68286680Sed for (i = 0; i < msghdr.msg_iovlen; i++) { 69286680Sed error = copyin(&((cloudabi64_iovec_t *)ri.ri_data)[i], &iovobj, 70286680Sed sizeof(iovobj)); 71286680Sed if (error != 0) { 72286680Sed free(msghdr.msg_iov, M_SOCKET); 73286680Sed return (error); 74286680Sed } 75286680Sed msghdr.msg_iov[i].iov_base = (void *)iovobj.iov_base; 76286680Sed msghdr.msg_iov[i].iov_len = iovobj.iov_len; 77286680Sed } 78286680Sed msghdr.msg_name = &ss; 79286680Sed msghdr.msg_namelen = sizeof(ss); 80286680Sed if (ri.ri_flags & CLOUDABI_MSG_PEEK) 81286680Sed msghdr.msg_flags |= MSG_PEEK; 82286680Sed if (ri.ri_flags & CLOUDABI_MSG_WAITALL) 83286680Sed msghdr.msg_flags |= MSG_WAITALL; 84286680Sed 85286680Sed /* TODO(ed): Add file descriptor passing. */ 86297247Sed error = kern_recvit(td, uap->sock, &msghdr, UIO_SYSSPACE, NULL); 87286680Sed free(msghdr.msg_iov, M_SOCKET); 88286680Sed if (error != 0) 89286680Sed return (error); 90286680Sed 91286680Sed /* Convert results in msghdr to cloudabi_recv_out_t. */ 92286680Sed ro.ro_datalen = td->td_retval[0]; 93286680Sed cloudabi_convert_sockaddr((struct sockaddr *)&ss, 94286680Sed MIN(msghdr.msg_namelen, sizeof(ss)), &ro.ro_peername); 95286680Sed td->td_retval[0] = 0; 96286680Sed return (copyout(&ro, uap->out, sizeof(ro))); 97285307Sed} 98285307Sed 99285307Sedint 100285307Sedcloudabi64_sys_sock_send(struct thread *td, 101285307Sed struct cloudabi64_sys_sock_send_args *uap) 102285307Sed{ 103286680Sed cloudabi64_send_in_t si; 104286680Sed cloudabi64_send_out_t so = {}; 105286680Sed cloudabi64_ciovec_t iovobj; 106286680Sed struct msghdr msghdr = {}; 107286680Sed size_t i; 108286680Sed int error, flags; 109285307Sed 110286680Sed error = copyin(uap->in, &si, sizeof(si)); 111286680Sed if (error != 0) 112286680Sed return (error); 113286680Sed 114286680Sed /* Convert results in cloudabi_send_in_t to struct msghdr. */ 115286680Sed if (si.si_datalen > UIO_MAXIOV) 116286680Sed return (EINVAL); 117286680Sed msghdr.msg_iovlen = si.si_datalen; 118286680Sed msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec), 119286680Sed M_SOCKET, M_WAITOK); 120286680Sed for (i = 0; i < msghdr.msg_iovlen; i++) { 121286680Sed error = copyin(&((cloudabi64_ciovec_t *)si.si_data)[i], &iovobj, 122286680Sed sizeof(iovobj)); 123286680Sed if (error != 0) { 124286680Sed free(msghdr.msg_iov, M_SOCKET); 125286680Sed return (error); 126286680Sed } 127286680Sed msghdr.msg_iov[i].iov_base = (void *)iovobj.iov_base; 128286680Sed msghdr.msg_iov[i].iov_len = iovobj.iov_len; 129286680Sed } 130286680Sed 131286680Sed flags = MSG_NOSIGNAL; 132286680Sed if (si.si_flags & CLOUDABI_MSG_EOR) 133286680Sed flags |= MSG_EOR; 134286680Sed 135286680Sed /* TODO(ed): Add file descriptor passing. */ 136297247Sed error = kern_sendit(td, uap->sock, &msghdr, flags, NULL, UIO_USERSPACE); 137286680Sed free(msghdr.msg_iov, M_SOCKET); 138286680Sed if (error != 0) 139286680Sed return (error); 140286680Sed 141286680Sed /* Convert results in msghdr to cloudabi_send_out_t. */ 142286680Sed so.so_datalen = td->td_retval[0]; 143286680Sed td->td_retval[0] = 0; 144286680Sed return (copyout(&so, uap->out, sizeof(so))); 145285307Sed} 146