[libvirt] [RFC PATCHv2 5/9] allow chain modification

David L Stevens dlstevens at us.ibm.com
Wed Oct 5 15:08:50 UTC 2011


	This patch adds the internal capability to add rules to existing
chains instead of using temporary chains and to generate placeholders for
chains that are referenced without generating a rule for them immediately.
Finally, it includes variable matching for filter instantiation
(i.e., instantiate only when a given variable is present in a filter, or
only when it is not).

Signed-off-by: David L Stevens <dlstevens at us.ibm.com>
---
 src/conf/nwfilter_conf.h                  |    4 +-
 src/nwfilter/nwfilter_ebiptables_driver.c |   93 +++++++++++++++++++++--------
 src/nwfilter/nwfilter_gentech_driver.c    |   32 +++++++++-
 3 files changed, 100 insertions(+), 29 deletions(-)

diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 17e954e..4348378 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -525,7 +525,9 @@ typedef int (*virNWFilterRuleCreateInstance)(virConnectPtr conn,
                                              virNWFilterRuleDefPtr rule,
                                              const char *ifname,
                                              virNWFilterHashTablePtr vars,
-                                             virNWFilterRuleInstPtr res);
+                                             virNWFilterRuleInstPtr res,
+                                             bool usetemp,
+                                             bool dummy);
 
 typedef int (*virNWFilterRuleApplyNewRules)(virConnectPtr conn,
                                             const char *ifname,
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index e6a4880..918625c 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -1136,6 +1136,7 @@ iptablesEnforceDirection(int directionIn,
  * @isIPv6 : Whether this is an IPv6 rule
  * @maySkipICMP : whether this rule may under certain circumstances skip
  *           the ICMP rule from being created
+ * @dummy : generate rule placeholder without installing
  *
  * Convert a single rule into its representation for later instantiation
  *
@@ -1154,7 +1155,8 @@ _iptablesCreateRuleInstance(int directionIn,
                             const char *match, bool defMatch,
                             const char *accept_target,
                             bool isIPv6,
-                            bool maySkipICMP)
+                            bool maySkipICMP,
+                            bool dummy)
 {
     char chain[MAX_CHAINNAME_LENGTH];
     char number[20];
@@ -1181,6 +1183,13 @@ _iptablesCreateRuleInstance(int directionIn,
 
     PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
 
+    if (dummy) {
+        virBufferAsprintf(&buf, CMD_DEF_PRE "%s -- %s -%%c %s %%s",
+                          "echo", iptables_cmd, chain);
+        bufUsed = virBufferUse(&buf);
+        goto prskip;
+    }
+
     switch (rule->prtclType) {
     case VIR_NWFILTER_RULE_PROTOCOL_TCP:
     case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -1521,6 +1530,8 @@ _iptablesCreateRuleInstance(int directionIn,
         return -1;
     }
 
+prskip:
+
     if ((srcMacSkipped && bufUsed == virBufferUse(&buf)) ||
          skipRule) {
         virBufferFreeAndReset(&buf);
@@ -1636,7 +1647,9 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
                                     const char *ifname,
                                     virNWFilterHashTablePtr vars,
                                     virNWFilterRuleInstPtr res,
-                                    bool isIPv6)
+                                    bool isIPv6,
+                                    bool usetemp,
+                                    bool dummy)
 {
     int rc;
     int directionIn = 0;
@@ -1668,7 +1681,7 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
             return 1;
     }
 
-    chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+    chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
     if (create) {
         rc = _iptablesCreateRuleInstance(directionIn,
                                          chainPrefix,
@@ -1680,7 +1693,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
                                          matchState, false,
                                          "RETURN",
                                          isIPv6,
-                                         maySkipICMP);
+                                         maySkipICMP,
+                                         dummy);
 
         VIR_FREE(matchState);
         if (rc)
@@ -1700,7 +1714,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
             return 1;
     }
 
-    chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+    chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_OUT_TEMP :
+                     CHAINPREFIX_HOST_OUT;
     if (create) {
         rc = _iptablesCreateRuleInstance(!directionIn,
                                          chainPrefix,
@@ -1712,7 +1727,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
                                          matchState, false,
                                          "ACCEPT",
                                          isIPv6,
-                                         maySkipICMP);
+                                         maySkipICMP,
+                                         dummy);
 
         VIR_FREE(matchState);
 
@@ -1736,7 +1752,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
 
     if (create) {
         chainPrefix[0] = 'H';
-        chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+        chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP :
+                         CHAINPREFIX_HOST_IN;
         rc = _iptablesCreateRuleInstance(directionIn,
                                          chainPrefix,
                                          nwfilter,
@@ -1747,7 +1764,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
                                          matchState, false,
                                          "RETURN",
                                          isIPv6,
-                                         maySkipICMP);
+                                         maySkipICMP,
+                                         dummy);
         VIR_FREE(matchState);
     }
 
@@ -1761,7 +1779,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                            const char *ifname,
                            virNWFilterHashTablePtr vars,
                            virNWFilterRuleInstPtr res,
-                           bool isIPv6)
+                           bool isIPv6,
+                           bool usetemp,
+                           bool dummy)
 {
     int rc;
     int directionIn = 0;
@@ -1777,7 +1797,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                                                    ifname,
                                                    vars,
                                                    res,
-                                                   isIPv6);
+                                                   isIPv6,
+                                                   usetemp,
+                                                   dummy);
     }
 
     if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) ||
