Skip to content

Commit 838706b

Browse files
committed
Implement sock_addr_local syscall
I also slightly changed the interface - since we already have a `__wasi_addr_t` structure which is an union, there's no need for passing length around - the address buffer will always have the right length (i.e. max of all address families).
1 parent 32c9416 commit 838706b

File tree

10 files changed

+264
-33
lines changed

10 files changed

+264
-33
lines changed

core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ sendmsg(int sockfd, const struct msghdr *msg, int flags);
8888

8989
int
9090
socket(int domain, int type, int protocol);
91+
92+
int
93+
getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
9194
#endif
9295

9396
/**
@@ -115,16 +118,15 @@ __wasi_sock_accept(__wasi_fd_t fd, __wasi_fd_t *fd_new)
115118
* either IP4 or IP6.
116119
*/
117120
int32_t
118-
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1,
119-
int32_t arg2)
121+
__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1)
120122
__attribute__((__import_module__("wasi_snapshot_preview1"),
121123
__import_name__("sock_addr_local")));
122124

123125
static inline __wasi_errno_t
124-
__wasi_sock_addr_local(__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len)
126+
__wasi_sock_addr_local(__wasi_fd_t fd, __wasi_addr_t *addr)
125127
{
126128
return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_local(
127-
(int32_t)fd, (int32_t)buf, (int32_t)buf_len);
129+
(int32_t)fd, (int32_t)addr);
128130
}
129131

