X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fnet%2Ftest%2Frun.c;h=d7f6c95a040dc8814cd301e8ab2eaf37103cec29;hp=2e241cbb40ea864b6bee5e4124c2a9fb9dacb966;hb=502fa86836da59f1534e0a37f2f516334ed35866;hpb=04a42d50a02645aca83d7dc02d8e9838540e818d diff --git a/ccan/net/test/run.c b/ccan/net/test/run.c index 2e241cbb..d7f6c95a 100644 --- a/ccan/net/test/run.c +++ b/ccan/net/test/run.c @@ -3,6 +3,7 @@ #include #include #include +#include #include static unsigned int server(int protocol, int type) @@ -42,55 +43,102 @@ 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; + +/* Get a localhost on ipv4 and IPv6. Fake it if we have to. */ +static struct addrinfo* double_addr_lookup(char* buf) { struct addrinfo *addr, *addr2; + + addr = net_client_lookup("localhost", buf, AF_UNSPEC, SOCK_STREAM); + if (!addr) + return addr; + + /* If we only got one, we need to fake up the other one. */ + if (addr->ai_next) { + addr2 = addr->ai_next; + } else { + we_faked_double = true; + + /* OK, IPv4 only? */ + if (addr->ai_family == AF_INET) { + /* These are the names I found on my Ubuntu system. */ + addr2 = net_client_lookup("ip6-localhost", buf, + AF_UNSPEC, SOCK_STREAM); + if (!addr2) + addr2 = net_client_lookup("localhost6", buf, + AF_UNSPEC, + SOCK_STREAM); + } else if (addr->ai_family == AF_INET6) + /* IPv6 only? This is a guess... */ + addr2 = net_client_lookup("ip4-localhost", buf, + AF_UNSPEC, SOCK_STREAM); + if (!addr2) + return NULL; + addr->ai_next = addr2; + } + + /* More than two? */ + if (addr2->ai_next) + return NULL; + /* One IPv4 and one IPv6? */ + if (addr->ai_family == AF_INET && addr2->ai_family == AF_INET6) + return addr; + if (addr->ai_family == AF_INET6 && addr2->ai_family == AF_INET) + return addr; + return NULL; +} + +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(addr2); +} + +int main(void) +{ + struct addrinfo *addr; int fd, status; struct sockaddr saddr; - socklen_t slen = sizeof(saddr); + socklen_t slen; 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); + addr = double_addr_lookup(buf); ok1(addr); - ok1(addr2); - /* Join them as if they were from one lookup. */ - addr->ai_next = addr2; - fd = net_connect(addr); ok1(fd >= 0); + slen = sizeof(saddr); 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); + addr = double_addr_lookup(buf); ok1(addr); - ok1(addr2); - /* Join them as if they were from one lookup. */ - addr->ai_next = addr2; - fd = net_connect(addr); ok1(fd >= 0); + slen = sizeof(saddr); ok1(getsockname(fd, &saddr, &slen) == 0); ok1(saddr.sa_family == AF_INET6); status = read(fd, buf, sizeof(buf)); @@ -98,9 +146,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));