This patch adds MAC address based port filtering to the qemu driver.
Signed-off-by: Gerhard Stenzel <gerhard.stenzel(a)de.ibm.com>
---
po/POTFILES.in | 1
src/Makefile.am | 4 +-
src/qemu/qemu.conf | 2 +
src/qemu/qemu_bridge_filter.c | 108 +++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_bridge_filter.h | 39 +++++++++++++++
src/qemu/qemu_conf.c | 25 +++++++++
src/qemu/qemu_conf.h | 4 ++
src/qemu/qemu_driver.c | 16 ++++++
8 files changed, 198 insertions(+), 1 deletions(-)
create mode 100644 src/qemu/qemu_bridge_filter.c
create mode 100644 src/qemu/qemu_bridge_filter.h
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1a12a39..e090f58 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -24,6 +24,7 @@ src/opennebula/one_driver.c
src/openvz/openvz_conf.c
src/openvz/openvz_driver.c
src/phyp/phyp_driver.c
+src/qemu/qemu_bridge_filter.c
src/qemu/qemu_conf.c
src/qemu/qemu_driver.c
src/qemu/qemu_monitor_text.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 055573a..8b02828 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -184,7 +184,9 @@ QEMU_DRIVER_SOURCES = \
qemu/qemu_conf.c qemu/qemu_conf.h \
qemu/qemu_monitor_text.c \
qemu/qemu_monitor_text.h \
- qemu/qemu_driver.c qemu/qemu_driver.h
+ qemu/qemu_driver.c qemu/qemu_driver.h \
+ qemu/qemu_bridge_filter.c \
+ qemu/qemu_bridge_filter.h
UML_DRIVER_SOURCES = \
uml/uml_conf.c uml/uml_conf.h \
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 6d6b86a..2af8ffe 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -152,3 +152,5 @@
# in a location of $MOUNTPOINT/libvirt/qemu
# hugetlbfs_mount = "/dev/hugepages"
+
+mac_filter = 1
diff --git a/src/qemu/qemu_bridge_filter.c b/src/qemu/qemu_bridge_filter.c
new file mode 100644
index 0000000..36dd01c
--- /dev/null
+++ b/src/qemu/qemu_bridge_filter.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009 IBM Corp.
+ * Copyright (C) 2007-2009 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Gerhard Stenzel <gerhard.stenzel(a)de.ibm.com>
+ */
+
+#include <config.h>
+
+#include "ebtables.h"
+#include "qemu_conf.h"
+#include "qemu_driver.h"
+#include "util.h"
+#include "virterror_internal.h"
+#include "logging.h"
+
+#include "qemu_bridge_filter.h"
+
+#define VIR_FROM_THIS VIR_FROM_QEMU
+
+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;
+}
+
+int
+networkAllowMacOnPort(virConnectPtr conn,
+ struct qemud_driver *driver,
+ const char * ifname,
+ const unsigned char * mac) {
+
+ int err;
+
+ /* allow this combination of macaddr and ifname */
+ ebtablesContext * ebtablescontext = driver->ebtables;
+ if ((err = ebtablesAddForwardAllowIn(ebtablescontext,
+ ifname,
+ mac))) {
+ virReportSystemError(conn, err,
+ _("failed to add ebtables rule to allow routing to
'%s'"),
+ ifname);
+ }
+
+ return 0;
+}
+
+
+int
+networkDisallowMacOnPort(virConnectPtr conn,
+ struct qemud_driver *driver,
+ const char * ifname,
+ const unsigned char * mac) {
+
+ int err;
+
+ /* disallow this combination of macaddr and ifname */
+ ebtablesContext * ebtablescontext = driver->ebtables;
+ if ((err = ebtablesRemoveForwardAllowIn(ebtablescontext,
+ ifname,
+ mac))) {
+ virReportSystemError(conn, err,
+ _("failed to add ebtables rule to allow routing to
'%s'"),
+ ifname);
+ }
+
+ return 0;
+}
diff --git a/src/qemu/qemu_bridge_filter.h b/src/qemu/qemu_bridge_filter.h
new file mode 100644
index 0000000..ccb4710
--- /dev/null
+++ b/src/qemu/qemu_bridge_filter.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 IBM Corp.
+ * Copyright (C) 2007-2009 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Gerhard Stenzel <gerhard.stenzel(a)de.ibm.com>
+ */
+
+#ifndef __QEMUD_BRIDGE_FILTER_H__
+#define __QEMUD_BRIDGE_FILTER_H__
+
+
+int networkAllowMacOnPort(virConnectPtr conn,
+ struct qemud_driver *driver,
+ const char * ifname,
+ const unsigned char * mac);
+int networkDisallowMacOnPort(virConnectPtr conn,
+ struct qemud_driver *driver,
+ const char * ifname,
+ const unsigned char * mac);
+int networkDisableAllFrames(struct qemud_driver *driver);
+int networkAddEbtablesRules(struct qemud_driver *driver);
+
+
+#endif /* __QEMUD_BRIDGE_FILTER_H__ */
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index a095cb7..6559058 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -40,6 +40,7 @@
#include "c-ctype.h"
#include "virterror_internal.h"
#include "qemu_conf.h"
+#include "qemu_bridge_filter.h"
#include "uuid.h"
#include "buf.h"
#include "conf.h"
@@ -318,6 +319,22 @@ 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;
+ virReportSystemError(NULL, errno,
+ _("failed to enable mac filter in in
'%s'"), __FILE__);
+ }
+
+ if ((errno = networkDisableAllFrames(driver))) {
+ virReportSystemError(NULL, errno,
+ _("failed to add rule to drop all frames in
'%s'"), __FILE__);
+ }
+ }
+
virConfFree (conf);
return 0;
}
@@ -1196,6 +1213,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..42b8f56 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 */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 082cb04..aa16b4c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -56,6 +56,7 @@
#include "qemu_driver.h"
#include "qemu_conf.h"
#include "qemu_monitor_text.h"
+#include "qemu_bridge_filter.h"
#include "c-ctype.h"
#include "event.h"
#include "buf.h"
@@ -2176,6 +2177,21 @@ 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 (net->ifname == NULL)
+ continue;
+ 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,