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