Introduce virNetDevGetIfaddrsAddress to help to get interface IPv6 and IPv4 address. Introduce virNetDevGetIPAddress to use virNetDevGetIfaddrsAddress and virNetDevGetIPv4Address to get IP address. Signed-off-by: Luyao Huang <lhuang@xxxxxxxxxx> --- v2: add a new function virNetDevGetIPAddress to call virNetDevGetIfaddrsAddress , and make virNetDevGetIfaddrsAddress can get ipv4 address for a interface. Also add a error output in virNetDevGetIfaddrsAddress when get multiple ip address for a host interface. src/libvirt_private.syms | 1 + src/util/virnetdev.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 4 ++ 3 files changed, 103 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ba05cc6..f88626a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1670,6 +1670,7 @@ virNetDevClearIPAddress; virNetDevDelMulti; virNetDevExists; virNetDevGetIndex; +virNetDevGetIPAddress; virNetDevGetIPv4Address; virNetDevGetLinkInfo; virNetDevGetMAC; diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 2a0eb43..318c3b6 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -33,6 +33,10 @@ #include "virstring.h" #include "virutil.h" +#if defined(HAVE_GETIFADDRS) +# include <ifaddrs.h> +#endif + #include <sys/ioctl.h> #include <net/if.h> #include <fcntl.h> @@ -1432,6 +1436,100 @@ int virNetDevGetIPv4Address(const char *ifname ATTRIBUTE_UNUSED, #endif /* ! SIOCGIFADDR */ +/** + * virNetDevGetIfaddrsAddress: + * @ifname: name of the interface whose IP address we want + * @want_ipv6: get IPv4 or IPv6 address + * @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 defined(HAVE_GETIFADDRS) +static int virNetDevGetIfaddrsAddress(const char *ifname, + bool want_ipv6, + virSocketAddrPtr addr) +{ + struct ifaddrs *ifap, *ifa; + int ret = -1; + int nIPaddr = 0; + + if (getifaddrs(&ifap) < 0) { + virReportSystemError(errno, + _("Could not get interface list for '%s'"), + ifname); + return -1; + } + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr || + STRNEQ(ifa->ifa_name, ifname)) { + continue; + } + if (ifa->ifa_addr->sa_family == (want_ipv6 ? AF_INET6 : AF_INET)) { + if (++nIPaddr > 1) + break; + if (want_ipv6) { + 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 = ifa->ifa_addr->sa_family; + } + } + + if (nIPaddr == 1) + ret = 0; + else if (nIPaddr > 1) + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Interface '%s' has multiple %s address"), + ifname, want_ipv6 ? "IPv6" : "IPv4"); + else + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Interface '%s' not found"), + ifname); + + freeifaddrs(ifap); + return ret; +} + +#else + +static int virNetDevGetIfaddrsAddress(const char *ifname ATTRIBUTE_UNUSED, + bool want_ipv6, + virSocketAddrPtr addr ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, + _("Unable to get %s address on this platform"), + want_ipv6 ? "IPv6" : "IPv4"); + return -2; +} + +#endif + + +int virNetDevGetIPAddress(const char *ifname, + bool want_ipv6, + virSocketAddrPtr addr) +{ + int ret; + + memset(addr, 0, sizeof(*addr)); + addr->data.stor.ss_family = AF_UNSPEC; + + ret = virNetDevGetIfaddrsAddress(ifname, want_ipv6, addr); + if (ret != -2) + return ret; + + if (!want_ipv6) + return virNetDevGetIPv4Address(ifname, addr); + + return -1; +} /** * virNetDevValidateConfig: diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index de8b480..faf3b2f 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -104,6 +104,10 @@ int virNetDevClearIPAddress(const char *ifname, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; int virNetDevGetIPv4Address(const char *ifname, virSocketAddrPtr addr) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; +int virNetDevGetIPAddress(const char *ifname, + bool want_ipv6, + virSocketAddrPtr addr) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK; int virNetDevSetMAC(const char *ifname, -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list