Merge dev/socket into main (#1393)

Implement more socket APIs, refer to #1336 and below PRs:
- Implement wasi_addr_resolve function (#1319)
- Fix socket-api byte order issue when host/network order are the same (#1327)
- Enhance sock_addr_local syscall (#1320)
- Implement sock_addr_remote syscall (#1360)
- Add support for IPv6 in WAMR (#1411)
- Implement ns lookup allowlist (#1420)
- Implement sock_send_to and sock_recv_from system calls (#1457)
- Added http downloader and multicast socket options (#1467)
- Fix `bind()` calls to receive the correct size of `sockaddr` structure (#1490)
- Assert on correct parameters (#1505)
- Copy only received bytes from socket recv buffer into the app buffer (#1497)

Co-authored-by: Marcin Kolny <mkolny@amazon.com>
Co-authored-by: Marcin Kolny <marcin.kolny@gmail.com>
Co-authored-by: Callum Macmillan <callumimacmillan@gmail.com>
This commit is contained in:
Wenyong Huang
2022-09-22 21:46:14 +08:00
committed by GitHub
parent 32d2d16908
commit 78b5c5b484
31 changed files with 6345 additions and 438 deletions

View File

@ -59,7 +59,7 @@ wasm_create_gdbserver(const char *host, int32 *port)
memset(server->receive_ctx, 0, sizeof(rsp_recv_context_t));
if (0 != os_socket_create(&listen_fd, 1)) {
if (0 != os_socket_create(&listen_fd, true, true)) {
LOG_ERROR("wasm gdb server error: create socket failed");
goto fail;
}

View File

@ -6,6 +6,7 @@
#ifndef _WASI_SOCKET_EXT_H_
#define _WASI_SOCKET_EXT_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -20,7 +21,12 @@ typedef uint16_t __wasi_ip_port_t;
typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
/* n0.n1.n2.n3 */
/*
n0.n1.n2.n3
Example:
IP Address: 127.0.0.1
Structure: {n0: 127, n1: 0, n2: 0, n3: 1}
*/
typedef struct __wasi_addr_ip4_t {
uint8_t n0;
uint8_t n1;
@ -30,9 +36,18 @@ typedef struct __wasi_addr_ip4_t {
typedef struct __wasi_addr_ip4_port_t {
__wasi_addr_ip4_t addr;
__wasi_ip_port_t port;
__wasi_ip_port_t port; /* host byte order */
} __wasi_addr_ip4_port_t;
/*
n0:n1:n2:n3:h0:h1:h2:h3, each 16bit value uses host byte order
Example (little-endian system)
IP Address fe80::3ba2:893b:4be0:e3dd
Structure: {
n0: 0xfe80, n1:0x0, n2: 0x0, n3: 0x0,
h0: 0x3ba2, h1: 0x893b, h2: 0x4be0, h3: 0xe3dd
}
*/
typedef struct __wasi_addr_ip6_t {
uint16_t n0;
uint16_t n1;
@ -46,9 +61,17 @@ typedef struct __wasi_addr_ip6_t {
typedef struct __wasi_addr_ip6_port_t {
__wasi_addr_ip6_t addr;
__wasi_ip_port_t port;
__wasi_ip_port_t port; /* host byte order */
} __wasi_addr_ip6_port_t;
typedef struct __wasi_addr_ip_t {
__wasi_addr_type_t kind;
union {
__wasi_addr_ip4_t ip4;
__wasi_addr_ip6_t ip6;
} addr;
} __wasi_addr_ip_t;
typedef struct __wasi_addr_t {
__wasi_addr_type_t kind;
union {
@ -59,6 +82,18 @@ typedef struct __wasi_addr_t {
typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
typedef struct __wasi_addr_info_t {
__wasi_addr_t addr;
__wasi_sock_type_t type;
} __wasi_addr_info_t;
typedef struct __wasi_addr_info_hints_t {
__wasi_sock_type_t type;
__wasi_address_family_t family;
// this is to workaround lack of optional parameters
uint8_t hints_enabled;
} __wasi_addr_info_hints_t;
#ifdef __wasi__
/**
* Reimplement below POSIX APIs with __wasi_sock_XXX functions.
@ -67,6 +102,43 @@ typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
* <sys/socket.h>
* <sys/types.h>
*/
#define SO_REUSEADDR 2
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
#define SO_KEEPALIVE 9
#define SO_LINGER 13
#define SO_REUSEPORT 15
#define SO_RCVTIMEO 20
#define SO_SNDTIMEO 21
#define TCP_NODELAY 1
#define TCP_KEEPIDLE 4
#define TCP_KEEPINTVL 5
#define TCP_QUICKACK 12
#define TCP_FASTOPEN_CONNECT 30
#define IP_TTL 2
#define IP_MULTICAST_TTL 33
#define IP_MULTICAST_LOOP 34
#define IP_ADD_MEMBERSHIP 35
#define IP_DROP_MEMBERSHIP 36
#define IPV6_MULTICAST_LOOP 19
#define IPV6_JOIN_GROUP 20
#define IPV6_LEAVE_GROUP 21
#define IPV6_V6ONLY 26
struct addrinfo {
int ai_flags; /* Input flags. */
int ai_family; /* Protocol family for socket. */
int ai_socktype; /* Socket type. */
int ai_protocol; /* Protocol for socket. */
socklen_t ai_addrlen; /* Length of socket address. */
struct sockaddr *ai_addr; /* Socket address for socket. */
char *ai_canonname; /* Canonical name for service location. */
struct addrinfo *ai_next; /* Pointer to next in list. */
};
int
accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
@ -86,8 +158,37 @@ recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t
sendmsg(int sockfd, const struct msghdr *msg, int flags);
ssize_t
sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t
recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
int
socket(int domain, int type, int protocol);
int
getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int
getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int
getsockopt(int sockfd, int level, int optname, void *__restrict optval,
socklen_t *__restrict optlen);
int
setsockopt(int sockfd, int level, int optname, const void *optval,
socklen_t optlen);
int
getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
struct addrinfo **res);
void
freeaddrinfo(struct addrinfo *res);
#endif
/**
@ -115,16 +216,15 @@ __wasi_sock_accept(__wasi_fd_t fd, __wasi_fd_t *fd_new)
* either IP4 or IP6.
*/
int32_t
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1,
int32_t arg2)
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_addr_local")));
static inline __wasi_errno_t
__wasi_sock_addr_local(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
__wasi_sock_addr_local(__wasi_fd_t fd, __wasi_addr_t *addr)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_local(
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
(int32_t)fd, (int32_t)addr);
}
/**
@ -136,43 +236,49 @@ __wasi_sock_addr_local(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
* either IP4 or IP6.
*/
int32_t
__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1,
int32_t arg2)
__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_addr_remote")));
static inline __wasi_errno_t
__wasi_sock_addr_remote(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
__wasi_sock_addr_remote(__wasi_fd_t fd, __wasi_addr_t *addr)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_remote(
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
(int32_t)fd, (int32_t)addr);
}
/**
* Resolves a hostname and a port to one or more IP addresses. Port is optional
* and you can pass 0 (zero) in most cases, it is used a hint for protocol.
* Resolve a hostname and a service to one or more IP addresses. Service is
* optional and you can pass empty string in most cases, it is used as a hint
* for protocol.
*
* Note: This is similar to `getaddrinfo` in POSIX
*
* When successful, the contents of the output buffer consist of a sequence of
* IPv4 and/or IPv6 addresses. Each address entry consists of a addr_t object.
* IPv4 and/or IPv6 addresses. Each address entry consists of a wasi_addr_t
* object.
*
* This function fills the output buffer as much as possible, potentially
* truncating the last address entry. It is advisable that the buffer is
* This function fills the output buffer as much as possible, truncating the
* entries that didn't fit into the buffer. A number of available addresses
* will be returned through the last parameter.
*/
int32_t
__imported_wasi_snapshot_preview1_addr_resolve(int32_t arg0, int32_t arg1,
int32_t arg2, int32_t arg3,
int32_t arg4)
__imported_wasi_snapshot_preview1_sock_addr_resolve(int32_t arg0, int32_t arg1,
int32_t arg2, int32_t arg3,
int32_t arg4, int32_t arg5)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("addr_resolve")));
__import_name__("sock_addr_resolve")));
static inline __wasi_errno_t
__wasi_addr_resolve(__wasi_fd_t fd, const char *host, __wasi_ip_port_t port,
uint8_t *buf, __wasi_size_t size)
__wasi_sock_addr_resolve(const char *host, const char *service,
__wasi_addr_info_hints_t *hints,
__wasi_addr_info_t *addr_info,
__wasi_size_t addr_info_size,
__wasi_size_t *max_info_size)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_addr_resolve(
(int32_t)fd, (int32_t)host, (int32_t)port, (int32_t)buf, (int32_t)size);
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_resolve(
(int32_t)host, (int32_t)service, (int32_t)hints, (int32_t)addr_info,
(int32_t)addr_info_size, (int32_t)max_info_size);
}
/**
@ -191,6 +297,48 @@ __wasi_sock_bind(__wasi_fd_t fd, __wasi_addr_t *addr)
(int32_t)fd, (int32_t)addr);
}
/**
* Send data to a specific target
* Note: This is similar to `sendto` in POSIX
*/
int32_t
__imported_wasi_snapshot_preview1_sock_send_to(int32_t arg0, int32_t arg1,
int32_t arg2, int32_t arg3,
int32_t arg4, int32_t arg5)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_send_to")));
static inline __wasi_errno_t
__wasi_sock_send_to(__wasi_fd_t fd, const __wasi_ciovec_t *si_data,
uint32_t si_data_len, __wasi_siflags_t si_flags,
const __wasi_addr_t *dest_addr, uint32_t *so_data_len)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_send_to(
(int32_t)fd, (int32_t)si_data, (int32_t)si_data_len, (int32_t)si_flags,
(uint32_t)dest_addr, (uint32_t)so_data_len);
}
/**
* Receives data from a socket
* Note: This is similar to `recvfrom` in POSIX
*/
int32_t
__imported_wasi_snapshot_preview1_sock_recv_from(int32_t arg0, int32_t arg1,
int32_t arg2, int32_t arg3,
int32_t arg4, int32_t arg5)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_recv_from")));
static inline __wasi_errno_t
__wasi_sock_recv_from(__wasi_fd_t fd, __wasi_ciovec_t *ri_data,
uint32_t ri_data_len, __wasi_riflags_t ri_flags,
__wasi_addr_t *src_addr, uint32_t *ro_data_len)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_recv_from(
(int32_t)fd, (int32_t)ri_data, (int32_t)ri_data_len, (int32_t)ri_flags,
(uint32_t)src_addr, (uint32_t)ro_data_len);
}
/**
* Close a socket (this is an alias for `fd_close`)
* Note: This is similar to `close` in POSIX.
@ -252,7 +400,7 @@ __imported_wasi_snapshot_preview1_sock_get_reuse_addr(int32_t arg0,
__import_name__("sock_get_reuse_addr")));
static inline __wasi_errno_t
__wasi_sock_get_reuse_addr(__wasi_fd_t fd, uint8_t *reuse)
__wasi_sock_get_reuse_addr(__wasi_fd_t fd, bool *reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_reuse_addr((int32_t)fd,
@ -270,7 +418,7 @@ __imported_wasi_snapshot_preview1_sock_get_reuse_port(int32_t arg0,
__import_name__("sock_get_reuse_port")));
static inline __wasi_errno_t
__wasi_sock_get_reuse_port(__wasi_fd_t fd, int8_t *reuse)
__wasi_sock_get_reuse_port(__wasi_fd_t fd, bool *reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_reuse_port((int32_t)fd,
@ -367,7 +515,7 @@ __imported_wasi_snapshot_preview1_sock_set_reuse_addr(int32_t arg0,
__import_name__("sock_set_reuse_addr")));
static inline __wasi_errno_t
__wasi_sock_set_reuse_addr(__wasi_fd_t fd, uint8_t reuse)
__wasi_sock_set_reuse_addr(__wasi_fd_t fd, bool reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_reuse_addr((int32_t)fd,
@ -385,7 +533,7 @@ __imported_wasi_snapshot_preview1_sock_set_reuse_port(int32_t arg0,
__import_name__("sock_set_reuse_port")));
static inline __wasi_errno_t
__wasi_sock_set_reuse_port(__wasi_fd_t fd, uint8_t reuse)
__wasi_sock_set_reuse_port(__wasi_fd_t fd, bool reuse)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_reuse_port((int32_t)fd,
@ -397,20 +545,435 @@ __wasi_sock_set_reuse_port(__wasi_fd_t fd, uint8_t reuse)
* Note: This is similar to `setsockopt` in POSIX for SO_SNDBUF
*/
int32_t
__imported_wasi_snapshot_preview1_sock_set_send_buf_size(int32_t arg0)
__imported_wasi_snapshot_preview1_sock_set_send_buf_size(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_send_buf_size")));
static inline __wasi_errno_t
__wasi_sock_set_send_buf_size(__wasi_fd_t fd)
__wasi_sock_set_send_buf_size(__wasi_fd_t fd, __wasi_size_t buf_len)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_send_buf_size((int32_t)fd);
__imported_wasi_snapshot_preview1_sock_set_send_buf_size(
(int32_t)fd, (int32_t)buf_len);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_recv_timeout(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_recv_timeout")));
static inline __wasi_errno_t
__wasi_sock_get_recv_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_recv_timeout(
(int32_t)fd, (int32_t)timeout_us);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_recv_timeout(int32_t arg0,
int64_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_recv_timeout")));
static inline __wasi_errno_t
__wasi_sock_set_recv_timeout(__wasi_fd_t fd, uint64_t timeout_us)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_recv_timeout(
(int32_t)fd, (int64_t)timeout_us);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_send_timeout(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_send_timeout")));
static inline __wasi_errno_t
__wasi_sock_get_send_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_send_timeout(
(int32_t)fd, (int32_t)timeout_us);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_send_timeout(int32_t arg0,
int64_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_send_timeout")));
static inline __wasi_errno_t
__wasi_sock_set_send_timeout(__wasi_fd_t fd, uint64_t timeout_us)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_send_timeout(
(int32_t)fd, (int64_t)timeout_us);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_keep_alive(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_keep_alive")));
static inline __wasi_errno_t
__wasi_sock_set_keep_alive(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_keep_alive((int32_t)fd,
(int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_keep_alive(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_keep_alive")));
static inline __wasi_errno_t
__wasi_sock_get_keep_alive(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_keep_alive((int32_t)fd,
(int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_linger(int32_t arg0, int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_linger")));
static inline __wasi_errno_t
__wasi_sock_set_linger(__wasi_fd_t fd, bool is_enabled, int linger_s)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_linger(
(int32_t)fd, (int32_t)is_enabled, (int32_t)linger_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_linger(int32_t arg0, int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_linger")));
static inline __wasi_errno_t
__wasi_sock_get_linger(__wasi_fd_t fd, bool *is_enabled, int *linger_s)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_linger(
(int32_t)fd, (int32_t)is_enabled, (int32_t)linger_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_keep_idle(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_keep_idle")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_keep_idle(__wasi_fd_t fd, uint32_t time_s)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_keep_idle(
(int32_t)fd, (int32_t)time_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_keep_idle(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_keep_idle")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_keep_idle(__wasi_fd_t fd, uint32_t *time_s)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_keep_idle(
(int32_t)fd, (int32_t)time_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_keep_intvl(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_keep_intvl")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_keep_intvl(__wasi_fd_t fd, uint32_t time_s)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_keep_intvl(
(int32_t)fd, (int32_t)time_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_keep_intvl(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_keep_intvl")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_keep_intvl(__wasi_fd_t fd, uint32_t *time_s)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_keep_intvl(
(int32_t)fd, (int32_t)time_s);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_fastopen_connect(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_fastopen_connect")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_fastopen_connect(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_fastopen_connect(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_fastopen_connect(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_fastopen_connect")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_fastopen_connect(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_fastopen_connect(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_multicast_loop(int32_t arg0,
int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_multicast_loop")));
static inline __wasi_errno_t
__wasi_sock_set_ip_multicast_loop(__wasi_fd_t fd, bool ipv6, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_ip_multicast_loop(
(int32_t)fd, (int32_t)ipv6, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_ip_multicast_loop(int32_t arg0,
int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_ip_multicast_loop")));
static inline __wasi_errno_t
__wasi_sock_get_ip_multicast_loop(__wasi_fd_t fd, bool ipv6, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_ip_multicast_loop(
(int32_t)fd, (int32_t)ipv6, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_multicast_ttl(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_multicast_ttl")));
static inline __wasi_errno_t
__wasi_sock_set_ip_multicast_ttl(__wasi_fd_t fd, uint8_t option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_ip_multicast_ttl(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_ip_multicast_ttl(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_ip_multicast_ttl")));
static inline __wasi_errno_t
__wasi_sock_get_ip_multicast_ttl(__wasi_fd_t fd, uint8_t *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_ip_multicast_ttl(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_add_membership(int32_t arg0,
int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_add_membership")));
static inline __wasi_errno_t
__wasi_sock_set_ip_add_membership(__wasi_fd_t fd,
__wasi_addr_ip_t *imr_multiaddr,
uint32_t imr_interface)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_ip_add_membership(
(int32_t)fd, (int32_t)imr_multiaddr, (int32_t)imr_interface);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_drop_membership(int32_t arg0,
int32_t arg1,
int32_t arg2)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_drop_membership")));
static inline __wasi_errno_t
__wasi_sock_set_ip_drop_membership(__wasi_fd_t fd,
__wasi_addr_ip_t *imr_multiaddr,
uint32_t imr_interface)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_ip_drop_membership(
(int32_t)fd, (int32_t)imr_multiaddr, (int32_t)imr_interface);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_broadcast(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_broadcast")));
static inline __wasi_errno_t
__wasi_sock_set_broadcast(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_broadcast(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_broadcast(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_broadcast")));
static inline __wasi_errno_t
__wasi_sock_get_broadcast(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_broadcast(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_no_delay(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_no_delay")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_no_delay(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_no_delay(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_no_delay(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_no_delay")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_no_delay(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_no_delay(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_tcp_quick_ack(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_tcp_quick_ack")));
static inline __wasi_errno_t
__wasi_sock_set_tcp_quick_ack(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_set_tcp_quick_ack(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_tcp_quick_ack(int32_t arg0,
int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_tcp_quick_ack")));
static inline __wasi_errno_t
__wasi_sock_get_tcp_quick_ack(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)
__imported_wasi_snapshot_preview1_sock_get_tcp_quick_ack(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ip_ttl(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ip_ttl")));
static inline __wasi_errno_t
__wasi_sock_set_ip_ttl(__wasi_fd_t fd, uint8_t option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_ip_ttl(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_ip_ttl(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_ip_ttl")));
static inline __wasi_errno_t
__wasi_sock_get_ip_ttl(__wasi_fd_t fd, uint8_t *option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_ip_ttl(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_set_ipv6_only(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_set_ipv6_only")));
static inline __wasi_errno_t
__wasi_sock_set_ipv6_only(__wasi_fd_t fd, bool option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_ipv6_only(
(int32_t)fd, (int32_t)option);
}
int32_t
__imported_wasi_snapshot_preview1_sock_get_ipv6_only(int32_t arg0, int32_t arg1)
__attribute__((__import_module__("wasi_snapshot_preview1"),
__import_name__("sock_get_ipv6_only")));
static inline __wasi_errno_t
__wasi_sock_get_ipv6_only(__wasi_fd_t fd, bool *option)
{
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_ipv6_only(
(int32_t)fd, (int32_t)option);
}
/**
* TODO: modify recv() and send()
* since don't want to re-compile the wasi-libc,
* we tend to keep original implentations of recv() and send().
*/
#endif
#endif

View File

@ -18,16 +18,44 @@
return -1; \
}
static void
ipv4_addr_to_wasi_ip4_addr(uint32_t addr_num, __wasi_addr_ip4_t *out)
{
addr_num = ntohl(addr_num);
out->n0 = (addr_num & 0xFF000000) >> 24;
out->n1 = (addr_num & 0x00FF0000) >> 16;
out->n2 = (addr_num & 0x0000FF00) >> 8;
out->n3 = (addr_num & 0x000000FF);
}
/* addr_num and port are in network order */
static void
ipv4_addr_to_wasi_addr(uint32_t addr_num, uint16_t port, __wasi_addr_t *out)
{
out->kind = IPv4;
out->addr.ip4.port = ntohs(port);
out->addr.ip4.addr.n3 = (addr_num & 0xFF000000) >> 24;
out->addr.ip4.addr.n2 = (addr_num & 0x00FF0000) >> 16;
out->addr.ip4.addr.n1 = (addr_num & 0x0000FF00) >> 8;
out->addr.ip4.addr.n0 = (addr_num & 0x000000FF);
ipv4_addr_to_wasi_ip4_addr(addr_num, &(out->addr.ip4.addr));
}
static void
ipv6_addr_to_wasi_ipv6_addr(uint16_t *addr, __wasi_addr_ip6_t *out)
{
out->n0 = ntohs(addr[0]);
out->n1 = ntohs(addr[1]);
out->n2 = ntohs(addr[2]);
out->n3 = ntohs(addr[3]);
out->h0 = ntohs(addr[4]);
out->h1 = ntohs(addr[5]);
out->h2 = ntohs(addr[6]);
out->h3 = ntohs(addr[7]);
}
static void
ipv6_addr_to_wasi_addr(uint16_t *addr, uint16_t port, __wasi_addr_t *out)
{
out->kind = IPv6;
out->addr.ip6.port = ntohs(port);
ipv6_addr_to_wasi_ipv6_addr(addr, &(out->addr.ip6.addr));
}
static __wasi_errno_t
@ -36,15 +64,17 @@ sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
{
__wasi_errno_t ret = __WASI_ERRNO_SUCCESS;
if (AF_INET == sock_addr->sa_family) {
assert(sizeof(struct sockaddr_in) == addrlen);
assert(sizeof(struct sockaddr_in) <= addrlen);
ipv4_addr_to_wasi_addr(
((struct sockaddr_in *)sock_addr)->sin_addr.s_addr,
((struct sockaddr_in *)sock_addr)->sin_port, wasi_addr);
}
else if (AF_INET6 == sock_addr->sa_family) {
// TODO: IPV6
ret = __WASI_ERRNO_AFNOSUPPORT;
assert(sizeof(struct sockaddr_in6) <= addrlen);
ipv6_addr_to_wasi_addr(
(uint16_t *)((struct sockaddr_in6 *)sock_addr)->sin6_addr.s6_addr,
((struct sockaddr_in6 *)sock_addr)->sin6_port, wasi_addr);
}
else {
ret = __WASI_ERRNO_AFNOSUPPORT;
@ -54,38 +84,52 @@ sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
}
static __wasi_errno_t
sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
struct sockaddr *sock_addr, socklen_t *addrlen)
{
__wasi_addr_t wasi_addr = { 0 };
__wasi_errno_t error;
switch (wasi_addr->kind) {
case IPv4:
{
struct sockaddr_in sock_addr_in = { 0 };
uint32_t s_addr;
error =
__wasi_sock_addr_remote(fd, (uint8_t *)&wasi_addr, sizeof(wasi_addr));
if (__WASI_ERRNO_SUCCESS != error) {
return error;
s_addr = (wasi_addr->addr.ip4.addr.n0 << 24)
| (wasi_addr->addr.ip4.addr.n1 << 16)
| (wasi_addr->addr.ip4.addr.n2 << 8)
| wasi_addr->addr.ip4.addr.n3;
sock_addr_in.sin_family = AF_INET;
sock_addr_in.sin_addr.s_addr = htonl(s_addr);
sock_addr_in.sin_port = htons(wasi_addr->addr.ip4.port);
memcpy(sock_addr, &sock_addr_in, sizeof(sock_addr_in));
*addrlen = sizeof(sock_addr_in);
break;
}
case IPv6:
{
struct sockaddr_in6 sock_addr_in6 = { 0 };
uint16_t *addr_buf = (uint16_t *)sock_addr_in6.sin6_addr.s6_addr;
addr_buf[0] = htons(wasi_addr->addr.ip6.addr.n0);
addr_buf[1] = htons(wasi_addr->addr.ip6.addr.n1);
addr_buf[2] = htons(wasi_addr->addr.ip6.addr.n2);
addr_buf[3] = htons(wasi_addr->addr.ip6.addr.n3);
addr_buf[4] = htons(wasi_addr->addr.ip6.addr.h0);
addr_buf[5] = htons(wasi_addr->addr.ip6.addr.h1);
addr_buf[6] = htons(wasi_addr->addr.ip6.addr.h2);
addr_buf[7] = htons(wasi_addr->addr.ip6.addr.h3);
sock_addr_in6.sin6_family = AF_INET6;
sock_addr_in6.sin6_port = htons(wasi_addr->addr.ip6.port);
memcpy(sock_addr, &sock_addr_in6, sizeof(sock_addr_in6));
*addrlen = sizeof(sock_addr_in6);
break;
}
default:
return __WASI_ERRNO_AFNOSUPPORT;
}
if (IPv4 == wasi_addr.kind) {
struct sockaddr_in sock_addr_in = { 0 };
sock_addr_in.sin_family = AF_INET;
sock_addr_in.sin_addr.s_addr = (wasi_addr.addr.ip4.addr.n3 << 24)
| (wasi_addr.addr.ip4.addr.n2 << 16)
| (wasi_addr.addr.ip4.addr.n1 << 8)
| wasi_addr.addr.ip4.addr.n0;
sock_addr_in.sin_port = htons(wasi_addr.addr.ip4.port);
memcpy(sock_addr, &sock_addr_in, sizeof(sock_addr_in));
*addrlen = sizeof(sock_addr_in);
}
else if (IPv6 == wasi_addr.kind) {
// TODO: IPV6
return __WASI_ERRNO_AFNOSUPPORT;
}
else {
return __WASI_ERRNO_AFNOSUPPORT;
}
return __WASI_ERRNO_SUCCESS;
}
@ -99,9 +143,8 @@ accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
error = __wasi_sock_accept(sockfd, &new_sockfd);
HANDLE_ERROR(error)
// error = sock_addr_remote(new_sockfd, addr, addrlen);
// HANDLE_ERROR(error)
*addrlen = 0;
error = getpeername(new_sockfd, addr, addrlen);
HANDLE_ERROR(error)
return new_sockfd;
}
@ -221,6 +264,66 @@ sendmsg(int sockfd, const struct msghdr *msg, int flags)
return so_datalen;
}
ssize_t
sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
{
// Prepare input parameters.
__wasi_ciovec_t iov = { .buf = buf, .buf_len = len };
uint32_t so_datalen = 0;
__wasi_addr_t wasi_addr;
__wasi_errno_t error;
size_t si_data_len = 1;
__wasi_siflags_t si_flags = 0;
// This implementation does not support any flags.
if (flags != 0) {
HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
}
error = sockaddr_to_wasi_addr(dest_addr, addrlen, &wasi_addr);
HANDLE_ERROR(error);
// Perform system call.
error = __wasi_sock_send_to(sockfd, &iov, si_data_len, si_flags, &wasi_addr,
&so_datalen);
HANDLE_ERROR(error)
return so_datalen;
}
ssize_t
recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
{
// Prepare input parameters.
__wasi_ciovec_t iov = { .buf = buf, .buf_len = len };
uint32_t so_datalen = 0;
__wasi_addr_t wasi_addr;
__wasi_errno_t error;
size_t si_data_len = 1;
__wasi_siflags_t si_flags = 0;
// This implementation does not support any flags.
if (flags != 0) {
HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
}
if (!src_addr) {
return recv(sockfd, buf, len, flags);
}
// Perform system call.
error = __wasi_sock_recv_from(sockfd, &iov, si_data_len, si_flags,
&wasi_addr, &so_datalen);
HANDLE_ERROR(error);
error = wasi_addr_to_sockaddr(&wasi_addr, src_addr, addrlen);
HANDLE_ERROR(error);
return so_datalen;
}
int
socket(int domain, int type, int protocol)
{
@ -256,3 +359,612 @@ socket(int domain, int type, int protocol)
return sockfd;
}
int
getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
__wasi_addr_t wasi_addr = { 0 };
__wasi_errno_t error;
error = __wasi_sock_addr_local(sockfd, &wasi_addr);
HANDLE_ERROR(error)
error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
HANDLE_ERROR(error)
return __WASI_ERRNO_SUCCESS;
}
int
getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
__wasi_addr_t wasi_addr = { 0 };
__wasi_errno_t error;
error = __wasi_sock_addr_remote(sockfd, &wasi_addr);
HANDLE_ERROR(error)
error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
HANDLE_ERROR(error)
return __WASI_ERRNO_SUCCESS;
}
struct aibuf {
struct addrinfo ai;
union sa {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} sa;
};
static __wasi_errno_t
addrinfo_hints_to_wasi_hints(const struct addrinfo *hints,
__wasi_addr_info_hints_t *wasi_hints)
{
if (hints) {
wasi_hints->hints_enabled = 1;
switch (hints->ai_family) {
case AF_INET:
wasi_hints->family = INET4;
break;
case AF_INET6:
wasi_hints->family = INET6;
break;
default:
return __WASI_ERRNO_AFNOSUPPORT;
}
switch (hints->ai_socktype) {
case SOCK_STREAM:
wasi_hints->type = SOCKET_STREAM;
break;
case SOCK_DGRAM:
wasi_hints->type = SOCKET_DGRAM;
break;
default:
return __WASI_ERRNO_NOTSUP;
}
if (hints->ai_protocol != 0) {
return __WASI_ERRNO_NOTSUP;
}
if (hints->ai_flags != 0) {
return __WASI_ERRNO_NOTSUP;
}
}
else {
wasi_hints->hints_enabled = 0;
}
return __WASI_ERRNO_SUCCESS;
}
static __wasi_errno_t
wasi_addr_info_to_addr_info(const __wasi_addr_info_t *addr_info,
struct addrinfo *ai)
{
ai->ai_socktype =
addr_info->type == SOCKET_DGRAM ? SOCK_DGRAM : SOCK_STREAM;
ai->ai_protocol = 0;
ai->ai_canonname = NULL;
if (addr_info->addr.kind == IPv4) {
ai->ai_family = AF_INET;
ai->ai_addrlen = sizeof(struct sockaddr_in);
}
else {
ai->ai_family = AF_INET6;
ai->ai_addrlen = sizeof(struct sockaddr_in6);
}
return wasi_addr_to_sockaddr(&addr_info->addr, ai->ai_addr,
&ai->ai_addrlen); // TODO err handling
}
int
getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
struct addrinfo **res)
{
__wasi_addr_info_hints_t wasi_hints;
__wasi_addr_info_t *addr_info = NULL;
__wasi_size_t addr_info_size, i;
__wasi_size_t max_info_size = 16;
__wasi_errno_t error;
struct aibuf *aibuf_res;
error = addrinfo_hints_to_wasi_hints(hints, &wasi_hints);
HANDLE_ERROR(error)
do {
if (addr_info)
free(addr_info);
addr_info_size = max_info_size;
addr_info = (__wasi_addr_info_t *)malloc(addr_info_size
* sizeof(__wasi_addr_info_t));
if (!addr_info) {
HANDLE_ERROR(__WASI_ERRNO_NOMEM)
}
error = __wasi_sock_addr_resolve(node, service == NULL ? "" : service,
&wasi_hints, addr_info, addr_info_size,
&max_info_size);
if (error != __WASI_ERRNO_SUCCESS) {
free(addr_info);
HANDLE_ERROR(error);
}
} while (max_info_size > addr_info_size);
if (addr_info_size == 0) {
free(addr_info);
*res = NULL;
return __WASI_ERRNO_SUCCESS;
}
aibuf_res = calloc(1, addr_info_size * sizeof(struct aibuf));
if (!aibuf_res) {
free(addr_info);
HANDLE_ERROR(__WASI_ERRNO_NOMEM)
}
*res = &aibuf_res[0].ai;
if (addr_info_size) {
addr_info_size = max_info_size;
}
for (i = 0; i < addr_info_size; i++) {
struct addrinfo *ai = &aibuf_res[i].ai;
ai->ai_addr = (struct sockaddr *)&aibuf_res[i].sa;
error = wasi_addr_info_to_addr_info(&addr_info[i], ai);
if (error != __WASI_ERRNO_SUCCESS) {
free(addr_info);
free(aibuf_res);
HANDLE_ERROR(error)
}
ai->ai_next = i == addr_info_size - 1 ? NULL : &aibuf_res[i + 1].ai;
}
free(addr_info);
return __WASI_ERRNO_SUCCESS;
}
void
freeaddrinfo(struct addrinfo *res)
{
/* res is a pointer to a first field in the first element
* of aibuf array allocated in getaddrinfo, therefore this call
* frees the memory of the entire array. */
free(res);
}
struct timeval
time_us_to_timeval(uint64_t time_us)
{
struct timeval tv;
tv.tv_sec = time_us / 1000000UL;
tv.tv_usec = time_us % 1000000UL;
return tv;
}
uint64_t
timeval_to_time_us(struct timeval tv)
{
return (tv.tv_sec * 1000000UL) + tv.tv_usec;
}
int
get_sol_socket_option(int sockfd, int optname, void *__restrict optval,
socklen_t *__restrict optlen)
{
__wasi_errno_t error;
uint64_t timeout_us;
bool is_linger_enabled;
int linger_s;
switch (optname) {
case SO_RCVTIMEO:
assert(*optlen == sizeof(struct timeval));
error = __wasi_sock_get_recv_timeout(sockfd, &timeout_us);
HANDLE_ERROR(error);
*(struct timeval *)optval = time_us_to_timeval(timeout_us);
return error;
case SO_SNDTIMEO:
assert(*optlen == sizeof(struct timeval));
error = __wasi_sock_get_send_timeout(sockfd, &timeout_us);
HANDLE_ERROR(error);
*(struct timeval *)optval = time_us_to_timeval(timeout_us);
return error;
case SO_SNDBUF:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_send_buf_size(sockfd, (size_t *)optval);
HANDLE_ERROR(error);
return error;
case SO_RCVBUF:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_recv_buf_size(sockfd, (size_t *)optval);
HANDLE_ERROR(error);
return error;
case SO_KEEPALIVE:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_keep_alive(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_REUSEADDR:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_reuse_addr(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_REUSEPORT:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_reuse_port(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_LINGER:
assert(*optlen == sizeof(struct linger));
error =
__wasi_sock_get_linger(sockfd, &is_linger_enabled, &linger_s);
HANDLE_ERROR(error);
((struct linger *)optval)->l_onoff = (int)is_linger_enabled;
((struct linger *)optval)->l_linger = linger_s;
return error;
case SO_BROADCAST:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_broadcast(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
get_ipproto_tcp_option(int sockfd, int optname, void *__restrict optval,
socklen_t *__restrict optlen)
{
__wasi_errno_t error;
switch (optname) {
case TCP_KEEPIDLE:
assert(*optlen == sizeof(uint32_t));
error = __wasi_sock_get_tcp_keep_idle(sockfd, (uint32_t *)optval);
HANDLE_ERROR(error);
return error;
case TCP_KEEPINTVL:
assert(*optlen == sizeof(uint32_t));
error = __wasi_sock_get_tcp_keep_intvl(sockfd, (uint32_t *)optval);
HANDLE_ERROR(error);
return error;
case TCP_FASTOPEN_CONNECT:
assert(*optlen == sizeof(int));
error =
__wasi_sock_get_tcp_fastopen_connect(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case TCP_NODELAY:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_tcp_no_delay(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case TCP_QUICKACK:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_tcp_quick_ack(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
get_ipproto_ip_option(int sockfd, int optname, void *__restrict optval,
socklen_t *__restrict optlen)
{
__wasi_errno_t error;
switch (optname) {
case IP_MULTICAST_LOOP:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_ip_multicast_loop(sockfd, false,
(bool *)optval);
HANDLE_ERROR(error);
return error;
case IP_TTL:
assert(*optlen == sizeof(uint8_t));
error = __wasi_sock_get_ip_ttl(sockfd, (uint8_t *)optval);
HANDLE_ERROR(error);
return error;
case IP_MULTICAST_TTL:
assert(*optlen == sizeof(uint8_t));
error = __wasi_sock_get_ip_multicast_ttl(sockfd, (uint8_t *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
get_ipproto_ipv6_option(int sockfd, int optname, void *__restrict optval,
socklen_t *__restrict optlen)
{
__wasi_errno_t error;
switch (optname) {
case IPV6_V6ONLY:
assert(*optlen == sizeof(int));
error = __wasi_sock_get_ipv6_only(sockfd, (bool *)optval);
HANDLE_ERROR(error);
return error;
case IPV6_MULTICAST_LOOP:
assert(*optlen == sizeof(int));
error =
__wasi_sock_get_ip_multicast_loop(sockfd, true, (bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
getsockopt(int sockfd, int level, int optname, void *__restrict optval,
socklen_t *__restrict optlen)
{
__wasi_errno_t error;
switch (level) {
case SOL_SOCKET:
return get_sol_socket_option(sockfd, optname, optval, optlen);
case IPPROTO_TCP:
return get_ipproto_tcp_option(sockfd, optname, optval, optlen);
case IPPROTO_IP:
return get_ipproto_ip_option(sockfd, optname, optval, optlen);
case IPPROTO_IPV6:
return get_ipproto_ipv6_option(sockfd, optname, optval, optlen);
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
set_sol_socket_option(int sockfd, int optname, const void *optval,
socklen_t optlen)
{
__wasi_errno_t error;
uint64_t timeout_us;
switch (optname) {
case SO_RCVTIMEO:
assert(optlen == sizeof(struct timeval));
timeout_us = timeval_to_time_us(*(struct timeval *)optval);
error = __wasi_sock_set_recv_timeout(sockfd, timeout_us);
HANDLE_ERROR(error);
return error;
case SO_SNDTIMEO:
assert(optlen == sizeof(struct timeval));
timeout_us = timeval_to_time_us(*(struct timeval *)optval);
error = __wasi_sock_set_send_timeout(sockfd, timeout_us);
HANDLE_ERROR(error);
return error;
case SO_SNDBUF:
assert(optlen == sizeof(int));
error = __wasi_sock_set_send_buf_size(sockfd, *(size_t *)optval);
HANDLE_ERROR(error);
return error;
case SO_RCVBUF:
assert(optlen == sizeof(int));
error = __wasi_sock_set_recv_buf_size(sockfd, *(size_t *)optval);
HANDLE_ERROR(error);
return error;
case SO_KEEPALIVE:
assert(optlen == sizeof(int));
error = __wasi_sock_set_keep_alive(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_REUSEADDR:
assert(optlen == sizeof(int));
error = __wasi_sock_set_reuse_addr(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_REUSEPORT:
assert(optlen == sizeof(int));
error = __wasi_sock_set_reuse_port(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case SO_LINGER:
assert(optlen == sizeof(struct linger));
struct linger *linger_opt = ((struct linger *)optval);
error = __wasi_sock_set_linger(sockfd, (bool)linger_opt->l_onoff,
linger_opt->l_linger);
HANDLE_ERROR(error);
return error;
case SO_BROADCAST:
assert(optlen == sizeof(int));
error = __wasi_sock_set_broadcast(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
set_ipproto_tcp_option(int sockfd, int optname, const void *optval,
socklen_t optlen)
{
__wasi_errno_t error;
switch (optname) {
case TCP_NODELAY:
assert(optlen == sizeof(int));
error = __wasi_sock_set_tcp_no_delay(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case TCP_KEEPIDLE:
assert(optlen == sizeof(uint32_t));
error = __wasi_sock_set_tcp_keep_idle(sockfd, *(uint32_t *)optval);
HANDLE_ERROR(error);
return error;
case TCP_KEEPINTVL:
assert(optlen == sizeof(uint32_t));
error = __wasi_sock_set_tcp_keep_intvl(sockfd, *(uint32_t *)optval);
HANDLE_ERROR(error);
return error;
case TCP_FASTOPEN_CONNECT:
assert(optlen == sizeof(int));
error =
__wasi_sock_set_tcp_fastopen_connect(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case TCP_QUICKACK:
assert(optlen == sizeof(int));
error = __wasi_sock_set_tcp_quick_ack(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
set_ipproto_ip_option(int sockfd, int optname, const void *optval,
socklen_t optlen)
{
__wasi_errno_t error;
__wasi_addr_ip_t imr_multiaddr;
struct ip_mreq *ip_mreq_opt;
switch (optname) {
case IP_MULTICAST_LOOP:
assert(optlen == sizeof(int));
error = __wasi_sock_set_ip_multicast_loop(sockfd, false,
*(bool *)optval);
HANDLE_ERROR(error);
return error;
case IP_ADD_MEMBERSHIP:
assert(optlen == sizeof(struct ip_mreq));
ip_mreq_opt = (struct ip_mreq *)optval;
imr_multiaddr.kind = IPv4;
ipv4_addr_to_wasi_ip4_addr(ip_mreq_opt->imr_multiaddr.s_addr,
&imr_multiaddr.addr.ip4);
error = __wasi_sock_set_ip_add_membership(
sockfd, &imr_multiaddr, ip_mreq_opt->imr_interface.s_addr);
HANDLE_ERROR(error);
return error;
case IP_DROP_MEMBERSHIP:
assert(optlen == sizeof(struct ip_mreq));
ip_mreq_opt = (struct ip_mreq *)optval;
imr_multiaddr.kind = IPv4;
ipv4_addr_to_wasi_ip4_addr(ip_mreq_opt->imr_multiaddr.s_addr,
&imr_multiaddr.addr.ip4);
error = __wasi_sock_set_ip_drop_membership(
sockfd, &imr_multiaddr, ip_mreq_opt->imr_interface.s_addr);
HANDLE_ERROR(error);
return error;
case IP_TTL:
assert(optlen == sizeof(uint8_t));
error = __wasi_sock_set_ip_ttl(sockfd, *(uint8_t *)optval);
HANDLE_ERROR(error);
return error;
case IP_MULTICAST_TTL:
assert(optlen == sizeof(uint8_t));
error =
__wasi_sock_set_ip_multicast_ttl(sockfd, *(uint8_t *)optval);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
set_ipproto_ipv6_option(int sockfd, int optname, const void *optval,
socklen_t optlen)
{
__wasi_errno_t error;
struct ipv6_mreq *ipv6_mreq_opt;
__wasi_addr_ip_t imr_multiaddr;
switch (optname) {
case IPV6_V6ONLY:
assert(optlen == sizeof(int));
error = __wasi_sock_set_ipv6_only(sockfd, *(bool *)optval);
HANDLE_ERROR(error);
return error;
case IPV6_MULTICAST_LOOP:
assert(optlen == sizeof(int));
error = __wasi_sock_set_ip_multicast_loop(sockfd, true,
*(bool *)optval);
HANDLE_ERROR(error);
return error;
case IPV6_JOIN_GROUP:
assert(optlen == sizeof(struct ipv6_mreq));
ipv6_mreq_opt = (struct ipv6_mreq *)optval;
imr_multiaddr.kind = IPv6;
ipv6_addr_to_wasi_ipv6_addr(
(uint16_t *)ipv6_mreq_opt->ipv6mr_multiaddr.s6_addr,
&imr_multiaddr.addr.ip6);
error = __wasi_sock_set_ip_add_membership(
sockfd, &imr_multiaddr, ipv6_mreq_opt->ipv6mr_interface);
HANDLE_ERROR(error);
return error;
case IPV6_LEAVE_GROUP:
assert(optlen == sizeof(struct ipv6_mreq));
ipv6_mreq_opt = (struct ipv6_mreq *)optval;
imr_multiaddr.kind = IPv6;
ipv6_addr_to_wasi_ipv6_addr(
(uint16_t *)ipv6_mreq_opt->ipv6mr_multiaddr.s6_addr,
&imr_multiaddr.addr.ip6);
error = __wasi_sock_set_ip_drop_membership(
sockfd, &imr_multiaddr, ipv6_mreq_opt->ipv6mr_interface);
HANDLE_ERROR(error);
return error;
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}
int
setsockopt(int sockfd, int level, int optname, const void *optval,
socklen_t optlen)
{
__wasi_errno_t error;
switch (level) {
case SOL_SOCKET:
return set_sol_socket_option(sockfd, optname, optval, optlen);
case IPPROTO_TCP:
return set_ipproto_tcp_option(sockfd, optname, optval, optlen);
case IPPROTO_IP:
return set_ipproto_ip_option(sockfd, optname, optval, optlen);
case IPPROTO_IPV6:
return set_ipproto_ipv6_option(sockfd, optname, optval, optlen);
default:
error = __WASI_ERRNO_NOTSUP;
HANDLE_ERROR(error);
return error;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
#ifndef WASMTIME_SSP_H
#define WASMTIME_SSP_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -588,6 +589,14 @@ typedef struct __wasi_addr_ip6_port_t {
__wasi_ip_port_t port;
} __wasi_addr_ip6_port_t;
typedef struct __wasi_addr_ip_t {
__wasi_addr_type_t kind;
union {
__wasi_addr_ip4_t ip4;
__wasi_addr_ip6_t ip6;
} addr;
} __wasi_addr_ip_t;
typedef struct __wasi_addr_t {
__wasi_addr_type_t kind;
union {
@ -598,6 +607,18 @@ typedef struct __wasi_addr_t {
typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
typedef struct __wasi_addr_info_t {
__wasi_addr_t addr;
__wasi_sock_type_t type;
} __wasi_addr_info_t;
typedef struct __wasi_addr_info_hints_t {
__wasi_sock_type_t type;
__wasi_address_family_t family;
// this is to workaround lack of optional parameters
uint8_t hints_enabled;
} __wasi_addr_info_hints_t;
#if defined(WASMTIME_SSP_WASI_API)
#define WASMTIME_SSP_SYSCALL_NAME(name) \
asm("__wasi_" #name)
@ -995,7 +1016,7 @@ wasi_ssp_sock_addr_local(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len
__wasi_fd_t fd, __wasi_addr_t *addr
) __attribute__((__warn_unused_result__));
__wasi_errno_t
@ -1003,7 +1024,7 @@ wasi_ssp_sock_addr_remote(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len
__wasi_fd_t fd, __wasi_addr_t *addr
) __attribute__((__warn_unused_result__));
__wasi_errno_t
@ -1023,6 +1044,16 @@ wasi_ssp_sock_bind(
__wasi_fd_t fd, __wasi_addr_t *addr
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_addr_resolve(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, char **ns_lookup_list,
#endif
const char *host, const char* service,
__wasi_addr_info_hints_t *hints, __wasi_addr_info_t *addr_info,
__wasi_size_t addr_info_size, __wasi_size_t *max_info_size
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_connect(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
@ -1049,6 +1080,18 @@ __wasi_errno_t wasmtime_ssp_sock_recv(
size_t *recv_len
) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_recv_from(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
void *buf,
size_t buf_len,
__wasi_riflags_t ri_flags,
__wasi_addr_t *src_addr,
size_t *recv_len
) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_send(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
@ -1059,6 +1102,18 @@ __wasi_errno_t wasmtime_ssp_sock_send(
size_t *sent_len
) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_send_to(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t sock,
const void *buf,
size_t buf_len,
__wasi_siflags_t si_flags,
const __wasi_addr_t *dest_addr,
size_t *sent_len
) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_shutdown(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
@ -1066,6 +1121,315 @@ __wasi_errno_t wasmtime_ssp_sock_shutdown(
__wasi_fd_t sock
) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_recv_timeout(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint64_t timeout_us
) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_recv_timeout(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint64_t *timeout_us
) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_send_timeout(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint64_t timeout_us
) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_send_timeout(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint64_t *timeout_us
) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_send_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
size_t bufsiz
) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_send_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
size_t *bufsiz
) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
size_t bufsiz
) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
size_t *bufsiz
) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_keep_alive(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_keep_alive(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_reuse_addr(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_reuse_addr(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_reuse_port(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_reuse_port(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_linger(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled,
int linger_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_linger(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, bool *is_enabled, int *linger_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_broadcast(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_broadcast(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint32_t time_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint32_t *time_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint32_t time_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint32_t *time_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool ipv6,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool ipv6,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
__wasi_addr_ip_t *imr_multiaddr,
uint32_t imr_interface
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
__wasi_addr_ip_t *imr_multiaddr,
uint32_t imr_interface
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_ttl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint8_t ttl_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_ip_ttl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint8_t *ttl_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint8_t ttl_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint8_t *ttl_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ipv6_only(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_ipv6_only(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sched_yield(void)
WASMTIME_SSP_SYSCALL_NAME(sched_yield) __attribute__((__warn_unused_result__));

View File

@ -161,6 +161,31 @@ convert_errno(int error)
return errors[error];
}
static bool
ns_lookup_list_search(char **list, const char *host)
{
size_t host_len = strlen(host), suffix_len;
while (*list) {
if (*list[0] == '*') {
suffix_len = strlen(*list) - 1;
if (suffix_len <= host_len
&& strncmp(host + host_len - suffix_len, *list + 1, suffix_len)
== 0) {
return true;
}
}
else {
if (strcmp(*list, host) == 0) {
return true;
}
}
list++;
}
return false;
}
// Converts a POSIX timespec to a CloudABI timestamp.
static __wasi_timestamp_t
convert_timespec(const struct timespec *ts)
@ -199,6 +224,82 @@ convert_clockid(__wasi_clockid_t in, clockid_t *out)
}
}
static void
wasi_addr_to_bh_sockaddr(const __wasi_addr_t *wasi_addr,
bh_sockaddr_t *sockaddr)
{
if (wasi_addr->kind == IPv4) {
sockaddr->addr_bufer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24)
| (wasi_addr->addr.ip4.addr.n1 << 16)
| (wasi_addr->addr.ip4.addr.n2 << 8)
| wasi_addr->addr.ip4.addr.n3;
sockaddr->is_ipv4 = true;
sockaddr->port = wasi_addr->addr.ip4.port;
}
else {
sockaddr->addr_bufer.ipv6[0] = wasi_addr->addr.ip6.addr.n0;
sockaddr->addr_bufer.ipv6[1] = wasi_addr->addr.ip6.addr.n1;
sockaddr->addr_bufer.ipv6[2] = wasi_addr->addr.ip6.addr.n2;
sockaddr->addr_bufer.ipv6[3] = wasi_addr->addr.ip6.addr.n3;
sockaddr->addr_bufer.ipv6[4] = wasi_addr->addr.ip6.addr.h0;
sockaddr->addr_bufer.ipv6[5] = wasi_addr->addr.ip6.addr.h1;
sockaddr->addr_bufer.ipv6[6] = wasi_addr->addr.ip6.addr.h2;
sockaddr->addr_bufer.ipv6[7] = wasi_addr->addr.ip6.addr.h3;
sockaddr->is_ipv4 = false;
sockaddr->port = wasi_addr->addr.ip6.port;
}
}
// Converts an IPv6 binary address object to WASI address object.
static void
bh_sockaddr_to_wasi_addr(const bh_sockaddr_t *sockaddr,
__wasi_addr_t *wasi_addr)
{
if (sockaddr->is_ipv4) {
wasi_addr->kind = IPv4;
wasi_addr->addr.ip4.port = sockaddr->port;
wasi_addr->addr.ip4.addr.n0 =
(sockaddr->addr_bufer.ipv4 & 0xFF000000) >> 24;
wasi_addr->addr.ip4.addr.n1 =
(sockaddr->addr_bufer.ipv4 & 0x00FF0000) >> 16;
wasi_addr->addr.ip4.addr.n2 =
(sockaddr->addr_bufer.ipv4 & 0x0000FF00) >> 8;
wasi_addr->addr.ip4.addr.n3 = (sockaddr->addr_bufer.ipv4 & 0x000000FF);
}
else {
wasi_addr->kind = IPv6;
wasi_addr->addr.ip6.port = sockaddr->port;
wasi_addr->addr.ip6.addr.n0 = sockaddr->addr_bufer.ipv6[0];
wasi_addr->addr.ip6.addr.n1 = sockaddr->addr_bufer.ipv6[1];
wasi_addr->addr.ip6.addr.n2 = sockaddr->addr_bufer.ipv6[2];
wasi_addr->addr.ip6.addr.n3 = sockaddr->addr_bufer.ipv6[3];
wasi_addr->addr.ip6.addr.h0 = sockaddr->addr_bufer.ipv6[4];
wasi_addr->addr.ip6.addr.h1 = sockaddr->addr_bufer.ipv6[5];
wasi_addr->addr.ip6.addr.h2 = sockaddr->addr_bufer.ipv6[6];
wasi_addr->addr.ip6.addr.h3 = sockaddr->addr_bufer.ipv6[7];
}
}
static void
wasi_addr_ip_to_bh_ip_addr_buffer(__wasi_addr_ip_t *addr,
bh_ip_addr_buffer_t *out)
{
if (addr->kind == IPv4) {
out->ipv4 = htonl((addr->addr.ip4.n0 << 24) | (addr->addr.ip4.n1 << 16)
| (addr->addr.ip4.n2 << 8) | addr->addr.ip4.n3);
}
else {
out->ipv6[0] = htons(addr->addr.ip6.n0);
out->ipv6[1] = htons(addr->addr.ip6.n1);
out->ipv6[2] = htons(addr->addr.ip6.n2);
out->ipv6[3] = htons(addr->addr.ip6.n3);
out->ipv6[4] = htons(addr->addr.ip6.h0);
out->ipv6[5] = htons(addr->addr.ip6.h1);
out->ipv6[6] = htons(addr->addr.ip6.h2);
out->ipv6[7] = htons(addr->addr.ip6.h3);
}
}
__wasi_errno_t
wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id,
__wasi_timestamp_t *resolution)
@ -2852,16 +2953,26 @@ wasi_ssp_sock_addr_local(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8 *buf, __wasi_size_t buf_len)
__wasi_fd_t fd, __wasi_addr_t *addr)
{
struct fd_object *fo;
bh_sockaddr_t bh_addr;
int ret;
__wasi_errno_t error =
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
if (error != __WASI_ESUCCESS)
return error;
ret = os_socket_addr_local(fd_number(fo), &bh_addr);
fd_object_release(fo);
return __WASI_ENOSYS;
if (ret != BHT_OK) {
return convert_errno(errno);
}
bh_sockaddr_to_wasi_addr(&bh_addr, addr);
return __WASI_ESUCCESS;
}
__wasi_errno_t
@ -2869,16 +2980,55 @@ wasi_ssp_sock_addr_remote(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8 *buf, __wasi_size_t buf_len)
__wasi_fd_t fd, __wasi_addr_t *addr)
{
struct fd_object *fo;
bh_sockaddr_t bh_addr;
int ret;
__wasi_errno_t error =
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_REMOTE, 0);
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
if (error != __WASI_ESUCCESS)
return error;
ret = os_socket_addr_remote(fd_number(fo), &bh_addr);
fd_object_release(fo);
return __WASI_ENOSYS;
if (ret != BHT_OK) {
return convert_errno(errno);
}
bh_sockaddr_to_wasi_addr(&bh_addr, addr);
return __WASI_ESUCCESS;
}
static bool
wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen)
{
if (addr->kind == IPv4) {
const char *format = "%u.%u.%u.%u";
assert(buflen >= 16);
snprintf(buf, buflen, format, addr->addr.ip4.addr.n0,
addr->addr.ip4.addr.n1, addr->addr.ip4.addr.n2,
addr->addr.ip4.addr.n3);
return true;
}
else if (addr->kind == IPv6) {
const char *format = "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x";
__wasi_addr_ip6_t ipv6 = addr->addr.ip6.addr;
assert(buflen >= 40);
snprintf(buf, buflen, format, ipv6.n0, ipv6.n1, ipv6.n2, ipv6.n3,
ipv6.h0, ipv6.h1, ipv6.h2, ipv6.h3);
return true;
}
return false;
}
__wasi_errno_t
@ -2888,15 +3038,15 @@ wasi_ssp_sock_bind(
#endif
__wasi_fd_t fd, __wasi_addr_t *addr)
{
char buf[24] = { 0 };
const char *format = "%u.%u.%u.%u";
char buf[48] = { 0 };
struct fd_object *fo;
__wasi_errno_t error;
int port = addr->addr.ip4.port;
int port = addr->kind == IPv4 ? addr->addr.ip4.port : addr->addr.ip6.port;
int ret;
snprintf(buf, 24, format, addr->addr.ip4.addr.n0, addr->addr.ip4.addr.n1,
addr->addr.ip4.addr.n2, addr->addr.ip4.addr.n3);
if (!wasi_addr_to_string(addr, buf, sizeof(buf))) {
return __WASI_EPROTONOSUPPORT;
}
if (!addr_pool_search(addr_pool, buf)) {
return __WASI_EACCES;
@ -2915,6 +3065,55 @@ wasi_ssp_sock_bind(
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasi_ssp_sock_addr_resolve(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, char **ns_lookup_list,
#endif
const char *host, const char *service, __wasi_addr_info_hints_t *hints,
__wasi_addr_info_t *addr_info, __wasi_size_t addr_info_size,
__wasi_size_t *max_info_size)
{
bh_addr_info_t *wamr_addr_info =
wasm_runtime_malloc(addr_info_size * sizeof(bh_addr_info_t));
uint8_t hints_is_ipv4 = hints->family == INET4;
uint8_t hints_is_tcp = hints->type == SOCKET_STREAM;
size_t _max_info_size;
size_t actual_info_size;
if (!ns_lookup_list_search(ns_lookup_list, host)) {
return __WASI_EACCES;
}
if (!wamr_addr_info) {
return __WASI_ENOMEM;
}
int ret = os_socket_addr_resolve(
host, service, hints->hints_enabled ? &hints_is_tcp : NULL,
hints->hints_enabled ? &hints_is_ipv4 : NULL, wamr_addr_info,
addr_info_size, &_max_info_size);
if (ret != BHT_OK) {
wasm_runtime_free(wamr_addr_info);
return convert_errno(errno);
}
*max_info_size = _max_info_size;
actual_info_size =
addr_info_size < *max_info_size ? addr_info_size : *max_info_size;
for (size_t i = 0; i < actual_info_size; i++) {
addr_info[i].type =
wamr_addr_info[i].is_tcp ? SOCKET_STREAM : SOCKET_DGRAM;
bh_sockaddr_to_wasi_addr(&wamr_addr_info[i].sockaddr,
&addr_info[i].addr);
}
wasm_runtime_free(wamr_addr_info);
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasi_ssp_sock_connect(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
@ -2922,14 +3121,14 @@ wasi_ssp_sock_connect(
#endif
__wasi_fd_t fd, __wasi_addr_t *addr)
{
char buf[24] = { 0 };
const char *format = "%u.%u.%u.%u";
char buf[48] = { 0 };
struct fd_object *fo;
__wasi_errno_t error;
int ret;
snprintf(buf, 24, format, addr->addr.ip4.addr.n0, addr->addr.ip4.addr.n1,
addr->addr.ip4.addr.n2, addr->addr.ip4.addr.n3);
if (!wasi_addr_to_string(addr, buf, sizeof(buf))) {
return __WASI_EPROTONOSUPPORT;
}
if (!addr_pool_search(addr_pool, buf)) {
return __WASI_EACCES;
@ -2939,7 +3138,9 @@ wasi_ssp_sock_connect(
if (error != __WASI_ESUCCESS)
return error;
ret = os_socket_connect(fd_number(fo), buf, addr->addr.ip4.port);
ret = os_socket_connect(fd_number(fo), buf,
addr->kind == IPv4 ? addr->addr.ip4.port
: addr->addr.ip6.port);
fd_object_release(fo);
if (BHT_OK != ret) {
return convert_errno(errno);
@ -2980,7 +3181,8 @@ wasi_ssp_sock_open(
__wasi_fd_t *sockfd)
{
bh_socket_t sock;
int tcp_or_udp = 0;
bool is_tcp = SOCKET_DGRAM == socktype ? false : true;
bool is_ipv4 = INET6 == af ? false : true;
int ret;
__wasi_filetype_t wasi_type;
__wasi_rights_t max_base, max_inheriting;
@ -2988,13 +3190,7 @@ wasi_ssp_sock_open(
(void)poolfd;
if (INET4 != af) {
return __WASI_EAFNOSUPPORT;
}
tcp_or_udp = SOCKET_DGRAM == socktype ? 0 : 1;
ret = os_socket_create(&sock, tcp_or_udp);
ret = os_socket_create(&sock, is_ipv4, is_tcp);
if (BHT_OK != ret) {
return convert_errno(errno);
}
@ -3029,9 +3225,24 @@ wasmtime_ssp_sock_recv(
struct fd_table *curfds,
#endif
__wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len)
{
__wasi_addr_t src_addr;
return wasmtime_ssp_sock_recv_from(curfds, sock, buf, buf_len, 0, &src_addr,
recv_len);
}
__wasi_errno_t
wasmtime_ssp_sock_recv_from(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, void *buf, size_t buf_len, __wasi_riflags_t ri_flags,
__wasi_addr_t *src_addr, size_t *recv_len)
{
struct fd_object *fo;
__wasi_errno_t error;
bh_sockaddr_t sockaddr;
int ret;
error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0);
@ -3039,12 +3250,14 @@ wasmtime_ssp_sock_recv(
return error;
}
ret = os_socket_recv(fd_number(fo), buf, buf_len);
ret = os_socket_recv_from(fd_number(fo), buf, buf_len, 0, &sockaddr);
fd_object_release(fo);
if (-1 == ret) {
return convert_errno(errno);
}
bh_sockaddr_to_wasi_addr(&sockaddr, src_addr);
*recv_len = (size_t)ret;
return __WASI_ESUCCESS;
}
@ -3075,6 +3288,45 @@ wasmtime_ssp_sock_send(
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasmtime_ssp_sock_send_to(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t sock, const void *buf, size_t buf_len,
__wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr, size_t *sent_len)
{
char addr_buf[48] = { 0 };
struct fd_object *fo;
__wasi_errno_t error;
int ret;
bh_sockaddr_t sockaddr;
if (!wasi_addr_to_string(dest_addr, addr_buf, sizeof(addr_buf))) {
return __WASI_EPROTONOSUPPORT;
}
if (!addr_pool_search(addr_pool, addr_buf)) {
return __WASI_EACCES;
}
error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0);
if (error != 0) {
return error;
}
wasi_addr_to_bh_sockaddr(dest_addr, &sockaddr);
ret = os_socket_send_to(fd_number(fo), buf, buf_len, 0, &sockaddr);
fd_object_release(fo);
if (-1 == ret) {
return convert_errno(errno);
}
*sent_len = (size_t)ret;
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasmtime_ssp_sock_shutdown(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
@ -3220,9 +3472,8 @@ fd_prestats_destroy(struct fd_prestats *pt)
bool
addr_pool_init(struct addr_pool *addr_pool)
{
addr_pool->next = NULL;
addr_pool->addr = 0;
addr_pool->mask = 0;
memset(addr_pool, 0, sizeof(*addr_pool));
return true;
}
@ -3231,6 +3482,7 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
{
struct addr_pool *cur = addr_pool;
struct addr_pool *next;
bh_ip_addr_buffer_t target;
if (!addr_pool) {
return false;
@ -3242,9 +3494,20 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
next->next = NULL;
next->mask = mask;
if (os_socket_inet_network(addr, &next->addr) != BHT_OK) {
wasm_runtime_free(next);
return false;
if (os_socket_inet_network(true, addr, &target) != BHT_OK) {
// If parsing IPv4 fails, try IPv6
if (os_socket_inet_network(false, addr, &target) != BHT_OK) {
wasm_runtime_free(next);
return false;
}
next->type = IPv6;
bh_memcpy_s(next->addr.ip6, sizeof(next->addr.ip6), target.ipv6,
sizeof(target.ipv6));
}
else {
next->type = IPv4;
next->addr.ip4 = target.ipv4;
}
/* attach with */
@ -3255,47 +3518,106 @@ addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
return true;
}
static bool
compare_address(const struct addr_pool *addr_pool_entry, const char *addr)
static inline size_t
min(size_t a, size_t b)
{
/* host order */
uint32 target;
uint32 address = addr_pool_entry->addr;
/* 0.0.0.0 means any address */
if (0 == address) {
return a > b ? b : a;
}
static void
init_address_mask(uint8_t *buf, size_t buflen, size_t mask)
{
size_t element_size = sizeof(uint8_t) * 8;
for (size_t i = 0; i < buflen; i++) {
if (mask <= i * element_size) {
buf[i] = 0;
}
else {
size_t offset = min(mask - i * element_size, element_size);
buf[i] = (~0u) << (element_size - offset);
}
}
}
/* target must be in network byte order */
static bool
compare_address(const struct addr_pool *addr_pool_entry,
bh_ip_addr_buffer_t *target)
{
uint8_t maskbuf[16] = { 0 };
uint8_t basebuf[16] = { 0 };
size_t addr_size;
uint8_t max_addr_mask;
if (addr_pool_entry->type == IPv4) {
uint32_t addr_ip4 = htonl(addr_pool_entry->addr.ip4);
bh_memcpy_s(basebuf, sizeof(addr_ip4), &addr_ip4, sizeof(addr_ip4));
addr_size = 4;
}
else {
uint16_t partial_addr_ip6;
for (int i = 0; i < 8; i++) {
partial_addr_ip6 = htons(addr_pool_entry->addr.ip6[i]);
bh_memcpy_s(&basebuf[i * sizeof(partial_addr_ip6)],
sizeof(partial_addr_ip6), &partial_addr_ip6,
sizeof(partial_addr_ip6));
}
addr_size = 16;
}
max_addr_mask = addr_size * 8;
/* IPv4 0.0.0.0 or IPv6 :: means any address */
if (basebuf[0] == 0 && !memcmp(basebuf, basebuf + 1, addr_size - 1)) {
return true;
}
if (os_socket_inet_network(addr, &target) != BHT_OK) {
/* No support for invalid mask value */
if (addr_pool_entry->mask > max_addr_mask) {
return false;
}
const uint32 max_mask_value = 32;
/* no support for invalid mask values */
if (addr_pool_entry->mask > max_mask_value) {
return false;
init_address_mask(maskbuf, addr_size, addr_pool_entry->mask);
for (size_t i = 0; i < addr_size; i++) {
uint8_t addr_mask = target->data[i] & maskbuf[i];
uint8_t range_mask = basebuf[i] & maskbuf[i];
if (addr_mask != range_mask) {
return false;
}
}
/* convert mask number into 32-bit mask value, i.e. mask /24 will be
converted to 4294967040 (binary: 11111111 11111111 11111111 00000000) */
uint32 mask = 0;
for (int i = 0; i < addr_pool_entry->mask; i++) {
mask |= 1 << (max_mask_value - 1 - i);
}
uint32 first_address = address & mask;
uint32 last_address = address | (~mask);
return first_address <= target && target <= last_address;
return true;
}
bool
addr_pool_search(struct addr_pool *addr_pool, const char *addr)
{
struct addr_pool *cur = addr_pool->next;
bh_ip_addr_buffer_t target;
__wasi_addr_type_t addr_type;
if (os_socket_inet_network(true, addr, &target) != BHT_OK) {
size_t i;
if (os_socket_inet_network(false, addr, &target) != BHT_OK) {
return false;
}
addr_type = IPv6;
for (i = 0; i < sizeof(target.ipv6) / sizeof(target.ipv6[0]); i++) {
target.ipv6[i] = htons(target.ipv6[i]);
}
}
else {
addr_type = IPv4;
target.ipv4 = htonl(target.ipv4);
}
while (cur) {
if (compare_address(cur, addr))
if (cur->type == addr_type && compare_address(cur, &target)) {
return true;
}
cur = cur->next;
}
@ -3313,3 +3635,203 @@ addr_pool_destroy(struct addr_pool *addr_pool)
cur = next;
}
}
#ifndef WASMTIME_SSP_STATIC_CURFDS
#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE struct fd_table *curfds,
#else
#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE
#endif
// Defines a function that passes through the socket option to the OS
// implementation
#define WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(FUNC_NAME, OPTION_TYPE) \
__wasi_errno_t wasmtime_ssp_sock_##FUNC_NAME( \
WASMTIME_SSP_PASSTHROUGH_FD_TABLE __wasi_fd_t sock, \
OPTION_TYPE option) \
{ \
struct fd_object *fo; \
__wasi_errno_t error; \
int ret; \
error = fd_object_get(curfds, &fo, sock, 0, 0); \
if (error != 0) \
return error; \
ret = os_socket_##FUNC_NAME(fd_number(fo), option); \
fd_object_release(fo); \
if (BHT_OK != ret) \
return convert_errno(errno); \
return __WASI_ESUCCESS; \
}
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_send_timeout, uint64)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_send_timeout, uint64 *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_recv_timeout, uint64)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_recv_timeout, uint64 *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_send_buf_size, size_t)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_send_buf_size, size_t *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_recv_buf_size, size_t)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_recv_buf_size, size_t *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_broadcast, bool)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_broadcast, bool *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_keep_alive, bool)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_keep_alive, bool *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_reuse_addr, bool)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_reuse_addr, bool *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_reuse_port, bool)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_reuse_port, bool *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_no_delay, bool)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_no_delay, bool *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_quick_ack, bool)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_quick_ack, bool *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_keep_idle, uint32)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_keep_idle, uint32 *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_keep_intvl, uint32)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_keep_intvl, uint32 *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_fastopen_connect, bool)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_fastopen_connect, bool *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ip_ttl, uint8_t)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ip_ttl, uint8_t *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ip_multicast_ttl, uint8_t)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ip_multicast_ttl, uint8_t *)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ipv6_only, bool)
WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ipv6_only, bool *)
#undef WASMTIME_SSP_PASSTHROUGH_FD_TABLE
#undef WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION
__wasi_errno_t
wasmtime_ssp_sock_set_linger(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, bool is_enabled, int linger_s)
{
struct fd_object *fo;
__wasi_errno_t error;
int ret;
error = fd_object_get(curfds, &fo, sock, 0, 0);
if (error != 0)
return error;
ret = os_socket_set_linger(fd_number(fo), is_enabled, linger_s);
fd_object_release(fo);
if (BHT_OK != ret)
return convert_errno(errno);
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasmtime_ssp_sock_get_linger(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, bool *is_enabled, int *linger_s)
{
struct fd_object *fo;
__wasi_errno_t error;
int ret;
error = fd_object_get(curfds, &fo, sock, 0, 0);
if (error != 0)
return error;
ret = os_socket_get_linger(fd_number(fo), is_enabled, linger_s);
fd_object_release(fo);
if (BHT_OK != ret)
return convert_errno(errno);
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasmtime_ssp_sock_set_ip_add_membership(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface)
{
struct fd_object *fo;
__wasi_errno_t error;
int ret;
bh_ip_addr_buffer_t addr_info;
bool is_ipv6;
error = fd_object_get(curfds, &fo, sock, 0, 0);
if (error != 0)
return error;
wasi_addr_ip_to_bh_ip_addr_buffer(imr_multiaddr, &addr_info);
is_ipv6 = imr_multiaddr->kind == IPv6;
ret = os_socket_set_ip_add_membership(fd_number(fo), &addr_info,
imr_interface, is_ipv6);
fd_object_release(fo);
if (BHT_OK != ret)
return convert_errno(errno);
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasmtime_ssp_sock_set_ip_drop_membership(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface)
{
struct fd_object *fo;
__wasi_errno_t error;
int ret;
bh_ip_addr_buffer_t addr_info;
bool is_ipv6;
error = fd_object_get(curfds, &fo, sock, 0, 0);
if (error != 0)
return error;
wasi_addr_ip_to_bh_ip_addr_buffer(imr_multiaddr, &addr_info);
is_ipv6 = imr_multiaddr->kind == IPv6;
ret = os_socket_set_ip_drop_membership(fd_number(fo), &addr_info,
imr_interface, is_ipv6);
fd_object_release(fo);
if (BHT_OK != ret)
return convert_errno(errno);
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasmtime_ssp_sock_set_ip_multicast_loop(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, bool ipv6, bool is_enabled)
{
struct fd_object *fo;
__wasi_errno_t error;
int ret;
error = fd_object_get(curfds, &fo, sock, 0, 0);
if (error != 0)
return error;
ret = os_socket_set_ip_multicast_loop(fd_number(fo), ipv6, is_enabled);
fd_object_release(fo);
if (BHT_OK != ret)
return convert_errno(errno);
return __WASI_ESUCCESS;
}
__wasi_errno_t
wasmtime_ssp_sock_get_ip_multicast_loop(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, bool ipv6, bool *is_enabled)
{
struct fd_object *fo;
__wasi_errno_t error;
int ret;
error = fd_object_get(curfds, &fo, sock, 0, 0);
if (error != 0)
return error;
ret = os_socket_get_ip_multicast_loop(fd_number(fo), ipv6, is_enabled);
fd_object_release(fo);
if (BHT_OK != ret)
return convert_errno(errno);
return __WASI_ESUCCESS;
}

View File

@ -47,9 +47,13 @@ struct argv_environ_values {
};
struct addr_pool {
struct addr_pool *next;
/* addr and mask in host order */
uint32 addr;
union {
uint32 ip4;
uint16 ip6[8];
} addr;
struct addr_pool *next;
__wasi_addr_type_t type;
uint8 mask;
};