]> xenbits.xensource.com Git - libvirt.git/commitdiff
network: provide internal API to return IP of a network
authorLaine Stump <laine@laine.org>
Thu, 7 Jul 2011 04:24:08 +0000 (00:24 -0400)
committerDaniel Veillard <veillard@redhat.com>
Mon, 25 Jul 2011 05:48:55 +0000 (13:48 +0800)
The new listenNetwork attribute needs to learn an IP address based on a
named network. This patch provides a function networkGetNetworkAddress
which provides that.

Some networks have an IP address explicitly in their configuration
(ie, those with a forward type of "none", "route", or "nat"). For
those, we can just return the IP address from the config.

The rest will have a physical device associated with them (either via
<bridge name='...'/>, <forward ... dev='...'/>, or possibly via a pool
of interfaces inside the network's <forward> element) and we will need
to ask the kernel for a current IP address of that device (via the
newly added ifaceGetIPAddress)

If networkGetNetworkAddress encounters an error while trying to learn
the address for a network, it will return -1. In the case that libvirt
has been compiled without the network driver, the call is a macro
which reduces to -2. This allows differentiating between a failure of
the network driver, and its complete absence.

src/libvirt_network.syms
src/network/bridge_driver.c
src/network/bridge_driver.h

index e402b5f28366081293ffec677bd009671d151f5a..1fe89027b4615a8a5eed2abd675c4bab2cf59e40 100644 (file)
@@ -5,5 +5,6 @@
 # bridge_driver.h
 networkAllocateActualDevice;
 networkBuildDhcpDaemonCommandLine;
+networkGetNetworkAddress;
 networkNotifyActualDevice;
 networkReleaseActualDevice;
index 99033a2e048b2ec6a44e03e44ce8a094eb8bb552..4a274086e477cf4ddff16429396eff634b236f7a 100644 (file)
@@ -55,6 +55,7 @@
 #include "uuid.h"
 #include "iptables.h"
 #include "bridge.h"
+#include "interface.h"
 #include "logging.h"
 #include "dnsmasq.h"
 #include "util/network.h"
@@ -3090,3 +3091,103 @@ cleanup:
     iface->data.network.actual = NULL;
     return ret;
 }
+
+/*
+ * networkGetNetworkAddress:
+ * @netname: the name of a network
+ * @netaddr: string representation of IP address for that network.
+ *
+ * Attempt to return an IP (v4) address associated with the named
+ * network. If a libvirt virtual network, that will be provided in the
+ * configuration. For host bridge and direct (macvtap) networks, we
+ * must do an ioctl to learn the address.
+ *
+ * Note: This function returns the 1st IPv4 address it finds. It might
+ * be useful if it was more flexible, but the current use (getting a
+ * listen address for qemu's vnc/spice graphics server) can only use a
+ * single address anyway.
+ *
+ * Returns 0 on success, and puts a string (which must be free'd by
+ * the caller) into *netaddr. Returns -1 on failure or -2 if
+ * completely unsupported.
+ */
+int
+networkGetNetworkAddress(const char *netname, char **netaddr)
+{
+    int ret = -1;
+    struct network_driver *driver = driverState;
+    virNetworkObjPtr network = NULL;
+    virNetworkDefPtr netdef;
+    virNetworkIpDefPtr ipdef;
+    virSocketAddr addr;
+    virSocketAddrPtr addrptr = NULL;
+    char *devname = NULL;
+
+    *netaddr = NULL;
+    networkDriverLock(driver);
+    network = virNetworkFindByName(&driver->networks, netname);
+    networkDriverUnlock(driver);
+    if (!network) {
+        networkReportError(VIR_ERR_NO_NETWORK,
+                           _("no network with matching name '%s'"),
+                           netname);
+        goto cleanup;
+    }
+    netdef = network->def;
+
+    switch (netdef->forwardType) {
+    case VIR_NETWORK_FORWARD_NONE:
+    case VIR_NETWORK_FORWARD_NAT:
+    case VIR_NETWORK_FORWARD_ROUTE:
+        /* if there's an ipv4def, get it's address */
+        ipdef = virNetworkDefGetIpByIndex(netdef, AF_INET, 0);
+        if (!ipdef) {
+            networkReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("network '%s' doesn't have an IPv4 address"),
+                               netdef->name);
+            break;
+        }
+        addrptr = &ipdef->address;
+        break;
+
+    case VIR_NETWORK_FORWARD_BRIDGE:
+        if ((devname = netdef->bridge))
+            break;
+        /*
+         * fall through if netdef->bridge wasn't set, since this is
+         * also a direct-mode interface.
+         */
+    case VIR_NETWORK_FORWARD_PRIVATE:
+    case VIR_NETWORK_FORWARD_VEPA:
+    case VIR_NETWORK_FORWARD_PASSTHROUGH:
+        if ((netdef->nForwardIfs > 0) && netdef->forwardIfs)
+            devname = netdef->forwardIfs[0].dev;
+
+        if (!devname) {
+            networkReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("network '%s' has no associated interface or bridge"),
+                               netdef->name);
+        }
+        break;
+    }
+
+    if (devname) {
+        if (ifaceGetIPAddress(devname, &addr)) {
+            virReportSystemError(errno,
+                                 _("Failed to get IP address for '%s' (network '%s')"),
+                                 devname, netdef->name);
+        } else {
+            addrptr = &addr;
+        }
+    }
+
+    if (addrptr &&
+        (*netaddr = virSocketFormatAddr(addrptr))) {
+        ret = 0;
+    }
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return ret;
+}
index d409f761360ce9cc544dbcd4fe3497383ac14822..518a5ba3bb376453a5cbd4fd9fab6540fa4be081 100644 (file)
@@ -43,6 +43,9 @@ int networkNotifyActualDevice(virDomainNetDefPtr iface)
 int networkReleaseActualDevice(virDomainNetDefPtr iface)
     ATTRIBUTE_NONNULL(1);
 
+int networkGetNetworkAddress(const char *netname, char **netaddr)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
 int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
                                       virCommandPtr *cmdout, char *pidfile,
                                       dnsmasqContext *dctx)
@@ -52,6 +55,7 @@ int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
 #  define networkAllocateActualDevice(iface) 0
 #  define networkNotifyActualDevice(iface) 0
 #  define networkReleaseActualDevice(iface) 0
+#  defing networkGetNetworkAddress(netname, netaddr) (-2)
 #  define networkBuildDhcpDaemonCommandLine(network, cmdout, pidfile, dctx) 0
 # endif