static bool isValidVarValue(const char *value);
-static void
+void
virNWFilterVarValueFree(virNWFilterVarValuePtr val)
{
unsigned i;
VIR_FREE(val);
}
-static virNWFilterVarValuePtr
+virNWFilterVarValuePtr
virNWFilterVarValueCopy(const virNWFilterVarValuePtr val)
{
virNWFilterVarValuePtr res;
return rc;
}
+static int
+virNWFilterVarValueDelNthValue(virNWFilterVarValuePtr val, unsigned int pos)
+{
+ switch (val->valType) {
+ case NWFILTER_VALUE_TYPE_SIMPLE:
+ return -1;
+
+ case NWFILTER_VALUE_TYPE_ARRAY:
+ if (pos < val->u.array.nValues) {
+ VIR_FREE(val->u.array.values[pos]);
+ val->u.array.nValues--;
+
+ if (pos < val->u.array.nValues)
+ memmove(&val->u.array.values[pos],
+ &val->u.array.values[pos + 1],
+ sizeof(val->u.array.values[0]) *
+ (val->u.array.nValues - pos));
+ return 0;
+ }
+ break;
+
+ case NWFILTER_VALUE_TYPE_LAST:
+ break;
+ }
+
+ return -1;
+}
+
+int
+virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value)
+{
+ unsigned int i;
+
+ switch (val->valType) {
+ case NWFILTER_VALUE_TYPE_SIMPLE:
+ return -1;
+
+ case NWFILTER_VALUE_TYPE_ARRAY:
+ for (i = 0; i < val->u.array.nValues; i++)
+ if (STREQ(value, val->u.array.values[i]))
+ return virNWFilterVarValueDelNthValue(val, i);
+ break;
+
+ case NWFILTER_VALUE_TYPE_LAST:
+ break;
+ }
+
+ return -1;
+}
+
void
virNWFilterVarCombIterFree(virNWFilterVarCombIterPtr ci)
{
}
-int
+void *
virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr ht,
const char *entry)
{
int i;
- int rc = virHashRemoveEntry(ht->hashTable, entry);
+ void *value = virHashSteal(ht->hashTable, entry);
- if (rc == 0) {
+ if (value) {
for (i = 0; i < ht->nNames; i++) {
if (STREQ(ht->names[i], entry)) {
VIR_FREE(ht->names[i]);
}
}
}
- return rc;
+ return value;
}
virNWFilterVarValuePtr virNWFilterVarValueCreateSimple(char *);
virNWFilterVarValuePtr virNWFilterVarValueCreateSimpleCopyValue(const char *);
+virNWFilterVarValuePtr virNWFilterVarValueCopy(const virNWFilterVarValuePtr);
+void virNWFilterVarValueFree(virNWFilterVarValuePtr val);
const char *virNWFilterVarValueGetSimple(const virNWFilterVarValuePtr val);
const char *virNWFilterVarValueGetNthValue(virNWFilterVarValuePtr val,
unsigned int idx);
unsigned int virNWFilterVarValueGetCardinality(const virNWFilterVarValuePtr);
int virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value);
+int virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value);
typedef struct _virNWFilterHashTable virNWFilterHashTable;
typedef virNWFilterHashTable *virNWFilterHashTablePtr;
const char *name,
virNWFilterVarValuePtr val,
int freeName);
-int virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table,
- const char *name);
+void *virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table,
+ const char *name);
int virNWFilterHashTablePutAll(virNWFilterHashTablePtr src,
virNWFilterHashTablePtr dest);
virNWFilterVarCombIterFree;
virNWFilterVarCombIterGetVarValue;
virNWFilterVarCombIterNext;
+virNWFilterVarValueAddValue;
+virNWFilterVarValueCopy;
virNWFilterVarValueCreateSimple;
virNWFilterVarValueCreateSimpleCopyValue;
+virNWFilterVarValueDelValue;
+virNWFilterVarValueFree;
+virNWFilterVarValueGetCardinality;
+virNWFilterVarValueGetNthValue;
virNWFilterVarValueGetSimple;
static int
virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table,
char *macaddr,
- char *ipaddr)
+ const virNWFilterVarValuePtr ipaddr)
{
virNWFilterVarValue *val;
}
if (ipaddr) {
- val = virNWFilterVarValueCreateSimple(ipaddr);
+ val = virNWFilterVarValueCopy(ipaddr);
if (!val)
return 1;
* is attached to the virConnect object.
*/
virNWFilterHashTablePtr
-virNWFilterCreateVarHashmap(char *macaddr, char *ipaddr) {
+virNWFilterCreateVarHashmap(char *macaddr,
+ const virNWFilterVarValuePtr ipaddr) {
virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0);
if (!table) {
virReportOOMError();
virNWFilterDefPtr filter;
char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0};
char *str_macaddr = NULL;
- const char *ipaddr;
+ virNWFilterVarValuePtr ipaddr;
char *str_ipaddr = NULL;
techdriver = virNWFilterTechDriverForName(drvname);
}
ipaddr = virNWFilterGetIpAddrForIfname(ifname);
- if (ipaddr) {
- str_ipaddr = strdup(ipaddr);
- if (!str_ipaddr) {
- virReportOOMError();
- rc = 1;
- goto err_exit;
- }
- }
- vars1 = virNWFilterCreateVarHashmap(str_macaddr, str_ipaddr);
+ vars1 = virNWFilterCreateVarHashmap(str_macaddr, ipaddr);
if (!vars1) {
rc = 1;
goto err_exit;
techdriver->allTeardown(ifname);
- virNWFilterDelIpAddrForIfname(ifname);
+ virNWFilterDelIpAddrForIfname(ifname, NULL);
virNWFilterUnlockIface(ifname);
int virNWFilterTeardownFilter(const virDomainNetDefPtr net);
virNWFilterHashTablePtr virNWFilterCreateVarHashmap(char *macaddr,
- char *ipaddr);
+ const virNWFilterVarValuePtr);
void virNWFilterDomainFWUpdateCB(void *payload,
const void *name,
return res;
}
-
-
+/* Add an IP address to the list of IP addresses an interface is
+ * known to use. This function feeds the per-interface cache that
+ * is used to instantiate filters with variable '$IP'.
+ *
+ * @ifname: The name of the (tap) interface
+ * @addr: An IPv4 address in dotted decimal format that the (tap)
+ * interface is known to use.
+ *
+ * This function returns 0 on success, -1 otherwise
+ */
static int
-virNWFilterAddIpAddrForIfname(const char *ifname, char *addr) {
+virNWFilterAddIpAddrForIfname(const char *ifname, char *addr)
+{
int ret;
- virNWFilterVarValuePtr val = virNWFilterVarValueCreateSimple(addr);
-
- if (!val)
- return 1;
+ virNWFilterVarValuePtr val;
virMutexLock(&ipAddressMapLock);
- ret = virNWFilterHashTablePut(ipAddressMap, ifname, val, 1);
+ val = virHashLookup(ipAddressMap->hashTable, ifname);
+ if (!val) {
+ val = virNWFilterVarValueCreateSimple(addr);
+ if (!val) {
+ virReportOOMError();
+ ret = -1;
+ goto err_exit;
+ }
+ ret = virNWFilterHashTablePut(ipAddressMap, ifname, val, 1);
+ } else {
+ if (virNWFilterVarValueAddValue(val, addr) < 0)
+ ret = -1;
+ }
+err_exit:
virMutexUnlock(&ipAddressMapLock);
return ret;
}
#endif
-
-void
-virNWFilterDelIpAddrForIfname(const char *ifname) {
+/* Delete all or a specific IP address from an interface. After this
+ * call either all or the given IP address will not be associated
+ * with the interface anymore.
+ *
+ * @ifname: The name of the (tap) interface
+ * @addr: An IPv4 address in dotted decimal format that the (tap)
+ * interface is not using anymore; provide NULL to remove all IP
+ * addresses associated with the given interface
+ *
+ * This function returns the number of IP addresses that are still
+ * known to be associated with this interface, in case of an error
+ * -1 is returned. Error conditions are:
+ * - IP addresses is not known to be associated with the interface
+ */
+int
+virNWFilterDelIpAddrForIfname(const char *ifname, const char *ipaddr)
+{
+ int ret = -1;
+ virNWFilterVarValuePtr val = NULL;
virMutexLock(&ipAddressMapLock);
- if (virHashLookup(ipAddressMap->hashTable, ifname))
- virNWFilterHashTableRemoveEntry(ipAddressMap, ifname);
+ if (ipaddr != NULL) {
+ val = virHashLookup(ipAddressMap->hashTable, ifname);
+ if (val) {
+ if (virNWFilterVarValueGetCardinality(val) == 1 &&
+ STREQ(ipaddr,
+ virNWFilterVarValueGetNthValue(val, 0)))
+ goto remove_entry;
+ virNWFilterVarValueDelValue(val, ipaddr);
+ ret = virNWFilterVarValueGetCardinality(val);
+ }
+ } else {
+remove_entry:
+ /* remove whole entry */
+ val = virNWFilterHashTableRemoveEntry(ipAddressMap, ifname);
+ virNWFilterVarValueFree(val);
+ ret = 0;
+ }
virMutexUnlock(&ipAddressMapLock);
-}
+ return ret;
+}
-const char *
-virNWFilterGetIpAddrForIfname(const char *ifname) {
+/* Get the list of IP addresses known to be in use by an interface
+ *
+ * This function returns NULL in case no IP address is known to be
+ * associated with the interface, a virNWFilterVarValuePtr otherwise
+ * that then can contain one or multiple entries.
+ */
+virNWFilterVarValuePtr
+virNWFilterGetIpAddrForIfname(const char *ifname)
+{
virNWFilterVarValuePtr res;
virMutexLock(&ipAddressMapLock);
virMutexUnlock(&ipAddressMapLock);
- if (res)
- return virNWFilterVarValueGetSimple(res);
-
- return NULL;
+ return res;
}
char *inetaddr;
if ((inetaddr = virSocketAddrFormat(&sa))!= NULL) {
- virNWFilterAddIpAddrForIfname(req->ifname, inetaddr);
+ if (virNWFilterAddIpAddrForIfname(req->ifname, inetaddr) < 0) {
+ VIR_ERROR(_("Failed to add IP address %s to IP address "
+ "cache for interface %s"), inetaddr, req->ifname);
+ }
ret = virNWFilterInstantiateFilterLate(NULL,
req->ifname,
#ifndef __NWFILTER_LEARNIPADDR_H
# define __NWFILTER_LEARNIPADDR_H
+# include "conf/nwfilter_params.h"
+
enum howDetect {
DETECT_DHCP = 1,
DETECT_STATIC = 2,
virNWFilterIPAddrLearnReqPtr virNWFilterLookupLearnReq(int ifindex);
int virNWFilterTerminateLearnReq(const char *ifname);
-void virNWFilterDelIpAddrForIfname(const char *ifname);
-const char *virNWFilterGetIpAddrForIfname(const char *ifname);
+int virNWFilterDelIpAddrForIfname(const char *ifname, const char *ipaddr);
+virNWFilterVarValuePtr virNWFilterGetIpAddrForIfname(const char *ifname);
int virNWFilterLockIface(const char *ifname) ATTRIBUTE_RETURN_CHECK;
void virNWFilterUnlockIface(const char *ifname);