Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information