]> xenbits.xensource.com Git - libvirt.git/commitdiff
Rework value part of name-value pairs
authorStefan Berger <stefanb@linux.vnet.ibm.com>
Fri, 18 Nov 2011 16:58:18 +0000 (11:58 -0500)
committerStefan Berger <stefanb@us.ibm.com>
Fri, 18 Nov 2011 16:58:18 +0000 (11:58 -0500)
NWFilters can be provided name-value pairs using the following
XML notation:

      <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.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
src/conf/domain_conf.c
src/conf/nwfilter_params.c
src/conf/nwfilter_params.h
src/libvirt_private.syms
src/nwfilter/nwfilter_ebiptables_driver.c
src/nwfilter/nwfilter_gentech_driver.c
src/nwfilter/nwfilter_learnipaddr.c

index 4fa4313687b25fd5e078c7fcda935679f142c9a2..452c8b28ea9ab4a1bb5a0e0b687db396282acf7f 100644 (file)
@@ -3261,7 +3261,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 871aca9b97292c0b94e55bab06c5030c07fe7b51..2a429757efce054db4930730c1ad6d8e36b01942 100644 (file)
 
 #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_INVALID_ARG,
+                               _("Variable value contains invalid 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;
+}
+
+int
+virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value)
+{
+    char *tmp;
+    int rc = -1;
+
+    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 -1;
+        }
+        val->valType = NWFILTER_VALUE_TYPE_ARRAY;
+        val->u.array.nValues = 2;
+        val->u.array.values[0] = tmp;
+        val->u.array.values[1] = value;
+        rc  = 0;
+        break;
+
+    case NWFILTER_VALUE_TYPE_ARRAY:
+        if (VIR_EXPAND_N(val->u.array.values,
+                         val->u.array.nValues, 1) < 0) {
+            virReportOOMError();
+            return -1;
+        }
+        val->u.array.values[val->u.array.nValues - 1] = value;
+        rc = 0;
+        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 *name ATTRIBUTE_UNUSED)
 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 *name, void *data)
                                _("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(xmlNodePtr cur)
             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 43452297bc5c3f281068aecff463acc287be3765..ab888649b07a347f500fc894a478ddd5d6135f22 100644 (file)
 # 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);
+int virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value);
+
 typedef struct _virNWFilterHashTable virNWFilterHashTable;
 typedef virNWFilterHashTable *virNWFilterHashTablePtr;
 struct _virNWFilterHashTable {
@@ -45,7 +75,7 @@ virNWFilterHashTablePtr virNWFilterHashTableCreate(int n);
 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 fedac70605bec8ee430870ee856c5a2b3b67a52a..03630dcc31c5195e8a9e1830f58572a0fb2afbae 100644 (file)
@@ -840,6 +840,9 @@ virNWFilterHashTableFree;
 virNWFilterHashTablePut;
 virNWFilterHashTablePutAll;
 virNWFilterHashTableRemoveEntry;
+virNWFilterVarValueCreateSimple;
+virNWFilterVarValueCreateSimpleCopyValue;
+virNWFilterVarValueGetSimple;
 
 
 # pci.h
index a1b12c958dab2b271233e2ea734fd398c65ae5ed..7403cbefc170d34398bcf9461228a201ff751232 100644 (file)
@@ -216,14 +216,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 4abc6f28e540dd1235452406f43e943438920272..bba7d0b678db80e9405a425f2cdda8a205053945 100644 (file)
@@ -147,10 +147,16 @@ virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table,
                                   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(virNWFilterHashTablePtr table,
     }
 
     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(virConnectPtr conn,
     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(virConnectPtr conn,
             /* 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 1843c98b3169ec44adf3ff9b70c85b7edab0da86..d1e5648a22be113a44f4ffc56bb177de9358579a 100644 (file)
@@ -315,10 +315,14 @@ virNWFilterDeregisterLearnReq(int ifindex) {
 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);
 
@@ -341,7 +345,7 @@ virNWFilterDelIpAddrForIfname(const char *ifname) {
 
 const char *
 virNWFilterGetIpAddrForIfname(const char *ifname) {
-    const char *res;
+    virNWFilterVarValuePtr res;
 
     virMutexLock(&ipAddressMapLock);
 
@@ -349,7 +353,10 @@ virNWFilterGetIpAddrForIfname(const char *ifname) {
 
     virMutexUnlock(&ipAddressMapLock);
 
-    return res;
+    if (res)
+        return virNWFilterVarValueGetSimple(res);
+
+    return NULL;
 }