From e8ee6b1dc271a8d88f7d14a50af06b3877186272 Mon Sep 17 00:00:00 2001 From: Henri Nurmi Date: Sun, 1 Sep 2024 00:43:23 +0300 Subject: [PATCH 1/3] wasi-sockets: add services table --- expected/wasm32-wasip2/defined-symbols.txt | 3 ++ .../headers/private/wasi/sockets_utils.h | 13 +++++ libc-bottom-half/sources/sockets_utils.c | 52 +++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/expected/wasm32-wasip2/defined-symbols.txt b/expected/wasm32-wasip2/defined-symbols.txt index 8960ca0d..1ba148fe 100644 --- a/expected/wasm32-wasip2/defined-symbols.txt +++ b/expected/wasm32-wasip2/defined-symbols.txt @@ -301,10 +301,13 @@ __wasi_sock_accept __wasi_sock_recv __wasi_sock_send __wasi_sock_shutdown +__wasi_sockets_services_db __wasi_sockets_utils__any_addr __wasi_sockets_utils__borrow_network __wasi_sockets_utils__create_streams __wasi_sockets_utils__drop_streams +__wasi_sockets_utils__get_service_entry_by_name +__wasi_sockets_utils__get_service_entry_by_port __wasi_sockets_utils__map_error __wasi_sockets_utils__output_addr_validate __wasi_sockets_utils__output_addr_write diff --git a/libc-bottom-half/headers/private/wasi/sockets_utils.h b/libc-bottom-half/headers/private/wasi/sockets_utils.h index 396c6301..354664d9 100644 --- a/libc-bottom-half/headers/private/wasi/sockets_utils.h +++ b/libc-bottom-half/headers/private/wasi/sockets_utils.h @@ -26,6 +26,17 @@ typedef struct { }; } output_sockaddr_t; +typedef struct { + char *s_name; + uint16_t port; + uint16_t protocol; +} service_entry_t; + +typedef enum { + SERVICE_PROTOCOL_TCP = 1, + SERVICE_PROTOCOL_UDP = 2 +} service_protocol_e; + network_borrow_network_t __wasi_sockets_utils__borrow_network(); int __wasi_sockets_utils__map_error(network_error_code_t wasi_error); bool __wasi_sockets_utils__parse_address( @@ -50,5 +61,7 @@ bool __wasi_sockets_utils__stream(udp_socket_t *socket, network_error_code_t *error); void __wasi_sockets_utils__drop_streams(udp_socket_streams_t streams); int __wasi_sockets_utils__parse_port(const char *port); +const service_entry_t *__wasi_sockets_utils__get_service_entry_by_name(const char *name); +const service_entry_t *__wasi_sockets_utils__get_service_entry_by_port(const uint16_t port); #endif diff --git a/libc-bottom-half/sources/sockets_utils.c b/libc-bottom-half/sources/sockets_utils.c index d98fd02a..386a8e5c 100644 --- a/libc-bottom-half/sources/sockets_utils.c +++ b/libc-bottom-half/sources/sockets_utils.c @@ -1,11 +1,33 @@ #include #include #include +#include #include static network_own_network_t global_network; static bool global_network_initialized = false; +static const service_entry_t global_services[] = { + { "domain", 53, SERVICE_PROTOCOL_TCP | SERVICE_PROTOCOL_UDP }, + { "ftp", 21, SERVICE_PROTOCOL_TCP }, + { "ftp-data", 20, SERVICE_PROTOCOL_TCP }, + { "ftps", 990, SERVICE_PROTOCOL_TCP }, + { "ftps-data", 989, SERVICE_PROTOCOL_TCP }, + { "http", 80, SERVICE_PROTOCOL_TCP | SERVICE_PROTOCOL_UDP }, + { "https", 443, SERVICE_PROTOCOL_TCP | SERVICE_PROTOCOL_UDP }, + { "imap", 143, SERVICE_PROTOCOL_TCP }, + { "imaps", 993, SERVICE_PROTOCOL_TCP }, + { "ntp", 123, SERVICE_PROTOCOL_TCP }, + { "pop3", 110, SERVICE_PROTOCOL_TCP }, + { "pop3s", 995, SERVICE_PROTOCOL_TCP }, + { "smtp", 25, SERVICE_PROTOCOL_TCP }, + { "ssh", 22, SERVICE_PROTOCOL_TCP }, + { "submission", 587, SERVICE_PROTOCOL_TCP }, + { "submissions", 465, SERVICE_PROTOCOL_TCP }, + { "telnet", 23, SERVICE_PROTOCOL_TCP }, + { 0 }, +}; +weak_alias(global_services, __wasi_sockets_services_db); network_borrow_network_t __wasi_sockets_utils__borrow_network() { @@ -482,3 +504,33 @@ int __wasi_sockets_utils__parse_port(const char *restrict port_str) return (int)port; } + +const service_entry_t *__wasi_sockets_utils__get_service_entry_by_name(const char *name) +{ + if (!name) { + return NULL; + } + + const service_entry_t *entry = __wasi_sockets_services_db; + while(entry->s_name) { + if (strcmp(name, entry->s_name) == 0) { + return entry; + } + ++entry; + } + + return NULL; +} + +const service_entry_t *__wasi_sockets_utils__get_service_entry_by_port(const uint16_t port) +{ + const service_entry_t *entry = __wasi_sockets_services_db; + while(entry->s_name) { + if (entry->port == port) { + return entry; + } + ++entry; + } + + return NULL; +} From 6872c8e15616afe22a2f321fbabc235baa5d9387 Mon Sep 17 00:00:00 2001 From: Henri Nurmi Date: Sun, 1 Sep 2024 00:43:57 +0300 Subject: [PATCH 2/3] wasi-sockets: add service support for getaddrinfo --- libc-bottom-half/sources/netdb.c | 35 ++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/libc-bottom-half/sources/netdb.c b/libc-bottom-half/sources/netdb.c index f6b1718b..53226958 100644 --- a/libc-bottom-half/sources/netdb.c +++ b/libc-bottom-half/sources/netdb.c @@ -27,6 +27,7 @@ static int map_error(ip_name_lookup_error_code_t error) static int add_addr(ip_name_lookup_option_ip_address_t address, in_port_t port, + int socktype, const struct addrinfo *restrict hint, struct addrinfo **restrict current, struct addrinfo **restrict res) @@ -117,7 +118,7 @@ static int add_addr(ip_name_lookup_option_ip_address_t address, *result = (struct addrinfo){ .ai_family = family, .ai_flags = 0, - .ai_socktype = SOCK_STREAM, + .ai_socktype = socktype, .ai_protocol = 0, .ai_addrlen = addrlen, .ai_addr = addr, @@ -155,16 +156,19 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, ip_name_lookup_borrow_resolve_address_stream_t stream_borrow = ip_name_lookup_borrow_resolve_address_stream(stream); // The 'serv' parameter can be either a port number or a service name. - // - // TODO wasi-sockets: If the conversion of 'serv' to a valid port - // number fails, use getservbyname() to resolve the service name to - // its corresponding port number. This can be done after the - // getservbyname function is implemented.) int port = 0; + uint16_t protocol = SERVICE_PROTOCOL_TCP; if (serv != NULL) { port = __wasi_sockets_utils__parse_port(serv); if (port < 0) { - return EAI_NONAME; + const service_entry_t *service = __wasi_sockets_utils__get_service_entry_by_name(serv); + if (service) { + port = service->port; + protocol = service->protocol; + } + else { + return EAI_NONAME; + } } } while (true) { @@ -172,10 +176,19 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, if (ip_name_lookup_method_resolve_address_stream_resolve_next_address( stream_borrow, &address, &error)) { if (address.is_some) { - int error = add_addr(address, htons(port), hint, - ¤t, res); - if (error) { - return error; + if (protocol & SERVICE_PROTOCOL_TCP) { + int error = add_addr(address, htons(port), SOCK_STREAM, + hint, ¤t, res); + if (error) { + return error; + } + } + if (protocol & SERVICE_PROTOCOL_UDP) { + int error = add_addr(address, htons(port), SOCK_DGRAM, + hint, ¤t, res); + if (error) { + return error; + } } } else { return 0; From 84f6f6fbac75c46925e2ba4627553726e0438747 Mon Sep 17 00:00:00 2001 From: Henri Nurmi Date: Sun, 1 Sep 2024 10:22:10 +0300 Subject: [PATCH 3/3] wasi-sockets: implement getservbyname & getservbyport --- libc-bottom-half/sources/netdb.c | 39 ++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/libc-bottom-half/sources/netdb.c b/libc-bottom-half/sources/netdb.c index 53226958..b9c9bb08 100644 --- a/libc-bottom-half/sources/netdb.c +++ b/libc-bottom-half/sources/netdb.c @@ -7,6 +7,8 @@ _Thread_local int h_errno = 0; +static struct servent global_serv = { 0 }; + static int map_error(ip_name_lookup_error_code_t error) { switch (error) { @@ -137,6 +139,29 @@ static int add_addr(ip_name_lookup_option_ip_address_t address, return 0; } +static bool set_global_serv_entry(const service_entry_t *entry, const char *proto) { + if (!entry) { + return false; // Service not found + } + + global_serv.s_name = entry->s_name; + global_serv.s_port = htons(entry->port); + global_serv.s_aliases = NULL; + + // If proto is NULL then any protocol is matched + if ((!proto || strcmp(proto, "tcp") == 0) && entry->protocol & SERVICE_PROTOCOL_TCP) { + global_serv.s_proto = "tcp"; + } + else if ((!proto || strcmp(proto, "udp") == 0) && entry->protocol & SERVICE_PROTOCOL_UDP) { + global_serv.s_proto = "udp"; + } + else { + return false; // Protocol not supported + } + + return true; +} + int getaddrinfo(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict hint, struct addrinfo **restrict res) @@ -249,14 +274,20 @@ const char *hstrerror(int err) struct servent *getservbyname(const char *name, const char *proto) { - // TODO wasi-sockets - return NULL; + const service_entry_t *entry = __wasi_sockets_utils__get_service_entry_by_name(name); + if (!set_global_serv_entry(entry, proto)) { + return NULL; + } + return &global_serv; } struct servent *getservbyport(int port, const char *proto) { - // TODO wasi-sockets - return NULL; + const service_entry_t *entry = __wasi_sockets_utils__get_service_entry_by_port(htons(port)); + if (!set_global_serv_entry(entry, proto)) { + return NULL; + } + return &global_serv; } struct protoent *getprotobyname(const char *name)