diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 59593f9d64..a7903c3deb 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -33,6 +33,10 @@ #include "virstring.h" #include "virutil.h" +#if HAVE_GETIFADDRS +# include +#endif + #include #include #include @@ -1435,6 +1439,70 @@ virNetDevGetIPv4AddressIoctl(const char *ifname ATTRIBUTE_UNUSED, #endif /* ! SIOCGIFADDR */ +/** + * virNetDevGetifaddrsAddress: + * @ifname: name of the interface whose IP address we want + * @addr: filled with the IP address + * + * This function gets the IP address for the interface @ifname + * and stores it in @addr + * + * Returns 0 on success, -1 on failure, -2 on unsupported. + */ +#if HAVE_GETIFADDRS +static int +virNetDevGetifaddrsAddress(const char *ifname, + virSocketAddrPtr addr) +{ + struct ifaddrs *ifap, *ifa; + int ret = -1; + + if (getifaddrs(&ifap) < 0) { + virReportSystemError(errno, + _("Could not get interface list for '%s'"), + ifname); + return -1; + } + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + int family = ifa->ifa_addr->sa_family; + + if (STRNEQ_NULLABLE(ifa->ifa_name, ifname)) + continue; + if (family != AF_INET6 && family != AF_INET) + continue; + + if (family == AF_INET6) { + addr->len = sizeof(addr->data.inet6); + memcpy(&addr->data.inet6, ifa->ifa_addr, addr->len); + } else { + addr->len = sizeof(addr->data.inet4); + memcpy(&addr->data.inet4, ifa->ifa_addr, addr->len); + } + addr->data.stor.ss_family = family; + ret = 0; + goto cleanup; + } + + virReportError(VIR_ERR_INTERNAL_ERROR, + _("no IP address found for interface '%s'"), + ifname); + cleanup: + freeifaddrs(ifap); + return ret; +} + +#else /* ! HAVE_GETIFADDRS */ + +static int +virNetDevGetifaddrsAddress(const char *ifname ATTRIBUTE_UNUSED, + virSocketAddrPtr addr ATTRIBUTE_UNUSED) +{ + return -2; +} + +#endif + /** * virNetDevGetIPAddress: * @ifname: name of the interface whose IP address we want @@ -1454,6 +1522,9 @@ virNetDevGetIPAddress(const char *ifname, memset(addr, 0, sizeof(*addr)); addr->data.stor.ss_family = AF_UNSPEC; + if ((ret = virNetDevGetifaddrsAddress(ifname, addr)) != -2) + return ret; + if ((ret = virNetDevGetIPv4AddressIoctl(ifname, addr)) != -2) return ret;