From: Michal Privoznik <[email protected]>

When the network driver starts up it may inject some firewall
rules (e.g. for a network with NAT). So far, this scenario wasn't
covered in our test suite. The reason for adding this test is
twofold: the fist, check we add correct rules, the second is to
cover iptablesPrivateChainCreate() as its implementation is soon
to be changed.

Signed-off-by: Michal Privoznik <[email protected]>
---
 src/network/meson.build |   1 +
 tests/meson.build       |   9 +++-
 tests/virfirewalltest.c | 111 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 120 insertions(+), 1 deletion(-)

diff --git a/src/network/meson.build b/src/network/meson.build
index 51bbf7063d..7a98974852 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -10,6 +10,7 @@ if host_machine.system() == 'freebsd'
   network_driver_sources += 'network_pf.c'
 endif
 
+network_inc_dir = include_directories('.')
 driver_source_files += files(network_driver_sources)
 stateful_driver_source_files += files(network_driver_sources)
 
diff --git a/tests/meson.build b/tests/meson.build
index bb6ee6b4ee..1f73d6c029 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -259,6 +259,13 @@ if conf.has('WITH_QEMU')
   domaincapstest_link_whole += [ test_utils_qemu_lib ]
 endif
 
+virfirewalltest_include = []
+virfirewalltest_link_with = []
+if conf.has('WITH_NETWORK')
+  virfirewalltest_include += [ network_inc_dir ]
+  virfirewalltest_link_with += [ network_driver_impl ]
+endif
+
 tests += [
   { 'name': 'commandtest' },
   { 'name': 'cputest', 'link_with': cputest_link_with, 'link_whole': 
cputest_link_whole },
@@ -286,7 +293,7 @@ tests += [
   { 'name': 'virerrortest' },
   { 'name': 'virfilecachetest' },
   { 'name': 'virfiletest' },
-  { 'name': 'virfirewalltest' },
+  { 'name': 'virfirewalltest', 'include': virfirewalltest_include, 
'link_with': virfirewalltest_link_with },
   { 'name': 'virhostcputest', 'link_whole': [ test_file_wrapper_lib ] },
   { 'name': 'virhostdevtest' },
   { 'name': 'viridentitytest' },
diff --git a/tests/virfirewalltest.c b/tests/virfirewalltest.c
index 38726dcc7a..942eba90d7 100644
--- a/tests/virfirewalltest.c
+++ b/tests/virfirewalltest.c
@@ -26,6 +26,9 @@
 
 # include "virbuffer.h"
 # include "virfirewall.h"
+# if WITH_NETWORK
+#  include "network_iptables.h"
+# endif
 
 # define LIBVIRT_VIRCOMMANDPRIV_H_ALLOW
 # include "vircommandpriv.h"
@@ -763,6 +766,113 @@ testFirewallQuery(const void *opaque G_GNUC_UNUSED)
 }
 
 
+static void G_GNUC_UNUSED
+testIPtablesSetupPrivateChainsHook(const char *const *args,
+                                   const char *const *env G_GNUC_UNUSED,
+                                   const char *input G_GNUC_UNUSED,
+                                   char **output,
+                                   char **error,
+                                   int *status,
+                                   void *opaque G_GNUC_UNUSED)
+{
+    if (STREQ_NULLABLE(*args, "iptables") &&
+        STREQ_NULLABLE(*(args + 1), "-w") &&
+        STREQ_NULLABLE(*(args + 2), "--table") &&
+        STREQ_NULLABLE(*(args + 3), "filter") &&
+        STREQ_NULLABLE(*(args + 4), "--list-rules")) {
+        *output = g_strdup("-P INPUT ACCEPT\n"
+                           "-P FORWARD ACCEPT\n"
+                           "-P OUTPUT ACCEPT\n"
+                          );
+        *error = NULL;
+        *status = EXIT_SUCCESS;
+        return;
+    }
+
+    if (STREQ_NULLABLE(*args, "iptables") &&
+        STREQ_NULLABLE(*(args + 1), "-w") &&
+        STREQ_NULLABLE(*(args + 2), "--table") &&
+        STREQ_NULLABLE(*(args + 3), "nat") &&
+        STREQ_NULLABLE(*(args + 4), "--list-rules")) {
+        *output = g_strdup("-P PREROUTING ACCEPT\n"
+                           "-P INPUT ACCEPT\n"
+                           "-P OUTPUT ACCEPT\n"
+                           "-P POSTROUTING ACCEPT\n");
+        *error = NULL;
+        *status = EXIT_SUCCESS;
+        return;
+    }
+
+    /* Intentionally steering away from empty rules above. This is how the
+     * table looks AFTER we've injected our rules. The idea is to cover more
+     * lines, esp. in iptablesPrivateChainCreate(). */
+    if (STREQ_NULLABLE(*args, "iptables") &&
+        STREQ_NULLABLE(*(args + 1), "-w") &&
+        STREQ_NULLABLE(*(args + 2), "--table") &&
+        STREQ_NULLABLE(*(args + 3), "mangle") &&
+        STREQ_NULLABLE(*(args + 4), "--list-rules")) {
+        *output = g_strdup("-P PREROUTING ACCEPT\n"
+                           "-P INPUT ACCEPT\n"
+                           "-P FORWARD ACCEPT\n"
+                           "-P OUTPUT ACCEPT\n"
+                           "-P POSTROUTING ACCEPT\n"
+                           "-N LIBVIRT_PRT\n"
+                           "-A POSTROUTING -j LIBVIRT_PRT\n"
+                           "-A LIBVIRT_PRT -o virbr0 -p udp -m udp --dport 68 
-j CHECKSUM --checksum-fill\n");
+        *error = NULL;
+        *status = EXIT_SUCCESS;
+        return;
+    }
+
+    *output = NULL;
+    *error = NULL;
+    *status = EXIT_SUCCESS;
+}
+
+
+static int
+testIPtablesSetupPrivateChains(const void *opaque G_GNUC_UNUSED)
+{
+# if WITH_NETWORK
+    g_auto(virBuffer) cmdbuf = VIR_BUFFER_INITIALIZER;
+    g_autoptr(virCommandDryRunToken) dryRunToken = virCommandDryRunTokenNew();
+    const char *actual;
+    const char *expected =
+        IPTABLES " -w --table filter --list-rules\n"
+        IPTABLES " -w --table nat --list-rules\n"
+        IPTABLES " -w --table mangle --list-rules\n"
+        IPTABLES " -w --table filter --new-chain LIBVIRT_INP\n"
+        IPTABLES " -w --table filter --insert INPUT --jump LIBVIRT_INP\n"
+        IPTABLES " -w --table filter --new-chain LIBVIRT_OUT\n"
+        IPTABLES " -w --table filter --insert OUTPUT --jump LIBVIRT_OUT\n"
+        IPTABLES " -w --table filter --new-chain LIBVIRT_FWO\n"
+        IPTABLES " -w --table filter --insert FORWARD --jump LIBVIRT_FWO\n"
+        IPTABLES " -w --table filter --new-chain LIBVIRT_FWI\n"
+        IPTABLES " -w --table filter --insert FORWARD --jump LIBVIRT_FWI\n"
+        IPTABLES " -w --table filter --new-chain LIBVIRT_FWX\n"
+        IPTABLES " -w --table filter --insert FORWARD --jump LIBVIRT_FWX\n"
+        IPTABLES " -w --table nat --new-chain LIBVIRT_PRT\n"
+        IPTABLES " -w --table nat --insert POSTROUTING --jump LIBVIRT_PRT\n";
+
+    virCommandSetDryRun(dryRunToken, &cmdbuf, false, false, 
testIPtablesSetupPrivateChainsHook, NULL);
+
+    if (iptablesSetupPrivateChains(VIR_FIREWALL_LAYER_IPV4) < 0)
+        return -1;
+
+    actual = virBufferCurrentContent(&cmdbuf);
+
+    if (virTestCompareToString(expected, actual) < 0) {
+        fprintf(stderr, "Unexpected command execution\n");
+        return -1;
+    }
+
+    return 0;
+# else
+    return EXIT_AM_SKIP;
+# endif
+}
+
+
 static int
 mymain(void)
 {
@@ -784,6 +894,7 @@ mymain(void)
     RUN_TEST("many rollback", testFirewallManyRollback);
     RUN_TEST("chained rollback", testFirewallChainedRollback);
     RUN_TEST("query transaction", testFirewallQuery);
+    RUN_TEST("setup private chains", testIPtablesSetupPrivateChains);
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-- 
2.51.2

Reply via email to