NWFilters can be provided name-value pairs using the following
XML notiation:
<filterref filter='xyz'>
<parameter name='PORT' value='80'/>
<parameter name='VAL' value='abc'/>
</filterref>
The internal representation currently is so that a name is stored as a
string and the value as well. This patch now addresses the value part of it
and introduces a data structure for storing a value either as a simple
value or as an array for later support of lists (provided in python-like
notation ( [a,b,c] ).
This patch adjusts all code that was handling the values in hash tables
and makes it use the new data type.
Signed-off-by: Stefan Berger <stefanb(a)linux.vnet.ibm.com>
---
src/conf/domain_conf.c | 2
src/conf/nwfilter_params.c | 288 ++++++++++++++++++++++++++++--
src/conf/nwfilter_params.h | 38 +++
src/libvirt_private.syms | 3
src/nwfilter/nwfilter_ebiptables_driver.c | 15 +
src/nwfilter/nwfilter_gentech_driver.c | 27 ++
src/nwfilter/nwfilter_learnipaddr.c | 13 +
7 files changed, 365 insertions(+), 21 deletions(-)
Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -200,14 +200,25 @@ printVar(virNWFilterHashTablePtr vars,
*done = 0;
if ((item->flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
- char *val = (char *)virHashLookup(vars->hashTable, item->var);
- if (!val) {
+ virNWFilterVarValuePtr varval;
+ const char *val;
+
+ varval = virHashLookup(vars->hashTable, item->var);
+ if (!varval) {
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot find value for '%s'"),
item->var);
return 1;
}
+ val = virNWFilterVarValueGetSimple(varval);
+ if (!val) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot get simple value of
'%s'"),
+ item->var);
+ return 1;
+ }
+
if (!virStrcpy(buf, val, bufsize)) {
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
_("Buffer to small to print MAC address "
Index: libvirt-acl/src/conf/nwfilter_params.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_params.c
+++ libvirt-acl/src/conf/nwfilter_params.c
@@ -30,14 +30,268 @@
#include "datatypes.h"
#include "nwfilter_params.h"
#include "domain_conf.h"
+#include "c-ctype.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
+static bool isValidVarValue(const char *value);
+
+
+static void
+virNWFilterVarValueFree(virNWFilterVarValuePtr val)
+{
+ unsigned i;
+
+ if (!val)
+ return;
+
+ switch (val->valType) {
+ case NWFILTER_VALUE_TYPE_SIMPLE:
+ VIR_FREE(val->u.simple.value);
+ break;
+ case NWFILTER_VALUE_TYPE_ARRAY:
+ for (i = 0; i < val->u.array.nValues; i++)
+ VIR_FREE(val->u.array.values[i]);
+ VIR_FREE(val->u.array.values);
+ break;
+ case NWFILTER_VALUE_TYPE_LAST:
+ break;
+ }
+ VIR_FREE(val);
+}
+
+static virNWFilterVarValuePtr
+virNWFilterVarValueCopy(const virNWFilterVarValuePtr val)
+{
+ virNWFilterVarValuePtr res;
+ unsigned i;
+ char *str;
+
+ if (VIR_ALLOC(res) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+ res->valType = val->valType;
+
+ switch (res->valType) {
+ case NWFILTER_VALUE_TYPE_SIMPLE:
+ if (val->u.simple.value) {
+ res->u.simple.value = strdup(val->u.simple.value);
+ if (!res->u.simple.value)
+ goto err_exit;
+ }
+ break;
+ case NWFILTER_VALUE_TYPE_ARRAY:
+ if (VIR_ALLOC_N(res->u.array.values, val->u.array.nValues))
+ goto err_exit;
+ res->u.array.nValues = val->u.array.nValues;
+ for (i = 0; i < val->u.array.nValues; i++) {
+ str = strdup(val->u.array.values[i]);
+ if (!str)
+ goto err_exit;
+ res->u.array.values[i] = str;
+ }
+ break;
+ case NWFILTER_VALUE_TYPE_LAST:
+ break;
+ }
+
+ return res;
+
+err_exit:
+ virReportOOMError();
+ virNWFilterVarValueFree(res);
+ return NULL;
+}
+
+void
+virNWFilterVarValuePrint(virNWFilterVarValuePtr val, virBufferPtr buf)
+{
+ unsigned i;
+ char *item;
+
+ switch (val->valType) {
+ case NWFILTER_VALUE_TYPE_SIMPLE:
+ virBufferAdd(buf, val->u.simple.value, -1);
+ break;
+ case NWFILTER_VALUE_TYPE_ARRAY:
+ virBufferAddLit(buf, "[");
+ for (i = 0; i < val->u.array.nValues; i++) {
+ if (i > 0)
+ virBufferAddLit(buf, ", ");
+ item = val->u.array.values[i];
+ if (item) {
+ bool quote = false;
+ if (c_isspace(item[0]) || c_isspace(item[strlen(item)- 1 ]))
+ quote = true;
+ if (quote)
+ virBufferEscapeString(buf, "%s", "'");
+ virBufferAdd(buf, val->u.array.values[i], -1);
+ if (quote)
+ virBufferEscapeString(buf, "%s", "'");
+ }
+ }
+ virBufferAddLit(buf, "]");
+ break;
+ case NWFILTER_VALUE_TYPE_LAST:
+ break;
+ }
+}
+
+virNWFilterVarValuePtr
+virNWFilterVarValueCreateSimple(const char *value, bool copy_value)
+{
+ virNWFilterVarValuePtr val;
+
+ if (!isValidVarValue(value))
+ return NULL;
+
+ if (VIR_ALLOC(val) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ val->valType = NWFILTER_VALUE_TYPE_SIMPLE;
+ if (copy_value) {
+ val->u.simple.value = strdup(value);
+ if (!val->u.simple.value) {
+ VIR_FREE(val);
+ virReportOOMError();
+ return NULL;
+ }
+ } else
+ val->u.simple.value = (char *)value;
+
+ return val;
+}
+
+const char *
+virNWFilterVarValueGetSimple(virNWFilterVarValuePtr val)
+{
+ if (val->valType == NWFILTER_VALUE_TYPE_SIMPLE)
+ return val->u.simple.value;
+ return NULL;
+}
+
+const char *
+virNWFilterVarValueGetNthValue(virNWFilterVarValuePtr val, unsigned int idx)
+{
+ const char *res = NULL;
+
+ switch (val->valType) {
+ case NWFILTER_VALUE_TYPE_SIMPLE:
+ if (idx == 0)
+ res = val->u.simple.value;
+ break;
+ case NWFILTER_VALUE_TYPE_ARRAY:
+ if (idx < val->u.array.nValues)
+ res = val->u.array.values[idx];
+ break;
+ case NWFILTER_VALUE_TYPE_LAST:
+ break;
+ }
+
+ return res;
+}
+
+unsigned int
+virNWFilterVarValueGetCardinality(virNWFilterVarValuePtr val)
+{
+ switch (val->valType) {
+ case NWFILTER_VALUE_TYPE_SIMPLE:
+ return 1;
+ break;
+ case NWFILTER_VALUE_TYPE_ARRAY:
+ return val->u.array.nValues;
+ break;
+ case NWFILTER_VALUE_TYPE_LAST:
+ return 0;
+ }
+ return 0;
+}
+
+bool
+virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value)
+{
+ unsigned int i;
+
+ switch (val->valType) {
+ case NWFILTER_VALUE_TYPE_SIMPLE:
+ return false;
+
+ case NWFILTER_VALUE_TYPE_ARRAY:
+ for (i = 0; i < val->u.array.nValues; i++) {
+ if (STREQ(value, val->u.array.values[i])) {
+ VIR_FREE(val->u.array.values[i]);
+ val->u.array.nValues--;
+ val->u.array.values[i] =
+ val->u.array.values[val->u.array.nValues];
+ return true;
+ }
+ }
+ break;
+
+ case NWFILTER_VALUE_TYPE_LAST:
+ break;
+ }
+
+ return false;
+}
+
+bool
+virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, const char *value,
+ bool make_copy)
+{
+ char *tmp;
+ bool rc = false;
+
+ if (make_copy) {
+ value = strdup(value);
+ if (!value) {
+ virReportOOMError();
+ return false;
+ }
+ }
+
+ switch (val->valType) {
+ case NWFILTER_VALUE_TYPE_SIMPLE:
+ /* switch to array */
+ tmp = val->u.simple.value;
+ if (VIR_ALLOC_N(val->u.array.values, 2) < 0) {
+ val->u.simple.value = tmp;
+ virReportOOMError();
+ return false;
+ }
+ val->valType = NWFILTER_VALUE_TYPE_ARRAY;
+ val->u.array.nValues = 2;
+ val->u.array.values[0] = tmp;
+ val->u.array.values[1] = (char *)value;
+ rc = true;
+ break;
+
+ case NWFILTER_VALUE_TYPE_ARRAY:
+ if (VIR_REALLOC_N(val->u.array.values,
+ val->u.array.nValues + 1) < 0) {
+ virReportOOMError();
+ return false;
+ }
+ val->u.array.values[val->u.array.nValues] = (char *)value;
+ val->u.array.nValues += 1;
+ rc = true;
+ break;
+
+ case NWFILTER_VALUE_TYPE_LAST:
+ break;
+ }
+
+ return rc;
+}
+
static void
hashDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
{
- VIR_FREE(payload);
+ virNWFilterVarValueFree(payload);
}
@@ -56,7 +310,7 @@ hashDataFree(void *payload, const void *
int
virNWFilterHashTablePut(virNWFilterHashTablePtr table,
const char *name,
- char *val,
+ virNWFilterVarValuePtr val,
int copyName)
{
if (!virHashLookup(table->hashTable, name)) {
@@ -160,12 +414,12 @@ static void
addToTable(void *payload, const void *name, void *data)
{
struct addToTableStruct *atts = (struct addToTableStruct *)data;
- char *val;
+ virNWFilterVarValuePtr val;
if (atts->errOccurred)
return;
- val = strdup((char *)payload);
+ val = virNWFilterVarValueCopy((virNWFilterVarValuePtr)payload);
if (!val) {
virReportOOMError();
atts->errOccurred = 1;
@@ -177,7 +431,7 @@ addToTable(void *payload, const void *na
_("Could not put variable '%s' into
hashmap"),
(const char *)name);
atts->errOccurred = 1;
- VIR_FREE(val);
+ virNWFilterVarValueFree(val);
}
}
@@ -215,11 +469,17 @@ isValidVarValue(const char *value)
return value[strspn(value, VALID_VARVALUE)] == 0;
}
+static virNWFilterVarValuePtr
+virNWFilterParseVarValue(const char *val)
+{
+ return virNWFilterVarValueCreateSimple(val, true);
+}
virNWFilterHashTablePtr
virNWFilterParseParamAttributes(xmlNodePtr cur)
{
char *nam, *val;
+ virNWFilterVarValuePtr value;
virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0);
if (!table) {
@@ -234,20 +494,24 @@ virNWFilterParseParamAttributes(xmlNodeP
if (xmlStrEqual(cur->name, BAD_CAST "parameter")) {
nam = virXMLPropString(cur, "name");
val = virXMLPropString(cur, "value");
+ value = NULL;
if (nam != NULL && val != NULL) {
if (!isValidVarName(nam))
goto skip_entry;
- if (!isValidVarValue(nam))
+ value = virNWFilterParseVarValue(val);
+ if (!value)
goto skip_entry;
- if (virNWFilterHashTablePut(table, nam, val, 1)) {
+ if (virNWFilterHashTablePut(table, nam, value, 1)) {
VIR_FREE(nam);
VIR_FREE(val);
+ virNWFilterVarValueFree(value);
virNWFilterHashTableFree(table);
return NULL;
}
- val = NULL;
+ value = NULL;
}
skip_entry:
+ virNWFilterVarValueFree(value);
VIR_FREE(nam);
VIR_FREE(val);
}
@@ -268,11 +532,13 @@ static void
_formatParameterAttrs(void *payload, const void *name, void *data)
{
struct formatterParam *fp = (struct formatterParam *)data;
+ virNWFilterVarValuePtr value = payload;
- virBufferAsprintf(fp->buf, "%s<parameter name='%s'
value='%s'/>\n",
+ virBufferAsprintf(fp->buf, "%s<parameter name='%s'
value='",
fp->indent,
- (const char *)name,
- (char *)payload);
+ (const char *)name);
+ virNWFilterVarValuePrint(value, fp->buf);
+ virBufferAddLit(fp->buf, "'/>\n");
}
Index: libvirt-acl/src/conf/nwfilter_params.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_params.h
+++ libvirt-acl/src/conf/nwfilter_params.h
@@ -23,6 +23,42 @@
# define NWFILTER_PARAMS_H
# include "hash.h"
+# include "buf.h"
+
+enum virNWFilterVarValueType {
+ NWFILTER_VALUE_TYPE_SIMPLE,
+ NWFILTER_VALUE_TYPE_ARRAY,
+
+ NWFILTER_VALUE_TYPE_LAST
+};
+
+typedef struct _virNWFilterVarValue virNWFilterVarValue;
+typedef virNWFilterVarValue *virNWFilterVarValuePtr;
+struct _virNWFilterVarValue {
+ enum virNWFilterVarValueType valType;
+ union {
+ struct {
+ char *value;
+ } simple;
+ struct {
+ char **values;
+ unsigned nValues;
+ } array;
+ } u;
+};
+
+virNWFilterVarValuePtr virNWFilterVarValueCreateSimple(const char *,
+ bool copy_value);
+const char *virNWFilterVarValueGetSimple(virNWFilterVarValuePtr val);
+const char *virNWFilterVarValueGetNthValue(virNWFilterVarValuePtr val,
+ unsigned int idx);
+unsigned int virNWFilterVarValueGetCardinality(virNWFilterVarValuePtr val);
+bool virNWFilterVarValueDelValue(virNWFilterVarValuePtr val,
+ const char *value);
+bool virNWFilterVarValueAddValue(virNWFilterVarValuePtr val,
+ const char *value,
+ bool make_copy);
+void virNWFilterVarValuePrint(virNWFilterVarValuePtr val, virBufferPtr buf);
typedef struct _virNWFilterHashTable virNWFilterHashTable;
typedef virNWFilterHashTable *virNWFilterHashTablePtr;
@@ -42,7 +78,7 @@ virNWFilterHashTablePtr virNWFilterHashT
void virNWFilterHashTableFree(virNWFilterHashTablePtr table);
int virNWFilterHashTablePut(virNWFilterHashTablePtr table,
const char *name,
- char *val,
+ virNWFilterVarValuePtr val,
int freeName);
int virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table,
const char *name);
Index: libvirt-acl/src/conf/domain_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/domain_conf.c
+++ libvirt-acl/src/conf/domain_conf.c
@@ -3152,7 +3152,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
event_idx = virXMLPropString(cur, "event_idx");
} else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) {
filter = virXMLPropString(cur, "filter");
- VIR_FREE(filterparams);
+ virNWFilterHashTableFree(filterparams);
filterparams = virNWFilterParseParamAttributes(cur);
} else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
xmlStrEqual(cur->name, BAD_CAST "state")) {
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
@@ -147,10 +147,17 @@ virNWFilterVarHashmapAddStdValues(virNWF
char *macaddr,
char *ipaddr)
{
+ virNWFilterVarValue *val;
+
if (macaddr) {
+ val = virNWFilterVarValueCreateSimple(macaddr, false);
+ if (!val) {
+ virReportOOMError();
+ return 1;
+ }
if (virHashAddEntry(table->hashTable,
NWFILTER_STD_VAR_MAC,
- macaddr) < 0) {
+ val) < 0) {
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Could not add variable
'MAC' to hashmap"));
return 1;
@@ -158,9 +165,14 @@ virNWFilterVarHashmapAddStdValues(virNWF
}
if (ipaddr) {
+ val = virNWFilterVarValueCreateSimple(ipaddr, false);
+ if (!val) {
+ virReportOOMError();
+ return 1;
+ }
if (virHashAddEntry(table->hashTable,
NWFILTER_STD_VAR_IP,
- ipaddr) < 0) {
+ val) < 0) {
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Could not add variable
'IP' to hashmap"));
return 1;
@@ -491,6 +503,7 @@ virNWFilterDetermineMissingVarsRec(virCo
int rc = 0;
int i, j;
virNWFilterDefPtr next_filter;
+ virNWFilterVarValuePtr val;
for (i = 0; i < filter->nentries; i++) {
virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule;
@@ -499,10 +512,18 @@ virNWFilterDetermineMissingVarsRec(virCo
/* check all variables of this rule */
for (j = 0; j < rule->nvars; j++) {
if (!virHashLookup(vars->hashTable, rule->vars[j])) {
+ val = virNWFilterVarValueCreateSimple("1", true);
+ if (!val) {
+ virReportOOMError();
+ rc = 1;
+ break;
+ }
virNWFilterHashTablePut(missing_vars, rule->vars[j],
- strdup("1"), 1);
+ val, 1);
}
}
+ if (rc)
+ break;
} else if (inc) {
VIR_DEBUG("Following filter %s\n", inc->filterref);
obj = virNWFilterObjFindByName(&driver->nwfilters,
inc->filterref);
Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.c
+++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c
@@ -313,10 +313,14 @@ virNWFilterDeregisterLearnReq(int ifinde
static int
virNWFilterAddIpAddrForIfname(const char *ifname, char *addr) {
int ret;
+ virNWFilterVarValuePtr val = virNWFilterVarValueCreateSimple(addr, false);
+
+ if (!val)
+ return 1;
virMutexLock(&ipAddressMapLock);
- ret = virNWFilterHashTablePut(ipAddressMap, ifname, addr, 1);
+ ret = virNWFilterHashTablePut(ipAddressMap, ifname, val, 1);
virMutexUnlock(&ipAddressMapLock);
@@ -339,7 +343,7 @@ virNWFilterDelIpAddrForIfname(const char
const char *
virNWFilterGetIpAddrForIfname(const char *ifname) {
- const char *res;
+ virNWFilterVarValuePtr res;
virMutexLock(&ipAddressMapLock);
@@ -347,7 +351,10 @@ virNWFilterGetIpAddrForIfname(const char
virMutexUnlock(&ipAddressMapLock);
- return res;
+ if (res)
+ return virNWFilterVarValueGetSimple(res);
+
+ return NULL;
}
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -881,6 +881,9 @@ virNWFilterHashTableFree;
virNWFilterHashTablePut;
virNWFilterHashTablePutAll;
virNWFilterHashTableRemoveEntry;
+virNWFilterVarValueCreateSimple;
+virNWFilterVarValueGetSimple;
+virNWFilterVarValuePrint;
# pci.h