This patch adds MAC address based port filtering to the qemu driver.
Signed-off-by: Gerhard Stenzel <gerhard.stenzel(a)de.ibm.com>
---
src/qemu/qemu.conf | 3 ++
src/qemu/qemu_conf.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_conf.h | 8 +++++
src/qemu/qemu_driver.c | 44 +++++++++++++++++++++++++
4 files changed, 140 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 6d6b86a..53c4522 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -152,3 +152,6 @@
# in a location of $MOUNTPOINT/libvirt/qemu
# hugetlbfs_mount = "/dev/hugepages"
+
+mac_filter = 1
+
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index ac63570..606152c 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -318,6 +318,20 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
}
}
+ p = virConfGetValue (conf, "mac_filter");
+ CHECK_TYPE ("mac_filter", VIR_CONF_LONG);
+ if (p) {
+ driver->macFilter = p->l;
+ if (!(driver->ebtables = ebtablesContextNew("qemu"))) {
+ driver->macFilter = 0; // TODO: we need to report an error here
+ }
+
+ if ((errno = networkDisableAllFrames(driver))) {
+ virReportSystemError(NULL, errno,
+ _("failed to add rule to drop all frames in
'%s'"), __FILE__);
+ }
+ }
+
virConfFree (conf);
return 0;
}
@@ -1119,6 +1133,69 @@ int qemudExtractVersion(virConnectPtr conn,
int
+networkAddEbtablesRules(struct qemud_driver *driver) {
+ int err;
+
+ /* Set forward policy to DROP */
+ if ((err = ebtablesAddForwardPolicyReject(driver->ebtables))) {
+ virReportSystemError(NULL, err,
+ _("failed to add ebtables rule to set default policy to
drop on '%s'"),
+ __FILE__);
+ return err;
+ }
+ ebtablesSaveRules(driver->ebtables);
+
+ return 0;
+}
+
+
+int
+networkDisableAllFrames(struct qemud_driver *driver) {
+ int err;
+
+ /* add default rules */
+ if ((err = networkAddEbtablesRules(driver))) {
+ virReportSystemError(NULL, err,
+ _("cannot filter mac addresses on bridge
'%s'"),
+ __FILE__);
+ return err;
+ }
+ return 0;
+}
+
+static int
+networkAllowMacOnPort(virConnectPtr conn,
+ struct qemud_driver *driver,
+ char * ifname,
+ unsigned char * mac) {
+
+ int err;
+ char *macaddr;
+
+ if (virAsprintf(&macaddr,
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1],
+ mac[2], mac[3],
+ mac[4], mac[5]) < 0) {
+ virReportOOMError(conn);
+ return -1;
+ }
+ /* allow this combination of macaddr and ifname */
+
+ ebtablesContext * ebtablescontext = driver->ebtables;
+ if ((err = ebtablesAddForwardAllowIn(ebtablescontext,
+ ifname,
+ macaddr))) {
+ virReportSystemError(conn, err,
+ _("failed to add ebtables rule to allow routing to
'%s'"),
+ ifname);
+ }
+
+ return 0;
+}
+
+
+int
qemudNetworkIfaceConnect(virConnectPtr conn,
struct qemud_driver *driver,
virDomainNetDefPtr net,
@@ -1193,6 +1270,14 @@ qemudNetworkIfaceConnect(virConnectPtr conn,
tapfd = -1;
}
+ if (driver->macFilter) {
+ if ((err = networkAllowMacOnPort(conn, driver, net->ifname, net->mac))) {
+ virReportSystemError(conn, err,
+ _("failed to add ebtables rule to allow MAC address
on '%s'"),
+ net->ifname);
+ }
+ }
+
cleanup:
VIR_FREE(brname);
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index f9a970f..3074ad1 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -26,6 +26,7 @@
#include <config.h>
+#include "ebtables.h"
#include "internal.h"
#include "bridge.h"
#include "capabilities.h"
@@ -112,6 +113,9 @@ struct qemud_driver {
char *hugetlbfs_mount;
char *hugepage_path;
+ unsigned int macFilter : 1;
+ ebtablesContext *ebtables;
+
virCapsPtr caps;
/* An array of callbacks */
@@ -205,4 +209,8 @@ virDomainDefPtr qemuParseCommandLineString(virConnectPtr conn,
virCapsPtr caps,
const char *args);
+
+int networkDisableAllFrames(struct qemud_driver *driver);
+int networkAddEbtablesRules(struct qemud_driver *driver);
+
#endif /* __QEMUD_CONF_H */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3812f91..8abb19a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2164,6 +2164,37 @@ cleanup:
return -1;
}
+static int
+networkDisallowMacOnPort(virConnectPtr conn,
+ struct qemud_driver *driver,
+ char * ifname,
+ unsigned char * mac) {
+
+ int err;
+ char *macaddr;
+
+ if (virAsprintf(&macaddr,
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1],
+ mac[2], mac[3],
+ mac[4], mac[5]) < 0) {
+ virReportOOMError(conn);
+ return -1;
+ }
+ /* disallow this combination of macaddr and ifname */
+
+ ebtablesContext * ebtablescontext = driver->ebtables;
+ if ((err = ebtablesRemoveForwardAllowIn(ebtablescontext,
+ ifname,
+ macaddr))) {
+ virReportSystemError(conn, err,
+ _("failed to add ebtables rule to allow routing to
'%s'"),
+ ifname);
+ }
+
+ return 0;
+}
+
static void qemudShutdownVMDaemon(virConnectPtr conn,
struct qemud_driver *driver,
@@ -2176,6 +2207,19 @@ static void qemudShutdownVMDaemon(virConnectPtr conn,
VIR_DEBUG(_("Shutting down VM '%s'\n"), vm->def->name);
+ if (driver->macFilter) {
+ int i;
+ virDomainDefPtr def = vm->def;
+ for (i = 0 ; i < def->nnets ; i++) {
+ virDomainNetDefPtr net = def->nets[i];
+ if ((errno = networkDisallowMacOnPort(conn, driver, net->ifname,
net->mac))) {
+ virReportSystemError(conn, errno,
+ _("failed to remove ebtables rule to allow MAC
address on '%s'"),
+ net->ifname);
+ }
+ }
+ }
+
if (virKillProcess(vm->pid, 0) == 0 &&
virKillProcess(vm->pid, SIGTERM) < 0)
virReportSystemError(conn, errno,