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

[libvirt] [PATCH 5/9] add DHCP snooping support to nwfilter



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 us ibm com>

diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 72bdade..25f7b60 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -517,7 +517,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 f16a143..f74f63b 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -1134,6 +1134,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
  *
@@ -1152,7 +1153,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];
@@ -1179,6 +1181,13 @@ _iptablesCreateRuleInstance(int directionIn,
 
     PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
 
+    if (dummy) {
+        virBufferVSprintf(&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:
@@ -1510,6 +1519,8 @@ _iptablesCreateRuleInstance(int directionIn,
         return -1;
     }
 
+prskip:
+
     if ((srcMacSkipped && bufUsed == virBufferUse(&buf)) ||
          skipRule) {
         virBufferFreeAndReset(&buf);
@@ -1625,7 +1636,9 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
                                     const char *ifname,
                                     virNWFilterHashTablePtr vars,
                                     virNWFilterRuleInstPtr res,
-                                    bool isIPv6)
+                                    bool isIPv6,
+                                    bool usetemp,
+                                    bool dummy)
 {
     int rc;
     int directionIn = 0, directionOut = 0;
@@ -1658,7 +1671,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,
@@ -1670,7 +1683,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
                                          matchState, false,
                                          "RETURN",
                                          isIPv6,
-                                         maySkipICMP);
+                                         maySkipICMP,
+                                         dummy);
 
         VIR_FREE(matchState);
         if (rc)
@@ -1690,7 +1704,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,
@@ -1702,7 +1717,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
                                          matchState, false,
                                          "ACCEPT",
                                          isIPv6,
-                                         maySkipICMP);
+                                         maySkipICMP,
+                                         dummy);
 
         VIR_FREE(matchState);
 
@@ -1726,7 +1742,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,
@@ -1737,7 +1754,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
                                          matchState, false,
                                          "RETURN",
                                          isIPv6,
-                                         maySkipICMP);
+                                         maySkipICMP,
+                                         dummy);
         VIR_FREE(matchState);
     }
 
@@ -1751,7 +1769,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                            const char *ifname,
                            virNWFilterHashTablePtr vars,
                            virNWFilterRuleInstPtr res,
-                           bool isIPv6)
+                           bool isIPv6,
+                           bool usetemp,
+                           bool dummy)
 {
     int rc;
     int directionIn = 0;
@@ -1767,7 +1787,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                                                    ifname,
                                                    vars,
                                                    res,
-                                                   isIPv6);
+                                                   isIPv6,
+                                                   usetemp,
+                                                   dummy);
     }
 
     if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) ||
@@ -1790,7 +1812,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,
@@ -1801,7 +1823,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                                      matchState, true,
                                      "RETURN",
                                      isIPv6,
-                                     maySkipICMP);
+                                     maySkipICMP,
+                                     dummy);
     if (rc)
         return rc;
 
@@ -1812,7 +1835,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,
@@ -1823,7 +1846,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                                      matchState, true,
                                      "ACCEPT",
                                      isIPv6,
-                                     maySkipICMP);
+                                     maySkipICMP,
+                                     dummy);
     if (rc)
         return rc;
 
@@ -1834,7 +1858,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,
@@ -1845,7 +1869,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                                      matchState, true,
                                      "RETURN",
                                      isIPv6,
-                                     maySkipICMP);
+                                     maySkipICMP,
+                                     dummy);
 
     return rc;
 }
@@ -1876,7 +1901,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],
@@ -1899,6 +1925,11 @@ ebtablesCreateRuleInstance(char chainPrefix,
         PRINT_CHAIN(chain, chainPrefix, ifname,
                     virNWFilterChainSuffixTypeToString(nwfilter->chainsuffix));
 
+    if (dummy) {
+        virBufferVSprintf(&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:
@@ -2300,6 +2331,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
         return -1;
     }
 
+prskip:
+
     switch (rule->action) {
     case VIR_NWFILTER_RULE_ACTION_REJECT:
         /* REJECT not supported */
@@ -2357,11 +2390,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:
@@ -2372,26 +2409,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;
 
@@ -2417,7 +2458,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         ifname,
                                         vars,
                                         res,
-                                        isIPv6);
+                                        isIPv6,
+                                        usetemp,
+                                        dummy);
     break;
 
     case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -2441,7 +2484,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 f89fb79..0bc3537 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -222,7 +222,9 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
                            virNWFilterDefPtr filter,
                            virNWFilterRuleDefPtr rule,
                            const char *ifname,
-                           virNWFilterHashTablePtr vars)
+                           virNWFilterHashTablePtr vars,
+                           bool usetemp,
+                           bool dummy)
 {
     int rc;
     int i;
@@ -235,8 +237,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++)
@@ -292,6 +294,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
@@ -315,6 +319,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,
@@ -325,18 +331,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;
@@ -394,6 +416,7 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
                                                 next_filter,
                                                 ifname,
                                                 tmpvars,
+                                                matchvar, notmatch,
                                                 nEntries, insts,
                                                 useNewFilter,
                                                 foundNewFilter,
@@ -623,6 +646,7 @@ virNWFilterInstantiate(virConnectPtr conn,
                                     filter,
                                     ifname,
                                     vars,
+                                    0, 0,
                                     &nEntries, &insts,
                                     useNewFilter, foundNewFilter,
                                     driver);



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