diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4fa4313687..452c8b28ea 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -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")) { diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index 871aca9b97..2a429757ef 100644 --- a/src/conf/nwfilter_params.c +++ b/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_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); } diff --git a/src/conf/nwfilter_params.h b/src/conf/nwfilter_params.h index 43452297bc..ab888649b0 100644 --- a/src/conf/nwfilter_params.h +++ b/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); +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); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fedac70605..03630dcc31 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -840,6 +840,9 @@ virNWFilterHashTableFree; virNWFilterHashTablePut; virNWFilterHashTablePutAll; virNWFilterHashTableRemoveEntry; +virNWFilterVarValueCreateSimple; +virNWFilterVarValueCreateSimpleCopyValue; +virNWFilterVarValueGetSimple; # pci.h diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index a1b12c958d..7403cbefc1 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -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 " diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 4abc6f28e5..bba7d0b678 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -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); diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 1843c98b31..d1e5648a22 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -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; }