2
* Copyright (C) 2007-2010 Red Hat, Inc.
3
* Copyright (C) 2009 IBM Corp.
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
* Gerhard Stenzel <gerhard.stenzel@de.ibm.com>
34
#include <sys/types.h>
46
#include "virterror_internal.h"
49
struct _ebtablesContext
51
ebtRules *input_filter;
52
ebtRules *forward_filter;
53
ebtRules *nat_postrouting;
65
ebtRuleFree(ebtRule *rule)
72
VIR_FREE(rule->argv[i++]);
78
ebtRulesAppend(ebtRules *rules,
83
if (VIR_REALLOC_N(rules->rules, rules->nrules+1) < 0) {
91
rules->rules[rules->nrules].rule = rule;
92
rules->rules[rules->nrules].argv = argv;
93
rules->rules[rules->nrules].command_idx = command_idx;
101
ebtRulesRemove(ebtRules *rules,
106
for (i = 0; i < rules->nrules; i++)
107
if (STREQ(rules->rules[i].rule, rule))
110
if (i >= rules->nrules)
113
ebtRuleFree(&rules->rules[i]);
115
memmove(&rules->rules[i],
117
(rules->nrules - i - 1) * sizeof (ebtRule));
125
ebtRulesFree(ebtRules *rules)
129
VIR_FREE(rules->table);
130
VIR_FREE(rules->chain);
133
for (i = 0; i < rules->nrules; i++)
134
ebtRuleFree(&rules->rules[i]);
136
VIR_FREE(rules->rules);
145
ebtRulesNew(const char *table,
150
if (VIR_ALLOC(rules) < 0)
153
if (!(rules->table = strdup(table)))
156
if (!(rules->chain = strdup(chain)))
169
static int ATTRIBUTE_SENTINEL
170
ebtablesAddRemoveRule(ebtRules *rules, int action, const char *arg, ...)
179
n = 1 + /* /sbin/ebtables */
180
2 + /* --table foo */
181
2 + /* --insert bar */
185
while (va_arg(args, const char *))
190
if (VIR_ALLOC_N(argv, n + 1) < 0)
195
if (!(argv[n++] = strdup(EBTABLES_PATH)))
200
if(action == ADD || action == REMOVE) {
201
if (!(argv[n++] = strdup("--insert")))
204
if (!(argv[n++] = strdup(rules->chain)))
208
if (!(argv[n++] = strdup(arg)))
213
while ((s = va_arg(args, const char *))) {
214
if (!(argv[n++] = strdup(s))) {
222
if (!(rule = virArgvToString(&argv[command_idx])))
225
if (action == REMOVE) {
226
VIR_FREE(argv[command_idx]);
227
if (!(argv[command_idx] = strdup("--delete")))
231
if (virRun(argv, NULL) < 0) {
236
if (action == ADD || action == CREATE || action == POLICY ||
238
retval = ebtRulesAppend(rules, rule, argv, command_idx);
242
retval = ebtRulesRemove(rules, rule);
260
* ebtablesContextNew:
262
* Create a new ebtable context
264
* Returns a pointer to the new structure or NULL in case of error
267
ebtablesContextNew(const char *driver)
269
bool success = false;
270
ebtablesContext *ctx = NULL;
271
char *input_chain = NULL;
272
char *forward_chain = NULL;
273
char *nat_chain = NULL;
275
if (VIR_ALLOC(ctx) < 0)
278
if (virAsprintf(&input_chain, "libvirt_%s_INPUT", driver) < 0 ||
279
virAsprintf(&forward_chain, "libvirt_%s_FORWARD", driver) < 0 ||
280
virAsprintf(&nat_chain, "libvirt_%s_POSTROUTING", driver) < 0) {
284
if (!(ctx->input_filter = ebtRulesNew("filter", input_chain)))
287
if (!(ctx->forward_filter = ebtRulesNew("filter", forward_chain)))
290
if (!(ctx->nat_postrouting = ebtRulesNew("nat", nat_chain)))
296
VIR_FREE(input_chain);
297
VIR_FREE(forward_chain);
301
ebtablesContextFree(ctx);
309
* ebtablesContextFree:
310
* @ctx: pointer to the EB table context
312
* Free the resources associated with an EB table context
315
ebtablesContextFree(ebtablesContext *ctx)
319
if (ctx->input_filter)
320
ebtRulesFree(ctx->input_filter);
321
if (ctx->forward_filter)
322
ebtRulesFree(ctx->forward_filter);
323
if (ctx->nat_postrouting)
324
ebtRulesFree(ctx->nat_postrouting);
329
ebtablesAddForwardPolicyReject(ebtablesContext *ctx)
331
return ebtablesForwardPolicyReject(ctx, ADD);
336
ebtablesRemoveForwardPolicyReject(ebtablesContext *ctx)
338
return ebtablesForwardPolicyReject(ctx, REMOVE);
342
ebtablesForwardPolicyReject(ebtablesContext *ctx,
345
/* create it, if it does not exist */
347
ebtablesAddRemoveRule(ctx->forward_filter,
349
"--new-chain", ctx->forward_filter->chain, NULL,
351
ebtablesAddRemoveRule(ctx->forward_filter,
353
"--insert", "FORWARD", "--jump",
354
ctx->forward_filter->chain, NULL);
357
return ebtablesAddRemoveRule(ctx->forward_filter,
359
"-P", ctx->forward_filter->chain, "DROP",
364
* Allow all traffic destined to the bridge, with a valid network address
367
ebtablesForwardAllowIn(ebtablesContext *ctx,
372
return ebtablesAddRemoveRule(ctx->forward_filter,
374
"--in-interface", iface,
381
* ebtablesAddForwardAllowIn:
382
* @ctx: pointer to the EB table context
383
* @iface: the output interface name
384
* @physdev: the physical input device or NULL
386
* Add rules to the EB table context to allow the traffic on
387
* @physdev device to be forwarded to interface @iface. This allows
388
* the inbound traffic on a bridge.
390
* Returns 0 in case of success or an error code otherwise
393
ebtablesAddForwardAllowIn(ebtablesContext *ctx,
395
const unsigned char *mac)
399
if (virAsprintf(&macaddr,
400
"%02x:%02x:%02x:%02x:%02x:%02x",
403
mac[4], mac[5]) < 0) {
406
return ebtablesForwardAllowIn(ctx, iface, macaddr, ADD);
410
* ebtablesRemoveForwardAllowIn:
411
* @ctx: pointer to the EB table context
412
* @iface: the output interface name
413
* @physdev: the physical input device or NULL
415
* Remove rules from the EB table context hence forbidding the traffic
416
* on the @physdev device to be forwarded to interface @iface. This
417
* stops the inbound traffic on a bridge.
419
* Returns 0 in case of success or an error code otherwise
422
ebtablesRemoveForwardAllowIn(ebtablesContext *ctx,
424
const unsigned char *mac)
428
if (virAsprintf(&macaddr,
429
"%02x:%02x:%02x:%02x:%02x:%02x",
432
mac[4], mac[5]) < 0) {
435
return ebtablesForwardAllowIn(ctx, iface, macaddr, REMOVE);