[libvirt] [PATCHv2 1/4] util: introduce 2 new helpers for get interface IPv6 address

Luyao Huang lhuang at redhat.com
Sat Feb 28 09:08:31 UTC 2015


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 at redhat.com>
---
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




More information about the libvir-list mailing list