Here are a couple of patches that seem to fix the test failures.  The
first patch updates the test-harness to use ::1 if 127.0.0.1 is not
available.  The second patch updates a few test-cases to prevent them
failing, either by changing them to work with ::1, or just skipping
them.

I've tested by running the build in a net namespace where lo doesn't
have 127.0.0.1:

  $ sudo ip netns exec ipv6test ip -4 addr show lo
  $ sudo ip netns exec ipv6test ip -6 addr show lo
  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group 
default qlen 1000
      inet6 ::1/128 scope host 
         valid_lft forever preferred_lft forever
  $ sudo ip netns exec ipv6test sudo -u $USER fakeroot debian/rules clean binary
  [...]
  make[2]: Entering directory 
'/space/azazel/tmp/neon27/debian/build-tree/neon-openssl/test'
  [...]
  rm -rf ca ca2
  OPENSSL=/usr/bin/openssl \
   /bin/bash makekeys ../../../../test 2>makekeys.out
  gzip -c --no-name ../../../../NEWS > file1.gz
  gzip -c --name ../../../../NEWS > file2.gz
  gzip -c --no-name ../../../../NEWS > trailing.gz
  echo "hello, world" >> trailing.gz
  dd of=badcsum.gz if=file1.gz bs=1 count=`perl -e 'printf "%d", 
(stat("file1.gz"))[7] - 8;'`
  25010+0 records in
  25010+0 records out
  25010 bytes (25 kB, 24 KiB) copied, 0.0247032 s, 1.0 MB/s
  echo 'broken!' >> badcsum.gz
  dd if=file1.gz of=truncated.gz bs=2048 count=2
  2+0 records in
  2+0 records out
  4096 bytes (4.1 kB, 4.0 KiB) copied, 3.8031e-05 s, 108 MB/s
  dd of=corrupt1.gz if=file1.gz bs=1 count=500
  500+0 records in
  500+0 records out
  500 bytes copied, 0.000968376 s, 516 kB/s
  cat ../../../../NEWS >> corrupt1.gz
  cat ../../../../NEWS > corrupt2.gz
  touch empty.gz
  cat ../../../../NEWS > random.txt
  echo hello world > hello.txt
  gzip -c hello.txt > hello.gz
  echo foobar > foobar.txt
  ../../../../test/run.sh: line 5: ulimit: core file size: cannot modify limit: 
Operation not permitted
  uri-tests............. 15/15 passed
  util-tests............  9/ 9 passed
  string-tests.......... 32/32 passed
  socket................ 10/47 SKIPPED - addr_connect
  socket................ 11/47 SKIPPED - addr_peer
  socket................ 36/47 SKIPPED - prebind
  socket................ 44/47 passed (3 skipped)
  session...............  8/ 8 passed
  request............... 82/92 SKIPPED - local_addr
  request............... 84/92 SKIPPED - addrlist
  request............... 90/92 passed (2 skipped)
  auth.................. 21/21 passed
  basic................. 11/11 passed
  stubs.................  1/ 1 passed
  redirect..............  6/ 6 passed
  socket-ssl............ 11/48 SKIPPED - addr_connect
  socket-ssl............ 12/48 SKIPPED - addr_peer
  socket-ssl............ 22/48 SKIPPED - ssl_session_id (zero-length session 
ID, cannot test further)
  socket-ssl............ 37/48 SKIPPED - prebind
  socket-ssl............ 44/48 passed (4 skipped)
  ssl................... 62/63 WARNING: NSS required for PKCS#11 testing
  ssl................... 62/63 SKIPPED - pkcs11
  ssl................... 63/63 WARNING: NSS required for PKCS#11 testing
  ssl................... 63/63 SKIPPED - pkcs11_dsa
  ssl................... 61/63 passed (2 skipped) (2 warnings)
  compress.............. 22/22 passed
  xml...................  5/ 5 passed
  xmlreq................  3/ 3 passed
  oldacl................  4/ 4 passed
  acl3744...............  4/ 4 passed
  props.................  7/ 7 passed
  lock.................. 16/16 passed
  make[2]: Leaving directory 
'/space/azazel/tmp/neon27/debian/build-tree/neon-openssl/test'
  [...]
  make[2]: Entering directory 
