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 <stefanb(a)us.ibm.com>
---
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);