Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC and virNetworkDHCPLeaseFree. * virNetworkGetDHCPLeases: returns the dhcp leases information for a given virtual network. For DHCPv4, the information includes: - Expirytime - MAC Address - IPv4 address (with type and prefix) - Hostname (can be NULL) - Client ID (can be NULL) For DHCPv6, the information includes - Expirytime - IAID - IPv6 address (with type and prefix) - Hostname (can be NULL) - Client DUID * virNetworkGetDHCPLeasesForMAC: returns the dhcp leases information for a given virtual network and specified MAC Address. * virNetworkDHCPLeaseFree: allows the upper layer application to free the network interface object conveniently. There is no support for flags, so user is expected to pass 0 for both the APIs. include/libvirt/libvirt.h.in: * Define virNetworkGetDHCPLeases * Define virNetworkGetDHCPLeasesForMAC * Define virNetworkDHCPLeaseFree python/generator.py: * Skip the auto-generation for virNetworkGetDHCPLeases * Skip the auto-generation for virNetworkGetDHCPLeasesForMAC * Skip the auto-generation for virNetworkDHCPLeaseFree src/driver.h: * Define networkGetDHCPLeases * Define networkGetDHCPLeasesForMAC src/libvirt.c: * Implement virNetworkGetDHCPLeases * Implement virNetworkGetDHCPLeasesForMAC * Implement virNetworkDHCPLeaseFree src/libvirt_public.syms: * Export the new symbols --- include/libvirt/libvirt.h.in | 36 +++++++++ python/generator.py | 3 + src/driver.h | 13 ++++ src/libvirt.c | 177 +++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 3 + 5 files changed, 232 insertions(+) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 83c219e..557a4c1 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2800,6 +2800,42 @@ int virConnectNumOfDefinedInterfaces (virConnectPtr conn); int virConnectListDefinedInterfaces (virConnectPtr conn, char **const names, int maxnames); + +typedef enum { + VIR_IP_ADDR_TYPE_IPV4, + VIR_IP_ADDR_TYPE_IPV6, + +#ifdef VIR_ENUM_SENTINELS + VIR_IP_ADDR_TYPE_LAST +#endif +} virIPAddrType; + +typedef struct _virNetworkDHCPLeases virNetworkDHCPLeases; +typedef virNetworkDHCPLeases *virNetworkDHCPLeasesPtr; +struct _virNetworkDHCPLeases { + long long expirytime; /* Seconds since epoch */ + union { + char *mac; /* MAC address */ + unsigned long iaid; /* Identity association identifier (IAID) */ + } id; + char *ipaddr; /* IP address */ + char *hostname; /* Hostname */ + char *clientid; /* Client ID or DUID */ + int type; /* virIPAddrType */ + unsigned int prefix; /* IP address prefix */ +}; + +void virNetworkDHCPLeaseFree(virNetworkDHCPLeasesPtr lease); + +int virNetworkGetDHCPLeases(virNetworkPtr network, + virNetworkDHCPLeasesPtr **leases, + unsigned int flags); + +int virNetworkGetDHCPLeasesForMAC(virNetworkPtr network, + const char *mac, + virNetworkDHCPLeasesPtr **leases, + unsigned int flags); + /* * virConnectListAllInterfaces: * diff --git a/python/generator.py b/python/generator.py index 12c14f1..1079d6c 100755 --- a/python/generator.py +++ b/python/generator.py @@ -461,6 +461,8 @@ skip_impl = ( 'virNodeGetCPUMap', 'virDomainMigrate3', 'virDomainMigrateToURI3', + 'virNetworkGetDHCPLeases', + 'virNetworkGetDHCPLeasesForMAC', ) lxc_skip_impl = ( @@ -561,6 +563,7 @@ skip_function = ( "virTypedParamsGetString", "virTypedParamsGetUInt", "virTypedParamsGetULLong", + 'virNetworkDHCPLeaseFree', ) lxc_skip_function = ( diff --git a/src/driver.h b/src/driver.h index 8cd164a..e000b17 100644 --- a/src/driver.h +++ b/src/driver.h @@ -1127,6 +1127,17 @@ typedef int int cookieinlen, unsigned int flags, int cancelled); +typedef int +(*virDrvNetworkGetDHCPLeases)(virNetworkPtr network, + virNetworkDHCPLeasesPtr **leases, + unsigned int flags); + +typedef int +(*virDrvNetworkGetDHCPLeasesForMAC)(virNetworkPtr network, + const char *mac, + virNetworkDHCPLeasesPtr **leases, + unsigned int flags); + typedef struct _virDriver virDriver; typedef virDriver *virDriverPtr; @@ -1458,6 +1469,8 @@ struct _virNetworkDriver { virDrvNetworkSetAutostart networkSetAutostart; virDrvNetworkIsActive networkIsActive; virDrvNetworkIsPersistent networkIsPersistent; + virDrvNetworkGetDHCPLeases networkGetDHCPLeases; + virDrvNetworkGetDHCPLeasesForMAC networkGetDHCPLeasesForMAC; }; diff --git a/src/libvirt.c b/src/libvirt.c index 9f579a6..93ea3bf 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -68,6 +68,7 @@ #include "virstring.h" #include "virutil.h" #include "virtypedparam.h" +#include "virmacaddr.h" #ifdef WITH_TEST # include "test/test_driver.h" @@ -22018,3 +22019,179 @@ error: virDispatchError(dom->conn); return -1; } + +/** + * virNetworkGetDHCPLeases: + * @network: Pointer to network object + * @leases: Pointer to a variable to store the array containing details on + * obtained leases, or NULL if the list is not required (just returns + * number of leases). + * @flags: Extra flags, not used yet, so callers should always pass 0 + * + * The API fetches lease info for all network interfaces connected to the given + * virtual network. In case of DHCPv4, the fields returned are expiry time, MAC + * address, IPv4 address, hostname and client ID, out of which, hostname and + * client ID can be NULL. In case of DHCPv6, the fields returned are expiry time, + * IAID, IPv6 address, hostname and client DUID, out of which, only hostname can + * be NULL. + * + * Returns the number of leases found or -1 and sets @leases to NULL in case of + * error. On success, the array stored into @leases is guaranteed to have an + * extra allocated element set to NULL but not included in the return count, + * to make iteration easier. The caller is responsible for calling + * virNetworkDHCPLeaseFree() on each array element, then calling free() on @leases. + * + * Example of usage: + * + * virNetworkDHCPLeasesPtr *leases = NULL; + * virNetworkPtr network = ... obtain a network pointer here ...; + * size_t i; + * int nleases; + * unsigned int flags = 0; + * + * nleases = virNetworkGetDHCPLeases(network, &leases, flags); + * if (nleases < 0) + * error(); + * + * ... do something with returned values, for example: + * + * for (i = 0; i < nleases; i++) { + * virNetworkDHCPLeasesPtr lease = leases[i]; + * + * printf("Time(epoch): %lu, MAC address: %s, " + * "IP address: %s, Hostname: %s, ClientID: %s\n", + * leas->expirytime, lease->mac, lease->ipaddr, + * lease->hostname, lease->clientid); + * + * virNetworkDHCPLeaseFree(leases[i]); + * } + * + * free(leases); + * + */ +int +virNetworkGetDHCPLeases(virNetworkPtr network, + virNetworkDHCPLeasesPtr **leases, + unsigned int flags) +{ + virConnectPtr conn; + VIR_DEBUG("network=%p, leases=%p, flags=%x", + network, leases, flags); + + virResetLastError(); + + if (leases) + *leases = NULL; + + if (!VIR_IS_CONNECTED_NETWORK(network)) { + virLibNetworkError(VIR_ERR_INVALID_NETWORK, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + conn = network->conn; + + if (conn->networkDriver && conn->networkDriver->networkGetDHCPLeases) { + int ret; + ret = conn->networkDriver->networkGetDHCPLeases(network,leases, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(network->conn); + return -1; +} + +/** + * virNetworkGetDHCPLeasesForMAC: + * @network: Pointer to network object + * @mac: ASCII formatted MAC address of an interface + * @leases: Pointer to a variable to store the array containing details on + * obtained leases, or NULL if the list is not required (just returns + * number of leases). + * @flags: extra flags, not used yet, so callers should always pass 0 + * + * The API fetches leases info of the interface which matches with the + * given @mac. There can be multiple leases for a single @mac because this + * API supports DHCPv6 too. + * + * Returns the number of leases found or -1 and sets @leases to NULL in case of + * error. On success, the array stored into @leases is guaranteed to have an + * extra allocated element set to NULL but not included in the return count, + * to make iteration easier. The caller is responsible for calling + * virNetworkDHCPLeaseFree() on each array element, then calling free() on @leases. + */ +int +virNetworkGetDHCPLeasesForMAC(virNetworkPtr network, + const char *mac, + virNetworkDHCPLeasesPtr **leases, + unsigned int flags) +{ + virConnectPtr conn; + virMacAddr addr; + + VIR_DEBUG("network=%p, mac=%s, leases=%p, flags=%x", + network, mac, leases, flags); + + virResetLastError(); + + if (leases) + *leases = NULL; + + virCheckNonNullArgGoto(mac, error); + + if (!VIR_IS_CONNECTED_NETWORK(network)) { + virLibNetworkError(VIR_ERR_INVALID_NETWORK, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + /* Validate the MAC address */ + if (virMacAddrParse(mac, &addr) < 0) { + virReportInvalidArg(mac, "%s", + _("Given MAC Address doesn't comply " + "with the standard (IEEE 802) format")); + goto error; + } + + conn = network->conn; + + if (conn->networkDriver && + conn->networkDriver->networkGetDHCPLeasesForMAC) { + int ret; + ret = conn->networkDriver->networkGetDHCPLeasesForMAC(network, mac, + leases, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(network->conn); + return -1; +} + +/** + * virNetworkDHCPLeaseFree: + * @lease: pointer to a leases object + * + * Frees all the memory occupied by @lease. + */ +void +virNetworkDHCPLeaseFree(virNetworkDHCPLeasesPtr lease) +{ + if (!lease) + return; + if (lease->type == VIR_IP_ADDR_TYPE_IPV4) + VIR_FREE(lease->id.mac); + VIR_FREE(lease->ipaddr); + VIR_FREE(lease->hostname); + VIR_FREE(lease->clientid); + VIR_FREE(lease); +} diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index fe9b497..a07be7e 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -636,7 +636,10 @@ LIBVIRT_1.1.1 { LIBVIRT_1.1.3 { global: + virNetworkDHCPLeaseFree; + virNetworkGetDHCPLeases; virConnectGetCPUModelNames; + virNetworkGetDHCPLeasesForMAC; } LIBVIRT_1.1.1; # .... define new API here using predicted next version number .... -- 1.7.11.7 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list