mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 21:34:54 +03:00
network: provide internal API to return IP of a network
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.
This commit is contained in:
parent
c5d1592e20
commit
239322cbd4
@ -5,5 +5,6 @@
|
||||
# bridge_driver.h
|
||||
networkAllocateActualDevice;
|
||||
networkBuildDhcpDaemonCommandLine;
|
||||
networkGetNetworkAddress;
|
||||
networkNotifyActualDevice;
|
||||
networkReleaseActualDevice;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user