Merge dev/socket into main (#1393)

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

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

View File

@ -7,29 +7,123 @@
#include "platform_api_extension.h"
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
static void
textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr_in *out)
static bool
textual_addr_to_sockaddr(const char *textual, int port, struct sockaddr *out,
socklen_t *out_len)
{
struct sockaddr_in *v4;
struct sockaddr_in6 *v6;
assert(textual);
out->sin_family = AF_INET;
out->sin_port = htons(port);
out->sin_addr.s_addr = inet_addr(textual);
v4 = (struct sockaddr_in *)out;
if (inet_pton(AF_INET, textual, &v4->sin_addr.s_addr) == 1) {
v4->sin_family = AF_INET;
v4->sin_port = htons(port);
*out_len = sizeof(struct sockaddr_in);
return true;
}
v6 = (struct sockaddr_in6 *)out;
if (inet_pton(AF_INET6, textual, &v6->sin6_addr.s6_addr) == 1) {
v6->sin6_family = AF_INET6;
v6->sin6_port = htons(port);
*out_len = sizeof(struct sockaddr_in6);
return true;
}
return false;
}
static int
sockaddr_to_bh_sockaddr(const struct sockaddr *sockaddr, socklen_t socklen,
bh_sockaddr_t *bh_sockaddr)
{
switch (sockaddr->sa_family) {
case AF_INET:
{
struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
assert(socklen >= sizeof(struct sockaddr_in));
bh_sockaddr->port = ntohs(addr->sin_port);
bh_sockaddr->addr_bufer.ipv4 = ntohl(addr->sin_addr.s_addr);
bh_sockaddr->is_ipv4 = true;
return BHT_OK;
}
case AF_INET6:
{
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr;
size_t i;
assert(socklen >= sizeof(struct sockaddr_in6));
bh_sockaddr->port = ntohs(addr->sin6_port);
for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6)
/ sizeof(bh_sockaddr->addr_bufer.ipv6[0]);
i++) {
uint16 part_addr = addr->sin6_addr.s6_addr[i * 2]
| (addr->sin6_addr.s6_addr[i * 2 + 1] << 8);
bh_sockaddr->addr_bufer.ipv6[i] = ntohs(part_addr);
}
bh_sockaddr->is_ipv4 = false;
return BHT_OK;
}
default:
errno = EAFNOSUPPORT;
return BHT_ERROR;
}
}
static void
bh_sockaddr_to_sockaddr(const bh_sockaddr_t *bh_sockaddr,
struct sockaddr_storage *sockaddr, socklen_t *socklen)
{
if (bh_sockaddr->is_ipv4) {
struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr;
addr->sin_port = htons(bh_sockaddr->port);
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = htonl(bh_sockaddr->addr_bufer.ipv4);
*socklen = sizeof(*addr);
}
else {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)sockaddr;
size_t i;
addr->sin6_port = htons(bh_sockaddr->port);
addr->sin6_family = AF_INET6;
for (i = 0; i < sizeof(bh_sockaddr->addr_bufer.ipv6)
/ sizeof(bh_sockaddr->addr_bufer.ipv6[0]);
i++) {
uint16 part_addr = htons(bh_sockaddr->addr_bufer.ipv6[i]);
addr->sin6_addr.s6_addr[i * 2] = 0xff & part_addr;
addr->sin6_addr.s6_addr[i * 2 + 1] = (0xff00 & part_addr) >> 8;
}
*socklen = sizeof(*addr);
}
}
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
{
int af = is_ipv4 ? AF_INET : AF_INET6;
if (!sock) {
return BHT_ERROR;
}
if (1 == tcp_or_udp) {
*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (is_tcp) {
*sock = socket(af, SOCK_STREAM, IPPROTO_TCP);
}
else if (0 == tcp_or_udp) {
*sock = socket(AF_INET, SOCK_DGRAM, 0);
else {
*sock = socket(af, SOCK_DGRAM, 0);
}
return (*sock == -1) ? BHT_ERROR : BHT_OK;
@ -38,7 +132,7 @@ os_socket_create(bh_socket_t *sock, int tcp_or_udp)
int
os_socket_bind(bh_socket_t socket, const char *host, int *port)
{
struct sockaddr_in addr;
struct sockaddr_storage addr = { 0 };
struct linger ling;
socklen_t socklen;
int ret;
@ -59,11 +153,12 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port)
goto fail;
}
addr.sin_addr.s_addr = inet_addr(host);
addr.sin_port = htons(*port);
addr.sin_family = AF_INET;
if (!textual_addr_to_sockaddr(host, *port, (struct sockaddr *)&addr,
&socklen)) {
goto fail;
}
ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr));
ret = bind(socket, (struct sockaddr *)&addr, socklen);
if (ret < 0) {
goto fail;
}
@ -73,7 +168,9 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port)
goto fail;
}
*port = ntohs(addr.sin_port);
*port = ntohs(addr.ss_family == AF_INET
? ((struct sockaddr_in *)&addr)->sin_port
: ((struct sockaddr_in6 *)&addr)->sin6_port);
return BHT_OK;
@ -114,7 +211,7 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
struct sockaddr addr_tmp;
unsigned int len = sizeof(struct sockaddr);
*sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len);
*sock = accept(server_sock, &addr_tmp, &len);
if (*sock < 0) {
return BHT_ERROR;
@ -126,11 +223,14 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
int
os_socket_connect(bh_socket_t socket, const char *addr, int port)
{
struct sockaddr_in addr_in = { 0 };
socklen_t addr_len = sizeof(struct sockaddr_in);
struct sockaddr_storage addr_in = { 0 };
socklen_t addr_len;
int ret = 0;
textual_addr_to_sockaddr(addr, port, &addr_in);
if (!textual_addr_to_sockaddr(addr, port, (struct sockaddr *)&addr_in,
&addr_len)) {
return BHT_ERROR;
}
ret = connect(socket, (struct sockaddr *)&addr_in, addr_len);
if (ret == -1) {
@ -146,12 +246,48 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
return recv(socket, buf, len, 0);
}
int
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
bh_sockaddr_t *src_addr)
{
struct sockaddr_storage sock_addr = { 0 };
socklen_t socklen = sizeof(sock_addr);
int ret;
ret = recvfrom(socket, buf, len, flags, (struct sockaddr *)&sock_addr,
&socklen);
if (ret < 0) {
return ret;
}
if (src_addr) {
sockaddr_to_bh_sockaddr((struct sockaddr *)&sock_addr, socklen,
src_addr);
}
return ret;
}
int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
{
return send(socket, buf, len, 0);
}
int
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
int flags, const bh_sockaddr_t *dest_addr)
{
struct sockaddr_storage sock_addr = { 0 };
socklen_t socklen = 0;
bh_sockaddr_to_sockaddr(dest_addr, &sock_addr, &socklen);
return sendto(socket, buf, len, 0, (const struct sockaddr *)&sock_addr,
socklen);
}
int
os_socket_close(bh_socket_t socket)
{
@ -167,12 +303,668 @@ os_socket_shutdown(bh_socket_t socket)
}
int
os_socket_inet_network(const char *cp, uint32 *out)
os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
{
if (!cp)
return BHT_ERROR;
/* Note: ntohl(INADDR_NONE) == INADDR_NONE */
*out = ntohl(inet_addr(cp));
if (is_ipv4) {
if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
return BHT_ERROR;
}
/* Note: ntohl(INADDR_NONE) == INADDR_NONE */
out->ipv4 = ntohl(out->ipv4);
}
else {
if (inet_pton(AF_INET6, cp, out->ipv6) != 1) {
return BHT_ERROR;
}
for (int i = 0; i < 8; i++) {
out->ipv6[i] = ntohs(out->ipv6[i]);
}
}
return BHT_OK;
}
static int
getaddrinfo_error_to_errno(int error)
{
switch (error) {
case EAI_AGAIN:
return EAGAIN;
case EAI_FAIL:
return EFAULT;
case EAI_MEMORY:
return ENOMEM;
case EAI_SYSTEM:
return errno;
default:
return EINVAL;
}
}
static int
is_addrinfo_supported(struct addrinfo *info)
{
return
// Allow only IPv4 and IPv6
(info->ai_family == AF_INET || info->ai_family == AF_INET6)
// Allow only UDP and TCP
&& (info->ai_socktype == SOCK_DGRAM || info->ai_socktype == SOCK_STREAM)
&& (info->ai_protocol == IPPROTO_TCP
|| info->ai_protocol == IPPROTO_UDP);
}
int
os_socket_addr_resolve(const char *host, const char *service,
uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
bh_addr_info_t *addr_info, size_t addr_info_size,
size_t *max_info_size)
{
struct addrinfo hints = { 0 }, *res, *result;
int hints_enabled = hint_is_tcp || hint_is_ipv4;
int ret;
size_t pos = 0;
if (hints_enabled) {
if (hint_is_ipv4) {
hints.ai_family = *hint_is_ipv4 ? AF_INET : AF_INET6;
}
if (hint_is_tcp) {
hints.ai_socktype = *hint_is_tcp ? SOCK_STREAM : SOCK_DGRAM;
}
}
ret = getaddrinfo(host, strlen(service) == 0 ? NULL : service,
hints_enabled ? &hints : NULL, &result);
if (ret != BHT_OK) {
errno = getaddrinfo_error_to_errno(ret);
return BHT_ERROR;
}
res = result;
while (res) {
if (addr_info_size > pos) {
if (!is_addrinfo_supported(res)) {
res = res->ai_next;
continue;
}
sockaddr_to_bh_sockaddr(res->ai_addr, sizeof(struct sockaddr_in),
&addr_info[pos].sockaddr);
addr_info[pos].is_tcp = res->ai_socktype == SOCK_STREAM;
}
pos++;
res = res->ai_next;
}
*max_info_size = pos;
freeaddrinfo(result);
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(is_enabled);
assert(linger_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)
{
struct timeval tv;
tv.tv_sec = timeout_us / 1000000UL;
tv.tv_usec = timeout_us % 1000000UL;
if (setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) != 0) {
return BHT_ERROR;
}
return BHT_OK;
}
int
os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us)
{
struct timeval tv;
socklen_t tv_len = sizeof(tv);
if (getsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, &tv_len) != 0) {
return BHT_ERROR;
}
*timeout_us = (tv.tv_sec * 1000000UL) + tv.tv_usec;
return BHT_OK;
}
int
os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us)
{
struct timeval tv;
tv.tv_sec = timeout_us / 1000000UL;
tv.tv_usec = timeout_us % 1000000UL;
if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) {
return BHT_ERROR;
}
return BHT_OK;
}
int
os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
{
struct timeval tv;
socklen_t tv_len = sizeof(tv);
if (getsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, &tv_len) != 0) {
return BHT_ERROR;
}
*timeout_us = (tv.tv_sec * 1000000UL) + tv.tv_usec;
return BHT_OK;
}
int
os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
{
struct sockaddr_storage addr_storage = { 0 };
socklen_t addr_len = sizeof(addr_storage);
int ret;
ret = getsockname(socket, (struct sockaddr *)&addr_storage, &addr_len);
if (ret != BHT_OK) {
return BHT_ERROR;
}
return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, addr_len,
sockaddr);
}
int
os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
{
struct sockaddr_storage addr_storage = { 0 };
socklen_t addr_len = sizeof(addr_storage);
int ret;
ret = getpeername(socket, (struct sockaddr *)&addr_storage, &addr_len);
if (ret != BHT_OK) {
return BHT_ERROR;
}
return sockaddr_to_bh_sockaddr((struct sockaddr *)&addr_storage, addr_len,
sockaddr);
}