130132
/**

core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,34 @@ sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
5353
return ret;
5454
}
5555

56+
static __wasi_errno_t
57+
wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
58+
struct sockaddr *sock_addr, socklen_t *addrlen)
59+
{
60+
switch (wasi_addr->kind) {
61+
case IPv4:
62+
{
63+
struct sockaddr_in sock_addr_in = { 0 };
64+
65+
sock_addr_in.sin_family = AF_INET;
66+
sock_addr_in.sin_addr.s_addr = (wasi_addr->addr.ip4.addr.n3 << 24)
67+
| (wasi_addr->addr.ip4.addr.n2 << 16)
68+
| (wasi_addr->addr.ip4.addr.n1 << 8)
69+
| wasi_addr->addr.ip4.addr.n0;
70+
sock_addr_in.sin_port = htons(wasi_addr->addr.ip4.port);
71+
memcpy(sock_addr, &sock_addr_in, sizeof(sock_addr_in));
72+
73+
*addrlen = sizeof(sock_addr_in);
74+
} break;
75+
case IPv6:
76+
// TODO: IPV6
77+
return __WASI_ERRNO_AFNOSUPPORT;
78+
default:
79+
return __WASI_ERRNO_AFNOSUPPORT;
80+
}
81+
return __WASI_ERRNO_SUCCESS;
82+
}
83+
5684
static __wasi_errno_t
5785
sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
5886
{
@@ -65,28 +93,7 @@ sock_addr_remote(__wasi_fd_t fd, struct sockaddr *sock_addr, socklen_t *addrlen)
6593
return error;
6694
}
6795

68-
if (IPv4 == wasi_addr.kind) {
69-
struct sockaddr_in sock_addr_in = { 0 };
70-
71-
sock_addr_in.sin_family = AF_INET;
72-
sock_addr_in.sin_addr.s_addr = (wasi_addr.addr.ip4.addr.n3 << 24)
73-
| (wasi_addr.addr.ip4.addr.n2 << 16)
74-
| (wasi_addr.addr.ip4.addr.n1 << 8)
75-
| wasi_addr.addr.ip4.addr.n0;
76-
sock_addr_in.sin_port = htons(wasi_addr.addr.ip4.port);
77-
memcpy(sock_addr, &sock_addr_in, sizeof(sock_addr_in));
78-
79-
*addrlen = sizeof(sock_addr_in);
80-
}
81-
else if (IPv6 == wasi_addr.kind) {
82-
// TODO: IPV6
83-
return __WASI_ERRNO_AFNOSUPPORT;
84-
}
85-
else {
86-
return __WASI_ERRNO_AFNOSUPPORT;
87-
}
88-
89-
return __WASI_ERRNO_SUCCESS;
96+
return wasi_addr_to_sockaddr(&wasi_addr, sock_addr, addrlen);
9097
}
9198

9299
int
@@ -256,3 +263,18 @@ socket(int domain, int type, int protocol)
256263

257264
return sockfd;
258265
}
266+
267+
int
268+
getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
269+
{
270+
__wasi_addr_t wasi_addr = { 0 };
271+
__wasi_errno_t error;
272+
273+
error = __wasi_sock_addr_local(sockfd, &wasi_addr);
274+
HANDLE_ERROR(error)
275+
276+
error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
277+
HANDLE_ERROR(error)
278+
279+
return __WASI_ERRNO_SUCCESS;
280+
}

core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,8 +1009,8 @@ wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fd_t *fd_new)
10091009
}
10101010

10111011
static wasi_errno_t
1012-
wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *buf,
1013-
wasi_size_t buf_len)
1012+
wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd,
1013+
__wasi_addr_t *addr)
10141014
{
10151015
wasm_module_inst_t module_inst = get_module_inst(exec_env);
10161016
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
@@ -1021,7 +1021,7 @@ wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8 *buf,
10211021

10221022
curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
10231023

1024-
return wasi_ssp_sock_addr_local(curfds, fd, buf, buf_len);
1024+
return wasi_ssp_sock_addr_local(curfds, fd, addr);
10251025
}
10261026

10271027
static wasi_errno_t
@@ -1388,7 +1388,7 @@ static NativeSymbol native_symbols_libc_wasi[] = {
13881388
REG_NATIVE_FUNC(proc_raise, "(i)i"),
13891389
REG_NATIVE_FUNC(random_get, "(*~)i"),
13901390
REG_NATIVE_FUNC(sock_accept, "(i*)i"),
1391-
REG_NATIVE_FUNC(sock_addr_local, "(i*i)i"),
1391+
REG_NATIVE_FUNC(sock_addr_local, "(i*)i"),
13921392
REG_NATIVE_FUNC(sock_addr_remote, "(i*i)i"),
13931393
REG_NATIVE_FUNC(sock_addr_resolve, "(i*i*i)i"),
13941394
REG_NATIVE_FUNC(sock_bind, "(i*)i"),

core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ wasi_ssp_sock_addr_local(
995995
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
996996
struct fd_table *curfds,
997997
#endif
998-
__wasi_fd_t fd, uint8_t *buf, __wasi_size_t buf_len
998+
__wasi_fd_t fd, __wasi_addr_t *addr
999999
) __attribute__((__warn_unused_result__));
10001000

10011001
__wasi_errno_t

core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,34 @@ convert_errno(int error)
161161
return errors[error];
162162
}
163163

164+
// Converts an IPv4 binary address object to WASI address.
165+
static void
166+
ipv4_addr_to_wasi_addr(uint32_t addr, __wasi_ip_port_t port, __wasi_addr_t *out)
167+
{
168+
out->kind = IPv4;
169+
out->addr.ip4.port = port;
170+
out->addr.ip4.addr.n3 = (addr & 0xFF000000) >> 24;
171+
out->addr.ip4.addr.n2 = (addr & 0x00FF0000) >> 16;
172+
out->addr.ip4.addr.n1 = (addr & 0x0000FF00) >> 8;
173+
out->addr.ip4.addr.n0 = (addr & 0x000000FF);
174+
}
175+
176+
// Converts an IPv6 binary address object to WASI address object.
177+
static void
178+
ipv6_addr_to_wasi_addr(uint16_t addr[8], __wasi_ip_port_t port, __wasi_addr_t *out)
179+
{
180+
out->kind = IPv6;
181+
out->addr.ip6.port = port;
182+
out->addr.ip6.addr.n0 = addr[0];
183+
out->addr.ip6.addr.n1 = addr[1];
184+
out->addr.ip6.addr.n2 = addr[2];
185+
out->addr.ip6.addr.n3 = addr[3];
186+
out->addr.ip6.addr.h0 = addr[4];
187+
out->addr.ip6.addr.h1 = addr[5];
188+
out->addr.ip6.addr.h2 = addr[6];
189+
out->addr.ip6.addr.h3 = addr[7];
190+
}
191+
164192
// Converts a POSIX timespec to a CloudABI timestamp.
165193
static __wasi_timestamp_t
166194
convert_timespec(const struct timespec *ts)
@@ -2852,16 +2880,57 @@ wasi_ssp_sock_addr_local(
28522880
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
28532881
struct fd_table *curfds,
28542882
#endif
2855-
__wasi_fd_t fd, uint8 *buf, __wasi_size_t buf_len)
2883+
__wasi_fd_t fd, __wasi_addr_t *addr)
28562884
{
28572885
struct fd_object *fo;
2886+
char buf[64];
2887+
__wasi_ip_port_t port;
2888+
uint8_t is_ipv4;
2889+
int ret;
2890+
uint8_t inet_pton_dest[16];
2891+
28582892
__wasi_errno_t error =
28592893
fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
28602894
if (error != __WASI_ESUCCESS)
28612895
return error;
28622896

2897+
ret = os_socket_addr_local(fd_number(fo), buf, sizeof(buf)/sizeof(buf[0]), &port, &is_ipv4);
28632898
fd_object_release(fo);
2864-
return __WASI_ENOSYS;
2899+
if (ret != BHT_OK) {
2900+
error = convert_errno(errno);
2901+
}
2902+
2903+
if (BHT_OK != os_socket_inet_pton(is_ipv4, buf, inet_pton_dest)) {
2904+
return __WASI_EINVAL;
2905+
}
2906+
if (is_ipv4) {
2907+
ipv4_addr_to_wasi_addr(*(uint32_t*)inet_pton_dest, port, addr);
2908+
} else {
2909+
ipv6_addr_to_wasi_addr((uint16*)inet_pton_dest, port, addr);
2910+
}
2911+
2912+
// addr_len = sizeof(addr_storage);
2913+
// if (getsockname(fd_number(fo), (struct sockaddr *)&addr_storage, &addr_len)
2914+
// == BHT_OK) {
2915+
// switch (addr_storage.ss_family) {
2916+
// case AF_INET:
2917+
// ipv4_sockaddr_to_wasi_addr((struct sockaddr_in *)&addr_storage,
2918+
// addr);
2919+
// break;
2920+
// case AF_INET6:
2921+
// ipv6_addr_to_wasi_addr((struct sockaddr_in6 *)&addr_storage,
2922+
// addr);
2923+
// break;
2924+
// default:
2925+
// error = __WASI_EAFNOSUPPORT;
2926+
// }
2927+
// }
2928+
// else {
2929+
// error = convert_errno(errno);
2930+
// }
2931+
2932+
2933+
return error;
28652934
}
28662935

28672936
__wasi_errno_t

core/shared/platform/common/posix/posix_socket.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,57 @@ os_socket_inet_network(const char *cp, uint32 *out)
176176
*out = ntohl(inet_addr(cp));
177177
return BHT_OK;
178178
}
179+
180+
int
181+
os_socket_inet_pton(uint8_t is_ipv4, const char *src, void *dst)
182+
{
183+
int af = is_ipv4 ? AF_INET : AF_INET6;
184+
185+
if (inet_pton(af, src, dst) != 1) {
186+
return BHT_ERROR;
187+
}
188+
189+
if (!is_ipv4) {
190+
uint16_t *data = dst;
191+
for (int i = 0; i < 8; i++) {
192+
data[i] = ntohs(data[i]);
193+
}
194+
}
195+
196+
return BHT_OK;
197+
}
198+
199+
int
200+
os_socket_addr_local(bh_socket_t socket, char *buf, size_t buflen, uint16_t *port, uint8_t *is_ipv4)
201+
{
202+
struct sockaddr_storage addr_storage = { 0 };
203+
socklen_t addr_len = sizeof(addr_storage);
204+
int ret;
205+
206+
assert(buf);
207+
assert(is_ipv4);
208+
assert(port);
209+
210+
ret = getsockname(socket, (struct sockaddr *)&addr_storage, &addr_len);
211+
212+
if (ret != BHT_OK) {
213+
return BHT_ERROR;
214+
}
215+
216+
*is_ipv4 = addr_storage.ss_family == AF_INET;
217+
218+
switch (addr_storage.ss_family) {
219+
case AF_INET:
220+
*port = ntohs(((struct sockaddr_in *)&addr_storage)->sin_port);
221+
inet_ntop(AF_INET, &((struct sockaddr_in *)&addr_storage)->sin_addr, buf, buflen);
222+
break;
223+
case AF_INET6:
224+
*port = ntohs(((struct sockaddr_in6 *)&addr_storage)->sin6_port);
225+
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr_storage)->sin6_addr, buf, buflen);
226+
break;
227+
default:
228+
return BHT_ERROR;
229+
}
230+
231+
return BHT_OK;
232+
}

core/shared/platform/include/platform_api_extension.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,41 @@ os_socket_shutdown(bh_socket_t socket);
339339
int
340340
os_socket_inet_network(const char *cp, uint32 *out);
341341

342+
/**
343+
* converts src into a number in host byte order suitable for use as
344+
* an Internet network address
345+
*
346+
* @param is_ipv4 determines whether the address is IPv4 or IPv6 address
347+
*
348+
* @param src a string in IPv4 numbers-and-dots notation for IPv4 and
349+
* in format given in RFC 4291 for IPv6
350+
*
351+
* @param dst a destination buffer for the binary address
352+
*
353+
* @return On success, returns 0; otherwise, it returns -1.
354+
*/
355+
int
356+
os_socket_inet_pton(uint8_t is_ipv4, const char *src, void *dst);
357+
358+
/**
359+
* Returns an address and a port of the local socket
360+
*
361+
* @param socket the local socket
362+
*
363+
* @param buf buffer to store address to
364+
*
365+
* @param buflen length of the buf buffer
366+
*
367+
* @param port a buffer for storing socket's port
368+
*
369+
* @param is_ipv4 a buffer for storing information about the address family
370+
*
371+
* @return On success, returns 0; otherwise, it returns -1.
372+
*/
373+
int
374+
os_socket_addr_local(bh_socket_t socket, char *buf, size_t buflen, uint16_t *port, uint8_t *is_ipv4);
375+
376+
342377
#ifdef __cplusplus
343378
}
344379
#endif

