[PATCH V3 2/4] Create rules for each member of a list

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

 



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 (internally) 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.

v2:
 - pass the iterator all the way to the function that accesses the
   hash table and provide a function to pick the value of a variable
   that is reflected by the current state of the iterator

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

---
 src/conf/nwfilter_params.c                |  129 ++++++++++++++++++++++++++++++
 src/conf/nwfilter_params.h                |   25 +++++
 src/libvirt_private.syms                  |    4 
 src/nwfilter/nwfilter_ebiptables_driver.c |   84 +++++++++++++------
 4 files changed, 215 insertions(+), 27 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
@@ -192,7 +192,7 @@ static const struct ushort_map l3_protoc
 
 
 static int
-printVar(virNWFilterHashTablePtr vars,
+printVar(virNWFilterVarCombIterPtr vars,
          char *buf, int bufsize,
          nwItemDescPtr item,
          int *done)
@@ -200,22 +200,11 @@ printVar(virNWFilterHashTablePtr vars,
     *done = 0;
 
     if ((item->flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
-        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);
+        val = virNWFilterVarCombIterGetVarValue(vars, item->var);
         if (!val) {
-            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
-                                   _("cannot get simple value of '%s'"),
-                                   item->var);
+            /* error has been reported */
             return 1;
         }
 
@@ -234,7 +223,7 @@ printVar(virNWFilterHashTablePtr vars,
 
 
 static int
-_printDataType(virNWFilterHashTablePtr vars,
+_printDataType(virNWFilterVarCombIterPtr vars,
                char *buf, int bufsize,
                nwItemDescPtr item,
                bool asHex)
@@ -329,7 +318,7 @@ _printDataType(virNWFilterHashTablePtr v
 
 
 static int
-printDataType(virNWFilterHashTablePtr vars,
+printDataType(virNWFilterVarCombIterPtr vars,
               char *buf, int bufsize,
               nwItemDescPtr item)
 {
@@ -338,7 +327,7 @@ printDataType(virNWFilterHashTablePtr va
 
 
 static int
-printDataTypeAsHex(virNWFilterHashTablePtr vars,
+printDataTypeAsHex(virNWFilterVarCombIterPtr vars,
                    char *buf, int bufsize,
                    nwItemDescPtr item)
 {
@@ -406,7 +395,7 @@ ebiptablesAddRuleInst(virNWFilterRuleIns
 
 static int
 ebtablesHandleEthHdr(virBufferPtr buf,
-                     virNWFilterHashTablePtr vars,
+                     virNWFilterVarCombIterPtr vars,
                      ethHdrDataDefPtr ethHdr,
                      bool reverse)
 {
@@ -884,7 +873,7 @@ iptablesInstCommand(virBufferPtr buf,
 
 static int
 iptablesHandleSrcMacAddr(virBufferPtr buf,
-                         virNWFilterHashTablePtr vars,
+                         virNWFilterVarCombIterPtr vars,
                          nwItemDescPtr srcMacAddr,
                          int directionIn,
                          bool *srcmacskipped)
@@ -921,7 +910,7 @@ err_exit:
 static int
 iptablesHandleIpHdr(virBufferPtr buf,
                     virBufferPtr afterStateMatch,
-                    virNWFilterHashTablePtr vars,
+                    virNWFilterVarCombIterPtr vars,
                     ipHdrDataDefPtr ipHdr,
                     int directionIn,
                     bool *skipRule, bool *skipMatch,
@@ -1095,7 +1084,7 @@ err_exit:
 
 static int
 iptablesHandlePortData(virBufferPtr buf,
-                       virNWFilterHashTablePtr vars,
+                       virNWFilterVarCombIterPtr vars,
                        portDataDefPtr portData,
                        int directionIn)
 {
@@ -1201,7 +1190,7 @@ _iptablesCreateRuleInstance(int directio
                             virNWFilterDefPtr nwfilter,
                             virNWFilterRuleDefPtr rule,
                             const char *ifname,
-                            virNWFilterHashTablePtr vars,
+                            virNWFilterVarCombIterPtr vars,
                             virNWFilterRuleInstPtr res,
                             const char *match, bool defMatch,
                             const char *accept_target,
@@ -1687,7 +1676,7 @@ static int
 iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
                                     virNWFilterRuleDefPtr rule,
                                     const char *ifname,
-                                    virNWFilterHashTablePtr vars,
+                                    virNWFilterVarCombIterPtr vars,
                                     virNWFilterRuleInstPtr res,
                                     bool isIPv6)
 {
@@ -1812,7 +1801,7 @@ static int
 iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                            virNWFilterRuleDefPtr rule,
                            const char *ifname,
-                           virNWFilterHashTablePtr vars,
+                           virNWFilterVarCombIterPtr vars,
                            virNWFilterRuleInstPtr res,
                            bool isIPv6)
 {
@@ -1937,7 +1926,7 @@ ebtablesCreateRuleInstance(char chainPre
                            virNWFilterDefPtr nwfilter,
                            virNWFilterRuleDefPtr rule,
                            const char *ifname,
-                           virNWFilterHashTablePtr vars,
+                           virNWFilterVarCombIterPtr vars,
                            virNWFilterRuleInstPtr res,
                            bool reverse)
 {
@@ -2429,7 +2418,7 @@ ebiptablesCreateRuleInstance(virConnectP
                              virNWFilterDefPtr nwfilter,
                              virNWFilterRuleDefPtr rule,
                              const char *ifname,
-                             virNWFilterHashTablePtr vars,
+                             virNWFilterVarCombIterPtr vars,
                              virNWFilterRuleInstPtr res)
 {
     int rc = 0;
@@ -2513,6 +2502,47 @@ 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 vciter;
+    unsigned int loop_limit = 10;
+
+    /* 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.
+     */
+    vciter = virNWFilterVarCombIterCreate(vars, rule->vars, rule->nvars,
+                                          loop_limit);
+    if (!vciter) {
+        return 1;
+    }
+
+    do {
+        rc = ebiptablesCreateRuleInstance(conn,
+                                          nettype,
+                                          nwfilter,
+                                          rule,
+                                          ifname,
+                                          vciter,
+                                          res);
+        if (rc)
+            break;
+        vciter = virNWFilterVarCombIterNext(vciter);
+    } while (vciter != NULL);
+
+    virNWFilterVarCombIterFree(vciter);
+
+    return rc;
+}
 
 static int
 ebiptablesFreeRuleInstance(void *_inst)
@@ -3896,7 +3926,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,135 @@ virNWFilterVarValueAddValue(virNWFilterV
     return rc;
 }
 
+void
+virNWFilterVarCombIterFree(virNWFilterVarCombIterPtr ci)
+{
+    if (!ci)
+        return;
+
+    VIR_FREE(ci);
+}
+
+virNWFilterVarCombIterPtr
+virNWFilterVarCombIterCreate(virNWFilterHashTablePtr hash,
+                             char * const *vars, unsigned int nVars,
+                             unsigned int loop_limit)
+{
+    virNWFilterVarCombIterPtr res;
+    virNWFilterVarValuePtr varVal;
+    unsigned int i;
+    unsigned int loops = 1;
+
+    if (VIR_ALLOC_VAR(res, virNWFilterVarCombEntry, nVars) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    res->nEntries = nVars;
+    res->hashTable = hash;
+
+    for (i = 0; i < nVars; i++) {
+        varVal = virHashLookup(hash->hashTable, vars[i]);
+        if (varVal == 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(varVal);
+
+        loops *= res->entry[i].cardinality;
+        if (loop_limit && loops > loop_limit) {
+            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("Lists sizes are too big and would cause "
+                                    "the iterator to exceep the maximum number"
+                                    "of loops (%u)"), loop_limit);
+            goto err_exit;
+        }
+    }
+
+    return res;
+
+err_exit:
+    virNWFilterVarCombIterFree(res);
+    return NULL;
+}
+
+virNWFilterVarCombIterPtr
+virNWFilterVarCombIterNext(virNWFilterVarCombIterPtr ci)
+{
+    unsigned int i;
+
+    if ((ci->nEntries == 0) ||
+        (ci->nEntries == 1 && ci->entry[0].cardinality == 1)) {
+        virNWFilterVarCombIterFree(ci);
+        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)
+            break;
+        else
+            ci->entry[i].idx = 0;
+    }
+
+    if (ci->nEntries == i) {
+        virNWFilterVarCombIterFree(ci);
+        return NULL;
+    }
+
+    return ci;
+}
+
+const char *
+virNWFilterVarCombIterGetVarValue(virNWFilterVarCombIterPtr ci,
+                                  const char *varname)
+{
+    unsigned int i;
+    bool found = false;
+    const char *res = NULL;
+    virNWFilterVarValuePtr value;
+
+    for (i = 0; i < ci->nEntries; i++) {
+        if (STREQ(ci->entry[i].key, varname)) {
+            found = true;
+            break;
+        }
+    }
+
+    if (!found) {
+        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Could not find variable '%s' in iterator"),
+                               varname);
+        return NULL;
+    }
+
+    value = virHashLookup(ci->hashTable->hashTable, varname);
+    if (!value) {
+        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Could not find value for variable '%s'"),
+                               varname);
+        return NULL;
+    }
+
+    res = virNWFilterVarValueGetNthValue(value, ci->entry[i].idx);
+    if (!res) {
+        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Could not get nth (%u) value of "
+                               "variable '%s'"),
+                               ci->entry[i].idx, varname);
+        return NULL;
+    }
+
+    return res;
+}
+
 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
@@ -91,4 +91,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;
+    unsigned int nEntries;
+    virNWFilterVarCombEntry entry[1];
+};
+virNWFilterVarCombIterPtr virNWFilterVarCombIterCreate(
+                             virNWFilterHashTablePtr hash,
+                             char * const *vars, unsigned int nVars,
+                             unsigned int loop_limit);
+
+void virNWFilterVarCombIterFree(virNWFilterVarCombIterPtr ci);
+virNWFilterVarCombIterPtr virNWFilterVarCombIterNext(
+                                virNWFilterVarCombIterPtr ci);
+const char *virNWFilterVarCombIterGetVarValue(virNWFilterVarCombIterPtr ci,
+                                              const char *varname);
+
 #endif /* NWFILTER_PARAMS_H */
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -881,6 +881,10 @@ virNWFilterHashTableFree;
 virNWFilterHashTablePut;
 virNWFilterHashTablePutAll;
 virNWFilterHashTableRemoveEntry;
+virNWFilterVarCombIterCreate;
+virNWFilterVarCombIterFree;
+virNWFilterVarCombIterGetVarValue;
+virNWFilterVarCombIterNext;
 virNWFilterVarValueCreateSimple;
 virNWFilterVarValueGetSimple;
 virNWFilterVarValuePrint;

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