[libvirt] [PATCH 00/26] Rewrite firewall code to use formal API

Currently we have three places which interact with the firewall - util/virebtables - simple MAC filtering used by QEMU driver - util/viriptables - used by network driver - nwfilter - general purpose guest filtering All of these have been hacked to support firewalld by re-directing them via the 'firewall-cmd' command line tool. Unfortunately talking to firewalld via this CLI tool is incredibly inefficient. eg timing the network driver $ for i in `seq 1 10` ; do virsh net-start default; virsh net-destroy default ; done Direct iptables: 3 seconds Via firewall-cmd: 42 seconds Or timing the nwfilter driver via libvirt-tck/scripts/nwfilter/050-apply-verify-host.t Direct iptables: 28 seconds Via firewall-cmd: 479 seconds IOW it is more than x10 slower to use firewall-cmd. Testing revealed that this performance penalty is entirely due to the 'firewall-cmd' command line tool. If you talk directly to firewalld over DBus then the performance is near native. Unfortunately switching to use the DBus API is non-trivial since all the code we have for interacting with the firewall is just constructing virCommand instances directly (viriptables) or constructing gross shell scripts (nwfilter). Thus to enable use of the DBus API this series introduces the concept of a new object and APIs for interacting with the firewall "virFirewall". This API is designed to be a fairly generic basis for interacting with any firewall. It just has a concept of a level (ethernet, ipv4 or ipv6) and lists of rules, where each rule is just a string array of args. The idea is that the mechanism for interacting with the firewall can be generic and portable, even though the actual rules will be different on Linux vs FreeBSD vs other OS. The initial virFirewall implementation supports direct iptables/ebtables invocation or the DBus firewalld API. Use of firewall-cmd has been killed completely. Adapting code to use virFirewall has been a pretty horrific job, so is split up into as many patches as is practical. By far the worst/hardest patch is the one for nwfilter applyNewRules method (patch 23). Fortunately the libvirt-tck has a large set of XML data files and corresponding expected iptables/ebtables rules. This series passes the libvirt-tck 100% before and after, so I'm fairly confident that all the core functionality is working correctly. I also introduced new unit tests, that re-use the XML files from the libvirt-tck to validate the actual iptables/ebtables commands that libvirt tests. I've run this unit test under valgrind and under the OOM simulator to identify and fix any crashes / leaks that the refactoring introduced. With this series applied the performance is vastly improved for firewalld eg timing the network driver $ for i in `seq 1 10` ; do virsh net-start default; virsh net-destroy default ; done Direct iptables: 3 seconds Via firewall-cmd: 3 seconds Or timing the nwfilter driver via libvirt-tck/scripts/nwfilter/050-apply-verify-host.t Direct iptables: 29 seconds Via firewall-cmd: 37 seconds IOW firewalld is only marginly slower than direct iptables usage now. Regards, Daniel Daniel P. Berrange (26): Move virNWFilterTechDriver struct out of nwfilter_conf.h Remove virDomainNetType parameter from nwfilter drivers Remove pointless storage of var names in virNWFilterHashTable Remove nwfilter tech driver 'removeRules' callback Remove nwfilter tech driver 'displayRuleInstance' callback Add helper methods for determining what protocol layer is used Push virNWFilterRuleInstPtr out of (eb|ip)tablesCreateRuleInstance Merge nwfilter createRuleInstance driver into applyNewRules Remove two-stage construction of commands in nwfilter Preserve error when tearing down nwfilter rules Introduce an object for managing firewall rulesets Convert bridge driver over to use new firewall APIs Replace virNetworkObjPtr with virNetworkDefPtr in network platform APIs Add test for converting network XML to iptables rules Convert ebtables code over to use firewall APIs Convert nwfilter ebiptablesAllTeardown to virFirewall Convert nwfilter ebiptablesTearOldRules to virFirewall Convert nwfilter ebtablesRemoveBasicRules to virFirewall Convert nwfilter ebiptablesTearNewRules to virFirewall Convert nwfilter ebtablesApplyBasicRules to virFirewall Convert nwfilter ebtablesApplyDHCPOnlyRules to virFirewall Convert nwfilter ebtablesApplyDropAllRules to virFirewall Convert nwfilter ebiptablesApplyNewRules to virFirewall Convert ebiptablesDriverProbeStateMatch to virFirewall Remove last trace of direct firewall command exection Add a test suite for nwfilter ebiptables tech driver include/libvirt/virterror.h | 1 + po/POTFILES.in | 1 + src/Makefile.am | 21 +- src/conf/nwfilter_conf.c | 49 +- src/conf/nwfilter_conf.h | 107 +- src/conf/nwfilter_ipaddrmap.c | 2 +- src/conf/nwfilter_params.c | 63 +- src/conf/nwfilter_params.h | 7 +- src/libvirt_private.syms | 22 + src/network/bridge_driver.c | 18 +- src/network/bridge_driver_linux.c | 757 ++-- src/network/bridge_driver_nop.c | 6 +- src/network/bridge_driver_platform.h | 7 +- src/nwfilter/nwfilter_dhcpsnoop.c | 6 - src/nwfilter/nwfilter_dhcpsnoop.h | 3 +- src/nwfilter/nwfilter_ebiptables_driver.c | 3867 ++++++++------------ src/nwfilter/nwfilter_ebiptables_driver.h | 19 +- src/nwfilter/nwfilter_gentech_driver.c | 415 +-- src/nwfilter/nwfilter_gentech_driver.h | 2 +- src/nwfilter/nwfilter_learnipaddr.c | 5 - src/nwfilter/nwfilter_learnipaddr.h | 3 +- src/nwfilter/nwfilter_tech_driver.h | 96 + src/qemu/qemu_command.c | 6 +- src/util/virebtables.c | 185 +- src/util/virerror.c | 1 + src/util/virfirewall.c | 922 +++++ src/util/virfirewall.h | 109 + src/util/virfirewallpriv.h | 45 + src/util/viriptables.c | 632 ++-- src/util/viriptables.h | 114 +- tests/Makefile.am | 42 +- .../networkxml2firewalldata/nat-default-linux.args | 30 + tests/networkxml2firewalldata/nat-default.xml | 10 + tests/networkxml2firewalldata/nat-ipv6-linux.args | 44 + tests/networkxml2firewalldata/nat-ipv6.xml | 15 + .../nat-many-ips-linux.args | 58 + tests/networkxml2firewalldata/nat-many-ips.xml | 12 + .../networkxml2firewalldata/nat-no-dhcp-linux.args | 42 + tests/networkxml2firewalldata/nat-no-dhcp.xml | 7 + tests/networkxml2firewalldata/nat-tftp-linux.args | 32 + tests/networkxml2firewalldata/nat-tftp.xml | 11 + .../route-default-linux.args | 20 + tests/networkxml2firewalldata/route-default.xml | 10 + tests/networkxml2firewalltest.c | 162 + tests/nwfilterebiptablestest.c | 548 +++ tests/nwfilterxml2firewalldata/ah-ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/ah-ipv6.xml | 19 + tests/nwfilterxml2firewalldata/ah-linux.args | 18 + tests/nwfilterxml2firewalldata/ah.xml | 18 + tests/nwfilterxml2firewalldata/all-ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/all-ipv6.xml | 19 + tests/nwfilterxml2firewalldata/all-linux.args | 18 + tests/nwfilterxml2firewalldata/all.xml | 18 + tests/nwfilterxml2firewalldata/arp-linux.args | 11 + tests/nwfilterxml2firewalldata/arp.xml | 32 + tests/nwfilterxml2firewalldata/comment-linux.args | 49 + tests/nwfilterxml2firewalldata/comment.xml | 71 + .../nwfilterxml2firewalldata/conntrack-linux.args | 7 + tests/nwfilterxml2firewalldata/conntrack.xml | 12 + tests/nwfilterxml2firewalldata/esp-ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/esp-ipv6.xml | 19 + tests/nwfilterxml2firewalldata/esp-linux.args | 18 + tests/nwfilterxml2firewalldata/esp.xml | 18 + .../nwfilterxml2firewalldata/example-1-linux.args | 13 + tests/nwfilterxml2firewalldata/example-1.xml | 24 + .../nwfilterxml2firewalldata/example-2-linux.args | 20 + tests/nwfilterxml2firewalldata/example-2.xml | 37 + tests/nwfilterxml2firewalldata/hex-data-linux.args | 28 + tests/nwfilterxml2firewalldata/hex-data.xml | 56 + .../icmp-direction-linux.args | 9 + tests/nwfilterxml2firewalldata/icmp-direction.xml | 15 + .../icmp-direction2-linux.args | 9 + tests/nwfilterxml2firewalldata/icmp-direction2.xml | 15 + .../icmp-direction3-linux.args | 6 + tests/nwfilterxml2firewalldata/icmp-direction3.xml | 10 + tests/nwfilterxml2firewalldata/icmp-linux.args | 9 + tests/nwfilterxml2firewalldata/icmp.xml | 13 + tests/nwfilterxml2firewalldata/icmpv6-linux.args | 12 + tests/nwfilterxml2firewalldata/icmpv6.xml | 19 + tests/nwfilterxml2firewalldata/igmp-linux.args | 18 + tests/nwfilterxml2firewalldata/igmp.xml | 18 + tests/nwfilterxml2firewalldata/ip-linux.args | 8 + tests/nwfilterxml2firewalldata/ip.xml | 28 + tests/nwfilterxml2firewalldata/ipset-linux.args | 36 + tests/nwfilterxml2firewalldata/ipset.xml | 25 + .../ipt-no-macspoof-linux.args | 2 + tests/nwfilterxml2firewalldata/ipt-no-macspoof.xml | 14 + tests/nwfilterxml2firewalldata/ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/ipv6.xml | 43 + tests/nwfilterxml2firewalldata/iter1-linux.args | 18 + tests/nwfilterxml2firewalldata/iter1.xml | 6 + tests/nwfilterxml2firewalldata/iter2-linux.args | 342 ++ tests/nwfilterxml2firewalldata/iter2.xml | 23 + tests/nwfilterxml2firewalldata/iter3-linux.args | 30 + tests/nwfilterxml2firewalldata/iter3.xml | 13 + tests/nwfilterxml2firewalldata/mac-linux.args | 8 + tests/nwfilterxml2firewalldata/mac.xml | 19 + tests/nwfilterxml2firewalldata/rarp-linux.args | 12 + tests/nwfilterxml2firewalldata/rarp.xml | 28 + tests/nwfilterxml2firewalldata/ref-rule.xml | 18 + tests/nwfilterxml2firewalldata/ref.xml | 4 + .../nwfilterxml2firewalldata/sctp-ipv6-linux.args | 22 + tests/nwfilterxml2firewalldata/sctp-ipv6.xml | 22 + tests/nwfilterxml2firewalldata/sctp-linux.args | 20 + tests/nwfilterxml2firewalldata/sctp.xml | 22 + tests/nwfilterxml2firewalldata/stp-linux.args | 18 + tests/nwfilterxml2firewalldata/stp.xml | 26 + tests/nwfilterxml2firewalldata/target-linux.args | 75 + tests/nwfilterxml2firewalldata/target.xml | 66 + tests/nwfilterxml2firewalldata/target2-linux.args | 13 + tests/nwfilterxml2firewalldata/target2.xml | 18 + tests/nwfilterxml2firewalldata/tcp-ipv6-linux.args | 22 + tests/nwfilterxml2firewalldata/tcp-ipv6.xml | 22 + tests/nwfilterxml2firewalldata/tcp-linux.args | 22 + tests/nwfilterxml2firewalldata/tcp.xml | 34 + tests/nwfilterxml2firewalldata/udp-ipv6-linux.args | 22 + tests/nwfilterxml2firewalldata/udp-ipv6.xml | 22 + tests/nwfilterxml2firewalldata/udp-linux.args | 20 + tests/nwfilterxml2firewalldata/udp.xml | 22 + .../udplite-ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/udplite-ipv6.xml | 19 + tests/nwfilterxml2firewalldata/udplite-linux.args | 18 + tests/nwfilterxml2firewalldata/udplite.xml | 18 + tests/nwfilterxml2firewalldata/vlan-linux.args | 14 + tests/nwfilterxml2firewalldata/vlan.xml | 38 + tests/nwfilterxml2firewalltest.c | 534 +++ tests/testutils.c | 18 +- tests/virfirewalltest.c | 1186 ++++++ 128 files changed, 8637 insertions(+), 3685 deletions(-) create mode 100644 src/nwfilter/nwfilter_tech_driver.h create mode 100644 src/util/virfirewall.c create mode 100644 src/util/virfirewall.h create mode 100644 src/util/virfirewallpriv.h create mode 100644 tests/networkxml2firewalldata/nat-default-linux.args create mode 100644 tests/networkxml2firewalldata/nat-default.xml create mode 100644 tests/networkxml2firewalldata/nat-ipv6-linux.args create mode 100644 tests/networkxml2firewalldata/nat-ipv6.xml create mode 100644 tests/networkxml2firewalldata/nat-many-ips-linux.args create mode 100644 tests/networkxml2firewalldata/nat-many-ips.xml create mode 100644 tests/networkxml2firewalldata/nat-no-dhcp-linux.args create mode 100644 tests/networkxml2firewalldata/nat-no-dhcp.xml create mode 100644 tests/networkxml2firewalldata/nat-tftp-linux.args create mode 100644 tests/networkxml2firewalldata/nat-tftp.xml create mode 100644 tests/networkxml2firewalldata/route-default-linux.args create mode 100644 tests/networkxml2firewalldata/route-default.xml create mode 100644 tests/networkxml2firewalltest.c create mode 100644 tests/nwfilterebiptablestest.c create mode 100644 tests/nwfilterxml2firewalldata/ah-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ah-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/ah-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ah.xml create mode 100644 tests/nwfilterxml2firewalldata/all-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/all-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/all-linux.args create mode 100644 tests/nwfilterxml2firewalldata/all.xml create mode 100644 tests/nwfilterxml2firewalldata/arp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/arp.xml create mode 100644 tests/nwfilterxml2firewalldata/comment-linux.args create mode 100644 tests/nwfilterxml2firewalldata/comment.xml create mode 100644 tests/nwfilterxml2firewalldata/conntrack-linux.args create mode 100644 tests/nwfilterxml2firewalldata/conntrack.xml create mode 100644 tests/nwfilterxml2firewalldata/esp-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/esp-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/esp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/esp.xml create mode 100644 tests/nwfilterxml2firewalldata/example-1-linux.args create mode 100644 tests/nwfilterxml2firewalldata/example-1.xml create mode 100644 tests/nwfilterxml2firewalldata/example-2-linux.args create mode 100644 tests/nwfilterxml2firewalldata/example-2.xml create mode 100644 tests/nwfilterxml2firewalldata/hex-data-linux.args create mode 100644 tests/nwfilterxml2firewalldata/hex-data.xml create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction.xml create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction2-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction2.xml create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction3-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction3.xml create mode 100644 tests/nwfilterxml2firewalldata/icmp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmp.xml create mode 100644 tests/nwfilterxml2firewalldata/icmpv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmpv6.xml create mode 100644 tests/nwfilterxml2firewalldata/igmp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/igmp.xml create mode 100644 tests/nwfilterxml2firewalldata/ip-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ip.xml create mode 100644 tests/nwfilterxml2firewalldata/ipset-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ipset.xml create mode 100644 tests/nwfilterxml2firewalldata/ipt-no-macspoof-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ipt-no-macspoof.xml create mode 100644 tests/nwfilterxml2firewalldata/ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/iter1-linux.args create mode 100644 tests/nwfilterxml2firewalldata/iter1.xml create mode 100644 tests/nwfilterxml2firewalldata/iter2-linux.args create mode 100644 tests/nwfilterxml2firewalldata/iter2.xml create mode 100644 tests/nwfilterxml2firewalldata/iter3-linux.args create mode 100644 tests/nwfilterxml2firewalldata/iter3.xml create mode 100644 tests/nwfilterxml2firewalldata/mac-linux.args create mode 100644 tests/nwfilterxml2firewalldata/mac.xml create mode 100644 tests/nwfilterxml2firewalldata/rarp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/rarp.xml create mode 100644 tests/nwfilterxml2firewalldata/ref-rule.xml create mode 100644 tests/nwfilterxml2firewalldata/ref.xml create mode 100644 tests/nwfilterxml2firewalldata/sctp-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/sctp-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/sctp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/sctp.xml create mode 100644 tests/nwfilterxml2firewalldata/stp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/stp.xml create mode 100644 tests/nwfilterxml2firewalldata/target-linux.args create mode 100644 tests/nwfilterxml2firewalldata/target.xml create mode 100644 tests/nwfilterxml2firewalldata/target2-linux.args create mode 100644 tests/nwfilterxml2firewalldata/target2.xml create mode 100644 tests/nwfilterxml2firewalldata/tcp-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/tcp-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/tcp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/tcp.xml create mode 100644 tests/nwfilterxml2firewalldata/udp-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/udp-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/udp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/udp.xml create mode 100644 tests/nwfilterxml2firewalldata/udplite-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/udplite-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/udplite-linux.args create mode 100644 tests/nwfilterxml2firewalldata/udplite.xml create mode 100644 tests/nwfilterxml2firewalldata/vlan-linux.args create mode 100644 tests/nwfilterxml2firewalldata/vlan.xml create mode 100644 tests/nwfilterxml2firewalltest.c create mode 100644 tests/virfirewalltest.c -- 1.9.0

The virNWFilterTechDriver struct is nothing todo with the nwfilter XML configuration. It stores data specific to the driver implementation so should be in a header in the driver directory instead. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/Makefile.am | 1 + src/conf/nwfilter_conf.h | 86 ---------------------- src/nwfilter/nwfilter_dhcpsnoop.h | 2 + src/nwfilter/nwfilter_ebiptables_driver.h | 2 + src/nwfilter/nwfilter_gentech_driver.h | 1 + src/nwfilter/nwfilter_learnipaddr.h | 1 + src/nwfilter/nwfilter_tech_driver.h | 115 ++++++++++++++++++++++++++++++ 7 files changed, 122 insertions(+), 86 deletions(-) create mode 100644 src/nwfilter/nwfilter_tech_driver.h diff --git a/src/Makefile.am b/src/Makefile.am index 21d56fc..7e9a702 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -858,6 +858,7 @@ UTIL_IO_HELPER_SOURCES = \ # Network filters NWFILTER_DRIVER_SOURCES = \ nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \ + nwfilter/nwfilter_tech_driver.h \ nwfilter/nwfilter_gentech_driver.c \ nwfilter/nwfilter_gentech_driver.h \ nwfilter/nwfilter_dhcpsnoop.c \ diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index 071343e..aded4de 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -567,19 +567,6 @@ struct _virNWFilterDriverState { }; -typedef struct _virNWFilterTechDriver virNWFilterTechDriver; -typedef virNWFilterTechDriver *virNWFilterTechDriverPtr; - - -typedef struct _virNWFilterRuleInst virNWFilterRuleInst; -typedef virNWFilterRuleInst *virNWFilterRuleInstPtr; -struct _virNWFilterRuleInst { - size_t ndata; - void **data; - virNWFilterTechDriverPtr techdriver; -}; - - enum UpdateStep { STEP_APPLY_NEW, STEP_TEAR_NEW, @@ -594,79 +581,6 @@ struct domUpdateCBStruct { }; -typedef int (*virNWFilterTechDrvInit)(bool privileged); -typedef void (*virNWFilterTechDrvShutdown)(void); - -enum virDomainNetType; - -typedef int (*virNWFilterRuleCreateInstance)(enum virDomainNetType nettype, - virNWFilterDefPtr filter, - virNWFilterRuleDefPtr rule, - const char *ifname, - virNWFilterHashTablePtr vars, - virNWFilterRuleInstPtr res); - -typedef int (*virNWFilterRuleApplyNewRules)(const char *ifname, - int nruleInstances, - void **_inst); - -typedef int (*virNWFilterRuleTeardownNewRules)(const char *ifname); - -typedef int (*virNWFilterRuleTeardownOldRules)(const char *ifname); - -typedef int (*virNWFilterRuleRemoveRules)(const char *ifname, - int nruleInstances, - void **_inst); - -typedef int (*virNWFilterRuleAllTeardown)(const char *ifname); - -typedef int (*virNWFilterRuleFreeInstanceData)(void * _inst); - -typedef int (*virNWFilterRuleDisplayInstanceData)(void *_inst); - -typedef int (*virNWFilterCanApplyBasicRules)(void); - -typedef int (*virNWFilterApplyBasicRules)(const char *ifname, - const virMacAddr *macaddr); - -typedef int (*virNWFilterApplyDHCPOnlyRules)(const char *ifname, - const virMacAddr *macaddr, - virNWFilterVarValuePtr dhcpsrvs, - bool leaveTemporary); - -typedef int (*virNWFilterRemoveBasicRules)(const char *ifname); - -typedef int (*virNWFilterDropAllRules)(const char *ifname); - -enum techDrvFlags { - TECHDRV_FLAG_INITIALIZED = (1 << 0), -}; - -struct _virNWFilterTechDriver { - const char *name; - enum techDrvFlags flags; - - virNWFilterTechDrvInit init; - virNWFilterTechDrvShutdown shutdown; - - virNWFilterRuleCreateInstance createRuleInstance; - virNWFilterRuleApplyNewRules applyNewRules; - virNWFilterRuleTeardownNewRules tearNewRules; - virNWFilterRuleTeardownOldRules tearOldRules; - virNWFilterRuleRemoveRules removeRules; - virNWFilterRuleAllTeardown allTeardown; - virNWFilterRuleFreeInstanceData freeRuleInstance; - virNWFilterRuleDisplayInstanceData displayRuleInstance; - - virNWFilterCanApplyBasicRules canApplyBasicRules; - virNWFilterApplyBasicRules applyBasicRules; - virNWFilterApplyDHCPOnlyRules applyDHCPOnlyRules; - virNWFilterDropAllRules applyDropAllRules; - virNWFilterRemoveBasicRules removeBasicRules; -}; - - - void virNWFilterRuleDefFree(virNWFilterRuleDefPtr def); void virNWFilterDefFree(virNWFilterDefPtr def); diff --git a/src/nwfilter/nwfilter_dhcpsnoop.h b/src/nwfilter/nwfilter_dhcpsnoop.h index c6b45d1..6e73eb3 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.h +++ b/src/nwfilter/nwfilter_dhcpsnoop.h @@ -25,6 +25,8 @@ #ifndef __NWFILTER_DHCPSNOOP_H # define __NWFILTER_DHCPSNOOP_H +# include "nwfilter_tech_driver.h" + int virNWFilterDHCPSnoopInit(void); void virNWFilterDHCPSnoopShutdown(void); int virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, diff --git a/src/nwfilter/nwfilter_ebiptables_driver.h b/src/nwfilter/nwfilter_ebiptables_driver.h index d909abb..8a17452 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.h +++ b/src/nwfilter/nwfilter_ebiptables_driver.h @@ -23,6 +23,8 @@ #ifndef VIR_NWFILTER_EBTABLES_DRIVER_H__ # define VIR_NWFILTER_EBTABLES_DRIVER_H__ +# include "nwfilter_tech_driver.h" + # define MAX_CHAINNAME_LENGTH 32 /* see linux/netfilter_bridge/ebtables.h */ enum RuleType { diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index 52bd1f6..da85508 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -25,6 +25,7 @@ # define __NWFILTER_GENTECH_DRIVER_H # include "nwfilter_conf.h" +# include "nwfilter_tech_driver.h" virNWFilterTechDriverPtr virNWFilterTechDriverForName(const char *name); diff --git a/src/nwfilter/nwfilter_learnipaddr.h b/src/nwfilter/nwfilter_learnipaddr.h index 783dc16..0195d10 100644 --- a/src/nwfilter/nwfilter_learnipaddr.h +++ b/src/nwfilter/nwfilter_learnipaddr.h @@ -27,6 +27,7 @@ # define __NWFILTER_LEARNIPADDR_H # include "conf/nwfilter_params.h" +# include "nwfilter_tech_driver.h" # include <net/if.h> enum howDetect { diff --git a/src/nwfilter/nwfilter_tech_driver.h b/src/nwfilter/nwfilter_tech_driver.h new file mode 100644 index 0000000..5777757 --- /dev/null +++ b/src/nwfilter/nwfilter_tech_driver.h @@ -0,0 +1,115 @@ +/* + * nwfilter_tech_driver.h: network filter technology driver interface + * + * Copyright (C) 2006-2014 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * + * Copyright (C) 2010 IBM Corporation + * + * 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 + * <http://www.gnu.org/licenses/>. + * + * Author: Stefan Berger <stefanb@us.ibm.com> + */ + +#ifndef __NWFILTER_TECH_DRIVER_H__ +# define __NWFILTER_TECH_DRIVER_H__ + +# include "nwfilter_conf.h" + +typedef struct _virNWFilterTechDriver virNWFilterTechDriver; +typedef virNWFilterTechDriver *virNWFilterTechDriverPtr; + + +typedef struct _virNWFilterRuleInst virNWFilterRuleInst; +typedef virNWFilterRuleInst *virNWFilterRuleInstPtr; +struct _virNWFilterRuleInst { + size_t ndata; + void **data; + virNWFilterTechDriverPtr techdriver; +}; + + +typedef int (*virNWFilterTechDrvInit)(bool privileged); +typedef void (*virNWFilterTechDrvShutdown)(void); + +enum virDomainNetType; + +typedef int (*virNWFilterRuleCreateInstance)(enum virDomainNetType nettype, + virNWFilterDefPtr filter, + virNWFilterRuleDefPtr rule, + const char *ifname, + virNWFilterHashTablePtr vars, + virNWFilterRuleInstPtr res); + +typedef int (*virNWFilterRuleApplyNewRules)(const char *ifname, + int nruleInstances, + void **_inst); + +typedef int (*virNWFilterRuleTeardownNewRules)(const char *ifname); + +typedef int (*virNWFilterRuleTeardownOldRules)(const char *ifname); + +typedef int (*virNWFilterRuleRemoveRules)(const char *ifname, + int nruleInstances, + void **_inst); + +typedef int (*virNWFilterRuleAllTeardown)(const char *ifname); + +typedef int (*virNWFilterRuleFreeInstanceData)(void * _inst); + +typedef int (*virNWFilterRuleDisplayInstanceData)(void *_inst); + +typedef int (*virNWFilterCanApplyBasicRules)(void); + +typedef int (*virNWFilterApplyBasicRules)(const char *ifname, + const virMacAddr *macaddr); + +typedef int (*virNWFilterApplyDHCPOnlyRules)(const char *ifname, + const virMacAddr *macaddr, + virNWFilterVarValuePtr dhcpsrvs, + bool leaveTemporary); + +typedef int (*virNWFilterRemoveBasicRules)(const char *ifname); + +typedef int (*virNWFilterDropAllRules)(const char *ifname); + +enum techDrvFlags { + TECHDRV_FLAG_INITIALIZED = (1 << 0), +}; + +struct _virNWFilterTechDriver { + const char *name; + enum techDrvFlags flags; + + virNWFilterTechDrvInit init; + virNWFilterTechDrvShutdown shutdown; + + virNWFilterRuleCreateInstance createRuleInstance; + virNWFilterRuleApplyNewRules applyNewRules; + virNWFilterRuleTeardownNewRules tearNewRules; + virNWFilterRuleTeardownOldRules tearOldRules; + virNWFilterRuleRemoveRules removeRules; + virNWFilterRuleAllTeardown allTeardown; + virNWFilterRuleFreeInstanceData freeRuleInstance; + virNWFilterRuleDisplayInstanceData displayRuleInstance; + + virNWFilterCanApplyBasicRules canApplyBasicRules; + virNWFilterApplyBasicRules applyBasicRules; + virNWFilterApplyDHCPOnlyRules applyDHCPOnlyRules; + virNWFilterDropAllRules applyDropAllRules; + virNWFilterRemoveBasicRules removeBasicRules; +}; + +#endif /* __NWFILTER_TECH_DRIVER_H__ */ -- 1.9.0

On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
The virNWFilterTechDriver struct is nothing todo with the nwfilter XML configuration. It stores data specific to the driver implementation so should be in a header in the driver directory instead.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This patch looks like a straight forward move. ACK

On 04/08/2014 09:37 AM, Daniel P. Berrange wrote:
The virNWFilterTechDriver struct is nothing todo with the nwfilter
s/todo/to do/
XML configuration. It stores data specific to the driver implementation so should be in a header in the driver directory instead.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/Makefile.am | 1 + src/conf/nwfilter_conf.h | 86 ---------------------- src/nwfilter/nwfilter_dhcpsnoop.h | 2 + src/nwfilter/nwfilter_ebiptables_driver.h | 2 + src/nwfilter/nwfilter_gentech_driver.h | 1 + src/nwfilter/nwfilter_learnipaddr.h | 1 + src/nwfilter/nwfilter_tech_driver.h | 115 ++++++++++++++++++++++++++++++ 7 files changed, 122 insertions(+), 86 deletions(-) create mode 100644 src/nwfilter/nwfilter_tech_driver.h
+ +enum virDomainNetType;
Do we still need this forward declaration, or now that it is in a dedicated header can it just include the correct prereq file? -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

The 'virDomainNetType' is unused in every impl of the virNWFilterRuleCreateInstance driver method. Remove it from the code to avoid the dependancy on the external enum. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_dhcpsnoop.c | 6 ------ src/nwfilter/nwfilter_dhcpsnoop.h | 1 - src/nwfilter/nwfilter_ebiptables_driver.c | 18 +++++++----------- src/nwfilter/nwfilter_gentech_driver.c | 17 +++-------------- src/nwfilter/nwfilter_gentech_driver.h | 1 - src/nwfilter/nwfilter_learnipaddr.c | 5 ----- src/nwfilter/nwfilter_learnipaddr.h | 2 -- src/nwfilter/nwfilter_tech_driver.h | 5 +---- 8 files changed, 11 insertions(+), 44 deletions(-) diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index df46a72..bfd0553 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -137,7 +137,6 @@ struct _virNWFilterSnoopReq { char *ifname; int ifindex; char *linkdev; - enum virDomainNetType nettype; char ifkey[VIR_IFKEY_LEN]; virMacAddr macaddr; char *filtername; @@ -493,7 +492,6 @@ virNWFilterSnoopIPLeaseInstallRule(virNWFilterSnoopIPLeasePtr ipl, req->ifname, req->ifindex, req->linkdev, - req->nettype, &req->macaddr, req->filtername, req->vars); @@ -879,7 +877,6 @@ virNWFilterSnoopReqLeaseDel(virNWFilterSnoopReqPtr req, req->ifname, req->ifindex, req->linkdev, - req->nettype, &req->macaddr, req->filtername, req->vars); @@ -1592,7 +1589,6 @@ int virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, const char *ifname, const char *linkdev, - enum virDomainNetType nettype, const unsigned char *vmuuid, const virMacAddr *macaddr, const char *filtername, @@ -1628,7 +1624,6 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, req->driver = driver; req->techdriver = techdriver; tmp = virNetDevGetIndex(ifname, &req->ifindex); - req->nettype = nettype; virMacAddrSet(&req->macaddr, macaddr); req->vars = virNWFilterHashTableCreate(0); req->linkdev = NULL; @@ -2230,7 +2225,6 @@ int virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver ATTRIBUTE_UNUSED, const char *ifname ATTRIBUTE_UNUSED, const char *linkdev ATTRIBUTE_UNUSED, - enum virDomainNetType nettype ATTRIBUTE_UNUSED, const unsigned char *vmuuid ATTRIBUTE_UNUSED, const virMacAddr *macaddr ATTRIBUTE_UNUSED, const char *filtername ATTRIBUTE_UNUSED, diff --git a/src/nwfilter/nwfilter_dhcpsnoop.h b/src/nwfilter/nwfilter_dhcpsnoop.h index 6e73eb3..3ef96fa 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.h +++ b/src/nwfilter/nwfilter_dhcpsnoop.h @@ -32,7 +32,6 @@ void virNWFilterDHCPSnoopShutdown(void); int virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, const char *ifname, const char *linkdev, - enum virDomainNetType nettype, const unsigned char *vmuuid, const virMacAddr *macaddr, const char *filtername, diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index ce0b7e3..4365c1f 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -2649,8 +2649,7 @@ ebtablesCreateRuleInstance(char chainPrefix, * pointed to by res, -1 otherwise */ static int -ebiptablesCreateRuleInstance(enum virDomainNetType nettype ATTRIBUTE_UNUSED, - virNWFilterDefPtr nwfilter, +ebiptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, @@ -2740,13 +2739,11 @@ ebiptablesCreateRuleInstance(enum virDomainNetType nettype ATTRIBUTE_UNUSED, } static int -ebiptablesCreateRuleInstanceIterate( - enum virDomainNetType nettype ATTRIBUTE_UNUSED, - virNWFilterDefPtr nwfilter, - virNWFilterRuleDefPtr rule, - const char *ifname, - virNWFilterHashTablePtr vars, - virNWFilterRuleInstPtr res) +ebiptablesCreateRuleInstanceIterate(virNWFilterDefPtr nwfilter, + virNWFilterRuleDefPtr rule, + const char *ifname, + virNWFilterHashTablePtr vars, + virNWFilterRuleInstPtr res) { int rc = 0; virNWFilterVarCombIterPtr vciter, tmp; @@ -2761,8 +2758,7 @@ ebiptablesCreateRuleInstanceIterate( return -1; do { - rc = ebiptablesCreateRuleInstance(nettype, - nwfilter, + rc = ebiptablesCreateRuleInstance(nwfilter, rule, ifname, tmp, diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 1ce5e70..82ff628 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -289,7 +289,6 @@ virNWFilterPrintVars(virHashTablePtr vars, */ static virNWFilterRuleInstPtr virNWFilterRuleInstantiate(virNWFilterTechDriverPtr techdriver, - enum virDomainNetType nettype, virNWFilterDefPtr filter, virNWFilterRuleDefPtr rule, const char *ifname, @@ -304,7 +303,7 @@ virNWFilterRuleInstantiate(virNWFilterTechDriverPtr techdriver, ret->techdriver = techdriver; - rc = techdriver->createRuleInstance(nettype, filter, + rc = techdriver->createRuleInstance(filter, rule, ifname, vars, ret); if (rc) { @@ -376,7 +375,6 @@ virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1, */ static int _virNWFilterInstantiateRec(virNWFilterTechDriverPtr techdriver, - enum virDomainNetType nettype, virNWFilterDefPtr filter, const char *ifname, virNWFilterHashTablePtr vars, @@ -396,7 +394,6 @@ _virNWFilterInstantiateRec(virNWFilterTechDriverPtr techdriver, virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include; if (rule) { inst = virNWFilterRuleInstantiate(techdriver, - nettype, filter, rule, ifname, @@ -449,7 +446,6 @@ _virNWFilterInstantiateRec(virNWFilterTechDriverPtr techdriver, } rc = _virNWFilterInstantiateRec(techdriver, - nettype, next_filter, ifname, tmpvars, @@ -634,7 +630,6 @@ virNWFilterRuleInstancesToArray(int nEntries, static int virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, virNWFilterTechDriverPtr techdriver, - enum virDomainNetType nettype, virNWFilterDefPtr filter, const char *ifname, int ifindex, @@ -690,7 +685,7 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, } if (STRCASEEQ(learning, "dhcp")) { rc = virNWFilterDHCPSnoopReq(techdriver, ifname, linkdev, - nettype, vmuuid, macaddr, + vmuuid, macaddr, filter->name, vars, driver); goto err_exit; } else if (STRCASEEQ(learning, "any")) { @@ -699,7 +694,7 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, ifname, ifindex, linkdev, - nettype, macaddr, + macaddr, filter->name, vars, driver, DETECT_DHCP|DETECT_STATIC); @@ -723,7 +718,6 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, } rc = _virNWFilterInstantiateRec(techdriver, - nettype, filter, ifname, vars, @@ -805,7 +799,6 @@ __virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver, const char *ifname, int ifindex, const char *linkdev, - enum virDomainNetType nettype, const virMacAddr *macaddr, const char *filtername, virNWFilterHashTablePtr filterparams, @@ -892,7 +885,6 @@ __virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver, rc = virNWFilterInstantiate(vmuuid, techdriver, - nettype, filter, ifname, ifindex, @@ -953,7 +945,6 @@ _virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver, net->ifname, ifindex, linkdev, - net->type, &net->mac, net->filter, net->filterparams, @@ -974,7 +965,6 @@ virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, const char *ifname, int ifindex, const char *linkdev, - enum virDomainNetType nettype, const virMacAddr *macaddr, const char *filtername, virNWFilterHashTablePtr filterparams) @@ -991,7 +981,6 @@ virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, ifname, ifindex, linkdev, - nettype, macaddr, filtername, filterparams, diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index da85508..8349ab4 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -51,7 +51,6 @@ int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, const char *ifname, int ifindex, const char *linkdev, - enum virDomainNetType nettype, const virMacAddr *macaddr, const char *filtername, virNWFilterHashTablePtr filterparams); diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index a6cdc87..4cea9cf 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -622,7 +622,6 @@ learnIPAddressThread(void *arg) req->ifname, req->ifindex, req->linkdev, - req->nettype, &req->macaddr, req->filtername, req->filterparams); @@ -661,7 +660,6 @@ learnIPAddressThread(void *arg) * @ifindex: the index of the interface * @linkdev : the name of the link device; currently only used in case of a * macvtap device - * @nettype : the type of interface * @macaddr : the MAC address of the interface * @filtername : the name of the top-level filter to apply to the interface * once its IP address has been detected @@ -681,7 +679,6 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, const char *ifname, int ifindex, const char *linkdev, - enum virDomainNetType nettype, const virMacAddr *macaddr, const char *filtername, virNWFilterHashTablePtr filterparams, @@ -733,7 +730,6 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, } req->ifindex = ifindex; - req->nettype = nettype; virMacAddrSet(&req->macaddr, macaddr); req->driver = driver; req->filterparams = ht; @@ -771,7 +767,6 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver ATTRIBUTE_UNUSED, const char *ifname ATTRIBUTE_UNUSED, int ifindex ATTRIBUTE_UNUSED, const char *linkdev ATTRIBUTE_UNUSED, - enum virDomainNetType nettype ATTRIBUTE_UNUSED, const virMacAddr *macaddr ATTRIBUTE_UNUSED, const char *filtername ATTRIBUTE_UNUSED, virNWFilterHashTablePtr filterparams ATTRIBUTE_UNUSED, diff --git a/src/nwfilter/nwfilter_learnipaddr.h b/src/nwfilter/nwfilter_learnipaddr.h index 0195d10..1cc881a 100644 --- a/src/nwfilter/nwfilter_learnipaddr.h +++ b/src/nwfilter/nwfilter_learnipaddr.h @@ -42,7 +42,6 @@ struct _virNWFilterIPAddrLearnReq { char ifname[IF_NAMESIZE]; int ifindex; char linkdev[IF_NAMESIZE]; - enum virDomainNetType nettype; virMacAddr macaddr; char *filtername; virNWFilterHashTablePtr filterparams; @@ -58,7 +57,6 @@ int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, const char *ifname, int ifindex, const char *linkdev, - enum virDomainNetType nettype, const virMacAddr *macaddr, const char *filtername, virNWFilterHashTablePtr filterparams, diff --git a/src/nwfilter/nwfilter_tech_driver.h b/src/nwfilter/nwfilter_tech_driver.h index 5777757..03588e2 100644 --- a/src/nwfilter/nwfilter_tech_driver.h +++ b/src/nwfilter/nwfilter_tech_driver.h @@ -44,10 +44,7 @@ struct _virNWFilterRuleInst { typedef int (*virNWFilterTechDrvInit)(bool privileged); typedef void (*virNWFilterTechDrvShutdown)(void); -enum virDomainNetType; - -typedef int (*virNWFilterRuleCreateInstance)(enum virDomainNetType nettype, - virNWFilterDefPtr filter, +typedef int (*virNWFilterRuleCreateInstance)(virNWFilterDefPtr filter, virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterHashTablePtr vars, -- 1.9.0

On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
The 'virDomainNetType' is unused in every impl of the virNWFilterRuleCreateInstance driver method. Remove it from the code to avoid the dependancy on the external enum.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
I suppose this compiles without problems. ACK

On 04/08/2014 09:37 AM, Daniel P. Berrange wrote:
The 'virDomainNetType' is unused in every impl of the virNWFilterRuleCreateInstance driver method. Remove it from the code to avoid the dependancy on the external enum.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> ---
+++ b/src/nwfilter/nwfilter_tech_driver.h @@ -44,10 +44,7 @@ struct _virNWFilterRuleInst { typedef int (*virNWFilterTechDrvInit)(bool privileged); typedef void (*virNWFilterTechDrvShutdown)(void);
-enum virDomainNetType; -
Ah, this answers my question from 1/26 :) -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

The virNWFilterHashTable struct contains a virHashTable and then a 'char **names' field which keeps a copy of all the hash keys. Presumably this was intended to record the ordering of the hash keys. No code ever uses this and the ordering is mangled whenever a variable is removed from the hash, because the last element in the list is copied into the middle of the list when shrinking the arra. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/conf/nwfilter_ipaddrmap.c | 2 +- src/conf/nwfilter_params.c | 48 +++++----------------------------- src/conf/nwfilter_params.h | 6 +---- src/nwfilter/nwfilter_gentech_driver.c | 2 +- 4 files changed, 9 insertions(+), 49 deletions(-) diff --git a/src/conf/nwfilter_ipaddrmap.c b/src/conf/nwfilter_ipaddrmap.c index 4bb6775..446f3de 100644 --- a/src/conf/nwfilter_ipaddrmap.c +++ b/src/conf/nwfilter_ipaddrmap.c @@ -60,7 +60,7 @@ virNWFilterIPAddrMapAddIPAddr(const char *ifname, char *addr) val = virNWFilterVarValueCreateSimple(addr); if (!val) goto cleanup; - ret = virNWFilterHashTablePut(ipAddressMap, ifname, val, 1); + ret = virNWFilterHashTablePut(ipAddressMap, ifname, val); goto cleanup; } else { if (virNWFilterVarValueAddValue(val, addr) < 0) diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index 3e85bc1..7655033 100644 --- a/src/conf/nwfilter_params.c +++ b/src/conf/nwfilter_params.c @@ -631,33 +631,14 @@ hashDataFree(void *payload, const void *name ATTRIBUTE_UNUSED) int virNWFilterHashTablePut(virNWFilterHashTablePtr table, const char *name, - virNWFilterVarValuePtr val, - int copyName) + virNWFilterVarValuePtr val) { if (!virHashLookup(table->hashTable, name)) { - char *newName; - if (copyName) { - if (VIR_STRDUP(newName, name) < 0) - return -1; - - if (VIR_APPEND_ELEMENT_COPY(table->names, - table->nNames, newName) < 0) { - VIR_FREE(newName); - return -1; - } - } - - if (virHashAddEntry(table->hashTable, name, val) < 0) { - if (copyName) { - VIR_FREE(newName); - table->nNames--; - } + if (virHashAddEntry(table->hashTable, name, val) < 0) return -1; - } } else { - if (virHashUpdateEntry(table->hashTable, name, val) < 0) { + if (virHashUpdateEntry(table->hashTable, name, val) < 0) return -1; - } } return 0; } @@ -675,14 +656,10 @@ virNWFilterHashTablePut(virNWFilterHashTablePtr table, void virNWFilterHashTableFree(virNWFilterHashTablePtr table) { - size_t i; if (!table) return; virHashFree(table->hashTable); - for (i = 0; i < table->nNames; i++) - VIR_FREE(table->names[i]); - VIR_FREE(table->names); VIR_FREE(table); } @@ -707,20 +684,7 @@ void * virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr ht, const char *entry) { - size_t i; - void *value = virHashSteal(ht->hashTable, entry); - - if (value) { - for (i = 0; i < ht->nNames; i++) { - if (STREQ(ht->names[i], entry)) { - VIR_FREE(ht->names[i]); - ht->names[i] = ht->names[--ht->nNames]; - ht->names[ht->nNames] = NULL; - break; - } - } - } - return value; + return virHashSteal(ht->hashTable, entry); } @@ -745,7 +709,7 @@ addToTable(void *payload, const void *name, void *data) return; } - if (virNWFilterHashTablePut(atts->target, (const char *)name, val, 1) < 0){ + if (virNWFilterHashTablePut(atts->target, (const char *)name, val) < 0){ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not put variable '%s' into hashmap"), (const char *)name); @@ -850,7 +814,7 @@ virNWFilterParseParamAttributes(xmlNodePtr cur) value = virNWFilterParseVarValue(val); if (!value) goto skip_entry; - if (virNWFilterHashTablePut(table, nam, value, 1) < 0) + if (virNWFilterHashTablePut(table, nam, value) < 0) goto err_exit; } value = NULL; diff --git a/src/conf/nwfilter_params.h b/src/conf/nwfilter_params.h index 5e9777b..f9efc42 100644 --- a/src/conf/nwfilter_params.h +++ b/src/conf/nwfilter_params.h @@ -66,9 +66,6 @@ typedef struct _virNWFilterHashTable virNWFilterHashTable; typedef virNWFilterHashTable *virNWFilterHashTablePtr; struct _virNWFilterHashTable { virHashTablePtr hashTable; - - size_t nNames; - char **names; }; @@ -81,8 +78,7 @@ virNWFilterHashTablePtr virNWFilterHashTableCreate(int n); void virNWFilterHashTableFree(virNWFilterHashTablePtr table); int virNWFilterHashTablePut(virNWFilterHashTablePtr table, const char *name, - virNWFilterVarValuePtr val, - int freeName); + virNWFilterVarValuePtr val); void *virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table, const char *name); int virNWFilterHashTablePutAll(virNWFilterHashTablePtr src, diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 82ff628..d482f43 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -512,7 +512,7 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, varAccess = virBufferContentAndReset(&buf); virNWFilterHashTablePut(missing_vars, varAccess, - val, 1); + val); VIR_FREE(varAccess); } } -- 1.9.0

On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
The virNWFilterHashTable struct contains a virHashTable and then a 'char **names' field which keeps a copy of all the hash keys. Presumably this was intended to record the ordering of the hash keys. No code ever uses this and the ordering is mangled whenever a variable is removed from the hash, because the last element in the list is copied into the middle of the list when shrinking the arra.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
ACK

On 04/08/2014 09:37 AM, Daniel P. Berrange wrote:
The virNWFilterHashTable struct contains a virHashTable and then a 'char **names' field which keeps a copy of all the hash keys. Presumably this was intended to record the ordering of the hash keys. No code ever uses this and the ordering is mangled whenever a variable is removed from the hash, because the last element in the list is copied into the middle of the list when shrinking the arra.
s/arra/array/
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> ---
-- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

The 'removeRules' callback in the nwfilter tech driver is never invoked, so can be deleted. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 40 ------------------------------- src/nwfilter/nwfilter_tech_driver.h | 5 ---- 2 files changed, 45 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 4365c1f..1dabe52 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -4046,45 +4046,6 @@ ebiptablesTearOldRules(const char *ifname) /** - * ebiptablesRemoveRules: - * @ifname : the name of the interface to which the rules apply - * @nRuleInstance : the number of given rules - * @_inst : array of rule instantiation data - * - * Remove all rules one after the other - * - * Return 0 on success, -1 if execution of one or more cleanup - * commands failed. - */ -static int -ebiptablesRemoveRules(const char *ifname ATTRIBUTE_UNUSED, - int nruleInstances, - void **_inst) -{ - int rc = -1; - size_t i; - virBuffer buf = VIR_BUFFER_INITIALIZER; - ebiptablesRuleInstPtr *inst = (ebiptablesRuleInstPtr *)_inst; - - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); - - for (i = 0; i < nruleInstances; i++) - ebiptablesInstCommand(&buf, - inst[i]->commandTemplate, - 'D', -1, - false); - - if (ebiptablesExecCLI(&buf, true, NULL) < 0) - goto cleanup; - - rc = 0; - - cleanup: - return rc; -} - - -/** * ebiptablesAllTeardown: * @ifname : the name of the interface to which the rules apply * @@ -4143,7 +4104,6 @@ virNWFilterTechDriver ebiptables_driver = { .tearNewRules = ebiptablesTearNewRules, .tearOldRules = ebiptablesTearOldRules, .allTeardown = ebiptablesAllTeardown, - .removeRules = ebiptablesRemoveRules, .freeRuleInstance = ebiptablesFreeRuleInstance, .displayRuleInstance = ebiptablesDisplayRuleInstance, diff --git a/src/nwfilter/nwfilter_tech_driver.h b/src/nwfilter/nwfilter_tech_driver.h index 03588e2..d1c85b4 100644 --- a/src/nwfilter/nwfilter_tech_driver.h +++ b/src/nwfilter/nwfilter_tech_driver.h @@ -58,10 +58,6 @@ typedef int (*virNWFilterRuleTeardownNewRules)(const char *ifname); typedef int (*virNWFilterRuleTeardownOldRules)(const char *ifname); -typedef int (*virNWFilterRuleRemoveRules)(const char *ifname, - int nruleInstances, - void **_inst); - typedef int (*virNWFilterRuleAllTeardown)(const char *ifname); typedef int (*virNWFilterRuleFreeInstanceData)(void * _inst); @@ -97,7 +93,6 @@ struct _virNWFilterTechDriver { virNWFilterRuleApplyNewRules applyNewRules; virNWFilterRuleTeardownNewRules tearNewRules; virNWFilterRuleTeardownOldRules tearOldRules; - virNWFilterRuleRemoveRules removeRules; virNWFilterRuleAllTeardown allTeardown; virNWFilterRuleFreeInstanceData freeRuleInstance; virNWFilterRuleDisplayInstanceData displayRuleInstance; -- 1.9.0

On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
The 'removeRules' callback in the nwfilter tech driver is never invoked, so can be deleted.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> ACK

The 'displayRuleInstance' callback in the nwfilter tech driver is never invoked, so can be deleted. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 12 ------------ src/nwfilter/nwfilter_tech_driver.h | 3 --- 2 files changed, 15 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 1dabe52..0885bb1 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -2781,17 +2781,6 @@ ebiptablesFreeRuleInstance(void *_inst) } -static int -ebiptablesDisplayRuleInstance(void *_inst) -{ - ebiptablesRuleInstPtr inst = (ebiptablesRuleInstPtr)_inst; - VIR_INFO("Command Template: '%s', Needed protocol: '%s'", - inst->commandTemplate, - inst->neededProtocolChain); - return 0; -} - - /** * ebiptablesExecCLI: * @buf: pointer to virBuffer containing the string with the commands to @@ -4105,7 +4094,6 @@ virNWFilterTechDriver ebiptables_driver = { .tearOldRules = ebiptablesTearOldRules, .allTeardown = ebiptablesAllTeardown, .freeRuleInstance = ebiptablesFreeRuleInstance, - .displayRuleInstance = ebiptablesDisplayRuleInstance, .canApplyBasicRules = ebiptablesCanApplyBasicRules, .applyBasicRules = ebtablesApplyBasicRules, diff --git a/src/nwfilter/nwfilter_tech_driver.h b/src/nwfilter/nwfilter_tech_driver.h index d1c85b4..ed09a67 100644 --- a/src/nwfilter/nwfilter_tech_driver.h +++ b/src/nwfilter/nwfilter_tech_driver.h @@ -62,8 +62,6 @@ typedef int (*virNWFilterRuleAllTeardown)(const char *ifname); typedef int (*virNWFilterRuleFreeInstanceData)(void * _inst); -typedef int (*virNWFilterRuleDisplayInstanceData)(void *_inst); - typedef int (*virNWFilterCanApplyBasicRules)(void); typedef int (*virNWFilterApplyBasicRules)(const char *ifname, @@ -95,7 +93,6 @@ struct _virNWFilterTechDriver { virNWFilterRuleTeardownOldRules tearOldRules; virNWFilterRuleAllTeardown allTeardown; virNWFilterRuleFreeInstanceData freeRuleInstance; - virNWFilterRuleDisplayInstanceData displayRuleInstance; virNWFilterCanApplyBasicRules canApplyBasicRules; virNWFilterApplyBasicRules applyBasicRules; -- 1.9.0

On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
The 'displayRuleInstance' callback in the nwfilter tech driver is never invoked, so can be deleted.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
ACK

Add virNWFilterRuleIsProtocol{Ethernet,IPv4,IPv6} helper methods to avoid having to write a giant switch statements with many cases. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/conf/nwfilter_conf.c | 27 ++++++++++++++ src/conf/nwfilter_conf.h | 14 ++++++++ src/libvirt_private.syms | 3 ++ src/nwfilter/nwfilter_ebiptables_driver.c | 58 +++++++------------------------ 4 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index f5a75e4..968e045 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -3484,3 +3484,30 @@ void virNWFilterObjUnlock(virNWFilterObjPtr obj) { virMutexUnlock(&obj->lock); } + + +bool virNWFilterRuleIsProtocolIPv4(virNWFilterRuleDefPtr rule) +{ + if (rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_TCP && + rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_ALL) + return true; + return false; +} + + +bool virNWFilterRuleIsProtocolIPv6(virNWFilterRuleDefPtr rule) +{ + if (rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6 && + rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_ALLoIPV6) + return true; + return false; +} + + +bool virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule) +{ + if (rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_NONE && + rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_IPV6) + return true; + return false; +} diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index aded4de..9f9deab 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -373,7 +373,13 @@ enum virNWFilterChainPolicyType { VIR_NWFILTER_CHAIN_POLICY_LAST, }; + +/* + * If adding protocols be sure to update the + * virNWFilterRuleIsProtocolXXXX function impls + */ enum virNWFilterRuleProtocolType { + /* Ethernet layer protocols */ VIR_NWFILTER_RULE_PROTOCOL_NONE = 0, VIR_NWFILTER_RULE_PROTOCOL_MAC, VIR_NWFILTER_RULE_PROTOCOL_VLAN, @@ -382,6 +388,8 @@ enum virNWFilterRuleProtocolType { VIR_NWFILTER_RULE_PROTOCOL_RARP, VIR_NWFILTER_RULE_PROTOCOL_IP, VIR_NWFILTER_RULE_PROTOCOL_IPV6, + + /* IPv4 layer protocols */ VIR_NWFILTER_RULE_PROTOCOL_TCP, VIR_NWFILTER_RULE_PROTOCOL_ICMP, VIR_NWFILTER_RULE_PROTOCOL_IGMP, @@ -391,6 +399,8 @@ enum virNWFilterRuleProtocolType { VIR_NWFILTER_RULE_PROTOCOL_AH, VIR_NWFILTER_RULE_PROTOCOL_SCTP, VIR_NWFILTER_RULE_PROTOCOL_ALL, + + /* IPv6 layer protocols */ VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6, VIR_NWFILTER_RULE_PROTOCOL_ICMPV6, VIR_NWFILTER_RULE_PROTOCOL_UDPoIPV6, @@ -667,6 +677,10 @@ void virNWFilterPrintTCPFlags(virBufferPtr buf, uint8_t mask, char sep, uint8_t flags); +bool virNWFilterRuleIsProtocolIPv4(virNWFilterRuleDefPtr rule); +bool virNWFilterRuleIsProtocolIPv6(virNWFilterRuleDefPtr rule); +bool virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule); + VIR_ENUM_DECL(virNWFilterRuleAction); VIR_ENUM_DECL(virNWFilterRuleDirection); VIR_ENUM_DECL(virNWFilterRuleProtocol); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 55aa586..0c2cf75 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -597,6 +597,9 @@ virNWFilterReadLockFilterUpdates; virNWFilterRegisterCallbackDriver; virNWFilterRuleActionTypeToString; virNWFilterRuleDirectionTypeToString; +virNWFilterRuleIsProtocolEthernet; +virNWFilterRuleIsProtocolIPv4; +virNWFilterRuleIsProtocolIPv6; virNWFilterRuleProtocolTypeToString; virNWFilterTestUnassignDef; virNWFilterUnlockFilterUpdates; diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 0885bb1..410f0e1 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -2656,18 +2656,8 @@ ebiptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, virNWFilterRuleInstPtr res) { int rc = 0; - bool isIPv6; - - switch (rule->prtclType) { - case VIR_NWFILTER_RULE_PROTOCOL_IP: - case VIR_NWFILTER_RULE_PROTOCOL_MAC: - case VIR_NWFILTER_RULE_PROTOCOL_VLAN: - case VIR_NWFILTER_RULE_PROTOCOL_STP: - case VIR_NWFILTER_RULE_PROTOCOL_ARP: - case VIR_NWFILTER_RULE_PROTOCOL_RARP: - case VIR_NWFILTER_RULE_PROTOCOL_NONE: - case VIR_NWFILTER_RULE_PROTOCOL_IPV6: + if (virNWFilterRuleIsProtocolEthernet(rule)) { if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_IN_TEMP, @@ -2691,48 +2681,24 @@ ebiptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, res, false); } - break; - - case VIR_NWFILTER_RULE_PROTOCOL_TCP: - case VIR_NWFILTER_RULE_PROTOCOL_UDP: - case VIR_NWFILTER_RULE_PROTOCOL_UDPLITE: - case VIR_NWFILTER_RULE_PROTOCOL_ESP: - case VIR_NWFILTER_RULE_PROTOCOL_AH: - case VIR_NWFILTER_RULE_PROTOCOL_SCTP: - case VIR_NWFILTER_RULE_PROTOCOL_ICMP: - case VIR_NWFILTER_RULE_PROTOCOL_IGMP: - case VIR_NWFILTER_RULE_PROTOCOL_ALL: - isIPv6 = false; - rc = iptablesCreateRuleInstance(nwfilter, - rule, - ifname, - vars, - res, - isIPv6); - break; + } else { + bool isIPv6; + if (virNWFilterRuleIsProtocolIPv6(rule)) { + isIPv6 = true; + } else if (virNWFilterRuleIsProtocolIPv4(rule)) { + isIPv6 = false; + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("unexpected protocol type")); + return -1; + } - case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6: - case VIR_NWFILTER_RULE_PROTOCOL_UDPoIPV6: - case VIR_NWFILTER_RULE_PROTOCOL_UDPLITEoIPV6: - case VIR_NWFILTER_RULE_PROTOCOL_ESPoIPV6: - case VIR_NWFILTER_RULE_PROTOCOL_AHoIPV6: - case VIR_NWFILTER_RULE_PROTOCOL_SCTPoIPV6: - case VIR_NWFILTER_RULE_PROTOCOL_ICMPV6: - case VIR_NWFILTER_RULE_PROTOCOL_ALLoIPV6: - isIPv6 = true; rc = iptablesCreateRuleInstance(nwfilter, rule, ifname, vars, res, isIPv6); - break; - - case VIR_NWFILTER_RULE_PROTOCOL_LAST: - virReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("illegal protocol type")); - rc = -1; - break; } return rc; -- 1.9.0

On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
Add virNWFilterRuleIsProtocol{Ethernet,IPv4,IPv6} helper methods to avoid having to write a giant switch statements with many cases.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
ACK

On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
+bool virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule) +{ + if (rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_NONE && + rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_IPV6) + return true; + return false; +}
I get a compilation error here. For me this code here works: if (/* rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_NONE && */ rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_IPV6) return true; Stefan

On Tue, Apr 15, 2014 at 10:06:22AM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
+bool virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule) +{ + if (rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_NONE && + rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_IPV6) + return true; + return false; +}
I get a compilation error here. For me this code here works:
if (/* rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_NONE && */ rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_IPV6) return true;
What is the actual error you get ? That constant exists in the header files $ git grep RULE_PROTOCOL_NONE src/conf/nwfilter_conf.h src/conf/nwfilter_conf.h: VIR_NWFILTER_RULE_PROTOCOL_NONE = 0, Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 04/15/2014 10:30 AM, Daniel P. Berrange wrote:
On Tue, Apr 15, 2014 at 10:06:22AM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
+bool virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule) +{ + if (rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_NONE && + rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_IPV6) + return true; + return false; +} I get a compilation error here. For me this code here works:
if (/* rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_NONE && */ rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_IPV6) return true; What is the actual error you get ?
That constant exists in the header files
$ git grep RULE_PROTOCOL_NONE src/conf/nwfilter_conf.h src/conf/nwfilter_conf.h: VIR_NWFILTER_RULE_PROTOCOL_NONE = 0,
Related to evaluation of >= 0 on unsigned int always being true. Stefan

On Tue, Apr 15, 2014 at 12:05:46PM -0400, Stefan Berger wrote:
On 04/15/2014 10:30 AM, Daniel P. Berrange wrote:
On Tue, Apr 15, 2014 at 10:06:22AM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
+bool virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule) +{ + if (rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_NONE && + rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_IPV6) + return true; + return false; +} I get a compilation error here. For me this code here works:
if (/* rule->prtclType >= VIR_NWFILTER_RULE_PROTOCOL_NONE && */ rule->prtclType <= VIR_NWFILTER_RULE_PROTOCOL_IPV6) return true; What is the actual error you get ?
That constant exists in the header files
$ git grep RULE_PROTOCOL_NONE src/conf/nwfilter_conf.h src/conf/nwfilter_conf.h: VIR_NWFILTER_RULE_PROTOCOL_NONE = 0,
Related to evaluation of >= 0 on unsigned int always being true.
Ah, ok, must be a gcc version warning difference. That makes sense to change Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Later refactoring will change use of the virNWFilterRuleInstPtr struct. Prepare for this by pushing use of the virNWFilterRuleInstPtr parameter out of the ebtablesCreateRuleInstance and iptablesCreateRuleInstance methods. Instead they simply string(s) with the constructed rule data. The ebiptablesCreateRuleInstance method will make use of the virNWFilterRuleInstPtr struct instead. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 209 ++++++++++++++++++------------ 1 file changed, 125 insertions(+), 84 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 410f0e1..5c876cc 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -1277,17 +1277,17 @@ iptablesEnforceDirection(bool directionIn, /* * _iptablesCreateRuleInstance: * @chainPrefix : The prefix to put in front of the name of the chain - * @nwfilter : The filter * @rule: The rule of the filter to convert * @ifname : The name of the interface to apply the rule to * @vars : A map containing the variables to resolve - * @res : The data structure to store the result(s) into * @match : optional string for state match * @accept_target : where to jump to on accepted traffic, i.e., "RETURN" * "ACCEPT" * @isIPv6 : Whether this is an IPv6 rule * @maySkipICMP : whether this rule may under certain circumstances skip * the ICMP rule from being created + * @templates: pointer to array to store rule template + * @ntemplates: pointer to storage rule template count * * Convert a single rule into its representation for later instantiation * @@ -1297,15 +1297,15 @@ iptablesEnforceDirection(bool directionIn, static int _iptablesCreateRuleInstance(bool directionIn, const char *chainPrefix, - virNWFilterDefPtr nwfilter, virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, - virNWFilterRuleInstPtr res, const char *match, bool defMatch, const char *accept_target, bool isIPv6, - bool maySkipICMP) + bool maySkipICMP, + char ***templates, + size_t *ntemplates) { char chain[MAX_CHAINNAME_LENGTH]; char number[MAX(INT_BUFSIZE_BOUND(uint32_t), @@ -1322,6 +1322,7 @@ _iptablesCreateRuleInstance(bool directionIn, bool skipRule = false; bool skipMatch = false; bool hasICMPType = false; + char *template; if (!iptables_cmd) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -1732,14 +1733,13 @@ _iptablesCreateRuleInstance(bool directionIn, final = &buf; - return ebiptablesAddRuleInst(res, - virBufferContentAndReset(final), - nwfilter->chainsuffix, - nwfilter->chainPriority, - '\0', - rule->priority, - (isIPv6) ? RT_IP6TABLES : RT_IPTABLES); + template = virBufferContentAndReset(final); + if (VIR_APPEND_ELEMENT(*templates, *ntemplates, template) < 0) { + VIR_FREE(template); + return -1; + } + return 0; err_exit: virBufferFreeAndReset(&buf); @@ -1775,12 +1775,12 @@ printStateMatchFlags(int32_t flags, char **bufptr) } static int -iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter, - virNWFilterRuleDefPtr rule, +iptablesCreateRuleInstanceStateCtrl(virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, - virNWFilterRuleInstPtr res, - bool isIPv6) + bool isIPv6, + char ***templates, + size_t *ntemplates) { int rc; bool directionIn = false; @@ -1816,15 +1816,15 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter, if (create) { rc = _iptablesCreateRuleInstance(directionIn, chainPrefix, - nwfilter, rule, ifname, vars, - res, matchState, false, "RETURN", isIPv6, - maySkipICMP); + maySkipICMP, + templates, + ntemplates); VIR_FREE(matchState); if (rc < 0) @@ -1848,15 +1848,15 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter, if (create) { rc = _iptablesCreateRuleInstance(!directionIn, chainPrefix, - nwfilter, rule, ifname, vars, - res, matchState, false, "ACCEPT", isIPv6, - maySkipICMP); + maySkipICMP, + templates, + ntemplates); VIR_FREE(matchState); @@ -1883,15 +1883,15 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter, chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP; rc = _iptablesCreateRuleInstance(directionIn, chainPrefix, - nwfilter, rule, ifname, vars, - res, matchState, false, "RETURN", isIPv6, - maySkipICMP); + maySkipICMP, + templates, + ntemplates); VIR_FREE(matchState); } @@ -1900,12 +1900,12 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter, static int -iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, - virNWFilterRuleDefPtr rule, +iptablesCreateRuleInstance(virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, - virNWFilterRuleInstPtr res, - bool isIPv6) + bool isIPv6, + char ***templates, + size_t *ntemplates) { int rc; bool directionIn = false; @@ -1916,12 +1916,12 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, if (!(rule->flags & RULE_FLAG_NO_STATEMATCH) && (rule->flags & IPTABLES_STATE_FLAGS)) { - return iptablesCreateRuleInstanceStateCtrl(nwfilter, - rule, + return iptablesCreateRuleInstanceStateCtrl(rule, ifname, vars, - res, - isIPv6); + isIPv6, + templates, + ntemplates); } if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) || @@ -1947,15 +1947,15 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP; rc = _iptablesCreateRuleInstance(directionIn, chainPrefix, - nwfilter, rule, ifname, vars, - res, matchState, true, "RETURN", isIPv6, - maySkipICMP); + maySkipICMP, + templates, + ntemplates); if (rc < 0) return rc; @@ -1969,15 +1969,15 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP; rc = _iptablesCreateRuleInstance(!directionIn, chainPrefix, - nwfilter, rule, ifname, vars, - res, matchState, true, "ACCEPT", isIPv6, - maySkipICMP); + maySkipICMP, + templates, + ntemplates); if (rc < 0) return rc; @@ -1991,15 +1991,15 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP; rc = _iptablesCreateRuleInstance(directionIn, chainPrefix, - nwfilter, rule, ifname, vars, - res, matchState, true, "RETURN", isIPv6, - maySkipICMP); + maySkipICMP, + templates, + ntemplates); return rc; } @@ -2010,12 +2010,13 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, /* * ebtablesCreateRuleInstance: * @chainPrefix : The prefix to put in front of the name of the chain - * @nwfilter : The filter + * @chainSuffix: The suffix to put on the end of the name of the chain * @rule: The rule of the filter to convert * @ifname : The name of the interface to apply the rule to * @vars : A map containing the variables to resolve - * @res : The data structure to store the result(s) into * @reverse : Whether to reverse src and dst attributes + * @templates: pointer to array to store rule template + * @ntemplates: pointer to storage rule template count * * Convert a single rule into its representation for later instantiation * @@ -2024,12 +2025,12 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, */ static int ebtablesCreateRuleInstance(char chainPrefix, - virNWFilterDefPtr nwfilter, + const char *chainSuffix, virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, - virNWFilterRuleInstPtr res, - bool reverse) + bool reverse, + char **template) { char macaddr[VIR_MAC_STRING_BUFLEN], ipaddr[INET_ADDRSTRLEN], @@ -2043,6 +2044,8 @@ ebtablesCreateRuleInstance(char chainPrefix, const char *target; bool hasMask = false; + *template = NULL; + if (!ebtables_cmd_path) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot create rule since ebtables tool is " @@ -2050,13 +2053,13 @@ ebtablesCreateRuleInstance(char chainPrefix, goto err_exit; } - if (STREQ(nwfilter->chainsuffix, + if (STREQ(chainSuffix, virNWFilterChainSuffixTypeToString( VIR_NWFILTER_CHAINSUFFIX_ROOT))) PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); else PRINT_CHAIN(chain, chainPrefix, ifname, - nwfilter->chainsuffix); + chainSuffix); switch (rule->prtclType) { @@ -2620,13 +2623,8 @@ ebtablesCreateRuleInstance(char chainPrefix, return -1; } - return ebiptablesAddRuleInst(res, - virBufferContentAndReset(&buf), - nwfilter->chainsuffix, - nwfilter->chainPriority, - chainPrefix, - rule->priority, - RT_EBTABLES); + *template = virBufferContentAndReset(&buf); + return 0; err_exit: virBufferFreeAndReset(&buf); @@ -2637,7 +2635,8 @@ ebtablesCreateRuleInstance(char chainPrefix, /* * ebiptablesCreateRuleInstance: - * @nwfilter : The filter + * @chainPriority : The priority of the chain + * @chainSuffix: The suffix to put on the end of the name of the chain * @rule: The rule of the filter to convert * @ifname : The name of the interface to apply the rule to * @vars : A map containing the variables to resolve @@ -2649,40 +2648,66 @@ ebtablesCreateRuleInstance(char chainPrefix, * pointed to by res, -1 otherwise */ static int -ebiptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, +ebiptablesCreateRuleInstance(virNWFilterChainPriority chainPriority, + const char *chainSuffix, virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, virNWFilterRuleInstPtr res) { - int rc = 0; - if (virNWFilterRuleIsProtocolEthernet(rule)) { if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { - rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_IN_TEMP, - nwfilter, - rule, - ifname, - vars, - res, - rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT); - if (rc < 0) - return rc; + char *template; + if (ebtablesCreateRuleInstance(CHAINPREFIX_HOST_IN_TEMP, + chainSuffix, + rule, + ifname, + vars, + rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT, + &template) < 0) + return -1; + + if (ebiptablesAddRuleInst(res, + template, + chainSuffix, + chainPriority, + CHAINPREFIX_HOST_IN_TEMP, + rule->priority, + RT_EBTABLES) < 0) { + VIR_FREE(template); + return -1; + } } if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN || rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { - rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_OUT_TEMP, - nwfilter, - rule, - ifname, - vars, - res, - false); + char *template; + if (ebtablesCreateRuleInstance(CHAINPREFIX_HOST_OUT_TEMP, + chainSuffix, + rule, + ifname, + vars, + false, + &template) < 0) + return -1; + + if (ebiptablesAddRuleInst(res, + template, + chainSuffix, + chainPriority, + CHAINPREFIX_HOST_OUT_TEMP, + rule->priority, + RT_EBTABLES) < 0) { + VIR_FREE(template); + return -1; + } } } else { bool isIPv6; + char **templates = NULL; + size_t ntemplates = 0; + size_t i, j; if (virNWFilterRuleIsProtocolIPv6(rule)) { isIPv6 = true; } else if (virNWFilterRuleIsProtocolIPv4(rule)) { @@ -2693,15 +2718,30 @@ ebiptablesCreateRuleInstance(virNWFilterDefPtr nwfilter, return -1; } - rc = iptablesCreateRuleInstance(nwfilter, - rule, - ifname, - vars, - res, - isIPv6); + if (iptablesCreateRuleInstance(rule, + ifname, + vars, + isIPv6, + &templates, + &ntemplates) < 0) + return -1; + + for (i = 0; i < ntemplates; i++) { + if (ebiptablesAddRuleInst(res, + templates[i], + chainSuffix, + chainPriority, + '\0', + rule->priority, + (isIPv6) ? RT_IP6TABLES : RT_IPTABLES) < 0) { + for (j = i; j < ntemplates; j++) + VIR_FREE(templates[j]); + return -1; + } + } } - return rc; + return 0; } static int @@ -2724,7 +2764,8 @@ ebiptablesCreateRuleInstanceIterate(virNWFilterDefPtr nwfilter, return -1; do { - rc = ebiptablesCreateRuleInstance(nwfilter, + rc = ebiptablesCreateRuleInstance(nwfilter->chainPriority, + nwfilter->chainsuffix, rule, ifname, tmp, -- 1.9.0

On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
Later refactoring will change use of the virNWFilterRuleInstPtr struct. Prepare for this by pushing use of the virNWFilterRuleInstPtr parameter out of the ebtablesCreateRuleInstance and iptablesCreateRuleInstance methods. Instead they simply string(s) with the constructed rule data. The ebiptablesCreateRuleInstance method will make use of the virNWFilterRuleInstPtr struct instead.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
ACK

The current nwfilter tech driver API has a 'createRuleInstance' method which populates virNWFilterRuleInstPtr with a command line string containing variable placeholders. The 'applyNewRules' method then expands the variables and executes the commands. This split of responsibility won't work when switching to the virFirewallPtr APIs, since we can't just build up command line strings. This patch this merges the functionality of 'createRuleInstance' into the applyNewRules method. The virNWFilterRuleInstPtr struct is changed from holding an array of opaque pointers, into holding generic metadata about the rules to be processed. In essence this is the result of taking a linked set of virNWFilterDefPtr's and flattening the tree to get a list of virNWFilterRuleDefPtr's. At the same time we must keep track of any nested virNWFilterObjPtr instances, so that the locks are held for the duration of the 'applyNewRules' method. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 371 +++++++++++++++------------- src/nwfilter/nwfilter_gentech_driver.c | 398 ++++++++++++++---------------- src/nwfilter/nwfilter_tech_driver.h | 22 +- 3 files changed, 390 insertions(+), 401 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 5c876cc..f93158f 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -477,46 +477,6 @@ printCommentVar(virBufferPtr dest, const char *buf) } -static void -ebiptablesRuleInstFree(ebiptablesRuleInstPtr inst) -{ - if (!inst) - return; - - VIR_FREE(inst->commandTemplate); - VIR_FREE(inst); -} - - -static int -ebiptablesAddRuleInst(virNWFilterRuleInstPtr res, - char *commandTemplate, - const char *neededChain, - virNWFilterChainPriority chainPriority, - char chainprefix, - virNWFilterRulePriority priority, - enum RuleType ruleType) -{ - ebiptablesRuleInstPtr inst; - - if (VIR_ALLOC(inst) < 0) - return -1; - - inst->commandTemplate = commandTemplate; - inst->neededProtocolChain = neededChain; - inst->chainPriority = chainPriority; - inst->chainprefix = chainprefix; - inst->priority = priority; - inst->ruleType = ruleType; - - if (VIR_APPEND_ELEMENT(res->data, res->ndata, inst) < 0) { - VIR_FREE(inst); - return -1; - } - return 0; -} - - static int ebtablesHandleEthHdr(virBufferPtr buf, virNWFilterVarCombIterPtr vars, @@ -2648,13 +2608,18 @@ ebtablesCreateRuleInstance(char chainPrefix, * pointed to by res, -1 otherwise */ static int -ebiptablesCreateRuleInstance(virNWFilterChainPriority chainPriority, - const char *chainSuffix, +ebiptablesCreateRuleInstance(const char *chainSuffix, virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, - virNWFilterRuleInstPtr res) + char ***templates, + size_t *ntemplates) { + size_t i; + + *templates = NULL; + *ntemplates = 0; + if (virNWFilterRuleIsProtocolEthernet(rule)) { if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { @@ -2666,17 +2631,11 @@ ebiptablesCreateRuleInstance(virNWFilterChainPriority chainPriority, vars, rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT, &template) < 0) - return -1; + goto error; - if (ebiptablesAddRuleInst(res, - template, - chainSuffix, - chainPriority, - CHAINPREFIX_HOST_IN_TEMP, - rule->priority, - RT_EBTABLES) < 0) { + if (VIR_APPEND_ELEMENT(*templates, *ntemplates, template) < 0) { VIR_FREE(template); - return -1; + goto error; } } @@ -2690,24 +2649,15 @@ ebiptablesCreateRuleInstance(virNWFilterChainPriority chainPriority, vars, false, &template) < 0) - return -1; + goto error; - if (ebiptablesAddRuleInst(res, - template, - chainSuffix, - chainPriority, - CHAINPREFIX_HOST_OUT_TEMP, - rule->priority, - RT_EBTABLES) < 0) { + if (VIR_APPEND_ELEMENT(*templates, *ntemplates, template) < 0) { VIR_FREE(template); - return -1; + goto error; } } } else { bool isIPv6; - char **templates = NULL; - size_t ntemplates = 0; - size_t i, j; if (virNWFilterRuleIsProtocolIPv6(rule)) { isIPv6 = true; } else if (virNWFilterRuleIsProtocolIPv4(rule)) { @@ -2715,76 +2665,27 @@ ebiptablesCreateRuleInstance(virNWFilterChainPriority chainPriority, } else { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("unexpected protocol type")); - return -1; + goto error; } if (iptablesCreateRuleInstance(rule, ifname, vars, isIPv6, - &templates, - &ntemplates) < 0) - return -1; - - for (i = 0; i < ntemplates; i++) { - if (ebiptablesAddRuleInst(res, - templates[i], - chainSuffix, - chainPriority, - '\0', - rule->priority, - (isIPv6) ? RT_IP6TABLES : RT_IPTABLES) < 0) { - for (j = i; j < ntemplates; j++) - VIR_FREE(templates[j]); - return -1; - } - } + templates, + ntemplates) < 0) + goto error; } return 0; -} -static int -ebiptablesCreateRuleInstanceIterate(virNWFilterDefPtr nwfilter, - virNWFilterRuleDefPtr rule, - const char *ifname, - virNWFilterHashTablePtr vars, - virNWFilterRuleInstPtr res) -{ - int rc = 0; - virNWFilterVarCombIterPtr vciter, tmp; - - /* rule->vars holds all the variables names that this rule will access. - * iterate over all combinations of the variables' values and instantiate - * the filtering rule with each combination. - */ - tmp = vciter = virNWFilterVarCombIterCreate(vars, - rule->varAccess, rule->nVarAccess); - if (!vciter) - return -1; - - do { - rc = ebiptablesCreateRuleInstance(nwfilter->chainPriority, - nwfilter->chainsuffix, - rule, - ifname, - tmp, - res); - if (rc < 0) - break; - tmp = virNWFilterVarCombIterNext(tmp); - } while (tmp != NULL); - - virNWFilterVarCombIterFree(vciter); - - return rc; -} - -static int -ebiptablesFreeRuleInstance(void *_inst) -{ - ebiptablesRuleInstFree((ebiptablesRuleInstPtr)_inst); - return 0; + error: + for (i = 0; i < *ntemplates; i++) + VIR_FREE((*templates)[i]); + VIR_FREE(*templates); + *templates = NULL; + *ntemplates = 0; + return -1; } @@ -3562,12 +3463,40 @@ ebiptablesRuleOrderSort(const void *a, const void *b) return insta->priority - instb->priority; } + +static int +virNWFilterRuleInstSort(const void *a, const void *b) +{ + const virNWFilterRuleInst *insta = a; + const virNWFilterRuleInst *instb = b; + const char *root = virNWFilterChainSuffixTypeToString( + VIR_NWFILTER_CHAINSUFFIX_ROOT); + bool root_a = STREQ(insta->chainSuffix, root); + bool root_b = STREQ(instb->chainSuffix, root); + + /* ensure root chain commands appear before all others since + we will need them to create the child chains */ + if (root_a) { + if (root_b) { + goto normal; + } + return -1; /* a before b */ + } + if (root_b) { + return 1; /* b before a */ + } + normal: + /* priorities are limited to range [-1000, 1000] */ + return insta->priority - instb->priority; +} + + static int -ebiptablesRuleOrderSortPtr(const void *a, const void *b) +virNWFilterRuleInstSortPtr(const void *a, const void *b) { - ebiptablesRuleInst * const *insta = a; - ebiptablesRuleInst * const *instb = b; - return ebiptablesRuleOrderSort(*insta, *instb); + virNWFilterRuleInst * const *insta = a; + virNWFilterRuleInst * const *instb = b; + return virNWFilterRuleInstSort(*insta, *instb); } static int @@ -3673,13 +3602,106 @@ ebtablesCreateTmpRootAndSubChains(virBufferPtr buf, return rc; } + +static int +iptablesRuleInstCommand(virBufferPtr buf, + const char *ifname, + virNWFilterRuleInstPtr rule, + char cmd, int pos) +{ + virNWFilterVarCombIterPtr vciter, tmp; + char **templates = NULL; + size_t ntemplates = 0; + size_t i; + int ret = -1; + + /* rule->vars holds all the variables names that this rule will access. + * iterate over all combinations of the variables' values and instantiate + * the filtering rule with each combination. + */ + tmp = vciter = virNWFilterVarCombIterCreate(rule->vars, + rule->def->varAccess, + rule->def->nVarAccess); + if (!vciter) + return -1; + + do { + if (ebiptablesCreateRuleInstance(rule->chainSuffix, + rule->def, + ifname, + tmp, + &templates, + &ntemplates) < 0) + goto cleanup; + tmp = virNWFilterVarCombIterNext(tmp); + } while (tmp != NULL); + + for (i = 0; i < ntemplates; i++) + iptablesInstCommand(buf, templates[i], cmd, pos); + + ret = 0; + cleanup: + for (i = 0; i < ntemplates; i++) + VIR_FREE(templates[i]); + VIR_FREE(templates); + virNWFilterVarCombIterFree(vciter); + return ret; +} + + +static int +ebtablesRuleInstCommand(virBufferPtr buf, + const char *ifname, + virNWFilterRuleInstPtr rule, + char cmd, int pos, + bool stopOnError) +{ + virNWFilterVarCombIterPtr vciter, tmp; + char **templates = NULL; + size_t ntemplates = 0; + size_t i; + int ret = -1; + + /* rule->vars holds all the variables names that this rule will access. + * iterate over all combinations of the variables' values and instantiate + * the filtering rule with each combination. + */ + tmp = vciter = virNWFilterVarCombIterCreate(rule->vars, + rule->def->varAccess, + rule->def->nVarAccess); + if (!vciter) + return -1; + + do { + if (ebiptablesCreateRuleInstance(rule->chainSuffix, + rule->def, + ifname, + tmp, + &templates, + &ntemplates) < 0) + goto cleanup; + tmp = virNWFilterVarCombIterNext(tmp); + } while (tmp != NULL); + + for (i = 0; i < ntemplates; i++) + ebiptablesInstCommand(buf, templates[i], cmd, pos, stopOnError); + + ret = 0; + cleanup: + for (i = 0; i < ntemplates; i++) + VIR_FREE(templates[i]); + VIR_FREE(templates); + virNWFilterVarCombIterFree(vciter); + return ret; +} + + static int ebiptablesApplyNewRules(const char *ifname, - int nruleInstances, - void **_inst) + virNWFilterRuleInstPtr *rules, + size_t nrules) { size_t i, j; - ebiptablesRuleInstPtr *inst = (ebiptablesRuleInstPtr *)_inst; virBuffer buf = VIR_BUFFER_INITIALIZER; virHashTablePtr chains_in_set = virHashCreate(10, NULL); virHashTablePtr chains_out_set = virHashCreate(10, NULL); @@ -3689,28 +3711,27 @@ ebiptablesApplyNewRules(const char *ifname, int nEbtChains = 0; char *errmsg = NULL; - if (inst == NULL) - nruleInstances = 0; - if (!chains_in_set || !chains_out_set) goto exit_free_sets; - if (nruleInstances > 1 && inst) - qsort(inst, nruleInstances, sizeof(inst[0]), - ebiptablesRuleOrderSortPtr); + if (nrules) + qsort(rules, nrules, sizeof(rules[0]), + virNWFilterRuleInstSortPtr); /* 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) { - const char *name = inst[i]->neededProtocolChain; - if (inst[i]->chainprefix == CHAINPREFIX_HOST_IN_TEMP) { + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { + const char *name = rules[i]->chainSuffix; + if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || + rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { if (virHashUpdateEntry(chains_in_set, name, - &inst[i]->chainPriority) < 0) + &rules[i]->chainPriority) < 0) goto exit_free_sets; - } else { + } + if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_IN || + rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { if (virHashUpdateEntry(chains_out_set, name, - &inst[i]->chainPriority) < 0) + &rules[i]->chainPriority) < 0) goto exit_free_sets; } } @@ -3759,37 +3780,34 @@ ebiptablesApplyNewRules(const char *ifname, * priority -500 and the chain with priority -500 will * then be created before it. */ - for (i = 0; i < nruleInstances; i++) { - if (inst[i]->chainPriority > inst[i]->priority && - !strstr("root", inst[i]->neededProtocolChain)) { + for (i = 0; i < nrules; i++) { + if (rules[i]->chainPriority > rules[i]->priority && + !strstr("root", rules[i]->chainSuffix)) { - inst[i]->priority = inst[i]->chainPriority; + rules[i]->priority = rules[i]->chainPriority; } } /* process ebtables commands; interleave commands from filters with commands for creating and connecting ebtables chains */ j = 0; - for (i = 0; i < nruleInstances; i++) { - sa_assert(inst); - switch (inst[i]->ruleType) { - case RT_EBTABLES: + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { while (j < nEbtChains && - ebtChains[j].priority <= inst[i]->priority) { + ebtChains[j].priority <= rules[i]->priority) { ebiptablesInstCommand(&buf, ebtChains[j++].commandTemplate, 'A', -1, true); } - ebiptablesInstCommand(&buf, - inst[i]->commandTemplate, - 'A', -1, true); - break; - case RT_IPTABLES: - haveIptables = true; - break; - case RT_IP6TABLES: - haveIp6tables = true; - break; + ebtablesRuleInstCommand(&buf, + ifname, + rules[i], + 'A', -1, true); + } else { + if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + haveIptables = true; + else if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + haveIp6tables = true; } } @@ -3828,12 +3846,12 @@ ebiptablesApplyNewRules(const char *ifname, NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - for (i = 0; i < nruleInstances; i++) { - sa_assert(inst); - if (inst[i]->ruleType == RT_IPTABLES) - iptablesInstCommand(&buf, - inst[i]->commandTemplate, - 'A', -1); + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + iptablesRuleInstCommand(&buf, + ifname, + rules[i], + 'A', -1); } if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) @@ -3869,11 +3887,12 @@ ebiptablesApplyNewRules(const char *ifname, NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - for (i = 0; i < nruleInstances; i++) { - if (inst[i]->ruleType == RT_IP6TABLES) - iptablesInstCommand(&buf, - inst[i]->commandTemplate, - 'A', -1); + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolIPv6(rules[i]->def)) + iptablesRuleInstCommand(&buf, + ifname, + rules[i], + 'A', -1); } if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) @@ -4095,12 +4114,10 @@ virNWFilterTechDriver ebiptables_driver = { .init = ebiptablesDriverInit, .shutdown = ebiptablesDriverShutdown, - .createRuleInstance = ebiptablesCreateRuleInstanceIterate, .applyNewRules = ebiptablesApplyNewRules, .tearNewRules = ebiptablesTearNewRules, .tearOldRules = ebiptablesTearOldRules, .allTeardown = ebiptablesAllTeardown, - .freeRuleInstance = ebiptablesFreeRuleInstance, .canApplyBasicRules = ebiptablesCanApplyBasicRules, .applyBasicRules = ebtablesApplyBasicRules, diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index d482f43..5bed106 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -119,14 +119,10 @@ virNWFilterTechDriverForName(const char *name) static void virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst) { - size_t i; if (!inst) return; - for (i = 0; i < inst->ndata; i++) - inst->techdriver->freeRuleInstance(inst->data[i]); - - VIR_FREE(inst->data); + virNWFilterHashTableFree(inst->vars); VIR_FREE(inst); } @@ -273,51 +269,6 @@ virNWFilterPrintVars(virHashTablePtr vars, /** - * virNWFilterRuleInstantiate: - * @techdriver: the driver to use for instantiation - * @filter: The filter the rule is part of - * @rule : The rule that is to be instantiated - * @ifname: The name of the interface - * @vars: map containing variable names and value used for instantiation - * - * Returns virNWFilterRuleInst object on success, NULL on error with - * error reported. - * - * Instantiate a single rule. Return a pointer to virNWFilterRuleInst - * object that will hold an array of driver-specific data resulting - * from the instantiation. Returns NULL on error with error reported. - */ -static virNWFilterRuleInstPtr -virNWFilterRuleInstantiate(virNWFilterTechDriverPtr techdriver, - virNWFilterDefPtr filter, - virNWFilterRuleDefPtr rule, - const char *ifname, - virNWFilterHashTablePtr vars) -{ - int rc; - size_t i; - virNWFilterRuleInstPtr ret; - - if (VIR_ALLOC(ret) < 0) - return NULL; - - ret->techdriver = techdriver; - - rc = techdriver->createRuleInstance(filter, - rule, ifname, vars, ret); - - if (rc) { - for (i = 0; i < ret->ndata; i++) - techdriver->freeRuleInstance(ret->data[i]); - VIR_FREE(ret); - ret = NULL; - } - - return ret; -} - - -/** * virNWFilterCreateVarsFrom: * @vars1: pointer to hash table * @vars2: pointer to hash table @@ -350,125 +301,198 @@ virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1, } -/** - * _virNWFilterInstantiateRec: - * @techdriver: The driver to use for instantiation - * @filter: The filter to instantiate - * @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. - * @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 - * def ptr which is useful during a filter update - * @foundNewFilter: pointer to int indivating whether a newDef pointer was - * ever used; variable expected to be initialized to 0 by caller - * - * Returns 0 on success, a value otherwise. - * - * Recursively instantiate a filter by instantiating the given filter along - * with all its subfilters in a depth-first traversal of the tree of - * referenced filters. The name of the interface to which the rules belong - * must be provided. Apply the values of variables as needed. Terminate with - * error when a referenced filter is missing or a variable could not be - * resolved -- among other reasons. - */ -static int -_virNWFilterInstantiateRec(virNWFilterTechDriverPtr techdriver, - virNWFilterDefPtr filter, - const char *ifname, - virNWFilterHashTablePtr vars, - size_t *nEntries, - virNWFilterRuleInstPtr **insts, - enum instCase useNewFilter, bool *foundNewFilter, - virNWFilterDriverStatePtr driver) +typedef struct _virNWFilterInst virNWFilterInst; +typedef virNWFilterInst *virNWFilterInstPtr; +struct _virNWFilterInst { + virNWFilterObjPtr *filters; + size_t nfilters; + virNWFilterRuleInstPtr *rules; + size_t nrules; +}; + + +static void +virNWFilterInstReset(virNWFilterInstPtr inst) { - virNWFilterObjPtr obj; - int rc = 0; size_t i; - virNWFilterRuleInstPtr inst; - virNWFilterDefPtr next_filter; - for (i = 0; i < filter->nentries; i++) { - virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule; - virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include; - if (rule) { - inst = virNWFilterRuleInstantiate(techdriver, - filter, - rule, - ifname, - vars); - if (!inst) { - rc = -1; - break; - } + for (i = 0; i < inst->nfilters; i++) + virNWFilterObjUnlock(inst->filters[i]); + VIR_FREE(inst->filters); + inst->nfilters = 0; - if (VIR_APPEND_ELEMENT_COPY(*insts, *nEntries, inst) < 0) { - rc = -1; - break; - } + for (i = 0; i < inst->nrules; i++) + virNWFilterRuleInstFree(inst->rules[i]); + VIR_FREE(inst->rules); +} - } else if (inc) { - VIR_DEBUG("Instantiating filter %s", inc->filterref); - obj = virNWFilterObjFindByName(&driver->nwfilters, inc->filterref); - if (obj) { - if (obj->wantRemoved) { - virReportError(VIR_ERR_NO_NWFILTER, - _("Filter '%s' is in use."), + +static int +virNWFilterDefToInst(virNWFilterDriverStatePtr driver, + virNWFilterDefPtr def, + virNWFilterHashTablePtr vars, + enum instCase useNewFilter, + bool *foundNewFilter, + virNWFilterInstPtr inst); + +static int +virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def, + virNWFilterRuleDefPtr rule, + virNWFilterHashTablePtr vars, + virNWFilterInstPtr inst) +{ + virNWFilterRuleInstPtr ruleinst; + int ret = -1; + + if (VIR_ALLOC(ruleinst) < 0) + goto cleanup; + + ruleinst->chainSuffix = def->chainsuffix; + ruleinst->chainPriority = def->chainPriority; + ruleinst->def = rule; + ruleinst->priority = rule->priority; + if (!(ruleinst->vars = virNWFilterHashTableCreate(0))) + goto cleanup; + if (virNWFilterHashTablePutAll(vars, ruleinst->vars) < 0) + goto cleanup; + + if (VIR_APPEND_ELEMENT(inst->rules, + inst->nrules, + ruleinst) < 0) + goto cleanup; + inst = NULL; + + ret = 0; + cleanup: + virNWFilterRuleInstFree(ruleinst); + return ret; +} + + +static int +virNWFilterIncludeDefToRuleInst(virNWFilterDriverStatePtr driver, + virNWFilterIncludeDefPtr inc, + virNWFilterHashTablePtr vars, + enum instCase useNewFilter, + bool *foundNewFilter, + virNWFilterInstPtr inst) +{ + virNWFilterObjPtr obj; + virNWFilterHashTablePtr tmpvars = NULL; + virNWFilterDefPtr childdef; + int ret = -1; + + VIR_DEBUG("Instantiating filter %s", inc->filterref); + obj = virNWFilterObjFindByName(&driver->nwfilters, inc->filterref); - rc = -1; - virNWFilterObjUnlock(obj); - break; - } + if (!obj) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("referenced filter '%s' is missing"), + inc->filterref); + goto cleanup; + } + if (obj->wantRemoved) { + virReportError(VIR_ERR_NO_NWFILTER, + _("Filter '%s' is in use."), + inc->filterref); + goto cleanup; + } - /* create a temporary hashmap for depth-first tree traversal */ - virNWFilterHashTablePtr tmpvars = - virNWFilterCreateVarsFrom(inc->params, - vars); - if (!tmpvars) { - rc = -1; - virNWFilterObjUnlock(obj); - break; - } + /* create a temporary hashmap for depth-first tree traversal */ + if (!(tmpvars = virNWFilterCreateVarsFrom(inc->params, + vars))) + goto cleanup; - next_filter = obj->def; + childdef = obj->def; - switch (useNewFilter) { - case INSTANTIATE_FOLLOW_NEWFILTER: - if (obj->newDef) { - next_filter = obj->newDef; - *foundNewFilter = true; - } - break; - case INSTANTIATE_ALWAYS: - break; - } + switch (useNewFilter) { + case INSTANTIATE_FOLLOW_NEWFILTER: + if (obj->newDef) { + childdef = obj->newDef; + *foundNewFilter = true; + } + break; + case INSTANTIATE_ALWAYS: + break; + } - rc = _virNWFilterInstantiateRec(techdriver, - next_filter, - ifname, - tmpvars, - nEntries, insts, - useNewFilter, - foundNewFilter, - driver); + if (VIR_APPEND_ELEMENT(inst->filters, + inst->nfilters, + obj) < 0) + goto cleanup; + obj = NULL; + + if (virNWFilterDefToInst(driver, + childdef, + tmpvars, + useNewFilter, + foundNewFilter, + inst) < 0) + goto cleanup; - virNWFilterHashTableFree(tmpvars); + ret = 0; + cleanup: + if (ret < 0) + virNWFilterInstReset(inst); + virNWFilterHashTableFree(tmpvars); + if (obj) + virNWFilterObjUnlock(obj); + return ret; +} - virNWFilterObjUnlock(obj); - if (rc < 0) - break; - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("referenced filter '%s' is missing"), - inc->filterref); - rc = -1; - break; - } + +/** + * virNWFilterDefToInst: + * @driver: the driver state pointer + * @def: The filter to instantiate + * @vars: A map holding variable names and values used for instantiating + * the filter and its subfilters. + * @useNewFilter: instruct whether to use a newDef pointer rather than a + * def ptr which is useful during a filter update + * @foundNewFilter: pointer to int indivating whether a newDef pointer was + * ever used; variable expected to be initialized to 0 by caller + * @rulesout: array to be filled with rule instance + * @nrulesout: counter to be filled with number of rule instances + * + * Recursively expand a nested filter into a flat list of rule instances, + * in a depth-first traversal of the tree. + * + * Returns 0 on success, -1 on error + */ +static int +virNWFilterDefToInst(virNWFilterDriverStatePtr driver, + virNWFilterDefPtr def, + virNWFilterHashTablePtr vars, + enum instCase useNewFilter, + bool *foundNewFilter, + virNWFilterInstPtr inst) +{ + size_t i; + int ret = -1; + + for (i = 0; i < def->nentries; i++) { + if (def->filterEntries[i]->rule) { + if (virNWFilterRuleDefToRuleInst(def, + def->filterEntries[i]->rule, + vars, + inst) < 0) + goto cleanup; + } else if (def->filterEntries[i]->include) { + if (virNWFilterIncludeDefToRuleInst(driver, + def->filterEntries[i]->include, + vars, + useNewFilter, foundNewFilter, + inst) < 0) + goto cleanup; } } - return rc; + + ret = 0; + cleanup: + if (ret < 0) + virNWFilterInstReset(inst); + return ret; } @@ -578,35 +602,6 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, } -static int -virNWFilterRuleInstancesToArray(int nEntries, - virNWFilterRuleInstPtr *insts, - void ***ptrs, - int *nptrs) -{ - size_t i, j; - - *nptrs = 0; - - for (j = 0; j < nEntries; j++) - (*nptrs) += insts[j]->ndata; - - if ((*nptrs) == 0) - return 0; - - if (VIR_ALLOC_N((*ptrs), (*nptrs)) < 0) - return -1; - - (*nptrs) = 0; - - for (j = 0; j < nEntries; j++) - for (i = 0; i < insts[j]->ndata; i++) - (*ptrs)[(*nptrs)++] = insts[j]->data[i]; - - return 0; -} - - /** * virNWFilterInstantiate: * @vmuuid: The UUID of the VM @@ -642,11 +637,7 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, bool forceWithPendingReq) { int rc; - size_t j; - int nptrs; - size_t nEntries = 0; - virNWFilterRuleInstPtr *insts = NULL; - void **ptrs = NULL; + virNWFilterInst inst; bool instantiate = true; char *buf; virNWFilterVarValuePtr lv; @@ -654,6 +645,9 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, bool reportIP = false; virNWFilterHashTablePtr missing_vars = virNWFilterHashTableCreate(0); + + memset(&inst, 0, sizeof(inst)); + if (!missing_vars) { rc = -1; goto err_exit; @@ -717,13 +711,11 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, goto err_exit; } - rc = _virNWFilterInstantiateRec(techdriver, - filter, - ifname, - vars, - &nEntries, &insts, - useNewFilter, foundNewFilter, - driver); + rc = virNWFilterDefToInst(driver, + filter, + vars, + useNewFilter, foundNewFilter, + &inst); if (rc < 0) goto err_exit; @@ -738,16 +730,10 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, } if (instantiate) { - - rc = virNWFilterRuleInstancesToArray(nEntries, insts, - &ptrs, &nptrs); - if (rc < 0) - goto err_exit; - if (virNWFilterLockIface(ifname) < 0) goto err_exit; - rc = techdriver->applyNewRules(ifname, nptrs, ptrs); + rc = techdriver->applyNewRules(ifname, inst.rules, inst.nrules); if (teardownOld && rc == 0) techdriver->tearOldRules(ifname); @@ -763,13 +749,7 @@ virNWFilterInstantiate(const unsigned char *vmuuid ATTRIBUTE_UNUSED, } err_exit: - - for (j = 0; j < nEntries; j++) - virNWFilterRuleInstFree(insts[j]); - - VIR_FREE(insts); - VIR_FREE(ptrs); - + virNWFilterInstReset(&inst); virNWFilterHashTableFree(missing_vars); return rc; diff --git a/src/nwfilter/nwfilter_tech_driver.h b/src/nwfilter/nwfilter_tech_driver.h index ed09a67..7b6f56f 100644 --- a/src/nwfilter/nwfilter_tech_driver.h +++ b/src/nwfilter/nwfilter_tech_driver.h @@ -35,24 +35,20 @@ typedef virNWFilterTechDriver *virNWFilterTechDriverPtr; typedef struct _virNWFilterRuleInst virNWFilterRuleInst; typedef virNWFilterRuleInst *virNWFilterRuleInstPtr; struct _virNWFilterRuleInst { - size_t ndata; - void **data; - virNWFilterTechDriverPtr techdriver; + const char *chainSuffix; + virNWFilterChainPriority chainPriority; + virNWFilterRuleDefPtr def; + virNWFilterRulePriority priority; + virNWFilterHashTablePtr vars; }; typedef int (*virNWFilterTechDrvInit)(bool privileged); typedef void (*virNWFilterTechDrvShutdown)(void); -typedef int (*virNWFilterRuleCreateInstance)(virNWFilterDefPtr filter, - virNWFilterRuleDefPtr rule, - const char *ifname, - virNWFilterHashTablePtr vars, - virNWFilterRuleInstPtr res); - typedef int (*virNWFilterRuleApplyNewRules)(const char *ifname, - int nruleInstances, - void **_inst); + virNWFilterRuleInstPtr *rules, + size_t nrules); typedef int (*virNWFilterRuleTeardownNewRules)(const char *ifname); @@ -60,8 +56,6 @@ typedef int (*virNWFilterRuleTeardownOldRules)(const char *ifname); typedef int (*virNWFilterRuleAllTeardown)(const char *ifname); -typedef int (*virNWFilterRuleFreeInstanceData)(void * _inst); - typedef int (*virNWFilterCanApplyBasicRules)(void); typedef int (*virNWFilterApplyBasicRules)(const char *ifname, @@ -87,12 +81,10 @@ struct _virNWFilterTechDriver { virNWFilterTechDrvInit init; virNWFilterTechDrvShutdown shutdown; - virNWFilterRuleCreateInstance createRuleInstance; virNWFilterRuleApplyNewRules applyNewRules; virNWFilterRuleTeardownNewRules tearNewRules; virNWFilterRuleTeardownOldRules tearOldRules; virNWFilterRuleAllTeardown allTeardown; - virNWFilterRuleFreeInstanceData freeRuleInstance; virNWFilterCanApplyBasicRules canApplyBasicRules; virNWFilterApplyBasicRules applyBasicRules; -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
The current nwfilter tech driver API has a 'createRuleInstance' method which populates virNWFilterRuleInstPtr with a command line string containing variable placeholders. The 'applyNewRules' method then expands the variables and executes the commands. This split of responsibility won't work when switching to the virFirewallPtr APIs, since we can't just build up command line strings. This patch this merges the functionality of 'createRuleInstance' into the applyNewRules method.
The virNWFilterRuleInstPtr struct is changed from holding an array of opaque pointers, into holding generic metadata about the rules to be processed. In essence this is the result of taking a linked set of virNWFilterDefPtr's and flattening the tree to get a list of virNWFilterRuleDefPtr's. At the same time we must keep track of any nested virNWFilterObjPtr instances, so that the locks are held for the duration of the 'applyNewRules' method.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Some parts are difficult to read in the patch, especially where you split the contents of _virNWFilterInstantiateRec into two functions. But I find that the pieces appear again in the new functions. /* process ebtables commands; interleave commands from filters with commands for creating and connecting ebtables chains */ j = 0; - for (i = 0; i < nruleInstances; i++) { - sa_assert(inst); - switch (inst[i]->ruleType) { - case RT_EBTABLES: + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { while (j < nEbtChains && - ebtChains[j].priority <= inst[i]->priority) { + ebtChains[j].priority <= rules[i]->priority) { ebiptablesInstCommand(&buf, ebtChains[j++].commandTemplate, 'A', -1, true); } - ebiptablesInstCommand(&buf, - inst[i]->commandTemplate, - 'A', -1, true); - break; - case RT_IPTABLES: - haveIptables = true; - break; - case RT_IP6TABLES: - haveIp6tables = true; - break; + ebtablesRuleInstCommand(&buf, + ifname, + rules[i], + 'A', -1, true); + } else { + if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + haveIptables = true; + else if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + haveIp6tables = true; Here's that typo. If you were to change this, the TCK test suite will probably pass after each step of applying the patches incrementally. ACK Stefan

The nwfilter ebiptables driver will build up commands to run in two phases. The first phase contains all of the command, except for the '-A' part. Instead it has a '%c' placeholder, along with a '%s' placeholder for a position arg. The second phase than substitutes these placeholders. The only values ever used for these substitutions though is '-A' and '', so it is entirely pointless. Remove the second phase entirely, since it will make it harder to convert to the new firewall APIs Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 109 +++++++++++++----------------- 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index f93158f..0361d99 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -898,12 +898,9 @@ iptablesRenameTmpRootChains(virBufferPtr buf, static void iptablesInstCommand(virBufferPtr buf, - const char *templ, char cmd, int pos) + const char *cmdstr) { - char position[10] = { 0 }; - if (pos >= 0) - snprintf(position, sizeof(position), "%d", pos); - virBufferAsprintf(buf, templ, cmd, position); + virBufferAdd(buf, cmdstr, -1); virBufferAsprintf(buf, CMD_SEPARATOR "%s", CMD_STOPONERR(true)); } @@ -1298,7 +1295,7 @@ _iptablesCreateRuleInstance(bool directionIn, case VIR_NWFILTER_RULE_PROTOCOL_TCP: case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6: virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -%%c %s %%s", + CMD_DEF_PRE "$IPT -A %s", chain); virBufferAddLit(&buf, " -p tcp"); @@ -1353,7 +1350,7 @@ _iptablesCreateRuleInstance(bool directionIn, case VIR_NWFILTER_RULE_PROTOCOL_UDP: case VIR_NWFILTER_RULE_PROTOCOL_UDPoIPV6: virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -%%c %s %%s", + CMD_DEF_PRE "$IPT -A %s", chain); virBufferAddLit(&buf, " -p udp"); @@ -1386,7 +1383,7 @@ _iptablesCreateRuleInstance(bool directionIn, case VIR_NWFILTER_RULE_PROTOCOL_UDPLITE: case VIR_NWFILTER_RULE_PROTOCOL_UDPLITEoIPV6: virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -%%c %s %%s", + CMD_DEF_PRE "$IPT -A %s", chain); virBufferAddLit(&buf, " -p udplite"); @@ -1414,7 +1411,7 @@ _iptablesCreateRuleInstance(bool directionIn, case VIR_NWFILTER_RULE_PROTOCOL_ESP: case VIR_NWFILTER_RULE_PROTOCOL_ESPoIPV6: virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -%%c %s %%s", + CMD_DEF_PRE "$IPT -A %s", chain); virBufferAddLit(&buf, " -p esp"); @@ -1442,7 +1439,7 @@ _iptablesCreateRuleInstance(bool directionIn, case VIR_NWFILTER_RULE_PROTOCOL_AH: case VIR_NWFILTER_RULE_PROTOCOL_AHoIPV6: virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -%%c %s %%s", + CMD_DEF_PRE "$IPT -A %s", chain); virBufferAddLit(&buf, " -p ah"); @@ -1470,7 +1467,7 @@ _iptablesCreateRuleInstance(bool directionIn, case VIR_NWFILTER_RULE_PROTOCOL_SCTP: case VIR_NWFILTER_RULE_PROTOCOL_SCTPoIPV6: virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -%%c %s %%s", + CMD_DEF_PRE "$IPT -A %s", chain); virBufferAddLit(&buf, " -p sctp"); @@ -1503,7 +1500,7 @@ _iptablesCreateRuleInstance(bool directionIn, case VIR_NWFILTER_RULE_PROTOCOL_ICMP: case VIR_NWFILTER_RULE_PROTOCOL_ICMPV6: virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -%%c %s %%s", + CMD_DEF_PRE "$IPT -A %s", chain); if (rule->prtclType == VIR_NWFILTER_RULE_PROTOCOL_ICMP) @@ -1568,7 +1565,7 @@ _iptablesCreateRuleInstance(bool directionIn, case VIR_NWFILTER_RULE_PROTOCOL_IGMP: virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -%%c %s %%s", + CMD_DEF_PRE "$IPT -A %s", chain); virBufferAddLit(&buf, " -p igmp"); @@ -1596,7 +1593,7 @@ _iptablesCreateRuleInstance(bool directionIn, case VIR_NWFILTER_RULE_PROTOCOL_ALL: case VIR_NWFILTER_RULE_PROTOCOL_ALLoIPV6: virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -%%c %s %%s", + CMD_DEF_PRE "$IPT -A %s", chain); virBufferAddLit(&buf, " -p all"); @@ -2026,7 +2023,7 @@ ebtablesCreateRuleInstance(char chainPrefix, case VIR_NWFILTER_RULE_PROTOCOL_MAC: virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -%%c %s %%s", + CMD_DEF_PRE "$EBT -t nat -A %s", chain); if (ebtablesHandleEthHdr(&buf, @@ -2050,7 +2047,7 @@ ebtablesCreateRuleInstance(char chainPrefix, case VIR_NWFILTER_RULE_PROTOCOL_VLAN: virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -%%c %s %%s", + CMD_DEF_PRE "$EBT -t nat -A %s", chain); @@ -2117,7 +2114,7 @@ ebtablesCreateRuleInstance(char chainPrefix, } virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -%%c %s %%s", + CMD_DEF_PRE "$EBT -t nat -A %s", chain); @@ -2155,7 +2152,7 @@ ebtablesCreateRuleInstance(char chainPrefix, case VIR_NWFILTER_RULE_PROTOCOL_RARP: virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -%%c %s %%s", + CMD_DEF_PRE "$EBT -t nat -A %s", chain); if (ebtablesHandleEthHdr(&buf, @@ -2282,7 +2279,7 @@ ebtablesCreateRuleInstance(char chainPrefix, case VIR_NWFILTER_RULE_PROTOCOL_IP: virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -%%c %s %%s", + CMD_DEF_PRE "$EBT -t nat -A %s", chain); if (ebtablesHandleEthHdr(&buf, @@ -2424,7 +2421,7 @@ ebtablesCreateRuleInstance(char chainPrefix, case VIR_NWFILTER_RULE_PROTOCOL_IPV6: virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -%%c %s %%s", + CMD_DEF_PRE "$EBT -t nat -A %s", chain); if (ebtablesHandleEthHdr(&buf, @@ -2554,7 +2551,7 @@ ebtablesCreateRuleInstance(char chainPrefix, case VIR_NWFILTER_RULE_PROTOCOL_NONE: virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -%%c %s %%s", + CMD_DEF_PRE "$EBT -t nat -A %s", chain); break; @@ -2908,7 +2905,7 @@ ebtablesCreateTmpSubChain(ebiptablesRuleInstPtr *inst, CMD_DEF("$EBT -t nat -N %s") CMD_SEPARATOR CMD_EXEC "%s" - CMD_DEF("$EBT -t nat -%%c %s %%s %s-j %s") + CMD_DEF("$EBT -t nat -A %s %s-j %s") CMD_SEPARATOR CMD_EXEC "%s", @@ -3071,15 +3068,11 @@ ebtablesRenameTmpSubAndRootChains(virBufferPtr buf, static void ebiptablesInstCommand(virBufferPtr buf, - const char *templ, char cmd, int pos, - bool stopOnError) + const char *cmdstr) { - char position[10] = { 0 }; - if (pos >= 0) - snprintf(position, sizeof(position), "%d", pos); - virBufferAsprintf(buf, templ, cmd, position); + virBufferAdd(buf, cmdstr, -1); virBufferAsprintf(buf, CMD_SEPARATOR "%s", - CMD_STOPONERR(stopOnError)); + CMD_STOPONERR(true)); } @@ -3606,12 +3599,11 @@ ebtablesCreateTmpRootAndSubChains(virBufferPtr buf, static int iptablesRuleInstCommand(virBufferPtr buf, const char *ifname, - virNWFilterRuleInstPtr rule, - char cmd, int pos) + virNWFilterRuleInstPtr rule) { virNWFilterVarCombIterPtr vciter, tmp; - char **templates = NULL; - size_t ntemplates = 0; + char **cmds = NULL; + size_t ncmds = 0; size_t i; int ret = -1; @@ -3630,20 +3622,20 @@ iptablesRuleInstCommand(virBufferPtr buf, rule->def, ifname, tmp, - &templates, - &ntemplates) < 0) + &cmds, + &ncmds) < 0) goto cleanup; tmp = virNWFilterVarCombIterNext(tmp); } while (tmp != NULL); - for (i = 0; i < ntemplates; i++) - iptablesInstCommand(buf, templates[i], cmd, pos); + for (i = 0; i < ncmds; i++) + iptablesInstCommand(buf, cmds[i]); ret = 0; cleanup: - for (i = 0; i < ntemplates; i++) - VIR_FREE(templates[i]); - VIR_FREE(templates); + for (i = 0; i < ncmds; i++) + VIR_FREE(cmds[i]); + VIR_FREE(cmds); virNWFilterVarCombIterFree(vciter); return ret; } @@ -3652,13 +3644,11 @@ iptablesRuleInstCommand(virBufferPtr buf, static int ebtablesRuleInstCommand(virBufferPtr buf, const char *ifname, - virNWFilterRuleInstPtr rule, - char cmd, int pos, - bool stopOnError) + virNWFilterRuleInstPtr rule) { virNWFilterVarCombIterPtr vciter, tmp; - char **templates = NULL; - size_t ntemplates = 0; + char **cmds = NULL; + size_t ncmds = 0; size_t i; int ret = -1; @@ -3677,20 +3667,20 @@ ebtablesRuleInstCommand(virBufferPtr buf, rule->def, ifname, tmp, - &templates, - &ntemplates) < 0) + &cmds, + &ncmds) < 0) goto cleanup; tmp = virNWFilterVarCombIterNext(tmp); } while (tmp != NULL); - for (i = 0; i < ntemplates; i++) - ebiptablesInstCommand(buf, templates[i], cmd, pos, stopOnError); + for (i = 0; i < ncmds; i++) + ebiptablesInstCommand(buf, cmds[i]); ret = 0; cleanup: - for (i = 0; i < ntemplates; i++) - VIR_FREE(templates[i]); - VIR_FREE(templates); + for (i = 0; i < ncmds; i++) + VIR_FREE(cmds[i]); + VIR_FREE(cmds); virNWFilterVarCombIterFree(vciter); return ret; } @@ -3796,13 +3786,11 @@ ebiptablesApplyNewRules(const char *ifname, while (j < nEbtChains && ebtChains[j].priority <= rules[i]->priority) { ebiptablesInstCommand(&buf, - ebtChains[j++].commandTemplate, - 'A', -1, true); + ebtChains[j++].commandTemplate); } ebtablesRuleInstCommand(&buf, ifname, - rules[i], - 'A', -1, true); + rules[i]); } else { if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) haveIptables = true; @@ -3813,8 +3801,7 @@ ebiptablesApplyNewRules(const char *ifname, while (j < nEbtChains) ebiptablesInstCommand(&buf, - ebtChains[j++].commandTemplate, - 'A', -1, true); + ebtChains[j++].commandTemplate); if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) goto tear_down_tmpebchains; @@ -3850,8 +3837,7 @@ ebiptablesApplyNewRules(const char *ifname, if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) iptablesRuleInstCommand(&buf, ifname, - rules[i], - 'A', -1); + rules[i]); } if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) @@ -3891,8 +3877,7 @@ ebiptablesApplyNewRules(const char *ifname, if (virNWFilterRuleIsProtocolIPv6(rules[i]->def)) iptablesRuleInstCommand(&buf, ifname, - rules[i], - 'A', -1); + rules[i]); } if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
The nwfilter ebiptables driver will build up commands to run in two phases. The first phase contains all of the command, except for the '-A' part. Instead it has a '%c' placeholder, along with a '%s' placeholder for a position arg. The second phase than substitutes these placeholders. The only values ever used for these substitutions though is '-A' and '', so it is entirely pointless. Remove the second phase entirely, since it will make it harder to convert to the new firewall APIs
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
ACK

When a VM fails to launch due to error creating nwfilter rules, we must avoid overwriting the original error when tearing down the partially created rules. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/qemu/qemu_command.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 379c094..e34e537 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7654,8 +7654,12 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd, ret = 0; cleanup: - if (ret < 0) + if (ret < 0) { + virErrorPtr saved_err = virSaveLastError(); virDomainConfNWFilterTeardown(net); + virSetError(saved_err); + virFreeError(saved_err); + } for (i = 0; tapfd && i < tapfdSize && tapfd[i] >= 0; i++) { if (ret < 0) VIR_FORCE_CLOSE(tapfd[i]); -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
When a VM fails to launch due to error creating nwfilter rules, we must avoid overwriting the original error when tearing down the partially created rules.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/qemu/qemu_command.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 379c094..e34e537 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7654,8 +7654,12 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
ret = 0; cleanup: - if (ret < 0) + if (ret < 0) { + virErrorPtr saved_err = virSaveLastError(); virDomainConfNWFilterTeardown(net); + virSetError(saved_err); + virFreeError(saved_err); + } for (i = 0; tapfd && i < tapfdSize && tapfd[i] >= 0; i++) { if (ret < 0) VIR_FORCE_CLOSE(tapfd[i]); ACK

The network and nwfilter drivers both have a need to update firewall rules. The currently share no code for interacting with iptables / firewalld. The nwfilter driver is fairly tied to the concept of creating shell scripts to execute which makes it very hard to port to talk to firewalld via DBus APIs. This patch introduces a virFirewallPtr object which is able to represent a complete sequence of rule changes, with the ability to have multiple transactional checkpoints with rollbacks. By formally separating the definition of the rules to be applied from the mechanism used to apply them, it is also possible to write a firewall engine that uses firewalld DBus APIs natively instead of via the slow firewalld-cmd. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- include/libvirt/virterror.h | 1 + po/POTFILES.in | 1 + src/Makefile.am | 2 + src/libvirt_private.syms | 17 + src/util/virerror.c | 1 + src/util/virfirewall.c | 922 +++++++++++++++++++++++++++++++++ src/util/virfirewall.h | 109 ++++ src/util/virfirewallpriv.h | 45 ++ tests/Makefile.am | 7 + tests/testutils.c | 18 +- tests/virfirewalltest.c | 1186 +++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 2305 insertions(+), 4 deletions(-) create mode 100644 src/util/virfirewall.c create mode 100644 src/util/virfirewall.h create mode 100644 src/util/virfirewallpriv.h create mode 100644 tests/virfirewalltest.c diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 495c121..be90797 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -122,6 +122,7 @@ typedef enum { VIR_FROM_SYSTEMD = 56, /* Error from systemd code */ VIR_FROM_BHYVE = 57, /* Error from bhyve driver */ VIR_FROM_CRYPTO = 58, /* Error from crypto code */ + VIR_FROM_FIREWALL = 59, /* Error from firewall */ # ifdef VIR_ENUM_SENTINELS VIR_ERR_DOMAIN_LAST diff --git a/po/POTFILES.in b/po/POTFILES.in index 122b853..e35eb82 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -161,6 +161,7 @@ src/util/virdbus.c src/util/virdnsmasq.c src/util/vireventpoll.c src/util/virfile.c +src/util/virfirewall.c src/util/virhash.c src/util/virhook.c src/util/virhostdev.c diff --git a/src/Makefile.am b/src/Makefile.am index 7e9a702..7615294 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -106,6 +106,8 @@ UTIL_SOURCES = \ util/virevent.c util/virevent.h \ util/vireventpoll.c util/vireventpoll.h \ util/virfile.c util/virfile.h \ + util/virfirewall.c util/virfirewall.h \ + util/virfirewallpriv.h \ util/virhash.c util/virhash.h \ util/virhashcode.c util/virhashcode.h \ util/virhook.c util/virhook.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0c2cf75..18be0e1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1277,6 +1277,23 @@ virFileWriteStr; virFindFileInPath; +# util/virfirewall.h +virFirewallAddRule; +virFirewallAddRuleFull; +virFirewallApply; +virFirewallFree; +virFirewallNew; +virFirewallRemoveRule; +virFirewallRuleAddArg; +virFirewallRuleAddArgFormat; +virFirewallRuleAddArgList; +virFirewallRuleAddArgSet; +virFirewallRuleGetArgCount; +virFirewallSetBackend; +virFirewallStartRollback; +virFirewallStartTransaction; + + # util/virhash.h virHashAddEntry; virHashCreate; diff --git a/src/util/virerror.c b/src/util/virerror.c index cbbaa83..e0bc970 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -129,6 +129,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST, "Systemd", "Bhyve", "Crypto", + "Firewall", ) diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c new file mode 100644 index 0000000..b558d2f --- /dev/null +++ b/src/util/virfirewall.c @@ -0,0 +1,922 @@ +/* + * virfirewall.c: integration with firewalls + * + * Copyright (C) 2013 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 + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Daniel P. Berrange <berrange@redhat.com> + */ + +#include <config.h> + +#define __VIR_FIREWALL_PRIV_H_ALLOW__ + +#include <stdarg.h> + +#include "viralloc.h" +#include "virfirewallpriv.h" +#include "virerror.h" +#include "virutil.h" +#include "virstring.h" +#include "vircommand.h" +#include "virlog.h" +#include "virdbus.h" +#include "virfile.h" +#include "virthread.h" + +#define VIR_FROM_THIS VIR_FROM_FIREWALL + +VIR_LOG_INIT("util.firewall"); + +typedef struct _virFirewallGroup virFirewallGroup; +typedef virFirewallGroup *virFirewallGroupPtr; + +VIR_ENUM_DECL(virFirewallLayerCommand) +VIR_ENUM_IMPL(virFirewallLayerCommand, VIR_FIREWALL_LAYER_LAST, + EBTABLES_PATH, + IPTABLES_PATH, + IP6TABLES_PATH); + +VIR_ENUM_DECL(virFirewallLayerFirewallD) +VIR_ENUM_IMPL(virFirewallLayerFirewallD, VIR_FIREWALL_LAYER_LAST, + "eb", "ipv4", "ipv6") + + +struct _virFirewallRule { + virFirewallLayer layer; + + virFirewallQueryCallback queryCB; + void *queryOpaque; + bool ignoreErrors; + + size_t argsAlloc; + size_t argsLen; + char **args; +}; + +struct _virFirewallGroup { + unsigned int actionFlags; + unsigned int rollbackFlags; + + size_t naction; + virFirewallRulePtr *action; + + size_t nrollback; + virFirewallRulePtr *rollback; + + bool addingRollback; +}; + + +struct _virFirewall { + int err; + + size_t ngroups; + virFirewallGroupPtr *groups; + size_t currentGroup; +}; + +static virFirewallBackend currentBackend = VIR_FIREWALL_BACKEND_AUTOMATIC; +static virMutex ruleLock = VIR_MUTEX_INITIALIZER; + +static int +virFirewallValidateBackend(virFirewallBackend backend); + +static int +virFirewallOnceInit(void) +{ + return virFirewallValidateBackend(currentBackend); +} + +VIR_ONCE_GLOBAL_INIT(virFirewall) + +static int +virFirewallValidateBackend(virFirewallBackend backend) +{ + VIR_DEBUG("Validating backend %d", backend); +#if WITH_DBUS + if (backend == VIR_FIREWALL_BACKEND_AUTOMATIC || + backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + int rv = virDBusIsServiceRegistered(VIR_FIREWALL_FIREWALLD_SERVICE); + VIR_DEBUG("Firewalled is registered ? %d", rv); + if (rv < 0) { + if (rv == -2) { + if (backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("firewalld firewall backend requested, but service is not running")); + return -1; + } else { + VIR_DEBUG("firewalld service not running, trying direct backend"); + backend = VIR_FIREWALL_BACKEND_DIRECT; + } + } else { + return -1; + } + } else { + VIR_DEBUG("firewalld service running, using firewalld backend"); + backend = VIR_FIREWALL_BACKEND_FIREWALLD; + } + } +#else + if (backend == VIR_FIREWALL_BACKEND_AUTOMATIC) { + VIR_DEBUG("DBus support disabled, trying direct backend"); + backend = VIR_FIREWALL_BACKEND_DIRECT; + } else if (backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("firewalld firewall backend requested, but DBus support disabled")); + return -1; + } +#endif + + if (backend == VIR_FIREWALL_BACKEND_DIRECT) { + const char *commands[] = { + IPTABLES_PATH, IP6TABLES_PATH, EBTABLES_PATH + }; + size_t i; + for (i = 0; i < ARRAY_CARDINALITY(commands); i++) { + if (!virFileIsExecutable(commands[i])) { + virReportSystemError(errno, + _("direct firewall backend requested, but %s is not available"), + commands[i]); + return -1; + } + } + VIR_DEBUG("found iptables/ip6tables/ebtables, using direct backend"); + } + + currentBackend = backend; + return 0; +} + +int +virFirewallSetBackend(virFirewallBackend backend) +{ + currentBackend = backend; + + if (virFirewallInitialize() < 0) + return -1; + + return virFirewallValidateBackend(backend); +} + +static virFirewallGroupPtr +virFirewallGroupNew(void) +{ + virFirewallGroupPtr group; + + if (VIR_ALLOC(group) < 0) + return NULL; + + return group; +} + + +/** + * virFirewallNew: + * + * Creates a new firewall ruleset for changing rules + * of @layer. This should be followed by a call to + * virFirewallStartTransaction before adding + * any rules + * + * Returns the new firewall ruleset + */ +virFirewallPtr virFirewallNew(void) +{ + virFirewallPtr firewall; + + if (VIR_ALLOC(firewall) < 0) + return NULL; + + return firewall; +} + + +static void +virFirewallRuleFree(virFirewallRulePtr rule) +{ + size_t i; + + if (!rule) + return; + + for (i = 0; i < rule->argsLen; i++) + VIR_FREE(rule->args[i]); + VIR_FREE(rule->args); + VIR_FREE(rule); +} + + +static void +virFirewallGroupFree(virFirewallGroupPtr group) +{ + size_t i; + + if (!group) + return; + + for (i = 0; i < group->naction; i++) + virFirewallRuleFree(group->action[i]); + VIR_FREE(group->action); + + for (i = 0; i < group->nrollback; i++) + virFirewallRuleFree(group->rollback[i]); + VIR_FREE(group->rollback); + + VIR_FREE(group); +} + + +/** + * virFirewallFree: + * + * Release all memory associated with the firewall + * ruleset + */ +void virFirewallFree(virFirewallPtr firewall) +{ + size_t i; + + if (!firewall) + return; + + for (i = 0; i < firewall->ngroups; i++) + virFirewallGroupFree(firewall->groups[i]); + VIR_FREE(firewall->groups); + + VIR_FREE(firewall); +} + +#define VIR_FIREWALL_RETURN_IF_ERROR(firewall) \ + if (!firewall || firewall->err) \ + return; + +#define VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, ruel)\ + if (!firewall || firewall->err || !rule) \ + return; + +#define VIR_FIREWALL_RETURN_NULL_IF_ERROR(firewall) \ + if (!firewall || firewall->err) \ + return NULL; + +#define ADD_ARG(rule, str) \ + if (VIR_RESIZE_N(rule->args, \ + rule->argsAlloc, \ + rule->argsLen, 1) < 0) \ + goto no_memory; \ + \ + if (VIR_STRDUP(rule->args[rule->argsLen++], str) < 0)\ + goto no_memory; + +static virFirewallRulePtr +virFirewallAddRuleFullV(virFirewallPtr firewall, + virFirewallLayer layer, + bool ignoreErrors, + virFirewallQueryCallback cb, + void *opaque, + va_list args) +{ + virFirewallGroupPtr group; + virFirewallRulePtr rule; + char *str; + + VIR_FIREWALL_RETURN_NULL_IF_ERROR(firewall); + + if (firewall->ngroups == 0) { + firewall->err = ENODATA; + return NULL; + } + group = firewall->groups[firewall->currentGroup]; + + + if (VIR_ALLOC(rule) < 0) + goto no_memory; + + rule->layer = layer; + rule->queryCB = cb; + rule->queryOpaque = opaque; + rule->ignoreErrors = ignoreErrors; + + while ((str = va_arg(args, char *)) != NULL) { + ADD_ARG(rule, str); + } + + if (group->addingRollback) { + if (VIR_APPEND_ELEMENT_COPY(group->rollback, + group->nrollback, + rule) < 0) + goto no_memory; + } else { + if (VIR_APPEND_ELEMENT_COPY(group->action, + group->naction, + rule) < 0) + goto no_memory; + } + + + return rule; + + no_memory: + firewall->err = ENOMEM; + virFirewallRuleFree(rule); + return NULL; +} + +/** + * virFirewallAddRule: + * @firewall: firewall ruleset to add to + * @layer: the firewall layer to change + * @...: NULL terminated list of strings for the rule + * + * Add any type of rule to the firewall ruleset. + * + * Returns the new rule + */ +virFirewallRulePtr +virFirewallAddRule(virFirewallPtr firewall, + virFirewallLayer layer, + ...) +{ + virFirewallRulePtr rule; + va_list args; + va_start(args, layer); + rule = virFirewallAddRuleFullV(firewall, layer, false, NULL, NULL, args); + va_end(args); + return rule; +} + + +/** + * virFirewallAddRuleFull: + * @firewall: firewall ruleset to add to + * @layer: the firewall layer to change + * @ignoreErrors: true to ignore failure of the command + * @cb: callback to invoke with result of query + * @opaque: data passed into @cb + * @...: NULL terminated list of strings for the rule + * + * Add any type of rule to the firewall ruleset. Any output + * generated by the addition will be fed into the query + * callback @cb. This callback is permitted to create new + * rules by invoking the virFirewallAddRule method, but + * is not permitted to start new transactions. + * + * If @ignoreErrors is set to TRUE, then any failure of + * the command is ignored. If it is set to FALSE, then + * the behaviour upon failure is determined by the flags + * set when the transaction was started. + * + * Returns the new rule + */ +virFirewallRulePtr virFirewallAddRuleFull(virFirewallPtr firewall, + virFirewallLayer layer, + bool ignoreErrors, + virFirewallQueryCallback cb, + void *opaque, + ...) +{ + virFirewallRulePtr rule; + va_list args; + va_start(args, opaque); + rule = virFirewallAddRuleFullV(firewall, layer, ignoreErrors, cb, opaque, args); + va_end(args); + return rule; +} + + +/** + * virFirewallRemoveRule: + * @firewall: firewall ruleset to remove from + * @rule: the rule to remove + * + * Remove a rule from the current transaction + */ +void virFirewallRemoveRule(virFirewallPtr firewall, + virFirewallRulePtr rule) +{ + size_t i; + virFirewallGroupPtr group; + + /* Explicitly not checking firewall->err too, + * because if rule was partially created + * before hitting error we must still remove + * it to avoid leaking 'rule' + */ + if (!firewall) + return; + + if (firewall->ngroups == 0) + return; + group = firewall->groups[firewall->currentGroup]; + + if (group->addingRollback) { + for (i = 0; i < group->nrollback; i++) { + if (group->rollback[i] == rule) { + VIR_DELETE_ELEMENT(group->rollback, + i, + group->nrollback); + virFirewallRuleFree(rule); + break; + } + } + } else { + for (i = 0; i < group->naction; i++) { + if (group->action[i] == rule) { + VIR_DELETE_ELEMENT(group->action, + i, + group->naction); + virFirewallRuleFree(rule); + return; + } + } + } +} + + +void virFirewallRuleAddArg(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *arg) +{ + VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, rule); + + ADD_ARG(rule, arg); + + return; + + no_memory: + firewall->err = ENOMEM; +} + + +void virFirewallRuleAddArgFormat(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *fmt, ...) +{ + char *arg; + va_list list; + + VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, rule); + + va_start(list, fmt); + + if (virVasprintf(&arg, fmt, list) < 0) + goto no_memory; + + ADD_ARG(rule, arg); + + va_end(list); + + VIR_FREE(arg); + return; + + no_memory: + firewall->err = ENOMEM; + va_end(list); + VIR_FREE(arg); +} + + +void virFirewallRuleAddArgSet(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *const *args) +{ + VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, rule); + + while (*args) { + ADD_ARG(rule, *args); + args++; + } + + return; + + no_memory: + firewall->err = ENOMEM; +} + + +void virFirewallRuleAddArgList(virFirewallPtr firewall, + virFirewallRulePtr rule, + ...) +{ + va_list list; + const char *str; + + VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, rule); + + va_start(list, rule); + + while ((str = va_arg(list, char *)) != NULL) { + ADD_ARG(rule, str); + } + + va_end(list); + + return; + + no_memory: + firewall->err = ENOMEM; + va_end(list); +} + + +size_t virFirewallRuleGetArgCount(virFirewallRulePtr rule) +{ + if (!rule) + return 0; + return rule->argsLen; +} + + +/** + * virFirewallStartTransaction: + * @firewall: the firewall ruleset + * @flags: bitset of virFirewallTransactionFlags + * + * Start a new transaction with associated rollback + * block. + * + * Should be followed by calls to add various rules to + * the transaction. Then virFirwallStartRollback should + * be used to provide rules to rollback upon transaction + * failure + */ +void virFirewallStartTransaction(virFirewallPtr firewall, + unsigned int flags) +{ + virFirewallGroupPtr group; + + VIR_FIREWALL_RETURN_IF_ERROR(firewall); + + if (!(group = virFirewallGroupNew())) { + firewall->err = ENOMEM; + return; + } + group->actionFlags = flags; + + if (VIR_EXPAND_N(firewall->groups, + firewall->ngroups, 1) < 0) { + firewall->err = ENOMEM; + virFirewallGroupFree(group); + return; + } + firewall->groups[firewall->ngroups - 1] = group; + firewall->currentGroup = firewall->ngroups - 1; +} + +/** + * virFirewallBeginRollback: + * @firewall: the firewall ruleset + * @flags: bitset of virFirewallRollbackFlags + * + * Mark the beginning of a set of rules able to rollback + * changes in this and all earlier transactions. + * + * Should be followed by calls to add various rules needed + * to rollback state. Then virFirewallStartTransaction + * should be used to indicate the beginning of the next + * transactional ruleset. + */ +void virFirewallStartRollback(virFirewallPtr firewall, + unsigned int flags) +{ + virFirewallGroupPtr group; + + VIR_FIREWALL_RETURN_IF_ERROR(firewall); + + if (firewall->ngroups == 0) { + firewall->err = ENODATA; + return; + } + + group = firewall->groups[firewall->ngroups-1]; + group->rollbackFlags = flags; + group->addingRollback = true; +} + + +static char * +virFirewallRuleToString(virFirewallRulePtr rule) +{ + const char *bin = virFirewallLayerCommandTypeToString(rule->layer); + virBuffer buf = VIR_BUFFER_INITIALIZER; + size_t i; + + virBufferAdd(&buf, bin, -1); + for (i = 0; i < rule->argsLen; i++) { + virBufferAddLit(&buf, " "); + virBufferAdd(&buf, rule->args[i], -1); + } + + return virBufferContentAndReset(&buf); +} + +static int +virFirewallApplyRuleDirect(virFirewallRulePtr rule, + bool ignoreErrors, + char **output) +{ + size_t i; + const char *bin = virFirewallLayerCommandTypeToString(rule->layer); + virCommandPtr cmd = NULL; + int status; + int ret = -1; + char *error = NULL; + + if (!bin) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown firewall layer %d"), + rule->layer); + goto cleanup; + } + + cmd = virCommandNewArgList(bin, NULL); + + for (i = 0; i < rule->argsLen; i++) + virCommandAddArg(cmd, rule->args[i]); + + virCommandSetOutputBuffer(cmd, output); + virCommandSetErrorBuffer(cmd, &error); + + if (virCommandRun(cmd, &status) < 0) + goto cleanup; + + if (status != 0) { + if (ignoreErrors) { + VIR_DEBUG("Ignoring error running command"); + } else { + char *args = virCommandToString(cmd); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to apply firewall rules %s: %s"), + NULLSTR(args), NULLSTR(error)); + VIR_FREE(args); + VIR_FREE(*output); + goto cleanup; + } + } + + ret = 0; + cleanup: + VIR_FREE(error); + virCommandFree(cmd); + return ret; +} + + +#ifdef WITH_DBUS +static int +virFirewallApplyRuleFirewallD(virFirewallRulePtr rule, + bool ignoreErrors, + char **output) +{ + const char *ipv = virFirewallLayerFirewallDTypeToString(rule->layer); + DBusConnection *sysbus = virDBusGetSystemBus(); + DBusMessage *reply = NULL; + DBusError error; + int ret = -1; + + if (!sysbus) + return -1; + + dbus_error_init(&error); + + if (!ipv) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown firewall layer %d"), + rule->layer); + goto cleanup; + } + + if (virDBusCallMethod(sysbus, + &reply, + &error, + VIR_FIREWALL_FIREWALLD_SERVICE, + "/org/fedoraproject/FirewallD1", + "org.fedoraproject.FirewallD1.direct", + "passthrough", + "sa&s", + ipv, + (int)rule->argsLen, + rule->args) < 0) + goto cleanup; + + if (dbus_error_is_set(&error)) { + /* + * As of firewalld-0.3.9.3-1.fc20.noarch the name and + * message fields in the error look like + * + * name="org.freedesktop.DBus.Python.dbus.exceptions.DBusException" + * message="COMMAND_FAILED: '/sbin/iptables --table filter --delete + * INPUT --in-interface virbr0 --protocol udp --destination-port 53 + * --jump ACCEPT' failed: iptables: Bad rule (does a matching rule + * exist in that chain?)." + * + * We'd like to only ignore DBus errors precisely related to the failure + * of iptables/ebtables commands. A well designed DBus interface would + * return specific named exceptions not the top level generic python dbus + * exception name. With this current scheme our only option is todo a + * sub-string match for 'COMMAND_FAILED' on the message. eg like + * + * if (ignoreErrors && + * STREQ(error.name, + * "org.freedesktop.DBus.Python.dbus.exceptions.DBusException") && + * STRPREFIX(error.message, "COMMAND_FAILED")) + * ... + * + * But this risks our error detecting code being broken if firewalld changes + * ever alter the message string, so we're avoiding doing that. + */ + if (ignoreErrors) { + VIR_DEBUG("Ignoring error '%s': '%s'", + error.name, error.message); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to apply rule '%s'"), + error.message); + goto cleanup; + } + } else { + if (virDBusMessageRead(reply, "s", output) < 0) + goto cleanup; + } + + ret = 0; + + cleanup: + dbus_error_free(&error); + if (reply) + dbus_message_unref(reply); + return ret; +} +#endif + +static int +virFirewallApplyRule(virFirewallPtr firewall, + virFirewallRulePtr rule, + bool ignoreErrors) +{ + char *output = NULL; + char **lines = NULL; + int ret = -1; + char *str = virFirewallRuleToString(rule); + VIR_INFO("Applying rule '%s'", NULLSTR(str)); + VIR_FREE(str); + + if (rule->ignoreErrors) + ignoreErrors = rule->ignoreErrors; + + switch (currentBackend) { + case VIR_FIREWALL_BACKEND_DIRECT: + if (virFirewallApplyRuleDirect(rule, ignoreErrors, &output) < 0) + return -1; + break; +#if WITH_DBUS + case VIR_FIREWALL_BACKEND_FIREWALLD: + if (virFirewallApplyRuleFirewallD(rule, ignoreErrors, &output) < 0) + return -1; + break; +#endif + default: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpected firewall engine backend")); + return -1; + } + + if (rule->queryCB && output) { + if (!(lines = virStringSplit(output, "\n", -1))) + goto cleanup; + + VIR_DEBUG("Invoking query %p with '%s'", rule->queryCB, output); + if (rule->queryCB(firewall, (const char *const *)lines, rule->queryOpaque) < 0) + goto cleanup; + + if (firewall->err == ENOMEM) { + virReportOOMError(); + goto cleanup; + } + if (firewall->err) { + virReportSystemError(firewall->err, "%s", + _("Unable to create rule")); + goto cleanup; + } + + } + + ret = 0; + cleanup: + virStringFreeList(lines); + VIR_FREE(output); + return ret; +} + +static int +virFirewallApplyGroup(virFirewallPtr firewall, + size_t idx) +{ + virFirewallGroupPtr group = firewall->groups[idx]; + bool ignoreErrors = (group->actionFlags & VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); + size_t i; + + VIR_INFO("Starting transaction for %p flags=%x", + group, group->actionFlags); + firewall->currentGroup = idx; + group->addingRollback = false; + for (i = 0; i < group->naction; i++) { + if (virFirewallApplyRule(firewall, + group->action[i], + ignoreErrors) < 0) + return -1; + } + return 0; +} + + +static void +virFirewallRollbackGroup(virFirewallPtr firewall, + size_t idx) +{ + virFirewallGroupPtr group = firewall->groups[idx]; + size_t i; + + VIR_INFO("Starting rollback for group %p", group); + firewall->currentGroup = idx; + group->addingRollback = true; + for (i = 0; i < group->nrollback; i++) { + ignore_value(virFirewallApplyRule(firewall, + group->rollback[i], + true)); + } +} + + +int +virFirewallApply(virFirewallPtr firewall) +{ + size_t i, j; + int ret = -1; + + virMutexLock(&ruleLock); + if (virFirewallInitialize() < 0) + goto cleanup; + + if (!firewall || firewall->err == ENOMEM) { + virReportOOMError(); + goto cleanup; + } + if (firewall->err) { + virReportSystemError(firewall->err, "%s", + _("Unable to create rule")); + goto cleanup; + } + + VIR_DEBUG("Applying groups for %p", firewall); + for (i = 0; i < firewall->ngroups; i++) { + if (virFirewallApplyGroup(firewall, i) < 0) { + VIR_DEBUG("Rolling back groups upto %zu for %p", i, firewall); + size_t first = i; + virErrorPtr saved_error = virSaveLastError(); + + /* + * Look at any inheritance markers to figure out + * what the first rollback group we need to apply is + */ + for (j = 0; j <= i; j++) { + VIR_DEBUG("Checking inheritance of group %zu", i - j); + if (firewall->groups[i - j]->rollbackFlags & + VIR_FIREWALL_ROLLBACK_INHERIT_PREVIOUS) + first = (i - j) - 1; + } + /* + * Now apply all rollback groups in order + */ + for (j = first; j <= i; j++) { + VIR_DEBUG("Rolling back group %zu", j); + virFirewallRollbackGroup(firewall, j); + } + + virSetError(saved_error); + virFreeError(saved_error); + VIR_DEBUG("Done rolling back groups for %p", firewall); + goto cleanup; + } + } + VIR_DEBUG("Done applying groups for %p", firewall); + + ret = 0; + cleanup: + virMutexUnlock(&ruleLock); + return ret; +} diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h new file mode 100644 index 0000000..5ca66fa --- /dev/null +++ b/src/util/virfirewall.h @@ -0,0 +1,109 @@ + /* + * virfirewall.h: integration with firewalls + * + * 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 + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Daniel P. Berrange <berrange@redhat.com> + */ + +#ifndef __VIR_FIREWALL_H__ +# define __VIR_FIREWALL_H__ + +# include "internal.h" + +typedef struct _virFirewall virFirewall; +typedef virFirewall *virFirewallPtr; + +typedef struct _virFirewallRule virFirewallRule; +typedef virFirewallRule *virFirewallRulePtr; + +typedef enum { + VIR_FIREWALL_LAYER_ETHERNET, + VIR_FIREWALL_LAYER_IPV4, + VIR_FIREWALL_LAYER_IPV6, + + VIR_FIREWALL_LAYER_LAST, +} virFirewallLayer; + +virFirewallPtr virFirewallNew(void); + +void virFirewallFree(virFirewallPtr firewall); + +virFirewallRulePtr virFirewallAddRule(virFirewallPtr firewall, + virFirewallLayer layer, + ...) + ATTRIBUTE_SENTINEL; + +typedef int (*virFirewallQueryCallback)(virFirewallPtr firewall, + const char *const *lines, + void *opaque); + +virFirewallRulePtr virFirewallAddRuleFull(virFirewallPtr firewall, + virFirewallLayer layer, + bool ignoreErrors, + virFirewallQueryCallback cb, + void *opaque, + ...) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_SENTINEL; + +void virFirewallRemoveRule(virFirewallPtr firewall, + virFirewallRulePtr rule); + +void virFirewallRuleAddArg(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *arg) + ATTRIBUTE_NONNULL(3); + +void virFirewallRuleAddArgFormat(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *fmt, ...) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_FMT_PRINTF(3, 4); + +void virFirewallRuleAddArgSet(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *const *args) + ATTRIBUTE_NONNULL(3); + +void virFirewallRuleAddArgList(virFirewallPtr firewall, + virFirewallRulePtr rule, + ...) + ATTRIBUTE_SENTINEL; + +size_t virFirewallRuleGetArgCount(virFirewallRulePtr rule); + +typedef enum { + /* Ignore all errors when applying rules, so no + * rollback block will be required */ + VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS = (1 << 0), +} virFirewallTransactionFlags; + +void virFirewallStartTransaction(virFirewallPtr firewall, + unsigned int flags); + +typedef enum { + /* Execute previous rollback block before this + * one, to chain cleanup */ + VIR_FIREWALL_ROLLBACK_INHERIT_PREVIOUS = (1 << 0), +} virFirewallRollbackFlags; + +void virFirewallStartRollback(virFirewallPtr firewall, + unsigned int flags); + +int virFirewallApply(virFirewallPtr firewall); + +#endif /* __VIR_FIREWALL_H__ */ diff --git a/src/util/virfirewallpriv.h b/src/util/virfirewallpriv.h new file mode 100644 index 0000000..130aaa1 --- /dev/null +++ b/src/util/virfirewallpriv.h @@ -0,0 +1,45 @@ +/* + * virfirewallpriv.h: integration with firewalls private APIs + * + * Copyright (C) 2013 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 + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Daniel P. Berrange <berrange@redhat.com> + */ + +#ifndef __VIR_FIREWALL_PRIV_H_ALLOW__ +# error "virfirewallpriv.h may only be included by virfirewall.c or test suites" +#endif + +#ifndef __VIR_FIREWALL_PRIV_H__ +# define __VIR_FIREWALL_PRIV_H__ + +# include "virfirewall.h" + +# define VIR_FIREWALL_FIREWALLD_SERVICE "org.fedoraproject.FirewallD1" + +typedef enum { + VIR_FIREWALL_BACKEND_AUTOMATIC, + VIR_FIREWALL_BACKEND_DIRECT, + VIR_FIREWALL_BACKEND_FIREWALLD, + + VIR_FIREWALL_BACKEND_LAST, +} virFirewallBackend; + +int virFirewallSetBackend(virFirewallBackend backend); + +#endif /* __VIR_FIREWALL_PRIV_H__ */ diff --git a/tests/Makefile.am b/tests/Makefile.am index c13cc15..a10919d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -148,6 +148,7 @@ test_programs = virshtest sockettest \ virpcitest \ virendiantest \ virfiletest \ + virfirewalltest \ viriscsitest \ virkeycodetest \ virlockspacetest \ @@ -998,6 +999,12 @@ virfiletest_SOURCES = \ virfiletest.c testutils.h testutils.c virfiletest_LDADD = $(LDADDS) +virfirewalltest_SOURCES = \ + virfirewalltest.c testutils.h testutils.c +virfirewalltest_LDADD = $(LDADDS) +virfirewalltest_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) +virfirewalltest_LDFLAGS = $(DRIVER_MODULE_LDFLAGS) + jsontest_SOURCES = \ jsontest.c testutils.h testutils.c jsontest_LDADD = $(LDADDS) diff --git a/tests/testutils.c b/tests/testutils.c index 9767a78..022d543 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -459,10 +459,20 @@ int virtTestDifference(FILE *stream, const char *expect, const char *actual) { - const char *expectStart = expect; - const char *expectEnd = expect + (strlen(expect)-1); - const char *actualStart = actual; - const char *actualEnd = actual + (strlen(actual)-1); + const char *expectStart; + const char *expectEnd; + const char *actualStart; + const char *actualEnd; + + if (!expect) + expect = ""; + if (!actual) + actual = ""; + + expectStart = expect; + expectEnd = expect + (strlen(expect)-1); + actualStart = actual; + actualEnd = actual + (strlen(actual)-1); if (!virTestGetDebug()) return 0; diff --git a/tests/virfirewalltest.c b/tests/virfirewalltest.c new file mode 100644 index 0000000..805fa44 --- /dev/null +++ b/tests/virfirewalltest.c @@ -0,0 +1,1186 @@ +/* + * Copyright (C) 2013-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 + * <http://www.gnu.org/licenses/>. + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */ + +#include <config.h> + +#define __VIR_FIREWALL_PRIV_H_ALLOW__ +#define __VIR_COMMAND_PRIV_H_ALLOW__ + +#include "testutils.h" +#include "virbuffer.h" +#include "vircommandpriv.h" +#include "virfirewallpriv.h" +#include "virmock.h" +#include "virdbuspriv.h" + +#define VIR_FROM_THIS VIR_FROM_FIREWALL + +#if WITH_DBUS +# include <dbus/dbus.h> +#endif + +static bool fwDisabled = true; +static virBufferPtr fwBuf; +static bool fwError; + +#define TEST_FILTER_TABLE_LIST \ + "Chain INPUT (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain FORWARD (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain OUTPUT (policy ACCEPT)\n" \ + "target prot opt source destination\n" + +#define TEST_NAT_TABLE_LIST \ + "Chain PREROUTING (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain INPUT (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain OUTPUT (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain POSTROUTING (policy ACCEPT)\n" \ + "target prot opt source destination\n" + +#if WITH_DBUS +VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, + DBusMessage *, + DBusConnection *, connection, + DBusMessage *, message, + int, timeout_milliseconds, + DBusError *, error) +{ + DBusMessage *reply = NULL; + const char *service = dbus_message_get_destination(message); + const char *member = dbus_message_get_member(message); + size_t i; + size_t nargs = 0; + char **args = NULL; + char *type = NULL; + + VIR_MOCK_IMPL_INIT_REAL(dbus_connection_send_with_reply_and_block); + + if (STREQ(service, "org.freedesktop.DBus") && + STREQ(member, "ListNames")) { + const char *svc1 = "org.foo.bar.wizz"; + const char *svc2 = VIR_FIREWALL_FIREWALLD_SERVICE; + DBusMessageIter iter; + DBusMessageIter sub; + reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + "s", &sub); + + if (!dbus_message_iter_append_basic(&sub, + DBUS_TYPE_STRING, + &svc1)) + goto error; + if (!fwDisabled && + !dbus_message_iter_append_basic(&sub, + DBUS_TYPE_STRING, + &svc2)) + goto error; + dbus_message_iter_close_container(&iter, &sub); + } else if (STREQ(service, VIR_FIREWALL_FIREWALLD_SERVICE) && + STREQ(member, "passthrough")) { + bool isAdd = false; + bool doError = false; + + if (virDBusMessageDecode(message, + "sa&s", + &type, + &nargs, + &args) < 0) + goto error; + + for (i = 0; i < nargs; i++) { + /* Fake failure on the command with this IP addr */ + if (STREQ(args[i], "-A")) { + isAdd = true; + } else if (isAdd && STREQ(args[i], "192.168.122.255")) { + doError = true; + } + } + + if (fwBuf) { + if (STREQ(type, "ipv4")) + virBufferAddLit(fwBuf, IPTABLES_PATH); + else if (STREQ(type, "ipv4")) + virBufferAddLit(fwBuf, IP6TABLES_PATH); + else + virBufferAddLit(fwBuf, EBTABLES_PATH); + } + for (i = 0; i < nargs; i++) { + if (fwBuf) { + virBufferAddLit(fwBuf, " "); + virBufferEscapeShell(fwBuf, args[i]); + } + } + if (fwBuf) + virBufferAddLit(fwBuf, "\n"); + if (doError) { + dbus_set_error_const(error, + "org.firewalld.error", + "something bad happened"); + } else { + if (nargs == 1 && + STREQ(type, "ipv4") && + STREQ(args[0], "-L")) { + if (virDBusCreateReply(&reply, + "s", TEST_FILTER_TABLE_LIST) < 0) + goto error; + } else if (nargs == 3 && + STREQ(type, "ipv4") && + STREQ(args[0], "-t") && + STREQ(args[1], "nat") && + STREQ(args[2], "-L")) { + if (virDBusCreateReply(&reply, + "s", TEST_NAT_TABLE_LIST) < 0) + goto error; + } else { + if (virDBusCreateReply(&reply, + "s", "success") < 0) + goto error; + } + } + } else { + reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); + } + + cleanup: + VIR_FREE(type); + for (i = 0; i < nargs; i++) + VIR_FREE(args[i]); + VIR_FREE(args); + return reply; + + error: + if (reply) + dbus_message_unref(reply); + reply = NULL; + if (error && !dbus_error_is_set(error)) + dbus_set_error_const(error, + "org.firewalld.error", + "something unexpected happened"); + + goto cleanup; +} +#endif + +struct testFirewallData { + virFirewallBackend tryBackend; + virFirewallBackend expectBackend; + bool fwDisabled; +}; + +static int +testFirewallSingleGroup(const void *opaque) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) + virCommandSetDryRun(&cmdbuf, NULL, NULL); + else + fwBuf = &cmdbuf; + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static int +testFirewallRemoveRule(const void *opaque) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + virFirewallRulePtr fwrule; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) + virCommandSetDryRun(&cmdbuf, NULL, NULL); + else + fwBuf = &cmdbuf; + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", NULL); + virFirewallRuleAddArg(fw, fwrule, "--source-host"); + virFirewallRemoveRule(fw, fwrule); + + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", NULL); + virFirewallRuleAddArg(fw, fwrule, "--source-host"); + virFirewallRuleAddArgFormat(fw, fwrule, "%s", "!192.168.122.1"); + virFirewallRuleAddArgList(fw, fwrule, "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static int +testFirewallManyGroups(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n" + IPTABLES_PATH " -A OUTPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A OUTPUT --jump DROP\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) + virCommandSetDryRun(&cmdbuf, NULL, NULL); + else + fwBuf = &cmdbuf; + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--jump", "DROP", NULL); + + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static void +testFirewallRollbackHook(const char *const*args, + const char *const*env ATTRIBUTE_UNUSED, + const char *input ATTRIBUTE_UNUSED, + char **output ATTRIBUTE_UNUSED, + char **error ATTRIBUTE_UNUSED, + int *status, + void *opaque ATTRIBUTE_UNUSED) +{ + bool isAdd = false; + while (*args) { + /* Fake failure on the command with this IP addr */ + if (STREQ(*args, "-A")) { + isAdd = true; + } else if (isAdd && STREQ(*args, "192.168.122.255")) { + *status = 127; + break; + } + args++; + } +} + +static int +testFirewallIgnoreFailGroup(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -A OUTPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A OUTPUT --jump DROP\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--jump", "DROP", NULL); + + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static int +testFirewallIgnoreFailRule(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -A OUTPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A OUTPUT --jump DROP\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_IPV4, + true, NULL, NULL, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--jump", "DROP", NULL); + + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static int +testFirewallNoRollback(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) == 0) { + fprintf(stderr, "Firewall apply unexpectedly worked\n"); + goto cleanup; + } + + if (virtTestOOMActive()) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static int +testFirewallSingleRollback(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwError = true; + fwBuf = &cmdbuf; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) == 0) { + fprintf(stderr, "Firewall apply unexpectedly worked\n"); + goto cleanup; + } + + if (virtTestOOMActive()) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static int +testFirewallManyRollback(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) == 0) { + fprintf(stderr, "Firewall apply unexpectedly worked\n"); + goto cleanup; + } + + if (virtTestOOMActive()) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static int +testFirewallChainedRollback(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.127 --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.127 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.127", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.127", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, VIR_FIREWALL_ROLLBACK_INHERIT_PREVIOUS); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) == 0) { + fprintf(stderr, "Firewall apply unexpectedly worked\n"); + goto cleanup; + } + + if (virtTestOOMActive()) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static const char *expectedLines[] = { + "Chain INPUT (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain FORWARD (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain OUTPUT (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain PREROUTING (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain INPUT (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain OUTPUT (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain POSTROUTING (policy ACCEPT)", + "target prot opt source destination", + "", +}; +static size_t expectedLineNum; +static bool expectedLineError; + +static void +testFirewallQueryHook(const char *const*args, + const char *const*env ATTRIBUTE_UNUSED, + const char *input ATTRIBUTE_UNUSED, + char **output, + char **error ATTRIBUTE_UNUSED, + int *status, + void *opaque ATTRIBUTE_UNUSED) +{ + if (STREQ(args[0], IPTABLES_PATH) && + STREQ(args[1], "-L")) { + if (VIR_STRDUP(*output, TEST_FILTER_TABLE_LIST) < 0) + *status = 127; + } else if (STREQ(args[0], IPTABLES_PATH) && + STREQ(args[1], "-t") && + STREQ(args[2], "nat") && + STREQ(args[3], "-L")) { + if (VIR_STRDUP(*output, TEST_NAT_TABLE_LIST) < 0) + *status = 127; + } +} + + +static int +testFirewallQueryCallback(virFirewallPtr fw, + const char *const *lines, + void *opaque ATTRIBUTE_UNUSED) +{ + size_t i; + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.129", + "--jump", "REJECT", NULL); + + for (i = 0; lines[i] != NULL; i++) { + if (expectedLineNum >= ARRAY_CARDINALITY(expectedLines)) { + expectedLineError = true; + break; + } + if (STRNEQ(expectedLines[expectedLineNum], lines[i])) { + fprintf(stderr, "Mismatch '%s' vs '%s' at %zu, %zu\n", + expectedLines[expectedLineNum], lines[i], + expectedLineNum, i); + expectedLineError = true; + break; + } + expectedLineNum++; + } + return 0; +} + +static int +testFirewallQuery(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.127 --jump REJECT\n" + IPTABLES_PATH " -L\n" + IPTABLES_PATH " -t nat -L\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.130 --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.129' --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.129' --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.128 --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + expectedLineNum = 0; + expectedLineError = false; + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallQueryHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.127", + "--jump", "REJECT", NULL); + + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_IPV4, + false, + testFirewallQueryCallback, + NULL, + "-L", NULL); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_IPV4, + false, + testFirewallQueryCallback, + NULL, + "-t", "nat", "-L", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.130", + "--jump", "REJECT", NULL); + + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.128", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (expectedLineError) { + fprintf(stderr, "Got some unexpected query data\n"); + goto cleanup; + } + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static int +mymain(void) +{ + int ret = 0; + +#define RUN_TEST_DIRECT(name, method) \ + do { \ + struct testFirewallData data; \ + data.tryBackend = VIR_FIREWALL_BACKEND_AUTOMATIC; \ + data.expectBackend = VIR_FIREWALL_BACKEND_DIRECT; \ + data.fwDisabled = true; \ + if (virtTestRun(name " auto direct", method, &data) < 0) \ + ret = -1; \ + data.tryBackend = VIR_FIREWALL_BACKEND_DIRECT; \ + data.expectBackend = VIR_FIREWALL_BACKEND_DIRECT; \ + data.fwDisabled = true; \ + if (virtTestRun(name " manual direct", method, &data) < 0) \ + ret = -1; \ + } while (0) + +#if WITH_DBUS +# define RUN_TEST_FIREWALLD(name, method) \ + do { \ + struct testFirewallData data; \ + data.tryBackend = VIR_FIREWALL_BACKEND_AUTOMATIC; \ + data.expectBackend = VIR_FIREWALL_BACKEND_FIREWALLD; \ + data.fwDisabled = false; \ + if (virtTestRun(name " auto firewalld", method, &data) < 0) \ + ret = -1; \ + data.tryBackend = VIR_FIREWALL_BACKEND_FIREWALLD; \ + data.expectBackend = VIR_FIREWALL_BACKEND_FIREWALLD; \ + data.fwDisabled = false; \ + if (virtTestRun(name " manual firewalld", method, &data) < 0) \ + ret = -1; \ + } while (0) + +# define RUN_TEST(name, method) \ + RUN_TEST_DIRECT(name, method); \ + RUN_TEST_FIREWALLD(name, method) +#else /* ! WITH_DBUS */ +# define RUN_TEST(name, method) \ + RUN_TEST_DIRECT(name, method) +#endif /* ! WITH_DBUS */ + + RUN_TEST("single group", testFirewallSingleGroup); + RUN_TEST("remove rule", testFirewallRemoveRule); + RUN_TEST("many groups", testFirewallManyGroups); + RUN_TEST("ignore fail group", testFirewallIgnoreFailGroup); + RUN_TEST("ignore fail rule", testFirewallIgnoreFailRule); + RUN_TEST("no rollback", testFirewallNoRollback); + RUN_TEST("single rollback", testFirewallSingleRollback); + RUN_TEST("many rollback", testFirewallManyRollback); + RUN_TEST("chained rollback", testFirewallChainedRollback); + RUN_TEST("query transaction", testFirewallQuery); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +#if WITH_DBUS +VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virmockdbus.so") +#else +VIRT_TEST_MAIN(mymain) +#endif -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
The network and nwfilter drivers both have a need to update firewall rules. The currently share no code for interacting with iptables / firewalld. The nwfilter driver is fairly tied to the concept of creating shell scripts to execute which makes it very hard to port to talk to firewalld via DBus APIs.
This patch introduces a virFirewallPtr object which is able to represent a complete sequence of rule changes, with the ability to have multiple transactional checkpoints with rollbacks. By formally separating the definition of the rules to be applied from the mechanism used to apply them, it is also possible to write a firewall engine that uses firewalld DBus APIs natively instead of via the slow firewalld-cmd.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
[...]
+ # util/virhash.h virHashAddEntry; virHashCreate; diff --git a/src/util/virerror.c b/src/util/virerror.c index cbbaa83..e0bc970 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -129,6 +129,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST, "Systemd", "Bhyve", "Crypto", + "Firewall", )
+static int +virFirewallValidateBackend(virFirewallBackend backend) +{ + VIR_DEBUG("Validating backend %d", backend); +#if WITH_DBUS + if (backend == VIR_FIREWALL_BACKEND_AUTOMATIC || + backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + int rv = virDBusIsServiceRegistered(VIR_FIREWALL_FIREWALLD_SERVICE);
Nit: empty line after var. decl. ?
+ VIR_DEBUG("Firewalled is registered ? %d", rv); + if (rv < 0) { + if (rv == -2) { + if (backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("firewalld firewall backend requested, but service is not running")); + return -1; + } else { + VIR_DEBUG("firewalld service not running, trying direct backend"); + backend = VIR_FIREWALL_BACKEND_DIRECT; + } + } else { + return -1; + } + } else { + VIR_DEBUG("firewalld service running, using firewalld backend"); + backend = VIR_FIREWALL_BACKEND_FIREWALLD; + } + } +#else + if (backend == VIR_FIREWALL_BACKEND_AUTOMATIC) { + VIR_DEBUG("DBus support disabled, trying direct backend"); + backend = VIR_FIREWALL_BACKEND_DIRECT; + } else if (backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("firewalld firewall backend requested, but DBus support disabled")); + return -1; + } +#endif + + if (backend == VIR_FIREWALL_BACKEND_DIRECT) { + const char *commands[] = { + IPTABLES_PATH, IP6TABLES_PATH, EBTABLES_PATH + }; + size_t i;
Also here? + +#define VIR_FIREWALL_RETURN_IF_ERROR(firewall) \ + if (!firewall || firewall->err) \ + return; + +#define VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, ruel)\ ruel -> rule -- seems unused since it compiles + +int +virFirewallApply(virFirewallPtr firewall) +{ + size_t i, j; + int ret = -1; + + virMutexLock(&ruleLock); + if (virFirewallInitialize() < 0) + goto cleanup; + + if (!firewall || firewall->err == ENOMEM) { + virReportOOMError(); + goto cleanup; + } + if (firewall->err) { + virReportSystemError(firewall->err, "%s", + _("Unable to create rule")); + goto cleanup; + } + + VIR_DEBUG("Applying groups for %p", firewall); + for (i = 0; i < firewall->ngroups; i++) { + if (virFirewallApplyGroup(firewall, i) < 0) { + VIR_DEBUG("Rolling back groups upto %zu for %p", i, firewall); + size_t first = i; + virErrorPtr saved_error = virSaveLastError(); + + /* + * Look at any inheritance markers to figure out + * what the first rollback group we need to apply is + */ + for (j = 0; j <= i; j++) { + VIR_DEBUG("Checking inheritance of group %zu", i - j); + if (firewall->groups[i - j]->rollbackFlags & + VIR_FIREWALL_ROLLBACK_INHERIT_PREVIOUS) + first = (i - j) - 1; if j = i then first = -1. This doesn't seem right. Limit the loop test to j < i ?
+ } + /* + * Now apply all rollback groups in order + */ + for (j = first; j <= i; j++) { + VIR_DEBUG("Rolling back group %zu", j); + virFirewallRollbackGroup(firewall, j); + } + + virSetError(saved_error); + virFreeError(saved_error); + VIR_DEBUG("Done rolling back groups for %p", firewall); + goto cleanup; + } + } + VIR_DEBUG("Done applying groups for %p", firewall); + + ret = 0; + cleanup: + virMutexUnlock(&ruleLock); + return ret; +}
+ +static int +testFirewallChainedRollback(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.127 --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.127 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); +
Hm, wondering why this rule doesn't make it into the expected output...
+ + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.127", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.127", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, VIR_FIREWALL_ROLLBACK_INHERIT_PREVIOUS); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) == 0) { + fprintf(stderr, "Firewall apply unexpectedly worked\n"); + goto cleanup; + } + + if (virtTestOOMActive()) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} +
ACK with nits addressed.

On Tue, Apr 15, 2014 at 05:15:02PM -0400, Stefan Berger wrote:
On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
The network and nwfilter drivers both have a need to update firewall rules. The currently share no code for interacting with iptables / firewalld. The nwfilter driver is fairly tied to the concept of creating shell scripts to execute which makes it very hard to port to talk to firewalld via DBus APIs.
This patch introduces a virFirewallPtr object which is able to represent a complete sequence of rule changes, with the ability to have multiple transactional checkpoints with rollbacks. By formally separating the definition of the rules to be applied from the mechanism used to apply them, it is also possible to write a firewall engine that uses firewalld DBus APIs natively instead of via the slow firewalld-cmd.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
[...]
+ # util/virhash.h virHashAddEntry; virHashCreate; diff --git a/src/util/virerror.c b/src/util/virerror.c index cbbaa83..e0bc970 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -129,6 +129,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST, "Systemd", "Bhyve", "Crypto", + "Firewall", )
[ ... ]
+#define VIR_FIREWALL_RETURN_IF_ERROR(firewall) \ + if (!firewall || firewall->err) \ + return; +
I have a strong prejudice *against* writing statements in a macro *unless* the macro expands as a SINGLE statement under all possible usage scenarios; otherwise the macro is just a latent problem waiting to happen. Consider what happens if I use the macro like this: 1: if (condition) 2: VIR_FIREWALL_RETURN_IF_ERROR(fw) 3: else 4: DO_SOMETHING_ELSE(fw); # test some other condition I don't get what I expected; the =else= on line 3 matches with the =if= hidden in the macro on line 2, not with the =if= on line 1! Please *consider* defining the macro like this: #define VIR_FIREWALL_RETURN_IF_ERROR(firewall) \ do { \ if (!firewall || firewall->err) \ return; \ } while (0) The "do { ... } while (0)" is a single statement that is guaranteed to execute exactly once. Modern compilers will notice and get rid of the loop, so there is no overhead. Also note the trailing ";" is omitted. This goes back to a time when compilers would complain about two semicolons in a row with no intervening statement, but I don't think that is common these days.
ACK with nits addressed.
Ditto. -Jeff

On 04/08/2014 05:38 PM, Daniel P. Berrange wrote:
The network and nwfilter drivers both have a need to update firewall rules. The currently share no code for interacting with iptables / firewalld. The nwfilter driver is fairly tied to the concept of creating shell scripts to execute which makes it very hard to port to talk to firewalld via DBus APIs.
This patch introduces a virFirewallPtr object which is able to represent a complete sequence of rule changes, with the ability to have multiple transactional checkpoints with rollbacks. By formally separating the definition of the rules to be applied from the mechanism used to apply them, it is also possible to write a firewall engine that uses firewalld DBus APIs natively instead of via the slow firewalld-cmd.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> ---
+ +static int +virFirewallOnceInit(void) +{ + return virFirewallValidateBackend(currentBackend); +} + +VIR_ONCE_GLOBAL_INIT(virFirewall) + +static int +virFirewallValidateBackend(virFirewallBackend backend) +{ + VIR_DEBUG("Validating backend %d", backend); +#if WITH_DBUS + if (backend == VIR_FIREWALL_BACKEND_AUTOMATIC || + backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + int rv = virDBusIsServiceRegistered(VIR_FIREWALL_FIREWALLD_SERVICE); + VIR_DEBUG("Firewalled is registered ? %d", rv);
s/Firewalled/Firewalld/
+ if (rv < 0) { + if (rv == -2) { + if (backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("firewalld firewall backend requested, but service is not running"));
+#define VIR_FIREWALL_RETURN_IF_ERROR(firewall) \ + if (!firewall || firewall->err) \ + return; + +#define VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, ruel)\
s/ruel/rule
+ if (!firewall || firewall->err || !rule) \ + return; +
@@ -998,6 +999,12 @@ virfiletest_SOURCES = \ virfiletest.c testutils.h testutils.c virfiletest_LDADD = $(LDADDS)
+virfirewalltest_SOURCES = \ + virfirewalltest.c testutils.h testutils.c +virfirewalltest_LDADD = $(LDADDS) +virfirewalltest_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
+virfirewalltest_LDFLAGS = $(DRIVER_MODULE_LDFLAGS)
This breaks the test when built --without-driver-modules. As of commit 844a5c1, omitting the LDFLAGS line should be fine.
+ jsontest_SOURCES = \ jsontest.c testutils.h testutils.c jsontest_LDADD = $(LDADDS)
Jan

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
The network and nwfilter drivers both have a need to update firewall rules. The currently share no code for interacting with iptables / firewalld. The nwfilter driver is fairly tied to the concept of creating shell scripts to execute which makes it very hard to port to talk to firewalld via DBus APIs.
This patch introduces a virFirewallPtr object which is able to represent a complete sequence of rule changes, with the ability to have multiple transactional checkpoints with rollbacks. By formally separating the definition of the rules to be applied from the mechanism used to apply them, it is also possible to write a firewall engine that uses firewalld DBus APIs natively instead of via the slow firewalld-cmd.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
You should add this here: --- ./po/POTFILES.in +++ ./po/POTFILES.in @@ -163,7 +163,6 @@ src/util/virerror.h src/util/vireventpoll.c src/util/virfile.c +src/util/virfirewall.c src/util/virhash.c src/util/virhook.c src/util/virhostdev.c Regards, Stefan

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
The network and nwfilter drivers both have a need to update firewall rules. The currently share no code for interacting with iptables / firewalld. The nwfilter driver is fairly tied to the concept of creating shell scripts to execute which makes it very hard to port to talk to firewalld via DBus APIs.
This patch introduces a virFirewallPtr object which is able to represent a complete sequence of rule changes, with the ability to have multiple transactional checkpoints with rollbacks. By formally separating the definition of the rules to be applied from the mechanism used to apply them, it is also possible to write a firewall engine that uses firewalld DBus APIs natively instead of via the slow firewalld-cmd.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- include/libvirt/virterror.h | 1 + po/POTFILES.in | 1 + src/Makefile.am | 2 + src/libvirt_private.syms | 17 + src/util/virerror.c | 1 + src/util/virfirewall.c | 922 +++++++++++++++++++++++++++++++++ src/util/virfirewall.h | 109 ++++ src/util/virfirewallpriv.h | 45 ++ tests/Makefile.am | 7 + tests/testutils.c | 18 +- tests/virfirewalltest.c | 1186 +++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 2305 insertions(+), 4 deletions(-) create mode 100644 src/util/virfirewall.c create mode 100644 src/util/virfirewall.h create mode 100644 src/util/virfirewallpriv.h create mode 100644 tests/virfirewalltest.c
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 495c121..be90797 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -122,6 +122,7 @@ typedef enum { VIR_FROM_SYSTEMD = 56, /* Error from systemd code */ VIR_FROM_BHYVE = 57, /* Error from bhyve driver */ VIR_FROM_CRYPTO = 58, /* Error from crypto code */ + VIR_FROM_FIREWALL = 59, /* Error from firewall */
# ifdef VIR_ENUM_SENTINELS VIR_ERR_DOMAIN_LAST diff --git a/po/POTFILES.in b/po/POTFILES.in index 122b853..e35eb82 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -161,6 +161,7 @@ src/util/virdbus.c src/util/virdnsmasq.c src/util/vireventpoll.c src/util/virfile.c +src/util/virfirewall.c src/util/virhash.c src/util/virhook.c src/util/virhostdev.c diff --git a/src/Makefile.am b/src/Makefile.am index 7e9a702..7615294 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -106,6 +106,8 @@ UTIL_SOURCES = \ util/virevent.c util/virevent.h \ util/vireventpoll.c util/vireventpoll.h \ util/virfile.c util/virfile.h \ + util/virfirewall.c util/virfirewall.h \ + util/virfirewallpriv.h \ util/virhash.c util/virhash.h \ util/virhashcode.c util/virhashcode.h \ util/virhook.c util/virhook.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0c2cf75..18be0e1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1277,6 +1277,23 @@ virFileWriteStr; virFindFileInPath;
+# util/virfirewall.h +virFirewallAddRule; +virFirewallAddRuleFull; +virFirewallApply; +virFirewallFree; +virFirewallNew; +virFirewallRemoveRule; +virFirewallRuleAddArg; +virFirewallRuleAddArgFormat; +virFirewallRuleAddArgList; +virFirewallRuleAddArgSet; +virFirewallRuleGetArgCount; +virFirewallSetBackend; +virFirewallStartRollback; +virFirewallStartTransaction; + + # util/virhash.h virHashAddEntry; virHashCreate; diff --git a/src/util/virerror.c b/src/util/virerror.c index cbbaa83..e0bc970 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -129,6 +129,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST, "Systemd", "Bhyve", "Crypto", + "Firewall", )
diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c new file mode 100644 index 0000000..b558d2f --- /dev/null +++ b/src/util/virfirewall.c @@ -0,0 +1,922 @@ +/* + * virfirewall.c: integration with firewalls + * + * Copyright (C) 2013 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 + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Daniel P. Berrange <berrange@redhat.com> + */ + +#include <config.h> + +#define __VIR_FIREWALL_PRIV_H_ALLOW__ + +#include <stdarg.h> + +#include "viralloc.h" +#include "virfirewallpriv.h" +#include "virerror.h" +#include "virutil.h" +#include "virstring.h" +#include "vircommand.h" +#include "virlog.h" +#include "virdbus.h" +#include "virfile.h" +#include "virthread.h" + +#define VIR_FROM_THIS VIR_FROM_FIREWALL + +VIR_LOG_INIT("util.firewall"); + +typedef struct _virFirewallGroup virFirewallGroup; +typedef virFirewallGroup *virFirewallGroupPtr; + +VIR_ENUM_DECL(virFirewallLayerCommand) +VIR_ENUM_IMPL(virFirewallLayerCommand, VIR_FIREWALL_LAYER_LAST, + EBTABLES_PATH, + IPTABLES_PATH, + IP6TABLES_PATH); + +VIR_ENUM_DECL(virFirewallLayerFirewallD) +VIR_ENUM_IMPL(virFirewallLayerFirewallD, VIR_FIREWALL_LAYER_LAST, + "eb", "ipv4", "ipv6") + + +struct _virFirewallRule { + virFirewallLayer layer; + + virFirewallQueryCallback queryCB; + void *queryOpaque; + bool ignoreErrors; + + size_t argsAlloc; + size_t argsLen; + char **args; +}; + +struct _virFirewallGroup { + unsigned int actionFlags; + unsigned int rollbackFlags; + + size_t naction; + virFirewallRulePtr *action; + + size_t nrollback; + virFirewallRulePtr *rollback; + + bool addingRollback; +}; + + +struct _virFirewall { + int err; + + size_t ngroups; + virFirewallGroupPtr *groups; + size_t currentGroup; +}; + +static virFirewallBackend currentBackend = VIR_FIREWALL_BACKEND_AUTOMATIC; +static virMutex ruleLock = VIR_MUTEX_INITIALIZER; + +static int +virFirewallValidateBackend(virFirewallBackend backend); + +static int +virFirewallOnceInit(void) +{ + return virFirewallValidateBackend(currentBackend); +} + +VIR_ONCE_GLOBAL_INIT(virFirewall) + +static int +virFirewallValidateBackend(virFirewallBackend backend) +{ + VIR_DEBUG("Validating backend %d", backend); +#if WITH_DBUS + if (backend == VIR_FIREWALL_BACKEND_AUTOMATIC || + backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + int rv = virDBusIsServiceRegistered(VIR_FIREWALL_FIREWALLD_SERVICE); + VIR_DEBUG("Firewalled is registered ? %d", rv); + if (rv < 0) { + if (rv == -2) { + if (backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("firewalld firewall backend requested, but service is not running")); + return -1; + } else { + VIR_DEBUG("firewalld service not running, trying direct backend"); + backend = VIR_FIREWALL_BACKEND_DIRECT; + } + } else { + return -1; + } + } else { + VIR_DEBUG("firewalld service running, using firewalld backend"); + backend = VIR_FIREWALL_BACKEND_FIREWALLD; + } + } +#else + if (backend == VIR_FIREWALL_BACKEND_AUTOMATIC) { + VIR_DEBUG("DBus support disabled, trying direct backend"); + backend = VIR_FIREWALL_BACKEND_DIRECT; + } else if (backend == VIR_FIREWALL_BACKEND_FIREWALLD) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("firewalld firewall backend requested, but DBus support disabled")); + return -1; + } +#endif + + if (backend == VIR_FIREWALL_BACKEND_DIRECT) { + const char *commands[] = { + IPTABLES_PATH, IP6TABLES_PATH, EBTABLES_PATH + }; + size_t i; + for (i = 0; i < ARRAY_CARDINALITY(commands); i++) { + if (!virFileIsExecutable(commands[i])) { + virReportSystemError(errno, + _("direct firewall backend requested, but %s is not available"), + commands[i]); + return -1; + } + } + VIR_DEBUG("found iptables/ip6tables/ebtables, using direct backend"); + } + + currentBackend = backend; + return 0; +} + +int +virFirewallSetBackend(virFirewallBackend backend) +{ + currentBackend = backend; + + if (virFirewallInitialize() < 0) + return -1; + + return virFirewallValidateBackend(backend); +} + +static virFirewallGroupPtr +virFirewallGroupNew(void) +{ + virFirewallGroupPtr group; + + if (VIR_ALLOC(group) < 0) + return NULL; + + return group; +} + + +/** + * virFirewallNew: + * + * Creates a new firewall ruleset for changing rules + * of @layer. This should be followed by a call to + * virFirewallStartTransaction before adding + * any rules + * + * Returns the new firewall ruleset + */ +virFirewallPtr virFirewallNew(void) +{ + virFirewallPtr firewall; + + if (VIR_ALLOC(firewall) < 0) + return NULL; + + return firewall; +} + + +static void +virFirewallRuleFree(virFirewallRulePtr rule) +{ + size_t i; + + if (!rule) + return; + + for (i = 0; i < rule->argsLen; i++) + VIR_FREE(rule->args[i]); + VIR_FREE(rule->args); + VIR_FREE(rule); +} + + +static void +virFirewallGroupFree(virFirewallGroupPtr group) +{ + size_t i; + + if (!group) + return; + + for (i = 0; i < group->naction; i++) + virFirewallRuleFree(group->action[i]); + VIR_FREE(group->action); + + for (i = 0; i < group->nrollback; i++) + virFirewallRuleFree(group->rollback[i]); + VIR_FREE(group->rollback); + + VIR_FREE(group); +} + + +/** + * virFirewallFree: + * + * Release all memory associated with the firewall + * ruleset + */ +void virFirewallFree(virFirewallPtr firewall) +{ + size_t i; + + if (!firewall) + return; + + for (i = 0; i < firewall->ngroups; i++) + virFirewallGroupFree(firewall->groups[i]); + VIR_FREE(firewall->groups); + + VIR_FREE(firewall); +} + +#define VIR_FIREWALL_RETURN_IF_ERROR(firewall) \ + if (!firewall || firewall->err) \ + return; + +#define VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, ruel)\ + if (!firewall || firewall->err || !rule) \ + return; + +#define VIR_FIREWALL_RETURN_NULL_IF_ERROR(firewall) \ + if (!firewall || firewall->err) \ + return NULL; + +#define ADD_ARG(rule, str) \ + if (VIR_RESIZE_N(rule->args, \ + rule->argsAlloc, \ + rule->argsLen, 1) < 0) \ + goto no_memory; \ + \ + if (VIR_STRDUP(rule->args[rule->argsLen++], str) < 0)\ + goto no_memory; + +static virFirewallRulePtr +virFirewallAddRuleFullV(virFirewallPtr firewall, + virFirewallLayer layer, + bool ignoreErrors, + virFirewallQueryCallback cb, + void *opaque, + va_list args) +{ + virFirewallGroupPtr group; + virFirewallRulePtr rule; + char *str; + + VIR_FIREWALL_RETURN_NULL_IF_ERROR(firewall); + + if (firewall->ngroups == 0) { + firewall->err = ENODATA; + return NULL; + } + group = firewall->groups[firewall->currentGroup]; + + + if (VIR_ALLOC(rule) < 0) + goto no_memory; + + rule->layer = layer; + rule->queryCB = cb; + rule->queryOpaque = opaque; + rule->ignoreErrors = ignoreErrors; + + while ((str = va_arg(args, char *)) != NULL) { + ADD_ARG(rule, str); + } + + if (group->addingRollback) { + if (VIR_APPEND_ELEMENT_COPY(group->rollback, + group->nrollback, + rule) < 0) + goto no_memory; + } else { + if (VIR_APPEND_ELEMENT_COPY(group->action, + group->naction, + rule) < 0) + goto no_memory; + } + + + return rule; + + no_memory: + firewall->err = ENOMEM; + virFirewallRuleFree(rule); + return NULL; +} + +/** + * virFirewallAddRule: + * @firewall: firewall ruleset to add to + * @layer: the firewall layer to change + * @...: NULL terminated list of strings for the rule + * + * Add any type of rule to the firewall ruleset. + * + * Returns the new rule + */ +virFirewallRulePtr +virFirewallAddRule(virFirewallPtr firewall, + virFirewallLayer layer, + ...) +{ + virFirewallRulePtr rule; + va_list args; + va_start(args, layer); + rule = virFirewallAddRuleFullV(firewall, layer, false, NULL, NULL, args); + va_end(args); + return rule; +} + + +/** + * virFirewallAddRuleFull: + * @firewall: firewall ruleset to add to + * @layer: the firewall layer to change + * @ignoreErrors: true to ignore failure of the command + * @cb: callback to invoke with result of query + * @opaque: data passed into @cb + * @...: NULL terminated list of strings for the rule + * + * Add any type of rule to the firewall ruleset. Any output + * generated by the addition will be fed into the query + * callback @cb. This callback is permitted to create new + * rules by invoking the virFirewallAddRule method, but + * is not permitted to start new transactions. + * + * If @ignoreErrors is set to TRUE, then any failure of + * the command is ignored. If it is set to FALSE, then + * the behaviour upon failure is determined by the flags + * set when the transaction was started. + * + * Returns the new rule + */ +virFirewallRulePtr virFirewallAddRuleFull(virFirewallPtr firewall, + virFirewallLayer layer, + bool ignoreErrors, + virFirewallQueryCallback cb, + void *opaque, + ...) +{ + virFirewallRulePtr rule; + va_list args; + va_start(args, opaque); + rule = virFirewallAddRuleFullV(firewall, layer, ignoreErrors, cb, opaque, args); + va_end(args); + return rule; +} + + +/** + * virFirewallRemoveRule: + * @firewall: firewall ruleset to remove from + * @rule: the rule to remove + * + * Remove a rule from the current transaction + */ +void virFirewallRemoveRule(virFirewallPtr firewall, + virFirewallRulePtr rule) +{ + size_t i; + virFirewallGroupPtr group; + + /* Explicitly not checking firewall->err too, + * because if rule was partially created + * before hitting error we must still remove + * it to avoid leaking 'rule' + */ + if (!firewall) + return; + + if (firewall->ngroups == 0) + return; + group = firewall->groups[firewall->currentGroup]; + + if (group->addingRollback) { + for (i = 0; i < group->nrollback; i++) { + if (group->rollback[i] == rule) { + VIR_DELETE_ELEMENT(group->rollback, + i, + group->nrollback); + virFirewallRuleFree(rule); + break; + } + } + } else { + for (i = 0; i < group->naction; i++) { + if (group->action[i] == rule) { + VIR_DELETE_ELEMENT(group->action, + i, + group->naction); + virFirewallRuleFree(rule); + return; + } + } + } +} + + +void virFirewallRuleAddArg(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *arg) +{ + VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, rule); + + ADD_ARG(rule, arg); + + return; + + no_memory: + firewall->err = ENOMEM; +} + + +void virFirewallRuleAddArgFormat(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *fmt, ...) +{ + char *arg; + va_list list; + + VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, rule); + + va_start(list, fmt); + + if (virVasprintf(&arg, fmt, list) < 0) + goto no_memory; + + ADD_ARG(rule, arg); + + va_end(list); + + VIR_FREE(arg); + return; + + no_memory: + firewall->err = ENOMEM; + va_end(list); + VIR_FREE(arg); +} + + +void virFirewallRuleAddArgSet(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *const *args) +{ + VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, rule); + + while (*args) { + ADD_ARG(rule, *args); + args++; + } + + return; + + no_memory: + firewall->err = ENOMEM; +} + + +void virFirewallRuleAddArgList(virFirewallPtr firewall, + virFirewallRulePtr rule, + ...) +{ + va_list list; + const char *str; + + VIR_FIREWALL_RULE_RETURN_IF_ERROR(firewall, rule); + + va_start(list, rule); + + while ((str = va_arg(list, char *)) != NULL) { + ADD_ARG(rule, str); + } + + va_end(list); + + return; + + no_memory: + firewall->err = ENOMEM; + va_end(list); +} + + +size_t virFirewallRuleGetArgCount(virFirewallRulePtr rule) +{ + if (!rule) + return 0; + return rule->argsLen; +} + + +/** + * virFirewallStartTransaction: + * @firewall: the firewall ruleset + * @flags: bitset of virFirewallTransactionFlags + * + * Start a new transaction with associated rollback + * block. + * + * Should be followed by calls to add various rules to + * the transaction. Then virFirwallStartRollback should + * be used to provide rules to rollback upon transaction + * failure + */ +void virFirewallStartTransaction(virFirewallPtr firewall, + unsigned int flags) +{ + virFirewallGroupPtr group; + + VIR_FIREWALL_RETURN_IF_ERROR(firewall); + + if (!(group = virFirewallGroupNew())) { + firewall->err = ENOMEM; + return; + } + group->actionFlags = flags; + + if (VIR_EXPAND_N(firewall->groups, + firewall->ngroups, 1) < 0) { + firewall->err = ENOMEM; + virFirewallGroupFree(group); + return; + } + firewall->groups[firewall->ngroups - 1] = group; + firewall->currentGroup = firewall->ngroups - 1; +} + +/** + * virFirewallBeginRollback: + * @firewall: the firewall ruleset + * @flags: bitset of virFirewallRollbackFlags + * + * Mark the beginning of a set of rules able to rollback + * changes in this and all earlier transactions. + * + * Should be followed by calls to add various rules needed + * to rollback state. Then virFirewallStartTransaction + * should be used to indicate the beginning of the next + * transactional ruleset. + */ +void virFirewallStartRollback(virFirewallPtr firewall, + unsigned int flags) +{ + virFirewallGroupPtr group; + + VIR_FIREWALL_RETURN_IF_ERROR(firewall); + + if (firewall->ngroups == 0) { + firewall->err = ENODATA; + return; + } + + group = firewall->groups[firewall->ngroups-1]; + group->rollbackFlags = flags; + group->addingRollback = true; +} + + +static char * +virFirewallRuleToString(virFirewallRulePtr rule) +{ + const char *bin = virFirewallLayerCommandTypeToString(rule->layer); + virBuffer buf = VIR_BUFFER_INITIALIZER; + size_t i; + + virBufferAdd(&buf, bin, -1); + for (i = 0; i < rule->argsLen; i++) { + virBufferAddLit(&buf, " "); + virBufferAdd(&buf, rule->args[i], -1); + } + + return virBufferContentAndReset(&buf); +} + +static int +virFirewallApplyRuleDirect(virFirewallRulePtr rule, + bool ignoreErrors, + char **output) +{ + size_t i; + const char *bin = virFirewallLayerCommandTypeToString(rule->layer); + virCommandPtr cmd = NULL; + int status; + int ret = -1; + char *error = NULL; + + if (!bin) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown firewall layer %d"), + rule->layer); + goto cleanup; + } + + cmd = virCommandNewArgList(bin, NULL); + + for (i = 0; i < rule->argsLen; i++) + virCommandAddArg(cmd, rule->args[i]); + + virCommandSetOutputBuffer(cmd, output); + virCommandSetErrorBuffer(cmd, &error); + + if (virCommandRun(cmd, &status) < 0) + goto cleanup; + + if (status != 0) { + if (ignoreErrors) { + VIR_DEBUG("Ignoring error running command"); + } else { + char *args = virCommandToString(cmd); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to apply firewall rules %s: %s"), + NULLSTR(args), NULLSTR(error)); + VIR_FREE(args); + VIR_FREE(*output); + goto cleanup; + } + } + + ret = 0; + cleanup: + VIR_FREE(error); + virCommandFree(cmd); + return ret; +} + + +#ifdef WITH_DBUS +static int +virFirewallApplyRuleFirewallD(virFirewallRulePtr rule, + bool ignoreErrors, + char **output) +{ + const char *ipv = virFirewallLayerFirewallDTypeToString(rule->layer); + DBusConnection *sysbus = virDBusGetSystemBus(); + DBusMessage *reply = NULL; + DBusError error; + int ret = -1; + + if (!sysbus) + return -1; + + dbus_error_init(&error); + + if (!ipv) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown firewall layer %d"), + rule->layer); + goto cleanup; + } + + if (virDBusCallMethod(sysbus, + &reply, + &error, + VIR_FIREWALL_FIREWALLD_SERVICE, + "/org/fedoraproject/FirewallD1", + "org.fedoraproject.FirewallD1.direct", + "passthrough", + "sa&s", + ipv, + (int)rule->argsLen, + rule->args) < 0) + goto cleanup; + + if (dbus_error_is_set(&error)) { + /* + * As of firewalld-0.3.9.3-1.fc20.noarch the name and + * message fields in the error look like + * + * name="org.freedesktop.DBus.Python.dbus.exceptions.DBusException" + * message="COMMAND_FAILED: '/sbin/iptables --table filter --delete + * INPUT --in-interface virbr0 --protocol udp --destination-port 53 + * --jump ACCEPT' failed: iptables: Bad rule (does a matching rule + * exist in that chain?)." + * + * We'd like to only ignore DBus errors precisely related to the failure + * of iptables/ebtables commands. A well designed DBus interface would + * return specific named exceptions not the top level generic python dbus + * exception name. With this current scheme our only option is todo a + * sub-string match for 'COMMAND_FAILED' on the message. eg like + * + * if (ignoreErrors && + * STREQ(error.name, + * "org.freedesktop.DBus.Python.dbus.exceptions.DBusException") && + * STRPREFIX(error.message, "COMMAND_FAILED")) + * ... + * + * But this risks our error detecting code being broken if firewalld changes + * ever alter the message string, so we're avoiding doing that. + */ + if (ignoreErrors) { + VIR_DEBUG("Ignoring error '%s': '%s'", + error.name, error.message); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to apply rule '%s'"), + error.message); + goto cleanup; + } + } else { + if (virDBusMessageRead(reply, "s", output) < 0) + goto cleanup; + } + + ret = 0; + + cleanup: + dbus_error_free(&error); + if (reply) + dbus_message_unref(reply); + return ret; +} +#endif + +static int +virFirewallApplyRule(virFirewallPtr firewall, + virFirewallRulePtr rule, + bool ignoreErrors) +{ + char *output = NULL; + char **lines = NULL; + int ret = -1; + char *str = virFirewallRuleToString(rule); + VIR_INFO("Applying rule '%s'", NULLSTR(str)); + VIR_FREE(str); + + if (rule->ignoreErrors) + ignoreErrors = rule->ignoreErrors; + + switch (currentBackend) { + case VIR_FIREWALL_BACKEND_DIRECT: + if (virFirewallApplyRuleDirect(rule, ignoreErrors, &output) < 0) + return -1; + break; +#if WITH_DBUS + case VIR_FIREWALL_BACKEND_FIREWALLD: + if (virFirewallApplyRuleFirewallD(rule, ignoreErrors, &output) < 0) + return -1; + break; +#endif + default: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unexpected firewall engine backend")); + return -1; + } + + if (rule->queryCB && output) { + if (!(lines = virStringSplit(output, "\n", -1))) + goto cleanup; + + VIR_DEBUG("Invoking query %p with '%s'", rule->queryCB, output); + if (rule->queryCB(firewall, (const char *const *)lines, rule->queryOpaque) < 0) + goto cleanup; + + if (firewall->err == ENOMEM) { + virReportOOMError(); + goto cleanup; + } + if (firewall->err) { + virReportSystemError(firewall->err, "%s", + _("Unable to create rule")); + goto cleanup; + } + + } + + ret = 0; + cleanup: + virStringFreeList(lines); + VIR_FREE(output); + return ret; +} + +static int +virFirewallApplyGroup(virFirewallPtr firewall, + size_t idx) +{ + virFirewallGroupPtr group = firewall->groups[idx]; + bool ignoreErrors = (group->actionFlags & VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); + size_t i; + + VIR_INFO("Starting transaction for %p flags=%x", + group, group->actionFlags); + firewall->currentGroup = idx; + group->addingRollback = false; + for (i = 0; i < group->naction; i++) { + if (virFirewallApplyRule(firewall, + group->action[i], + ignoreErrors) < 0) + return -1; + } + return 0; +} + + +static void +virFirewallRollbackGroup(virFirewallPtr firewall, + size_t idx) +{ + virFirewallGroupPtr group = firewall->groups[idx]; + size_t i; + + VIR_INFO("Starting rollback for group %p", group); + firewall->currentGroup = idx; + group->addingRollback = true; + for (i = 0; i < group->nrollback; i++) { + ignore_value(virFirewallApplyRule(firewall, + group->rollback[i], + true)); + } +} + + +int +virFirewallApply(virFirewallPtr firewall) +{ + size_t i, j; + int ret = -1; + + virMutexLock(&ruleLock); + if (virFirewallInitialize() < 0) + goto cleanup; + + if (!firewall || firewall->err == ENOMEM) { + virReportOOMError(); + goto cleanup; + } + if (firewall->err) { + virReportSystemError(firewall->err, "%s", + _("Unable to create rule")); + goto cleanup; + } + + VIR_DEBUG("Applying groups for %p", firewall); + for (i = 0; i < firewall->ngroups; i++) { + if (virFirewallApplyGroup(firewall, i) < 0) { + VIR_DEBUG("Rolling back groups upto %zu for %p", i, firewall); + size_t first = i; + virErrorPtr saved_error = virSaveLastError(); + + /* + * Look at any inheritance markers to figure out + * what the first rollback group we need to apply is + */ + for (j = 0; j <= i; j++) { + VIR_DEBUG("Checking inheritance of group %zu", i - j); + if (firewall->groups[i - j]->rollbackFlags & + VIR_FIREWALL_ROLLBACK_INHERIT_PREVIOUS) + first = (i - j) - 1; + } + /* + * Now apply all rollback groups in order + */ + for (j = first; j <= i; j++) { + VIR_DEBUG("Rolling back group %zu", j); + virFirewallRollbackGroup(firewall, j); + } + + virSetError(saved_error); + virFreeError(saved_error); + VIR_DEBUG("Done rolling back groups for %p", firewall); + goto cleanup; + } + } + VIR_DEBUG("Done applying groups for %p", firewall); + + ret = 0; + cleanup: + virMutexUnlock(&ruleLock); + return ret; +} diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h new file mode 100644 index 0000000..5ca66fa --- /dev/null +++ b/src/util/virfirewall.h @@ -0,0 +1,109 @@ + /* + * virfirewall.h: integration with firewalls + * + * 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 + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Daniel P. Berrange <berrange@redhat.com> + */ + +#ifndef __VIR_FIREWALL_H__ +# define __VIR_FIREWALL_H__ + +# include "internal.h" + +typedef struct _virFirewall virFirewall; +typedef virFirewall *virFirewallPtr; + +typedef struct _virFirewallRule virFirewallRule; +typedef virFirewallRule *virFirewallRulePtr; + +typedef enum { + VIR_FIREWALL_LAYER_ETHERNET, + VIR_FIREWALL_LAYER_IPV4, + VIR_FIREWALL_LAYER_IPV6, + + VIR_FIREWALL_LAYER_LAST, +} virFirewallLayer; + +virFirewallPtr virFirewallNew(void); + +void virFirewallFree(virFirewallPtr firewall); + +virFirewallRulePtr virFirewallAddRule(virFirewallPtr firewall, + virFirewallLayer layer, + ...) + ATTRIBUTE_SENTINEL; + +typedef int (*virFirewallQueryCallback)(virFirewallPtr firewall, + const char *const *lines, + void *opaque); + +virFirewallRulePtr virFirewallAddRuleFull(virFirewallPtr firewall, + virFirewallLayer layer, + bool ignoreErrors, + virFirewallQueryCallback cb, + void *opaque, + ...) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_SENTINEL;
The Coverity build wasn't happy (it failed) since argument(3) is a bool: In file included from util/virebtables.c:34:0: util/virfirewall.h:62:5: error: nonnull argument references non-pointer operand (argument 1, operand 3) ATTRIBUTE_NONNULL(3) ATTRIBUTE_SENTINEL; ^ The only pointer argument is (1); however, virFirewallAddRuleFullV() will check for it being NULL. Perhaps this was a cut-n-paste from "virFirewallRuleAddArg()" below? I wasn't sure which way to go in order to repair. Since it's only the Coverity build that's broken - I figure it can wait for your feedback to handle it. If I changed it to (1), then my coverity build completes and there's no new errors. John
+ +void virFirewallRemoveRule(virFirewallPtr firewall, + virFirewallRulePtr rule); + +void virFirewallRuleAddArg(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *arg) + ATTRIBUTE_NONNULL(3); + +void virFirewallRuleAddArgFormat(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *fmt, ...) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_FMT_PRINTF(3, 4); + +void virFirewallRuleAddArgSet(virFirewallPtr firewall, + virFirewallRulePtr rule, + const char *const *args) + ATTRIBUTE_NONNULL(3); + +void virFirewallRuleAddArgList(virFirewallPtr firewall, + virFirewallRulePtr rule, + ...) + ATTRIBUTE_SENTINEL; + +size_t virFirewallRuleGetArgCount(virFirewallRulePtr rule); + +typedef enum { + /* Ignore all errors when applying rules, so no + * rollback block will be required */ + VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS = (1 << 0), +} virFirewallTransactionFlags; + +void virFirewallStartTransaction(virFirewallPtr firewall, + unsigned int flags); + +typedef enum { + /* Execute previous rollback block before this + * one, to chain cleanup */ + VIR_FIREWALL_ROLLBACK_INHERIT_PREVIOUS = (1 << 0), +} virFirewallRollbackFlags; + +void virFirewallStartRollback(virFirewallPtr firewall, + unsigned int flags); + +int virFirewallApply(virFirewallPtr firewall); + +#endif /* __VIR_FIREWALL_H__ */ diff --git a/src/util/virfirewallpriv.h b/src/util/virfirewallpriv.h new file mode 100644 index 0000000..130aaa1 --- /dev/null +++ b/src/util/virfirewallpriv.h @@ -0,0 +1,45 @@ +/* + * virfirewallpriv.h: integration with firewalls private APIs + * + * Copyright (C) 2013 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 + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Daniel P. Berrange <berrange@redhat.com> + */ + +#ifndef __VIR_FIREWALL_PRIV_H_ALLOW__ +# error "virfirewallpriv.h may only be included by virfirewall.c or test suites" +#endif + +#ifndef __VIR_FIREWALL_PRIV_H__ +# define __VIR_FIREWALL_PRIV_H__ + +# include "virfirewall.h" + +# define VIR_FIREWALL_FIREWALLD_SERVICE "org.fedoraproject.FirewallD1" + +typedef enum { + VIR_FIREWALL_BACKEND_AUTOMATIC, + VIR_FIREWALL_BACKEND_DIRECT, + VIR_FIREWALL_BACKEND_FIREWALLD, + + VIR_FIREWALL_BACKEND_LAST, +} virFirewallBackend; + +int virFirewallSetBackend(virFirewallBackend backend); + +#endif /* __VIR_FIREWALL_PRIV_H__ */ diff --git a/tests/Makefile.am b/tests/Makefile.am index c13cc15..a10919d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -148,6 +148,7 @@ test_programs = virshtest sockettest \ virpcitest \ virendiantest \ virfiletest \ + virfirewalltest \ viriscsitest \ virkeycodetest \ virlockspacetest \ @@ -998,6 +999,12 @@ virfiletest_SOURCES = \ virfiletest.c testutils.h testutils.c virfiletest_LDADD = $(LDADDS)
+virfirewalltest_SOURCES = \ + virfirewalltest.c testutils.h testutils.c +virfirewalltest_LDADD = $(LDADDS) +virfirewalltest_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) +virfirewalltest_LDFLAGS = $(DRIVER_MODULE_LDFLAGS) + jsontest_SOURCES = \ jsontest.c testutils.h testutils.c jsontest_LDADD = $(LDADDS) diff --git a/tests/testutils.c b/tests/testutils.c index 9767a78..022d543 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -459,10 +459,20 @@ int virtTestDifference(FILE *stream, const char *expect, const char *actual) { - const char *expectStart = expect; - const char *expectEnd = expect + (strlen(expect)-1); - const char *actualStart = actual; - const char *actualEnd = actual + (strlen(actual)-1); + const char *expectStart; + const char *expectEnd; + const char *actualStart; + const char *actualEnd; + + if (!expect) + expect = ""; + if (!actual) + actual = ""; + + expectStart = expect; + expectEnd = expect + (strlen(expect)-1); + actualStart = actual; + actualEnd = actual + (strlen(actual)-1);
if (!virTestGetDebug()) return 0; diff --git a/tests/virfirewalltest.c b/tests/virfirewalltest.c new file mode 100644 index 0000000..805fa44 --- /dev/null +++ b/tests/virfirewalltest.c @@ -0,0 +1,1186 @@ +/* + * Copyright (C) 2013-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 + * <http://www.gnu.org/licenses/>. + * + * Author: Daniel P. Berrange <berrange@redhat.com> + */ + +#include <config.h> + +#define __VIR_FIREWALL_PRIV_H_ALLOW__ +#define __VIR_COMMAND_PRIV_H_ALLOW__ + +#include "testutils.h" +#include "virbuffer.h" +#include "vircommandpriv.h" +#include "virfirewallpriv.h" +#include "virmock.h" +#include "virdbuspriv.h" + +#define VIR_FROM_THIS VIR_FROM_FIREWALL + +#if WITH_DBUS +# include <dbus/dbus.h> +#endif + +static bool fwDisabled = true; +static virBufferPtr fwBuf; +static bool fwError; + +#define TEST_FILTER_TABLE_LIST \ + "Chain INPUT (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain FORWARD (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain OUTPUT (policy ACCEPT)\n" \ + "target prot opt source destination\n" + +#define TEST_NAT_TABLE_LIST \ + "Chain PREROUTING (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain INPUT (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain OUTPUT (policy ACCEPT)\n" \ + "target prot opt source destination\n" \ + "\n" \ + "Chain POSTROUTING (policy ACCEPT)\n" \ + "target prot opt source destination\n" + +#if WITH_DBUS +VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, + DBusMessage *, + DBusConnection *, connection, + DBusMessage *, message, + int, timeout_milliseconds, + DBusError *, error) +{ + DBusMessage *reply = NULL; + const char *service = dbus_message_get_destination(message); + const char *member = dbus_message_get_member(message); + size_t i; + size_t nargs = 0; + char **args = NULL; + char *type = NULL; + + VIR_MOCK_IMPL_INIT_REAL(dbus_connection_send_with_reply_and_block); + + if (STREQ(service, "org.freedesktop.DBus") && + STREQ(member, "ListNames")) { + const char *svc1 = "org.foo.bar.wizz"; + const char *svc2 = VIR_FIREWALL_FIREWALLD_SERVICE; + DBusMessageIter iter; + DBusMessageIter sub; + reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + "s", &sub); + + if (!dbus_message_iter_append_basic(&sub, + DBUS_TYPE_STRING, + &svc1)) + goto error; + if (!fwDisabled && + !dbus_message_iter_append_basic(&sub, + DBUS_TYPE_STRING, + &svc2)) + goto error; + dbus_message_iter_close_container(&iter, &sub); + } else if (STREQ(service, VIR_FIREWALL_FIREWALLD_SERVICE) && + STREQ(member, "passthrough")) { + bool isAdd = false; + bool doError = false; + + if (virDBusMessageDecode(message, + "sa&s", + &type, + &nargs, + &args) < 0) + goto error; + + for (i = 0; i < nargs; i++) { + /* Fake failure on the command with this IP addr */ + if (STREQ(args[i], "-A")) { + isAdd = true; + } else if (isAdd && STREQ(args[i], "192.168.122.255")) { + doError = true; + } + } + + if (fwBuf) { + if (STREQ(type, "ipv4")) + virBufferAddLit(fwBuf, IPTABLES_PATH); + else if (STREQ(type, "ipv4")) + virBufferAddLit(fwBuf, IP6TABLES_PATH); + else + virBufferAddLit(fwBuf, EBTABLES_PATH); + } + for (i = 0; i < nargs; i++) { + if (fwBuf) { + virBufferAddLit(fwBuf, " "); + virBufferEscapeShell(fwBuf, args[i]); + } + } + if (fwBuf) + virBufferAddLit(fwBuf, "\n"); + if (doError) { + dbus_set_error_const(error, + "org.firewalld.error", + "something bad happened"); + } else { + if (nargs == 1 && + STREQ(type, "ipv4") && + STREQ(args[0], "-L")) { + if (virDBusCreateReply(&reply, + "s", TEST_FILTER_TABLE_LIST) < 0) + goto error; + } else if (nargs == 3 && + STREQ(type, "ipv4") && + STREQ(args[0], "-t") && + STREQ(args[1], "nat") && + STREQ(args[2], "-L")) { + if (virDBusCreateReply(&reply, + "s", TEST_NAT_TABLE_LIST) < 0) + goto error; + } else { + if (virDBusCreateReply(&reply, + "s", "success") < 0) + goto error; + } + } + } else { + reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); + } + + cleanup: + VIR_FREE(type); + for (i = 0; i < nargs; i++) + VIR_FREE(args[i]); + VIR_FREE(args); + return reply; + + error: + if (reply) + dbus_message_unref(reply); + reply = NULL; + if (error && !dbus_error_is_set(error)) + dbus_set_error_const(error, + "org.firewalld.error", + "something unexpected happened"); + + goto cleanup; +} +#endif + +struct testFirewallData { + virFirewallBackend tryBackend; + virFirewallBackend expectBackend; + bool fwDisabled; +}; + +static int +testFirewallSingleGroup(const void *opaque) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) + virCommandSetDryRun(&cmdbuf, NULL, NULL); + else + fwBuf = &cmdbuf; + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static int +testFirewallRemoveRule(const void *opaque) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + virFirewallRulePtr fwrule; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) + virCommandSetDryRun(&cmdbuf, NULL, NULL); + else + fwBuf = &cmdbuf; + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", NULL); + virFirewallRuleAddArg(fw, fwrule, "--source-host"); + virFirewallRemoveRule(fw, fwrule); + + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", NULL); + virFirewallRuleAddArg(fw, fwrule, "--source-host"); + virFirewallRuleAddArgFormat(fw, fwrule, "%s", "!192.168.122.1"); + virFirewallRuleAddArgList(fw, fwrule, "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static int +testFirewallManyGroups(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n" + IPTABLES_PATH " -A OUTPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A OUTPUT --jump DROP\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) + virCommandSetDryRun(&cmdbuf, NULL, NULL); + else + fwBuf = &cmdbuf; + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--jump", "DROP", NULL); + + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static void +testFirewallRollbackHook(const char *const*args, + const char *const*env ATTRIBUTE_UNUSED, + const char *input ATTRIBUTE_UNUSED, + char **output ATTRIBUTE_UNUSED, + char **error ATTRIBUTE_UNUSED, + int *status, + void *opaque ATTRIBUTE_UNUSED) +{ + bool isAdd = false; + while (*args) { + /* Fake failure on the command with this IP addr */ + if (STREQ(*args, "-A")) { + isAdd = true; + } else if (isAdd && STREQ(*args, "192.168.122.255")) { + *status = 127; + break; + } + args++; + } +} + +static int +testFirewallIgnoreFailGroup(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -A OUTPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A OUTPUT --jump DROP\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--jump", "DROP", NULL); + + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static int +testFirewallIgnoreFailRule(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -A OUTPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A OUTPUT --jump DROP\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_IPV4, + true, NULL, NULL, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "OUTPUT", + "--jump", "DROP", NULL); + + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static int +testFirewallNoRollback(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) == 0) { + fprintf(stderr, "Firewall apply unexpectedly worked\n"); + goto cleanup; + } + + if (virtTestOOMActive()) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static int +testFirewallSingleRollback(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwError = true; + fwBuf = &cmdbuf; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) == 0) { + fprintf(stderr, "Firewall apply unexpectedly worked\n"); + goto cleanup; + } + + if (virtTestOOMActive()) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static int +testFirewallManyRollback(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) == 0) { + fprintf(stderr, "Firewall apply unexpectedly worked\n"); + goto cleanup; + } + + if (virtTestOOMActive()) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static int +testFirewallChainedRollback(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.127 --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.127 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host 192.168.122.255 --jump REJECT\n" + IPTABLES_PATH " -D INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.127", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.127", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + virFirewallStartRollback(fw, VIR_FIREWALL_ROLLBACK_INHERIT_PREVIOUS); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "192.168.122.255", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-D", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) == 0) { + fprintf(stderr, "Firewall apply unexpectedly worked\n"); + goto cleanup; + } + + if (virtTestOOMActive()) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + + +static const char *expectedLines[] = { + "Chain INPUT (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain FORWARD (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain OUTPUT (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain PREROUTING (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain INPUT (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain OUTPUT (policy ACCEPT)", + "target prot opt source destination", + "", + "Chain POSTROUTING (policy ACCEPT)", + "target prot opt source destination", + "", +}; +static size_t expectedLineNum; +static bool expectedLineError; + +static void +testFirewallQueryHook(const char *const*args, + const char *const*env ATTRIBUTE_UNUSED, + const char *input ATTRIBUTE_UNUSED, + char **output, + char **error ATTRIBUTE_UNUSED, + int *status, + void *opaque ATTRIBUTE_UNUSED) +{ + if (STREQ(args[0], IPTABLES_PATH) && + STREQ(args[1], "-L")) { + if (VIR_STRDUP(*output, TEST_FILTER_TABLE_LIST) < 0) + *status = 127; + } else if (STREQ(args[0], IPTABLES_PATH) && + STREQ(args[1], "-t") && + STREQ(args[2], "nat") && + STREQ(args[3], "-L")) { + if (VIR_STRDUP(*output, TEST_NAT_TABLE_LIST) < 0) + *status = 127; + } +} + + +static int +testFirewallQueryCallback(virFirewallPtr fw, + const char *const *lines, + void *opaque ATTRIBUTE_UNUSED) +{ + size_t i; + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.129", + "--jump", "REJECT", NULL); + + for (i = 0; lines[i] != NULL; i++) { + if (expectedLineNum >= ARRAY_CARDINALITY(expectedLines)) { + expectedLineError = true; + break; + } + if (STRNEQ(expectedLines[expectedLineNum], lines[i])) { + fprintf(stderr, "Mismatch '%s' vs '%s' at %zu, %zu\n", + expectedLines[expectedLineNum], lines[i], + expectedLineNum, i); + expectedLineError = true; + break; + } + expectedLineNum++; + } + return 0; +} + +static int +testFirewallQuery(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = NULL; + int ret = -1; + const char *actual = NULL; + const char *expected = + IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.127 --jump REJECT\n" + IPTABLES_PATH " -L\n" + IPTABLES_PATH " -t nat -L\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.130 --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.129' --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.129' --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host 192.168.122.128 --jump REJECT\n" + IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n"; + const struct testFirewallData *data = opaque; + + expectedLineNum = 0; + expectedLineError = false; + fwDisabled = data->fwDisabled; + if (virFirewallSetBackend(data->tryBackend) < 0) + goto cleanup; + + if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) { + virCommandSetDryRun(&cmdbuf, testFirewallQueryHook, NULL); + } else { + fwBuf = &cmdbuf; + fwError = true; + } + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.1", + "--jump", "ACCEPT", NULL); + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.127", + "--jump", "REJECT", NULL); + + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_IPV4, + false, + testFirewallQueryCallback, + NULL, + "-L", NULL); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_IPV4, + false, + testFirewallQueryCallback, + NULL, + "-t", "nat", "-L", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.130", + "--jump", "REJECT", NULL); + + + virFirewallStartTransaction(fw, 0); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "192.168.122.128", + "--jump", "REJECT", NULL); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "-A", "INPUT", + "--source-host", "!192.168.122.1", + "--jump", "REJECT", NULL); + + if (virFirewallApply(fw) < 0) + goto cleanup; + + if (virBufferError(&cmdbuf)) + goto cleanup; + + actual = virBufferCurrentContent(&cmdbuf); + + if (expectedLineError) { + fprintf(stderr, "Got some unexpected query data\n"); + goto cleanup; + } + + if (STRNEQ_NULLABLE(expected, actual)) { + fprintf(stderr, "Unexected command execution\n"); + virtTestDifference(stderr, expected, actual); + goto cleanup; + } + + ret = 0; + cleanup: + virBufferFreeAndReset(&cmdbuf); + fwBuf = NULL; + virCommandSetDryRun(NULL, NULL, NULL); + virFirewallFree(fw); + return ret; +} + +static int +mymain(void) +{ + int ret = 0; + +#define RUN_TEST_DIRECT(name, method) \ + do { \ + struct testFirewallData data; \ + data.tryBackend = VIR_FIREWALL_BACKEND_AUTOMATIC; \ + data.expectBackend = VIR_FIREWALL_BACKEND_DIRECT; \ + data.fwDisabled = true; \ + if (virtTestRun(name " auto direct", method, &data) < 0) \ + ret = -1; \ + data.tryBackend = VIR_FIREWALL_BACKEND_DIRECT; \ + data.expectBackend = VIR_FIREWALL_BACKEND_DIRECT; \ + data.fwDisabled = true; \ + if (virtTestRun(name " manual direct", method, &data) < 0) \ + ret = -1; \ + } while (0) + +#if WITH_DBUS +# define RUN_TEST_FIREWALLD(name, method) \ + do { \ + struct testFirewallData data; \ + data.tryBackend = VIR_FIREWALL_BACKEND_AUTOMATIC; \ + data.expectBackend = VIR_FIREWALL_BACKEND_FIREWALLD; \ + data.fwDisabled = false; \ + if (virtTestRun(name " auto firewalld", method, &data) < 0) \ + ret = -1; \ + data.tryBackend = VIR_FIREWALL_BACKEND_FIREWALLD; \ + data.expectBackend = VIR_FIREWALL_BACKEND_FIREWALLD; \ + data.fwDisabled = false; \ + if (virtTestRun(name " manual firewalld", method, &data) < 0) \ + ret = -1; \ + } while (0) + +# define RUN_TEST(name, method) \ + RUN_TEST_DIRECT(name, method); \ + RUN_TEST_FIREWALLD(name, method) +#else /* ! WITH_DBUS */ +# define RUN_TEST(name, method) \ + RUN_TEST_DIRECT(name, method) +#endif /* ! WITH_DBUS */ + + RUN_TEST("single group", testFirewallSingleGroup); + RUN_TEST("remove rule", testFirewallRemoveRule); + RUN_TEST("many groups", testFirewallManyGroups); + RUN_TEST("ignore fail group", testFirewallIgnoreFailGroup); + RUN_TEST("ignore fail rule", testFirewallIgnoreFailRule); + RUN_TEST("no rollback", testFirewallNoRollback); + RUN_TEST("single rollback", testFirewallSingleRollback); + RUN_TEST("many rollback", testFirewallManyRollback); + RUN_TEST("chained rollback", testFirewallChainedRollback); + RUN_TEST("query transaction", testFirewallQuery); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +#if WITH_DBUS +VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virmockdbus.so") +#else +VIRT_TEST_MAIN(mymain) +#endif

On 8.4.2014 17:38, Daniel P. Berrange wrote:
The network and nwfilter drivers both have a need to update firewall rules. The currently share no code for interacting with iptables / firewalld. The nwfilter driver is fairly tied to the concept of creating shell scripts to execute which makes it very hard to port to talk to firewalld via DBus APIs.
This patch introduces a virFirewallPtr object which is able to represent a complete sequence of rule changes, with the ability to have multiple transactional checkpoints with rollbacks. By formally separating the definition of the rules to be applied from the mechanism used to apply them, it is also possible to write a firewall engine that uses firewalld DBus APIs natively instead of via the slow firewalld-cmd.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- include/libvirt/virterror.h | 1 + po/POTFILES.in | 1 + src/Makefile.am | 2 + src/libvirt_private.syms | 17 + src/util/virerror.c | 1 + src/util/virfirewall.c | 922 +++++++++++++++++++++++++++++++++ src/util/virfirewall.h | 109 ++++ src/util/virfirewallpriv.h | 45 ++ tests/Makefile.am | 7 + tests/testutils.c | 18 +- tests/virfirewalltest.c | 1186 +++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 2305 insertions(+), 4 deletions(-) create mode 100644 src/util/virfirewall.c create mode 100644 src/util/virfirewall.h create mode 100644 src/util/virfirewallpriv.h create mode 100644 tests/virfirewalltest.c
[...]
diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c new file mode 100644 index 0000000..b558d2f --- /dev/null +++ b/src/util/virfirewall.c @@ -0,0 +1,922 @@
[...]
+static virFirewallRulePtr +virFirewallAddRuleFullV(virFirewallPtr firewall, + virFirewallLayer layer, + bool ignoreErrors, + virFirewallQueryCallback cb, + void *opaque, + va_list args) +{ + virFirewallGroupPtr group; + virFirewallRulePtr rule; + char *str; + + VIR_FIREWALL_RETURN_NULL_IF_ERROR(firewall); + + if (firewall->ngroups == 0) { + firewall->err = ENODATA; + return NULL; + } + group = firewall->groups[firewall->currentGroup];
[...]
+void virFirewallStartRollback(virFirewallPtr firewall, + unsigned int flags) +{ + virFirewallGroupPtr group; + + VIR_FIREWALL_RETURN_IF_ERROR(firewall); + + if (firewall->ngroups == 0) { + firewall->err = ENODATA; + return; + } + + group = firewall->groups[firewall->ngroups-1]; + group->rollbackFlags = flags; + group->addingRollback = true; +}
Hi Dan, The ENODATA error is not defined in freebsd and I'm wondering whether it should be compiled there? If yes, than we have to add: #ifndef ENODATA # define ENODATA ENOMSG #endif into that file. Pavel

On Tue, Apr 29, 2014 at 04:45:31PM +0200, Pavel Hrdina wrote:
On 8.4.2014 17:38, Daniel P. Berrange wrote:
The network and nwfilter drivers both have a need to update firewall rules. The currently share no code for interacting with iptables / firewalld. The nwfilter driver is fairly tied to the concept of creating shell scripts to execute which makes it very hard to port to talk to firewalld via DBus APIs.
This patch introduces a virFirewallPtr object which is able to represent a complete sequence of rule changes, with the ability to have multiple transactional checkpoints with rollbacks. By formally separating the definition of the rules to be applied from the mechanism used to apply them, it is also possible to write a firewall engine that uses firewalld DBus APIs natively instead of via the slow firewalld-cmd.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+void virFirewallStartRollback(virFirewallPtr firewall, + unsigned int flags) +{ + virFirewallGroupPtr group; + + VIR_FIREWALL_RETURN_IF_ERROR(firewall); + + if (firewall->ngroups == 0) { + firewall->err = ENODATA; + return; + } + + group = firewall->groups[firewall->ngroups-1]; + group->rollbackFlags = flags; + group->addingRollback = true; +}
Hi Dan,
The ENODATA error is not defined in freebsd and I'm wondering whether it should be compiled there? If yes, than we have to add:
#ifndef ENODATA # define ENODATA ENOMSG #endif
into that file.
Yes, this is intended to be usable on freebsd. The ENODATA choice was kind of arbitrary - I think we could just use EINVAL instead as a safe bet. This would only ever occur if the caller was ignoring the defined API usage rules, so only ever likely to see this during devevelopment Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Update the iptablesXXXX methods so that instead of directly executing iptables commands, they populate rules in an instance of virFirewallPtr. The bridge driver can thus construct the ruleset and then invoke it in one operation having rollback handled automatically. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/network/bridge_driver_linux.c | 669 ++++++++++++++++---------------------- src/util/viriptables.c | 632 +++++++++++++++-------------------- src/util/viriptables.h | 114 ++++--- 3 files changed, 619 insertions(+), 796 deletions(-) diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c index 3891357..9f4911b 100644 --- a/src/network/bridge_driver_linux.c +++ b/src/network/bridge_driver_linux.c @@ -28,6 +28,7 @@ #include "viriptables.h" #include "virstring.h" #include "virlog.h" +#include "virfirewall.h" #define VIR_FROM_THIS VIR_FROM_NONE @@ -134,7 +135,8 @@ static const char networkLocalMulticast[] = "224.0.0.0/24"; static const char networkLocalBroadcast[] = "255.255.255.255/32"; static int -networkAddMasqueradingFirewallRules(virNetworkObjPtr network, +networkAddMasqueradingFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network, virNetworkIpDefPtr ipdef) { int prefix = virNetworkIpDefPrefix(ipdef); @@ -144,32 +146,26 @@ networkAddMasqueradingFirewallRules(virNetworkObjPtr network, virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid prefix or netmask for '%s'"), network->def->bridge); - goto masqerr1; + return -1; } /* allow forwarding packets from the bridge interface */ - if (iptablesAddForwardAllowOut(&ipdef->address, + if (iptablesAddForwardAllowOut(fw, + &ipdef->address, prefix, network->def->bridge, - forwardIf) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow forwarding from '%s'"), - network->def->bridge); - goto masqerr1; - } + forwardIf) < 0) + return -1; /* allow forwarding packets to the bridge interface if they are * part of an existing connection */ - if (iptablesAddForwardAllowRelatedIn(&ipdef->address, + if (iptablesAddForwardAllowRelatedIn(fw, + &ipdef->address, prefix, network->def->bridge, - forwardIf) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow forwarding to '%s'"), - network->def->bridge); - goto masqerr2; - } + forwardIf) < 0) + return -1; /* * Enable masquerading. @@ -204,176 +200,127 @@ networkAddMasqueradingFirewallRules(virNetworkObjPtr network, */ /* First the generic masquerade rule for other protocols */ - if (iptablesAddForwardMasquerade(&ipdef->address, + if (iptablesAddForwardMasquerade(fw, + &ipdef->address, prefix, forwardIf, &network->def->forward.addr, &network->def->forward.port, - NULL) < 0) { - if (forwardIf) - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to enable masquerading to %s"), - forwardIf); - else - virReportError(VIR_ERR_SYSTEM_ERROR, "%s", - _("failed to add iptables rule to enable masquerading")); - goto masqerr3; - } + NULL) < 0) + return -1; /* UDP with a source port restriction */ - if (iptablesAddForwardMasquerade(&ipdef->address, + if (iptablesAddForwardMasquerade(fw, + &ipdef->address, prefix, forwardIf, &network->def->forward.addr, &network->def->forward.port, - "udp") < 0) { - if (forwardIf) - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to enable UDP masquerading to %s"), - forwardIf); - else - virReportError(VIR_ERR_SYSTEM_ERROR, "%s", - _("failed to add iptables rule to enable UDP masquerading")); - goto masqerr4; - } + "udp") < 0) + return -1; /* TCP with a source port restriction */ - if (iptablesAddForwardMasquerade(&ipdef->address, + if (iptablesAddForwardMasquerade(fw, + &ipdef->address, prefix, forwardIf, &network->def->forward.addr, &network->def->forward.port, - "tcp") < 0) { - if (forwardIf) - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to enable TCP masquerading to %s"), - forwardIf); - else - virReportError(VIR_ERR_SYSTEM_ERROR, "%s", - _("failed to add iptables rule to enable TCP masquerading")); - goto masqerr5; - } + "tcp") < 0) + return -1; /* exempt local network broadcast address as destination */ - if (iptablesAddDontMasquerade(&ipdef->address, + if (iptablesAddDontMasquerade(fw, + &ipdef->address, prefix, forwardIf, - networkLocalBroadcast) < 0) { - if (forwardIf) - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to prevent local broadcast masquerading on %s"), - forwardIf); - else - virReportError(VIR_ERR_SYSTEM_ERROR, "%s", - _("failed to add iptables rule to prevent local broadcast masquerading")); - goto masqerr6; - } + networkLocalBroadcast) < 0) + return -1; /* exempt local multicast range as destination */ - if (iptablesAddDontMasquerade(&ipdef->address, + if (iptablesAddDontMasquerade(fw, + &ipdef->address, prefix, forwardIf, - networkLocalMulticast) < 0) { - if (forwardIf) - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to prevent local multicast masquerading on %s"), - forwardIf); - else - virReportError(VIR_ERR_SYSTEM_ERROR, "%s", - _("failed to add iptables rule to prevent local multicast masquerading")); - goto masqerr7; - } + networkLocalMulticast) < 0) + return -1; return 0; - - masqerr7: - iptablesRemoveDontMasquerade(&ipdef->address, - prefix, - forwardIf, - networkLocalBroadcast); - masqerr6: - iptablesRemoveForwardMasquerade(&ipdef->address, - prefix, - forwardIf, - &network->def->forward.addr, - &network->def->forward.port, - "tcp"); - masqerr5: - iptablesRemoveForwardMasquerade(&ipdef->address, - prefix, - forwardIf, - &network->def->forward.addr, - &network->def->forward.port, - "udp"); - masqerr4: - iptablesRemoveForwardMasquerade(&ipdef->address, - prefix, - forwardIf, - &network->def->forward.addr, - &network->def->forward.port, - NULL); - masqerr3: - iptablesRemoveForwardAllowRelatedIn(&ipdef->address, - prefix, - network->def->bridge, - forwardIf); - masqerr2: - iptablesRemoveForwardAllowOut(&ipdef->address, - prefix, - network->def->bridge, - forwardIf); - masqerr1: - return -1; } -static void -networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network, +static int +networkRemoveMasqueradingFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network, virNetworkIpDefPtr ipdef) { int prefix = virNetworkIpDefPrefix(ipdef); const char *forwardIf = virNetworkDefForwardIf(network->def, 0); - if (prefix >= 0) { - iptablesRemoveDontMasquerade(&ipdef->address, + if (prefix < 0) + return 0; + + if (iptablesRemoveDontMasquerade(fw, + &ipdef->address, prefix, forwardIf, - networkLocalMulticast); - iptablesRemoveDontMasquerade(&ipdef->address, + networkLocalMulticast) < 0) + return -1; + + if (iptablesRemoveDontMasquerade(fw, + &ipdef->address, prefix, forwardIf, - networkLocalBroadcast); - iptablesRemoveForwardMasquerade(&ipdef->address, + networkLocalBroadcast) < 0) + return -1; + + if (iptablesRemoveForwardMasquerade(fw, + &ipdef->address, prefix, forwardIf, &network->def->forward.addr, &network->def->forward.port, - "tcp"); - iptablesRemoveForwardMasquerade(&ipdef->address, + "tcp") < 0) + return -1; + + if (iptablesRemoveForwardMasquerade(fw, + &ipdef->address, prefix, forwardIf, &network->def->forward.addr, &network->def->forward.port, - "udp"); - iptablesRemoveForwardMasquerade(&ipdef->address, + "udp") < 0) + return -1; + + if (iptablesRemoveForwardMasquerade(fw, + &ipdef->address, prefix, forwardIf, &network->def->forward.addr, &network->def->forward.port, - NULL); + NULL) < 0) + return -1; - iptablesRemoveForwardAllowRelatedIn(&ipdef->address, + if (iptablesRemoveForwardAllowRelatedIn(fw, + &ipdef->address, prefix, network->def->bridge, - forwardIf); - iptablesRemoveForwardAllowOut(&ipdef->address, + forwardIf) < 0) + return -1; + + if (iptablesRemoveForwardAllowOut(fw, + &ipdef->address, prefix, network->def->bridge, - forwardIf); - } + forwardIf) < 0) + return -1; + + return 0; } + static int -networkAddRoutingFirewallRules(virNetworkObjPtr network, +networkAddRoutingFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network, virNetworkIpDefPtr ipdef) { int prefix = virNetworkIpDefPrefix(ipdef); @@ -383,168 +330,199 @@ networkAddRoutingFirewallRules(virNetworkObjPtr network, virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid prefix or netmask for '%s'"), network->def->bridge); - goto routeerr1; + return -1; } /* allow routing packets from the bridge interface */ - if (iptablesAddForwardAllowOut(&ipdef->address, + if (iptablesAddForwardAllowOut(fw, + &ipdef->address, prefix, network->def->bridge, - forwardIf) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow routing from '%s'"), - network->def->bridge); - goto routeerr1; - } + forwardIf) < 0) + return -1; /* allow routing packets to the bridge interface */ - if (iptablesAddForwardAllowIn(&ipdef->address, + if (iptablesAddForwardAllowIn(fw, + &ipdef->address, prefix, network->def->bridge, - forwardIf) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow routing to '%s'"), - network->def->bridge); - goto routeerr2; - } + forwardIf) < 0) + return -1; return 0; - - routeerr2: - iptablesRemoveForwardAllowOut(&ipdef->address, - prefix, - network->def->bridge, - forwardIf); - routeerr1: - return -1; } -static void -networkRemoveRoutingFirewallRules(virNetworkObjPtr network, +static int +networkRemoveRoutingFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network, virNetworkIpDefPtr ipdef) { int prefix = virNetworkIpDefPrefix(ipdef); const char *forwardIf = virNetworkDefForwardIf(network->def, 0); - if (prefix >= 0) { - iptablesRemoveForwardAllowIn(&ipdef->address, + if (prefix < 0) + return 0; + + if (iptablesRemoveForwardAllowIn(fw, + &ipdef->address, prefix, network->def->bridge, - forwardIf); + forwardIf) < 0) + return -1; - iptablesRemoveForwardAllowOut(&ipdef->address, + if (iptablesRemoveForwardAllowOut(fw, + &ipdef->address, prefix, network->def->bridge, - forwardIf); + forwardIf) < 0) + return -1; + + return 0; +} + + +static void +networkAddGeneralIPv4FirewallRules(virFirewallPtr fw, + virNetworkObjPtr network) +{ + size_t i; + virNetworkIpDefPtr ipv4def; + + /* First look for first IPv4 address that has dhcp or tftpboot defined. */ + /* We support dhcp config on 1 IPv4 interface only. */ + for (i = 0; + (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i)); + i++) { + if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot) + break; + } + + /* allow DHCP requests through to dnsmasq */ + iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 67); + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 67); + iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 68); + + /* allow DNS requests through to dnsmasq */ + iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 53); + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 53); + + /* allow TFTP requests through to dnsmasq if necessary */ + if (ipv4def && ipv4def->tftproot) + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 69); + + /* Catch all rules to block forwarding to/from bridges */ + iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); + iptablesAddForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); + + /* Allow traffic between guests on the same bridge */ + iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); +} + +static void +networkRemoveGeneralIPv4FirewallRules(virFirewallPtr fw, + virNetworkObjPtr network) +{ + size_t i; + virNetworkIpDefPtr ipv4def; + + for (i = 0; + (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i)); + i++) { + if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot) + break; } + + iptablesRemoveForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); + iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); + iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); + + if (ipv4def && ipv4def->tftproot) + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 69); + + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 53); + iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 53); + + iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 68); + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 67); + iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 67); } + /* Add all once/network rules required for IPv6. * If no IPv6 addresses are defined and <network ipv6='yes'> is * specified, then allow IPv6 commuinications between virtual systems. * If any IPv6 addresses are defined, then add the rules for regular operation. */ -static int -networkAddGeneralIp6tablesRules(virNetworkObjPtr network) +static void +networkAddGeneralIPv6FirewallRules(virFirewallPtr fw, + virNetworkObjPtr network) { if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) && !network->def->ipv6nogw) { - return 0; + return; } /* Catch all rules to block forwarding to/from bridges */ - - if (iptablesAddForwardRejectOut(AF_INET6, network->def->bridge) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add ip6tables rule to block outbound traffic from '%s'"), - network->def->bridge); - goto err1; - } - - if (iptablesAddForwardRejectIn(AF_INET6, network->def->bridge) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add ip6tables rule to block inbound traffic to '%s'"), - network->def->bridge); - goto err2; - } + iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); + iptablesAddForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); /* Allow traffic between guests on the same bridge */ - if (iptablesAddForwardAllowCross(AF_INET6, network->def->bridge) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add ip6tables rule to allow cross bridge traffic on '%s'"), - network->def->bridge); - goto err3; - } - - /* if no IPv6 addresses are defined, we are done. */ - if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) - return 0; - - /* allow DNS over IPv6 */ - if (iptablesAddTcpInput(AF_INET6, network->def->bridge, 53) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add ip6tables rule to allow DNS requests from '%s'"), - network->def->bridge); - goto err4; - } - - if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 53) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add ip6tables rule to allow DNS requests from '%s'"), - network->def->bridge); - goto err5; - } + iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); - if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 547) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add ip6tables rule to allow DHCP6 requests from '%s'"), - network->def->bridge); - goto err6; + if (virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) { + /* allow DNS over IPv6 */ + iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 53); + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 53); + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 547); } - - return 0; - - /* unwind in reverse order from the point of failure */ - err6: - iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53); - err5: - iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53); - err4: - iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge); - err3: - iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge); - err2: - iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge); - err1: - return -1; } static void -networkRemoveGeneralIp6tablesRules(virNetworkObjPtr network) +networkRemoveGeneralIPv6FirewallRules(virFirewallPtr fw, + virNetworkObjPtr network) { if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) && !network->def->ipv6nogw) { return; } + if (virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) { - iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 547); - iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53); - iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53); + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 547); + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 53); + iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 53); } /* the following rules are there if no IPv6 address has been defined * but network->def->ipv6nogw == true */ - iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge); - iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge); - iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge); + iptablesRemoveForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); + iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); + iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); } -static int -networkAddGeneralFirewallRules(virNetworkObjPtr network) +static void +networkAddGeneralFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network) +{ + networkAddGeneralIPv4FirewallRules(fw, network); + networkAddGeneralIPv6FirewallRules(fw, network); +} + + +static void +networkRemoveGeneralFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network) +{ + networkRemoveGeneralIPv4FirewallRules(fw, network); + networkRemoveGeneralIPv6FirewallRules(fw, network); +} + +static void +networkAddChecksumFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network) { size_t i; virNetworkIpDefPtr ipv4def; @@ -554,161 +532,44 @@ networkAddGeneralFirewallRules(virNetworkObjPtr network) for (i = 0; (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i)); i++) { - if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot) + if (ipv4def->nranges || ipv4def->nhosts) break; } - /* allow DHCP requests through to dnsmasq */ - - if (iptablesAddTcpInput(AF_INET, network->def->bridge, 67) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow DHCP requests from '%s'"), - network->def->bridge); - goto err1; - } - - if (iptablesAddUdpInput(AF_INET, network->def->bridge, 67) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow DHCP requests from '%s'"), - network->def->bridge); - goto err2; - } - - if (iptablesAddUdpOutput(AF_INET, network->def->bridge, 68) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow DHCP replies to '%s'"), - network->def->bridge); - goto err3; - } - /* If we are doing local DHCP service on this network, attempt to * add a rule that will fixup the checksum of DHCP response * packets back to the guests (but report failure without * aborting, since not all iptables implementations support it). */ - - if (ipv4def && (ipv4def->nranges || ipv4def->nhosts) && - (iptablesAddOutputFixUdpChecksum(network->def->bridge, 68) < 0)) { - VIR_WARN("Could not add rule to fixup DHCP response checksums " - "on network '%s'.", network->def->name); - VIR_WARN("May need to update iptables package & kernel to support CHECKSUM rule."); - } - - /* allow DNS requests through to dnsmasq */ - if (iptablesAddTcpInput(AF_INET, network->def->bridge, 53) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow DNS requests from '%s'"), - network->def->bridge); - goto err4; - } - - if (iptablesAddUdpInput(AF_INET, network->def->bridge, 53) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow DNS requests from '%s'"), - network->def->bridge); - goto err5; - } - - /* allow TFTP requests through to dnsmasq if necessary */ - if (ipv4def && ipv4def->tftproot && - iptablesAddUdpInput(AF_INET, network->def->bridge, 69) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow TFTP requests from '%s'"), - network->def->bridge); - goto err6; - } - - /* Catch all rules to block forwarding to/from bridges */ - - if (iptablesAddForwardRejectOut(AF_INET, network->def->bridge) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to block outbound traffic from '%s'"), - network->def->bridge); - goto err7; - } - - if (iptablesAddForwardRejectIn(AF_INET, network->def->bridge) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to block inbound traffic to '%s'"), - network->def->bridge); - goto err8; - } - - /* Allow traffic between guests on the same bridge */ - if (iptablesAddForwardAllowCross(AF_INET, network->def->bridge) < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("failed to add iptables rule to allow cross bridge traffic on '%s'"), - network->def->bridge); - goto err9; - } - - /* add IPv6 general rules, if needed */ - if (networkAddGeneralIp6tablesRules(network) < 0) { - goto err10; - } - - return 0; - - /* unwind in reverse order from the point of failure */ - err10: - iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge); - err9: - iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge); - err8: - iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge); - err7: - if (ipv4def && ipv4def->tftproot) { - iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69); - } - err6: - iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53); - err5: - iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53); - err4: - iptablesRemoveUdpOutput(AF_INET, network->def->bridge, 68); - err3: - iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67); - err2: - iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67); - err1: - return -1; + if (ipv4def) + iptablesAddOutputFixUdpChecksum(fw, network->def->bridge, 68); } static void -networkRemoveGeneralFirewallRules(virNetworkObjPtr network) +networkRemoveChecksumFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network) { size_t i; virNetworkIpDefPtr ipv4def; - networkRemoveGeneralIp6tablesRules(network); - + /* First look for first IPv4 address that has dhcp or tftpboot defined. */ + /* We support dhcp config on 1 IPv4 interface only. */ for (i = 0; (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i)); i++) { - if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot) + if (ipv4def->nranges || ipv4def->nhosts) break; } - iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge); - iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge); - iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge); - if (ipv4def && ipv4def->tftproot) { - iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69); - } - iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53); - iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53); - if (ipv4def && (ipv4def->nranges || ipv4def->nhosts)) { - iptablesRemoveOutputFixUdpChecksum(network->def->bridge, 68); - } - iptablesRemoveUdpOutput(AF_INET, network->def->bridge, 68); - iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67); - iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67); + if (ipv4def) + iptablesRemoveOutputFixUdpChecksum(fw, network->def->bridge, 68); } static int -networkAddIpSpecificFirewallRules(virNetworkObjPtr network, +networkAddIpSpecificFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network, virNetworkIpDefPtr ipdef) { /* NB: in the case of IPv6, routing rules are added when the @@ -717,70 +578,74 @@ networkAddIpSpecificFirewallRules(virNetworkObjPtr network, if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) { if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) - return networkAddMasqueradingFirewallRules(network, ipdef); + return networkAddMasqueradingFirewallRules(fw, network, ipdef); else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) - return networkAddRoutingFirewallRules(network, ipdef); + return networkAddRoutingFirewallRules(fw, network, ipdef); } else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) { - return networkAddRoutingFirewallRules(network, ipdef); + return networkAddRoutingFirewallRules(fw, network, ipdef); } return 0; } -static void -networkRemoveIpSpecificFirewallRules(virNetworkObjPtr network, +static int +networkRemoveIpSpecificFirewallRules(virFirewallPtr fw, + virNetworkObjPtr network, virNetworkIpDefPtr ipdef) { if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) { if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) - networkRemoveMasqueradingFirewallRules(network, ipdef); + return networkRemoveMasqueradingFirewallRules(fw, network, ipdef); else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) - networkRemoveRoutingFirewallRules(network, ipdef); + return networkRemoveRoutingFirewallRules(fw, network, ipdef); } else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) { - networkRemoveRoutingFirewallRules(network, ipdef); + return networkRemoveRoutingFirewallRules(fw, network, ipdef); } + return 0; } /* Add all rules for all ip addresses (and general rules) on a network */ int networkAddFirewallRules(virNetworkObjPtr network) { - size_t i, j; + size_t i; virNetworkIpDefPtr ipdef; - virErrorPtr orig_error; + virFirewallPtr fw = NULL; + int ret = -1; - /* Add "once per network" rules */ - if (networkAddGeneralFirewallRules(network) < 0) - return -1; + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, 0); + + networkAddGeneralFirewallRules(fw, network); for (i = 0; (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i)); i++) { - /* Add address-specific iptables rules */ - if (networkAddIpSpecificFirewallRules(network, ipdef) < 0) { - goto err; - } + if (networkAddIpSpecificFirewallRules(fw, network, ipdef) < 0) + goto cleanup; } - return 0; - err: - /* store the previous error message before attempting removal of rules */ - orig_error = virSaveLastError(); + virFirewallStartRollback(fw, 0); - /* The final failed call to networkAddIpSpecificFirewallRules will - * have removed any rules it created, but we need to remove those - * added for previous IP addresses. - */ - for (j = 0; j < i; j++) { - if ((ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, j))) - networkRemoveIpSpecificFirewallRules(network, ipdef); + for (i = 0; + (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i)); + i++) { + if (networkRemoveIpSpecificFirewallRules(fw, network, ipdef) < 0) + goto cleanup; } - networkRemoveGeneralFirewallRules(network); + networkRemoveGeneralFirewallRules(fw, network); + + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); + networkAddChecksumFirewallRules(fw, network); + + if (virFirewallApply(fw) < 0) + goto cleanup; - /* return the original error */ - virSetError(orig_error); - virFreeError(orig_error); - return -1; + ret = 0; + cleanup: + virFirewallFree(fw); + return ret; } /* Remove all rules for all ip addresses (and general rules) on a network */ @@ -788,11 +653,25 @@ void networkRemoveFirewallRules(virNetworkObjPtr network) { size_t i; virNetworkIpDefPtr ipdef; + virFirewallPtr fw = NULL; + + fw = virFirewallNew(); + + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); + networkRemoveChecksumFirewallRules(fw, network); + + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); for (i = 0; (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i)); i++) { - networkRemoveIpSpecificFirewallRules(network, ipdef); + if (networkRemoveIpSpecificFirewallRules(fw, network, ipdef) < 0) + goto cleanup; } - networkRemoveGeneralFirewallRules(network); + networkRemoveGeneralFirewallRules(fw, network); + + virFirewallApply(fw); + + cleanup: + virFirewallFree(fw); } diff --git a/src/util/viriptables.c b/src/util/viriptables.c index c8c4175..4f3ac9c 100644 --- a/src/util/viriptables.c +++ b/src/util/viriptables.c @@ -54,56 +54,6 @@ VIR_LOG_INIT("util.iptables"); bool iptables_supports_xlock = false; -#if HAVE_FIREWALLD -static char *firewall_cmd_path = NULL; -#endif - -static int -virIpTablesOnceInit(void) -{ - virCommandPtr cmd; - int status; - -#if HAVE_FIREWALLD - firewall_cmd_path = virFindFileInPath("firewall-cmd"); - if (!firewall_cmd_path) { - VIR_INFO("firewall-cmd not found on system. " - "firewalld support disabled for iptables."); - } else { - cmd = virCommandNew(firewall_cmd_path); - - virCommandAddArgList(cmd, "--state", NULL); - /* don't log non-zero status */ - if (virCommandRun(cmd, &status) < 0 || status != 0) { - VIR_INFO("firewall-cmd found but disabled for iptables"); - VIR_FREE(firewall_cmd_path); - firewall_cmd_path = NULL; - } else { - VIR_INFO("using firewalld for iptables commands"); - } - virCommandFree(cmd); - } - - if (firewall_cmd_path) - return 0; - -#endif - - cmd = virCommandNew(IPTABLES_PATH); - virCommandAddArgList(cmd, "-w", "-L", "-n", NULL); - /* don't log non-zero status */ - if (virCommandRun(cmd, &status) < 0 || status != 0) { - VIR_INFO("xtables locking not supported by your iptables"); - } else { - VIR_INFO("using xtables locking for iptables"); - iptables_supports_xlock = true; - } - virCommandFree(cmd); - return 0; -} - -VIR_ONCE_GLOBAL_INIT(virIpTables) - #define VIR_FROM_THIS VIR_FROM_NONE enum { @@ -111,63 +61,10 @@ enum { REMOVE }; -static virCommandPtr -iptablesCommandNew(const char *table, const char *chain, int family, int action) -{ - virCommandPtr cmd = NULL; - virIpTablesInitialize(); -#if HAVE_FIREWALLD - if (firewall_cmd_path) { - cmd = virCommandNew(firewall_cmd_path); - virCommandAddArgList(cmd, "--direct", "--passthrough", - (family == AF_INET6) ? "ipv6" : "ipv4", NULL); - } -#endif - - if (cmd == NULL) { - cmd = virCommandNew((family == AF_INET6) - ? IP6TABLES_PATH : IPTABLES_PATH); - if (iptables_supports_xlock) - virCommandAddArgList(cmd, "-w", NULL); - } - - virCommandAddArgList(cmd, "--table", table, - action == ADD ? "--insert" : "--delete", - chain, NULL); - return cmd; -} - -static int -iptablesCommandRunAndFree(virCommandPtr cmd) -{ - int ret; - ret = virCommandRun(cmd, NULL); - virCommandFree(cmd); - return ret; -} - -static int ATTRIBUTE_SENTINEL -iptablesAddRemoveRule(const char *table, const char *chain, int family, int action, - const char *arg, ...) -{ - va_list args; - virCommandPtr cmd = NULL; - const char *s; - - cmd = iptablesCommandNew(table, chain, family, action); - virCommandAddArg(cmd, arg); - - va_start(args, arg); - while ((s = va_arg(args, const char *))) - virCommandAddArg(cmd, s); - va_end(args); - - return iptablesCommandRunAndFree(cmd); -} - -static int -iptablesInput(int family, +static void +iptablesInput(virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port, int action, @@ -178,18 +75,19 @@ iptablesInput(int family, snprintf(portstr, sizeof(portstr), "%d", port); portstr[sizeof(portstr) - 1] = '\0'; - return iptablesAddRemoveRule("filter", "INPUT", - family, - action, - "--in-interface", iface, - "--protocol", tcp ? "tcp" : "udp", - "--destination-port", portstr, - "--jump", "ACCEPT", - NULL); + virFirewallAddRule(fw, layer, + "--table", "filter", + action == ADD ? "--insert" : "--delete", "INPUT", + "--in-interface", iface, + "--protocol", tcp ? "tcp" : "udp", + "--destination-port", portstr, + "--jump", "ACCEPT", + NULL); } -static int -iptablesOutput(int family, +static void +iptablesOutput(virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port, int action, @@ -200,14 +98,14 @@ iptablesOutput(int family, snprintf(portstr, sizeof(portstr), "%d", port); portstr[sizeof(portstr) - 1] = '\0'; - return iptablesAddRemoveRule("filter", "OUTPUT", - family, - action, - "--out-interface", iface, - "--protocol", tcp ? "tcp" : "udp", - "--destination-port", portstr, - "--jump", "ACCEPT", - NULL); + virFirewallAddRule(fw, layer, + "--table", "filter", + action == ADD ? "--insert" : "--delete", "OUTPUT", + "--out-interface", iface, + "--protocol", tcp ? "tcp" : "udp", + "--destination-port", portstr, + "--jump", "ACCEPT", + NULL); } /** @@ -218,16 +116,14 @@ iptablesOutput(int family, * * Add an input to the IP table allowing access to the given @port on * the given @iface interface for TCP packets - * - * Returns 0 in case of success or an error code in case of error */ - -int -iptablesAddTcpInput(int family, +void +iptablesAddTcpInput(virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port) { - return iptablesInput(family, iface, port, ADD, 1); + iptablesInput(fw, layer, iface, port, ADD, 1); } /** @@ -238,15 +134,14 @@ iptablesAddTcpInput(int family, * * Removes an input from the IP table, hence forbidding access to the given * @port on the given @iface interface for TCP packets - * - * Returns 0 in case of success or an error code in case of error */ -int -iptablesRemoveTcpInput(int family, +void +iptablesRemoveTcpInput(virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port) { - return iptablesInput(family, iface, port, REMOVE, 1); + iptablesInput(fw, layer, iface, port, REMOVE, 1); } /** @@ -257,16 +152,14 @@ iptablesRemoveTcpInput(int family, * * Add an input to the IP table allowing access to the given @port on * the given @iface interface for UDP packets - * - * Returns 0 in case of success or an error code in case of error */ - -int -iptablesAddUdpInput(int family, +void +iptablesAddUdpInput(virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port) { - return iptablesInput(family, iface, port, ADD, 0); + iptablesInput(fw, layer, iface, port, ADD, 0); } /** @@ -277,15 +170,14 @@ iptablesAddUdpInput(int family, * * Removes an input from the IP table, hence forbidding access to the given * @port on the given @iface interface for UDP packets - * - * Returns 0 in case of success or an error code in case of error */ -int -iptablesRemoveUdpInput(int family, +void +iptablesRemoveUdpInput(virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port) { - return iptablesInput(family, iface, port, REMOVE, 0); + return iptablesInput(fw, layer, iface, port, REMOVE, 0); } /** @@ -296,16 +188,14 @@ iptablesRemoveUdpInput(int family, * * Add an output to the IP table allowing access to the given @port from * the given @iface interface for UDP packets - * - * Returns 0 in case of success or an error code in case of error */ - -int -iptablesAddUdpOutput(int family, +void +iptablesAddUdpOutput(virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port) { - return iptablesOutput(family, iface, port, ADD, 0); + iptablesOutput(fw, layer, iface, port, ADD, 0); } /** @@ -316,15 +206,14 @@ iptablesAddUdpOutput(int family, * * Removes an output from the IP table, hence forbidding access to the given * @port from the given @iface interface for UDP packets - * - * Returns 0 in case of success or an error code in case of error */ -int -iptablesRemoveUdpOutput(int family, +void +iptablesRemoveUdpOutput(virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port) { - return iptablesOutput(family, iface, port, REMOVE, 0); + iptablesOutput(fw, layer, iface, port, REMOVE, 0); } @@ -364,34 +253,40 @@ static char *iptablesFormatNetwork(virSocketAddr *netaddr, * to proceed to WAN */ static int -iptablesForwardAllowOut(virSocketAddr *netaddr, +iptablesForwardAllowOut(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev, int action) { - int ret; char *networkstr; - virCommandPtr cmd = NULL; + virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ? + VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; - cmd = iptablesCommandNew("filter", "FORWARD", - VIR_SOCKET_ADDR_FAMILY(netaddr), - action); - virCommandAddArgList(cmd, - "--source", networkstr, - "--in-interface", iface, NULL); - if (physdev && physdev[0]) - virCommandAddArgList(cmd, "--out-interface", physdev, NULL); - - virCommandAddArgList(cmd, "--jump", "ACCEPT", NULL); + virFirewallAddRule(fw, layer, + "--table", "filter", + action == ADD ? "--insert" : "--delete", "FORWARD", + "--source", networkstr, + "--in-interface", iface, + "--out-interface", physdev, + "--jump", "ACCEPT", + NULL); + else + virFirewallAddRule(fw, layer, + "--table", "filter", + action == ADD ? "--insert" : "--delete", "FORWARD", + "--source", networkstr, + "--in-interface", iface, + "--jump", "ACCEPT", + NULL); - ret = iptablesCommandRunAndFree(cmd); VIR_FREE(networkstr); - return ret; + return 0; } /** @@ -408,12 +303,13 @@ iptablesForwardAllowOut(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise */ int -iptablesAddForwardAllowOut(virSocketAddr *netaddr, +iptablesAddForwardAllowOut(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev) { - return iptablesForwardAllowOut(netaddr, prefix, iface, physdev, ADD); + return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev, ADD); } /** @@ -430,12 +326,13 @@ iptablesAddForwardAllowOut(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise */ int -iptablesRemoveForwardAllowOut(virSocketAddr *netaddr, +iptablesRemoveForwardAllowOut(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev) { - return iptablesForwardAllowOut(netaddr, prefix, iface, physdev, REMOVE); + return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev, REMOVE); } @@ -443,42 +340,44 @@ iptablesRemoveForwardAllowOut(virSocketAddr *netaddr, * and associated with an existing connection */ static int -iptablesForwardAllowRelatedIn(virSocketAddr *netaddr, +iptablesForwardAllowRelatedIn(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev, int action) { - int ret; + virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ? + VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6; char *networkstr; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; - if (physdev && physdev[0]) { - ret = iptablesAddRemoveRule("filter", "FORWARD", - VIR_SOCKET_ADDR_FAMILY(netaddr), - action, - "--destination", networkstr, - "--in-interface", physdev, - "--out-interface", iface, - "--match", "conntrack", - "--ctstate", "ESTABLISHED,RELATED", - "--jump", "ACCEPT", - NULL); - } else { - ret = iptablesAddRemoveRule("filter", "FORWARD", - VIR_SOCKET_ADDR_FAMILY(netaddr), - action, - "--destination", networkstr, - "--out-interface", iface, - "--match", "conntrack", - "--ctstate", "ESTABLISHED,RELATED", - "--jump", "ACCEPT", - NULL); - } + if (physdev && physdev[0]) + virFirewallAddRule(fw, layer, + "--table", "filter", + action == ADD ? "--insert" : "--delete", "FORWARD", + "--destination", networkstr, + "--in-interface", physdev, + "--out-interface", iface, + "--match", "conntrack", + "--ctstate", "ESTABLISHED,RELATED", + "--jump", "ACCEPT", + NULL); + else + virFirewallAddRule(fw, layer, + "--table", "filter", + action == ADD ? "--insert" : "--delete", "FORWARD", + "--destination", networkstr, + "--out-interface", iface, + "--match", "conntrack", + "--ctstate", "ESTABLISHED,RELATED", + "--jump", "ACCEPT", + NULL); + VIR_FREE(networkstr); - return ret; + return 0; } /** @@ -495,12 +394,13 @@ iptablesForwardAllowRelatedIn(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise */ int -iptablesAddForwardAllowRelatedIn(virSocketAddr *netaddr, +iptablesAddForwardAllowRelatedIn(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev) { - return iptablesForwardAllowRelatedIn(netaddr, prefix, iface, physdev, ADD); + return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev, ADD); } /** @@ -517,49 +417,51 @@ iptablesAddForwardAllowRelatedIn(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise */ int -iptablesRemoveForwardAllowRelatedIn(virSocketAddr *netaddr, +iptablesRemoveForwardAllowRelatedIn(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev) { - return iptablesForwardAllowRelatedIn(netaddr, prefix, iface, physdev, REMOVE); + return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev, REMOVE); } /* Allow all traffic destined to the bridge, with a valid network address */ static int -iptablesForwardAllowIn(virSocketAddr *netaddr, +iptablesForwardAllowIn(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev, int action) { - int ret; + virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ? + VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6; char *networkstr; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; - if (physdev && physdev[0]) { - ret = iptablesAddRemoveRule("filter", "FORWARD", - VIR_SOCKET_ADDR_FAMILY(netaddr), - action, - "--destination", networkstr, - "--in-interface", physdev, - "--out-interface", iface, - "--jump", "ACCEPT", - NULL); - } else { - ret = iptablesAddRemoveRule("filter", "FORWARD", - VIR_SOCKET_ADDR_FAMILY(netaddr), - action, - "--destination", networkstr, - "--out-interface", iface, - "--jump", "ACCEPT", - NULL); - } + if (physdev && physdev[0]) + virFirewallAddRule(fw, layer, + "--table", "filter", + action == ADD ? "--insert" : "--delete", "FORWARD", + "--destination", networkstr, + "--in-interface", physdev, + "--out-interface", iface, + "--jump", "ACCEPT", + NULL); + else + virFirewallAddRule(fw, layer, + "--table", "filter", + action == ADD ? "--insert" : "--delete", "FORWARD", + "--destination", networkstr, + "--out-interface", iface, + "--jump", "ACCEPT", + NULL); VIR_FREE(networkstr); - return ret; + return 0; } /** @@ -576,12 +478,13 @@ iptablesForwardAllowIn(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise */ int -iptablesAddForwardAllowIn(virSocketAddr *netaddr, +iptablesAddForwardAllowIn(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev) { - return iptablesForwardAllowIn(netaddr, prefix, iface, physdev, ADD); + return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev, ADD); } /** @@ -598,30 +501,13 @@ iptablesAddForwardAllowIn(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise */ int -iptablesRemoveForwardAllowIn(virSocketAddr *netaddr, +iptablesRemoveForwardAllowIn(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev) { - return iptablesForwardAllowIn(netaddr, prefix, iface, physdev, REMOVE); -} - - -/* Allow all traffic between guests on the same bridge, - * with a valid network address - */ -static int -iptablesForwardAllowCross(int family, - const char *iface, - int action) -{ - return iptablesAddRemoveRule("filter", "FORWARD", - family, - action, - "--in-interface", iface, - "--out-interface", iface, - "--jump", "ACCEPT", - NULL); + return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev, REMOVE); } /** @@ -635,11 +521,18 @@ iptablesForwardAllowCross(int family, * * Returns 0 in case of success or an error code otherwise */ -int -iptablesAddForwardAllowCross(int family, +void +iptablesAddForwardAllowCross(virFirewallPtr fw, + virFirewallLayer layer, const char *iface) { - return iptablesForwardAllowCross(family, iface, ADD); + virFirewallAddRule(fw, layer, + "--table", "filter", + "--insert", "FORWARD", + "--in-interface", iface, + "--out-interface", iface, + "--jump", "ACCEPT", + NULL); } /** @@ -653,28 +546,18 @@ iptablesAddForwardAllowCross(int family, * * Returns 0 in case of success or an error code otherwise */ -int -iptablesRemoveForwardAllowCross(int family, +void +iptablesRemoveForwardAllowCross(virFirewallPtr fw, + virFirewallLayer layer, const char *iface) { - return iptablesForwardAllowCross(family, iface, REMOVE); -} - - -/* Drop all traffic trying to forward from the bridge. - * ie the bridge is the in interface - */ -static int -iptablesForwardRejectOut(int family, - const char *iface, - int action) -{ - return iptablesAddRemoveRule("filter", "FORWARD", - family, - action, - "--in-interface", iface, - "--jump", "REJECT", - NULL); + virFirewallAddRule(fw, layer, + "--table", "filter", + "--delete", "FORWARD", + "--in-interface", iface, + "--out-interface", iface, + "--jump", "ACCEPT", + NULL); } /** @@ -687,11 +570,17 @@ iptablesForwardRejectOut(int family, * * Returns 0 in case of success or an error code otherwise */ -int -iptablesAddForwardRejectOut(int family, +void +iptablesAddForwardRejectOut(virFirewallPtr fw, + virFirewallLayer layer, const char *iface) { - return iptablesForwardRejectOut(family, iface, ADD); + virFirewallAddRule(fw, layer, + "--table", "filter", + "--insert", "FORWARD", + "--in-interface", iface, + "--jump", "REJECT", + NULL); } /** @@ -704,32 +593,20 @@ iptablesAddForwardRejectOut(int family, * * Returns 0 in case of success or an error code otherwise */ -int -iptablesRemoveForwardRejectOut(int family, +void +iptablesRemoveForwardRejectOut(virFirewallPtr fw, + virFirewallLayer layer, const char *iface) { - return iptablesForwardRejectOut(family, iface, REMOVE); + virFirewallAddRule(fw, layer, + "--table", "filter", + "--delete", "FORWARD", + "--in-interface", iface, + "--jump", "REJECT", + NULL); } - - -/* Drop all traffic trying to forward to the bridge. - * ie the bridge is the out interface - */ -static int -iptablesForwardRejectIn(int family, - const char *iface, - int action) -{ - return iptablesAddRemoveRule("filter", "FORWARD", - family, - action, - "--out-interface", iface, - "--jump", "REJECT", - NULL); -} - /** * iptablesAddForwardRejectIn: * @ctx: pointer to the IP table context @@ -740,11 +617,17 @@ iptablesForwardRejectIn(int family, * * Returns 0 in case of success or an error code otherwise */ -int -iptablesAddForwardRejectIn(int family, +void +iptablesAddForwardRejectIn(virFirewallPtr fw, + virFirewallLayer layer, const char *iface) { - return iptablesForwardRejectIn(family, iface, ADD); + virFirewallAddRule(fw, layer, + "--table", "filter", + "--insert", "FORWARD", + "--out-interface", iface, + "--jump", "REJECT", + NULL); } /** @@ -757,11 +640,17 @@ iptablesAddForwardRejectIn(int family, * * Returns 0 in case of success or an error code otherwise */ -int -iptablesRemoveForwardRejectIn(int family, +void +iptablesRemoveForwardRejectIn(virFirewallPtr fw, + virFirewallLayer layer, const char *iface) { - return iptablesForwardRejectIn(family, iface, REMOVE); + virFirewallAddRule(fw, layer, + "--table", "filter", + "--delete", "FORWARD", + "--out-interface", iface, + "--jump", "REJECT", + NULL); } @@ -769,7 +658,8 @@ iptablesRemoveForwardRejectIn(int family, * with the bridge */ static int -iptablesForwardMasquerade(virSocketAddr *netaddr, +iptablesForwardMasquerade(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, virSocketAddrRangePtr addr, @@ -783,7 +673,7 @@ iptablesForwardMasquerade(virSocketAddr *netaddr, char *addrEndStr = NULL; char *portRangeStr = NULL; char *natRangeStr = NULL; - virCommandPtr cmd = NULL; + virFirewallRulePtr rule; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; @@ -805,16 +695,25 @@ iptablesForwardMasquerade(virSocketAddr *netaddr, } } - cmd = iptablesCommandNew("nat", "POSTROUTING", AF_INET, action); - virCommandAddArgList(cmd, "--source", networkstr, NULL); - - if (protocol && protocol[0]) - virCommandAddArgList(cmd, "-p", protocol, NULL); - - virCommandAddArgList(cmd, "!", "--destination", networkstr, NULL); + if (protocol && protocol[0]) { + rule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "--table", "nat", + action == ADD ? "--insert" : "--delete", "POSTROUTING", + "--source", networkstr, + "-p", protocol, + "!", "--destination", networkstr, + NULL); + } else { + rule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "--table", "nat", + action == ADD ? "--insert" : "--delete", "POSTROUTING", + "--source", networkstr, + "!", "--destination", networkstr, + NULL); + } if (physdev && physdev[0]) - virCommandAddArgList(cmd, "--out-interface", physdev, NULL); + virFirewallRuleAddArgList(fw, rule, "--out-interface", physdev, NULL); if (protocol && protocol[0]) { if (port->start == 0 && port->end == 0) { @@ -848,18 +747,20 @@ iptablesForwardMasquerade(virSocketAddr *netaddr, if (r < 0) goto cleanup; - virCommandAddArgList(cmd, "--jump", "SNAT", + virFirewallRuleAddArgList(fw, rule, + "--jump", "SNAT", "--to-source", natRangeStr, NULL); - } else { - virCommandAddArgList(cmd, "--jump", "MASQUERADE", NULL); + } else { + virFirewallRuleAddArgList(fw, rule, + "--jump", "MASQUERADE", NULL); - if (portRangeStr && portRangeStr[0]) - virCommandAddArgList(cmd, "--to-ports", &portRangeStr[1], NULL); - } + if (portRangeStr && portRangeStr[0]) + virFirewallRuleAddArgList(fw, rule, + "--to-ports", &portRangeStr[1], NULL); + } - ret = virCommandRun(cmd, NULL); + ret = 0; cleanup: - virCommandFree(cmd); VIR_FREE(networkstr); VIR_FREE(addrStartStr); VIR_FREE(addrEndStr); @@ -882,14 +783,15 @@ iptablesForwardMasquerade(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise */ int -iptablesAddForwardMasquerade(virSocketAddr *netaddr, +iptablesAddForwardMasquerade(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, virSocketAddrRangePtr addr, virPortRangePtr port, const char *protocol) { - return iptablesForwardMasquerade(netaddr, prefix, physdev, addr, port, + return iptablesForwardMasquerade(fw, netaddr, prefix, physdev, addr, port, protocol, ADD); } @@ -907,14 +809,15 @@ iptablesAddForwardMasquerade(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise */ int -iptablesRemoveForwardMasquerade(virSocketAddr *netaddr, +iptablesRemoveForwardMasquerade(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, virSocketAddrRangePtr addr, virPortRangePtr port, const char *protocol) { - return iptablesForwardMasquerade(netaddr, prefix, physdev, addr, port, + return iptablesForwardMasquerade(fw, netaddr, prefix, physdev, addr, port, protocol, REMOVE); } @@ -923,7 +826,8 @@ iptablesRemoveForwardMasquerade(virSocketAddr *netaddr, * if said traffic targets @destaddr. */ static int -iptablesForwardDontMasquerade(virSocketAddr *netaddr, +iptablesForwardDontMasquerade(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, const char *destaddr, @@ -931,7 +835,6 @@ iptablesForwardDontMasquerade(virSocketAddr *netaddr, { int ret = -1; char *networkstr = NULL; - virCommandPtr cmd = NULL; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; @@ -944,16 +847,26 @@ iptablesForwardDontMasquerade(virSocketAddr *netaddr, goto cleanup; } - cmd = iptablesCommandNew("nat", "POSTROUTING", AF_INET, action); - if (physdev && physdev[0]) - virCommandAddArgList(cmd, "--out-interface", physdev, NULL); - - virCommandAddArgList(cmd, "--source", networkstr, - "--destination", destaddr, "--jump", "RETURN", NULL); - ret = virCommandRun(cmd, NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "--table", "nat", + action == ADD ? "--insert" : "--delete", "POSTROUTING", + "--out-interface", physdev, + "--source", networkstr, + "--destination", destaddr, + "--jump", "RETURN", + NULL); + else + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "--table", "nat", + action == ADD ? "--insert" : "--delete", "POSTROUTING", + "--source", networkstr, + "--destination", destaddr, + "--jump", "RETURN", + NULL); + + ret = 0; cleanup: - virCommandFree(cmd); VIR_FREE(networkstr); return ret; } @@ -973,12 +886,13 @@ iptablesForwardDontMasquerade(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise. */ int -iptablesAddDontMasquerade(virSocketAddr *netaddr, +iptablesAddDontMasquerade(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, const char *destaddr) { - return iptablesForwardDontMasquerade(netaddr, prefix, physdev, destaddr, + return iptablesForwardDontMasquerade(fw, netaddr, prefix, physdev, destaddr, ADD); } @@ -997,18 +911,20 @@ iptablesAddDontMasquerade(virSocketAddr *netaddr, * Returns 0 in case of success or an error code otherwise. */ int -iptablesRemoveDontMasquerade(virSocketAddr *netaddr, +iptablesRemoveDontMasquerade(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, const char *destaddr) { - return iptablesForwardDontMasquerade(netaddr, prefix, physdev, destaddr, + return iptablesForwardDontMasquerade(fw, netaddr, prefix, physdev, destaddr, REMOVE); } -static int -iptablesOutputFixUdpChecksum(const char *iface, +static void +iptablesOutputFixUdpChecksum(virFirewallPtr fw, + const char *iface, int port, int action) { @@ -1017,14 +933,14 @@ iptablesOutputFixUdpChecksum(const char *iface, snprintf(portstr, sizeof(portstr), "%d", port); portstr[sizeof(portstr) - 1] = '\0'; - return iptablesAddRemoveRule("mangle", "POSTROUTING", - AF_INET, - action, - "--out-interface", iface, - "--protocol", "udp", - "--destination-port", portstr, - "--jump", "CHECKSUM", "--checksum-fill", - NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, + "--table", "mangle", + action == ADD ? "--insert" : "--delete", "POSTROUTING", + "--out-interface", iface, + "--protocol", "udp", + "--destination-port", portstr, + "--jump", "CHECKSUM", "--checksum-fill", + NULL); } /** @@ -1037,16 +953,13 @@ iptablesOutputFixUdpChecksum(const char *iface, * checksum of packets with the given destination @port. * the given @iface interface for TCP packets. * - * Returns 0 in case of success or an error code in case of error. - * (NB: if the system's iptables does not support checksum mangling, - * this will return an error, which should be ignored.) */ - -int -iptablesAddOutputFixUdpChecksum(const char *iface, +void +iptablesAddOutputFixUdpChecksum(virFirewallPtr fw, + const char *iface, int port) { - return iptablesOutputFixUdpChecksum(iface, port, ADD); + iptablesOutputFixUdpChecksum(fw, iface, port, ADD); } /** @@ -1057,14 +970,11 @@ iptablesAddOutputFixUdpChecksum(const char *iface, * * Removes the checksum fixup rule that was previous added with * iptablesAddOutputFixUdpChecksum. - * - * Returns 0 in case of success or an error code in case of error - * (again, if iptables doesn't support checksum fixup, this will - * return an error, which should be ignored) */ -int -iptablesRemoveOutputFixUdpChecksum(const char *iface, +void +iptablesRemoveOutputFixUdpChecksum(virFirewallPtr fw, + const char *iface, int port) { - return iptablesOutputFixUdpChecksum(iface, port, REMOVE); + iptablesOutputFixUdpChecksum(fw, iface, port, REMOVE); } diff --git a/src/util/viriptables.h b/src/util/viriptables.h index 2f9a212..9ea25fc 100644 --- a/src/util/viriptables.h +++ b/src/util/viriptables.h @@ -21,97 +21,131 @@ * Mark McLoughlin <markmc@redhat.com> */ -#ifndef __QEMUD_IPTABLES_H__ -# define __QEMUD_IPTABLES_H__ +#ifndef __VIR_IPTABLES_H__ +# define __VIR_IPTABLES_H__ # include "virsocketaddr.h" +# include "virfirewall.h" -int iptablesAddTcpInput (int family, +void iptablesAddTcpInput (virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port); -int iptablesRemoveTcpInput (int family, +void iptablesRemoveTcpInput (virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port); -int iptablesAddUdpInput (int family, +void iptablesAddUdpInput (virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port); -int iptablesRemoveUdpInput (int family, +void iptablesRemoveUdpInput (virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port); -int iptablesAddUdpOutput (int family, +void iptablesAddUdpOutput (virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port); -int iptablesRemoveUdpOutput (int family, +void iptablesRemoveUdpOutput (virFirewallPtr fw, + virFirewallLayer layer, const char *iface, int port); -int iptablesAddForwardAllowOut (virSocketAddr *netaddr, +int iptablesAddForwardAllowOut (virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, - const char *physdev); -int iptablesRemoveForwardAllowOut (virSocketAddr *netaddr, + const char *physdev) + ATTRIBUTE_RETURN_CHECK; +int iptablesRemoveForwardAllowOut (virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, - const char *physdev); - -int iptablesAddForwardAllowRelatedIn(virSocketAddr *netaddr, - unsigned int prefix, - const char *iface, - const char *physdev); -int iptablesRemoveForwardAllowRelatedIn(virSocketAddr *netaddr, + const char *physdev) + ATTRIBUTE_RETURN_CHECK; +int iptablesAddForwardAllowRelatedIn(virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, - const char *physdev); + const char *physdev) + ATTRIBUTE_RETURN_CHECK; +int iptablesRemoveForwardAllowRelatedIn(virFirewallPtr fw, + virSocketAddr *netaddr, + unsigned int prefix, + const char *iface, + const char *physdev) + ATTRIBUTE_RETURN_CHECK; -int iptablesAddForwardAllowIn (virSocketAddr *netaddr, +int iptablesAddForwardAllowIn (virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, - const char *physdev); -int iptablesRemoveForwardAllowIn (virSocketAddr *netaddr, + const char *physdev) + ATTRIBUTE_RETURN_CHECK; +int iptablesRemoveForwardAllowIn (virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *iface, - const char *physdev); + const char *physdev) + ATTRIBUTE_RETURN_CHECK; -int iptablesAddForwardAllowCross (int family, +void iptablesAddForwardAllowCross (virFirewallPtr fw, + virFirewallLayer layer, const char *iface); -int iptablesRemoveForwardAllowCross (int family, +void iptablesRemoveForwardAllowCross (virFirewallPtr fw, + virFirewallLayer layer, const char *iface); -int iptablesAddForwardRejectOut (int family, +void iptablesAddForwardRejectOut (virFirewallPtr fw, + virFirewallLayer layer, const char *iface); -int iptablesRemoveForwardRejectOut (int family, +void iptablesRemoveForwardRejectOut (virFirewallPtr fw, + virFirewallLayer layer, const char *iface); -int iptablesAddForwardRejectIn (int family, +void iptablesAddForwardRejectIn (virFirewallPtr fw, + virFirewallLayer layer, const char *iface); -int iptablesRemoveForwardRejectIn (int family, +void iptablesRemoveForwardRejectIn (virFirewallPtr fw, + virFirewallLayer layery, const char *iface); -int iptablesAddForwardMasquerade (virSocketAddr *netaddr, +int iptablesAddForwardMasquerade (virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, virSocketAddrRangePtr addr, virPortRangePtr port, - const char *protocol); -int iptablesRemoveForwardMasquerade (virSocketAddr *netaddr, + const char *protocol) + ATTRIBUTE_RETURN_CHECK; +int iptablesRemoveForwardMasquerade (virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, virSocketAddrRangePtr addr, virPortRangePtr port, - const char *protocol); -int iptablesAddDontMasquerade (virSocketAddr *netaddr, + const char *protocol) + ATTRIBUTE_RETURN_CHECK; +int iptablesAddDontMasquerade (virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, - const char *destaddr); -int iptablesRemoveDontMasquerade (virSocketAddr *netaddr, + const char *destaddr) + ATTRIBUTE_RETURN_CHECK; +int iptablesRemoveDontMasquerade (virFirewallPtr fw, + virSocketAddr *netaddr, unsigned int prefix, const char *physdev, - const char *destaddr); -int iptablesAddOutputFixUdpChecksum (const char *iface, + const char *destaddr) + ATTRIBUTE_RETURN_CHECK; +void iptablesAddOutputFixUdpChecksum (virFirewallPtr fw, + const char *iface, int port); -int iptablesRemoveOutputFixUdpChecksum (const char *iface, +void iptablesRemoveOutputFixUdpChecksum (virFirewallPtr fw, + const char *iface, int port); -#endif /* __QEMUD_IPTABLES_H__ */ +#endif /* __VIR_IPTABLES_H__ */ -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Update the iptablesXXXX methods so that instead of directly executing iptables commands, they populate rules in an instance of virFirewallPtr. The bridge driver can thus construct the ruleset and then invoke it in one operation having rollback handled automatically.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
I looked at this 2 times now... ACK

The networkCheckRouteCollision, networkAddFirewallRules and networkRemoveFirewallRules APIs all take a virNetworkObjPtr instance, but only ever access the 'def' member. It thus simplifies testing if the APIs are changed to just take a virNetworkDefPtr instead Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/network/bridge_driver.c | 18 +-- src/network/bridge_driver_linux.c | 226 +++++++++++++++++------------------ src/network/bridge_driver_nop.c | 6 +- src/network/bridge_driver_platform.h | 7 +- 4 files changed, 129 insertions(+), 128 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index eb276cd..201b22f 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -1650,8 +1650,8 @@ networkReloadFirewallRules(virNetworkDriverStatePtr driver) /* Only the three L3 network types that are configured by libvirt * need to have iptables rules reloaded. */ - networkRemoveFirewallRules(network); - if (networkAddFirewallRules(network) < 0) { + networkRemoveFirewallRules(network->def); + if (networkAddFirewallRules(network->def) < 0) { /* failed to add but already logged */ } } @@ -1833,7 +1833,7 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver, int tapfd = -1; /* Check to see if any network IP collides with an existing route */ - if (networkCheckRouteCollision(network) < 0) + if (networkCheckRouteCollision(network->def) < 0) return -1; /* Create and configure the bridge device */ @@ -1882,7 +1882,7 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver, goto err1; /* Add "once per network" rules */ - if (networkAddFirewallRules(network) < 0) + if (networkAddFirewallRules(network->def) < 0) goto err1; for (i = 0; @@ -1975,7 +1975,7 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver, err2: if (!save_err) save_err = virSaveLastError(); - networkRemoveFirewallRules(network); + networkRemoveFirewallRules(network->def); err1: if (!save_err) @@ -2029,7 +2029,7 @@ static int networkShutdownNetworkVirtual(virNetworkDriverStatePtr driver ATTRIBU ignore_value(virNetDevSetOnline(network->def->bridge, 0)); - networkRemoveFirewallRules(network); + networkRemoveFirewallRules(network->def); ignore_value(virNetDevBridgeDelete(network->def->bridge)); @@ -2897,7 +2897,7 @@ networkUpdate(virNetworkPtr net, * old rules (and remember to load new ones after the * update). */ - networkRemoveFirewallRules(network); + networkRemoveFirewallRules(network->def); needFirewallRefresh = true; break; default: @@ -2909,11 +2909,11 @@ networkUpdate(virNetworkPtr net, /* update the network config in memory/on disk */ if (virNetworkObjUpdate(network, command, section, parentIndex, xml, flags) < 0) { if (needFirewallRefresh) - ignore_value(networkAddFirewallRules(network)); + ignore_value(networkAddFirewallRules(network->def)); goto cleanup; } - if (needFirewallRefresh && networkAddFirewallRules(network) < 0) + if (needFirewallRefresh && networkAddFirewallRules(network->def) < 0) goto cleanup; if (flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG) { diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c index 9f4911b..6b32838 100644 --- a/src/network/bridge_driver_linux.c +++ b/src/network/bridge_driver_linux.c @@ -40,7 +40,7 @@ VIR_LOG_INIT("network.bridge_driver_linux"); * other scenarios where we can ruin host network connectivity. * XXX: Using a proper library is preferred over parsing /proc */ -int networkCheckRouteCollision(virNetworkObjPtr network) +int networkCheckRouteCollision(virNetworkDefPtr def) { int ret = 0, len; char *cur, *buf = NULL; @@ -100,7 +100,7 @@ int networkCheckRouteCollision(virNetworkObjPtr network) addr_val &= mask_val; for (i = 0; - (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, i)); + (ipdef = virNetworkDefGetIpByIndex(def, AF_INET, i)); i++) { unsigned int net_dest; @@ -108,7 +108,7 @@ int networkCheckRouteCollision(virNetworkObjPtr network) if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) { VIR_WARN("Failed to get netmask of '%s'", - network->def->bridge); + def->bridge); continue; } @@ -136,16 +136,16 @@ static const char networkLocalBroadcast[] = "255.255.255.255/32"; static int networkAddMasqueradingFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network, + virNetworkDefPtr def, virNetworkIpDefPtr ipdef) { int prefix = virNetworkIpDefPrefix(ipdef); - const char *forwardIf = virNetworkDefForwardIf(network->def, 0); + const char *forwardIf = virNetworkDefForwardIf(def, 0); if (prefix < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid prefix or netmask for '%s'"), - network->def->bridge); + def->bridge); return -1; } @@ -153,7 +153,7 @@ networkAddMasqueradingFirewallRules(virFirewallPtr fw, if (iptablesAddForwardAllowOut(fw, &ipdef->address, prefix, - network->def->bridge, + def->bridge, forwardIf) < 0) return -1; @@ -163,7 +163,7 @@ networkAddMasqueradingFirewallRules(virFirewallPtr fw, if (iptablesAddForwardAllowRelatedIn(fw, &ipdef->address, prefix, - network->def->bridge, + def->bridge, forwardIf) < 0) return -1; @@ -204,8 +204,8 @@ networkAddMasqueradingFirewallRules(virFirewallPtr fw, &ipdef->address, prefix, forwardIf, - &network->def->forward.addr, - &network->def->forward.port, + &def->forward.addr, + &def->forward.port, NULL) < 0) return -1; @@ -214,8 +214,8 @@ networkAddMasqueradingFirewallRules(virFirewallPtr fw, &ipdef->address, prefix, forwardIf, - &network->def->forward.addr, - &network->def->forward.port, + &def->forward.addr, + &def->forward.port, "udp") < 0) return -1; @@ -224,8 +224,8 @@ networkAddMasqueradingFirewallRules(virFirewallPtr fw, &ipdef->address, prefix, forwardIf, - &network->def->forward.addr, - &network->def->forward.port, + &def->forward.addr, + &def->forward.port, "tcp") < 0) return -1; @@ -250,11 +250,11 @@ networkAddMasqueradingFirewallRules(virFirewallPtr fw, static int networkRemoveMasqueradingFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network, + virNetworkDefPtr def, virNetworkIpDefPtr ipdef) { int prefix = virNetworkIpDefPrefix(ipdef); - const char *forwardIf = virNetworkDefForwardIf(network->def, 0); + const char *forwardIf = virNetworkDefForwardIf(def, 0); if (prefix < 0) return 0; @@ -277,8 +277,8 @@ networkRemoveMasqueradingFirewallRules(virFirewallPtr fw, &ipdef->address, prefix, forwardIf, - &network->def->forward.addr, - &network->def->forward.port, + &def->forward.addr, + &def->forward.port, "tcp") < 0) return -1; @@ -286,8 +286,8 @@ networkRemoveMasqueradingFirewallRules(virFirewallPtr fw, &ipdef->address, prefix, forwardIf, - &network->def->forward.addr, - &network->def->forward.port, + &def->forward.addr, + &def->forward.port, "udp") < 0) return -1; @@ -295,22 +295,22 @@ networkRemoveMasqueradingFirewallRules(virFirewallPtr fw, &ipdef->address, prefix, forwardIf, - &network->def->forward.addr, - &network->def->forward.port, + &def->forward.addr, + &def->forward.port, NULL) < 0) return -1; if (iptablesRemoveForwardAllowRelatedIn(fw, &ipdef->address, prefix, - network->def->bridge, + def->bridge, forwardIf) < 0) return -1; if (iptablesRemoveForwardAllowOut(fw, &ipdef->address, prefix, - network->def->bridge, + def->bridge, forwardIf) < 0) return -1; @@ -320,16 +320,16 @@ networkRemoveMasqueradingFirewallRules(virFirewallPtr fw, static int networkAddRoutingFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network, + virNetworkDefPtr def, virNetworkIpDefPtr ipdef) { int prefix = virNetworkIpDefPrefix(ipdef); - const char *forwardIf = virNetworkDefForwardIf(network->def, 0); + const char *forwardIf = virNetworkDefForwardIf(def, 0); if (prefix < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid prefix or netmask for '%s'"), - network->def->bridge); + def->bridge); return -1; } @@ -337,7 +337,7 @@ networkAddRoutingFirewallRules(virFirewallPtr fw, if (iptablesAddForwardAllowOut(fw, &ipdef->address, prefix, - network->def->bridge, + def->bridge, forwardIf) < 0) return -1; @@ -345,7 +345,7 @@ networkAddRoutingFirewallRules(virFirewallPtr fw, if (iptablesAddForwardAllowIn(fw, &ipdef->address, prefix, - network->def->bridge, + def->bridge, forwardIf) < 0) return -1; @@ -355,11 +355,11 @@ networkAddRoutingFirewallRules(virFirewallPtr fw, static int networkRemoveRoutingFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network, + virNetworkDefPtr def, virNetworkIpDefPtr ipdef) { int prefix = virNetworkIpDefPrefix(ipdef); - const char *forwardIf = virNetworkDefForwardIf(network->def, 0); + const char *forwardIf = virNetworkDefForwardIf(def, 0); if (prefix < 0) return 0; @@ -367,14 +367,14 @@ networkRemoveRoutingFirewallRules(virFirewallPtr fw, if (iptablesRemoveForwardAllowIn(fw, &ipdef->address, prefix, - network->def->bridge, + def->bridge, forwardIf) < 0) return -1; if (iptablesRemoveForwardAllowOut(fw, &ipdef->address, prefix, - network->def->bridge, + def->bridge, forwardIf) < 0) return -1; @@ -384,7 +384,7 @@ networkRemoveRoutingFirewallRules(virFirewallPtr fw, static void networkAddGeneralIPv4FirewallRules(virFirewallPtr fw, - virNetworkObjPtr network) + virNetworkDefPtr def) { size_t i; virNetworkIpDefPtr ipv4def; @@ -392,60 +392,60 @@ networkAddGeneralIPv4FirewallRules(virFirewallPtr fw, /* First look for first IPv4 address that has dhcp or tftpboot defined. */ /* We support dhcp config on 1 IPv4 interface only. */ for (i = 0; - (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i)); + (ipv4def = virNetworkDefGetIpByIndex(def, AF_INET, i)); i++) { if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot) break; } /* allow DHCP requests through to dnsmasq */ - iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 67); - iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 67); - iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 68); + iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67); + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67); + iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68); /* allow DNS requests through to dnsmasq */ - iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 53); - iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 53); + iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); /* allow TFTP requests through to dnsmasq if necessary */ if (ipv4def && ipv4def->tftproot) - iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 69); + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69); /* Catch all rules to block forwarding to/from bridges */ - iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); - iptablesAddForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); + iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); + iptablesAddForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); /* Allow traffic between guests on the same bridge */ - iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); + iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); } static void networkRemoveGeneralIPv4FirewallRules(virFirewallPtr fw, - virNetworkObjPtr network) + virNetworkDefPtr def) { size_t i; virNetworkIpDefPtr ipv4def; for (i = 0; - (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i)); + (ipv4def = virNetworkDefGetIpByIndex(def, AF_INET, i)); i++) { if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot) break; } - iptablesRemoveForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); - iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); - iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge); + iptablesRemoveForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); + iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); + iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); if (ipv4def && ipv4def->tftproot) - iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 69); + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69); - iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 53); - iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 53); + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); + iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); - iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 68); - iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 67); - iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, network->def->bridge, 67); + iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68); + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67); + iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67); } @@ -456,73 +456,73 @@ networkRemoveGeneralIPv4FirewallRules(virFirewallPtr fw, */ static void networkAddGeneralIPv6FirewallRules(virFirewallPtr fw, - virNetworkObjPtr network) + virNetworkDefPtr def) { - if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) && - !network->def->ipv6nogw) { + if (!virNetworkDefGetIpByIndex(def, AF_INET6, 0) && + !def->ipv6nogw) { return; } /* Catch all rules to block forwarding to/from bridges */ - iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); - iptablesAddForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); + iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge); + iptablesAddForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge); /* Allow traffic between guests on the same bridge */ - iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); + iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge); - if (virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) { + if (virNetworkDefGetIpByIndex(def, AF_INET6, 0)) { /* allow DNS over IPv6 */ - iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 53); - iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 53); - iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 547); + iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); + iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 547); } } static void networkRemoveGeneralIPv6FirewallRules(virFirewallPtr fw, - virNetworkObjPtr network) + virNetworkDefPtr def) { - if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) && - !network->def->ipv6nogw) { + if (!virNetworkDefGetIpByIndex(def, AF_INET6, 0) && + !def->ipv6nogw) { return; } - if (virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) { - iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 547); - iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 53); - iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge, 53); + if (virNetworkDefGetIpByIndex(def, AF_INET6, 0)) { + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 547); + iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); + iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); } /* the following rules are there if no IPv6 address has been defined - * but network->def->ipv6nogw == true + * but def->ipv6nogw == true */ - iptablesRemoveForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); - iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); - iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV6, network->def->bridge); + iptablesRemoveForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge); + iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge); + iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge); } static void networkAddGeneralFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network) + virNetworkDefPtr def) { - networkAddGeneralIPv4FirewallRules(fw, network); - networkAddGeneralIPv6FirewallRules(fw, network); + networkAddGeneralIPv4FirewallRules(fw, def); + networkAddGeneralIPv6FirewallRules(fw, def); } static void networkRemoveGeneralFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network) + virNetworkDefPtr def) { - networkRemoveGeneralIPv4FirewallRules(fw, network); - networkRemoveGeneralIPv6FirewallRules(fw, network); + networkRemoveGeneralIPv4FirewallRules(fw, def); + networkRemoveGeneralIPv6FirewallRules(fw, def); } static void networkAddChecksumFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network) + virNetworkDefPtr def) { size_t i; virNetworkIpDefPtr ipv4def; @@ -530,7 +530,7 @@ networkAddChecksumFirewallRules(virFirewallPtr fw, /* First look for first IPv4 address that has dhcp or tftpboot defined. */ /* We support dhcp config on 1 IPv4 interface only. */ for (i = 0; - (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i)); + (ipv4def = virNetworkDefGetIpByIndex(def, AF_INET, i)); i++) { if (ipv4def->nranges || ipv4def->nhosts) break; @@ -542,13 +542,13 @@ networkAddChecksumFirewallRules(virFirewallPtr fw, * aborting, since not all iptables implementations support it). */ if (ipv4def) - iptablesAddOutputFixUdpChecksum(fw, network->def->bridge, 68); + iptablesAddOutputFixUdpChecksum(fw, def->bridge, 68); } static void networkRemoveChecksumFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network) + virNetworkDefPtr def) { size_t i; virNetworkIpDefPtr ipv4def; @@ -556,33 +556,33 @@ networkRemoveChecksumFirewallRules(virFirewallPtr fw, /* First look for first IPv4 address that has dhcp or tftpboot defined. */ /* We support dhcp config on 1 IPv4 interface only. */ for (i = 0; - (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i)); + (ipv4def = virNetworkDefGetIpByIndex(def, AF_INET, i)); i++) { if (ipv4def->nranges || ipv4def->nhosts) break; } if (ipv4def) - iptablesRemoveOutputFixUdpChecksum(fw, network->def->bridge, 68); + iptablesRemoveOutputFixUdpChecksum(fw, def->bridge, 68); } static int networkAddIpSpecificFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network, + virNetworkDefPtr def, virNetworkIpDefPtr ipdef) { /* NB: in the case of IPv6, routing rules are added when the * forward mode is NAT. This is because IPv6 has no NAT. */ - if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) { + if (def->forward.type == VIR_NETWORK_FORWARD_NAT) { if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) - return networkAddMasqueradingFirewallRules(fw, network, ipdef); + return networkAddMasqueradingFirewallRules(fw, def, ipdef); else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) - return networkAddRoutingFirewallRules(fw, network, ipdef); - } else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) { - return networkAddRoutingFirewallRules(fw, network, ipdef); + return networkAddRoutingFirewallRules(fw, def, ipdef); + } else if (def->forward.type == VIR_NETWORK_FORWARD_ROUTE) { + return networkAddRoutingFirewallRules(fw, def, ipdef); } return 0; } @@ -590,23 +590,23 @@ networkAddIpSpecificFirewallRules(virFirewallPtr fw, static int networkRemoveIpSpecificFirewallRules(virFirewallPtr fw, - virNetworkObjPtr network, + virNetworkDefPtr def, virNetworkIpDefPtr ipdef) { - if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) { + if (def->forward.type == VIR_NETWORK_FORWARD_NAT) { if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) - return networkRemoveMasqueradingFirewallRules(fw, network, ipdef); + return networkRemoveMasqueradingFirewallRules(fw, def, ipdef); else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) - return networkRemoveRoutingFirewallRules(fw, network, ipdef); - } else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) { - return networkRemoveRoutingFirewallRules(fw, network, ipdef); + return networkRemoveRoutingFirewallRules(fw, def, ipdef); + } else if (def->forward.type == VIR_NETWORK_FORWARD_ROUTE) { + return networkRemoveRoutingFirewallRules(fw, def, ipdef); } return 0; } /* Add all rules for all ip addresses (and general rules) on a network */ -int networkAddFirewallRules(virNetworkObjPtr network) +int networkAddFirewallRules(virNetworkDefPtr def) { size_t i; virNetworkIpDefPtr ipdef; @@ -617,27 +617,27 @@ int networkAddFirewallRules(virNetworkObjPtr network) virFirewallStartTransaction(fw, 0); - networkAddGeneralFirewallRules(fw, network); + networkAddGeneralFirewallRules(fw, def); for (i = 0; - (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i)); + (ipdef = virNetworkDefGetIpByIndex(def, AF_UNSPEC, i)); i++) { - if (networkAddIpSpecificFirewallRules(fw, network, ipdef) < 0) + if (networkAddIpSpecificFirewallRules(fw, def, ipdef) < 0) goto cleanup; } virFirewallStartRollback(fw, 0); for (i = 0; - (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i)); + (ipdef = virNetworkDefGetIpByIndex(def, AF_UNSPEC, i)); i++) { - if (networkRemoveIpSpecificFirewallRules(fw, network, ipdef) < 0) + if (networkRemoveIpSpecificFirewallRules(fw, def, ipdef) < 0) goto cleanup; } - networkRemoveGeneralFirewallRules(fw, network); + networkRemoveGeneralFirewallRules(fw, def); virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); - networkAddChecksumFirewallRules(fw, network); + networkAddChecksumFirewallRules(fw, def); if (virFirewallApply(fw) < 0) goto cleanup; @@ -649,7 +649,7 @@ int networkAddFirewallRules(virNetworkObjPtr network) } /* Remove all rules for all ip addresses (and general rules) on a network */ -void networkRemoveFirewallRules(virNetworkObjPtr network) +void networkRemoveFirewallRules(virNetworkDefPtr def) { size_t i; virNetworkIpDefPtr ipdef; @@ -658,17 +658,17 @@ void networkRemoveFirewallRules(virNetworkObjPtr network) fw = virFirewallNew(); virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); - networkRemoveChecksumFirewallRules(fw, network); + networkRemoveChecksumFirewallRules(fw, def); virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); for (i = 0; - (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i)); + (ipdef = virNetworkDefGetIpByIndex(def, AF_UNSPEC, i)); i++) { - if (networkRemoveIpSpecificFirewallRules(fw, network, ipdef) < 0) + if (networkRemoveIpSpecificFirewallRules(fw, def, ipdef) < 0) goto cleanup; } - networkRemoveGeneralFirewallRules(fw, network); + networkRemoveGeneralFirewallRules(fw, def); virFirewallApply(fw); diff --git a/src/network/bridge_driver_nop.c b/src/network/bridge_driver_nop.c index b8aeaba..5e1acd0 100644 --- a/src/network/bridge_driver_nop.c +++ b/src/network/bridge_driver_nop.c @@ -21,16 +21,16 @@ #include <config.h> -int networkCheckRouteCollision(virNetworkObjPtr network ATTRIBUTE_UNUSED) +int networkCheckRouteCollision(virNetworkDefPtr def ATTRIBUTE_UNUSED) { return 0; } -int networkAddFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED) +int networkAddFirewallRules(virNetworkDefPtr def ATTRIBUTE_UNUSED) { return 0; } -void networkRemoveFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED) +void networkRemoveFirewallRules(virNetworkDefPtr def ATTRIBUTE_UNUSED) { } diff --git a/src/network/bridge_driver_platform.h b/src/network/bridge_driver_platform.h index 6a571da..a1286da 100644 --- a/src/network/bridge_driver_platform.h +++ b/src/network/bridge_driver_platform.h @@ -21,6 +21,7 @@ * Author: Daniel P. Berrange <berrange@redhat.com> */ + #ifndef __VIR_BRIDGE_DRIVER_PLATFORM_H__ # define __VIR_BRIDGE_DRIVER_PLATFORM_H__ @@ -50,10 +51,10 @@ struct _virNetworkDriverState { typedef struct _virNetworkDriverState virNetworkDriverState; typedef virNetworkDriverState *virNetworkDriverStatePtr; -int networkCheckRouteCollision(virNetworkObjPtr network); +int networkCheckRouteCollision(virNetworkDefPtr def); -int networkAddFirewallRules(virNetworkObjPtr network); +int networkAddFirewallRules(virNetworkDefPtr def); -void networkRemoveFirewallRules(virNetworkObjPtr network); +void networkRemoveFirewallRules(virNetworkDefPtr def); #endif /* __VIR_BRIDGE_DRIVER_PLATFORM_H__ */ -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
The networkCheckRouteCollision, networkAddFirewallRules and networkRemoveFirewallRules APIs all take a virNetworkObjPtr instance, but only ever access the 'def' member. It thus simplifies testing if the APIs are changed to just take a virNetworkDefPtr instead
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
diff --git a/src/network/bridge_driver_platform.h b/src/network/bridge_driver_platform.h index 6a571da..a1286da 100644 --- a/src/network/bridge_driver_platform.h +++ b/src/network/bridge_driver_platform.h @@ -21,6 +21,7 @@ * Author: Daniel P. Berrange <berrange@redhat.com> */
+
This may be the only unnecessary part. Otherwise a replacement by pattern. Compile doesn't complain ... ACK

Using the virCommand dry run capability, capture iptables rules created by various network XML documents. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- tests/Makefile.am | 17 ++- .../networkxml2firewalldata/nat-default-linux.args | 30 ++++ tests/networkxml2firewalldata/nat-default.xml | 10 ++ tests/networkxml2firewalldata/nat-ipv6-linux.args | 44 ++++++ tests/networkxml2firewalldata/nat-ipv6.xml | 15 ++ .../nat-many-ips-linux.args | 58 ++++++++ tests/networkxml2firewalldata/nat-many-ips.xml | 12 ++ .../networkxml2firewalldata/nat-no-dhcp-linux.args | 42 ++++++ tests/networkxml2firewalldata/nat-no-dhcp.xml | 7 + tests/networkxml2firewalldata/nat-tftp-linux.args | 32 ++++ tests/networkxml2firewalldata/nat-tftp.xml | 11 ++ .../route-default-linux.args | 20 +++ tests/networkxml2firewalldata/route-default.xml | 10 ++ tests/networkxml2firewalltest.c | 162 +++++++++++++++++++++ 14 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 tests/networkxml2firewalldata/nat-default-linux.args create mode 100644 tests/networkxml2firewalldata/nat-default.xml create mode 100644 tests/networkxml2firewalldata/nat-ipv6-linux.args create mode 100644 tests/networkxml2firewalldata/nat-ipv6.xml create mode 100644 tests/networkxml2firewalldata/nat-many-ips-linux.args create mode 100644 tests/networkxml2firewalldata/nat-many-ips.xml create mode 100644 tests/networkxml2firewalldata/nat-no-dhcp-linux.args create mode 100644 tests/networkxml2firewalldata/nat-no-dhcp.xml create mode 100644 tests/networkxml2firewalldata/nat-tftp-linux.args create mode 100644 tests/networkxml2firewalldata/nat-tftp.xml create mode 100644 tests/networkxml2firewalldata/route-default-linux.args create mode 100644 tests/networkxml2firewalldata/route-default.xml create mode 100644 tests/networkxml2firewalltest.c diff --git a/tests/Makefile.am b/tests/Makefile.am index a10919d..75e723f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -87,6 +87,7 @@ EXTRA_DIST = \ networkxml2confdata \ networkxml2xmlupdatein \ networkxml2xmlupdateout \ + networkxml2firewalldata \ nodedevschemadata \ nodedevschematest \ nodeinfodata \ @@ -249,10 +250,16 @@ if WITH_YAJL test_programs += jsontest endif WITH_YAJL -test_programs += networkxml2xmltest networkxml2xmlupdatetest +test_programs += \ + networkxml2xmltest \ + networkxml2xmlupdatetest \ + $(NULL) if WITH_NETWORK -test_programs += networkxml2conftest +test_programs += \ + networkxml2conftest \ + networkxml2firewalltest \ + $(NULL) endif WITH_NETWORK if WITH_STORAGE_SHEEPDOG @@ -655,6 +662,12 @@ networkxml2conftest_SOURCES = \ networkxml2conftest.c \ testutils.c testutils.h networkxml2conftest_LDADD = ../src/libvirt_driver_network_impl.la $(LDADDS) + +networkxml2firewalltest_SOURCES = \ + networkxml2firewalltest.c \ + testutils.c testutils.h +networkxml2firewalltest_LDADD = ../src/libvirt_driver_network_impl.la $(LDADDS) + else ! WITH_NETWORK EXTRA_DIST += networkxml2conftest.c endif ! WITH_NETWORK diff --git a/tests/networkxml2firewalldata/nat-default-linux.args b/tests/networkxml2firewalldata/nat-default-linux.args new file mode 100644 index 0000000..0ec2807 --- /dev/null +++ b/tests/networkxml2firewalldata/nat-default-linux.args @@ -0,0 +1,30 @@ +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert OUTPUT --out-interface virbr0 --protocol udp \ +--destination-port 68 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --source 192.168.122.0/24 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --destination 192.168.122.0/24 \ +--out-interface virbr0 --match conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 '!' \ +--destination 192.168.122.0/24 --jump MASQUERADE +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p udp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p tcp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 255.255.255.255/32 --jump RETURN +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 224.0.0.0/24 --jump RETURN +/usr/sbin/iptables --table mangle --insert POSTROUTING --out-interface virbr0 \ +--protocol udp --destination-port 68 --jump CHECKSUM --checksum-fill diff --git a/tests/networkxml2firewalldata/nat-default.xml b/tests/networkxml2firewalldata/nat-default.xml new file mode 100644 index 0000000..d7241d0 --- /dev/null +++ b/tests/networkxml2firewalldata/nat-default.xml @@ -0,0 +1,10 @@ +<network> + <name>default</name> + <bridge name="virbr0"/> + <forward/> + <ip address="192.168.122.1" netmask="255.255.255.0"> + <dhcp> + <range start="192.168.122.2" end="192.168.122.254"/> + </dhcp> + </ip> +</network> diff --git a/tests/networkxml2firewalldata/nat-ipv6-linux.args b/tests/networkxml2firewalldata/nat-ipv6-linux.args new file mode 100644 index 0000000..690a354 --- /dev/null +++ b/tests/networkxml2firewalldata/nat-ipv6-linux.args @@ -0,0 +1,44 @@ +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert OUTPUT --out-interface virbr0 --protocol udp \ +--destination-port 68 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT +/usr/sbin/ip6tables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT +/usr/sbin/ip6tables --table filter --insert FORWARD --in-interface virbr0 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 547 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --source 192.168.122.0/24 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --destination 192.168.122.0/24 \ +--out-interface virbr0 --match conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 '!' \ +--destination 192.168.122.0/24 --jump MASQUERADE +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p udp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p tcp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 255.255.255.255/32 --jump RETURN +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 224.0.0.0/24 --jump RETURN +/usr/sbin/ip6tables --table filter --insert FORWARD --source 2001:db8:ca2:2::/64 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert FORWARD --destination 2001:db8:ca2:2::/64 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table mangle --insert POSTROUTING --out-interface virbr0 \ +--protocol udp --destination-port 68 --jump CHECKSUM --checksum-fill diff --git a/tests/networkxml2firewalldata/nat-ipv6.xml b/tests/networkxml2firewalldata/nat-ipv6.xml new file mode 100644 index 0000000..337e71d --- /dev/null +++ b/tests/networkxml2firewalldata/nat-ipv6.xml @@ -0,0 +1,15 @@ +<network> + <name>default</name> + <bridge name="virbr0"/> + <forward/> + <ip address="192.168.122.1" netmask="255.255.255.0"> + <dhcp> + <range start="192.168.122.2" end="192.168.122.254"/> + </dhcp> + </ip> + <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" > + <dhcp> + <range start="2001:db8:ca2:2:1::10" end="2001:db8:ca2:2:1::ff" /> + </dhcp> + </ip> +</network> diff --git a/tests/networkxml2firewalldata/nat-many-ips-linux.args b/tests/networkxml2firewalldata/nat-many-ips-linux.args new file mode 100644 index 0000000..92c6069 --- /dev/null +++ b/tests/networkxml2firewalldata/nat-many-ips-linux.args @@ -0,0 +1,58 @@ +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert OUTPUT --out-interface virbr0 --protocol udp \ +--destination-port 68 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --source 192.168.122.0/24 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --destination 192.168.122.0/24 \ +--out-interface virbr0 --match conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 '!' \ +--destination 192.168.122.0/24 --jump MASQUERADE +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p udp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p tcp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 255.255.255.255/32 --jump RETURN +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 224.0.0.0/24 --jump RETURN +/usr/sbin/iptables --table filter --insert FORWARD --source 192.168.128.0/24 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --destination 192.168.128.0/24 \ +--out-interface virbr0 --match conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.128.0/24 '!' \ +--destination 192.168.128.0/24 --jump MASQUERADE +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.128.0/24 \ +-p udp '!' --destination 192.168.128.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.128.0/24 \ +-p tcp '!' --destination 192.168.128.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.128.0/24 \ +--destination 255.255.255.255/32 --jump RETURN +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.128.0/24 \ +--destination 224.0.0.0/24 --jump RETURN +/usr/sbin/iptables --table filter --insert FORWARD --source 192.168.150.0/24 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --destination 192.168.150.0/24 \ +--out-interface virbr0 --match conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.150.0/24 '!' \ +--destination 192.168.150.0/24 --jump MASQUERADE +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.150.0/24 \ +-p udp '!' --destination 192.168.150.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.150.0/24 \ +-p tcp '!' --destination 192.168.150.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.150.0/24 \ +--destination 255.255.255.255/32 --jump RETURN +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.150.0/24 \ +--destination 224.0.0.0/24 --jump RETURN +/usr/sbin/iptables --table mangle --insert POSTROUTING --out-interface virbr0 \ +--protocol udp --destination-port 68 --jump CHECKSUM --checksum-fill diff --git a/tests/networkxml2firewalldata/nat-many-ips.xml b/tests/networkxml2firewalldata/nat-many-ips.xml new file mode 100644 index 0000000..0c8dcff --- /dev/null +++ b/tests/networkxml2firewalldata/nat-many-ips.xml @@ -0,0 +1,12 @@ +<network> + <name>default</name> + <bridge name="virbr0"/> + <forward/> + <ip address="192.168.122.1" netmask="255.255.255.0"> + <dhcp> + <range start="192.168.122.2" end="192.168.122.254"/> + </dhcp> + </ip> + <ip address="192.168.128.1" netmask="255.255.255.0"/> + <ip address="192.168.150.1" netmask="255.255.255.0"/> +</network> diff --git a/tests/networkxml2firewalldata/nat-no-dhcp-linux.args b/tests/networkxml2firewalldata/nat-no-dhcp-linux.args new file mode 100644 index 0000000..bbfb3eb --- /dev/null +++ b/tests/networkxml2firewalldata/nat-no-dhcp-linux.args @@ -0,0 +1,42 @@ +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert OUTPUT --out-interface virbr0 --protocol udp \ +--destination-port 68 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT +/usr/sbin/ip6tables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT +/usr/sbin/ip6tables --table filter --insert FORWARD --in-interface virbr0 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 547 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --source 192.168.122.0/24 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --destination 192.168.122.0/24 \ +--out-interface virbr0 --match conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 '!' \ +--destination 192.168.122.0/24 --jump MASQUERADE +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p udp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p tcp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 255.255.255.255/32 --jump RETURN +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 224.0.0.0/24 --jump RETURN +/usr/sbin/ip6tables --table filter --insert FORWARD --source 2001:db8:ca2:2::/64 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/ip6tables --table filter --insert FORWARD --destination 2001:db8:ca2:2::/64 \ +--out-interface virbr0 --jump ACCEPT diff --git a/tests/networkxml2firewalldata/nat-no-dhcp.xml b/tests/networkxml2firewalldata/nat-no-dhcp.xml new file mode 100644 index 0000000..0bccd1d --- /dev/null +++ b/tests/networkxml2firewalldata/nat-no-dhcp.xml @@ -0,0 +1,7 @@ +<network> + <name>default</name> + <bridge name="virbr0"/> + <forward/> + <ip address="192.168.122.1" netmask="255.255.255.0"/> + <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64"/> +</network> diff --git a/tests/networkxml2firewalldata/nat-tftp-linux.args b/tests/networkxml2firewalldata/nat-tftp-linux.args new file mode 100644 index 0000000..d6d65c1 --- /dev/null +++ b/tests/networkxml2firewalldata/nat-tftp-linux.args @@ -0,0 +1,32 @@ +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert OUTPUT --out-interface virbr0 --protocol udp \ +--destination-port 68 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 69 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --source 192.168.122.0/24 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --destination 192.168.122.0/24 \ +--out-interface virbr0 --match conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 '!' \ +--destination 192.168.122.0/24 --jump MASQUERADE +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p udp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +-p tcp '!' --destination 192.168.122.0/24 --jump MASQUERADE --to-ports 1024-65535 +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 255.255.255.255/32 --jump RETURN +/usr/sbin/iptables --table nat --insert POSTROUTING --source 192.168.122.0/24 \ +--destination 224.0.0.0/24 --jump RETURN +/usr/sbin/iptables --table mangle --insert POSTROUTING --out-interface virbr0 \ +--protocol udp --destination-port 68 --jump CHECKSUM --checksum-fill diff --git a/tests/networkxml2firewalldata/nat-tftp.xml b/tests/networkxml2firewalldata/nat-tftp.xml new file mode 100644 index 0000000..17e8e0a --- /dev/null +++ b/tests/networkxml2firewalldata/nat-tftp.xml @@ -0,0 +1,11 @@ +<network> + <name>default</name> + <bridge name="virbr0"/> + <forward/> + <ip address="192.168.122.1" netmask="255.255.255.0"> + <tftp root='/some/dir'/> + <dhcp> + <range start="192.168.122.2" end="192.168.122.254"/> + </dhcp> + </ip> +</network> diff --git a/tests/networkxml2firewalldata/route-default-linux.args b/tests/networkxml2firewalldata/route-default-linux.args new file mode 100644 index 0000000..31e5394 --- /dev/null +++ b/tests/networkxml2firewalldata/route-default-linux.args @@ -0,0 +1,20 @@ +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 67 --jump ACCEPT +/usr/sbin/iptables --table filter --insert OUTPUT --out-interface virbr0 --protocol udp \ +--destination-port 68 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp \ +--destination-port 53 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT +/usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --source 192.168.122.0/24 \ +--in-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table filter --insert FORWARD --destination 192.168.122.0/24 \ +--out-interface virbr0 --jump ACCEPT +/usr/sbin/iptables --table mangle --insert POSTROUTING --out-interface virbr0 \ +--protocol udp --destination-port 68 --jump CHECKSUM --checksum-fill diff --git a/tests/networkxml2firewalldata/route-default.xml b/tests/networkxml2firewalldata/route-default.xml new file mode 100644 index 0000000..3bc7bb9 --- /dev/null +++ b/tests/networkxml2firewalldata/route-default.xml @@ -0,0 +1,10 @@ +<network> + <name>default</name> + <bridge name="virbr0"/> + <forward mode='route'/> + <ip address="192.168.122.1" netmask="255.255.255.0"> + <dhcp> + <range start="192.168.122.2" end="192.168.122.254"/> + </dhcp> + </ip> +</network> diff --git a/tests/networkxml2firewalltest.c b/tests/networkxml2firewalltest.c new file mode 100644 index 0000000..55cb38a --- /dev/null +++ b/tests/networkxml2firewalltest.c @@ -0,0 +1,162 @@ +/* + * networkxml2firewalltest.c: Test iptables 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 + * <http://www.gnu.org/licenses/>. + * + */ + +#include <config.h> + +#if defined (__linux__) + +# include "testutils.h" +# include "network/bridge_driver_platform.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 const char *abs_top_srcdir; + +# ifdef __linux__ +# define RULESTYPE "linux" +# else +# error "test case not ported to this platform" +# endif + +static int testCompareXMLToArgvFiles(const char *xml, + const char *cmdline) +{ + char *expectargv = NULL; + int len; + char *actualargv = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + virNetworkDefPtr def = NULL; + int ret = -1; + + virCommandSetDryRun(&buf, NULL, NULL); + + if (!(def = virNetworkDefParseFile(xml))) + goto cleanup; + + if (networkAddFirewallRules(def) < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actualargv = virBufferContentAndReset(&buf); + virCommandSetDryRun(NULL, NULL, NULL); + + len = virtTestLoadFile(cmdline, &expectargv); + if (len < 0) + goto cleanup; + + if (STRNEQ(expectargv, actualargv)) { + virtTestDifference(stderr, expectargv, actualargv); + goto cleanup; + } + + ret = 0; + + cleanup: + virBufferFreeAndReset(&buf); + VIR_FREE(expectargv); + VIR_FREE(actualargv); + virNetworkDefFree(def); + return ret; +} + +struct testInfo { + const char *name; +}; + + +static int +testCompareXMLToIPTablesHelper(const void *data) +{ + int result = -1; + const struct testInfo *info = data; + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/networkxml2firewalldata/%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&args, "%s/networkxml2firewalldata/%s-%s.args", + abs_srcdir, info->name, RULESTYPE) < 0) + goto cleanup; + + result = testCompareXMLToArgvFiles(xml, args); + + cleanup: + VIR_FREE(xml); + VIR_FREE(args); + return result; +} + + +static int +mymain(void) +{ + int ret = 0; + + abs_top_srcdir = getenv("abs_top_srcdir"); + if (!abs_top_srcdir) + abs_top_srcdir = abs_srcdir "/.."; + +# define DO_TEST(name) \ + do { \ + static struct testInfo info = { \ + name, \ + }; \ + if (virtTestRun("Network XML-2-iptables " name, \ + testCompareXMLToIPTablesHelper, &info) < 0) \ + ret = -1; \ + } while (0) + + if (virFirewallSetBackend(VIR_FIREWALL_BACKEND_DIRECT) < 0) { + ret = -1; + goto cleanup; + } + + DO_TEST("nat-default"); + DO_TEST("nat-tftp"); + DO_TEST("nat-many-ips"); + DO_TEST("nat-no-dhcp"); + DO_TEST("nat-ipv6"); + DO_TEST("route-default"); + DO_TEST("route-default"); + + cleanup: + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain) + +#else /* ! defined (__linux__) */ + +int main(void) +{ + return EXIT_AM_SKIP; +} + +#endif /* ! defined (__linux__) */ -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Using the virCommand dry run capability, capture iptables rules created by various network XML documents.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> ---
Great. I did not check the individual iptables rules whether they are correct for the XML. ACK

On 04/08/2014 05:38 PM, Daniel P. Berrange wrote:
Using the virCommand dry run capability, capture iptables rules created by various network XML documents.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> ---
diff --git a/tests/networkxml2firewalldata/nat-default-linux.args b/tests/networkxml2firewalldata/nat-default-linux.args new file mode 100644 index 0000000..0ec2807 --- /dev/null +++ b/tests/networkxml2firewalldata/nat-default-linux.args @@ -0,0 +1,30 @@ +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 67 --jump ACCEPT
This test fails on systems having iptables in /sbin Jan

On Wed, Apr 16, 2014 at 03:54:48PM +0200, Ján Tomko wrote:
On 04/08/2014 05:38 PM, Daniel P. Berrange wrote:
Using the virCommand dry run capability, capture iptables rules created by various network XML documents.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> ---
diff --git a/tests/networkxml2firewalldata/nat-default-linux.args b/tests/networkxml2firewalldata/nat-default-linux.args new file mode 100644 index 0000000..0ec2807 --- /dev/null +++ b/tests/networkxml2firewalldata/nat-default-linux.args @@ -0,0 +1,30 @@ +/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp \ +--destination-port 67 --jump ACCEPT
This test fails on systems having iptables in /sbin
I'm going to add the following code which strips off any path component from the buffer we construct. The '.args' files can then be changed to say 'iptables' instead of '/sbin/iptables' which will make is portable diff --git a/tests/networkxml2firewalltest.c b/tests/networkxml2firewalltest.c index 55cb38a..9255e01 100644 --- a/tests/networkxml2firewalltest.c +++ b/tests/networkxml2firewalltest.c @@ -65,6 +65,7 @@ static int testCompareXMLToArgvFiles(const char *xml, goto cleanup; actualargv = virBufferContentAndReset(&buf); + virtTestClearCommandPath(actualargv); virCommandSetDryRun(NULL, NULL, NULL); len = virtTestLoadFile(cmdline, &expectargv); diff --git a/tests/testutils.c b/tests/testutils.c index feda22b..a1d31f0 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -855,6 +855,57 @@ int virtTestClearLineRegex(const char *pattern, } +/* + * @cmdset contains a list of command line args, eg + * + * "/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp --destination-port 53 --jump ACCEPT + * /usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp --destination-port 53 --jump ACCEPT + * /usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT + * /usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT + * /usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --out-interface virbr0 --jump ACCEPT" + * + * And we're munging it in-place to string the path component + * of the command line, to produce + * + * "iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp --destination-port 53 --jump ACCEPT + * iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp --destination-port 53 --jump ACCEPT + * iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT + * iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT + * iptables --table filter --insert FORWARD --in-interface virbr0 --out-interface virbr0 --jump ACCEPT" + */ +void virtTestClearCommandPath(char *cmdset) +{ + size_t offset = 0; + char *lineStart = cmdset; + char *lineEnd = strchr(lineStart, '\n'); + + while (lineStart) { + char *dirsep; + char *movestart; + size_t movelen; + dirsep = strchr(lineStart, ' '); + if (dirsep) { + while (dirsep > lineStart && *dirsep != '/') + dirsep--; + if (*dirsep == '/') + dirsep++; + movestart = dirsep; + } else { + movestart = lineStart; + } + movelen = lineEnd ? lineEnd - movestart : strlen(movestart); + + if (movelen) { + memmove(cmdset + offset, movestart, movelen + 1); + offset += movelen + 1; + } + lineStart = lineEnd ? lineEnd + 1 : NULL; + lineEnd = lineStart ? strchr(lineStart, '\n') : NULL; + } + cmdset[offset] = '\0'; +} + + virCapsPtr virTestGenericCapsInit(void) { virCapsPtr caps; diff --git a/tests/testutils.h b/tests/testutils.h index e89492b..ad28ea7 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -59,6 +59,8 @@ int virtTestCaptureProgramOutput(const char *const argv[], char **buf, int maxle int virtTestClearLineRegex(const char *pattern, char *string); +void virtTestClearCommandPath(char *cmdset); + int virtTestDifference(FILE *stream, const char *expect, const char *actual); Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 04/25/2014 07:37 AM, Daniel P. Berrange wrote:
On Wed, Apr 16, 2014 at 03:54:48PM +0200, Ján Tomko wrote:
On 04/08/2014 05:38 PM, Daniel P. Berrange wrote:
Using the virCommand dry run capability, capture iptables rules created by various network XML documents.
+ * And we're munging it in-place to string the path component + * of the command line, to produce
s/string/strip/ -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

Convert the virebtables.{c,h} files to use the new virFirewall APIs for changing ebtables rules. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/util/virebtables.c | 185 ++++++++++++------------------------------------- 1 file changed, 45 insertions(+), 140 deletions(-) diff --git a/src/util/virebtables.c b/src/util/virebtables.c index 2e5c025..2ffff08 100644 --- a/src/util/virebtables.c +++ b/src/util/virebtables.c @@ -25,67 +25,18 @@ #include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include <limits.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> - -#ifdef HAVE_PATHS_H -# include <paths.h> -#endif - #include "internal.h" #include "virebtables.h" -#include "vircommand.h" #include "viralloc.h" #include "virerror.h" -#include "virfile.h" #include "virlog.h" -#include "virthread.h" #include "virstring.h" -#include "virutil.h" +#include "virfirewall.h" #define VIR_FROM_THIS VIR_FROM_NONE VIR_LOG_INIT("util.ebtables"); -#if HAVE_FIREWALLD -static char *firewall_cmd_path = NULL; - -static int -virEbTablesOnceInit(void) -{ - firewall_cmd_path = virFindFileInPath("firewall-cmd"); - if (!firewall_cmd_path) { - VIR_INFO("firewall-cmd not found on system. " - "firewalld support disabled for ebtables."); - } else { - virCommandPtr cmd = virCommandNew(firewall_cmd_path); - - virCommandAddArgList(cmd, "--state", NULL); - if (virCommandRun(cmd, NULL) < 0) { - VIR_INFO("firewall-cmd found but disabled for ebtables"); - VIR_FREE(firewall_cmd_path); - firewall_cmd_path = NULL; - } else { - VIR_INFO("using firewalld for ebtables commands"); - } - virCommandFree(cmd); - } - return 0; -} - -VIR_ONCE_GLOBAL_INIT(virEbTables) - -#endif - struct _ebtablesContext { char *chain; @@ -96,84 +47,6 @@ enum { REMOVE, }; - -static int ATTRIBUTE_SENTINEL -ebtablesAddRemoveRule(const char *arg, ...) -{ - va_list args; - int retval = ENOMEM; - char **argv; - const char *s; - int n; - - n = 1 + /* /sbin/ebtables */ - 2 + /* --table foo */ - 2 + /* --insert bar */ - 1; /* arg */ - -#if HAVE_FIREWALLD - virEbTablesInitialize(); - if (firewall_cmd_path) - n += 3; /* --direct --passthrough eb */ -#endif - - va_start(args, arg); - while (va_arg(args, const char *)) - n++; - - va_end(args); - - if (VIR_ALLOC_N(argv, n + 1) < 0) - goto error; - - n = 0; - -#if HAVE_FIREWALLD - if (firewall_cmd_path) { - if (VIR_STRDUP(argv[n++], firewall_cmd_path) < 0) - goto error; - if (VIR_STRDUP(argv[n++], "--direct") < 0) - goto error; - if (VIR_STRDUP(argv[n++], "--passthrough") < 0) - goto error; - if (VIR_STRDUP(argv[n++], "eb") < 0) - goto error; - } else -#endif - if (VIR_STRDUP(argv[n++], EBTABLES_PATH) < 0) - goto error; - - if (VIR_STRDUP(argv[n++], arg) < 0) - goto error; - - va_start(args, arg); - - while ((s = va_arg(args, const char *))) { - if (VIR_STRDUP(argv[n++], s) < 0) { - va_end(args); - goto error; - } - } - - va_end(args); - - if (virRun((const char **)argv, NULL) < 0) { - retval = errno; - goto error; - } - - error: - if (argv) { - n = 0; - while (argv[n]) - VIR_FREE(argv[n++]); - VIR_FREE(argv); - } - - return retval; -} - - /** * ebtablesContextNew: * @@ -216,12 +89,30 @@ ebtablesContextFree(ebtablesContext *ctx) int ebtablesAddForwardPolicyReject(ebtablesContext *ctx) { - ebtablesAddRemoveRule("--new-chain", ctx->chain, NULL, - NULL); - ebtablesAddRemoveRule("--insert", "FORWARD", "--jump", - ctx->chain, NULL); - return ebtablesAddRemoveRule("-P", ctx->chain, "DROP", - NULL); + virFirewallPtr fw = NULL; + int ret = -1; + + fw = virFirewallNew(); + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "--new-chain", ctx->chain, + NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "--insert", "FORWARD", + "--jump", ctx->chain, NULL); + + virFirewallStartTransaction(fw, 0); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-P", ctx->chain, "DROP", + NULL); + + if (virFirewallApply(fw) < 0) + goto cleanup; + + ret = 0; + cleanup: + virFirewallFree(fw); + return ret; } @@ -234,12 +125,26 @@ ebtablesForwardAllowIn(ebtablesContext *ctx, const char *macaddr, int action) { - return ebtablesAddRemoveRule(action == ADD ? "--insert" : "--delete", - ctx->chain, - "--in-interface", iface, - "--source", macaddr, - "--jump", "ACCEPT", - NULL); + virFirewallPtr fw = NULL; + int ret = -1; + + fw = virFirewallNew(); + virFirewallStartTransaction(fw, 0); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + action == ADD ? "--insert" : "--delete", + ctx->chain, + "--in-interface", iface, + "--source", macaddr, + "--jump", "ACCEPT", + NULL); + + if (virFirewallApply(fw) < 0) + goto cleanup; + + ret = 0; + cleanup: + virFirewallFree(fw); + return ret; } /** -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the virebtables.{c,h} files to use the new virFirewall APIs for changing ebtables rules.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
/** * ebtablesContextNew: * @@ -216,12 +89,30 @@ ebtablesContextFree(ebtablesContext *ctx) int ebtablesAddForwardPolicyReject(ebtablesContext *ctx) { - ebtablesAddRemoveRule("--new-chain", ctx->chain, NULL, - NULL); - ebtablesAddRemoveRule("--insert", "FORWARD", "--jump", - ctx->chain, NULL); - return ebtablesAddRemoveRule("-P", ctx->chain, "DROP", - NULL); + virFirewallPtr fw = NULL; + int ret = -1; + + fw = virFirewallNew(); + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
Ignoring errors because the ebtablesAdd* calls above ignored them as well... makes sense.
+ virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "--new-chain", ctx->chain, + NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "--insert", "FORWARD", + "--jump", ctx->chain, NULL); + + virFirewallStartTransaction(fw, 0); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-P", ctx->chain, "DROP", + NULL); + + if (virFirewallApply(fw) < 0) + goto cleanup; + + ret = 0; + cleanup: + virFirewallFree(fw); + return ret; }
ACK

Convert the nwfilter ebiptablesAllTeardown method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/Makefile.am | 18 +- src/nwfilter/nwfilter_ebiptables_driver.c | 326 ++++++++++++++++++++++++++---- tests/Makefile.am | 11 + tests/nwfilterebiptablestest.c | 116 +++++++++++ 4 files changed, 422 insertions(+), 49 deletions(-) create mode 100644 tests/nwfilterebiptablestest.c diff --git a/src/Makefile.am b/src/Makefile.am index 7615294..70ef6b6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1536,6 +1536,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 @@ -1543,20 +1546,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 0361d99..8a53ceb 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); @@ -661,6 +659,32 @@ _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); + + virFirewallAddRule(fw, layer, "-F", chain, NULL); + virFirewallAddRule(fw, layer, "-X", chain, NULL); +} + + +static void iptablesRemoveRootChain(virBufferPtr buf, char prefix, bool incoming, @@ -671,6 +695,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, bool incoming, @@ -702,6 +737,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, char prefix, @@ -762,14 +808,14 @@ 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); + virFirewallAddRule(fw, layer, + "-D", VIRT_IN_POST_CHAIN, + MATCH_PHYSDEV_IN_FW, + ifname, "-j", "ACCEPT", NULL); } static void @@ -817,6 +863,54 @@ _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) + virFirewallAddRule(fw, layer, + "-D", basechain, + MATCH_PHYSDEV_IN_FW, ifname, + "-g", chain, + NULL); + else + virFirewallAddRule(fw, layer, + "-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) + virFirewallAddRule(fw, layer, + "-D", basechain, + MATCH_PHYSDEV_OUT_OLD_FW, ifname, + "-g", chain, + NULL); +} + + +static void iptablesUnlinkRootChain(virBufferPtr buf, const char *basechain, char prefix, @@ -826,6 +920,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, @@ -849,6 +954,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) { @@ -2802,6 +2918,29 @@ _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); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-F", chain, NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-X", chain, NULL); +} + + +static void ebtablesRemoveRootChain(virBufferPtr buf, bool incoming, const char *ifname) { @@ -2810,6 +2949,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) { @@ -2845,6 +2992,32 @@ _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); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-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) { @@ -2853,6 +3026,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 +3153,58 @@ _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 *chains = 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; chains[j]; j++) { + if (tmp[0] == chains[j] && + tmp[1] == '-') { + VIR_DEBUG("Processing chain '%s'", tmp); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + false, ebtablesRemoveSubChainsQuery, + (void *)chains, + "-t", "nat", "-L", tmp, NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-F", tmp, NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-X", tmp, NULL); + } + } + } + + return 0; +} + + +static void +_ebtablesRemoveSubChainsFW(virFirewallPtr fw, + const char *ifname, + const char *chains) +{ + char rootchain[MAX_CHAINNAME_LENGTH]; + size_t i; + + for (i = 0; chains[i] != 0; i++) { + PRINT_ROOT_CHAIN(rootchain, chains[i], ifname); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + false, ebtablesRemoveSubChainsQuery, + (void *)chains, + "-t", "nat", "-L", rootchain, NULL); + } +} + static void ebtablesRemoveSubChains(virBufferPtr buf, const char *ifname) @@ -2986,6 +3219,19 @@ ebtablesRemoveSubChains(virBufferPtr buf, } static void +ebtablesRemoveSubChainsFW(virFirewallPtr fw, + const char *ifname) +{ + char chains[3] = { + CHAINPREFIX_HOST_IN, + CHAINPREFIX_HOST_OUT, + 0 + }; + + _ebtablesRemoveSubChainsFW(fw, ifname, chains); +} + +static void ebtablesRemoveTmpSubChains(virBufferPtr buf, const char *ifname) { @@ -4052,43 +4298,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; - - if (iptables_cmd_path) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); + virFirewallPtr fw = virFirewallNew(); + int ret = -1; - iptablesUnlinkRootChains(&buf, ifname); - iptablesClearVirtInPost(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - } + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); - if (ip6tables_cmd_path) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesClearVirtInPostFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); - iptablesUnlinkRootChains(&buf, ifname); - iptablesClearVirtInPost(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - } + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesClearVirtInPostFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + ebtablesUnlinkRootChainFW(fw, true, ifname); + ebtablesUnlinkRootChainFW(fw, false, ifname); - ebtablesUnlinkRootChain(&buf, true, ifname); - ebtablesUnlinkRootChain(&buf, false, ifname); + ebtablesRemoveSubChainsFW(fw, ifname); - ebtablesRemoveSubChains(&buf, ifname); + ebtablesRemoveRootChainFW(fw, true, ifname); + ebtablesRemoveRootChainFW(fw, false, 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 75e723f..9547c02 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -268,6 +268,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 @@ -687,6 +691,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 0000000..c05682b --- /dev/null +++ b/tests/nwfilterebiptablestest.c @@ -0,0 +1,116 @@ +/* + * 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 + * <http://www.gnu.org/licenses/>. + * + */ + +#include <config.h> + +#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 = + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/iptables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/iptables -F FO-vnet0\n" + "/usr/sbin/iptables -X FO-vnet0\n" + "/usr/sbin/iptables -F FI-vnet0\n" + "/usr/sbin/iptables -X FI-vnet0\n" + "/usr/sbin/iptables -F HI-vnet0\n" + "/usr/sbin/iptables -X HI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/ip6tables -F FO-vnet0\n" + "/usr/sbin/ip6tables -X FO-vnet0\n" + "/usr/sbin/ip6tables -F FI-vnet0\n" + "/usr/sbin/ip6tables -X FI-vnet0\n" + "/usr/sbin/ip6tables -F HI-vnet0\n" + "/usr/sbin/ip6tables -X HI-vnet0\n" + "/usr/sbin/ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-O-vnet0\n"; + const char *actual = NULL; + int ret = -1; + + virCommandSetDryRun(&buf, NULL, NULL); + + if (ebiptables_driver.allTeardown("vnet0") < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actual = virBufferCurrentContent(&buf); + + if (STRNEQ_NULLABLE(actual, expected)) { + virtTestDifference(stderr, actual, expected); + goto cleanup; + } + + ret = 0; + cleanup: + virCommandSetDryRun(NULL, NULL, NULL); + virBufferFreeAndReset(&buf); + 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) -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebiptablesAllTeardown method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
@@ -2972,6 +3153,58 @@ _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 *chains = opaque; +
The problem here is 'opaque' may have gone out of scope ... [continue below]
+ 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; chains[j]; j++) { + if (tmp[0] == chains[j] && + tmp[1] == '-') { + VIR_DEBUG("Processing chain '%s'", tmp); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + false, ebtablesRemoveSubChainsQuery, + (void *)chains, + "-t", "nat", "-L", tmp, NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-F", tmp, NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-X", tmp, NULL); + } + } + } + + return 0; +} + + +static void +_ebtablesRemoveSubChainsFW(virFirewallPtr fw, + const char *ifname, + const char *chains) +{ + char rootchain[MAX_CHAINNAME_LENGTH]; + size_t i; +
[...] @@ -2986,6 +3219,19 @@ ebtablesRemoveSubChains(virBufferPtr buf, } static void +ebtablesRemoveSubChainsFW(virFirewallPtr fw, + const char *ifname) +{ + char chains[3] = { + CHAINPREFIX_HOST_IN, + CHAINPREFIX_HOST_OUT, + 0 + }; + ... due to these arrays residing on the stack. So I prepended 'static' to these arrays and the ebtables rules cleanup started working. My suggested modification to this patch would be this here: 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 @@ -139,6 +139,19 @@ static const struct ushort_map l3_protoc }; +static char chainprefixes_host[3] = { + CHAINPREFIX_HOST_IN, + CHAINPREFIX_HOST_OUT, + 0 +}; + +static char chainprefixes_host_temp[3] = { + CHAINPREFIX_HOST_IN_TEMP, + CHAINPREFIX_HOST_OUT_TEMP, + 0 +}; + + static int printVar(virNWFilterVarCombIterPtr vars, char *buf, int bufsize, @@ -2621,7 +2634,7 @@ ebtablesRemoveSubChainsQuery(virFirewall void *opaque) { size_t i, j; - const char *chains = opaque; + const char *chainprefixes = opaque; for (i = 0; lines[i] != NULL; i++) { VIR_DEBUG("Considering '%s'", lines[i]); @@ -2629,13 +2642,13 @@ ebtablesRemoveSubChainsQuery(virFirewall if (!tmp) continue; tmp = tmp + 3; - for (j = 0; chains[j]; j++) { - if (tmp[0] == chains[j] && + 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 *)chains, + (void *)chainprefixes, "-t", "nat", "-L", tmp, NULL); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, "-t", "nat", "-F", tmp, NULL); @@ -2652,16 +2665,16 @@ ebtablesRemoveSubChainsQuery(virFirewall static void _ebtablesRemoveSubChainsFW(virFirewallPtr fw, const char *ifname, - const char *chains) + const char *chainprefixes) { char rootchain[MAX_CHAINNAME_LENGTH]; size_t i; - for (i = 0; chains[i] != 0; i++) { - PRINT_ROOT_CHAIN(rootchain, chains[i], ifname); + for (i = 0; chainprefixes[i] != 0; i++) { + PRINT_ROOT_CHAIN(rootchain, chainprefixes[i], ifname); virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, false, ebtablesRemoveSubChainsQuery, - (void *)chains, + (void *)chainprefixes, "-t", "nat", "-L", rootchain, NULL); } } @@ -2670,13 +2683,7 @@ static void ebtablesRemoveSubChainsFW(virFirewallPtr fw, const char *ifname) { - char chains[3] = { - CHAINPREFIX_HOST_IN, - CHAINPREFIX_HOST_OUT, - 0 - }; - - _ebtablesRemoveSubChainsFW(fw, ifname, chains); + _ebtablesRemoveSubChainsFW(fw, ifname, chainprefixes_host); } @@ -2684,13 +2691,7 @@ static void ebtablesRemoveTmpSubChainsFW(virFirewallPtr fw, const char *ifname) { - char chains[3] = { - CHAINPREFIX_HOST_IN_TEMP, - CHAINPREFIX_HOST_OUT_TEMP, - 0 - }; - - _ebtablesRemoveSubChainsFW(fw, ifname, chains); + _ebtablesRemoveSubChainsFW(fw, ifname, chainprefixes_host_temp); } static void

Convert the nwfilter ebiptablesTearOldRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 228 ++++++++++++++++-------------- tests/nwfilterebiptablestest.c | 74 ++++++++++ 2 files changed, 192 insertions(+), 110 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 8a53ceb..da4d096 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -685,16 +685,6 @@ _iptablesRemoveRootChainFW(virFirewallPtr fw, static void -iptablesRemoveRootChain(virBufferPtr buf, - char prefix, - bool incoming, - const char *ifname) -{ - _iptablesRemoveRootChain(buf, prefix, incoming, ifname, false); -} - - -static void iptablesRemoveRootChainFW(virFirewallPtr fw, virFirewallLayer layer, char prefix, @@ -727,16 +717,6 @@ iptablesRemoveTmpRootChains(virBufferPtr buf, static void -iptablesRemoveRootChains(virBufferPtr buf, - const char *ifname) -{ - iptablesRemoveRootChain(buf, 'F', false, ifname); - iptablesRemoveRootChain(buf, 'F', true, ifname); - iptablesRemoveRootChain(buf, 'H', true, ifname); -} - - -static void iptablesRemoveRootChainsFW(virFirewallPtr fw, virFirewallLayer layer, const char *ifname) @@ -911,16 +891,6 @@ _iptablesUnlinkRootChainFW(virFirewallPtr fw, static void -iptablesUnlinkRootChain(virBufferPtr buf, - const char *basechain, - char prefix, - bool incoming, const char *ifname) -{ - _iptablesUnlinkRootChain(buf, - basechain, prefix, incoming, ifname, false); -} - -static void iptablesUnlinkRootChainFW(virFirewallPtr fw, virFirewallLayer layer, const char *basechain, @@ -944,16 +914,6 @@ iptablesUnlinkTmpRootChain(virBufferPtr buf, static void -iptablesUnlinkRootChains(virBufferPtr buf, - const char *ifname) -{ - iptablesUnlinkRootChain(buf, VIRT_OUT_CHAIN, 'F', false, ifname); - iptablesUnlinkRootChain(buf, VIRT_IN_CHAIN, 'F', true, ifname); - iptablesUnlinkRootChain(buf, HOST_IN_CHAIN, 'H', true, ifname); -} - - -static void iptablesUnlinkRootChainsFW(virFirewallPtr fw, virFirewallLayer layer, const char *ifname) @@ -975,10 +935,11 @@ iptablesUnlinkTmpRootChains(virBufferPtr buf, static void -iptablesRenameTmpRootChain(virBufferPtr buf, - char prefix, - bool incoming, - const char *ifname) +iptablesRenameTmpRootChainFW(virFirewallPtr fw, + virFirewallLayer layer, + char prefix, + bool incoming, + const char *ifname) { char tmpchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH]; char tmpChainPrefix[2] = { @@ -995,20 +956,19 @@ iptablesRenameTmpRootChain(virBufferPtr buf, PRINT_IPT_ROOT_CHAIN(tmpchain, tmpChainPrefix, ifname); PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname); - virBufferAsprintf(buf, - "$IPT -E %s %s" CMD_SEPARATOR, - tmpchain, - chain); + virFirewallAddRule(fw, layer, + "-E", tmpchain, chain, NULL); } static void -iptablesRenameTmpRootChains(virBufferPtr buf, - const char *ifname) +iptablesRenameTmpRootChainsFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *ifname) { - iptablesRenameTmpRootChain(buf, 'F', false, ifname); - iptablesRenameTmpRootChain(buf, 'F', true, ifname); - iptablesRenameTmpRootChain(buf, 'H', true, ifname); + iptablesRenameTmpRootChainFW(fw, layer, 'F', false, ifname); + iptablesRenameTmpRootChainFW(fw, layer, 'F', true, ifname); + iptablesRenameTmpRootChainFW(fw, layer, 'H', true, ifname); } @@ -3270,6 +3230,30 @@ ebtablesRenameTmpSubChain(virBufferPtr buf, } static void +ebtablesRenameTmpSubChainFW(virFirewallPtr fw, + int incoming, + const char *ifname, + const char *protocol) +{ + char tmpchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH]; + char tmpChainPrefix = (incoming) ? CHAINPREFIX_HOST_IN_TEMP + : CHAINPREFIX_HOST_OUT_TEMP; + char chainPrefix = (incoming) ? CHAINPREFIX_HOST_IN + : CHAINPREFIX_HOST_OUT; + + if (protocol) { + PRINT_CHAIN(tmpchain, tmpChainPrefix, ifname, protocol); + PRINT_CHAIN(chain, chainPrefix, ifname, protocol); + } else { + PRINT_ROOT_CHAIN(tmpchain, tmpChainPrefix, ifname); + PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); + } + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-E", tmpchain, chain, NULL); +} + +static void ebtablesRenameTmpRootChain(virBufferPtr buf, bool incoming, const char *ifname) @@ -3278,38 +3262,77 @@ ebtablesRenameTmpRootChain(virBufferPtr buf, } static void -ebtablesRenameTmpSubAndRootChains(virBufferPtr buf, - const char *ifname) +ebtablesRenameTmpRootChainFW(virFirewallPtr fw, + bool incoming, + const char *ifname) +{ + ebtablesRenameTmpSubChainFW(fw, incoming, ifname, NULL); +} + + +static int +ebtablesRenameTmpSubAndRootChainsQuery(virFirewallPtr fw, + const char *const *lines, + void *opaque ATTRIBUTE_UNUSED) +{ + size_t i; + char newchain[MAX_CHAINNAME_LENGTH]; + + 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; + if (tmp[0] != CHAINPREFIX_HOST_IN_TEMP && + tmp[0] != CHAINPREFIX_HOST_OUT_TEMP) + continue; + if (tmp[1] != '-') + continue; + + ignore_value(virStrcpyStatic(newchain, tmp)); + if (newchain[0] == CHAINPREFIX_HOST_IN_TEMP) + newchain[0] = CHAINPREFIX_HOST_IN; + else + newchain[0] = CHAINPREFIX_HOST_OUT; + VIR_DEBUG("Renaming chain '%s' to '%s'", tmp, newchain); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + false, ebtablesRenameTmpSubAndRootChainsQuery, + NULL, + "-t", "nat", "-L", tmp, NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-F", newchain, NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-X", newchain, NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-E", tmp, newchain, NULL); + } + + return 0; +} + + +static void +ebtablesRenameTmpSubAndRootChainsFW(virFirewallPtr fw, + const char *ifname) { char rootchain[MAX_CHAINNAME_LENGTH]; size_t i; char chains[3] = { CHAINPREFIX_HOST_IN_TEMP, CHAINPREFIX_HOST_OUT_TEMP, - 0}; - - NWFILTER_SET_EBTABLES_SHELLVAR(buf); - - virBufferAsprintf(buf, NWFILTER_FUNC_COLLECT_CHAINS, - chains); - virBufferAsprintf(buf, NWFILTER_FUNC_RENAME_CHAINS, - CHAINPREFIX_HOST_IN_TEMP, - CHAINPREFIX_HOST_IN, - CHAINPREFIX_HOST_OUT_TEMP, - CHAINPREFIX_HOST_OUT); - - virBufferAsprintf(buf, NWFILTER_FUNC_SET_IFS); - virBufferAddLit(buf, "chains=\"$(collect_chains"); + 0 + }; for (i = 0; chains[i] != 0; i++) { PRINT_ROOT_CHAIN(rootchain, chains[i], ifname); - virBufferAsprintf(buf, " %s", rootchain); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_ETHERNET, + false, ebtablesRenameTmpSubAndRootChainsQuery, + NULL, + "-t", "nat", "-L", rootchain, NULL); } - virBufferAddLit(buf, ")\"\n"); - - virBufferAddLit(buf, "rename_chains $chains\n"); - ebtablesRenameTmpRootChain(buf, true, ifname); - ebtablesRenameTmpRootChain(buf, false, ifname); + ebtablesRenameTmpRootChainFW(fw, true, ifname); + ebtablesRenameTmpRootChainFW(fw, false, ifname); } static void @@ -4248,46 +4271,31 @@ ebiptablesTearNewRules(const char *ifname) static int ebiptablesTearOldRules(const char *ifname) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - - /* switch to new iptables user defined chains */ - if (iptables_cmd_path) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesUnlinkRootChains(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - - iptablesRenameTmpRootChains(&buf, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } - - if (ip6tables_cmd_path) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - - iptablesUnlinkRootChains(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - - iptablesRenameTmpRootChains(&buf, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } - - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); - - ebtablesUnlinkRootChain(&buf, true, ifname); - ebtablesUnlinkRootChain(&buf, false, ifname); + virFirewallPtr fw = virFirewallNew(); + int ret = -1; - ebtablesRemoveSubChains(&buf, ifname); + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); - ebtablesRemoveRootChain(&buf, true, ifname); - ebtablesRemoveRootChain(&buf, false, ifname); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRenameTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); - ebtablesRenameTmpSubAndRootChains(&buf, ifname); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRenameTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } + ebtablesUnlinkRootChainFW(fw, true, ifname); + ebtablesUnlinkRootChainFW(fw, false, ifname); + ebtablesRemoveSubChainsFW(fw, ifname); + ebtablesRemoveRootChainFW(fw, true, ifname); + ebtablesRemoveRootChainFW(fw, false, ifname); + ebtablesRenameTmpSubAndRootChainsFW(fw, ifname); - return 0; + virMutexLock(&execCLIMutex); + ret = virFirewallApply(fw); + virMutexUnlock(&execCLIMutex); + virFirewallFree(fw); + return ret; } diff --git a/tests/nwfilterebiptablestest.c b/tests/nwfilterebiptablestest.c index c05682b..85077f1 100644 --- a/tests/nwfilterebiptablestest.c +++ b/tests/nwfilterebiptablestest.c @@ -95,6 +95,75 @@ testNWFilterEBIPTablesAllTeardown(const void *opaque ATTRIBUTE_UNUSED) static int +testNWFilterEBIPTablesTearOldRules(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *expected = + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/iptables -F FO-vnet0\n" + "/usr/sbin/iptables -X FO-vnet0\n" + "/usr/sbin/iptables -F FI-vnet0\n" + "/usr/sbin/iptables -X FI-vnet0\n" + "/usr/sbin/iptables -F HI-vnet0\n" + "/usr/sbin/iptables -X HI-vnet0\n" + "/usr/sbin/iptables -E FP-vnet0 FO-vnet0\n" + "/usr/sbin/iptables -E FJ-vnet0 FI-vnet0\n" + "/usr/sbin/iptables -E HJ-vnet0 HI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/ip6tables -F FO-vnet0\n" + "/usr/sbin/ip6tables -X FO-vnet0\n" + "/usr/sbin/ip6tables -F FI-vnet0\n" + "/usr/sbin/ip6tables -X FI-vnet0\n" + "/usr/sbin/ip6tables -F HI-vnet0\n" + "/usr/sbin/ip6tables -X HI-vnet0\n" + "/usr/sbin/ip6tables -E FP-vnet0 FO-vnet0\n" + "/usr/sbin/ip6tables -E FJ-vnet0 FI-vnet0\n" + "/usr/sbin/ip6tables -E HJ-vnet0 HI-vnet0\n" + "/usr/sbin/ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -E libvirt-J-vnet0 libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -E libvirt-P-vnet0 libvirt-O-vnet0\n"; + const char *actual = NULL; + int ret = -1; + + virCommandSetDryRun(&buf, NULL, NULL); + + if (ebiptables_driver.tearOldRules("vnet0") < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actual = virBufferCurrentContent(&buf); + + if (STRNEQ_NULLABLE(actual, expected)) { + virtTestDifference(stderr, actual, expected); + goto cleanup; + } + + ret = 0; + cleanup: + virCommandSetDryRun(NULL, NULL, NULL); + virBufferFreeAndReset(&buf); + return ret; +} + + +static int mymain(void) { int ret = 0; @@ -109,6 +178,11 @@ mymain(void) NULL) < 0) ret = -1; + if (virtTestRun("ebiptablesTearOldRules", + testNWFilterEBIPTablesTearOldRules, + NULL) < 0) + ret = -1; + cleanup: return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebiptablesTearOldRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
static void @@ -4248,46 +4271,31 @@ ebiptablesTearNewRules(const char *ifname) static int ebiptablesTearOldRules(const char *ifname) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - - /* switch to new iptables user defined chains */ - if (iptables_cmd_path) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesUnlinkRootChains(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - - iptablesRenameTmpRootChains(&buf, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } - - if (ip6tables_cmd_path) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - - iptablesUnlinkRootChains(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - - iptablesRenameTmpRootChains(&buf, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } - - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); - - ebtablesUnlinkRootChain(&buf, true, ifname); - ebtablesUnlinkRootChain(&buf, false, ifname); + virFirewallPtr fw = virFirewallNew(); + int ret = -1;
- ebtablesRemoveSubChains(&buf, ifname); + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
- ebtablesRemoveRootChain(&buf, true, ifname); - ebtablesRemoveRootChain(&buf, false, ifname); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRenameTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname);
- ebtablesRenameTmpSubAndRootChains(&buf, ifname); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRenameTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname);
- ebiptablesExecCLI(&buf, true, NULL); - } + ebtablesUnlinkRootChainFW(fw, true, ifname); + ebtablesUnlinkRootChainFW(fw, false, ifname); + ebtablesRemoveSubChainsFW(fw, ifname); + ebtablesRemoveRootChainFW(fw, true, ifname); + ebtablesRemoveRootChainFW(fw, false, ifname); + ebtablesRenameTmpSubAndRootChainsFW(fw, ifname);
- return 0; + virMutexLock(&execCLIMutex); + ret = virFirewallApply(fw); + virMutexUnlock(&execCLIMutex); + virFirewallFree(fw); + return ret; }
Looks like the transformations I have seen in the other patches - really amazing!. I suppose we wouldn't get here if either iptables, ip6tables, or ebtables weren't installed? Besides I see the lock being grabbed here. You shouldn't need this lock anymore if you lock in the virFirewall code, where I guess you have to have a libvirt-internal centralized lock (possibly 3 locks , one for iptables, ip6tables, and ebtables if they don't mutually influence each other -- would need to test this -- or one lock for all of them) in case of direct eb/ip/ip6tables execution and none in case of firewalld, which should do its own locking. Regards, Stefan

On Wed, Apr 16, 2014 at 07:41:10AM -0400, Stefan Berger wrote:
On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebiptablesTearOldRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
static void @@ -4248,46 +4271,31 @@ ebiptablesTearNewRules(const char *ifname) static int ebiptablesTearOldRules(const char *ifname) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - - /* switch to new iptables user defined chains */ - if (iptables_cmd_path) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesUnlinkRootChains(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - - iptablesRenameTmpRootChains(&buf, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } - - if (ip6tables_cmd_path) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - - iptablesUnlinkRootChains(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - - iptablesRenameTmpRootChains(&buf, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } - - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); - - ebtablesUnlinkRootChain(&buf, true, ifname); - ebtablesUnlinkRootChain(&buf, false, ifname); + virFirewallPtr fw = virFirewallNew(); + int ret = -1;
- ebtablesRemoveSubChains(&buf, ifname); + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
- ebtablesRemoveRootChain(&buf, true, ifname); - ebtablesRemoveRootChain(&buf, false, ifname); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRenameTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname);
- ebtablesRenameTmpSubAndRootChains(&buf, ifname); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRenameTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname);
- ebiptablesExecCLI(&buf, true, NULL); - } + ebtablesUnlinkRootChainFW(fw, true, ifname); + ebtablesUnlinkRootChainFW(fw, false, ifname); + ebtablesRemoveSubChainsFW(fw, ifname); + ebtablesRemoveRootChainFW(fw, true, ifname); + ebtablesRemoveRootChainFW(fw, false, ifname); + ebtablesRenameTmpSubAndRootChainsFW(fw, ifname);
- return 0; + virMutexLock(&execCLIMutex); + ret = virFirewallApply(fw); + virMutexUnlock(&execCLIMutex); + virFirewallFree(fw); + return ret; }
Looks like the transformations I have seen in the other patches - really amazing!. I suppose we wouldn't get here if either iptables, ip6tables, or ebtables weren't installed?
The RPM will ensure they are all available, and the virfirewall code will complain if they're missing, so IMHO that's sufficient.
Besides I see the lock being grabbed here. You shouldn't need this lock anymore if you lock in the virFirewall code, where I guess you have to have a libvirt-internal centralized lock (possibly 3 locks , one for iptables, ip6tables, and ebtables if they don't mutually influence each other -- would need to test this -- or one lock for all of them) in case of direct eb/ip/ip6tables execution and none in case of firewalld, which should do its own locking.
These locks are just to protect things during the intermediate part-converted stage. They go away at the end of this series so we rely on the lock in virfirewall.c, which obsoletes the execCLIMutex. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 04/16/2014 07:55 AM, Daniel P. Berrange wrote:
On Wed, Apr 16, 2014 at 07:41:10AM -0400, Stefan Berger wrote:
On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebiptablesTearOldRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
static void @@ -4248,46 +4271,31 @@ ebiptablesTearNewRules(const char *ifname) static int ebiptablesTearOldRules(const char *ifname) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - - /* switch to new iptables user defined chains */ - if (iptables_cmd_path) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesUnlinkRootChains(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - - iptablesRenameTmpRootChains(&buf, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } - - if (ip6tables_cmd_path) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - - iptablesUnlinkRootChains(&buf, ifname); - iptablesRemoveRootChains(&buf, ifname); - - iptablesRenameTmpRootChains(&buf, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } - - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); - - ebtablesUnlinkRootChain(&buf, true, ifname); - ebtablesUnlinkRootChain(&buf, false, ifname); + virFirewallPtr fw = virFirewallNew(); + int ret = -1;
- ebtablesRemoveSubChains(&buf, ifname); + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
- ebtablesRemoveRootChain(&buf, true, ifname); - ebtablesRemoveRootChain(&buf, false, ifname); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRenameTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname);
- ebtablesRenameTmpSubAndRootChains(&buf, ifname); + iptablesUnlinkRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRemoveRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRenameTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname);
- ebiptablesExecCLI(&buf, true, NULL); - } + ebtablesUnlinkRootChainFW(fw, true, ifname); + ebtablesUnlinkRootChainFW(fw, false, ifname); + ebtablesRemoveSubChainsFW(fw, ifname); + ebtablesRemoveRootChainFW(fw, true, ifname); + ebtablesRemoveRootChainFW(fw, false, ifname); + ebtablesRenameTmpSubAndRootChainsFW(fw, ifname);
- return 0; + virMutexLock(&execCLIMutex); + ret = virFirewallApply(fw); + virMutexUnlock(&execCLIMutex); + virFirewallFree(fw); + return ret; } Looks like the transformations I have seen in the other patches - really amazing!. I suppose we wouldn't get here if either iptables, ip6tables, or ebtables weren't installed? The RPM will ensure they are all available, and the virfirewall code will complain if they're missing, so IMHO that's sufficient.
Besides I see the lock being grabbed here. You shouldn't need this lock anymore if you lock in the virFirewall code, where I guess you have to have a libvirt-internal centralized lock (possibly 3 locks , one for iptables, ip6tables, and ebtables if they don't mutually influence each other -- would need to test this -- or one lock for all of them) in case of direct eb/ip/ip6tables execution and none in case of firewalld, which should do its own locking. These locks are just to protect things during the intermediate part-converted stage. They go away at the end of this series so we rely on the lock in virfirewall.c, which obsoletes the execCLIMutex.
With this explanation: ACK

Convert the nwfilter ebtablesRemoveBasicRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 95 ++++++++++++++++--------------- tests/nwfilterebiptablestest.c | 52 +++++++++++++++++ 2 files changed, 100 insertions(+), 47 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index da4d096..7740960 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -206,7 +206,7 @@ static const char *m_physdev_out_old_str = "-m physdev --physdev-out"; static int ebtablesRemoveBasicRules(const char *ifname); static int ebiptablesDriverInit(bool privileged); static void ebiptablesDriverShutdown(void); -static void ebtablesCleanAll(const char *ifname); +static int ebtablesCleanAll(const char *ifname); static int ebiptablesAllTeardown(const char *ifname); static virMutex execCLIMutex = VIR_MUTEX_INITIALIZER; @@ -2901,14 +2901,6 @@ _ebtablesRemoveRootChainFW(virFirewallPtr fw, static void -ebtablesRemoveRootChain(virBufferPtr buf, - bool incoming, const char *ifname) -{ - _ebtablesRemoveRootChain(buf, incoming, ifname, false); -} - - -static void ebtablesRemoveRootChainFW(virFirewallPtr fw, bool incoming, const char *ifname) { @@ -2925,6 +2917,14 @@ ebtablesRemoveTmpRootChain(virBufferPtr buf, static void +ebtablesRemoveTmpRootChainFW(virFirewallPtr fw, + bool incoming, const char *ifname) +{ + _ebtablesRemoveRootChainFW(fw, incoming, ifname, 1); +} + + +static void _ebtablesUnlinkRootChain(virBufferPtr buf, bool incoming, const char *ifname, bool isTempChain) @@ -2978,14 +2978,6 @@ _ebtablesUnlinkRootChainFW(virFirewallPtr fw, static void -ebtablesUnlinkRootChain(virBufferPtr buf, - bool incoming, const char *ifname) -{ - _ebtablesUnlinkRootChain(buf, incoming, ifname, false); -} - - -static void ebtablesUnlinkRootChainFW(virFirewallPtr fw, bool incoming, const char *ifname) { @@ -3001,6 +2993,14 @@ ebtablesUnlinkTmpRootChain(virBufferPtr buf, } +static void +ebtablesUnlinkTmpRootChainFW(virFirewallPtr fw, + int incoming, const char *ifname) +{ + _ebtablesUnlinkRootChainFW(fw, incoming, ifname, 1); +} + + static int ebtablesCreateTmpSubChain(ebiptablesRuleInstPtr *inst, int *nRuleInstances, @@ -3166,8 +3166,8 @@ _ebtablesRemoveSubChainsFW(virFirewallPtr fw, } static void -ebtablesRemoveSubChains(virBufferPtr buf, - const char *ifname) +ebtablesRemoveSubChainsFW(virFirewallPtr fw, + const char *ifname) { char chains[3] = { CHAINPREFIX_HOST_IN, @@ -3175,25 +3175,25 @@ ebtablesRemoveSubChains(virBufferPtr buf, 0 }; - _ebtablesRemoveSubChains(buf, ifname, chains); + _ebtablesRemoveSubChainsFW(fw, ifname, chains); } static void -ebtablesRemoveSubChainsFW(virFirewallPtr fw, - const char *ifname) +ebtablesRemoveTmpSubChains(virBufferPtr buf, + const char *ifname) { char chains[3] = { - CHAINPREFIX_HOST_IN, - CHAINPREFIX_HOST_OUT, + CHAINPREFIX_HOST_IN_TEMP, + CHAINPREFIX_HOST_OUT_TEMP, 0 }; - _ebtablesRemoveSubChainsFW(fw, ifname, chains); + _ebtablesRemoveSubChains(buf, ifname, chains); } static void -ebtablesRemoveTmpSubChains(virBufferPtr buf, - const char *ifname) +ebtablesRemoveTmpSubChainsFW(virFirewallPtr fw, + const char *ifname) { char chains[3] = { CHAINPREFIX_HOST_IN_TEMP, @@ -3201,7 +3201,7 @@ ebtablesRemoveTmpSubChains(virBufferPtr buf, 0 }; - _ebtablesRemoveSubChains(buf, ifname, chains); + _ebtablesRemoveSubChainsFW(fw, ifname, chains); } static void @@ -3668,34 +3668,35 @@ ebtablesApplyDropAllRules(const char *ifname) static int ebtablesRemoveBasicRules(const char *ifname) { - ebtablesCleanAll(ifname); - return 0; + return ebtablesCleanAll(ifname); } -static void +static int ebtablesCleanAll(const char *ifname) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - - if (!ebtables_cmd_path) - return; + virFirewallPtr fw = virFirewallNew(); + int ret = -1; - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); - ebtablesUnlinkRootChain(&buf, true, ifname); - ebtablesUnlinkRootChain(&buf, false, ifname); - ebtablesRemoveSubChains(&buf, ifname); - ebtablesRemoveRootChain(&buf, true, ifname); - ebtablesRemoveRootChain(&buf, false, ifname); + ebtablesUnlinkRootChainFW(fw, true, ifname); + ebtablesUnlinkRootChainFW(fw, false, ifname); + ebtablesRemoveSubChainsFW(fw, ifname); + ebtablesRemoveRootChainFW(fw, true, ifname); + ebtablesRemoveRootChainFW(fw, false, ifname); - ebtablesUnlinkTmpRootChain(&buf, true, ifname); - ebtablesUnlinkTmpRootChain(&buf, false, ifname); - ebtablesRemoveTmpSubChains(&buf, ifname); - ebtablesRemoveTmpRootChain(&buf, true, ifname); - ebtablesRemoveTmpRootChain(&buf, false, ifname); + ebtablesUnlinkTmpRootChainFW(fw, true, ifname); + ebtablesUnlinkTmpRootChainFW(fw, false, ifname); + ebtablesRemoveTmpSubChainsFW(fw, ifname); + ebtablesRemoveTmpRootChainFW(fw, true, ifname); + ebtablesRemoveTmpRootChainFW(fw, false, ifname); - ebiptablesExecCLI(&buf, true, NULL); + virMutexLock(&execCLIMutex); + ret = virFirewallApply(fw); + virMutexUnlock(&execCLIMutex); + virFirewallFree(fw); + return ret; } diff --git a/tests/nwfilterebiptablestest.c b/tests/nwfilterebiptablestest.c index 85077f1..11b7fb5 100644 --- a/tests/nwfilterebiptablestest.c +++ b/tests/nwfilterebiptablestest.c @@ -164,6 +164,53 @@ testNWFilterEBIPTablesTearOldRules(const void *opaque ATTRIBUTE_UNUSED) static int +testNWFilterEBIPTablesRemoveBasicRules(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *expected = + "/usr/sbin/ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-P-vnet0\n"; + const char *actual = NULL; + int ret = -1; + + virCommandSetDryRun(&buf, NULL, NULL); + + if (ebiptables_driver.removeBasicRules("vnet0") < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actual = virBufferCurrentContent(&buf); + + if (STRNEQ_NULLABLE(actual, expected)) { + virtTestDifference(stderr, actual, expected); + goto cleanup; + } + + ret = 0; + cleanup: + virCommandSetDryRun(NULL, NULL, NULL); + virBufferFreeAndReset(&buf); + return ret; +} + + +static int mymain(void) { int ret = 0; @@ -183,6 +230,11 @@ mymain(void) NULL) < 0) ret = -1; + if (virtTestRun("ebiptablesRemoveBasicRules", + testNWFilterEBIPTablesRemoveBasicRules, + NULL) < 0) + ret = -1; + cleanup: return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebtablesRemoveBasicRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
static void -ebtablesRemoveSubChainsFW(virFirewallPtr fw, - const char *ifname) +ebtablesRemoveTmpSubChains(virBufferPtr buf, + const char *ifname) { char chains[3] = { - CHAINPREFIX_HOST_IN, - CHAINPREFIX_HOST_OUT, + CHAINPREFIX_HOST_IN_TEMP, + CHAINPREFIX_HOST_OUT_TEMP, 0 };
- _ebtablesRemoveSubChainsFW(fw, ifname, chains); + _ebtablesRemoveSubChains(buf, ifname, chains); }
This is really the only odd part about this patch, a conversion in the other direction. Maybe not-yet converted code needs it at this point. ACK

On Wed, Apr 16, 2014 at 09:45:56AM -0400, Stefan Berger wrote:
On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebtablesRemoveBasicRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
static void -ebtablesRemoveSubChainsFW(virFirewallPtr fw, - const char *ifname) +ebtablesRemoveTmpSubChains(virBufferPtr buf, + const char *ifname) { char chains[3] = { - CHAINPREFIX_HOST_IN, - CHAINPREFIX_HOST_OUT, + CHAINPREFIX_HOST_IN_TEMP, + CHAINPREFIX_HOST_OUT_TEMP, 0 };
- _ebtablesRemoveSubChainsFW(fw, ifname, chains); + _ebtablesRemoveSubChains(buf, ifname, chains); }
This is really the only odd part about this patch, a conversion in the other direction. Maybe not-yet converted code needs it at this point.
This is just 'diff' producing a very misleading patch context - we're not actually reverting the previous change. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Convert the nwfilter ebiptablesTearNewRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing. --- src/nwfilter/nwfilter_ebiptables_driver.c | 88 ++++++++++++++++++++++--------- tests/nwfilterebiptablestest.c | 65 +++++++++++++++++++++++ 2 files changed, 128 insertions(+), 25 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 7740960..4093bd9 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -707,6 +707,18 @@ iptablesRemoveTmpRootChain(virBufferPtr buf, static void +iptablesRemoveTmpRootChainFW(virFirewallPtr fw, + virFirewallLayer layer, + char prefix, + bool incoming, + const char *ifname) +{ + _iptablesRemoveRootChainFW(fw, layer, prefix, + incoming, ifname, 1); +} + + +static void iptablesRemoveTmpRootChains(virBufferPtr buf, const char *ifname) { @@ -717,6 +729,17 @@ iptablesRemoveTmpRootChains(virBufferPtr buf, static void +iptablesRemoveTmpRootChainsFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *ifname) +{ + iptablesRemoveTmpRootChainFW(fw, layer, 'F', false, ifname); + iptablesRemoveTmpRootChainFW(fw, layer, 'F', true, ifname); + iptablesRemoveTmpRootChainFW(fw, layer, 'H', true, ifname); +} + + +static void iptablesRemoveRootChainsFW(virFirewallPtr fw, virFirewallLayer layer, const char *ifname) @@ -914,6 +937,18 @@ iptablesUnlinkTmpRootChain(virBufferPtr buf, static void +iptablesUnlinkTmpRootChainFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *basechain, + char prefix, + bool incoming, const char *ifname) +{ + _iptablesUnlinkRootChainFW(fw, layer, + basechain, prefix, incoming, ifname, 1); +} + + +static void iptablesUnlinkRootChainsFW(virFirewallPtr fw, virFirewallLayer layer, const char *ifname) @@ -935,6 +970,17 @@ iptablesUnlinkTmpRootChains(virBufferPtr buf, static void +iptablesUnlinkTmpRootChainsFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *ifname) +{ + iptablesUnlinkTmpRootChainFW(fw, layer, VIRT_OUT_CHAIN, 'F', false, ifname); + iptablesUnlinkTmpRootChainFW(fw, layer, VIRT_IN_CHAIN, 'F', true, ifname); + iptablesUnlinkTmpRootChainFW(fw, layer, HOST_IN_CHAIN, 'H', true, ifname); +} + + +static void iptablesRenameTmpRootChainFW(virFirewallPtr fw, virFirewallLayer layer, char prefix, @@ -4236,36 +4282,28 @@ ebiptablesApplyNewRules(const char *ifname, static int ebiptablesTearNewRules(const char *ifname) { - virBuffer buf = VIR_BUFFER_INITIALIZER; - - if (iptables_cmd_path) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesUnlinkTmpRootChains(&buf, ifname); - iptablesRemoveTmpRootChains(&buf, ifname); - } - - if (ip6tables_cmd_path) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); + virFirewallPtr fw = virFirewallNew(); + int ret = -1; - iptablesUnlinkTmpRootChains(&buf, ifname); - iptablesRemoveTmpRootChains(&buf, ifname); - } + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + iptablesUnlinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); - ebtablesUnlinkTmpRootChain(&buf, true, ifname); - ebtablesUnlinkTmpRootChain(&buf, false, ifname); + iptablesUnlinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRemoveTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); - ebtablesRemoveTmpSubChains(&buf, ifname); - ebtablesRemoveTmpRootChain(&buf, true, ifname); - ebtablesRemoveTmpRootChain(&buf, false, ifname); - } - - ebiptablesExecCLI(&buf, true, NULL); + ebtablesUnlinkTmpRootChainFW(fw, true, ifname); + ebtablesUnlinkTmpRootChainFW(fw, false, ifname); + ebtablesRemoveTmpSubChainsFW(fw, ifname); + ebtablesRemoveTmpRootChainFW(fw, true, ifname); + ebtablesRemoveTmpRootChainFW(fw, false, ifname); - return 0; + virMutexLock(&execCLIMutex); + ret = virFirewallApply(fw); + virMutexUnlock(&execCLIMutex); + virFirewallFree(fw); + return ret; } diff --git a/tests/nwfilterebiptablestest.c b/tests/nwfilterebiptablestest.c index 11b7fb5..d728e4c 100644 --- a/tests/nwfilterebiptablestest.c +++ b/tests/nwfilterebiptablestest.c @@ -211,6 +211,66 @@ testNWFilterEBIPTablesRemoveBasicRules(const void *opaque ATTRIBUTE_UNUSED) static int +testNWFilterEBIPTablesTearNewRules(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *expected = + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n" + "/usr/sbin/iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n" + "/usr/sbin/iptables -F FP-vnet0\n" + "/usr/sbin/iptables -X FP-vnet0\n" + "/usr/sbin/iptables -F FJ-vnet0\n" + "/usr/sbin/iptables -X FJ-vnet0\n" + "/usr/sbin/iptables -F HJ-vnet0\n" + "/usr/sbin/iptables -X HJ-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n" + "/usr/sbin/ip6tables -F FP-vnet0\n" + "/usr/sbin/ip6tables -X FP-vnet0\n" + "/usr/sbin/ip6tables -F FJ-vnet0\n" + "/usr/sbin/ip6tables -X FJ-vnet0\n" + "/usr/sbin/ip6tables -F HJ-vnet0\n" + "/usr/sbin/ip6tables -X HJ-vnet0\n" + "/usr/sbin/ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-P-vnet0\n"; + + const char *actual = NULL; + int ret = -1; + + virCommandSetDryRun(&buf, NULL, NULL); + + if (ebiptables_driver.tearNewRules("vnet0") < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actual = virBufferCurrentContent(&buf); + + if (STRNEQ_NULLABLE(actual, expected)) { + virtTestDifference(stderr, actual, expected); + goto cleanup; + } + + ret = 0; + cleanup: + virCommandSetDryRun(NULL, NULL, NULL); + virBufferFreeAndReset(&buf); + return ret; +} + + +static int mymain(void) { int ret = 0; @@ -235,6 +295,11 @@ mymain(void) NULL) < 0) ret = -1; + if (virtTestRun("ebiptablesTearNewRules", + testNWFilterEBIPTablesTearNewRules, + NULL) < 0) + ret = -1; + cleanup: return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebiptablesTearNewRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
NIt: Signed-off-by... ACK

Convert the nwfilter ebtablesApplyBasicRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 113 +++++++++++++++++------------- tests/nwfilterebiptablestest.c | 74 +++++++++++++++++++ 2 files changed, 137 insertions(+), 50 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 4093bd9..d9c6822 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -2877,6 +2877,21 @@ ebtablesCreateTmpRootChain(virBufferPtr buf, static void +ebtablesCreateTmpRootChainFW(virFirewallPtr fw, + int incoming, const char *ifname) +{ + char chain[MAX_CHAINNAME_LENGTH]; + char chainPrefix = (incoming) ? CHAINPREFIX_HOST_IN_TEMP + : CHAINPREFIX_HOST_OUT_TEMP; + + PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-N", chain, NULL); +} + + +static void ebtablesLinkTmpRootChain(virBufferPtr buf, bool incoming, const char *ifname) { @@ -2900,6 +2915,24 @@ ebtablesLinkTmpRootChain(virBufferPtr buf, static void +ebtablesLinkTmpRootChainFW(virFirewallPtr fw, + int incoming, const char *ifname) +{ + char chain[MAX_CHAINNAME_LENGTH]; + char chainPrefix = incoming ? CHAINPREFIX_HOST_IN_TEMP + : CHAINPREFIX_HOST_OUT_TEMP; + + PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); + + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", + incoming ? EBTABLES_CHAIN_INCOMING : EBTABLES_CHAIN_OUTGOING, + incoming ? "-i" : "-o", + ifname, "-j", chain, NULL); +} + + +static void _ebtablesRemoveRootChain(virBufferPtr buf, bool incoming, const char *ifname, bool isTempChain) @@ -3421,74 +3454,54 @@ static int ebtablesApplyBasicRules(const char *ifname, const virMacAddr *macaddr) { - virBuffer buf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = virFirewallNew(); char chain[MAX_CHAINNAME_LENGTH]; char chainPrefix = CHAINPREFIX_HOST_IN_TEMP; char macaddr_str[VIR_MAC_STRING_BUFLEN]; - if (!ebtables_cmd_path) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot create rules since ebtables tool is " - "missing.")); - return -1; - } - virMacAddrFormat(macaddr, macaddr_str); - ebiptablesAllTeardown(ifname); + if (ebiptablesAllTeardown(ifname) < 0) + goto error; - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + virFirewallStartTransaction(fw, 0); - ebtablesCreateTmpRootChain(&buf, true, ifname); + ebtablesCreateTmpRootChainFW(fw, true, ifname); PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s -s ! %s -j DROP") CMD_SEPARATOR - CMD_EXEC - "%s", - - chain, macaddr_str, - CMD_STOPONERR(true)); - - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s -p IPv4 -j ACCEPT") CMD_SEPARATOR - CMD_EXEC - "%s", - - chain, - CMD_STOPONERR(true)); - - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s -p ARP -j ACCEPT") CMD_SEPARATOR - CMD_EXEC - "%s", - - chain, - CMD_STOPONERR(true)); - - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s -j DROP") CMD_SEPARATOR - CMD_EXEC - "%s", - - chain, - CMD_STOPONERR(true)); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, + "-s", "!", macaddr_str, + "-j", "DROP", NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, + "-p", "IPv4", + "-j", "ACCEPT", NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, + "-p", "ARP", + "-j", "ACCEPT", NULL); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, + "-j", "DROP", NULL); - ebtablesLinkTmpRootChain(&buf, true, ifname); - ebtablesRenameTmpRootChain(&buf, true, ifname); + ebtablesLinkTmpRootChainFW(fw, true, ifname); + ebtablesRenameTmpRootChainFW(fw, true, ifname); - if (ebiptablesExecCLI(&buf, false, NULL) < 0) + virMutexLock(&execCLIMutex); + if (virFirewallApply(fw) < 0) { + virMutexUnlock(&execCLIMutex); goto tear_down_tmpebchains; + } + virMutexUnlock(&execCLIMutex); + virFirewallFree(fw); return 0; tear_down_tmpebchains: ebtablesCleanAll(ifname); - - virReportError(VIR_ERR_BUILD_FIREWALL, - "%s", - _("Some rules could not be created.")); - + error: + virFirewallFree(fw); return -1; } diff --git a/tests/nwfilterebiptablestest.c b/tests/nwfilterebiptablestest.c index d728e4c..22460fe 100644 --- a/tests/nwfilterebiptablestest.c +++ b/tests/nwfilterebiptablestest.c @@ -271,6 +271,75 @@ testNWFilterEBIPTablesTearNewRules(const void *opaque ATTRIBUTE_UNUSED) static int +testNWFilterEBIPTablesApplyBasicRules(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *expected = + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/iptables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/iptables -F FO-vnet0\n" + "/usr/sbin/iptables -X FO-vnet0\n" + "/usr/sbin/iptables -F FI-vnet0\n" + "/usr/sbin/iptables -X FI-vnet0\n" + "/usr/sbin/iptables -F HI-vnet0\n" + "/usr/sbin/iptables -X HI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/ip6tables -F FO-vnet0\n" + "/usr/sbin/ip6tables -X FO-vnet0\n" + "/usr/sbin/ip6tables -F FI-vnet0\n" + "/usr/sbin/ip6tables -X FI-vnet0\n" + "/usr/sbin/ip6tables -F HI-vnet0\n" + "/usr/sbin/ip6tables -X HI-vnet0\n" + "/usr/sbin/ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -N libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s '!' 10:20:30:40:50:60 -j DROP\n" + "/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -p IPv4 -j ACCEPT\n" + "/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -p ARP -j ACCEPT\n" + "/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -j DROP\n" + "/usr/sbin/ebtables -t nat -A PREROUTING -i vnet0 -j libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -E libvirt-J-vnet0 libvirt-I-vnet0\n"; + const char *actual = NULL; + int ret = -1; + virMacAddr mac = { .addr = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 } }; + + virCommandSetDryRun(&buf, NULL, NULL); + + if (ebiptables_driver.applyBasicRules("vnet0", &mac) < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actual = virBufferCurrentContent(&buf); + + if (STRNEQ_NULLABLE(actual, expected)) { + virtTestDifference(stderr, actual, expected); + goto cleanup; + } + + ret = 0; + cleanup: + virCommandSetDryRun(NULL, NULL, NULL); + virBufferFreeAndReset(&buf); + return ret; +} + + +static int mymain(void) { int ret = 0; @@ -300,6 +369,11 @@ mymain(void) NULL) < 0) ret = -1; + if (virtTestRun("ebiptablesApplyBasicRules", + testNWFilterEBIPTablesApplyBasicRules, + NULL) < 0) + ret = -1; + cleanup: return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebtablesApplyBasicRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
ACK Stefan

Convert the nwfilter ebtablesApplyDHCPOnlyRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 120 ++++++++++++------------------ tests/nwfilterebiptablestest.c | 92 +++++++++++++++++++++++ 2 files changed, 140 insertions(+), 72 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index d9c6822..62866ac 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -3529,127 +3529,103 @@ ebtablesApplyDHCPOnlyRules(const char *ifname, virNWFilterVarValuePtr dhcpsrvrs, bool leaveTemporary) { - virBuffer buf = VIR_BUFFER_INITIALIZER; char chain_in [MAX_CHAINNAME_LENGTH], chain_out[MAX_CHAINNAME_LENGTH]; char macaddr_str[VIR_MAC_STRING_BUFLEN]; unsigned int idx = 0; unsigned int num_dhcpsrvrs; - - if (!ebtables_cmd_path) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot create rules since ebtables tool is " - "missing.")); - return -1; - } + virFirewallPtr fw = virFirewallNew(); virMacAddrFormat(macaddr, macaddr_str); - ebiptablesAllTeardown(ifname); + if (ebiptablesAllTeardown(ifname) < 0) + goto error; - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + virFirewallStartTransaction(fw, 0); - ebtablesCreateTmpRootChain(&buf, true, ifname); - ebtablesCreateTmpRootChain(&buf, false, ifname); + ebtablesCreateTmpRootChainFW(fw, true, ifname); + ebtablesCreateTmpRootChainFW(fw, false, ifname); PRINT_ROOT_CHAIN(chain_in, CHAINPREFIX_HOST_IN_TEMP, ifname); PRINT_ROOT_CHAIN(chain_out, CHAINPREFIX_HOST_OUT_TEMP, ifname); - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s" - " -s %s" - " -p ipv4 --ip-protocol udp" - " --ip-sport 68 --ip-dport 67" - " -j ACCEPT") CMD_SEPARATOR - CMD_EXEC - "%s", - - chain_in, - macaddr_str, - CMD_STOPONERR(true)); - - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s -j DROP") CMD_SEPARATOR - CMD_EXEC - "%s", + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain_in, + "-s", macaddr_str, + "-p", "ipv4", "--ip-protocol", "udp", + "--ip-sport", "68", "--ip-dport", "67", + "-j", "ACCEPT", NULL); - chain_in, - CMD_STOPONERR(true)); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain_in, + "-j", "DROP", NULL); num_dhcpsrvrs = (dhcpsrvrs != NULL) ? virNWFilterVarValueGetCardinality(dhcpsrvrs) : 0; while (true) { - char *srcIPParam = NULL; + const char *dhcpserver = NULL; int ctr; - if (idx < num_dhcpsrvrs) { - const char *dhcpserver; - + if (idx < num_dhcpsrvrs) dhcpserver = virNWFilterVarValueGetNthValue(dhcpsrvrs, idx); - if (virAsprintf(&srcIPParam, "--ip-src %s", dhcpserver) < 0) - goto tear_down_tmpebchains; - } - /* * create two rules allowing response to MAC address of VM * or to broadcast MAC address */ for (ctr = 0; ctr < 2; ctr++) { - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s" - " -d %s" - " -p ipv4 --ip-protocol udp" - " %s" - " --ip-sport 67 --ip-dport 68" - " -j ACCEPT") CMD_SEPARATOR - CMD_EXEC - "%s", - - chain_out, - (ctr == 0) ? macaddr_str : "ff:ff:ff:ff:ff:ff", - srcIPParam != NULL ? srcIPParam : "", - CMD_STOPONERR(true)); + if (dhcpserver) + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain_out, + "-d", (ctr == 0) ? macaddr_str : "ff:ff:ff:ff:ff:ff", + "-p", "ipv4", "--ip-protocol", "udp", + "--ip-src", dhcpserver, + "--ip-sport", "67", "--ip-dport", "68", + "-j", "ACCEPT", NULL); + else + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain_out, + "-d", (ctr == 0) ? macaddr_str : "ff:ff:ff:ff:ff:ff", + "-p", "ipv4", "--ip-protocol", "udp", + "--ip-sport", "67", "--ip-dport", "68", + "-j", "ACCEPT", NULL); } - VIR_FREE(srcIPParam); - idx++; if (idx >= num_dhcpsrvrs) break; } - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s -j DROP") CMD_SEPARATOR - CMD_EXEC - "%s", - - chain_out, - CMD_STOPONERR(true)); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain_out, + "-j", "DROP", NULL); - ebtablesLinkTmpRootChain(&buf, true, ifname); - ebtablesLinkTmpRootChain(&buf, false, ifname); + ebtablesLinkTmpRootChainFW(fw, true, ifname); + ebtablesLinkTmpRootChainFW(fw, false, ifname); if (!leaveTemporary) { - ebtablesRenameTmpRootChain(&buf, true, ifname); - ebtablesRenameTmpRootChain(&buf, false, ifname); + ebtablesRenameTmpRootChainFW(fw, true, ifname); + ebtablesRenameTmpRootChainFW(fw, false, ifname); } - if (ebiptablesExecCLI(&buf, false, NULL) < 0) + virMutexLock(&execCLIMutex); + if (virFirewallApply(fw) < 0) { + virMutexUnlock(&execCLIMutex); goto tear_down_tmpebchains; + } + virMutexUnlock(&execCLIMutex); + + virFirewallFree(fw); return 0; tear_down_tmpebchains: ebtablesCleanAll(ifname); - - virReportError(VIR_ERR_BUILD_FIREWALL, - "%s", - _("Some rules could not be created.")); - + error: + virFirewallFree(fw); return -1; } diff --git a/tests/nwfilterebiptablestest.c b/tests/nwfilterebiptablestest.c index 22460fe..3010668 100644 --- a/tests/nwfilterebiptablestest.c +++ b/tests/nwfilterebiptablestest.c @@ -340,6 +340,93 @@ testNWFilterEBIPTablesApplyBasicRules(const void *opaque ATTRIBUTE_UNUSED) static int +testNWFilterEBIPTablesApplyDHCPOnlyRules(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *expected = + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/iptables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/iptables -F FO-vnet0\n" + "/usr/sbin/iptables -X FO-vnet0\n" + "/usr/sbin/iptables -F FI-vnet0\n" + "/usr/sbin/iptables -X FI-vnet0\n" + "/usr/sbin/iptables -F HI-vnet0\n" + "/usr/sbin/iptables -X HI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/ip6tables -F FO-vnet0\n" + "/usr/sbin/ip6tables -X FO-vnet0\n" + "/usr/sbin/ip6tables -F FI-vnet0\n" + "/usr/sbin/ip6tables -X FI-vnet0\n" + "/usr/sbin/ip6tables -F HI-vnet0\n" + "/usr/sbin/ip6tables -X HI-vnet0\n" + "/usr/sbin/ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -N libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -N libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 10:20:30:40:50:60 -p ipv4 --ip-protocol udp --ip-sport 68 --ip-dport 67 -j ACCEPT\n" + "/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -j DROP\n" + "/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d 10:20:30:40:50:60 -p ipv4 --ip-protocol udp --ip-src 192.168.122.1 --ip-sport 67 --ip-dport 68 -j ACCEPT\n" + "/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d ff:ff:ff:ff:ff:ff -p ipv4 --ip-protocol udp --ip-src 192.168.122.1 --ip-sport 67 --ip-dport 68 -j ACCEPT\n" + "/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d 10:20:30:40:50:60 -p ipv4 --ip-protocol udp --ip-src 10.0.0.1 --ip-sport 67 --ip-dport 68 -j ACCEPT\n" + "/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d ff:ff:ff:ff:ff:ff -p ipv4 --ip-protocol udp --ip-src 10.0.0.1 --ip-sport 67 --ip-dport 68 -j ACCEPT\n" + "/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d 10:20:30:40:50:60 -p ipv4 --ip-protocol udp --ip-src 10.0.0.2 --ip-sport 67 --ip-dport 68 -j ACCEPT\n" + "/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d ff:ff:ff:ff:ff:ff -p ipv4 --ip-protocol udp --ip-src 10.0.0.2 --ip-sport 67 --ip-dport 68 -j ACCEPT\n" + "/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -j DROP\n" + "/usr/sbin/ebtables -t nat -A PREROUTING -i vnet0 -j libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -A POSTROUTING -o vnet0 -j libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -E libvirt-J-vnet0 libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -E libvirt-P-vnet0 libvirt-O-vnet0\n"; + const char *actual = NULL; + int ret = -1; + virMacAddr mac = { .addr = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 } }; + const char *servers[] = { "192.168.122.1", "10.0.0.1", "10.0.0.2" }; + virNWFilterVarValue val = { + .valType = NWFILTER_VALUE_TYPE_ARRAY, + .u = { + .array = { + .values = (char **)servers, + .nValues = 3, + } + } + }; + + virCommandSetDryRun(&buf, NULL, NULL); + + if (ebiptables_driver.applyDHCPOnlyRules("vnet0", &mac, &val, false) < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actual = virBufferCurrentContent(&buf); + + if (STRNEQ_NULLABLE(actual, expected)) { + virtTestDifference(stderr, actual, expected); + goto cleanup; + } + + ret = 0; + cleanup: + virCommandSetDryRun(NULL, NULL, NULL); + virBufferFreeAndReset(&buf); + return ret; +} + + +static int mymain(void) { int ret = 0; @@ -374,6 +461,11 @@ mymain(void) NULL) < 0) ret = -1; + if (virtTestRun("ebiptablesApplyDHCPOnlyRules", + testNWFilterEBIPTablesApplyDHCPOnlyRules, + NULL) < 0) + ret = -1; + cleanup: return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebtablesApplyDHCPOnlyRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> ACK

Convert the nwfilter ebtablesApplyDropAllRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 93 ++++++++----------------------- tests/nwfilterebiptablestest.c | 75 +++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 69 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 62866ac..db6e324 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -3284,31 +3284,6 @@ ebtablesRemoveTmpSubChainsFW(virFirewallPtr fw, } static void -ebtablesRenameTmpSubChain(virBufferPtr buf, - bool incoming, - const char *ifname, - const char *protocol) -{ - char tmpchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH]; - char tmpChainPrefix = incoming ? CHAINPREFIX_HOST_IN_TEMP - : CHAINPREFIX_HOST_OUT_TEMP; - char chainPrefix = incoming ? CHAINPREFIX_HOST_IN - : CHAINPREFIX_HOST_OUT; - - if (protocol) { - PRINT_CHAIN(tmpchain, tmpChainPrefix, ifname, protocol); - PRINT_CHAIN(chain, chainPrefix, ifname, protocol); - } else { - PRINT_ROOT_CHAIN(tmpchain, tmpChainPrefix, ifname); - PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); - } - - virBufferAsprintf(buf, - "$EBT -t nat -E %s %s" CMD_SEPARATOR, - tmpchain, chain); -} - -static void ebtablesRenameTmpSubChainFW(virFirewallPtr fw, int incoming, const char *ifname, @@ -3333,14 +3308,6 @@ ebtablesRenameTmpSubChainFW(virFirewallPtr fw, } static void -ebtablesRenameTmpRootChain(virBufferPtr buf, - bool incoming, - const char *ifname) -{ - ebtablesRenameTmpSubChain(buf, incoming, ifname, NULL); -} - -static void ebtablesRenameTmpRootChainFW(virFirewallPtr fw, bool incoming, const char *ifname) @@ -3642,60 +3609,48 @@ ebtablesApplyDHCPOnlyRules(const char *ifname, static int ebtablesApplyDropAllRules(const char *ifname) { - virBuffer buf = VIR_BUFFER_INITIALIZER; char chain_in [MAX_CHAINNAME_LENGTH], chain_out[MAX_CHAINNAME_LENGTH]; + virFirewallPtr fw = virFirewallNew(); - if (!ebtables_cmd_path) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot create rules since ebtables tool is " - "missing.")); - return -1; - } - - ebiptablesAllTeardown(ifname); + if (ebiptablesAllTeardown(ifname) < 0) + goto error; - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + virFirewallStartTransaction(fw, 0); - ebtablesCreateTmpRootChain(&buf, true, ifname); - ebtablesCreateTmpRootChain(&buf, false, ifname); + ebtablesCreateTmpRootChainFW(fw, true, ifname); + ebtablesCreateTmpRootChainFW(fw, false, ifname); PRINT_ROOT_CHAIN(chain_in, CHAINPREFIX_HOST_IN_TEMP, ifname); PRINT_ROOT_CHAIN(chain_out, CHAINPREFIX_HOST_OUT_TEMP, ifname); - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s -j DROP") CMD_SEPARATOR - CMD_EXEC - "%s", - - chain_in, - CMD_STOPONERR(true)); - - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -A %s -j DROP") CMD_SEPARATOR - CMD_EXEC - "%s", + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain_in, + "-j", "DROP", NULL); - chain_out, - CMD_STOPONERR(true)); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain_out, + "-j", "DROP", NULL); - ebtablesLinkTmpRootChain(&buf, true, ifname); - ebtablesLinkTmpRootChain(&buf, false, ifname); - ebtablesRenameTmpRootChain(&buf, true, ifname); - ebtablesRenameTmpRootChain(&buf, false, ifname); + ebtablesLinkTmpRootChainFW(fw, true, ifname); + ebtablesLinkTmpRootChainFW(fw, false, ifname); + ebtablesRenameTmpRootChainFW(fw, true, ifname); + ebtablesRenameTmpRootChainFW(fw, false, ifname); - if (ebiptablesExecCLI(&buf, false, NULL) < 0) + virMutexLock(&execCLIMutex); + if (virFirewallApply(fw) < 0) { + virMutexUnlock(&execCLIMutex); goto tear_down_tmpebchains; + } + virMutexUnlock(&execCLIMutex); + virFirewallFree(fw); return 0; tear_down_tmpebchains: ebtablesCleanAll(ifname); - - virReportError(VIR_ERR_BUILD_FIREWALL, - "%s", - _("Some rules could not be created.")); - + error: + virFirewallFree(fw); return -1; } diff --git a/tests/nwfilterebiptablestest.c b/tests/nwfilterebiptablestest.c index 3010668..f994331 100644 --- a/tests/nwfilterebiptablestest.c +++ b/tests/nwfilterebiptablestest.c @@ -426,6 +426,76 @@ testNWFilterEBIPTablesApplyDHCPOnlyRules(const void *opaque ATTRIBUTE_UNUSED) } + +static int +testNWFilterEBIPTablesApplyDropAllRules(const void *opaque ATTRIBUTE_UNUSED) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *expected = + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/iptables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/iptables -F FO-vnet0\n" + "/usr/sbin/iptables -X FO-vnet0\n" + "/usr/sbin/iptables -F FI-vnet0\n" + "/usr/sbin/iptables -X FI-vnet0\n" + "/usr/sbin/iptables -F HI-vnet0\n" + "/usr/sbin/iptables -X HI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FO-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HI-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/ip6tables -F FO-vnet0\n" + "/usr/sbin/ip6tables -X FO-vnet0\n" + "/usr/sbin/ip6tables -F FI-vnet0\n" + "/usr/sbin/ip6tables -X FI-vnet0\n" + "/usr/sbin/ip6tables -F HI-vnet0\n" + "/usr/sbin/ip6tables -X HI-vnet0\n" + "/usr/sbin/ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-O-vnet0\n" + "/usr/sbin/ebtables -t nat -N libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -N libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -j DROP\n" + "/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -j DROP\n" + "/usr/sbin/ebtables -t nat -A PREROUTING -i vnet0 -j libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -A POSTROUTING -o vnet0 -j libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -E libvirt-J-vnet0 libvirt-I-vnet0\n" + "/usr/sbin/ebtables -t nat -E libvirt-P-vnet0 libvirt-O-vnet0\n"; + const char *actual = NULL; + int ret = -1; + + virCommandSetDryRun(&buf, NULL, NULL); + + if (ebiptables_driver.applyDropAllRules("vnet0") < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actual = virBufferCurrentContent(&buf); + + if (STRNEQ_NULLABLE(actual, expected)) { + virtTestDifference(stderr, actual, expected); + goto cleanup; + } + + ret = 0; + cleanup: + virCommandSetDryRun(NULL, NULL, NULL); + virBufferFreeAndReset(&buf); + return ret; +} + + static int mymain(void) { @@ -466,6 +536,11 @@ mymain(void) NULL) < 0) ret = -1; + if (virtTestRun("ebiptablesApplyDropAllRules", + testNWFilterEBIPTablesApplyDropAllRules, + NULL) < 0) + ret = -1; + cleanup: return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebtablesApplyDropAllRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
ACK

Convert the nwfilter ebtablesApplyNewRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/conf/nwfilter_conf.c | 22 +- src/conf/nwfilter_conf.h | 7 +- src/nwfilter/nwfilter_ebiptables_driver.c | 2748 +++++++++++------------------ src/nwfilter/nwfilter_ebiptables_driver.h | 17 - 4 files changed, 1090 insertions(+), 1704 deletions(-) diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 968e045..f57dcef 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -962,13 +962,16 @@ printTCPFlags(virBufferPtr buf, uint8_t flags) } -void -virNWFilterPrintTCPFlags(virBufferPtr buf, - uint8_t mask, char sep, uint8_t flags) +char * +virNWFilterPrintTCPFlags(uint8_t flags) { - printTCPFlags(buf, mask); - virBufferAddChar(buf, sep); - printTCPFlags(buf, flags); + virBuffer buf = VIR_BUFFER_INITIALIZER; + printTCPFlags(&buf, flags); + if (virBufferError(&buf)) { + virReportOOMError(); + return NULL; + } + return virBufferContentAndReset(&buf); } @@ -977,10 +980,9 @@ tcpFlagsFormatter(virBufferPtr buf, virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED, nwItemDesc *item) { - virNWFilterPrintTCPFlags(buf, - item->u.tcpFlags.mask, - '/', - item->u.tcpFlags.flags); + printTCPFlags(buf, item->u.tcpFlags.mask); + virBufferAddLit(buf, "/"); + printTCPFlags(buf, item->u.tcpFlags.flags); return true; } diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index 9f9deab..3c7985c 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -82,8 +82,8 @@ enum virNWFilterEntryItemFlags { # define HAS_ENTRY_ITEM(data) \ (((data)->flags) & NWFILTER_ENTRY_ITEM_FLAG_EXISTS) -# define ENTRY_GET_NEG_SIGN(data) \ - ((((data)->flags) & NWFILTER_ENTRY_ITEM_FLAG_IS_NEG) ? "!" : "") +# define ENTRY_WANT_NEG_SIGN(data) \ + (((data)->flags) & NWFILTER_ENTRY_ITEM_FLAG_IS_NEG) /* datatypes appearing in rule attributes */ enum attrDatatype { @@ -673,8 +673,7 @@ void virNWFilterCallbackDriversLock(void); void virNWFilterCallbackDriversUnlock(void); -void virNWFilterPrintTCPFlags(virBufferPtr buf, uint8_t mask, - char sep, uint8_t flags); +char *virNWFilterPrintTCPFlags(uint8_t flags); bool virNWFilterRuleIsProtocolIPv4(virNWFilterRuleDefPtr rule); diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index db6e324..835e068 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -105,65 +105,6 @@ static enum ctdirStatus iptables_ctdir_corrected; #define PRINT_CHAIN(buf, prefix, ifname, suffix) \ snprintf(buf, sizeof(buf), "%c-%s-%s", prefix, ifname, suffix) -/* The collect_chains() script recursively determines all names - * of ebtables (nat) chains that are 'children' of a given 'root' chain. - * The typical output of an ebtables call is as follows: - * - * #> ebtables -t nat -L libvirt-I-tck-test205002 - * Bridge table: nat - * - * Bridge chain: libvirt-I-tck-test205002, entries: 5, policy: ACCEPT - * -p IPv4 -j I-tck-test205002-ipv4 - * -p ARP -j I-tck-test205002-arp - * -p 0x8035 -j I-tck-test205002-rarp - * -p 0x835 -j ACCEPT - * -j DROP - */ -static const char ebtables_script_func_collect_chains[] = - "collect_chains()\n" - "{\n" - " for tmp2 in $*; do\n" - " for tmp in $($EBT -t nat -L $tmp2 | \\\n" - " sed -n \"/Bridge chain/,\\$ s/.*-j \\\\([%s]-.*\\\\)/\\\\1/p\");\n" - " do\n" - " echo $tmp\n" - " collect_chains $tmp\n" - " done\n" - " done\n" - "}\n"; - -static const char ebiptables_script_func_rm_chains[] = - "rm_chains()\n" - "{\n" - " for tmp in $*; do $EBT -t nat -F $tmp; done\n" - " for tmp in $*; do $EBT -t nat -X $tmp; done\n" - "}\n"; - -static const char ebiptables_script_func_rename_chains[] = - "rename_chain()\n" - "{\n" - " $EBT -t nat -F $2\n" - " $EBT -t nat -X $2\n" - " $EBT -t nat -E $1 $2\n" - "}\n" - "rename_chains()\n" - "{\n" - " for tmp in $*; do\n" - " case $tmp in\n" - " %c*) rename_chain $tmp %c${tmp#?} ;;\n" - " %c*) rename_chain $tmp %c${tmp#?} ;;\n" - " esac\n" - " done\n" - "}\n"; - -static const char ebiptables_script_set_ifs[] = - "tmp='\n'\n" - "IFS=' ''\t'$tmp\n"; - -#define NWFILTER_FUNC_COLLECT_CHAINS ebtables_script_func_collect_chains -#define NWFILTER_FUNC_RM_CHAINS ebiptables_script_func_rm_chains -#define NWFILTER_FUNC_RENAME_CHAINS ebiptables_script_func_rename_chains -#define NWFILTER_FUNC_SET_IFS ebiptables_script_set_ifs #define NWFILTER_SET_EBTABLES_SHELLVAR(BUFPTR) \ virBufferAsprintf(BUFPTR, "EBT=\"%s\"\n", ebtables_cmd_path); @@ -180,29 +121,12 @@ static const char ebiptables_script_set_ifs[] = #define PRINT_IPT_ROOT_CHAIN(buf, prefix, ifname) \ snprintf(buf, sizeof(buf), "%c%c-%s", prefix[0], prefix[1], ifname) -#define PHYSDEV_IN "--physdev-in" - -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-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 -#define MATCH_PHYSDEV_IN m_physdev_in_str -#define MATCH_PHYSDEV_OUT m_physdev_out_str -#define MATCH_PHYSDEV_OUT_OLD m_physdev_out_old_str +static bool newMatchState; #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); static int ebiptablesDriverInit(bool privileged); static void ebiptablesDriverShutdown(void); @@ -455,55 +379,39 @@ printDataTypeAsHex(virNWFilterVarCombIterPtr vars, } -static void -printCommentVar(virBufferPtr dest, const char *buf) -{ - size_t i, len = strlen(buf); - - virBufferAddLit(dest, COMMENT_VARNAME "='"); - - if (len > IPTABLES_MAX_COMMENT_LENGTH) - len = IPTABLES_MAX_COMMENT_LENGTH; - - for (i = 0; i < len; i++) { - if (buf[i] == '\'') - virBufferAddLit(dest, "'\\''"); - else - virBufferAddChar(dest, buf[i]); - } - virBufferAddLit(dest, "'" CMD_SEPARATOR); -} - - static int -ebtablesHandleEthHdr(virBufferPtr buf, +ebtablesHandleEthHdr(virFirewallPtr fw, + virFirewallRulePtr fwrule, virNWFilterVarCombIterPtr vars, ethHdrDataDefPtr ethHdr, bool reverse) { char macaddr[VIR_MAC_STRING_BUFLEN]; + char macmask[VIR_MAC_STRING_BUFLEN]; + int ret = -1; if (HAS_ENTRY_ITEM(ðHdr->dataSrcMACAddr)) { if (printDataType(vars, macaddr, sizeof(macaddr), ðHdr->dataSrcMACAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - " %s %s %s", - reverse ? "-d" : "-s", - ENTRY_GET_NEG_SIGN(ðHdr->dataSrcMACAddr), - macaddr); + virFirewallRuleAddArgList(fw, fwrule, + reverse ? "-d" : "-s", + NULL); + if (ENTRY_WANT_NEG_SIGN(ðHdr->dataSrcMACAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(ðHdr->dataSrcMACMask)) { if (printDataType(vars, - macaddr, sizeof(macaddr), + macmask, sizeof(macmask), ðHdr->dataSrcMACMask) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - "/%s", - macaddr); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", macaddr, macmask); + } else { + virFirewallRuleAddArg(fw, fwrule, macaddr); } } @@ -511,96 +419,80 @@ ebtablesHandleEthHdr(virBufferPtr buf, if (printDataType(vars, macaddr, sizeof(macaddr), ðHdr->dataDstMACAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - " %s %s %s", - reverse ? "-s" : "-d", - ENTRY_GET_NEG_SIGN(ðHdr->dataDstMACAddr), - macaddr); + virFirewallRuleAddArgList(fw, fwrule, + reverse ? "-s" : "-d", + NULL); + if (ENTRY_WANT_NEG_SIGN(ðHdr->dataDstMACAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(ðHdr->dataDstMACMask)) { if (printDataType(vars, - macaddr, sizeof(macaddr), + macmask, sizeof(macmask), ðHdr->dataDstMACMask) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - "/%s", - macaddr); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", macaddr, macmask); + } else { + virFirewallRuleAddArg(fw, fwrule, macaddr); } } - return 0; - - err_exit: - virBufferFreeAndReset(buf); - - return -1; + ret = 0; + cleanup: + return ret; } /************************ iptables support ************************/ -static void -iptablesLinkIPTablesBaseChain(virBufferPtr buf, - const char *udchain, - const char *syschain, - unsigned int pos) -{ - virBufferAsprintf(buf, - "res=$($IPT -L %s -n --line-number | %s '%s')\n" - "if [ $? -ne 0 ]; then\n" - " $IPT -I %s %d -j %s\n" - "else\n" - " set dummy $res; r=$2\n" - " if [ \"${r}\" != \"%d\" ]; then\n" - " " CMD_DEF("$IPT -I %s %d -j %s") CMD_SEPARATOR - " " CMD_EXEC - " %s" - " r=$(( $r + 1 ))\n" - " " CMD_DEF("$IPT -D %s ${r}") CMD_SEPARATOR - " " CMD_EXEC - " %s" - " fi\n" - "fi\n", - - syschain, grep_cmd_path, udchain, - - syschain, pos, udchain, - - pos, - - syschain, pos, udchain, - CMD_STOPONERR(true), - - syschain, - CMD_STOPONERR(true)); -} - static void -iptablesCreateBaseChains(virBufferPtr buf) -{ - virBufferAddLit(buf, "$IPT -N " VIRT_IN_CHAIN CMD_SEPARATOR - "$IPT -N " VIRT_OUT_CHAIN CMD_SEPARATOR - "$IPT -N " VIRT_IN_POST_CHAIN CMD_SEPARATOR - "$IPT -N " HOST_IN_CHAIN CMD_SEPARATOR); - iptablesLinkIPTablesBaseChain(buf, - VIRT_IN_CHAIN, "FORWARD", 1); - iptablesLinkIPTablesBaseChain(buf, - VIRT_OUT_CHAIN, "FORWARD", 2); - iptablesLinkIPTablesBaseChain(buf, - VIRT_IN_POST_CHAIN, "FORWARD", 3); - iptablesLinkIPTablesBaseChain(buf, - HOST_IN_CHAIN, "INPUT", 1); +iptablesCreateBaseChainsFW(virFirewallPtr fw, + virFirewallLayer layer) +{ + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-N", VIRT_IN_CHAIN, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-N", VIRT_OUT_CHAIN, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-N", VIRT_IN_POST_CHAIN, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-N", HOST_IN_CHAIN, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", "FORWARD", "-j", VIRT_IN_CHAIN, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", "FORWARD", "-j", VIRT_OUT_CHAIN, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", "FORWARD", "-j", VIRT_IN_POST_CHAIN, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", "INPUT", "-j", HOST_IN_CHAIN, NULL); + virFirewallAddRule(fw, layer, + "-I", "FORWARD", "1", "-j", VIRT_IN_CHAIN, NULL); + virFirewallAddRule(fw, layer, + "-I", "FORWARD", "2", "-j", VIRT_OUT_CHAIN, NULL); + virFirewallAddRule(fw, layer, + "-I", "FORWARD", "3", "-j", VIRT_IN_POST_CHAIN, NULL); + virFirewallAddRule(fw, layer, + "-I", "INPUT", "1", "-j", HOST_IN_CHAIN, NULL); } static void -iptablesCreateTmpRootChain(virBufferPtr buf, - char prefix, - bool incoming, const char *ifname) +iptablesCreateTmpRootChainFW(virFirewallPtr fw, + virFirewallLayer layer, + char prefix, + bool incoming, const char *ifname) { char chain[MAX_CHAINNAME_LENGTH]; char chainPrefix[2] = { @@ -611,50 +503,19 @@ iptablesCreateTmpRootChain(virBufferPtr buf, PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname); - virBufferAsprintf(buf, - CMD_DEF("$IPT -N %s") CMD_SEPARATOR - CMD_EXEC - "%s", - chain, - CMD_STOPONERR(true)); -} - - -static void -iptablesCreateTmpRootChains(virBufferPtr buf, - const char *ifname) -{ - iptablesCreateTmpRootChain(buf, 'F', false, ifname); - iptablesCreateTmpRootChain(buf, 'F', true, ifname); - iptablesCreateTmpRootChain(buf, 'H', true, ifname); + virFirewallAddRule(fw, layer, + "-N", chain, NULL); } static void -_iptablesRemoveRootChain(virBufferPtr buf, - char prefix, - bool incoming, const char *ifname, - bool isTempChain) +iptablesCreateTmpRootChainsFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *ifname) { - 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); - - virBufferAsprintf(buf, - "$IPT -F %s" CMD_SEPARATOR - "$IPT -X %s" CMD_SEPARATOR, - chain, - chain); + iptablesCreateTmpRootChainFW(fw, layer, 'F', false, ifname); + iptablesCreateTmpRootChainFW(fw, layer, 'F', true, ifname); + iptablesCreateTmpRootChainFW(fw, layer, 'H', true, ifname); } @@ -679,8 +540,12 @@ _iptablesRemoveRootChainFW(virFirewallPtr fw, PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname); - virFirewallAddRule(fw, layer, "-F", chain, NULL); - virFirewallAddRule(fw, layer, "-X", chain, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-F", chain, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-X", chain, NULL); } @@ -696,17 +561,6 @@ iptablesRemoveRootChainFW(virFirewallPtr fw, static void -iptablesRemoveTmpRootChain(virBufferPtr buf, - char prefix, - bool incoming, - const char *ifname) -{ - _iptablesRemoveRootChain(buf, prefix, - incoming, ifname, true); -} - - -static void iptablesRemoveTmpRootChainFW(virFirewallPtr fw, virFirewallLayer layer, char prefix, @@ -719,16 +573,6 @@ iptablesRemoveTmpRootChainFW(virFirewallPtr fw, static void -iptablesRemoveTmpRootChains(virBufferPtr buf, - const char *ifname) -{ - iptablesRemoveTmpRootChain(buf, 'F', false, ifname); - iptablesRemoveTmpRootChain(buf, 'F', true, ifname); - iptablesRemoveTmpRootChain(buf, 'H', true, ifname); -} - - -static void iptablesRemoveTmpRootChainsFW(virFirewallPtr fw, virFirewallLayer layer, const char *ifname) @@ -751,10 +595,11 @@ iptablesRemoveRootChainsFW(virFirewallPtr fw, static void -iptablesLinkTmpRootChain(virBufferPtr buf, - const char *basechain, - char prefix, - bool incoming, const char *ifname) +iptablesLinkTmpRootChainFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *basechain, + char prefix, + bool incoming, const char *ifname) { char chain[MAX_CHAINNAME_LENGTH]; char chainPrefix[2] = { @@ -762,51 +607,49 @@ iptablesLinkTmpRootChain(virBufferPtr buf, incoming ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_OUT_TEMP }; - const char *match = incoming ? MATCH_PHYSDEV_IN - : MATCH_PHYSDEV_OUT; PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname); - virBufferAsprintf(buf, - CMD_DEF("$IPT -A %s " - "%s %s -g %s") CMD_SEPARATOR - CMD_EXEC - "%s", - basechain, - match, ifname, chain, - - CMD_STOPONERR(true)); + if (incoming) + virFirewallAddRule(fw, layer, + "-A", basechain, + MATCH_PHYSDEV_IN_FW, + ifname, + "-g", chain, NULL); + else + virFirewallAddRule(fw, layer, + "-A", basechain, + MATCH_PHYSDEV_OUT_FW, + ifname, + "-g", chain, NULL); } static void -iptablesLinkTmpRootChains(virBufferPtr buf, - const char *ifname) +iptablesLinkTmpRootChainsFW(virFirewallPtr fw, + virFirewallLayer layer, + const char *ifname) { - iptablesLinkTmpRootChain(buf, VIRT_OUT_CHAIN, 'F', false, ifname); - iptablesLinkTmpRootChain(buf, VIRT_IN_CHAIN, 'F', true, ifname); - iptablesLinkTmpRootChain(buf, HOST_IN_CHAIN, 'H', true, ifname); + iptablesLinkTmpRootChainFW(fw, layer, VIRT_OUT_CHAIN, 'F', false, ifname); + iptablesLinkTmpRootChainFW(fw, layer, VIRT_IN_CHAIN, 'F', true, ifname); + iptablesLinkTmpRootChainFW(fw, layer, HOST_IN_CHAIN, 'H', true, ifname); } static void -iptablesSetupVirtInPost(virBufferPtr buf, - const char *ifname) -{ - const char *match = MATCH_PHYSDEV_IN; - virBufferAsprintf(buf, - "res=$($IPT -n -L " VIRT_IN_POST_CHAIN - " | grep \"\\%s %s\")\n" - "if [ \"${res}\" = \"\" ]; then " - CMD_DEF("$IPT" - " -A " VIRT_IN_POST_CHAIN - " %s %s -j ACCEPT") CMD_SEPARATOR - CMD_EXEC - "%s" - "fi\n", - PHYSDEV_IN, ifname, - match, ifname, - CMD_STOPONERR(true)); +iptablesSetupVirtInPostFW(virFirewallPtr fw ATTRIBUTE_UNUSED, + virFirewallLayer layer ATTRIBUTE_UNUSED, + const char *ifname ATTRIBUTE_UNUSED) +{ + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", VIRT_IN_POST_CHAIN, + MATCH_PHYSDEV_IN_FW, + ifname, "-j", "ACCEPT", NULL); + virFirewallAddRule(fw, layer, + "-A", VIRT_IN_POST_CHAIN, + MATCH_PHYSDEV_IN_FW, + ifname, "-j", "ACCEPT", NULL); } @@ -821,49 +664,6 @@ iptablesClearVirtInPostFW(virFirewallPtr fw, ifname, "-j", "ACCEPT", NULL); } -static void -_iptablesUnlinkRootChain(virBufferPtr buf, - const char *basechain, - char prefix, - bool incoming, const char *ifname, - bool 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; - const char *match = incoming ? MATCH_PHYSDEV_IN - : MATCH_PHYSDEV_OUT; - const char *old_match = incoming ? NULL - : MATCH_PHYSDEV_OUT_OLD; - - PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname); - - virBufferAsprintf(buf, - "$IPT -D %s " - "%s %s -g %s" CMD_SEPARATOR, - basechain, - match, ifname, chain); - - /* - * Previous versions of libvirt may have created a rule - * with the --physdev-is-bridged missing. Remove this one - * as well. - */ - if (old_match) - virBufferAsprintf(buf, - "$IPT -D %s " - "%s %s -g %s" CMD_SEPARATOR, - basechain, - old_match, ifname, chain); -} - static void _iptablesUnlinkRootChainFW(virFirewallPtr fw, @@ -887,17 +687,19 @@ _iptablesUnlinkRootChainFW(virFirewallPtr fw, PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname); if (incoming) - virFirewallAddRule(fw, layer, - "-D", basechain, - MATCH_PHYSDEV_IN_FW, ifname, - "-g", chain, - NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", basechain, + MATCH_PHYSDEV_IN_FW, ifname, + "-g", chain, + NULL); else - virFirewallAddRule(fw, layer, - "-D", basechain, - MATCH_PHYSDEV_OUT_FW, ifname, - "-g", chain, - NULL); + 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 @@ -905,11 +707,12 @@ _iptablesUnlinkRootChainFW(virFirewallPtr fw, * as well. */ if (!incoming) - virFirewallAddRule(fw, layer, - "-D", basechain, - MATCH_PHYSDEV_OUT_OLD_FW, ifname, - "-g", chain, - NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-D", basechain, + MATCH_PHYSDEV_OUT_OLD_FW, ifname, + "-g", chain, + NULL); } @@ -926,17 +729,6 @@ iptablesUnlinkRootChainFW(virFirewallPtr fw, static void -iptablesUnlinkTmpRootChain(virBufferPtr buf, - const char *basechain, - char prefix, - bool incoming, const char *ifname) -{ - _iptablesUnlinkRootChain(buf, - basechain, prefix, incoming, ifname, true); -} - - -static void iptablesUnlinkTmpRootChainFW(virFirewallPtr fw, virFirewallLayer layer, const char *basechain, @@ -960,16 +752,6 @@ iptablesUnlinkRootChainsFW(virFirewallPtr fw, static void -iptablesUnlinkTmpRootChains(virBufferPtr buf, - const char *ifname) -{ - iptablesUnlinkTmpRootChain(buf, VIRT_OUT_CHAIN, 'F', false, ifname); - iptablesUnlinkTmpRootChain(buf, VIRT_IN_CHAIN, 'F', true, ifname); - iptablesUnlinkTmpRootChain(buf, HOST_IN_CHAIN, 'H', true, ifname); -} - - -static void iptablesUnlinkTmpRootChainsFW(virFirewallPtr fw, virFirewallLayer layer, const char *ifname) @@ -1018,24 +800,17 @@ iptablesRenameTmpRootChainsFW(virFirewallPtr fw, } -static void -iptablesInstCommand(virBufferPtr buf, - const char *cmdstr) -{ - virBufferAdd(buf, cmdstr, -1); - virBufferAsprintf(buf, CMD_SEPARATOR "%s", - CMD_STOPONERR(true)); -} - - static int -iptablesHandleSrcMacAddr(virBufferPtr buf, +iptablesHandleSrcMacAddr(virFirewallPtr fw, + virFirewallRulePtr fwrule, virNWFilterVarCombIterPtr vars, nwItemDescPtr srcMacAddr, bool directionIn, bool *srcmacskipped) { char macaddr[VIR_MAC_STRING_BUFLEN]; + int ret = -1; + *srcmacskipped = false; if (HAS_ENTRY_ITEM(srcMacAddr)) { @@ -1047,40 +822,43 @@ iptablesHandleSrcMacAddr(virBufferPtr buf, if (printDataType(vars, macaddr, sizeof(macaddr), srcMacAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - " -m mac %s --mac-source %s", - ENTRY_GET_NEG_SIGN(srcMacAddr), - macaddr); + virFirewallRuleAddArgList(fw, fwrule, + "-m", "mac", + NULL); + if (ENTRY_WANT_NEG_SIGN(srcMacAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArgList(fw, fwrule, + "--mac-source", + macaddr, + NULL); } - return 0; - - err_exit: - virBufferFreeAndReset(buf); - - return -1; + ret = 0; + cleanup: + return ret; } static int -iptablesHandleIpHdr(virBufferPtr buf, - virBufferPtr afterStateMatch, +iptablesHandleIpHdr(virFirewallPtr fw, + virFirewallRulePtr fwrule, virNWFilterVarCombIterPtr vars, ipHdrDataDefPtr ipHdr, bool directionIn, - bool *skipRule, bool *skipMatch, - virBufferPtr prefix) + bool *skipRule, bool *skipMatch) { char ipaddr[INET6_ADDRSTRLEN], + ipaddralt[INET6_ADDRSTRLEN], number[MAX(INT_BUFSIZE_BOUND(uint32_t), INT_BUFSIZE_BOUND(int))]; - char str[MAX_IPSET_NAME_LENGTH]; const char *src = "--source"; const char *dst = "--destination"; const char *srcrange = "--src-range"; const char *dstrange = "--dst-range"; + int ret = -1; + if (directionIn) { src = "--destination"; dst = "--source"; @@ -1088,138 +866,116 @@ iptablesHandleIpHdr(virBufferPtr buf, dstrange = "--src-range"; } - if (HAS_ENTRY_ITEM(&ipHdr->dataIPSet) && - HAS_ENTRY_ITEM(&ipHdr->dataIPSetFlags)) { - - if (printDataType(vars, - str, sizeof(str), - &ipHdr->dataIPSet) < 0) - goto err_exit; - - virBufferAsprintf(afterStateMatch, - " -m set --match-set \"%s\" ", - str); - - if (printDataTypeDirection(vars, - str, sizeof(str), - &ipHdr->dataIPSetFlags, directionIn) < 0) - goto err_exit; - - virBufferAdd(afterStateMatch, str, -1); - } - if (HAS_ENTRY_ITEM(&ipHdr->dataSrcIPAddr)) { - if (printDataType(vars, ipaddr, sizeof(ipaddr), &ipHdr->dataSrcIPAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - " %s %s %s", - ENTRY_GET_NEG_SIGN(&ipHdr->dataSrcIPAddr), - src, - ipaddr); + if (ENTRY_WANT_NEG_SIGN(&ipHdr->dataSrcIPAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, src); if (HAS_ENTRY_ITEM(&ipHdr->dataSrcIPMask)) { if (printDataType(vars, number, sizeof(number), &ipHdr->dataSrcIPMask) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - "/%s", - number); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", ipaddr, number); + } else { + virFirewallRuleAddArg(fw, fwrule, ipaddr); } } else if (HAS_ENTRY_ITEM(&ipHdr->dataSrcIPFrom)) { - if (printDataType(vars, ipaddr, sizeof(ipaddr), &ipHdr->dataSrcIPFrom) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - " -m iprange %s %s %s", - ENTRY_GET_NEG_SIGN(&ipHdr->dataSrcIPFrom), - srcrange, - ipaddr); + virFirewallRuleAddArgList(fw, fwrule, + "-m", "iprange", + NULL); + if (ENTRY_WANT_NEG_SIGN(&ipHdr->dataSrcIPFrom)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, srcrange); if (HAS_ENTRY_ITEM(&ipHdr->dataSrcIPTo)) { if (printDataType(vars, - ipaddr, sizeof(ipaddr), + ipaddralt, sizeof(ipaddralt), &ipHdr->dataSrcIPTo) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - "-%s", - ipaddr); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s-%s", ipaddr, ipaddralt); + } else { + virFirewallRuleAddArg(fw, fwrule, ipaddr); } } if (HAS_ENTRY_ITEM(&ipHdr->dataDstIPAddr)) { - if (printDataType(vars, ipaddr, sizeof(ipaddr), &ipHdr->dataDstIPAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - " %s %s %s", - ENTRY_GET_NEG_SIGN(&ipHdr->dataDstIPAddr), - dst, - ipaddr); + if (ENTRY_WANT_NEG_SIGN(&ipHdr->dataDstIPAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, dst); if (HAS_ENTRY_ITEM(&ipHdr->dataDstIPMask)) { - if (printDataType(vars, number, sizeof(number), &ipHdr->dataDstIPMask) < 0) - goto err_exit; - - virBufferAsprintf(buf, - "/%s", - number); + goto cleanup; + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", ipaddr, number); + } else { + virFirewallRuleAddArg(fw, fwrule, ipaddr); } } else if (HAS_ENTRY_ITEM(&ipHdr->dataDstIPFrom)) { - if (printDataType(vars, ipaddr, sizeof(ipaddr), &ipHdr->dataDstIPFrom) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - " -m iprange %s %s %s", - ENTRY_GET_NEG_SIGN(&ipHdr->dataDstIPFrom), - dstrange, - ipaddr); + virFirewallRuleAddArgList(fw, fwrule, + "-m", "iprange", + NULL); + if (ENTRY_WANT_NEG_SIGN(&ipHdr->dataDstIPFrom)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, dstrange); if (HAS_ENTRY_ITEM(&ipHdr->dataDstIPTo)) { - if (printDataType(vars, - ipaddr, sizeof(ipaddr), + ipaddralt, sizeof(ipaddralt), &ipHdr->dataDstIPTo) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - "-%s", - ipaddr); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s-%s", ipaddr, ipaddralt); + } else { + virFirewallRuleAddArg(fw, fwrule, ipaddr); } } if (HAS_ENTRY_ITEM(&ipHdr->dataDSCP)) { - if (printDataType(vars, number, sizeof(number), &ipHdr->dataDSCP) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(buf, - " -m dscp %s --dscp %s", - ENTRY_GET_NEG_SIGN(&ipHdr->dataDSCP), - number); + virFirewallRuleAddArgList(fw, fwrule, + "-m", "dscp", + NULL); + if (ENTRY_WANT_NEG_SIGN(&ipHdr->dataDSCP)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArgList(fw, fwrule, + "--dscp", number, + NULL); } if (HAS_ENTRY_ITEM(&ipHdr->dataConnlimitAbove)) { @@ -1227,47 +983,93 @@ iptablesHandleIpHdr(virBufferPtr buf, /* only support for limit in outgoing dir. */ *skipRule = true; } else { + *skipMatch = true; + } + } + + ret = 0; + cleanup: + return ret; +} + + +static int +iptablesHandleIpHdrAfterStateMatch(virFirewallPtr fw, + virFirewallRulePtr fwrule, + virNWFilterVarCombIterPtr vars, + ipHdrDataDefPtr ipHdr, + bool directionIn) +{ + char number[MAX(INT_BUFSIZE_BOUND(uint32_t), + INT_BUFSIZE_BOUND(int))]; + char str[MAX_IPSET_NAME_LENGTH]; + int ret = -1; + + if (HAS_ENTRY_ITEM(&ipHdr->dataIPSet) && + HAS_ENTRY_ITEM(&ipHdr->dataIPSetFlags)) { + + if (printDataType(vars, + str, sizeof(str), + &ipHdr->dataIPSet) < 0) + goto cleanup; + + virFirewallRuleAddArgList(fw, fwrule, + "-m", "set", + "--match-set", str, + NULL); + + if (printDataTypeDirection(vars, + str, sizeof(str), + &ipHdr->dataIPSetFlags, directionIn) < 0) + goto cleanup; + + virFirewallRuleAddArg(fw, fwrule, str); + } + + if (HAS_ENTRY_ITEM(&ipHdr->dataConnlimitAbove)) { + if (!directionIn) { if (printDataType(vars, number, sizeof(number), &ipHdr->dataConnlimitAbove) < 0) - goto err_exit; + goto cleanup; /* place connlimit after potential -m state --state ... since this is the most useful order */ - virBufferAsprintf(afterStateMatch, - " -m connlimit %s --connlimit-above %s", - ENTRY_GET_NEG_SIGN(&ipHdr->dataConnlimitAbove), - number); - *skipMatch = true; + virFirewallRuleAddArgList(fw, fwrule, + "-m", "connlimit", + NULL); + if (ENTRY_WANT_NEG_SIGN(&ipHdr->dataConnlimitAbove)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArgList(fw, fwrule, + "--connlimit-above", number, + NULL); } } if (HAS_ENTRY_ITEM(&ipHdr->dataComment)) { - printCommentVar(prefix, ipHdr->dataComment.u.string); - /* keep comments behind everything else -- they are packet eval. no-ops */ - virBufferAddLit(afterStateMatch, - " -m comment --comment \"$" COMMENT_VARNAME "\""); + virFirewallRuleAddArgList(fw, fwrule, + "-m", "comment", + "--comment", ipHdr->dataComment.u.string, + NULL); } - return 0; - - err_exit: - virBufferFreeAndReset(buf); - virBufferFreeAndReset(afterStateMatch); - - return -1; + ret = 0; + cleanup: + return ret; } static int -iptablesHandlePortData(virBufferPtr buf, +iptablesHandlePortData(virFirewallPtr fw, + virFirewallRulePtr fwrule, virNWFilterVarCombIterPtr vars, portDataDefPtr portData, bool directionIn) { char portstr[20]; + char portstralt[20]; const char *sport = "--sport"; const char *dport = "--dport"; if (directionIn) { @@ -1281,21 +1083,20 @@ iptablesHandlePortData(virBufferPtr buf, &portData->dataSrcPortStart) < 0) goto err_exit; - virBufferAsprintf(buf, - " %s %s %s", - ENTRY_GET_NEG_SIGN(&portData->dataSrcPortStart), - sport, - portstr); + if (ENTRY_WANT_NEG_SIGN(&portData->dataSrcPortStart)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, sport); if (HAS_ENTRY_ITEM(&portData->dataSrcPortEnd)) { if (printDataType(vars, - portstr, sizeof(portstr), + portstralt, sizeof(portstralt), &portData->dataSrcPortEnd) < 0) goto err_exit; - virBufferAsprintf(buf, - ":%s", - portstr); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s:%s", portstr, portstralt); + } else { + virFirewallRuleAddArg(fw, fwrule, portstr); } } @@ -1305,21 +1106,20 @@ iptablesHandlePortData(virBufferPtr buf, &portData->dataDstPortStart) < 0) goto err_exit; - virBufferAsprintf(buf, - " %s %s %s", - ENTRY_GET_NEG_SIGN(&portData->dataDstPortStart), - dport, - portstr); + if (ENTRY_WANT_NEG_SIGN(&portData->dataDstPortStart)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, dport); if (HAS_ENTRY_ITEM(&portData->dataDstPortEnd)) { if (printDataType(vars, - portstr, sizeof(portstr), + portstralt, sizeof(portstralt), &portData->dataDstPortEnd) < 0) goto err_exit; - virBufferAsprintf(buf, - ":%s", - portstr); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s:%s", portstr, portstralt); + } else { + virFirewallRuleAddArg(fw, fwrule, portstr); } } @@ -1331,9 +1131,10 @@ iptablesHandlePortData(virBufferPtr buf, static void -iptablesEnforceDirection(bool directionIn, - virNWFilterRuleDefPtr rule, - virBufferPtr buf) +iptablesEnforceDirection(virFirewallPtr fw, + virFirewallRulePtr fwrule, + bool directionIn, + virNWFilterRuleDefPtr rule) { switch (iptables_ctdir_corrected) { case CTDIR_STATUS_UNKNOWN: @@ -1347,14 +1148,20 @@ iptablesEnforceDirection(bool directionIn, } if (rule->tt != VIR_NWFILTER_RULE_DIRECTION_INOUT) - virBufferAsprintf(buf, " -m conntrack --ctdir %s", - (directionIn) ? "Original" - : "Reply"); + virFirewallRuleAddArgList(fw, fwrule, + "-m", "conntrack", + "--ctdir", + (directionIn ? + "Original" : + "Reply"), + NULL); } /* * _iptablesCreateRuleInstance: + * @fw: the firewall ruleset instance + * @layer: the firewall layer * @chainPrefix : The prefix to put in front of the name of the chain * @rule: The rule of the filter to convert * @ifname : The name of the interface to apply the rule to @@ -1362,11 +1169,8 @@ iptablesEnforceDirection(bool directionIn, * @match : optional string for state match * @accept_target : where to jump to on accepted traffic, i.e., "RETURN" * "ACCEPT" - * @isIPv6 : Whether this is an IPv6 rule * @maySkipICMP : whether this rule may under certain circumstances skip * the ICMP rule from being created - * @templates: pointer to array to store rule template - * @ntemplates: pointer to storage rule template count * * Convert a single rule into its representation for later instantiation * @@ -1374,287 +1178,267 @@ iptablesEnforceDirection(bool directionIn, * pointed to by res, != 0 otherwise. */ static int -_iptablesCreateRuleInstance(bool directionIn, +_iptablesCreateRuleInstance(virFirewallPtr fw, + virFirewallLayer layer, + bool directionIn, const char *chainPrefix, virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, const char *match, bool defMatch, const char *accept_target, - bool isIPv6, - bool maySkipICMP, - char ***templates, - size_t *ntemplates) + bool maySkipICMP) { char chain[MAX_CHAINNAME_LENGTH]; char number[MAX(INT_BUFSIZE_BOUND(uint32_t), INT_BUFSIZE_BOUND(int))]; - virBuffer prefix = VIR_BUFFER_INITIALIZER; - virBuffer buf = VIR_BUFFER_INITIALIZER; - virBuffer afterStateMatch = VIR_BUFFER_INITIALIZER; - virBufferPtr final = NULL; + char numberalt[MAX(INT_BUFSIZE_BOUND(uint32_t), + INT_BUFSIZE_BOUND(int))]; const char *target; - const char *iptables_cmd = (isIPv6) ? ip6tables_cmd_path - : iptables_cmd_path; - unsigned int bufUsed; bool srcMacSkipped = false; bool skipRule = false; bool skipMatch = false; bool hasICMPType = false; - char *template; - - if (!iptables_cmd) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot create rule since %s tool is " - "missing."), - isIPv6 ? "ip6tables" : "iptables"); - goto err_exit; - } + virFirewallRulePtr fwrule; + size_t fwruleargs; + int ret = -1; PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname); switch (rule->prtclType) { case VIR_NWFILTER_RULE_PROTOCOL_TCP: case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -A %s", - chain); + fwrule = virFirewallAddRule(fw, layer, + "-A", chain, + "-p", "tcp", + NULL); - virBufferAddLit(&buf, " -p tcp"); + fwruleargs = virFirewallRuleGetArgCount(fwrule); - bufUsed = virBufferUse(&buf); - - if (iptablesHandleSrcMacAddr(&buf, + if (iptablesHandleSrcMacAddr(fw, fwrule, vars, &rule->p.tcpHdrFilter.dataSrcMACAddr, directionIn, &srcMacSkipped) < 0) - goto err_exit; + goto cleanup; - if (iptablesHandleIpHdr(&buf, - &afterStateMatch, + if (iptablesHandleIpHdr(fw, fwrule, vars, &rule->p.tcpHdrFilter.ipHdr, directionIn, - &skipRule, &skipMatch, - &prefix) < 0) - goto err_exit; + &skipRule, &skipMatch) < 0) + goto cleanup; if (HAS_ENTRY_ITEM(&rule->p.tcpHdrFilter.dataTCPFlags)) { - virBufferAsprintf(&buf, " %s --tcp-flags ", - ENTRY_GET_NEG_SIGN(&rule->p.tcpHdrFilter.dataTCPFlags)); - virNWFilterPrintTCPFlags(&buf, - rule->p.tcpHdrFilter.dataTCPFlags.u.tcpFlags.mask, - ' ', - rule->p.tcpHdrFilter.dataTCPFlags.u.tcpFlags.flags); + char *flags; + if (ENTRY_WANT_NEG_SIGN(&rule->p.tcpHdrFilter.dataTCPFlags)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, "--tcp-flags"); + + if (!(flags = virNWFilterPrintTCPFlags(rule->p.tcpHdrFilter.dataTCPFlags.u.tcpFlags.mask))) + goto cleanup; + virFirewallRuleAddArg(fw, fwrule, flags); + VIR_FREE(flags); + if (!(flags = virNWFilterPrintTCPFlags(rule->p.tcpHdrFilter.dataTCPFlags.u.tcpFlags.flags))) + goto cleanup; + virFirewallRuleAddArg(fw, fwrule, flags); + VIR_FREE(flags); } - if (iptablesHandlePortData(&buf, + if (iptablesHandlePortData(fw, fwrule, vars, &rule->p.tcpHdrFilter.portData, directionIn) < 0) - goto err_exit; + goto cleanup; if (HAS_ENTRY_ITEM(&rule->p.tcpHdrFilter.dataTCPOption)) { if (printDataType(vars, number, sizeof(number), &rule->p.tcpHdrFilter.dataTCPOption) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " %s --tcp-option %s", - ENTRY_GET_NEG_SIGN(&rule->p.tcpHdrFilter.dataTCPOption), - number); + if (ENTRY_WANT_NEG_SIGN(&rule->p.tcpHdrFilter.dataTCPOption)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArgList(fw, fwrule, + "--tcp-option", number, NULL); } break; case VIR_NWFILTER_RULE_PROTOCOL_UDP: case VIR_NWFILTER_RULE_PROTOCOL_UDPoIPV6: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -A %s", - chain); + fwrule = virFirewallAddRule(fw, layer, + "-A", chain, + "-p", "udp", + NULL); - virBufferAddLit(&buf, " -p udp"); + fwruleargs = virFirewallRuleGetArgCount(fwrule); - bufUsed = virBufferUse(&buf); - - if (iptablesHandleSrcMacAddr(&buf, + if (iptablesHandleSrcMacAddr(fw, fwrule, vars, &rule->p.udpHdrFilter.dataSrcMACAddr, directionIn, &srcMacSkipped) < 0) - goto err_exit; + goto cleanup; - if (iptablesHandleIpHdr(&buf, - &afterStateMatch, + if (iptablesHandleIpHdr(fw, fwrule, vars, &rule->p.udpHdrFilter.ipHdr, directionIn, - &skipRule, &skipMatch, - &prefix) < 0) - goto err_exit; + &skipRule, &skipMatch) < 0) + goto cleanup; - if (iptablesHandlePortData(&buf, + if (iptablesHandlePortData(fw, fwrule, vars, &rule->p.udpHdrFilter.portData, directionIn) < 0) - goto err_exit; + goto cleanup; break; case VIR_NWFILTER_RULE_PROTOCOL_UDPLITE: case VIR_NWFILTER_RULE_PROTOCOL_UDPLITEoIPV6: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -A %s", - chain); - - virBufferAddLit(&buf, " -p udplite"); + fwrule = virFirewallAddRule(fw, layer, + "-A", chain, + "-p", "udplite", + NULL); - bufUsed = virBufferUse(&buf); + fwruleargs = virFirewallRuleGetArgCount(fwrule); - if (iptablesHandleSrcMacAddr(&buf, + if (iptablesHandleSrcMacAddr(fw, fwrule, vars, &rule->p.udpliteHdrFilter.dataSrcMACAddr, directionIn, &srcMacSkipped) < 0) - goto err_exit; + goto cleanup; - if (iptablesHandleIpHdr(&buf, - &afterStateMatch, + if (iptablesHandleIpHdr(fw, fwrule, vars, &rule->p.udpliteHdrFilter.ipHdr, directionIn, - &skipRule, &skipMatch, - &prefix) < 0) - goto err_exit; + &skipRule, &skipMatch) < 0) + goto cleanup; break; case VIR_NWFILTER_RULE_PROTOCOL_ESP: case VIR_NWFILTER_RULE_PROTOCOL_ESPoIPV6: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -A %s", - chain); + fwrule = virFirewallAddRule(fw, layer, + "-A", chain, + "-p", "esp", + NULL); - virBufferAddLit(&buf, " -p esp"); + fwruleargs = virFirewallRuleGetArgCount(fwrule); - bufUsed = virBufferUse(&buf); - - if (iptablesHandleSrcMacAddr(&buf, + if (iptablesHandleSrcMacAddr(fw, fwrule, vars, &rule->p.espHdrFilter.dataSrcMACAddr, directionIn, &srcMacSkipped) < 0) - goto err_exit; + goto cleanup; - if (iptablesHandleIpHdr(&buf, - &afterStateMatch, + if (iptablesHandleIpHdr(fw, fwrule, vars, &rule->p.espHdrFilter.ipHdr, directionIn, - &skipRule, &skipMatch, - &prefix) < 0) - goto err_exit; + &skipRule, &skipMatch) < 0) + goto cleanup; break; case VIR_NWFILTER_RULE_PROTOCOL_AH: case VIR_NWFILTER_RULE_PROTOCOL_AHoIPV6: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -A %s", - chain); + fwrule = virFirewallAddRule(fw, layer, + "-A", chain, + "-p", "ah", + NULL); - virBufferAddLit(&buf, " -p ah"); + fwruleargs = virFirewallRuleGetArgCount(fwrule); - bufUsed = virBufferUse(&buf); - - if (iptablesHandleSrcMacAddr(&buf, + if (iptablesHandleSrcMacAddr(fw, fwrule, vars, &rule->p.ahHdrFilter.dataSrcMACAddr, directionIn, &srcMacSkipped) < 0) - goto err_exit; + goto cleanup; - if (iptablesHandleIpHdr(&buf, - &afterStateMatch, + if (iptablesHandleIpHdr(fw, fwrule, vars, &rule->p.ahHdrFilter.ipHdr, directionIn, - &skipRule, &skipMatch, - &prefix) < 0) - goto err_exit; + &skipRule, &skipMatch) < 0) + goto cleanup; break; case VIR_NWFILTER_RULE_PROTOCOL_SCTP: case VIR_NWFILTER_RULE_PROTOCOL_SCTPoIPV6: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -A %s", - chain); - - virBufferAddLit(&buf, " -p sctp"); + fwrule = virFirewallAddRule(fw, layer, + "-A", chain, + "-p", "sctp", + NULL); - bufUsed = virBufferUse(&buf); + fwruleargs = virFirewallRuleGetArgCount(fwrule); - if (iptablesHandleSrcMacAddr(&buf, + if (iptablesHandleSrcMacAddr(fw, fwrule, vars, &rule->p.sctpHdrFilter.dataSrcMACAddr, directionIn, &srcMacSkipped) < 0) - goto err_exit; + goto cleanup; - if (iptablesHandleIpHdr(&buf, - &afterStateMatch, + if (iptablesHandleIpHdr(fw, fwrule, vars, &rule->p.sctpHdrFilter.ipHdr, directionIn, - &skipRule, &skipMatch, - &prefix) < 0) - goto err_exit; + &skipRule, &skipMatch) < 0) + goto cleanup; - if (iptablesHandlePortData(&buf, + if (iptablesHandlePortData(fw, fwrule, vars, &rule->p.sctpHdrFilter.portData, directionIn) < 0) - goto err_exit; + goto cleanup; break; case VIR_NWFILTER_RULE_PROTOCOL_ICMP: case VIR_NWFILTER_RULE_PROTOCOL_ICMPV6: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -A %s", - chain); + fwrule = virFirewallAddRule(fw, layer, + "-A", chain, + NULL); if (rule->prtclType == VIR_NWFILTER_RULE_PROTOCOL_ICMP) - virBufferAddLit(&buf, " -p icmp"); + virFirewallRuleAddArgList(fw, fwrule, + "-p", "icmp", NULL); else - virBufferAddLit(&buf, " -p icmpv6"); + virFirewallRuleAddArgList(fw, fwrule, + "-p", "icmpv6", NULL); - bufUsed = virBufferUse(&buf); + fwruleargs = virFirewallRuleGetArgCount(fwrule); - if (iptablesHandleSrcMacAddr(&buf, + if (iptablesHandleSrcMacAddr(fw, fwrule, vars, &rule->p.icmpHdrFilter.dataSrcMACAddr, directionIn, &srcMacSkipped) < 0) - goto err_exit; + goto cleanup; - if (iptablesHandleIpHdr(&buf, - &afterStateMatch, + if (iptablesHandleIpHdr(fw, fwrule, vars, &rule->p.icmpHdrFilter.ipHdr, directionIn, - &skipRule, &skipMatch, - &prefix) < 0) - goto err_exit; + &skipRule, &skipMatch) < 0) + goto cleanup; if (HAS_ENTRY_ITEM(&rule->p.icmpHdrFilter.dataICMPType)) { const char *parm; hasICMPType = true; - if (maySkipICMP) - goto exit_no_error; + if (maySkipICMP) { + virFirewallRemoveRule(fw, fwrule); + ret = 0; + goto cleanup; + } if (rule->prtclType == VIR_NWFILTER_RULE_PROTOCOL_ICMP) parm = "--icmp-type"; @@ -1664,90 +1448,86 @@ _iptablesCreateRuleInstance(bool directionIn, if (printDataType(vars, number, sizeof(number), &rule->p.icmpHdrFilter.dataICMPType) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - ENTRY_GET_NEG_SIGN(&rule->p.icmpHdrFilter.dataICMPType), - parm, - number); + if (ENTRY_WANT_NEG_SIGN(&rule->p.icmpHdrFilter.dataICMPType)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, parm); if (HAS_ENTRY_ITEM(&rule->p.icmpHdrFilter.dataICMPCode)) { if (printDataType(vars, - number, sizeof(number), + numberalt, sizeof(numberalt), &rule->p.icmpHdrFilter.dataICMPCode) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - "/%s", - number); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", number, numberalt); + } else { + virFirewallRuleAddArg(fw, fwrule, number); } } break; case VIR_NWFILTER_RULE_PROTOCOL_IGMP: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -A %s", - chain); - - virBufferAddLit(&buf, " -p igmp"); + fwrule = virFirewallAddRule(fw, layer, + "-A", chain, + "-p", "igmp", + NULL); - bufUsed = virBufferUse(&buf); + fwruleargs = virFirewallRuleGetArgCount(fwrule); - if (iptablesHandleSrcMacAddr(&buf, + if (iptablesHandleSrcMacAddr(fw, fwrule, vars, &rule->p.igmpHdrFilter.dataSrcMACAddr, directionIn, &srcMacSkipped) < 0) - goto err_exit; + goto cleanup; - if (iptablesHandleIpHdr(&buf, - &afterStateMatch, + if (iptablesHandleIpHdr(fw, fwrule, vars, &rule->p.igmpHdrFilter.ipHdr, directionIn, - &skipRule, &skipMatch, - &prefix) < 0) - goto err_exit; + &skipRule, &skipMatch) < 0) + goto cleanup; break; case VIR_NWFILTER_RULE_PROTOCOL_ALL: case VIR_NWFILTER_RULE_PROTOCOL_ALLoIPV6: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$IPT -A %s", - chain); - - virBufferAddLit(&buf, " -p all"); + fwrule = virFirewallAddRule(fw, layer, + "-A", chain, + "-p", "all", + NULL); - bufUsed = virBufferUse(&buf); + fwruleargs = virFirewallRuleGetArgCount(fwrule); - if (iptablesHandleSrcMacAddr(&buf, + if (iptablesHandleSrcMacAddr(fw, fwrule, vars, &rule->p.allHdrFilter.dataSrcMACAddr, directionIn, &srcMacSkipped) < 0) - goto err_exit; + goto cleanup; - if (iptablesHandleIpHdr(&buf, - &afterStateMatch, + if (iptablesHandleIpHdr(fw, fwrule, vars, &rule->p.allHdrFilter.ipHdr, directionIn, - &skipRule, &skipMatch, - &prefix) < 0) - goto err_exit; + &skipRule, &skipMatch) < 0) + goto cleanup; break; default: - return -1; + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected protocol %d"), + rule->prtclType); + goto cleanup; } - if ((srcMacSkipped && bufUsed == virBufferUse(&buf)) || - skipRule) { - virBufferFreeAndReset(&buf); - virBufferFreeAndReset(&prefix); + if ((srcMacSkipped && + fwruleargs == virFirewallRuleGetArgCount(fwrule)) || + skipRule) { + virFirewallRemoveRule(fw, fwrule); return 0; } @@ -1758,81 +1538,36 @@ _iptablesCreateRuleInstance(bool directionIn, skipMatch = defMatch; } - if (match && !skipMatch) - virBufferAsprintf(&buf, " %s", match); - - if (defMatch && match != NULL && !skipMatch && !hasICMPType) - iptablesEnforceDirection(directionIn, - rule, - &buf); - - if (virBufferError(&afterStateMatch)) { - virBufferFreeAndReset(&buf); - virBufferFreeAndReset(&prefix); - virBufferFreeAndReset(&afterStateMatch); - virReportOOMError(); - return -1; - } - - if (virBufferUse(&afterStateMatch)) { - char *s = virBufferContentAndReset(&afterStateMatch); - - virBufferAdd(&buf, s, -1); - - VIR_FREE(s); - } - - virBufferAsprintf(&buf, - " -j %s" CMD_DEF_POST CMD_SEPARATOR - CMD_EXEC, - target); - - if (virBufferError(&buf) || virBufferError(&prefix)) { - virBufferFreeAndReset(&buf); - virBufferFreeAndReset(&prefix); - virReportOOMError(); - return -1; - } - - if (virBufferUse(&prefix)) { - char *s = virBufferContentAndReset(&buf); - - virBufferAdd(&prefix, s, -1); - - VIR_FREE(s); - - final = &prefix; - - if (virBufferError(&prefix)) { - virBufferFreeAndReset(&prefix); - virReportOOMError(); - return -1; - } - } else - final = &buf; - - - template = virBufferContentAndReset(final); - if (VIR_APPEND_ELEMENT(*templates, *ntemplates, template) < 0) { - VIR_FREE(template); - return -1; + if (match && !skipMatch) { + if (newMatchState) + virFirewallRuleAddArgList(fw, fwrule, + "-m", "conntrack", + "--ctstate", match, + NULL); + else + virFirewallRuleAddArgList(fw, fwrule, + "-m", "state", + "--state", match, + NULL); } - return 0; - - err_exit: - virBufferFreeAndReset(&buf); - virBufferFreeAndReset(&prefix); - virBufferFreeAndReset(&afterStateMatch); + if (defMatch && match != NULL && !skipMatch && !hasICMPType) + iptablesEnforceDirection(fw, fwrule, + directionIn, + rule); - return -1; + if (iptablesHandleIpHdrAfterStateMatch(fw, fwrule, + vars, + &rule->p.allHdrFilter.ipHdr, + directionIn) < 0) + goto cleanup; - exit_no_error: - virBufferFreeAndReset(&buf); - virBufferFreeAndReset(&prefix); - virBufferFreeAndReset(&afterStateMatch); + virFirewallRuleAddArgList(fw, fwrule, + "-j", target, NULL); - return 0; + ret = 0; + cleanup: + return ret; } @@ -1841,7 +1576,7 @@ printStateMatchFlags(int32_t flags, char **bufptr) { virBuffer buf = VIR_BUFFER_INITIALIZER; virNWFilterPrintStateMatchFlags(&buf, - "-m state --state ", + "", flags, false); if (virBufferError(&buf)) { @@ -1854,12 +1589,11 @@ printStateMatchFlags(int32_t flags, char **bufptr) } static int -iptablesCreateRuleInstanceStateCtrl(virNWFilterRuleDefPtr rule, +iptablesCreateRuleInstanceStateCtrl(virFirewallPtr fw, + virFirewallLayer layer, + virNWFilterRuleDefPtr rule, const char *ifname, - virNWFilterVarCombIterPtr vars, - bool isIPv6, - char ***templates, - size_t *ntemplates) + virNWFilterVarCombIterPtr vars) { int rc; bool directionIn = false; @@ -1893,17 +1627,16 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterRuleDefPtr rule, chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP; if (create) { - rc = _iptablesCreateRuleInstance(directionIn, + rc = _iptablesCreateRuleInstance(fw, + layer, + directionIn, chainPrefix, rule, ifname, vars, matchState, false, "RETURN", - isIPv6, - maySkipICMP, - templates, - ntemplates); + maySkipICMP); VIR_FREE(matchState); if (rc < 0) @@ -1925,17 +1658,16 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterRuleDefPtr rule, chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP; if (create) { - rc = _iptablesCreateRuleInstance(!directionIn, + rc = _iptablesCreateRuleInstance(fw, + layer, + !directionIn, chainPrefix, rule, ifname, vars, matchState, false, "ACCEPT", - isIPv6, - maySkipICMP, - templates, - ntemplates); + maySkipICMP); VIR_FREE(matchState); @@ -1960,17 +1692,16 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterRuleDefPtr rule, if (create) { chainPrefix[0] = 'H'; chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP; - rc = _iptablesCreateRuleInstance(directionIn, + rc = _iptablesCreateRuleInstance(fw, + layer, + directionIn, chainPrefix, rule, ifname, vars, matchState, false, "RETURN", - isIPv6, - maySkipICMP, - templates, - ntemplates); + maySkipICMP); VIR_FREE(matchState); } @@ -1979,12 +1710,11 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterRuleDefPtr rule, static int -iptablesCreateRuleInstance(virNWFilterRuleDefPtr rule, +iptablesCreateRuleInstance(virFirewallPtr fw, + virFirewallLayer layer, + virNWFilterRuleDefPtr rule, const char *ifname, - virNWFilterVarCombIterPtr vars, - bool isIPv6, - char ***templates, - size_t *ntemplates) + virNWFilterVarCombIterPtr vars) { int rc; bool directionIn = false; @@ -1995,12 +1725,11 @@ iptablesCreateRuleInstance(virNWFilterRuleDefPtr rule, if (!(rule->flags & RULE_FLAG_NO_STATEMATCH) && (rule->flags & IPTABLES_STATE_FLAGS)) { - return iptablesCreateRuleInstanceStateCtrl(rule, + return iptablesCreateRuleInstanceStateCtrl(fw, + layer, + rule, ifname, - vars, - isIPv6, - templates, - ntemplates); + vars); } if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) || @@ -2019,66 +1748,63 @@ iptablesCreateRuleInstance(virNWFilterRuleDefPtr rule, maySkipICMP = directionIn || inout; if (needState) - matchState = directionIn ? MATCH_STATE_IN : MATCH_STATE_OUT; + matchState = directionIn ? "ESTABLISHED" : "NEW,ESTABLISHED"; else matchState = NULL; chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP; - rc = _iptablesCreateRuleInstance(directionIn, + rc = _iptablesCreateRuleInstance(fw, + layer, + directionIn, chainPrefix, rule, ifname, vars, matchState, true, "RETURN", - isIPv6, - maySkipICMP, - templates, - ntemplates); + maySkipICMP); if (rc < 0) return rc; maySkipICMP = !directionIn || inout; if (needState) - matchState = directionIn ? MATCH_STATE_OUT : MATCH_STATE_IN; + matchState = directionIn ? "NEW,ESTABLISHED" : "ESTABLISHED"; else matchState = NULL; chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP; - rc = _iptablesCreateRuleInstance(!directionIn, + rc = _iptablesCreateRuleInstance(fw, + layer, + !directionIn, chainPrefix, rule, ifname, vars, matchState, true, "ACCEPT", - isIPv6, - maySkipICMP, - templates, - ntemplates); + maySkipICMP); if (rc < 0) return rc; maySkipICMP = directionIn; if (needState) - matchState = directionIn ? MATCH_STATE_IN : MATCH_STATE_OUT; + matchState = directionIn ? "ESTABLISHED" : "NEW,ESTABLISHED"; else matchState = NULL; chainPrefix[0] = 'H'; chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP; - rc = _iptablesCreateRuleInstance(directionIn, + rc = _iptablesCreateRuleInstance(fw, + layer, + directionIn, chainPrefix, rule, ifname, vars, matchState, true, "RETURN", - isIPv6, - maySkipICMP, - templates, - ntemplates); + maySkipICMP); return rc; } @@ -2088,14 +1814,13 @@ iptablesCreateRuleInstance(virNWFilterRuleDefPtr rule, /* * ebtablesCreateRuleInstance: + * @fw: the firewall ruleset to add to * @chainPrefix : The prefix to put in front of the name of the chain * @chainSuffix: The suffix to put on the end of the name of the chain * @rule: The rule of the filter to convert * @ifname : The name of the interface to apply the rule to * @vars : A map containing the variables to resolve * @reverse : Whether to reverse src and dst attributes - * @templates: pointer to array to store rule template - * @ntemplates: pointer to storage rule template count * * Convert a single rule into its representation for later instantiation * @@ -2103,13 +1828,13 @@ iptablesCreateRuleInstance(virNWFilterRuleDefPtr rule, * pointed to by res, != 0 otherwise. */ static int -ebtablesCreateRuleInstance(char chainPrefix, +ebtablesCreateRuleInstance(virFirewallPtr fw, + char chainPrefix, const char *chainSuffix, virNWFilterRuleDefPtr rule, const char *ifname, virNWFilterVarCombIterPtr vars, - bool reverse, - char **template) + bool reverse) { char macaddr[VIR_MAC_STRING_BUFLEN], ipaddr[INET_ADDRSTRLEN], @@ -2117,20 +1842,15 @@ ebtablesCreateRuleInstance(char chainPrefix, ipv6addr[INET6_ADDRSTRLEN], number[MAX(INT_BUFSIZE_BOUND(uint32_t), INT_BUFSIZE_BOUND(int))], - field[MAX(VIR_MAC_STRING_BUFLEN, INET6_ADDRSTRLEN)]; + numberalt[MAX(INT_BUFSIZE_BOUND(uint32_t), + INT_BUFSIZE_BOUND(int))], + field[MAX(VIR_MAC_STRING_BUFLEN, INET6_ADDRSTRLEN)], + fieldalt[MAX(VIR_MAC_STRING_BUFLEN, INET6_ADDRSTRLEN)]; char chain[MAX_CHAINNAME_LENGTH]; - virBuffer buf = VIR_BUFFER_INITIALIZER; const char *target; bool hasMask = false; - - *template = NULL; - - if (!ebtables_cmd_path) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot create rule since ebtables tool is " - "missing.")); - goto err_exit; - } + virFirewallRulePtr fwrule; + int ret = -1; if (STREQ(chainSuffix, virNWFilterChainSuffixTypeToString( @@ -2140,89 +1860,85 @@ ebtablesCreateRuleInstance(char chainPrefix, PRINT_CHAIN(chain, chainPrefix, ifname, chainSuffix); +#define INST_ITEM(STRUCT, ITEM, CLI) \ + if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM)) { \ + if (printDataType(vars, \ + field, sizeof(field), \ + &rule->p.STRUCT.ITEM) < 0) \ + goto cleanup; \ + virFirewallRuleAddArg(fw, fwrule, CLI); \ + if (ENTRY_WANT_NEG_SIGN(&rule->p.STRUCT.ITEM)) \ + virFirewallRuleAddArg(fw, fwrule, "!"); \ + virFirewallRuleAddArg(fw, fwrule, field); \ + } + +#define INST_ITEM_2PARMS(STRUCT, ITEM, ITEM_HI, CLI, SEP) \ + if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM)) { \ + if (printDataType(vars, \ + field, sizeof(field), \ + &rule->p.STRUCT.ITEM) < 0) \ + goto cleanup; \ + virFirewallRuleAddArg(fw, fwrule, CLI); \ + if (ENTRY_WANT_NEG_SIGN(&rule->p.STRUCT.ITEM)) \ + virFirewallRuleAddArg(fw, fwrule, "!"); \ + if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM_HI)) { \ + if (printDataType(vars, \ + fieldalt, sizeof(fieldalt), \ + &rule->p.STRUCT.ITEM_HI) < 0) \ + goto cleanup; \ + virFirewallRuleAddArgFormat(fw, fwrule, \ + "%s%s%s", field, SEP, fieldalt); \ + } else { \ + virFirewallRuleAddArg(fw, fwrule, field); \ + } \ + } +#define INST_ITEM_RANGE(S, I, I_HI, C) \ + INST_ITEM_2PARMS(S, I, I_HI, C, ":") +#define INST_ITEM_MASK(S, I, MASK, C) \ + INST_ITEM_2PARMS(S, I, MASK, C, "/") switch (rule->prtclType) { case VIR_NWFILTER_RULE_PROTOCOL_MAC: + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", + "-A", chain, NULL); - virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -A %s", - chain); - - if (ebtablesHandleEthHdr(&buf, + if (ebtablesHandleEthHdr(fw, fwrule, vars, &rule->p.ethHdrFilter.ethHdr, reverse) < 0) - goto err_exit; + goto cleanup; if (HAS_ENTRY_ITEM(&rule->p.ethHdrFilter.dataProtocolID)) { if (printDataTypeAsHex(vars, number, sizeof(number), &rule->p.ethHdrFilter.dataProtocolID) < 0) - goto err_exit; - virBufferAsprintf(&buf, - " -p %s %s", - ENTRY_GET_NEG_SIGN(&rule->p.ethHdrFilter.dataProtocolID), - number); + goto cleanup; + virFirewallRuleAddArg(fw, fwrule, "-p"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ethHdrFilter.dataProtocolID)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, number); } - break; + break; case VIR_NWFILTER_RULE_PROTOCOL_VLAN: + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, NULL); - virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -A %s", - chain); - - - if (ebtablesHandleEthHdr(&buf, + if (ebtablesHandleEthHdr(fw, fwrule, vars, &rule->p.vlanHdrFilter.ethHdr, reverse) < 0) - goto err_exit; + goto cleanup; - virBufferAddLit(&buf, - " -p 0x8100"); - -#define INST_ITEM(STRUCT, ITEM, CLI) \ - if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM)) { \ - if (printDataType(vars, \ - field, sizeof(field), \ - &rule->p.STRUCT.ITEM) < 0) \ - goto err_exit; \ - virBufferAsprintf(&buf, \ - " " CLI " %s %s", \ - ENTRY_GET_NEG_SIGN(&rule->p.STRUCT.ITEM), \ - field); \ - } - -#define INST_ITEM_2PARMS(STRUCT, ITEM, ITEM_HI, CLI, SEP) \ - if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM)) { \ - if (printDataType(vars, \ - field, sizeof(field), \ - &rule->p.STRUCT.ITEM) < 0) \ - goto err_exit; \ - virBufferAsprintf(&buf, \ - " " CLI " %s %s", \ - ENTRY_GET_NEG_SIGN(&rule->p.STRUCT.ITEM), \ - field); \ - if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM_HI)) { \ - if (printDataType(vars, \ - field, sizeof(field), \ - &rule->p.STRUCT.ITEM_HI) < 0) \ - goto err_exit; \ - virBufferAsprintf(&buf, SEP "%s", field); \ - } \ - } -#define INST_ITEM_RANGE(S, I, I_HI, C) \ - INST_ITEM_2PARMS(S, I, I_HI, C, ":") -#define INST_ITEM_MASK(S, I, MASK, C) \ - INST_ITEM_2PARMS(S, I, MASK, C, "/") + virFirewallRuleAddArgList(fw, fwrule, + "-p", "0x8100", NULL); INST_ITEM(vlanHdrFilter, dataVlanID, "--vlan-id") INST_ITEM(vlanHdrFilter, dataVlanEncap, "--vlan-encap") - break; + break; case VIR_NWFILTER_RULE_PROTOCOL_STP: - /* cannot handle inout direction with srcmask set in reverse dir. since this clashes with -d below... */ if (reverse && @@ -2235,18 +1951,17 @@ ebtablesCreateRuleInstance(char chainPrefix, return -1; } - virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -A %s", - chain); - + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, NULL); - if (ebtablesHandleEthHdr(&buf, + if (ebtablesHandleEthHdr(fw, fwrule, vars, &rule->p.stpHdrFilter.ethHdr, reverse) < 0) - goto err_exit; + goto cleanup; - virBufferAddLit(&buf, " -d " NWFILTER_MAC_BGA); + virFirewallRuleAddArgList(fw, fwrule, + "-d", NWFILTER_MAC_BGA, NULL); INST_ITEM(stpHdrFilter, dataType, "--stp-type") INST_ITEM(stpHdrFilter, dataFlags, "--stp-flags") @@ -2268,172 +1983,169 @@ ebtablesCreateRuleInstance(char chainPrefix, "--stp-hello-time"); INST_ITEM_RANGE(stpHdrFilter, dataFwdDelay, dataFwdDelayHi, "--stp-forward-delay"); - break; + break; case VIR_NWFILTER_RULE_PROTOCOL_ARP: case VIR_NWFILTER_RULE_PROTOCOL_RARP: + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, NULL); - virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -A %s", - chain); - - if (ebtablesHandleEthHdr(&buf, + if (ebtablesHandleEthHdr(fw, fwrule, vars, &rule->p.arpHdrFilter.ethHdr, reverse) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, " -p 0x%x", - (rule->prtclType == VIR_NWFILTER_RULE_PROTOCOL_ARP) - ? l3_protocols[L3_PROTO_ARP_IDX].attr - : l3_protocols[L3_PROTO_RARP_IDX].attr); + virFirewallRuleAddArg(fw, fwrule, "-p"); + virFirewallRuleAddArgFormat(fw, fwrule, "0x%x", + (rule->prtclType == VIR_NWFILTER_RULE_PROTOCOL_ARP) + ? l3_protocols[L3_PROTO_ARP_IDX].attr + : l3_protocols[L3_PROTO_RARP_IDX].attr); if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataHWType)) { - if (printDataType(vars, - number, sizeof(number), - &rule->p.arpHdrFilter.dataHWType) < 0) - goto err_exit; - virBufferAsprintf(&buf, - " --arp-htype %s %s", - ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataHWType), - number); + if (printDataType(vars, + number, sizeof(number), + &rule->p.arpHdrFilter.dataHWType) < 0) + goto cleanup; + virFirewallRuleAddArg(fw, fwrule, "--arp-htype"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.arpHdrFilter.dataHWType)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, number); } if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataOpcode)) { if (printDataType(vars, number, sizeof(number), &rule->p.arpHdrFilter.dataOpcode) < 0) - goto err_exit; - virBufferAsprintf(&buf, - " --arp-opcode %s %s", - ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataOpcode), - number); + goto cleanup; + virFirewallRuleAddArg(fw, fwrule, "--arp-opcode"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.arpHdrFilter.dataOpcode)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, number); } if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataProtocolType)) { if (printDataTypeAsHex(vars, number, sizeof(number), &rule->p.arpHdrFilter.dataProtocolType) < 0) - goto err_exit; - virBufferAsprintf(&buf, - " --arp-ptype %s %s", - ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataProtocolType), - number); + goto cleanup; + virFirewallRuleAddArg(fw, fwrule, "--arp-ptype"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.arpHdrFilter.dataProtocolType)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, number); } if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataARPSrcIPAddr)) { if (printDataType(vars, ipaddr, sizeof(ipaddr), &rule->p.arpHdrFilter.dataARPSrcIPAddr) < 0) - goto err_exit; + goto cleanup; if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataARPSrcIPMask)) { if (printDataType(vars, ipmask, sizeof(ipmask), &rule->p.arpHdrFilter.dataARPSrcIPMask) < 0) - goto err_exit; + goto cleanup; hasMask = true; } - virBufferAsprintf(&buf, - " %s %s %s/%s", - reverse ? "--arp-ip-dst" : "--arp-ip-src", - ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataARPSrcIPAddr), - ipaddr, - hasMask ? ipmask : "32"); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--arp-ip-dst" : "--arp-ip-src"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.arpHdrFilter.dataARPSrcIPAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", ipaddr, hasMask ? ipmask : "32"); } if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataARPDstIPAddr)) { if (printDataType(vars, ipaddr, sizeof(ipaddr), &rule->p.arpHdrFilter.dataARPDstIPAddr) < 0) - goto err_exit; + goto cleanup; if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataARPDstIPMask)) { if (printDataType(vars, ipmask, sizeof(ipmask), &rule->p.arpHdrFilter.dataARPDstIPMask) < 0) - goto err_exit; + goto cleanup; hasMask = true; } - virBufferAsprintf(&buf, - " %s %s %s/%s", - reverse ? "--arp-ip-src" : "--arp-ip-dst", - ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataARPDstIPAddr), - ipaddr, - hasMask ? ipmask : "32"); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--arp-ip-src" : "--arp-ip-dst"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.arpHdrFilter.dataARPDstIPAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", ipaddr, hasMask ? ipmask : "32"); } if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataARPSrcMACAddr)) { if (printDataType(vars, macaddr, sizeof(macaddr), &rule->p.arpHdrFilter.dataARPSrcMACAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--arp-mac-dst" : "--arp-mac-src", - ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataARPSrcMACAddr), - macaddr); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--arp-mac-dst" : "--arp-mac-src"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.arpHdrFilter.dataARPSrcMACAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, macaddr); } if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataARPDstMACAddr)) { if (printDataType(vars, macaddr, sizeof(macaddr), &rule->p.arpHdrFilter.dataARPDstMACAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--arp-mac-src" : "--arp-mac-dst", - ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataARPDstMACAddr), - macaddr); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--arp-mac-src" : "--arp-mac-dst"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.arpHdrFilter.dataARPDstMACAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, macaddr); } if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataGratuitousARP) && rule->p.arpHdrFilter.dataGratuitousARP.u.boolean) { - virBufferAsprintf(&buf, - " %s --arp-gratuitous", - ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataGratuitousARP)); + if (ENTRY_WANT_NEG_SIGN(&rule->p.arpHdrFilter.dataGratuitousARP)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, "--arp-gratuitous"); } - break; + break; case VIR_NWFILTER_RULE_PROTOCOL_IP: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -A %s", - chain); + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, NULL); - if (ebtablesHandleEthHdr(&buf, + if (ebtablesHandleEthHdr(fw, fwrule, vars, &rule->p.ipHdrFilter.ethHdr, reverse) < 0) - goto err_exit; + goto cleanup; - virBufferAddLit(&buf, - " -p ipv4"); + virFirewallRuleAddArgList(fw, fwrule, + "-p", "ipv4", NULL); if (HAS_ENTRY_ITEM(&rule->p.ipHdrFilter.ipHdr.dataSrcIPAddr)) { if (printDataType(vars, ipaddr, sizeof(ipaddr), &rule->p.ipHdrFilter.ipHdr.dataSrcIPAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--ip-destination" : "--ip-source", - ENTRY_GET_NEG_SIGN(&rule->p.ipHdrFilter.ipHdr.dataSrcIPAddr), - ipaddr); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--ip-destination" : "--ip-source"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipHdrFilter.ipHdr.dataSrcIPAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(&rule->p.ipHdrFilter.ipHdr.dataSrcIPMask)) { if (printDataType(vars, number, sizeof(number), - &rule->p.ipHdrFilter.ipHdr.dataSrcIPMask) - < 0) - goto err_exit; - virBufferAsprintf(&buf, - "/%s", - number); + &rule->p.ipHdrFilter.ipHdr.dataSrcIPMask) < 0) + goto cleanup; + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", ipaddr, number); + } else { + virFirewallRuleAddArg(fw, fwrule, ipaddr); } } @@ -2442,23 +2154,22 @@ ebtablesCreateRuleInstance(char chainPrefix, if (printDataType(vars, ipaddr, sizeof(ipaddr), &rule->p.ipHdrFilter.ipHdr.dataDstIPAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--ip-source" : "--ip-destination", - ENTRY_GET_NEG_SIGN(&rule->p.ipHdrFilter.ipHdr.dataDstIPAddr), - ipaddr); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--ip-source" : "--ip-destination"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipHdrFilter.ipHdr.dataDstIPAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(&rule->p.ipHdrFilter.ipHdr.dataDstIPMask)) { if (printDataType(vars, number, sizeof(number), - &rule->p.ipHdrFilter.ipHdr.dataDstIPMask) - < 0) - goto err_exit; - virBufferAsprintf(&buf, - "/%s", - number); + &rule->p.ipHdrFilter.ipHdr.dataDstIPMask) < 0) + goto cleanup; + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", ipaddr, number); + } else { + virFirewallRuleAddArg(fw, fwrule, ipaddr); } } @@ -2466,65 +2177,59 @@ ebtablesCreateRuleInstance(char chainPrefix, if (printDataType(vars, number, sizeof(number), &rule->p.ipHdrFilter.ipHdr.dataProtocolID) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " --ip-protocol %s %s", - ENTRY_GET_NEG_SIGN(&rule->p.ipHdrFilter.ipHdr.dataProtocolID), - number); + virFirewallRuleAddArg(fw, fwrule, "--ip-protocol"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipHdrFilter.ipHdr.dataProtocolID)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, number); } if (HAS_ENTRY_ITEM(&rule->p.ipHdrFilter.portData.dataSrcPortStart)) { - if (printDataType(vars, number, sizeof(number), - &rule->p.ipHdrFilter.portData.dataSrcPortStart) - < 0) - goto err_exit; + &rule->p.ipHdrFilter.portData.dataSrcPortStart) < 0) + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--ip-destination-port" : "--ip-source-port", - ENTRY_GET_NEG_SIGN(&rule->p.ipHdrFilter.portData.dataSrcPortStart), - number); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--ip-destination-port" : "--ip-source-port"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipHdrFilter.portData.dataSrcPortStart)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(&rule->p.ipHdrFilter.portData.dataSrcPortEnd)) { if (printDataType(vars, - number, sizeof(number), - &rule->p.ipHdrFilter.portData.dataSrcPortEnd) - < 0) - goto err_exit; + numberalt, sizeof(numberalt), + &rule->p.ipHdrFilter.portData.dataSrcPortEnd) < 0) + goto cleanup; - virBufferAsprintf(&buf, - ":%s", - number); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s:%s", number, numberalt); + } else { + virFirewallRuleAddArg(fw, fwrule, number); } } if (HAS_ENTRY_ITEM(&rule->p.ipHdrFilter.portData.dataDstPortStart)) { - if (printDataType(vars, number, sizeof(number), - &rule->p.ipHdrFilter.portData.dataDstPortStart) - < 0) - goto err_exit; + &rule->p.ipHdrFilter.portData.dataDstPortStart) < 0) + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--ip-source-port" : "--ip-destination-port", - ENTRY_GET_NEG_SIGN(&rule->p.ipHdrFilter.portData.dataDstPortStart), - number); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--ip-source-port" : "--ip-destination-port"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipHdrFilter.portData.dataDstPortStart)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(&rule->p.ipHdrFilter.portData.dataDstPortEnd)) { if (printDataType(vars, - number, sizeof(number), - &rule->p.ipHdrFilter.portData.dataDstPortEnd) - < 0) - goto err_exit; - - virBufferAsprintf(&buf, - ":%s", - number); + numberalt, sizeof(numberalt), + &rule->p.ipHdrFilter.portData.dataDstPortEnd) < 0) + goto cleanup; + + virFirewallRuleAddArgFormat(fw, fwrule, + "%s:%s", number, numberalt); + } else { + virFirewallRuleAddArg(fw, fwrule, number); } } @@ -2532,50 +2237,48 @@ ebtablesCreateRuleInstance(char chainPrefix, if (printDataTypeAsHex(vars, number, sizeof(number), &rule->p.ipHdrFilter.ipHdr.dataDSCP) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " --ip-tos %s %s", - ENTRY_GET_NEG_SIGN(&rule->p.ipHdrFilter.ipHdr.dataDSCP), - number); + virFirewallRuleAddArg(fw, fwrule, "--ip-tos"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipHdrFilter.ipHdr.dataDSCP)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, number); } - break; + break; case VIR_NWFILTER_RULE_PROTOCOL_IPV6: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -A %s", - chain); + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, NULL); - if (ebtablesHandleEthHdr(&buf, + if (ebtablesHandleEthHdr(fw, fwrule, vars, &rule->p.ipv6HdrFilter.ethHdr, reverse) < 0) - goto err_exit; + goto cleanup; - virBufferAddLit(&buf, - " -p ipv6"); + virFirewallRuleAddArgList(fw, fwrule, + "-p", "ipv6", NULL); if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.ipHdr.dataSrcIPAddr)) { if (printDataType(vars, ipv6addr, sizeof(ipv6addr), &rule->p.ipv6HdrFilter.ipHdr.dataSrcIPAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--ip6-destination" : "--ip6-source", - ENTRY_GET_NEG_SIGN(&rule->p.ipv6HdrFilter.ipHdr.dataSrcIPAddr), - ipv6addr); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--ip6-destination" : "--ip6-source"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipv6HdrFilter.ipHdr.dataSrcIPAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.ipHdr.dataSrcIPMask)) { if (printDataType(vars, number, sizeof(number), - &rule->p.ipv6HdrFilter.ipHdr.dataSrcIPMask) - < 0) - goto err_exit; - virBufferAsprintf(&buf, - "/%s", - number); + &rule->p.ipv6HdrFilter.ipHdr.dataSrcIPMask) < 0) + goto cleanup; + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", ipv6addr, number); + } else { + virFirewallRuleAddArg(fw, fwrule, ipv6addr); } } @@ -2584,23 +2287,22 @@ ebtablesCreateRuleInstance(char chainPrefix, if (printDataType(vars, ipv6addr, sizeof(ipv6addr), &rule->p.ipv6HdrFilter.ipHdr.dataDstIPAddr) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--ip6-source" : "--ip6-destination", - ENTRY_GET_NEG_SIGN(&rule->p.ipv6HdrFilter.ipHdr.dataDstIPAddr), - ipv6addr); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--ip6-source" : "--ip6-destination"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipv6HdrFilter.ipHdr.dataDstIPAddr)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.ipHdr.dataDstIPMask)) { if (printDataType(vars, number, sizeof(number), - &rule->p.ipv6HdrFilter.ipHdr.dataDstIPMask) - < 0) - goto err_exit; - virBufferAsprintf(&buf, - "/%s", - number); + &rule->p.ipv6HdrFilter.ipHdr.dataDstIPMask) < 0) + goto cleanup; + virFirewallRuleAddArgFormat(fw, fwrule, + "%s/%s", ipv6addr, number); + } else { + virFirewallRuleAddArg(fw, fwrule, ipv6addr); } } @@ -2608,38 +2310,36 @@ ebtablesCreateRuleInstance(char chainPrefix, if (printDataType(vars, number, sizeof(number), &rule->p.ipv6HdrFilter.ipHdr.dataProtocolID) < 0) - goto err_exit; + goto cleanup; - virBufferAsprintf(&buf, - " --ip6-protocol %s %s", - ENTRY_GET_NEG_SIGN(&rule->p.ipv6HdrFilter.ipHdr.dataProtocolID), - number); + virFirewallRuleAddArg(fw, fwrule, "--ip6-protocol"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipv6HdrFilter.ipHdr.dataProtocolID)) + virFirewallRuleAddArg(fw, fwrule, "!"); + virFirewallRuleAddArg(fw, fwrule, number); } if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.portData.dataSrcPortStart)) { if (printDataType(vars, number, sizeof(number), - &rule->p.ipv6HdrFilter.portData.dataSrcPortStart) - < 0) - goto err_exit; + &rule->p.ipv6HdrFilter.portData.dataSrcPortStart) < 0) + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--ip6-destination-port" : "--ip6-source-port", - ENTRY_GET_NEG_SIGN(&rule->p.ipv6HdrFilter.portData.dataSrcPortStart), - number); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--ip6-destination-port" : "--ip6-source-port"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipv6HdrFilter.portData.dataSrcPortStart)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.portData.dataSrcPortEnd)) { if (printDataType(vars, - number, sizeof(number), - &rule->p.ipv6HdrFilter.portData.dataSrcPortEnd) - < 0) - goto err_exit; + numberalt, sizeof(numberalt), + &rule->p.ipv6HdrFilter.portData.dataSrcPortEnd) < 0) + goto cleanup; - virBufferAsprintf(&buf, - ":%s", - number); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s:%s", number, numberalt); + } else { + virFirewallRuleAddArg(fw, fwrule, number); } } @@ -2647,37 +2347,37 @@ ebtablesCreateRuleInstance(char chainPrefix, if (printDataType(vars, number, sizeof(number), - &rule->p.ipv6HdrFilter.portData.dataDstPortStart) - < 0) - goto err_exit; + &rule->p.ipv6HdrFilter.portData.dataDstPortStart) < 0) + goto cleanup; - virBufferAsprintf(&buf, - " %s %s %s", - reverse ? "--ip6-source-port" : "--ip6-destination-port", - ENTRY_GET_NEG_SIGN(&rule->p.ipv6HdrFilter.portData.dataDstPortStart), - number); + virFirewallRuleAddArg(fw, fwrule, + reverse ? "--ip6-source-port" : "--ip6-destination-port"); + if (ENTRY_WANT_NEG_SIGN(&rule->p.ipv6HdrFilter.portData.dataDstPortStart)) + virFirewallRuleAddArg(fw, fwrule, "!"); if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.portData.dataDstPortEnd)) { if (printDataType(vars, - number, sizeof(number), - &rule->p.ipv6HdrFilter.portData.dataDstPortEnd) - < 0) - goto err_exit; + numberalt, sizeof(numberalt), + &rule->p.ipv6HdrFilter.portData.dataDstPortEnd) < 0) + goto cleanup; - virBufferAsprintf(&buf, - ":%s", - number); + virFirewallRuleAddArgFormat(fw, fwrule, + "%s:%s", number, numberalt); + } else { + virFirewallRuleAddArg(fw, fwrule, number); } } - break; + break; case VIR_NWFILTER_RULE_PROTOCOL_NONE: - virBufferAsprintf(&buf, - CMD_DEF_PRE "$EBT -t nat -A %s", - chain); - break; + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", chain, NULL); + break; default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected rule protocol %d"), + rule->prtclType); return -1; } @@ -2686,29 +2386,22 @@ ebtablesCreateRuleInstance(char chainPrefix, /* REJECT not supported */ target = virNWFilterJumpTargetTypeToString( VIR_NWFILTER_RULE_ACTION_DROP); - break; + break; default: target = virNWFilterJumpTargetTypeToString(rule->action); } - virBufferAsprintf(&buf, - " -j %s" CMD_DEF_POST CMD_SEPARATOR - CMD_EXEC, - target); - - if (virBufferError(&buf)) { - virBufferFreeAndReset(&buf); - virReportOOMError(); - return -1; - } - - *template = virBufferContentAndReset(&buf); - return 0; + virFirewallRuleAddArgList(fw, fwrule, + "-j", target, NULL); - err_exit: - virBufferFreeAndReset(&buf); +#undef INST_ITEM_RANGE +#undef INST_ITEM_MASK +#undef INST_ITEM_2PARMS +#undef INST_ITEM - return -1; + ret = 0; + cleanup: + return ret; } @@ -2727,84 +2420,61 @@ ebtablesCreateRuleInstance(char chainPrefix, * pointed to by res, -1 otherwise */ static int -ebiptablesCreateRuleInstance(const char *chainSuffix, +ebiptablesCreateRuleInstance(virFirewallPtr fw, + const char *chainSuffix, virNWFilterRuleDefPtr rule, const char *ifname, - virNWFilterVarCombIterPtr vars, - char ***templates, - size_t *ntemplates) + virNWFilterVarCombIterPtr vars) { - size_t i; - - *templates = NULL; - *ntemplates = 0; + int ret = -1; if (virNWFilterRuleIsProtocolEthernet(rule)) { if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { - char *template; - if (ebtablesCreateRuleInstance(CHAINPREFIX_HOST_IN_TEMP, + if (ebtablesCreateRuleInstance(fw, + CHAINPREFIX_HOST_IN_TEMP, chainSuffix, rule, ifname, vars, - rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT, - &template) < 0) - goto error; - - if (VIR_APPEND_ELEMENT(*templates, *ntemplates, template) < 0) { - VIR_FREE(template); - goto error; - } + rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) < 0) + goto cleanup; } if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN || rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { - char *template; - if (ebtablesCreateRuleInstance(CHAINPREFIX_HOST_OUT_TEMP, + if (ebtablesCreateRuleInstance(fw, + CHAINPREFIX_HOST_OUT_TEMP, chainSuffix, rule, ifname, vars, - false, - &template) < 0) - goto error; - - if (VIR_APPEND_ELEMENT(*templates, *ntemplates, template) < 0) { - VIR_FREE(template); - goto error; - } + false) < 0) + goto cleanup; } } else { - bool isIPv6; + virFirewallLayer layer; if (virNWFilterRuleIsProtocolIPv6(rule)) { - isIPv6 = true; + layer = VIR_FIREWALL_LAYER_IPV6; } else if (virNWFilterRuleIsProtocolIPv4(rule)) { - isIPv6 = false; + layer = VIR_FIREWALL_LAYER_IPV4; } else { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("unexpected protocol type")); - goto error; + goto cleanup; } - if (iptablesCreateRuleInstance(rule, + if (iptablesCreateRuleInstance(fw, + layer, + rule, ifname, - vars, - isIPv6, - templates, - ntemplates) < 0) - goto error; + vars) < 0) + goto cleanup; } - return 0; - - error: - for (i = 0; i < *ntemplates; i++) - VIR_FREE((*templates)[i]); - VIR_FREE(*templates); - *templates = NULL; - *ntemplates = 0; - return -1; + ret = 0; + cleanup: + return ret; } @@ -2839,6 +2509,7 @@ ebiptablesExecCLI(virBufferPtr buf, bool ignoreNonzero, char **outbuf) if (outbuf) VIR_FREE(*outbuf); + VIR_INFO("Run [%s]", virBufferCurrentContent(buf)); cmd = virCommandNewArgList("/bin/sh", "-c", NULL); virCommandAddArgBuffer(cmd, buf); if (outbuf) @@ -2857,26 +2528,6 @@ ebiptablesExecCLI(virBufferPtr buf, bool ignoreNonzero, char **outbuf) static void -ebtablesCreateTmpRootChain(virBufferPtr buf, - bool incoming, const char *ifname) -{ - char chain[MAX_CHAINNAME_LENGTH]; - char chainPrefix = incoming ? CHAINPREFIX_HOST_IN_TEMP - : CHAINPREFIX_HOST_OUT_TEMP; - - PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); - - virBufferAsprintf(buf, - CMD_DEF("$EBT -t nat -N %s") CMD_SEPARATOR - CMD_EXEC - "%s", - chain, - CMD_STOPONERR(true)); - -} - - -static void ebtablesCreateTmpRootChainFW(virFirewallPtr fw, int incoming, const char *ifname) { @@ -2892,29 +2543,6 @@ ebtablesCreateTmpRootChainFW(virFirewallPtr fw, static void -ebtablesLinkTmpRootChain(virBufferPtr buf, - bool incoming, const char *ifname) -{ - char chain[MAX_CHAINNAME_LENGTH]; - char chainPrefix = incoming ? CHAINPREFIX_HOST_IN_TEMP - : CHAINPREFIX_HOST_OUT_TEMP; - char iodev = incoming ? 'i' : 'o'; - - PRINT_ROOT_CHAIN(chain, chainPrefix, ifname); - - virBufferAsprintf(buf, - CMD_DEF("$EBT -t nat -A %s -%c %s -j %s") CMD_SEPARATOR - CMD_EXEC - "%s", - incoming ? EBTABLES_CHAIN_INCOMING - : EBTABLES_CHAIN_OUTGOING, - iodev, ifname, chain, - - CMD_STOPONERR(true)); -} - - -static void ebtablesLinkTmpRootChainFW(virFirewallPtr fw, int incoming, const char *ifname) { @@ -2933,30 +2561,6 @@ ebtablesLinkTmpRootChainFW(virFirewallPtr fw, static void -_ebtablesRemoveRootChain(virBufferPtr buf, - bool incoming, const char *ifname, - bool 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); - - virBufferAsprintf(buf, - "$EBT -t nat -F %s" CMD_SEPARATOR - "$EBT -t nat -X %s" CMD_SEPARATOR, - chain, - chain); -} - - -static void _ebtablesRemoveRootChainFW(virFirewallPtr fw, bool incoming, const char *ifname, int isTempChain) @@ -2988,14 +2592,6 @@ ebtablesRemoveRootChainFW(virFirewallPtr fw, static void -ebtablesRemoveTmpRootChain(virBufferPtr buf, - bool incoming, const char *ifname) -{ - _ebtablesRemoveRootChain(buf, incoming, ifname, true); -} - - -static void ebtablesRemoveTmpRootChainFW(virFirewallPtr fw, bool incoming, const char *ifname) { @@ -3004,33 +2600,6 @@ ebtablesRemoveTmpRootChainFW(virFirewallPtr fw, static void -_ebtablesUnlinkRootChain(virBufferPtr buf, - bool incoming, const char *ifname, - bool isTempChain) -{ - char chain[MAX_CHAINNAME_LENGTH]; - char iodev = incoming ? 'i' : 'o'; - 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); - - virBufferAsprintf(buf, - "$EBT -t nat -D %s -%c %s -j %s" CMD_SEPARATOR, - incoming ? EBTABLES_CHAIN_INCOMING - : EBTABLES_CHAIN_OUTGOING, - iodev, ifname, chain); -} - - -static void _ebtablesUnlinkRootChainFW(virFirewallPtr fw, bool incoming, const char *ifname, int isTempChain) @@ -3064,132 +2633,58 @@ ebtablesUnlinkRootChainFW(virFirewallPtr fw, } -static void -ebtablesUnlinkTmpRootChain(virBufferPtr buf, - bool incoming, const char *ifname) -{ - _ebtablesUnlinkRootChain(buf, incoming, ifname, true); -} - - -static void -ebtablesUnlinkTmpRootChainFW(virFirewallPtr fw, - int incoming, const char *ifname) -{ - _ebtablesUnlinkRootChainFW(fw, incoming, ifname, 1); -} - - -static int -ebtablesCreateTmpSubChain(ebiptablesRuleInstPtr *inst, - int *nRuleInstances, - bool incoming, - const char *ifname, - enum l3_proto_idx protoidx, - const char *filtername, - virNWFilterChainPriority priority) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; - ebiptablesRuleInstPtr tmp = *inst; - size_t count = *nRuleInstances; - char rootchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH]; - char chainPrefix = incoming ? CHAINPREFIX_HOST_IN_TEMP - : CHAINPREFIX_HOST_OUT_TEMP; - char *protostr = NULL; - - PRINT_ROOT_CHAIN(rootchain, chainPrefix, ifname); - PRINT_CHAIN(chain, chainPrefix, ifname, - (filtername) ? filtername : l3_protocols[protoidx].val); - - switch (protoidx) { - case L2_PROTO_MAC_IDX: - ignore_value(VIR_STRDUP(protostr, "")); - break; - case L2_PROTO_STP_IDX: - ignore_value(VIR_STRDUP(protostr, "-d " NWFILTER_MAC_BGA " ")); - break; - default: - ignore_value(virAsprintf(&protostr, "-p 0x%04x ", - l3_protocols[protoidx].attr)); - break; - } - - if (!protostr) - return -1; - - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -F %s") CMD_SEPARATOR - CMD_EXEC - CMD_DEF("$EBT -t nat -X %s") CMD_SEPARATOR - CMD_EXEC - CMD_DEF("$EBT -t nat -N %s") CMD_SEPARATOR - CMD_EXEC - "%s" - CMD_DEF("$EBT -t nat -A %s %s-j %s") - CMD_SEPARATOR - CMD_EXEC - "%s", - - chain, - chain, - chain, - - CMD_STOPONERR(true), - - rootchain, protostr, chain, - - CMD_STOPONERR(true)); - - VIR_FREE(protostr); - - if (virBufferError(&buf) || - VIR_EXPAND_N(tmp, count, 1) < 0) { - virReportOOMError(); - virBufferFreeAndReset(&buf); - return -1; - } - - *nRuleInstances = count; - *inst = tmp; - - tmp[*nRuleInstances - 1].priority = priority; - tmp[*nRuleInstances - 1].commandTemplate = - virBufferContentAndReset(&buf); - tmp[*nRuleInstances - 1].neededProtocolChain = - virNWFilterChainSuffixTypeToString(VIR_NWFILTER_CHAINSUFFIX_ROOT); - - return 0; +static void +ebtablesUnlinkTmpRootChainFW(virFirewallPtr fw, + int incoming, const char *ifname) +{ + _ebtablesUnlinkRootChainFW(fw, incoming, ifname, 1); } static void -_ebtablesRemoveSubChains(virBufferPtr buf, - const char *ifname, - const char *chains) +ebtablesCreateTmpSubChainFW(virFirewallPtr fw, + bool incoming, + const char *ifname, + enum l3_proto_idx protoidx, + const char *filtername) { - char rootchain[MAX_CHAINNAME_LENGTH]; - size_t i; + char rootchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH]; + char chainPrefix = incoming ? CHAINPREFIX_HOST_IN_TEMP + : CHAINPREFIX_HOST_OUT_TEMP; + virFirewallRulePtr fwrule; + + PRINT_ROOT_CHAIN(rootchain, chainPrefix, ifname); + PRINT_CHAIN(chain, chainPrefix, ifname, + (filtername) ? filtername : l3_protocols[protoidx].val); - NWFILTER_SET_EBTABLES_SHELLVAR(buf); + 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); + virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-N", chain, NULL); - virBufferAsprintf(buf, NWFILTER_FUNC_COLLECT_CHAINS, - chains); - virBufferAdd(buf, NWFILTER_FUNC_RM_CHAINS, -1); + fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, + "-t", "nat", "-A", rootchain, NULL); - virBufferAsprintf(buf, NWFILTER_FUNC_SET_IFS); - virBufferAddLit(buf, "chains=\"$(collect_chains"); - for (i = 0; chains[i] != 0; i++) { - PRINT_ROOT_CHAIN(rootchain, chains[i], ifname); - virBufferAsprintf(buf, " %s", rootchain); + switch (protoidx) { + case L2_PROTO_MAC_IDX: + break; + case L2_PROTO_STP_IDX: + virFirewallRuleAddArgList(fw, fwrule, + "-d", NWFILTER_MAC_BGA, NULL); + break; + default: + virFirewallRuleAddArg(fw, fwrule, "-p"); + virFirewallRuleAddArgFormat(fw, fwrule, + "0x%04x", + l3_protocols[protoidx].attr); + break; } - virBufferAddLit(buf, ")\"\n"); - for (i = 0; chains[i] != 0; i++) { - PRINT_ROOT_CHAIN(rootchain, chains[i], ifname); - virBufferAsprintf(buf, - "$EBT -t nat -F %s\n", - rootchain); - } - virBufferAddLit(buf, "rm_chains $chains\n"); + virFirewallRuleAddArgList(fw, fwrule, + "-j", chain, NULL); } @@ -3257,18 +2752,6 @@ ebtablesRemoveSubChainsFW(virFirewallPtr fw, _ebtablesRemoveSubChainsFW(fw, ifname, chains); } -static void -ebtablesRemoveTmpSubChains(virBufferPtr buf, - const char *ifname) -{ - char chains[3] = { - CHAINPREFIX_HOST_IN_TEMP, - CHAINPREFIX_HOST_OUT_TEMP, - 0 - }; - - _ebtablesRemoveSubChains(buf, ifname, chains); -} static void ebtablesRemoveTmpSubChainsFW(virFirewallPtr fw, @@ -3381,15 +2864,6 @@ ebtablesRenameTmpSubAndRootChainsFW(virFirewallPtr fw, ebtablesRenameTmpRootChainFW(fw, false, ifname); } -static void -ebiptablesInstCommand(virBufferPtr buf, - const char *cmdstr) -{ - virBufferAdd(buf, cmdstr, -1); - virBufferAsprintf(buf, CMD_SEPARATOR "%s", - CMD_STOPONERR(true)); -} - /** * ebiptablesCanApplyBasicRules @@ -3691,33 +3165,6 @@ ebtablesCleanAll(const char *ifname) static int -ebiptablesRuleOrderSort(const void *a, const void *b) -{ - const ebiptablesRuleInst *insta = a; - const ebiptablesRuleInst *instb = b; - const char *root = virNWFilterChainSuffixTypeToString( - VIR_NWFILTER_CHAINSUFFIX_ROOT); - bool root_a = STREQ(insta->neededProtocolChain, root); - bool root_b = STREQ(instb->neededProtocolChain, root); - - /* ensure root chain commands appear before all others since - we will need them to create the child chains */ - if (root_a) { - if (root_b) { - goto normal; - } - return -1; /* a before b */ - } - if (root_b) { - return 1; /* b before a */ - } - normal: - /* priorities are limited to range [-1000, 1000] */ - return insta->priority - instb->priority; -} - - -static int virNWFilterRuleInstSort(const void *a, const void *b) { const virNWFilterRuleInst *insta = a; @@ -3752,6 +3199,7 @@ virNWFilterRuleInstSortPtr(const void *a, const void *b) return virNWFilterRuleInstSort(*insta, *instb); } + static int ebiptablesFilterOrderSort(const virHashKeyValuePair *a, const virHashKeyValuePair *b) @@ -3761,6 +3209,7 @@ ebiptablesFilterOrderSort(const virHashKeyValuePair *a, *(virNWFilterChainPriority *)b->value; } + static void iptablesCheckBridgeNFCallEnabled(bool isIPv6) { @@ -3817,54 +3266,13 @@ ebtablesGetProtoIdxByFiltername(const char *filtername) return -1; } -static int -ebtablesCreateTmpRootAndSubChains(virBufferPtr buf, - const char *ifname, - virHashTablePtr chains, - bool incoming, - ebiptablesRuleInstPtr *inst, - int *nRuleInstances) -{ - int rc = 0; - size_t i; - virHashKeyValuePairPtr filter_names; - const virNWFilterChainPriority *priority; - - ebtablesCreateTmpRootChain(buf, incoming, ifname); - - filter_names = virHashGetItems(chains, - ebiptablesFilterOrderSort); - if (filter_names == NULL) - return -1; - - for (i = 0; filter_names[i].key; i++) { - enum l3_proto_idx idx = ebtablesGetProtoIdxByFiltername( - filter_names[i].key); - if ((int)idx < 0) - continue; - priority = (const virNWFilterChainPriority *)filter_names[i].value; - rc = ebtablesCreateTmpSubChain(inst, nRuleInstances, - incoming, ifname, idx, - filter_names[i].key, - *priority); - if (rc < 0) - break; - } - - VIR_FREE(filter_names); - return rc; -} - static int -iptablesRuleInstCommand(virBufferPtr buf, +iptablesRuleInstCommand(virFirewallPtr fw, const char *ifname, virNWFilterRuleInstPtr rule) { virNWFilterVarCombIterPtr vciter, tmp; - char **cmds = NULL; - size_t ncmds = 0; - size_t i; int ret = -1; /* rule->vars holds all the variables names that this rule will access. @@ -3878,38 +3286,28 @@ iptablesRuleInstCommand(virBufferPtr buf, return -1; do { - if (ebiptablesCreateRuleInstance(rule->chainSuffix, + if (ebiptablesCreateRuleInstance(fw, + rule->chainSuffix, rule->def, ifname, - tmp, - &cmds, - &ncmds) < 0) + tmp) < 0) goto cleanup; tmp = virNWFilterVarCombIterNext(tmp); } while (tmp != NULL); - for (i = 0; i < ncmds; i++) - iptablesInstCommand(buf, cmds[i]); - ret = 0; cleanup: - for (i = 0; i < ncmds; i++) - VIR_FREE(cmds[i]); - VIR_FREE(cmds); virNWFilterVarCombIterFree(vciter); return ret; } static int -ebtablesRuleInstCommand(virBufferPtr buf, +ebtablesRuleInstCommand(virFirewallPtr fw, const char *ifname, virNWFilterRuleInstPtr rule) { virNWFilterVarCombIterPtr vciter, tmp; - char **cmds = NULL; - size_t ncmds = 0; - size_t i; int ret = -1; /* rule->vars holds all the variables names that this rule will access. @@ -3923,28 +3321,90 @@ ebtablesRuleInstCommand(virBufferPtr buf, return -1; do { - if (ebiptablesCreateRuleInstance(rule->chainSuffix, + if (ebiptablesCreateRuleInstance(fw, + rule->chainSuffix, rule->def, ifname, - tmp, - &cmds, - &ncmds) < 0) + tmp) < 0) goto cleanup; tmp = virNWFilterVarCombIterNext(tmp); } while (tmp != NULL); - for (i = 0; i < ncmds; i++) - ebiptablesInstCommand(buf, cmds[i]); - ret = 0; cleanup: - for (i = 0; i < ncmds; i++) - VIR_FREE(cmds[i]); - VIR_FREE(cmds); virNWFilterVarCombIterFree(vciter); return ret; } +struct ebtablesSubChainInst { + virNWFilterChainPriority priority; + bool incoming; + enum l3_proto_idx protoidx; + const char *filtername; +}; + + +static int +ebtablesSubChainInstSort(const void *a, const void *b) +{ + const struct ebtablesSubChainInst **insta = (const struct ebtablesSubChainInst **)a; + const struct ebtablesSubChainInst **instb = (const struct ebtablesSubChainInst **)b; + + /* priorities are limited to range [-1000, 1000] */ + return (*insta)->priority - (*instb)->priority; +} + + +static int +ebtablesGetSubChainInsts(virHashTablePtr chains, + bool incoming, + struct ebtablesSubChainInst ***insts, + size_t *ninsts) +{ + virHashKeyValuePairPtr filter_names; + size_t i; + int ret = -1; + + filter_names = virHashGetItems(chains, + ebiptablesFilterOrderSort); + if (filter_names == NULL) + return -1; + + for (i = 0; filter_names[i].key; i++) { + struct ebtablesSubChainInst *inst; + enum l3_proto_idx idx = ebtablesGetProtoIdxByFiltername( + filter_names[i].key); + + if ((int)idx < 0) + continue; + + if (VIR_ALLOC(inst) < 0) + goto cleanup; + inst->priority = *(const virNWFilterChainPriority *)filter_names[i].value; + inst->incoming = incoming; + inst->protoidx = idx; + inst->filtername = filter_names[i].key; + + if (VIR_APPEND_ELEMENT(*insts, *ninsts, inst) < 0) { + VIR_FREE(inst); + goto cleanup; + } + } + + ret = 0; + + cleanup: + VIR_FREE(filter_names); + if (ret < 0) { + for (i = 0; i < *ninsts; i++) { + VIR_FREE(*insts[i]); + } + VIR_FREE(*insts); + *ninsts = 0; + } + return ret; + +} static int ebiptablesApplyNewRules(const char *ifname, @@ -3952,74 +3412,33 @@ ebiptablesApplyNewRules(const char *ifname, size_t nrules) { size_t i, j; - virBuffer buf = VIR_BUFFER_INITIALIZER; + virFirewallPtr fw = virFirewallNew(); virHashTablePtr chains_in_set = virHashCreate(10, NULL); virHashTablePtr chains_out_set = virHashCreate(10, NULL); + bool haveEbtables = false; bool haveIptables = false; bool haveIp6tables = false; - ebiptablesRuleInstPtr ebtChains = NULL; - int nEbtChains = 0; char *errmsg = NULL; + struct ebtablesSubChainInst **subchains = NULL; + size_t nsubchains = 0; + int ret = -1; if (!chains_in_set || !chains_out_set) - goto exit_free_sets; + goto cleanup; if (nrules) qsort(rules, nrules, sizeof(rules[0]), virNWFilterRuleInstSortPtr); - /* scan the rules to see which chains need to be created */ - for (i = 0; i < nrules; i++) { - if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { - const char *name = rules[i]->chainSuffix; - if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || - rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { - if (virHashUpdateEntry(chains_in_set, name, - &rules[i]->chainPriority) < 0) - goto exit_free_sets; - } - if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_IN || - rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { - if (virHashUpdateEntry(chains_out_set, name, - &rules[i]->chainPriority) < 0) - goto exit_free_sets; - } - } - } - - /* cleanup whatever may exist */ - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); - - ebtablesUnlinkTmpRootChain(&buf, true, ifname); - ebtablesUnlinkTmpRootChain(&buf, false, ifname); - ebtablesRemoveTmpSubChains(&buf, ifname); - ebtablesRemoveTmpRootChain(&buf, true, ifname); - ebtablesRemoveTmpRootChain(&buf, false, ifname); - ebiptablesExecCLI(&buf, true, NULL); - } - - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); - - /* create needed chains */ - if ((virHashSize(chains_in_set) > 0 && - ebtablesCreateTmpRootAndSubChains(&buf, ifname, chains_in_set, true, - &ebtChains, &nEbtChains) < 0) || - (virHashSize(chains_out_set) > 0 && - ebtablesCreateTmpRootAndSubChains(&buf, ifname, chains_out_set, false, - &ebtChains, &nEbtChains) < 0)) { - goto tear_down_tmpebchains; - } - - if (nEbtChains > 0) - qsort(&ebtChains[0], nEbtChains, sizeof(ebtChains[0]), - ebiptablesRuleOrderSort); - - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpebchains; + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); + ebtablesUnlinkTmpRootChainFW(fw, true, ifname); + ebtablesUnlinkTmpRootChainFW(fw, false, ifname); + ebtablesRemoveTmpSubChainsFW(fw, ifname); + ebtablesRemoveTmpRootChainFW(fw, true, ifname); + ebtablesRemoveTmpRootChainFW(fw, false, ifname); - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + virFirewallStartTransaction(fw, 0); /* walk the list of rules and increase the priority * of rules in case the chain priority is of higher value; @@ -4038,188 +3457,173 @@ ebiptablesApplyNewRules(const char *ifname, } } - /* process ebtables commands; interleave commands from filters with - commands for creating and connecting ebtables chains */ - j = 0; for (i = 0; i < nrules; i++) { if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { - while (j < nEbtChains && - ebtChains[j].priority <= rules[i]->priority) { - ebiptablesInstCommand(&buf, - ebtChains[j++].commandTemplate); - } - ebtablesRuleInstCommand(&buf, - ifname, - rules[i]); + haveEbtables = true; } else { if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) haveIptables = true; - else if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + else if (virNWFilterRuleIsProtocolIPv6(rules[i]->def)) haveIp6tables = true; } } + /* process ebtables commands; interleave commands from filters with + commands for creating and connecting ebtables chains */ + if (haveEbtables) { - while (j < nEbtChains) - ebiptablesInstCommand(&buf, - ebtChains[j++].commandTemplate); + /* scan the rules to see which chains need to be created */ + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { + const char *name = rules[i]->chainSuffix; + if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || + rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { + if (virHashUpdateEntry(chains_in_set, name, + &rules[i]->chainPriority) < 0) + goto cleanup; + } + if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_IN || + rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { + if (virHashUpdateEntry(chains_out_set, name, + &rules[i]->chainPriority) < 0) + goto cleanup; + } + } + } - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpebchains; + /* create needed chains */ + if (virHashSize(chains_in_set) > 0) { + ebtablesCreateTmpRootChainFW(fw, true, ifname); + if (ebtablesGetSubChainInsts(chains_in_set, + true, + &subchains, + &nsubchains) < 0) + goto cleanup; + } + if (virHashSize(chains_out_set) > 0) { + ebtablesCreateTmpRootChainFW(fw, false, ifname); + if (ebtablesGetSubChainInsts(chains_out_set, + false, + &subchains, + &nsubchains) < 0) + goto cleanup; + } + + if (nsubchains > 0) + qsort(subchains, nsubchains, sizeof(subchains[0]), + ebtablesSubChainInstSort); + + for (i = 0, j = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { + while (j < nsubchains && + subchains[j]->priority <= rules[i]->priority) { + ebtablesCreateTmpSubChainFW(fw, + subchains[j]->incoming, + ifname, + subchains[j]->protoidx, + subchains[j]->filtername); + j++; + } + if (ebtablesRuleInstCommand(fw, + ifname, + rules[i]) < 0) + goto cleanup; + } + } + while (j < nsubchains) { + ebtablesCreateTmpSubChainFW(fw, + subchains[j]->incoming, + ifname, + subchains[j]->protoidx, + subchains[j]->filtername); + j++; + } + } if (haveIptables) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesUnlinkTmpRootChains(&buf, ifname); - iptablesRemoveTmpRootChains(&buf, ifname); - - iptablesCreateBaseChains(&buf); - - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpebchains; - - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); + iptablesUnlinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); - iptablesCreateTmpRootChains(&buf, ifname); + iptablesCreateBaseChainsFW(fw, VIR_FIREWALL_LAYER_IPV4); + iptablesCreateTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpiptchains; - - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesLinkTmpRootChains(&buf, ifname); - iptablesSetupVirtInPost(&buf, ifname); - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpiptchains; - - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); + iptablesLinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesSetupVirtInPostFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); for (i = 0; i < nrules; i++) { - if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) - iptablesRuleInstCommand(&buf, - ifname, - rules[i]); + if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) { + if (iptablesRuleInstCommand(fw, + ifname, + rules[i]) < 0) + goto cleanup; + } } - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpiptchains; - iptablesCheckBridgeNFCallEnabled(false); } if (haveIp6tables) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - - iptablesUnlinkTmpRootChains(&buf, ifname); - iptablesRemoveTmpRootChains(&buf, ifname); - - iptablesCreateBaseChains(&buf); - - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpiptchains; - - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - - iptablesCreateTmpRootChains(&buf, ifname); + iptablesUnlinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRemoveTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpip6tchains; + iptablesCreateBaseChainsFW(fw, VIR_FIREWALL_LAYER_IPV6); + iptablesCreateTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - - iptablesLinkTmpRootChains(&buf, ifname); - iptablesSetupVirtInPost(&buf, ifname); - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpip6tchains; - - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); + iptablesLinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesSetupVirtInPostFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); for (i = 0; i < nrules; i++) { - if (virNWFilterRuleIsProtocolIPv6(rules[i]->def)) - iptablesRuleInstCommand(&buf, - ifname, - rules[i]); + if (virNWFilterRuleIsProtocolIPv6(rules[i]->def)) { + if (iptablesRuleInstCommand(fw, + ifname, + rules[i]) < 0) + goto cleanup; + } } - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpip6tchains; - iptablesCheckBridgeNFCallEnabled(true); } - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); - if (virHashSize(chains_in_set) != 0) - ebtablesLinkTmpRootChain(&buf, true, ifname); + ebtablesLinkTmpRootChainFW(fw, true, ifname); if (virHashSize(chains_out_set) != 0) - ebtablesLinkTmpRootChain(&buf, false, ifname); - - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_ebsubchains_and_unlink; - - virHashFree(chains_in_set); - virHashFree(chains_out_set); - - for (i = 0; i < nEbtChains; i++) - VIR_FREE(ebtChains[i].commandTemplate); - VIR_FREE(ebtChains); - - VIR_FREE(errmsg); - - return 0; - - tear_down_ebsubchains_and_unlink: - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + ebtablesLinkTmpRootChainFW(fw, false, ifname); - ebtablesUnlinkTmpRootChain(&buf, true, ifname); - ebtablesUnlinkTmpRootChain(&buf, false, ifname); - } - - tear_down_tmpip6tchains: + virFirewallStartRollback(fw, 0); + ebtablesUnlinkTmpRootChainFW(fw, true, ifname); + ebtablesUnlinkTmpRootChainFW(fw, false, ifname); if (haveIp6tables) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - - iptablesUnlinkTmpRootChains(&buf, ifname); - iptablesRemoveTmpRootChains(&buf, ifname); + iptablesUnlinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); + iptablesRemoveTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV6, ifname); } - tear_down_tmpiptchains: if (haveIptables) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesUnlinkTmpRootChains(&buf, ifname); - iptablesRemoveTmpRootChains(&buf, ifname); + iptablesUnlinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); } - tear_down_tmpebchains: - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); + ebtablesRemoveTmpSubChainsFW(fw, ifname); + ebtablesRemoveTmpRootChainFW(fw, true, ifname); + ebtablesRemoveTmpRootChainFW(fw, false, ifname); - ebtablesRemoveTmpSubChains(&buf, ifname); - ebtablesRemoveTmpRootChain(&buf, true, ifname); - ebtablesRemoveTmpRootChain(&buf, false, ifname); + virMutexLock(&execCLIMutex); + if (virFirewallApply(fw) < 0) { + virMutexUnlock(&execCLIMutex); + goto cleanup; } + virMutexUnlock(&execCLIMutex); - ebiptablesExecCLI(&buf, true, NULL); - - virReportError(VIR_ERR_BUILD_FIREWALL, - _("Some rules could not be created for " - "interface %s%s%s"), - ifname, - errmsg ? ": " : "", - errmsg ? errmsg : ""); + ret = 0; - exit_free_sets: + cleanup: + for (i = 0; i < nsubchains; i++) + VIR_FREE(subchains[i]); + VIR_FREE(subchains); + virFirewallFree(fw); virHashFree(chains_in_set); virHashFree(chains_out_set); - for (i = 0; i < nEbtChains; i++) - VIR_FREE(ebtChains[i].commandTemplate); - VIR_FREE(ebtChains); - VIR_FREE(errmsg); - - return -1; + return ret; } @@ -4544,10 +3948,8 @@ ebiptablesDriverProbeStateMatch(void) * since version 1.4.16 '-m state --state ...' will be converted to * '-m conntrack --ctstate ...' */ - if (thisversion >= 1 * 1000000 + 4 * 1000 + 16) { - m_state_out_str = m_state_out_str_new; - m_state_in_str = m_state_in_str_new; - } + if (thisversion >= 1 * 1000000 + 4 * 1000 + 16) + newMatchState = true; cleanup: VIR_FREE(cmdout); diff --git a/src/nwfilter/nwfilter_ebiptables_driver.h b/src/nwfilter/nwfilter_ebiptables_driver.h index 8a17452..098d5dd 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.h +++ b/src/nwfilter/nwfilter_ebiptables_driver.h @@ -27,23 +27,6 @@ # define MAX_CHAINNAME_LENGTH 32 /* see linux/netfilter_bridge/ebtables.h */ -enum RuleType { - RT_EBTABLES, - RT_IPTABLES, - RT_IP6TABLES, -}; - -typedef struct _ebiptablesRuleInst ebiptablesRuleInst; -typedef ebiptablesRuleInst *ebiptablesRuleInstPtr; -struct _ebiptablesRuleInst { - char *commandTemplate; - const char *neededProtocolChain; - virNWFilterChainPriority chainPriority; - char chainprefix; /* I for incoming, O for outgoing */ - virNWFilterRulePriority priority; - enum RuleType ruleType; -}; - extern virNWFilterTechDriver ebiptables_driver; # define EBIPTABLES_DRIVER_ID "ebiptables" -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Convert the nwfilter ebtablesApplyNewRules method to use the virFirewall object APIs instead of creating shell scripts using virBuffer APIs. This provides a performance improvement through allowing direct use of firewalld dbus APIs and will facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> [...] @@ -679,8 +540,12 @@ _iptablesRemoveRootChainFW(virFirewallPtr fw,
PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
- virFirewallAddRule(fw, layer, "-F", chain, NULL); - virFirewallAddRule(fw, layer, "-X", chain, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-F", chain, NULL); + virFirewallAddRuleFull(fw, layer, + true, NULL, NULL, + "-X", chain, NULL); }
Looks like I didn't spot this in a previous patch. We have to ignore the errors here... on -F, -X and -D probably everywhere.
@@ -1088,138 +866,116 @@ iptablesHandleIpHdr(virBufferPtr buf, dstrange = "--src-range"; }
- if (HAS_ENTRY_ITEM(&ipHdr->dataIPSet) && - HAS_ENTRY_ITEM(&ipHdr->dataIPSetFlags)) { - - if (printDataType(vars, - str, sizeof(str), - &ipHdr->dataIPSet) < 0) - goto err_exit; - - virBufferAsprintf(afterStateMatch, - " -m set --match-set \"%s\" ", - str); - - if (printDataTypeDirection(vars, - str, sizeof(str), - &ipHdr->dataIPSetFlags, directionIn) < 0) - goto err_exit; - - virBufferAdd(afterStateMatch, str, -1); - } -
You are removing this entirely? ... ah I see it further below... Oh, I see, you moved it because of the afterStateMatch buffer that this part is using.
}
if (HAS_ENTRY_ITEM(&ipHdr->dataComment)) { - printCommentVar(prefix, ipHdr->dataComment.u.string); - /* keep comments behind everything else -- they are packet eval. no-ops */ - virBufferAddLit(afterStateMatch, - " -m comment --comment \"$" COMMENT_VARNAME "\""); + virFirewallRuleAddArgList(fw, fwrule, + "-m", "comment", + "--comment", ipHdr->dataComment.u.string, + NULL); }
The interesting part about comments was before to ensure that $(foo) never executes in a subshell. With TCK passing it seems this concern is addressed.
@@ -4038,188 +3457,173 @@ ebiptablesApplyNewRules(const char *ifname, } }
- /* process ebtables commands; interleave commands from filters with - commands for creating and connecting ebtables chains */ - j = 0; for (i = 0; i < nrules; i++) { if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { - while (j < nEbtChains && - ebtChains[j].priority <= rules[i]->priority) { - ebiptablesInstCommand(&buf, - ebtChains[j++].commandTemplate); - } - ebtablesRuleInstCommand(&buf, - ifname, - rules[i]); + haveEbtables = true; } else { if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) haveIptables = true; - else if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + else if (virNWFilterRuleIsProtocolIPv6(rules[i]->def)) haveIp6tables = true;
Ah, this is probably the reason why IPv6 rules didn't work in TCK and 23/26 now fixes it. That's probably a typo introduced in 8/26. If you want to go back to 8/26 to fix this ... unless this has other negative side effects during the surgery. Up to you.
} } + /* process ebtables commands; interleave commands from filters with + commands for creating and connecting ebtables chains */ + if (haveEbtables) {
- while (j < nEbtChains) - ebiptablesInstCommand(&buf, - ebtChains[j++].commandTemplate); + /* scan the rules to see which chains need to be created */ + for (i = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { + const char *name = rules[i]->chainSuffix; + if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_OUT || + rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { + if (virHashUpdateEntry(chains_in_set, name, + &rules[i]->chainPriority) < 0) + goto cleanup; + } + if (rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_IN || + rules[i]->def->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) { + if (virHashUpdateEntry(chains_out_set, name, + &rules[i]->chainPriority) < 0) + goto cleanup; + } + } + }
- if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpebchains; + /* create needed chains */ + if (virHashSize(chains_in_set) > 0) { + ebtablesCreateTmpRootChainFW(fw, true, ifname); + if (ebtablesGetSubChainInsts(chains_in_set, + true, + &subchains, + &nsubchains) < 0) + goto cleanup; + } + if (virHashSize(chains_out_set) > 0) { + ebtablesCreateTmpRootChainFW(fw, false, ifname); + if (ebtablesGetSubChainInsts(chains_out_set, + false, + &subchains, + &nsubchains) < 0) + goto cleanup; + } + + if (nsubchains > 0) + qsort(subchains, nsubchains, sizeof(subchains[0]), + ebtablesSubChainInstSort); + + for (i = 0, j = 0; i < nrules; i++) { + if (virNWFilterRuleIsProtocolEthernet(rules[i]->def)) { + while (j < nsubchains && + subchains[j]->priority <= rules[i]->priority) { + ebtablesCreateTmpSubChainFW(fw, + subchains[j]->incoming, + ifname, + subchains[j]->protoidx, + subchains[j]->filtername); + j++; + } + if (ebtablesRuleInstCommand(fw, + ifname, + rules[i]) < 0) + goto cleanup; + } + } + while (j < nsubchains) { + ebtablesCreateTmpSubChainFW(fw, + subchains[j]->incoming, + ifname, + subchains[j]->protoidx, + subchains[j]->filtername); + j++; + } + }
if (haveIptables) {
Based on your comment in another patch, now I am surprised to still see this check 'haveIptables' here. Wouldn't the rpm also solve this here as well?
- NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesUnlinkTmpRootChains(&buf, ifname); - iptablesRemoveTmpRootChains(&buf, ifname); - - iptablesCreateBaseChains(&buf); - - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpebchains; - - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); + iptablesUnlinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesRemoveTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname);
- iptablesCreateTmpRootChains(&buf, ifname); + iptablesCreateBaseChainsFW(fw, VIR_FIREWALL_LAYER_IPV4); + iptablesCreateTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname);
- if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpiptchains; - - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - iptablesLinkTmpRootChains(&buf, ifname); - iptablesSetupVirtInPost(&buf, ifname); - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpiptchains; - - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); + iptablesLinkTmpRootChainsFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname); + iptablesSetupVirtInPostFW(fw, VIR_FIREWALL_LAYER_IPV4, ifname);
for (i = 0; i < nrules; i++) { - if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) - iptablesRuleInstCommand(&buf, - ifname, - rules[i]); + if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) { + if (iptablesRuleInstCommand(fw, + ifname, + rules[i]) < 0) + goto cleanup; + } }
- if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) - goto tear_down_tmpiptchains; - iptablesCheckBridgeNFCallEnabled(false); }
if (haveIp6tables) {
... also this here. Tentative ACK

On Wed, Apr 16, 2014 at 03:38:39PM -0400, Stefan Berger wrote:
}
if (HAS_ENTRY_ITEM(&ipHdr->dataComment)) { - printCommentVar(prefix, ipHdr->dataComment.u.string); - /* keep comments behind everything else -- they are packet eval. no-ops */ - virBufferAddLit(afterStateMatch, - " -m comment --comment \"$" COMMENT_VARNAME "\""); + virFirewallRuleAddArgList(fw, fwrule, + "-m", "comment", + "--comment", ipHdr->dataComment.u.string, + NULL); }
The interesting part about comments was before to ensure that $(foo) never executes in a subshell. With TCK passing it seems this concern is addressed.
Well the way we execute iptables now means that the shell is never involved in any part of the stack, so the issue goes away entirely.
} else { if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) haveIptables = true; - else if (virNWFilterRuleIsProtocolIPv4(rules[i]->def)) + else if (virNWFilterRuleIsProtocolIPv6(rules[i]->def)) haveIp6tables = true;
Ah, this is probably the reason why IPv6 rules didn't work in TCK and 23/26 now fixes it. That's probably a typo introduced in 8/26. If you want to go back to 8/26 to fix this ... unless this has other negative side effects during the surgery. Up to you.
Yep, easy to fix the original. Thanks for finding this.
if (haveIptables) {
Based on your comment in another patch, now I am surprised to still see this check 'haveIptables' here. Wouldn't the rpm also solve this here as well?
This boolean is about whether any iptables rules are defined for the filter. It lets us avoid creating the base chains if there are no rules to put in them.
if (haveIp6tables) {
... also this here.
Likewise. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Conver the ebiptablesDriverProbeStateMatch initialization check to use the virFirewall APIs for querying iptables version. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 68 +++++++++++++++++++------------ 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 835e068..8f237a2 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -3915,45 +3915,62 @@ ebiptablesDriverProbeCtdir(void) iptables_ctdir_corrected = CTDIR_STATUS_OLD; } -static void -ebiptablesDriverProbeStateMatch(void) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; - char *cmdout = NULL, *version; - unsigned long thisversion; - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - virBufferAsprintf(&buf, - "$IPT --version"); +static int +ebiptablesDriverProbeStateMatchQuery(virFirewallPtr fw ATTRIBUTE_UNUSED, + const char *const *lines, + void *opaque) +{ + unsigned long *version = opaque; + char *tmp; - if (ebiptablesExecCLI(&buf, false, &cmdout) < 0) { - VIR_ERROR(_("Testing of iptables command failed: %s"), - cmdout); - return; + if (!lines || !lines[0]) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No output from iptables --version")); + return -1; } /* * we expect output in the format - * iptables v1.4.16 + * 'iptables v1.4.16' */ - if (!(version = strchr(cmdout, 'v')) || - virParseVersionString(version + 1, &thisversion, true) < 0) { - VIR_ERROR(_("Could not determine iptables version from string %s"), - cmdout); - goto cleanup; + if (!(tmp = strchr(lines[0], 'v')) || + virParseVersionString(tmp + 1, version, true) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot parse version string '%s'"), + lines[0]); + return -1; } + return 0; +} + + +static int +ebiptablesDriverProbeStateMatch(void) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + unsigned long version; + virFirewallPtr fw = virFirewallNew(); + + NWFILTER_SET_IPTABLES_SHELLVAR(&buf); + + virFirewallStartTransaction(fw, 0); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_IPV4, + false, ebiptablesDriverProbeStateMatchQuery, &version, + "--version", NULL); + + if (virFirewallApply(fw) < 0) + return -1; + /* * since version 1.4.16 '-m state --state ...' will be converted to * '-m conntrack --ctstate ...' */ - if (thisversion >= 1 * 1000000 + 4 * 1000 + 16) + if (version >= 1 * 1000000 + 4 * 1000 + 16) newMatchState = true; - cleanup: - VIR_FREE(cmdout); - return; + return 0; } static int @@ -3992,7 +4009,8 @@ ebiptablesDriverInit(bool privileged) if (iptables_cmd_path) { ebiptablesDriverProbeCtdir(); - ebiptablesDriverProbeStateMatch(); + if (ebiptablesDriverProbeStateMatch() < 0) + return -1; } ebiptables_driver.flags = TECHDRV_FLAG_INITIALIZED; -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Conver the ebiptablesDriverProbeStateMatch initialization check to use the virFirewall APIs for querying iptables version.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 68 +++++++++++++++++++------------ 1 file changed, 43 insertions(+), 25 deletions(-)
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 835e068..8f237a2 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -3915,45 +3915,62 @@ ebiptablesDriverProbeCtdir(void) iptables_ctdir_corrected = CTDIR_STATUS_OLD; }
-static void -ebiptablesDriverProbeStateMatch(void) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; - char *cmdout = NULL, *version; - unsigned long thisversion;
- NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - virBufferAsprintf(&buf, - "$IPT --version"); +static int +ebiptablesDriverProbeStateMatchQuery(virFirewallPtr fw ATTRIBUTE_UNUSED, + const char *const *lines, + void *opaque) +{ + unsigned long *version = opaque; + char *tmp;
- if (ebiptablesExecCLI(&buf, false, &cmdout) < 0) { - VIR_ERROR(_("Testing of iptables command failed: %s"), - cmdout); - return; + if (!lines || !lines[0]) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No output from iptables --version")); + return -1; }
/* * we expect output in the format - * iptables v1.4.16 + * 'iptables v1.4.16' */ - if (!(version = strchr(cmdout, 'v')) || - virParseVersionString(version + 1, &thisversion, true) < 0) { - VIR_ERROR(_("Could not determine iptables version from string %s"), - cmdout); - goto cleanup; + if (!(tmp = strchr(lines[0], 'v')) || + virParseVersionString(tmp + 1, version, true) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot parse version string '%s'"), + lines[0]); + return -1; }
+ return 0; +} + + +static int +ebiptablesDriverProbeStateMatch(void) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + unsigned long version; + virFirewallPtr fw = virFirewallNew(); + + NWFILTER_SET_IPTABLES_SHELLVAR(&buf); + + virFirewallStartTransaction(fw, 0); + virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_IPV4, + false, ebiptablesDriverProbeStateMatchQuery, &version, + "--version", NULL); + + if (virFirewallApply(fw) < 0) + return -1; + /* * since version 1.4.16 '-m state --state ...' will be converted to * '-m conntrack --ctstate ...' */ - if (thisversion >= 1 * 1000000 + 4 * 1000 + 16) + if (version >= 1 * 1000000 + 4 * 1000 + 16) newMatchState = true;
- cleanup: - VIR_FREE(cmdout); - return; + return 0; }
static int @@ -3992,7 +4009,8 @@ ebiptablesDriverInit(bool privileged)
if (iptables_cmd_path) { ebiptablesDriverProbeCtdir(); - ebiptablesDriverProbeStateMatch(); + if (ebiptablesDriverProbeStateMatch() < 0) + return -1; }
ebiptables_driver.flags = TECHDRV_FLAG_INITIALIZED;
ACK

Remove all the left over code related to the direct invocation of firewall-cmd/iptables/ip6tables/ebtables. This is all handled by the virFirewallPtr APIs now. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_ebiptables_driver.c | 301 +----------------------------- 1 file changed, 8 insertions(+), 293 deletions(-) diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 8f237a2..702deb6 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -59,23 +59,6 @@ VIR_LOG_INIT("nwfilter.nwfilter_ebiptables_driver"); #define CHAINPREFIX_HOST_IN_TEMP 'J' #define CHAINPREFIX_HOST_OUT_TEMP 'P' -/* This file generates a temporary shell script. Since ebiptables is - Linux-specific, we can be reasonably certain that /bin/sh is more - or less POSIX-compliant, so we can use $() and $(()). However, we - cannot assume that /bin/sh is bash, so stick to POSIX syntax. */ - -#define CMD_SEPARATOR "\n" -#define CMD_DEF_PRE "cmd='" -#define CMD_DEF_POST "'" -#define CMD_DEF(X) CMD_DEF_PRE X CMD_DEF_POST -#define CMD_EXEC "eval res=\\$\\(\"${cmd} 2>&1\"\\)" CMD_SEPARATOR -#define CMD_STOPONERR(X) \ - X ? "if [ $? -ne 0 ]; then" \ - " echo \"Failure to execute command '${cmd}' : '${res}'.\";" \ - " exit 1;" \ - "fi" CMD_SEPARATOR \ - : "" - #define PROC_BRIDGE_NF_CALL_IPTABLES \ "/proc/sys/net/bridge/bridge-nf-call-iptables" @@ -84,11 +67,6 @@ VIR_LOG_INIT("nwfilter.nwfilter_ebiptables_driver"); #define BRIDGE_NF_CALL_ALERT_INTERVAL 10 /* seconds */ -static char *ebtables_cmd_path; -static char *iptables_cmd_path; -static char *ip6tables_cmd_path; -static char *grep_cmd_path; - /* * --ctdir original vs. --ctdir reply's meaning was inverted in netfilter * at some point (Linux 2.6.39) @@ -105,14 +83,6 @@ static enum ctdirStatus iptables_ctdir_corrected; #define PRINT_CHAIN(buf, prefix, ifname, suffix) \ snprintf(buf, sizeof(buf), "%c-%s-%s", prefix, ifname, suffix) - -#define NWFILTER_SET_EBTABLES_SHELLVAR(BUFPTR) \ - virBufferAsprintf(BUFPTR, "EBT=\"%s\"\n", ebtables_cmd_path); -#define NWFILTER_SET_IPTABLES_SHELLVAR(BUFPTR) \ - virBufferAsprintf(BUFPTR, "IPT=\"%s\"\n", iptables_cmd_path); -#define NWFILTER_SET_IP6TABLES_SHELLVAR(BUFPTR) \ - virBufferAsprintf(BUFPTR, "IPT=\"%s\"\n", ip6tables_cmd_path); - #define VIRT_IN_CHAIN "libvirt-in" #define VIRT_OUT_CHAIN "libvirt-out" #define VIRT_IN_POST_CHAIN "libvirt-in-post" @@ -133,8 +103,6 @@ static void ebiptablesDriverShutdown(void); static int ebtablesCleanAll(const char *ifname); static int ebiptablesAllTeardown(const char *ifname); -static virMutex execCLIMutex = VIR_MUTEX_INITIALIZER; - struct ushort_map { unsigned short attr; const char *val; @@ -2478,55 +2446,6 @@ ebiptablesCreateRuleInstance(virFirewallPtr fw, } -/** - * ebiptablesExecCLI: - * @buf: pointer to virBuffer containing the string with the commands to - * execute. - * @ignoreNonzero: true if non-zero status is not fatal - * @outbuf: Optional pointer to a string that will hold the buffer with - * output of the executed command. The actual buffer holding - * the message will be newly allocated by this function and - * any passed in buffer freed first. - * - * Returns 0 in case of success, < 0 in case of an error. The returned - * value is NOT the result of running the commands inside the shell - * script. - * - * Execute a sequence of commands (held in the given buffer) as a /bin/sh - * script. Depending on ignoreNonzero, this function will fail if the - * script has unexpected status. - */ -static int -ebiptablesExecCLI(virBufferPtr buf, bool ignoreNonzero, char **outbuf) -{ - int rc = -1; - virCommandPtr cmd; - int status; - - if (!virBufferError(buf) && !virBufferUse(buf)) - return 0; - - if (outbuf) - VIR_FREE(*outbuf); - - VIR_INFO("Run [%s]", virBufferCurrentContent(buf)); - cmd = virCommandNewArgList("/bin/sh", "-c", NULL); - virCommandAddArgBuffer(cmd, buf); - if (outbuf) - virCommandSetOutputBuffer(cmd, outbuf); - - virMutexLock(&execCLIMutex); - - rc = virCommandRun(cmd, ignoreNonzero ? &status : NULL); - - virMutexUnlock(&execCLIMutex); - - virCommandFree(cmd); - - return rc; -} - - static void ebtablesCreateTmpRootChainFW(virFirewallPtr fw, int incoming, const char *ifname) @@ -2875,7 +2794,7 @@ ebtablesRenameTmpSubAndRootChainsFW(virFirewallPtr fw, static int ebiptablesCanApplyBasicRules(void) { - return ebtables_cmd_path != NULL; + return true; } /** @@ -2929,12 +2848,8 @@ ebtablesApplyBasicRules(const char *ifname, ebtablesLinkTmpRootChainFW(fw, true, ifname); ebtablesRenameTmpRootChainFW(fw, true, ifname); - virMutexLock(&execCLIMutex); - if (virFirewallApply(fw) < 0) { - virMutexUnlock(&execCLIMutex); + if (virFirewallApply(fw) < 0) goto tear_down_tmpebchains; - } - virMutexUnlock(&execCLIMutex); virFirewallFree(fw); return 0; @@ -3052,12 +2967,8 @@ ebtablesApplyDHCPOnlyRules(const char *ifname, ebtablesRenameTmpRootChainFW(fw, false, ifname); } - virMutexLock(&execCLIMutex); - if (virFirewallApply(fw) < 0) { - virMutexUnlock(&execCLIMutex); + if (virFirewallApply(fw) < 0) goto tear_down_tmpebchains; - } - virMutexUnlock(&execCLIMutex); virFirewallFree(fw); @@ -3111,12 +3022,8 @@ ebtablesApplyDropAllRules(const char *ifname) ebtablesRenameTmpRootChainFW(fw, true, ifname); ebtablesRenameTmpRootChainFW(fw, false, ifname); - virMutexLock(&execCLIMutex); - if (virFirewallApply(fw) < 0) { - virMutexUnlock(&execCLIMutex); + if (virFirewallApply(fw) < 0) goto tear_down_tmpebchains; - } - virMutexUnlock(&execCLIMutex); virFirewallFree(fw); return 0; @@ -3156,9 +3063,7 @@ ebtablesCleanAll(const char *ifname) ebtablesRemoveTmpRootChainFW(fw, true, ifname); ebtablesRemoveTmpRootChainFW(fw, false, ifname); - virMutexLock(&execCLIMutex); ret = virFirewallApply(fw); - virMutexUnlock(&execCLIMutex); virFirewallFree(fw); return ret; } @@ -3605,12 +3510,8 @@ ebiptablesApplyNewRules(const char *ifname, ebtablesRemoveTmpRootChainFW(fw, true, ifname); ebtablesRemoveTmpRootChainFW(fw, false, ifname); - virMutexLock(&execCLIMutex); - if (virFirewallApply(fw) < 0) { - virMutexUnlock(&execCLIMutex); + if (virFirewallApply(fw) < 0) goto cleanup; - } - virMutexUnlock(&execCLIMutex); ret = 0; @@ -3647,9 +3548,7 @@ ebiptablesTearNewRules(const char *ifname) ebtablesRemoveTmpRootChainFW(fw, true, ifname); ebtablesRemoveTmpRootChainFW(fw, false, ifname); - virMutexLock(&execCLIMutex); ret = virFirewallApply(fw); - virMutexUnlock(&execCLIMutex); virFirewallFree(fw); return ret; } @@ -3678,9 +3577,7 @@ ebiptablesTearOldRules(const char *ifname) ebtablesRemoveRootChainFW(fw, false, ifname); ebtablesRenameTmpSubAndRootChainsFW(fw, ifname); - virMutexLock(&execCLIMutex); ret = virFirewallApply(fw); - virMutexUnlock(&execCLIMutex); virFirewallFree(fw); return ret; } @@ -3719,9 +3616,7 @@ ebiptablesAllTeardown(const char *ifname) ebtablesRemoveRootChainFW(fw, true, ifname); ebtablesRemoveRootChainFW(fw, false, ifname); - virMutexLock(&execCLIMutex); ret = virFirewallApply(fw); - virMutexUnlock(&execCLIMutex); virFirewallFree(fw); return ret; } @@ -3746,149 +3641,6 @@ virNWFilterTechDriver ebiptables_driver = { .removeBasicRules = ebtablesRemoveBasicRules, }; -/* - * ebiptablesDriverInitWithFirewallD - * - * Try to use firewall-cmd by testing it once; if it works, have ebtables - * and ip6tables commands use firewall-cmd. - */ -static int -ebiptablesDriverInitWithFirewallD(void) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; - char *firewall_cmd_path; - char *output = NULL; - int ret = -1; - - if (!virNWFilterDriverIsWatchingFirewallD()) - return -1; - - firewall_cmd_path = virFindFileInPath("firewall-cmd"); - - if (firewall_cmd_path) { - virBufferAsprintf(&buf, "FWC=%s\n", firewall_cmd_path); - virBufferAsprintf(&buf, - CMD_DEF("$FWC --state") CMD_SEPARATOR - CMD_EXEC - "%s", - CMD_STOPONERR(true)); - - if (ebiptablesExecCLI(&buf, false, &output) < 0) { - VIR_INFO("firewalld support disabled for nwfilter"); - } else { - VIR_INFO("firewalld support enabled for nwfilter"); - - if (virAsprintf(&ebtables_cmd_path, - "%s --direct --passthrough eb", - firewall_cmd_path) < 0 || - virAsprintf(&iptables_cmd_path, - "%s --direct --passthrough ipv4", - firewall_cmd_path) < 0 || - virAsprintf(&ip6tables_cmd_path, - "%s --direct --passthrough ipv6", - firewall_cmd_path) < 0) { - VIR_FREE(ebtables_cmd_path); - VIR_FREE(iptables_cmd_path); - VIR_FREE(ip6tables_cmd_path); - ret = -1; - goto err_exit; - } - ret = 0; - } - } - - err_exit: - VIR_FREE(firewall_cmd_path); - VIR_FREE(output); - - return ret; -} - -static void -ebiptablesDriverInitCLITools(void) -{ - ebtables_cmd_path = virFindFileInPath("ebtables"); - if (!ebtables_cmd_path) - VIR_WARN("Could not find 'ebtables' executable"); - - iptables_cmd_path = virFindFileInPath("iptables"); - if (!iptables_cmd_path) - VIR_WARN("Could not find 'iptables' executable"); - - ip6tables_cmd_path = virFindFileInPath("ip6tables"); - if (!ip6tables_cmd_path) - VIR_WARN("Could not find 'ip6tables' executable"); -} - -/* - * ebiptablesDriverTestCLITools - * - * Test the CLI tools. If one is found not to be working, free the buffer - * holding its path as a sign that the tool cannot be used. - */ -static int -ebiptablesDriverTestCLITools(void) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; - char *errmsg = NULL; - int ret = 0; - - if (ebtables_cmd_path) { - NWFILTER_SET_EBTABLES_SHELLVAR(&buf); - /* basic probing */ - virBufferAsprintf(&buf, - CMD_DEF("$EBT -t nat -L") CMD_SEPARATOR - CMD_EXEC - "%s", - CMD_STOPONERR(true)); - - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) { - VIR_FREE(ebtables_cmd_path); - VIR_ERROR(_("Testing of ebtables command failed: %s"), - errmsg); - ret = -1; - } - } - - if (iptables_cmd_path) { - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - - virBufferAsprintf(&buf, - CMD_DEF("$IPT -n -L FORWARD") CMD_SEPARATOR - CMD_EXEC - "%s", - CMD_STOPONERR(true)); - - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) { - VIR_FREE(iptables_cmd_path); - VIR_ERROR(_("Testing of iptables command failed: %s"), - errmsg); - ret = -1; - } - } - - if (ip6tables_cmd_path) { - NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); - - virBufferAsprintf(&buf, - CMD_DEF("$IPT -n -L FORWARD") CMD_SEPARATOR - CMD_EXEC - "%s", - CMD_STOPONERR(true)); - - if (ebiptablesExecCLI(&buf, false, &errmsg) < 0) { - VIR_FREE(ip6tables_cmd_path); - VIR_ERROR(_("Testing of ip6tables command failed: %s"), - errmsg); - ret = -1; - } - } - - VIR_FREE(errmsg); - - return ret; -} - static void ebiptablesDriverProbeCtdir(void) { @@ -3949,12 +3701,9 @@ ebiptablesDriverProbeStateMatchQuery(virFirewallPtr fw ATTRIBUTE_UNUSED, static int ebiptablesDriverProbeStateMatch(void) { - virBuffer buf = VIR_BUFFER_INITIALIZER; unsigned long version; virFirewallPtr fw = virFirewallNew(); - NWFILTER_SET_IPTABLES_SHELLVAR(&buf); - virFirewallStartTransaction(fw, 0); virFirewallAddRuleFull(fw, VIR_FIREWALL_LAYER_IPV4, false, ebiptablesDriverProbeStateMatchQuery, &version, @@ -3979,39 +3728,9 @@ ebiptablesDriverInit(bool privileged) if (!privileged) return 0; - grep_cmd_path = virFindFileInPath("grep"); - - /* - * check whether we can run with firewalld's tools -- - * if not, we just fall back to eb/iptables command - * line tools. - */ - if (ebiptablesDriverInitWithFirewallD() < 0) - ebiptablesDriverInitCLITools(); - - /* make sure tools are available and work */ - ebiptablesDriverTestCLITools(); - - /* ip(6)tables support needs awk & grep, ebtables doesn't */ - if ((iptables_cmd_path != NULL || ip6tables_cmd_path != NULL) && - !grep_cmd_path) { - VIR_ERROR(_("essential tools to support ip(6)tables " - "firewalls could not be located")); - VIR_FREE(iptables_cmd_path); - VIR_FREE(ip6tables_cmd_path); - } - - if (!ebtables_cmd_path && !iptables_cmd_path && !ip6tables_cmd_path) { - VIR_ERROR(_("firewall tools were not found or cannot be used")); - ebiptablesDriverShutdown(); - return -ENOTSUP; - } - - if (iptables_cmd_path) { - ebiptablesDriverProbeCtdir(); - if (ebiptablesDriverProbeStateMatch() < 0) - return -1; - } + ebiptablesDriverProbeCtdir(); + if (ebiptablesDriverProbeStateMatch() < 0) + return -1; ebiptables_driver.flags = TECHDRV_FLAG_INITIALIZED; @@ -4022,9 +3741,5 @@ ebiptablesDriverInit(bool privileged) static void ebiptablesDriverShutdown(void) { - VIR_FREE(grep_cmd_path); - VIR_FREE(ebtables_cmd_path); - VIR_FREE(iptables_cmd_path); - VIR_FREE(ip6tables_cmd_path); ebiptables_driver.flags = 0; } -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Remove all the left over code related to the direct invocation of firewall-cmd/iptables/ip6tables/ebtables. This is all handled by the virFirewallPtr APIs now.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
ACK

Create a nwfilterxml2firewalltest to exercise the ebiptables_driver.applyNewRules method with a variety of different XML input files. The XML input files are taken from the libvirt-tck nwfilter tests. While the nwfilter tests verify the final state of the iptables chains, this test verifies the set of commands invoked to create the chains. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/conf/nwfilter_params.c | 15 + src/conf/nwfilter_params.h | 1 + src/libvirt_private.syms | 2 + tests/Makefile.am | 7 + tests/nwfilterxml2firewalldata/ah-ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/ah-ipv6.xml | 19 + tests/nwfilterxml2firewalldata/ah-linux.args | 18 + tests/nwfilterxml2firewalldata/ah.xml | 18 + tests/nwfilterxml2firewalldata/all-ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/all-ipv6.xml | 19 + tests/nwfilterxml2firewalldata/all-linux.args | 18 + tests/nwfilterxml2firewalldata/all.xml | 18 + tests/nwfilterxml2firewalldata/arp-linux.args | 11 + tests/nwfilterxml2firewalldata/arp.xml | 32 ++ tests/nwfilterxml2firewalldata/comment-linux.args | 49 ++ tests/nwfilterxml2firewalldata/comment.xml | 71 +++ .../nwfilterxml2firewalldata/conntrack-linux.args | 7 + tests/nwfilterxml2firewalldata/conntrack.xml | 12 + tests/nwfilterxml2firewalldata/esp-ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/esp-ipv6.xml | 19 + tests/nwfilterxml2firewalldata/esp-linux.args | 18 + tests/nwfilterxml2firewalldata/esp.xml | 18 + .../nwfilterxml2firewalldata/example-1-linux.args | 13 + tests/nwfilterxml2firewalldata/example-1.xml | 24 + .../nwfilterxml2firewalldata/example-2-linux.args | 20 + tests/nwfilterxml2firewalldata/example-2.xml | 37 ++ tests/nwfilterxml2firewalldata/hex-data-linux.args | 28 ++ tests/nwfilterxml2firewalldata/hex-data.xml | 56 +++ .../icmp-direction-linux.args | 9 + tests/nwfilterxml2firewalldata/icmp-direction.xml | 15 + .../icmp-direction2-linux.args | 9 + tests/nwfilterxml2firewalldata/icmp-direction2.xml | 15 + .../icmp-direction3-linux.args | 6 + tests/nwfilterxml2firewalldata/icmp-direction3.xml | 10 + tests/nwfilterxml2firewalldata/icmp-linux.args | 9 + tests/nwfilterxml2firewalldata/icmp.xml | 13 + tests/nwfilterxml2firewalldata/icmpv6-linux.args | 12 + tests/nwfilterxml2firewalldata/icmpv6.xml | 19 + tests/nwfilterxml2firewalldata/igmp-linux.args | 18 + tests/nwfilterxml2firewalldata/igmp.xml | 18 + tests/nwfilterxml2firewalldata/ip-linux.args | 8 + tests/nwfilterxml2firewalldata/ip.xml | 28 ++ tests/nwfilterxml2firewalldata/ipset-linux.args | 36 ++ tests/nwfilterxml2firewalldata/ipset.xml | 25 + .../ipt-no-macspoof-linux.args | 2 + tests/nwfilterxml2firewalldata/ipt-no-macspoof.xml | 14 + tests/nwfilterxml2firewalldata/ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/ipv6.xml | 43 ++ tests/nwfilterxml2firewalldata/iter1-linux.args | 18 + tests/nwfilterxml2firewalldata/iter1.xml | 6 + tests/nwfilterxml2firewalldata/iter2-linux.args | 342 +++++++++++++ tests/nwfilterxml2firewalldata/iter2.xml | 23 + tests/nwfilterxml2firewalldata/iter3-linux.args | 30 ++ tests/nwfilterxml2firewalldata/iter3.xml | 13 + tests/nwfilterxml2firewalldata/mac-linux.args | 8 + tests/nwfilterxml2firewalldata/mac.xml | 19 + tests/nwfilterxml2firewalldata/rarp-linux.args | 12 + tests/nwfilterxml2firewalldata/rarp.xml | 28 ++ tests/nwfilterxml2firewalldata/ref-rule.xml | 18 + tests/nwfilterxml2firewalldata/ref.xml | 4 + .../nwfilterxml2firewalldata/sctp-ipv6-linux.args | 22 + tests/nwfilterxml2firewalldata/sctp-ipv6.xml | 22 + tests/nwfilterxml2firewalldata/sctp-linux.args | 20 + tests/nwfilterxml2firewalldata/sctp.xml | 22 + tests/nwfilterxml2firewalldata/stp-linux.args | 18 + tests/nwfilterxml2firewalldata/stp.xml | 26 + tests/nwfilterxml2firewalldata/target-linux.args | 75 +++ tests/nwfilterxml2firewalldata/target.xml | 66 +++ tests/nwfilterxml2firewalldata/target2-linux.args | 13 + tests/nwfilterxml2firewalldata/target2.xml | 18 + tests/nwfilterxml2firewalldata/tcp-ipv6-linux.args | 22 + tests/nwfilterxml2firewalldata/tcp-ipv6.xml | 22 + tests/nwfilterxml2firewalldata/tcp-linux.args | 22 + tests/nwfilterxml2firewalldata/tcp.xml | 34 ++ tests/nwfilterxml2firewalldata/udp-ipv6-linux.args | 22 + tests/nwfilterxml2firewalldata/udp-ipv6.xml | 22 + tests/nwfilterxml2firewalldata/udp-linux.args | 20 + tests/nwfilterxml2firewalldata/udp.xml | 22 + .../udplite-ipv6-linux.args | 20 + tests/nwfilterxml2firewalldata/udplite-ipv6.xml | 19 + tests/nwfilterxml2firewalldata/udplite-linux.args | 18 + tests/nwfilterxml2firewalldata/udplite.xml | 18 + tests/nwfilterxml2firewalldata/vlan-linux.args | 14 + tests/nwfilterxml2firewalldata/vlan.xml | 38 ++ tests/nwfilterxml2firewalltest.c | 534 +++++++++++++++++++++ 85 files changed, 2609 insertions(+) create mode 100644 tests/nwfilterxml2firewalldata/ah-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ah-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/ah-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ah.xml create mode 100644 tests/nwfilterxml2firewalldata/all-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/all-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/all-linux.args create mode 100644 tests/nwfilterxml2firewalldata/all.xml create mode 100644 tests/nwfilterxml2firewalldata/arp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/arp.xml create mode 100644 tests/nwfilterxml2firewalldata/comment-linux.args create mode 100644 tests/nwfilterxml2firewalldata/comment.xml create mode 100644 tests/nwfilterxml2firewalldata/conntrack-linux.args create mode 100644 tests/nwfilterxml2firewalldata/conntrack.xml create mode 100644 tests/nwfilterxml2firewalldata/esp-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/esp-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/esp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/esp.xml create mode 100644 tests/nwfilterxml2firewalldata/example-1-linux.args create mode 100644 tests/nwfilterxml2firewalldata/example-1.xml create mode 100644 tests/nwfilterxml2firewalldata/example-2-linux.args create mode 100644 tests/nwfilterxml2firewalldata/example-2.xml create mode 100644 tests/nwfilterxml2firewalldata/hex-data-linux.args create mode 100644 tests/nwfilterxml2firewalldata/hex-data.xml create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction.xml create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction2-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction2.xml create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction3-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmp-direction3.xml create mode 100644 tests/nwfilterxml2firewalldata/icmp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmp.xml create mode 100644 tests/nwfilterxml2firewalldata/icmpv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/icmpv6.xml create mode 100644 tests/nwfilterxml2firewalldata/igmp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/igmp.xml create mode 100644 tests/nwfilterxml2firewalldata/ip-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ip.xml create mode 100644 tests/nwfilterxml2firewalldata/ipset-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ipset.xml create mode 100644 tests/nwfilterxml2firewalldata/ipt-no-macspoof-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ipt-no-macspoof.xml create mode 100644 tests/nwfilterxml2firewalldata/ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/iter1-linux.args create mode 100644 tests/nwfilterxml2firewalldata/iter1.xml create mode 100644 tests/nwfilterxml2firewalldata/iter2-linux.args create mode 100644 tests/nwfilterxml2firewalldata/iter2.xml create mode 100644 tests/nwfilterxml2firewalldata/iter3-linux.args create mode 100644 tests/nwfilterxml2firewalldata/iter3.xml create mode 100644 tests/nwfilterxml2firewalldata/mac-linux.args create mode 100644 tests/nwfilterxml2firewalldata/mac.xml create mode 100644 tests/nwfilterxml2firewalldata/rarp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/rarp.xml create mode 100644 tests/nwfilterxml2firewalldata/ref-rule.xml create mode 100644 tests/nwfilterxml2firewalldata/ref.xml create mode 100644 tests/nwfilterxml2firewalldata/sctp-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/sctp-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/sctp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/sctp.xml create mode 100644 tests/nwfilterxml2firewalldata/stp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/stp.xml create mode 100644 tests/nwfilterxml2firewalldata/target-linux.args create mode 100644 tests/nwfilterxml2firewalldata/target.xml create mode 100644 tests/nwfilterxml2firewalldata/target2-linux.args create mode 100644 tests/nwfilterxml2firewalldata/target2.xml create mode 100644 tests/nwfilterxml2firewalldata/tcp-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/tcp-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/tcp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/tcp.xml create mode 100644 tests/nwfilterxml2firewalldata/udp-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/udp-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/udp-linux.args create mode 100644 tests/nwfilterxml2firewalldata/udp.xml create mode 100644 tests/nwfilterxml2firewalldata/udplite-ipv6-linux.args create mode 100644 tests/nwfilterxml2firewalldata/udplite-ipv6.xml create mode 100644 tests/nwfilterxml2firewalldata/udplite-linux.args create mode 100644 tests/nwfilterxml2firewalldata/udplite.xml create mode 100644 tests/nwfilterxml2firewalldata/vlan-linux.args create mode 100644 tests/nwfilterxml2firewalldata/vlan.xml create mode 100644 tests/nwfilterxml2firewalltest.c diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index 7655033..ac4d4a8 100644 --- a/src/conf/nwfilter_params.c +++ b/src/conf/nwfilter_params.c @@ -252,6 +252,21 @@ virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value) return rc; } + +int +virNWFilterVarValueAddValueCopy(virNWFilterVarValuePtr val, const char *value) +{ + char *valdup; + if (VIR_STRDUP(valdup, value) < 0) + return -1; + if (virNWFilterVarValueAddValue(val, valdup) < 0) { + VIR_FREE(valdup); + return -1; + } + return 0; +} + + static int virNWFilterVarValueDelNthValue(virNWFilterVarValuePtr val, unsigned int pos) { diff --git a/src/conf/nwfilter_params.h b/src/conf/nwfilter_params.h index f9efc42..08e448f 100644 --- a/src/conf/nwfilter_params.h +++ b/src/conf/nwfilter_params.h @@ -60,6 +60,7 @@ unsigned int virNWFilterVarValueGetCardinality(const virNWFilterVarValue *); bool virNWFilterVarValueEqual(const virNWFilterVarValue *a, const virNWFilterVarValue *b); int virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value); +int virNWFilterVarValueAddValueCopy(virNWFilterVarValuePtr val, const char *value); int virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value); typedef struct _virNWFilterHashTable virNWFilterHashTable; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 18be0e1..67edd20 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -578,6 +578,7 @@ virNWFilterConfLayerInit; virNWFilterConfLayerShutdown; virNWFilterDefFormat; virNWFilterDefFree; +virNWFilterDefParseFile; virNWFilterDefParseString; virNWFilterInstFiltersOnAllVMs; virNWFilterJumpTargetTypeToString; @@ -630,6 +631,7 @@ virNWFilterVarCombIterFree; virNWFilterVarCombIterGetVarValue; virNWFilterVarCombIterNext; virNWFilterVarValueAddValue; +virNWFilterVarValueAddValueCopy; virNWFilterVarValueCopy; virNWFilterVarValueCreateSimple; virNWFilterVarValueCreateSimpleCopyValue; diff --git a/tests/Makefile.am b/tests/Makefile.am index 9547c02..4a71f37 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -270,6 +270,7 @@ test_programs += nwfilterxml2xmltest if WITH_NWFILTER test_programs += nwfilterebiptablestest +test_programs += nwfilterxml2firewalltest endif WITH_NWFILTER if WITH_STORAGE @@ -696,6 +697,12 @@ nwfilterebiptablestest_SOURCES = \ nwfilterebiptablestest.c \ testutils.c testutils.h nwfilterebiptablestest_LDADD = ../src/libvirt_driver_nwfilter_impl.la $(LDADDS) + +nwfilterxml2firewalltest_SOURCES = \ + nwfilterxml2firewalltest.c \ + testutils.c testutils.h +nwfilterxml2firewalltest_LDADD = \ + ../src/libvirt_driver_nwfilter_impl.la $(LDADDS) endif WITH_NWFILTER secretxml2xmltest_SOURCES = \ diff --git a/tests/nwfilterxml2firewalldata/ah-ipv6-linux.args b/tests/nwfilterxml2firewalldata/ah-ipv6-linux.args new file mode 100644 index 0000000..aa7a70d --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ah-ipv6-linux.args @@ -0,0 +1,20 @@ +/usr/sbin/ip6tables -A FJ-vnet0 -p ah -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p ah --destination f:e:d::c:b:a/127 \ +--source a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p ah -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p ah --destination a:b:c::/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p ah -m mac --mac-source 01:02:03:04:05:06 \ +--source a:b:c::/128 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p ah --destination a:b:c::/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p ah --destination ::10.1.2.3/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p ah -m mac --mac-source 01:02:03:04:05:06 \ +--source ::10.1.2.3/128 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p ah --destination ::10.1.2.3/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/ah-ipv6.xml b/tests/nwfilterxml2firewalldata/ah-ipv6.xml new file mode 100644 index 0000000..95ebbc9 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ah-ipv6.xml @@ -0,0 +1,19 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <ah-ipv6 srcmacaddr='1:2:3:4:5:6' + dstipaddr='a:b:c::d:e:f' dstipmask='128' + srcipaddr='f:e:d::c:b:a' srcipmask='127' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <ah-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='a:b:c::' srcipmask='128' + dscp='33'/> + </rule> + <rule action='accept' direction='in'> + <ah-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='::10.1.2.3' srcipmask='128' + dscp='33'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/ah-linux.args b/tests/nwfilterxml2firewalldata/ah-linux.args new file mode 100644 index 0000000..a0f5fb6 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ah-linux.args @@ -0,0 +1,18 @@ +/usr/sbin/iptables -A FJ-vnet0 -p ah -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p ah --source 10.1.2.3/32 -m dscp --dscp 2 -m state \ +--state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p ah -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p ah --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p ah -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p ah --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p ah --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p ah -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p ah --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/ah.xml b/tests/nwfilterxml2firewalldata/ah.xml new file mode 100644 index 0000000..287c10b --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ah.xml @@ -0,0 +1,18 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <ah srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <ah srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> + <rule action='accept' direction='in'> + <ah srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/all-ipv6-linux.args b/tests/nwfilterxml2firewalldata/all-ipv6-linux.args new file mode 100644 index 0000000..6559434 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/all-ipv6-linux.args @@ -0,0 +1,20 @@ +/usr/sbin/ip6tables -A FJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p all --destination f:e:d::c:b:a/127 \ +--source a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p all --destination a:b:c::/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--source a:b:c::/128 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p all --destination a:b:c::/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p all --destination ::10.1.2.3/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--source ::10.1.2.3/128 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p all --destination ::10.1.2.3/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/all-ipv6.xml b/tests/nwfilterxml2firewalldata/all-ipv6.xml new file mode 100644 index 0000000..5cf3519 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/all-ipv6.xml @@ -0,0 +1,19 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <all-ipv6 srcmacaddr='1:2:3:4:5:6' + dstipaddr='a:b:c::d:e:f' dstipmask='128' + srcipaddr='f:e:d::c:b:a' srcipmask='127' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <all-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='a:b:c::' srcipmask='128' + dscp='33'/> + </rule> + <rule action='accept' direction='in'> + <all-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='::10.1.2.3' srcipmask='128' + dscp='33'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/all-linux.args b/tests/nwfilterxml2firewalldata/all-linux.args new file mode 100644 index 0000000..c8116f5 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/all-linux.args @@ -0,0 +1,18 @@ +/usr/sbin/iptables -A FJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all --source 10.1.2.3/32 -m dscp --dscp 2 -m state \ +--state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/all.xml b/tests/nwfilterxml2firewalldata/all.xml new file mode 100644 index 0000000..a66923c --- /dev/null +++ b/tests/nwfilterxml2firewalldata/all.xml @@ -0,0 +1,18 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <all srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <all srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> + <rule action='accept' direction='in'> + <all srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/arp-linux.args b/tests/nwfilterxml2firewalldata/arp-linux.args new file mode 100644 index 0000000..469b75a --- /dev/null +++ b/tests/nwfilterxml2firewalldata/arp-linux.args @@ -0,0 +1,11 @@ +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x806 --arp-htype 12 --arp-opcode 1 \ +--arp-ptype 0x22 --arp-mac-src 01:02:03:04:05:06 --arp-mac-dst 0a:0b:0c:0d:0e:0f \ +-j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x806 --arp-htype 255 --arp-opcode 1 --arp-ptype 0xff -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x806 --arp-htype 256 --arp-opcode 11 --arp-ptype 0x100 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x806 --arp-htype 65535 --arp-opcode 65535 --arp-ptype 0xffff -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -p 0x806 --arp-gratuitous -j ACCEPT diff --git a/tests/nwfilterxml2firewalldata/arp.xml b/tests/nwfilterxml2firewalldata/arp.xml new file mode 100644 index 0000000..d0abf94 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/arp.xml @@ -0,0 +1,32 @@ +<filter name='tck-testcase'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <arp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + protocolid='arp' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + hwtype='12' + protocoltype='34' + opcode='Request' + arpsrcmacaddr='1:2:3:4:5:6' + arpdstmacaddr='a:b:c:d:e:f'/> + </rule> + + <rule action='accept' direction='out'> + <arp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + opcode='1' hwtype='255' protocoltype='255'/> + </rule> + + <rule action='accept' direction='out'> + <arp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + opcode='11' hwtype='256' protocoltype='256'/> + </rule> + + <rule action='accept' direction='out'> + <arp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + opcode='65535' hwtype='65535' protocoltype='65535' /> + </rule> + + <rule action='accept' direction='in'> + <arp gratuitous='true'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/comment-linux.args b/tests/nwfilterxml2firewalldata/comment-linux.args new file mode 100644 index 0000000..e776d22 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/comment-linux.args @@ -0,0 +1,49 @@ +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -p 0x1234 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p ipv4 --ip-source 10.1.2.3/32 \ +--ip-destination 10.1.2.3/32 --ip-protocol 17 --ip-source-port 291:564 \ +--ip-destination-port 13398:17767 --ip-tos 0x32 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:fe \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:80 -p ipv6 --ip6-source ::10.1.2.3/22 \ +--ip6-destination ::10.1.2.3/113 --ip6-protocol 6 --ip6-source-port 273:400 \ +--ip6-destination-port 13107:65535 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x806 --arp-htype 18 --arp-opcode 1 \ +--arp-ptype 0x56 --arp-mac-src 01:02:03:04:05:06 --arp-mac-dst 0a:0b:0c:0d:0e:0f \ +-j ACCEPT +/usr/sbin/iptables -A FJ-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 34 --sport 291:400 --dport 564:1092 -m state \ +--state NEW,ESTABLISHED -m comment --comment 'udp rule' -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --source 10.1.2.3/32 -m dscp --dscp 34 \ +--dport 291:400 --sport 564:1092 -m state --state ESTABLISHED -m comment \ +--comment 'udp rule' -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 34 --sport 291:400 --dport 564:1092 -m state \ +--state NEW,ESTABLISHED -m comment --comment 'udp rule' -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p tcp --destination a:b:c::/128 -m dscp --dscp 57 \ +--dport 32:33 --sport 256:4369 -m state --state ESTABLISHED -m comment \ +--comment 'tcp/ipv6 rule' -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--source a:b:c::/128 -m dscp --dscp 57 --sport 32:33 --dport 256:4369 -m state \ +--state NEW,ESTABLISHED -m comment --comment 'tcp/ipv6 rule' -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p tcp --destination a:b:c::/128 -m dscp --dscp 57 \ +--dport 32:33 --sport 256:4369 -m state --state ESTABLISHED -m comment \ +--comment 'tcp/ipv6 rule' -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p udp -m state --state ESTABLISHED -m comment \ +--comment '`ls`;${COLUMNS};$(ls);"test";&'\''3 spaces'\''' -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p udp -m state --state NEW,ESTABLISHED -m comment \ +--comment '`ls`;${COLUMNS};$(ls);"test";&'\''3 spaces'\''' -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p udp -m state --state ESTABLISHED -m comment \ +--comment '`ls`;${COLUMNS};$(ls);"test";&'\''3 spaces'\''' -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p sctp -m state --state ESTABLISHED -m comment \ +--comment 'comment with lone '\'', `, ", `, \, $x, and two spaces' -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p sctp -m state --state NEW,ESTABLISHED -m comment \ +--comment 'comment with lone '\'', `, ", `, \, $x, and two spaces' -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p sctp -m state --state ESTABLISHED -m comment \ +--comment 'comment with lone '\'', `, ", `, \, $x, and two spaces' -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p ah -m state --state ESTABLISHED -m comment \ +--comment 'tmp=`mktemp`; echo ${RANDOM} > ${tmp} ; cat < ${tmp}; rm -f ${tmp}' -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p ah -m state --state NEW,ESTABLISHED -m comment \ +--comment 'tmp=`mktemp`; echo ${RANDOM} > ${tmp} ; cat < ${tmp}; rm -f ${tmp}' -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p ah -m state --state ESTABLISHED -m comment \ +--comment 'tmp=`mktemp`; echo ${RANDOM} > ${tmp} ; cat < ${tmp}; rm -f ${tmp}' -j RETURN diff --git a/tests/nwfilterxml2firewalldata/comment.xml b/tests/nwfilterxml2firewalldata/comment.xml new file mode 100644 index 0000000..a154a17 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/comment.xml @@ -0,0 +1,71 @@ +<filter name='tck-testcase'> + <uuid>0a5288ea-612c-834a-6bbf-82a03a1a3244</uuid> + + <rule action='accept' direction='in'> + <mac protocolid='0x1234' comment='mac rule'/> + </rule> + + <rule action='accept' direction='out'> + <ip srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + srcipaddr='10.1.2.3' srcipmask='255.255.255.255' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + protocol='udp' + srcportstart='0x123' srcportend='0x234' + dstportstart='0x3456' dstportend='0x4567' + dscp='0x32' comment='ip rule'/> + </rule> + + <rule action='accept' direction='out'> + <ipv6 srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:fe' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:80' + srcipaddr='::10.1.2.3' srcipmask='22' + dstipaddr='::10.1.2.3' + dstipmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000' + protocol='tcp' + srcportstart='0x111' srcportend='400' + dstportstart='0x3333' dstportend='65535' comment='ipv6 rule'/> + </rule> + + <rule action='accept' direction='out'> + <arp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + hwtype='0x12' + protocoltype='0x56' + opcode='Request' + arpsrcmacaddr='1:2:3:4:5:6' + arpdstmacaddr='a:b:c:d:e:f' + comment='arp rule'/> + </rule> + + <rule action='accept' direction='out'> + <udp srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='0x22' + srcportstart='0x123' srcportend='400' + dstportstart='0x234' dstportend='0x444' + comment='udp rule'/> + </rule> + + <rule action='accept' direction='in'> + <tcp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='a:b:c::' srcipmask='128' + dscp='0x39' + srcportstart='0x20' srcportend='0x21' + dstportstart='0x100' dstportend='0x1111' + comment='tcp/ipv6 rule'/> + </rule> + + <rule action='accept' direction='in'> + <udp-ipv6 comment='`ls`;${COLUMNS};$(ls);"test";&'3 spaces''/> + </rule> + + <rule action='accept' direction='in'> + <sctp-ipv6 comment='comment with lone ', `, ", `, \, $x, and two spaces'/> + </rule> + + <rule action='accept' direction='in'> + <ah-ipv6 comment='tmp=`mktemp`; echo ${RANDOM} > ${tmp} ; cat < ${tmp}; rm -f ${tmp}'/> + </rule> + +</filter> diff --git a/tests/nwfilterxml2firewalldata/conntrack-linux.args b/tests/nwfilterxml2firewalldata/conntrack-linux.args new file mode 100644 index 0000000..96b29ac --- /dev/null +++ b/tests/nwfilterxml2firewalldata/conntrack-linux.args @@ -0,0 +1,7 @@ +/usr/sbin/iptables -A FJ-vnet0 -p icmp -m connlimit --connlimit-above 1 -j DROP +/usr/sbin/iptables -A HJ-vnet0 -p icmp -m connlimit --connlimit-above 1 -j DROP +/usr/sbin/iptables -A FJ-vnet0 -p tcp -m connlimit --connlimit-above 2 -j DROP +/usr/sbin/iptables -A HJ-vnet0 -p tcp -m connlimit --connlimit-above 2 -j DROP +/usr/sbin/iptables -A FJ-vnet0 -p all -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m state --state NEW,ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/conntrack.xml b/tests/nwfilterxml2firewalldata/conntrack.xml new file mode 100644 index 0000000..0682b25 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/conntrack.xml @@ -0,0 +1,12 @@ +<filter name='tck-testcase' chain='root'> + <uuid>0a5288ea-612c-834a-6bbf-82a03a1a3244</uuid> + <rule action='drop' direction='out' priority='500'> + <icmp connlimit-above='1'/> + </rule> + <rule action='drop' direction='out' priority='500'> + <tcp connlimit-above='2'/> + </rule> + <rule action='accept' direction='out' priority='500'> + <all/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/esp-ipv6-linux.args b/tests/nwfilterxml2firewalldata/esp-ipv6-linux.args new file mode 100644 index 0000000..d8c3a3c --- /dev/null +++ b/tests/nwfilterxml2firewalldata/esp-ipv6-linux.args @@ -0,0 +1,20 @@ +/usr/sbin/ip6tables -A FJ-vnet0 -p esp -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p esp --destination f:e:d::c:b:a/127 \ +--source a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p esp -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p esp --destination a:b:c::/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p esp -m mac --mac-source 01:02:03:04:05:06 \ +--source a:b:c::/128 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p esp --destination a:b:c::/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p esp --destination ::10.1.2.3/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p esp -m mac --mac-source 01:02:03:04:05:06 \ +--source ::10.1.2.3/128 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p esp --destination ::10.1.2.3/128 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/esp-ipv6.xml b/tests/nwfilterxml2firewalldata/esp-ipv6.xml new file mode 100644 index 0000000..295d0f9 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/esp-ipv6.xml @@ -0,0 +1,19 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <esp-ipv6 srcmacaddr='1:2:3:4:5:6' + dstipaddr='a:b:c::d:e:f' dstipmask='128' + srcipaddr='f:e:d::c:b:a' srcipmask='127' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <esp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='a:b:c::' srcipmask='128' + dscp='33'/> + </rule> + <rule action='accept' direction='in'> + <esp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='::10.1.2.3' srcipmask='128' + dscp='33'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/esp-linux.args b/tests/nwfilterxml2firewalldata/esp-linux.args new file mode 100644 index 0000000..aeee6eb --- /dev/null +++ b/tests/nwfilterxml2firewalldata/esp-linux.args @@ -0,0 +1,18 @@ +/usr/sbin/iptables -A FJ-vnet0 -p esp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p esp --source 10.1.2.3/32 -m dscp --dscp 2 -m state \ +--state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p esp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p esp --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p esp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p esp --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p esp --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p esp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p esp --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/esp.xml b/tests/nwfilterxml2firewalldata/esp.xml new file mode 100644 index 0000000..1f75df1 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/esp.xml @@ -0,0 +1,18 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <esp srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <esp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> + <rule action='accept' direction='in'> + <esp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/example-1-linux.args b/tests/nwfilterxml2firewalldata/example-1-linux.args new file mode 100644 index 0000000..647980b --- /dev/null +++ b/tests/nwfilterxml2firewalldata/example-1-linux.args @@ -0,0 +1,13 @@ +/usr/sbin/iptables -A FJ-vnet0 -p tcp --sport 22 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED \ +-j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --sport 22 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p icmp -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p icmp -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p icmp -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -j DROP +/usr/sbin/iptables -A FP-vnet0 -p all -j DROP +/usr/sbin/iptables -A HJ-vnet0 -p all -j DROP diff --git a/tests/nwfilterxml2firewalldata/example-1.xml b/tests/nwfilterxml2firewalldata/example-1.xml new file mode 100644 index 0000000..ad15a98 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/example-1.xml @@ -0,0 +1,24 @@ +<filter name='tck-testcase'> + <uuid>0a5288ea-612c-834a-6bbf-82a03a1a3244</uuid> + + <!-- allow incoming ssh connections --> + <rule action='accept' direction='in' priority='100'> + <tcp dstportstart='22'/> + </rule> + + <!-- allow incoming ICMP (ping) packets --> + <rule action='accept' direction='in' priority='200'> + <icmp/> + </rule> + + <!-- allow all outgoing traffic --> + <rule action='accept' direction='in' priority='300'> + <all/> + </rule> + + <!-- drop all other traffic --> + <rule action='drop' direction='inout' priority='1000'> + <all/> + </rule> + +</filter> diff --git a/tests/nwfilterxml2firewalldata/example-2-linux.args b/tests/nwfilterxml2firewalldata/example-2-linux.args new file mode 100644 index 0000000..445aa73 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/example-2-linux.args @@ -0,0 +1,20 @@ +/usr/sbin/iptables -A FJ-vnet0 -p all -m state --state ESTABLISHED,RELATED -m comment \ +--comment 'out: existing and related (ftp) connections' -j RETURN +/usr/sbin/iptables -A HJ-vnet0 -p all -m state --state ESTABLISHED,RELATED -m comment \ +--comment 'out: existing and related (ftp) connections' -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m state --state ESTABLISHED -m comment \ +--comment 'in: existing connections' -j ACCEPT +/usr/sbin/iptables -A FP-vnet0 -p tcp --dport 21:22 -m state --state NEW -m comment \ +--comment 'in: ftp and ssh' -j ACCEPT +/usr/sbin/iptables -A FP-vnet0 -p icmp -m state --state NEW -m comment \ +--comment 'in: icmp' -j ACCEPT +/usr/sbin/iptables -A FJ-vnet0 -p udp --dport 53 -m state --state NEW -m comment \ +--comment 'out: DNS lookups' -j RETURN +/usr/sbin/iptables -A HJ-vnet0 -p udp --dport 53 -m state --state NEW -m comment \ +--comment 'out: DNS lookups' -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -m comment \ +--comment 'inout: drop all non-accepted traffic' -j DROP +/usr/sbin/iptables -A FP-vnet0 -p all -m comment \ +--comment 'inout: drop all non-accepted traffic' -j DROP +/usr/sbin/iptables -A HJ-vnet0 -p all -m comment \ +--comment 'inout: drop all non-accepted traffic' -j DROP diff --git a/tests/nwfilterxml2firewalldata/example-2.xml b/tests/nwfilterxml2firewalldata/example-2.xml new file mode 100644 index 0000000..7bda4e6 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/example-2.xml @@ -0,0 +1,37 @@ +<filter name='tck-testcase'> + <uuid>0a5288ea-612c-834a-6bbf-82a03a1a3244</uuid> + + <!-- VM outgoing: allow all established and related connections --> + <rule action='accept' direction='out' priority='100'> + <all state='ESTABLISHED,RELATED' + comment='out: existing and related (ftp) connections'/> + </rule> + + <!-- VM incoming: allow all established connections --> + <rule action='accept' direction='in' priority='100'> + <all state='ESTABLISHED' + comment='in: existing connections'/> + </rule> + + <!-- allow incoming ssh and ftp traffic --> + <rule action='accept' direction='in' priority='200'> + <tcp dstportstart='21' dstportend='22' state='NEW' + comment='in: ftp and ssh'/> + </rule> + + <!-- allow incoming ICMP (ping) packets --> + <rule action='accept' direction='in' priority='300'> + <icmp state='NEW' comment='in: icmp'/> + </rule> + + <!-- allow outgong DNS lookups --> + <rule action='accept' direction='out' priority='300'> + <udp dstportstart='53' state='NEW' comment='out: DNS lookups'/> + </rule> + + <!-- drop all other traffic --> + <rule action='drop' direction='inout' priority='1000'> + <all comment='inout: drop all non-accepted traffic'/> + </rule> + +</filter> diff --git a/tests/nwfilterxml2firewalldata/hex-data-linux.args b/tests/nwfilterxml2firewalldata/hex-data-linux.args new file mode 100644 index 0000000..209c863 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/hex-data-linux.args @@ -0,0 +1,28 @@ +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -p 0x1234 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p ipv4 --ip-source 10.1.2.3/32 \ +--ip-destination 10.1.2.3/32 --ip-protocol 17 --ip-source-port 291:564 \ +--ip-destination-port 13398:17767 --ip-tos 0x32 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:fe \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:80 -p ipv6 --ip6-source ::10.1.2.3/22 \ +--ip6-destination ::10.1.2.3/113 --ip6-protocol 6 --ip6-source-port 273:400 \ +--ip6-destination-port 13107:65535 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x806 --arp-htype 18 --arp-opcode 1 \ +--arp-ptype 0x56 --arp-mac-src 01:02:03:04:05:06 --arp-mac-dst 0a:0b:0c:0d:0e:0f \ +-j ACCEPT +/usr/sbin/iptables -A FJ-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 34 --sport 291:400 --dport 564:1092 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --source 10.1.2.3/32 -m dscp --dscp 34 \ +--dport 291:400 --sport 564:1092 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 34 --sport 291:400 --dport 564:1092 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p tcp --destination a:b:c::/128 -m dscp --dscp 57 \ +--dport 32:33 --sport 256:4369 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--source a:b:c::/128 -m dscp --dscp 57 --sport 32:33 --dport 256:4369 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p tcp --destination a:b:c::/128 -m dscp --dscp 57 \ +--dport 32:33 --sport 256:4369 -m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/hex-data.xml b/tests/nwfilterxml2firewalldata/hex-data.xml new file mode 100644 index 0000000..45df451 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/hex-data.xml @@ -0,0 +1,56 @@ +<filter name='tck-testcase'> + <uuid>01a992d2-f8c8-7c27-f69b-ab0a9d377379</uuid> + + <rule action='accept' direction='in'> + <mac protocolid='0x1234'/> + </rule> + + <rule action='accept' direction='out'> + <ip srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + srcipaddr='10.1.2.3' srcipmask='255.255.255.255' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + protocol='udp' + srcportstart='0x123' srcportend='0x234' + dstportstart='0x3456' dstportend='0x4567' + dscp='0x32'/> + </rule> + + <rule action='accept' direction='out'> + <ipv6 srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:fe' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:80' + srcipaddr='::10.1.2.3' srcipmask='22' + dstipaddr='::10.1.2.3' + dstipmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000' + protocol='tcp' + srcportstart='0x111' srcportend='400' + dstportstart='0x3333' dstportend='65535'/> + </rule> + + <rule action='accept' direction='out'> + <arp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + hwtype='0x12' + protocoltype='0x56' + opcode='Request' + arpsrcmacaddr='1:2:3:4:5:6' + arpdstmacaddr='a:b:c:d:e:f'/> + </rule> + + <rule action='accept' direction='out'> + <udp srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='0x22' + srcportstart='0x123' srcportend='400' + dstportstart='0x234' dstportend='0x444'/> + </rule> + + <rule action='accept' direction='in'> + <tcp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='a:b:c::' srcipmask='128' + dscp='0x39' + srcportstart='0x20' srcportend='0x21' + dstportstart='0x100' dstportend='0x1111'/> + </rule> + +</filter> diff --git a/tests/nwfilterxml2firewalldata/icmp-direction-linux.args b/tests/nwfilterxml2firewalldata/icmp-direction-linux.args new file mode 100644 index 0000000..b4df953 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmp-direction-linux.args @@ -0,0 +1,9 @@ +/usr/sbin/iptables -A FP-vnet0 -p icmp --icmp-type 0 -m state --state NEW,ESTABLISHED \ +-j ACCEPT +/usr/sbin/iptables -A FJ-vnet0 -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/iptables -A HJ-vnet0 -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p icmp -j DROP +/usr/sbin/iptables -A FP-vnet0 -p icmp -j DROP +/usr/sbin/iptables -A HJ-vnet0 -p icmp -j DROP diff --git a/tests/nwfilterxml2firewalldata/icmp-direction.xml b/tests/nwfilterxml2firewalldata/icmp-direction.xml new file mode 100644 index 0000000..e2184e8 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmp-direction.xml @@ -0,0 +1,15 @@ +<filter name='tck-testcase'> + <uuid>f4b3f745-d23d-2ee6-218a-d5671611229b</uuid> + <!-- allow incoming ICMP Echo Reply --> + <rule action='accept' direction='in' priority='500'> + <icmp type='0'/> + </rule> + <!-- allow outgoing ICMP Echo Request --> + <rule action='accept' direction='out' priority='500'> + <icmp type='8'/> + </rule> + <!-- drop all other ICMP traffic --> + <rule action='drop' direction='inout' priority='600'> + <icmp/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/icmp-direction2-linux.args b/tests/nwfilterxml2firewalldata/icmp-direction2-linux.args new file mode 100644 index 0000000..fe1e316 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmp-direction2-linux.args @@ -0,0 +1,9 @@ +/usr/sbin/iptables -A FP-vnet0 -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED \ +-j ACCEPT +/usr/sbin/iptables -A FJ-vnet0 -p icmp --icmp-type 0 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/iptables -A HJ-vnet0 -p icmp --icmp-type 0 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p icmp -j DROP +/usr/sbin/iptables -A FP-vnet0 -p icmp -j DROP +/usr/sbin/iptables -A HJ-vnet0 -p icmp -j DROP diff --git a/tests/nwfilterxml2firewalldata/icmp-direction2.xml b/tests/nwfilterxml2firewalldata/icmp-direction2.xml new file mode 100644 index 0000000..a552985 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmp-direction2.xml @@ -0,0 +1,15 @@ +<filter name='tck-testcase'> + <uuid>d6b1a2af-def6-2898-9f8d-4a74e3c39558</uuid> + <!-- allow incoming ICMP Echo Request --> + <rule action='accept' direction='in' priority='500'> + <icmp type='8'/> + </rule> + <!-- allow outgoing ICMP Echo Reply --> + <rule action='accept' direction='out' priority='500'> + <icmp type='0'/> + </rule> + <!-- drop all other ICMP traffic --> + <rule action='drop' direction='inout' priority='600'> + <icmp/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/icmp-direction3-linux.args b/tests/nwfilterxml2firewalldata/icmp-direction3-linux.args new file mode 100644 index 0000000..31fa70e --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmp-direction3-linux.args @@ -0,0 +1,6 @@ +/usr/sbin/iptables -A FJ-vnet0 -p icmp -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p icmp -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p icmp -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -j DROP +/usr/sbin/iptables -A FP-vnet0 -p all -j DROP +/usr/sbin/iptables -A HJ-vnet0 -p all -j DROP diff --git a/tests/nwfilterxml2firewalldata/icmp-direction3.xml b/tests/nwfilterxml2firewalldata/icmp-direction3.xml new file mode 100644 index 0000000..c592903 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmp-direction3.xml @@ -0,0 +1,10 @@ +<filter name='tck-testcase'> + <uuid>d6b1a2af-def6-2898-9f8d-4a74e3c39558</uuid> + <rule action='accept' direction='out' priority='500'> + <icmp/> + </rule> + <!-- drop all other traffic --> + <rule action='drop' direction='inout' priority='600'> + <all/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/icmp-linux.args b/tests/nwfilterxml2firewalldata/icmp-linux.args new file mode 100644 index 0000000..b09941d --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmp-linux.args @@ -0,0 +1,9 @@ +/usr/sbin/iptables -A FJ-vnet0 -p icmp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 --icmp-type 12/11 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A HJ-vnet0 -p icmp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 --icmp-type 12/11 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p icmp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 --icmp-type 255/255 -m state \ +--state NEW,ESTABLISHED -j ACCEPT diff --git a/tests/nwfilterxml2firewalldata/icmp.xml b/tests/nwfilterxml2firewalldata/icmp.xml new file mode 100644 index 0000000..fff5d42 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmp.xml @@ -0,0 +1,13 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <icmp srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2' type='12' code='11'/> + </rule> + <rule action='accept' direction='in'> + <icmp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33' type='255' code='255'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/icmpv6-linux.args b/tests/nwfilterxml2firewalldata/icmpv6-linux.args new file mode 100644 index 0000000..f4dd2af --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmpv6-linux.args @@ -0,0 +1,12 @@ +/usr/sbin/ip6tables -A FJ-vnet0 -p icmpv6 -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 \ +--icmpv6-type 12/11 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A HJ-vnet0 -p icmpv6 -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 \ +--icmpv6-type 12/11 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p icmpv6 -m mac --mac-source 01:02:03:04:05:06 \ +--source a:b:c::/128 -m dscp --dscp 33 --icmpv6-type 255/255 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A FP-vnet0 -p icmpv6 -m mac --mac-source 01:02:03:04:05:06 \ +--source ::10.1.2.3/128 -m dscp --dscp 33 --icmpv6-type 255/255 -m state \ +--state NEW,ESTABLISHED -j ACCEPT diff --git a/tests/nwfilterxml2firewalldata/icmpv6.xml b/tests/nwfilterxml2firewalldata/icmpv6.xml new file mode 100644 index 0000000..9d24826 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/icmpv6.xml @@ -0,0 +1,19 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <icmpv6 srcmacaddr='1:2:3:4:5:6' + dstipaddr='a:b:c::d:e:f' dstipmask='128' + srcipaddr='f:e:d::c:b:a' srcipmask='127' + dscp='2' type='12' code='11'/> + </rule> + <rule action='accept' direction='in'> + <icmpv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='a:b:c::' srcipmask='128' + dscp='33' type='255' code='255'/> + </rule> + <rule action='accept' direction='in'> + <icmpv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='::10.1.2.3' srcipmask='128' + dscp='33' type='255' code='255'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/igmp-linux.args b/tests/nwfilterxml2firewalldata/igmp-linux.args new file mode 100644 index 0000000..b3b3ba3 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/igmp-linux.args @@ -0,0 +1,18 @@ +/usr/sbin/iptables -A FJ-vnet0 -p igmp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p igmp --source 10.1.2.3/32 -m dscp --dscp 2 -m state \ +--state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p igmp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p igmp --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p igmp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p igmp --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p igmp --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p igmp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p igmp --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/igmp.xml b/tests/nwfilterxml2firewalldata/igmp.xml new file mode 100644 index 0000000..0f4dcd4 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/igmp.xml @@ -0,0 +1,18 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <igmp srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <igmp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> + <rule action='accept' direction='in'> + <igmp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/ip-linux.args b/tests/nwfilterxml2firewalldata/ip-linux.args new file mode 100644 index 0000000..a577a60 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ip-linux.args @@ -0,0 +1,8 @@ +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p ipv4 --ip-source 10.1.2.3/32 \ +--ip-destination 10.1.2.3/32 --ip-protocol 17 --ip-source-port 20:22 \ +--ip-destination-port 100:101 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -p ipv4 --ip-source 10.1.2.3/17 \ +--ip-destination 10.1.2.3/24 --ip-protocol 17 --ip-tos 0x3f -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -p ipv4 --ip-source 10.1.2.3/31 \ +--ip-destination 10.1.2.3/25 --ip-protocol 255 --ip-tos 0x3f -j ACCEPT diff --git a/tests/nwfilterxml2firewalldata/ip.xml b/tests/nwfilterxml2firewalldata/ip.xml new file mode 100644 index 0000000..da362a1 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ip.xml @@ -0,0 +1,28 @@ +<filter name='tck-testcase'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <ip srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + srcipaddr='10.1.2.3' srcipmask='255.255.255.255' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + protocol='udp' + srcportstart='20' srcportend='22' + dstportstart='100' dstportend='101' + /> + </rule> + + <rule action='accept' direction='out'> + <ip srcipaddr='10.1.2.3' srcipmask='255.255.128.0' + dstipaddr='10.1.2.3' dstipmask='255.255.255.0' + protocol='17' dscp='63' + /> + </rule> + + <rule action='accept' direction='in'> + <ip srcipaddr='10.1.2.3' srcipmask='255.255.255.254' + dstipaddr='10.1.2.3' dstipmask='255.255.255.128' + protocol='255' dscp='63' + /> + </rule> + +</filter> diff --git a/tests/nwfilterxml2firewalldata/ipset-linux.args b/tests/nwfilterxml2firewalldata/ipset-linux.args new file mode 100644 index 0000000..4eeb208 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ipset-linux.args @@ -0,0 +1,36 @@ +/usr/sbin/iptables -A FJ-vnet0 -p all -m state --state NEW,ESTABLISHED -m set \ +--match-set tck_test src,dst -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m state --state ESTABLISHED -m set \ +--match-set tck_test dst,src -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m state --state NEW,ESTABLISHED -m set \ +--match-set tck_test src,dst -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m set --match-set tck_test src,dst -m comment \ +--comment in+NONE -j ACCEPT +/usr/sbin/iptables -A FJ-vnet0 -p all -m set --match-set tck_test src,dst -m comment \ +--comment out+NONE -j RETURN +/usr/sbin/iptables -A HJ-vnet0 -p all -m set --match-set tck_test src,dst -m comment \ +--comment out+NONE -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -m state --state ESTABLISHED -m set \ +--match-set tck_test dst,src,dst -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m state --state NEW,ESTABLISHED -m set \ +--match-set tck_test src,dst,src -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m state --state ESTABLISHED -m set \ +--match-set tck_test dst,src,dst -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -m state --state ESTABLISHED -m set \ +--match-set tck_test dst,src,dst -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m state --state NEW,ESTABLISHED -m set \ +--match-set tck_test src,dst,src -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m state --state ESTABLISHED -m set \ +--match-set tck_test dst,src,dst -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -m state --state ESTABLISHED -m set \ +--match-set tck_test dst,src -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m state --state NEW,ESTABLISHED -m set \ +--match-set tck_test src,dst -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m state --state ESTABLISHED -m set \ +--match-set tck_test dst,src -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -m set --match-set tck_test dst,src -m comment \ +--comment inout -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m set --match-set tck_test src,dst -m comment \ +--comment inout -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m set --match-set tck_test dst,src -m comment \ +--comment inout -j RETURN diff --git a/tests/nwfilterxml2firewalldata/ipset.xml b/tests/nwfilterxml2firewalldata/ipset.xml new file mode 100644 index 0000000..cc8ccc4 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ipset.xml @@ -0,0 +1,25 @@ +<!-- #ipset help && iptables -t match-set -h && ipset list tck_test || ipset create tck_test hash:ip# --> +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <all ipset='tck_test' ipsetflags='src,dst' /> + </rule> + <rule action='accept' direction='in'> + <all state='NONE' ipset='tck_test' ipsetflags='src,dst' comment='in+NONE'/> + </rule> + <rule action='accept' direction='out'> + <all state='NONE' ipset='tck_test' ipsetflags='src,dst' comment='out+NONE'/> + </rule> + <rule action='accept' direction='in'> + <all ipset='tck_test' ipsetflags='SRC,DST,SRC' /> + </rule> + <rule action='accept' direction='in'> + <all ipset='tck_test' ipsetflags='SRC,dSt,SRC' /> + </rule> + <rule action='accept' direction='in'> + <all ipset='$IPSETNAME' ipsetflags='src,dst' /> + </rule> + <rule action='accept' direction='inout'> + <all ipset='$IPSETNAME' ipsetflags='src,dst' comment='inout'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/ipt-no-macspoof-linux.args b/tests/nwfilterxml2firewalldata/ipt-no-macspoof-linux.args new file mode 100644 index 0000000..f74f449 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ipt-no-macspoof-linux.args @@ -0,0 +1,2 @@ +/usr/sbin/iptables -A FP-vnet0 -p all -m mac '!' --mac-source 12:34:56:78:9a:bc -j DROP +/usr/sbin/iptables -A FP-vnet0 -p all -m mac '!' --mac-source aa:aa:aa:aa:aa:aa -j DROP diff --git a/tests/nwfilterxml2firewalldata/ipt-no-macspoof.xml b/tests/nwfilterxml2firewalldata/ipt-no-macspoof.xml new file mode 100644 index 0000000..2e8f2ce --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ipt-no-macspoof.xml @@ -0,0 +1,14 @@ +<filter name='tck-testcase'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='drop' direction='inout'> + <!-- should use $MAC for MAC address, but tests would depend on VM's + MAC address --> + <all match='no' srcmacaddr='12:34:56:78:9a:bc'/> + </rule> + + <rule action='drop' direction='in'> + <!-- not accepting incoming traffic from a certain MAC address --> + <all match='no' srcmacaddr='aa:aa:aa:aa:aa:aa'/> + </rule> + +</filter> diff --git a/tests/nwfilterxml2firewalldata/ipv6-linux.args b/tests/nwfilterxml2firewalldata/ipv6-linux.args new file mode 100644 index 0000000..e6674f6 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ipv6-linux.args @@ -0,0 +1,20 @@ +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:fe \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:80 -p ipv6 --ip6-source ::10.1.2.3/22 \ +--ip6-destination ::10.1.2.3/113 --ip6-protocol 17 --ip6-source-port 20:22 \ +--ip6-destination-port 100:101 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -p ipv6 --ip6-destination 1::2/128 \ +--ip6-source a:b:c::/65 --ip6-protocol 6 --ip6-destination-port 20:22 \ +--ip6-source-port 100:101 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -p ipv6 --ip6-source 1::2/128 \ +--ip6-destination a:b:c::/65 --ip6-protocol 6 --ip6-source-port 20:22 \ +--ip6-destination-port 100:101 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -p ipv6 --ip6-destination 1::2/128 \ +--ip6-source a:b:c::/65 --ip6-protocol 6 --ip6-destination-port 255:256 \ +--ip6-source-port 65535:65535 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -p ipv6 --ip6-source 1::2/128 \ +--ip6-destination a:b:c::/65 --ip6-protocol 6 --ip6-source-port 255:256 \ +--ip6-destination-port 65535:65535 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -p ipv6 --ip6-destination 1::2/128 \ +--ip6-source a:b:c::/65 --ip6-protocol 18 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -p ipv6 --ip6-source 1::2/128 \ +--ip6-destination a:b:c::/65 --ip6-protocol 18 -j ACCEPT diff --git a/tests/nwfilterxml2firewalldata/ipv6.xml b/tests/nwfilterxml2firewalldata/ipv6.xml new file mode 100644 index 0000000..9f67bea --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ipv6.xml @@ -0,0 +1,43 @@ +<filter name='tck-testcase'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <ipv6 srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:fe' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:80' + srcipaddr='::10.1.2.3' srcipmask='22' + dstipaddr='::10.1.2.3' + dstipmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000' + protocol='udp' + srcportstart='20' srcportend='22' + dstportstart='100' dstportend='101' + /> + </rule> + + <rule action='accept' direction='inout'> + <ipv6 srcipaddr='1::2' srcipmask='128' + dstipaddr='a:b:c::' + dstipmask='ffff:ffff:ffff:ffff:8000::' + protocol='6' + srcportstart='20' srcportend='22' + dstportstart='100' dstportend='101' + /> + </rule> + + <rule action='accept' direction='inout'> + <ipv6 srcipaddr='1::2' srcipmask='128' + dstipaddr='a:b:c::' + dstipmask='ffff:ffff:ffff:ffff:8000::' + protocol='6' + srcportstart='255' srcportend='256' + dstportstart='65535' dstportend='65535' + /> + </rule> + + <rule action='accept' direction='inout'> + <ipv6 srcipaddr='1::2' srcipmask='128' + dstipaddr='a:b:c::' + dstipmask='ffff:ffff:ffff:ffff:8000::' + protocol='18' + /> + </rule> + +</filter> diff --git a/tests/nwfilterxml2firewalldata/iter1-linux.args b/tests/nwfilterxml2firewalldata/iter1-linux.args new file mode 100644 index 0000000..5d8d213 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/iter1-linux.args @@ -0,0 +1,18 @@ +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 2 --dport 80 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 2 --dport 90 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 2 --dport 80 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/iter1.xml b/tests/nwfilterxml2firewalldata/iter1.xml new file mode 100644 index 0000000..c2090e6 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/iter1.xml @@ -0,0 +1,6 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <tcp srcipaddr='$A' srcportstart='$B' dscp='2'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/iter2-linux.args b/tests/nwfilterxml2firewalldata/iter2-linux.args new file mode 100644 index 0000000..42d9e92 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/iter2-linux.args @@ -0,0 +1,342 @@ +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 1 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 1 --dport 80 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 1 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 1 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 1 --dport 90 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 1 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 1 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 1 --dport 80 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 1 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 1.1.1.1 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 1.1.1.1 -m dscp --dscp 2 --dport 80 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 1.1.1.1 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 2.2.2.2 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 2.2.2.2 -m dscp --dscp 2 --dport 80 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 2.2.2.2 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 3.3.3.3 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 3.3.3.3 -m dscp --dscp 2 --dport 80 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 3.3.3.3 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 1.1.1.1 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 1.1.1.1 -m dscp --dscp 2 --dport 90 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 1.1.1.1 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 2.2.2.2 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 2.2.2.2 -m dscp --dscp 2 --dport 90 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 2.2.2.2 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 3.3.3.3 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 3.3.3.3 -m dscp --dscp 2 --dport 90 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 3.3.3.3 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 1.1.1.1 -m dscp --dscp 3 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 1.1.1.1 -m dscp --dscp 3 \ +--dport 80 --sport 1080 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 1.1.1.1 -m dscp --dscp 3 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 2.2.2.2 -m dscp --dscp 3 \ +--dport 80 --sport 1080 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 3.3.3.3 -m dscp --dscp 3 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 3.3.3.3 -m dscp --dscp 3 \ +--dport 80 --sport 1080 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 3.3.3.3 -m dscp --dscp 3 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 1.1.1.1 -m dscp --dscp 3 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 1.1.1.1 -m dscp --dscp 3 \ +--dport 90 --sport 1090 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 1.1.1.1 -m dscp --dscp 3 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 2.2.2.2 -m dscp --dscp 3 \ +--dport 90 --sport 1090 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 3.3.3.3 -m dscp --dscp 3 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 3.3.3.3 -m dscp --dscp 3 \ +--dport 90 --sport 1090 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 3.3.3.3 -m dscp --dscp 3 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 1.1.1.1 -m dscp --dscp 3 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 1.1.1.1 -m dscp --dscp 3 \ +--dport 80 --sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 1.1.1.1 -m dscp --dscp 3 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 2.2.2.2 -m dscp --dscp 3 \ +--dport 80 --sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 3.3.3.3 -m dscp --dscp 3 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 3.3.3.3 -m dscp --dscp 3 \ +--dport 80 --sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 3.3.3.3 -m dscp --dscp 3 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 1.1.1.1 -m dscp --dscp 3 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 1.1.1.1 -m dscp --dscp 3 \ +--dport 80 --sport 1110 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 1.1.1.1 -m dscp --dscp 3 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 2.2.2.2 -m dscp --dscp 3 \ +--dport 80 --sport 1110 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 3.3.3.3 -m dscp --dscp 3 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 3.3.3.3 -m dscp --dscp 3 \ +--dport 80 --sport 1110 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 3.3.3.3 -m dscp --dscp 3 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 4 --dport 80 \ +--sport 1080 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 4 --dport 80 \ +--sport 1080 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 4 --dport 80 \ +--sport 1080 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 80 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 90 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 4 --dport 90 \ +--sport 1080 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 90 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 90 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 4 --dport 90 \ +--sport 1080 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 90 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 90 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 4 --dport 90 \ +--sport 1080 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 90 \ +--dport 1080 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 80 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 4 --dport 80 \ +--sport 1090 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 80 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 80 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 4 --dport 80 \ +--sport 1090 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 80 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 80 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 4 --dport 80 \ +--sport 1090 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 80 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 4 --dport 90 \ +--sport 1090 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 4 --dport 90 \ +--sport 1090 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 4 --dport 90 \ +--sport 1090 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 90 \ +--dport 1090 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 4 --dport 80 \ +--sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 4 --dport 80 \ +--sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 4 --dport 80 \ +--sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 90 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 4 --dport 90 \ +--sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 90 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 90 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 4 --dport 90 \ +--sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 90 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 90 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 4 --dport 90 \ +--sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 90 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 4 --dport 80 \ +--sport 1110 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 4 --dport 80 \ +--sport 1110 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 4 --dport 80 \ +--sport 1110 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 80 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 90 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 4 --dport 90 \ +--sport 1110 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 4 --sport 90 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 90 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 2.2.2.2 -m dscp --dscp 4 --dport 90 \ +--sport 1110 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 2.2.2.2 -m dscp --dscp 4 --sport 90 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 90 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 3.3.3.3 -m dscp --dscp 4 --dport 90 \ +--sport 1110 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 3.3.3.3 -m dscp --dscp 4 --sport 90 \ +--dport 1110 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 1.1.1.1 --destination 1.1.1.1 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 1.1.1.1 --source 1.1.1.1 -m dscp \ +--dscp 5 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 1.1.1.1 --destination 1.1.1.1 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 2.2.2.2 --destination 1.1.1.1 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 2.2.2.2 --source 1.1.1.1 -m dscp \ +--dscp 5 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 2.2.2.2 --destination 1.1.1.1 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 3.3.3.3 --destination 1.1.1.1 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 3.3.3.3 --source 1.1.1.1 -m dscp \ +--dscp 5 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 3.3.3.3 --destination 1.1.1.1 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 1.1.1.1 --destination 2.2.2.2 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 1.1.1.1 --source 2.2.2.2 -m dscp \ +--dscp 5 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 1.1.1.1 --destination 2.2.2.2 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 2.2.2.2 --destination 2.2.2.2 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 2.2.2.2 --source 2.2.2.2 -m dscp \ +--dscp 5 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 2.2.2.2 --destination 2.2.2.2 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 3.3.3.3 --destination 2.2.2.2 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 3.3.3.3 --source 2.2.2.2 -m dscp \ +--dscp 5 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 3.3.3.3 --destination 2.2.2.2 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 1.1.1.1 --destination 3.3.3.3 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 1.1.1.1 --source 3.3.3.3 -m dscp \ +--dscp 5 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 1.1.1.1 --destination 3.3.3.3 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 2.2.2.2 --destination 3.3.3.3 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 2.2.2.2 --source 3.3.3.3 -m dscp \ +--dscp 5 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 2.2.2.2 --destination 3.3.3.3 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 3.3.3.3 --destination 3.3.3.3 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 3.3.3.3 --source 3.3.3.3 -m dscp \ +--dscp 5 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 3.3.3.3 --destination 3.3.3.3 -m dscp \ +--dscp 5 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 1.1.1.1 --destination 1.1.1.1 -m dscp \ +--dscp 6 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 1.1.1.1 --source 1.1.1.1 -m dscp \ +--dscp 6 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 1.1.1.1 --destination 1.1.1.1 -m dscp \ +--dscp 6 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 2.2.2.2 --destination 2.2.2.2 -m dscp \ +--dscp 6 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 2.2.2.2 --source 2.2.2.2 -m dscp \ +--dscp 6 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 2.2.2.2 --destination 2.2.2.2 -m dscp \ +--dscp 6 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 3.3.3.3 --destination 3.3.3.3 -m dscp \ +--dscp 6 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 3.3.3.3 --source 3.3.3.3 -m dscp \ +--dscp 6 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 3.3.3.3 --destination 3.3.3.3 -m dscp \ +--dscp 6 -m state --state NEW,ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/iter2.xml b/tests/nwfilterxml2firewalldata/iter2.xml new file mode 100644 index 0000000..3a3174a --- /dev/null +++ b/tests/nwfilterxml2firewalldata/iter2.xml @@ -0,0 +1,23 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <tcp srcipaddr='$A' srcportstart='$B[@0]' dscp='1'/> + </rule> + <rule action='accept' direction='out'> + <udp srcipaddr='$A[@1]' srcportstart='$B[@2]' dscp='2'/> + </rule> + <rule action='accept' direction='out'> + <sctp srcipaddr='$A[@1]' srcportstart='$B[@2]' dstportstart='$C[@2]' + dscp='3'/> + </rule> + <rule action='accept' direction='out'> + <tcp srcipaddr='$A[@1]' srcportstart='$B[@2]' dstportstart='$C[@3]' + dscp='4'/> + </rule> + <rule action='accept' direction='out'> + <udp srcipaddr='$A[@1]' dstipaddr='$A[@2]' dscp='5'/> + </rule> + <rule action='accept' direction='out'> + <sctp srcipaddr='$A' dstipaddr='$A' dscp='6'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/iter3-linux.args b/tests/nwfilterxml2firewalldata/iter3-linux.args new file mode 100644 index 0000000..c74338c --- /dev/null +++ b/tests/nwfilterxml2firewalldata/iter3-linux.args @@ -0,0 +1,30 @@ +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 1 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 1 --dport 80 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 1 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 1 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --destination 1.1.1.1 -m dscp --dscp 1 --dport 90 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --source 1.1.1.1 -m dscp --dscp 1 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 2.2.2.2 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 2.2.2.2 -m dscp --dscp 2 --dport 80 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 2.2.2.2 -m dscp --dscp 2 --sport 80 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --source 2.2.2.2 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --destination 2.2.2.2 -m dscp --dscp 2 --dport 90 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --source 2.2.2.2 -m dscp --dscp 2 --sport 90 \ +-m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --destination 2.2.2.2 -m dscp --dscp 3 \ +--dport 80 --sport 1100 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --source 2.2.2.2 -m dscp --dscp 3 --sport 80 \ +--dport 1100 -m state --state NEW,ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/iter3.xml b/tests/nwfilterxml2firewalldata/iter3.xml new file mode 100644 index 0000000..47f5096 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/iter3.xml @@ -0,0 +1,13 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <tcp srcipaddr='$A[ 0]' srcportstart='$B[ @0 ] ' dscp='1'/> + </rule> + <rule action='accept' direction='out'> + <udp srcipaddr='$A[1 ]' srcportstart='$B[ @2 ]' dscp='2'/> + </rule> + <rule action='accept' direction='out'> + <sctp srcipaddr='$A[ 1 ] ' srcportstart='$B[2 ] ' dstportstart='$C[ 2 ]' + dscp='3'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/mac-linux.args b/tests/nwfilterxml2firewalldata/mac-linux.args new file mode 100644 index 0000000..d03b706 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/mac-linux.args @@ -0,0 +1,8 @@ +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x806 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff \ +-p 0x800 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff \ +-p 0x600 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff \ +-p 0xffff -j ACCEPT diff --git a/tests/nwfilterxml2firewalldata/mac.xml b/tests/nwfilterxml2firewalldata/mac.xml new file mode 100644 index 0000000..2aec935 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/mac.xml @@ -0,0 +1,19 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <mac srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + protocolid='arp'/> + </rule> + <rule action='accept' direction='in'> + <mac dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + protocolid='ipv4'/> + </rule> + <rule action='accept' direction='in'> + <mac dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + protocolid='1536'/> + </rule> + <rule action='accept' direction='in'> + <mac dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + protocolid='65535'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/rarp-linux.args b/tests/nwfilterxml2firewalldata/rarp-linux.args new file mode 100644 index 0000000..c100470 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/rarp-linux.args @@ -0,0 +1,12 @@ +/usr/sbin/ebtables -t nat -N libvirt-J-vnet0 +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x8035 --arp-htype 12 --arp-opcode 1 \ +--arp-ptype 0x22 --arp-mac-src 01:02:03:04:05:06 --arp-mac-dst 0a:0b:0c:0d:0e:0f \ +-j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x8035 --arp-htype 255 --arp-opcode 1 --arp-ptype 0xff -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x8035 --arp-htype 256 --arp-opcode 11 --arp-ptype 0x100 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x8035 --arp-htype 65535 --arp-opcode 65535 --arp-ptype 0xffff -j ACCEPT +/usr/sbin/ebtables -t nat -A PREROUTING -i vnet0 -j libvirt-J-vnet0 diff --git a/tests/nwfilterxml2firewalldata/rarp.xml b/tests/nwfilterxml2firewalldata/rarp.xml new file mode 100644 index 0000000..77c1127 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/rarp.xml @@ -0,0 +1,28 @@ +<filter name='tck-testcase'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <rarp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + protocolid='rarp' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + hwtype='12' + protocoltype='34' + opcode='Request' + arpsrcmacaddr='1:2:3:4:5:6' + arpdstmacaddr='a:b:c:d:e:f'/> + </rule> + + <rule action='accept' direction='out'> + <rarp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + opcode='1' hwtype='255' protocoltype='255'/> + </rule> + + <rule action='accept' direction='out'> + <rarp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + opcode='11' hwtype='256' protocoltype='256'/> + </rule> + + <rule action='accept' direction='out'> + <rarp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + opcode='65535' hwtype='65535' protocoltype='65535' /> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/ref-rule.xml b/tests/nwfilterxml2firewalldata/ref-rule.xml new file mode 100644 index 0000000..5cb2fad --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ref-rule.xml @@ -0,0 +1,18 @@ +<filter name='tck-testcase'> + <uuid>83011800-f663-96d6-8841-fd836b4318c6</uuid> + <filterref filter='clean-traffic'/> + <rule action='accept' direction='out'> + <mac srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + protocolid='arp'/> + </rule> + <rule action='accept' direction='out'> + <tcp srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2'/> + </rule> + <rule action='accept' direction='out'> + <udp-ipv6 srcmacaddr='1:2:3:4:5:6' + dstipaddr='a:b:c::d:e:f' dstipmask='128' + dscp='2'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/ref.xml b/tests/nwfilterxml2firewalldata/ref.xml new file mode 100644 index 0000000..beb46d2 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/ref.xml @@ -0,0 +1,4 @@ +<filter name='tck-testcase'> + <uuid>83011800-f663-96d6-8841-fd836b4318c6</uuid> + <filterref filter='clean-traffic'/> +</filter> diff --git a/tests/nwfilterxml2firewalldata/sctp-ipv6-linux.args b/tests/nwfilterxml2firewalldata/sctp-ipv6-linux.args new file mode 100644 index 0000000..956ab82 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/sctp-ipv6-linux.args @@ -0,0 +1,22 @@ +/usr/sbin/ip6tables -A FJ-vnet0 -p sctp -m mac --mac-source 01:02:03:04:05:06 \ +--destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p sctp --source a:b:c::d:e:f/128 -m dscp --dscp 2 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p sctp -m mac --mac-source 01:02:03:04:05:06 \ +--destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p sctp --destination a:b:c::/128 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p sctp -m mac --mac-source 01:02:03:04:05:06 \ +--source a:b:c::/128 -m dscp --dscp 33 --sport 20:21 --dport 100:1111 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p sctp --destination a:b:c::/128 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p sctp --destination ::10.1.2.3/128 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p sctp -m mac --mac-source 01:02:03:04:05:06 \ +--source ::10.1.2.3/128 -m dscp --dscp 63 --sport 255:256 --dport 65535:65535 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p sctp --destination ::10.1.2.3/128 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/sctp-ipv6.xml b/tests/nwfilterxml2firewalldata/sctp-ipv6.xml new file mode 100644 index 0000000..d1a57b8 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/sctp-ipv6.xml @@ -0,0 +1,22 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <sctp-ipv6 srcmacaddr='1:2:3:4:5:6' + dstipaddr='a:b:c::d:e:f' dstipmask='128' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <sctp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='a:b:c::' srcipmask='128' + dscp='33' + srcportstart='20' srcportend='21' + dstportstart='100' dstportend='1111'/> + </rule> + <rule action='accept' direction='in'> + <sctp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='::10.1.2.3' srcipmask='128' + dscp='63' + srcportstart='255' srcportend='256' + dstportstart='65535' dstportend='65535'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/sctp-linux.args b/tests/nwfilterxml2firewalldata/sctp-linux.args new file mode 100644 index 0000000..643db68 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/sctp-linux.args @@ -0,0 +1,20 @@ +/usr/sbin/iptables -A FJ-vnet0 -p sctp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp --source 10.1.2.3/32 -m dscp --dscp 2 -m state \ +--state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --destination 10.1.2.3/32 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/32 -m dscp --dscp 33 --sport 20:21 --dport 100:1111 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --destination 10.1.2.3/32 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p sctp --destination 10.1.2.3/32 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p sctp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/32 -m dscp --dscp 63 --sport 255:256 --dport 65535:65535 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p sctp --destination 10.1.2.3/32 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/sctp.xml b/tests/nwfilterxml2firewalldata/sctp.xml new file mode 100644 index 0000000..c3c1000 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/sctp.xml @@ -0,0 +1,22 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <sctp srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <sctp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='32' + dscp='33' + srcportstart='20' srcportend='21' + dstportstart='100' dstportend='1111'/> + </rule> + <rule action='accept' direction='in'> + <sctp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='32' + dscp='63' + srcportstart='255' srcportend='256' + dstportstart='65535' dstportend='65535'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/stp-linux.args b/tests/nwfilterxml2firewalldata/stp-linux.args new file mode 100644 index 0000000..4f66836 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/stp-linux.args @@ -0,0 +1,18 @@ +/usr/sbin/ebtables -t nat -F J-vnet0-stp-xyz +/usr/sbin/ebtables -t nat -X J-vnet0-stp-xyz +/usr/sbin/ebtables -t nat -N J-vnet0-stp-xyz +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -d 01:80:c2:00:00:00 -j J-vnet0-stp-xyz +/usr/sbin/ebtables -t nat -F P-vnet0-stp-xyz +/usr/sbin/ebtables -t nat -X P-vnet0-stp-xyz +/usr/sbin/ebtables -t nat -N P-vnet0-stp-xyz +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d 01:80:c2:00:00:00 -j P-vnet0-stp-xyz +/usr/sbin/ebtables -t nat -A P-vnet0-stp-xyz -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d 01:80:c2:00:00:00 --stp-type 18 --stp-flags 68 -j CONTINUE +/usr/sbin/ebtables -t nat -A J-vnet0-stp-xyz -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d 01:80:c2:00:00:00 --stp-root-pri 4660:9029 \ +--stp-root-addr 06:05:04:03:02:01/ff:ff:ff:ff:ff:ff \ +--stp-root-cost 287454020:573785173 -j RETURN +/usr/sbin/ebtables -t nat -A P-vnet0-stp-xyz -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d 01:80:c2:00:00:00 --stp-sender-prio 4660 --stp-sender-addr 06:05:04:03:02:01 \ +--stp-port 123:234 --stp-msg-age 5544:5555 --stp-max-age 7777:8888 \ +--stp-hello-time 12345:12346 --stp-forward-delay 54321:65432 -j DROP diff --git a/tests/nwfilterxml2firewalldata/stp.xml b/tests/nwfilterxml2firewalldata/stp.xml new file mode 100644 index 0000000..6b5a625 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/stp.xml @@ -0,0 +1,26 @@ +<filter name='tck-testcase' chain='stp-xyz'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='continue' direction='in'> + <stp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + type='0x12' flags='0x44'/> + </rule> + + <rule action='return' direction='out'> + <stp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + root-priority='0x1234' root-priority-hi='0x2345' + root-address="6:5:4:3:2:1" root-address-mask='ff:ff:ff:ff:ff:ff' + root-cost='0x11223344' root-cost-hi='0x22334455' /> + </rule> + + <rule action='reject' direction='in'> + <stp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + sender-priority='0x1234' + sender-address="6:5:4:3:2:1" + port='123' port-hi='234' + age='5544' age-hi='5555' + max-age='7777' max-age-hi='8888' + hello-time='12345' hello-time-hi='12346' + forward-delay='54321' forward-delay-hi='65432'/> + </rule> + +</filter> diff --git a/tests/nwfilterxml2firewalldata/target-linux.args b/tests/nwfilterxml2firewalldata/target-linux.args new file mode 100644 index 0000000..bf3b2dc --- /dev/null +++ b/tests/nwfilterxml2firewalldata/target-linux.args @@ -0,0 +1,75 @@ +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x806 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x806 -j DROP +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-p 0x806 -j DROP +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff \ +-p 0x800 -j ACCEPT +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff \ +-p 0x800 -j DROP +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff \ +-p 0x800 -j DROP +/usr/sbin/iptables -A FJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -m comment \ +--comment 'accept rule -- dir out' -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all --source 10.1.2.3/32 -m dscp --dscp 2 -m state \ +--state ESTABLISHED -m comment --comment 'accept rule -- dir out' -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -m comment \ +--comment 'accept rule -- dir out' -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m comment \ +--comment 'drop rule -- dir out' -j DROP +/usr/sbin/iptables -A FP-vnet0 -p all --source 10.1.2.3/32 -m dscp --dscp 2 -m comment \ +--comment 'drop rule -- dir out' -j DROP +/usr/sbin/iptables -A HJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m comment \ +--comment 'drop rule -- dir out' -j DROP +/usr/sbin/iptables -A FJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m comment \ +--comment 'reject rule -- dir out' -j REJECT +/usr/sbin/iptables -A FP-vnet0 -p all --source 10.1.2.3/32 -m dscp --dscp 2 \ +-m comment --comment 'reject rule -- dir out' -j REJECT +/usr/sbin/iptables -A HJ-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m comment \ +--comment 'reject rule -- dir out' -j REJECT +/usr/sbin/iptables -A FJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -m comment --comment 'accept rule -- dir in' -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -m comment \ +--comment 'accept rule -- dir in' -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m state --state ESTABLISHED -m comment --comment 'accept rule -- dir in' -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m comment --comment 'drop rule -- dir in' -j DROP +/usr/sbin/iptables -A FP-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m comment --comment 'drop rule -- dir in' \ +-j DROP +/usr/sbin/iptables -A HJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m comment --comment 'drop rule -- dir in' -j DROP +/usr/sbin/iptables -A FJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m comment --comment 'reject rule -- dir in' -j REJECT +/usr/sbin/iptables -A FP-vnet0 -p all -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m comment --comment 'reject rule -- dir in' \ +-j REJECT +/usr/sbin/iptables -A HJ-vnet0 -p all --destination 10.1.2.3/22 -m dscp --dscp 33 \ +-m comment --comment 'reject rule -- dir in' -j REJECT +/usr/sbin/iptables -A FJ-vnet0 -p all -m comment --comment 'accept rule -- dir inout' \ +-j RETURN +/usr/sbin/iptables -A FP-vnet0 -p all -m comment --comment 'accept rule -- dir inout' \ +-j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p all -m comment --comment 'accept rule -- dir inout' \ +-j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p all -m comment --comment 'drop rule -- dir inout' \ +-j DROP +/usr/sbin/iptables -A FP-vnet0 -p all -m comment --comment 'drop rule -- dir inout' \ +-j DROP +/usr/sbin/iptables -A HJ-vnet0 -p all -m comment --comment 'drop rule -- dir inout' \ +-j DROP +/usr/sbin/iptables -A FJ-vnet0 -p all -m comment --comment 'reject rule -- dir inout' \ +-j REJECT +/usr/sbin/iptables -A FP-vnet0 -p all -m comment --comment 'reject rule -- dir inout' \ +-j REJECT +/usr/sbin/iptables -A HJ-vnet0 -p all -m comment --comment 'reject rule -- dir inout' \ +-j REJECT diff --git a/tests/nwfilterxml2firewalldata/target.xml b/tests/nwfilterxml2firewalldata/target.xml new file mode 100644 index 0000000..aa7465b --- /dev/null +++ b/tests/nwfilterxml2firewalldata/target.xml @@ -0,0 +1,66 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <all srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2' comment='accept rule -- dir out'/> + </rule> + <rule action='drop' direction='out'> + <all srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2' comment='drop rule -- dir out'/> + </rule> + <rule action='reject' direction='out'> + <all srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2' comment='reject rule -- dir out'/> + </rule> + <rule action='accept' direction='in'> + <all srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33' comment='accept rule -- dir in'/> + </rule> + <rule action='drop' direction='in'> + <all srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33' comment='drop rule -- dir in'/> + </rule> + <rule action='reject' direction='in'> + <all srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33' comment='reject rule -- dir in'/> + </rule> + <rule action='accept' direction='inout'> + <all comment='accept rule -- dir inout'/> + </rule> + <rule action='drop' direction='in'> + <all comment='drop rule -- dir inout'/> + </rule> + <rule action='reject' direction='in'> + <all comment='reject rule -- dir inout'/> + </rule> + <rule action='accept' direction='out'> + <mac srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + protocolid='arp'/> + </rule> + <rule action='drop' direction='out'> + <mac srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + protocolid='arp'/> + </rule> + <rule action='reject' direction='out'> + <mac srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + protocolid='arp'/> + </rule> + <rule action='accept' direction='in'> + <mac dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + protocolid='ipv4'/> + </rule> + <rule action='drop' direction='in'> + <mac dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + protocolid='ipv4'/> + </rule> + <rule action='reject' direction='in'> + <mac dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + protocolid='ipv4'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/target2-linux.args b/tests/nwfilterxml2firewalldata/target2-linux.args new file mode 100644 index 0000000..a1e4c86 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/target2-linux.args @@ -0,0 +1,13 @@ +/usr/sbin/iptables -A FP-vnet0 -p tcp --dport 22 -j ACCEPT +/usr/sbin/iptables -A FJ-vnet0 -p tcp --sport 22 -j RETURN +/usr/sbin/iptables -A HJ-vnet0 -p tcp --sport 22 -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --sport 80 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED \ +-j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --sport 80 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp -j REJECT +/usr/sbin/iptables -A FP-vnet0 -p tcp -j REJECT +/usr/sbin/iptables -A HJ-vnet0 -p tcp -j REJECT +/usr/sbin/iptables -A FJ-vnet0 -p all -j DROP +/usr/sbin/iptables -A FP-vnet0 -p all -j DROP +/usr/sbin/iptables -A HJ-vnet0 -p all -j DROP diff --git a/tests/nwfilterxml2firewalldata/target2.xml b/tests/nwfilterxml2firewalldata/target2.xml new file mode 100644 index 0000000..c913bf5 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/target2.xml @@ -0,0 +1,18 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='in'> + <tcp dstportstart='22' state='NONE'/> + </rule> + <rule action='accept' direction='out'> + <tcp srcportstart='22' state='NONE'/> + </rule> + <rule action='accept' direction='in'> + <tcp dstportstart='80'/> + </rule> + <rule action='reject' direction='inout'> + <tcp/> + </rule> + <rule action='drop' direction='inout'> + <all/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/tcp-ipv6-linux.args b/tests/nwfilterxml2firewalldata/tcp-ipv6-linux.args new file mode 100644 index 0000000..836937f --- /dev/null +++ b/tests/nwfilterxml2firewalldata/tcp-ipv6-linux.args @@ -0,0 +1,22 @@ +/usr/sbin/ip6tables -A FJ-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p tcp --source a:b:c::d:e:f/128 -m dscp --dscp 2 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p tcp --destination a:b:c::/128 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--source a:b:c::/128 -m dscp --dscp 33 --sport 20:21 --dport 100:1111 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p tcp --destination a:b:c::/128 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p tcp --destination ::10.1.2.3/128 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--source ::10.1.2.3/128 -m dscp --dscp 63 --sport 255:256 --dport 65535:65535 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p tcp --destination ::10.1.2.3/128 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/tcp-ipv6.xml b/tests/nwfilterxml2firewalldata/tcp-ipv6.xml new file mode 100644 index 0000000..d4f24f4 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/tcp-ipv6.xml @@ -0,0 +1,22 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <tcp-ipv6 srcmacaddr='1:2:3:4:5:6' + dstipaddr='a:b:c::d:e:f' dstipmask='128' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <tcp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='a:b:c::' srcipmask='128' + dscp='33' + srcportstart='20' srcportend='21' + dstportstart='100' dstportend='1111'/> + </rule> + <rule action='accept' direction='in'> + <tcp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='::10.1.2.3' srcipmask='128' + dscp='63' + srcportstart='255' srcportend='256' + dstportstart='65535' dstportend='65535'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/tcp-linux.args b/tests/nwfilterxml2firewalldata/tcp-linux.args new file mode 100644 index 0000000..c8e351b --- /dev/null +++ b/tests/nwfilterxml2firewalldata/tcp-linux.args @@ -0,0 +1,22 @@ +/usr/sbin/iptables -A FJ-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --source 10.1.2.3/32 -m dscp --dscp 2 -m state \ +--state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --destination 10.1.2.3/32 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/32 -m dscp --dscp 33 --sport 20:21 --dport 100:1111 -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --destination 10.1.2.3/32 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p tcp --destination 10.1.2.3/32 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/32 -m dscp --dscp 63 --sport 255:256 --dport 65535:65535 -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p tcp --destination 10.1.2.3/32 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p tcp --tcp-flags SYN ALL -j ACCEPT +/usr/sbin/iptables -A FP-vnet0 -p tcp --tcp-flags SYN SYN,ACK -j ACCEPT +/usr/sbin/iptables -A FP-vnet0 -p tcp --tcp-flags RST NONE -j ACCEPT +/usr/sbin/iptables -A FP-vnet0 -p tcp --tcp-flags PSH NONE -j ACCEPT diff --git a/tests/nwfilterxml2firewalldata/tcp.xml b/tests/nwfilterxml2firewalldata/tcp.xml new file mode 100644 index 0000000..14ebd35 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/tcp.xml @@ -0,0 +1,34 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <tcp srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2'/> + </rule> + <rule action='accept' direction='in' statematch='false'> + <tcp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='32' + dscp='33' + srcportstart='20' srcportend='21' + dstportstart='100' dstportend='1111'/> + </rule> + <rule action='accept' direction='in' statematch='0'> + <tcp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='32' + dscp='63' + srcportstart='255' srcportend='256' + dstportstart='65535' dstportend='65535'/> + </rule> + <rule action='accept' direction='in'> + <tcp state='NONE' flags='SYN/ALL'/> + </rule> + <rule action='accept' direction='in'> + <tcp state='NONE' flags='SYN/SYN,ACK'/> + </rule> + <rule action='accept' direction='in'> + <tcp state='NONE' flags='RST/NONE'/> + </rule> + <rule action='accept' direction='in'> + <tcp state='NONE' flags='PSH/'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/udp-ipv6-linux.args b/tests/nwfilterxml2firewalldata/udp-ipv6-linux.args new file mode 100644 index 0000000..d9e2060 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/udp-ipv6-linux.args @@ -0,0 +1,22 @@ +/usr/sbin/ip6tables -A FJ-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p udp --source a:b:c::d:e:f/128 -m dscp --dscp 2 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED \ +-j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p udp --destination ::a:b:c/128 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--source ::a:b:c/128 -m dscp --dscp 33 --sport 20:21 --dport 100:1111 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p udp --destination ::a:b:c/128 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p udp --destination ::10.1.2.3/128 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--source ::10.1.2.3/128 -m dscp --dscp 63 --sport 255:256 --dport 65535:65535 \ +-m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p udp --destination ::10.1.2.3/128 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/udp-ipv6.xml b/tests/nwfilterxml2firewalldata/udp-ipv6.xml new file mode 100644 index 0000000..fd4f135 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/udp-ipv6.xml @@ -0,0 +1,22 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <udp-ipv6 srcmacaddr='1:2:3:4:5:6' + dstipaddr='a:b:c::d:e:f' dstipmask='128' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <udp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='::a:b:c' srcipmask='128' + dscp='33' + srcportstart='20' srcportend='21' + dstportstart='100' dstportend='1111'/> + </rule> + <rule action='accept' direction='in'> + <udp-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='::10.1.2.3' srcipmask='128' + dscp='63' + srcportstart='255' srcportend='256' + dstportstart='65535' dstportend='65535'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/udp-linux.args b/tests/nwfilterxml2firewalldata/udp-linux.args new file mode 100644 index 0000000..8638d8d --- /dev/null +++ b/tests/nwfilterxml2firewalldata/udp-linux.args @@ -0,0 +1,20 @@ +/usr/sbin/iptables -A FJ-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp --source 10.1.2.3/32 -m dscp --dscp 2 -m state \ +--state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --destination 10.1.2.3/32 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/32 -m dscp --dscp 33 --sport 20:21 --dport 100:1111 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --destination 10.1.2.3/32 -m dscp --dscp 33 \ +--dport 20:21 --sport 100:1111 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udp --destination 10.1.2.3/32 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udp -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/32 -m dscp --dscp 63 --sport 255:256 --dport 65535:65535 -m state \ +--state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udp --destination 10.1.2.3/32 -m dscp --dscp 63 \ +--dport 255:256 --sport 65535:65535 -m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/udp.xml b/tests/nwfilterxml2firewalldata/udp.xml new file mode 100644 index 0000000..359dfa2 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/udp.xml @@ -0,0 +1,22 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <udp srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <udp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='32' + dscp='33' + srcportstart='20' srcportend='21' + dstportstart='100' dstportend='1111'/> + </rule> + <rule action='accept' direction='in'> + <udp srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='32' + dscp='63' + srcportstart='255' srcportend='256' + dstportstart='65535' dstportend='65535'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/udplite-ipv6-linux.args b/tests/nwfilterxml2firewalldata/udplite-ipv6-linux.args new file mode 100644 index 0000000..22d37e5 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/udplite-ipv6-linux.args @@ -0,0 +1,20 @@ +/usr/sbin/ip6tables -A FJ-vnet0 -p udplite -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p udplite --destination f:e:d::c:b:a/127 \ +--source a:b:c::d:e:f/128 -m dscp --dscp 2 -m state --state ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p udplite -m mac --mac-source 01:02:03:04:05:06 \ +--source f:e:d::c:b:a/127 --destination a:b:c::d:e:f/128 -m dscp --dscp 2 -m state \ +--state NEW,ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p udplite --destination a:b:c::/128 -m dscp \ +--dscp 33 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p udplite -m mac --mac-source 01:02:03:04:05:06 \ +--source a:b:c::/128 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p udplite --destination a:b:c::/128 -m dscp \ +--dscp 33 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FJ-vnet0 -p udplite --destination ::10.1.2.3/128 -m dscp \ +--dscp 33 -m state --state ESTABLISHED -j RETURN +/usr/sbin/ip6tables -A FP-vnet0 -p udplite -m mac --mac-source 01:02:03:04:05:06 \ +--source ::10.1.2.3/128 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/ip6tables -A HJ-vnet0 -p udplite --destination ::10.1.2.3/128 -m dscp \ +--dscp 33 -m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/udplite-ipv6.xml b/tests/nwfilterxml2firewalldata/udplite-ipv6.xml new file mode 100644 index 0000000..5b941a2 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/udplite-ipv6.xml @@ -0,0 +1,19 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <udplite-ipv6 srcmacaddr='1:2:3:4:5:6' + dstipaddr='a:b:c::d:e:f' dstipmask='128' + srcipaddr='f:e:d::c:b:a' srcipmask='127' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <udplite-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='a:b:c::' srcipmask='128' + dscp='33'/> + </rule> + <rule action='accept' direction='in'> + <udplite-ipv6 srcmacaddr='1:2:3:4:5:6' + srcipaddr='::10.1.2.3' srcipmask='128' + dscp='33'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/udplite-linux.args b/tests/nwfilterxml2firewalldata/udplite-linux.args new file mode 100644 index 0000000..52ca3df --- /dev/null +++ b/tests/nwfilterxml2firewalldata/udplite-linux.args @@ -0,0 +1,18 @@ +/usr/sbin/iptables -A FJ-vnet0 -p udplite -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udplite --source 10.1.2.3/32 -m dscp --dscp 2 \ +-m state --state ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udplite -m mac --mac-source 01:02:03:04:05:06 \ +--destination 10.1.2.3/32 -m dscp --dscp 2 -m state --state NEW,ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udplite --destination 10.1.2.3/22 -m dscp \ +--dscp 33 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udplite -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udplite --destination 10.1.2.3/22 -m dscp \ +--dscp 33 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FJ-vnet0 -p udplite --destination 10.1.2.3/22 -m dscp \ +--dscp 33 -m state --state ESTABLISHED -j RETURN +/usr/sbin/iptables -A FP-vnet0 -p udplite -m mac --mac-source 01:02:03:04:05:06 \ +--source 10.1.2.3/22 -m dscp --dscp 33 -m state --state NEW,ESTABLISHED -j ACCEPT +/usr/sbin/iptables -A HJ-vnet0 -p udplite --destination 10.1.2.3/22 -m dscp \ +--dscp 33 -m state --state ESTABLISHED -j RETURN diff --git a/tests/nwfilterxml2firewalldata/udplite.xml b/tests/nwfilterxml2firewalldata/udplite.xml new file mode 100644 index 0000000..91262fd --- /dev/null +++ b/tests/nwfilterxml2firewalldata/udplite.xml @@ -0,0 +1,18 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='accept' direction='out'> + <udplite srcmacaddr='1:2:3:4:5:6' + dstipaddr='10.1.2.3' dstipmask='255.255.255.255' + dscp='2'/> + </rule> + <rule action='accept' direction='in'> + <udplite srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> + <rule action='accept' direction='in'> + <udplite srcmacaddr='1:2:3:4:5:6' + srcipaddr='10.1.2.3' srcipmask='22' + dscp='33'/> + </rule> +</filter> diff --git a/tests/nwfilterxml2firewalldata/vlan-linux.args b/tests/nwfilterxml2firewalldata/vlan-linux.args new file mode 100644 index 0000000..6f858f1 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/vlan-linux.args @@ -0,0 +1,14 @@ +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -d 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-s aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x8100 --vlan-id 291 -j CONTINUE +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x8100 --vlan-id 291 -j CONTINUE +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -d 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-s aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x8100 --vlan-id 1234 -j RETURN +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x8100 --vlan-id 1234 -j RETURN +/usr/sbin/ebtables -t nat -A libvirt-P-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x8100 --vlan-id 291 -j DROP +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x8100 --vlan-encap 2054 -j DROP +/usr/sbin/ebtables -t nat -A libvirt-J-vnet0 -s 01:02:03:04:05:06/ff:ff:ff:ff:ff:ff \ +-d aa:bb:cc:dd:ee:ff/ff:ff:ff:ff:ff:ff -p 0x8100 --vlan-encap 4660 -j ACCEPT diff --git a/tests/nwfilterxml2firewalldata/vlan.xml b/tests/nwfilterxml2firewalldata/vlan.xml new file mode 100644 index 0000000..a5e7b38 --- /dev/null +++ b/tests/nwfilterxml2firewalldata/vlan.xml @@ -0,0 +1,38 @@ +<filter name='tck-testcase' chain='root'> + <uuid>5c6d49af-b071-6127-b4ec-6f8ed4b55335</uuid> + <rule action='continue' direction='inout'> + <vlan srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + vlanid='0x123' + /> + </rule> + + <rule action='return' direction='inout'> + <vlan srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + vlanid='1234' + /> + </rule> + + <rule action='reject' direction='in'> + <vlan srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + vlanid='0x123' + /> + </rule> + + <rule action='drop' direction='out'> + <vlan srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + encap-protocol='arp' + /> + </rule> + + <rule action='accept' direction='out'> + <vlan srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' + dstmacaddr='aa:bb:cc:dd:ee:ff' dstmacmask='ff:ff:ff:ff:ff:ff' + encap-protocol='0x1234' + /> + </rule> + +</filter> diff --git a/tests/nwfilterxml2firewalltest.c b/tests/nwfilterxml2firewalltest.c new file mode 100644 index 0000000..653ac82 --- /dev/null +++ b/tests/nwfilterxml2firewalltest.c @@ -0,0 +1,534 @@ +/* + * nwfilterxml2firewalltest.c: Test iptables 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 + * <http://www.gnu.org/licenses/>. + * + */ + +#include <config.h> + +#if defined (__linux__) + +# 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 const char *abs_top_srcdir; + +# ifdef __linux__ +# define RULESTYPE "linux" +# else +# error "test case not ported to this platform" +# endif + +typedef struct _virNWFilterInst virNWFilterInst; +typedef virNWFilterInst *virNWFilterInstPtr; +struct _virNWFilterInst { + virNWFilterDefPtr *filters; + size_t nfilters; + virNWFilterRuleInstPtr *rules; + size_t nrules; +}; + +/* + * Some sets of rules that will be common to all test files, + * so we don't bother including them in the test data files + * as that would just bloat them + */ + +static const char *commonRules[] = { + /* Dropping ebtables rules */ + "/usr/sbin/ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -L libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -F libvirt-P-vnet0\n" + "/usr/sbin/ebtables -t nat -X libvirt-P-vnet0\n", + + /* Creating ebtables chains */ + "/usr/sbin/ebtables -t nat -N libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -N libvirt-P-vnet0\n", + + /* Dropping iptables rules */ + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n" + "/usr/sbin/iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n" + "/usr/sbin/iptables -F FP-vnet0\n" + "/usr/sbin/iptables -X FP-vnet0\n" + "/usr/sbin/iptables -F FJ-vnet0\n" + "/usr/sbin/iptables -X FJ-vnet0\n" + "/usr/sbin/iptables -F HJ-vnet0\n" + "/usr/sbin/iptables -X HJ-vnet0\n", + + /* Creating iptables chains */ + "/usr/sbin/iptables -N libvirt-in\n" + "/usr/sbin/iptables -N libvirt-out\n" + "/usr/sbin/iptables -N libvirt-in-post\n" + "/usr/sbin/iptables -N libvirt-host-in\n" + "/usr/sbin/iptables -D FORWARD -j libvirt-in\n" + "/usr/sbin/iptables -D FORWARD -j libvirt-out\n" + "/usr/sbin/iptables -D FORWARD -j libvirt-in-post\n" + "/usr/sbin/iptables -D INPUT -j libvirt-host-in\n" + "/usr/sbin/iptables -I FORWARD 1 -j libvirt-in\n" + "/usr/sbin/iptables -I FORWARD 2 -j libvirt-out\n" + "/usr/sbin/iptables -I FORWARD 3 -j libvirt-in-post\n" + "/usr/sbin/iptables -I INPUT 1 -j libvirt-host-in\n" + "/usr/sbin/iptables -N FP-vnet0\n" + "/usr/sbin/iptables -N FJ-vnet0\n" + "/usr/sbin/iptables -N HJ-vnet0\n" + "/usr/sbin/iptables -A libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/iptables -A libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n" + "/usr/sbin/iptables -A libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n" + "/usr/sbin/iptables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/iptables -A libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n", + + /* Dropping ip6tables rules */ + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n" + "/usr/sbin/ip6tables -F FP-vnet0\n" + "/usr/sbin/ip6tables -X FP-vnet0\n" + "/usr/sbin/ip6tables -F FJ-vnet0\n" + "/usr/sbin/ip6tables -X FJ-vnet0\n" + "/usr/sbin/ip6tables -F HJ-vnet0\n" + "/usr/sbin/ip6tables -X HJ-vnet0\n", + + /* Creating ip6tables chains */ + "/usr/sbin/ip6tables -N libvirt-in\n" + "/usr/sbin/ip6tables -N libvirt-out\n" + "/usr/sbin/ip6tables -N libvirt-in-post\n" + "/usr/sbin/ip6tables -N libvirt-host-in\n" + "/usr/sbin/ip6tables -D FORWARD -j libvirt-in\n" + "/usr/sbin/ip6tables -D FORWARD -j libvirt-out\n" + "/usr/sbin/ip6tables -D FORWARD -j libvirt-in-post\n" + "/usr/sbin/ip6tables -D INPUT -j libvirt-host-in\n" + "/usr/sbin/ip6tables -I FORWARD 1 -j libvirt-in\n" + "/usr/sbin/ip6tables -I FORWARD 2 -j libvirt-out\n" + "/usr/sbin/ip6tables -I FORWARD 3 -j libvirt-in-post\n" + "/usr/sbin/ip6tables -I INPUT 1 -j libvirt-host-in\n" + "/usr/sbin/ip6tables -N FP-vnet0\n" + "/usr/sbin/ip6tables -N FJ-vnet0\n" + "/usr/sbin/ip6tables -N HJ-vnet0\n" + "/usr/sbin/ip6tables -A libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n" + "/usr/sbin/ip6tables -A libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n" + "/usr/sbin/ip6tables -A libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n" + "/usr/sbin/ip6tables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n" + "/usr/sbin/ip6tables -A libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n", + + /* Inserting ebtables rules */ + "/usr/sbin/ebtables -t nat -A PREROUTING -i vnet0 -j libvirt-J-vnet0\n" + "/usr/sbin/ebtables -t nat -A POSTROUTING -o vnet0 -j libvirt-P-vnet0\n", +}; + + +static virNWFilterHashTablePtr +virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1, + virNWFilterHashTablePtr vars2) +{ + virNWFilterHashTablePtr res = virNWFilterHashTableCreate(0); + if (!res) + return NULL; + + if (virNWFilterHashTablePutAll(vars1, res) < 0) + goto err_exit; + + if (virNWFilterHashTablePutAll(vars2, res) < 0) + goto err_exit; + + return res; + + err_exit: + virNWFilterHashTableFree(res); + return NULL; +} + + +static void +virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst) +{ + if (!inst) + return; + + virNWFilterHashTableFree(inst->vars); + VIR_FREE(inst); +} + + +static void +virNWFilterInstReset(virNWFilterInstPtr inst) +{ + size_t i; + + for (i = 0; i < inst->nfilters; i++) + virNWFilterDefFree(inst->filters[i]); + VIR_FREE(inst->filters); + inst->nfilters = 0; + + for (i = 0; i < inst->nrules; i++) + virNWFilterRuleInstFree(inst->rules[i]); + inst->nrules = 0; + VIR_FREE(inst->rules); +} + + +static int +virNWFilterDefToInst(const char *xml, + virNWFilterHashTablePtr vars, + virNWFilterInstPtr inst); + +static int +virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def, + virNWFilterRuleDefPtr rule, + virNWFilterHashTablePtr vars, + virNWFilterInstPtr inst) +{ + virNWFilterRuleInstPtr ruleinst; + int ret = -1; + + if (VIR_ALLOC(ruleinst) < 0) + goto cleanup; + + ruleinst->chainSuffix = def->chainsuffix; + ruleinst->chainPriority = def->chainPriority; + ruleinst->def = rule; + ruleinst->priority = rule->priority; + if (!(ruleinst->vars = virNWFilterHashTableCreate(0))) + goto cleanup; + if (virNWFilterHashTablePutAll(vars, ruleinst->vars) < 0) + goto cleanup; + + if (VIR_APPEND_ELEMENT(inst->rules, + inst->nrules, + ruleinst) < 0) + goto cleanup; + ruleinst = NULL; + + ret = 0; + cleanup: + virNWFilterRuleInstFree(ruleinst); + return ret; +} + + +static int +virNWFilterIncludeDefToRuleInst(virNWFilterIncludeDefPtr inc, + virNWFilterHashTablePtr vars, + virNWFilterInstPtr inst) +{ + virNWFilterHashTablePtr tmpvars = NULL; + int ret = -1; + char *xml; + + if (virAsprintf(&xml, "%s/nwfilterxml2firewalldata/%s.xml", + abs_srcdir, inc->filterref) < 0) + return -1; + + /* create a temporary hashmap for depth-first tree traversal */ + if (!(tmpvars = virNWFilterCreateVarsFrom(inc->params, + vars))) + goto cleanup; + + if (virNWFilterDefToInst(xml, + tmpvars, + inst) < 0) + goto cleanup; + + ret = 0; + cleanup: + if (ret < 0) + virNWFilterInstReset(inst); + virNWFilterHashTableFree(tmpvars); + VIR_FREE(xml); + return ret; +} + +static int +virNWFilterDefToInst(const char *xml, + virNWFilterHashTablePtr vars, + virNWFilterInstPtr inst) +{ + size_t i; + int ret = -1; + virNWFilterDefPtr def = virNWFilterDefParseFile(xml); + + if (!def) + return -1; + + if (VIR_APPEND_ELEMENT_COPY(inst->filters, + inst->nfilters, + def) < 0) { + virNWFilterDefFree(def); + goto cleanup; + } + + for (i = 0; i < def->nentries; i++) { + if (def->filterEntries[i]->rule) { + if (virNWFilterRuleDefToRuleInst(def, + def->filterEntries[i]->rule, + vars, + inst) < 0) + goto cleanup; + } else if (def->filterEntries[i]->include) { + if (virNWFilterIncludeDefToRuleInst(def->filterEntries[i]->include, + vars, + inst) < 0) + goto cleanup; + } + } + + ret = 0; + cleanup: + if (ret < 0) + virNWFilterInstReset(inst); + return ret; +} + + +static void testRemoveCommonRules(char *rules) +{ + size_t i; + char *offset = rules; + + for (i = 0; i < ARRAY_CARDINALITY(commonRules); i++) { + char *tmp = strstr(offset, commonRules[i]); + size_t len = strlen(commonRules[i]); + if (tmp) { + memmove(tmp, tmp + len, (strlen(tmp) + 1) - len); + offset = tmp; + } + } +} + + +static int testSetOneParameter(virNWFilterHashTablePtr vars, + const char *name, + const char *value) +{ + int ret = -1; + virNWFilterVarValuePtr val; + + if ((val = virHashLookup(vars->hashTable, name)) == NULL) { + val = virNWFilterVarValueCreateSimpleCopyValue(value); + if (!val) + goto cleanup; + if (virNWFilterHashTablePut(vars, name, val) < 0) { + virNWFilterVarValueFree(val); + goto cleanup; + } + } else { + if (virNWFilterVarValueAddValueCopy(val, value) < 0) + goto cleanup; + } + ret = 0; + cleanup: + return ret; +} + +static int testSetDefaultParameters(virNWFilterHashTablePtr vars) +{ + if (testSetOneParameter(vars, "IPSETNAME", "tck_test") < 0 || + testSetOneParameter(vars, "A", "1.1.1.1") || + testSetOneParameter(vars, "A", "2.2.2.2") || + testSetOneParameter(vars, "A", "3.3.3.3") || + testSetOneParameter(vars, "A", "3.3.3.3") || + testSetOneParameter(vars, "B", "80") || + testSetOneParameter(vars, "B", "90") || + testSetOneParameter(vars, "B", "80") || + testSetOneParameter(vars, "B", "80") || + testSetOneParameter(vars, "C", "1080") || + testSetOneParameter(vars, "C", "1090") || + testSetOneParameter(vars, "C", "1100") || + testSetOneParameter(vars, "C", "1110")) + return -1; + return 0; +} + +static int testCompareXMLToArgvFiles(const char *xml, + const char *cmdline) +{ + char *expectargv = NULL; + int len; + char *actualargv = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + virNWFilterHashTablePtr vars = virNWFilterHashTableCreate(0); + virNWFilterInst inst; + int ret = -1; + + memset(&inst, 0, sizeof(inst)); + + virCommandSetDryRun(&buf, NULL, NULL); + + if (!vars) + goto cleanup; + + if (testSetDefaultParameters(vars) < 0) + goto cleanup; + + if (virNWFilterDefToInst(xml, + vars, + &inst) < 0) + goto cleanup; + + if (ebiptables_driver.applyNewRules("vnet0", inst.rules, inst.nrules) < 0) + goto cleanup; + + if (virBufferError(&buf)) + goto cleanup; + + actualargv = virBufferContentAndReset(&buf); + virCommandSetDryRun(NULL, NULL, NULL); + + testRemoveCommonRules(actualargv); + + len = virtTestLoadFile(cmdline, &expectargv); + if (len < 0) + goto cleanup; + + if (STRNEQ(expectargv, actualargv)) { + virtTestDifference(stderr, expectargv, actualargv); + goto cleanup; + } + + ret = 0; + + cleanup: + virBufferFreeAndReset(&buf); + VIR_FREE(expectargv); + VIR_FREE(actualargv); + virNWFilterInstReset(&inst); + virNWFilterHashTableFree(vars); + return ret; +} + +struct testInfo { + const char *name; +}; + + +static int +testCompareXMLToIPTablesHelper(const void *data) +{ + int result = -1; + const struct testInfo *info = data; + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/nwfilterxml2firewalldata/%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&args, "%s/nwfilterxml2firewalldata/%s-%s.args", + abs_srcdir, info->name, RULESTYPE) < 0) + goto cleanup; + + result = testCompareXMLToArgvFiles(xml, args); + + cleanup: + VIR_FREE(xml); + VIR_FREE(args); + return result; +} + + +static int +mymain(void) +{ + int ret = 0; + + abs_top_srcdir = getenv("abs_top_srcdir"); + if (!abs_top_srcdir) + abs_top_srcdir = abs_srcdir "/.."; + +# define DO_TEST(name) \ + do { \ + static struct testInfo info = { \ + name, \ + }; \ + if (virtTestRun("NWFilter XML-2-firewall " name, \ + testCompareXMLToIPTablesHelper, &info) < 0) \ + ret = -1; \ + } while (0) + + if (virFirewallSetBackend(VIR_FIREWALL_BACKEND_DIRECT) < 0) { + ret = -1; + goto cleanup; + } + + DO_TEST("ah"); + DO_TEST("ah-ipv6"); + DO_TEST("all"); + DO_TEST("all-ipv6"); + DO_TEST("arp"); + DO_TEST("comment"); + DO_TEST("conntrack"); + DO_TEST("esp"); + DO_TEST("esp-ipv6"); + DO_TEST("example-1"); + DO_TEST("example-2"); + DO_TEST("hex-data"); + DO_TEST("icmp-direction2"); + DO_TEST("icmp-direction3"); + DO_TEST("icmp-direction"); + DO_TEST("icmp"); + DO_TEST("icmpv6"); + DO_TEST("igmp"); + DO_TEST("ip"); + DO_TEST("ipset"); + DO_TEST("ipt-no-macspoof"); + DO_TEST("ipv6"); + DO_TEST("iter1"); + DO_TEST("iter2"); + DO_TEST("iter3"); + DO_TEST("mac"); + DO_TEST("rarp"); + DO_TEST("sctp"); + DO_TEST("sctp-ipv6"); + DO_TEST("stp"); + DO_TEST("target2"); + DO_TEST("target"); + DO_TEST("tcp"); + DO_TEST("tcp-ipv6"); + DO_TEST("udp"); + DO_TEST("udp-ipv6"); + DO_TEST("udplite"); + DO_TEST("udplite-ipv6"); + DO_TEST("vlan"); + + cleanup: + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain) + +#else /* ! defined (__linux__) */ + +int main(void) +{ + return EXIT_AM_SKIP; +} + +#endif /* ! defined (__linux__) */ -- 1.9.0

On 04/08/2014 11:38 AM, Daniel P. Berrange wrote:
Create a nwfilterxml2firewalltest to exercise the ebiptables_driver.applyNewRules method with a variety of different XML input files. The XML input files are taken from the libvirt-tck nwfilter tests. While the nwfilter tests verify the final state of the iptables chains, this test verifies the set of commands invoked to create the chains.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
You are reusing the TCK tests. With TCK tests passing, the created commands must be correct.
+ +static void +virNWFilterInstReset(virNWFilterInstPtr inst) +{ + size_t i; + + for (i = 0; i < inst->nfilters; i++) + virNWFilterDefFree(inst->filters[i]); + VIR_FREE(inst->filters); + inst->nfilters = 0; + + for (i = 0; i < inst->nrules; i++) + virNWFilterRuleInstFree(inst->rules[i]); + inst->nrules = 0; + VIR_FREE(inst->rules); +}
The VIR_FREE(inst->rules) could be placed before the inst->nrules = 0 to match the pattern above :-) Not even a memory leak... ACK

On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
Currently we have three places which interact with the firewall
- util/virebtables - simple MAC filtering used by QEMU driver - util/viriptables - used by network driver - nwfilter - general purpose guest filtering
Oh my, so much work! -- Thanks I'll review as much as I can. Regards, Stefan

On Mon, Apr 14, 2014 at 04:47:50PM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
Currently we have three places which interact with the firewall
- util/virebtables - simple MAC filtering used by QEMU driver - util/viriptables - used by network driver - nwfilter - general purpose guest filtering
Oh my, so much work! -- Thanks
I'll review as much as I can.
Thanks, I appreciate any review you can do particularly of the big nwfilter patches, since you're main expert in that area. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 04/15/2014 04:29 AM, Daniel P. Berrange wrote:
On Mon, Apr 14, 2014 at 04:47:50PM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
Currently we have three places which interact with the firewall
- util/virebtables - simple MAC filtering used by QEMU driver - util/viriptables - used by network driver - nwfilter - general purpose guest filtering Oh my, so much work! -- Thanks
I'll review as much as I can. Thanks, I appreciate any review you can do particularly of the big nwfilter patches, since you're main expert in that area.
Some of the patches are so involved that besides looking at them I'll mostly have to rely on the TCK tests to see whether they still pass. The TCK tests unfortunately also need updating due to recent changes in the code (elimination of the source MAC tests in recent patches) as well as different output by the ip6tables command related to IPv6 addresses. Regards, Stefan

On Tue, Apr 15, 2014 at 07:40:41AM -0400, Stefan Berger wrote:
On 04/15/2014 04:29 AM, Daniel P. Berrange wrote:
On Mon, Apr 14, 2014 at 04:47:50PM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
Currently we have three places which interact with the firewall
- util/virebtables - simple MAC filtering used by QEMU driver - util/viriptables - used by network driver - nwfilter - general purpose guest filtering Oh my, so much work! -- Thanks
I'll review as much as I can. Thanks, I appreciate any review you can do particularly of the big nwfilter patches, since you're main expert in that area.
Some of the patches are so involved that besides looking at them I'll mostly have to rely on the TCK tests to see whether they still pass. The TCK tests unfortunately also need updating due to recent changes in the code (elimination of the source MAC tests in recent patches) as well as different output by the ip6tables command related to IPv6 addresses.
The TCK tests shouldn't need updating. The current libvirt-tck GIT master nwfilter tests pass against libvirt GIT master, and also pass after this patch series is applied (at least on Fedora 20). Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 04/15/2014 07:42 AM, Daniel P. Berrange wrote:
On Mon, Apr 14, 2014 at 04:47:50PM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
Currently we have three places which interact with the firewall
- util/virebtables - simple MAC filtering used by QEMU driver - util/viriptables - used by network driver - nwfilter - general purpose guest filtering Oh my, so much work! -- Thanks
I'll review as much as I can. Thanks, I appreciate any review you can do particularly of the big nwfilter patches, since you're main expert in that area. Some of the patches are so involved that besides looking at them I'll mostly have to rely on the TCK tests to see whether they still
On 04/15/2014 04:29 AM, Daniel P. Berrange wrote: pass. The TCK tests unfortunately also need updating due to recent changes in the code (elimination of the source MAC tests in recent patches) as well as different output by the ip6tables command related to IPv6 addresses. The TCK tests shouldn't need updating. The current libvirt-tck GIT master nwfilter tests pass against libvirt GIT master, and also
On Tue, Apr 15, 2014 at 07:40:41AM -0400, Stefan Berger wrote: pass after this patch series is applied (at least on Fedora 20).
That's interesting. I am running this on Fedora 18. This patch here https://www.redhat.com/archives/libvir-list/2014-March/msg00660.html is necessary on Fedora 18, but not on Fedora 20 I assume. Probably it was a temporary regression in iptables. Is this patch series incremental so that the TCK test suite should work after each one of them? At least for me it passes up to patch 7/26 but then patch 8/26 starts causing ip6tables related problems. Regards, Stefan

On Tue, Apr 15, 2014 at 10:04:01AM -0400, Stefan Berger wrote:
On 04/15/2014 07:42 AM, Daniel P. Berrange wrote:
On Mon, Apr 14, 2014 at 04:47:50PM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote:
Currently we have three places which interact with the firewall
- util/virebtables - simple MAC filtering used by QEMU driver - util/viriptables - used by network driver - nwfilter - general purpose guest filtering Oh my, so much work! -- Thanks
I'll review as much as I can. Thanks, I appreciate any review you can do particularly of the big nwfilter patches, since you're main expert in that area. Some of the patches are so involved that besides looking at them I'll mostly have to rely on the TCK tests to see whether they still
On 04/15/2014 04:29 AM, Daniel P. Berrange wrote: pass. The TCK tests unfortunately also need updating due to recent changes in the code (elimination of the source MAC tests in recent patches) as well as different output by the ip6tables command related to IPv6 addresses. The TCK tests shouldn't need updating. The current libvirt-tck GIT master nwfilter tests pass against libvirt GIT master, and also
On Tue, Apr 15, 2014 at 07:40:41AM -0400, Stefan Berger wrote: pass after this patch series is applied (at least on Fedora 20).
That's interesting. I am running this on Fedora 18. This patch here
https://www.redhat.com/archives/libvir-list/2014-March/msg00660.html
is necessary on Fedora 18, but not on Fedora 20 I assume. Probably it was a temporary regression in iptables.
Is this patch series incremental so that the TCK test suite should work after each one of them? At least for me it passes up to patch 7/26 but then patch 8/26 starts causing ip6tables related problems.
It was intended to be incremental, but I honestly haven't tested the TCK against the individual patches - only the end result. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 04/15/2014 10:06 AM, Daniel P. Berrange wrote:
On Tue, Apr 15, 2014 at 10:04:01AM -0400, Stefan Berger wrote:
On 04/15/2014 07:42 AM, Daniel P. Berrange wrote:
On Mon, Apr 14, 2014 at 04:47:50PM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote: > Currently we have three places which interact with the firewall > > - util/virebtables - simple MAC filtering used by QEMU driver > - util/viriptables - used by network driver > - nwfilter - general purpose guest filtering Oh my, so much work! -- Thanks
I'll review as much as I can. Thanks, I appreciate any review you can do particularly of the big nwfilter patches, since you're main expert in that area. Some of the patches are so involved that besides looking at them I'll mostly have to rely on the TCK tests to see whether they still
On 04/15/2014 04:29 AM, Daniel P. Berrange wrote: pass. The TCK tests unfortunately also need updating due to recent changes in the code (elimination of the source MAC tests in recent patches) as well as different output by the ip6tables command related to IPv6 addresses. The TCK tests shouldn't need updating. The current libvirt-tck GIT master nwfilter tests pass against libvirt GIT master, and also
On Tue, Apr 15, 2014 at 07:40:41AM -0400, Stefan Berger wrote: pass after this patch series is applied (at least on Fedora 20). That's interesting. I am running this on Fedora 18. This patch here
https://www.redhat.com/archives/libvir-list/2014-March/msg00660.html
is necessary on Fedora 18, but not on Fedora 20 I assume. Probably it was a temporary regression in iptables.
Is this patch series incremental so that the TCK test suite should work after each one of them? At least for me it passes up to patch 7/26 but then patch 8/26 starts causing ip6tables related problems. It was intended to be incremental, but I honestly haven't tested the TCK against the individual patches - only the end result.
The end result also works for me. Patch 23/26 corrects the ip6tables problem. Regards, Stefan

On 04/15/2014 10:06 AM, Daniel P. Berrange wrote:
On Tue, Apr 15, 2014 at 10:04:01AM -0400, Stefan Berger wrote:
On 04/15/2014 07:42 AM, Daniel P. Berrange wrote:
On Mon, Apr 14, 2014 at 04:47:50PM -0400, Stefan Berger wrote:
On 04/08/2014 11:37 AM, Daniel P. Berrange wrote: > Currently we have three places which interact with the firewall > > - util/virebtables - simple MAC filtering used by QEMU driver > - util/viriptables - used by network driver > - nwfilter - general purpose guest filtering Oh my, so much work! -- Thanks
I'll review as much as I can. Thanks, I appreciate any review you can do particularly of the big nwfilter patches, since you're main expert in that area. Some of the patches are so involved that besides looking at them I'll mostly have to rely on the TCK tests to see whether they still
On 04/15/2014 04:29 AM, Daniel P. Berrange wrote: pass. The TCK tests unfortunately also need updating due to recent changes in the code (elimination of the source MAC tests in recent patches) as well as different output by the ip6tables command related to IPv6 addresses. The TCK tests shouldn't need updating. The current libvirt-tck GIT master nwfilter tests pass against libvirt GIT master, and also
On Tue, Apr 15, 2014 at 07:40:41AM -0400, Stefan Berger wrote: pass after this patch series is applied (at least on Fedora 20). That's interesting. I am running this on Fedora 18. This patch here
https://www.redhat.com/archives/libvir-list/2014-March/msg00660.html
is necessary on Fedora 18, but not on Fedora 20 I assume. Probably it was a temporary regression in iptables.
Is this patch series incremental so that the TCK test suite should work after each one of them? At least for me it passes up to patch 7/26 but then patch 8/26 starts causing ip6tables related problems. It was intended to be incremental, but I honestly haven't tested the TCK against the individual patches - only the end result.
I did some more tests now using iptables directly. From what I can see it is working as expected. There was a locking problem that I just sent a patch for. So from my perspective these patches can go in with the modifications applied to 16/26. Regards, Stefan
participants (7)
-
Daniel P. Berrange
-
Eric Blake
-
Jeff E. Nelson
-
John Ferlan
-
Ján Tomko
-
Pavel Hrdina
-
Stefan Berger