[libvirt] [PATCH 2/2] add MAC address based port filtering to qemu

Gerhard Stenzel gstenzel at linux.vnet.ibm.com
Tue Oct 27 11:36:14 UTC 2009


This patch adds MAC address based port filtering to the qemu driver.

Signed-off-by: Gerhard Stenzel <gerhard.stenzel at 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 at 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 at 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,




More information about the libvir-list mailing list