This patch adds MAC address based port filtering to the qemu driver. Signed-off-by: Gerhard Stenzel <gerhard.stenzel@xxxxxxxxxx> --- 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@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + */ + +#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, -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list