From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> --- src/Makefile.am | 2 +- src/qemu/qemu_bridge_filter.c | 2 +- src/qemu/qemu_conf.h | 2 +- src/util/ebtables.c | 486 ------------------------------------------ src/util/ebtables.h | 67 ------ src/util/virebtables.c | 486 ++++++++++++++++++++++++++++++++++++++++++ src/util/virebtables.h | 67 ++++++ 7 files changed, 556 insertions(+), 556 deletions(-) delete mode 100644 src/util/ebtables.c delete mode 100644 src/util/ebtables.h create mode 100644 src/util/virebtables.c create mode 100644 src/util/virebtables.h diff --git a/src/Makefile.am b/src/Makefile.am index ce16e87..daefa95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -57,7 +57,6 @@ UTIL_SOURCES = \ util/event_poll.c util/event_poll.h \ util/hooks.c util/hooks.h \ util/iptables.c util/iptables.h \ - util/ebtables.c util/ebtables.h \ util/json.c util/json.h \ util/logging.c util/logging.h \ util/memory.c util/memory.h \ @@ -83,6 +82,7 @@ UTIL_SOURCES = \ util/vircommand.c util/vircommand.h \ util/virconf.c util/virconf.h \ util/virdnsmasq.c util/virdnsmasq.h \ + util/virebtables.c util/virebtables.h \ util/virfile.c util/virfile.h \ util/virnodesuspend.c util/virnodesuspend.h \ util/virobject.c util/virobject.h \ diff --git a/src/qemu/qemu_bridge_filter.c b/src/qemu/qemu_bridge_filter.c index a34a92e..a6d0d4f 100644 --- a/src/qemu/qemu_bridge_filter.c +++ b/src/qemu/qemu_bridge_filter.c @@ -22,7 +22,7 @@ #include <config.h> -#include "ebtables.h" +#include "virebtables.h" #include "qemu_conf.h" #include "qemu_driver.h" #include "util.h" diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index eafaf9f..5499203 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -26,7 +26,7 @@ # include <config.h> -# include "ebtables.h" +# include "virebtables.h" # include "internal.h" # include "capabilities.h" # include "network_conf.h" diff --git a/src/util/ebtables.c b/src/util/ebtables.c deleted file mode 100644 index 4b427ee..0000000 --- a/src/util/ebtables.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright (C) 2007-2012 Red Hat, Inc. - * Copyright (C) 2009 IBM Corp. - * - * 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, see - * <http://www.gnu.org/licenses/>. - * - * based on iptables.c - * Authors: - * Gerhard Stenzel <gerhard.stenzel@xxxxxxxxxx> - */ - -#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> -#include <sys/wait.h> - -#ifdef HAVE_PATHS_H -# include <paths.h> -#endif - -#include "internal.h" -#include "ebtables.h" -#include "vircommand.h" -#include "memory.h" -#include "virterror_internal.h" -#include "logging.h" -#include "threads.h" - -#if HAVE_FIREWALLD -static char *firewall_cmd_path = NULL; - -static int -virEbTablesOnceInit(void) -{ - firewall_cmd_path = virFindFileInPath("firewall-cmd"); - if (!firewall_cmd_path) { - VIR_INFO("firewall-cmd not found on system. " - "firewalld support disabled for ebtables."); - } else { - virCommandPtr cmd = virCommandNew(firewall_cmd_path); - int status; - - virCommandAddArgList(cmd, "--state", NULL); - if (virCommandRun(cmd, &status) < 0 || status != 0) { - VIR_INFO("firewall-cmd found but disabled for ebtables"); - VIR_FREE(firewall_cmd_path); - firewall_cmd_path = NULL; - } else { - VIR_INFO("using firewalld for ebtables commands"); - } - virCommandFree(cmd); - } - return 0; -} - -VIR_ONCE_GLOBAL_INIT(virEbTables) - -#endif - -struct _ebtablesContext -{ - ebtRules *input_filter; - ebtRules *forward_filter; - ebtRules *nat_postrouting; -}; - -enum { - ADD = 0, - REMOVE, - CREATE, - POLICY, - INSERT -}; - -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; - } - - 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; - - return rules; - - error: - ebtRulesFree(rules); - return NULL; -} - -static int ATTRIBUTE_SENTINEL -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 */ - -#if HAVE_FIREWALLD - virEbTablesInitialize(); - if (firewall_cmd_path) - n += 3; /* --direct --passthrough eb */ -#endif - - va_start(args, arg); - while (va_arg(args, const char *)) - n++; - - va_end(args); - - if (VIR_ALLOC_N(argv, n + 1) < 0) - goto error; - - n = 0; - -#if HAVE_FIREWALLD - if (firewall_cmd_path) { - if (!(argv[n++] = strdup(firewall_cmd_path))) - goto error; - if (!(argv[n++] = strdup("--direct"))) - goto error; - if (!(argv[n++] = strdup("--passthrough"))) - goto error; - if (!(argv[n++] = strdup("eb"))) - goto error; - } else -#endif - if (!(argv[n++] = strdup(EBTABLES_PATH))) - goto error; - - command_idx = n; - - if (action == ADD || action == REMOVE) { - 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))) { - va_end(args); - 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(argv, NULL) < 0) { - retval = errno; - goto error; - } - - if (action == ADD || action == CREATE || action == POLICY || - action == INSERT) { - 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(const char *driver) -{ - bool success = false; - ebtablesContext *ctx = NULL; - char *input_chain = NULL; - char *forward_chain = NULL; - char *nat_chain = NULL; - - if (VIR_ALLOC(ctx) < 0) - return NULL; - - if (virAsprintf(&input_chain, "libvirt_%s_INPUT", driver) < 0 || - virAsprintf(&forward_chain, "libvirt_%s_FORWARD", driver) < 0 || - virAsprintf(&nat_chain, "libvirt_%s_POSTROUTING", driver) < 0) { - goto cleanup; - } - - if (!(ctx->input_filter = ebtRulesNew("filter", input_chain))) - goto cleanup; - - if (!(ctx->forward_filter = ebtRulesNew("filter", forward_chain))) - goto cleanup; - - if (!(ctx->nat_postrouting = ebtRulesNew("nat", nat_chain))) - goto cleanup; - - success = true; - -cleanup: - VIR_FREE(input_chain); - VIR_FREE(forward_chain); - VIR_FREE(nat_chain); - - if (!success) { - ebtablesContextFree(ctx); - ctx = NULL; - } - - return ctx; -} - -/** - * ebtablesContextFree: - * @ctx: pointer to the EB table context - * - * Free the resources associated with an EB table context - */ -void -ebtablesContextFree(ebtablesContext *ctx) -{ - if (!ctx) - return; - 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); -} - -int -ebtablesAddForwardPolicyReject(ebtablesContext *ctx) -{ - return ebtablesForwardPolicyReject(ctx, ADD); -} - - -int -ebtablesRemoveForwardPolicyReject(ebtablesContext *ctx) -{ - return ebtablesForwardPolicyReject(ctx, REMOVE); -} - -int -ebtablesForwardPolicyReject(ebtablesContext *ctx, - int action) -{ - /* create it, if it does not exist */ - if (action == ADD) { - ebtablesAddRemoveRule(ctx->forward_filter, - CREATE, - "--new-chain", ctx->forward_filter->chain, NULL, - NULL); - ebtablesAddRemoveRule(ctx->forward_filter, - INSERT, - "--insert", "FORWARD", "--jump", - ctx->forward_filter->chain, NULL); - } - - return ebtablesAddRemoveRule(ctx->forward_filter, - POLICY, - "-P", ctx->forward_filter->chain, "DROP", - NULL); -} - -/* - * Allow all traffic destined to the bridge, with a valid network address - */ -static int -ebtablesForwardAllowIn(ebtablesContext *ctx, - const char *iface, - const char *macaddr, - int action) -{ - return ebtablesAddRemoveRule(ctx->forward_filter, - action, - "--in-interface", iface, - "--source", macaddr, - "--jump", "ACCEPT", - NULL); -} - -/** - * ebtablesAddForwardAllowIn: - * @ctx: pointer to the EB table context - * @iface: the output interface name - * @physdev: the physical input device or NULL - * - * Add rules to the EB table context to allow the traffic on - * @physdev device to be forwarded to interface @iface. This allows - * the inbound traffic on a bridge. - * - * Returns 0 in case of success or an error code otherwise - */ -int -ebtablesAddForwardAllowIn(ebtablesContext *ctx, - const char *iface, - const virMacAddrPtr mac) -{ - char *macaddr; - - if (virAsprintf(&macaddr, - "%02x:%02x:%02x:%02x:%02x:%02x", - mac->addr[0], mac->addr[1], - mac->addr[2], mac->addr[3], - mac->addr[4], mac->addr[5]) < 0) { - return -1; - } - return ebtablesForwardAllowIn(ctx, iface, macaddr, ADD); -} - -/** - * ebtablesRemoveForwardAllowIn: - * @ctx: pointer to the EB table context - * @iface: the output interface name - * @physdev: the physical input device or NULL - * - * Remove rules from the EB table context hence forbidding the traffic - * on the @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 *iface, - const virMacAddrPtr mac) -{ - char *macaddr; - - if (virAsprintf(&macaddr, - "%02x:%02x:%02x:%02x:%02x:%02x", - mac->addr[0], mac->addr[1], - mac->addr[2], mac->addr[3], - mac->addr[4], mac->addr[5]) < 0) { - return -1; - } - return ebtablesForwardAllowIn(ctx, iface, macaddr, REMOVE); -} diff --git a/src/util/ebtables.h b/src/util/ebtables.h deleted file mode 100644 index 49dc8a0..0000000 --- a/src/util/ebtables.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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, see - * <http://www.gnu.org/licenses/>. - * - * based on iptables.h - * Authors: - * Gerhard Stenzel <gerhard.stenzel@xxxxxxxxxx> - */ - -#ifndef __QEMUD_EBTABLES_H__ -# define __QEMUD_EBTABLES_H__ - -# include "virmacaddr.h" - -typedef struct -{ - char *rule; - const char **argv; - int command_idx; -} ebtRule; - -typedef struct -{ - char *table; - char *chain; - - int nrules; - ebtRule *rules; - -} ebtRules; - -typedef struct _ebtablesContext ebtablesContext; - -ebtablesContext *ebtablesContextNew (const char *driver); -void ebtablesContextFree (ebtablesContext *ctx); - -void ebtablesSaveRules (ebtablesContext *ctx); - -int ebtablesAddForwardAllowIn (ebtablesContext *ctx, - const char *iface, - const virMacAddrPtr mac); -int ebtablesRemoveForwardAllowIn (ebtablesContext *ctx, - const char *iface, - const virMacAddrPtr mac); - -int ebtablesAddForwardPolicyReject(ebtablesContext *ctx); - -int ebtablesRemoveForwardPolicyReject(ebtablesContext *ctx); - -int ebtablesForwardPolicyReject(ebtablesContext *ctx, - int action); - -#endif /* __QEMUD_ebtabLES_H__ */ diff --git a/src/util/virebtables.c b/src/util/virebtables.c new file mode 100644 index 0000000..8474b2a --- /dev/null +++ b/src/util/virebtables.c @@ -0,0 +1,486 @@ +/* + * Copyright (C) 2007-2012 Red Hat, Inc. + * Copyright (C) 2009 IBM Corp. + * + * 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, see + * <http://www.gnu.org/licenses/>. + * + * based on iptables.c + * Authors: + * Gerhard Stenzel <gerhard.stenzel@xxxxxxxxxx> + */ + +#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> +#include <sys/wait.h> + +#ifdef HAVE_PATHS_H +# include <paths.h> +#endif + +#include "internal.h" +#include "virebtables.h" +#include "vircommand.h" +#include "memory.h" +#include "virterror_internal.h" +#include "logging.h" +#include "threads.h" + +#if HAVE_FIREWALLD +static char *firewall_cmd_path = NULL; + +static int +virEbTablesOnceInit(void) +{ + firewall_cmd_path = virFindFileInPath("firewall-cmd"); + if (!firewall_cmd_path) { + VIR_INFO("firewall-cmd not found on system. " + "firewalld support disabled for ebtables."); + } else { + virCommandPtr cmd = virCommandNew(firewall_cmd_path); + int status; + + virCommandAddArgList(cmd, "--state", NULL); + if (virCommandRun(cmd, &status) < 0 || status != 0) { + VIR_INFO("firewall-cmd found but disabled for ebtables"); + VIR_FREE(firewall_cmd_path); + firewall_cmd_path = NULL; + } else { + VIR_INFO("using firewalld for ebtables commands"); + } + virCommandFree(cmd); + } + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virEbTables) + +#endif + +struct _ebtablesContext +{ + ebtRules *input_filter; + ebtRules *forward_filter; + ebtRules *nat_postrouting; +}; + +enum { + ADD = 0, + REMOVE, + CREATE, + POLICY, + INSERT +}; + +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; + } + + 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; + + return rules; + + error: + ebtRulesFree(rules); + return NULL; +} + +static int ATTRIBUTE_SENTINEL +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 */ + +#if HAVE_FIREWALLD + virEbTablesInitialize(); + if (firewall_cmd_path) + n += 3; /* --direct --passthrough eb */ +#endif + + va_start(args, arg); + while (va_arg(args, const char *)) + n++; + + va_end(args); + + if (VIR_ALLOC_N(argv, n + 1) < 0) + goto error; + + n = 0; + +#if HAVE_FIREWALLD + if (firewall_cmd_path) { + if (!(argv[n++] = strdup(firewall_cmd_path))) + goto error; + if (!(argv[n++] = strdup("--direct"))) + goto error; + if (!(argv[n++] = strdup("--passthrough"))) + goto error; + if (!(argv[n++] = strdup("eb"))) + goto error; + } else +#endif + if (!(argv[n++] = strdup(EBTABLES_PATH))) + goto error; + + command_idx = n; + + if (action == ADD || action == REMOVE) { + 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))) { + va_end(args); + 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(argv, NULL) < 0) { + retval = errno; + goto error; + } + + if (action == ADD || action == CREATE || action == POLICY || + action == INSERT) { + 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(const char *driver) +{ + bool success = false; + ebtablesContext *ctx = NULL; + char *input_chain = NULL; + char *forward_chain = NULL; + char *nat_chain = NULL; + + if (VIR_ALLOC(ctx) < 0) + return NULL; + + if (virAsprintf(&input_chain, "libvirt_%s_INPUT", driver) < 0 || + virAsprintf(&forward_chain, "libvirt_%s_FORWARD", driver) < 0 || + virAsprintf(&nat_chain, "libvirt_%s_POSTROUTING", driver) < 0) { + goto cleanup; + } + + if (!(ctx->input_filter = ebtRulesNew("filter", input_chain))) + goto cleanup; + + if (!(ctx->forward_filter = ebtRulesNew("filter", forward_chain))) + goto cleanup; + + if (!(ctx->nat_postrouting = ebtRulesNew("nat", nat_chain))) + goto cleanup; + + success = true; + +cleanup: + VIR_FREE(input_chain); + VIR_FREE(forward_chain); + VIR_FREE(nat_chain); + + if (!success) { + ebtablesContextFree(ctx); + ctx = NULL; + } + + return ctx; +} + +/** + * ebtablesContextFree: + * @ctx: pointer to the EB table context + * + * Free the resources associated with an EB table context + */ +void +ebtablesContextFree(ebtablesContext *ctx) +{ + if (!ctx) + return; + 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); +} + +int +ebtablesAddForwardPolicyReject(ebtablesContext *ctx) +{ + return ebtablesForwardPolicyReject(ctx, ADD); +} + + +int +ebtablesRemoveForwardPolicyReject(ebtablesContext *ctx) +{ + return ebtablesForwardPolicyReject(ctx, REMOVE); +} + +int +ebtablesForwardPolicyReject(ebtablesContext *ctx, + int action) +{ + /* create it, if it does not exist */ + if (action == ADD) { + ebtablesAddRemoveRule(ctx->forward_filter, + CREATE, + "--new-chain", ctx->forward_filter->chain, NULL, + NULL); + ebtablesAddRemoveRule(ctx->forward_filter, + INSERT, + "--insert", "FORWARD", "--jump", + ctx->forward_filter->chain, NULL); + } + + return ebtablesAddRemoveRule(ctx->forward_filter, + POLICY, + "-P", ctx->forward_filter->chain, "DROP", + NULL); +} + +/* + * Allow all traffic destined to the bridge, with a valid network address + */ +static int +ebtablesForwardAllowIn(ebtablesContext *ctx, + const char *iface, + const char *macaddr, + int action) +{ + return ebtablesAddRemoveRule(ctx->forward_filter, + action, + "--in-interface", iface, + "--source", macaddr, + "--jump", "ACCEPT", + NULL); +} + +/** + * ebtablesAddForwardAllowIn: + * @ctx: pointer to the EB table context + * @iface: the output interface name + * @physdev: the physical input device or NULL + * + * Add rules to the EB table context to allow the traffic on + * @physdev device to be forwarded to interface @iface. This allows + * the inbound traffic on a bridge. + * + * Returns 0 in case of success or an error code otherwise + */ +int +ebtablesAddForwardAllowIn(ebtablesContext *ctx, + const char *iface, + const virMacAddrPtr mac) +{ + char *macaddr; + + if (virAsprintf(&macaddr, + "%02x:%02x:%02x:%02x:%02x:%02x", + mac->addr[0], mac->addr[1], + mac->addr[2], mac->addr[3], + mac->addr[4], mac->addr[5]) < 0) { + return -1; + } + return ebtablesForwardAllowIn(ctx, iface, macaddr, ADD); +} + +/** + * ebtablesRemoveForwardAllowIn: + * @ctx: pointer to the EB table context + * @iface: the output interface name + * @physdev: the physical input device or NULL + * + * Remove rules from the EB table context hence forbidding the traffic + * on the @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 *iface, + const virMacAddrPtr mac) +{ + char *macaddr; + + if (virAsprintf(&macaddr, + "%02x:%02x:%02x:%02x:%02x:%02x", + mac->addr[0], mac->addr[1], + mac->addr[2], mac->addr[3], + mac->addr[4], mac->addr[5]) < 0) { + return -1; + } + return ebtablesForwardAllowIn(ctx, iface, macaddr, REMOVE); +} diff --git a/src/util/virebtables.h b/src/util/virebtables.h new file mode 100644 index 0000000..49dc8a0 --- /dev/null +++ b/src/util/virebtables.h @@ -0,0 +1,67 @@ +/* + * 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, see + * <http://www.gnu.org/licenses/>. + * + * based on iptables.h + * Authors: + * Gerhard Stenzel <gerhard.stenzel@xxxxxxxxxx> + */ + +#ifndef __QEMUD_EBTABLES_H__ +# define __QEMUD_EBTABLES_H__ + +# include "virmacaddr.h" + +typedef struct +{ + char *rule; + const char **argv; + int command_idx; +} ebtRule; + +typedef struct +{ + char *table; + char *chain; + + int nrules; + ebtRule *rules; + +} ebtRules; + +typedef struct _ebtablesContext ebtablesContext; + +ebtablesContext *ebtablesContextNew (const char *driver); +void ebtablesContextFree (ebtablesContext *ctx); + +void ebtablesSaveRules (ebtablesContext *ctx); + +int ebtablesAddForwardAllowIn (ebtablesContext *ctx, + const char *iface, + const virMacAddrPtr mac); +int ebtablesRemoveForwardAllowIn (ebtablesContext *ctx, + const char *iface, + const virMacAddrPtr mac); + +int ebtablesAddForwardPolicyReject(ebtablesContext *ctx); + +int ebtablesRemoveForwardPolicyReject(ebtablesContext *ctx); + +int ebtablesForwardPolicyReject(ebtablesContext *ctx, + int action); + +#endif /* __QEMUD_ebtabLES_H__ */ -- 1.7.11.7 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list