@@ -1800,7 +1822,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
     else
         matchState = NULL;
 
-    chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+    chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
     rc = _iptablesCreateRuleInstance(directionIn,
                                      chainPrefix,
                                      nwfilter,
@@ -1811,7 +1833,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                                      matchState, true,
                                      "RETURN",
                                      isIPv6,
-                                     maySkipICMP);
+                                     maySkipICMP,
+                                     dummy);
     if (rc)
         return rc;
 
@@ -1822,7 +1845,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
     else
         matchState = NULL;
 
-    chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+    chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_OUT_TEMP : CHAINPREFIX_HOST_OUT;
     rc = _iptablesCreateRuleInstance(!directionIn,
                                      chainPrefix,
                                      nwfilter,
@@ -1833,7 +1856,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                                      matchState, true,
                                      "ACCEPT",
                                      isIPv6,
-                                     maySkipICMP);
+                                     maySkipICMP,
+                                     dummy);
     if (rc)
         return rc;
 
@@ -1844,7 +1868,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
         matchState = NULL;
 
     chainPrefix[0] = 'H';
-    chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+    chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
     rc = _iptablesCreateRuleInstance(directionIn,
                                      chainPrefix,
                                      nwfilter,
@@ -1855,7 +1879,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                                      matchState, true,
                                      "RETURN",
                                      isIPv6,
-                                     maySkipICMP);
+                                     maySkipICMP,
+                                     dummy);
 
     return rc;
 }
@@ -1886,7 +1911,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
                            const char *ifname,
                            virNWFilterHashTablePtr vars,
                            virNWFilterRuleInstPtr res,
-                           bool reverse)
+                           bool reverse,
+                           bool dummy)
 {
     char macaddr[VIR_MAC_STRING_BUFLEN],
          ipaddr[INET_ADDRSTRLEN],
@@ -1909,6 +1935,11 @@ ebtablesCreateRuleInstance(char chainPrefix,
         PRINT_CHAIN(chain, chainPrefix, ifname,
                     virNWFilterChainSuffixTypeToString(nwfilter->chainsuffix));
 
+    if (dummy) {
+        virBufferAsprintf(&buf, CMD_DEF_PRE "%s -- -t %s -%%c %s %%s",
+                          "echo", EBTABLES_DEFAULT_TABLE, chain);
+        goto prskip;
+    }
 
     switch (rule->prtclType) {
     case VIR_NWFILTER_RULE_PROTOCOL_MAC:
@@ -2317,6 +2348,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
         return -1;
     }
 
+prskip:
+
     switch (rule->action) {
     case VIR_NWFILTER_RULE_ACTION_REJECT:
         /* REJECT not supported */
@@ -2374,11 +2407,15 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
                              virNWFilterRuleDefPtr rule,
                              const char *ifname,
                              virNWFilterHashTablePtr vars,
-                             virNWFilterRuleInstPtr res)
+                             virNWFilterRuleInstPtr res,
+                             bool usetemp,
+                             bool dummy)
 {
     int rc = 0;
     bool isIPv6;
+    char chainPrefix;
 
+    chainPrefix = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
     switch (rule->prtclType) {
     case VIR_NWFILTER_RULE_PROTOCOL_IP:
     case VIR_NWFILTER_RULE_PROTOCOL_MAC:
@@ -2389,26 +2426,30 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
 
         if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_OUT ||
             rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) {
-            rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_IN_TEMP,
+            rc = ebtablesCreateRuleInstance(chainPrefix,
                                             nwfilter,
                                             rule,
                                             ifname,
                                             vars,
                                             res,
-                                            rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT);
+                                            rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT,
+                                            dummy);
             if (rc)
                 return rc;
         }
 
+        chainPrefix = usetemp ? CHAINPREFIX_HOST_OUT_TEMP :
+                      CHAINPREFIX_HOST_OUT;
         if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN ||
             rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) {
-            rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_OUT_TEMP,
+            rc = ebtablesCreateRuleInstance(chainPrefix,
                                             nwfilter,
                                             rule,
                                             ifname,
                                             vars,
                                             res,
-                                            false);
+                                            false,
+                                            dummy);
         }
     break;
 
