I rewrote some parts of this patch here. Will send out a V2.
Stefan
On 10/21/2011 03:31 PM, Stefan Berger wrote:
This patch extends the NWFilter driver for Linux (ebiptables) to
create
rules for each member of a previously introduced list. If for example
an attribute value looks like this:
IP = [10.0.0.1, 10.0.0.2, 10.0.0.3]
then 3 rules will be generated for a rule accessing the variable 'IP',
one for each member of the list. The effect of this is that this now
allows for filtering for multiple values in one field. This can then be
used to support for filtering/allowing of multiple IP addresses per
interface.
An interator is introduced that extracts each member of a list and
puts it into a hash table which then is passed to the function creating
a rule. For the above example the iterator would cause 3 loops.
Signed-off-by: Stefan Berger<stefanb(a)linux.vnet.ibm.com>
---
src/conf/nwfilter_params.c | 146 ++++++++++++++++++++++++++++++
src/conf/nwfilter_params.h | 25 +++++
src/libvirt_private.syms | 4
src/nwfilter/nwfilter_ebiptables_driver.c | 44 ++++++++-
4 files changed, 218 insertions(+), 1 deletion(-)
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
@@ -2513,6 +2513,48 @@ ebiptablesCreateRuleInstance(virConnectP
return rc;
}
+static int
+ebiptablesCreateRuleInstanceCombinations(
+ virConnectPtr conn ATTRIBUTE_UNUSED,
+ enum virDomainNetType nettype ATTRIBUTE_UNUSED,
+ virNWFilterDefPtr nwfilter,
+ virNWFilterRuleDefPtr rule,
+ const char *ifname,
+ virNWFilterHashTablePtr vars,
+ virNWFilterRuleInstPtr res)
+{
+ int rc = 0;
+ virNWFilterVarCombIterPtr iter;
+ virNWFilterHashTablePtr itervars;
+
+ /* rule->vars holds all the variables names that this rule will access.
+ * iterate over all combinations of the variables' values and instantiate
+ * the filtering rule with each combination.
+ */
+ iter = virNWFilterVarCombIterCreate(vars, rule->vars, rule->nvars);
+ if (!iter) {
+ return 1;
+ }
+
+ itervars = virNWFilterVarCombIterFirst(iter);
+
+ while (rc == 0&& itervars != NULL) {
+ rc = ebiptablesCreateRuleInstance(conn,
+ nettype,
+ nwfilter,
+ rule,
+ ifname,
+ itervars,
+ res);
+ if (rc)
+ break;
+ itervars = virNWFilterVarCombIterNext(iter,&rc);
+ };
+
+ virNWFilterVarCombIterFree(iter);
+
+ return rc;
+}
static int
ebiptablesFreeRuleInstance(void *_inst)
@@ -3896,7 +3938,7 @@ virNWFilterTechDriver ebiptables_driver
.init = ebiptablesDriverInit,
.shutdown = ebiptablesDriverShutdown,
- .createRuleInstance = ebiptablesCreateRuleInstance,
+ .createRuleInstance = ebiptablesCreateRuleInstanceCombinations,
.applyNewRules = ebiptablesApplyNewRules,
.tearNewRules = ebiptablesTearNewRules,
.tearOldRules = ebiptablesTearOldRules,
Index: libvirt-acl/src/conf/nwfilter_params.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_params.c
+++ libvirt-acl/src/conf/nwfilter_params.c
@@ -288,6 +288,152 @@ virNWFilterVarValueAddValue(virNWFilterV
return rc;
}
+void
+virNWFilterVarCombIterFree(virNWFilterVarCombIterPtr ci)
+{
+ if (!ci)
+ return;
+
+ virNWFilterHashTableFree(ci->hashTable);
+ VIR_FREE(ci);
+}
+
+virNWFilterVarCombIterPtr
+virNWFilterVarCombIterCreate(virNWFilterHashTablePtr hash,
+ char * const *vars, unsigned int nVars)
+{
+ virNWFilterVarCombIterPtr res;
+ virNWFilterVarValuePtr value, orig;
+ unsigned int i;
+ const char *val;
+
+ if (VIR_ALLOC_VAR(res, virNWFilterVarCombEntry, nVars)< 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ res->hashTable = virNWFilterHashTableCreate(nVars);
+ res->nEntries = nVars;
+ res->orig = hash;
+
+ for (i = 0; i< nVars; i++) {
+ orig = virHashLookup(hash->hashTable, vars[i]);
+ if (orig == NULL) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find value for variable
'%s'"),
+ vars[i]);
+ goto err_exit;
+ }
+
+ res->entry[i].key = vars[i];
+ res->entry[i].cardinality = virNWFilterVarValueGetCardinality(orig);
+
+ val = virNWFilterVarValueGetNthValue(orig, 0);
+ if (!val) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get 0.th value of "
+ "variable '%s'"),
+ res->entry[i].key);
+ goto err_exit;
+ }
+
+ value = virNWFilterVarValueCreateSimple(val, true);
+ if (!value) {
+ virReportOOMError();
+ goto err_exit;
+ }
+
+ if (virNWFilterHashTablePut(res->hashTable, vars[i], value, false)) {
+ virReportOOMError();
+ goto err_exit;
+ }
+ }
+
+ return res;
+
+err_exit:
+ virNWFilterVarCombIterFree(res);
+ return NULL;
+}
+
+virNWFilterHashTablePtr
+virNWFilterVarCombIterFirst(virNWFilterVarCombIterPtr ci)
+{
+ return ci->hashTable;
+}
+
+virNWFilterHashTablePtr
+virNWFilterVarCombIterNext(virNWFilterVarCombIterPtr ci, int *error)
+{
+ unsigned int i;
+ virNWFilterVarValuePtr value;
+ bool done = false;
+ bool end = (ci->nEntries == 0) ||
+ (ci->nEntries == 1&& ci->entry[0].cardinality == 1);
+ const char *val;
+
+ *error = 0;
+
+ if (end)
+ return NULL;
+
+ for (i = 0; i< ci->nEntries; i++) {
+ if (ci->entry[i].cardinality == 1)
+ continue;
+
+ ci->entry[i].idx++;
+ if (ci->entry[i].idx< ci->entry[i].cardinality) {
+ done = true;
+ } else {
+ ci->entry[i].idx = 0;
+ }
+
+ value = virHashLookup(ci->orig->hashTable, ci->entry[i].key);
+ if (!value) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find value for variable
'%s'"),
+ ci->entry[i].key);
+ *error = 1;
+ break;
+ }
+
+ val = virNWFilterVarValueGetNthValue(value, ci->entry[i].idx);
+ if (!val) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get nth (%u) value of "
+ "variable '%s'"),
+ ci->entry[i].idx, ci->entry[i].key);
+ *error = 1;
+ break;
+ }
+
+ value = virNWFilterVarValueCreateSimple(val, true);
+ if (!value) {
+ virReportOOMError();
+ *error = 1;
+ break;
+ }
+
+ if (virNWFilterHashTablePut(ci->hashTable, ci->entry[i].key,
+ value, false)) {
+ virReportOOMError();
+ *error = 1;
+ break;
+ }
+
+ if (done || *error)
+ break;
+ }
+
+ if (ci->nEntries == i)
+ end = true;
+
+ if (end || *error)
+ return NULL;
+
+ return ci->hashTable;
+}
+
static void
hashDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
{
Index: libvirt-acl/src/conf/nwfilter_params.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_params.h
+++ libvirt-acl/src/conf/nwfilter_params.h
@@ -89,4 +89,29 @@ int virNWFilterHashTablePutAll(virNWFilt
# define VALID_VARVALUE \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.:"
+typedef struct _virNWFilterVarCombEntry virNWFilterVarCombEntry;
+struct _virNWFilterVarCombEntry {
+ const char *key;
+ unsigned int idx;
+ unsigned int cardinality;
+};
+
+typedef struct _virNWFilterVarCombIter virNWFilterVarCombIter;
+typedef virNWFilterVarCombIter *virNWFilterVarCombIterPtr;
+struct _virNWFilterVarCombIter {
+ virNWFilterHashTablePtr hashTable;
+ virNWFilterHashTablePtr orig;
+ unsigned int nEntries;
+ virNWFilterVarCombEntry entry[1];
+};
+virNWFilterVarCombIterPtr virNWFilterVarCombIterCreate(
+ virNWFilterHashTablePtr hash,
+ char * const *vars,
+ unsigned int nvars);
+
+void virNWFilterVarCombIterFree(virNWFilterVarCombIterPtr combiter);
+virNWFilterHashTablePtr virNWFilterVarCombIterFirst(virNWFilterVarCombIterPtr);
+virNWFilterHashTablePtr virNWFilterVarCombIterNext(virNWFilterVarCombIterPtr,
+ int *error);
+
#endif /* NWFILTER_PARAMS_H */
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -878,6 +878,10 @@ virNWFilterHashTableFree;
virNWFilterHashTablePut;
virNWFilterHashTablePutAll;
virNWFilterHashTableRemoveEntry;
+virNWFilterVarCombIterCreate;
+virNWFilterVarCombIterFirst;
+virNWFilterVarCombIterFree;
+virNWFilterVarCombIterNext;
virNWFilterVarValueCreateSimple;
virNWFilterVarValueGetSimple;