core/shared/platform/linux-sgx/sgx_socket.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,4 +620,20 @@ os_socket_shutdown(bh_socket_t socket)
620620
return shutdown(socket, O_RDWR);
621621
}
622622

623+
int
624+
os_socket_inet_pton(uint8_t is_ipv4, const char *src, void *dst)
625+
{
626+
errno = ENOSYS;
627+
628+
return BHT_ERROR;
629+
}
630+
631+
int
632+
os_socket_addr_local(bh_socket_t socket, char *buf, size_t buflen, uint16_t *port, uint8_t *is_ipv4)
633+
{
634+
errno = ENOSYS;
635+
636+
return BHT_ERROR;
637+
}
638+
623639
#endif

core/shared/platform/windows/win_socket.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,20 @@ os_socket_inet_network(const char *cp, uint32 *out)
161161

162162
*out = inet_addr(cp);
163163
return BHT_OK;
164+
}
165+
166+
int
167+
os_socket_inet_pton(uint8_t is_ipv4, const char *src, void *dst)
168+
{
169+
errno = ENOSYS;
170+
171+
return BHT_ERROR;
172+
}
173+
174+
int
175+
os_socket_addr_local(bh_socket_t socket, char *buf, size_t buflen, uint16_t *port, uint8_t *is_ipv4)
176+
{
177+
errno = ENOSYS;
178+
179+
return BHT_ERROR;
164180
}

0 commit comments

Comments
 (0)