@@ -2427,7 +2468,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         ifname,
                                         vars,
                                         res,
-                                        isIPv6);
+                                        isIPv6,
+                                        usetemp,
+                                        dummy);
     break;
 
     case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -2444,7 +2487,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         ifname,
                                         vars,
                                         res,
-                                        isIPv6);
+                                        isIPv6,
+                                        usetemp,
+                                        dummy);
     break;
 
     case VIR_NWFILTER_RULE_PROTOCOL_LAST:
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index 7891983..79350ac 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -284,7 +284,9 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
                            virNWFilterDefPtr filter,
                            virNWFilterRuleDefPtr rule,
                            const char *ifname,
-                           virNWFilterHashTablePtr vars)
+                           virNWFilterHashTablePtr vars,
+                           bool usetemp,
+                           bool dummy)
 {
     int rc;
     int i;
@@ -297,8 +299,8 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
 
     ret->techdriver = techdriver;
 
-    rc = techdriver->createRuleInstance(conn, nettype, filter,
-                                        rule, ifname, vars, ret);
+    rc = techdriver->createRuleInstance(conn, nettype, filter, rule, ifname,
+                                        vars, ret, usetemp, dummy);
 
     if (rc) {
         for (i = 0; i < ret->ndata; i++)
@@ -354,6 +356,8 @@ err_exit:
  * @ifname: The name of the interface to apply the rules to
  * @vars: A map holding variable names and values used for instantiating
  *  the filter and its subfilters.
+ * @matchvar: if non-null, variable name to match
+ * @notmatch: if matchvar set, match filters that do not reference matchvar
  * @nEntries: number of virNWFilterInst objects collected
  * @insts: pointer to array for virNWFilterIns object pointers
  * @useNewFilter: instruct whether to use a newDef pointer rather than a
@@ -377,6 +381,8 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
                            virNWFilterDefPtr filter,
                            const char *ifname,
                            virNWFilterHashTablePtr vars,
+                           const char *matchvar,
+                           bool notmatch,
                            int *nEntries,
                            virNWFilterRuleInstPtr **insts,
                            enum instCase useNewFilter, bool *foundNewFilter,
@@ -387,18 +393,34 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
     int i;
     virNWFilterRuleInstPtr inst;
     virNWFilterDefPtr next_filter;
+    bool usetemp, dummy;
 
     for (i = 0; i < filter->nentries; i++) {
         virNWFilterRuleDefPtr    rule = filter->filterEntries[i]->rule;
         virNWFilterIncludeDefPtr inc  = filter->filterEntries[i]->include;
         if (rule) {
+            usetemp = 1;
+            dummy = 0;
+            if (matchvar) {
+                int j;
+
+                for (j = 0; j < rule->nvars; ++j)
+                     if (strcmp(rule->vars[j], matchvar) == 0)
+                         break;
+                /* use temp chains only on base rule install */
+                usetemp = notmatch;
+                /* skip if not found; notmatch reverses the sense */
+                dummy = (j == rule->nvars) ^ notmatch;
+            }
             inst = virNWFilterRuleInstantiate(conn,
                                               techdriver,
                                               nettype,
                                               filter,
                                               rule,
                                               ifname,
-                                              vars);
+                                              vars,
+                                              usetemp,
+                                              dummy);
             if (!inst) {
                 rc = 1;
                 break;
@@ -456,6 +478,7 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
                                                 next_filter,
                                                 ifname,
                                                 tmpvars,
+                                                matchvar, notmatch,
                                                 nEntries, insts,
                                                 useNewFilter,
                                                 foundNewFilter,
@@ -684,6 +707,7 @@ virNWFilterInstantiate(virConnectPtr conn,
                                     filter,
                                     ifname,
                                     vars,
+                                    0, 0,
                                     &nEntries, &insts,
                                     useNewFilter, foundNewFilter,
                                     driver);
-- 
1.7.6.4




More information about the libvir-list mailing list