From 43c0a84cdab7479bc0bf83d0c99cd7c7ebc98841 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 21 May 2015 16:27:15 +0100 Subject: [PATCH] rpc: add API for checking IPv4/6 availability The socket test suite has a function for checking if IPv4 or IPv6 are available, and returning a free socket. The first bit of that will be needed in another test, so pull that logic out into a separate helper method. Signed-off-by: Daniel P. Berrange --- src/libvirt_remote.syms | 1 + src/rpc/virnetsocket.c | 66 ++++++++++++++++++++++++++++++++++++++++ src/rpc/virnetsocket.h | 3 ++ tests/virnetsockettest.c | 36 ++-------------------- 4 files changed, 72 insertions(+), 34 deletions(-) diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms index 0d650b6b27..bdd68f63e9 100644 --- a/src/libvirt_remote.syms +++ b/src/libvirt_remote.syms @@ -172,6 +172,7 @@ virNetServerServiceToggle; # rpc/virnetsocket.h virNetSocketAccept; virNetSocketAddIOCallback; +virNetSocketCheckProtocols; virNetSocketClose; virNetSocketDupFD; virNetSocketGetFD; diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index d9f3e11b0f..2497f674ce 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -29,6 +29,9 @@ #include #include #include +#ifdef HAVE_IFADDRS_H +# include +#endif #include #ifdef HAVE_NETINET_TCP_H @@ -142,6 +145,69 @@ static int virNetSocketForkDaemon(const char *binary) } #endif +int virNetSocketCheckProtocols(bool *hasIPv4, + bool *hasIPv6) +{ +#ifdef HAVE_IFADDRS_H + struct ifaddrs *ifaddr = NULL, *ifa; + struct addrinfo hints; + struct addrinfo *ai = NULL; + int ret = -1; + int gaierr; + + memset(&hints, 0, sizeof(hints)); + + *hasIPv4 = *hasIPv6 = false; + + if (getifaddrs(&ifaddr) < 0) { + virReportSystemError(errno, "%s", + _("Cannot get host interface addresses")); + goto cleanup; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) + continue; + + if (ifa->ifa_addr->sa_family == AF_INET) + *hasIPv4 = true; + if (ifa->ifa_addr->sa_family == AF_INET6) + *hasIPv6 = true; + } + + freeifaddrs(ifaddr); + + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + + if ((gaierr = getaddrinfo("::1", NULL, &hints, &ai)) != 0) { + if (gaierr == EAI_ADDRFAMILY || + gaierr == EAI_FAMILY) { + *hasIPv6 = false; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot resolve ::1 address: %s"), + gai_strerror(gaierr)); + goto cleanup; + } + } + + freeaddrinfo(ai); + + VIR_DEBUG("Protocols: v4 %d v6 %d\n", *hasIPv4, *hasIPv6); + + ret = 0; + cleanup: + return ret; +#else + *hasIPv4 = *hasIPv6 = false; + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("Cannot check address family on this platform")); + return -1; +#endif +} + static virNetSocketPtr virNetSocketNew(virSocketAddrPtr localAddr, virSocketAddrPtr remoteAddr, diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h index a8ff8a9e48..5de3d92631 100644 --- a/src/rpc/virnetsocket.h +++ b/src/rpc/virnetsocket.h @@ -45,6 +45,9 @@ typedef void (*virNetSocketIOFunc)(virNetSocketPtr sock, void *opaque); +int virNetSocketCheckProtocols(bool *hasIPv4, + bool *hasIPv6); + int virNetSocketNewListenTCP(const char *nodename, const char *service, int family, diff --git a/tests/virnetsockettest.c b/tests/virnetsockettest.c index f609484c20..1ababad9c5 100644 --- a/tests/virnetsockettest.c +++ b/tests/virnetsockettest.c @@ -48,47 +48,15 @@ static int checkProtocols(bool *hasIPv4, bool *hasIPv6, int *freePort) { - struct ifaddrs *ifaddr = NULL, *ifa; - struct addrinfo hints; - struct addrinfo *ai = NULL; struct sockaddr_in in4; struct sockaddr_in6 in6; int s4 = -1, s6 = -1; size_t i; int ret = -1; - memset(&hints, 0, sizeof(hints)); - - *hasIPv4 = *hasIPv6 = false; *freePort = 0; - - if (getifaddrs(&ifaddr) < 0) { - perror("getifaddrs"); - goto cleanup; - } - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr) - continue; - - if (ifa->ifa_addr->sa_family == AF_INET) - *hasIPv4 = true; - if (ifa->ifa_addr->sa_family == AF_INET6) - *hasIPv6 = true; - } - - hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_STREAM; - - if (getaddrinfo("::1", "5672", &hints, &ai) != 0) - *hasIPv6 = false; - - freeaddrinfo(ai); - - VIR_DEBUG("Protocols: v4 %d v6 %d\n", *hasIPv4, *hasIPv6); - - freeifaddrs(ifaddr); + if (virNetSocketCheckProtocols(hasIPv4, hasIPv6) < 0) + return -1; for (i = 0; i < 50; i++) { int only = 1;