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

David L Stevens dlstevens at us.ibm.com
Mon May 9 20:07:58 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>

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);






More information about the libvir-list mailing list