[libvirt] [RFC PATCH 0/6] Series short description

The following series of patches is a prototype implementation of a ebtables based MAC address filter. This is currently not intended for inclusion, but rather to get some feedback/comments about the approach and the implementation. At the moment, some defaults are set when libvirtd starts and when a domain is started or destroyed. The plan is to extend this filter capability to the API level and virsh command level. The plan is also to add more filtering features like VLAN filtering and QoS filtering. Thanks, Gerhard --- Gerhard Stenzel (6): remove currently unused parameter to pass make check test add MAC address based port filtering to qemu add MAC address based port filtering to libvirt add the ebtables wrapper to network driver add build support for ebtables wrapper add ebtables wrapper configure.in | 3 include/libvirt/libvirt.h.in | 14 + src/Makefile.am | 1 src/conf/network_conf.h | 10 src/driver.h | 14 + src/libvirt.c | 119 +++++ src/libvirt_private.syms | 26 + src/libvirt_public.syms | 3 src/network/bridge_driver.c | 175 ++++++++ src/qemu/qemu.conf | 3 src/qemu/qemu_conf.c | 14 + src/qemu/qemu_conf.h | 2 src/qemu/qemu_driver.c | 23 + src/test/test_driver.c | 3 src/util/ebtables.c | 961 ++++++++++++++++++++++++++++++++++++++++++ src/util/ebtables.h | 134 ++++++ 16 files changed, 1505 insertions(+), 0 deletions(-) create mode 100644 src/util/ebtables.c create mode 100644 src/util/ebtables.h --

