diff options
author | Daniel P. Berrange <berrange@redhat.com> | 2016-03-08 11:39:36 +0000 |
---|---|---|
committer | Daniel P. Berrange <berrange@redhat.com> | 2016-03-10 17:10:18 +0000 |
commit | 0a27af918b9cfb7fc1605c66dfc70700be16fab5 (patch) | |
tree | 3c361913d997f0c634e031d98f491587e00ef08f /tests | |
parent | c619644067f98098dcdbc951e2dda79e97560afa (diff) | |
download | qemu-0a27af918b9cfb7fc1605c66dfc70700be16fab5.zip qemu-0a27af918b9cfb7fc1605c66dfc70700be16fab5.tar.gz qemu-0a27af918b9cfb7fc1605c66dfc70700be16fab5.tar.bz2 |
io: use bind() to check for IPv4/6 availability
Currently the test-io-channel-socket.c test uses getifaddrs
to see if an IPv4/6 address is present on any host NIC, as
a way to determine if IPv4/6 sockets can be used. This is
problematic because getifaddrs is not available on Win32.
Rather than testing indirectly via getifaddrs, just create
a socket and try to bind() to the loopback address instead.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test-io-channel-socket.c | 79 |
1 files changed, 31 insertions, 48 deletions
diff --git a/tests/test-io-channel-socket.c b/tests/test-io-channel-socket.c index 8a34056..6098fee 100644 --- a/tests/test-io-channel-socket.c +++ b/tests/test-io-channel-socket.c @@ -22,66 +22,49 @@ #include "io/channel-socket.h" #include "io/channel-util.h" #include "io-channel-helpers.h" -#ifdef HAVE_IFADDRS_H -#include <ifaddrs.h> -#endif -static int check_protocol_support(bool *has_ipv4, bool *has_ipv6) +static int check_bind(struct sockaddr *sa, socklen_t salen, bool *has_proto) { -#ifdef HAVE_IFADDRS_H - struct ifaddrs *ifaddr = NULL, *ifa; - struct addrinfo hints = { 0 }; - struct addrinfo *ai = NULL; - int gaierr; - - *has_ipv4 = *has_ipv6 = false; + int fd; - if (getifaddrs(&ifaddr) < 0) { - g_printerr("Failed to lookup interface addresses: %s\n", - strerror(errno)); + fd = socket(sa->sa_family, SOCK_STREAM, 0); + if (fd < 0) { return -1; } - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr) { - continue; - } - - if (ifa->ifa_addr->sa_family == AF_INET) { - *has_ipv4 = true; - } - if (ifa->ifa_addr->sa_family == AF_INET6) { - *has_ipv6 = true; + if (bind(fd, sa, salen) < 0) { + close(fd); + if (errno == EADDRNOTAVAIL) { + *has_proto = false; + return 0; } + return -1; } - freeifaddrs(ifaddr); - - hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_STREAM; - - gaierr = getaddrinfo("::1", NULL, &hints, &ai); - if (gaierr != 0) { - if (gaierr == EAI_ADDRFAMILY || - gaierr == EAI_FAMILY || - gaierr == EAI_NONAME) { - *has_ipv6 = false; - } else { - g_printerr("Failed to resolve ::1 address: %s\n", - gai_strerror(gaierr)); - return -1; - } - } + close(fd); + *has_proto = true; + return 0; +} - freeaddrinfo(ai); +static int check_protocol_support(bool *has_ipv4, bool *has_ipv6) +{ + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_addr = { .s_addr = htonl(INADDR_LOOPBACK) }, + }; + struct sockaddr_in6 sin6 = { + .sin6_family = AF_INET6, + .sin6_addr = IN6ADDR_LOOPBACK_INIT, + }; - return 0; -#else - *has_ipv4 = *has_ipv6 = false; + if (check_bind((struct sockaddr *)&sin, sizeof(sin), has_ipv4) < 0) { + return -1; + } + if (check_bind((struct sockaddr *)&sin6, sizeof(sin6), has_ipv6) < 0) { + return -1; + } - return -1; -#endif + return 0; } |