[patch 2/5] nwfilter: Instantiate state match in ip(6)tables rules

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

 



In this patch I am extending the rule instantiator to create the state
match according to the state attribute in the XML. Only one iptables 
rule in the incoming or outgoing direction will be created for a rule
in direction 'in' or 'out' respectively. A rule in direction 'inout' does
get iptables rules in both directions.

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

---
 src/nwfilter/nwfilter_ebiptables_driver.c |  163 +++++++++++++++++++++++++++++-
 1 file changed, 158 insertions(+), 5 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
@@ -1129,7 +1129,7 @@ _iptablesCreateRuleInstance(int directio
                             const char *ifname,
                             virNWFilterHashTablePtr vars,
                             virNWFilterRuleInstPtr res,
-                            const char *match,
+                            const char *match, bool defMatch,
                             const char *accept_target,
                             bool isIPv6,
                             bool maySkipICMP)
@@ -1488,7 +1488,7 @@ _iptablesCreateRuleInstance(int directio
         target = accept_target;
     else {
         target = "DROP";
-        skipMatch = true;
+        skipMatch = defMatch;
     }
 
     if (match && !skipMatch)
@@ -1548,6 +1548,149 @@ exit_no_error:
 
 
 static int
+printStateMatchFlags(int32_t flags, char **bufptr)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virNWFilterPrintStateMatchFlags(&buf,
+                                    "-m state --state ",
+                                    flags,
+                                    false);
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        return 1;
+    }
+    *bufptr = virBufferContentAndReset(&buf);
+    return 0;
+}
+
+static int
+iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
+                                    virNWFilterRuleDefPtr rule,
+                                    const char *ifname,
+                                    virNWFilterHashTablePtr vars,
+                                    virNWFilterRuleInstPtr res,
+                                    bool isIPv6)
+{
+    int rc;
+    int directionIn = 0, directionOut = 0;
+    char chainPrefix[2];
+    bool maySkipICMP, inout = false;
+    char *matchState = NULL;
+    bool create;
+
+    if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) ||
+        (rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT)) {
+        directionIn = 1;
+        directionOut = inout = (rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT);
+    } else
+        directionOut = 1;
+
+    chainPrefix[0] = 'F';
+
+    maySkipICMP = directionIn || inout;
+
+    create = true;
+    matchState = NULL;
+
+    if (directionIn && !inout) {
+        if ((rule->flags & IPTABLES_STATE_FLAGS))
+            create = false;
+    }
+
+    if (create && (rule->flags & IPTABLES_STATE_FLAGS)) {
+        if (printStateMatchFlags(rule->flags, &matchState))
+            return 1;
+    }
+
+    chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+    if (create) {
+        rc = _iptablesCreateRuleInstance(directionIn,
+                                         chainPrefix,
+                                         nwfilter,
+                                         rule,
+                                         ifname,
+                                         vars,
+                                         res,
+                                         matchState, false,
+                                         "RETURN",
+                                         isIPv6,
+                                         maySkipICMP);
+
+        VIR_FREE(matchState);
+        if (rc)
+            return rc;
+    }
+
+    maySkipICMP = !directionIn || inout;
+    create = true;
+
+    if (!directionIn) {
+        if ((rule->flags & IPTABLES_STATE_FLAGS))
+            create = false;
+    }
+
+    if (create && (rule->flags & IPTABLES_STATE_FLAGS)) {
+        if (printStateMatchFlags(rule->flags, &matchState))
+            return 1;
+    }
+
+    chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+    if (create) {
+        rc = _iptablesCreateRuleInstance(!directionIn,
+                                         chainPrefix,
+                                         nwfilter,
+                                         rule,
+                                         ifname,
+                                         vars,
+                                         res,
+                                         matchState, false,
+                                         "ACCEPT",
+                                         isIPv6,
+                                         maySkipICMP);
+
+        VIR_FREE(matchState);
+
+        if (rc)
+            return rc;
+    }
+
+    maySkipICMP = directionIn;
+
+    create = true;
+
+    if (directionIn && !inout) {
+        if ((rule->flags & IPTABLES_STATE_FLAGS))
+            create = false;
+    } else {
+        if ((rule->flags & IPTABLES_STATE_FLAGS)) {
+            if (printStateMatchFlags(rule->flags, &matchState))
+                return 1;
+        }
+    }
+
+    if (create) {
+        chainPrefix[0] = 'H';
+        chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+        rc = _iptablesCreateRuleInstance(directionIn,
+                                         chainPrefix,
+                                         nwfilter,
+                                         rule,
+                                         ifname,
+                                         vars,
+                                         res,
+                                         matchState, false,
+                                         "RETURN",
+                                         isIPv6,
+                                         maySkipICMP);
+        VIR_FREE(matchState);
+    }
+
+    return rc;
+}
+
+
+static int
 iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
                            virNWFilterRuleDefPtr rule,
                            const char *ifname,
@@ -1562,6 +1705,16 @@ iptablesCreateRuleInstance(virNWFilterDe
     bool maySkipICMP, inout = false;
     const char *matchState;
 
+    if (!(rule->flags & RULE_FLAG_NO_STATEMATCH) &&
+         (rule->flags & IPTABLES_STATE_FLAGS)) {
+        return iptablesCreateRuleInstanceStateCtrl(nwfilter,
+                                                   rule,
+                                                   ifname,
+                                                   vars,
+                                                   res,
+                                                   isIPv6);
+    }
+
     if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) ||
         (rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT)) {
         directionIn = 1;
@@ -1590,7 +1743,7 @@ iptablesCreateRuleInstance(virNWFilterDe
                                      ifname,
                                      vars,
                                      res,
-                                     matchState,
+                                     matchState, true,
                                      "RETURN",
                                      isIPv6,
                                      maySkipICMP);
@@ -1612,7 +1765,7 @@ iptablesCreateRuleInstance(virNWFilterDe
                                      ifname,
                                      vars,
                                      res,
-                                     matchState,
+                                     matchState, true,
                                      "ACCEPT",
                                      isIPv6,
                                      maySkipICMP);
@@ -1630,7 +1783,7 @@ iptablesCreateRuleInstance(virNWFilterDe
                                      ifname,
                                      vars,
                                      res,
-                                     NULL,
+                                     NULL, true,
                                      "ACCEPT",
                                      isIPv6,
                                      maySkipICMP);

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