wasi-libc/libc-bottom-half
Henri Nurmi 1b19fc65ad
getaddrinfo: improve the service/port resolution (#524)
Hello,

While experimenting with the `wasm32-wasip2` target and CPython, I
discovered an issue with the `getaddrinfo()` implementation: it fails to
resolve the provided service into a port number, causing `sin_port` to
always be set to 0. This issue leads to failures in network-related
functions that rely on `getaddrinfo()`, such as Python's `urllib3`
library, which passes the result directly to `connect()`. This results
in connection attempts using a port value of 0, which naturally fails.

### Minimal example to reproduce the problem
```c
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>

int main(void) {
    struct addrinfo *res = NULL;
    getaddrinfo("google.com", "443", NULL, &res);

    for (struct addrinfo *i = res; i != NULL; i = i->ai_next) {
        char str[INET6_ADDRSTRLEN];
        if (i->ai_addr->sa_family == AF_INET) {
            struct sockaddr_in *p = (struct sockaddr_in *)i->ai_addr;
            int port = ntohs(p->sin_port);
            printf("%s: %i\n", inet_ntop(AF_INET, &p->sin_addr, str, sizeof(str)), port);
        } else if (i->ai_addr->sa_family == AF_INET6) {
            struct sockaddr_in6 *p = (struct sockaddr_in6 *)i->ai_addr;
            int port = ntohs(p->sin6_port);
            printf("%s: %i\n", inet_ntop(AF_INET6, &p->sin6_addr, str, sizeof(str)), port);
        }
    }

    return 0;
}
```
```
$ /opt/wasi-sdk/bin/clang -target wasm32-wasip2 -o foo foo.c
$ wasmtime run -S allow-ip-name-lookup=y foo
216.58.211.238: 0
2a00:1450:4026:808::200e: 0
```
Expected output:
```
216.58.211.238: 443
2a00:1450:4026:808::200e: 443
```
### Root Cause

The root cause is that `getaddrinfo()` does not correctly translate the
provided service into a port number. As described in the `getaddrinfo()`
man [page](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html),
the function should:

> service sets the port in each returned address structure. If
this argument is a service name (see
[services(5)](https://man7.org/linux/man-pages/man5/services.5.html)),
it is
translated to the corresponding port number. This argument can
also be specified as a decimal number, which is simply converted
to binary. If service is NULL, then the port number of the
returned socket addresses will be left uninitialized.

### Proposed Fix

This pull request addresses the issue by implementing the following
behavior for `getaddrinfo()`:

* If the service is `NULL`, the port number in the returned socket
addresses remains uninitialized.
* The value is converted to an integer and validated if the service is
numeric.

The PR does not currently add support for translating named services
into port numbers because `getservbyname()` has not been implemented. In
cases where a named service is provided, the `EAI_NONAME` error code is
returned.
2024-08-27 17:39:34 -07:00
..
clocks times should always return 0 for tms_cutime (#510) 2024-07-02 22:46:25 -07:00
cloudlibc wasip2 support for close, poll, pselect (#486) 2024-03-27 12:24:10 -07:00
crt crt1-command.c: fix whitespace issues (#480) 2024-03-11 17:04:46 -07:00
getpid Implement emulated support for getpid. 2021-04-05 16:58:36 -07:00
headers getaddrinfo: improve the service/port resolution (#524) 2024-08-27 17:39:34 -07:00
mman Extend wasi-emulated-mman with mprotect. (#500) 2024-05-22 10:09:22 -07:00
signal Fix typo in signal.c error messages (#437) 2023-09-27 08:42:02 -07:00
sources getaddrinfo: improve the service/port resolution (#524) 2024-08-27 17:39:34 -07:00
README.md Merge the basics component into libc-bottom-half. (#199) 2020-06-01 16:44:05 -07:00

WASI libc "bottom half".

The WASI libc "bottom half" is conceptually the lower half of a traditional libc implementation, consisting of C interfaces to the low-level WASI syscalls.

This implementation is partially derived from the "bottom half" of cloudlibc, revision 8835639f27fc42d32096d59d294a0bbb857dc368.

This implementation includes preopen functionality, which emulates POSIX APIs accepting absolute paths by translating them into pre-opened directory handles and relative paths that can be opened with openat. This technique is inspired by libpreopen, however the implementation here is designed to be built into libc rather than to be a layer on top of libc.

The WASI libc lower half currently depends on the dlmalloc component.