The new listenNetwork atribute 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 the current IP address of that device (via the
newly added ifaceGetIPAddress
---
src/libvirt_network.syms | 1 +
src/network/bridge_driver.c | 98 +++++++++++++++++++++++++++++++++++++++++++
src/network/bridge_driver.h | 2 +
3 files changed, 101 insertions(+), 0 deletions(-)
diff --git a/src/libvirt_network.syms b/src/libvirt_network.syms
index e402b5f..1fe8902 100644
--- a/src/libvirt_network.syms
+++ b/src/libvirt_network.syms
@@ -5,5 +5,6 @@
# bridge_driver.h
networkAllocateActualDevice;
networkBuildDhcpDaemonCommandLine;
+networkGetNetworkAddress;
networkNotifyActualDevice;
networkReleaseActualDevice;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 56c77f2..a7453ea 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -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"
@@ -3102,3 +3103,100 @@ cleanup:
iface->data.network.actual = NULL;
return ret;
}
+
+/*
+ * networkGetNetworkAddress:
+ * @netname: the name of a network
+ *
+ * Attempt to return the 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 a string (which must be free'd by the caller) on success,
+ * or NULL on failure.
+ */
+char *
+networkGetNetworkAddress(const char *netname)
+{
+ struct network_driver *driver = driverState;
+ virNetworkObjPtr network = NULL;
+ virNetworkDefPtr netdef;
+ virNetworkIpDefPtr ipdef;
+ virSocketAddr addr;
+ virSocketAddrPtr addrptr = NULL;
+ char *devname = NULL;
+ char *addrstr = 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 IP
address"),
+ netdef->name);
+ break;
+ }
+ addrptr = &ipdef->address;
+ break;
+
+ case VIR_NETWORK_FORWARD_BRIDGE:
+ if ((devname = netdef->bridge))
+ break;
+ /*
+ * If netdef->bridge wasn't set, this is a direct-mode
+ * interface, so purposefully drop through to the next case
+ */
+ case VIR_NETWORK_FORWARD_PRIVATE:
+ case VIR_NETWORK_FORWARD_VEPA:
+ case VIR_NETWORK_FORWARD_PASSTHROUGH:
+ if (netdef->nForwardIfs == 0)
+ devname = netdef->forwardDev;
+ else if (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)
+ addrstr = virSocketFormatAddr(addrptr);
+
+cleanup:
+ if (network)
+ virNetworkObjUnlock(network);
+ return addrstr;
+}
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
index 4f6a54d..3c76af2 100644
--- a/src/network/bridge_driver.h
+++ b/src/network/bridge_driver.h
@@ -39,6 +39,8 @@ int networkAllocateActualDevice(virDomainNetDefPtr iface);
int networkNotifyActualDevice(virDomainNetDefPtr iface);
int networkReleaseActualDevice(virDomainNetDefPtr iface);
+char *networkGetNetworkAddress(const char *netname);
+
int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
virCommandPtr *cmdout, char *pidfile,
dnsmasqContext *dctx);
--
1.7.3.4