'/space/azazel/tmp/neon27/debian/build-tree/neon-gnutls/test'
  [...]
  rm -rf ca ca2
  OPENSSL=/usr/bin/openssl \
   /bin/bash makekeys ../../../../test 2>makekeys.out
  gzip -c --no-name ../../../../NEWS > file1.gz
  gzip -c --name ../../../../NEWS > file2.gz
  gzip -c --no-name ../../../../NEWS > trailing.gz
  echo "hello, world" >> trailing.gz
  dd of=badcsum.gz if=file1.gz bs=1 count=`perl -e 'printf "%d", 
(stat("file1.gz"))[7] - 8;'`
  25010+0 records in
  25010+0 records out
  25010 bytes (25 kB, 24 KiB) copied, 0.0250625 s, 998 kB/s
  echo 'broken!' >> badcsum.gz
  dd if=file1.gz of=truncated.gz bs=2048 count=2
  2+0 records in
  2+0 records out
  4096 bytes (4.1 kB, 4.0 KiB) copied, 4.0065e-05 s, 102 MB/s
  dd of=corrupt1.gz if=file1.gz bs=1 count=500
  500+0 records in
  500+0 records out
  500 bytes copied, 0.000531978 s, 940 kB/s
  cat ../../../../NEWS >> corrupt1.gz
  cat ../../../../NEWS > corrupt2.gz
  touch empty.gz
  cat ../../../../NEWS > random.txt
  echo hello world > hello.txt
  gzip -c hello.txt > hello.gz
  echo foobar > foobar.txt
  ../../../../test/run.sh: line 5: ulimit: core file size: cannot modify limit: 
Operation not permitted
  uri-tests............. 15/15 passed
  util-tests............  9/ 9 passed
  string-tests.......... 31/32 SKIPPED - strhash_sha_512_256 (SHA-2-512/256 not 
supported)
  string-tests.......... 31/32 passed (1 skipped)
  socket................ 10/47 SKIPPED - addr_connect
  socket................ 11/47 SKIPPED - addr_peer
  socket................ 36/47 SKIPPED - prebind
  socket................ 44/47 passed (3 skipped)
  session...............  8/ 8 passed
  request............... 82/92 SKIPPED - local_addr
  request............... 84/92 SKIPPED - addrlist
  request............... 90/92 passed (2 skipped)
  auth..................  9/21 SKIPPED - digest_sha512_256 (SHA-512/256 not 
supported)
  auth.................. 20/21 passed (1 skipped)
  basic................. 11/11 passed
  stubs.................  1/ 1 passed
  redirect..............  6/ 6 passed
  socket-ssl............ 11/48 SKIPPED - addr_connect
  socket-ssl............ 12/48 SKIPPED - addr_peer
  socket-ssl............ 37/48 SKIPPED - prebind
  socket-ssl............ 45/48 passed (3 skipped)
  ssl................... 13/63 WARNING: no friendly name given
  ssl................... 62/63 WARNING: NSS required for PKCS#11 testing
  ssl................... 62/63 SKIPPED - pkcs11
  ssl................... 63/63 WARNING: NSS required for PKCS#11 testing
  ssl................... 63/63 SKIPPED - pkcs11_dsa
  ssl................... 61/63 passed (2 skipped) (3 warnings)
  compress.............. 22/22 passed
  xml...................  5/ 5 passed
  xmlreq................  3/ 3 passed
  oldacl................  4/ 4 passed
  acl3744...............  4/ 4 passed
  props.................  7/ 7 passed
  lock.................. 16/16 passed
  make[2]: Leaving directory 
'/space/azazel/tmp/neon27/debian/build-tree/neon-gnutls/test'
  [...]

J.
From aaa0f2d4f6f50878e9320c29a920ae2aa4830b76 Mon Sep 17 00:00:00 2001
From: Jeremy Sowden <jer...@azazel.net>
Date: Sun, 26 Mar 2023 14:49:09 +0100
Subject: [PATCH 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 | 134 ++++++++++++++++++++++++++++++++++++--------
 test/common/child.h |   3 +
 test/utils.c        |   5 +-
 3 files changed, 116 insertions(+), 26 deletions(-)

diff --git a/test/common/child.c b/test/common/child.c
index 872fbdaddf4f..7ff7ba8fe67a 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,72 @@ 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 (getifaddrs(&ifaddr) == -1)
+	goto err_return_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_return_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;
 }
 
+const char *
+get_lo_addr(void)
+{
+    if (!have_lh_addr)
+	lookup_localhost();
+
+    return lh_name;
+}
+
+int
+get_lo_family(void)
+{
+    return lh_family;
+}
+
 int lookup_hostname(void)
 {
     char buf[BUFSIZ];
@@ -101,19 +173,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_INET6) {
+	    lh_sockaddr.in6.sin6_port = htons(port);
+	    saddr = (struct sockaddr *) &lh_sockaddr.in6;
+	    saddrlen = sizeof(lh_sockaddr.in6);
+    } else {
+	    lh_sockaddr.in.sin_port = htons(port);
+	    saddr = (struct sockaddr *) &lh_sockaddr.in;
+	    saddrlen = sizeof(lh_sockaddr.in);
+    }
+
+    if (bind(ls, saddr, saddrlen)) {
 	printf("bind failed: %s\n", strerror(errno));
 	return -1;
     }
