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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list