summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-10-09 20:11:16 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2014-11-24 11:35:34 +0100
commit902e92ceedba96d3241fa8ff701c061cd53a197d (patch)
tree9c45d7fcb97a3f507c727b31d77e7311cab1d74d
parentda871de2a6efb576b6378a66222c0871f4282e96 (diff)
ebtables-compat: use ebtables_command_state in bootstrap code
And introduce fake ebt_entry. This gets the code in sync in other existing compat tools. This will likely allow to consolidate common infrastructure. This code is still quite experimental. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/linux/netfilter_bridge/ebtables.h276
-rw-r--r--iptables/nft-bridge.c177
-rw-r--r--iptables/nft-bridge.h98
-rw-r--r--iptables/nft-shared.c4
-rw-r--r--iptables/nft-shared.h3
-rw-r--r--iptables/nft.h9
-rw-r--r--iptables/xtables-eb-standalone.c3
-rw-r--r--iptables/xtables-eb.c100
-rw-r--r--iptables/xtables-ebtables.h49
9 files changed, 252 insertions, 467 deletions
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
deleted file mode 100644
index f7ed1dcf..00000000
--- a/include/linux/netfilter_bridge/ebtables.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * ebtables
- *
- * Authors:
- * Bart De Schuymer <bdschuym@pandora.be>
- *
- * ebtables.c,v 2.0, April, 2002
- *
- * This code is stongly inspired on the iptables code which is
- * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
- */
-
-/* Local copy of the kernel file, needed for Sparc64 support */
-#ifndef __LINUX_BRIDGE_EFF_H
-#define __LINUX_BRIDGE_EFF_H
-#include <net/if.h>
-#include <linux/netfilter_bridge.h>
-#include <linux/if_ether.h>
-
-#define EBT_TABLE_MAXNAMELEN 32
-#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
-#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
-
-/* verdicts >0 are "branches" */
-#define EBT_ACCEPT -1
-#define EBT_DROP -2
-#define EBT_CONTINUE -3
-#define EBT_RETURN -4
-#define NUM_STANDARD_TARGETS 4
-/* ebtables target modules store the verdict inside an int. We can
- * reclaim a part of this int for backwards compatible extensions.
- * The 4 lsb are more than enough to store the verdict. */
-#define EBT_VERDICT_BITS 0x0000000F
-
-struct ebt_counter
-{
- uint64_t pcnt;
- uint64_t bcnt;
-};
-
-struct ebt_replace
-{
- char name[EBT_TABLE_MAXNAMELEN];
- unsigned int valid_hooks;
- /* nr of rules in the table */
- unsigned int nentries;
- /* total size of the entries */
- unsigned int entries_size;
- /* start of the chains */
-#ifdef KERNEL_64_USERSPACE_32
- uint64_t hook_entry[NF_BR_NUMHOOKS];
-#else
- struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
-#endif
- /* nr of counters userspace expects back */
- unsigned int num_counters;
- /* where the kernel will put the old counters */
-#ifdef KERNEL_64_USERSPACE_32
- uint64_t counters;
- uint64_t entries;
-#else
- struct ebt_counter *counters;
- char *entries;
-#endif
-};
-
-struct ebt_entries {
- /* this field is always set to zero
- * See EBT_ENTRY_OR_ENTRIES.
- * Must be same size as ebt_entry.bitmask */
- unsigned int distinguisher;
- /* the chain name */
- char name[EBT_CHAIN_MAXNAMELEN];
- /* counter offset for this chain */
- unsigned int counter_offset;
- /* one standard (accept, drop, return) per hook */
- int policy;
- /* nr. of entries */
- unsigned int nentries;
- /* entry list */
- char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-/* used for the bitmask of struct ebt_entry */
-
-/* This is a hack to make a difference between an ebt_entry struct and an
- * ebt_entries struct when traversing the entries from start to end.
- * Using this simplifies the code alot, while still being able to use
- * ebt_entries.
- * Contrary, iptables doesn't use something like ebt_entries and therefore uses
- * different techniques for naming the policy and such. So, iptables doesn't
- * need a hack like this.
- */
-#define EBT_ENTRY_OR_ENTRIES 0x01
-/* these are the normal masks */
-#define EBT_NOPROTO 0x02
-#define EBT_802_3 0x04
-#define EBT_SOURCEMAC 0x08
-#define EBT_DESTMAC 0x10
-#define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \
- | EBT_ENTRY_OR_ENTRIES)
-
-#define EBT_IPROTO 0x01
-#define EBT_IIN 0x02
-#define EBT_IOUT 0x04
-#define EBT_ISOURCE 0x8
-#define EBT_IDEST 0x10
-#define EBT_ILOGICALIN 0x20
-#define EBT_ILOGICALOUT 0x40
-#define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \
- | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST)
-
-struct ebt_entry_match
-{
- union {
- char name[EBT_FUNCTION_MAXNAMELEN];
- struct ebt_match *match;
- } u;
- /* size of data */
- unsigned int match_size;
-#ifdef KERNEL_64_USERSPACE_32
- unsigned int pad;
-#endif
- unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-struct ebt_entry_watcher
-{
- union {
- char name[EBT_FUNCTION_MAXNAMELEN];
- struct ebt_watcher *watcher;
- } u;
- /* size of data */
- unsigned int watcher_size;
-#ifdef KERNEL_64_USERSPACE_32
- unsigned int pad;
-#endif
- unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-struct ebt_entry_target
-{
- union {
- char name[EBT_FUNCTION_MAXNAMELEN];
- struct ebt_target *target;
- } u;
- /* size of data */
- unsigned int target_size;
-#ifdef KERNEL_64_USERSPACE_32
- unsigned int pad;
-#endif
- unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-#define EBT_STANDARD_TARGET "standard"
-struct ebt_standard_target
-{
- struct ebt_entry_target target;
- int verdict;
-#ifdef KERNEL_64_USERSPACE_32
- unsigned int pad;
-#endif
-};
-
-/* one entry */
-struct ebt_entry {
- /* this needs to be the first field */
- unsigned int bitmask;
- unsigned int invflags;
- uint16_t ethproto;
- /* the physical in-dev */
- char in[IFNAMSIZ];
- /* the logical in-dev */
- char logical_in[IFNAMSIZ];
- /* the physical out-dev */
- char out[IFNAMSIZ];
- /* the logical out-dev */
- char logical_out[IFNAMSIZ];
- unsigned char sourcemac[ETH_ALEN];
- unsigned char sourcemsk[ETH_ALEN];
- unsigned char destmac[ETH_ALEN];
- unsigned char destmsk[ETH_ALEN];
- /* sizeof ebt_entry + matches */
- unsigned int watchers_offset;
- /* sizeof ebt_entry + matches + watchers */
- unsigned int target_offset;
- /* sizeof ebt_entry + matches + watchers + target */
- unsigned int next_offset;
- unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
-};
-
-/* {g,s}etsockopt numbers */
-#define EBT_BASE_CTL 128
-
-#define EBT_SO_SET_ENTRIES (EBT_BASE_CTL)
-#define EBT_SO_SET_COUNTERS (EBT_SO_SET_ENTRIES+1)
-#define EBT_SO_SET_MAX (EBT_SO_SET_COUNTERS+1)
-
-#define EBT_SO_GET_INFO (EBT_BASE_CTL)
-#define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO+1)
-#define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES+1)
-#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1)
-#define EBT_SO_GET_MAX (EBT_SO_GET_INIT_ENTRIES+1)
-
-/* blatently stolen from ip_tables.h
- * fn returns 0 to continue iteration */
-#define EBT_MATCH_ITERATE(e, fn, args...) \
-({ \
- unsigned int __i; \
- int __ret = 0; \
- struct ebt_entry_match *__match; \
- \
- for (__i = sizeof(struct ebt_entry); \
- __i < (e)->watchers_offset; \
- __i += __match->match_size + \
- sizeof(struct ebt_entry_match)) { \
- __match = (void *)(e) + __i; \
- \
- __ret = fn(__match , ## args); \
- if (__ret != 0) \
- break; \
- } \
- if (__ret == 0) { \
- if (__i != (e)->watchers_offset) \
- __ret = -EINVAL; \
- } \
- __ret; \
-})
-
-#define EBT_WATCHER_ITERATE(e, fn, args...) \
-({ \
- unsigned int __i; \
- int __ret = 0; \
- struct ebt_entry_watcher *__watcher; \
- \
- for (__i = e->watchers_offset; \
- __i < (e)->target_offset; \
- __i += __watcher->watcher_size + \
- sizeof(struct ebt_entry_watcher)) { \
- __watcher = (void *)(e) + __i; \
- \
- __ret = fn(__watcher , ## args); \
- if (__ret != 0) \
- break; \
- } \
- if (__ret == 0) { \
- if (__i != (e)->target_offset) \
- __ret = -EINVAL; \
- } \
- __ret; \
-})
-
-#define EBT_ENTRY_ITERATE(entries, size, fn, args...) \
-({ \
- unsigned int __i; \
- int __ret = 0; \
- struct ebt_entry *__entry; \
- \
- for (__i = 0; __i < (size);) { \
- __entry = (void *)(entries) + __i; \
- __ret = fn(__entry , ## args); \
- if (__ret != 0) \
- break; \
- if (__entry->bitmask != 0) \
- __i += __entry->next_offset; \
- else \
- __i += sizeof(struct ebt_entries); \
- } \
- if (__ret == 0) { \
- if (__i != (size)) \
- __ret = -EINVAL; \
- } \
- __ret; \
-})
-
-#endif
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 66361ee9..ab97881d 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -18,11 +18,13 @@
#include <ebtables/ethernetdb.h>
#include "nft-shared.h"
+#include "nft-bridge.h"
#include "nft.h"
/* 0: default, print only 2 digits if necessary
* 2: always print 2 digits, a printed mac address
- * then always has the same length */
+ * then always has the same length
+ */
int ebt_printstyle_mac;
static void ebt_print_mac(const unsigned char *mac)
@@ -132,31 +134,36 @@ static void add_logical_outiface(struct nft_rule *r, char *iface, int invflags)
add_cmp_ptr(r, op, iface, iface_len + 1);
}
-static int _add_action(struct nft_rule *r, struct xtables_ebt_entry *fw)
+/* TODO: Use generic add_action() once we convert this to use
+ * iptables_command_state.
+ */
+static int _add_action(struct nft_rule *r, struct ebtables_command_state *cs)
{
int ret = 0;
- /* If no target at all, add nothing (default to continue) */
- if (fw->target != NULL) {
- /* Standard target? */
- if (strcmp(fw->jumpto, XTC_LABEL_ACCEPT) == 0)
- ret = add_verdict(r, NF_ACCEPT);
- else if (strcmp(fw->jumpto, XTC_LABEL_DROP) == 0)
- ret = add_verdict(r, NF_DROP);
- else if (strcmp(fw->jumpto, XTC_LABEL_RETURN) == 0)
- ret = add_verdict(r, NFT_RETURN);
- else
- ret = add_target(r, fw->target->t);
- } else if (strlen(fw->jumpto) > 0)
+ /* If no target at all, add nothing (default to continue) */
+ if (cs->target != NULL) {
+ /* Standard target? */
+ if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
+ ret = add_verdict(r, NF_ACCEPT);
+ else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
+ ret = add_verdict(r, NF_DROP);
+ else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
+ ret = add_verdict(r, NFT_RETURN);
+ else
+ ret = add_target(r, cs->target->t);
+ } else if (strlen(cs->jumpto) > 0) {
/* Not standard, then it's a jump to chain */
- ret = add_jumpto(r, fw->jumpto, NFT_JUMP);
+ ret = add_jumpto(r, cs->jumpto, NFT_JUMP);
+ }
- return ret;
+ return ret;
}
static int nft_bridge_add(struct nft_rule *r, void *data)
{
- struct xtables_ebt_entry *fw = data;
+ struct ebtables_command_state *cs = data;
+ struct ebt_entry *fw = &cs->fw;
uint8_t flags = ebt_to_ipt_flags(fw->invflags);
char *addr;
@@ -189,13 +196,14 @@ static int nft_bridge_add(struct nft_rule *r, void *data)
add_cmp_u16(r, fw->ethproto, NFT_CMP_EQ);
}
- return _add_action(r, fw);
+ return _add_action(r, cs);
}
static void nft_bridge_parse_meta(struct nft_xt_ctx *ctx,
struct nft_rule_expr *e, void *data)
{
- struct xtables_ebt_entry *fw = data;
+ struct ebtables_command_state *cs = data;
+ struct ebt_entry *fw = &cs->fw;
uint8_t flags = 0;
int iface = 0;
const void *ifname;
@@ -214,7 +222,7 @@ static void nft_bridge_parse_meta(struct nft_xt_ctx *ctx,
memcpy(fw->logical_in, ifname, len);
- if (fw->logical_in[len] == '\0')
+ if (fw->logical_in[len] == '\0')
memset(fw->in_mask, 0xff, len);
else {
fw->logical_in[len] = '+';
@@ -248,7 +256,8 @@ out:
static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
struct nft_rule_expr *e, void *data)
{
- struct xtables_ebt_entry *fw = data;
+ struct ebtables_command_state *cs = data;
+ struct ebt_entry *fw = &cs->fw;
unsigned char addr[ETH_ALEN];
unsigned short int ethproto;
bool inv;
@@ -271,28 +280,30 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
break;
}
}
+
static void nft_bridge_parse_immediate(const char *jumpto, bool nft_goto,
void *data)
{
- struct xtables_ebt_entry *fw = data;
+ struct ebtables_command_state *cs = data;
- fw->jumpto = jumpto;
+ cs->jumpto = jumpto;
}
static void nft_bridge_parse_target(struct xtables_target *t, void *data)
{
- struct xtables_ebt_entry *fw = data;
+ struct ebtables_command_state *cs = data;
- fw->target = t;
+ cs->target = t;
}
-void nft_rule_to_xtables_ebt_entry(struct nft_rule *r, struct xtables_ebt_entry *fw)
+void nft_rule_to_ebtables_command_state(struct nft_rule *r,
+ struct ebtables_command_state *cs)
{
struct nft_rule_expr_iter *iter;
struct nft_rule_expr *expr;
int family = nft_rule_attr_get_u32(r, NFT_RULE_ATTR_FAMILY);
struct nft_xt_ctx ctx = {
- .state.ebfw = fw,
+ .state.cs_eb = cs,
.family = family,
};
@@ -306,15 +317,19 @@ void nft_rule_to_xtables_ebt_entry(struct nft_rule *r, struct xtables_ebt_entry
nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
if (strcmp(name, "counter") == 0)
- nft_parse_counter(expr, &fw->counters);
+ nft_parse_counter(expr, &cs->counters);
else if (strcmp(name, "payload") == 0)
nft_parse_payload(&ctx, expr);
else if (strcmp(name, "meta") == 0)
nft_parse_meta(&ctx, expr);
+ else if (strcmp(name, "bitwise") == 0)
+ nft_parse_bitwise(&ctx, expr);
else if (strcmp(name, "cmp") == 0)
nft_parse_cmp(&ctx, expr);
else if (strcmp(name, "immediate") == 0)
nft_parse_immediate(&ctx, expr);
+ else if (strcmp(name, "match") == 0)
+ nft_parse_match(&ctx, expr);
else if (strcmp(name, "target") == 0)
nft_parse_target(&ctx, expr);
@@ -323,12 +338,12 @@ void nft_rule_to_xtables_ebt_entry(struct nft_rule *r, struct xtables_ebt_entry
nft_rule_expr_iter_destroy(iter);
- if (fw->target != NULL)
- fw->jumpto = fw->target->name;
- else if (fw->jumpto != NULL)
- fw->target = xtables_find_target(fw->jumpto, XTF_TRY_LOAD);
+ if (cs->target != NULL)
+ cs->jumpto = cs->target->name;
+ else if (cs->jumpto != NULL)
+ cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
else
- fw->jumpto = "";
+ cs->jumpto = "";
}
static void print_iface(const char *iface)
@@ -351,81 +366,80 @@ static void nft_bridge_print_header(unsigned int format, const char *chain,
print_header(format, chain, pol, counters, basechain, refs);
}
-static void
-nft_bridge_print_firewall(struct nft_rule *r, unsigned int num,
- unsigned int format)
+static void nft_bridge_print_firewall(struct nft_rule *r, unsigned int num,
+ unsigned int format)
{
- struct xtables_ebt_entry fw = {};
+ struct ebtables_command_state cs = {};
char *addr;
- nft_rule_to_xtables_ebt_entry(r, &fw);
+ nft_rule_to_ebtables_command_state(r, &cs);
if (format & FMT_LINENUMBERS)
printf("%d ", num);
/* Dont print anything about the protocol if no protocol was
* specified, obviously this means any protocol will do. */
- if (fw.ethproto != 0) {
+ if (cs.fw.ethproto != 0) {
printf("-p ");
- if (fw.invflags & EBT_IPROTO)
+ if (cs.fw.invflags & EBT_IPROTO)
printf("! ");
- if (fw.bitmask & EBT_802_3)
+ if (cs.fw.bitmask & EBT_802_3)
printf("Length ");
else {
struct ethertypeent *ent;
- ent = getethertypebynumber(ntohs(fw.ethproto));
+ ent = getethertypebynumber(ntohs(cs.fw.ethproto));
if (!ent)
- printf("0x%x ", ntohs(fw.ethproto));
+ printf("0x%x ", ntohs(cs.fw.ethproto));
else
printf("%s ", ent->e_name);
}
}
- addr = ether_ntoa((struct ether_addr *) fw.sourcemac);
+ addr = ether_ntoa((struct ether_addr *) cs.fw.sourcemac);
if (strcmp(addr, "0:0:0:0:0:0") != 0) {
printf("-s ");
- if (fw.invflags & EBT_ISOURCE)
+ if (cs.fw.invflags & EBT_ISOURCE)
printf("! ");
- ebt_print_mac_and_mask(fw.sourcemac, fw.sourcemsk);
+ ebt_print_mac_and_mask(cs.fw.sourcemac, cs.fw.sourcemsk);
printf(" ");
}
- addr = ether_ntoa((struct ether_addr *) fw.destmac);
+ addr = ether_ntoa((struct ether_addr *) cs.fw.destmac);
if (strcmp(addr, "0:0:0:0:0:0") != 0) {
printf("-d ");
- if (fw.invflags & EBT_IDEST)
+ if (cs.fw.invflags & EBT_IDEST)
printf("! ");
- ebt_print_mac_and_mask(fw.destmac, fw.destmsk);
+ ebt_print_mac_and_mask(cs.fw.destmac, cs.fw.destmsk);
printf(" ");
}
- if (fw.in[0] != '\0') {
+ if (cs.fw.in[0] != '\0') {
printf("-i ");
- if (fw.invflags & EBT_IIN)
+ if (cs.fw.invflags & EBT_IIN)
printf("! ");
- print_iface(fw.in);
+ print_iface(cs.fw.in);
}
- if (fw.logical_in[0] != '\0') {
+ if (cs.fw.logical_in[0] != '\0') {
printf("--logical-in ");
- if (fw.invflags & EBT_ILOGICALIN)
+ if (cs.fw.invflags & EBT_ILOGICALIN)
printf("! ");
- print_iface(fw.logical_in);
+ print_iface(cs.fw.logical_in);
}
- if (fw.logical_out[0] != '\0') {
+ if (cs.fw.logical_out[0] != '\0') {
printf("--logical-out ");
- if (fw.invflags & EBT_ILOGICALOUT)
+ if (cs.fw.invflags & EBT_ILOGICALOUT)
printf("! ");
- print_iface(fw.logical_out);
+ print_iface(cs.fw.logical_out);
}
- if (fw.out[0] != '\0') {
+ if (cs.fw.out[0] != '\0') {
printf("-o ");
- if (fw.invflags & EBT_IOUT)
+ if (cs.fw.invflags & EBT_IOUT)
printf("! ");
- print_iface(fw.out);
+ print_iface(cs.fw.out);
}
/* old code to adapt
@@ -447,12 +461,12 @@ nft_bridge_print_firewall(struct nft_rule *r, unsigned int num,
}*/
printf("-j ");
if (!(format & FMT_NOTARGET))
- printf("%s", fw.jumpto);
+ printf("%s", cs.jumpto);
- if (fw.target != NULL) {
- if (fw.target->print != NULL) {
- fw.target->print(&fw, fw.target->t,
- format & FMT_NUMERIC);
+ if (cs.target != NULL) {
+ if (cs.target->print != NULL) {
+ cs.target->print(&cs.fw, cs.target->t,
+ format & FMT_NUMERIC);
}
}
@@ -460,16 +474,15 @@ nft_bridge_print_firewall(struct nft_rule *r, unsigned int num,
fputc('\n', stdout);
}
-static bool nft_bridge_is_same(const void *data_a,
- const void *data_b)
+static bool nft_bridge_is_same(const void *data_a, const void *data_b)
{
- const struct xtables_ebt_entry *a = data_a;
- const struct xtables_ebt_entry *b = data_b;
+ const struct ebt_entry *a = data_a;
+ const struct ebt_entry *b = data_b;
int i;
- if (a->ethproto != b->ethproto
- /*|| a->flags != b->flags*/
- || a->invflags != b->invflags) {
+ if (a->ethproto != b->ethproto ||
+ /* FIXME: a->flags != b->flags || */
+ a->invflags != b->invflags) {
DEBUGP("different proto/flags/invflags\n");
return false;
}
@@ -515,27 +528,27 @@ static bool nft_bridge_is_same(const void *data_a,
static bool nft_bridge_rule_find(struct nft_family_ops *ops, struct nft_rule *r,
void *data)
{
- struct xtables_ebt_entry *fw = data;
- struct xtables_ebt_entry this = {};
+ struct ebtables_command_state *cs = data;
+ struct ebtables_command_state this = {};
- nft_rule_to_xtables_ebt_entry(r, &this);
+ nft_rule_to_ebtables_command_state(r, &this);
DEBUGP("comparing with... ");
- if (!ops->is_same(fw, &this))
+ if (!nft_bridge_is_same(cs, &this))
return false;
- if (!compare_matches(fw->matches, this.matches)) {
+ if (!compare_matches(cs->matches, this.matches)) {
DEBUGP("Different matches\n");
return false;
}
- if (!compare_targets(fw->target, this.target)) {
+ if (!compare_targets(cs->target, this.target)) {
DEBUGP("Different target\n");
return false;
}
- if (strcmp(fw->jumpto, this.jumpto) != 0) {
+ if (strcmp(cs->jumpto, this.jumpto) != 0) {
DEBUGP("Different verdict\n");
return false;
}
@@ -550,9 +563,11 @@ struct nft_family_ops nft_family_ops_bridge = {
.parse_meta = nft_bridge_parse_meta,
.parse_payload = nft_bridge_parse_payload,
.parse_immediate = nft_bridge_parse_immediate,
+ .parse_target = nft_bridge_parse_target,
.print_header = nft_bridge_print_header,
.print_firewall = nft_bridge_print_firewall,
+ .save_firewall = NULL,
+ .save_counters = NULL,
.post_parse = NULL,
.rule_find = nft_bridge_rule_find,
- .parse_target = nft_bridge_parse_target,
};
diff --git a/iptables/nft-bridge.h b/iptables/nft-bridge.h
new file mode 100644
index 00000000..1e3f0a16
--- /dev/null
+++ b/iptables/nft-bridge.h
@@ -0,0 +1,98 @@
+#ifndef _NFT_BRIDGE_H_
+#define _NFT_BRIDGE_H_
+
+#include <netinet/in.h>
+//#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter/x_tables.h>
+
+/* We use replace->flags, so we can't use the following values:
+ * 0x01 == OPT_COMMAND, 0x02 == OPT_TABLE, 0x100 == OPT_ZERO */
+#define LIST_N 0x04
+#define LIST_C 0x08
+#define LIST_X 0x10
+#define LIST_MAC2 0x20
+
+/* Be backwards compatible, so don't use '+' in kernel */
+#define IF_WILDCARD 1
+
+extern unsigned char eb_mac_type_unicast[ETH_ALEN];
+extern unsigned char eb_msk_type_unicast[ETH_ALEN];
+extern unsigned char eb_mac_type_multicast[ETH_ALEN];
+extern unsigned char eb_msk_type_multicast[ETH_ALEN];
+extern unsigned char eb_mac_type_broadcast[ETH_ALEN];
+extern unsigned char eb_msk_type_broadcast[ETH_ALEN];
+extern unsigned char eb_mac_type_bridge_group[ETH_ALEN];
+extern unsigned char eb_msk_type_bridge_group[ETH_ALEN];
+
+int ebt_get_mac_and_mask(const char *from, unsigned char *to, unsigned char *mask);
+
+/* From: include/linux/netfilter_bridge/ebtables.h
+ *
+ * Adapted for the need of the ebtables-compat.
+ */
+
+#define EBT_TABLE_MAXNAMELEN 32
+#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
+#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
+
+/* verdicts >0 are "branches" */
+#define EBT_ACCEPT -1
+#define EBT_DROP -2
+#define EBT_CONTINUE -3
+#define EBT_RETURN -4
+#define NUM_STANDARD_TARGETS 4
+
+#define EBT_ENTRY_OR_ENTRIES 0x01
+/* these are the normal masks */
+#define EBT_NOPROTO 0x02
+#define EBT_802_3 0x04
+#define EBT_SOURCEMAC 0x08
+#define EBT_DESTMAC 0x10
+#define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \
+ | EBT_ENTRY_OR_ENTRIES)
+
+#define EBT_IPROTO 0x01
+#define EBT_IIN 0x02
+#define EBT_IOUT 0x04
+#define EBT_ISOURCE 0x8
+#define EBT_IDEST 0x10
+#define EBT_ILOGICALIN 0x20
+#define EBT_ILOGICALOUT 0x40
+#define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \
+ | EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST)
+
+/* Fake ebt_entry */
+struct ebt_entry {
+ /* this needs to be the first field */
+ unsigned int bitmask;
+ unsigned int invflags;
+ uint16_t ethproto;
+ /* the physical in-dev */
+ char in[IFNAMSIZ];
+ /* the logical in-dev */
+ char logical_in[IFNAMSIZ];
+ /* the physical out-dev */
+ char out[IFNAMSIZ];
+ /* the logical out-dev */
+ char logical_out[IFNAMSIZ];
+ unsigned char sourcemac[ETH_ALEN];
+ unsigned char sourcemsk[ETH_ALEN];
+ unsigned char destmac[ETH_ALEN];
+ unsigned char destmsk[ETH_ALEN];
+
+ unsigned char in_mask[IFNAMSIZ];
+ unsigned char out_mask[IFNAMSIZ];
+};
+
+struct ebtables_command_state {
+ struct ebt_entry fw;
+ struct xtables_target *target;
+ struct xtables_rule_match *matches;
+ const char *jumpto;
+ struct xt_counters counters;
+};
+
+void nft_rule_to_ebtables_command_state(struct nft_rule *r,
+ struct ebtables_command_state *cs);
+
+#endif
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 9ca2e35c..71c44763 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -280,7 +280,7 @@ static void *nft_get_data(struct nft_xt_ctx *ctx)
case NFPROTO_ARP:
return ctx->state.cs_arp;
case NFPROTO_BRIDGE:
- return ctx->state.ebfw;
+ return ctx->state.cs_eb;
default:
/* Should not happen */
return NULL;
@@ -320,7 +320,7 @@ void nft_parse_target(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
ops->parse_target(target, data);
}
-static void nft_parse_match(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
+void nft_parse_match(struct nft_xt_ctx *ctx, struct nft_rule_expr *e)
{
uint32_t mt_len;
const char *mt_name = nft_rule_expr_get_str(e, NFT_EXPR_MT_NAME);
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 97d41df8..361e9566 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -48,7 +48,7 @@ struct nft_xt_ctx {
union {
struct iptables_command_state *cs;
struct arptables_command_state *cs_arp;
- struct xtables_ebt_entry *ebfw;
+ struct ebtables_command_state *cs_eb;
} state;
struct nft_rule_expr_iter *iter;
int family;
@@ -130,6 +130,7 @@ void print_proto(uint16_t proto, int invert);
void get_cmp_data(struct nft_rule_expr *e, void *data, size_t dlen, bool *inv);
void nft_parse_bitwise(struct nft_xt_ctx *ctx, struct nft_rule_expr *e);
void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nft_rule_expr *e);
+void nft_parse_match(struct nft_xt_ctx *ctx, struct nft_rule_expr *e);
void nft_parse_target(struct nft_xt_ctx *ctx, struct nft_rule_expr *e);
void nft_parse_meta(struct nft_xt_ctx *ctx, struct nft_rule_expr *e);
void nft_parse_payload(struct nft_xt_ctx *ctx, struct nft_rule_expr *e);
diff --git a/iptables/nft.h b/iptables/nft.h
index 4f0b733c..ab3d64ac 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -170,13 +170,4 @@ int nft_arp_rule_insert(struct nft_handle *h, const char *chain,
void nft_rule_to_arpt_entry(struct nft_rule *r, struct arpt_entry *fw);
-/*
- * BRIDGE
- */
-
-#include "xtables-ebtables.h"
-
-struct xtables_ebt_entry;
-
-void nft_rule_to_xtables_ebt_entry(struct nft_rule *r, struct xtables_ebt_entry *fw);
#endif
diff --git a/iptables/xtables-eb-standalone.c b/iptables/xtables-eb-standalone.c
index 6ec418cb..1c3cbf07 100644
--- a/iptables/xtables-eb-standalone.c
+++ b/iptables/xtables-eb-standalone.c
@@ -83,5 +83,8 @@ int xtables_eb_main(int argc, char *argv[])
if (ret)
ret = nft_commit(&h);
+ if (!ret)
+ fprintf(stderr, "%s\n", nft_strerror(errno));
+
exit(!ret);
}
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 73a38db9..99d930e5 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -31,9 +31,11 @@
#include <netinet/ether.h>
#include <xtables.h>
+#include <linux/netfilter_bridge.h>
#include <ebtables/ethernetdb.h>
#include "xshared.h"
#include "nft.h"
+#include "nft-bridge.h"
extern struct xtables_globals xtables_globals;
#define prog_name xtables_globals.program_name
@@ -213,16 +215,16 @@ static int
append_entry(struct nft_handle *h,
const char *chain,
const char *table,
- struct xtables_ebt_entry *fw,
+ struct ebtables_command_state *cs,
int rule_nr,
bool verbose, bool append)
{
int ret = 1;
if (append)
- ret = nft_rule_append(h, chain, table, fw, 0, verbose);
+ ret = nft_rule_append(h, chain, table, cs, 0, verbose);
else
- ret = nft_rule_insert(h, chain, table, fw, rule_nr, verbose);
+ ret = nft_rule_insert(h, chain, table, cs, rule_nr, verbose);
return ret;
}
@@ -231,7 +233,7 @@ static int
delete_entry(struct nft_handle *h,
const char *chain,
const char *table,
- struct xtables_ebt_entry *fw,
+ struct ebtables_command_state *cs,
int rule_nr,
int rule_nr_end,
bool verbose)
@@ -239,7 +241,7 @@ delete_entry(struct nft_handle *h,
int ret = 1;
if (rule_nr == -1)
- ret = nft_rule_delete(h, chain, table, fw, verbose);
+ ret = nft_rule_delete(h, chain, table, cs, verbose);
else {
do {
ret = nft_rule_delete_num(h, chain, table,
@@ -342,7 +344,7 @@ static struct option *ebt_options = ebt_original_options;
/*
* More glue code.
*/
-static struct xtables_target *command_jump(struct xtables_ebt_entry *fw,
+static struct xtables_target *command_jump(struct ebtables_command_state *cs,
const char *jumpto)
{
struct xtables_target *target;
@@ -490,7 +492,7 @@ static int parse_rule_range(const char *argv, int *rule_nr, int *rule_nr_end)
/* Incrementing or decrementing rules in daemon mode is not supported as the
* involved code overload is not worth it (too annoying to take the increased
* counters in the kernel into account). */
-static int parse_change_counters_rule(int argc, char **argv, int *rule_nr, int *rule_nr_end, int exec_style, struct xtables_ebt_entry *fw)
+static int parse_change_counters_rule(int argc, char **argv, int *rule_nr, int *rule_nr_end, int exec_style, struct ebtables_command_state *cs)
{
char *buffer;
int ret = 0;
@@ -515,16 +517,16 @@ daemon_incr:
xtables_error(PARAMETER_PROBLEM,
"Incrementing rule counters (%s) not allowed in daemon mode", argv[optind]);
ret += 1;
- fw->counters.pcnt = strtoull(argv[optind] + 1, &buffer, 10);
+ cs->counters.pcnt = strtoull(argv[optind] + 1, &buffer, 10);
} else if (argv[optind][0] == '-') {
if (exec_style == EXEC_STYLE_DAEMON)
daemon_decr:
xtables_error(PARAMETER_PROBLEM,
"Decrementing rule counters (%s) not allowed in daemon mode", argv[optind]);
ret += 2;
- fw->counters.pcnt = strtoull(argv[optind] + 1, &buffer, 10);
+ cs->counters.pcnt = strtoull(argv[optind] + 1, &buffer, 10);
} else
- fw->counters.pcnt = strtoull(argv[optind], &buffer, 10);
+ cs->counters.pcnt = strtoull(argv[optind], &buffer, 10);
if (*buffer != '\0')
goto invalid;
@@ -533,14 +535,14 @@ daemon_decr:
if (exec_style == EXEC_STYLE_DAEMON)
goto daemon_incr;
ret += 3;
- fw->counters.bcnt = strtoull(argv[optind] + 1, &buffer, 10);
+ cs->counters.bcnt = strtoull(argv[optind] + 1, &buffer, 10);
} else if (argv[optind][0] == '-') {
if (exec_style == EXEC_STYLE_DAEMON)
goto daemon_decr;
ret += 6;
- fw->counters.bcnt = strtoull(argv[optind] + 1, &buffer, 10);
+ cs->counters.bcnt = strtoull(argv[optind] + 1, &buffer, 10);
} else
- fw->counters.bcnt = strtoull(argv[optind], &buffer, 10);
+ cs->counters.bcnt = strtoull(argv[optind], &buffer, 10);
if (*buffer != '\0')
goto invalid;
@@ -577,7 +579,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
int ret = 0;
unsigned int flags = 0;
struct xtables_target *t;
- struct xtables_ebt_entry fw;
+ struct ebtables_command_state cs;
char command = 'h';
const char *chain = NULL;
const char *newname = NULL;
@@ -585,7 +587,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
int exec_style = EXEC_STYLE_PRG;
int selected_chain = -1;
- memset(&fw, 0, sizeof(fw));
+ memset(&cs, 0, sizeof(cs));
if (nft_init(h, xtables_bridge) < 0)
xtables_error(OTHER_PROBLEM,
@@ -651,7 +653,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
"Problem with the specified rule number(s) '%s'", argv[optind]);
optind++;
} else if (c == 'C') {
- if ((chcounter = parse_change_counters_rule(argc, argv, &rule_nr, &rule_nr_end, exec_style, &fw)) == -1)
+ if ((chcounter = parse_change_counters_rule(argc, argv, &rule_nr, &rule_nr_end, exec_style, &cs)) == -1)
return -1;
} else if (c == 'I') {
if (optind >= argc || (argv[optind][0] == '-' && (argv[optind][1] < '0' || argv[optind][1] > '9')))
@@ -748,7 +750,7 @@ print_zero:
struct ebt_u_watcher *w;*/
if (!strcasecmp("list_extensions", argv[optind])) {
- ebt_list_extensions(xtables_targets, fw.matches);
+ ebt_list_extensions(xtables_targets, cs.matches);
exit(0);
}
/*if ((m = ebt_find_match(argv[optind])))
@@ -761,7 +763,7 @@ print_zero:
if (flags & OPT_JUMP)
xtables_error(PARAMETER_PROBLEM,"Sorry, you can only see help for one target extension at a time");
flags |= OPT_JUMP;
- fw.target = t;
+ cs.target = t;
//}
optind++;
}
@@ -798,14 +800,14 @@ print_zero:
xtables_error(PARAMETER_PROBLEM,
"Use -i only in INPUT, FORWARD, PREROUTING and BROUTING chains");
if (ebt_check_inverse2(optarg, argc, argv))
- fw.invflags |= EBT_IIN;
+ cs.fw.invflags |= EBT_IIN;
if (strlen(optarg) >= IFNAMSIZ)
big_iface_length:
xtables_error(PARAMETER_PROBLEM,
"Interface name length cannot exceed %d characters",
IFNAMSIZ - 1);
- xtables_parse_interface(optarg, fw.in, fw.in_mask);
+ xtables_parse_interface(optarg, cs.fw.in, cs.fw.in_mask);
break;
} else if (c == 2) {
ebt_check_option2(&flags, OPT_LOGICALIN);
@@ -813,12 +815,12 @@ big_iface_length:
xtables_error(PARAMETER_PROBLEM,
"Use --logical-in only in INPUT, FORWARD, PREROUTING and BROUTING chains");
if (ebt_check_inverse2(optarg, argc, argv))
- fw.invflags |= EBT_ILOGICALIN;
+ cs.fw.invflags |= EBT_ILOGICALIN;
if (strlen(optarg) >= IFNAMSIZ)
goto big_iface_length;
- strcpy(fw.logical_in, optarg);
- if (parse_iface(fw.logical_in, "--logical-in"))
+ strcpy(cs.fw.logical_in, optarg);
+ if (parse_iface(cs.fw.logical_in, "--logical-in"))
return -1;
break;
} else if (c == 'o') {
@@ -827,12 +829,12 @@ big_iface_length:
xtables_error(PARAMETER_PROBLEM,
"Use -o only in OUTPUT, FORWARD and POSTROUTING chains");
if (ebt_check_inverse2(optarg, argc, argv))
- fw.invflags |= EBT_IOUT;
+ cs.fw.invflags |= EBT_IOUT;
if (strlen(optarg) >= IFNAMSIZ)
goto big_iface_length;
- xtables_parse_interface(optarg, fw.out, fw.out_mask);
+ xtables_parse_interface(optarg, cs.fw.out, cs.fw.out_mask);
break;
} else if (c == 3) {
ebt_check_option2(&flags, OPT_LOGICALOUT);
@@ -840,36 +842,36 @@ big_iface_length:
xtables_error(PARAMETER_PROBLEM,
"Use --logical-out only in OUTPUT, FORWARD and POSTROUTING chains");
if (ebt_check_inverse2(optarg, argc, argv))
- fw.invflags |= EBT_ILOGICALOUT;
+ cs.fw.invflags |= EBT_ILOGICALOUT;
if (strlen(optarg) >= IFNAMSIZ)
goto big_iface_length;
- strcpy(fw.logical_out, optarg);
- if (parse_iface(fw.logical_out, "--logical-out"))
+ strcpy(cs.fw.logical_out, optarg);
+ if (parse_iface(cs.fw.logical_out, "--logical-out"))
return -1;
break;
} else if (c == 'j') {
ebt_check_option2(&flags, OPT_JUMP);
- fw.jumpto = parse_target(optarg);
- fw.target = command_jump(&fw, fw.jumpto);
+ cs.jumpto = parse_target(optarg);
+ cs.target = command_jump(&cs, cs.jumpto);
break;
} else if (c == 's') {
ebt_check_option2(&flags, OPT_SOURCE);
if (ebt_check_inverse2(optarg, argc, argv))
- fw.invflags |= EBT_ISOURCE;
+ cs.fw.invflags |= EBT_ISOURCE;
- if (ebt_get_mac_and_mask(optarg, fw.sourcemac, fw.sourcemsk))
+ if (ebt_get_mac_and_mask(optarg, cs.fw.sourcemac, cs.fw.sourcemsk))
xtables_error(PARAMETER_PROBLEM, "Problem with specified source mac '%s'", optarg);
- fw.bitmask |= EBT_SOURCEMAC;
+ cs.fw.bitmask |= EBT_SOURCEMAC;
break;
} else if (c == 'd') {
ebt_check_option2(&flags, OPT_DEST);
if (ebt_check_inverse2(optarg, argc, argv))
- fw.invflags |= EBT_IDEST;
+ cs.fw.invflags |= EBT_IDEST;
- if (ebt_get_mac_and_mask(optarg, fw.destmac, fw.destmsk))
+ if (ebt_get_mac_and_mask(optarg, cs.fw.destmac, cs.fw.destmsk))
xtables_error(PARAMETER_PROBLEM, "Problem with specified destination mac '%s'", optarg);
- fw.bitmask |= EBT_DESTMAC;
+ cs.fw.bitmask |= EBT_DESTMAC;
break;
} else if (c == 'c') {
ebt_check_option2(&flags, OPT_COUNT);
@@ -880,12 +882,12 @@ big_iface_length:
xtables_error(PARAMETER_PROBLEM,
"Option -c needs 2 arguments");
- fw.counters.pcnt = strtoull(optarg, &buffer, 10);
+ cs.counters.pcnt = strtoull(optarg, &buffer, 10);
if (*buffer != '\0')
xtables_error(PARAMETER_PROBLEM,
"Packet counter '%s' invalid",
optarg);
- fw.counters.bcnt = strtoull(argv[optind], &buffer, 10);
+ cs.counters.bcnt = strtoull(argv[optind], &buffer, 10);
if (*buffer != '\0')
xtables_error(PARAMETER_PROBLEM,
"Packet counter '%s' invalid",
@@ -895,9 +897,9 @@ big_iface_length:
}
ebt_check_option2(&flags, OPT_PROTOCOL);
if (ebt_check_inverse2(optarg, argc, argv))
- fw.invflags |= EBT_IPROTO;
+ cs.fw.invflags |= EBT_IPROTO;
- fw.bitmask &= ~((unsigned int)EBT_NOPROTO);
+ cs.fw.bitmask &= ~((unsigned int)EBT_NOPROTO);
i = strtol(optarg, &buffer, 16);
if (*buffer == '\0' && (i < 0 || i > 0xFFFF))
xtables_error(PARAMETER_PROBLEM,
@@ -906,18 +908,18 @@ big_iface_length:
struct ethertypeent *ent;
if (!strcasecmp(optarg, "LENGTH")) {
- fw.bitmask |= EBT_802_3;
+ cs.fw.bitmask |= EBT_802_3;
break;
}
ent = getethertypebyname(optarg);
if (!ent)
xtables_error(PARAMETER_PROBLEM,
"Problem with the specified Ethernet protocol '%s', perhaps "_PATH_ETHERTYPES " is missing", optarg);
- fw.ethproto = ent->e_ethertype;
+ cs.fw.ethproto = ent->e_ethertype;
} else
- fw.ethproto = i;
+ cs.fw.ethproto = i;
- if (fw.ethproto < 0x0600)
+ if (cs.fw.ethproto < 0x0600)
xtables_error(PARAMETER_PROBLEM,
"Sorry, protocols have values above or equal to 0x0600");
break;
@@ -1103,7 +1105,7 @@ check_extension: */
ebt_print_error2("Bad table name");*/
if (command == 'h' && !(flags & OPT_ZERO)) {
- print_help(fw.target, fw.matches, *table);
+ print_help(cs.target, cs.matches, *table);
if (exec_style == EXEC_STYLE_PRG)
exit(0);
}
@@ -1142,7 +1144,7 @@ check_extension: */
}*/
/* So, the extensions can work with the host endian.
* The kernel does not have to do this of course */
- fw.ethproto = htons(fw.ethproto);
+ cs.fw.ethproto = htons(cs.fw.ethproto);
if (command == 'P') {
if (selected_chain < NF_BR_NUMHOOKS && strcmp(policy, "RETURN")==0)
@@ -1166,13 +1168,13 @@ check_extension: */
} else if (command == 'F') {
ret = nft_rule_flush(h, chain, *table);
} else if (command == 'A') {
- ret = append_entry(h, chain, *table, &fw, 0,
+ ret = append_entry(h, chain, *table, &cs, 0,
flags&OPT_VERBOSE, true);
} else if (command == 'I') {
- ret = append_entry(h, chain, *table, &fw, rule_nr - 1,
+ ret = append_entry(h, chain, *table, &cs, rule_nr - 1,
flags&OPT_VERBOSE, false);
} else if (command == 'D') {
- ret = delete_entry(h, chain, *table, &fw, rule_nr - 1,
+ ret = delete_entry(h, chain, *table, &cs, rule_nr - 1,
rule_nr_end, flags&OPT_VERBOSE);
} /*else if (replace->command == 'C') {
ebt_change_counters(replace, new_entry, rule_nr, rule_nr_end, &(new_entry->cnt_surplus), chcounter);
diff --git a/iptables/xtables-ebtables.h b/iptables/xtables-ebtables.h
deleted file mode 100644
index 1e479b1b..00000000
--- a/iptables/xtables-ebtables.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef _XTABLES_EBTABLES_H_
-#define _XTABLES_EBTABLES_H_
-
-#include <netinet/in.h>
-#include <linux/netfilter_bridge/ebtables.h>
-#include <linux/netfilter/x_tables.h>
-
-/* We use replace->flags, so we can't use the following values:
- * 0x01 == OPT_COMMAND, 0x02 == OPT_TABLE, 0x100 == OPT_ZERO */
-#define LIST_N 0x04
-#define LIST_C 0x08
-#define LIST_X 0x10
-#define LIST_MAC2 0x20
-
-/* Be backwards compatible, so don't use '+' in kernel */
-#define IF_WILDCARD 1
-
-extern unsigned char eb_mac_type_unicast[ETH_ALEN];
-extern unsigned char eb_msk_type_unicast[ETH_ALEN];
-extern unsigned char eb_mac_type_multicast[ETH_ALEN];
-extern unsigned char eb_msk_type_multicast[ETH_ALEN];
-extern unsigned char eb_mac_type_broadcast[ETH_ALEN];
-extern unsigned char eb_msk_type_broadcast[ETH_ALEN];
-extern unsigned char eb_mac_type_bridge_group[ETH_ALEN];
-extern unsigned char eb_msk_type_bridge_group[ETH_ALEN];
-
-int ebt_get_mac_and_mask(const char *from, unsigned char *to, unsigned char *mask);
-
-struct xtables_ebt_entry {
- unsigned int bitmask;
- unsigned int invflags;
- unsigned int flags;
- uint16_t ethproto;
- char in[IFNAMSIZ];
- char logical_in[IFNAMSIZ];
- unsigned char in_mask[IFNAMSIZ];
- char out[IFNAMSIZ];
- char logical_out[IFNAMSIZ];
- unsigned char out_mask[IFNAMSIZ];
- unsigned char sourcemac[ETH_ALEN];
- unsigned char sourcemsk[ETH_ALEN];
- unsigned char destmac[ETH_ALEN];
- unsigned char destmsk[ETH_ALEN];
- struct xtables_rule_match *matches;
- struct xtables_target *target;
- struct xt_counters counters;
- const char *jumpto;
-};
-#endif