[PATCH V1 3/6] Make filter creation in root table more flexible

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

 



Use the previously introduced chain priorities to sort the chains for access
from the 'root' table and have them created in the proper order. This gets
rid of a lot of code that was previously creating the chains in a  more
hardcoded way.

To detmerine what protocol a filter is used for evaluation do prefix-
matching, i.e., the filter 'arp' is used to filter for the 'arp' protocol,
'ipv4' for the 'ipv4' protocol and 'arp-xyz' will also be used to filter
for the 'arp' protocol.

---
 src/nwfilter/nwfilter_ebiptables_driver.c |  130 ++++++++++++++++++++++--------
 1 file changed, 98 insertions(+), 32 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
@@ -2774,6 +2774,7 @@ ebtablesCreateTmpSubChain(virBufferPtr b
                           int incoming,
                           const char *ifname,
                           enum l3_proto_idx protoidx,
+                          const char *filtername,
                           int stopOnError)
 {
     char rootchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH];
@@ -2781,7 +2782,8 @@ ebtablesCreateTmpSubChain(virBufferPtr b
                                   : CHAINPREFIX_HOST_OUT_TEMP;
 
     PRINT_ROOT_CHAIN(rootchain, chainPrefix, ifname);
-    PRINT_CHAIN(chain, chainPrefix, ifname, l3_protocols[protoidx].val);
+    PRINT_CHAIN(chain, chainPrefix, ifname,
+                (filtername) ? filtername : l3_protocols[protoidx].val);
 
     virBufferAsprintf(buf,
                       CMD_DEF("%s -t %s -N %s") CMD_SEPARATOR
@@ -3288,6 +3290,13 @@ ebiptablesRuleOrderSort(const void *a, c
     return ((*insta)->priority - (*instb)->priority);
 }
 
+static int
+ebiptablesFilterOrderSort(const virHashKeyValuePairPtr a,
+                          const virHashKeyValuePairPtr b)
+{
+    return *(virNWFilterChainPriority *)a->value -
+           *(virNWFilterChainPriority *)b->value;
+}
 
 static void
 iptablesCheckBridgeNFCallEnabled(bool isIPv6)
@@ -3327,6 +3336,56 @@ iptablesCheckBridgeNFCallEnabled(bool is
     }
 }
 
+/*
+ * Given a filtername determine the protocol it is used for evaluating
+ * We do prefix-matching to determine the protocol.
+ */
+static enum l3_proto_idx
+ebtablesGetProtoIdxByFiltername(const char *filtername)
+{
+    enum l3_proto_idx idx;
+
+    for (idx = 0; idx < L3_PROTO_LAST_IDX; idx++) {
+        if (STRPREFIX(filtername, l3_protocols[idx].val)) {
+            return idx;
+        }
+    }
+
+    return -1;
+}
+
+static int
+ebtablesCreateTmpRootAndSubChains(virBufferPtr buf,
+                                  const char *ifname,
+                                  virHashTablePtr chains, int direction)
+{
+    int rc = 0, i;
+
+    if (virHashSize(chains) != 0) {
+        char **filter_names;
+
+        ebtablesCreateTmpRootChain(buf, direction, ifname, 1);
+        filter_names = (char **)virHashGetKeys(chains,
+                                               ebiptablesFilterOrderSort);
+        if (filter_names == NULL) {
+            virReportOOMError();
+            rc = 1;
+            goto err_exit;
+        }
+        for (i = 0; filter_names[i]; i++) {
+            enum l3_proto_idx idx = ebtablesGetProtoIdxByFiltername(
+                                      filter_names[i]);
+            if ((int)idx < 0)
+                continue;
+            ebtablesCreateTmpSubChain(buf, direction, ifname, idx,
+                                      filter_names[i], 1);
+        }
+        virHashFreeKeys(chains, (void **)filter_names);
+    }
+
+ err_exit:
+    return rc;
+}
 
 static int
 ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
@@ -3337,24 +3396,43 @@ ebiptablesApplyNewRules(virConnectPtr co
     int i;
     int cli_status;
     ebiptablesRuleInstPtr *inst = (ebiptablesRuleInstPtr *)_inst;
-    int chains_in = 0, chains_out = 0;
     virBuffer buf = VIR_BUFFER_INITIALIZER;
+    virHashTablePtr chains_in_set  = virHashCreate(10, NULL),
+                    chains_out_set = virHashCreate(10, NULL);
     bool haveIptables = false;
     bool haveIp6tables = false;
 
+    if (!chains_in_set || !chains_out_set) {
+        virReportOOMError();
+        goto exit_free_sets;
+    }
+
     if (nruleInstances > 1 && inst)
         qsort(inst, nruleInstances, sizeof(inst[0]), ebiptablesRuleOrderSort);
 
+    /* scan the rules to see which chains need to be created */
     for (i = 0; i < nruleInstances; i++) {
         sa_assert (inst);
         if (inst[i]->ruleType == RT_EBTABLES) {
-            if (inst[i]->chainprefix == CHAINPREFIX_HOST_IN_TEMP)
-                chains_in  |= (1 << inst[i]->neededProtocolChain);
-            else
-                chains_out |= (1 << inst[i]->neededProtocolChain);
+            const char *name = virNWFilterChainSuffixTypeToString(
+                                      inst[i]->neededProtocolChain);
+            if (inst[i]->chainprefix == CHAINPREFIX_HOST_IN_TEMP) {
+                if (virHashUpdateEntry(chains_in_set, name,
+                                       &inst[i]->chainPriority)) {
+                    virReportOOMError();
+                    goto exit_free_sets;
+                }
+            } else {
+                if (virHashUpdateEntry(chains_out_set, name,
+                                       &inst[i]->chainPriority)) {
+                    virReportOOMError();
+                    goto exit_free_sets;
+                }
+            }
         }
     }
 
+    /* cleanup whatever may exist */
     if (ebtables_cmd_path) {
         ebtablesUnlinkTmpRootChain(&buf, 1, ifname);
         ebtablesUnlinkTmpRootChain(&buf, 0, ifname);
@@ -3364,30 +3442,11 @@ ebiptablesApplyNewRules(virConnectPtr co
         ebiptablesExecCLI(&buf, &cli_status);
     }
 
-    if (chains_in != 0)
-        ebtablesCreateTmpRootChain(&buf, 1, ifname, 1);
-    if (chains_out != 0)
-        ebtablesCreateTmpRootChain(&buf, 0, ifname, 1);
-
-    if (chains_in  & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv4))
-        ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_IPV4_IDX, 1);
-    if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv4))
-        ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_IPV4_IDX, 1);
-
-    if (chains_in  & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv6))
-        ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_IPV6_IDX, 1);
-    if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv6))
-        ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_IPV6_IDX, 1);
-
-    /* keep arp,rarp as last */
-    if (chains_in  & (1 << VIR_NWFILTER_CHAINSUFFIX_ARP))
-        ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_ARP_IDX, 1);
-    if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_ARP))
-        ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_ARP_IDX, 1);
-    if (chains_in  & (1 << VIR_NWFILTER_CHAINSUFFIX_RARP))
-        ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_RARP_IDX, 1);
-    if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_RARP))
-        ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_RARP_IDX, 1);
+    /* create needed chains */
+    if (ebtablesCreateTmpRootAndSubChains(&buf, ifname, chains_in_set , 1) ||
+        ebtablesCreateTmpRootAndSubChains(&buf, ifname, chains_out_set, 0)) {
+        goto tear_down_tmpebchains;
+    }
 
     if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0)
         goto tear_down_tmpebchains;
@@ -3477,14 +3536,17 @@ ebiptablesApplyNewRules(virConnectPtr co
         iptablesCheckBridgeNFCallEnabled(true);
     }
 
-    if (chains_in != 0)
+    if (virHashSize(chains_in_set) != 0)
         ebtablesLinkTmpRootChain(&buf, 1, ifname, 1);
-    if (chains_out != 0)
+    if (virHashSize(chains_out_set) != 0)
         ebtablesLinkTmpRootChain(&buf, 0, ifname, 1);
 
     if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0)
         goto tear_down_ebsubchains_and_unlink;
 
+    virHashFree(chains_in_set);
+    virHashFree(chains_out_set);
+
     return 0;
 
 tear_down_ebsubchains_and_unlink:
@@ -3519,6 +3581,10 @@ tear_down_tmpebchains:
                              "interface %s."),
                            ifname);
 
+exit_free_sets:
+    virHashFree(chains_in_set);
+    virHashFree(chains_out_set);
+
     return 1;
 }
 

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