View File

@ -292,16 +292,29 @@ os_sem_unlink(const char *name);
* need to implement these APIs
*/
typedef union {
uint32 ipv4;
uint16 ipv6[8];
uint8 data[1];
} bh_ip_addr_buffer_t;
typedef struct {
bh_ip_addr_buffer_t addr_bufer;
uint16 port;
bool is_ipv4;
} bh_sockaddr_t;
/**
* Create a socket
*
* @param sock [OUTPUT] the pointer of socket
* @param tcp_or_udp 1 for tcp, 0 for udp
* @param is_ipv4 true for IPv4, false for IPv6
* @param is_tcp true for tcp, false for udp
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp);
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp);
/**
* Assign the address and port to the socket
@ -380,6 +393,22 @@ os_socket_connect(bh_socket_t socket, const char *addr, int port);
int
os_socket_recv(bh_socket_t socket, void *buf, unsigned int len);
/**
* Blocking receive message from a socket.
*
* @param socket the socket to send message
* @param buf the buffer to store the data
* @param len length of the buffer, this API does not guarantee that
* [len] bytes are received
* @param flags control the operation
* @param src_addr source address
*
* @return number of bytes sent if success, -1 otherwise
*/
int
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
bh_sockaddr_t *src_addr);
/**
* Blocking send message on a socket
*
@ -392,6 +421,21 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len);
int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len);
/**
* Blocking send message on a socket to the target address
*
* @param socket the socket to send message
* @param buf the buffer of data to be sent
* @param len length of the buffer
* @param flags control the operation
* @param dest_addr target address
*
* @return number of bytes sent if success, -1 otherwise
*/
int
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
int flags, const bh_sockaddr_t *dest_addr);
/**
* Close a socket
*
@ -416,13 +460,522 @@ os_socket_shutdown(bh_socket_t socket);
* converts cp into a number in host byte order suitable for use as
* an Internet network address
*
* @param cp a string in IPv4 numbers-and-dots notation
* @param is_ipv4 a flag that indicates whether the string is an IPv4 or
* IPv6 address
*
* @return On success, the converted address is returned.
* @param cp a string in IPv4 numbers-and-dots notation or IPv6
* numbers-and-colons notation
*
* @param out an output buffer to store binary address
*
* @return On success, the function returns 0.
* If the input is invalid, -1 is returned
*/
int
os_socket_inet_network(const char *cp, uint32 *out);
os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out);
typedef struct {
bh_sockaddr_t sockaddr;
uint8_t is_tcp;
} bh_addr_info_t;
/**
* Resolve a host a hostname and a service to one or more IP addresses
*
* @param host a host to resolve
*
* @param service a service to find a port for
*
* @param hint_is_tcp an optional flag that determines a preferred socket type
(TCP or UDP).
*
* @param hint_is_ipv4 an optional flag that determines a preferred address
family (IPv4 or IPv6)
*
* @param addr_info a buffer for resolved addresses
*
* @param addr_info_size a size of the buffer for resolved addresses
* @param max_info_size a maximum number of addresses available (can be bigger
or smaller than buffer size)
* @return On success, the function returns 0; otherwise, it returns -1
*/
int
os_socket_addr_resolve(const char *host, const char *service,
uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
bh_addr_info_t *addr_info, size_t addr_info_size,
size_t *max_info_size);
/**
* Returns an binary address and a port of the local socket
*
* @param socket the local socket
*
* @param sockaddr a buffer for storing the address
*
* @return On success, returns 0; otherwise, it returns -1.
*/
int
os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr);
/**
* Returns an binary address and a port of the remote socket
*
* @param socket the remote socket
*
* @param sockaddr a buffer for storing the address
*
* @return On success, returns 0; otherwise, it returns -1.
*/
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
*
* @param socket the socket to set
* @param time_us microseconds until timeout
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us);
/**
* Get the send timeout until reporting an error
*
* @param socket the socket to set
* @param time_us the returned microseconds until timeout
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us);
/**
* Set the recv timeout until reporting an error
*
* @param socket the socket to set
* @param time_us microseconds until timeout
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us);
/**
* Get the recv timeout until reporting an error
*
* @param socket the socket to set
* @param time_us the returned microseconds until timeout
*
* @return 0 if success, -1 otherwise
*/
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
}

View File

@ -4,6 +4,7 @@
*/
#include "platform_api_vmcore.h"
#include "platform_api_extension.h"
#ifndef SGX_DISABLE_WASI
@ -91,7 +92,7 @@ swap16(uint8 *pData)
*(pData + 1) = value;
}
static uint32
uint32
htonl(uint32 value)
{
uint32 ret;
@ -104,13 +105,13 @@ htonl(uint32 value)
return value;
}
static uint32
uint32
ntohl(uint32 value)
{
return htonl(value);
}
static uint16
uint16
htons(uint16 value)
{
uint16 ret;
@ -131,57 +132,96 @@ ntohs(uint16 value)
/* Coming from musl, under MIT license */
static int
__inet_aton(const char *s0, struct in_addr *dest)
hexval(unsigned c)
{
const char *s = s0;
unsigned char *d = (void *)dest;
unsigned long a[4] = { 0 };
char *z;
int i;
for (i = 0; i < 4; i++) {
a[i] = strtoul(s, &z, 0);
if (z == s || (*z && *z != '.') || !isdigit(*s))
return 0;
if (!*z)
break;
s = z + 1;
}
if (i == 4)
return 0;
switch (i) {
case 0:
a[1] = a[0] & 0xffffff;
a[0] >>= 24;
case 1:
a[2] = a[1] & 0xffff;
a[1] >>= 16;
case 2:
a[3] = a[2] & 0xff;
a[2] >>= 8;
}
for (i = 0; i < 4; i++) {
if (a[i] > 255)
return 0;
d[i] = a[i];
}
return 1;
if (c - '0' < 10)
return c - '0';
c |= 32;
if (c - 'a' < 6)
return c - 'a' + 10;
return -1;
}
/* Coming from musl, under MIT license */
static int
inet_addr(const char *p)
inet_pton(int af, const char *restrict s, void *restrict a0)
{
struct in_addr a;
if (!__inet_aton(p, &a))
uint16_t ip[8];
unsigned char *a = a0;
int i, j, v, d, brk = -1, need_v4 = 0;
if (af == AF_INET) {
for (i = 0; i < 4; i++) {
for (v = j = 0; j < 3 && isdigit(s[j]); j++)
v = 10 * v + s[j] - '0';
if (j == 0 || (j > 1 && s[0] == '0') || v > 255)
return 0;
a[i] = v;
if (s[j] == 0 && i == 3)
return 1;
if (s[j] != '.')
return 0;
s += j + 1;
}
return 0;
}
else if (af != AF_INET6) {
errno = EAFNOSUPPORT;
return -1;
return a.s_addr;
}
if (*s == ':' && *++s != ':')
return 0;
for (i = 0;; i++) {
if (s[0] == ':' && brk < 0) {
brk = i;
ip[i & 7] = 0;
if (!*++s)
break;
if (i == 7)
return 0;
continue;
}
for (v = j = 0; j < 4 && (d = hexval(s[j])) >= 0; j++)
v = 16 * v + d;
if (j == 0)
return 0;
ip[i & 7] = v;
if (!s[j] && (brk >= 0 || i == 7))
break;
if (i == 7)
return 0;
if (s[j] != ':') {
if (s[j] != '.' || (i < 6 && brk < 0))
return 0;
need_v4 = 1;
i++;
break;
}
s += j + 1;
}
if (brk >= 0) {
memmove(ip + brk + 7 - i, ip + brk, 2 * (i + 1 - brk));
for (j = 0; j < 7 - i; j++)
ip[brk + j] = 0;
}
for (j = 0; j < 8; j++) {
*a++ = ip[j] >> 8;
*a++ = ip[j];
}
if (need_v4 && inet_pton(AF_INET, (void *)s, a - 4) <= 0)
return 0;
return 1;
}
static int
inet_network(const char *p)
inet_addr(const char *p)
{
return ntohl(inet_addr(p));
struct in_addr a;
if (!inet_pton(AF_INET, p, &a))
return -1;
return a.s_addr;
}
/** In-enclave implementation of POSIX functions end **/
@ -527,21 +567,30 @@ os_socket_connect(bh_socket_t socket, const char *addr, int port)
}
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
{
int af;
if (!sock) {
return BHT_ERROR;
}
if (1 == tcp_or_udp) {
if (ocall_socket(sock, AF_INET, SOCK_STREAM, IPPROTO_TCP)
!= SGX_SUCCESS) {
if (is_ipv4) {
af = AF_INET;
}
else {
errno = ENOSYS;
return BHT_ERROR;
}
if (is_tcp) {
if (ocall_socket(sock, af, SOCK_STREAM, IPPROTO_TCP) != SGX_SUCCESS) {
TRACE_OCALL_FAIL();
return -1;
}
}
else if (0 == tcp_or_udp) {
if (ocall_socket(sock, AF_INET, SOCK_DGRAM, 0) != SGX_SUCCESS) {
else {
if (ocall_socket(sock, af, SOCK_DGRAM, 0) != SGX_SUCCESS) {
TRACE_OCALL_FAIL();
return -1;
}
@ -556,12 +605,26 @@ os_socket_create(bh_socket_t *sock, int tcp_or_udp)
}
int
os_socket_inet_network(const char *cp, uint32 *out)
os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
{
if (!cp)
return BHT_ERROR;
*out = inet_network(cp);
if (is_ipv4) {
if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
return BHT_ERROR;
}
/* Note: ntohl(INADDR_NONE) == INADDR_NONE */
out->ipv4 = ntohl(out->ipv4);
}
else {
if (inet_pton(AF_INET6, cp, out->ipv6) != 1) {
return BHT_ERROR;
}
for (int i = 0; i < 8; i++) {
out->ipv6[i] = ntohs(out->ipv6[i]);
}
}
return BHT_OK;
}
@ -598,6 +661,15 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
return ret;
}
int
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
bh_sockaddr_t *src_addr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
{
@ -614,10 +686,354 @@ os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
return ret;
}
int
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
int flags, const bh_sockaddr_t *dest_addr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_shutdown(bh_socket_t socket)
{
return shutdown(socket, O_RDWR);
}
int
os_socket_addr_resolve(const char *host, const char *service,
uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
bh_addr_info_t *addr_info, size_t addr_info_size,
size_t *max_info_size)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
{
errno = ENOSYS;
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

View File

@ -46,7 +46,8 @@ 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. */
#define IPPROTO_TCP 6 /* Transmission Control Protocol. */
@ -95,6 +96,15 @@ struct sockaddr {
char sa_data[14]; /* Address data. */
};
uint32_t
ntohl(uint32_t value);
uint32_t
htonl(uint32_t value);
uint16_t
htons(uint16_t value);
int
socket(int domain, int type, int protocol);

View File

@ -37,17 +37,27 @@ deinit_winsock()
}
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp)
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
{
int af;
if (!sock) {
return BHT_ERROR;
}
if (1 == tcp_or_udp) {
*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (is_ipv4) {
af = AF_INET;
}
else if (0 == tcp_or_udp) {
*sock = socket(AF_INET, SOCK_DGRAM, 0);
else {
errno = ENOSYS;
return BHT_ERROR;
}
if (is_tcp) {
*sock = socket(af, SOCK_STREAM, IPPROTO_TCP);
}
else {
*sock = socket(af, SOCK_DGRAM, 0);
}
return (*sock == -1) ? BHT_ERROR : BHT_OK;
@ -133,12 +143,30 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len)
return recv(socket, buf, len, 0);
}
int
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
bh_sockaddr_t *src_addr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
{
return send(socket, buf, len, 0);
}
int
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
int flags, const bh_sockaddr_t *dest_addr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_close(bh_socket_t socket)
{
@ -154,11 +182,360 @@ os_socket_shutdown(bh_socket_t socket)
}
int
os_socket_inet_network(const char *cp, uint32 *out)
os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
{
if (!cp)
return BHT_ERROR;
*out = inet_addr(cp);
if (is_ipv4) {
if (inet_pton(AF_INET, cp, &out->ipv4) != 1) {
return BHT_ERROR;
}
/* Note: ntohl(INADDR_NONE) == INADDR_NONE */
out->ipv4 = ntohl(out->ipv4);
}
else {
if (inet_pton(AF_INET6, cp, out->ipv6) != 1) {
return BHT_ERROR;
}
for (int i = 0; i < 8; i++) {
out->ipv6[i] = ntohs(out->ipv6[i]);
}
}
return BHT_OK;
}
}
int
os_socket_addr_resolve(const char *host, const char *service,
uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
bh_addr_info_t *addr_info, size_t addr_info_size,
size_t *max_info_size)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
{
errno = ENOSYS;
return BHT_ERROR;
}
int
os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
{
errno = ENOSYS;
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;
}