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;