[ccan] [PATCH] net: fix tests on hosts where 'localhost' is v4 _and_ v6
Sam Vilain
sam at vilain.net
Sun Feb 6 14:46:41 EST 2011
If 'localhost' exists in /etc/hosts with a v4 and a v6 address, the hack
which joins two addrinfo entries together is not necessary. Detect to see
if 'localhost' returned a v6 address, and if so, just return the single
linked list result from getaddrinfo()
Signed-off-by: Sam Vilain <sam at vilain.net>
---
ccan/net/test/run.c | 75 ++++++++++++++++++++++++++++++++++----------------
1 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/ccan/net/test/run.c b/ccan/net/test/run.c
index 2e241cb..fe2ff99 100644
--- a/ccan/net/test/run.c
+++ b/ccan/net/test/run.c
@@ -42,52 +42,81 @@ static unsigned int server(int protocol, int type)
? addr.ipv4.sin_port : addr.ipv6.sin6_port);
}
-int main(void)
+static bool we_faked_double = false;
+
+/* some systems (eg Ubuntu) already have 'localhost' defined as both
+ ipv6 and ipv4; our first lookup might return two addresses. Given
+ this is the situation we are trying to support, allow it to happen
+ before looking up the 'ip6-localhost' name and faking it. */
+static struct addrinfo* double_addr_lookup(char* buf)
{
struct addrinfo *addr, *addr2;
+ addr = net_client_lookup("localhost", buf, AF_UNSPEC, SOCK_STREAM);
+ ok1(addr);
+ addr2 = addr;
+ while (addr2) {
+ /* assume that we're not running on a v6-only stack */
+ if (addr2->ai_family == AF_INET6) {
+ goto out;
+ }
+ }
+ /* 'localhost' didn't resolve to a v6 address; try
+ * 'ip6-localhost' */
+ addr2 = net_client_lookup("ip6-localhost", buf,
+ AF_UNSPEC, SOCK_STREAM);
+ ok1(addr2);
+
+ /* Join them as if they were from one lookup. */
+ addr->ai_next = addr2;
+ we_faked_double = true;
+
+out:
+ return addr;
+}
+
+static void double_addr_free(struct addrinfo* addr)
+{
+ struct addrinfo *addr2;
+ if (we_faked_double) {
+ addr2 = addr->ai_next;
+ addr->ai_next = NULL;
+ }
+ freeaddrinfo(addr);
+ if (we_faked_double)
+ freeaddrinfo(addr);
+}
+
+int main(void)
+{
+ struct addrinfo *addr;
int fd, status;
struct sockaddr saddr;
socklen_t slen = sizeof(saddr);
char buf[20];
unsigned int port;
- plan_tests(16);
+ plan_tests(14);
port = server(AF_INET, SOCK_STREAM);
sprintf(buf, "%u", port);
- addr = net_client_lookup("localhost", buf, AF_UNSPEC, SOCK_STREAM);
- addr2 = net_client_lookup("ip6-localhost", buf,
- AF_UNSPEC, SOCK_STREAM);
- ok1(addr);
- ok1(addr2);
- /* Join them as if they were from one lookup. */
- addr->ai_next = addr2;
-
+ addr = double_addr_lookup(buf);
fd = net_connect(addr);
ok1(fd >= 0);
ok1(getsockname(fd, &saddr, &slen) == 0);
+ diag("family = %d", saddr.sa_family);
ok1(saddr.sa_family == AF_INET);
status = read(fd, buf, sizeof(buf));
ok(status == strlen("Yay!"),
"Read returned %i (%s)", status, strerror(errno));
ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
close(fd);
- addr->ai_next = NULL;
- freeaddrinfo(addr);
- freeaddrinfo(addr2);
+ double_addr_free(addr);
port = server(AF_INET6, SOCK_STREAM);
sprintf(buf, "%u", port);
- addr = net_client_lookup("localhost", buf, AF_UNSPEC, SOCK_STREAM);
- addr2 = net_client_lookup("ip6-localhost", buf,
- AF_UNSPEC, SOCK_STREAM);
- ok1(addr);
- ok1(addr2);
- /* Join them as if they were from one lookup. */
- addr->ai_next = addr2;
-
+ addr = double_addr_lookup(buf);
fd = net_connect(addr);
ok1(fd >= 0);
@@ -98,9 +127,7 @@ int main(void)
"Read returned %i (%s)", status, strerror(errno));
ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
close(fd);
- addr->ai_next = NULL;
- freeaddrinfo(addr);
- freeaddrinfo(addr2);
+ double_addr_free(addr);
wait(&status);
ok1(WIFEXITED(status));
--
1.7.0.4
More information about the ccan
mailing list