This patch adds the files which implement the ebtables wrapper. Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> --- src/util/ebtables.c | 964 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/ebtables.h | 136 +++++++ 2 files changed, 1100 insertions(+), 0 deletions(-) create mode 100644 src/util/ebtables.c create mode 100644 src/util/ebtables.h diff --git a/src/util/ebtables.c b/src/util/ebtables.c new file mode 100644 index 0000000..930d046 --- /dev/null +++ b/src/util/ebtables.c @@ -0,0 +1,964 @@ +/* + * 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 + * + * based on iptables.c + * Authors: + * Gerhard Stenzel <gerhard.stenzel@de.ibm.com> + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <limits.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_PATHS_H +#include <paths.h> +#endif + +#include "internal.h" +#include "ebtables.h" +#include "util.h" +#include "memory.h" +#include "virterror_internal.h" +#include "logging.h" + +enum { + ADD = 0, + REMOVE +}; + + +#ifdef ENABLE_ebtabLES_LOKKIT +static void +notifyRulesUpdated(const char *table, + const char *path) +{ + char arg[PATH_MAX]; + const char *argv[4]; + + snprintf(arg, sizeof(arg), "--custom-rules=ipv4:%s:%s", table, path); + + argv[0] = (char *) LOKKIT_PATH; + argv[1] = (char *) "--nostart"; + argv[2] = arg; + argv[3] = NULL; + + char ebuf[1024]; + if (virRun(NULL, argv, NULL) < 0) + VIR_WARN(_("Failed to run '%s %s': %s"), + LOKKIT_PATH, arg, virStrerror(errno, ebuf, sizeof ebuf)); +} + +static int +stripLine(char *str, int len, const char *line) +{ + char *s, *p; + int changed; + + changed = 0; + s = str; + + while ((p = strchr(s, '\n'))) { + if (p == s || STRNEQLEN(s, line, p - s)) { + s = ++p; + continue; + } + + ++p; + memmove(s, p, len - (p - str) + 1); + len -= p - s; + changed = 1; + } + + if (STREQ(s, line)) { + *s = '\0'; + changed = 1; + } + + return changed; +} + +static void +notifyRulesRemoved(const char *table, + const char *path) +{ +/* 10 MB limit on config file size as a sanity check */ +#define MAX_FILE_LEN (1024*1024*10) + + char arg[PATH_MAX]; + char *content; + int len; + FILE *f = NULL; + + len = virFileReadAll(SYSCONF_DIR "/sysconfig/system-config-firewall", + MAX_FILE_LEN, &content); + if (len < 0) { + VIR_WARN("%s", _("Failed to read " SYSCONF_DIR + "/sysconfig/system-config-firewall")); + return; + } + + snprintf(arg, sizeof(arg), "--custom-rules=ipv4:%s:%s", table, path); + + if (!stripLine(content, len, arg)) { + VIR_FREE(content); + return; + } + + if (!(f = fopen(SYSCONF_DIR "/sysconfig/system-config-firewall", "w"))) + goto write_error; + + if (fputs(content, f) == EOF) + goto write_error; + + if (fclose(f) == EOF) { + f = NULL; + goto write_error; + } + + VIR_FREE(content); + + return; + + write_error:; + char ebuf[1024]; + VIR_WARN(_("Failed to write to " SYSCONF_DIR + "/sysconfig/system-config-firewall : %s"), + virStrerror(errno, ebuf, sizeof ebuf)); + if (f) + fclose(f); + VIR_FREE(content); + +#undef MAX_FILE_LEN +} + +static int +writeRules(const char *path, + const ebtRule *rules, + int nrules) +{ + char tmp[PATH_MAX]; + FILE *f; + int istmp; + int i; + + if (nrules == 0 && unlink(path) == 0) + return 0; + + if (snprintf(tmp, PATH_MAX, "%s.new", path) >= PATH_MAX) + return EINVAL; + + istmp = 1; + + if (!(f = fopen(tmp, "w"))) { + istmp = 0; + if (!(f = fopen(path, "w"))) + return errno; + } + + for (i = 0; i < nrules; i++) { + if (fputs(rules[i].rule, f) == EOF || + fputc('\n', f) == EOF) { + fclose(f); + if (istmp) + unlink(tmp); + return errno; + } + } + + fclose(f); + + if (istmp && rename(tmp, path) < 0) { + unlink(tmp); + return errno; + } + + if (istmp) + unlink(tmp); + + return 0; +} +#endif /* ENABLE_ebtabLES_LOKKIT */ + +static void +ebtRulesSave(ebtRules *rules) +{ +#ifdef ENABLE_ebtabLES_LOKKIT + int err; + + char ebuf[1024]; + if ((err = virFileMakePath(rules->dir))) { + VIR_WARN(_("Failed to create directory %s : %s"), + rules->dir, virStrerror(err, ebuf, sizeof ebuf)); + return; + } + + if ((err = writeRules(rules->path, rules->rules, rules->nrules))) { + VIR_WARN(_("Failed to saves ebtables rules to %s : %s"), + rules->path, virStrerror(err, ebuf, sizeof ebuf)); + return; + } + + if (rules->nrules > 0) + notifyRulesUpdated(rules->table, rules->path); + else + notifyRulesRemoved(rules->table, rules->path); +#else + (void) rules; +#endif /* ENABLE_ebtabLES_LOKKIT */ +} + +static void +ebtRuleFree(ebtRule *rule) +{ + VIR_FREE(rule->rule); + + if (rule->argv) { + int i = 0; + while (rule->argv[i]) + VIR_FREE(rule->argv[i++]); + VIR_FREE(rule->argv); + } +} + +static int +ebtRulesAppend(ebtRules *rules, + char *rule, + const char **argv, + int command_idx) +{ + if (VIR_REALLOC_N(rules->rules, rules->nrules+1) < 0) { + int i = 0; + while (argv[i]) + VIR_FREE(argv[i++]); + VIR_FREE(argv); + return ENOMEM; + } + + rules->rules[rules->nrules].rule = rule; + rules->rules[rules->nrules].argv = argv; + rules->rules[rules->nrules].command_idx = command_idx; + + rules->nrules++; + + return 0; +} + +static int +ebtRulesRemove(ebtRules *rules, + char *rule) +{ + int i; + + for (i = 0; i < rules->nrules; i++) + if (STREQ(rules->rules[i].rule, rule)) + break; + + if (i >= rules->nrules) + return EINVAL; + + ebtRuleFree(&rules->rules[i]); + + memmove(&rules->rules[i], + &rules->rules[i+1], + (rules->nrules - i - 1) * sizeof (ebtRule)); + + rules->nrules--; + + return 0; +} + +static void +ebtRulesFree(ebtRules *rules) +{ + int i; + + VIR_FREE(rules->table); + VIR_FREE(rules->chain); + + if (rules->rules) { + for (i = 0; i < rules->nrules; i++) + ebtRuleFree(&rules->rules[i]); + + VIR_FREE(rules->rules); + + rules->nrules = 0; + } + +#ifdef ENABLE_ebtabLES_LOKKIT + rules->dir[0] = '\0'; + rules->path[0] = '\0'; +#endif /* ENABLE_ebtabLES_LOKKIT */ + + VIR_FREE(rules); +} + +static ebtRules * +ebtRulesNew(const char *table, + const char *chain) +{ + ebtRules *rules; + + if (VIR_ALLOC(rules) < 0) + return NULL; + + if (!(rules->table = strdup(table))) + goto error; + + if (!(rules->chain = strdup(chain))) + goto error; + + rules->rules = NULL; + rules->nrules = 0; + +#ifdef ENABLE_ebtabLES_LOKKIT + if (virFileBuildPath(LOCAL_STATE_DIR "/lib/libvirt/ebtables", table, NULL, + rules->dir, sizeof(rules->dir)) < 0) + goto error; + + if (virFileBuildPath(rules->dir, chain, ".chain", rules->path, sizeof(rules->path)) < 0) + goto error; +#endif /* ENABLE_ebtabLES_LOKKIT */ + + return rules; + + error: + ebtRulesFree(rules); + return NULL; +} + +static int +ebtablesAddRemoveRule(ebtRules *rules, int action, const char *arg, ...) +{ + va_list args; + int retval = ENOMEM; + const char **argv; + char *rule = NULL; + const char *s; + int n, command_idx; + + n = 1 + /* /sbin/ebtables */ + 2 + /* --table foo */ + 2 + /* --insert bar */ + 1; /* arg */ + + va_start(args, arg); + while ((s = va_arg(args, const char *))) + n++; + + va_end(args); + + if (VIR_ALLOC_N(argv, n + 1) < 0) + goto error; + + n = 0; + + if (!(argv[n++] = strdup(EBTABLES_PATH))) + goto error; + +/* + if (!(argv[n++] = strdup("--table"))) + goto error; + + if (!(argv[n++] = strdup(rules->table))) + goto error; +*/ + command_idx = n; +/* + if (!(argv[n++] = strdup("--insert"))) + goto error; + + if (!(argv[n++] = strdup(rules->chain))) + goto error; +*/ + if (!(argv[n++] = strdup(arg))) + goto error; + + va_start(args, arg); + + while ((s = va_arg(args, const char *))) + if (!(argv[n++] = strdup(s))) + goto error; + + va_end(args); + + if (!(rule = virArgvToString(&argv[command_idx]))) + goto error; + + if (action == REMOVE) { + VIR_FREE(argv[command_idx]); + if (!(argv[command_idx] = strdup("--delete"))) + goto error; + } + + if (virRun(NULL, argv, NULL) < 0) { + retval = errno; + goto error; + } + + if (action == ADD) { + retval = ebtRulesAppend(rules, rule, argv, command_idx); + rule = NULL; + argv = NULL; + } else { + retval = ebtRulesRemove(rules, rule); + } + + error: + VIR_FREE(rule); + + if (argv) { + n = 0; + while (argv[n]) + VIR_FREE(argv[n++]); + VIR_FREE(argv); + } + + return retval; +} + +/** + * ebtablesContextNew: + * + * Create a new ebtable context + * + * Returns a pointer to the new structure or NULL in case of error + */ +ebtablesContext * +ebtablesContextNew(void) +{ + ebtablesContext *ctx; + + if (VIR_ALLOC(ctx) < 0) + return NULL; + + if (!(ctx->input_filter = ebtRulesNew("filter", "INPUT"))) + goto error; + + if (!(ctx->forward_filter = ebtRulesNew("filter", "FORWARD"))) + goto error; + + if (!(ctx->nat_postrouting = ebtRulesNew("nat", "POSTROUTING"))) + goto error; + + return ctx; + + error: + ebtablesContextFree(ctx); + return NULL; +} + +/** + * ebtablesContextFree: + * @ctx: pointer to the IP table context + * + * Free the resources associated with an IP table context + */ +void +ebtablesContextFree(ebtablesContext *ctx) +{ + if (ctx->input_filter) + ebtRulesFree(ctx->input_filter); + if (ctx->forward_filter) + ebtRulesFree(ctx->forward_filter); + if (ctx->nat_postrouting) + ebtRulesFree(ctx->nat_postrouting); + VIR_FREE(ctx); +} + +/** + * ebtablesSaveRules: + * @ctx: pointer to the IP table context + * + * Saves all the IP table rules associated with a context + * to disk so that if ebtables is restarted, the rules + * will automatically be reload. + */ +void +ebtablesSaveRules(ebtablesContext *ctx) +{ + ebtRulesSave(ctx->input_filter); + ebtRulesSave(ctx->forward_filter); + ebtRulesSave(ctx->nat_postrouting); +} + +static void +ebtRulesReload(ebtRules *rules) +{ + int i; + char ebuf[1024]; + + for (i = 0; i < rules->nrules; i++) { + ebtRule *rule = &rules->rules[i]; + const char *orig; + + orig = rule->argv[rule->command_idx]; + rule->argv[rule->command_idx] = (char *) "--delete"; + + if (virRun(NULL, rule->argv, NULL) < 0) + VIR_WARN(_("Failed to remove ebtables rule '%s'" + " from chain '%s' in table '%s': %s"), + rule->rule, rules->chain, rules->table, + virStrerror(errno, ebuf, sizeof ebuf)); + + rule->argv[rule->command_idx] = orig; + } + + for (i = 0; i < rules->nrules; i++) + if (virRun(NULL, rules->rules[i].argv, NULL) < 0) + VIR_WARN(_("Failed to add ebtables rule '%s'" + " to chain '%s' in table '%s': %s"), + rules->rules[i].rule, rules->chain, rules->table, + virStrerror(errno, ebuf, sizeof ebuf)); +} + +/** + * ebtablesReloadRules: + * @ctx: pointer to the IP table context + * + * Reloads all the IP table rules associated to a context + */ +void +ebtablesReloadRules(ebtablesContext *ctx) +{ + ebtRulesReload(ctx->input_filter); + ebtRulesReload(ctx->forward_filter); + ebtRulesReload(ctx->nat_postrouting); +} + +/* +static int +ebtablesInput(ebtablesContext *ctx, + const char *iface, + int port, + int action, + int tcp) +{ + char portstr[32]; + + snprintf(portstr, sizeof(portstr), "%d", port); + portstr[sizeof(portstr) - 1] = '\0'; + + return ebtablesAddRemoveRule(ctx->input_filter, + action, + "--in-interface", iface, + "--protocol", tcp ? "tcp" : "udp", + "--destination-port", portstr, + "--jump", "ACCEPT", + NULL); +} +*/ +/* Allow all traffic coming from the bridge, with a valid network address + * to proceed to WAN + */ +static int +ebtablesForwardAllowOut(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev, + int action) +{ + if (physdev && physdev[0]) { + return ebtablesAddRemoveRule(ctx->forward_filter, + action, + "--source", network, + "--in-interface", iface, + "--out-interface", physdev, + "--jump", "ACCEPT", + NULL); + } else { + return ebtablesAddRemoveRule(ctx->forward_filter, + action, + "--source", network, + "--in-interface", iface, + "--jump", "ACCEPT", + NULL); + } +} + +int +ebtablesAddForwardPolicyReject(ebtablesContext *ctx) +{ + return ebtablesForwardPolicyReject(ctx, ADD); +} + +int +ebtablesRemoveForwardPolicyReject(ebtablesContext *ctx) +{ + return ebtablesForwardPolicyReject(ctx, REMOVE); +} + +int +ebtablesForwardPolicyReject(ebtablesContext *ctx, + int action) +{ + return ebtablesAddRemoveRule(ctx->forward_filter, + action, + "-P", "FORWARD", "DROP", + NULL); +} + +/** + * ebtablesAddForwardAllowOut: + * @ctx: pointer to the IP table context + * @network: the source network name + * @iface: the source interface name + * @physdev: the physical output device + * + * Add a rule to the IP table context to allow the traffic for the + * network @network via interface @iface to be forwarded to + * @physdev device. This allow the outbound traffic on a bridge. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesAddForwardAllowOut(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return ebtablesForwardAllowOut(ctx, network, iface, physdev, ADD); +} + +/** + * ebtablesRemoveForwardAllowOut: + * @ctx: pointer to the IP table context + * @network: the source network name + * @iface: the source interface name + * @physdev: the physical output device + * + * Remove a rule from the IP table context hence forbidding forwarding + * of the traffic for the network @network via interface @iface + * to the @physdev device output. This stops the outbound traffic on a bridge. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesRemoveForwardAllowOut(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return ebtablesForwardAllowOut(ctx, network, iface, physdev, REMOVE); +} + + +/* Allow all traffic destined to the bridge, with a valid network address + * and associated with an existing connection + */ +static int +ebtablesForwardAllowRelatedIn(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev, + int action) +{ + if (physdev && physdev[0]) { + return ebtablesAddRemoveRule(ctx->forward_filter, + action, + "--destination", network, + "--in-interface", physdev, + "--out-interface", iface, + "--match", "state", + "--state", "ESTABLISHED,RELATED", + "--jump", "ACCEPT", + NULL); + } else { + return ebtablesAddRemoveRule(ctx->forward_filter, + action, + "--destination", network, + "--out-interface", iface, + "--match", "state", + "--state", "ESTABLISHED,RELATED", + "--jump", "ACCEPT", + NULL); + } +} + +/** + * ebtablesAddForwardAllowRelatedIn: + * @ctx: pointer to the IP table context + * @network: the source network name + * @iface: the output interface name + * @physdev: the physical input device or NULL + * + * Add rules to the IP table context to allow the traffic for the + * network @network on @physdev device to be forwarded to + * interface @iface, if it is part of an existing connection. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesAddForwardAllowRelatedIn(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return ebtablesForwardAllowRelatedIn(ctx, network, iface, physdev, ADD); +} + +/** + * ebtablesRemoveForwardAllowRelatedIn: + * @ctx: pointer to the IP table context + * @network: the source network name + * @iface: the output interface name + * @physdev: the physical input device or NULL + * + * Remove rules from the IP table context hence forbidding the traffic for + * network @network on @physdev device to be forwarded to + * interface @iface, if it is part of an existing connection. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesRemoveForwardAllowRelatedIn(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return ebtablesForwardAllowRelatedIn(ctx, network, iface, physdev, REMOVE); +} + +/* Allow all traffic destined to the bridge, with a valid network address + */ +static int +ebtablesForwardAllowIn(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *macaddr, + int action) +{ + return ebtablesAddRemoveRule(ctx->forward_filter, + action, +/* "--destination", network,*/ + "--insert", "FORWARD", + "--in-interface", iface, +/* "--out-interface", network, */ + "--source", macaddr, + "--jump", "ACCEPT", + NULL); +} + +/** + * ebtablesAddForwardAllowIn: + * @ctx: pointer to the IP table context + * @network: the source network name + * @iface: the output interface name + * @physdev: the physical input device or NULL + * + * Add rules to the IP table context to allow the traffic for the + * network @network on @physdev device to be forwarded to + * interface @iface. This allow the inbound traffic on a bridge. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesAddForwardAllowIn(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return ebtablesForwardAllowIn(ctx, network, iface, physdev, ADD); +} + +/** + * ebtablesRemoveForwardAllowIn: + * @ctx: pointer to the IP table context + * @network: the source network name + * @iface: the output interface name + * @physdev: the physical input device or NULL + * + * Remove rules from the IP table context hence forbidding the traffic for + * network @network on @physdev device to be forwarded to + * interface @iface. This stops the inbound traffic on a bridge. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesRemoveForwardAllowIn(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return ebtablesForwardAllowIn(ctx, network, iface, physdev, REMOVE); +} + + +/* Allow all traffic between guests on the same bridge, + * with a valid network address + */ +static int +ebtablesForwardAllowCross(ebtablesContext *ctx, + const char *iface, + int action) +{ + return ebtablesAddRemoveRule(ctx->forward_filter, + action, + "--in-interface", iface, + "--out-interface", iface, + "--jump", "ACCEPT", + NULL); +} + +/** + * ebtablesAddForwardAllowCross: + * @ctx: pointer to the IP table context + * @iface: the input/output interface name + * + * Add rules to the IP table context to allow traffic to cross that + * interface. It allows all traffic between guests on the same bridge + * represented by that interface. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesAddForwardAllowCross(ebtablesContext *ctx, + const char *iface) { + return ebtablesForwardAllowCross(ctx, iface, ADD); +} + +/** + * ebtablesRemoveForwardAllowCross: + * @ctx: pointer to the IP table context + * @iface: the input/output interface name + * + * Remove rules to the IP table context to block traffic to cross that + * interface. It forbids traffic between guests on the same bridge + * represented by that interface. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesRemoveForwardAllowCross(ebtablesContext *ctx, + const char *iface) { + return ebtablesForwardAllowCross(ctx, iface, REMOVE); +} + + +/* Drop all traffic trying to forward from the bridge. + * ie the bridge is the in interface + */ +static int +ebtablesForwardRejectOut(ebtablesContext *ctx, + const char *iface, + int action) +{ + return ebtablesAddRemoveRule(ctx->forward_filter, + action, + "--in-interface", iface, + "--jump", "DROP", + NULL); +} + +/** + * ebtablesAddForwardRejectOut: + * @ctx: pointer to the EB table context + * @iface: the output interface name + * + * Add rules to the EB table context to forbid all traffic to that + * interface. It forbids forwarding from the bridge to that interface. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesAddForwardRejectOut(ebtablesContext *ctx, + const char *iface) +{ + return ebtablesForwardRejectOut(ctx, iface, ADD); +} + +/** + * ebtablesRemoveForwardRejectOut: + * @ctx: pointer to the EB table context + * @iface: the output interface name + * + * Remove rules from the EB table context forbidding all traffic to that + * interface. It reallow forwarding from the bridge to that interface. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesRemoveForwardRejectOut(ebtablesContext *ctx, + const char *iface) +{ + return ebtablesForwardRejectOut(ctx, iface, REMOVE); +} + + + + +/* Drop all traffic trying to forward to the bridge. + * ie the bridge is the out interface + */ +static int +ebtablesForwardRejectIn(ebtablesContext *ctx, + const char *iface, + int action) +{ + return ebtablesAddRemoveRule(ctx->forward_filter, + action, + "--out-interface", iface, + "--jump", "DROP", + NULL); +} + +/** + * ebtablesAddForwardRejectIn: + * @ctx: pointer to the IP table context + * @iface: the input interface name + * + * Add rules to the IP table context to forbid all traffic from that + * interface. It forbids forwarding from that interface to the bridge. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesAddForwardRejectIn(ebtablesContext *ctx, + const char *iface) +{ + return ebtablesForwardRejectIn(ctx, iface, ADD); +} + +/** + * ebtablesRemoveForwardRejectIn: + * @ctx: pointer to the IP table context + * @iface: the input interface name + * + * Remove rules from the IP table context forbidding all traffic from that + * interface. It allows forwarding from that interface to the bridge. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesRemoveForwardRejectIn(ebtablesContext *ctx, + const char *iface) +{ + return ebtablesForwardRejectIn(ctx, iface, REMOVE); +} diff --git a/src/util/ebtables.h b/src/util/ebtables.h new file mode 100644 index 0000000..30b1056 --- /dev/null +++ b/src/util/ebtables.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2009 IBM Corp. + * Copyright (C) 2007, 2008 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 + * + * based on iptables.h + * Authors: + * Gerhard Stenzel <gerhard.stenzel@de.ibm.com> + */ + +#ifndef __QEMUD_EBTABLES_H__ +#define __QEMUD_EBTABLES_H__ + +typedef struct +{ + char *rule; + const char **argv; + int command_idx; +} ebtRule; + +typedef struct +{ + char *table; + char *chain; + + int nrules; + ebtRule *rules; + +#ifdef ENABLE_ebtabLES_LOKKIT + + char dir[PATH_MAX]; + char path[PATH_MAX]; + +#endif /* ENABLE_ebtabLES_LOKKIT */ + +} ebtRules; + +struct _ebtablesContext +{ + ebtRules *input_filter; + ebtRules *forward_filter; + ebtRules *nat_postrouting; +}; + +typedef struct _ebtablesContext ebtablesContext; + +ebtablesContext *ebtablesContextNew (void); +void ebtablesContextFree (ebtablesContext *ctx); + +void ebtablesSaveRules (ebtablesContext *ctx); +void ebtablesReloadRules (ebtablesContext *ctx); + +int ebtablesAddTcpInput (ebtablesContext *ctx, + const char *iface, + int port); +int ebtablesRemoveTcpInput (ebtablesContext *ctx, + const char *iface, + int port); + +int ebtablesAddUdpInput (ebtablesContext *ctx, + const char *iface, + int port); +int ebtablesRemoveUdpInput (ebtablesContext *ctx, + const char *iface, + int port); + +int ebtablesAddForwardAllowOut (ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev); +int ebtablesRemoveForwardAllowOut (ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev); + +int ebtablesAddForwardAllowRelatedIn(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev); +int ebtablesRemoveForwardAllowRelatedIn(ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev); + +int ebtablesAddForwardAllowIn (ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev); +int ebtablesRemoveForwardAllowIn (ebtablesContext *ctx, + const char *network, + const char *iface, + const char *physdev); + +int ebtablesAddForwardAllowCross (ebtablesContext *ctx, + const char *iface); +int ebtablesRemoveForwardAllowCross (ebtablesContext *ctx, + const char *iface); + +int ebtablesAddForwardRejectOut (ebtablesContext *ctx, + const char *iface); +int ebtablesRemoveForwardRejectOut (ebtablesContext *ctx, + const char *iface); + +int ebtablesAddForwardRejectIn (ebtablesContext *ctx, + const char *iface); +int ebtablesRemoveForwardRejectIn (ebtablesContext *ctx, + const char *iface); + +int ebtablesAddForwardMasquerade (ebtablesContext *ctx, + const char *network, + const char *physdev); +int ebtablesRemoveForwardMasquerade (ebtablesContext *ctx, + const char *network, + const char *physdev); + +int ebtablesAddForwardPolicyReject(ebtablesContext *ctx); + +int ebtablesRemoveForwardPolicyReject(ebtablesContext *ctx); + +int ebtablesForwardPolicyReject(ebtablesContext *ctx, + int action); + +#endif /* __QEMUD_ebtabLES_H__ */

