diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 13:54:38 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 13:54:38 +0000 |
commit | 8c1ab65c0f548d20b7f177bdb736daaf603340e1 (patch) | |
tree | df55b7e75bf43f2bf500845b105afe3ac3a5157e /libc-bottom-half/cloudlibc/src/libc/sys/socket | |
parent | Initial commit. (diff) | |
download | wasi-libc-upstream/0.0_git20221206.8b7148f.tar.xz wasi-libc-upstream/0.0_git20221206.8b7148f.zip |
Adding upstream version 0.0~git20221206.8b7148f.upstream/0.0_git20221206.8b7148f
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libc-bottom-half/cloudlibc/src/libc/sys/socket')
5 files changed, 204 insertions, 0 deletions
diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c new file mode 100644 index 0000000..1fe41c4 --- /dev/null +++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/getsockopt.c @@ -0,0 +1,48 @@ +// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ +// +// SPDX-License-Identifier: BSD-2-Clause + +#include <sys/socket.h> + +#include <wasi/api.h> +#include <errno.h> +#include <string.h> + +int getsockopt(int socket, int level, int option_name, + void *restrict option_value, socklen_t *restrict option_len) { + // Only support SOL_SOCKET options for now. + if (level != SOL_SOCKET) { + errno = ENOPROTOOPT; + return -1; + } + + int value; + switch (option_name) { + case SO_TYPE: { + // Return the type of the socket. This information can simply be + // obtained by looking at the file descriptor type. + __wasi_fdstat_t fsb; + if (__wasi_fd_fdstat_get(socket, &fsb) != 0) { + errno = EBADF; + return -1; + } + if (fsb.fs_filetype != __WASI_FILETYPE_SOCKET_DGRAM && + fsb.fs_filetype != __WASI_FILETYPE_SOCKET_STREAM) { + errno = ENOTSOCK; + return -1; + } + value = fsb.fs_filetype; + break; + } + default: { + errno = ENOPROTOOPT; + return -1; + } + } + + // Copy out integer value. + memcpy(option_value, &value, + *option_len < sizeof(int) ? *option_len : sizeof(int)); + *option_len = sizeof(int); + return 0; +} diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c new file mode 100644 index 0000000..d35f889 --- /dev/null +++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c @@ -0,0 +1,40 @@ +// Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/ +// +// SPDX-License-Identifier: BSD-2-Clause + +#include <sys/socket.h> + +#include <assert.h> +#include <wasi/api.h> +#include <errno.h> +#include <stdint.h> + +static_assert(MSG_PEEK == __WASI_RIFLAGS_RECV_PEEK, "Value mismatch"); +static_assert(MSG_WAITALL == __WASI_RIFLAGS_RECV_WAITALL, "Value mismatch"); + +ssize_t recv(int socket, void *restrict buffer, size_t length, int flags) { + // Validate flags. + if ((flags & ~(MSG_PEEK | MSG_WAITALL)) != 0) { + errno = EOPNOTSUPP; + return -1; + } + + // Prepare input parameters. + __wasi_iovec_t iov = {.buf = buffer, .buf_len = length}; + __wasi_iovec_t *ri_data = &iov; + size_t ri_data_len = 1; + __wasi_riflags_t ri_flags = flags; + + // Perform system call. + size_t ro_datalen; + __wasi_roflags_t ro_flags; + __wasi_errno_t error = __wasi_sock_recv(socket, + ri_data, ri_data_len, ri_flags, + &ro_datalen, + &ro_flags); + if (error != 0) { + errno = error; + return -1; + } + return ro_datalen; +} diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c new file mode 100644 index 0000000..85a298a --- /dev/null +++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c @@ -0,0 +1,32 @@ +// Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/ +// +// SPDX-License-Identifier: BSD-2-Clause + +#include <sys/socket.h> + +#include <assert.h> +#include <wasi/api.h> +#include <errno.h> + +ssize_t send(int socket, const void *buffer, size_t length, int flags) { + // This implementation does not support any flags. + if (flags != 0) { + errno = EOPNOTSUPP; + return -1; + } + + // Prepare input parameters. + __wasi_ciovec_t iov = {.buf = buffer, .buf_len = length}; + __wasi_ciovec_t *si_data = &iov; + size_t si_data_len = 1; + __wasi_siflags_t si_flags = 0; + + // Perform system call. + size_t so_datalen; + __wasi_errno_t error = __wasi_sock_send(socket, si_data, si_data_len, si_flags, &so_datalen); + if (error != 0) { + errno = error; + return -1; + } + return so_datalen; +} diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c b/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c new file mode 100644 index 0000000..261fcb8 --- /dev/null +++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c @@ -0,0 +1,27 @@ +// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ +// +// SPDX-License-Identifier: BSD-2-Clause + +#include <sys/socket.h> + +#include <assert.h> +#include <wasi/api.h> +#include <errno.h> + +static_assert(SHUT_RD == __WASI_SDFLAGS_RD, "Value mismatch"); +static_assert(SHUT_WR == __WASI_SDFLAGS_WR, "Value mismatch"); + +int shutdown(int socket, int how) { + // Validate shutdown flags. + if (how != SHUT_RD && how != SHUT_WR && how != SHUT_RDWR) { + errno = EINVAL; + return -1; + } + + __wasi_errno_t error = __wasi_sock_shutdown(socket, how); + if (error != 0) { + errno = error; + return -1; + } + return error; +} diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/socket/socket_impl.h b/libc-bottom-half/cloudlibc/src/libc/sys/socket/socket_impl.h new file mode 100644 index 0000000..7b1a366 --- /dev/null +++ b/libc-bottom-half/cloudlibc/src/libc/sys/socket/socket_impl.h @@ -0,0 +1,57 @@ +// Copyright (c) 2015-2017 Nuxi, https://nuxi.nl/ +// +// SPDX-License-Identifier: BSD-2-Clause + +#ifndef SYS_SOCKET_SOCKET_IMPL_H +#define SYS_SOCKET_SOCKET_IMPL_H + +#include <sys/socket.h> +#include <sys/un.h> + +#include <netinet/in.h> + +#include <assert.h> +#include <stdalign.h> +#include <stddef.h> +#include <stdint.h> + +static_assert(sizeof(struct sockaddr_storage) >= sizeof(struct sockaddr), + "struct sockaddr_storage too small"); +static_assert(alignof(struct sockaddr_storage) == alignof(struct sockaddr), + "struct sockaddr alignment incorrect"); +static_assert(sizeof(struct sockaddr_storage) >= sizeof(struct sockaddr_in), + "struct sockaddr_storage too small"); +static_assert(alignof(struct sockaddr_storage) == alignof(struct sockaddr_in), + "struct sockaddr_in alignment incorrect"); +static_assert(sizeof(struct sockaddr_storage) >= sizeof(struct sockaddr_in6), + "struct sockaddr_storage too small"); +static_assert(alignof(struct sockaddr_storage) == alignof(struct sockaddr_in6), + "struct sockaddr_in6 alignment incorrect"); +static_assert(sizeof(struct sockaddr_storage) >= sizeof(struct sockaddr_un), + "struct sockaddr_storage too small"); +static_assert(alignof(struct sockaddr_storage) == alignof(struct sockaddr_un), + "struct sockaddr_un alignment incorrect"); + +// Returns the control message header stored at a provided memory +// address, ensuring that it is stored within the ancillary data buffer +// of a message header. +static inline struct cmsghdr *CMSG_GET(const struct msghdr *mhdr, void *cmsg) { + // Safety belt: require that the returned object is properly aligned. + assert((uintptr_t)cmsg % alignof(struct cmsghdr) == 0 && + "Attempted to access unaligned control message header"); + + // Safety belt: the computed starting address of the control message + // header may only lie inside the ancillary data buffer, or right + // after it in case we've reached the end of the buffer. + const unsigned char *begin = mhdr->msg_control; + const unsigned char *end = begin + mhdr->msg_controllen; + assert((unsigned char *)cmsg >= begin && + (unsigned char *)cmsg < end + alignof(struct cmsghdr) && + "Computed object outside of buffer boundaries"); + + // Only return the control message header in case all of its fields + // lie within the ancillary data buffer. + return CMSG_DATA((struct cmsghdr *)cmsg) <= end ? cmsg : NULL; +} + +#endif |