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

Gerhard Stenzel gstenzel at linux.vnet.ibm.com
Tue Oct 13 10:57:24 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>
---

 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,




More information about the libvir-list mailing list