Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasi-sockets: Add services database and implement getservbyname/getservbyport functions #532

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions expected/wasm32-wasip2/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions libc-bottom-half/headers/private/wasi/sockets_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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
74 changes: 59 additions & 15 deletions libc-bottom-half/sources/netdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -27,6 +29,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)
Expand Down Expand Up @@ -117,7 +120,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,
Expand All @@ -136,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)
Expand All @@ -155,27 +181,39 @@ 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) {
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, htons(port), hint,
&current, res);
if (error) {
return error;
if (protocol & SERVICE_PROTOCOL_TCP) {
int error = add_addr(address, htons(port), SOCK_STREAM,
hint, &current, res);
if (error) {
return error;
}
}
if (protocol & SERVICE_PROTOCOL_UDP) {
int error = add_addr(address, htons(port), SOCK_DGRAM,
hint, &current, res);
if (error) {
return error;
}
}
} else {
return 0;
Expand Down Expand Up @@ -236,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)
Expand Down
52 changes: 52 additions & 0 deletions libc-bottom-half/sources/sockets_utils.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#include <wasi/sockets_utils.h>

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()
{
Expand Down Expand Up @@ -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;
}