The functions invoked by the IP address learning thread that apply some basic filtering rules did not clean up any previous filtering rules that may still be there (due to a libvirt restart for example). With the patch below all the rules are cleaned up first. Also, I am introducing a function to drop all traffic in case the IP address learning thread could not apply the rules. Signed-off-by: Stefan Berger --- src/conf/nwfilter_conf.h | 3 src/nwfilter/nwfilter_ebiptables_driver.c | 104 +++++++++++++++++++++++++----- src/nwfilter/nwfilter_learnipaddr.c | 4 - src/nwfilter/nwfilter_learnipaddr.h | 2 4 files changed, 96 insertions(+), 17 deletions(-) Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c +++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c @@ -102,6 +102,7 @@ static const char *m_physdev_out_str = " static int ebtablesRemoveBasicRules(const char *ifname); static int ebiptablesDriverInit(void); static void ebiptablesDriverShutdown(void); +static int ebtablesCleanAll(const char *ifname); struct ushort_map { @@ -2679,12 +2680,7 @@ ebtablesApplyBasicRules(const char *ifna virFormatMacAddr(macaddr, macaddr_str); - ebtablesUnlinkTmpRootChain(&buf, 1, ifname); - ebtablesUnlinkTmpRootChain(&buf, 0, ifname); - ebtablesRemoveTmpSubChains(&buf, ifname); - ebtablesRemoveTmpRootChain(&buf, 1, ifname); - ebtablesRemoveTmpRootChain(&buf, 0, ifname); - ebiptablesExecCLI(&buf, &cli_status); + ebtablesCleanAll(ifname); ebtablesCreateTmpRootChain(&buf, 1, ifname, 1); @@ -2723,6 +2719,7 @@ ebtablesApplyBasicRules(const char *ifna CMD_STOPONERR(1)); ebtablesLinkTmpRootChain(&buf, 1, ifname, 1); + ebtablesRenameTmpRootChain(&buf, 1, ifname); if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) goto tear_down_tmpebchains; @@ -2730,7 +2727,7 @@ ebtablesApplyBasicRules(const char *ifna return 0; tear_down_tmpebchains: - ebtablesRemoveBasicRules(ifname); + ebtablesCleanAll(ifname); virNWFilterReportError(VIR_ERR_BUILD_FIREWALL, "%s", @@ -2782,12 +2779,7 @@ ebtablesApplyDHCPOnlyRules(const char *i virFormatMacAddr(macaddr, macaddr_str); - ebtablesUnlinkTmpRootChain(&buf, 1, ifname); - ebtablesUnlinkTmpRootChain(&buf, 0, ifname); - ebtablesRemoveTmpSubChains(&buf, ifname); - ebtablesRemoveTmpRootChain(&buf, 1, ifname); - ebtablesRemoveTmpRootChain(&buf, 0, ifname); - ebiptablesExecCLI(&buf, &cli_status); + ebtablesCleanAll(ifname); ebtablesCreateTmpRootChain(&buf, 1, ifname, 1); ebtablesCreateTmpRootChain(&buf, 0, ifname, 1); @@ -2842,6 +2834,8 @@ ebtablesApplyDHCPOnlyRules(const char *i ebtablesLinkTmpRootChain(&buf, 1, ifname, 1); ebtablesLinkTmpRootChain(&buf, 0, ifname, 1); + ebtablesRenameTmpRootChain(&buf, 1, ifname); + ebtablesRenameTmpRootChain(&buf, 0, ifname); if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) goto tear_down_tmpebchains; @@ -2851,7 +2845,7 @@ ebtablesApplyDHCPOnlyRules(const char *i return 0; tear_down_tmpebchains: - ebtablesRemoveBasicRules(ifname); + ebtablesCleanAll(ifname); virNWFilterReportError(VIR_ERR_BUILD_FIREWALL, "%s", @@ -2863,15 +2857,96 @@ tear_down_tmpebchains: } +/** + * ebtablesApplyDropAllRules + * + * @ifname: name of the backend-interface to which to apply the rules + * + * Returns 0 on success, 1 on failure with the rules removed + * + * Apply filtering rules so that the VM cannot receive or send traffic. + */ +static int +ebtablesApplyDropAllRules(const char *ifname) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + int cli_status; + char chain_in [MAX_CHAINNAME_LENGTH], + chain_out[MAX_CHAINNAME_LENGTH]; + + if (!ebtables_cmd_path) { + virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot create rules since ebtables tool is " + "missing.")); + return 1; + } + + ebtablesCleanAll(ifname); + + ebtablesCreateTmpRootChain(&buf, 1, ifname, 1); + ebtablesCreateTmpRootChain(&buf, 0, ifname, 1); + + PRINT_ROOT_CHAIN(chain_in , CHAINPREFIX_HOST_IN_TEMP , ifname); + PRINT_ROOT_CHAIN(chain_out, CHAINPREFIX_HOST_OUT_TEMP, ifname); + + virBufferVSprintf(&buf, + CMD_DEF("%s -t %s -A %s -j DROP") CMD_SEPARATOR + CMD_EXEC + "%s", + + ebtables_cmd_path, EBTABLES_DEFAULT_TABLE, chain_in, + CMD_STOPONERR(1)); + + virBufferVSprintf(&buf, + CMD_DEF("%s -t %s -A %s -j DROP") CMD_SEPARATOR + CMD_EXEC + "%s", + + ebtables_cmd_path, EBTABLES_DEFAULT_TABLE, chain_out, + CMD_STOPONERR(1)); + + ebtablesLinkTmpRootChain(&buf, 1, ifname, 1); + ebtablesLinkTmpRootChain(&buf, 0, ifname, 1); + ebtablesRenameTmpRootChain(&buf, 1, ifname); + ebtablesRenameTmpRootChain(&buf, 0, ifname); + + if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + goto tear_down_tmpebchains; + + return 0; + +tear_down_tmpebchains: + ebtablesCleanAll(ifname); + + virNWFilterReportError(VIR_ERR_BUILD_FIREWALL, + "%s", + _("Some rules could not be created.")); + + return 1; +} + + static int ebtablesRemoveBasicRules(const char *ifname) { + return ebtablesCleanAll(ifname); +} + + +static int ebtablesCleanAll(const char *ifname) +{ virBuffer buf = VIR_BUFFER_INITIALIZER; int cli_status; if (!ebtables_cmd_path) return 0; + ebtablesUnlinkRootChain(&buf, 1, ifname); + ebtablesUnlinkRootChain(&buf, 0, ifname); + ebtablesRemoveSubChains(&buf, ifname); + ebtablesRemoveRootChain(&buf, 1, ifname); + ebtablesRemoveRootChain(&buf, 0, ifname); + ebtablesUnlinkTmpRootChain(&buf, 1, ifname); ebtablesUnlinkTmpRootChain(&buf, 0, ifname); ebtablesRemoveTmpSubChains(&buf, ifname); @@ -3265,6 +3340,7 @@ virNWFilterTechDriver ebiptables_driver .canApplyBasicRules = ebiptablesCanApplyBasicRules, .applyBasicRules = ebtablesApplyBasicRules, .applyDHCPOnlyRules = ebtablesApplyDHCPOnlyRules, + .applyDropAllRules = ebtablesApplyDropAllRules, .removeBasicRules = ebtablesRemoveBasicRules, }; Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.c +++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c @@ -598,8 +598,6 @@ learnIPAddressThread(void *arg) if (handle) pcap_close(handle); - techdriver->removeBasicRules(req->ifname); - if (req->status == 0) { int ret; char inetaddr[INET_ADDRSTRLEN]; @@ -624,6 +622,8 @@ learnIPAddressThread(void *arg) _("encountered an error on interface %s " "index %d"), req->ifname, req->ifindex); + + techdriver->applyDropAllRules(req->ifname); } memset(&req->thread, 0x0, sizeof(req->thread)); Index: libvirt-acl/src/conf/nwfilter_conf.h =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.h +++ libvirt-acl/src/conf/nwfilter_conf.h @@ -521,6 +521,8 @@ typedef int (*virNWFilterApplyDHCPOnlyRu typedef int (*virNWFilterRemoveBasicRules)(const char *ifname); +typedef int (*virNWFilterDropAllRules)(const char *ifname); + enum techDrvFlags { TECHDRV_FLAG_INITIALIZED = (1 << 0), }; @@ -544,6 +546,7 @@ struct _virNWFilterTechDriver { virNWFilterCanApplyBasicRules canApplyBasicRules; virNWFilterApplyBasicRules applyBasicRules; virNWFilterApplyDHCPOnlyRules applyDHCPOnlyRules; + virNWFilterDropAllRules applyDropAllRules; virNWFilterRemoveBasicRules removeBasicRules; }; Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.h =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.h +++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.h @@ -60,7 +60,7 @@ int virNWFilterLearnIPAddress(virNWFilte enum howDetect howDetect); virNWFilterIPAddrLearnReqPtr virNWFilterLookupLearnReq(int ifindex); - +int virNWFilterTerminateLearnReq(const char *ifname); void virNWFilterDelIpAddrForIfname(const char *ifname); const char *virNWFilterGetIpAddrForIfname(const char *ifname);