diff --git a/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h b/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h index 84b8811ac..cad60b112 100644 --- a/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h +++ b/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h @@ -6,6 +6,7 @@ #ifndef _WASI_SOCKET_EXT_H_ #define _WASI_SOCKET_EXT_H_ +#include #include #include @@ -63,6 +64,14 @@ typedef struct __wasi_addr_ip6_port_t { __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 { @@ -93,10 +102,33 @@ typedef struct __wasi_addr_info_hints_t { * * */ - +#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. */ @@ -368,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, @@ -386,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, @@ -483,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, @@ -501,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, @@ -513,15 +545,17 @@ __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 @@ -580,6 +614,363 @@ __wasi_sock_set_send_timeout(__wasi_fd_t fd, uint64_t timeout_us) (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, diff --git a/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c b/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c index bc15125f3..aaf658dd3 100644 --- a/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c +++ b/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c @@ -18,17 +18,36 @@ 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) { - addr_num = ntohl(addr_num); out->kind = IPv4; out->addr.ip4.port = ntohs(port); - out->addr.ip4.addr.n0 = (addr_num & 0xFF000000) >> 24; - out->addr.ip4.addr.n1 = (addr_num & 0x00FF0000) >> 16; - out->addr.ip4.addr.n2 = (addr_num & 0x0000FF00) >> 8; - out->addr.ip4.addr.n3 = (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 @@ -36,14 +55,7 @@ ipv6_addr_to_wasi_addr(uint16_t *addr, uint16_t port, __wasi_addr_t *out) { out->kind = IPv6; out->addr.ip6.port = ntohs(port); - out->addr.ip6.addr.n0 = ntohs(addr[0]); - out->addr.ip6.addr.n1 = ntohs(addr[1]); - out->addr.ip6.addr.n2 = ntohs(addr[2]); - out->addr.ip6.addr.n3 = ntohs(addr[3]); - out->addr.ip6.addr.h0 = ntohs(addr[4]); - out->addr.ip6.addr.h1 = ntohs(addr[5]); - out->addr.ip6.addr.h2 = ntohs(addr[6]); - out->addr.ip6.addr.h3 = ntohs(addr[7]); + ipv6_addr_to_wasi_ipv6_addr(addr, &(out->addr.ip6.addr)); } static __wasi_errno_t @@ -552,6 +564,8 @@ get_sol_socket_option(int sockfd, int optname, void *__restrict optval, { __wasi_errno_t error; uint64_t timeout_us; + bool is_linger_enabled; + int linger_s; switch (optname) { case SO_RCVTIMEO: @@ -566,21 +580,165 @@ get_sol_socket_option(int sockfd, int optname, void *__restrict optval, 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; } +} - HANDLE_ERROR(__WASI_ERRNO_NOTSUP); +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; } - - HANDLE_ERROR(__WASI_ERRNO_NOTSUP); } int @@ -603,19 +761,210 @@ set_sol_socket_option(int sockfd, int optname, const void *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; } +} - HANDLE_ERROR(__WASI_ERRNO_NOTSUP); +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; } - - HANDLE_ERROR(__WASI_ERRNO_NOTSUP); } diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 327941ca7..bd76c1225 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -1120,10 +1120,80 @@ wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) } static wasi_errno_t -wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, - wasi_size_t *size) +wasi_sock_get_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) { - return __WASI_ENOSYS; + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_broadcast(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_keep_alive(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool *is_enabled, + int *linger_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool)) + || !validate_native_addr(linger_s, sizeof(int))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_linger(curfds, fd, is_enabled, linger_s); +} + +static wasi_errno_t +wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, + size_t *size) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(size, sizeof(wasi_size_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_recv_buf_size(curfds, fd, size); } static wasi_errno_t @@ -1146,22 +1216,60 @@ wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, } static wasi_errno_t -wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *reuse) +wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) { - return __WASI_ENOSYS; + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_reuse_addr(curfds, fd, is_enabled); } static wasi_errno_t -wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *reuse) +wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) { - return __WASI_ENOSYS; + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_reuse_port(curfds, fd, is_enabled); } static wasi_errno_t wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, - wasi_size_t *size) + size_t *size) { - return __WASI_ENOSYS; + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(size, sizeof(__wasi_size_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_send_buf_size(curfds, fd, size); } static wasi_errno_t @@ -1183,6 +1291,177 @@ wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, return wasmtime_ssp_sock_get_send_timeout(curfds, fd, timeout_us); } +static wasi_errno_t +wasi_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_fastopen_connect(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_no_delay(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_quick_ack(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint32_t *time_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(time_s, sizeof(uint32_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_keep_idle(curfds, fd, time_s); +} + +static wasi_errno_t +wasi_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint32_t *time_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(time_s, sizeof(uint32_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_tcp_keep_intvl(curfds, fd, time_s); +} + +static wasi_errno_t +wasi_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool ipv6, bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_ip_multicast_loop(curfds, fd, ipv6, + is_enabled); +} + +static wasi_errno_t +wasi_sock_get_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t *ttl_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(ttl_s, sizeof(uint8_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_ip_ttl(curfds, fd, ttl_s); +} + +static wasi_errno_t +wasi_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint8_t *ttl_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(ttl_s, sizeof(uint8_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_ip_multicast_ttl(curfds, fd, ttl_s); +} + +static wasi_errno_t +wasi_sock_get_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool *is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(is_enabled, sizeof(bool))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_get_ipv6_only(curfds, fd, is_enabled); +} + static wasi_errno_t wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog) { @@ -1216,10 +1495,65 @@ wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd, } static wasi_errno_t -wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, - wasi_size_t size) +wasi_sock_set_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) { - return __WASI_ENOSYS; + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_broadcast(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_keep_alive(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled, + int linger_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_linger(curfds, fd, is_enabled, linger_s); +} + +static wasi_errno_t +wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_recv_buf_size(curfds, fd, size); } static wasi_errno_t @@ -1239,22 +1573,50 @@ wasi_sock_set_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, } static wasi_errno_t -wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 reuse) +wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) { - return __WASI_ENOSYS; + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_reuse_addr(curfds, fd, is_enabled); } static wasi_errno_t -wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 reuse) +wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) { - return __WASI_ENOSYS; + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_reuse_port(curfds, fd, is_enabled); } static wasi_errno_t -wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, - wasi_size_t size) +wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) { - return __WASI_ENOSYS; + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_send_buf_size(curfds, fd, size); } static wasi_errno_t @@ -1273,6 +1635,191 @@ wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, return wasmtime_ssp_sock_set_send_timeout(curfds, fd, timeout_us); } +static wasi_errno_t +wasi_sock_set_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_fastopen_connect(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_no_delay(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_quick_ack(curfds, fd, is_enabled); +} + +static wasi_errno_t +wasi_sock_set_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint32_t time_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_keep_idle(curfds, fd, time_s); +} + +static wasi_errno_t +wasi_sock_set_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint32_t time_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_tcp_keep_intvl(curfds, fd, time_s); +} + +static wasi_errno_t +wasi_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, + bool ipv6, bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_multicast_loop(curfds, fd, ipv6, + is_enabled); +} + +static wasi_errno_t +wasi_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_add_membership(curfds, fd, imr_multiaddr, + imr_interface); +} + +static wasi_errno_t +wasi_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, + __wasi_addr_ip_t *imr_multiaddr, + uint32_t imr_interface) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t))) + return __WASI_EINVAL; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_drop_membership(curfds, fd, imr_multiaddr, + imr_interface); +} + +static wasi_errno_t +wasi_sock_set_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t ttl_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_ttl(curfds, fd, ttl_s); +} + +static wasi_errno_t +wasi_sock_set_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, + uint8_t ttl_s) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ip_multicast_ttl(curfds, fd, ttl_s); +} + +static wasi_errno_t +wasi_sock_set_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + struct fd_table *curfds = NULL; + + if (!wasi_ctx) + return __WASI_EACCES; + + curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + + return wasmtime_ssp_sock_set_ipv6_only(curfds, fd, is_enabled); +} + static wasi_errno_t allocate_iovec_app_buffer(wasm_module_inst_t module_inst, const iovec_app_t *data, uint32 data_len, @@ -1589,24 +2136,50 @@ static NativeSymbol native_symbols_libc_wasi[] = { REG_NATIVE_FUNC(sock_bind, "(i*)i"), REG_NATIVE_FUNC(sock_close, "(i)i"), REG_NATIVE_FUNC(sock_connect, "(i*)i"), + REG_NATIVE_FUNC(sock_get_broadcast, "(i*)i"), + REG_NATIVE_FUNC(sock_get_keep_alive, "(i*)i"), + REG_NATIVE_FUNC(sock_get_linger, "(i**)i"), REG_NATIVE_FUNC(sock_get_recv_buf_size, "(i*)i"), REG_NATIVE_FUNC(sock_get_recv_timeout, "(i*)i"), REG_NATIVE_FUNC(sock_get_reuse_addr, "(i*)i"), REG_NATIVE_FUNC(sock_get_reuse_port, "(i*)i"), REG_NATIVE_FUNC(sock_get_send_buf_size, "(i*)i"), REG_NATIVE_FUNC(sock_get_send_timeout, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_fastopen_connect, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_keep_idle, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_keep_intvl, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_no_delay, "(i*)i"), + REG_NATIVE_FUNC(sock_get_tcp_quick_ack, "(i*)i"), + REG_NATIVE_FUNC(sock_get_ip_multicast_loop, "(ii*)i"), + REG_NATIVE_FUNC(sock_get_ip_multicast_ttl, "(i*)i"), + REG_NATIVE_FUNC(sock_get_ip_ttl, "(i*)i"), + REG_NATIVE_FUNC(sock_get_ipv6_only, "(i*)i"), REG_NATIVE_FUNC(sock_listen, "(ii)i"), REG_NATIVE_FUNC(sock_open, "(iii*)i"), REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"), REG_NATIVE_FUNC(sock_recv_from, "(i*ii**)i"), REG_NATIVE_FUNC(sock_send, "(i*ii*)i"), REG_NATIVE_FUNC(sock_send_to, "(i*ii**)i"), + REG_NATIVE_FUNC(sock_set_broadcast, "(ii)i"), + REG_NATIVE_FUNC(sock_set_keep_alive, "(ii)i"), + REG_NATIVE_FUNC(sock_set_linger, "(iii)i"), REG_NATIVE_FUNC(sock_set_recv_buf_size, "(ii)i"), REG_NATIVE_FUNC(sock_set_recv_timeout, "(iI)i"), REG_NATIVE_FUNC(sock_set_reuse_addr, "(ii)i"), REG_NATIVE_FUNC(sock_set_reuse_port, "(ii)i"), REG_NATIVE_FUNC(sock_set_send_buf_size, "(ii)i"), REG_NATIVE_FUNC(sock_set_send_timeout, "(iI)i"), + REG_NATIVE_FUNC(sock_set_tcp_fastopen_connect, "(ii)i"), + REG_NATIVE_FUNC(sock_set_tcp_keep_idle, "(ii)i"), + REG_NATIVE_FUNC(sock_set_tcp_keep_intvl, "(ii)i"), + REG_NATIVE_FUNC(sock_set_tcp_no_delay, "(ii)i"), + REG_NATIVE_FUNC(sock_set_tcp_quick_ack, "(ii)i"), + REG_NATIVE_FUNC(sock_set_ip_multicast_loop, "(iii)i"), + REG_NATIVE_FUNC(sock_set_ip_multicast_ttl, "(ii)i"), + REG_NATIVE_FUNC(sock_set_ip_add_membership, "(i*i)i"), + REG_NATIVE_FUNC(sock_set_ip_drop_membership, "(i*i)i"), + REG_NATIVE_FUNC(sock_set_ip_ttl, "(ii)i"), + REG_NATIVE_FUNC(sock_set_ipv6_only, "(ii)i"), REG_NATIVE_FUNC(sock_shutdown, "(ii)i"), REG_NATIVE_FUNC(sched_yield, "()i"), }; diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index 79f1375a3..60e1975d0 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -18,6 +18,7 @@ #ifndef WASMTIME_SSP_H #define WASMTIME_SSP_H +#include #include #include @@ -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 { @@ -1144,6 +1153,283 @@ __wasi_errno_t wasmtime_ssp_sock_get_send_timeout( 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__)); diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 9d7026378..b0760fd84 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -250,6 +250,7 @@ wasi_addr_to_bh_sockaddr(const __wasi_addr_t *wasi_addr, } } +// 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) @@ -279,6 +280,26 @@ bh_sockaddr_to_wasi_addr(const bh_sockaddr_t *sockaddr, } } +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) @@ -3645,6 +3666,172 @@ 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; +} diff --git a/core/shared/platform/common/posix/posix_socket.c b/core/shared/platform/common/posix/posix_socket.c index 229aa589a..f6091cde2 100644 --- a/core/shared/platform/common/posix/posix_socket.c +++ b/core/shared/platform/common/posix/posix_socket.c @@ -8,6 +8,8 @@ #include #include +#include +#include static bool textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out) @@ -400,6 +402,485 @@ os_socket_addr_resolve(const char *host, const char *service, return BHT_OK; } +static int +os_socket_setbooloption(bh_socket_t socket, int level, int optname, + bool is_enabled) +{ + int option = (int)is_enabled; + if (setsockopt(socket, level, optname, &option, sizeof(option)) != 0) { + return BHT_ERROR; + } + + return BHT_OK; +} + +static int +os_socket_getbooloption(bh_socket_t socket, int level, int optname, + bool *is_enabled) +{ + assert(is_enabled); + + int optval; + int optval_size = sizeof(optval); + if (getsockopt(socket, level, optname, &optval, &optval_size) != 0) { + return BHT_ERROR; + } + *is_enabled = (bool)optval; + return BHT_OK; +} + +int +os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) +{ + int buf_size_int = (int)bufsiz; + if (setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buf_size_int, + sizeof(buf_size_int)) + != 0) { + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + assert(bufsiz); + + int buf_size_int; + socklen_t bufsiz_len = sizeof(buf_size_int); + if (getsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buf_size_int, &bufsiz_len) + != 0) { + return BHT_ERROR; + } + *bufsiz = (size_t)buf_size_int; + + return BHT_OK; +} + +int +os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) +{ + int buf_size_int = (int)bufsiz; + if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buf_size_int, + sizeof(buf_size_int)) + != 0) { + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + assert(bufsiz); + + int buf_size_int; + socklen_t bufsiz_len = sizeof(buf_size_int); + if (getsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buf_size_int, &bufsiz_len) + != 0) { + return BHT_ERROR; + } + *bufsiz = (size_t)buf_size_int; + + return BHT_OK; +} + +int +os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) +{ + return os_socket_setbooloption(socket, SOL_SOCKET, SO_KEEPALIVE, + is_enabled); +} + +int +os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) +{ + return os_socket_getbooloption(socket, SOL_SOCKET, SO_KEEPALIVE, + is_enabled); +} + +int +os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) +{ + return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEADDR, + is_enabled); +} + +int +os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) +{ + return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEADDR, + is_enabled); +} + +int +os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) +{ + return os_socket_setbooloption(socket, SOL_SOCKET, SO_REUSEPORT, + is_enabled); +} + +int +os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) +{ + return os_socket_getbooloption(socket, SOL_SOCKET, SO_REUSEPORT, + is_enabled); +} + +int +os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) +{ + struct linger linger_opts = { .l_onoff = (int)is_enabled, + .l_linger = linger_s }; + if (setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_opts, + sizeof(linger_opts)) + != 0) { + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) +{ + assert(time_s); + + struct linger linger_opts; + socklen_t linger_opts_len = sizeof(linger_opts); + if (getsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_opts, + &linger_opts_len) + != 0) { + return BHT_ERROR; + } + *linger_s = linger_opts.l_linger; + *is_enabled = (bool)linger_opts.l_onoff; + return BHT_OK; +} + +int +os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) +{ + return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_NODELAY, + is_enabled); +} + +int +os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) +{ + return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_NODELAY, + is_enabled); +} + +int +os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) +{ +#ifdef TCP_QUICKACK + return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_QUICKACK, + is_enabled); +#else + errno = ENOSYS; + + return BHT_ERROR; +#endif +} + +int +os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) +{ +#ifdef TCP_QUICKACK + return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_QUICKACK, + is_enabled); +#else + errno = ENOSYS; + + return BHT_ERROR; +#endif +} + +int +os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) +{ + int time_s_int = (int)time_s; +#ifdef TCP_KEEPIDLE + if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int, + sizeof(time_s_int)) + != 0) { + return BHT_ERROR; + } + return BHT_OK; +#elif defined(TCP_KEEPALIVE) + if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int, + sizeof(time_s_int)) + != 0) { + return BHT_ERROR; + } + return BHT_OK; +#else + errno = ENOSYS; + + return BHT_ERROR; +#endif +} + +int +os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) +{ + assert(time_s); + int time_s_int; + socklen_t time_s_len = sizeof(time_s_int); +#ifdef TCP_KEEPIDLE + if (getsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &time_s_int, &time_s_len) + != 0) { + return BHT_ERROR; + } + *time_s = (uint32)time_s_int; + return BHT_OK; +#elif defined(TCP_KEEPALIVE) + if (getsockopt(socket, IPPROTO_TCP, TCP_KEEPALIVE, &time_s_int, &time_s_len) + != 0) { + return BHT_ERROR; + } + *time_s = (uint32)time_s_int; + return BHT_OK; +#else + errno = ENOSYS; + + return BHT_ERROR; +#endif +} + +int +os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) +{ + int time_s_int = (int)time_s; +#ifdef TCP_KEEPINTVL + if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &time_s_int, + sizeof(time_s_int)) + != 0) { + return BHT_ERROR; + } + + return BHT_OK; +#else + errno = ENOSYS; + + return BHT_ERROR; +#endif +} + +int +os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) +{ +#ifdef TCP_KEEPINTVL + assert(time_s); + int time_s_int; + socklen_t time_s_len = sizeof(time_s_int); + if (getsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &time_s_int, &time_s_len) + != 0) { + return BHT_ERROR; + } + *time_s = (uint32)time_s_int; + return BHT_OK; +#else + errno = ENOSYS; + + return BHT_ERROR; +#endif +} + +int +os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) +{ +#ifdef TCP_FASTOPEN_CONNECT + return os_socket_setbooloption(socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, + is_enabled); +#else + errno = ENOSYS; + + return BHT_ERROR; +#endif +} + +int +os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) +{ +#ifdef TCP_FASTOPEN_CONNECT + return os_socket_getbooloption(socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, + is_enabled); +#else + errno = ENOSYS; + + return BHT_ERROR; +#endif +} + +int +os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) +{ + if (ipv6) { + return os_socket_setbooloption(socket, IPPROTO_IPV6, + IPV6_MULTICAST_LOOP, is_enabled); + } + else { + return os_socket_setbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP, + is_enabled); + } +} + +int +os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled) +{ + if (ipv6) { + return os_socket_getbooloption(socket, IPPROTO_IPV6, + IPV6_MULTICAST_LOOP, is_enabled); + } + else { + return os_socket_getbooloption(socket, IPPROTO_IP, IP_MULTICAST_LOOP, + is_enabled); + } +} + +int +os_socket_set_ip_add_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + assert(imr_multiaddr); + if (is_ipv6) { + struct ipv6_mreq mreq; + for (int i = 0; i < 8; i++) { + ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] = + imr_multiaddr->ipv6[i]; + } + mreq.ipv6mr_interface = imr_interface; + if (setsockopt(socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, + sizeof(mreq)) + != 0) { + return BHT_ERROR; + } + } + else { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4; + mreq.imr_interface.s_addr = imr_interface; + if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, + sizeof(mreq)) + != 0) { + return BHT_ERROR; + } + } + + return BHT_OK; +} + +int +os_socket_set_ip_drop_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + assert(imr_multiaddr); + if (is_ipv6) { + struct ipv6_mreq mreq; + for (int i = 0; i < 8; i++) { + ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] = + imr_multiaddr->ipv6[i]; + } + mreq.ipv6mr_interface = imr_interface; + if (setsockopt(socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, + sizeof(mreq)) + != 0) { + return BHT_ERROR; + } + } + else { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = imr_multiaddr->ipv4; + mreq.imr_interface.s_addr = imr_interface; + if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, + sizeof(mreq)) + != 0) { + return BHT_ERROR; + } + } + + return BHT_OK; +} + +int +os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + if (setsockopt(socket, IPPROTO_IP, IP_TTL, &ttl_s, sizeof(ttl_s)) != 0) { + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + socklen_t opt_len = sizeof(ttl_s); + if (getsockopt(socket, IPPROTO_IP, IP_TTL, ttl_s, &opt_len) != 0) { + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl_s, sizeof(ttl_s)) + != 0) { + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + socklen_t opt_len = sizeof(ttl_s); + if (getsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, ttl_s, &opt_len) + != 0) { + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled) +{ + return os_socket_setbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY, + is_enabled); +} + +int +os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled) +{ + return os_socket_getbooloption(socket, IPPROTO_IPV6, IPV6_V6ONLY, + is_enabled); +} + +int +os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) +{ + return os_socket_setbooloption(socket, SOL_SOCKET, SO_BROADCAST, + is_enabled); +} + +int +os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled) +{ + return os_socket_getbooloption(socket, SOL_SOCKET, SO_BROADCAST, + is_enabled); +} + int os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us) { diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 148dc45ca..c214c88fa 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -531,6 +531,73 @@ os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr); int os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr); +/** + * Set the maximum send buffer size. + * + * @param socket the socket to set + * @param bufsiz requested kernel buffer size + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz); + +/** + * Get the maximum send buffer size. + * + * @param socket the socket to set + * @param bufsiz the returned kernel buffer size + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz); + +/** + * Set the maximum receive buffer size. + * + * @param socket the socket to set + * @param bufsiz requested kernel buffer size + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz); + +/** + * Get the maximum receive buffer size. + * + * @param socket the socket to set + * @param bufsiz the returned kernel buffer size + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz); + +/** + * Enable sending of keep-alive messages on connection-oriented sockets + * + * @param socket the socket to set the flag + * @param is_enabled 1 to enable or 0 to disable + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled); + +/** + * Get if sending of keep-alive messages on connection-oriented sockets is + * enabled + * + * @param socket the socket to check + * @param is_enabled 1 if enabled or 0 if disabled + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled); + /** * Set the send timeout until reporting an error * @@ -575,6 +642,341 @@ os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us); int os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us); +/** + * Enable re-use of local addresses + * + * @param socket the socket to set + * @param is_enabled 1 to enable or 0 to disable + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled); + +/** + * Get whether re-use of local addresses is enabled + * + * @param socket the socket to set + * @param is_enabled 1 for enabled or 0 for disabled + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled); + +/** + * Enable re-use of local ports + * + * @param socket the socket to set + * @param is_enabled 1 to enable or 0 to disable + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled); + +/** + * Get whether re-use of local ports is enabled + * + * @param socket the socket to set + * @param is_enabled 1 for enabled or 0 for disabled + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled); + +/** + * Set the linger options for the given socket + * + * @param socket the socket to set + * @param is_enabled whether linger is enabled + * @param linger_s linger time (seconds) + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s); + +/** + * Get the linger options for the given socket + * + * @param socket the socket to get + * @param is_enabled whether linger is enabled + * @param linger_s linger time (seconds) + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s); + +/** + * Set no delay TCP + * If set, disable the Nagle algorithm. + * This means that segments are always sent as soon as possible, + * even if there is only a small amount of data + * + * @param socket the socket to set the flag + * @param is_enabled 1 to enable or 0 to disable + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled); + +/** + * Get no delay TCP + * If set, disable the Nagle algorithm. + * This means that segments are always sent as soon as possible, + * even if there is only a small amount of data + * + * @param socket the socket to check + * @param is_enabled 1 if enabled or 0 if disabled + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled); + +/** + * Enable/Disable tcp quickack mode + * In quickack mode, acks are sent immediately, rather than delayed if needed in + * accordance to normal TCP operation + * + * @param socket the socket to set the flag + * @param is_enabled 1 to enable or 0 to disable + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled); + +/** + * Enable/Disable tcp quickack mode + * In quickack mode, acks are sent immediately, rather than delayed if needed in + * accordance to normal TCP operation + * + * @param socket the socket to check + * @param is_enabled 1 if enabled or 0 if disabled + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled); + +/** + * Set the time the connection needs to remain idle before sending keepalive + * probes + * + * @param socket the socket to set + * @param time_s seconds until keepalive probes are sent + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32_t time_s); + +/** + * Gets the time the connection needs to remain idle before sending keepalive + * probes + * + * @param socket the socket to check + * @param time_s seconds until keepalive probes are sent + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32_t *time_s); + +/** + * Set the time between individual keepalive probes + * + * @param socket the socket to set + * @param time_us seconds between individual keepalive probes + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32_t time_s); + +/** + * Get the time between individual keepalive probes + * + * @param socket the socket to get + * @param time_s seconds between individual keepalive probes + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32_t *time_s); + +/** + * Set use of TCP Fast Open + * + * @param socket the socket to set + * @param is_enabled 1 to enable or 0 to disable + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled); + +/** + * Get whether use of TCP Fast Open is enabled + * + * @param socket the socket to get + * @param is_enabled 1 to enabled or 0 to disabled + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled); + +/** + * Set enable or disable IPv4 or IPv6 multicast loopback. + * + * @param socket the socket to set + * @param ipv6 true to set ipv6 loopback or false for ipv4 + * @param is_enabled 1 to enable or 0 to disable + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled); + +/** + * Get enable or disable IPv4 or IPv6 multicast loopback. + * + * @param socket the socket to check + * @param ipv6 true to set ipv6 loopback or false for ipv4 + * @param is_enabled 1 for enabled or 0 for disabled + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, + bool *is_enabled); + +/** + * Add membership to a group + * + * @param socket the socket to add membership to + * @param imr_multiaddr the group multicast address (IPv4 or IPv6) + * @param imr_interface the interface to join on + * @param is_ipv6 whether the imr_multiaddr is IPv4 or IPv6 (true for IPv6) + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_ip_add_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6); + +/** + * Drop membership of a group + * + * @param socket the socket to drop membership to + * @param imr_multiaddr the group multicast address (IPv4 or IPv6) + * @param imr_interface the interface to join on + * @param is_ipv6 whether the imr_multiaddr is IPv4 or IPv6 (true for IPv6) + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_ip_drop_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6); + +/** + * Set the current time-to-live field that is + * used in every packet sent from this socket. + * @param socket the socket to set the flag + * @param ttl_s time to live (seconds) + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s); + +/** + * Retrieve the current time-to-live field that is + * used in every packet sent from this socket. + * @param socket the socket to set the flag + * @param ttl_s time to live (seconds) + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s); + +/** + * Set the time-to-live value of outgoing multicast + * packets for this socket + * @param socket the socket to set the flag + * @param ttl_s time to live (seconds) + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s); + +/** + * Read the time-to-live value of outgoing multicast + * packets for this socket + * @param socket the socket to set the flag + * @param ttl_s time to live (seconds) + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s); + +/** + * Restrict to sending and receiving IPv6 packets only + * + * @param socket the socket to set + * @param is_enabled 1 to enable or 0 to disable + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled); + +/** + * Get whether only sending and receiving IPv6 packets + * + * @param socket the socket to check + * @param is_enabled 1 for enabled or 0 for disabled + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled); + +/** + * Set whether broadcast is enabled + * When enabled, datagram sockets are allowed + * to send packets to a broadcast address. + * + * @param socket the socket to set the flag + * @param is_enabled 1 to enable or 0 to disable + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_set_broadcast(bh_socket_t socket, bool is_enabled); + +/** + * Get whether broadcast is enabled + * When enabled, datagram sockets are allowed + * to send packets to a broadcast address. + * + * @param socket the socket to check + * @param is_enabled 1 if enabled or 0 if disabled + * + * @return 0 if success, -1 otherwise + */ +int +os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/linux-sgx/sgx_socket.c b/core/shared/platform/linux-sgx/sgx_socket.c index b2979592f..2911cd3c5 100644 --- a/core/shared/platform/linux-sgx/sgx_socket.c +++ b/core/shared/platform/linux-sgx/sgx_socket.c @@ -760,4 +760,280 @@ os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us) return BHT_ERROR; } +int +os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_add_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_drop_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ipv6_only(bh_socket_t socket, bool option) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ipv6_only(bh_socket_t socket, bool *option) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + #endif diff --git a/core/shared/platform/linux-sgx/sgx_socket.h b/core/shared/platform/linux-sgx/sgx_socket.h index adb129675..6339b15d7 100644 --- a/core/shared/platform/linux-sgx/sgx_socket.h +++ b/core/shared/platform/linux-sgx/sgx_socket.h @@ -46,7 +46,7 @@ extern "C" { #define SHUT_RDWR 2 /* Address families. */ -#define AF_INET 2 /* IP protocol family. */ +#define AF_INET 2 /* IP protocol family. */ #define AF_INET6 10 /* IP version 6. */ /* Standard well-defined IP protocols. */ diff --git a/core/shared/platform/windows/win_socket.c b/core/shared/platform/windows/win_socket.c index abd2f376d..9a1c7a3c9 100644 --- a/core/shared/platform/windows/win_socket.c +++ b/core/shared/platform/windows/win_socket.c @@ -263,4 +263,279 @@ os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr) errno = ENOSYS; return BHT_ERROR; -} \ No newline at end of file +} + +int +os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_add_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_drop_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ipv6_only(bh_socket_t socket, bool option) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ipv6_only(bh_socket_t socket, bool *option) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + return BHT_ERROR; +} diff --git a/samples/socket-api/README.md b/samples/socket-api/README.md index 3cd5d0800..5260e851f 100644 --- a/samples/socket-api/README.md +++ b/samples/socket-api/README.md @@ -87,12 +87,15 @@ Data: $ ./iwasm ./socket_opts.wasm ``` -The output is: +The output describes the different socket options that are set & retrieved, like so: ```bash -[Client] Create socket -recv_timeout is expected -send_timeout is expected -[Client] Close socket +[Client] Create TCP socket +[Client] Create UDP socket +[Client] Create UDP IPv6 socket +SO_RCVTIMEO tv_sec is expected +SO_RCVTIMEO tv_usec is expected +... +[Client] Close sockets ``` Refer to [socket api document](../../doc/socket_api.md) for more details. diff --git a/samples/socket-api/wasm-src/socket_opts.c b/samples/socket-api/wasm-src/socket_opts.c index f33078034..3078c0b36 100644 --- a/samples/socket-api/wasm-src/socket_opts.c +++ b/samples/socket-api/wasm-src/socket_opts.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include #include #include @@ -12,6 +16,7 @@ } \ else { \ printf("%s is unexpected\n", OPTION); \ + perror("assertion failed"); \ return EXIT_FAILURE; \ } @@ -22,35 +27,236 @@ to_timeval(time_t tv_sec, suseconds_t tv_usec) return tv; } +int +set_and_get_bool_opt(int socket_fd, int level, int optname, int val) +{ + int bool_opt = val; + socklen_t opt_len = sizeof(bool_opt); + setsockopt(socket_fd, level, optname, &bool_opt, sizeof(bool_opt)); + bool_opt = !bool_opt; + getsockopt(socket_fd, level, optname, &bool_opt, &opt_len); + return bool_opt; +} + int main(int argc, char *argv[]) { - int socket_fd = 0; + int tcp_socket_fd = 0; + int udp_socket_fd = 0; + int udp_ipv6_socket_fd = 0; struct timeval tv; - socklen_t tv_len = sizeof(tv); + socklen_t opt_len; + int buf_len; + int result; + struct linger linger_opt; + uint32_t time_s; + struct ip_mreq mcast; + struct ipv6_mreq mcast_ipv6; + unsigned char ttl; - printf("[Client] Create socket\n"); - socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd == -1) { + printf("[Client] Create TCP socket\n"); + tcp_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (tcp_socket_fd == -1) { perror("Create socket failed"); return EXIT_FAILURE; } + printf("[Client] Create UDP socket\n"); + udp_socket_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (udp_socket_fd == -1) { + perror("Create socket failed"); + return EXIT_FAILURE; + } + + printf("[Client] Create UDP IPv6 socket\n"); + udp_ipv6_socket_fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (udp_ipv6_socket_fd == -1) { + perror("Create socket failed"); + return EXIT_FAILURE; + } + + // SO_RCVTIMEO tv = to_timeval(123, 1000); - setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + setsockopt(tcp_socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); tv = to_timeval(0, 0); - getsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &tv_len); + opt_len = sizeof(tv); + getsockopt(tcp_socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &opt_len); OPTION_ASSERT(tv.tv_sec, 123, "SO_RCVTIMEO tv_sec"); OPTION_ASSERT(tv.tv_usec, 1000, "SO_RCVTIMEO tv_usec"); + // SO_SNDTIMEO tv = to_timeval(456, 2000); - setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + setsockopt(tcp_socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); tv = to_timeval(0, 0); - getsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &tv_len); + opt_len = sizeof(tv); + getsockopt(tcp_socket_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &opt_len); OPTION_ASSERT(tv.tv_sec, 456, "SO_SNDTIMEO tv_sec"); OPTION_ASSERT(tv.tv_usec, 2000, "SO_SNDTIMEO tv_usec"); - printf("[Client] Close socket\n"); - close(socket_fd); + // SO_SNDBUF + buf_len = 8192; + setsockopt(tcp_socket_fd, SOL_SOCKET, SO_SNDBUF, &buf_len, sizeof(buf_len)); + buf_len = 0; + opt_len = sizeof(buf_len); + getsockopt(tcp_socket_fd, SOL_SOCKET, SO_SNDBUF, &buf_len, &opt_len); + OPTION_ASSERT(buf_len, 16384, "SO_SNDBUF buf_len"); + + // SO_RCVBUF + buf_len = 4096; + setsockopt(tcp_socket_fd, SOL_SOCKET, SO_RCVBUF, &buf_len, sizeof(buf_len)); + buf_len = 0; + opt_len = sizeof(buf_len); + getsockopt(tcp_socket_fd, SOL_SOCKET, SO_RCVBUF, &buf_len, &opt_len); + OPTION_ASSERT(buf_len, 8192, "SO_RCVBUF buf_len"); + + // SO_KEEPALIVE + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, SOL_SOCKET, SO_KEEPALIVE, 1), 1, + "SO_KEEPALIVE enabled"); + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, SOL_SOCKET, SO_KEEPALIVE, 0), 0, + "SO_KEEPALIVE disabled"); + + // SO_REUSEADDR + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, SOL_SOCKET, SO_REUSEADDR, 1), 1, + "SO_REUSEADDR enabled"); + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, SOL_SOCKET, SO_REUSEADDR, 0), 0, + "SO_REUSEADDR disabled"); + + // SO_REUSEPORT + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, SOL_SOCKET, SO_REUSEPORT, 1), 1, + "SO_REUSEPORT enabled"); + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, SOL_SOCKET, SO_REUSEPORT, 0), 0, + "SO_REUSEPORT disabled"); + + // SO_LINGER + linger_opt.l_onoff = 1; + linger_opt.l_linger = 10; + setsockopt(tcp_socket_fd, SOL_SOCKET, SO_LINGER, &linger_opt, + sizeof(linger_opt)); + linger_opt.l_onoff = 0; + linger_opt.l_linger = 0; + opt_len = sizeof(linger_opt); + getsockopt(tcp_socket_fd, SOL_SOCKET, SO_LINGER, &linger_opt, &opt_len); + OPTION_ASSERT(linger_opt.l_onoff, 1, "SO_LINGER l_onoff"); + OPTION_ASSERT(linger_opt.l_linger, 10, "SO_LINGER l_linger"); + + // SO_BROADCAST + OPTION_ASSERT( + set_and_get_bool_opt(udp_socket_fd, SOL_SOCKET, SO_BROADCAST, 1), 1, + "SO_BROADCAST enabled"); + OPTION_ASSERT( + set_and_get_bool_opt(udp_socket_fd, SOL_SOCKET, SO_BROADCAST, 0), 0, + "SO_BROADCAST disabled"); + + // TCP_KEEPIDLE + time_s = 16; + setsockopt(tcp_socket_fd, IPPROTO_TCP, TCP_KEEPIDLE, &time_s, + sizeof(time_s)); + time_s = 0; + opt_len = sizeof(time_s); + getsockopt(tcp_socket_fd, IPPROTO_TCP, TCP_KEEPIDLE, &time_s, &opt_len); + OPTION_ASSERT(time_s, 16, "TCP_KEEPIDLE"); + + // TCP_KEEPINTVL + time_s = 8; + setsockopt(tcp_socket_fd, IPPROTO_TCP, TCP_KEEPINTVL, &time_s, + sizeof(time_s)); + time_s = 0; + opt_len = sizeof(time_s); + getsockopt(tcp_socket_fd, IPPROTO_TCP, TCP_KEEPINTVL, &time_s, &opt_len); + OPTION_ASSERT(time_s, 8, "TCP_KEEPINTVL"); + + // TCP_FASTOPEN_CONNECT + OPTION_ASSERT(set_and_get_bool_opt(tcp_socket_fd, IPPROTO_TCP, + TCP_FASTOPEN_CONNECT, 1), + 1, "TCP_FASTOPEN_CONNECT enabled"); + OPTION_ASSERT(set_and_get_bool_opt(tcp_socket_fd, IPPROTO_TCP, + TCP_FASTOPEN_CONNECT, 0), + 0, "TCP_FASTOPEN_CONNECT disabled"); + + // TCP_NODELAY + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, IPPROTO_TCP, TCP_NODELAY, 1), 1, + "TCP_NODELAY enabled"); + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, IPPROTO_TCP, TCP_NODELAY, 0), 0, + "TCP_NODELAY disabled"); + + // TCP_QUICKACK + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, IPPROTO_TCP, TCP_QUICKACK, 1), 1, + "TCP_QUICKACK enabled"); + OPTION_ASSERT( + set_and_get_bool_opt(tcp_socket_fd, IPPROTO_TCP, TCP_QUICKACK, 0), 0, + "TCP_QUICKACK disabled"); + + // IP_TTL + ttl = 8; + setsockopt(tcp_socket_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); + ttl = 0; + opt_len = sizeof(ttl); + getsockopt(tcp_socket_fd, IPPROTO_IP, IP_TTL, &ttl, &opt_len); + OPTION_ASSERT(ttl, 8, "IP_TTL"); + + // IPV6_V6ONLY + OPTION_ASSERT( + set_and_get_bool_opt(udp_ipv6_socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, 1), + 1, "IPV6_V6ONLY enabled"); + OPTION_ASSERT( + set_and_get_bool_opt(udp_ipv6_socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, 0), + 0, "IPV6_V6ONLY disabled"); + + // IP_MULTICAST_LOOP + OPTION_ASSERT( + set_and_get_bool_opt(udp_socket_fd, IPPROTO_IP, IP_MULTICAST_LOOP, 1), + 1, "IP_MULTICAST_LOOP enabled"); + OPTION_ASSERT( + set_and_get_bool_opt(udp_socket_fd, IPPROTO_IP, IP_MULTICAST_LOOP, 0), + 0, "IP_MULTICAST_LOOP disabled"); + + // IP_ADD_MEMBERSHIP + mcast.imr_multiaddr.s_addr = 16777440; + mcast.imr_interface.s_addr = htonl(INADDR_ANY); + result = setsockopt(udp_socket_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, + sizeof(mcast)); + OPTION_ASSERT(result, 0, "IP_ADD_MEMBERSHIP"); + + // IP_DROP_MEMBERSHIP + result = setsockopt(udp_socket_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mcast, + sizeof(mcast)); + OPTION_ASSERT(result, 0, "IP_DROP_MEMBERSHIP"); + + // IP_MULTICAST_TTL + ttl = 8; + setsockopt(udp_socket_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); + ttl = 0; + opt_len = sizeof(ttl); + getsockopt(udp_socket_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, &opt_len); + OPTION_ASSERT(ttl, 8, "IP_MULTICAST_TTL"); + + // IPV6_MULTICAST_LOOP + OPTION_ASSERT(set_and_get_bool_opt(udp_ipv6_socket_fd, IPPROTO_IPV6, + IPV6_MULTICAST_LOOP, 1), + 1, "IPV6_MULTICAST_LOOP enabled"); + OPTION_ASSERT(set_and_get_bool_opt(udp_ipv6_socket_fd, IPPROTO_IPV6, + IPV6_MULTICAST_LOOP, 0), + 0, "IPV6_MULTICAST_LOOP disabled"); + + // IPV6_JOIN_GROUP + setsockopt(udp_ipv6_socket_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mcast_ipv6, + sizeof(mcast_ipv6)); + + // IPV6_LEAVE_GROUP + setsockopt(udp_ipv6_socket_fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mcast_ipv6, + sizeof(mcast_ipv6)); + + printf("[Client] Close sockets\n"); + close(tcp_socket_fd); + close(udp_socket_fd); return EXIT_SUCCESS; }