Actually, it wasn't much more work to get all the failing tests to pass. Version 2 of the patches attached.
J.
From 1f6b8e55807794c2466603116ae8ba9e6a50919a Mon Sep 17 00:00:00 2001 From: Jeremy Sowden <jer...@azazel.net> Date: Sun, 26 Mar 2023 14:49:09 +0100 Subject: [PATCH v2 1/2] Use ipv6 lookback address if ipv4 is not available Note that the `bind_local` parameter of `spawn_server_addr` is now ignored. It wasn't actually possible to set `hn_addr`, so passing `0` would never have worked anyway. --- test/common/child.c | 160 +++++++++++++++++++++++++++++++++++++------- test/common/child.h | 4 ++ test/utils.c | 5 +- 3 files changed, 143 insertions(+), 26 deletions(-) diff --git a/test/common/child.c b/test/common/child.c index 872fbdaddf4f..5c480def6c44 100644 --- a/test/common/child.c +++ b/test/common/child.c @@ -43,6 +43,10 @@ #include <netdb.h> #include <signal.h> +#include <ifaddrs.h> +#include <sys/types.h> +#include <string.h> + #include "ne_socket.h" #include "ne_utils.h" #include "ne_string.h" @@ -50,14 +54,23 @@ #include "tests.h" #include "child.h" +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif + static pid_t child = 0; int clength; -static struct in_addr lh_addr, hn_addr; - static int have_lh_addr; +static union { + struct sockaddr_in in; + struct sockaddr_in6 in6; +} lh_sockaddr; +static int lh_family = AF_UNSPEC; +static char lh_name[NI_MAXHOST]; + const char *want_header = NULL; got_header_fn got_header = NULL; char *local_hostname = NULL; @@ -72,13 +85,98 @@ char *local_hostname = NULL; int lookup_localhost(void) { - /* this will break if a system is set up so that `localhost' does - * not resolve to 127.0.0.1, but... */ - lh_addr.s_addr = inet_addr("127.0.0.1"); + struct ifaddrs *ifaddr; + + if (have_lh_addr) + return OK; + + if (getifaddrs(&ifaddr) == -1) + goto err_use_ipv4; + + for (struct ifaddrs *ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) + continue; + + if (strcmp(ifa->ifa_name, "lo") != 0) + continue; + + if (ifa->ifa_addr->sa_family != AF_INET && + ifa->ifa_addr->sa_family != AF_INET6) + continue; + + if (getnameinfo(ifa->ifa_addr, + ifa->ifa_addr->sa_family == AF_INET + ? sizeof(struct sockaddr_in) + : sizeof(struct sockaddr_in6), + lh_name, sizeof lh_name, + NULL, 0, + NI_NUMERICHOST)) + continue; + + memcpy(&lh_sockaddr, ifa->ifa_addr, + ifa->ifa_addr->sa_family == AF_INET + ? sizeof(lh_sockaddr.in) + : sizeof(lh_sockaddr.in6)); + + lh_family = ifa->ifa_addr->sa_family; + + if (lh_family == AF_INET) + break; + } + + freeifaddrs(ifaddr); + +err_use_ipv4: + + if (lh_family == AF_UNSPEC) { + lh_family = AF_INET; + strcpy(lh_name, "127.0.0.1"); + lh_sockaddr.in.sin_family = lh_family; + lh_sockaddr.in.sin_addr.s_addr = inet_addr(lh_name); + } + have_lh_addr = 1; return OK; } +int +get_lh_family(void) +{ + if (!have_lh_addr) + lookup_localhost(); + + return lh_family; +} + +const char * +get_lh_addr(void) +{ + if (!have_lh_addr) + lookup_localhost(); + + return lh_name; +} + +ne_inet_addr * +get_lh_inet_addr(void) +{ + ne_iaddr_type type; + unsigned char *raw; + + if (!have_lh_addr) + lookup_localhost(); + + if (lh_family == AF_INET) { + type = ne_iaddr_ipv4; + raw = (unsigned char *) &lh_sockaddr.in.sin_addr.s_addr; + } else { + type = ne_iaddr_ipv6; + raw = lh_sockaddr.in6.sin6_addr.s6_addr; + } + + return ne_iaddr_make(type, raw); +} + int lookup_hostname(void) { char buf[BUFSIZ]; @@ -101,19 +199,26 @@ int lookup_hostname(void) return OK; } -static int do_listen(struct in_addr addr, int port) +static int do_listen(int port) { - int ls = socket(AF_INET, SOCK_STREAM, 0); - struct sockaddr_in saddr = {0}; + int ls = socket(lh_family, SOCK_STREAM, 0); + struct sockaddr *saddr; + socklen_t saddrlen; int val = 1; setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int)); - - saddr.sin_addr = addr; - saddr.sin_port = htons(port); - saddr.sin_family = AF_INET; - if (bind(ls, (struct sockaddr *)&saddr, sizeof(saddr))) { + if (lh_family == AF_INET) { + lh_sockaddr.in.sin_port = htons(port); + saddr = (struct sockaddr *) &lh_sockaddr.in; + saddrlen = sizeof(lh_sockaddr.in); + } else { + lh_sockaddr.in6.sin6_port = htons(port); + saddr = (struct sockaddr *) &lh_sockaddr.in6; + saddrlen = sizeof(lh_sockaddr.in6); + } + + if (bind(ls, saddr, saddrlen)) { printf("bind failed: %s\n", strerror(errno)); return -1; } @@ -171,7 +276,7 @@ static int close_socket(ne_socket *sock) } /* This runs as the child process. */ -static int server_child(int readyfd, struct in_addr addr, int port, +static int server_child(int readyfd, int port, server_fn callback, void *userdata) { ne_socket *s = ne_sock_create(); @@ -179,7 +284,7 @@ static int server_child(int readyfd, struct in_addr addr, int port, in_child(); - listener = do_listen(addr, port); + listener = do_listen(port); if (listener < 0) return FAIL; @@ -205,9 +310,8 @@ int spawn_server(int port, server_fn fn, void *ud) int spawn_server_addr(int bind_local, int port, server_fn fn, void *ud) { int fds[2]; - struct in_addr addr; - addr = bind_local?lh_addr:hn_addr; + (void) bind_local; #ifdef USE_PIPE if (pipe(fds)) { @@ -227,7 +331,7 @@ int spawn_server_addr(int bind_local, int port, server_fn fn, void *ud) /* this is the child. */ int ret; - ret = server_child(fds[1], addr, port, fn, ud); + ret = server_child(fds[1], port, fn, ud); #ifdef USE_PIPE close(fds[0]); @@ -276,22 +380,30 @@ int new_spawn_server(int count, server_fn fn, void *userdata, int new_spawn_server2(int count, server_fn fn, void *userdata, ne_inet_addr **addr, unsigned int *port) { - struct sockaddr_in sa; + static union { + struct sockaddr_in in; + struct sockaddr_in6 in6; + } sa; socklen_t salen = sizeof sa; int ls; if (!have_lh_addr) lookup_localhost(); - ls = do_listen(lh_addr, 0); + ls = do_listen(0); ONN("could not bind/listen fd for server", ls < 0); - ONV(getsockname(ls, &sa, &salen) != 0, + ONV(getsockname(ls, (struct sockaddr *) &sa, &salen) != 0, ("could not get socket name for listening fd: %s", strerror(errno))); - - *port = ntohs(sa.sin_port); - *addr = ne_iaddr_make(ne_iaddr_ipv4, (unsigned char *)&lh_addr.s_addr); + + if (salen == sizeof(sa.in)) { + *port = ntohs(sa.in.sin_port); + *addr = ne_iaddr_make(ne_iaddr_ipv4, (void *) &sa.in.sin_addr.s_addr); + } else { + *port = ntohs(sa.in6.sin6_port); + *addr = ne_iaddr_make(ne_iaddr_ipv6, (void *) sa.in6.sin6_addr.s6_addr); + } NE_DEBUG(NE_DBG_SOCKET, "child using port %u\n", *port); diff --git a/test/common/child.h b/test/common/child.h index e34ff3b7877b..0fe66829251f 100644 --- a/test/common/child.h +++ b/test/common/child.h @@ -34,6 +34,10 @@ * named test. */ int lookup_localhost(void); +int get_lh_family(void); +const char *get_lh_addr(void); +ne_inet_addr *get_lh_inet_addr(void); + /* Test which looks up real local hostname. */ int lookup_hostname(void); diff --git a/test/utils.c b/test/utils.c index 2bf8228d88e6..8b037ec6843c 100644 --- a/test/utils.c +++ b/test/utils.c @@ -204,7 +204,8 @@ int multi_session_server(ne_session **sess, int session_server(ne_session **sess, server_fn fn, void *userdata) { - return multi_session_server(sess, "http", "127.0.0.1", 1, fn, userdata); + return multi_session_server(sess, "http", get_lh_addr(), 1, + fn, userdata); } int proxied_session_server(ne_session **sess, const char *scheme, @@ -219,7 +220,7 @@ int proxied_session_server(ne_session **sess, const char *scheme, NE_DEBUG(NE_DBG_HTTP, "test: Using proxied session to port %u.\n", port); - ne_session_proxy(*sess, "127.0.0.1", port); + ne_session_proxy(*sess, get_lh_addr(), port); return OK; } -- 2.39.2
From 876d887c4166f0e4a0a640f3e653d6fde7c00d95 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden <jer...@azazel.net> Date: Sun, 26 Mar 2023 14:49:28 +0100 Subject: [PATCH v2 2/2] Fix ipv4-related test failures Update some tests which use 127.0.0.1 and skip others where the ipv4 assumptions are not so easily fixed. --- test/request.c | 26 ++++++++++++++------------ test/socket.c | 6 +++--- test/ssl.c | 4 ++-- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/test/request.c b/test/request.c index e663d6dc557f..ddb0491af43c 100644 --- a/test/request.c +++ b/test/request.c @@ -2049,17 +2049,19 @@ static int status(void) { ne_session *sess; ne_buffer *buf = ne_buffer_create(); + const char *lh_addr = get_lh_addr(); char expect[1024]; ne_snprintf(expect, sizeof expect, - "lookup(127.0.0.1)-" - "connecting(127.0.0.1,127.0.0.1)-" - "connected(127.0.0.1)-" + "lookup(%s)-" + "connecting(%s,%s)-" + "connected(%s)-" "send(0,5000)-" "send(5000,5000)-" "recv(0,5)-" "recv(5,5)-" - "disconnected(127.0.0.1)-"); + "disconnected(%s)-", + lh_addr, lh_addr, lh_addr, lh_addr, lh_addr); CALL(make_session(&sess, single_serve_string, RESP200 "Content-Length: 5\r\n\r\n" "abcde")); @@ -2084,14 +2086,15 @@ static int status_chunked(void) { ne_session *sess; ne_buffer *buf = ne_buffer_create(); + const char *lh_addr = get_lh_addr(); char expect[1024]; /* This sequence is not exactly guaranteed by the API, but it's * what the current implementation should do. */ ne_snprintf(expect, sizeof expect, - "lookup(127.0.0.1)-" - "connecting(127.0.0.1,127.0.0.1)-" - "connected(127.0.0.1)-" + "lookup(%s)-" + "connecting(%s,%s)-" + "connected(%s)-" "send(0,5000)-" "send(5000,5000)-" "recv(0,-1)-" @@ -2100,7 +2103,8 @@ static int status_chunked(void) "recv(3,-1)-" "recv(4,-1)-" "recv(5,-1)-" - "disconnected(127.0.0.1)-"); + "disconnected(%s)-", + lh_addr, lh_addr, lh_addr, lh_addr, lh_addr); CALL(make_session(&sess, single_serve_string, RESP200 TE_CHUNKED "\r\n" ABCDE_CHUNKS)); @@ -2121,12 +2125,10 @@ static int status_chunked(void) return OK; } -static const unsigned char raw_127[4] = "\x7f\0\0\01"; /* 127.0.0.1 */ - static int local_addr(void) { ne_session *sess; - ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127); + ne_inet_addr *ia = get_lh_inet_addr(); CALL(make_session(&sess, single_serve_string, RESP200 "Connection: close\r\n\r\n")); @@ -2160,7 +2162,7 @@ static int dereg_progress(void) static int addrlist(void) { ne_session *sess; - ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127); + ne_inet_addr *ia = get_lh_inet_addr(); const ne_inet_addr *ial[1]; unsigned int port; diff --git a/test/socket.c b/test/socket.c index 566cbe156f2d..0484a46e368b 100644 --- a/test/socket.c +++ b/test/socket.c @@ -453,7 +453,7 @@ static int addr_connect(void) ne_inet_addr *ia; unsigned int port; - ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127); + ia = get_lh_inet_addr(); ONN("ne_iaddr_make returned NULL", ia == NULL); CALL(new_spawn_server(1, serve_close, NULL, &port)); @@ -470,7 +470,7 @@ static int addr_peer(void) unsigned int port = 9999, realport; int ret; - ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127); + ia = get_lh_inet_addr(); ONN("ne_iaddr_make returned NULL", ia == NULL); CALL(new_spawn_server(1, serve_close, NULL, &realport)); @@ -1331,7 +1331,7 @@ static int try_prebind(int addr, int port) char buf[128], line[256]; unsigned int srvport; - ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127); + ia = get_lh_inet_addr(); ONN("ne_iaddr_make returned NULL", ia == NULL); CALL(new_spawn_server(1, serve_ppeer, NULL, &srvport)); diff --git a/test/ssl.c b/test/ssl.c index 470521e1d29a..fc5e1bff81ab 100644 --- a/test/ssl.c +++ b/test/ssl.c @@ -971,7 +971,7 @@ static int fail_missing_CN(void) /* test for a bad ipAddress altname */ static int fail_bad_ipaltname(void) { - return fail_ssl_request("altname6.cert", CA_CERT, "127.0.0.1", + return fail_ssl_request("altname6.cert", CA_CERT, get_lh_addr(), "bad IP altname cert", NE_SSL_IDMISMATCH); } @@ -997,7 +997,7 @@ static int fail_wildcard(void) static int fail_wildcard_ip(void) { - return fail_ssl_request("wildip.cert", CA_CERT, "127.0.0.1", + return fail_ssl_request("wildip.cert", CA_CERT, get_lh_addr(), "wildcard IP", NE_SSL_IDMISMATCH); } -- 2.39.2
signature.asc
Description: PGP signature