On Fri, Oct 02, 2009 at 03:48:11PM +0200, Gerhard Stenzel wrote:
+ + +#ifdef ENABLE_ebtabLES_LOKKIT
Something went a little wrong with upper/lower case there I think
+static void +notifyRulesUpdated(const char *table, + const char *path) +{ + char arg[PATH_MAX]; + const char *argv[4]; + + snprintf(arg, sizeof(arg), "--custom-rules=ipv4:%s:%s", table, path); + + argv[0] = (char *) LOKKIT_PATH; + argv[1] = (char *) "--nostart"; + argv[2] = arg; + argv[3] = NULL;
It is desirable not to cast away const-ness, but rather to declare it correctly - you can also initialize at the same time as declaring to avoid needing to hardcode array indexes, eg const char * const argv[] = { LOKKIT_PATH, "--nostart", arg, NULL, };
+ebtablesContext * +ebtablesContextNew(void) +{ + ebtablesContext *ctx; + + if (VIR_ALLOC(ctx) < 0) + return NULL; + + if (!(ctx->input_filter = ebtRulesNew("filter", "INPUT"))) + goto error; + + if (!(ctx->forward_filter = ebtRulesNew("filter", "FORWARD"))) + goto error; + + if (!(ctx->nat_postrouting = ebtRulesNew("nat", "POSTROUTING"))) + goto error; + + return ctx; + + error: + ebtablesContextFree(ctx); + return NULL; +}
I know you're just following the existing style/pattern used by the iptables.c/h file here by directly manipulating the main INPUT/FORWARD/POSTROUTING chains, but I think this could be improved a little Add a custom 'libvirt_INPUT' chain as the first entry in the main 'INPUT' chain, and then put all our rules on this custom chain. This will make it clearer for admins where all these extra rules are coming from, and make it slightly safer for management since there willbe less risk of rules in our custom chain getting blown away / mis-ordered wrt other rules I think it would even be desirable to have a custom chain per libvirt driver, since multiple drivers might want todo this MAC filtering. Thus I'd suggest adding a 'const char *driverName' parameter to ebtablesContextNew(const char *driver), and then creating chains named with that, eg so if QEMU, LXC and UML drivers all uses this ebtables code, we'd end up with the INPUT chain having references to 3 custom chains libvirt_qemu_INPUT libvirt_lxc_INPUT libvirt_uml_INPUT Likewise for FORWARD/POSTROUTING. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch adds build support for the ebtables wrapper. Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> --- configure.in | 3 +++ src/Makefile.am | 1 + 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/configure.in b/configure.in index cb5ce55..9e9aa3a 100644 --- a/configure.in +++ b/configure.in @@ -287,6 +287,9 @@ fi AC_PATH_PROG([IPTABLES_PATH], [iptables], /sbin/iptables, [/usr/sbin:$PATH]) AC_DEFINE_UNQUOTED([IPTABLES_PATH], "$IPTABLES_PATH", [path to iptables binary]) +AC_PATH_PROG([EBTABLES_PATH], [ebtables], /sbin/ebtables, [/usr/sbin:$PATH]) +AC_DEFINE_UNQUOTED([EBTABLES_PATH], "$EBTABLES_PATH", [path to ebtables binary]) + if test "$with_openvz" = "yes"; then AC_DEFINE_UNQUOTED([WITH_OPENVZ], 1, [whether OpenVZ driver is enabled]) fi diff --git a/src/Makefile.am b/src/Makefile.am index de7765c..4a6716c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,6 +43,7 @@ UTIL_SOURCES = \ util/event.c util/event.h \ util/hash.c util/hash.h \ util/iptables.c util/iptables.h \ + util/ebtables.c util/ebtables.h \ util/logging.c util/logging.h \ util/memory.c util/memory.h \ util/pci.c util/pci.h \

On Fri, Oct 02, 2009 at 03:48:16PM +0200, Gerhard Stenzel wrote:
This patch adds build support for the ebtables wrapper.
Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> ---
configure.in | 3 +++ src/Makefile.am | 1 + 2 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/configure.in b/configure.in index cb5ce55..9e9aa3a 100644 --- a/configure.in +++ b/configure.in @@ -287,6 +287,9 @@ fi AC_PATH_PROG([IPTABLES_PATH], [iptables], /sbin/iptables, [/usr/sbin:$PATH]) AC_DEFINE_UNQUOTED([IPTABLES_PATH], "$IPTABLES_PATH", [path to iptables binary])
+AC_PATH_PROG([EBTABLES_PATH], [ebtables], /sbin/ebtables, [/usr/sbin:$PATH]) +AC_DEFINE_UNQUOTED([EBTABLES_PATH], "$EBTABLES_PATH", [path to ebtables binary]) + if test "$with_openvz" = "yes"; then AC_DEFINE_UNQUOTED([WITH_OPENVZ], 1, [whether OpenVZ driver is enabled]) fi diff --git a/src/Makefile.am b/src/Makefile.am index de7765c..4a6716c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,6 +43,7 @@ UTIL_SOURCES = \ util/event.c util/event.h \ util/hash.c util/hash.h \ util/iptables.c util/iptables.h \ + util/ebtables.c util/ebtables.h \ util/logging.c util/logging.h \ util/memory.c util/memory.h \ util/pci.c util/pci.h \
ACK, looks ok Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch adds the ebtables wrapper to the network driver. Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> --- src/conf/network_conf.h | 10 ++ src/libvirt_private.syms | 26 ++++++ src/network/bridge_driver.c | 179 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 0 deletions(-) diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index e983a01..2f7d536 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -55,6 +55,13 @@ struct _virNetworkDHCPHostDef { char *ip; }; +typedef struct _virNetworkBridgePortDef virNetworkBridgePortDef; +typedef virNetworkBridgePortDef *virNetworkBridgePortDefPtr; +struct _virNetworkBridgePortDef { + char *mac; + char *name; +}; + typedef struct _virNetworkDef virNetworkDef; typedef virNetworkDef *virNetworkDefPtr; struct _virNetworkDef { @@ -79,6 +86,9 @@ struct _virNetworkDef { unsigned int nhosts; /* Zero or more dhcp hosts */ virNetworkDHCPHostDefPtr hosts; + unsigned int nports; /* Zero or more filtered ports */ + virNetworkBridgePortDefPtr ports; + char *tftproot; char *bootfile; }; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b699fb2..f92f646 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -227,6 +227,32 @@ iptablesRemoveTcpInput; iptablesRemoveUdpInput; iptablesSaveRules; +# ebtables.h +ebtablesAddForwardAllowCross; +ebtablesAddForwardAllowIn; +ebtablesAddForwardAllowOut; +ebtablesAddForwardAllowRelatedIn; +ebtablesAddForwardMasquerade; +ebtablesAddForwardRejectIn; +ebtablesAddForwardRejectOut; +ebtablesAddTcpInput; +ebtablesAddUdpInput; +ebtablesContextFree; +ebtablesContextNew; +ebtablesReloadRules; +ebtablesRemoveForwardAllowCross; +ebtablesRemoveForwardAllowIn; +ebtablesRemoveForwardAllowOut; +ebtablesRemoveForwardAllowRelatedIn; +ebtablesRemoveForwardMasquerade; +ebtablesRemoveForwardRejectIn; +ebtablesRemoveForwardRejectOut; +ebtablesRemoveTcpInput; +ebtablesRemoveUdpInput; +ebtablesSaveRules; +ebtablesAddForwardPolicyReject; +ebtablesRemoveForwardPolicyReject; +ebtablesForwardPolicyReject; # libvirt_internal.h virStateInitialize; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 95bc810..acd7afe 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -54,6 +54,7 @@ #include "util.h" #include "memory.h" #include "uuid.h" +#include "ebtables.h" #include "iptables.h" #include "bridge.h" #include "logging.h" @@ -70,6 +71,7 @@ struct network_driver { virNetworkObjList networks; iptablesContext *iptables; + ebtablesContext *ebtables; brControl *brctl; char *networkConfigDir; char *networkAutostartDir; @@ -245,6 +247,10 @@ networkStartup(int privileged) { goto out_of_memory; } + if (!(driverState->ebtables = ebtablesContextNew())) { + goto out_of_memory; + } + if (virNetworkLoadAllConfigs(NULL, &driverState->networks, @@ -293,6 +299,11 @@ networkReload(void) { iptablesReloadRules(driverState->iptables); } + if (driverState->ebtables) { + VIR_INFO0(_("Reloading ebtables rules\n")); + ebtablesReloadRules(driverState->ebtables); + } + networkAutostartConfigs(driverState); networkDriverUnlock(driverState); return 0; @@ -350,6 +361,9 @@ networkShutdown(void) { if (driverState->iptables) iptablesContextFree(driverState->iptables); + if (driverState->ebtables) + ebtablesContextFree(driverState->ebtables); + networkDriverUnlock(driverState); virMutexDestroy(&driverState->lock); @@ -573,6 +587,168 @@ cleanup: return ret; } + +static int +networkAddEbtablesRules(virConnectPtr conn, + struct network_driver *driver) { + int err; + + /* Catch all rules to block forwarding to/from bridges */ +/* + if ((err = ebtablesAddForwardRejectOut(driver->ebtables, network->def->bridge))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to block outbound traffic from '%s'"), + network->def->bridge); + goto err5; + } + + if ((err = ebtablesAddForwardRejectIn(driver->ebtables, network->def->bridge))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to block inbound traffic to '%s'"), + network->def->bridge); + goto err6; + } +*/ + /* Set forward policy to DROP */ + if ((err = ebtablesAddForwardPolicyReject(driver->ebtables))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to set default policy to drop on '%s'"), + __FILE__); + return err; + } + /* Allow traffic between guests on the same bridge */ +/* + if ((err = ebtablesAddForwardAllowCross(driver->ebtables, network->def->bridge))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to allow cross bridge traffic on '%s'"), + network->def->bridge); + goto err7; + } +*/ + + /* if routing is enabled, set up the rules*/ +/* + networkAddRoutingEbtablesRules(conn, driver, network); + if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE && + !networkAddRoutingEbtablesRules(conn, driver, network)) + goto err8; +*/ +/* + for (r = 0 ; r < network->def->nports ; r++) { + virNetworkBridgePortDefPtr port = &(network->def->ports[r]); + if ((port->mac) && (port->name)) { + fprintf(stderr, "mac %s,name %s\n", + port->mac, port->name); + } + } + +*/ + ebtablesSaveRules(driver->ebtables); + + return 1; +/* + err8: + ebtablesRemoveForwardAllowCross(driver->ebtables, + network->def->bridge); + err7: + ebtablesRemoveForwardRejectIn(driver->ebtables, + network->def->bridge); + err6: + ebtablesRemoveForwardRejectOut(driver->ebtables, + network->def->bridge); + err5: + */ + return 0; +} + + +static int +networkDisableAllFrames(virConnectPtr conn) { + int err; + struct network_driver *netdriver = conn->networkPrivateData; + + /* Set forward policy to DROP */ + if ((err = !networkAddEbtablesRules(conn, netdriver))) { + virReportSystemError(conn, err, + _("cannot filter mac addresses on bridge '%s'"), + __FILE__); + return err; + } +/* if ((err = ebtablesAddForwardPolicyReject(netdriver->ebtables, "dummy"))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to set default policy to drop on '%s'"), + "dummy"); + } +*/ + return 0; +} + +static int +networkDisallowMacOnPort(virConnectPtr conn, + char * brname, + char * ifname, + unsigned char * mac) { + + int err; + char *macaddr; + struct network_driver *netdriver = conn->networkPrivateData; + + 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 = netdriver->ebtables; + if ((err = ebtablesRemoveForwardAllowIn(ebtablescontext, + brname, + ifname, + macaddr))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to allow routing to '%s'"), + ifname); + } + + return 0; +} + +static int +networkAllowMacOnPort(virConnectPtr conn, + char * brname, + char * ifname, + unsigned char * mac) { + + int err; + char *macaddr; + struct network_driver *netdriver = conn->networkPrivateData; + + 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 = netdriver->ebtables; + if ((err = ebtablesAddForwardAllowIn(ebtablescontext, + brname, + ifname, + macaddr))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to allow routing to '%s'"), + ifname); + } + + return 0; +} + static int networkAddMasqueradingIptablesRules(virConnectPtr conn, struct network_driver *driver, @@ -1497,6 +1673,9 @@ static virNetworkDriver networkDriver = { networkGetBridgeName, /* networkGetBridgeName */ networkGetAutostart, /* networkGetAutostart */ networkSetAutostart, /* networkSetAutostart */ + networkAllowMacOnPort, /* networkAllowMacOnPort */ + networkDisallowMacOnPort, /* networkDisallowMacOnPort */ + networkDisableAllFrames, /* networkDisableAllFrames */ }; static virStateDriver networkStateDriver = {

On Fri, Oct 02, 2009 at 03:48:21PM +0200, Gerhard Stenzel wrote:
This patch adds the ebtables wrapper to the network driver.
Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> ---
src/conf/network_conf.h | 10 ++ src/libvirt_private.syms | 26 ++++++ src/network/bridge_driver.c | 179 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 0 deletions(-)
IMHO, this code does not belong in the virNetwork apis / driver because that restricts its usefulness to guests using the virtual network configuration mode, ignoring any guests using bridged configs which are arguably far more important since those have ability to spoof MACs on the real LAN, not merely local machine. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch adds MAC address based port filtering support to libvirt. Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> --- include/libvirt/libvirt.h.in | 16 ++++++ src/driver.h | 16 ++++++ src/libvirt.c | 121 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 3 + src/test/test_driver.c | 3 + 5 files changed, 159 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 4e63e48..78e5cce 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -884,6 +884,22 @@ int virNetworkSetAutostart (virNetworkPtr network, int autostart); /* + * MAC address based filtering + */ + +int virNetworkDisableAllFrames(virConnectPtr conn); + +int virNetworkAllowMacOnPort(virNetworkPtr network, + char * brname, + char * ifname, + unsigned char * mac); + +int virNetworkDisallowMacOnPort(virNetworkPtr network, + char * brname, + char * ifname, + unsigned char * mac); + +/* * Physical host interface configuration API */ diff --git a/src/driver.h b/src/driver.h index 6a3dcc2..fea6247 100644 --- a/src/driver.h +++ b/src/driver.h @@ -470,6 +470,19 @@ typedef int typedef int (*virDrvNetworkSetAutostart) (virNetworkPtr network, int autostart); +typedef int + (*virDrvNetworkAllowMacOnPort) (virConnectPtr conn, + char * brname, + char * ifname, + unsigned char * mac); +typedef int + (*virDrvNetworkDisableAllFrames) (virConnectPtr conn); + +typedef int + (*virDrvNetworkDisallowMacOnPort) (virConnectPtr conn, + char * brname, + char * ifname, + unsigned char * mac); typedef struct _virNetworkDriver virNetworkDriver; @@ -504,6 +517,9 @@ struct _virNetworkDriver { virDrvNetworkGetBridgeName networkGetBridgeName; virDrvNetworkGetAutostart networkGetAutostart; virDrvNetworkSetAutostart networkSetAutostart; + virDrvNetworkAllowMacOnPort networkAllowMacOnPort; + virDrvNetworkDisallowMacOnPort networkDisallowMacOnPort; + virDrvNetworkDisableAllFrames networkDisableAllFrames; }; /*-------*/ diff --git a/src/libvirt.c b/src/libvirt.c index 4cc19ec..ca65beb 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5456,6 +5456,127 @@ error: } /** + * virNetworkDisableAllFrames: + * @network: a network object + * + * Provides a bridge interface name to which a domain may connect + * a network interface in order to join the network. + * + * Returns -1 in case of error, 0 in case of success + */ + +int +virNetworkDisableAllFrames(virConnectPtr conn) { + + virResetLastError(); + + if (conn->networkDriver && conn->networkDriver->networkDisableAllFrames) { + int ret; + ret = conn->networkDriver->networkDisableAllFrames(conn); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + return -1; +} + + +/** + * virNetworkDisallowMacOnPort: + * @network: a network object + * + * Provides a bridge interface name to which a domain may connect + * a network interface in order to join the network. + * + * Returns -1 in case of error, 0 in case of success + */ + +int +virNetworkDisallowMacOnPort(virNetworkPtr network, + char * brname, + char * ifname, + unsigned char * mac) { + + virConnectPtr conn; + DEBUG("network=%p", network); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + return (-1); + } + + conn = network->conn; + + if (conn->networkDriver && conn->networkDriver->networkDisallowMacOnPort) { + int ret; + ret = conn->networkDriver->networkDisallowMacOnPort (conn, brname, ifname, mac); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); + return -1; +} + +/** + * virNetworkAllowMacOnPort: + * @network: a network object + * + * Provides a bridge interface name to which a domain may connect + * a network interface in order to join the network. + * + * Returns -1 in case of error, 0 in case of success + */ + +int +virNetworkAllowMacOnPort(virNetworkPtr network, + char * brname, + char * ifname, + unsigned char * mac) { + + virConnectPtr conn; + DEBUG("network=%p", network); + DEBUG("%s: ifname=%s", __FILE__, ifname); + DEBUG("%s: mac=%s", __FILE__, mac); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_NETWORK(network)) { + virLibNetworkError(NULL, VIR_ERR_INVALID_NETWORK, __FUNCTION__); + return (-1); + } + + conn = network->conn; + + if (conn->networkDriver && conn->networkDriver->networkAllowMacOnPort) { + int ret; + ret = conn->networkDriver->networkAllowMacOnPort (conn, brname, ifname, mac); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(network->conn); + return -1; +} + +/** * virNetworkGetBridgeName: * @network: a network object * diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 7226e88..6ec6fa6 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -326,6 +326,9 @@ LIBVIRT_0.7.2 { virStreamFinish; virStreamAbort; virStreamFree; + virNetworkDisableAllFrames; + virNetworkAllowMacOnPort; + virNetworkDisallowMacOnPort; } LIBVIRT_0.7.1; # .... define new API here using predicted next version number .... diff --git a/src/test/test_driver.c b/src/test/test_driver.c index cb48f64..d72c453 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -4288,6 +4288,9 @@ static virNetworkDriver testNetworkDriver = { testNetworkGetBridgeName, /* networkGetBridgeName */ testNetworkGetAutostart, /* networkGetAutostart */ testNetworkSetAutostart, /* networkSetAutostart */ + NULL, /* */ + NULL, /* */ + NULL, /* */ }; static virInterfaceDriver testInterfaceDriver = {

This patch adds MAC address based port filtering to the qemu driver. Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> --- src/qemu/qemu.conf | 3 +++ src/qemu/qemu_conf.c | 14 ++++++++++++++ src/qemu/qemu_conf.h | 2 ++ src/qemu/qemu_driver.c | 23 +++++++++++++++++++++++ 4 files changed, 42 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..7a3b1f1 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -318,6 +318,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, } } + p = virConfGetValue (conf, "mac_filter"); + CHECK_TYPE ("mac_filter", VIR_CONF_LONG); + if (p) driver->macFilter = p->l; + virConfFree (conf); return 0; } @@ -1193,6 +1197,16 @@ qemudNetworkIfaceConnect(virConnectPtr conn, tapfd = -1; } + if (driver->macFilter) { + virNetworkPtr network = virNetworkLookupByName(conn, + net->data.network.name); + if ((err = virNetworkAllowMacOnPort(network, brname, 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..ddcbd8a 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -112,6 +112,8 @@ struct qemud_driver { char *hugetlbfs_mount; char *hugepage_path; + unsigned int macFilter : 1; + virCapsPtr caps; /* An array of callbacks */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 155e4a3..a95c867 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -239,6 +239,14 @@ qemudAutostartConfigs(struct qemud_driver *driver) { } virDomainObjUnlock(vm); } + if (qemu_driver->macFilter) { + fprintf(stderr,"%s:%s:%d macFilter=%d\n", __FILE__, __FUNCTION__, __LINE__, qemu_driver->macFilter); + if ((errno = virNetworkDisableAllFrames(conn))) { + virReportSystemError(conn, errno, + _("failed to add rule to drop all frames in '%s'"), __FILE__); + } + } + qemuDriverUnlock(driver); if (conn) @@ -2167,8 +2175,23 @@ cleanup: static void qemudShutdownVMDaemon(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm) { + int ret; int retries = 0; + char *brname; + + virDomainNetDefPtr net = vm->def->nets[0]; + virNetworkPtr network = virNetworkLookupByName(conn, + net->data.network.name); + brname = virNetworkGetBridgeName(network); + + if (driver->macFilter) { + if ((errno = virNetworkDisallowMacOnPort(network, brname, net->ifname, net->mac))) { + virReportSystemError(conn, errno, + _("failed to add ebtables rule to allow MAC address on '%s'"), + net->ifname); + } + } if (!virDomainIsActive(vm)) return;

On Fri, Oct 02, 2009 at 03:48:36PM +0200, Gerhard Stenzel wrote:
This patch adds MAC address based port filtering to the qemu driver.
Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> ---
src/qemu/qemu.conf | 3 +++ src/qemu/qemu_conf.c | 14 ++++++++++++++ src/qemu/qemu_conf.h | 2 ++ src/qemu/qemu_driver.c | 23 +++++++++++++++++++++++ 4 files changed, 42 insertions(+), 0 deletions(-)
@@ -1193,6 +1197,16 @@ qemudNetworkIfaceConnect(virConnectPtr conn, tapfd = -1; }
+ if (driver->macFilter) { + virNetworkPtr network = virNetworkLookupByName(conn, + net->data.network.name); + if ((err = virNetworkAllowMacOnPort(network, brname, net->ifname, net->mac))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to allow MAC address on '%s'"), + net->ifname); + } + }
This will crash in a large number of scenarios, since it is only valid to deference net->data.network fields once you have verified net->type == VIR_DOMAIN_NET_TYPE_NETWORK. It is also failing to check for virNetworkLookupByName() returning NULL. This is why the MAC filtering should not be part of the virNetwork API set. The QEMU driver should be directly calling the ebtables APIs you added in patch 1, rather then indirectly via virNetwork.. This would allow this MAC filtering to work with bridged network modes too.
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 155e4a3..a95c867 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -239,6 +239,14 @@ qemudAutostartConfigs(struct qemud_driver *driver) { } virDomainObjUnlock(vm); } + if (qemu_driver->macFilter) { + fprintf(stderr,"%s:%s:%d macFilter=%d\n", __FILE__, __FUNCTION__, __LINE__, qemu_driver->macFilter);
There's a VIR_DEBUG() macro available for logging.
+ if ((errno = virNetworkDisableAllFrames(conn))) { + virReportSystemError(conn, errno, + _("failed to add rule to drop all frames in '%s'"), __FILE__); + } + } + qemuDriverUnlock(driver);
if (conn) @@ -2167,8 +2175,23 @@ cleanup: static void qemudShutdownVMDaemon(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm) { + int ret; int retries = 0; + char *brname; + + virDomainNetDefPtr net = vm->def->nets[0];
This assumes the guest has exactly one NIC - it'll crash if there are no NICs, and it'll miss cleanup steps if there are multiple NICs
+ virNetworkPtr network = virNetworkLookupByName(conn, + net->data.network.name); + brname = virNetworkGetBridgeName(network); + + if (driver->macFilter) { + if ((errno = virNetworkDisallowMacOnPort(network, brname, net->ifname, net->mac))) { + virReportSystemError(conn, errno, + _("failed to add ebtables rule to allow MAC address on '%s'"), + net->ifname); + } + }
Same comment as before about not using virNetwork for any of this Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, 2009-10-05 at 13:19 +0100, Daniel P. Berrange wrote:
On Fri, Oct 02, 2009 at 03:48:36PM +0200, Gerhard Stenzel wrote:
This patch adds MAC address based port filtering to the qemu driver.
Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> ---
src/qemu/qemu.conf | 3 +++ src/qemu/qemu_conf.c | 14 ++++++++++++++ src/qemu/qemu_conf.h | 2 ++ src/qemu/qemu_driver.c | 23 +++++++++++++++++++++++ 4 files changed, 42 insertions(+), 0 deletions(-)
@@ -1193,6 +1197,16 @@ qemudNetworkIfaceConnect(virConnectPtr conn, tapfd = -1; }
+ if (driver->macFilter) { + virNetworkPtr network = virNetworkLookupByName(conn, + net->data.network.name); + if ((err = virNetworkAllowMacOnPort(network, brname, net->ifname, net->mac))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to allow MAC address on '%s'"), + net->ifname); + } + }
This will crash in a large number of scenarios, since it is only valid to deference net->data.network fields once you have verified net->type == VIR_DOMAIN_NET_TYPE_NETWORK. It is also failing to check for virNetworkLookupByName() returning NULL.
This is why the MAC filtering should not be part of the virNetwork API set. The QEMU driver should be directly calling the ebtables APIs you added in patch 1, rather then indirectly via virNetwork.. This would allow this MAC filtering to work with bridged network modes too.
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 155e4a3..a95c867 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -239,6 +239,14 @@ qemudAutostartConfigs(struct qemud_driver *driver) { } virDomainObjUnlock(vm); } + if (qemu_driver->macFilter) { + fprintf(stderr,"%s:%s:%d macFilter=%d\n", __FILE__, __FUNCTION__, __LINE__, qemu_driver->macFilter);
There's a VIR_DEBUG() macro available for logging.
+ if ((errno = virNetworkDisableAllFrames(conn))) { + virReportSystemError(conn, errno, + _("failed to add rule to drop all frames in '%s'"), __FILE__); + } + } + qemuDriverUnlock(driver);
if (conn) @@ -2167,8 +2175,23 @@ cleanup: static void qemudShutdownVMDaemon(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm) { + int ret; int retries = 0; + char *brname; + + virDomainNetDefPtr net = vm->def->nets[0];
This assumes the guest has exactly one NIC - it'll crash if there are no NICs, and it'll miss cleanup steps if there are multiple NICs
+ virNetworkPtr network = virNetworkLookupByName(conn, + net->data.network.name); + brname = virNetworkGetBridgeName(network); + + if (driver->macFilter) { + if ((errno = virNetworkDisallowMacOnPort(network, brname, net->ifname, net->mac))) { + virReportSystemError(conn, errno, + _("failed to add ebtables rule to allow MAC address on '%s'"), + net->ifname); + } + }
Same comment as before about not using virNetwork for any of this
Regards, Daniel
Thanks for the feedback so far. I know there is more to be done like handling multiple NICs and some more error checking, but is the following more in the direction you would like to have it? Index: libvirt/src/qemu/qemu_conf.c =================================================================== --- libvirt.orig/src/qemu/qemu_conf.c +++ libvirt/src/qemu/qemu_conf.c @@ -37,6 +37,7 @@ #include <sys/utsname.h> #include <mntent.h> +#include "ebtables.h" #include "c-ctype.h" #include "virterror_internal.h" #include "qemu_conf.h" @@ -318,6 +319,10 @@ int qemudLoadDriverConfig(struct qemud_d } } + p = virConfGetValue (conf, "mac_filter"); + CHECK_TYPE ("mac_filter", VIR_CONF_LONG); + if (p) driver->macFilter = p->l; + virConfFree (conf); return 0; } @@ -1118,6 +1123,38 @@ int qemudExtractVersion(virConnectPtr co } +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, @@ -1193,6 +1230,14 @@ qemudNetworkIfaceConnect(virConnectPtr c 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); Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -50,6 +50,7 @@ #include <sched.h> #endif +#include "ebtables.h" #include "virterror_internal.h" #include "logging.h" #include "datatypes.h" @@ -200,6 +201,74 @@ qemudLogReadFD(virConnectPtr conn, const return fd; } +static int +networkAddEbtablesRules(virConnectPtr conn, + struct qemud_driver *driver) { + int err; + + /* Set forward policy to DROP */ + if ((err = ebtablesAddForwardPolicyReject(driver->ebtables))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to set default policy to drop on '%s'"), + __FILE__); + return err; + } + ebtablesSaveRules(driver->ebtables); + + return 0; +} + +static int +networkDisableAllFrames(virConnectPtr conn, + struct qemud_driver *driver) { + int err; + + /* Set forward policy to DROP */ + if ((err = !networkAddEbtablesRules(conn, driver))) { + virReportSystemError(conn, err, + _("cannot filter mac addresses on bridge '%s'"), + __FILE__); + return err; + } +/* if ((err = ebtablesAddForwardPolicyReject(netdriver->ebtables, "dummy"))) { + virReportSystemError(conn, err, + _("failed to add ebtables rule to set default policy to drop on '%s'"), + "dummy"); + } +*/ + return 0; +} + +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; + } + /* allow 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 qemudAutostartConfigs(struct qemud_driver *driver) { @@ -240,6 +309,17 @@ qemudAutostartConfigs(struct qemud_drive } virDomainObjUnlock(vm); } + if (qemu_driver->macFilter) { + if (!(driver->ebtables = ebtablesContextNew())) { + qemu_driver->macFilter = 0; // TODO: we need to report an error here + } + + if ((errno = networkDisableAllFrames(conn, driver))) { + virReportSystemError(conn, errno, + _("failed to add rule to drop all frames in '%s'"), __FILE__); + } + } + qemuDriverUnlock(driver); if (conn) @@ -2168,8 +2248,18 @@ cleanup: static void qemudShutdownVMDaemon(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm) { int ret; int retries = 0; + + virDomainNetDefPtr net = vm->def->nets[0]; + + if (driver->macFilter) { + if ((errno = networkDisallowMacOnPort(conn, driver, net->ifname, net->mac))) { + virReportSystemError(conn, errno, + _("failed to add ebtables rule to allow MAC address on '%s'"), + net->ifname); + } + } if (!virDomainIsActive(vm)) return; Index: libvirt/src/qemu/qemu.conf =================================================================== --- libvirt.orig/src/qemu/qemu.conf +++ libvirt/src/qemu/qemu.conf @@ -152,3 +152,6 @@ # in a location of $MOUNTPOINT/libvirt/qemu # hugetlbfs_mount = "/dev/hugepages" + +mac_filter = 1 + Index: libvirt/src/qemu/qemu_conf.h =================================================================== --- libvirt.orig/src/qemu/qemu_conf.h +++ libvirt/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 */ -- Best regards, Gerhard Stenzel, ----------------------------------------------------------------------------------------------------------------------------------- IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Erich Baier Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294

This patch removes the currently unused "network" parameter to pass "make check" Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com> --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -890,12 +890,10 @@ int virNetworkSetAutostart (virNetworkPtr network, int virNetworkDisableAllFrames(virConnectPtr conn); int virNetworkAllowMacOnPort(virNetworkPtr network, - char * brname, char * ifname, unsigned char * mac); int virNetworkDisallowMacOnPort(virNetworkPtr network, - char * brname, char * ifname, unsigned char * mac); --- include/libvirt/libvirt.h.in | 2 -- src/driver.h | 2 -- src/libvirt.c | 6 ++---- src/network/bridge_driver.c | 4 ---- src/qemu/qemu_conf.c | 2 +- src/qemu/qemu_driver.c | 2 +- src/util/ebtables.c | 7 ++----- src/util/ebtables.h | 2 -- 8 files changed, 6 insertions(+), 21 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 78e5cce..13f6586 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -890,12 +890,10 @@ int virNetworkSetAutostart (virNetworkPtr network, int virNetworkDisableAllFrames(virConnectPtr conn); int virNetworkAllowMacOnPort(virNetworkPtr network, - char * brname, char * ifname, unsigned char * mac); int virNetworkDisallowMacOnPort(virNetworkPtr network, - char * brname, char * ifname, unsigned char * mac); diff --git a/src/driver.h b/src/driver.h index fea6247..e3936ff 100644 --- a/src/driver.h +++ b/src/driver.h @@ -472,7 +472,6 @@ typedef int int autostart); typedef int (*virDrvNetworkAllowMacOnPort) (virConnectPtr conn, - char * brname, char * ifname, unsigned char * mac); typedef int @@ -480,7 +479,6 @@ typedef int typedef int (*virDrvNetworkDisallowMacOnPort) (virConnectPtr conn, - char * brname, char * ifname, unsigned char * mac); diff --git a/src/libvirt.c b/src/libvirt.c index ca65beb..76d55ee 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5498,7 +5498,6 @@ error: int virNetworkDisallowMacOnPort(virNetworkPtr network, - char * brname, char * ifname, unsigned char * mac) { @@ -5516,7 +5515,7 @@ virNetworkDisallowMacOnPort(virNetworkPtr network, if (conn->networkDriver && conn->networkDriver->networkDisallowMacOnPort) { int ret; - ret = conn->networkDriver->networkDisallowMacOnPort (conn, brname, ifname, mac); + ret = conn->networkDriver->networkDisallowMacOnPort (conn, ifname, mac); if (ret < 0) goto error; return ret; @@ -5542,7 +5541,6 @@ error: int virNetworkAllowMacOnPort(virNetworkPtr network, - char * brname, char * ifname, unsigned char * mac) { @@ -5562,7 +5560,7 @@ virNetworkAllowMacOnPort(virNetworkPtr network, if (conn->networkDriver && conn->networkDriver->networkAllowMacOnPort) { int ret; - ret = conn->networkDriver->networkAllowMacOnPort (conn, brname, ifname, mac); + ret = conn->networkDriver->networkAllowMacOnPort (conn, ifname, mac); if (ret < 0) goto error; return ret; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index acd7afe..7d4cf2d 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -685,7 +685,6 @@ networkDisableAllFrames(virConnectPtr conn) { static int networkDisallowMacOnPort(virConnectPtr conn, - char * brname, char * ifname, unsigned char * mac) { @@ -705,7 +704,6 @@ networkDisallowMacOnPort(virConnectPtr conn, ebtablesContext * ebtablescontext = netdriver->ebtables; if ((err = ebtablesRemoveForwardAllowIn(ebtablescontext, - brname, ifname, macaddr))) { virReportSystemError(conn, err, @@ -718,7 +716,6 @@ networkDisallowMacOnPort(virConnectPtr conn, static int networkAllowMacOnPort(virConnectPtr conn, - char * brname, char * ifname, unsigned char * mac) { @@ -738,7 +735,6 @@ networkAllowMacOnPort(virConnectPtr conn, ebtablesContext * ebtablescontext = netdriver->ebtables; if ((err = ebtablesAddForwardAllowIn(ebtablescontext, - brname, ifname, macaddr))) { virReportSystemError(conn, err, diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 7a3b1f1..49a7b9b 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1200,7 +1200,7 @@ qemudNetworkIfaceConnect(virConnectPtr conn, if (driver->macFilter) { virNetworkPtr network = virNetworkLookupByName(conn, net->data.network.name); - if ((err = virNetworkAllowMacOnPort(network, brname, net->ifname, net->mac))) { + if ((err = virNetworkAllowMacOnPort(network, net->ifname, net->mac))) { virReportSystemError(conn, err, _("failed to add ebtables rule to allow MAC address on '%s'"), net->ifname); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a95c867..0c0af47 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2186,7 +2186,7 @@ static void qemudShutdownVMDaemon(virConnectPtr conn, brname = virNetworkGetBridgeName(network); if (driver->macFilter) { - if ((errno = virNetworkDisallowMacOnPort(network, brname, net->ifname, net->mac))) { + if ((errno = virNetworkDisallowMacOnPort(network, net->ifname, net->mac))) { virReportSystemError(conn, errno, _("failed to add ebtables rule to allow MAC address on '%s'"), net->ifname); diff --git a/src/util/ebtables.c b/src/util/ebtables.c index 930d046..5a86d44 100644 --- a/src/util/ebtables.c +++ b/src/util/ebtables.c @@ -750,7 +750,6 @@ ebtablesRemoveForwardAllowRelatedIn(ebtablesContext *ctx, */ static int ebtablesForwardAllowIn(ebtablesContext *ctx, - const char *network, const char *iface, const char *macaddr, int action) @@ -781,11 +780,10 @@ ebtablesForwardAllowIn(ebtablesContext *ctx, */ int ebtablesAddForwardAllowIn(ebtablesContext *ctx, - const char *network, const char *iface, const char *physdev) { - return ebtablesForwardAllowIn(ctx, network, iface, physdev, ADD); + return ebtablesForwardAllowIn(ctx, iface, physdev, ADD); } /** @@ -803,11 +801,10 @@ ebtablesAddForwardAllowIn(ebtablesContext *ctx, */ int ebtablesRemoveForwardAllowIn(ebtablesContext *ctx, - const char *network, const char *iface, const char *physdev) { - return ebtablesForwardAllowIn(ctx, network, iface, physdev, REMOVE); + return ebtablesForwardAllowIn(ctx, iface, physdev, REMOVE); } diff --git a/src/util/ebtables.h b/src/util/ebtables.h index 30b1056..2a4863b 100644 --- a/src/util/ebtables.h +++ b/src/util/ebtables.h @@ -96,11 +96,9 @@ int ebtablesRemoveForwardAllowRelatedIn(ebtablesContext *ctx, const char *physdev); int ebtablesAddForwardAllowIn (ebtablesContext *ctx, - const char *network, const char *iface, const char *physdev); int ebtablesRemoveForwardAllowIn (ebtablesContext *ctx, - const char *network, const char *iface, const char *physdev);
participants (2)
-
Daniel P. Berrange
-
Gerhard Stenzel