diff --git a/src/Makefile.am b/src/Makefile.am index 0f295ed36e..dd0abe74ce 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1538,6 +1538,9 @@ endif WITH_NODE_DEVICES if WITH_NWFILTER +noinst_LTLIBRARIES += libvirt_driver_nwfilter_impl.la +libvirt_driver_nwfilter_la_SOURCES = +libvirt_driver_nwfilter_la_LIBADD = libvirt_driver_nwfilter_impl.la if WITH_DRIVER_MODULES mod_LTLIBRARIES += libvirt_driver_nwfilter.la else ! WITH_DRIVER_MODULES @@ -1545,20 +1548,23 @@ noinst_LTLIBRARIES += libvirt_driver_nwfilter.la # Stateful, so linked to daemon instead #libvirt_la_BUILT_LIBADD += libvirt_driver_nwfilter.la endif ! WITH_DRIVER_MODULES -libvirt_driver_nwfilter_la_CFLAGS = \ +libvirt_driver_nwfilter_impl_la_CFLAGS = \ $(LIBPCAP_CFLAGS) \ $(LIBNL_CFLAGS) \ $(DBUS_CFLAGS) \ -I$(top_srcdir)/src/access \ -I$(top_srcdir)/src/conf \ $(AM_CFLAGS) -libvirt_driver_nwfilter_la_LDFLAGS = $(AM_LDFLAGS) -libvirt_driver_nwfilter_la_LIBADD = $(LIBPCAP_LIBS) $(LIBNL_LIBS) $(DBUS_LIBS) +libvirt_driver_nwfilter_impl_la_LDFLAGS = $(AM_LDFLAGS) +libvirt_driver_nwfilter_impl_la_LIBADD = \ + $(LIBPCAP_LIBS) \ + $(LIBNL_LIBS) \ + $(DBUS_LIBS) if WITH_DRIVER_MODULES -libvirt_driver_nwfilter_la_LIBADD += ../gnulib/lib/libgnu.la -libvirt_driver_nwfilter_la_LDFLAGS += -module -avoid-version +libvirt_driver_nwfilter_impl_la_LIBADD += ../gnulib/lib/libgnu.la +libvirt_driver_nwfilter_impl_la_LDFLAGS += -module -avoid-version endif WITH_DRIVER_MODULES -libvirt_driver_nwfilter_la_SOURCES = $(NWFILTER_DRIVER_SOURCES) +libvirt_driver_nwfilter_impl_la_SOURCES = $(NWFILTER_DRIVER_SOURCES) endif WITH_NWFILTER diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 07589be4c1..7b944dfd50 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -45,6 +45,7 @@ #include "configmake.h" #include "intprops.h" #include "virstring.h" +#include "virfirewall.h" #define VIR_FROM_THIS VIR_FROM_NWFILTER @@ -180,22 +181,15 @@ static const char ebiptables_script_set_ifs[] = snprintf(buf, sizeof(buf), "%c%c-%s", prefix[0], prefix[1], ifname) #define PHYSDEV_IN "--physdev-in" -#define PHYSDEV_OUT "--physdev-is-bridged --physdev-out" -/* - * Previous versions of libvirt only used --physdev-out. - * To be able to upgrade with running VMs we need to be able to - * remove rules generated by those older versions of libvirt. - */ -#define PHYSDEV_OUT_OLD "--physdev-out" static const char *m_state_out_str = "-m state --state NEW,ESTABLISHED"; static const char *m_state_in_str = "-m state --state ESTABLISHED"; static const char *m_state_out_str_new = "-m conntrack --ctstate NEW,ESTABLISHED"; static const char *m_state_in_str_new = "-m conntrack --ctstate ESTABLISHED"; -static const char *m_physdev_in_str = "-m physdev " PHYSDEV_IN; -static const char *m_physdev_out_str = "-m physdev " PHYSDEV_OUT; -static const char *m_physdev_out_old_str = "-m physdev " PHYSDEV_OUT_OLD; +static const char *m_physdev_in_str = "-m physdev --physdev-in"; +static const char *m_physdev_out_str = "-m physdev --physdev-is-bridged --physdev-out"; +static const char *m_physdev_out_old_str = "-m physdev --physdev-out"; #define MATCH_STATE_OUT m_state_out_str #define MATCH_STATE_IN m_state_in_str @@ -203,6 +197,10 @@ static const char *m_physdev_out_old_str = "-m physdev " PHYSDEV_OUT_OLD; #define MATCH_PHYSDEV_OUT m_physdev_out_str #define MATCH_PHYSDEV_OUT_OLD m_physdev_out_old_str +#define MATCH_PHYSDEV_IN_FW "-m", "physdev", "--physdev-in" +#define MATCH_PHYSDEV_OUT_FW "-m", "physdev", "--physdev-is-bridged", "--physdev-out" +#define MATCH_PHYSDEV_OUT_OLD_FW "-m", "physdev", "--physdev-out" + #define COMMENT_VARNAME "comment" static int ebtablesRemoveBasicRules(const char *ifname); @@ -249,6 +247,12 @@ static const struct ushort_map l3_protocols[] = { }; +static char chainprefixes_host[3] = { + CHAINPREFIX_HOST_IN, + CHAINPREFIX_HOST_OUT, + 0 +}; + static int printVar(virNWFilterVarCombIterPtr vars, char *buf, int bufsize, @@ -660,6 +664,36 @@ _iptablesRemoveRootChain(virBufferPtr buf, } +static void +_iptablesRemoveRootChainFW(virFirewallPtr fw, + virFirewallLayer layer, + char prefix, + bool incoming, const char *ifname, + int isTempChain) +{ + char chain[MAX_CHAINNAME_LENGTH]; + char chainPrefix[2] = { + prefix, + }; + + if (isTempChain) + chainPrefix[1] = incoming ? CHAINPREFIX_HOST_IN_TEMP + : CHAINPREFIX_HOST_OUT_TEMP; + else + chainPrefix[1] = incoming ? CHAINPREFIX_HOST_IN + : CHAINPREFIX_HOST_OUT; + + PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname); + + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-F", chain, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-X", chain, NULL); +} + + static void iptablesRemoveRootChain(virBufferPtr buf, char prefix, @@ -670,6 +704,17 @@ iptablesRemoveRootChain(virBufferPtr buf, } +static void +iptablesRemoveRootChainFW(virFirewallPtr fw, + virFirewallLayer layer, + char prefix, + bool incoming, + const char *ifname) +{ + _iptablesRemoveRootChainFW(fw, layer, prefix, incoming, ifname, false); +} + + static void iptablesRemoveTmpRootChain(virBufferPtr buf, char prefix, @@ -701,6 +746,17 @@ iptablesRemoveRootChains(virBufferPtr buf, } +static void +iptablesRemoveRootChainsFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *ifname) +{ + iptablesRemoveRootChainFW(fw, layer, 'F', false, ifname); + iptablesRemoveRootChainFW(fw, layer, 'F', true, ifname); + iptablesRemoveRootChainFW(fw, layer, 'H', true, ifname); +} + + static void iptablesLinkTmpRootChain(virBufferPtr buf, const char *basechain, @@ -762,14 +818,15 @@ iptablesSetupVirtInPost(virBufferPtr buf, static void -iptablesClearVirtInPost(virBufferPtr buf, - const char *ifname) +iptablesClearVirtInPostFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *ifname) { - const char *match = MATCH_PHYSDEV_IN; - virBufferAsprintf(buf, - "$IPT -D " VIRT_IN_POST_CHAIN - " %s %s -j ACCEPT" CMD_SEPARATOR, - match, ifname); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", VIRT_IN_POST_CHAIN, + MATCH_PHYSDEV_IN_FW, + ifname, "-j", "ACCEPT", NULL); } static void @@ -816,6 +873,57 @@ _iptablesUnlinkRootChain(virBufferPtr buf, } +static void +_iptablesUnlinkRootChainFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *basechain, + char prefix, + bool incoming, const char *ifname, + int isTempChain) +{ + char chain[MAX_CHAINNAME_LENGTH]; + char chainPrefix[2] = { + prefix, + }; + if (isTempChain) + chainPrefix[1] = incoming ? CHAINPREFIX_HOST_IN_TEMP + : CHAINPREFIX_HOST_OUT_TEMP; + else + chainPrefix[1] = incoming ? CHAINPREFIX_HOST_IN + : CHAINPREFIX_HOST_OUT; + + PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname); + + if (incoming) + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", basechain, + MATCH_PHYSDEV_IN_FW, ifname, + "-g", chain, + NULL); + else + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", basechain, + MATCH_PHYSDEV_OUT_FW, ifname, + "-g", chain, + NULL); + + /* + * Previous versions of libvirt may have created a rule + * with the --physdev-is-bridged missing. Remove this one + * as well. + */ + if (!incoming) + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", basechain, + MATCH_PHYSDEV_OUT_OLD_FW, ifname, + "-g", chain, + NULL); +} + + static void iptablesUnlinkRootChain(virBufferPtr buf, const char *basechain, @@ -826,6 +934,17 @@ iptablesUnlinkRootChain(virBufferPtr buf, basechain, prefix, incoming, ifname, false); } +static void +iptablesUnlinkRootChainFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *basechain, + char prefix, + bool incoming, const char *ifname) +{ + _iptablesUnlinkRootChainFW(fw, layer, + basechain, prefix, incoming, ifname, false); +} + static void iptablesUnlinkTmpRootChain(virBufferPtr buf, @@ -848,6 +967,17 @@ iptablesUnlinkRootChains(virBufferPtr buf, } +static void +iptablesUnlinkRootChainsFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *ifname) +{ + iptablesUnlinkRootChainFW(fw, layer, VIRT_OUT_CHAIN, 'F', false, ifname); + iptablesUnlinkRootChainFW(fw, layer, VIRT_IN_CHAIN, 'F', true, ifname); + iptablesUnlinkRootChainFW(fw, layer, HOST_IN_CHAIN, 'H', true, ifname); +} + + static void iptablesUnlinkTmpRootChains(virBufferPtr buf, const char *ifname) @@ -2801,6 +2931,31 @@ _ebtablesRemoveRootChain(virBufferPtr buf, } +static void +_ebtablesRemoveRootChainFW(virFirewallPtr fw, + bool incoming, const char *ifname, + int isTempChain) +{ + char chain[MAX_CHAINNAME_LENGTH]; + char chainPrefix; + if (isTempChain) + chainPrefix = incoming ? CHAINPREFIX_HOST_IN_TEMP + : CHAINPREFIX_HOST_OUT_TEMP; + else + chainPrefix = incoming ? CHAINPREFIX_HOST_IN + : CHAINPREFIX_HOST_OUT; + + PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); + + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + true, NULL, NULL, + "-t", "nat", "-F", chain, NULL); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + true, NULL, NULL, + "-t", "nat", "-X", chain, NULL); +} + + static void ebtablesRemoveRootChain(virBufferPtr buf, bool incoming, const char *ifname) @@ -2809,6 +2964,14 @@ ebtablesRemoveRootChain(virBufferPtr buf, } +static void +ebtablesRemoveRootChainFW(virFirewallPtr fw, + bool incoming, const char *ifname) +{ + _ebtablesRemoveRootChainFW(fw, incoming, ifname, false); +} + + static void ebtablesRemoveTmpRootChain(virBufferPtr buf, bool incoming, const char *ifname) @@ -2844,6 +3007,33 @@ _ebtablesUnlinkRootChain(virBufferPtr buf, } +static void +_ebtablesUnlinkRootChainFW(virFirewallPtr fw, + bool incoming, const char *ifname, + int isTempChain) +{ + char chain[MAX_CHAINNAME_LENGTH]; + char chainPrefix; + + if (isTempChain) { + chainPrefix = incoming ? CHAINPREFIX_HOST_IN_TEMP + : CHAINPREFIX_HOST_OUT_TEMP; + } else { + chainPrefix = incoming ? CHAINPREFIX_HOST_IN + : CHAINPREFIX_HOST_OUT; + } + + PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); + + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + true, NULL, NULL, + "-t", "nat", "-D", + incoming ? EBTABLES_CHAIN_INCOMING : EBTABLES_CHAIN_OUTGOING, + incoming ? "-i" : "-o", + ifname, "-j", chain, NULL); +} + + static void ebtablesUnlinkRootChain(virBufferPtr buf, bool incoming, const char *ifname) @@ -2852,6 +3042,14 @@ ebtablesUnlinkRootChain(virBufferPtr buf, } +static void +ebtablesUnlinkRootChainFW(virFirewallPtr fw, + bool incoming, const char *ifname) +{ + _ebtablesUnlinkRootChainFW(fw, incoming, ifname, false); +} + + static void ebtablesUnlinkTmpRootChain(virBufferPtr buf, bool incoming, const char *ifname) @@ -2972,6 +3170,60 @@ _ebtablesRemoveSubChains(virBufferPtr buf, virBufferAddLit(buf, "rm_chains $chains\n"); } + +static int +ebtablesRemoveSubChainsQuery(virFirewallPtr fw, + const char *const *lines, + void *opaque) +{ + size_t i, j; + const char *chainprefixes = opaque; + + for (i = 0; lines[i] != NULL; i++) { + VIR_DEBUG("Considering '%s'", lines[i]); + char *tmp = strstr(lines[i], "-j "); + if (!tmp) + continue; + tmp = tmp + 3; + for (j = 0; chainprefixes[j]; j++) { + if (tmp[0] == chainprefixes[j] && + tmp[1] == '-') { + VIR_DEBUG("Processing chain '%s'", tmp); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + false, ebtablesRemoveSubChainsQuery, + (void *)chainprefixes, + "-t", "nat", "-L", tmp, NULL); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + true, NULL, NULL, + "-t", "nat", "-F", tmp, NULL); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + true, NULL, NULL, + "-t", "nat", "-X", tmp, NULL); + } + } + } + + return 0; +} + + +static void +_ebtablesRemoveSubChainsFW(virFirewallPtr fw, + const char *ifname, + const char *chainprefixes) +{ + char rootchain[MAX_CHAINNAME_LENGTH]; + size_t i; + + for (i = 0; chainprefixes[i] != 0; i++) { + PRINT_ROOT_CHAIN(rootchain, chainprefixes[i], ifname); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + false, ebtablesRemoveSubChainsQuery, + (void *)chainprefixes, + "-t", "nat", "-L", rootchain, NULL); + } +} + static void ebtablesRemoveSubChains(virBufferPtr buf, const char *ifname) @@ -2985,6 +3237,13 @@ ebtablesRemoveSubChains(virBufferPtr buf, _ebtablesRemoveSubChains(buf, ifname, chains); } +static void +ebtablesRemoveSubChainsFW(virFirewallPtr fw, + const char *ifname) +{ + _ebtablesRemoveSubChainsFW(fw, ifname, chainprefixes_host); +} + static void ebtablesRemoveTmpSubChains(virBufferPtr buf, const char *ifname) @@ -4052,43 +4311,37 @@ ebiptablesTearOldRules(const char *ifname) * Unconditionally remove all possible user defined tables and rules * that were created for the given interface (ifname). * - * Always returns 0. + * Returns 0 on success, -1 on OOM */ static int ebiptablesAllTeardown(const char *ifname) { - virBuffer buf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = virFirewallNew(); + int ret = -1; - if (iptables_cmd_path) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); - iptablesUnlinkRootChains(&buf, ifname); - iptablesClearVirtInPost(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - } + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesClearVirtInPostFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); - if (ip6tables_cmd_path) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesClearVirtInPostFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); - iptablesUnlinkRootChains(&buf, ifname); - iptablesClearVirtInPost(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - } + ebtablesUnlinkRootChainFW(fw, true, ifname); + ebtablesUnlinkRootChainFW(fw, false, ifname); - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + ebtablesRemoveSubChainsFW(fw, ifname); - ebtablesUnlinkRootChain(&buf, true, ifname); - ebtablesUnlinkRootChain(&buf, false, ifname); + ebtablesRemoveRootChainFW(fw, true, ifname); + ebtablesRemoveRootChainFW(fw, false, ifname); - ebtablesRemoveSubChains(&buf, ifname); - - ebtablesRemoveRootChain(&buf, true, ifname); - ebtablesRemoveRootChain(&buf, false, ifname); - } - ebiptablesExecCLI(&buf, true, NULL); - - return 0; + virMutexLock(&execCLIMutex); + ret = virFirewallApply(fw); + virMutexUnlock(&execCLIMutex); + virFirewallFree(fw); + return ret; } diff --git a/tests/Makefile.am b/tests/Makefile.am index bda3632742..3917b9d52d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -272,6 +272,10 @@ endif WITH_STORAGE_SHEEPDOG test_programs += nwfilterxml2xmltest +if WITH_NWFILTER +test_programs += nwfilterebiptablestest +endif WITH_NWFILTER + if WITH_STORAGE test_programs += storagevolxml2argvtest endif WITH_STORAGE @@ -696,6 +700,13 @@ nwfilterxml2xmltest_SOURCES = \ testutils.c testutils.h nwfilterxml2xmltest_LDADD = $(LDADDS) +if WITH_NWFILTER +nwfilterebiptablestest_SOURCES = \ + nwfilterebiptablestest.c \ + testutils.c testutils.h +nwfilterebiptablestest_LDADD = ../src/libvirt_driver_nwfilter_impl.la $(LDADDS) +endif WITH_NWFILTER + secretxml2xmltest_SOURCES = \ secretxml2xmltest.c \ testutils.c testutils.h diff --git a/tests/nwfilterebiptablestest.c b/tests/nwfilterebiptablestest.c new file mode 100644 index 0000000000..da17d6a653 --- /dev/null +++ b/tests/nwfilterebiptablestest.c @@ -0,0 +1,118 @@ +/* + * nwfilterebiptablestest.c: Test {eb,ip,ip6}tables rule generation + * + * Copyright (C) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + */ + +#include + +#include "testutils.h" +#include "nwfilter/nwfilter_ebiptables_driver.h" +#include "virbuffer.h" + +#define __VIR_FIREWALL_PRIV_H_ALLOW__ +#include "virfirewallpriv.h" + +#define __VIR_COMMAND_PRIV_H_ALLOW__ +#include "vircommandpriv.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +static int +testNWFilterEBIPTablesAllTeardown(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *expected = + "iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "iptables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "iptables -F FO-vnet0\n" + "iptables -X FO-vnet0\n" + "iptables -F FI-vnet0\n" + "iptables -X FI-vnet0\n" + "iptables -F HI-vnet0\n" + "iptables -X HI-vnet0\n" + "ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "ip6tables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "ip6tables -F FO-vnet0\n" + "ip6tables -X FO-vnet0\n" + "ip6tables -F FI-vnet0\n" + "ip6tables -X FI-vnet0\n" + "ip6tables -F HI-vnet0\n" + "ip6tables -X HI-vnet0\n" + "ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-I-vnet0\n" + "ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-O-vnet0\n" + "ebtables -t nat -L libvirt-I-vnet0\n" + "ebtables -t nat -L libvirt-O-vnet0\n" + "ebtables -t nat -F libvirt-I-vnet0\n" + "ebtables -t nat -X libvirt-I-vnet0\n" + "ebtables -t nat -F libvirt-O-vnet0\n" + "ebtables -t nat -X libvirt-O-vnet0\n"; + char *actual = NULL; + int ret = -1; + + virCommandSetDryRun(&buf, NULL, NULL); + + if (ebiptables_driver.allTeardown("vnet0") < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actual = virBufferContentAndReset(&buf); + virtTestClearCommandPath(actual); + + if (STRNEQ_NULLABLE(actual, expected)) { + virtTestDifference(stderr, actual, expected); + goto cleanup; + } + + ret = 0; + cleanup: + virCommandSetDryRun(NULL, NULL, NULL); + virBufferFreeAndReset(&buf); + VIR_FREE(actual); + return ret; +} + + +static int +mymain(void) +{ + int ret = 0; + + if (virFirewallSetBackend(VIR_FIREWALL_BACKEND_DIRECT) < 0) { + ret = -1; + goto cleanup; + } + + if (virtTestRun("ebiptablesAllTeardown", + testNWFilterEBIPTablesAllTeardown, + NULL) < 0) + ret = -1; + + cleanup: + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain)