X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fnet%2Ftest%2Frun.c;h=d7f6c95a040dc8814cd301e8ab2eaf37103cec29;hp=57fc985554ec7b5bbc4c157c00df9c13bc42b61a;hb=37e247dbcb57f4b2effd44b37b96dc679ee525d0;hpb=708b846815c758645cf19f905513c67f7a024491 diff --git a/ccan/net/test/run.c b/ccan/net/test/run.c index 57fc9855..d7f6c95a 100644 --- a/ccan/net/test/run.c +++ b/ccan/net/test/run.c @@ -43,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)); @@ -99,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));