* [PATCH 0/2] xtables-eb for the compatibility layer
@ 2014-02-05 18:17 Giuseppe Longo
2014-02-05 18:17 ` [PATCH 1/2] xtables: bootstrap xtables-eb for nftables Giuseppe Longo
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Giuseppe Longo @ 2014-02-05 18:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Giuseppe Longo
Hi,
this patchset implements ebtables for the nftables compatibility layer.
I would explain some points:
- The code is not built with the gcc version 4.7.3 (Gentoo 4.7.3-r1 p1.3, pie-0.5.5):
xtables_multi-nft-bridge.o:/home/giuseppe/git/iptables-nftables/iptables/nft-bridge.c:53: first defined here
xtables_multi-nft-bridge.o: In function `nft_rule_to_xtables_ebt_entry':
/home/giuseppe/git/iptables-nftables/iptables/nft-bridge.c:226: multiple definition of `nft_rule_to_xtables_ebt_entry'
xtables_multi-nft-bridge.o:/home/giuseppe/git/iptables-nftables/iptables/nft-bridge.c:226: first defined here
xtables_multi-nft-bridge.o:(.data+0x0): multiple definition of `nft_family_ops_bridge'
xtables_multi-nft-bridge.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
but, with the gcc version 4.8.2 (Debian 4.8.2-1) (on my vm) it works fine.
I didn't figure out the reason, honestly.
- I didn't figure out how to replace some parts of codes, for istance:
from xtables-eb.c, line 928:
t = (struct ebt_u_target *)new_entry->t;
if ((t->parse(c - t->option_offset, argv, argc, new_entry, &t->flags, &t->t))) {
if (ebt_errormsg[0] != '\0')
return -1;
goto check_extension;
}
/* Is it a match_option? */
for (m = ebt_matches; m; m = m->next)
if (m->parse(c - m->option_offset, argv, argc, new_entry, &m->flags, &m->m))
break;
if (m != NULL) {
if (ebt_errormsg[0] != '\0')
return -1;
if (m->used == 0) {
ebt_add_match(new_entry, m);
m->used = 1;
}
goto check_extension;
}
Looking at extensions, I noticed that any xtables_match/xtables_target have parse functions. Maybe I'm wrong.
Even the code from line 992 is not very clear, about final checks. I don't know if I can remove this part of code.
Thanks
Giuseppe Longo (2):
xtables: bootstrap xtables-eb for nftables
Operations for bridge family
include/linux/netfilter_bridge.h | 33 +
include/linux/netfilter_bridge/ebtables.h | 276 +++++++
include/linux/netfilter_bridge/ethernetdb.h | 58 ++
iptables/Makefile.am | 8 +-
iptables/getethertype.c | 161 ++++
iptables/nft-bridge.c | 384 +++++++++
iptables/nft-shared.c | 3 +
iptables/nft.c | 28 +
iptables/nft.h | 12 +
iptables/xtables-eb-standalone.c | 87 +++
iptables/xtables-eb.c | 1122 +++++++++++++++++++++++++++
iptables/xtables-ebtables.h | 39 +
iptables/xtables-multi.c | 1 +
iptables/xtables-multi.h | 1 +
14 files changed, 2210 insertions(+), 3 deletions(-)
create mode 100644 include/linux/netfilter_bridge.h
create mode 100644 include/linux/netfilter_bridge/ebtables.h
create mode 100644 include/linux/netfilter_bridge/ethernetdb.h
create mode 100644 iptables/getethertype.c
create mode 100644 iptables/nft-bridge.c
create mode 100644 iptables/xtables-eb-standalone.c
create mode 100644 iptables/xtables-eb.c
create mode 100644 iptables/xtables-ebtables.h
--
1.8.1.5
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] xtables: bootstrap xtables-eb for nftables
2014-02-05 18:17 [PATCH 0/2] xtables-eb for the compatibility layer Giuseppe Longo
@ 2014-02-05 18:17 ` Giuseppe Longo
2014-02-05 23:26 ` Giuseppe Longo
2014-02-05 18:17 ` [PATCH 2/2] Operations for bridge family Giuseppe Longo
2014-02-05 20:43 ` [PATCH 0/2] xtables-eb for the compatibility layer Bart De Schuymer
2 siblings, 1 reply; 6+ messages in thread
From: Giuseppe Longo @ 2014-02-05 18:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Giuseppe Longo
This patch bootstraps xtables-eb for the nftables compatibility layer
Signed-off-by: Giuseppe Longo <giuseppelng@gmail.com>
---
include/linux/netfilter_bridge.h | 33 +
include/linux/netfilter_bridge/ebtables.h | 276 +++++++
include/linux/netfilter_bridge/ethernetdb.h | 58 ++
iptables/Makefile.am | 6 +-
iptables/getethertype.c | 161 ++++
iptables/nft.c | 28 +
iptables/nft.h | 9 +
iptables/xtables-eb-standalone.c | 87 +++
iptables/xtables-eb.c | 1122 +++++++++++++++++++++++++++
iptables/xtables-ebtables.h | 39 +
iptables/xtables-multi.c | 1 +
iptables/xtables-multi.h | 1 +
12 files changed, 1819 insertions(+), 2 deletions(-)
create mode 100644 include/linux/netfilter_bridge.h
create mode 100644 include/linux/netfilter_bridge/ebtables.h
create mode 100644 include/linux/netfilter_bridge/ethernetdb.h
create mode 100644 iptables/getethertype.c
create mode 100644 iptables/xtables-eb-standalone.c
create mode 100644 iptables/xtables-eb.c
create mode 100644 iptables/xtables-ebtables.h
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
new file mode 100644
index 0000000..71e9299
--- /dev/null
+++ b/include/linux/netfilter_bridge.h
@@ -0,0 +1,33 @@
+#ifndef __LINUX_BRIDGE_NETFILTER_H
+#define __LINUX_BRIDGE_NETFILTER_H
+
+/* bridge-specific defines for netfilter.
+ */
+#include <limits.h>
+
+/* Bridge Hooks */
+/* After promisc drops, checksum checks. */
+#define NF_BR_PRE_ROUTING 0
+/* If the packet is destined for this box. */
+#define NF_BR_LOCAL_IN 1
+/* If the packet is destined for another interface. */
+#define NF_BR_FORWARD 2
+/* Packets coming from a local process. */
+#define NF_BR_LOCAL_OUT 3
+/* Packets about to hit the wire. */
+#define NF_BR_POST_ROUTING 4
+/* Not really a hook, but used for the ebtables broute table */
+#define NF_BR_BROUTING 5
+#define NF_BR_NUMHOOKS 6
+
+enum nf_br_hook_priorities {
+ NF_BR_PRI_FIRST = INT_MIN,
+ NF_BR_PRI_FILTER_BRIDGED = -200,
+ NF_BR_PRI_FILTER_OTHER = 200,
+ NF_BR_PRI_NAT_DST_BRIDGED = -300,
+ NF_BR_PRI_NAT_DST_OTHER = 100,
+ NF_BR_PRI_NAT_SRC = 300,
+ NF_BR_PRI_LAST = INT_MAX,
+};
+
+#endif
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
new file mode 100644
index 0000000..f7ed1dc
--- /dev/null
+++ b/include/linux/netfilter_bridge/ebtables.h
@@ -0,0 +1,276 @@
+/*
+ * 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/include/linux/netfilter_bridge/ethernetdb.h b/include/linux/netfilter_bridge/ethernetdb.h
new file mode 100644
index 0000000..46d8bfd
--- /dev/null
+++ b/include/linux/netfilter_bridge/ethernetdb.h
@@ -0,0 +1,58 @@
+/*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/* All data returned by the network data base library are supplied in
+ host order and returned in network order (suitable for use in
+ system calls). */
+
+#ifndef _ETHERNETDB_H
+#define _ETHERNETDB_H 1
+
+#include <features.h>
+#include <netinet/in.h>
+#include <stdint.h>
+
+/* Absolute file name for network data base files. */
+#ifndef _PATH_ETHERTYPES
+#define _PATH_ETHERTYPES "/etc/ethertypes"
+#endif /* _PATH_ETHERTYPES */
+
+struct ethertypeent {
+ char *e_name; /* Official ethernet type name. */
+ char **e_aliases; /* Alias list. */
+ int e_ethertype; /* Ethernet type number. */
+};
+
+/* Open ethertype data base files and mark them as staying open even
+ after a later search if STAY_OPEN is non-zero. */
+extern void setethertypeent(int __stay_open) __THROW;
+
+/* Close ethertype data base files and clear `stay open' flag. */
+extern void endethertypeent(void) __THROW;
+
+/* Get next entry from ethertype data base file. Open data base if
+ necessary. */
+extern struct ethertypeent *getethertypeent(void) __THROW;
+
+/* Return entry from ethertype data base for network with NAME. */
+extern struct ethertypeent *getethertypebyname(__const char *__name)
+ __THROW;
+
+/* Return entry from ethertype data base which number is PROTO. */
+extern struct ethertypeent *getethertypebynumber(int __ethertype) __THROW;
+
+
+#endif /* ethernetdb.h */
diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index 5a8c52f..be31d0e 100644
--- a/iptables/Makefile.am
+++ b/iptables/Makefile.am
@@ -32,7 +32,9 @@ xtables_multi_SOURCES += xtables-save.c xtables-restore.c \
xtables-standalone.c xtables.c nft.c \
nft-shared.c nft-ipv4.c nft-ipv6.c nft-arp.c \
xtables-config.c xtables-events.c \
- xtables-arp-standalone.c xtables-arp.c
+ xtables-arp-standalone.c xtables-arp.c \
+ getethertype.c nft-bridge.c \
+ xtables-eb-standalone.c xtables-eb.c
xtables_multi_LDADD += -lmnl -lnftables ${libmnl_LIBS} ${libnftables_LIBS}
xtables_multi_CFLAGS += -DENABLE_NFTABLES
# yacc and lex generate dirty code
@@ -57,7 +59,7 @@ v6_sbin_links = ip6tables ip6tables-restore ip6tables-save
endif
if ENABLE_NFTABLES
x_sbin_links = xtables xtables-restore xtables-save xtables-config \
- xtables-events xtables-arp
+ xtables-events xtables-arp xtables-eb
endif
iptables-extensions.8: ${srcdir}/iptables-extensions.8.tmpl ../extensions/matches.man ../extensions/targets.man
diff --git a/iptables/getethertype.c b/iptables/getethertype.c
new file mode 100644
index 0000000..7c9ef3d
--- /dev/null
+++ b/iptables/getethertype.c
@@ -0,0 +1,161 @@
+/*
+* getethertype.c
+*
+* This file was part of the NYS Library.
+*
+** The NYS Library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Library General Public License as
+** published by the Free Software Foundation; either version 2 of the
+** License, or (at your option) any later version.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/********************************************************************
+* Description: Ethertype name service switch and the ethertypes
+* database access functions
+* Author: Nick Fedchik <fnm@ukrsat.com>
+* Checker: Bart De Schuymer <bdschuym@pandora.be>
+* Origin: uClibc-0.9.16/libc/inet/getproto.c
+* Created at: Mon Nov 11 12:20:11 EET 2002
+********************************************************************/
+
+#include <ctype.h>
+#include <features.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/ether.h>
+#include <net/ethernet.h>
+
+#include <linux/netfilter_bridge/ethernetdb.h>
+
+#define MAXALIASES 35
+
+static FILE *etherf = NULL;
+static char line[BUFSIZ + 1];
+static struct ethertypeent et_ent;
+static char *ethertype_aliases[MAXALIASES];
+static int ethertype_stayopen;
+
+void setethertypeent(int f)
+{
+ if (etherf == NULL)
+ etherf = fopen(_PATH_ETHERTYPES, "r");
+ else
+ rewind(etherf);
+ ethertype_stayopen |= f;
+}
+
+void endethertypeent(void)
+{
+ if (etherf) {
+ fclose(etherf);
+ etherf = NULL;
+ }
+ ethertype_stayopen = 0;
+}
+
+struct ethertypeent *getethertypeent(void)
+{
+ char *e;
+ char *endptr;
+ register char *cp, **q;
+
+ if (etherf == NULL
+ && (etherf = fopen(_PATH_ETHERTYPES, "r")) == NULL) {
+ return (NULL);
+ }
+
+again:
+ if ((e = fgets(line, BUFSIZ, etherf)) == NULL) {
+ return (NULL);
+ }
+ if (*e == '#')
+ goto again;
+ cp = strpbrk(e, "#\n");
+ if (cp == NULL)
+ goto again;
+ *cp = '\0';
+ et_ent.e_name = e;
+ cp = strpbrk(e, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ e = strpbrk(cp, " \t");
+ if (e != NULL)
+ *e++ = '\0';
+// Check point
+ et_ent.e_ethertype = strtol(cp, &endptr, 16);
+ if (*endptr != '\0'
+ || (et_ent.e_ethertype < ETH_ZLEN
+ || et_ent.e_ethertype > 0xFFFF))
+ goto again; // Skip invalid etherproto type entry
+ q = et_ent.e_aliases = ethertype_aliases;
+ if (e != NULL) {
+ cp = e;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < ðertype_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ }
+ *q = NULL;
+ return (&et_ent);
+}
+
+
+struct ethertypeent *getethertypebyname(const char *name)
+{
+ register struct ethertypeent *e;
+ register char **cp;
+
+ setethertypeent(ethertype_stayopen);
+ while ((e = getethertypeent()) != NULL) {
+ if (strcasecmp(e->e_name, name) == 0)
+ break;
+ for (cp = e->e_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!ethertype_stayopen)
+ endethertypeent();
+ return (e);
+}
+
+struct ethertypeent *getethertypebynumber(int type)
+{
+ register struct ethertypeent *e;
+
+ setethertypeent(ethertype_stayopen);
+ while ((e = getethertypeent()) != NULL)
+ if (e->e_ethertype == type)
+ break;
+ if (!ethertype_stayopen)
+ endethertypeent();
+ return (e);
+}
diff --git a/iptables/nft.c b/iptables/nft.c
index 01e0264..8c8c026 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -427,6 +427,34 @@ struct builtin_table xtables_arp[TABLES_MAX] = {
},
};
+#include <linux/netfilter_bridge.h>
+
+struct builtin_table xtables_bridge[TABLES_MAX] = {
+ [FILTER] = {
+ .name = "filter",
+ .chains = {
+ {
+ .name = "INPUT",
+ .type = "filter",
+ .prio = NF_BR_PRI_FILTER_BRIDGED,
+ .hook = NF_BR_LOCAL_IN,
+ },
+ {
+ .name = "FORWARD",
+ .type = "filter",
+ .prio = NF_BR_PRI_FILTER_BRIDGED,
+ .hook = NF_BR_FORWARD,
+ },
+ {
+ .name = "OUTPUT",
+ .type = "filter",
+ .prio = NF_BR_PRI_FILTER_BRIDGED,
+ .hook = NF_BR_LOCAL_OUT,
+ },
+ },
+ },
+};
+
int
nft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t,
bool dormant)
diff --git a/iptables/nft.h b/iptables/nft.h
index 26b60b9..2a8831e 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -38,6 +38,7 @@ struct nft_handle {
extern struct builtin_table xtables_ipv4[TABLES_MAX];
extern struct builtin_table xtables_arp[TABLES_MAX];
+extern struct builtin_table xtables_bridge[TABLES_MAX];
int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
int (*cb)(const struct nlmsghdr *nlh, void *data),
@@ -138,6 +139,8 @@ const char *nft_strerror(int err);
int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table);
/* For xtables-arptables.c */
int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table);
+/* For xtables-eb.c */
+int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table);
/*
* Parse config for tables and chain helper functions
@@ -170,4 +173,10 @@ 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
+ */
+
+struct ebt_entry;
+
#endif
diff --git a/iptables/xtables-eb-standalone.c b/iptables/xtables-eb-standalone.c
new file mode 100644
index 0000000..f634761
--- /dev/null
+++ b/iptables/xtables-eb-standalone.c
@@ -0,0 +1,87 @@
+/*
+ * Author: Paul.Russell@rustcorp.com.au and mneuling@radlogic.com.au
+ *
+ * Based on the ipchains code by Paul Russell and Michael Neuling
+ *
+ * (C) 2000-2002 by the netfilter coreteam <coreteam@netfilter.org>:
+ * Paul 'Rusty' Russell <rusty@rustcorp.com.au>
+ * Marc Boucher <marc+nf@mbsi.ca>
+ * James Morris <jmorris@intercode.com.au>
+ * Harald Welte <laforge@gnumonks.org>
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * arptables -- IP firewall administration for kernels with
+ * firewall table (aimed for the 2.3 kernels)
+ *
+ * See the accompanying manual page arptables(8) for information
+ * about proper usage of this program.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <xtables.h>
+#include "nft.h"
+
+#include "xtables-multi.h"
+
+extern struct xtables_globals xtables_globals;
+extern const char *program_version, *program_name;
+
+static const struct xtables_afinfo afinfo_bridge = {
+ .kmod = "eb_tables",
+ .proc_exists = "/proc/net/eb_tables_names",
+ .libprefix = "libeb_",
+ .family = NFPROTO_BRIDGE,
+ .ipproto = IPPROTO_IP,
+ .so_rev_match = -1,
+ .so_rev_target = -1,
+};
+
+int xtables_eb_main(int argc, char *argv[])
+{
+ int ret;
+ char *table = "filter";
+ struct nft_handle h = {
+ .family = NFPROTO_BRIDGE,
+ };
+
+ xtables_globals.program_name = "xtables-eb";
+ /* This code below could be replaced by xtables_init_all, which
+ * doesn't support NFPROTO_BRIDGE yet.
+ */
+ xtables_init();
+ afinfo = &afinfo_bridge;
+ ret = xtables_set_params(&xtables_globals);
+ if (ret < 0) {
+ fprintf(stderr, "%s/%s Failed to initialize xtables\n",
+ xtables_globals.program_name,
+ xtables_globals.program_version);
+ exit(1);
+ }
+
+#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
+ init_extensions();
+#endif
+
+ ret = do_commandeb(&h, argc, argv, &table);
+ if (ret)
+ ret = nft_commit(&h);
+
+ exit(!ret);
+}
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
new file mode 100644
index 0000000..90bfc65
--- /dev/null
+++ b/iptables/xtables-eb.c
@@ -0,0 +1,1122 @@
+/*
+ * ebtables.c, v2.0 July 2002
+ *
+ * Author: Bart De Schuymer
+ *
+ * This code was stongly inspired on the iptables code which is
+ * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <getopt.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <net/if.h>
+#include <xtables.h>
+
+#include "xshared.h"
+#include "nft.h"
+
+#include <linux/netfilter_bridge/ethernetdb.h>
+
+/* Checks whether a command has already been specified */
+#define OPT_COMMANDS (fw.flags & OPT_COMMAND || fw.flags & OPT_ZERO)
+
+#define OPT_COMMAND 0x01
+#define OPT_TABLE 0x02
+#define OPT_IN 0x04
+#define OPT_OUT 0x08
+#define OPT_JUMP 0x10
+#define OPT_PROTOCOL 0x20
+#define OPT_SOURCE 0x40
+#define OPT_DEST 0x80
+#define OPT_ZERO 0x100
+#define OPT_LOGICALIN 0x200
+#define OPT_LOGICALOUT 0x400
+#define OPT_KERNELDATA 0x800 /* This value is also defined in ebtablesd.c */
+#define OPT_COUNT 0x1000 /* This value is also defined in libebtc.c */
+#define OPT_CNT_INCR 0x2000 /* This value is also defined in libebtc.c */
+#define OPT_CNT_DECR 0x4000 /* This value is also defined in libebtc.c */
+
+#define EXEC_STYLE_PRG 0
+#define EXEC_STYLE_DAEMON 1
+
+/* Default command line options. Do not mess around with the already
+ * assigned numbers unless you know what you are doing */
+static struct option ebt_original_options[] =
+{
+ { "append" , required_argument, 0, 'A' },
+ { "insert" , required_argument, 0, 'I' },
+ { "delete" , required_argument, 0, 'D' },
+ { "list" , optional_argument, 0, 'L' },
+ { "Lc" , no_argument , 0, 4 },
+ { "Ln" , no_argument , 0, 5 },
+ { "Lx" , no_argument , 0, 6 },
+ { "Lmac2" , no_argument , 0, 12 },
+ { "zero" , optional_argument, 0, 'Z' },
+ { "flush" , optional_argument, 0, 'F' },
+ { "policy" , required_argument, 0, 'P' },
+ { "in-interface" , required_argument, 0, 'i' },
+ { "in-if" , required_argument, 0, 'i' },
+ { "logical-in" , required_argument, 0, 2 },
+ { "logical-out" , required_argument, 0, 3 },
+ { "out-interface" , required_argument, 0, 'o' },
+ { "out-if" , required_argument, 0, 'o' },
+ { "version" , no_argument , 0, 'V' },
+ { "help" , no_argument , 0, 'h' },
+ { "jump" , required_argument, 0, 'j' },
+ { "set-counters" , required_argument, 0, 'c' },
+ { "change-counters", required_argument, 0, 'C' },
+ { "proto" , required_argument, 0, 'p' },
+ { "protocol" , required_argument, 0, 'p' },
+ { "db" , required_argument, 0, 'b' },
+ { "source" , required_argument, 0, 's' },
+ { "src" , required_argument, 0, 's' },
+ { "destination" , required_argument, 0, 'd' },
+ { "dst" , required_argument, 0, 'd' },
+ { "table" , required_argument, 0, 't' },
+ { "modprobe" , required_argument, 0, 'M' },
+ { "new-chain" , required_argument, 0, 'N' },
+ { "rename-chain" , required_argument, 0, 'E' },
+ { "delete-chain" , optional_argument, 0, 'X' },
+ { "atomic-init" , no_argument , 0, 7 },
+ { "atomic-commit" , no_argument , 0, 8 },
+ { "atomic-file" , required_argument, 0, 9 },
+ { "atomic-save" , no_argument , 0, 10 },
+ { "init-table" , no_argument , 0, 11 },
+ { "concurrent" , no_argument , 0, 13 },
+ { 0 }
+};
+
+const char *PROGVERSION = XTABLES_VERSION;
+const char *PROGNAME = "xtables-eb";
+
+static struct option *ebt_options = ebt_original_options;
+
+extern struct xtables_globals xtables_globals;
+
+/* The four target names, from libebtc.c */
+const char* ebt_standard_targets[NUM_STANDARD_TARGETS] =
+{
+ "ACCEPT",
+ "DROP",
+ "CONTINUE",
+ "RETURN",
+};
+
+/* 0: default
+ * 1: the inverse '!' of the option has already been specified */
+int ebt_invert = 0;
+
+/* Prints all registered extensions */
+static void ebt_list_extensions(const struct xtables_target *t,
+ const struct xtables_rule_match *m)
+{
+ printf("%s v%s\n", PROGNAME, PROGVERSION);
+ printf("Loaded userspace extensions:\n");
+ /*printf("\nLoaded tables:\n");
+ while (tbl) {
+ printf("%s\n", tbl->name);
+ tbl = tbl->next;
+ }*/
+ printf("\nLoaded targets:\n");
+ for (t = xtables_targets; t; t = t->next) {
+ printf("%s\n", t->name);
+ }
+ printf("\nLoaded matches:\n");
+ for (; m != NULL; m = m->next)
+ printf("%s\n", m->match->name);
+ /*printf("\nLoaded watchers:\n");
+ while (w) {
+ printf("%s\n", w->name);
+ w = w->next;
+ }*/
+}
+
+static void print_help(const struct xtables_target *t,
+ const struct xtables_rule_match *m)
+{
+ printf("%s %s\n", PROGNAME, PROGVERSION);
+ printf(
+"Usage:\n"
+"ebtables -[ADI] chain rule-specification [options]\n"
+"ebtables -P chain target\n"
+"ebtables -[LFZ] [chain]\n"
+"ebtables -[NX] [chain]\n"
+"ebtables -E old-chain-name new-chain-name\n\n"
+"Commands:\n"
+"--append -A chain : append to chain\n"
+"--delete -D chain : delete matching rule from chain\n"
+"--delete -D chain rulenum : delete rule at position rulenum from chain\n"
+"--change-counters -C chain\n"
+" [rulenum] pcnt bcnt : change counters of existing rule\n"
+"--insert -I chain rulenum : insert rule at position rulenum in chain\n"
+"--list -L [chain] : list the rules in a chain or in all chains\n"
+"--flush -F [chain] : delete all rules in chain or in all chains\n"
+"--init-table : replace the kernel table with the initial table\n"
+"--zero -Z [chain] : put counters on zero in chain or in all chains\n"
+"--policy -P chain target : change policy on chain to target\n"
+"--new-chain -N chain : create a user defined chain\n"
+"--rename-chain -E old new : rename a chain\n"
+"--delete-chain -X [chain] : delete a user defined chain\n"
+"--atomic-commit : update the kernel w/t table contained in <FILE>\n"
+"--atomic-init : put the initial kernel table into <FILE>\n"
+"--atomic-save : put the current kernel table into <FILE>\n"
+"--atomic-file file : set <FILE> to file\n\n"
+"Options:\n"
+"--proto -p [!] proto : protocol hexadecimal, by name or LENGTH\n"
+"--src -s [!] address[/mask]: source mac address\n"
+"--dst -d [!] address[/mask]: destination mac address\n"
+"--in-if -i [!] name[+] : network input interface name\n"
+"--out-if -o [!] name[+] : network output interface name\n"
+"--logical-in [!] name[+] : logical bridge input interface name\n"
+"--logical-out [!] name[+] : logical bridge output interface name\n"
+"--set-counters -c chain\n"
+" pcnt bcnt : set the counters of the to be added rule\n"
+"--modprobe -M program : try to insert modules using this program\n"
+"--concurrent : use a file lock to support concurrent scripts\n"
+"--version -V : print package version\n\n"
+"Environment variable:\n"
+/*ATOMIC_ENV_VARIABLE " : if set <FILE> (see above) will equal its value"*/
+"\n\n");
+ for (; m != NULL; m = m->next) {
+ printf("\n");
+ m->match->help();
+ }
+ t->help();
+ printf("\n");
+ /*if (table->help)
+ table->help(ebt_hooknames);*/
+}
+
+/* Execute command L */
+static int list_rules(struct nft_handle *h, const char *chain, const char *table,
+ int rulenum, int verbose, int numeric, int expanded,
+ int linenumbers)
+{
+ unsigned int format;
+
+ format = FMT_OPTIONS;
+ if (!verbose)
+ format |= FMT_NOCOUNTS;
+ else
+ format |= FMT_VIA;
+
+ if (numeric)
+ format |= FMT_NUMERIC;
+
+ if (!expanded)
+ format |= FMT_KILOMEGAGIGA;
+
+ if (linenumbers)
+ format |= FMT_LINENUMBERS;
+
+ return nft_rule_list(h, chain, table, rulenum, format);
+}
+
+static int parse_rule_range(const char *argv, int *rule_nr, int *rule_nr_end)
+{
+ char *colon = strchr(argv, ':'), *buffer;
+
+ if (colon) {
+ *colon = '\0';
+ if (*(colon + 1) == '\0')
+ *rule_nr_end = -1; /* Until the last rule */
+ else {
+ *rule_nr_end = strtol(colon + 1, &buffer, 10);
+ if (*buffer != '\0' || *rule_nr_end == 0)
+ return -1;
+ }
+ }
+ if (colon == argv)
+ *rule_nr = 1; /* Beginning with the first rule */
+ else {
+ *rule_nr = strtol(argv, &buffer, 10);
+ if (*buffer != '\0' || *rule_nr == 0)
+ return -1;
+ }
+ if (!colon)
+ *rule_nr_end = *rule_nr;
+ return 0;
+}
+
+/* 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)
+{
+ char *buffer;
+ int ret = 0;
+
+ if (optind + 1 >= argc || (argv[optind][0] == '-' && (argv[optind][1] < '0' || argv[optind][1] > '9')) ||
+ (argv[optind + 1][0] == '-' && (argv[optind + 1][1] < '0' && argv[optind + 1][1] > '9')))
+ xtables_error(PARAMETER_PROBLEM,
+ "The command -C needs at least 2 arguments");
+ if (optind + 2 < argc && (argv[optind + 2][0] != '-' || (argv[optind + 2][1] >= '0' && argv[optind + 2][1] <= '9'))) {
+ if (optind + 3 != argc)
+ xtables_error(PARAMETER_PROBLEM,
+ "No extra options allowed with -C start_nr[:end_nr] pcnt bcnt");
+ if (parse_rule_range(argv[optind], rule_nr, rule_nr_end))
+ xtables_error(PARAMETER_PROBLEM,
+ "Something is wrong with the rule number specification '%s'", argv[optind]);
+ optind++;
+ }
+
+ if (argv[optind][0] == '+') {
+ if (exec_style == EXEC_STYLE_DAEMON)
+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);
+ } 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);
+ } else
+ fw->counters.pcnt = strtoull(argv[optind], &buffer, 10);
+
+ if (*buffer != '\0')
+ goto invalid;
+ optind++;
+ if (argv[optind][0] == '+') {
+ if (exec_style == EXEC_STYLE_DAEMON)
+ goto daemon_incr;
+ ret += 3;
+ fw->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);
+ } else
+ fw->counters.bcnt = strtoull(argv[optind], &buffer, 10);
+
+ if (*buffer != '\0')
+ goto invalid;
+ optind++;
+ return ret;
+invalid:
+ xtables_error(PARAMETER_PROBLEM,"Packet counter '%s' invalid", argv[optind]);
+}
+
+static int parse_iface(char *iface, char *option)
+{
+ char *c;
+
+ if ((c = strchr(iface, '+'))) {
+ if (*(c + 1) != '\0') {
+ xtables_error(PARAMETER_PROBLEM,
+ "Spurious characters after '+' wildcard for '%s'", option);
+ return -1;
+ } else
+ *c = IF_WILDCARD;
+ }
+ return 0;
+}
+
+/* Make sure the same option wasn't specified twice. This is used
+ * in the parse functions of the extensions and ebtables.c */
+static void check_option(unsigned int *flags, unsigned int mask)
+{
+ if (*flags & mask)
+ xtables_error(PARAMETER_PROBLEM,
+ "Multiple use of same option not allowed");
+ *flags |= mask;
+}
+
+static int check_inverse(const char option[], int argc, char **argv)
+{
+ if (!option)
+ return ebt_invert;
+ if (strcmp(option, "!") == 0) {
+ if (ebt_invert == 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "Double use of '!' not allowed");
+ if (optind >= argc)
+ optarg = NULL;
+ else
+ optarg = argv[optind];
+ optind++;
+ ebt_invert = 1;
+ return 1;
+ }
+ return ebt_invert;
+}
+
+static const char *
+parse_target(const char *targetname)
+{
+ const char *ptr;
+
+ if (strlen(targetname) < 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid target name (too short)");
+
+ if (strlen(targetname)+1 > EBT_CHAIN_MAXNAMELEN)
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid target '%s' (%d chars max)",
+ targetname, EBT_CHAIN_MAXNAMELEN);
+
+ for (ptr = targetname; *ptr; ptr++)
+ if (isspace(*ptr))
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid target name `%s'", targetname);
+ return targetname;
+}
+
+static struct xtables_target *command_jump(struct xtables_ebt_entry *fw,
+ const char *jumpto)
+{
+ struct xtables_target *target;
+ size_t size;
+
+ /* XTF_TRY_LOAD (may be chain name) */
+ target = xtables_find_target(jumpto, XTF_TRY_LOAD);
+
+ if (!target)
+ return NULL;
+
+ size = XT_ALIGN(sizeof(struct xt_entry_target))
+ + target->size;
+
+ target->t = xtables_calloc(1, size);
+ target->t->u.target_size = size;
+ strncpy(target->t->u.user.name, jumpto, sizeof(target->t->u.user.name));
+ target->t->u.user.name[sizeof(target->t->u.user.name)-1] = '\0';
+ target->t->u.user.revision = target->revision;
+
+ xs_init_target(target);
+
+ if (target->x6_options != NULL)
+ ebt_options = xtables_options_xfrm(xtables_globals.orig_opts,
+ ebt_options, target->x6_options,
+ &target->option_offset);
+ else
+ ebt_options = xtables_merge_options(xtables_globals.orig_opts,
+ ebt_options, target->extra_opts,
+ &target->option_offset);
+
+ return target;
+}
+
+static int
+append_entry(struct nft_handle *h,
+ const char *chain,
+ const char *table,
+ struct xtables_ebt_entry *fw,
+ int rulenum,
+ bool verbose, bool append)
+{
+ int ret = 1;
+
+ if (append)
+ ret = nft_rule_append(h, chain, table, fw, 0,
+ verbose);
+ else
+ ret = nft_rule_insert(h, chain, table, fw,
+ rulenum, verbose);
+
+ return ret;
+}
+
+/* We use exec_style instead of #ifdef's because ebtables.so is a shared object. */
+/*int do_commandeb(int argc, char *argv[], int exec_style,
+ struct ebt_u_replace *replace_)*/
+int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
+{
+ struct xtables_ebt_entry fw;
+ char *buffer;
+ char command = 'h';
+ const char *chain = NULL;
+ const char *newname = NULL;
+ int exec_style = EXEC_STYLE_PRG;
+ int c, i;
+ int zerochain = -1; /* Needed for the -Z option (we can have -Z <this> -L <that>) */
+ int selected_chain = -1;
+ int chcounter = 0; /* Needed for -C */
+ int policy = 0;
+ int rulenum = 0;
+ int rulenum_end = 0;
+ int ret = 0;
+ struct xtables_target *t;
+
+ memset(&fw, 0, sizeof(fw));
+
+ if (nft_init(h, xtables_bridge) < 0)
+ xtables_error(OTHER_PROBLEM,
+ "Could not initialize nftables layer.");
+
+ h->ops = nft_family_ops_lookup(h->family);
+ if (h->ops == NULL)
+ xtables_error(PARAMETER_PROBLEM, "Unknown family");
+
+ for (t = xtables_targets; t; t = t->next) {
+ t->tflags = 0;
+ t->used = 0;
+ }
+
+ /* Getopt saves the day */
+ while ((c = getopt_long(argc, argv,
+ "-A:D:C:I:N:E:X::L::Z::F::P:Vhi:o:j:c:p:s:d:t:M:", ebt_options, NULL)) != -1) {
+ switch (c) {
+
+ case 'A': /* Add a rule */
+ case 'D': /* Delete a rule */
+ case 'C': /* Change counters */
+ case 'P': /* Define policy */
+ case 'I': /* Insert a rule */
+ case 'N': /* Make a user defined chain */
+ case 'E': /* Rename chain */
+ case 'X': /* Delete chain */
+ /* We allow -N chainname -P policy */
+ if (command == 'N' && c == 'P') {
+ command = c;
+ optind--; /* No table specified */
+ goto handle_P;
+ }
+ if (OPT_COMMANDS)
+ xtables_error(PARAMETER_PROBLEM,
+ "Multiple commands are not allowed");
+
+ command = c;
+ chain = optarg;
+ fw.flags |= OPT_COMMAND;
+ /*if (!(replace->flags & OPT_KERNELDATA))
+ ebt_get_kernel_table(replace, 0);*/
+ /*if (optarg && (optarg[0] == '-' || !strcmp(optarg, "!")))
+ ebt_print_error2("No chain name specified");*/
+ if (c == 'N') {
+ ret = nft_chain_user_add(h, chain, *table);
+ break;
+ } else if (c == 'X') {
+ ret = nft_chain_user_del(h, chain, *table);
+ break;
+ }
+
+ if (c == 'E') {
+ ret = nft_chain_user_rename(h, chain, *table, newname);
+ break;
+ } else if (c == 'D' && optind < argc && (argv[optind][0] != '-' || (argv[optind][1] >= '0' && argv[optind][1] <= '9'))) {
+ if (optind != argc - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "No extra options allowed with -D start_nr[:end_nr]");
+ if (parse_rule_range(argv[optind], &rulenum, &rulenum_end))
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with the specified rule number(s) '%s'", argv[optind]);
+ optind++;
+ } else if (c == 'C') {
+ if ((chcounter = parse_change_counters_rule(argc, argv, &rulenum, &rulenum_end, exec_style, &fw)) == -1)
+ return -1;
+ } else if (c == 'I') {
+ if (optind >= argc || (argv[optind][0] == '-' && (argv[optind][1] < '0' || argv[optind][1] > '9')))
+ rulenum = 1;
+ else {
+ rulenum = strtol(argv[optind], &buffer, 10);
+ if (*buffer != '\0')
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with the specified rule number '%s'",
+ argv[optind]);
+ optind++;
+ }
+ } else if (c == 'P') {
+handle_P:
+ if (optind >= argc)
+ xtables_error(PARAMETER_PROBLEM,
+ "No policy specified");
+ for (i = 0; i < NUM_STANDARD_TARGETS; i++)
+ if (!strcmp(argv[optind], ebt_standard_targets[i])) {
+ policy = -i -1;
+ if (policy == EBT_CONTINUE)
+ xtables_error(PARAMETER_PROBLEM,
+ "Wrong policy '%s'",
+ argv[optind]);
+ break;
+ }
+ if (i == NUM_STANDARD_TARGETS)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unknown policy '%s'", argv[optind]);
+ optind++;
+ }
+ break;
+ case 'L': /* List */
+ case 'F': /* Flush */
+ case 'Z': /* Zero counters */
+ if (c == 'Z') {
+ if ((fw.flags & OPT_ZERO) || (fw.flags & OPT_COMMAND && command != 'L'))
+print_zero:
+ xtables_error(PARAMETER_PROBLEM,
+ "Command -Z only allowed together with command -L");
+ fw.flags |= OPT_ZERO;
+ } else {
+ if (fw.flags & OPT_COMMAND)
+ xtables_error(PARAMETER_PROBLEM,
+ "Multiple commands are not allowed");
+ command = c;
+ fw.flags |= OPT_COMMAND;
+ if (fw.flags & OPT_ZERO && c != 'L')
+ goto print_zero;
+ }
+
+#ifdef SILENT_DAEMON
+ if (c== 'L' && exec_style == EXEC_STYLE_DAEMON)
+ xtables_error(PARAMETER_PROBLEM,
+ "-L not supported in daemon mode");
+#endif
+
+ /*if (!(replace->flags & OPT_KERNELDATA))
+ ebt_get_kernel_table(replace, 0);
+ i = -1;
+ if (optind < argc && argv[optind][0] != '-') {
+ if ((i = ebt_get_chainnr(replace, argv[optind])) == -1)
+ ebt_print_error2("Chain '%s' doesn't exist", argv[optind]);
+ optind++;
+ }
+ if (i != -1) {
+ if (c == 'Z')
+ zerochain = i;
+ else
+ replace->selected_chain = i;
+ }*/
+ break;
+ case 'V': /* Version */
+ if (OPT_COMMANDS)
+ xtables_error(PARAMETER_PROBLEM,
+ "Multiple commands are not allowed");
+ command = 'V';
+ if (exec_style == EXEC_STYLE_DAEMON)
+ xtables_error(PARAMETER_PROBLEM,
+ "%s %s\n", PROGNAME, PROGVERSION);
+ printf("%s %s\n", PROGNAME, PROGVERSION);
+ exit(0);
+ case 'h': /* Help */
+#ifdef SILENT_DAEMON
+ if (exec_style == EXEC_STYLE_DAEMON)
+ xtables_error(PARAMETER_PROBLEM,
+ "-h not supported in daemon mode");
+#endif
+ if (OPT_COMMANDS)
+ xtables_error(PARAMETER_PROBLEM,
+ "Multiple commands are not allowed");
+ command = 'h';
+
+ /* All other arguments should be extension names */
+ while (optind < argc) {
+ /*struct ebt_u_match *m;
+ struct ebt_u_watcher *w;*/
+
+ if (!strcasecmp("list_extensions", argv[optind])) {
+ ebt_list_extensions(xtables_targets, fw.matches);
+ exit(0);
+ }
+ /*if ((m = ebt_find_match(argv[optind])))
+ ebt_add_match(new_entry, m);
+ else if ((w = ebt_find_watcher(argv[optind])))
+ ebt_add_watcher(new_entry, w);
+ else {*/
+ if (!(t = xtables_find_target(argv[optind], XTF_TRY_LOAD)))
+ xtables_error(PARAMETER_PROBLEM,"Extension '%s' not found", argv[optind]);
+ if (fw.flags & OPT_JUMP)
+ xtables_error(PARAMETER_PROBLEM,"Sorry, you can only see help for one target extension at a time");
+ fw.flags |= OPT_JUMP;
+ fw.target = t;
+ //}
+ optind++;
+ }
+ break;
+ case 't': /* Table */
+ if (OPT_COMMANDS)
+ xtables_error(PARAMETER_PROBLEM,
+ "Please put the -t option first");
+ check_option(&fw.flags, OPT_TABLE);
+ if (strlen(optarg) > EBT_TABLE_MAXNAMELEN - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "Table name length cannot exceed %d characters",
+ EBT_TABLE_MAXNAMELEN - 1);
+ *table = optarg;
+ break;
+ case 'i': /* Input interface */
+ case 2 : /* Logical input interface */
+ case 'o': /* Output interface */
+ case 3 : /* Logical output interface */
+ case 'j': /* Target */
+ case 'p': /* Net family protocol */
+ case 's': /* Source mac */
+ case 'd': /* Destination mac */
+ case 'c': /* Set counters */
+ if (!OPT_COMMANDS)
+ xtables_error(PARAMETER_PROBLEM,
+ "No command specified");
+ if (command != 'A' && command != 'D' && command != 'I' && command != 'C')
+ xtables_error(PARAMETER_PROBLEM,
+ "Command and option do not match");
+ if (c == 'i') {
+ check_option(&fw.flags, OPT_IN);
+ if (selected_chain > 2 && selected_chain < NF_BR_BROUTING)
+ xtables_error(PARAMETER_PROBLEM,
+ "Use -i only in INPUT, FORWARD, PREROUTING and BROUTING chains");
+ if (check_inverse(optarg, argc, argv))
+ fw.invflags |= EBT_IIN;
+
+ if (strlen(optarg) >= IFNAMSIZ)
+big_iface_length:
+ xtables_error(PARAMETER_PROBLEM,
+ "Interface name length cannot exceed %d characters",
+ IFNAMSIZ - 1);
+ strcpy(fw.in, optarg);
+ if (parse_iface(fw.in, "-i"))
+ return -1;
+ break;
+ } else if (c == 2) {
+ check_option(&fw.flags, OPT_LOGICALIN);
+ if (selected_chain > 2 && selected_chain < NF_BR_BROUTING)
+ xtables_error(PARAMETER_PROBLEM,
+ "Use --logical-in only in INPUT, FORWARD, PREROUTING and BROUTING chains");
+ if (check_inverse(optarg, argc, argv))
+ 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"))
+ return -1;
+ break;
+ } else if (c == 'o') {
+ check_option(&fw.flags, OPT_OUT);
+ if (selected_chain < 2 || selected_chain == NF_BR_BROUTING)
+ xtables_error(PARAMETER_PROBLEM,
+ "Use -o only in OUTPUT, FORWARD and POSTROUTING chains");
+ if (check_inverse(optarg, argc, argv))
+ fw.invflags |= EBT_IOUT;
+
+ if (strlen(optarg) >= IFNAMSIZ)
+ goto big_iface_length;
+ strcpy(fw.out, optarg);
+ if (parse_iface(fw.out, "-o"))
+ return -1;
+ break;
+ } else if (c == 3) {
+ check_option(&fw.flags, OPT_LOGICALOUT);
+ if (selected_chain < 2 || selected_chain == NF_BR_BROUTING)
+ xtables_error(PARAMETER_PROBLEM,
+ "Use --logical-out only in OUTPUT, FORWARD and POSTROUTING chains");
+ if (check_inverse(optarg, argc, argv))
+ 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"))
+ return -1;
+ break;
+ } else if (c == 'j') {
+ check_option(&fw.flags, OPT_JUMP);
+ fw.jumpto = parse_target(optarg);
+ fw.target = command_jump(&fw, fw.jumpto);
+ break;
+ } else if (c == 's') {
+ check_option(&fw.flags, OPT_SOURCE);
+ if (check_inverse(optarg, argc, argv))
+ fw.invflags |= EBT_ISOURCE;
+
+ if (ebt_get_mac_and_mask(optarg, fw.sourcemac, fw.sourcemsk))
+ xtables_error(PARAMETER_PROBLEM, "Problem with specified source mac '%s'", optarg);
+ fw.bitmask |= EBT_SOURCEMAC;
+ break;
+ } else if (c == 'd') {
+ check_option(&fw.flags, OPT_DEST);
+ if (check_inverse(optarg, argc, argv))
+ fw.invflags |= EBT_IDEST;
+
+ if (ebt_get_mac_and_mask(optarg, fw.destmac, fw.destmsk))
+ xtables_error(PARAMETER_PROBLEM, "Problem with specified destination mac '%s'", optarg);
+ fw.bitmask |= EBT_DESTMAC;
+ break;
+ } else if (c == 'c') {
+ check_option(&fw.flags, OPT_COUNT);
+ if (check_inverse(optarg, argc, argv))
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected '!' after -c");
+ if (optind >= argc || optarg[0] == '-' || argv[optind][0] == '-')
+ xtables_error(PARAMETER_PROBLEM,
+ "Option -c needs 2 arguments");
+
+ fw.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);
+ if (*buffer != '\0')
+ xtables_error(PARAMETER_PROBLEM,
+ "Packet counter '%s' invalid",
+ argv[optind]);
+ optind++;
+ break;
+ }
+ check_option(&fw.flags, OPT_PROTOCOL);
+ if (check_inverse(optarg, argc, argv))
+ fw.invflags |= EBT_IPROTO;
+
+ fw.bitmask &= ~((unsigned int)EBT_NOPROTO);
+ i = strtol(optarg, &buffer, 16);
+ if (*buffer == '\0' && (i < 0 || i > 0xFFFF))
+ xtables_error(PARAMETER_PROBLEM,
+ "Problem with the specified protocol");
+ if (*buffer != '\0') {
+ struct ethertypeent *ent;
+
+ if (!strcasecmp(optarg, "LENGTH")) {
+ 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;
+ } else
+ fw.ethproto = i;
+
+ if (fw.ethproto < 0x0600)
+ xtables_error(PARAMETER_PROBLEM,
+ "Sorry, protocols have values above or equal to 0x0600");
+ break;
+ case 4 : /* Lc */
+#ifdef SILENT_DAEMON
+ if (exec_style == EXEC_STYLE_DAEMON)
+ xtables_error(PARAMETER_PROBLEM,
+ "--Lc is not supported in daemon mode");
+#endif
+ check_option(&fw.flags, LIST_C);
+ if (command != 'L')
+ xtables_error(PARAMETER_PROBLEM,
+ "Use --Lc with -L");
+ fw.flags |= LIST_C;
+ break;
+ case 5 : /* Ln */
+#ifdef SILENT_DAEMON
+ if (exec_style == EXEC_STYLE_DAEMON)
+ xtables_error(PARAMETER_PROBLEM,
+ "--Ln is not supported in daemon mode");
+#endif
+ check_option(&fw.flags, LIST_N);
+ if (command != 'L')
+ xtables_error(PARAMETER_PROBLEM,
+ "Use --Ln with -L");
+ if (fw.flags & LIST_X)
+ xtables_error(PARAMETER_PROBLEM,
+ "--Lx is not compatible with --Ln");
+ fw.flags |= LIST_N;
+ break;
+ case 6 : /* Lx */
+#ifdef SILENT_DAEMON
+ if (exec_style == EXEC_STYLE_DAEMON)
+ xtables_error(PARAMETER_PROBLEM,
+ "--Lx is not supported in daemon mode");
+#endif
+ check_option(&fw.flags, LIST_X);
+ if (command != 'L')
+ xtables_error(PARAMETER_PROBLEM,
+ "Use --Lx with -L");
+ if (fw.flags & LIST_N)
+ xtables_error(PARAMETER_PROBLEM,
+ "--Lx is not compatible with --Ln");
+ fw.flags |= LIST_X;
+ break;
+ case 12 : /* Lmac2 */
+#ifdef SILENT_DAEMON
+ if (exec_style == EXEC_STYLE_DAEMON)
+ xtables_error(PARAMETER_PROBLEM,
+ "--Lmac2 is not supported in daemon mode");
+#endif
+ check_option(&fw.flags, LIST_MAC2);
+ if (command != 'L')
+ xtables_error(PARAMETER_PROBLEM,
+ "Use --Lmac2 with -L");
+ fw.flags |= LIST_MAC2;
+ break;
+ case 8 : /* atomic-commit */
+/* if (exec_style == EXEC_STYLE_DAEMON)
+ ebt_print_error2("--atomic-commit is not supported in daemon mode");
+ replace->command = c;
+ if (OPT_COMMANDS)
+ ebt_print_error2("Multiple commands are not allowed");
+ replace->flags |= OPT_COMMAND;
+ if (!replace->filename)
+ ebt_print_error2("No atomic file specified");*/
+ /* Get the information from the file */
+ /*ebt_get_table(replace, 0);*/
+ /* We don't want the kernel giving us its counters,
+ * they would overwrite the counters extracted from
+ * the file */
+ /*replace->num_counters = 0;*/
+ /* Make sure the table will be written to the kernel */
+ /*free(replace->filename);
+ replace->filename = NULL;
+ break;*/
+ /*case 7 :*/ /* atomic-init */
+ /*case 10:*/ /* atomic-save */
+ /*case 11:*/ /* init-table */
+ /* if (exec_style == EXEC_STYLE_DAEMON) {
+ if (c == 7) {
+ ebt_print_error2("--atomic-init is not supported in daemon mode");
+ } else if (c == 10)
+ ebt_print_error2("--atomic-save is not supported in daemon mode");
+ ebt_print_error2("--init-table is not supported in daemon mode");
+ }
+ replace->command = c;
+ if (OPT_COMMANDS)
+ ebt_print_error2("Multiple commands are not allowed");
+ if (c != 11 && !replace->filename)
+ ebt_print_error2("No atomic file specified");
+ replace->flags |= OPT_COMMAND;
+ {
+ char *tmp = replace->filename;*/
+
+ /* Get the kernel table */
+ /*replace->filename = NULL;
+ ebt_get_kernel_table(replace, c == 10 ? 0 : 1);
+ replace->filename = tmp;
+ }
+ break;
+ case 9 :*/ /* atomic */
+ /*if (exec_style == EXEC_STYLE_DAEMON)
+ ebt_print_error2("--atomic is not supported in daemon mode");
+ if (OPT_COMMANDS)
+ ebt_print_error2("--atomic has to come before the command");*/
+ /* A possible memory leak here, but this is not
+ * executed in daemon mode */
+ /*replace->filename = (char *)malloc(strlen(optarg) + 1);
+ strcpy(replace->filename, optarg);
+ break;
+ case 13 : *//* concurrent */
+ /*signal(SIGINT, sighandler);
+ signal(SIGTERM, sighandler);
+ use_lockfd = 1;
+ break;*/
+ case 1 :
+ if (!strcmp(optarg, "!"))
+ check_inverse(optarg, argc, argv);
+ else
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad argument : '%s'", optarg);
+ /* ebt_check_inverse() did optind++ */
+ optind--;
+ continue;
+ default:
+ /* Is it a target option? */
+ /*t = (struct ebt_u_target *)new_entry->t;
+ if ((t->parse(c - t->option_offset, argv, argc, new_entry, &t->flags, &t->t))) {
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ goto check_extension;
+ }*/
+
+ /* Is it a match_option? */
+ /*for (m = ebt_matches; m; m = m->next)
+ if (m->parse(c - m->option_offset, argv, argc, new_entry, &m->flags, &m->m))
+ break;
+
+ if (m != NULL) {
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ if (m->used == 0) {
+ ebt_add_match(new_entry, m);
+ m->used = 1;
+ }
+ goto check_extension;
+ }*/
+
+ /* Is it a watcher option? */
+ /*for (w = ebt_watchers; w; w = w->next)
+ if (w->parse(c - w->option_offset, argv, argc, new_entry, &w->flags, &w->w))
+ break;
+
+ if (w == NULL && c == '?')
+ ebt_print_error2("Unknown argument: '%s'", argv[optind - 1], (char)optopt, (char)c);
+ else if (w == NULL) {
+ if (!strcmp(t->name, "standard"))
+ ebt_print_error2("Unknown argument: don't forget the -t option");
+ else
+ ebt_print_error2("Target-specific option does not correspond with specified target");
+ }
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ if (w->used == 0) {
+ ebt_add_watcher(new_entry, w);
+ w->used = 1;
+ }*/
+check_extension:
+ if (command != 'A' && command != 'I' &&
+ command != 'D' && command != 'C')
+ xtables_error(PARAMETER_PROBLEM,
+ "Extensions only for -A, -I, -D and -C");
+ }
+ ebt_invert = 0;
+ }
+
+ /* Just in case we didn't catch an error */
+ /*if (ebt_errormsg[0] != '\0')
+ return -1;
+
+ if (!(table = ebt_find_table(replace->name)))
+ ebt_print_error2("Bad table name");*/
+
+ if (command == 'h' && !(fw.flags & OPT_ZERO)) {
+ print_help(fw.target, fw.matches);
+ if (exec_style == EXEC_STYLE_PRG)
+ exit(0);
+ }
+
+ /* Do the final checks */
+ /*if (replace->command == 'A' || replace->command == 'I' ||
+ replace->command == 'D' || replace->command == 'C') {*/
+ /* This will put the hook_mask right for the chains */
+ /*ebt_check_for_loops(replace);
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ entries = ebt_to_chain(replace);
+ m_l = new_entry->m_list;
+ w_l = new_entry->w_list;
+ t = (struct ebt_u_target *)new_entry->t;
+ while (m_l) {
+ m = (struct ebt_u_match *)(m_l->m);
+ m->final_check(new_entry, m->m, replace->name,
+ entries->hook_mask, 0);
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ m_l = m_l->next;
+ }
+ while (w_l) {
+ w = (struct ebt_u_watcher *)(w_l->w);
+ w->final_check(new_entry, w->w, replace->name,
+ entries->hook_mask, 0);
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ w_l = w_l->next;
+ }
+ t->final_check(new_entry, t->t, replace->name,
+ entries->hook_mask, 0);
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ }*/
+ /* So, the extensions can work with the host endian.
+ * The kernel does not have to do this of course */
+ /*new_entry->ethproto = htons(new_entry->ethproto);
+
+ if (replace->command == 'P') {
+ if (replace->selected_chain < NF_BR_NUMHOOKS && policy == EBT_RETURN)
+ ebt_print_error2("Policy RETURN only allowed for user defined chains");
+ ebt_change_policy(replace, policy);
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ } else*/ if (command == 'L') {
+ ret = list_rules(h, chain, *table, rulenum,
+ fw.flags&OPT_VERBOSE,
+ fw.flags&OPT_NUMERIC,
+ /*fw.flags&OPT_EXPANDED*/0,
+ fw.flags&OPT_LINENUMBERS);
+ if (!(fw.flags & OPT_ZERO) && exec_style == EXEC_STYLE_PRG)
+ exit(0);
+ }
+ if (fw.flags & OPT_ZERO) {
+ selected_chain = zerochain;
+ ret = nft_chain_zero_counters(h, chain, *table);
+ } else if (command == 'F') {
+ ret = nft_rule_flush(h, chain, *table);
+ } else if (command == 'A') {
+ ret = append_entry(h, chain, *table, &fw, 0,
+ fw.flags&OPT_VERBOSE, true);
+ } else if (command == 'I') {
+ ret = append_entry(h, chain, *table, &fw, rulenum,
+ fw.flags&OPT_VERBOSE, false);
+ }
+ /*|| replace->command == 'I') {
+ ebt_add_rule(replace, new_entry, rule_nr);
+ if (ebt_errormsg[0] != '\0')
+ return -1;*/
+ /* Makes undoing the add easier (jumps to delete_the_rule) */
+ /*if (rule_nr <= 0)
+ rule_nr--;
+ rule_nr_end = rule_nr;*/
+
+ /* a jump to a udc requires checking for loops */
+ /*if (!strcmp(new_entry->t->u.name, EBT_STANDARD_TARGET) &&
+ ((struct ebt_standard_target *)(new_entry->t))->verdict >= 0) {*/
+ /* FIXME: this can be done faster */
+ /*ebt_check_for_loops(replace);
+ if (ebt_errormsg[0] != '\0')
+ goto delete_the_rule;
+ }*/
+
+ /* Do the final_check(), for all entries.
+ * This is needed when adding a rule that has a chain target */
+ /*i = -1;
+ while (++i != replace->num_chains) {
+ struct ebt_u_entry *e;
+
+ entries = replace->chains[i];
+ if (!entries) {
+ if (i < NF_BR_NUMHOOKS)
+ continue;
+ else
+ ebt_print_bug("whoops\n");
+ }
+ e = entries->entries->next;
+ while (e != entries->entries) {
+ *//* Userspace extensions use host endian */
+ /*e->ethproto = ntohs(e->ethproto);
+ ebt_do_final_checks(replace, e, entries);
+ if (ebt_errormsg[0] != '\0')
+ goto delete_the_rule;
+ e->ethproto = htons(e->ethproto);
+ e = e->next;
+ }
+ }*/
+ /* Don't reuse the added rule */
+ /*new_entry = NULL;
+ } else if (replace->command == 'D') {
+delete_the_rule:
+ ebt_delete_rule(replace, new_entry, rule_nr, rule_nr_end);
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ } else if (replace->command == 'C') {
+ ebt_change_counters(replace, new_entry, rule_nr, rule_nr_end, &(new_entry->cnt_surplus), chcounter);
+ if (ebt_errormsg[0] != '\0')
+ return -1;
+ }*/
+ /* Commands -N, -E, -X, --atomic-commit, --atomic-commit, --atomic-save,
+ * --init-table fall through */
+
+ /*if (ebt_errormsg[0] != '\0')
+ return -1;
+ if (table->check)
+ table->check(replace);
+
+ if (exec_style == EXEC_STYLE_PRG) {*//* Implies ebt_errormsg[0] == '\0' */
+ /*ebt_deliver_table(replace);
+
+ if (replace->nentries)
+ ebt_deliver_counters(replace);*/
+ return ret;
+}
diff --git a/iptables/xtables-ebtables.h b/iptables/xtables-ebtables.h
new file mode 100644
index 0000000..a734574
--- /dev/null
+++ b/iptables/xtables-ebtables.h
@@ -0,0 +1,39 @@
+#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
+
+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];
+ char out[IFNAMSIZ];
+ char logical_out[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
diff --git a/iptables/xtables-multi.c b/iptables/xtables-multi.c
index 5f48735..47e16f2 100644
--- a/iptables/xtables-multi.c
+++ b/iptables/xtables-multi.c
@@ -43,6 +43,7 @@ static const struct subcommand multi_subcommands[] = {
{"xtables-config", xtables_config_main},
{"xtables-events", xtables_events_main},
{"xtables-arp", xtables_arp_main},
+ {"xtables-eb", xtables_eb_main},
#endif
{NULL},
};
diff --git a/iptables/xtables-multi.h b/iptables/xtables-multi.h
index 759e24f..66ccbba 100644
--- a/iptables/xtables-multi.h
+++ b/iptables/xtables-multi.h
@@ -8,5 +8,6 @@ extern int xtables_restore_main(int, char **);
extern int xtables_config_main(int, char **);
extern int xtables_events_main(int, char **);
extern int xtables_arp_main(int, char **);
+extern int xtables_eb_main(int, char **);
#endif /* _XTABLES_MULTI_H */
--
1.8.1.5
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] Operations for bridge family
2014-02-05 18:17 [PATCH 0/2] xtables-eb for the compatibility layer Giuseppe Longo
2014-02-05 18:17 ` [PATCH 1/2] xtables: bootstrap xtables-eb for nftables Giuseppe Longo
@ 2014-02-05 18:17 ` Giuseppe Longo
2014-02-05 20:43 ` [PATCH 0/2] xtables-eb for the compatibility layer Bart De Schuymer
2 siblings, 0 replies; 6+ messages in thread
From: Giuseppe Longo @ 2014-02-05 18:17 UTC (permalink / raw)
To: netfilter-devel; +Cc: Giuseppe Longo
The following patch implements the operations for bridge family.
Signed-off-by: Giuseppe Longo <giuseppelng@gmail.com>
---
iptables/Makefile.am | 2 +-
iptables/nft-bridge.c | 384 ++++++++++++++++++++++++++++++++++++++++++++++++++
iptables/nft-shared.c | 3 +
iptables/nft.h | 5 +-
4 files changed, 392 insertions(+), 2 deletions(-)
create mode 100644 iptables/nft-bridge.c
diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index be31d0e..e322afb 100644
--- a/iptables/Makefile.am
+++ b/iptables/Makefile.am
@@ -31,7 +31,7 @@ xtables_multi_SOURCES += xtables-config-parser.y xtables-config-syntax.l
xtables_multi_SOURCES += xtables-save.c xtables-restore.c \
xtables-standalone.c xtables.c nft.c \
nft-shared.c nft-ipv4.c nft-ipv6.c nft-arp.c \
- xtables-config.c xtables-events.c \
+ nft-bridge.c xtables-config.c xtables-events.c \
xtables-arp-standalone.c xtables-arp.c \
getethertype.c nft-bridge.c \
xtables-eb-standalone.c xtables-eb.c
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
new file mode 100644
index 0000000..0239ef9
--- /dev/null
+++ b/iptables/nft-bridge.c
@@ -0,0 +1,384 @@
+/*
+ * (C) 2013 by Giuseppe Longo <giuseppelng@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/ether.h>
+
+#include <xtables.h>
+#include <libiptc/libxtc.h>
+#include <linux/netfilter/nf_tables.h>
+#include <linux/netfilter_bridge/ethernetdb.h>
+
+#include "xtables-ebtables.h"
+#include "nft-shared.h"
+#include "nft.h"
+
+static unsigned char mac_type_unicast[ETH_ALEN] = {0,0,0,0,0,0};
+static unsigned char msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0};
+static unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
+static unsigned char msk_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
+static unsigned char mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
+static unsigned char msk_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
+static unsigned char mac_type_bridge_group[ETH_ALEN] = {0x01,0x80,0xc2,0,0,0};
+static unsigned char msk_type_bridge_group[ETH_ALEN] = {255,255,255,255,255,255};
+
+/* 0: default, print only 2 digits if necessary
+ * 2: always print 2 digits, a printed mac address
+ * then always has the same length */
+int ebt_printstyle_mac;
+
+static void ebt_print_mac(const unsigned char *mac)
+{
+ if (ebt_printstyle_mac == 2) {
+ int j;
+ for (j = 0; j < ETH_ALEN; j++)
+ printf("%02x%s", mac[j],
+ (j==ETH_ALEN-1) ? "" : ":");
+ } else
+ printf("%s", ether_ntoa((struct ether_addr *) mac));
+}
+
+/* Put the mac address into 6 (ETH_ALEN) bytes returns 0 on success. */
+int ebt_get_mac_and_mask(const char *from, unsigned char *to,
+ unsigned char *mask)
+{
+ char *p;
+ int i;
+ struct ether_addr *addr = NULL;
+
+ if (strcasecmp(from, "Unicast") == 0) {
+ memcpy(to, mac_type_unicast, ETH_ALEN);
+ memcpy(mask, msk_type_unicast, ETH_ALEN);
+ return 0;
+ }
+ if (strcasecmp(from, "Multicast") == 0) {
+ memcpy(to, mac_type_multicast, ETH_ALEN);
+ memcpy(mask, msk_type_multicast, ETH_ALEN);
+ return 0;
+ }
+ if (strcasecmp(from, "Broadcast") == 0) {
+ memcpy(to, mac_type_broadcast, ETH_ALEN);
+ memcpy(mask, msk_type_broadcast, ETH_ALEN);
+ return 0;
+ }
+ if (strcasecmp(from, "BGA") == 0) {
+ memcpy(to, mac_type_bridge_group, ETH_ALEN);
+ memcpy(mask, msk_type_bridge_group, ETH_ALEN);
+ return 0;
+ }
+ if ( (p = strrchr(from, '/')) != NULL) {
+ *p = '\0';
+ if (!(addr = ether_aton(p + 1)))
+ return -1;
+ memcpy(mask, addr, ETH_ALEN);
+ } else
+ memset(mask, 0xff, ETH_ALEN);
+ if (!(addr = ether_aton(from)))
+ return -1;
+ /*memcpy(to, addr, ETH_ALEN);*/
+ for (i = 0; i < ETH_ALEN; i++)
+ to[i] &= mask[i];
+ return 0;
+}
+
+static void ebt_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
+{
+ char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ if (!memcmp(mac, mac_type_unicast, 6) &&
+ !memcmp(mask, msk_type_unicast, 6))
+ printf("Unicast");
+ else if (!memcmp(mac, mac_type_multicast, 6) &&
+ !memcmp(mask, msk_type_multicast, 6))
+ printf("Multicast");
+ else if (!memcmp(mac, mac_type_broadcast, 6) &&
+ !memcmp(mask, msk_type_broadcast, 6))
+ printf("Broadcast");
+ else if (!memcmp(mac, mac_type_bridge_group, 6) &&
+ !memcmp(mask, msk_type_bridge_group, 6))
+ printf("BGA");
+ else {
+ ebt_print_mac(mac);
+ if (memcmp(mask, hlpmsk, 6)) {
+ printf("/");
+ ebt_print_mac(mask);
+ }
+ }
+}
+
+static uint8_t ebt_to_ipt_flags(uint16_t invflags)
+{
+ uint8_t result = 0;
+
+ if (invflags & EBT_IIN)
+ result |= IPT_INV_VIA_IN;
+
+ if (invflags & EBT_IOUT)
+ result |= IPT_INV_VIA_OUT;
+
+ if (invflags & EBT_IPROTO)
+ result |= IPT_INV_PROTO;
+
+ if (invflags & EBT_INV_MASK)
+ result |= IPT_INV_MASK;
+
+ return result;
+}
+
+static uint16_t ipt_to_ebt_flags(uint8_t invflags)
+{
+ uint16_t result = 0;
+
+ if (invflags & IPT_INV_VIA_IN)
+ result |= EBT_IIN;
+
+ if (invflags & IPT_INV_VIA_OUT)
+ result |= EBT_IOUT;
+
+ if (invflags & IPT_INV_PROTO)
+ result |= EBT_IPROTO;
+
+ if (invflags & IPT_INV_MASK)
+ result |= EBT_INV_MASK;
+
+ return result;
+}
+
+static int _add_action(struct nft_rule *r, struct xtables_ebt_entry *fw)
+{
+ 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)
+ /* Not standard, then it's a jump to chain */
+ ret = add_jumpto(r, fw->jumpto, NFT_JUMP);
+
+ return ret;
+}
+
+static int nft_bridge_add(struct nft_rule *r, void *data)
+{
+ struct xtables_ebt_entry *fw = data;
+ uint8_t flags = ebt_to_ipt_flags(fw->invflags);
+
+ if (fw->in[0] != '\0')
+ add_iniface(r, fw->in, flags);
+
+ if (fw->out[0] != '\0')
+ add_outiface(r, fw->out, flags);
+
+ if (fw->ethproto != 0) {
+ add_payload(r, offsetof(struct ethhdr, h_proto), 2);
+ add_cmp_u16(r, fw->ethproto, NFT_CMP_EQ);
+ }
+
+ return _add_action(r,fw);
+}
+
+static void nft_bridge_parse_meta(struct nft_rule_expr *e, uint8_t key,
+ void *data)
+{
+ struct xtables_ebt_entry *fw = data;
+ uint8_t flags = 0;
+
+ parse_meta(e, key, fw->in, fw->sourcemsk,
+ fw->out, fw->destmsk,
+ &flags);
+
+ fw->invflags |= ipt_to_ebt_flags(flags);
+}
+
+static void nft_bridge_parse_immediate(const char *jumpto, bool nft_goto,
+ void *data)
+{
+ struct xtables_ebt_entry *fw = data;
+
+ fw->jumpto = jumpto;
+}
+
+static void nft_bridge_parse_target(struct xtables_target *t, void *data)
+{
+ struct xtables_ebt_entry *fw = data;
+
+ fw->target = t;
+}
+
+void nft_rule_to_xtables_ebt_entry(struct nft_rule *r, struct xtables_ebt_entry *fw)
+{
+ struct nft_rule_expr_iter *iter;
+ struct nft_rule_expr *expr;
+ int family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
+
+ iter = nft_rule_expr_iter_create(r);
+ if (iter == NULL)
+ return;
+
+ expr = nft_rule_expr_iter_next(iter);
+ while (expr != NULL) {
+ const char *name =
+ nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
+
+ if (strcmp(name, "counter") == 0)
+ nft_parse_counter(expr, iter, &fw->counters);
+ else if (strcmp(name, "payload") == 0)
+ nft_parse_payload(expr, iter, family, fw);
+ else if (strcmp(name, "meta") == 0)
+ nft_parse_meta(expr, iter, family, fw);
+ else if (strcmp(name, "immediate") == 0)
+ nft_parse_immediate(expr, iter, family, fw);
+ else if (strcmp(name, "target") == 0)
+ nft_parse_target(expr, iter, family, fw);
+
+ expr = nft_rule_expr_iter_next(iter);
+ }
+
+ 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);
+ else
+ fw->jumpto = "";
+}
+
+static void print_iface(const char *iface)
+{
+ char *c;
+
+ if ((c = strchr(iface, IF_WILDCARD)))
+ *c = '+';
+ printf("%s ", iface);
+ if (c)
+ *c = IF_WILDCARD;
+}
+
+static void
+nft_bridge_print_firewall(struct nft_rule *r, unsigned int num,
+ unsigned int format)
+{
+ struct xtables_ebt_entry fw = {};
+
+
+ nft_rule_to_xtables_ebt_entry(r, &fw);
+
+ /* Dont print anything about the protocol if no protocol was
+ * specified, obviously this means any protocol will do. */
+ if (!(fw.bitmask & EBT_NOPROTO)) {
+ printf("-p ");
+ if (fw.invflags & EBT_IPROTO)
+ printf("! ");
+ if (fw.bitmask & EBT_802_3)
+ printf("Length ");
+ else {
+ struct ethertypeent *ent;
+
+ ent = getethertypebynumber(ntohs(fw.ethproto));
+ if (!ent)
+ printf("0x%x ", ntohs(fw.ethproto));
+ else
+ printf("%s ", ent->e_name);
+ }
+ }
+
+ if (fw.bitmask & EBT_SOURCEMAC) {
+ printf("-s ");
+ if (fw.invflags & EBT_ISOURCE)
+ printf("! ");
+ ebt_print_mac_and_mask(fw.sourcemac, fw.sourcemsk);
+ printf(" ");
+ }
+
+ if (fw.bitmask & EBT_DESTMAC) {
+ printf("-d ");
+ if (fw.invflags & EBT_IDEST)
+ printf("! ");
+ ebt_print_mac_and_mask(fw.destmac, fw.destmsk);
+ printf(" ");
+ }
+
+ if (fw.in[0] != '\0') {
+ printf("-i ");
+ if (fw.invflags & EBT_IIN)
+ printf("! ");
+ print_iface(fw.in);
+ }
+
+ if (fw.logical_in[0] != '\0') {
+ printf("--logical-in ");
+ if (fw.invflags & EBT_ILOGICALIN)
+ printf("! ");
+ print_iface(fw.logical_in);
+ }
+
+ if (fw.logical_out[0] != '\0') {
+ printf("--logical-out ");
+ if (fw.invflags & EBT_ILOGICALOUT)
+ printf("! ");
+ print_iface(fw.logical_out);
+ }
+
+ if (fw.out[0] != '\0') {
+ printf("-o ");
+ if (fw.invflags & EBT_IOUT)
+ printf("! ");
+ print_iface(fw.out);
+ }
+
+ /* old code to adapt
+ m_l = hlp->m_list;
+ while (m_l) {
+ m = ebt_find_match(m_l->m->u.name);
+ if (!m)
+ ebt_print_bug("Match not found");
+ m->print(hlp, m_l->m);
+ m_l = m_l->next;
+ }
+ w_l = hlp->w_list;
+ while (w_l) {
+ w = ebt_find_watcher(w_l->w->u.name);
+ if (!w)
+ ebt_print_bug("Watcher not found");
+ w->print(hlp, w_l->w);
+ w_l = w_l->next;
+ }*/
+ printf("-j ");
+ if (fw.target != NULL) {
+ if (fw.target->print != NULL) {
+ fw.target->print(&fw, fw.target->t,
+ format & FMT_NUMERIC);
+ }
+ }
+}
+
+struct nft_family_ops nft_family_ops_bridge = {
+ .add = nft_bridge_add,
+ .is_same = NULL,
+ .print_payload = NULL,
+ .parse_meta = nft_bridge_parse_meta,
+ .parse_payload = NULL,
+ .parse_immediate = nft_bridge_parse_immediate,
+ .print_firewall = nft_bridge_print_firewall,
+ .post_parse = NULL,
+ .rule_find = NULL,
+ .parse_target = nft_bridge_parse_target,
+};
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index e0eaa17..233011c 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -32,6 +32,7 @@
extern struct nft_family_ops nft_family_ops_ipv4;
extern struct nft_family_ops nft_family_ops_ipv6;
extern struct nft_family_ops nft_family_ops_arp;
+extern struct nft_family_ops nft_family_ops_bridge;
void add_meta(struct nft_rule *r, uint32_t key)
{
@@ -649,6 +650,8 @@ struct nft_family_ops *nft_family_ops_lookup(int family)
return &nft_family_ops_ipv6;
case NFPROTO_ARP:
return &nft_family_ops_arp;
+ case NFPROTO_BRIDGE:
+ return &nft_family_ops_bridge;
default:
break;
}
diff --git a/iptables/nft.h b/iptables/nft.h
index 2a8831e..68f674e 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -177,6 +177,9 @@ void nft_rule_to_arpt_entry(struct nft_rule *r, struct arpt_entry *fw);
* BRIDGE
*/
-struct ebt_entry;
+#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
--
1.8.1.5
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] xtables-eb for the compatibility layer
2014-02-05 18:17 [PATCH 0/2] xtables-eb for the compatibility layer Giuseppe Longo
2014-02-05 18:17 ` [PATCH 1/2] xtables: bootstrap xtables-eb for nftables Giuseppe Longo
2014-02-05 18:17 ` [PATCH 2/2] Operations for bridge family Giuseppe Longo
@ 2014-02-05 20:43 ` Bart De Schuymer
2014-02-06 11:20 ` Giuseppe Longo
2 siblings, 1 reply; 6+ messages in thread
From: Bart De Schuymer @ 2014-02-05 20:43 UTC (permalink / raw)
To: Giuseppe Longo, netfilter-devel
Giuseppe Longo schreef op 5/02/2014 19:17:
> Hi,
> this patchset implements ebtables for the nftables compatibility layer.
> I would explain some points:
> - I didn't figure out how to replace some parts of codes, for istance:
> from xtables-eb.c, line 928:
> t = (struct ebt_u_target *)new_entry->t;
> if ((t->parse(c - t->option_offset, argv, argc, new_entry, &t->flags, &t->t))) {
> if (ebt_errormsg[0] != '\0')
> return -1;
> goto check_extension;
> }
>
> /* Is it a match_option? */
> for (m = ebt_matches; m; m = m->next)
> if (m->parse(c - m->option_offset, argv, argc, new_entry, &m->flags, &m->m))
> break;
>
> if (m != NULL) {
> if (ebt_errormsg[0] != '\0')
> return -1;
> if (m->used == 0) {
> ebt_add_match(new_entry, m);
> m->used = 1;
> }
> goto check_extension;
> }
>
> Looking at extensions, I noticed that any xtables_match/xtables_target have parse functions. Maybe I'm wrong.
The parse functions of the targets/matches/watchers will return 0 if the
command-line argument isn't one of their options. If the parse function
returns a non-zero value, the command line option belongs to that
target/match/watcher. So, unless you don't want support for
target/watcher/match command-line arguments, you will need that code.
> Even the code from line 992 is not very clear, about final checks. I don't know if I can remove this part of code.
The code you commented out checks for loops in the call chain and runs
the final_check functions of the target/matches/watchers. As an example,
the ebt_ip module's final_check function makes sure the Ethernet
protocol is specified to be IPv4.
I see you comment out more stuff below that. All I can tell you is that
it sure is required for correct behavior in the oldschool ebtables
program. Please take the time to figure this out (read the code
comments, step through the code with a debugger) because I doubt this
will be a smooth and stable integration process otherwise.
cheers,
Bart
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] xtables: bootstrap xtables-eb for nftables
2014-02-05 18:17 ` [PATCH 1/2] xtables: bootstrap xtables-eb for nftables Giuseppe Longo
@ 2014-02-05 23:26 ` Giuseppe Longo
0 siblings, 0 replies; 6+ messages in thread
From: Giuseppe Longo @ 2014-02-05 23:26 UTC (permalink / raw)
To: netfilter-devel
I made these changes, if I am not wrong now is possible to parse
target and match using libxtables:
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 90bfc65..c43e10c 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -459,6 +459,8 @@ int do_commandeb(struct nft_handle *h, int argc,
char *argv[], char **table)
int rulenum_end = 0;
int ret = 0;
struct xtables_target *t;
+ struct xtables_rule_match *matchp = NULL;
+ struct xtables_match *m = NULL;
memset(&fw, 0, sizeof(fw));
@@ -925,19 +927,23 @@ big_iface_length:
continue;
default:
/* Is it a target option? */
- /*t = (struct ebt_u_target *)new_entry->t;
- if ((t->parse(c - t->option_offset, argv,
argc, new_entry, &t->flags, &t->t))) {
- if (ebt_errormsg[0] != '\0')
- return -1;
+ if (fw.target) {
+ xtables_option_tpcall(c, argv,
fw.invflags, fw.target, &fw);
goto check_extension;
- }*/
+ }
/* Is it a match_option? */
- /*for (m = ebt_matches; m; m = m->next)
- if (m->parse(c - m->option_offset,
argv, argc, new_entry, &m->flags, &m->m))
- break;
+ for (matchp = fw.matches; matchp; matchp =
matchp->next) {
+ m = matchp->match;
+
+ if (matchp->completed ||
+ (m->x6_parse == NULL && m->parse == NULL))
+ continue;
+
+ xtables_option_mpcall(c, argv,
fw.invflags, m, &fw);
+ }
- if (m != NULL) {
+ /*if (m != NULL) {
if (ebt_errormsg[0] != '\0')
return -1;
if (m->used == 0) {
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] xtables-eb for the compatibility layer
2014-02-05 20:43 ` [PATCH 0/2] xtables-eb for the compatibility layer Bart De Schuymer
@ 2014-02-06 11:20 ` Giuseppe Longo
0 siblings, 0 replies; 6+ messages in thread
From: Giuseppe Longo @ 2014-02-06 11:20 UTC (permalink / raw)
To: Bart De Schuymer; +Cc: netfilter-devel
Hi Bart,
thank you for your explanation, I have to figure out how to port the
extensions to xtables.
It's more clearer now.
Cheers,
Giuseppe
2014-02-05 Bart De Schuymer <bdschuym@pandora.be>:
> Giuseppe Longo schreef op 5/02/2014 19:17:
>>
>> Hi,
>> this patchset implements ebtables for the nftables compatibility layer.
>> I would explain some points:
>> - I didn't figure out how to replace some parts of codes, for istance:
>> from xtables-eb.c, line 928:
>> t = (struct ebt_u_target *)new_entry->t;
>> if ((t->parse(c - t->option_offset, argv, argc, new_entry, &t->flags,
>> &t->t))) {
>> if (ebt_errormsg[0] != '\0')
>> return -1;
>> goto check_extension;
>> }
>>
>> /* Is it a match_option? */
>> for (m = ebt_matches; m; m = m->next)
>> if (m->parse(c - m->option_offset, argv, argc, new_entry,
>> &m->flags, &m->m))
>> break;
>>
>> if (m != NULL) {
>> if (ebt_errormsg[0] != '\0')
>> return -1;
>> if (m->used == 0) {
>> ebt_add_match(new_entry, m);
>> m->used = 1;
>> }
>> goto check_extension;
>> }
>>
>> Looking at extensions, I noticed that any xtables_match/xtables_target
>> have parse functions. Maybe I'm wrong.
>
>
> The parse functions of the targets/matches/watchers will return 0 if the
> command-line argument isn't one of their options. If the parse function
> returns a non-zero value, the command line option belongs to that
> target/match/watcher. So, unless you don't want support for
> target/watcher/match command-line arguments, you will need that code.
>
>
>> Even the code from line 992 is not very clear, about final checks. I don't
>> know if I can remove this part of code.
>
>
> The code you commented out checks for loops in the call chain and runs the
> final_check functions of the target/matches/watchers. As an example, the
> ebt_ip module's final_check function makes sure the Ethernet protocol is
> specified to be IPv4.
> I see you comment out more stuff below that. All I can tell you is that it
> sure is required for correct behavior in the oldschool ebtables program.
> Please take the time to figure this out (read the code comments, step
> through the code with a debugger) because I doubt this will be a smooth and
> stable integration process otherwise.
>
> cheers,
> Bart
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-02-06 11:20 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-05 18:17 [PATCH 0/2] xtables-eb for the compatibility layer Giuseppe Longo
2014-02-05 18:17 ` [PATCH 1/2] xtables: bootstrap xtables-eb for nftables Giuseppe Longo
2014-02-05 23:26 ` Giuseppe Longo
2014-02-05 18:17 ` [PATCH 2/2] Operations for bridge family Giuseppe Longo
2014-02-05 20:43 ` [PATCH 0/2] xtables-eb for the compatibility layer Bart De Schuymer
2014-02-06 11:20 ` Giuseppe Longo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).