@@ -171,7 +250,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 +258,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 +284,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 +305,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 +354,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..f3fdcdc3dac9 100644
--- a/test/common/child.h
+++ b/test/common/child.h
@@ -34,6 +34,9 @@
  * named test. */
 int lookup_localhost(void);
 
+const char *get_lo_addr(void);
+int get_lo_family(void);
+
 /* Test which looks up real local hostname. */
 int lookup_hostname(void);
 
diff --git a/test/utils.c b/test/utils.c
index 2bf8228d88e6..2006c77ffcbd 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_lo_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_lo_addr(), port);
 
     return OK;
 }
-- 
2.39.2

From 5cb7edbb2751edf982aea6fc95d4897b5de03a0b Mon Sep 17 00:00:00 2001
From: Jeremy Sowden <jer...@azazel.net>
Date: Sun, 26 Mar 2023 14:49:28 +0100
Subject: [PATCH 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 | 27 +++++++++++++++++++--------
 test/socket.c  |  9 +++++++++
 test/ssl.c     |  4 ++--
 3 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/test/request.c b/test/request.c
index e663d6dc557f..a5edd7ea99db 100644
--- a/test/request.c
+++ b/test/request.c
@@ -20,6 +20,7 @@
 
 #include "config.h"
 
+#include <arpa/inet.h>
 #include <sys/types.h>
 
 #include <time.h> /* for time() */
@@ -2050,16 +2051,18 @@ static int status(void)
     ne_session *sess;
     ne_buffer *buf = ne_buffer_create();
     char expect[1024];
+    const char *lo_addr = get_lo_addr();
 
     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)-",
+                lo_addr, lo_addr, lo_addr, lo_addr, lo_addr);
 
     CALL(make_session(&sess, single_serve_string, RESP200
                       "Content-Length: 5\r\n\r\n" "abcde"));
@@ -2085,13 +2088,14 @@ static int status_chunked(void)
     ne_session *sess;
     ne_buffer *buf = ne_buffer_create();
     char expect[1024];
+    const char *lo_addr = get_lo_addr();
 
     /* 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 +2104,8 @@ static int status_chunked(void)
                 "recv(3,-1)-"
                 "recv(4,-1)-"
                 "recv(5,-1)-"
-                "disconnected(127.0.0.1)-");
+                "disconnected(%s)-",
+                lo_addr, lo_addr, lo_addr, lo_addr, lo_addr);
 
     CALL(make_session(&sess, single_serve_string, 
                       RESP200 TE_CHUNKED "\r\n" ABCDE_CHUNKS));
@@ -2128,6 +2133,9 @@ static int local_addr(void)
     ne_session *sess;
     ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
 
+    if(get_lo_family() != AF_INET)
+	    return SKIP;
+
     CALL(make_session(&sess, single_serve_string, RESP200 
                       "Connection: close\r\n\r\n"));
 
@@ -2164,6 +2172,9 @@ static int addrlist(void)
     const ne_inet_addr *ial[1];
     unsigned int port;
 
+    if(get_lo_family() != AF_INET)
+	    return SKIP;
+
     CALL(new_spawn_server(1, single_serve_string, EMPTY_RESP, &port));
     sess = ne_session_create("http", "www.example.com", port);
 
diff --git a/test/socket.c b/test/socket.c
index 566cbe156f2d..0b4c9a469676 100644
--- a/test/socket.c
+++ b/test/socket.c
@@ -453,6 +453,9 @@ static int addr_connect(void)
     ne_inet_addr *ia;
     unsigned int port;
 
+    if (get_lo_family() != AF_INET)
+	    return SKIP;
+
     ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
     ONN("ne_iaddr_make returned NULL", ia == NULL);
     
@@ -470,6 +473,9 @@ static int addr_peer(void)
     unsigned int port = 9999, realport;
     int ret;
 
+    if (get_lo_family() != AF_INET)
+	    return SKIP;
+
     ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
     ONN("ne_iaddr_make returned NULL", ia == NULL);
     
@@ -1367,6 +1373,9 @@ static int try_prebind(int addr, int port)
 
 static int prebind(void)
 {
+    if(get_lo_family() != AF_INET)
+	return SKIP;
+
     CALL(try_prebind(1, 0));
     CALL(try_prebind(0, 1));
     CALL(try_prebind(1, 1));
diff --git a/test/ssl.c b/test/ssl.c
index 470521e1d29a..da0f706dc349 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_lo_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_lo_addr(),
                             "wildcard IP", NE_SSL_IDMISMATCH);
 }
 
-- 
2.39.2

Attachment: signature.asc
Description: PGP signature

Reply via email to