[PATCH V5 1/4] Rework value part of name-value pairs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

This patch adjusts all code that was handling the values in hash tables
and makes it use the new data type.

v5:
 - Addressing Eric Blake's comments: fixed function signatures

v4:
 - Fixed virNWFilterVarValueDelValue to maintain order of elements

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxxxxxxx>

---
 src/conf/domain_conf.c                    |    2 
 src/conf/nwfilter_params.c                |  214 ++++++++++++++++++++++++++++--
 src/conf/nwfilter_params.h                |   32 ++++
 src/libvirt_private.syms                  |    3 
 src/nwfilter/nwfilter_ebiptables_driver.c |   15 +-
 src/nwfilter/nwfilter_gentech_driver.c    |   24 ++-
 src/nwfilter/nwfilter_learnipaddr.c       |   13 +
 7 files changed, 285 insertions(+), 18 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
@@ -34,10 +34,198 @@
 
 #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;
+}
+
+virNWFilterVarValuePtr
+virNWFilterVarValueCreateSimple(char *value)
+{
+    virNWFilterVarValuePtr val;
+
+    if (!isValidVarValue(value)) {
+        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Variable value contains illegal character"));
+        return NULL;
+    }
+
+    if (VIR_ALLOC(val) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    val->valType = NWFILTER_VALUE_TYPE_SIMPLE;
+    val->u.simple.value = value;
+
+    return val;
+}
+
+virNWFilterVarValuePtr
+virNWFilterVarValueCreateSimpleCopyValue(const char *value)
+{
+    char *val = strdup(value);
+
+    if (!val) {
+        virReportOOMError();
+        return NULL;
+    }
+    return virNWFilterVarValueCreateSimple(val);
+}
+
+const char *
+virNWFilterVarValueGetSimple(const 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(const 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
+virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value)
+{
+    char *tmp;
+    bool rc = 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] = value;
+        rc  = true;
+        break;
+
+    case NWFILTER_VALUE_TYPE_ARRAY:
+        if (VIR_EXPAND_N(val->u.array.values,
+                         val->u.array.nValues, 1) < 0) {
+            virReportOOMError();
+            return false;
+        }
+        val->u.array.values[val->u.array.nValues - 1] = value;
+        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 +244,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 +348,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 +365,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 +403,17 @@ isValidVarValue(const char *value)
     return value[strspn(value, VALID_VARVALUE)] == 0;
 }
 
+static virNWFilterVarValuePtr
+virNWFilterParseVarValue(const char *val)
+{
+    return virNWFilterVarValueCreateSimpleCopyValue(val);
+}
 
 virNWFilterHashTablePtr
 virNWFilterParseParamAttributes(xmlNodePtr cur)
 {
     char *nam, *val;
+    virNWFilterVarValuePtr value;
 
     virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0);
     if (!table) {
@@ -234,20 +428,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);
             }
Index: libvirt-acl/src/conf/nwfilter_params.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_params.h
+++ libvirt-acl/src/conf/nwfilter_params.h
@@ -26,6 +26,36 @@
 # 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;
+            size_t nValues;
+        } array;
+    } u;
+};
+
+virNWFilterVarValuePtr virNWFilterVarValueCreateSimple(char *);
+virNWFilterVarValuePtr virNWFilterVarValueCreateSimpleCopyValue(const char *);
+const char *virNWFilterVarValueGetSimple(const virNWFilterVarValuePtr val);
+const char *virNWFilterVarValueGetNthValue(virNWFilterVarValuePtr val,
+                                           unsigned int idx);
+unsigned int virNWFilterVarValueGetCardinality(const virNWFilterVarValuePtr);
+bool virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value);
+
 typedef struct _virNWFilterHashTable virNWFilterHashTable;
 typedef virNWFilterHashTable *virNWFilterHashTablePtr;
 struct _virNWFilterHashTable {
@@ -45,7 +75,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
@@ -3182,7 +3182,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,16 @@ virNWFilterVarHashmapAddStdValues(virNWF
                                   char *macaddr,
                                   char *ipaddr)
 {
+    virNWFilterVarValue *val;
+
     if (macaddr) {
+        val = virNWFilterVarValueCreateSimple(macaddr);
+        if (!val)
+            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 +164,13 @@ virNWFilterVarHashmapAddStdValues(virNWF
     }
 
     if (ipaddr) {
+        val = virNWFilterVarValueCreateSimple(ipaddr);
+        if (!val)
+            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 +501,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 +510,17 @@ virNWFilterDetermineMissingVarsRec(virCo
             /* check all variables of this rule */
             for (j = 0; j < rule->nvars; j++) {
                 if (!virHashLookup(vars->hashTable, rule->vars[j])) {
+                    val = virNWFilterVarValueCreateSimpleCopyValue("1");
+                    if (!val) {
+                        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);
+
+    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
@@ -885,6 +885,9 @@ virNWFilterHashTableFree;
 virNWFilterHashTablePut;
 virNWFilterHashTablePutAll;
 virNWFilterHashTableRemoveEntry;
+virNWFilterVarValueCreateSimple;
+virNWFilterVarValueCreateSimpleCopyValue;
+virNWFilterVarValueGetSimple;
 
 
 # pci.h

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]