Display detected IP addresses in the domain XML using the IP_LEASE variable name. This variable name now becomes a reserved variable name that can be read only but not set by the user. The format of the value is: <ip address>,<lease timeout in seconds> An example of a displayed XML may then be: <interface type='bridge'> <mac address='52:54:00:68:e3:90'/> <source bridge='virbr0'/> <target dev='vnet1'/> <model type='virtio'/> <filterref filter='clean-traffic'> <parameter name='CTRL_IP_LEARNING' value='dhcp'/> <parameter name='IP_LEASE' value='192.168.122.210,100'/> </filterref> <alias name='net0'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </interface> This patch now also offers a better (libvirt-internal) API for accessing the detected IP addresses. The function virDomainConfNWFilterGetLeases can be used to retrieve a list of IP leases associated with a given interface. This function will then either retrieve the data from the DHCP snooping or IP learning subsystems, depending on which detection algorithm has been activated. If none is active, a NULL pointer for the array of leases will be returned. --- PS: This is the last remaining patch of the DHCP snooping series. I am submitting it now as a stand-alone patch restarting the version counting. --- docs/formatnwfilter.html.in | 27 +++++++++++ src/conf/domain_conf.c | 16 +++++-- src/conf/domain_nwfilter.c | 13 +++++ src/conf/domain_nwfilter.h | 15 ++++++ src/conf/nwfilter_conf.c | 3 - src/conf/nwfilter_ipaddrmap.c | 51 ++++++++++++++++++++++ src/conf/nwfilter_ipaddrmap.h | 5 ++ src/conf/nwfilter_params.c | 75 ++++++++++++++++++++++++++++++++- src/conf/nwfilter_params.h | 9 +++ src/libvirt_private.syms | 5 +- src/nwfilter/nwfilter_dhcpsnoop.c | 59 +++++++++++++++++++++++++ src/nwfilter/nwfilter_dhcpsnoop.h | 4 + src/nwfilter/nwfilter_driver.c | 10 ++++ src/nwfilter/nwfilter_gentech_driver.c | 26 +++++++++++ src/nwfilter/nwfilter_gentech_driver.h | 8 +++ src/nwfilter/nwfilter_learnipaddr.c | 9 +++ src/nwfilter/nwfilter_learnipaddr.h | 2 src/util/viriplease.h | 18 +++++++ 18 files changed, 345 insertions(+), 10 deletions(-) Index: libvirt-acl/src/conf/nwfilter_params.h =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_params.h +++ libvirt-acl/src/conf/nwfilter_params.h @@ -72,7 +72,10 @@ struct _virNWFilterHashTable { virNWFilterHashTablePtr virNWFilterParseParamAttributes(xmlNodePtr cur); int virNWFilterFormatParamAttributes(virBufferPtr buf, virNWFilterHashTablePtr table, - const char *filterref); + const char *filterref, + const unsigned char *vmuuid, + const unsigned char *mac, + const char *ifname); virNWFilterHashTablePtr virNWFilterHashTableCreate(int n); void virNWFilterHashTableFree(virNWFilterHashTablePtr table); @@ -89,12 +92,14 @@ int virNWFilterHashTablePutAll(virNWFilt "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" # define VALID_VARVALUE \ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.:" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.:," # define NWFILTER_VARNAME_IP "IP" # define NWFILTER_VARNAME_MAC "MAC" # define NWFILTER_VARNAME_CTRL_IP_LEARNING "CTRL_IP_LEARNING" # define NWFILTER_VARNAME_DHCPSERVER "DHCPSERVER" +# define NWFILTER_VARNAME_IP_LEASE "IP_LEASE" +# define NWFILTER_VARNAME_IPV6_LEASE "IPV6_LEASE" /* future */ enum virNWFilterVarAccessType { VIR_NWFILTER_VAR_ACCESS_ELEMENT = 0, Index: libvirt-acl/src/conf/domain_conf.c =================================================================== --- libvirt-acl.orig/src/conf/domain_conf.c +++ libvirt-acl/src/conf/domain_conf.c @@ -43,6 +43,7 @@ #include "buf.h" #include "c-ctype.h" #include "logging.h" +#include "nwfilter_params.h" #include "nwfilter_conf.h" #include "ignore-value.h" #include "storage_file.h" @@ -11500,7 +11501,8 @@ error: static int virDomainNetDefFormat(virBufferPtr buf, virDomainNetDefPtr def, - unsigned int flags) + unsigned int flags, + const unsigned char *vmuuid) { const char *type = virDomainNetTypeToString(def->type); @@ -11641,9 +11643,15 @@ virDomainNetDefFormat(virBufferPtr buf, } } if (def->filter) { + const char *ifname = NULL; + + if (!(flags & VIR_DOMAIN_XML_INACTIVE)) + ifname = def->ifname; + virBufferAdjustIndent(buf, 6); if (virNWFilterFormatParamAttributes(buf, def->filterparams, - def->filter) < 0) + def->filter, vmuuid, def->mac, + ifname) < 0) return -1; virBufferAdjustIndent(buf, -6); } @@ -12969,7 +12977,7 @@ virDomainDefFormatInternal(virDomainDefP for (n = 0 ; n < def->nnets ; n++) - if (virDomainNetDefFormat(buf, def->nets[n], flags) < 0) + if (virDomainNetDefFormat(buf, def->nets[n], flags, def->uuid) < 0) goto cleanup; for (n = 0 ; n < def->nsmartcards ; n++) @@ -15222,7 +15230,7 @@ virDomainDeviceDefCopy(virCapsPtr caps, rc = virDomainFSDefFormat(&buf, src->data.fs, flags); break; case VIR_DOMAIN_DEVICE_NET: - rc = virDomainNetDefFormat(&buf, src->data.net, flags); + rc = virDomainNetDefFormat(&buf, src->data.net, flags, def->uuid); break; case VIR_DOMAIN_DEVICE_INPUT: rc = virDomainInputDefFormat(&buf, src->data.input, flags); Index: libvirt-acl/src/conf/nwfilter_conf.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.c +++ libvirt-acl/src/conf/nwfilter_conf.c @@ -3406,7 +3406,8 @@ virNWFilterIncludeDefFormat(virNWFilterI virBufferAdjustIndent(&buf, 2); if (virNWFilterFormatParamAttributes(&buf, inc->params, - inc->filterref) < 0) { + inc->filterref, + NULL, NULL, NULL) < 0) { virBufferFreeAndReset(&buf); return NULL; } Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -552,6 +552,7 @@ virDomainLockLeaseDetach; # domain_nwfilter.h +virDomainConfNWFiltetGetLeases; virDomainConfNWFilterInstantiate; virDomainConfNWFilterRegister; virDomainConfNWFilterTeardown; @@ -873,15 +874,17 @@ virNWFilterTestUnassignDef; virNWFilterUnlockFilterUpdates; -# nwfilter_ipaddrmap +# nwfilter_ipaddrmap.h virNWFilterIPAddrMapAddIPAddr; virNWFilterIPAddrMapDelIPAddr; virNWFilterIPAddrMapGetIPAddr; +virNWFilterIPAddrMapGetIPLeases; virNWFilterIPAddrMapInit; virNWFilterIPAddrMapShutdown; # nwfilter_params.h +virNWFilterFormatParamAttributes; virNWFilterHashTableCreate; virNWFilterHashTableFree; virNWFilterHashTablePut; Index: libvirt-acl/src/conf/nwfilter_params.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_params.c +++ libvirt-acl/src/conf/nwfilter_params.c @@ -31,9 +31,16 @@ #include "nwfilter_params.h" #include "domain_conf.h" #include "logging.h" +#include "domain_nwfilter.h" +#include "nwfilter_ipaddrmap.h" #define VIR_FROM_THIS VIR_FROM_NWFILTER +static const char *virNWFilterReservedVarnames[] = { + NWFILTER_VARNAME_IP_LEASE, + NWFILTER_VARNAME_IPV6_LEASE, +}; + static bool isValidVarValue(const char *value); static void virNWFilterVarAccessSetIntIterId(virNWFilterVarAccessPtr, unsigned int); @@ -784,6 +791,19 @@ virNWFilterParseVarValue(const char *val return virNWFilterVarValueCreateSimpleCopyValue(val); } +static void +virNWFilterDelReservedVarnames(virNWFilterHashTablePtr ht) +{ + unsigned int i; + virNWFilterVarValuePtr val; + + for (i = 0; i < ARRAY_CARDINALITY(virNWFilterReservedVarnames); i++) { + val = virNWFilterHashTableRemoveEntry(ht, + virNWFilterReservedVarnames[i]); + virNWFilterVarValueFree(val); + } +} + virNWFilterHashTablePtr virNWFilterParseParamAttributes(xmlNodePtr cur) { @@ -834,6 +854,15 @@ skip_entry: } cur = cur->next; } + + /* + * read-only variables that may be usable in an incoming + * migration could be wired up here. + */ + + /* remove all reserved varnames from the table */ + virNWFilterDelReservedVarnames(table); + return table; err_exit: @@ -855,10 +884,16 @@ virNWFilterFormatParameterNameSorter(con int virNWFilterFormatParamAttributes(virBufferPtr buf, virNWFilterHashTablePtr table, - const char *filterref) + const char *filterref, + const unsigned char *vmuuid, + const unsigned char *mac, + const char *ifname) { virHashKeyValuePairPtr items; + virIPLeasePtr leases = NULL; + size_t nLeases = 0; int i, j, card, numKeys; + int ret = 0; numKeys = virHashSize(table->hashTable); @@ -889,14 +924,50 @@ virNWFilterFormatParamAttributes(virBuff virNWFilterVarValueGetNthValue(value, j)); } + if (ifname) { + time_t now = time(0); + /* also display the IP addresses being used */ + if (virDomainConfNWFilterGetLeases(&leases, &nLeases, + table, + ifname, + vmuuid, + mac) < 0) { + ret = -1; + goto cleanup; + } + + for (i = 0; i < nLeases; i++) { + int64_t to; + char *ipbuf = virSocketAddrFormat(&leases[i].addr); + + if (!ipbuf) { + virReportOOMError(); + ret = -1; + goto cleanup; + } + + to = (leases[i].timeout != VIR_IPLEASE_TIMEOUT_NONE) + ? (int64_t)(leases[i].timeout - now) + : -1; + + virBufferAsprintf(buf, + " <parameter name='" + NWFILTER_VARNAME_IP_LEASE + "' value='%s,%ld'/>\n", + ipbuf, to); + VIR_FREE(ipbuf); + } + } virBufferAddLit(buf, "</filterref>\n"); } else { virBufferAddLit(buf, "/>\n"); } +cleanup: VIR_FREE(items); + VIR_FREE(leases); - return 0; + return ret; } void Index: libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_dhcpsnoop.c +++ libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c @@ -1987,6 +1987,57 @@ virNWFilterSnoopLeaseFileLoad(void) } /* + * Get the detected IP addresses along with their absolute lease timeout. + */ +int +virNWFilterSnoopGetLeases(virIPLeasePtr *leases, size_t *nLeases, + const unsigned char *vmuuid, + const unsigned char *macaddr) +{ + int ret = 0; + char ifkey[VIR_IFKEY_LEN]; + virNWFilterSnoopReqPtr req; + virNWFilterSnoopIPLeasePtr ipl; + size_t ctr = 0; + virIPLeasePtr myleases = NULL; + + *leases = NULL; + + virNWFilterSnoopIFKeyFMT(ifkey, vmuuid, macaddr); + + req = virNWFilterSnoopReqGetByIFKey(ifkey); + if (req) { + time_t now = time(0); + + /* protect req->start */ + virNWFilterSnoopReqLock(req); + + for (ipl = req->start; ipl; ipl = ipl->next) { + if (ipl->timeout <= now) + continue; + + if (VIR_EXPAND_N(myleases, ctr, 1) < 0) { + VIR_FREE(myleases); + ret = -1; + goto cleanup; + } + + myleases[ctr-1].addr = ipl->ipAddress; + myleases[ctr-1].timeout = ipl->timeout; + } + + *leases = myleases; + *nLeases = ctr; + +cleanup: + virNWFilterSnoopReqUnlock(req); + + virNWFilterSnoopReqPut(req); + } + return ret; +} + +/* * Wait until all threads have ended. */ static void @@ -2174,6 +2225,14 @@ virNWFilterDHCPSnoopShutdown(void) #else /* HAVE_LIBPCAP */ int +virNWFilterSnoopGetLeases(virIPLeasePtr *leases ATTRIBUTE_UNUSED, + size_t *nLeases ATTRIBUTE_UNUSED, + const unsigned char *vmuuid ATTRIBUTE_UNUSED, + const unsigned char *macaddr ATTRIBUTE_UNUSED) +{ +} + +int virNWFilterDHCPSnoopInit(void) { return -1; Index: libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.h =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_dhcpsnoop.h +++ libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.h @@ -36,4 +36,8 @@ int virNWFilterDHCPSnoopReq(virNWFilterT virNWFilterHashTablePtr filterparams, virNWFilterDriverStatePtr driver); void virNWFilterDHCPSnoopEnd(const char *ifname); +int virNWFilterSnoopGetLeases(virIPLeasePtr *leases, size_t *nLeases, + const unsigned char *vmuuid, + const unsigned char *macaddr); + #endif /* __NWFILTER_DHCPSNOOP_H */ Index: libvirt-acl/src/conf/domain_nwfilter.c =================================================================== --- libvirt-acl.orig/src/conf/domain_nwfilter.c +++ libvirt-acl/src/conf/domain_nwfilter.c @@ -60,3 +60,16 @@ virDomainConfVMNWFilterTeardown(virDomai virDomainConfNWFilterTeardown(vm->def->nets[i]); } } + +int +virDomainConfNWFilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + virNWFilterHashTablePtr table, + const char *ifname, + const unsigned char *vmuuid, + const unsigned char *mac) +{ + if (nwfilterDriver != NULL) + return nwfilterDriver->getLeases(leases, nLeases, table, ifname, + vmuuid, mac); + return 0; +} Index: libvirt-acl/src/conf/domain_nwfilter.h =================================================================== --- libvirt-acl.orig/src/conf/domain_nwfilter.h +++ libvirt-acl/src/conf/domain_nwfilter.h @@ -23,14 +23,24 @@ #ifndef DOMAIN_NWFILTER_H # define DOMAIN_NWFILTER_H +# include "viriplease.h" + typedef int (*virDomainConfInstantiateNWFilter)(virConnectPtr conn, const unsigned char *vmuuid, virDomainNetDefPtr net); typedef void (*virDomainConfTeardownNWFilter)(virDomainNetDefPtr net); +typedef int (*virDomainConfGetLeases)(virIPLeasePtr *leases, + size_t *nLeases, + virNWFilterHashTablePtr table, + const char *ifname, + const unsigned char *vmuuid, + const unsigned char *mac); + typedef struct { virDomainConfInstantiateNWFilter instantiateFilter; virDomainConfTeardownNWFilter teardownFilter; + virDomainConfGetLeases getLeases; } virDomainConfNWFilterDriver; typedef virDomainConfNWFilterDriver *virDomainConfNWFilterDriverPtr; @@ -41,5 +51,10 @@ int virDomainConfNWFilterInstantiate(vir virDomainNetDefPtr net); void virDomainConfNWFilterTeardown(virDomainNetDefPtr net); void virDomainConfVMNWFilterTeardown(virDomainObjPtr vm); +int virDomainConfNWFilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + virNWFilterHashTablePtr table, + const char *ifname, + const unsigned char *vmuuid, + const unsigned char *mac); #endif /* DOMAIN_NWFILTER_H */ Index: libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_gentech_driver.c +++ libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c @@ -1209,3 +1209,29 @@ virNWFilterDomainFWUpdateCB(void *payloa virDomainObjUnlock(obj); } + +int +virNWFilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + virNWFilterHashTablePtr vars, + const char *ifname, + const unsigned char *vmuuid, + const unsigned char *mac) +{ + virNWFilterVarValuePtr lv; + const char *learning = NULL; + int ret = 0; + + if (!vars) + return 0; + + lv = virHashLookup(vars->hashTable, NWFILTER_VARNAME_CTRL_IP_LEARNING); + if (lv) + learning = virNWFilterVarValueGetNthValue(lv, 0); + + if (!learning || STRCASEEQ(learning, "any")) { + ret = virNWFilterLearnGetLeases(leases, nLeases, ifname); + } else if (STRCASEEQ(learning, "dhcp")) { + ret = virNWFilterSnoopGetLeases(leases, nLeases, vmuuid, mac); + } + return ret; +} Index: libvirt-acl/src/nwfilter/nwfilter_gentech_driver.h =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_gentech_driver.h +++ libvirt-acl/src/nwfilter/nwfilter_gentech_driver.h @@ -23,6 +23,8 @@ #ifndef __NWFILTER_GENTECH_DRIVER_H # define __NWFILTER_GENTECH_DRIVER_H +# include "viriplease.h" + virNWFilterTechDriverPtr virNWFilterTechDriverForName(const char *name); int virNWFilterRuleInstAddData(virNWFilterRuleInstPtr res, @@ -64,4 +66,10 @@ void virNWFilterDomainFWUpdateCB(void *p const void *name, void *data); +int virNWFilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + virNWFilterHashTablePtr vars, + const char *ifname, + const unsigned char *vmmuid, + const unsigned char *mac); + #endif Index: libvirt-acl/src/nwfilter/nwfilter_driver.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_driver.c +++ libvirt-acl/src/nwfilter/nwfilter_driver.c @@ -463,6 +463,15 @@ nwfilterTeardownFilter(virDomainNetDefPt virNWFilterTeardownFilter(net); } +static int +nwfilterGetLeases(virIPLeasePtr *leases, size_t *nLeases, + virNWFilterHashTablePtr vars, + const char *ifname, + const unsigned char *vmuuid, + const unsigned char *mac) +{ + return virNWFilterGetLeases(leases, nLeases, vars, ifname, vmuuid, mac); +} static virNWFilterDriver nwfilterDriver = { .name = "nwfilter", @@ -490,6 +499,7 @@ static virStateDriver stateDriver = { static virDomainConfNWFilterDriver domainNWFilterDriver = { .instantiateFilter = nwfilterInstantiateFilter, .teardownFilter = nwfilterTeardownFilter, + .getLeases = nwfilterGetLeases, }; Index: libvirt-acl/src/conf/nwfilter_ipaddrmap.h =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_ipaddrmap.h +++ libvirt-acl/src/conf/nwfilter_ipaddrmap.h @@ -26,6 +26,9 @@ #ifndef __VIR_NWFILTER_IPADDRMAP_H # define __VIR_NWFILTER_IPADDRMAP_H +# include "buf.h" +# include "viriplease.h" + int virNWFilterIPAddrMapInit(void); void virNWFilterIPAddrMapShutdown(void); @@ -33,5 +36,7 @@ int virNWFilterIPAddrMapAddIPAddr(const int virNWFilterIPAddrMapDelIPAddr(const char *ifname, const char *ipaddr); virNWFilterVarValuePtr virNWFilterIPAddrMapGetIPAddr(const char *ifname); +int virNWFilterIPAddrMapGetIPLeases(const char *ifname, + virIPLeasePtr *leases, size_t *nLeases); #endif /* __VIR_NWFILTER_IPADDRMAP_H */ Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.c +++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c @@ -771,6 +771,15 @@ virNWFilterLearnIPAddress(virNWFilterTec } #endif /* HAVE_LIBPCAP */ +/* + * Get the detected IP addresses along with their absolute lease timeout + */ +int +virNWFilterLearnGetLeases(virIPLeasePtr *leases, size_t *nLeases, + const char *ifname) +{ + return virNWFilterIPAddrMapGetIPLeases(ifname, leases, nLeases); +} /** * virNWFilterLearnInit Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.h =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.h +++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.h @@ -71,5 +71,7 @@ void virNWFilterUnlockIface(const char * int virNWFilterLearnInit(void); void virNWFilterLearnShutdown(void); void virNWFilterLearnThreadsTerminate(bool allowNewThreads); +int virNWFilterLearnGetLeases(virIPLeasePtr *leases, size_t *nLeases, + const char *ifname); #endif /* __NWFILTER_LEARNIPADDR_H */ Index: libvirt-acl/docs/formatnwfilter.html.in =================================================================== --- libvirt-acl.orig/docs/formatnwfilter.html.in +++ libvirt-acl/docs/formatnwfilter.html.in @@ -446,6 +446,22 @@ </interface> </pre> + <p> + Once an IP address has been detected, the domain's interface XML + will display the detected IP address and its lease expiration time + in seconds. Note that the <code>IP_LEASE</code> variable is read-only + and cannot be set by the user. + </p> +<pre> + <interface type='bridge'> + <source bridge='virbr0'/> + <filterref filter='clean-traffic'> + <parameter name='CTRL_IP_LEARNING' value='dhcp'/> + <parameter name='IP_LEASE' value='192.168.122.100,200'/> + </filterref> + </interface> +</pre> + <h3><a name="nwfelemsReservedVars">Reserved Variables</a></h3> <p> The following table lists reserved variables in use by libvirt. @@ -481,6 +497,17 @@ <td> CTRL_IP_LEARNING </td> <td> The choice of the IP address detection mode </td> </tr> + <tr> + <td> IP_LEASE (<span class="since">Since 0.9.13</span>)</td> + <td> Read-only variable displaying the detected IP lease in the + format IP address,lease expiration time in seconds </td> + </tr> + <tr> + <td> IPV6_LEASE </td> + <td> Not currently implemented: + Read-only variable displaying the detected IPV6 lease in the + format IPV6 address,lease expiration time in seconds </td> + </tr> </table> <h2><a name="nwfelems">Element and attribute overview</a></h2> Index: libvirt-acl/src/util/viriplease.h =================================================================== --- /dev/null +++ libvirt-acl/src/util/viriplease.h @@ -0,0 +1,18 @@ +#ifndef __VIR_IPLEASE_H__ +# define __VIR_IPLEASE_H__ + +# include <time.h> + +# include "virsocketaddr.h" + +typedef struct _virIPLease virIPLease; +typedef virIPLease *virIPLeasePtr; + +struct _virIPLease { + virSocketAddr addr; + time_t timeout; +}; + +#define VIR_IPLEASE_TIMEOUT_NONE (-1) + +#endif /* __VIR_IP_LEASE_H__ */ Index: libvirt-acl/src/conf/nwfilter_ipaddrmap.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_ipaddrmap.c +++ libvirt-acl/src/conf/nwfilter_ipaddrmap.c @@ -28,6 +28,7 @@ #include "virterror_internal.h" #include "datatypes.h" +#include "memory.h" #include "nwfilter_params.h" #include "nwfilter_ipaddrmap.h" @@ -142,6 +143,56 @@ virNWFilterIPAddrMapGetIPAddr(const char return res; } +/* + * Get the IP addresses associated with the interface as an array + * of virIPLease. Since we don't know about lease timeouts here, we + * set the lease timeout to VIR_IPLEASE_TIMEOUT_NONE. + */ +int +virNWFilterIPAddrMapGetIPLeases(const char *ifname, + virIPLeasePtr *leases, size_t *nLeases) +{ + int ret = 0; + virNWFilterVarValuePtr val; + virIPLeasePtr myleases = NULL; + + *leases = NULL; + + virMutexLock(&ipAddressMapLock); + + val = virHashLookup(ipAddressMap->hashTable, ifname); + + if (val) { + size_t card = virNWFilterVarValueGetCardinality(val); + unsigned int i; + + if (VIR_ALLOC_N(myleases, card) < 0) { + virReportOOMError(); + ret = -1; + goto cleanup; + } + + for (i = 0; i < card; i++) { + const char *value = virNWFilterVarValueGetNthValue(val, i); + + if (virSocketAddrParse(&myleases[i].addr, value, AF_UNSPEC) < 0) { + VIR_FREE(myleases); + ret = -1; + goto cleanup; + } + myleases[i].timeout = VIR_IPLEASE_TIMEOUT_NONE; + } + + *leases = myleases; + *nLeases = card; + } + +cleanup: + virMutexUnlock(&ipAddressMapLock); + + return ret; +} + int virNWFilterIPAddrMapInit(void) { -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list