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 <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2015-05-21 16:27:15 +01:00
parent d587704cc7
commit 43c0a84cda
4 changed files with 72 additions and 34 deletions

View File

@ -172,6 +172,7 @@ virNetServerServiceToggle;
# rpc/virnetsocket.h
virNetSocketAccept;
virNetSocketAddIOCallback;
virNetSocketCheckProtocols;
virNetSocketClose;
virNetSocketDupFD;
virNetSocketGetFD;

View File

@ -29,6 +29,9 @@
#include <sys/wait.h>
#include <signal.h>
#include <fcntl.h>
#ifdef HAVE_IFADDRS_H
# include <ifaddrs.h>
#endif
#include <netdb.h>
#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,

View File

@ -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,

View File

@ -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;