Go to file
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
.github/workflows Add libsetjmp.a/so (#483) 2024-04-01 15:36:28 -07:00
dlmalloc dlmalloc: account the footprint of the initial heap (#496) 2024-05-17 10:53:56 -07:00
emmalloc emmalloc: use __heap_end instead of sbrk(0) (#462) 2024-01-10 13:31:37 -08:00
expected getaddrinfo: improve the service/port resolution (#524) 2024-08-27 17:39:34 -07:00
libc-bottom-half getaddrinfo: improve the service/port resolution (#524) 2024-08-27 17:39:34 -07:00
libc-top-half fix shared library build with llvm-19 (#526) 2024-08-27 17:01:21 -07:00
test implement basic TCP/UDP client support (#477) 2024-03-13 10:59:27 -07:00
tools/wasi-headers build: update WASI and partially regenerate api.h 2022-04-20 13:39:57 -07:00
.gitattributes Correct the version of #136 on master (#141) 2019-11-21 20:55:26 -08:00
.gitignore gitignore build 2019-04-19 11:16:25 -07:00
.gitmodules Correct the version of #136 on master (#141) 2019-11-21 20:55:26 -08:00
CODE_OF_CONDUCT.md Add a CODE_OF_CONDUCT.md file. (#101) 2019-10-03 14:15:49 +02:00
LICENSE Beginning porting Emscripten's emmalloc to wasi-libc. 2022-11-01 12:54:26 -07:00
LICENSE-APACHE Multi-license wasi-libc under Apache and MIT licenses. (#174) 2020-02-29 10:52:28 +01:00
LICENSE-APACHE-LLVM Multi-license wasi-libc under Apache and MIT licenses. (#174) 2020-02-29 10:52:28 +01:00
LICENSE-MIT Multi-license wasi-libc under Apache and MIT licenses. (#174) 2020-02-29 10:52:28 +01:00
linker-provided-symbols.txt fix shared library build with llvm-19 (#526) 2024-08-27 17:01:21 -07:00
Makefile fix shared library build with llvm-19 (#526) 2024-08-27 17:01:21 -07:00
README.md Remove trailing backtick in README.md (#455) 2023-12-17 18:06:16 -08:00

wasi-libc

wasi-libc is a libc for WebAssembly programs built on top of WASI system calls. It provides a wide array of POSIX-compatible C APIs, including support for standard I/O, file I/O, filesystem manipulation, memory management, time, string, environment variables, program startup, and many other APIs.

wasi-libc is sufficiently stable and usable for many purposes, as most of the POSIX-compatible APIs are stable, though it is continuing to evolve to better align with wasm and WASI. For example, pthread support is experimentally provided via the wasi-threads proposal.

Usage

The easiest way to get started with this is to use wasi-sdk, which includes a build of wasi-libc in its sysroot.

Building from source

To build a WASI sysroot from source, obtain a WebAssembly-supporting C compiler (currently this is only clang 10+, though we'd like to support other compilers as well), and then run:

make CC=/path/to/clang/with/wasm/support \
     AR=/path/to/llvm-ar \
     NM=/path/to/llvm-nm

This makes a directory called "sysroot" by default. See the top of the Makefile for customization options.

To use the sysroot, use the --sysroot= option:

/path/to/wasm/supporting/c/compiler --sysroot=/path/to/the/newly/built/sysroot ...

to run the compiler using the newly built sysroot.

Note that Clang packages typically don't include cross-compiled builds of compiler-rt, libcxx, or libcxxabi, for libclang_rt.builtins-wasm32.a, libc++.a, or libc++abi.a, respectively, so they may not be usable without extra setup. This is one of the things wasi-sdk simplifies, as it includes cross-compiled builds of compiler-rt, libc++.a, and libc++abi.a.

Building in pthread support

To enable pthreads support via the wasi-threads proposal, follow the above build directions with one addition: make ... THREAD_MODEL=posix. This creates additional artifacts in sysroot/lib/wasm32-wasi-threads to support --target wasm32-wasi-threads.

Arch Linux AUR package

For Arch Linux users, there's an official wasi-libc package tracking this Git repository. You might want to install other WASI related packages as well.