mirror of
https://git.proxmox.com/git/wasi-libc
synced 2025-07-27 12:52:53 +00:00
implement getsockname
, getpeername
, and getaddrinfo
(#488)
This also includes stubs for `gethostbyname`, `gethostbyaddr`, etc. which were necessary to get CPython to build. I believe it will be possible to implement them all properly at some point, but don't have the bandwidth at the moment. Finally, this includes a few fixes for issues I missed in earlier PRs that surfaced when running the CPython `asyncio` test suite. Signed-off-by: Joel Dice <joel.dice@fermyon.com> Co-authored-by: Dave Bakker <github@davebakker.io>
This commit is contained in:
parent
1ab654e2f5
commit
d038294899
20
Makefile
20
Makefile
@ -94,7 +94,9 @@ LIBC_BOTTOM_HALF_OMIT_SOURCES := \
|
|||||||
$(LIBC_BOTTOM_HALF_SOURCES)/accept-wasip2.c \
|
$(LIBC_BOTTOM_HALF_SOURCES)/accept-wasip2.c \
|
||||||
$(LIBC_BOTTOM_HALF_SOURCES)/shutdown.c \
|
$(LIBC_BOTTOM_HALF_SOURCES)/shutdown.c \
|
||||||
$(LIBC_BOTTOM_HALF_SOURCES)/sockopt.c \
|
$(LIBC_BOTTOM_HALF_SOURCES)/sockopt.c \
|
||||||
$(LIBC_BOTTOM_HALF_SOURCES)/poll-wasip2.c
|
$(LIBC_BOTTOM_HALF_SOURCES)/poll-wasip2.c \
|
||||||
|
$(LIBC_BOTTOM_HALF_SOURCES)/getsockpeername.c \
|
||||||
|
$(LIBC_BOTTOM_HALF_SOURCES)/netdb.c
|
||||||
LIBC_BOTTOM_HALF_ALL_SOURCES := $(filter-out $(LIBC_BOTTOM_HALF_OMIT_SOURCES),$(LIBC_BOTTOM_HALF_ALL_SOURCES))
|
LIBC_BOTTOM_HALF_ALL_SOURCES := $(filter-out $(LIBC_BOTTOM_HALF_OMIT_SOURCES),$(LIBC_BOTTOM_HALF_ALL_SOURCES))
|
||||||
# Omit p2-specific headers from include-all.c test.
|
# Omit p2-specific headers from include-all.c test.
|
||||||
# for exception-handling.
|
# for exception-handling.
|
||||||
@ -249,6 +251,13 @@ LIBC_TOP_HALF_MUSL_SOURCES = \
|
|||||||
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/complex/*.c)) \
|
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/complex/*.c)) \
|
||||||
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/crypt/*.c)
|
$(wildcard $(LIBC_TOP_HALF_MUSL_SRC_DIR)/crypt/*.c)
|
||||||
|
|
||||||
|
ifeq ($(WASI_SNAPSHOT), p2)
|
||||||
|
LIBC_TOP_HALF_MUSL_SOURCES += \
|
||||||
|
$(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
|
||||||
|
network/gai_strerror.c \
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(THREAD_MODEL), posix)
|
ifeq ($(THREAD_MODEL), posix)
|
||||||
LIBC_TOP_HALF_MUSL_SOURCES += \
|
LIBC_TOP_HALF_MUSL_SOURCES += \
|
||||||
$(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
|
$(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
|
||||||
@ -387,6 +396,10 @@ ASMFLAGS += -matomics
|
|||||||
CFLAGS += -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)
|
CFLAGS += -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(WASI_SNAPSHOT), p2)
|
||||||
|
EXTRA_CFLAGS += -D__wasilibc_use_wasip2
|
||||||
|
endif
|
||||||
|
|
||||||
# Expose the public headers to the implementation. We use `-isystem` for
|
# Expose the public headers to the implementation. We use `-isystem` for
|
||||||
# purpose for two reasons:
|
# purpose for two reasons:
|
||||||
#
|
#
|
||||||
@ -500,7 +513,6 @@ MUSL_OMIT_HEADERS += \
|
|||||||
"sys/auxv.h" \
|
"sys/auxv.h" \
|
||||||
"pwd.h" "shadow.h" "grp.h" \
|
"pwd.h" "shadow.h" "grp.h" \
|
||||||
"mntent.h" \
|
"mntent.h" \
|
||||||
"netdb.h" \
|
|
||||||
"resolv.h" \
|
"resolv.h" \
|
||||||
"pty.h" \
|
"pty.h" \
|
||||||
"ulimit.h" \
|
"ulimit.h" \
|
||||||
@ -523,6 +535,10 @@ MUSL_OMIT_HEADERS += \
|
|||||||
"sys/sysmacros.h" \
|
"sys/sysmacros.h" \
|
||||||
"aio.h"
|
"aio.h"
|
||||||
|
|
||||||
|
ifeq ($(WASI_SNAPSHOT), p1)
|
||||||
|
MUSL_OMIT_HEADERS += "netdb.h"
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(THREAD_MODEL), single)
|
ifeq ($(THREAD_MODEL), single)
|
||||||
# Remove headers not supported in single-threaded mode.
|
# Remove headers not supported in single-threaded mode.
|
||||||
MUSL_OMIT_HEADERS += "pthread.h"
|
MUSL_OMIT_HEADERS += "pthread.h"
|
||||||
|
@ -535,6 +535,9 @@ dprintf
|
|||||||
drand48
|
drand48
|
||||||
drem
|
drem
|
||||||
dremf
|
dremf
|
||||||
|
drop_tcp_socket
|
||||||
|
drop_udp_socket
|
||||||
|
drop_udp_socket_streams
|
||||||
duplocale
|
duplocale
|
||||||
ecvt
|
ecvt
|
||||||
encrypt
|
encrypt
|
||||||
@ -709,6 +712,7 @@ fputws_unlocked
|
|||||||
fread
|
fread
|
||||||
fread_unlocked
|
fread_unlocked
|
||||||
free
|
free
|
||||||
|
freeaddrinfo
|
||||||
freelocale
|
freelocale
|
||||||
freopen
|
freopen
|
||||||
freopen64
|
freopen64
|
||||||
@ -737,11 +741,13 @@ fwprintf
|
|||||||
fwrite
|
fwrite
|
||||||
fwrite_unlocked
|
fwrite_unlocked
|
||||||
fwscanf
|
fwscanf
|
||||||
|
gai_strerror
|
||||||
gcvt
|
gcvt
|
||||||
get_avphys_pages
|
get_avphys_pages
|
||||||
get_nprocs
|
get_nprocs
|
||||||
get_nprocs_conf
|
get_nprocs_conf
|
||||||
get_phys_pages
|
get_phys_pages
|
||||||
|
getaddrinfo
|
||||||
getc
|
getc
|
||||||
getc_unlocked
|
getc_unlocked
|
||||||
getchar
|
getchar
|
||||||
@ -753,14 +759,22 @@ getdelim
|
|||||||
getdomainname
|
getdomainname
|
||||||
getentropy
|
getentropy
|
||||||
getenv
|
getenv
|
||||||
|
gethostbyaddr
|
||||||
|
gethostbyname
|
||||||
gethostid
|
gethostid
|
||||||
getline
|
getline
|
||||||
|
getnameinfo
|
||||||
getopt
|
getopt
|
||||||
getopt_long
|
getopt_long
|
||||||
getopt_long_only
|
getopt_long_only
|
||||||
getpagesize
|
getpagesize
|
||||||
|
getpeername
|
||||||
getpid
|
getpid
|
||||||
|
getprotobyname
|
||||||
getrusage
|
getrusage
|
||||||
|
getservbyname
|
||||||
|
getservbyport
|
||||||
|
getsockname
|
||||||
getsockopt
|
getsockopt
|
||||||
getsubopt
|
getsubopt
|
||||||
gettimeofday
|
gettimeofday
|
||||||
@ -775,12 +789,14 @@ globfree
|
|||||||
globfree64
|
globfree64
|
||||||
gmtime
|
gmtime
|
||||||
gmtime_r
|
gmtime_r
|
||||||
|
h_errno
|
||||||
hcreate
|
hcreate
|
||||||
hcreate_r
|
hcreate_r
|
||||||
hdestroy
|
hdestroy
|
||||||
hdestroy_r
|
hdestroy_r
|
||||||
hsearch
|
hsearch
|
||||||
hsearch_r
|
hsearch_r
|
||||||
|
hstrerror
|
||||||
htonl
|
htonl
|
||||||
htons
|
htons
|
||||||
hypot
|
hypot
|
||||||
@ -1246,6 +1262,8 @@ tcp_bind
|
|||||||
tcp_borrow_tcp_socket
|
tcp_borrow_tcp_socket
|
||||||
tcp_create_socket_create_tcp_socket
|
tcp_create_socket_create_tcp_socket
|
||||||
tcp_create_socket_result_own_tcp_socket_error_code_free
|
tcp_create_socket_result_own_tcp_socket_error_code_free
|
||||||
|
tcp_getpeername
|
||||||
|
tcp_getsockname
|
||||||
tcp_getsockopt
|
tcp_getsockopt
|
||||||
tcp_ip_socket_address_free
|
tcp_ip_socket_address_free
|
||||||
tcp_listen
|
tcp_listen
|
||||||
@ -1338,6 +1356,8 @@ udp_borrow_outgoing_datagram_stream
|
|||||||
udp_borrow_udp_socket
|
udp_borrow_udp_socket
|
||||||
udp_create_socket_create_udp_socket
|
udp_create_socket_create_udp_socket
|
||||||
udp_create_socket_result_own_udp_socket_error_code_free
|
udp_create_socket_result_own_udp_socket_error_code_free
|
||||||
|
udp_getpeername
|
||||||
|
udp_getsockname
|
||||||
udp_getsockopt
|
udp_getsockopt
|
||||||
udp_incoming_datagram_free
|
udp_incoming_datagram_free
|
||||||
udp_incoming_datagram_stream_drop_borrow
|
udp_incoming_datagram_stream_drop_borrow
|
||||||
|
@ -102,6 +102,7 @@
|
|||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <monetary.h>
|
#include <monetary.h>
|
||||||
#include <mqueue.h>
|
#include <mqueue.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/icmp6.h>
|
#include <netinet/icmp6.h>
|
||||||
#include <netinet/igmp.h>
|
#include <netinet/igmp.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
@ -37,6 +37,13 @@
|
|||||||
#define AF_INET6 PF_INET6
|
#define AF_INET6 PF_INET6
|
||||||
#define AF_UNIX 3
|
#define AF_UNIX 3
|
||||||
#define AF_UNSPEC PF_UNSPEC
|
#define AF_UNSPEC PF_UNSPEC
|
||||||
|
#define AI_ADDRCONFIG 0x20
|
||||||
|
#define AI_ALL 0x10
|
||||||
|
#define AI_CANONNAME 0x02
|
||||||
|
#define AI_NUMERICHOST 0x04
|
||||||
|
#define AI_NUMERICSERV 0x400
|
||||||
|
#define AI_PASSIVE 0x01
|
||||||
|
#define AI_V4MAPPED 0x08
|
||||||
#define ALT_DIGITS 0x2002F
|
#define ALT_DIGITS 0x2002F
|
||||||
#define AM_STR 0x20026
|
#define AM_STR 0x20026
|
||||||
#define ANYMARK 0x01
|
#define ANYMARK 0x01
|
||||||
@ -192,6 +199,24 @@
|
|||||||
#define EADDRNOTAVAIL __WASI_ERRNO_ADDRNOTAVAIL
|
#define EADDRNOTAVAIL __WASI_ERRNO_ADDRNOTAVAIL
|
||||||
#define EAFNOSUPPORT __WASI_ERRNO_AFNOSUPPORT
|
#define EAFNOSUPPORT __WASI_ERRNO_AFNOSUPPORT
|
||||||
#define EAGAIN __WASI_ERRNO_AGAIN
|
#define EAGAIN __WASI_ERRNO_AGAIN
|
||||||
|
#define EAI_ADDRFAMILY -9
|
||||||
|
#define EAI_AGAIN -3
|
||||||
|
#define EAI_ALLDONE -103
|
||||||
|
#define EAI_BADFLAGS -1
|
||||||
|
#define EAI_CANCELED -101
|
||||||
|
#define EAI_FAIL -4
|
||||||
|
#define EAI_FAMILY -6
|
||||||
|
#define EAI_IDN_ENCODE -105
|
||||||
|
#define EAI_INPROGRESS -100
|
||||||
|
#define EAI_INTR -104
|
||||||
|
#define EAI_MEMORY -10
|
||||||
|
#define EAI_NODATA -5
|
||||||
|
#define EAI_NONAME -2
|
||||||
|
#define EAI_NOTCANCELED -102
|
||||||
|
#define EAI_OVERFLOW -12
|
||||||
|
#define EAI_SERVICE -8
|
||||||
|
#define EAI_SOCKTYPE -7
|
||||||
|
#define EAI_SYSTEM -11
|
||||||
#define EALREADY __WASI_ERRNO_ALREADY
|
#define EALREADY __WASI_ERRNO_ALREADY
|
||||||
#define EBADF __WASI_ERRNO_BADF
|
#define EBADF __WASI_ERRNO_BADF
|
||||||
#define EBADID 5
|
#define EBADID 5
|
||||||
@ -489,6 +514,7 @@
|
|||||||
#define HIBITL MINLONG
|
#define HIBITL MINLONG
|
||||||
#define HIBITS MINSHORT
|
#define HIBITS MINSHORT
|
||||||
#define HOST_NAME_MAX 255
|
#define HOST_NAME_MAX 255
|
||||||
|
#define HOST_NOT_FOUND 1
|
||||||
#define HUGE 3.40282346638528859812e+38F
|
#define HUGE 3.40282346638528859812e+38F
|
||||||
#define HUGE_VAL ((double)INFINITY)
|
#define HUGE_VAL ((double)INFINITY)
|
||||||
#define HUGE_VALF INFINITY
|
#define HUGE_VALF INFINITY
|
||||||
@ -1239,6 +1265,14 @@
|
|||||||
#define NEW_ENV_VAR 0
|
#define NEW_ENV_VAR 0
|
||||||
#define NGROUPS 32
|
#define NGROUPS 32
|
||||||
#define NGROUPS_MAX 32
|
#define NGROUPS_MAX 32
|
||||||
|
#define NI_DGRAM 0x10
|
||||||
|
#define NI_MAXHOST 255
|
||||||
|
#define NI_MAXSERV 32
|
||||||
|
#define NI_NAMEREQD 0x08
|
||||||
|
#define NI_NOFQDN 0x04
|
||||||
|
#define NI_NUMERICHOST 0x01
|
||||||
|
#define NI_NUMERICSCOPE 0x100
|
||||||
|
#define NI_NUMERICSERV 0x02
|
||||||
#define NL_ARGMAX 9
|
#define NL_ARGMAX 9
|
||||||
#define NL_CAT_LOCALE 1
|
#define NL_CAT_LOCALE 1
|
||||||
#define NL_LANGMAX 32
|
#define NL_LANGMAX 32
|
||||||
@ -1257,6 +1291,9 @@
|
|||||||
#define NOTAUTH ns_r_notauth
|
#define NOTAUTH ns_r_notauth
|
||||||
#define NOTIMP ns_r_notimpl
|
#define NOTIMP ns_r_notimpl
|
||||||
#define NOTZONE ns_r_notzone
|
#define NOTZONE ns_r_notzone
|
||||||
|
#define NO_ADDRESS NO_DATA
|
||||||
|
#define NO_DATA 4
|
||||||
|
#define NO_RECOVERY 3
|
||||||
#define NR_ICMP_TYPES 18
|
#define NR_ICMP_TYPES 18
|
||||||
#define NR_ICMP_UNREACH 15
|
#define NR_ICMP_UNREACH 15
|
||||||
#define NSLC 18
|
#define NSLC 18
|
||||||
@ -1968,6 +2005,7 @@
|
|||||||
#define TOREAD 00004
|
#define TOREAD 00004
|
||||||
#define TOWRITE 00002
|
#define TOWRITE 00002
|
||||||
#define TRANSIENT 4
|
#define TRANSIENT 4
|
||||||
|
#define TRY_AGAIN 2
|
||||||
#define TSGID 02000
|
#define TSGID 02000
|
||||||
#define TSS_DTOR_ITERATIONS 4
|
#define TSS_DTOR_ITERATIONS 4
|
||||||
#define TSUID 04000
|
#define TSUID 04000
|
||||||
@ -2173,6 +2211,7 @@
|
|||||||
#define _MATH_H
|
#define _MATH_H
|
||||||
#define _MONETARY_H
|
#define _MONETARY_H
|
||||||
#define _MQUEUE_H
|
#define _MQUEUE_H
|
||||||
|
#define _NETDB_H
|
||||||
#define _NETINET_ICMP6_H
|
#define _NETINET_ICMP6_H
|
||||||
#define _NETINET_IGMP_H
|
#define _NETINET_IGMP_H
|
||||||
#define _NETINET_IN_H
|
#define _NETINET_IN_H
|
||||||
@ -3194,7 +3233,7 @@
|
|||||||
#define __wasilibc___typedef_suseconds_t_h
|
#define __wasilibc___typedef_suseconds_t_h
|
||||||
#define __wasilibc___typedef_time_t_h
|
#define __wasilibc___typedef_time_t_h
|
||||||
#define __wasilibc___typedef_uid_t_h
|
#define __wasilibc___typedef_uid_t_h
|
||||||
#define __wasilibc_use_wasip2
|
#define __wasilibc_use_wasip2 1
|
||||||
#define __wasm 1
|
#define __wasm 1
|
||||||
#define __wasm32 1
|
#define __wasm32 1
|
||||||
#define __wasm32__ 1
|
#define __wasm32__ 1
|
||||||
@ -3281,6 +3320,8 @@
|
|||||||
#define glob64 glob
|
#define glob64 glob
|
||||||
#define glob64_t glob_t
|
#define glob64_t glob_t
|
||||||
#define globfree64 globfree
|
#define globfree64 globfree
|
||||||
|
#define h_addr h_addr_list[0]
|
||||||
|
#define h_errno h_errno
|
||||||
#define howmany(n,d) (((n)+((d)-1))/(d))
|
#define howmany(n,d) (((n)+((d)-1))/(d))
|
||||||
#define htobe16(x) __bswap16(x)
|
#define htobe16(x) __bswap16(x)
|
||||||
#define htobe32(x) __bswap32(x)
|
#define htobe32(x) __bswap32(x)
|
||||||
|
229
libc-bottom-half/sources/getsockpeername.c
Normal file
229
libc-bottom-half/sources/getsockpeername.c
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <wasi/descriptor_table.h>
|
||||||
|
#include <wasi/sockets_utils.h>
|
||||||
|
|
||||||
|
int tcp_getsockname(tcp_socket_t *socket, struct sockaddr *addr,
|
||||||
|
socklen_t *addrlen)
|
||||||
|
{
|
||||||
|
output_sockaddr_t output_addr;
|
||||||
|
if (!__wasi_sockets_utils__output_addr_validate(
|
||||||
|
socket->family, addr, addrlen, &output_addr)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_addr.tag == OUTPUT_SOCKADDR_NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (socket->state.tag) {
|
||||||
|
case TCP_SOCKET_STATE_UNBOUND:
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case TCP_SOCKET_STATE_BOUND:
|
||||||
|
case TCP_SOCKET_STATE_CONNECTING:
|
||||||
|
case TCP_SOCKET_STATE_CONNECT_FAILED:
|
||||||
|
case TCP_SOCKET_STATE_LISTENING:
|
||||||
|
case TCP_SOCKET_STATE_CONNECTED:
|
||||||
|
// OK. Continue..
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* unreachable */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
network_error_code_t error;
|
||||||
|
network_ip_socket_address_t result;
|
||||||
|
tcp_borrow_tcp_socket_t socket_borrow =
|
||||||
|
tcp_borrow_tcp_socket(socket->socket);
|
||||||
|
if (!tcp_method_tcp_socket_local_address(socket_borrow, &result,
|
||||||
|
&error)) {
|
||||||
|
errno = __wasi_sockets_utils__map_error(error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__wasi_sockets_utils__output_addr_write(result, &output_addr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_getpeername(tcp_socket_t *socket, struct sockaddr *addr,
|
||||||
|
socklen_t *addrlen)
|
||||||
|
{
|
||||||
|
output_sockaddr_t output_addr;
|
||||||
|
if (!__wasi_sockets_utils__output_addr_validate(
|
||||||
|
socket->family, addr, addrlen, &output_addr)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_addr.tag == OUTPUT_SOCKADDR_NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (socket->state.tag) {
|
||||||
|
case TCP_SOCKET_STATE_UNBOUND:
|
||||||
|
case TCP_SOCKET_STATE_BOUND:
|
||||||
|
case TCP_SOCKET_STATE_CONNECTING:
|
||||||
|
case TCP_SOCKET_STATE_CONNECT_FAILED:
|
||||||
|
case TCP_SOCKET_STATE_LISTENING:
|
||||||
|
errno = ENOTCONN;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case TCP_SOCKET_STATE_CONNECTED:
|
||||||
|
// OK. Continue..
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* unreachable */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
network_error_code_t error;
|
||||||
|
network_ip_socket_address_t result;
|
||||||
|
tcp_borrow_tcp_socket_t socket_borrow =
|
||||||
|
tcp_borrow_tcp_socket(socket->socket);
|
||||||
|
if (!tcp_method_tcp_socket_remote_address(socket_borrow, &result,
|
||||||
|
&error)) {
|
||||||
|
errno = __wasi_sockets_utils__map_error(error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__wasi_sockets_utils__output_addr_write(result, &output_addr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int udp_getsockname(udp_socket_t *socket, struct sockaddr *addr,
|
||||||
|
socklen_t *addrlen)
|
||||||
|
{
|
||||||
|
output_sockaddr_t output_addr;
|
||||||
|
if (!__wasi_sockets_utils__output_addr_validate(
|
||||||
|
socket->family, addr, addrlen, &output_addr)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_addr.tag == OUTPUT_SOCKADDR_NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (socket->state.tag) {
|
||||||
|
case UDP_SOCKET_STATE_UNBOUND:
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case UDP_SOCKET_STATE_BOUND_NOSTREAMS:
|
||||||
|
case UDP_SOCKET_STATE_BOUND_STREAMING:
|
||||||
|
case UDP_SOCKET_STATE_CONNECTED:
|
||||||
|
// OK. Continue..
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* unreachable */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
network_error_code_t error;
|
||||||
|
network_ip_socket_address_t result;
|
||||||
|
udp_borrow_udp_socket_t socket_borrow =
|
||||||
|
udp_borrow_udp_socket(socket->socket);
|
||||||
|
if (!udp_method_udp_socket_local_address(socket_borrow, &result,
|
||||||
|
&error)) {
|
||||||
|
errno = __wasi_sockets_utils__map_error(error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__wasi_sockets_utils__output_addr_write(result, &output_addr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int udp_getpeername(udp_socket_t *socket, struct sockaddr *addr,
|
||||||
|
socklen_t *addrlen)
|
||||||
|
{
|
||||||
|
output_sockaddr_t output_addr;
|
||||||
|
if (!__wasi_sockets_utils__output_addr_validate(
|
||||||
|
socket->family, addr, addrlen, &output_addr)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_addr.tag == OUTPUT_SOCKADDR_NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (socket->state.tag) {
|
||||||
|
case UDP_SOCKET_STATE_UNBOUND:
|
||||||
|
case UDP_SOCKET_STATE_BOUND_NOSTREAMS:
|
||||||
|
case UDP_SOCKET_STATE_BOUND_STREAMING:
|
||||||
|
errno = ENOTCONN;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case UDP_SOCKET_STATE_CONNECTED:
|
||||||
|
// OK. Continue..
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* unreachable */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
network_error_code_t error;
|
||||||
|
network_ip_socket_address_t result;
|
||||||
|
udp_borrow_udp_socket_t socket_borrow =
|
||||||
|
udp_borrow_udp_socket(socket->socket);
|
||||||
|
if (!udp_method_udp_socket_remote_address(socket_borrow, &result,
|
||||||
|
&error)) {
|
||||||
|
errno = __wasi_sockets_utils__map_error(error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__wasi_sockets_utils__output_addr_write(result, &output_addr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getsockname(int socket, struct sockaddr *__restrict addr,
|
||||||
|
socklen_t *__restrict addrlen)
|
||||||
|
{
|
||||||
|
descriptor_table_entry_t *entry;
|
||||||
|
if (!descriptor_table_get_ref(socket, &entry)) {
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (entry->tag) {
|
||||||
|
case DESCRIPTOR_TABLE_ENTRY_TCP_SOCKET:
|
||||||
|
return tcp_getsockname(&entry->tcp_socket, addr, addrlen);
|
||||||
|
case DESCRIPTOR_TABLE_ENTRY_UDP_SOCKET:
|
||||||
|
return udp_getsockname(&entry->udp_socket, addr, addrlen);
|
||||||
|
default:
|
||||||
|
errno = EOPNOTSUPP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getpeername(int socket, struct sockaddr *__restrict addr,
|
||||||
|
socklen_t *__restrict addrlen)
|
||||||
|
{
|
||||||
|
descriptor_table_entry_t *entry;
|
||||||
|
if (!descriptor_table_get_ref(socket, &entry)) {
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (entry->tag) {
|
||||||
|
case DESCRIPTOR_TABLE_ENTRY_TCP_SOCKET:
|
||||||
|
return tcp_getpeername(&entry->tcp_socket, addr, addrlen);
|
||||||
|
case DESCRIPTOR_TABLE_ENTRY_UDP_SOCKET:
|
||||||
|
return udp_getpeername(&entry->udp_socket, addr, addrlen);
|
||||||
|
default:
|
||||||
|
errno = EOPNOTSUPP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
238
libc-bottom-half/sources/netdb.c
Normal file
238
libc-bottom-half/sources/netdb.c
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
#include <netdb.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <wasi/sockets_utils.h>
|
||||||
|
|
||||||
|
_Thread_local int h_errno = 0;
|
||||||
|
|
||||||
|
static int map_error(ip_name_lookup_error_code_t error)
|
||||||
|
{
|
||||||
|
switch (error) {
|
||||||
|
case NETWORK_ERROR_CODE_OUT_OF_MEMORY:
|
||||||
|
return EAI_MEMORY;
|
||||||
|
case NETWORK_ERROR_CODE_NAME_UNRESOLVABLE:
|
||||||
|
return EAI_NONAME;
|
||||||
|
case NETWORK_ERROR_CODE_TEMPORARY_RESOLVER_FAILURE:
|
||||||
|
return EAI_AGAIN;
|
||||||
|
case NETWORK_ERROR_CODE_PERMANENT_RESOLVER_FAILURE:
|
||||||
|
return EAI_FAIL;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errno = __wasi_sockets_utils__map_error(error);
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_addr(ip_name_lookup_option_ip_address_t address,
|
||||||
|
const struct addrinfo *restrict hint,
|
||||||
|
struct addrinfo **restrict current,
|
||||||
|
struct addrinfo **restrict res)
|
||||||
|
{
|
||||||
|
int family;
|
||||||
|
struct sockaddr *addr;
|
||||||
|
socklen_t addrlen;
|
||||||
|
switch (address.val.tag) {
|
||||||
|
case NETWORK_IP_ADDRESS_IPV4: {
|
||||||
|
if (hint && hint->ai_family != AF_UNSPEC &&
|
||||||
|
hint->ai_family != AF_INET) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
network_ipv4_address_t ip = address.val.val.ipv4;
|
||||||
|
|
||||||
|
family = PF_INET;
|
||||||
|
addrlen = sizeof(struct sockaddr_in);
|
||||||
|
addr = malloc(addrlen);
|
||||||
|
if (addr == NULL) {
|
||||||
|
freeaddrinfo(*res);
|
||||||
|
return EAI_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in sockaddr = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_port = 0,
|
||||||
|
.sin_addr = { .s_addr = ip.f0 | (ip.f1 << 8) |
|
||||||
|
(ip.f2 << 16) | (ip.f3 << 24) },
|
||||||
|
};
|
||||||
|
memcpy(addr, &sockaddr, addrlen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NETWORK_IP_ADDRESS_IPV6: {
|
||||||
|
if (hint && hint->ai_family != AF_UNSPEC &&
|
||||||
|
hint->ai_family != AF_INET6) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
network_ipv6_address_t ip = address.val.val.ipv6;
|
||||||
|
|
||||||
|
family = PF_INET6;
|
||||||
|
addrlen = sizeof(struct sockaddr_in6);
|
||||||
|
addr = malloc(addrlen);
|
||||||
|
if (addr == NULL) {
|
||||||
|
freeaddrinfo(*res);
|
||||||
|
return EAI_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in6 sockaddr = {
|
||||||
|
.sin6_family = AF_INET6,
|
||||||
|
.sin6_port = 0,
|
||||||
|
.sin6_addr = {
|
||||||
|
.s6_addr = {
|
||||||
|
ip.f0 >> 8,
|
||||||
|
ip.f0 & 0xFF,
|
||||||
|
ip.f1 >> 8,
|
||||||
|
ip.f1 & 0xFF,
|
||||||
|
ip.f2 >> 8,
|
||||||
|
ip.f2 & 0xFF,
|
||||||
|
ip.f3 >> 8,
|
||||||
|
ip.f3 & 0xFF,
|
||||||
|
ip.f4 >> 8,
|
||||||
|
ip.f4 & 0xFF,
|
||||||
|
ip.f5 >> 8,
|
||||||
|
ip.f5 & 0xFF,
|
||||||
|
ip.f6 >> 8,
|
||||||
|
ip.f6 & 0xFF,
|
||||||
|
ip.f7 >> 8,
|
||||||
|
ip.f7 & 0xFF,
|
||||||
|
} },
|
||||||
|
.sin6_flowinfo = 0,
|
||||||
|
.sin6_scope_id = 0,
|
||||||
|
};
|
||||||
|
memcpy(addr, &sockaddr, addrlen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: /* unreachable */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct addrinfo *result = malloc(sizeof(struct addrinfo));
|
||||||
|
if (result == NULL) {
|
||||||
|
freeaddrinfo(*res);
|
||||||
|
return EAI_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = (struct addrinfo){
|
||||||
|
.ai_family = family,
|
||||||
|
.ai_flags = 0,
|
||||||
|
.ai_socktype = SOCK_STREAM,
|
||||||
|
.ai_protocol = 0,
|
||||||
|
.ai_addrlen = addrlen,
|
||||||
|
.ai_addr = addr,
|
||||||
|
.ai_canonname = NULL,
|
||||||
|
.ai_next = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (*current) {
|
||||||
|
(*current)->ai_next = result;
|
||||||
|
*current = result;
|
||||||
|
} else {
|
||||||
|
*current = result;
|
||||||
|
*res = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getaddrinfo(const char *restrict host, const char *restrict serv,
|
||||||
|
const struct addrinfo *restrict hint,
|
||||||
|
struct addrinfo **restrict res)
|
||||||
|
{
|
||||||
|
if (host == NULL) {
|
||||||
|
host = "localhost";
|
||||||
|
}
|
||||||
|
|
||||||
|
*res = NULL;
|
||||||
|
struct addrinfo *current = NULL;
|
||||||
|
wasip2_string_t name = { .ptr = (uint8_t *)host, .len = strlen(host) };
|
||||||
|
ip_name_lookup_own_resolve_address_stream_t stream;
|
||||||
|
ip_name_lookup_error_code_t error;
|
||||||
|
if (ip_name_lookup_resolve_addresses(
|
||||||
|
__wasi_sockets_utils__borrow_network(), &name, &stream,
|
||||||
|
&error)) {
|
||||||
|
ip_name_lookup_borrow_resolve_address_stream_t stream_borrow =
|
||||||
|
ip_name_lookup_borrow_resolve_address_stream(stream);
|
||||||
|
while (true) {
|
||||||
|
ip_name_lookup_option_ip_address_t address;
|
||||||
|
if (ip_name_lookup_method_resolve_address_stream_resolve_next_address(
|
||||||
|
stream_borrow, &address, &error)) {
|
||||||
|
if (address.is_some) {
|
||||||
|
int error = add_addr(address, hint,
|
||||||
|
¤t, res);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (error == NETWORK_ERROR_CODE_WOULD_BLOCK) {
|
||||||
|
ip_name_lookup_own_pollable_t pollable =
|
||||||
|
ip_name_lookup_method_resolve_address_stream_subscribe(
|
||||||
|
stream_borrow);
|
||||||
|
poll_borrow_pollable_t pollable_borrow =
|
||||||
|
poll_borrow_pollable(pollable);
|
||||||
|
poll_method_pollable_block(pollable_borrow);
|
||||||
|
poll_pollable_drop_own(pollable);
|
||||||
|
} else {
|
||||||
|
freeaddrinfo(*res);
|
||||||
|
return map_error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return map_error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeaddrinfo(struct addrinfo *p)
|
||||||
|
{
|
||||||
|
while (p) {
|
||||||
|
struct addrinfo *next = p->ai_next;
|
||||||
|
free(p->ai_addr);
|
||||||
|
free(p);
|
||||||
|
p = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
|
||||||
|
char *restrict host, socklen_t hostlen, char *restrict serv,
|
||||||
|
socklen_t servlen, int flags)
|
||||||
|
{
|
||||||
|
// TODO wasi-sockets
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hostent *gethostbyname(const char *name)
|
||||||
|
{
|
||||||
|
// TODO wasi-sockets
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type)
|
||||||
|
{
|
||||||
|
// TODO wasi-sockets
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *hstrerror(int err)
|
||||||
|
{
|
||||||
|
// TODO wasi-sockets
|
||||||
|
return "hstrerror: TODO";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct servent *getservbyname(const char *name, const char *proto)
|
||||||
|
{
|
||||||
|
// TODO wasi-sockets
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct servent *getservbyport(int port, const char *proto)
|
||||||
|
{
|
||||||
|
// TODO wasi-sockets
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct protoent *getprotobyname(const char *name)
|
||||||
|
{
|
||||||
|
// TODO wasi-sockets
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -118,8 +118,13 @@ struct hostent *gethostbyaddr (const void *, socklen_t, int);
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__attribute__((const))
|
__attribute__((const))
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __wasilibc_unmodified_upstream
|
||||||
int *__h_errno_location(void);
|
int *__h_errno_location(void);
|
||||||
#define h_errno (*__h_errno_location())
|
#define h_errno (*__h_errno_location())
|
||||||
|
#elif (defined __wasilibc_use_wasip2)
|
||||||
|
extern _Thread_local int h_errno;
|
||||||
|
#define h_errno h_errno
|
||||||
|
#endif
|
||||||
#define HOST_NOT_FOUND 1
|
#define HOST_NOT_FOUND 1
|
||||||
#define TRY_AGAIN 2
|
#define TRY_AGAIN 2
|
||||||
#define NO_RECOVERY 3
|
#define NO_RECOVERY 3
|
||||||
|
@ -417,7 +417,7 @@ int listen (int, int);
|
|||||||
int accept (int, struct sockaddr *__restrict, socklen_t *__restrict);
|
int accept (int, struct sockaddr *__restrict, socklen_t *__restrict);
|
||||||
int accept4(int, struct sockaddr *__restrict, socklen_t *__restrict, int);
|
int accept4(int, struct sockaddr *__restrict, socklen_t *__restrict, int);
|
||||||
|
|
||||||
#ifdef __wasilibc_unmodified_upstream /* WASI has no getsockname/getpeername */
|
#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2)
|
||||||
int getsockname (int, struct sockaddr *__restrict, socklen_t *__restrict);
|
int getsockname (int, struct sockaddr *__restrict, socklen_t *__restrict);
|
||||||
int getpeername (int, struct sockaddr *__restrict, socklen_t *__restrict);
|
int getpeername (int, struct sockaddr *__restrict, socklen_t *__restrict);
|
||||||
#endif
|
#endif
|
||||||
@ -434,7 +434,7 @@ ssize_t recvmsg (int, struct msghdr *, int);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int getsockopt (int, int, int, void *__restrict, socklen_t *__restrict);
|
int getsockopt (int, int, int, void *__restrict, socklen_t *__restrict);
|
||||||
#ifdef __wasilibc_unmodified_upstream /* WASI has no setsockopt */
|
#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2)
|
||||||
int setsockopt (int, int, int, const void *, socklen_t);
|
int setsockopt (int, int, int, const void *, socklen_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user