mirror of
https://github.com/openharmony/third_party_iptables.git
synced 2026-07-01 05:52:22 -04:00
upgrade iptables to 1.8.11
Signed-off-by: HuangHaitao <huanghaitao16@huawei.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
Installation instructions for iptables
|
||||
======================================
|
||||
|
||||
iptables uses the well-known configure(autotools) infrastructure.
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
# make install
|
||||
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
* no kernel-source required
|
||||
|
||||
* but obviously a compiler, glibc-devel and linux-kernel-headers
|
||||
(/usr/include/linux)
|
||||
|
||||
|
||||
Configuring and compiling
|
||||
=========================
|
||||
|
||||
./configure [options]
|
||||
|
||||
--prefix=
|
||||
|
||||
The prefix to put all installed files under. It defaults to
|
||||
/usr/local, so the binaries will go into /usr/local/bin, sbin,
|
||||
manpages into /usr/local/share/man, etc.
|
||||
|
||||
--with-xtlibdir=
|
||||
|
||||
The path to where Xtables extensions should be installed to. It
|
||||
defaults to ${libdir}/xtables.
|
||||
|
||||
--enable-devel (or --disable-devel)
|
||||
|
||||
This option causes development files to be installed to
|
||||
${includedir}, which is needed for building additional packages,
|
||||
such as Xtables-addons or other 3rd-party extensions.
|
||||
|
||||
It is enabled by default.
|
||||
|
||||
--enable-static
|
||||
|
||||
Produce additional binaries, iptables-static/ip6tables-static,
|
||||
which have all shipped extensions compiled in.
|
||||
|
||||
--disable-shared
|
||||
|
||||
Produce binaries that have dynamic loading of extensions disabled.
|
||||
This implies --enable-static.
|
||||
(See some details below.)
|
||||
|
||||
--enable-libipq
|
||||
|
||||
This option causes libipq to be installed into ${libdir} and
|
||||
${includedir}.
|
||||
|
||||
--with-ksource=
|
||||
|
||||
Xtables does not depend on kernel headers anymore, but you can
|
||||
optionally specify a search path to include anyway. This is
|
||||
probably only useful for development.
|
||||
|
||||
If you want to enable debugging, use
|
||||
|
||||
./configure CFLAGS="-ggdb3 -O0"
|
||||
|
||||
(-O0 is used to turn off instruction reordering, which makes debugging
|
||||
much easier.)
|
||||
|
||||
To show debug traces you can add -DDEBUG to CFLAGS option
|
||||
|
||||
|
||||
Other notes
|
||||
===========
|
||||
|
||||
The make process will automatically build multipurpose binaries.
|
||||
These have the core (iptables), -save, -restore and -xml code
|
||||
compiled into one binary, but extensions remain as modules.
|
||||
|
||||
|
||||
Static and shared
|
||||
=================
|
||||
|
||||
Basically there are three configuration modes defined:
|
||||
|
||||
--disable-static --enable-shared (this is the default)
|
||||
|
||||
Build a binary that relies upon dynamic loading of extensions.
|
||||
|
||||
--enable-static --enable-shared
|
||||
|
||||
Build a binary that has the shipped extensions built-in, but
|
||||
is still capable of loading additional extensions.
|
||||
|
||||
--enable-static --disable-shared
|
||||
|
||||
Shipped extensions are built-in, and dynamic loading is
|
||||
deactivated.
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects dist-xz no-dist-gzip serial-tests
|
||||
|
||||
SUBDIRS = libiptc libxtables
|
||||
if ENABLE_DEVEL
|
||||
SUBDIRS += include
|
||||
endif
|
||||
if ENABLE_LIBIPQ
|
||||
SUBDIRS += libipq
|
||||
endif
|
||||
SUBDIRS += utils
|
||||
# Depends on libxtables:
|
||||
SUBDIRS += extensions
|
||||
# Depends on extensions/libext.a:
|
||||
SUBDIRS += iptables
|
||||
|
||||
EXTRA_DIST = autogen.sh iptables-test.py xlate-test.py
|
||||
|
||||
if ENABLE_NFTABLES
|
||||
confdir = $(sysconfdir)
|
||||
dist_conf_DATA = etc/ethertypes
|
||||
endif
|
||||
|
||||
.PHONY: tarball
|
||||
tarball:
|
||||
rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION};
|
||||
pushd ${top_srcdir} && git archive --prefix=${PACKAGE_TARNAME}-${PACKAGE_VERSION}/ HEAD | tar -C /tmp -x && popd;
|
||||
pushd /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION} && ./autogen.sh && popd;
|
||||
tar -C /tmp -cJf ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.xz --owner=root --group=root ${PACKAGE_TARNAME}-${PACKAGE_VERSION}/;
|
||||
rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION};
|
||||
|
||||
config.status: extensions/GNUmakefile.in \
|
||||
include/xtables-version.h.in
|
||||
|
||||
TESTS = xlate-test.py iptables-test.py iptables/tests/shell/run-tests.sh
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
[
|
||||
{
|
||||
"Name" : "openEuler:iptables",
|
||||
"Name" : "iptables",
|
||||
"License" : "GPL V2.0",
|
||||
"License File" : "COPYING",
|
||||
"Version Number" : "1.8.7-14.oe2203sp3",
|
||||
"Owner" : "lichunlin2@huawei.com",
|
||||
"Version Number" : "1.8.11",
|
||||
"Owner" : "heqianmo@huawei.com",
|
||||
"Upstream URL" : "https://netfilter.org/",
|
||||
"Description" : "iptables is the userspace command line program used to configure the Linux 2.4.x and later packet filtering ruleset. It is targeted towards system administrators."
|
||||
}
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
autoreconf -fi;
|
||||
rm -Rf autom4te*.cache;
|
||||
@@ -1,90 +0,0 @@
|
||||
From 17534cb18ed0a5052dc45c117401251359dba6aa Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 11 Feb 2022 17:47:22 +0100
|
||||
Subject: Improve error messages for unsupported extensions
|
||||
|
||||
If a given extension was not supported by the kernel, iptables would
|
||||
print a rather confusing error message if extension parameters were
|
||||
given:
|
||||
|
||||
| # rm /lib/modules/$(uname -r)/kernel/net/netfilter/xt_LOG.ko
|
||||
| # iptables -A FORWARD -j LOG --log-prefix foo
|
||||
| iptables v1.8.7 (legacy): unknown option "--log-prefix"
|
||||
|
||||
Avoid this by pretending extension revision 0 is always supported. It is
|
||||
the same hack as used to successfully print extension help texts as
|
||||
unprivileged user, extended to all error codes to serve privileged ones
|
||||
as well.
|
||||
|
||||
In addition, print a warning if kernel rejected revision 0 and it's not
|
||||
a permissions problem. This helps users find out which extension in a
|
||||
rule the kernel didn't like.
|
||||
|
||||
Finally, the above commands result in these messages:
|
||||
|
||||
| Warning: Extension LOG revision 0 not supported, missing kernel
|
||||
module?
|
||||
| iptables: No chain/target/match by that name.
|
||||
|
||||
Or, for iptables-nft:
|
||||
|
||||
| Warning: Extension LOG revision 0 not supported, missing kernel
|
||||
module?
|
||||
| iptables v1.8.7 (nf_tables): RULE_APPEND failed (No such file or
|
||||
directory): rule in chain FORWARD
|
||||
|
||||
Conflict: NA
|
||||
Reference:
|
||||
https://git.netfilter.org/iptables/commit/?id=17534cb18ed0a5052dc45c117401251359dba6aa
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
iptables/nft.c | 13 +++++++++----
|
||||
libxtables/xtables.c | 7 ++++++-
|
||||
2 files changed, 15 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/iptables/nft.c b/iptables/nft.c
|
||||
index c9a4940..18bf21c 100644
|
||||
--- a/iptables/nft.c
|
||||
+++ b/iptables/nft.c
|
||||
@@ -3245,11 +3245,16 @@ int nft_compatible_revision(const char *name, uint8_t rev, int opt)
|
||||
err:
|
||||
mnl_socket_close(nl);
|
||||
|
||||
- /* pretend revision 0 is valid if not permitted to check -
|
||||
- * this is required for printing extension help texts as user */
|
||||
- if (ret < 0 && errno == EPERM && rev == 0)
|
||||
+ /* pretend revision 0 is valid -
|
||||
+ * this is required for printing extension help texts as user, also
|
||||
+ * helps error messaging on unavailable kernel extension */
|
||||
+ if (ret < 0 && rev == 0) {
|
||||
+ if (errno != EPERM)
|
||||
+ fprintf(stderr,
|
||||
+ "Warning: Extension %s revision 0 not supported, missing kernel module?\n",
|
||||
+ name);
|
||||
return 1;
|
||||
-
|
||||
+ }
|
||||
return ret < 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
|
||||
index bc42ba8..1f585e5 100644
|
||||
--- a/libxtables/xtables.c
|
||||
+++ b/libxtables/xtables.c
|
||||
@@ -923,7 +923,12 @@ int xtables_compatible_revision(const char *name, uint8_t revision, int opt)
|
||||
/* Definitely don't support this? */
|
||||
if (errno == ENOENT || errno == EPROTONOSUPPORT) {
|
||||
close(sockfd);
|
||||
- return 0;
|
||||
+ /* Pretend revision 0 support for better error messaging */
|
||||
+ if (revision == 0)
|
||||
+ fprintf(stderr,
|
||||
+ "Warning: Extension %s revision 0 not supported, missing kernel module?\n",
|
||||
+ name);
|
||||
+ return (revision == 0);
|
||||
} else if (errno == ENOPROTOOPT) {
|
||||
close(sockfd);
|
||||
/* Assume only revision 0 support (old kernel) */
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
From b51aef061378b34fa9544b1af34021d89a76547a Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Thu, 26 Jan 2023 03:27:16 +0100
|
||||
Subject: [PATCH] ebtables-translate: Print flush command after parsing is
|
||||
finished
|
||||
|
||||
Otherwise, bad calls like 'ebtables-translate -F -F' produce wrong
|
||||
output instead of an error message.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=b51aef061378b34fa9544b1af34021d89a76547a
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
iptables/xtables-eb-translate.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/iptables/xtables-eb-translate.c b/iptables/xtables-eb-translate.c
|
||||
index 99347c0c..da7e5e3d 100644
|
||||
--- a/iptables/xtables-eb-translate.c
|
||||
+++ b/iptables/xtables-eb-translate.c
|
||||
@@ -247,13 +247,6 @@ static int do_commandeb_xlate(struct nft_handle *h, int argc, char *argv[], char
|
||||
ret = 1;
|
||||
break;
|
||||
case 'F': /* Flush */
|
||||
- if (p.chain) {
|
||||
- printf("flush chain bridge %s %s\n", p.table, p.chain);
|
||||
- } else {
|
||||
- printf("flush table bridge %s\n", p.table);
|
||||
- }
|
||||
- ret = 1;
|
||||
- break;
|
||||
case 'Z': /* Zero counters */
|
||||
if (c == 'Z') {
|
||||
if ((flags & OPT_ZERO) || (flags & OPT_COMMAND && command != 'L'))
|
||||
@@ -506,6 +499,13 @@ print_zero:
|
||||
|
||||
if (command == 'P') {
|
||||
return 0;
|
||||
+ } else if (command == 'F') {
|
||||
+ if (p.chain) {
|
||||
+ printf("flush chain bridge %s %s\n", p.table, p.chain);
|
||||
+ } else {
|
||||
+ printf("flush table bridge %s\n", p.table);
|
||||
+ }
|
||||
+ ret = 1;
|
||||
} else if (command == 'A') {
|
||||
ret = nft_rule_eb_xlate_add(h, &p, &cs, true);
|
||||
if (!ret)
|
||||
--
|
||||
2.23.0
|
||||
@@ -1,58 +0,0 @@
|
||||
From fca04aa7a53252464c289997e71de10189971da6 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 30 Sep 2022 17:51:55 +0200
|
||||
Subject: [PATCH] extensions: among: Fix for use with ebtables-restore
|
||||
|
||||
When restoring multiple rules which use among match, new size may be
|
||||
smaller than the old one which caused invalid writes by the memcpy()
|
||||
call. Expect this and realloc the match only if it needs to grow. Also
|
||||
use realloc instead of freeing and allocating from scratch.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=fca04aa7a53252464c289997e71de10189971da6
|
||||
|
||||
Fixes: 26753888720d8 ("nft: bridge: Rudimental among extension support")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
extensions/libebt_among.c | 14 ++++++--------
|
||||
1 file changed, 6 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c
|
||||
index c607a775..1eab2019 100644
|
||||
--- a/extensions/libebt_among.c
|
||||
+++ b/extensions/libebt_among.c
|
||||
@@ -119,7 +119,6 @@ static int bramong_parse(int c, char **argv, int invert,
|
||||
struct xt_entry_match **match)
|
||||
{
|
||||
struct nft_among_data *data = (struct nft_among_data *)(*match)->data;
|
||||
- struct xt_entry_match *new_match;
|
||||
bool have_ip, dst = false;
|
||||
size_t new_size, cnt;
|
||||
struct stat stats;
|
||||
@@ -170,18 +169,17 @@ static int bramong_parse(int c, char **argv, int invert,
|
||||
new_size *= sizeof(struct nft_among_pair);
|
||||
new_size += XT_ALIGN(sizeof(struct xt_entry_match)) +
|
||||
sizeof(struct nft_among_data);
|
||||
- new_match = xtables_calloc(1, new_size);
|
||||
- memcpy(new_match, *match, (*match)->u.match_size);
|
||||
- new_match->u.match_size = new_size;
|
||||
|
||||
- data = (struct nft_among_data *)new_match->data;
|
||||
+ if (new_size > (*match)->u.match_size) {
|
||||
+ *match = xtables_realloc(*match, new_size);
|
||||
+ (*match)->u.match_size = new_size;
|
||||
+ data = (struct nft_among_data *)(*match)->data;
|
||||
+ }
|
||||
+
|
||||
have_ip = nft_among_pairs_have_ip(optarg);
|
||||
poff = nft_among_prepare_data(data, dst, cnt, invert, have_ip);
|
||||
parse_nft_among_pairs(data->pairs + poff, optarg, cnt, have_ip);
|
||||
|
||||
- free(*match);
|
||||
- *match = new_match;
|
||||
-
|
||||
if (c == AMONG_DST_F || c == AMONG_SRC_F) {
|
||||
munmap(argv, flen);
|
||||
close(fd);
|
||||
--
|
||||
2.23.0
|
||||
@@ -1,31 +0,0 @@
|
||||
From 8543b6f2f4a3a15a5ece7dd1b320b477ce36a8d5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Wed, 16 Nov 2022 13:03:05 +0100
|
||||
Subject: [PATCH] extensions: libebt_redirect: Fix xlate return code
|
||||
|
||||
The callback is supposed to return 1 on success, not 0.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=8543b6f2f4a3a15a5ece7dd1b320b477ce36a8d5
|
||||
|
||||
Fixes: 24ce7465056ae ("ebtables-compat: add redirect match extension")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
extensions/libebt_redirect.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/extensions/libebt_redirect.c b/extensions/libebt_redirect.c
|
||||
index 6e653997..4d4c7a02 100644
|
||||
--- a/extensions/libebt_redirect.c
|
||||
+++ b/extensions/libebt_redirect.c
|
||||
@@ -86,7 +86,7 @@ static int brredir_xlate(struct xt_xlate *xl,
|
||||
xt_xlate_add(xl, "meta set pkttype host");
|
||||
if (red->target != EBT_ACCEPT)
|
||||
xt_xlate_add(xl, " %s ", brredir_verdict(red->target));
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static struct xtables_target brredirect_target = {
|
||||
--
|
||||
2.23.0
|
||||
@@ -1,40 +0,0 @@
|
||||
From 800bed28b2b7bbd931166c7426640ae619f03342 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Wed, 16 Nov 2022 13:09:16 +0100
|
||||
Subject: [PATCH] extensions: libipt_ttl: Sanitize xlate callback
|
||||
|
||||
Catch unexpected values in info->mode, also fix indenting.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=800bed28b2b7bbd931166c7426640ae619f03342
|
||||
|
||||
Fixes: 1b320a1a1dc1f ("extensions: libipt_ttl: Add translation to nft")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
extensions/libipt_ttl.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/extensions/libipt_ttl.c b/extensions/libipt_ttl.c
|
||||
index 6bdd2196..86ba554e 100644
|
||||
--- a/extensions/libipt_ttl.c
|
||||
+++ b/extensions/libipt_ttl.c
|
||||
@@ -106,7 +106,7 @@ static int ttl_xlate(struct xt_xlate *xl,
|
||||
const struct ipt_ttl_info *info =
|
||||
(struct ipt_ttl_info *) params->match->data;
|
||||
|
||||
- switch (info->mode) {
|
||||
+ switch (info->mode) {
|
||||
case IPT_TTL_EQ:
|
||||
xt_xlate_add(xl, "ip ttl");
|
||||
break;
|
||||
@@ -121,7 +121,7 @@ static int ttl_xlate(struct xt_xlate *xl,
|
||||
break;
|
||||
default:
|
||||
/* Should not happen. */
|
||||
- break;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
xt_xlate_add(xl, " %u", info->ttl);
|
||||
--
|
||||
2.23.0
|
||||
@@ -1,56 +0,0 @@
|
||||
From 82ccfb488eeac5507471099b9b4e6d136cc06e3b Mon Sep 17 00:00:00 2001
|
||||
From: Jacek Tomasiak <jacek.tomasiak@gmail.com>
|
||||
Date: Mon, 19 Jun 2023 13:46:36 +0200
|
||||
Subject: iptables: Fix handling of non-existent chains
|
||||
|
||||
Since 694612adf87 the "compatibility" check considers non-existent
|
||||
chains as "incompatible". This broke some scripts which used calls
|
||||
like `iptables -L CHAIN404` to test for chain existence and expect
|
||||
"No chain/target/match by that name." in the output.
|
||||
|
||||
This patch changes the logic of `nft_is_table_compatible()` to
|
||||
report non-existent chains as "compatible" which restores the old
|
||||
behavior.
|
||||
|
||||
Fixes: 694612adf87 ("nft: Fix selective chain compatibility checks")
|
||||
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1648
|
||||
Signed-off-by: Jacek Tomasiak <jtomasiak@arista.com>
|
||||
Signed-off-by: Jacek Tomasiak <jacek.tomasiak@gmail.com>
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=82ccfb488eeac5507471099b9b4e6d136cc06e3b
|
||||
|
||||
---
|
||||
iptables/nft.c | 2 +-
|
||||
iptables/tests/shell/testcases/iptables/0004-return-codes_0 | 1 +
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/iptables/nft.c b/iptables/nft.c
|
||||
index 1cb104e7..020553a4 100644
|
||||
--- a/iptables/nft.c
|
||||
+++ b/iptables/nft.c
|
||||
@@ -3860,7 +3860,7 @@ bool nft_is_table_compatible(struct nft_handle *h,
|
||||
if (chain) {
|
||||
struct nft_chain *c = nft_chain_find(h, table, chain);
|
||||
|
||||
- return c && !nft_is_chain_compatible(c, h);
|
||||
+ return !c || !nft_is_chain_compatible(c, h);
|
||||
}
|
||||
|
||||
return !nft_chain_foreach(h, table, nft_is_chain_compatible, h);
|
||||
diff --git a/iptables/tests/shell/testcases/iptables/0004-return-codes_0 b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
|
||||
index 33c5f1f3..234f3040 100755
|
||||
--- a/iptables/tests/shell/testcases/iptables/0004-return-codes_0
|
||||
+++ b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
|
||||
@@ -58,6 +58,7 @@ cmd 1 "$ENOENT" -Z bar
|
||||
cmd 0 -E foo bar
|
||||
cmd 1 "$EEXIST_F" -E foo bar
|
||||
cmd 1 "$ENOENT" -E foo bar2
|
||||
+cmd 1 "$ENOENT" -L foo
|
||||
cmd 0 -N foo2
|
||||
cmd 1 "$EEXIST_F" -E foo2 bar
|
||||
|
||||
--
|
||||
cgit v1.2.3
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
From fb63f8b7337aa11a667537e6a3b399062ede2eb5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 25 Nov 2022 21:35:28 +0100
|
||||
Subject: [PATCH] iptables: Plug memleaks in print_firewall()
|
||||
|
||||
When adding a rule in verbose mode, valgrind prints:
|
||||
|
||||
192 bytes in 1 blocks are definitely lost in loss record 1 of 2
|
||||
at 0x48417E5: malloc (vg_replace_malloc.c:381)
|
||||
by 0x486B158: xtables_malloc (xtables.c:446)
|
||||
by 0x486C1F6: xtables_find_match (xtables.c:826)
|
||||
by 0x10E684: print_match (iptables.c:115)
|
||||
by 0x10E684: print_firewall (iptables.c:169)
|
||||
by 0x10FC0C: print_firewall_line (iptables.c:196)
|
||||
by 0x10FC0C: append_entry (iptables.c:221)
|
||||
by 0x10FC0C: do_command4 (iptables.c:776)
|
||||
by 0x10E45B: iptables_main (iptables-standalone.c:59)
|
||||
by 0x49A2349: (below main) (in /lib64/libc.so.6)
|
||||
|
||||
200 bytes in 1 blocks are definitely lost in loss record 2 of 2
|
||||
at 0x48417E5: malloc (vg_replace_malloc.c:381)
|
||||
by 0x486B158: xtables_malloc (xtables.c:446)
|
||||
by 0x486BBD6: xtables_find_target (xtables.c:956)
|
||||
by 0x10E579: print_firewall (iptables.c:145)
|
||||
by 0x10FC0C: print_firewall_line (iptables.c:196)
|
||||
by 0x10FC0C: append_entry (iptables.c:221)
|
||||
by 0x10FC0C: do_command4 (iptables.c:776)
|
||||
by 0x10E45B: iptables_main (iptables-standalone.c:59)
|
||||
by 0x49A2349: (below main) (in /lib64/libc.so.6)
|
||||
|
||||
If the match/target was cloned, it needs to be freed. Basically a bug since
|
||||
day 1.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=fb63f8b7337aa11a667537e6a3b399062ede2eb5
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
iptables/ip6tables.c | 6 ++++++
|
||||
iptables/iptables.c | 6 ++++++
|
||||
2 files changed, 12 insertions(+)
|
||||
|
||||
diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
|
||||
index 062b2b15..1d232657 100644
|
||||
--- a/iptables/ip6tables.c
|
||||
+++ b/iptables/ip6tables.c
|
||||
@@ -122,6 +122,9 @@ print_match(const struct xt_entry_match *m,
|
||||
printf("%s%s ", match->name, unsupported_rev);
|
||||
else
|
||||
printf("%s ", match->name);
|
||||
+
|
||||
+ if (match->next == match)
|
||||
+ free(match);
|
||||
} else {
|
||||
if (name[0])
|
||||
printf("UNKNOWN match `%s' ", name);
|
||||
@@ -179,6 +182,9 @@ print_firewall(const struct ip6t_entry *fw,
|
||||
tg->print(&fw->ipv6, t, format & FMT_NUMERIC);
|
||||
else if (target->print)
|
||||
printf(" %s%s", target->name, unsupported_rev);
|
||||
+
|
||||
+ if (target->next == target)
|
||||
+ free(target);
|
||||
} else if (t->u.target_size != sizeof(*t))
|
||||
printf("[%u bytes of unknown target data] ",
|
||||
(unsigned int)(t->u.target_size - sizeof(*t)));
|
||||
diff --git a/iptables/iptables.c b/iptables/iptables.c
|
||||
index 0351b39f..d246198f 100644
|
||||
--- a/iptables/iptables.c
|
||||
+++ b/iptables/iptables.c
|
||||
@@ -122,6 +122,9 @@ print_match(const struct xt_entry_match *m,
|
||||
printf("%s%s ", match->name, unsupported_rev);
|
||||
else
|
||||
printf("%s ", match->name);
|
||||
+
|
||||
+ if (match->next == match)
|
||||
+ free(match);
|
||||
} else {
|
||||
if (name[0])
|
||||
printf("UNKNOWN match `%s' ", name);
|
||||
@@ -178,6 +181,9 @@ print_firewall(const struct ipt_entry *fw,
|
||||
tg->print(&fw->ip, t, format & FMT_NUMERIC);
|
||||
else if (target->print)
|
||||
printf(" %s%s", target->name, unsupported_rev);
|
||||
+
|
||||
+ if (target->next == target)
|
||||
+ free(target);
|
||||
} else if (t->u.target_size != sizeof(*t))
|
||||
printf("[%u bytes of unknown target data] ",
|
||||
(unsigned int)(t->u.target_size - sizeof(*t)));
|
||||
--
|
||||
2.23.0
|
||||
@@ -1,48 +0,0 @@
|
||||
From 18880dbde615449d00a3e38f3713a19d4566258e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 25 Nov 2022 19:24:38 +0100
|
||||
Subject: [PATCH] iptables-restore: Free handle with --test also
|
||||
|
||||
When running 'iptables-restore -t', valgrind reports:
|
||||
|
||||
1,496 (160 direct, 1,336 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4
|
||||
at 0x48417E5: malloc (vg_replace_malloc.c:381)
|
||||
by 0x4857A46: alloc_handle (libiptc.c:1279)
|
||||
by 0x4857A46: iptc_init (libiptc.c:1342)
|
||||
by 0x1167CE: create_handle (iptables-restore.c:72)
|
||||
by 0x1167CE: ip46tables_restore_main (iptables-restore.c:229)
|
||||
by 0x116DAE: iptables_restore_main (iptables-restore.c:388)
|
||||
by 0x49A2349: (below main) (in /lib64/libc.so.6)
|
||||
|
||||
Free the handle pointer before parsing the next table.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=18880dbde615449d00a3e38f3713a19d4566258e
|
||||
|
||||
Fixes: 1c9015b2cb483 ("libiptc: remove indirections")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
iptables/iptables-restore.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c
|
||||
index 05661bf6..6f7ddf93 100644
|
||||
--- a/iptables/iptables-restore.c
|
||||
+++ b/iptables/iptables-restore.c
|
||||
@@ -185,12 +185,12 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb,
|
||||
if (!testing) {
|
||||
DEBUGP("Calling commit\n");
|
||||
ret = cb->ops->commit(handle);
|
||||
- cb->ops->free(handle);
|
||||
- handle = NULL;
|
||||
} else {
|
||||
DEBUGP("Not calling commit, testing\n");
|
||||
ret = 1;
|
||||
}
|
||||
+ cb->ops->free(handle);
|
||||
+ handle = NULL;
|
||||
|
||||
/* Done with the current table, release the lock. */
|
||||
if (lock >= 0) {
|
||||
--
|
||||
2.23.0
|
||||
@@ -1,64 +0,0 @@
|
||||
From 2dbb49d15fb44ddd521a734eca3be3f940b7c1ba Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 11 Feb 2022 17:39:24 +0100
|
||||
Subject: libxtables: Register only the highest revision extension
|
||||
|
||||
When fully registering extensions, ignore all consecutive ones with same
|
||||
name and family value. Since commit b3ac87038f4e4 ("libxtables: Make
|
||||
sure extensions register in revision order"), one may safely assume the
|
||||
list of pending extensions has highest revision numbers first. Since
|
||||
iptables is only interested in the highest revision the kernel supports,
|
||||
registration and compatibility checks may be skipped once the first
|
||||
matching extension in pending list has validated.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit/?id=2dbb49d15fb44ddd521a734eca3be3f940b7c1ba
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
libxtables/xtables.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
|
||||
index 50fd6a44..b34d62ac 100644
|
||||
--- a/libxtables/xtables.c
|
||||
+++ b/libxtables/xtables.c
|
||||
@@ -697,6 +697,7 @@ xtables_find_match(const char *name, enum xtables_tryload tryload,
|
||||
struct xtables_match **dptr;
|
||||
struct xtables_match *ptr;
|
||||
const char *icmp6 = "icmp6";
|
||||
+ bool found = false;
|
||||
|
||||
if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
@@ -715,7 +716,9 @@ xtables_find_match(const char *name, enum xtables_tryload tryload,
|
||||
if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) {
|
||||
ptr = *dptr;
|
||||
*dptr = (*dptr)->next;
|
||||
- if (xtables_fully_register_pending_match(ptr, prev)) {
|
||||
+ if (!found &&
|
||||
+ xtables_fully_register_pending_match(ptr, prev)) {
|
||||
+ found = true;
|
||||
prev = ptr;
|
||||
continue;
|
||||
} else if (prev) {
|
||||
@@ -817,6 +820,7 @@ xtables_find_target(const char *name, enum xtables_tryload tryload)
|
||||
struct xtables_target *prev = NULL;
|
||||
struct xtables_target **dptr;
|
||||
struct xtables_target *ptr;
|
||||
+ bool found = false;
|
||||
|
||||
/* Standard target? */
|
||||
if (strcmp(name, "") == 0
|
||||
@@ -831,7 +835,9 @@ xtables_find_target(const char *name, enum xtables_tryload tryload)
|
||||
if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) {
|
||||
ptr = *dptr;
|
||||
*dptr = (*dptr)->next;
|
||||
- if (xtables_fully_register_pending_target(ptr, prev)) {
|
||||
+ if (!found &&
|
||||
+ xtables_fully_register_pending_target(ptr, prev)) {
|
||||
+ found = true;
|
||||
prev = ptr;
|
||||
continue;
|
||||
} else if (prev) {
|
||||
--
|
||||
cgit v1.2.3
|
||||
@@ -1,95 +0,0 @@
|
||||
From 0257293c68913dd5993c1cac44f2ee80af6d9792 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 26 Aug 2022 16:53:52 +0200
|
||||
Subject: [PATCH] nft: Expand extended error reporting to nft_cmd, too
|
||||
|
||||
Introduce the same embedded 'error' struct in nft_cmd and initialize it
|
||||
with the current value from nft_handle. Then in preparation phase,
|
||||
update nft_handle's error.lineno with the value from the current
|
||||
nft_cmd.
|
||||
|
||||
This serves two purposes:
|
||||
|
||||
* Allocated batch objects (obj_update) get the right lineno value
|
||||
instead of the COMMIT one.
|
||||
|
||||
* Any error during preparation may be reported with line number. Do this
|
||||
and change the relevant fprintf() call to use nft_handle's lineno
|
||||
instead of the global 'line' variable.
|
||||
|
||||
With this change, cryptic iptables-nft-restore error messages should
|
||||
finally be gone:
|
||||
|
||||
| # iptables-nft-restore <<EOF
|
||||
| *filter
|
||||
| -A nonexist
|
||||
| COMMIT
|
||||
| EOF
|
||||
| iptables-nft-restore: line 2 failed: No chain/target/match by that name.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=0257293c68913dd5993c1cac44f2ee80af6d9792
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
iptables/nft-cmd.c | 1 +
|
||||
iptables/nft-cmd.h | 3 +++
|
||||
iptables/nft.c | 2 ++
|
||||
iptables/xtables-restore.c | 2 +-
|
||||
4 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/iptables/nft-cmd.c b/iptables/nft-cmd.c
|
||||
index 9b0c964..f026c62 100644
|
||||
--- a/iptables/nft-cmd.c
|
||||
+++ b/iptables/nft-cmd.c
|
||||
@@ -26,6 +26,7 @@ struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
|
||||
if (!cmd)
|
||||
return NULL;
|
||||
|
||||
+ cmd->error.lineno = h->error.lineno;
|
||||
cmd->command = command;
|
||||
cmd->table = strdup(table);
|
||||
if (chain)
|
||||
diff --git a/iptables/nft-cmd.h b/iptables/nft-cmd.h
|
||||
index ecf7655..3caa3ed 100644
|
||||
--- a/iptables/nft-cmd.h
|
||||
+++ b/iptables/nft-cmd.h
|
||||
@@ -24,6 +24,9 @@ struct nft_cmd {
|
||||
struct xt_counters counters;
|
||||
const char *rename;
|
||||
int counters_save;
|
||||
+ struct {
|
||||
+ unsigned int lineno;
|
||||
+ } error;
|
||||
};
|
||||
|
||||
struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
|
||||
diff --git a/iptables/nft.c b/iptables/nft.c
|
||||
index 3e24c86..996d5bc 100644
|
||||
--- a/iptables/nft.c
|
||||
+++ b/iptables/nft.c
|
||||
@@ -3050,6 +3050,8 @@ static int nft_prepare(struct nft_handle *h)
|
||||
nft_cache_build(h);
|
||||
|
||||
list_for_each_entry_safe(cmd, next, &h->cmd_list, head) {
|
||||
+ h->error.lineno = cmd->error.lineno;
|
||||
+
|
||||
switch (cmd->command) {
|
||||
case NFT_COMPAT_TABLE_FLUSH:
|
||||
ret = nft_table_flush(h, cmd->table);
|
||||
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
|
||||
index d273949..abeaf76 100644
|
||||
--- a/iptables/xtables-restore.c
|
||||
+++ b/iptables/xtables-restore.c
|
||||
@@ -248,7 +248,7 @@ static void xtables_restore_parse_line(struct nft_handle *h,
|
||||
return;
|
||||
if (!ret) {
|
||||
fprintf(stderr, "%s: line %u failed\n",
|
||||
- xt_params->program_name, line);
|
||||
+ xt_params->program_name, h->error.lineno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
From 8468fd4f7c85c21ab375402bc80d0188412b6cbf Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Wed, 4 May 2022 11:19:16 +0200
|
||||
Subject: nft: Fix EPERM handling for extensions without rev 0
|
||||
|
||||
Treating revision 0 as compatible in EPERM case works fine as long as
|
||||
there is a revision 0 of that extension defined in DSO. Fix the code for
|
||||
others: Extend the EPERM handling to all revisions and keep the existing
|
||||
warning for revision 0.
|
||||
|
||||
Conflict: NA
|
||||
Reference:
|
||||
https://git.netfilter.org/iptables/commit/?id=8468fd4f7c85c21ab375402bc80d0188412b6cbf
|
||||
Fixes: 17534cb18ed0a ("Improve error messages for unsupported
|
||||
extensions")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
iptables/nft.c | 11 +++++++----
|
||||
.../shell/testcases/iptables/0008-unprivileged_0 | 7 +++++++
|
||||
2 files changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/iptables/nft.c b/iptables/nft.c
|
||||
index 18bf21c..ebab3cc 100644
|
||||
--- a/iptables/nft.c
|
||||
+++ b/iptables/nft.c
|
||||
@@ -3245,15 +3245,18 @@ int nft_compatible_revision(const char *name, uint8_t rev, int opt)
|
||||
err:
|
||||
mnl_socket_close(nl);
|
||||
|
||||
- /* pretend revision 0 is valid -
|
||||
+ /* ignore EPERM and errors for revision 0 -
|
||||
* this is required for printing extension help texts as user, also
|
||||
* helps error messaging on unavailable kernel extension */
|
||||
- if (ret < 0 && rev == 0) {
|
||||
- if (errno != EPERM)
|
||||
+ if (ret < 0) {
|
||||
+ if (errno == EPERM)
|
||||
+ return 1;
|
||||
+ if (rev == 0) {
|
||||
fprintf(stderr,
|
||||
"Warning: Extension %s revision 0 not supported, missing kernel module?\n",
|
||||
name);
|
||||
- return 1;
|
||||
+ return 1;
|
||||
+ }
|
||||
}
|
||||
return ret < 0 ? 0 : 1;
|
||||
}
|
||||
diff --git a/iptables/tests/shell/testcases/iptables/0008-unprivileged_0 b/iptables/tests/shell/testcases/iptables/0008-unprivileged_0
|
||||
index 0914c88..1f1d342 100644
|
||||
--- a/iptables/tests/shell/testcases/iptables/0008-unprivileged_0
|
||||
+++ b/iptables/tests/shell/testcases/iptables/0008-unprivileged_0
|
||||
@@ -34,6 +34,13 @@ let "rc+=$?"
|
||||
grep_or_rc "DNAT target options:" <<< "$out"
|
||||
let "rc+=$?"
|
||||
|
||||
+# TEE has no revision 0
|
||||
+out=$(run $XT_MULTI iptables -j TEE --help)
|
||||
+let "rc+=$?"
|
||||
+grep_or_rc "TEE target options:" <<< "$out"
|
||||
+let "rc+=$?"
|
||||
+
|
||||
+
|
||||
out=$(run $XT_MULTI iptables -p tcp -j DNAT --help)
|
||||
let "rc+=$?"
|
||||
grep_or_rc "tcp match options:" <<< "$out"
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
From aa0c54030300441e9fd66c7016d0090f6736d449 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Fri, 25 Nov 2022 21:21:22 +0100
|
||||
Subject: [PATCH] nft: Plug memleak in nft_rule_zero_counters()
|
||||
|
||||
When zeroing a specific rule, valgrind reports:
|
||||
|
||||
40 bytes in 1 blocks are definitely lost in loss record 1 of 1
|
||||
at 0x484659F: calloc (vg_replace_malloc.c:1328)
|
||||
by 0x48DE128: xtables_calloc (xtables.c:434)
|
||||
by 0x11C7C6: nft_parse_immediate (nft-shared.c:1071)
|
||||
by 0x11C7C6: nft_rule_to_iptables_command_state (nft-shared.c:1236)
|
||||
by 0x119AF5: nft_rule_zero_counters (nft.c:2877)
|
||||
by 0x11A3CA: nft_prepare (nft.c:3445)
|
||||
by 0x11A7A8: nft_commit (nft.c:3479)
|
||||
by 0x114258: xtables_main.isra.0 (xtables-standalone.c:94)
|
||||
by 0x1142D9: xtables_ip6_main (xtables-standalone.c:118)
|
||||
by 0x49F2349: (below main) (in /lib64/libc.so.6)
|
||||
|
||||
Have to free the matches/target in populated iptables_command_state object
|
||||
again. While being at it, call the proper family_ops callbacks since this is
|
||||
family-agnostic code.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=aa0c54030300441e9fd66c7016d0090f6736d449
|
||||
|
||||
Fixes: a69cc575295ee ("xtables: allow to reset the counters of an existing rule")
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
iptables/nft.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/iptables/nft.c b/iptables/nft.c
|
||||
index 67c5877c..430888e8 100644
|
||||
--- a/iptables/nft.c
|
||||
+++ b/iptables/nft.c
|
||||
@@ -2874,10 +2874,11 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
|
||||
goto error;
|
||||
}
|
||||
|
||||
- nft_rule_to_iptables_command_state(h, r, &cs);
|
||||
-
|
||||
+ h->ops->rule_to_cs(h, r, &cs);
|
||||
cs.counters.pcnt = cs.counters.bcnt = 0;
|
||||
new_rule = nft_rule_new(h, chain, table, &cs);
|
||||
+ h->ops->clear_cs(&cs);
|
||||
+
|
||||
if (!new_rule)
|
||||
return 1;
|
||||
|
||||
--
|
||||
2.23.0
|
||||
@@ -1,130 +0,0 @@
|
||||
From 26ecdf53960658771c0fc582f72a4025e2887f75 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Tue, 18 Jan 2022 22:39:08 +0100
|
||||
Subject: xshared: Fix response to unprivileged users
|
||||
|
||||
Expected behaviour in both variants is:
|
||||
|
||||
* Print help without error, append extension help if -m and/or -j
|
||||
options are present
|
||||
* Indicate lack of permissions in an error message for anything else
|
||||
|
||||
With iptables-nft, this was broken basically from day 1. Shared use of
|
||||
do_parse() then somewhat broke legacy: it started complaining about
|
||||
inability to create a lock file.
|
||||
|
||||
Fix this by making iptables-nft assume extension revision 0 is present
|
||||
if permissions don't allow to verify. This is consistent with legacy.
|
||||
|
||||
Second part is to exit directly after printing help - this avoids having
|
||||
to make the following code "nop-aware" to prevent privileged actions.
|
||||
|
||||
Conflict: NA
|
||||
Reference:
|
||||
https://git.netfilter.org/iptables/commit/?id=26ecdf53960658771c0fc582f72a4025e2887f75
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
Reviewed-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
iptables/nft.c | 5 ++
|
||||
.../testcases/iptables/0008-unprivileged_0 | 59 +++++++++++++++++++
|
||||
iptables/xtables.c | 2 +-
|
||||
3 files changed, 65 insertions(+), 1 deletion(-)
|
||||
create mode 100644 iptables/tests/shell/testcases/iptables/0008-unprivileged_0
|
||||
|
||||
diff --git a/iptables/nft.c b/iptables/nft.c
|
||||
index bde4ca7..c9a4940 100644
|
||||
--- a/iptables/nft.c
|
||||
+++ b/iptables/nft.c
|
||||
@@ -3245,6 +3245,11 @@ int nft_compatible_revision(const char *name, uint8_t rev, int opt)
|
||||
err:
|
||||
mnl_socket_close(nl);
|
||||
|
||||
+ /* pretend revision 0 is valid if not permitted to check -
|
||||
+ * this is required for printing extension help texts as user */
|
||||
+ if (ret < 0 && errno == EPERM && rev == 0)
|
||||
+ return 1;
|
||||
+
|
||||
return ret < 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
diff --git a/iptables/tests/shell/testcases/iptables/0008-unprivileged_0 b/iptables/tests/shell/testcases/iptables/0008-unprivileged_0
|
||||
new file mode 100644
|
||||
index 0000000..0914c88
|
||||
--- /dev/null
|
||||
+++ b/iptables/tests/shell/testcases/iptables/0008-unprivileged_0
|
||||
@@ -0,0 +1,59 @@
|
||||
+#!/bin/bash
|
||||
+# iptables may print match/target specific help texts
|
||||
+# help output should work for unprivileged users
|
||||
+
|
||||
+run() {
|
||||
+ echo "running: $*" >&2
|
||||
+ runuser -u nobody -- "$@"
|
||||
+}
|
||||
+
|
||||
+grep_or_rc() {
|
||||
+ declare -g rc
|
||||
+ grep -q "$*" && return 0
|
||||
+ echo "missing in output: $*" >&2
|
||||
+ return 1
|
||||
+}
|
||||
+
|
||||
+out=$(run $XT_MULTI iptables --help)
|
||||
+let "rc+=$?"
|
||||
+grep_or_rc "iptables -h (print this help information)" <<< "$out"
|
||||
+let "rc+=$?"
|
||||
+
|
||||
+out=$(run $XT_MULTI iptables -m limit --help)
|
||||
+let "rc+=$?"
|
||||
+grep_or_rc "limit match options:" <<< "$out"
|
||||
+let "rc+=$?"
|
||||
+
|
||||
+out=$(run $XT_MULTI iptables -p tcp --help)
|
||||
+let "rc+=$?"
|
||||
+grep_or_rc "tcp match options:" <<< "$out"
|
||||
+let "rc+=$?"
|
||||
+
|
||||
+out=$(run $XT_MULTI iptables -j DNAT --help)
|
||||
+let "rc+=$?"
|
||||
+grep_or_rc "DNAT target options:" <<< "$out"
|
||||
+let "rc+=$?"
|
||||
+
|
||||
+out=$(run $XT_MULTI iptables -p tcp -j DNAT --help)
|
||||
+let "rc+=$?"
|
||||
+grep_or_rc "tcp match options:" <<< "$out"
|
||||
+let "rc+=$?"
|
||||
+out=$(run $XT_MULTI iptables -p tcp -j DNAT --help)
|
||||
+let "rc+=$?"
|
||||
+grep_or_rc "DNAT target options:" <<< "$out"
|
||||
+let "rc+=$?"
|
||||
+
|
||||
+
|
||||
+run $XT_MULTI iptables -L 2>&1 | \
|
||||
+ grep_or_rc "Permission denied"
|
||||
+let "rc+=$?"
|
||||
+
|
||||
+run $XT_MULTI iptables -A FORWARD -p tcp --dport 123 2>&1 | \
|
||||
+ grep_or_rc "Permission denied"
|
||||
+let "rc+=$?"
|
||||
+
|
||||
+run $XT_MULTI iptables -A FORWARD -j DNAT --to-destination 1.2.3.4 2>&1 | \
|
||||
+ grep_or_rc "Permission denied"
|
||||
+let "rc+=$?"
|
||||
+
|
||||
+exit $rc
|
||||
diff --git a/iptables/xtables.c b/iptables/xtables.c
|
||||
index 9779bd8..a16bba7 100644
|
||||
--- a/iptables/xtables.c
|
||||
+++ b/iptables/xtables.c
|
||||
@@ -645,7 +645,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
|
||||
|
||||
printhelp(cs->matches);
|
||||
p->command = CMD_NONE;
|
||||
- return;
|
||||
+ exit(0);
|
||||
|
||||
/*
|
||||
* Option selection
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
From e900d40afdb731d2270a5110833ae49192974355 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Westphal <fw@strlen.de>
|
||||
Date: Tue, 14 Mar 2023 22:36:50 +0100
|
||||
Subject: [PATCH] xtables-eb: fix crash when opts isn't reallocated
|
||||
|
||||
opts may point to statically allocated memory.
|
||||
This fixes abort() from libc.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=e900d40afdb731d2270a5110833ae49192974355
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
iptables/xtables-eb.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
|
||||
index 3a73e797..068dffd2 100644
|
||||
--- a/iptables/xtables-eb.c
|
||||
+++ b/iptables/xtables-eb.c
|
||||
@@ -675,7 +675,8 @@ void nft_fini_eb(struct nft_handle *h)
|
||||
free(target->t);
|
||||
}
|
||||
|
||||
- free(opts);
|
||||
+ if (opts != ebt_original_options)
|
||||
+ free(opts);
|
||||
|
||||
nft_fini(h);
|
||||
xtables_fini();
|
||||
--
|
||||
2.23.0
|
||||
@@ -1,44 +0,0 @@
|
||||
From c70a33d219ccb43e6f59aa1b9bbab5dcb13f3443 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
Date: Thu, 25 Aug 2022 11:53:04 +0200
|
||||
Subject: [PATCH] xtables-restore: Extend failure error message
|
||||
|
||||
If a line causes zero 'ret' value and errno is set, call nft_strerror()
|
||||
for a more detailed error message. While not perfect, it helps with
|
||||
debugging ominous "line NN failed" messages pointing at COMMIT:
|
||||
|
||||
| # iptables-nft-restore <<EOF
|
||||
| *filter
|
||||
| -A nonexist
|
||||
| COMMIT
|
||||
| EOF
|
||||
| iptables-nft-restore: line 3 failed: No chain/target/match by that name.
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://git.netfilter.org/iptables/commit?id=c70a33d219ccb43e6f59aa1b9bbab5dcb13f3443
|
||||
|
||||
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||||
---
|
||||
iptables/xtables-restore.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
|
||||
index abeaf76..5940e9a 100644
|
||||
--- a/iptables/xtables-restore.c
|
||||
+++ b/iptables/xtables-restore.c
|
||||
@@ -247,8 +247,11 @@ static void xtables_restore_parse_line(struct nft_handle *h,
|
||||
(strcmp(p->tablename, state->curtable->name) != 0))
|
||||
return;
|
||||
if (!ret) {
|
||||
- fprintf(stderr, "%s: line %u failed\n",
|
||||
+ fprintf(stderr, "%s: line %u failed",
|
||||
xt_params->program_name, h->error.lineno);
|
||||
+ if (errno)
|
||||
+ fprintf(stderr, ": %s.", nft_strerror(errno));
|
||||
+ fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
From cbc3a30711701f0e8d7f5df14f84adfb2c9fec1f Mon Sep 17 00:00:00 2001
|
||||
From: majun <majun65@huawei.com>
|
||||
Date: Fri, 16 Apr 2021 14:52:42 +0800
|
||||
Subject: [PATCH]
|
||||
|
||||
iptables: add null check for fw in X_entry
|
||||
If the fw pointer is empty, a core dump occurs.
|
||||
|
||||
---
|
||||
iptables/ip6tables.c | 21 +++++++++++++++++++++
|
||||
iptables/iptables.c | 20 ++++++++++++++++++++
|
||||
2 files changed, 41 insertions(+)
|
||||
|
||||
diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
|
||||
index c95355b..1902cb4 100644
|
||||
--- a/iptables/ip6tables.c
|
||||
+++ b/iptables/ip6tables.c
|
||||
@@ -478,6 +478,10 @@ append_entry(const xt_chainlabel chain,
|
||||
unsigned int i, j;
|
||||
int ret = 1;
|
||||
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < nsaddrs; i++) {
|
||||
fw->ipv6.src = saddrs[i];
|
||||
fw->ipv6.smsk = smasks[i];
|
||||
@@ -502,6 +506,11 @@ replace_entry(const xt_chainlabel chain,
|
||||
int verbose,
|
||||
struct xtc_handle *handle)
|
||||
{
|
||||
+
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
fw->ipv6.src = *saddr;
|
||||
fw->ipv6.dst = *daddr;
|
||||
fw->ipv6.smsk = *smask;
|
||||
@@ -528,6 +537,10 @@ insert_entry(const xt_chainlabel chain,
|
||||
unsigned int i, j;
|
||||
int ret = 1;
|
||||
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < nsaddrs; i++) {
|
||||
fw->ipv6.src = saddrs[i];
|
||||
fw->ipv6.smsk = smasks[i];
|
||||
@@ -595,6 +608,10 @@ delete_entry(const xt_chainlabel chain,
|
||||
int ret = 1;
|
||||
unsigned char *mask;
|
||||
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
mask = make_delete_mask(matches, target);
|
||||
for (i = 0; i < nsaddrs; i++) {
|
||||
fw->ipv6.src = saddrs[i];
|
||||
@@ -625,6 +642,10 @@ check_entry(const xt_chainlabel chain, struct ip6t_entry *fw,
|
||||
int ret = 1;
|
||||
unsigned char *mask;
|
||||
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
mask = make_delete_mask(matches, target);
|
||||
for (i = 0; i < nsaddrs; i++) {
|
||||
fw->ipv6.src = saddrs[i];
|
||||
diff --git a/iptables/iptables.c b/iptables/iptables.c
|
||||
index 7d61831..a206825 100644
|
||||
--- a/iptables/iptables.c
|
||||
+++ b/iptables/iptables.c
|
||||
@@ -469,6 +469,10 @@ append_entry(const xt_chainlabel chain,
|
||||
unsigned int i, j;
|
||||
int ret = 1;
|
||||
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < nsaddrs; i++) {
|
||||
fw->ip.src.s_addr = saddrs[i].s_addr;
|
||||
fw->ip.smsk.s_addr = smasks[i].s_addr;
|
||||
@@ -493,6 +497,10 @@ replace_entry(const xt_chainlabel chain,
|
||||
int verbose,
|
||||
struct xtc_handle *handle)
|
||||
{
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
fw->ip.src.s_addr = saddr->s_addr;
|
||||
fw->ip.dst.s_addr = daddr->s_addr;
|
||||
fw->ip.smsk.s_addr = smask->s_addr;
|
||||
@@ -519,6 +527,10 @@ insert_entry(const xt_chainlabel chain,
|
||||
unsigned int i, j;
|
||||
int ret = 1;
|
||||
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < nsaddrs; i++) {
|
||||
fw->ip.src.s_addr = saddrs[i].s_addr;
|
||||
fw->ip.smsk.s_addr = smasks[i].s_addr;
|
||||
@@ -586,6 +598,10 @@ delete_entry(const xt_chainlabel chain,
|
||||
int ret = 1;
|
||||
unsigned char *mask;
|
||||
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
mask = make_delete_mask(matches, target);
|
||||
for (i = 0; i < nsaddrs; i++) {
|
||||
fw->ip.src.s_addr = saddrs[i].s_addr;
|
||||
@@ -616,6 +632,10 @@ check_entry(const xt_chainlabel chain, struct ipt_entry *fw,
|
||||
int ret = 1;
|
||||
unsigned char *mask;
|
||||
|
||||
+ if (!fw) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
mask = make_delete_mask(matches, target);
|
||||
for (i = 0; i < nsaddrs; i++) {
|
||||
fw->ip.src.s_addr = saddrs[i].s_addr;
|
||||
--
|
||||
2.27.0
|
||||
|
||||
+313
@@ -0,0 +1,313 @@
|
||||
|
||||
AC_INIT([iptables], [1.8.11])
|
||||
|
||||
# See libtool.info "Libtool's versioning system"
|
||||
libxtables_vcurrent=19
|
||||
libxtables_vage=7
|
||||
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PROG_INSTALL
|
||||
AM_INIT_AUTOMAKE([-Wall])
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
LT_INIT([disable-static])
|
||||
|
||||
AC_ARG_WITH([kernel],
|
||||
AS_HELP_STRING([--with-kernel=PATH],
|
||||
[Path to kernel source/build directory]),
|
||||
[kbuilddir="$withval"; ksourcedir="$withval";])
|
||||
AC_ARG_WITH([kbuild],
|
||||
AS_HELP_STRING([--with-kbuild=PATH],
|
||||
[Path to kernel build directory [[/lib/modules/CURRENT/build]]]),
|
||||
[kbuilddir="$withval"])
|
||||
AC_ARG_WITH([ksource],
|
||||
AS_HELP_STRING([--with-ksource=PATH],
|
||||
[Path to kernel source directory [[/lib/modules/CURRENT/source]]]),
|
||||
[ksourcedir="$withval"])
|
||||
AC_ARG_WITH([xtlibdir],
|
||||
AS_HELP_STRING([--with-xtlibdir=PATH],
|
||||
[Path where to install Xtables extensions [[LIBEXECDIR/xtables]]]),
|
||||
[xtlibdir="$withval"],
|
||||
[xtlibdir="${libdir}/xtables"])
|
||||
AC_ARG_ENABLE([ipv4],
|
||||
AS_HELP_STRING([--disable-ipv4], [Do not build iptables]),
|
||||
[enable_ipv4="$enableval"], [enable_ipv4="yes"])
|
||||
AC_ARG_ENABLE([ipv6],
|
||||
AS_HELP_STRING([--disable-ipv6], [Do not build ip6tables]),
|
||||
[enable_ipv6="$enableval"], [enable_ipv6="yes"])
|
||||
AC_ARG_ENABLE([largefile],
|
||||
AS_HELP_STRING([--disable-largefile], [Do not build largefile support]),
|
||||
[enable_largefile="$enableval"],
|
||||
[enable_largefile="yes"])
|
||||
AS_IF([test "$enable_largefile" = "yes"], [largefile_cppflags='-D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64'])
|
||||
|
||||
AC_ARG_ENABLE([devel],
|
||||
AS_HELP_STRING([--enable-devel],
|
||||
[Install Xtables development headers]),
|
||||
[enable_devel="$enableval"], [enable_devel="yes"])
|
||||
AC_ARG_ENABLE([libipq],
|
||||
AS_HELP_STRING([--enable-libipq], [Build and install libipq]),
|
||||
[enable_libipq="$enableval"], [enable_libipq="no"])
|
||||
AC_ARG_ENABLE([bpf-compiler],
|
||||
AS_HELP_STRING([--enable-bpf-compiler], [Build bpf compiler]),
|
||||
[enable_bpfc="$enableval"], [enable_bpfc="no"])
|
||||
AC_ARG_ENABLE([nfsynproxy],
|
||||
AS_HELP_STRING([--enable-nfsynproxy], [Build SYNPROXY configuration tool]),
|
||||
[enable_nfsynproxy="$enableval"], [enable_nfsynproxy="no"])
|
||||
AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH],
|
||||
[Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]),
|
||||
[pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig'])
|
||||
AC_ARG_ENABLE([nftables],
|
||||
AS_HELP_STRING([--disable-nftables], [Do not build nftables compat]),
|
||||
[enable_nftables="$enableval"], [enable_nftables="yes"])
|
||||
AC_ARG_ENABLE([libnfnetlink],
|
||||
AS_HELP_STRING([--disable-libnfnetlink], [Do not use netfilter netlink library]),
|
||||
[enable_libnfnetlink="$enableval"], [enable_libnfnetlink="auto"])
|
||||
AC_ARG_ENABLE([connlabel],
|
||||
AS_HELP_STRING([--disable-connlabel],
|
||||
[Do not build libnetfilter_conntrack]),
|
||||
[enable_connlabel="$enableval"], [enable_connlabel="yes"])
|
||||
AC_ARG_WITH([xt-lock-name], AS_HELP_STRING([--with-xt-lock-name=PATH],
|
||||
[Path to the xtables lock [[/run/xtables.lock]]]),
|
||||
[xt_lock_name="$withval"],
|
||||
[xt_lock_name="/run/xtables.lock"])
|
||||
AC_ARG_ENABLE([profiling],
|
||||
AS_HELP_STRING([--enable-profiling], [build for use of gcov/gprof]),
|
||||
[enable_profiling="$enableval"], [enable_profiling="no"])
|
||||
|
||||
AC_MSG_CHECKING([whether $LD knows -Wl,--no-undefined])
|
||||
saved_LDFLAGS="$LDFLAGS";
|
||||
LDFLAGS="-Wl,--no-undefined";
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([int main(void) {}])],
|
||||
[noundef_LDFLAGS="$LDFLAGS"; AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([no])]
|
||||
)
|
||||
LDFLAGS="$saved_LDFLAGS";
|
||||
|
||||
blacklist_modules=""
|
||||
blacklist_x_modules=""
|
||||
blacklist_b_modules=""
|
||||
blacklist_a_modules=""
|
||||
blacklist_4_modules=""
|
||||
blacklist_6_modules=""
|
||||
|
||||
AC_CHECK_HEADERS([linux/dccp.h linux/ip_vs.h linux/magic.h linux/proc_fs.h linux/bpf.h])
|
||||
if test "$ac_cv_header_linux_dccp_h" != "yes"; then
|
||||
blacklist_modules="$blacklist_modules dccp";
|
||||
fi;
|
||||
if test "$ac_cv_header_linux_ip_vs_h" != "yes"; then
|
||||
blacklist_modules="$blacklist_modules ipvs";
|
||||
fi;
|
||||
|
||||
AC_CHECK_SIZEOF([struct ip6_hdr], [], [#include <netinet/ip6.h>])
|
||||
|
||||
AM_CONDITIONAL([ENABLE_STATIC], [test "$enable_static" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_SHARED], [test "$enable_shared" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_IPV4], [test "$enable_ipv4" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_IPV6], [test "$enable_ipv6" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_LARGEFILE], [test "$enable_largefile" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_DEVEL], [test "$enable_devel" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_LIBIPQ], [test "$enable_libipq" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_BPFC], [test "$enable_bpfc" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_SYNCONF], [test "$enable_nfsynproxy" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_NFTABLES], [test "$enable_nftables" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_CONNLABEL], [test "$enable_connlabel" = "yes"])
|
||||
|
||||
# If specified explicitly on the command line, error out when library was not found
|
||||
# Otherwise, disable and continue
|
||||
AS_IF([test "x$enable_libnfnetlink" = "xyes"],
|
||||
[PKG_CHECK_MODULES([libnfnetlink], [libnfnetlink >= 1.0],
|
||||
[nfnetlink=1])],
|
||||
[test "x$enable_libnfnetlink" = "xauto"],
|
||||
[PKG_CHECK_MODULES([libnfnetlink], [libnfnetlink >= 1.0],
|
||||
[nfnetlink=1], [nfnetlink=0])])
|
||||
AM_CONDITIONAL([HAVE_LIBNFNETLINK], [test "$nfnetlink" = 1])
|
||||
|
||||
if test "x$enable_bpfc" = "xyes" || test "x$enable_nfsynproxy" = "xyes"; then
|
||||
PKG_CHECK_MODULES([libpcap], [libpcap], [], [
|
||||
AC_MSG_ERROR(missing libpcap library required by bpf compiler or nfsynproxy tool)])
|
||||
fi
|
||||
|
||||
if test "x$enable_nftables" = "xyes"; then
|
||||
PKG_CHECK_MODULES([libmnl], [libmnl >= 1.0], [mnl=1], [mnl=0])
|
||||
|
||||
if test "$mnl" = 0;
|
||||
then
|
||||
echo "*** Error: No suitable libmnl found. ***"
|
||||
echo " Please install the 'libmnl' package"
|
||||
echo " Or consider --disable-nftables to skip"
|
||||
echo " iptables-compat over nftables support."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES([libnftnl], [libnftnl >= 1.2.6], [nftables=1], [nftables=0])
|
||||
|
||||
if test "$nftables" = 0;
|
||||
then
|
||||
echo "*** Error: no suitable libnftnl found. ***"
|
||||
echo " Please install the 'libnftnl' package"
|
||||
echo " Or consider --disable-nftables to skip"
|
||||
echo " iptables-compat over nftables support."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([HAVE_LIBMNL], [test "$mnl" = 1])
|
||||
AM_CONDITIONAL([HAVE_LIBNFTNL], [test "$nftables" = 1])
|
||||
|
||||
if test "$nftables" != 1; then
|
||||
blacklist_b_modules="$blacklist_b_modules limit mark nflog mangle"
|
||||
blacklist_a_modules="$blacklist_a_modules mangle"
|
||||
fi
|
||||
|
||||
if test "x$enable_connlabel" = "xyes"; then
|
||||
PKG_CHECK_MODULES([libnetfilter_conntrack],
|
||||
[libnetfilter_conntrack >= 1.0.6],
|
||||
[nfconntrack=1], [nfconntrack=0])
|
||||
|
||||
if test "$nfconntrack" -ne 1; then
|
||||
blacklist_modules="$blacklist_modules connlabel";
|
||||
echo "WARNING: libnetfilter_conntrack not found, connlabel match will not be built";
|
||||
enable_connlabel="no";
|
||||
fi;
|
||||
else
|
||||
blacklist_modules="$blacklist_modules connlabel";
|
||||
fi;
|
||||
|
||||
AM_CONDITIONAL([HAVE_LIBNETFILTER_CONNTRACK], [test "$nfconntrack" = 1])
|
||||
|
||||
AC_SUBST([blacklist_modules])
|
||||
AC_SUBST([blacklist_x_modules])
|
||||
AC_SUBST([blacklist_b_modules])
|
||||
AC_SUBST([blacklist_a_modules])
|
||||
AC_SUBST([blacklist_4_modules])
|
||||
AC_SUBST([blacklist_6_modules])
|
||||
|
||||
regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
|
||||
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
|
||||
-Wlogical-op \
|
||||
-Winline -pipe";
|
||||
regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \
|
||||
-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL";
|
||||
kinclude_CPPFLAGS="";
|
||||
if [[ -n "$kbuilddir" ]]; then
|
||||
kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$kbuilddir/include/uapi -I$kbuilddir/include";
|
||||
fi;
|
||||
if [[ -n "$ksourcedir" ]]; then
|
||||
kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$ksourcedir/include/uapi -I$ksourcedir/include";
|
||||
fi;
|
||||
pkgdatadir='${datadir}/xtables';
|
||||
|
||||
if test "x$enable_profiling" = "xyes"; then
|
||||
regular_CFLAGS+=" -fprofile-arcs -ftest-coverage"
|
||||
regular_LDFLAGS+=" -lgcov --coverage"
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether the build is using musl-libc])
|
||||
enable_musl_build=""
|
||||
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[#include <netinet/if_ether.h>]],
|
||||
[[
|
||||
#if ! defined(__UAPI_DEF_ETHHDR) || __UAPI_DEF_ETHHDR != 0
|
||||
#error error trying musl...
|
||||
#endif
|
||||
]]
|
||||
)],
|
||||
[enable_musl_build="yes"],[enable_musl_build="no"]
|
||||
)
|
||||
AC_MSG_RESULT([${enable_musl_build}])
|
||||
|
||||
if test "x$enable_musl_build" = "xyes"; then
|
||||
regular_CFLAGS+=" -D__UAPI_DEF_ETHHDR=0"
|
||||
fi
|
||||
|
||||
define([EXPAND_VARIABLE],
|
||||
[$2=[$]$1
|
||||
if test $prefix = 'NONE'; then
|
||||
prefix="/usr/local"
|
||||
fi
|
||||
while true; do
|
||||
case "[$]$2" in
|
||||
*\[$]* ) eval "$2=[$]$2" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
eval "$2=[$]$2"
|
||||
])dnl EXPAND_VARIABLE
|
||||
|
||||
AC_SUBST([regular_CFLAGS])
|
||||
AC_SUBST([regular_CPPFLAGS])
|
||||
AC_SUBST([noundef_LDFLAGS])
|
||||
AC_SUBST([regular_LDFLAGS])
|
||||
AC_SUBST([kinclude_CPPFLAGS])
|
||||
AC_SUBST([kbuilddir])
|
||||
AC_SUBST([ksourcedir])
|
||||
AC_SUBST([xtlibdir])
|
||||
AC_SUBST([pkgconfigdir])
|
||||
AC_SUBST([pkgdatadir])
|
||||
AC_SUBST([libxtables_vcurrent])
|
||||
AC_SUBST([libxtables_vage])
|
||||
libxtables_vmajor=$(($libxtables_vcurrent - $libxtables_vage));
|
||||
AC_SUBST([libxtables_vmajor])
|
||||
|
||||
AC_DEFINE_UNQUOTED([XT_LOCK_NAME], "${xt_lock_name}",
|
||||
[Location of the iptables lock file])
|
||||
AC_SUBST([XT_LOCK_NAME], "${xt_lock_name}")
|
||||
|
||||
AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
|
||||
iptables/Makefile iptables/xtables.pc
|
||||
iptables/iptables.8 iptables/iptables-extensions.8.tmpl
|
||||
iptables/iptables-save.8 iptables/iptables-restore.8
|
||||
iptables/iptables-apply.8 iptables/iptables-xml.1
|
||||
libipq/Makefile libipq/libipq.pc
|
||||
libiptc/Makefile libiptc/libiptc.pc
|
||||
libiptc/libip4tc.pc libiptc/libip6tc.pc
|
||||
libxtables/Makefile utils/Makefile
|
||||
include/xtables-version.h
|
||||
iptables/xtables-monitor.8
|
||||
utils/nfnl_osf.8
|
||||
utils/nfbpf_compile.8])
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
EXPAND_VARIABLE(xtlibdir, e_xtlibdir)
|
||||
EXPAND_VARIABLE(pkgconfigdir, e_pkgconfigdir)
|
||||
|
||||
echo "
|
||||
Iptables Configuration:
|
||||
IPv4 support: ${enable_ipv4}
|
||||
IPv6 support: ${enable_ipv6}
|
||||
Devel support: ${enable_devel}
|
||||
IPQ support: ${enable_libipq}
|
||||
Large file support: ${enable_largefile}
|
||||
BPF utils support: ${enable_bpfc}
|
||||
nfsynproxy util support: ${enable_nfsynproxy}
|
||||
nftables support: ${enable_nftables}
|
||||
connlabel support: ${enable_connlabel}
|
||||
profiling support: ${enable_profiling}
|
||||
|
||||
Build parameters:
|
||||
Put plugins into executable (static): ${enable_static}
|
||||
Support plugins via dlopen (shared): ${enable_shared}
|
||||
Installation prefix (--prefix): ${prefix}
|
||||
Xtables extension directory: ${e_xtlibdir}
|
||||
Pkg-config directory: ${e_pkgconfigdir}
|
||||
Xtables lock file: ${xt_lock_name}
|
||||
Build against musl-libc: ${enable_musl_build}"
|
||||
|
||||
if [[ -n "$ksourcedir" ]]; then
|
||||
echo " Kernel source directory: ${ksourcedir}"
|
||||
fi;
|
||||
if [[ -n "$kbuilddir" ]]; then
|
||||
echo " Kernel build directory: ${kbuilddir}"
|
||||
fi;
|
||||
|
||||
echo " Host: ${host}
|
||||
GCC binary: ${CC}"
|
||||
|
||||
test x"$blacklist_modules" = "x" || echo "
|
||||
Iptables modules that will not be built: $blacklist_modules"
|
||||
@@ -1,35 +0,0 @@
|
||||
From 54c670ada541aa61ab9ab7907ab245718137efb8 Mon Sep 17 00:00:00 2001
|
||||
From: huangyu <huangyu106@huawei.com>
|
||||
Date: Sat, 26 Nov 2022 18:08:31 +0800
|
||||
Subject: [PATCH] enable makecheck in extensions
|
||||
|
||||
Signed-off-by: huangyu <huangyu106@huawei.com>
|
||||
---
|
||||
extensions/GNUmakefile.in | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
|
||||
index 956ccb3..70515c4 100644
|
||||
--- a/extensions/GNUmakefile.in
|
||||
+++ b/extensions/GNUmakefile.in
|
||||
@@ -79,7 +79,7 @@ targets_install :=
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
-.PHONY: all install uninstall clean distclean FORCE
|
||||
+.PHONY: all install uninstall check clean distclean FORCE
|
||||
|
||||
all: ${targets}
|
||||
|
||||
@@ -105,6 +105,8 @@ uninstall:
|
||||
rmdir -p --ignore-fail-on-non-empty "$$dir"; \
|
||||
}
|
||||
|
||||
+check:
|
||||
+
|
||||
clean:
|
||||
rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c initextb.c initexta.c;
|
||||
rm -f .*.d .*.dd;
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# Ethernet frame types
|
||||
# This file describes some of the various Ethernet
|
||||
# protocol types that are used on Ethernet networks.
|
||||
#
|
||||
# This list could be found on:
|
||||
# http://www.iana.org/assignments/ethernet-numbers
|
||||
# http://www.iana.org/assignments/ieee-802-numbers
|
||||
#
|
||||
# <name> <hexnumber> <alias1>...<alias35> #Comment
|
||||
#
|
||||
IPv4 0800 ip ip4 # Internet IP (IPv4)
|
||||
X25 0805
|
||||
ARP 0806 ether-arp #
|
||||
FR_ARP 0808 # Frame Relay ARP [RFC1701]
|
||||
BPQ 08FF # G8BPQ AX.25 Ethernet Packet
|
||||
DEC 6000 # DEC Assigned proto
|
||||
DNA_DL 6001 # DEC DNA Dump/Load
|
||||
DNA_RC 6002 # DEC DNA Remote Console
|
||||
DNA_RT 6003 # DEC DNA Routing
|
||||
LAT 6004 # DEC LAT
|
||||
DIAG 6005 # DEC Diagnostics
|
||||
CUST 6006 # DEC Customer use
|
||||
SCA 6007 # DEC Systems Comms Arch
|
||||
TEB 6558 # Trans Ether Bridging [RFC1701]
|
||||
RAW_FR 6559 # Raw Frame Relay [RFC1701]
|
||||
RARP 8035 # Reverse ARP [RFC903]
|
||||
AARP 80F3 # Appletalk AARP
|
||||
ATALK 809B # Appletalk
|
||||
802_1Q 8100 8021q 1q 802.1q dot1q # 802.1Q Virtual LAN tagged frame
|
||||
IPX 8137 # Novell IPX
|
||||
NetBEUI 8191 # NetBEUI
|
||||
IPv6 86DD ip6 # IP version 6
|
||||
PPP 880B # PPP
|
||||
ATMMPOA 884C # MultiProtocol over ATM
|
||||
PPP_DISC 8863 # PPPoE discovery messages
|
||||
PPP_SES 8864 # PPPoE session messages
|
||||
ATMFATE 8884 # Frame-based ATM Transport over Ethernet
|
||||
LOOP 9000 loopback # loop proto
|
||||
@@ -0,0 +1,266 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
top_builddir = @top_builddir@
|
||||
builddir = @builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
ksourcedir = @ksourcedir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
xtlibdir = @xtlibdir@
|
||||
|
||||
AR = @AR@
|
||||
CC = @CC@
|
||||
CCLD = ${CC}
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
regular_CFLAGS = @regular_CFLAGS@
|
||||
regular_CPPFLAGS = @regular_CPPFLAGS@
|
||||
kinclude_CPPFLAGS = @kinclude_CPPFLAGS@
|
||||
|
||||
AM_CFLAGS = ${regular_CFLAGS}
|
||||
AM_CPPFLAGS = ${regular_CPPFLAGS} \
|
||||
-I${top_builddir}/include \
|
||||
-I${top_builddir} \
|
||||
-I${top_srcdir}/include \
|
||||
-I${top_srcdir} \
|
||||
${kinclude_CPPFLAGS} \
|
||||
${CPPFLAGS} \
|
||||
@libnetfilter_conntrack_CFLAGS@ \
|
||||
@libnftnl_CFLAGS@
|
||||
AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
|
||||
AM_LDFLAGS = @noundef_LDFLAGS@ @regular_LDFLAGS@
|
||||
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
am__v_AR_0 = @echo " AR " $@;
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_LN_0 = @echo " LN " $@;
|
||||
am__v_AR_ = ${am__v_AR_@AM_DEFAULT_V@}
|
||||
am__v_CC_ = ${am__v_CC_@AM_DEFAULT_V@}
|
||||
am__v_CCLD_ = ${am__v_CCLD_@AM_DEFAULT_V@}
|
||||
am__v_GEN_ = ${am__v_GEN_@AM_DEFAULT_V@}
|
||||
am__v_LN_ = ${am__v_LN_@AM_DEFAULT_V@}
|
||||
AM_V_AR = ${am__v_AR_@AM_V@}
|
||||
AM_V_CC = ${am__v_CC_@AM_V@}
|
||||
AM_V_CCLD = ${am__v_CCLD_@AM_V@}
|
||||
AM_V_GEN = ${am__v_GEN_@AM_V@}
|
||||
AM_V_LN = ${am__v_LN_@AM_V@}
|
||||
|
||||
#
|
||||
# Wildcard module list
|
||||
#
|
||||
pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c)))
|
||||
@ENABLE_NFTABLES_TRUE@ pfb_build_mod := $(patsubst ${srcdir}/libebt_%.c,%,$(sort $(wildcard ${srcdir}/libebt_*.c)))
|
||||
@ENABLE_NFTABLES_TRUE@ pfa_build_mod := $(patsubst ${srcdir}/libarpt_%.c,%,$(sort $(wildcard ${srcdir}/libarpt_*.c)))
|
||||
pfx_symlinks := NOTRACK state REDIRECT MASQUERADE SNAT DNAT
|
||||
@ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c)))
|
||||
@ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c)))
|
||||
pfx_build_mod := $(filter-out @blacklist_modules@ @blacklist_x_modules@,${pfx_build_mod})
|
||||
pfb_build_mod := $(filter-out @blacklist_modules@ @blacklist_b_modules@,${pfb_build_mod})
|
||||
pfa_build_mod := $(filter-out @blacklist_modules@ @blacklist_a_modules@,${pfa_build_mod})
|
||||
pf4_build_mod := $(filter-out @blacklist_modules@ @blacklist_4_modules@,${pf4_build_mod})
|
||||
pf6_build_mod := $(filter-out @blacklist_modules@ @blacklist_6_modules@,${pf6_build_mod})
|
||||
pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod})
|
||||
pfb_objs := $(patsubst %,libebt_%.o,${pfb_build_mod})
|
||||
pfa_objs := $(patsubst %,libarpt_%.o,${pfa_build_mod})
|
||||
pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod})
|
||||
pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod})
|
||||
pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod})
|
||||
pfb_solibs := $(patsubst %,libebt_%.so,${pfb_build_mod})
|
||||
pfa_solibs := $(patsubst %,libarpt_%.so,${pfa_build_mod})
|
||||
pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod})
|
||||
pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
|
||||
pfx_symlink_files := $(patsubst %,libxt_%.so,${pfx_symlinks})
|
||||
|
||||
|
||||
#
|
||||
# Building blocks
|
||||
#
|
||||
targets := libext.a libext4.a libext6.a libext_ebt.a libext_arpt.a matches.man targets.man
|
||||
targets_install :=
|
||||
@ENABLE_STATIC_TRUE@ libext_objs := ${pfx_objs}
|
||||
@ENABLE_STATIC_TRUE@ libext_ebt_objs := ${pfb_objs}
|
||||
@ENABLE_STATIC_TRUE@ libext_arpt_objs := ${pfa_objs}
|
||||
@ENABLE_STATIC_TRUE@ libext4_objs := ${pf4_objs}
|
||||
@ENABLE_STATIC_TRUE@ libext6_objs := ${pf6_objs}
|
||||
@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs} ${pfx_symlink_files}
|
||||
@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs}
|
||||
@ENABLE_STATIC_FALSE@ symlinks_install := ${pfx_symlink_files}
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
.PHONY: all install uninstall clean distclean FORCE dvi check installcheck
|
||||
|
||||
all: ${targets}
|
||||
|
||||
install: ${targets_install} ${symlinks_install}
|
||||
@mkdir -p "${DESTDIR}${xtlibdir}";
|
||||
if test -n "${targets_install}"; then \
|
||||
install -pm0755 ${targets_install} "${DESTDIR}${xtlibdir}/"; \
|
||||
fi;
|
||||
if test -n "${symlinks_install}"; then \
|
||||
cp -P ${symlinks_install} "${DESTDIR}${xtlibdir}/"; \
|
||||
fi;
|
||||
|
||||
uninstall:
|
||||
dir=${DESTDIR}${xtlibdir}; { \
|
||||
test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; \
|
||||
} || { \
|
||||
test -z "${targets_install}" || ( \
|
||||
cd "$$dir" && rm -f ${targets_install} \
|
||||
); \
|
||||
test -z "${symlinks_install}" || ( \
|
||||
cd "$$dir" && rm -f ${symlinks_install} \
|
||||
); \
|
||||
rmdir -p --ignore-fail-on-non-empty "$$dir"; \
|
||||
}
|
||||
|
||||
clean:
|
||||
rm -f *.o *.oo *.so *.a matches.man targets.man
|
||||
rm -f initext.c initext4.c initext6.c initextb.c initexta.c
|
||||
rm -f .*.d .*.dd;
|
||||
|
||||
distclean: clean
|
||||
|
||||
init%.o: init%.c
|
||||
${AM_V_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
-include .*.d
|
||||
|
||||
|
||||
#
|
||||
# Shared libraries
|
||||
#
|
||||
lib%.so: lib%.oo
|
||||
${AM_V_CCLD} ${CCLD} ${AM_LDFLAGS} ${LDFLAGS} -shared -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD};
|
||||
|
||||
lib%.oo: ${srcdir}/lib%.c
|
||||
${AM_V_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
libxt_NOTRACK.so: libxt_CT.so
|
||||
${AM_V_LN} ln -fs $< $@
|
||||
libxt_state.so: libxt_conntrack.so
|
||||
${AM_V_LN} ln -fs $< $@
|
||||
libxt_REDIRECT.so: libxt_NAT.so
|
||||
${AM_V_LN} ln -fs $< $@
|
||||
libxt_MASQUERADE.so: libxt_NAT.so
|
||||
${AM_V_LN} ln -fs $< $@
|
||||
libxt_SNAT.so: libxt_NAT.so
|
||||
${AM_V_LN} ln -fs $< $@
|
||||
libxt_DNAT.so: libxt_NAT.so
|
||||
${AM_V_LN} ln -fs $< $@
|
||||
|
||||
# Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD
|
||||
xt_RATEEST_LIBADD = -lm
|
||||
xt_statistic_LIBADD = -lm
|
||||
xt_connlabel_LIBADD = @libnetfilter_conntrack_LIBS@
|
||||
|
||||
#
|
||||
# Static bits
|
||||
#
|
||||
# If static building is disabled, libext*.a will still be generated,
|
||||
# but will be empty. This is good since we can do with less case
|
||||
# handling code in the Makefiles.
|
||||
#
|
||||
lib%.o: ${srcdir}/lib%.c
|
||||
${AM_V_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
libext.a: initext.o ${libext_objs}
|
||||
${AM_V_AR} ${AR} crs $@ $^;
|
||||
|
||||
libext_ebt.a: initextb.o ${libext_ebt_objs}
|
||||
${AM_V_AR} ${AR} crs $@ $^;
|
||||
|
||||
libext_arpt.a: initexta.o ${libext_arpt_objs}
|
||||
${AM_V_AR} ${AR} crs $@ $^;
|
||||
|
||||
libext4.a: initext4.o ${libext4_objs}
|
||||
${AM_V_AR} ${AR} crs $@ $^;
|
||||
|
||||
libext6.a: initext6.o ${libext6_objs}
|
||||
${AM_V_AR} ${AR} crs $@ $^;
|
||||
|
||||
initext_func := $(addprefix xt_,${pfx_build_mod})
|
||||
initextb_func := $(addprefix ebt_,${pfb_build_mod})
|
||||
initexta_func := $(addprefix arpt_,${pfa_build_mod})
|
||||
initext4_func := $(addprefix ipt_,${pf4_build_mod})
|
||||
initext6_func := $(addprefix ip6t_,${pf6_build_mod})
|
||||
|
||||
initexts := ext exta extb ext4 ext6
|
||||
initext_depfiles = $(patsubst %,.init%.dd,${initexts})
|
||||
initext_sources = $(patsubst %,init%.c,${initexts})
|
||||
|
||||
${initext_depfiles}: FORCE
|
||||
@echo "$(value $(patsubst .%.dd,%,$@)_func)" >$@.tmp; \
|
||||
cmp -s $@ $@.tmp || mv $@.tmp $@; \
|
||||
rm -f $@.tmp;
|
||||
|
||||
${initext_sources}: %.c: .%.dd
|
||||
${AM_V_GEN}
|
||||
@( \
|
||||
initext_func="$(value $(basename $@)_func)"; \
|
||||
funcname="init_extensions$(patsubst initext%.c,%,$@)"; \
|
||||
echo "" >$@; \
|
||||
for i in $${initext_func}; do \
|
||||
echo "extern void lib$${i}_init(void);" >>$@; \
|
||||
done; \
|
||||
echo "void $${funcname}(void);" >>$@; \
|
||||
echo "void $${funcname}(void)" >>$@; \
|
||||
echo "{" >>$@; \
|
||||
for i in $${initext_func}; do \
|
||||
echo " ""lib$${i}_init();" >>$@; \
|
||||
done; \
|
||||
echo "}" >>$@; \
|
||||
);
|
||||
|
||||
#
|
||||
# Manual pages
|
||||
#
|
||||
ex_matches = $(shell echo ${1} | LC_ALL=POSIX grep -Eo '\b[[:lower:][:digit:]_]+\b')
|
||||
ex_targets = $(shell echo ${1} | LC_ALL=POSIX grep -Eo '\b[[:upper:][:digit:]_]+\b')
|
||||
man_run = \
|
||||
${AM_V_GEN} \
|
||||
for ext in $(sort ${1}); do \
|
||||
f="${srcdir}/libxt_$$ext.man"; \
|
||||
if [ -f "$$f" ]; then \
|
||||
printf "\t+ $$f\n" >&2; \
|
||||
echo ".SS $$ext"; \
|
||||
cat "$$f" || exit $$?; \
|
||||
fi; \
|
||||
f="${srcdir}/libip6t_$$ext.man"; \
|
||||
if [ -f "$$f" ]; then \
|
||||
printf "\t+ $$f\n" >&2; \
|
||||
echo ".SS $$ext (IPv6-specific)"; \
|
||||
cat "$$f" || exit $$?; \
|
||||
fi; \
|
||||
f="${srcdir}/libipt_$$ext.man"; \
|
||||
if [ -f "$$f" ]; then \
|
||||
printf "\t+ $$f\n" >&2; \
|
||||
echo ".SS $$ext (IPv4-specific)"; \
|
||||
cat "$$f" || exit $$?; \
|
||||
fi; \
|
||||
done >$@;
|
||||
|
||||
matches.man: ${initext_depfiles} $(wildcard ${srcdir}/lib*.man)
|
||||
$(call man_run,$(call ex_matches,${pfx_build_mod} ${pfb_build_mod} ${pfa_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
|
||||
|
||||
targets.man: ${initext_depfiles} $(wildcard ${srcdir}/lib*.man)
|
||||
$(call man_run,$(call ex_targets,${pfx_build_mod} ${pfb_build_mod} ${pfa_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
|
||||
|
||||
dist_initext_src = $(addprefix $(srcdir)/,${initext_sources})
|
||||
dist_sources = $(filter-out ${dist_initext_src},$(wildcard $(srcdir)/*.[ch]))
|
||||
|
||||
distdir:
|
||||
mkdir -p $(distdir)
|
||||
cp -p ${dist_sources} $(distdir)/
|
||||
cp -p $(wildcard ${srcdir}/lib*.man) $(distdir)/
|
||||
cp -p $(wildcard ${srcdir}/*.t ${srcdir}/*.txlate) $(distdir)/
|
||||
|
||||
dvi:
|
||||
check: all
|
||||
installcheck:
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* DiffServ classname <-> DiffServ codepoint mapping functions.
|
||||
*
|
||||
* The latest list of the mappings can be found at:
|
||||
* <http://www.iana.org/assignments/dscp-registry>
|
||||
*
|
||||
* This code is released under the GNU GPL v2, 1991
|
||||
*
|
||||
* Author: Iain Barnes
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
|
||||
|
||||
static const struct ds_class
|
||||
{
|
||||
const char *name;
|
||||
unsigned int dscp;
|
||||
} ds_classes[] =
|
||||
{
|
||||
{ "CS0", 0x00 },
|
||||
{ "CS1", 0x08 },
|
||||
{ "CS2", 0x10 },
|
||||
{ "CS3", 0x18 },
|
||||
{ "CS4", 0x20 },
|
||||
{ "CS5", 0x28 },
|
||||
{ "CS6", 0x30 },
|
||||
{ "CS7", 0x38 },
|
||||
{ "BE", 0x00 },
|
||||
{ "AF11", 0x0a },
|
||||
{ "AF12", 0x0c },
|
||||
{ "AF13", 0x0e },
|
||||
{ "AF21", 0x12 },
|
||||
{ "AF22", 0x14 },
|
||||
{ "AF23", 0x16 },
|
||||
{ "AF31", 0x1a },
|
||||
{ "AF32", 0x1c },
|
||||
{ "AF33", 0x1e },
|
||||
{ "AF41", 0x22 },
|
||||
{ "AF42", 0x24 },
|
||||
{ "AF43", 0x26 },
|
||||
{ "EF", 0x2e }
|
||||
};
|
||||
|
||||
|
||||
|
||||
static unsigned int
|
||||
class_to_dscp(const char *name)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ds_classes); i++) {
|
||||
if (!strncasecmp(name, ds_classes[i].name,
|
||||
strlen(ds_classes[i].name)))
|
||||
return ds_classes[i].dscp;
|
||||
}
|
||||
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid DSCP value `%s'", name);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static const char *
|
||||
dscp_to_name(unsigned int dscp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ds_classes); ++i)
|
||||
if (dscp == ds_classes[i].dscp)
|
||||
return ds_classes[i].name;
|
||||
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid DSCP value `%d'", dscp);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
arptables-translate -A OUTPUT --proto-type ipv4 -s 1.2.3.4 -j ACCEPT
|
||||
nft 'add rule arp filter OUTPUT arp htype 1 arp hlen 6 arp plen 4 arp ptype 0x800 arp saddr ip 1.2.3.4 counter accept'
|
||||
|
||||
arptables-translate -I OUTPUT -o oifname
|
||||
nft 'insert rule arp filter OUTPUT oifname "oifname" arp htype 1 arp hlen 6 arp plen 4 counter'
|
||||
|
||||
iptables-translate -I OUTPUT -p udp -d 8.8.8.8 -j ACCEPT
|
||||
nft 'insert rule ip filter OUTPUT ip protocol udp ip daddr 8.8.8.8 counter accept'
|
||||
|
||||
iptables-translate -F -t nat
|
||||
nft flush table ip nat
|
||||
|
||||
iptables-translate -I INPUT -i iifname -s 10.0.0.0/8
|
||||
nft 'insert rule ip filter INPUT iifname "iifname" ip saddr 10.0.0.0/8 counter'
|
||||
|
||||
iptables-translate -A INPUT -i iif+ ! -d 10.0.0.0/8
|
||||
nft 'add rule ip filter INPUT iifname "iif*" ip daddr != 10.0.0.0/8 counter'
|
||||
|
||||
iptables-translate -I INPUT -s 10.11.12.13/255.255.0.0
|
||||
nft 'insert rule ip filter INPUT ip saddr 10.11.0.0/16 counter'
|
||||
|
||||
iptables-translate -I INPUT -s 10.11.12.13/255.0.255.0
|
||||
nft 'insert rule ip filter INPUT ip saddr & 255.0.255.0 == 10.0.12.0 counter'
|
||||
|
||||
iptables-translate -I INPUT -s 10.11.12.13/0.255.0.255
|
||||
nft 'insert rule ip filter INPUT ip saddr & 0.255.0.255 == 0.11.0.13 counter'
|
||||
|
||||
iptables-translate -I INPUT ! -s 10.11.12.13/0.255.0.255
|
||||
nft 'insert rule ip filter INPUT ip saddr & 0.255.0.255 != 0.11.0.13 counter'
|
||||
|
||||
iptables-translate -I INPUT -s 0.0.0.0/16
|
||||
nft 'insert rule ip filter INPUT ip saddr 0.0.0.0/16 counter'
|
||||
|
||||
iptables-translate -I INPUT -s 0.0.0.0/0
|
||||
nft 'insert rule ip filter INPUT counter'
|
||||
|
||||
iptables-translate -I INPUT ! -s 0.0.0.0/0
|
||||
nft 'insert rule ip filter INPUT ip saddr != 0.0.0.0/0 counter'
|
||||
|
||||
ip6tables-translate -I INPUT -i iifname -s feed::/16
|
||||
nft 'insert rule ip6 filter INPUT iifname "iifname" ip6 saddr feed::/16 counter'
|
||||
|
||||
ip6tables-translate -A INPUT -i iif+ ! -d feed::/16
|
||||
nft 'add rule ip6 filter INPUT iifname "iif*" ip6 daddr != feed::/16 counter'
|
||||
|
||||
ip6tables-translate -I INPUT -s feed:babe::1/ffff:ff00::
|
||||
nft 'insert rule ip6 filter INPUT ip6 saddr feed:ba00::/24 counter'
|
||||
|
||||
ip6tables-translate -I INPUT -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/ffff:0:ffff:0:ffff:0:ffff:0
|
||||
nft 'insert rule ip6 filter INPUT ip6 saddr & ffff:0:ffff:0:ffff:0:ffff:0 == feed:0:c0ff:0:c0be:0:5678:0 counter'
|
||||
|
||||
ip6tables-translate -I INPUT -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/0:ffff:0:ffff:0:ffff:0:ffff
|
||||
nft 'insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff == 0:babe:0:ee00:0:1234:0:90ab counter'
|
||||
|
||||
ip6tables-translate -I INPUT ! -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/0:ffff:0:ffff:0:ffff:0:ffff
|
||||
nft 'insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff != 0:babe:0:ee00:0:1234:0:90ab counter'
|
||||
|
||||
ip6tables-translate -I INPUT -s ::/16
|
||||
nft 'insert rule ip6 filter INPUT ip6 saddr ::/16 counter'
|
||||
|
||||
ip6tables-translate -I INPUT -s ::/0
|
||||
nft 'insert rule ip6 filter INPUT counter'
|
||||
|
||||
ip6tables-translate -I INPUT ! -s ::/0
|
||||
nft 'insert rule ip6 filter INPUT ip6 saddr != ::/0 counter'
|
||||
|
||||
iptables-translate -A FORWARD -p 132
|
||||
nft 'add rule ip filter FORWARD ip protocol sctp counter'
|
||||
|
||||
ip6tables-translate -A FORWARD -p 132
|
||||
nft 'add rule ip6 filter FORWARD meta l4proto sctp counter'
|
||||
|
||||
iptables-translate -A FORWARD ! -p 132
|
||||
nft 'add rule ip filter FORWARD ip protocol != sctp counter'
|
||||
|
||||
ip6tables-translate -A FORWARD ! -p 132
|
||||
nft 'add rule ip6 filter FORWARD meta l4proto != sctp counter'
|
||||
|
||||
iptables-translate -A FORWARD -p 141
|
||||
nft 'add rule ip filter FORWARD ip protocol 141 counter'
|
||||
|
||||
ip6tables-translate -A FORWARD -p 141
|
||||
nft 'add rule ip6 filter FORWARD meta l4proto 141 counter'
|
||||
|
||||
iptables-translate -A FORWARD ! -p 141
|
||||
nft 'add rule ip filter FORWARD ip protocol != 141 counter'
|
||||
|
||||
ip6tables-translate -A FORWARD ! -p 141
|
||||
nft 'add rule ip6 filter FORWARD meta l4proto != 141 counter'
|
||||
|
||||
iptables-translate -A FORWARD -m tcp --dport 22 -p tcp
|
||||
nft 'add rule ip filter FORWARD tcp dport 22 counter'
|
||||
|
||||
ip6tables-translate -A FORWARD -m tcp --dport 22 -p tcp
|
||||
nft 'add rule ip6 filter FORWARD tcp dport 22 counter'
|
||||
|
||||
ebtables-translate -I INPUT -i iname --logical-in ilogname -s 0:0:0:0:0:0
|
||||
nft 'insert rule bridge filter INPUT iifname "iname" meta ibrname "ilogname" ether saddr 00:00:00:00:00:00 counter'
|
||||
|
||||
ebtables-translate -A FORWARD ! -i iname --logical-in ilogname -o out+ --logical-out lout+ -d 1:2:3:4:de:af
|
||||
nft 'add rule bridge filter FORWARD iifname != "iname" meta ibrname "ilogname" oifname "out*" meta obrname "lout*" ether daddr 01:02:03:04:de:af counter'
|
||||
|
||||
ebtables-translate -I INPUT -p ip -d 1:2:3:4:5:6/ff:ff:ff:ff:00:00
|
||||
nft 'insert rule bridge filter INPUT ether type 0x800 ether daddr and ff:ff:ff:ff:00:00 == 01:02:03:04:00:00 counter'
|
||||
|
||||
ebtables-translate -I INPUT -p Length
|
||||
nft 'insert rule bridge filter INPUT ether type < 0x0600 counter'
|
||||
|
||||
ebtables-translate -I INPUT -p ! Length
|
||||
nft 'insert rule bridge filter INPUT ether type >= 0x0600 counter'
|
||||
|
||||
# asterisk is not special in iptables and it is even a valid interface name
|
||||
iptables-translate -A FORWARD -i * -o eth*foo
|
||||
nft 'add rule ip filter FORWARD iifname "\*" oifname "eth*foo" counter'
|
||||
|
||||
# escape only suffix asterisk and translate only the last plus character
|
||||
iptables-translate -A FORWARD -i eth*foo*+ -o eth++
|
||||
nft 'add rule ip filter FORWARD iifname "eth*foo**" oifname "eth+*" counter'
|
||||
|
||||
# skip for always matching interface names
|
||||
iptables-translate -A FORWARD -i +
|
||||
nft 'add rule ip filter FORWARD counter'
|
||||
|
||||
# match against invalid interface name to simulate never matching rule
|
||||
iptables-translate -A FORWARD ! -i +
|
||||
nft 'add rule ip filter FORWARD iifname "INVAL/D" counter'
|
||||
@@ -0,0 +1,13 @@
|
||||
:FORWARD
|
||||
-i alongifacename0;=;OK
|
||||
-i thisinterfaceistoolong0;;FAIL
|
||||
-i eth+ -o alongifacename+;=;OK
|
||||
! -i eth0;=;OK
|
||||
! -o eth+;=;OK
|
||||
-i + -j ACCEPT;-j ACCEPT;OK
|
||||
! -i +;=;OK
|
||||
-c "";;FAIL
|
||||
-c ,3;;FAIL
|
||||
-c 3,;;FAIL
|
||||
-c ,;;FAIL
|
||||
-c 2,3 -j ACCEPT;-j ACCEPT;OK
|
||||
@@ -0,0 +1,4 @@
|
||||
:OUTPUT
|
||||
-o lo --destination-mac 11:22:33:44:55:66;-o lo --dst-mac 11:22:33:44:55:66;OK
|
||||
--dst-mac Broadcast ;--dst-mac ff:ff:ff:ff:ff:ff;OK
|
||||
! -o eth+ -d 1.2.3.4/24 -j CLASSIFY --set-class 0:0;-j CLASSIFY ! -o eth+ -d 1.2.3.0/24 --set-class 0:0;OK
|
||||
@@ -0,0 +1,4 @@
|
||||
:INPUT,OUTPUT
|
||||
-j MARK -d 0.0.0.0/8 --set-mark 1;=;OK
|
||||
-s ! 0.0.0.0 -j MARK --and-mark 0x17;-j MARK ! -s 0.0.0.0 --and-mark 17;OK
|
||||
-j MARK -s 0.0.0.0 --or-mark 17;=;OK
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Arturo Borrero Gonzalez <arturo@debian.org> adapted
|
||||
* this code to libxtables for arptables-compat in 2015
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <getopt.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_arp/arpt_mangle.h>
|
||||
#include "iptables/nft.h"
|
||||
|
||||
static void arpmangle_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"mangle target options:\n"
|
||||
"--mangle-ip-s IP address\n"
|
||||
"--mangle-ip-d IP address\n"
|
||||
"--mangle-mac-s MAC address\n"
|
||||
"--mangle-mac-d MAC address\n"
|
||||
"--mangle-target target (DROP, CONTINUE or ACCEPT -- default is ACCEPT)\n");
|
||||
}
|
||||
|
||||
/* internal use only, explicitly not covered by ARPT_MANGLE_MASK */
|
||||
#define ARPT_MANGLE_TARGET 0x10
|
||||
|
||||
static const struct xt_option_entry arpmangle_opts[] = {
|
||||
{ .name = "mangle-ip-s", .id = ARPT_MANGLE_SIP, .type = XTTYPE_HOSTMASK },
|
||||
{ .name = "mangle-ip-d", .id = ARPT_MANGLE_TIP, .type = XTTYPE_HOSTMASK },
|
||||
{ .name = "mangle-mac-s", .id = ARPT_MANGLE_SDEV, .type = XTTYPE_ETHERMAC },
|
||||
{ .name = "mangle-mac-d", .id = ARPT_MANGLE_TDEV, .type = XTTYPE_ETHERMAC },
|
||||
{ .name = "mangle-target", .id = ARPT_MANGLE_TARGET, .type = XTTYPE_STRING },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void arpmangle_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct arpt_mangle *mangle = (struct arpt_mangle *)target->data;
|
||||
|
||||
mangle->target = NF_ACCEPT;
|
||||
}
|
||||
|
||||
static void assert_hopts(const struct arpt_entry *e, const char *optname)
|
||||
{
|
||||
if (e->arp.arhln_mask == 0)
|
||||
xtables_error(PARAMETER_PROBLEM, "no --h-length defined");
|
||||
if (e->arp.invflags & IPT_INV_ARPHLN)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"! hln not allowed for --%s", optname);
|
||||
if (e->arp.arhln != 6)
|
||||
xtables_error(PARAMETER_PROBLEM, "only --h-length 6 supported");
|
||||
}
|
||||
|
||||
static void arpmangle_parse(struct xt_option_call *cb)
|
||||
{
|
||||
const struct arpt_entry *e = cb->xt_entry;
|
||||
struct arpt_mangle *mangle = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
mangle->flags |= (cb->entry->id & ARPT_MANGLE_MASK);
|
||||
switch (cb->entry->id) {
|
||||
case ARPT_MANGLE_SIP:
|
||||
mangle->u_s.src_ip = cb->val.haddr.in;
|
||||
break;
|
||||
case ARPT_MANGLE_TIP:
|
||||
mangle->u_t.tgt_ip = cb->val.haddr.in;
|
||||
break;
|
||||
case ARPT_MANGLE_SDEV:
|
||||
assert_hopts(e, cb->entry->name);
|
||||
memcpy(mangle->src_devaddr, cb->val.ethermac, ETH_ALEN);
|
||||
case ARPT_MANGLE_TDEV:
|
||||
assert_hopts(e, cb->entry->name);
|
||||
memcpy(mangle->tgt_devaddr, cb->val.ethermac, ETH_ALEN);
|
||||
break;
|
||||
case ARPT_MANGLE_TARGET:
|
||||
if (!strcmp(cb->arg, "DROP"))
|
||||
mangle->target = NF_DROP;
|
||||
else if (!strcmp(cb->arg, "ACCEPT"))
|
||||
mangle->target = NF_ACCEPT;
|
||||
else if (!strcmp(cb->arg, "CONTINUE"))
|
||||
mangle->target = XT_CONTINUE;
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"bad target for --mangle-target");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ipaddr_to(const struct in_addr *addrp, int numeric)
|
||||
{
|
||||
if (numeric)
|
||||
return xtables_ipaddr_to_numeric(addrp);
|
||||
else
|
||||
return xtables_ipaddr_to_anyname(addrp);
|
||||
}
|
||||
|
||||
static void
|
||||
arpmangle_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct arpt_mangle *m = (struct arpt_mangle *)(target->data);
|
||||
|
||||
if (m->flags & ARPT_MANGLE_SIP) {
|
||||
printf(" --mangle-ip-s %s",
|
||||
ipaddr_to(&(m->u_s.src_ip), numeric));
|
||||
}
|
||||
if (m->flags & ARPT_MANGLE_SDEV) {
|
||||
printf(" --mangle-mac-s ");
|
||||
xtables_print_mac((unsigned char *)m->src_devaddr);
|
||||
}
|
||||
if (m->flags & ARPT_MANGLE_TIP) {
|
||||
printf(" --mangle-ip-d %s",
|
||||
ipaddr_to(&(m->u_t.tgt_ip), numeric));
|
||||
}
|
||||
if (m->flags & ARPT_MANGLE_TDEV) {
|
||||
printf(" --mangle-mac-d ");
|
||||
xtables_print_mac((unsigned char *)m->tgt_devaddr);
|
||||
}
|
||||
if (m->target != NF_ACCEPT) {
|
||||
printf(" --mangle-target %s",
|
||||
m->target == NF_DROP ? "DROP" : "CONTINUE");
|
||||
}
|
||||
}
|
||||
|
||||
static void arpmangle_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
arpmangle_print(ip, target, 0);
|
||||
}
|
||||
|
||||
static void print_devaddr_xlate(const char *macaddress, struct xt_xlate *xl)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
xt_xlate_add(xl, "%02x", macaddress[0]);
|
||||
for (i = 1; i < ETH_ALEN; ++i)
|
||||
xt_xlate_add(xl, ":%02x", macaddress[i]);
|
||||
}
|
||||
|
||||
static int arpmangle_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_tg_params *params)
|
||||
{
|
||||
const struct arpt_mangle *m = (const void *)params->target->data;
|
||||
|
||||
if (m->flags & ARPT_MANGLE_SIP)
|
||||
xt_xlate_add(xl, "arp saddr ip set %s ",
|
||||
xtables_ipaddr_to_numeric(&m->u_s.src_ip));
|
||||
|
||||
if (m->flags & ARPT_MANGLE_SDEV) {
|
||||
xt_xlate_add(xl, "arp %caddr ether set ", 's');
|
||||
print_devaddr_xlate(m->src_devaddr, xl);
|
||||
}
|
||||
|
||||
if (m->flags & ARPT_MANGLE_TIP)
|
||||
xt_xlate_add(xl, "arp daddr ip set %s ",
|
||||
xtables_ipaddr_to_numeric(&m->u_t.tgt_ip));
|
||||
|
||||
if (m->flags & ARPT_MANGLE_TDEV) {
|
||||
xt_xlate_add(xl, "arp %caddr ether set ", 'd');
|
||||
print_devaddr_xlate(m->tgt_devaddr, xl);
|
||||
}
|
||||
|
||||
switch (m->target) {
|
||||
case NF_ACCEPT:
|
||||
xt_xlate_add(xl, "accept");
|
||||
break;
|
||||
case NF_DROP:
|
||||
xt_xlate_add(xl, "drop");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_target arpmangle_target = {
|
||||
.name = "mangle",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_ARP,
|
||||
.size = XT_ALIGN(sizeof(struct arpt_mangle)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct arpt_mangle)),
|
||||
.help = arpmangle_print_help,
|
||||
.init = arpmangle_init,
|
||||
.x6_parse = arpmangle_parse,
|
||||
.print = arpmangle_print,
|
||||
.save = arpmangle_save,
|
||||
.x6_options = arpmangle_opts,
|
||||
.xlate = arpmangle_xlate,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&arpmangle_target);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
:OUTPUT
|
||||
-j mangle -s 1.2.3.4 --mangle-ip-s 1.2.3.5;=;OK
|
||||
-j mangle -d 1.2.3.4 --mangle-ip-d 1.2.3.5;=;OK
|
||||
-j mangle -d 1.2.3.4 --mangle-mac-d 00:01:02:03:04:05;=;OK
|
||||
-d 1.2.3.4 --h-length 5 -j mangle --mangle-mac-s 00:01:02:03:04:05;=;FAIL
|
||||
-j mangle --mangle-ip-s 1.2.3.4 --mangle-target DROP;=;OK
|
||||
-j mangle --mangle-ip-s 1.2.3.4 --mangle-target ACCEPT;-j mangle --mangle-ip-s 1.2.3.4;OK
|
||||
-j mangle --mangle-ip-s 1.2.3.4 --mangle-target CONTINUE;=;OK
|
||||
-j mangle --mangle-ip-s 1.2.3.4 --mangle-target FOO;=;FAIL
|
||||
@@ -0,0 +1,6 @@
|
||||
arptables-translate -A OUTPUT -d 10.21.22.129 -j mangle --mangle-ip-s 10.21.22.161
|
||||
nft 'add rule arp filter OUTPUT arp htype 1 arp hlen 6 arp plen 4 arp daddr ip 10.21.22.129 counter arp saddr ip set 10.21.22.161 accept'
|
||||
arptables-translate -A OUTPUT -d 10.2.22.129/24 -j mangle --mangle-ip-d 10.2.22.1 --mangle-target CONTINUE
|
||||
nft 'add rule arp filter OUTPUT arp htype 1 arp hlen 6 arp plen 4 arp daddr ip 10.2.22.0/24 counter arp daddr ip set 10.2.22.1'
|
||||
arptables-translate -A OUTPUT -d 10.2.22.129/24 -j mangle --mangle-ip-d 10.2.22.1 --mangle-mac-d a:b:c:d:e:f
|
||||
nft 'add rule arp filter OUTPUT arp htype 1 arp hlen 6 arp plen 4 arp daddr ip 10.2.22.0/24 counter arp daddr ip set 10.2.22.1 arp daddr ether set 0a:0b:0c:0d:0e:0f accept'
|
||||
@@ -0,0 +1,25 @@
|
||||
:INPUT
|
||||
-s 192.168.0.1;=;OK
|
||||
-s 0.0.0.0/8;=;OK
|
||||
-s ! 0.0.0.0;! -s 0.0.0.0;OK
|
||||
-d 192.168.0.1;=;OK
|
||||
! -d 0.0.0.0;=;OK
|
||||
-d 0.0.0.0/24;=;OK
|
||||
-j DROP -i lo;=;OK
|
||||
-j ACCEPT ! -i lo;=;OK
|
||||
-i ppp+;=;OK
|
||||
! -i ppp+;=;OK
|
||||
-i + -j ACCEPT;-j ACCEPT;OK
|
||||
! -i +;=;OK
|
||||
-i lo --destination-mac 11:22:33:44:55:66;-i lo --dst-mac 11:22:33:44:55:66;OK
|
||||
--source-mac Unicast;--src-mac 00:00:00:00:00:00/01:00:00:00:00:00;OK
|
||||
! --src-mac Multicast;! --src-mac 01:00:00:00:00:00/01:00:00:00:00:00;OK
|
||||
--src-mac=01:02:03:04:05:06 --dst-mac=07:08:09:0A:0B:0C --h-length=6 --opcode=Request --h-type=Ethernet --proto-type=ipv4;--src-mac 01:02:03:04:05:06 --dst-mac 07:08:09:0a:0b:0c --opcode 1 --proto-type 0x800;OK
|
||||
--src-mac ! 01:02:03:04:05:06 --dst-mac ! 07:08:09:0A:0B:0C --h-length ! 6 --opcode ! Request --h-type ! Ethernet --proto-type ! ipv4;! --src-mac 01:02:03:04:05:06 ! --dst-mac 07:08:09:0a:0b:0c ! --h-length 6 ! --opcode 1 ! --h-type 0x1 ! --proto-type 0x800;OK
|
||||
--h-type 10;--h-type 0x10;OK
|
||||
--h-type 0x10;=;OK
|
||||
--proto-type 10;--proto-type 0xa;OK
|
||||
--proto-type 10/10;--proto-type 0xa/0xa;OK
|
||||
--proto-type 0x10;=;OK
|
||||
--proto-type 0x10/0x10;=;OK
|
||||
--h-length 6/15 --opcode 1/235 --h-type 0x8/0xcf --proto-type 0x800/0xde00;=;OK
|
||||
@@ -0,0 +1,86 @@
|
||||
/* 802_3
|
||||
*
|
||||
* Author:
|
||||
* Chris Vitale <csv@bluetail.com>
|
||||
*
|
||||
* May 2003
|
||||
*
|
||||
* Adapted by Arturo Borrero Gonzalez <arturo@debian.org>
|
||||
* to use libxtables for ebtables-compat
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_802_3.h>
|
||||
|
||||
static const struct xt_option_entry br802_3_opts[] =
|
||||
{
|
||||
{ .name = "802_3-sap", .id = EBT_802_3_SAP,
|
||||
.type = XTTYPE_UINT8, .base = 16,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_802_3_info, sap) },
|
||||
{ .name = "802_3-type", .id = EBT_802_3_TYPE,
|
||||
.type = XTTYPE_UINT16, .base = 16,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT | XTOPT_NBO,
|
||||
XTOPT_POINTER(struct ebt_802_3_info, type) },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void br802_3_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"802_3 options:\n"
|
||||
"[!] --802_3-sap protocol : 802.3 DSAP/SSAP- 1 byte value (hex)\n"
|
||||
" DSAP and SSAP are always the same. One SAP applies to both fields\n"
|
||||
"[!] --802_3-type protocol : 802.3 SNAP Type- 2 byte value (hex)\n"
|
||||
" Type implies SAP value 0xaa\n");
|
||||
}
|
||||
|
||||
static void br802_3_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_802_3_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
info->bitmask |= cb->entry->id;
|
||||
if (cb->invert)
|
||||
info->invflags |= cb->entry->id;
|
||||
}
|
||||
|
||||
static void br802_3_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data;
|
||||
|
||||
if (info->bitmask & EBT_802_3_SAP) {
|
||||
if (info->invflags & EBT_802_3_SAP)
|
||||
printf("! ");
|
||||
printf("--802_3-sap 0x%.2x ", info->sap);
|
||||
}
|
||||
if (info->bitmask & EBT_802_3_TYPE) {
|
||||
if (info->invflags & EBT_802_3_TYPE)
|
||||
printf("! ");
|
||||
printf("--802_3-type 0x%.4x ", ntohs(info->type));
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_match br802_3_match =
|
||||
{
|
||||
.name = "802_3",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_802_3_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_802_3_info)),
|
||||
.help = br802_3_print_help,
|
||||
.x6_parse = br802_3_parse,
|
||||
.print = br802_3_print,
|
||||
.x6_options = br802_3_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&br802_3_match);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
! --802_3-sap 0x0a -j CONTINUE;=;FAIL
|
||||
--802_3-type 0x000a -j RETURN;=;FAIL
|
||||
-p Length --802_3-sap 0x0a -j CONTINUE;=;OK
|
||||
-p Length ! --802_3-sap 0x0a -j CONTINUE;=;OK
|
||||
-p Length --802_3-type 0x000a -j RETURN;=;OK
|
||||
-p Length ! --802_3-type 0x000a -j RETURN;=;OK
|
||||
@@ -0,0 +1,241 @@
|
||||
/* ebt_among
|
||||
*
|
||||
* Authors:
|
||||
* Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
|
||||
*
|
||||
* August, 2003
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <xtables.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/netfilter_bridge/ebt_among.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
#define AMONG_DST '1'
|
||||
#define AMONG_SRC '2'
|
||||
#define AMONG_DST_F '3'
|
||||
#define AMONG_SRC_F '4'
|
||||
|
||||
static const struct option bramong_opts[] = {
|
||||
{"among-dst", required_argument, 0, AMONG_DST},
|
||||
{"among-src", required_argument, 0, AMONG_SRC},
|
||||
{"among-dst-file", required_argument, 0, AMONG_DST_F},
|
||||
{"among-src-file", required_argument, 0, AMONG_SRC_F},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void bramong_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"`among' options:\n"
|
||||
"[!] --among-dst list : matches if ether dst is in list\n"
|
||||
"[!] --among-src list : matches if ether src is in list\n"
|
||||
"[!] --among-dst-file file : obtain dst list from file\n"
|
||||
"[!] --among-src-file file : obtain src list from file\n"
|
||||
"list has form:\n"
|
||||
" xx:xx:xx:xx:xx:xx[=ip.ip.ip.ip],yy:yy:yy:yy:yy:yy[=ip.ip.ip.ip]"
|
||||
",...,zz:zz:zz:zz:zz:zz[=ip.ip.ip.ip][,]\n"
|
||||
"Things in brackets are optional.\n"
|
||||
"If you want to allow two (or more) IP addresses to one MAC address, you\n"
|
||||
"can specify two (or more) pairs with the same MAC, e.g.\n"
|
||||
" 00:00:00:fa:eb:fe=153.19.120.250,00:00:00:fa:eb:fe=192.168.0.1\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_nft_among_pair(char *buf, struct nft_among_pair *pair, bool have_ip)
|
||||
{
|
||||
char *sep = index(buf, '=');
|
||||
struct ether_addr *ether;
|
||||
|
||||
if (sep) {
|
||||
*sep = '\0';
|
||||
|
||||
if (!inet_pton(AF_INET, sep + 1, &pair->in))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid IP address '%s'", sep + 1);
|
||||
}
|
||||
ether = ether_aton(buf);
|
||||
if (!ether)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid MAC address '%s'", buf);
|
||||
memcpy(&pair->ether, ether, sizeof(*ether));
|
||||
}
|
||||
|
||||
static void
|
||||
parse_nft_among_pairs(struct nft_among_pair *pairs, char *buf,
|
||||
size_t cnt, bool have_ip)
|
||||
{
|
||||
size_t tmpcnt = 0;
|
||||
|
||||
buf = strtok(buf, ",");
|
||||
while (buf) {
|
||||
struct nft_among_pair pair = {};
|
||||
|
||||
parse_nft_among_pair(buf, &pair, have_ip);
|
||||
nft_among_insert_pair(pairs, &tmpcnt, &pair);
|
||||
buf = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
static size_t count_nft_among_pairs(char *buf)
|
||||
{
|
||||
size_t cnt = 0;
|
||||
char *p = buf;
|
||||
|
||||
if (!*buf)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
cnt++;
|
||||
p = index(++p, ',');
|
||||
} while (p);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static bool nft_among_pairs_have_ip(char *buf)
|
||||
{
|
||||
return !!index(buf, '=');
|
||||
}
|
||||
|
||||
static int bramong_parse(int c, char **argv, int invert,
|
||||
unsigned int *flags, const void *entry,
|
||||
struct xt_entry_match **match)
|
||||
{
|
||||
struct nft_among_data *data = (struct nft_among_data *)(*match)->data;
|
||||
bool have_ip, dst = false;
|
||||
size_t new_size, cnt;
|
||||
struct stat stats;
|
||||
int fd = -1, poff;
|
||||
long flen = 0;
|
||||
|
||||
switch (c) {
|
||||
case AMONG_DST_F:
|
||||
dst = true;
|
||||
/* fall through */
|
||||
case AMONG_SRC_F:
|
||||
if ((fd = open(optarg, O_RDONLY)) == -1)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Couldn't open file '%s'", optarg);
|
||||
if (fstat(fd, &stats) < 0)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"fstat(%s) failed: '%s'",
|
||||
optarg, strerror(errno));
|
||||
flen = stats.st_size;
|
||||
/* use mmap because the file will probably be big */
|
||||
optarg = mmap(0, flen, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE, fd, 0);
|
||||
if (optarg == MAP_FAILED)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Couldn't map file to memory");
|
||||
if (optarg[flen-1] != '\n')
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"File should end with a newline");
|
||||
if (strchr(optarg, '\n') != optarg+flen-1)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"File should only contain one line");
|
||||
optarg[flen-1] = '\0';
|
||||
break;
|
||||
case AMONG_DST:
|
||||
dst = true;
|
||||
/* fall through */
|
||||
case AMONG_SRC:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
cnt = count_nft_among_pairs(optarg);
|
||||
if (cnt == 0)
|
||||
return 0;
|
||||
|
||||
new_size = data->src.cnt + data->dst.cnt + cnt;
|
||||
new_size *= sizeof(struct nft_among_pair);
|
||||
new_size += XT_ALIGN(sizeof(struct xt_entry_match)) +
|
||||
sizeof(struct nft_among_data);
|
||||
|
||||
if (new_size > (*match)->u.match_size) {
|
||||
*match = xtables_realloc(*match, new_size);
|
||||
(*match)->u.match_size = new_size;
|
||||
data = (struct nft_among_data *)(*match)->data;
|
||||
}
|
||||
|
||||
have_ip = nft_among_pairs_have_ip(optarg);
|
||||
poff = nft_among_prepare_data(data, dst, cnt, invert, have_ip);
|
||||
parse_nft_among_pairs(data->pairs + poff, optarg, cnt, have_ip);
|
||||
|
||||
if (c == AMONG_DST_F || c == AMONG_SRC_F) {
|
||||
munmap(argv, flen);
|
||||
close(fd);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void __bramong_print(struct nft_among_pair *pairs,
|
||||
int cnt, bool have_ip)
|
||||
{
|
||||
char abuf[INET_ADDRSTRLEN];
|
||||
const char *isep = "";
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
printf("%s", isep);
|
||||
isep = ",";
|
||||
|
||||
printf("%s", ether_ntoa(&pairs[i].ether));
|
||||
if (pairs[i].in.s_addr != INADDR_ANY)
|
||||
printf("=%s", inet_ntop(AF_INET, &pairs[i].in,
|
||||
abuf, sizeof(abuf)));
|
||||
}
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static void bramong_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct nft_among_data *data = (struct nft_among_data *)match->data;
|
||||
|
||||
if (data->src.cnt) {
|
||||
printf("%s--among-src ", data->src.inv ? "! " : "");
|
||||
__bramong_print(data->pairs, data->src.cnt, data->src.ip);
|
||||
}
|
||||
if (data->dst.cnt) {
|
||||
printf("%s--among-dst ", data->dst.inv ? "! " : "");
|
||||
__bramong_print(data->pairs + data->src.cnt,
|
||||
data->dst.cnt, data->dst.ip);
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_match bramong_match = {
|
||||
.name = "among",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct nft_among_data)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nft_among_data)),
|
||||
.help = bramong_print_help,
|
||||
.parse = bramong_parse,
|
||||
.print = bramong_print,
|
||||
.extra_opts = bramong_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&bramong_match);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
--among-dst de:ad:0:be:ee:ff,c0:ff:ee:0:ba:be;--among-dst c0:ff:ee:0:ba:be,de:ad:0:be:ee:ff;OK
|
||||
! --among-dst c0:ff:ee:0:ba:be,de:ad:0:be:ee:ff;=;OK
|
||||
--among-src be:ef:0:c0:ff:ee,c0:ff:ee:0:ba:be,de:ad:0:be:ee:ff;=;OK
|
||||
--among-src de:ad:0:be:ee:ff=10.0.0.1,c0:ff:ee:0:ba:be=192.168.1.1;--among-src c0:ff:ee:0:ba:be=192.168.1.1,de:ad:0:be:ee:ff=10.0.0.1;OK
|
||||
! --among-src c0:ff:ee:0:ba:be=192.168.1.1,de:ad:0:be:ee:ff=10.0.0.1;=;OK
|
||||
--among-src de:ad:0:be:ee:ff --among-dst c0:ff:ee:0:ba:be;=;OK
|
||||
--among-src de:ad:0:be:ee:ff=10.0.0.1 --among-dst c0:ff:ee:0:ba:be=192.168.1.1;=;OK
|
||||
! --among-src de:ad:0:be:ee:ff --among-dst c0:ff:ee:0:ba:be;=;OK
|
||||
--among-src de:ad:0:be:ee:ff=10.0.0.1 ! --among-dst c0:ff:ee:0:ba:be=192.168.1.1;=;OK
|
||||
! --among-src de:ad:0:be:ee:ff --among-dst c0:ff:ee:0:ba:be=192.168.1.1;=;OK
|
||||
--among-src de:ad:0:be:ee:ff=10.0.0.1 ! --among-dst c0:ff:ee:0:ba:be=192.168.1.1;=;OK
|
||||
--among-src;=;FAIL
|
||||
--among-src 00:11=10.0.0.1;=;FAIL
|
||||
--among-src de:ad:0:be:ee:ff=10.256.0.1;=;FAIL
|
||||
--among-src c0:ff:ee:0:ba:be=192.168.1.1,de:ad:0:be:ee:ff;=;OK
|
||||
@@ -0,0 +1,230 @@
|
||||
/* ebt_arp
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
* Tim Gardner <timg@tpi.com>
|
||||
*
|
||||
* April, 2002
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <netinet/ether.h>
|
||||
|
||||
#include <xtables.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <linux/netfilter_bridge/ebt_arp.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
/* values must correspond with EBT_ARP_* bit positions */
|
||||
enum {
|
||||
O_OPCODE = 0,
|
||||
O_HTYPE,
|
||||
O_PTYPE,
|
||||
O_SRC_IP,
|
||||
O_DST_IP,
|
||||
O_SRC_MAC,
|
||||
O_DST_MAC,
|
||||
O_GRAT,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brarp_opts[] = {
|
||||
#define ENTRY(n, i, t) { .name = n, .id = i, .type = t, .flags = XTOPT_INVERT }
|
||||
ENTRY("arp-opcode", O_OPCODE, XTTYPE_STRING),
|
||||
ENTRY("arp-op", O_OPCODE, XTTYPE_STRING),
|
||||
ENTRY("arp-htype", O_HTYPE, XTTYPE_STRING),
|
||||
ENTRY("arp-ptype", O_PTYPE, XTTYPE_STRING),
|
||||
ENTRY("arp-ip-src", O_SRC_IP, XTTYPE_HOSTMASK),
|
||||
ENTRY("arp-ip-dst", O_DST_IP, XTTYPE_HOSTMASK),
|
||||
ENTRY("arp-mac-src", O_SRC_MAC, XTTYPE_ETHERMACMASK),
|
||||
ENTRY("arp-mac-dst", O_DST_MAC, XTTYPE_ETHERMACMASK),
|
||||
ENTRY("arp-gratuitous", O_GRAT, XTTYPE_NONE),
|
||||
#undef ENTRY
|
||||
XTOPT_TABLEEND
|
||||
};
|
||||
|
||||
/* a few names */
|
||||
static char *opcodes[] =
|
||||
{
|
||||
"Request",
|
||||
"Reply",
|
||||
"Request_Reverse",
|
||||
"Reply_Reverse",
|
||||
"DRARP_Request",
|
||||
"DRARP_Reply",
|
||||
"DRARP_Error",
|
||||
"InARP_Request",
|
||||
"ARP_NAK",
|
||||
};
|
||||
|
||||
static void brarp_print_help(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(
|
||||
"arp options:\n"
|
||||
"[!] --arp-opcode opcode : ARP opcode (integer or string)\n"
|
||||
"[!] --arp-htype type : ARP hardware type (integer or string)\n"
|
||||
"[!] --arp-ptype type : ARP protocol type (hexadecimal or string)\n"
|
||||
"[!] --arp-ip-src address[/mask]: ARP IP source specification\n"
|
||||
"[!] --arp-ip-dst address[/mask]: ARP IP target specification\n"
|
||||
"[!] --arp-mac-src address[/mask]: ARP MAC source specification\n"
|
||||
"[!] --arp-mac-dst address[/mask]: ARP MAC target specification\n"
|
||||
"[!] --arp-gratuitous : ARP gratuitous packet\n"
|
||||
" opcode strings: \n");
|
||||
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
|
||||
printf(" %d = %s\n", i + 1, opcodes[i]);
|
||||
printf(
|
||||
" hardware type string: 1 = Ethernet\n"
|
||||
" protocol type string: see "XT_PATH_ETHERTYPES"\n");
|
||||
}
|
||||
|
||||
static void brarp_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_arp_info *arpinfo = cb->data;
|
||||
struct xt_ethertypeent *ent;
|
||||
long int i;
|
||||
char *end;
|
||||
|
||||
|
||||
xtables_option_parse(cb);
|
||||
|
||||
arpinfo->bitmask |= 1 << cb->entry->id;
|
||||
if (cb->invert)
|
||||
arpinfo->invflags |= 1 << cb->entry->id;
|
||||
|
||||
switch (cb->entry->id) {
|
||||
case O_OPCODE:
|
||||
i = strtol(cb->arg, &end, 10);
|
||||
if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
|
||||
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
|
||||
if (!strcasecmp(opcodes[i], cb->arg))
|
||||
break;
|
||||
if (i == ARRAY_SIZE(opcodes))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Problem with specified ARP opcode");
|
||||
i++;
|
||||
}
|
||||
arpinfo->opcode = htons(i);
|
||||
break;
|
||||
case O_HTYPE:
|
||||
i = strtol(cb->arg, &end, 10);
|
||||
if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
|
||||
if (!strcasecmp("Ethernet", cb->arg))
|
||||
i = 1;
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Problem with specified ARP hardware type");
|
||||
}
|
||||
arpinfo->htype = htons(i);
|
||||
break;
|
||||
case O_PTYPE:
|
||||
i = strtol(cb->arg, &end, 16);
|
||||
if (i >= 0 && i < (0x1 << 16) && *end == '\0') {
|
||||
arpinfo->ptype = htons(i);
|
||||
break;
|
||||
}
|
||||
ent = xtables_getethertypebyname(cb->arg);
|
||||
if (!ent)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Problem with specified ARP protocol type");
|
||||
arpinfo->ptype = htons(ent->e_ethertype);
|
||||
break;
|
||||
case O_SRC_IP:
|
||||
arpinfo->saddr = cb->val.haddr.ip & cb->val.hmask.ip;
|
||||
arpinfo->smsk = cb->val.hmask.ip;
|
||||
break;
|
||||
case O_DST_IP:
|
||||
arpinfo->daddr = cb->val.haddr.ip & cb->val.hmask.ip;
|
||||
arpinfo->dmsk = cb->val.hmask.ip;
|
||||
break;
|
||||
case O_SRC_MAC:
|
||||
memcpy(arpinfo->smaddr, cb->val.ethermac, ETH_ALEN);
|
||||
memcpy(arpinfo->smmsk, cb->val.ethermacmask, ETH_ALEN);
|
||||
break;
|
||||
case O_DST_MAC:
|
||||
memcpy(arpinfo->dmaddr, cb->val.ethermac, ETH_ALEN);
|
||||
memcpy(arpinfo->dmmsk, cb->val.ethermacmask, ETH_ALEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void brarp_print(const void *ip, const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
const struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
|
||||
|
||||
if (arpinfo->bitmask & EBT_ARP_OPCODE) {
|
||||
int opcode = ntohs(arpinfo->opcode);
|
||||
|
||||
if (arpinfo->invflags & EBT_ARP_OPCODE)
|
||||
printf("! ");
|
||||
printf("--arp-op ");
|
||||
if (opcode > 0 && opcode <= ARRAY_SIZE(opcodes))
|
||||
printf("%s ", opcodes[opcode - 1]);
|
||||
else
|
||||
printf("%d ", opcode);
|
||||
}
|
||||
if (arpinfo->bitmask & EBT_ARP_HTYPE) {
|
||||
if (arpinfo->invflags & EBT_ARP_HTYPE)
|
||||
printf("! ");
|
||||
printf("--arp-htype %d ", ntohs(arpinfo->htype));
|
||||
}
|
||||
if (arpinfo->bitmask & EBT_ARP_PTYPE) {
|
||||
if (arpinfo->invflags & EBT_ARP_PTYPE)
|
||||
printf("! ");
|
||||
printf("--arp-ptype 0x%x ", ntohs(arpinfo->ptype));
|
||||
}
|
||||
if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
|
||||
if (arpinfo->invflags & EBT_ARP_SRC_IP)
|
||||
printf("! ");
|
||||
printf("--arp-ip-src %s%s ",
|
||||
xtables_ipaddr_to_numeric((void *)&arpinfo->saddr),
|
||||
xtables_ipmask_to_numeric((void *)&arpinfo->smsk));
|
||||
}
|
||||
if (arpinfo->bitmask & EBT_ARP_DST_IP) {
|
||||
if (arpinfo->invflags & EBT_ARP_DST_IP)
|
||||
printf("! ");
|
||||
printf("--arp-ip-dst %s%s ",
|
||||
xtables_ipaddr_to_numeric((void *)&arpinfo->daddr),
|
||||
xtables_ipmask_to_numeric((void *)&arpinfo->dmsk));
|
||||
}
|
||||
if (arpinfo->bitmask & EBT_ARP_SRC_MAC) {
|
||||
if (arpinfo->invflags & EBT_ARP_SRC_MAC)
|
||||
printf("! ");
|
||||
printf("--arp-mac-src ");
|
||||
xtables_print_mac_and_mask(arpinfo->smaddr, arpinfo->smmsk);
|
||||
printf(" ");
|
||||
}
|
||||
if (arpinfo->bitmask & EBT_ARP_DST_MAC) {
|
||||
if (arpinfo->invflags & EBT_ARP_DST_MAC)
|
||||
printf("! ");
|
||||
printf("--arp-mac-dst ");
|
||||
xtables_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk);
|
||||
printf(" ");
|
||||
}
|
||||
if (arpinfo->bitmask & EBT_ARP_GRAT) {
|
||||
if (arpinfo->invflags & EBT_ARP_GRAT)
|
||||
printf("! ");
|
||||
printf("--arp-gratuitous ");
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_match brarp_match = {
|
||||
.name = "arp",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_arp_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_arp_info)),
|
||||
.help = brarp_print_help,
|
||||
.x6_parse = brarp_parse,
|
||||
.print = brarp_print,
|
||||
.x6_options = brarp_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brarp_match);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
-p ARP --arp-op Request;=;OK
|
||||
-p ARP ! --arp-op Request;=;OK
|
||||
-p ARP --arp-htype Ethernet;-p ARP --arp-htype 1;OK
|
||||
-p ARP --arp-htype 1;=;OK
|
||||
-p ARP ! --arp-htype 1;=;OK
|
||||
-p ARP --arp-ptype 0x2;=;OK
|
||||
-p ARP ! --arp-ptype 0x2;=;OK
|
||||
-p ARP --arp-ip-src 1.2.3.4;=;OK
|
||||
-p ARP --arp-ip-dst ! 1.2.3.4;-p ARP ! --arp-ip-dst 1.2.3.4 -j CONTINUE;OK
|
||||
-p ARP ! --arp-ip-src 0.0.0.0;=;OK
|
||||
-p ARP ! --arp-ip-dst 0.0.0.0/8;=;OK
|
||||
-p ARP ! --arp-ip-src 1.2.3.4/32;-p ARP ! --arp-ip-src 1.2.3.4;OK
|
||||
-p ARP ! --arp-ip-src 1.2.3.4/255.255.255.0;-p ARP ! --arp-ip-src 1.2.3.0/24;OK
|
||||
-p ARP ! --arp-ip-src 1.2.3.4/255.0.255.255;-p ARP ! --arp-ip-src 1.0.3.4/255.0.255.255;OK
|
||||
-p ARP --arp-mac-src 00:de:ad:be:ef:00;=;OK
|
||||
-p ARP ! --arp-mac-src 00:de:ad:be:ef:00;=;OK
|
||||
-p ARP --arp-mac-dst de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
|
||||
-p ARP ! --arp-mac-dst de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
|
||||
-p ARP --arp-gratuitous;=;OK
|
||||
-p ARP ! --arp-gratuitous;=;OK
|
||||
--arp-htype 1;=;FAIL
|
||||
@@ -0,0 +1,85 @@
|
||||
/* ebt_arpreply
|
||||
*
|
||||
* Authors:
|
||||
* Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* August, 2003
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <linux/netfilter_bridge/ebt_arpreply.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
enum {
|
||||
O_MAC,
|
||||
O_TARGET,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brarpreply_opts[] = {
|
||||
{ .name = "arpreply-mac" , .id = O_MAC, .type = XTTYPE_ETHERMAC,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_arpreply_info, mac) },
|
||||
{ .name = "arpreply-target" , .id = O_TARGET, .type = XTTYPE_STRING },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brarpreply_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"arpreply target options:\n"
|
||||
" --arpreply-mac address : source MAC of generated reply\n"
|
||||
" --arpreply-target target : ACCEPT, DROP, RETURN or CONTINUE\n"
|
||||
" (standard target is DROP)\n");
|
||||
}
|
||||
|
||||
static void brarpreply_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct ebt_arpreply_info *replyinfo = (void *)target->data;
|
||||
|
||||
replyinfo->target = EBT_DROP;
|
||||
}
|
||||
|
||||
static void brarpreply_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_arpreply_info *replyinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
if (cb->entry->id == O_TARGET &&
|
||||
ebt_fill_target(cb->arg, (unsigned int *)&replyinfo->target))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Illegal --arpreply-target target");
|
||||
}
|
||||
|
||||
static void brarpreply_print(const void *ip, const struct xt_entry_target *t, int numeric)
|
||||
{
|
||||
struct ebt_arpreply_info *replyinfo = (void *)t->data;
|
||||
|
||||
printf("--arpreply-mac ");
|
||||
xtables_print_mac(replyinfo->mac);
|
||||
if (replyinfo->target == EBT_DROP)
|
||||
return;
|
||||
printf(" --arpreply-target %s", ebt_target_name(replyinfo->target));
|
||||
}
|
||||
|
||||
static struct xtables_target arpreply_target = {
|
||||
.name = "arpreply",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.init = brarpreply_init,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_arpreply_info)),
|
||||
.help = brarpreply_print_help,
|
||||
.x6_parse = brarpreply_parse,
|
||||
.print = brarpreply_print,
|
||||
.x6_options = brarpreply_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&arpreply_target);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
:PREROUTING
|
||||
*nat
|
||||
-j arpreply;=;FAIL
|
||||
-p ARP -i foo -j arpreply;-p ARP -i foo -j arpreply --arpreply-mac 00:00:00:00:00:00;OK
|
||||
-p ARP -i foo -j arpreply --arpreply-mac de:ad:00:be:ee:ff --arpreply-target ACCEPT;=;OK
|
||||
-p ARP -i foo -j arpreply --arpreply-mac de:ad:00:be:ee:ff;=;OK
|
||||
-p ARP -j arpreply ! --arpreply-mac de:ad:00:be:ee:ff;;FAIL
|
||||
-p ARP -j arpreply --arpreply-mac de:ad:00:be:ee:ff ! --arpreply-target ACCEPT;;FAIL
|
||||
@@ -0,0 +1,119 @@
|
||||
/* ebt_nat
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* June, 2002
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_nat.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
enum {
|
||||
O_DST,
|
||||
O_TARGET,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brdnat_opts[] =
|
||||
{
|
||||
{ .name = "to-destination", .id = O_DST, .type = XTTYPE_ETHERMAC,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
|
||||
{ .name = "to-dst" , .id = O_DST, .type = XTTYPE_ETHERMAC,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
|
||||
{ .name = "dnat-target" , .id = O_TARGET, .type = XTTYPE_STRING },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brdnat_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"dnat options:\n"
|
||||
" --to-dst address : MAC address to map destination to\n"
|
||||
" --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n"
|
||||
" (standard target is ACCEPT)\n");
|
||||
}
|
||||
|
||||
static void brdnat_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
|
||||
|
||||
natinfo->target = EBT_ACCEPT;
|
||||
}
|
||||
|
||||
static void brdnat_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_nat_info *natinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
if (cb->entry->id == O_TARGET &&
|
||||
ebt_fill_target(cb->arg, (unsigned int *)&natinfo->target))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Illegal --dnat-target target");
|
||||
}
|
||||
|
||||
static void brdnat_final_check(struct xt_fcheck_call *fc)
|
||||
{
|
||||
if (!fc->xflags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"You must specify proper arguments");
|
||||
}
|
||||
|
||||
static void brdnat_print(const void *ip, const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
|
||||
|
||||
printf("--to-dst ");
|
||||
xtables_print_mac(natinfo->mac);
|
||||
printf(" --dnat-target %s", ebt_target_name(natinfo->target));
|
||||
}
|
||||
|
||||
static const char* brdnat_verdict(int verdict)
|
||||
{
|
||||
switch (verdict) {
|
||||
case EBT_ACCEPT: return "accept";
|
||||
case EBT_DROP: return "drop";
|
||||
case EBT_CONTINUE: return "continue";
|
||||
case EBT_RETURN: return "return";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static int brdnat_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_tg_params *params)
|
||||
{
|
||||
const struct ebt_nat_info *natinfo = (const void*)params->target->data;
|
||||
|
||||
xt_xlate_add(xl, "ether daddr set %s %s ",
|
||||
ether_ntoa((struct ether_addr *)natinfo->mac),
|
||||
brdnat_verdict(natinfo->target));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_target brdnat_target =
|
||||
{
|
||||
.name = "dnat",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_nat_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_nat_info)),
|
||||
.help = brdnat_print_help,
|
||||
.init = brdnat_init,
|
||||
.x6_parse = brdnat_parse,
|
||||
.x6_fcheck = brdnat_final_check,
|
||||
.print = brdnat_print,
|
||||
.xlate = brdnat_xlate,
|
||||
.x6_options = brdnat_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&brdnat_target);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
:PREROUTING
|
||||
*nat
|
||||
-i someport -j dnat --to-dst de:ad:0:be:ee:ff;-i someport -j dnat --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT;OK
|
||||
-j dnat --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT;=;OK
|
||||
-j dnat --to-dst de:ad:00:be:ee:ff --dnat-target CONTINUE;=;OK
|
||||
@@ -0,0 +1,8 @@
|
||||
ebtables-translate -t nat -A PREROUTING -i someport -j dnat --to-dst de:ad:00:be:ee:ff
|
||||
nft 'add rule bridge nat PREROUTING iifname "someport" counter ether daddr set de:ad:0:be:ee:ff accept'
|
||||
|
||||
ebtables-translate -t nat -A PREROUTING -i someport -j dnat --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT
|
||||
nft 'add rule bridge nat PREROUTING iifname "someport" counter ether daddr set de:ad:0:be:ee:ff accept'
|
||||
|
||||
ebtables-translate -t nat -A PREROUTING -i someport -j dnat --to-dst de:ad:00:be:ee:ff --dnat-target CONTINUE
|
||||
nft 'add rule bridge nat PREROUTING iifname "someport" counter ether daddr set de:ad:0:be:ee:ff continue'
|
||||
@@ -0,0 +1,461 @@
|
||||
/* ebt_ip
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* Changes:
|
||||
* added ip-sport and ip-dport; parsing of port arguments is
|
||||
* based on code from iptables-1.2.7a
|
||||
* Innominate Security Technologies AG <mhopf@innominate.com>
|
||||
* September, 2002
|
||||
*
|
||||
* Adapted by Arturo Borrero Gonzalez <arturo@debian.org>
|
||||
* to use libxtables for ebtables-compat in 2015.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <inttypes.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_ip.h>
|
||||
|
||||
#include "libxt_icmp.h"
|
||||
|
||||
/* must correspond to the bit position in EBT_IP6_* defines */
|
||||
enum {
|
||||
O_SOURCE = 0,
|
||||
O_DEST,
|
||||
O_TOS,
|
||||
O_PROTO,
|
||||
O_SPORT,
|
||||
O_DPORT,
|
||||
O_ICMP,
|
||||
O_IGMP,
|
||||
F_PORT = 1 << O_ICMP | 1 << O_IGMP,
|
||||
F_ICMP = 1 << O_SPORT | 1 << O_DPORT | 1 << O_IGMP,
|
||||
F_IGMP = 1 << O_SPORT | 1 << O_DPORT | 1 << O_ICMP,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brip_opts[] = {
|
||||
{ .name = "ip-source", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_INVERT },
|
||||
{ .name = "ip-src", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_INVERT },
|
||||
{ .name = "ip-destination", .id = O_DEST, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_INVERT },
|
||||
{ .name = "ip-dst", .id = O_DEST, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_INVERT },
|
||||
{ .name = "ip-tos", .id = O_TOS, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip_info, tos) },
|
||||
{ .name = "ip-protocol", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip_info, protocol) },
|
||||
{ .name = "ip-proto", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip_info, protocol) },
|
||||
{ .name = "ip-source-port", .id = O_SPORT, .type = XTTYPE_PORTRC,
|
||||
.excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip_info, sport) },
|
||||
{ .name = "ip-sport", .id = O_SPORT, .type = XTTYPE_PORTRC,
|
||||
.excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip_info, sport) },
|
||||
{ .name = "ip-destination-port",.id = O_DPORT, .type = XTTYPE_PORTRC,
|
||||
.excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip_info, dport) },
|
||||
{ .name = "ip-dport", .id = O_DPORT, .type = XTTYPE_PORTRC,
|
||||
.excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip_info, dport) },
|
||||
{ .name = "ip-icmp-type", .id = O_ICMP, .type = XTTYPE_STRING,
|
||||
.excl = F_ICMP, .flags = XTOPT_INVERT },
|
||||
{ .name = "ip-igmp-type", .id = O_IGMP, .type = XTTYPE_STRING,
|
||||
.excl = F_IGMP, .flags = XTOPT_INVERT },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brip_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"ip options:\n"
|
||||
"[!] --ip-src address[/mask]: ip source specification\n"
|
||||
"[!] --ip-dst address[/mask]: ip destination specification\n"
|
||||
"[!] --ip-tos tos : ip tos specification\n"
|
||||
"[!] --ip-proto protocol : ip protocol specification\n"
|
||||
"[!] --ip-sport port[:port] : tcp/udp source port or port range\n"
|
||||
"[!] --ip-dport port[:port] : tcp/udp destination port or port range\n"
|
||||
"[!] --ip-icmp-type type[[:type]/code[:code]] : icmp type/code or type/code range\n"
|
||||
"[!] --ip-igmp-type type[:type] : igmp type or type range\n");
|
||||
|
||||
printf("\nValid ICMP Types:\n");
|
||||
xt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes));
|
||||
printf("\nValid IGMP Types:\n");
|
||||
xt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types));
|
||||
}
|
||||
|
||||
/* original code from ebtables: useful_functions.c */
|
||||
static void print_icmp_code(uint8_t *code)
|
||||
{
|
||||
if (!code)
|
||||
return;
|
||||
|
||||
if (code[0] == code[1])
|
||||
printf("/%"PRIu8 " ", code[0]);
|
||||
else
|
||||
printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
|
||||
}
|
||||
|
||||
static void ebt_print_icmp_type(const struct xt_icmp_names *codes,
|
||||
size_t n_codes, uint8_t *type, uint8_t *code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (type[0] != type[1]) {
|
||||
printf("%"PRIu8 ":%" PRIu8, type[0], type[1]);
|
||||
print_icmp_code(code);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_codes; i++) {
|
||||
if (codes[i].type != type[0])
|
||||
continue;
|
||||
|
||||
if (!code || (codes[i].code_min == code[0] &&
|
||||
codes[i].code_max == code[1])) {
|
||||
printf("%s ", codes[i].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("%"PRIu8, type[0]);
|
||||
print_icmp_code(code);
|
||||
}
|
||||
|
||||
static void brip_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_ip_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
|
||||
info->bitmask |= 1 << cb->entry->id;
|
||||
info->invflags |= cb->invert ? 1 << cb->entry->id : 0;
|
||||
|
||||
switch (cb->entry->id) {
|
||||
case O_SOURCE:
|
||||
cb->val.haddr.all[0] &= cb->val.hmask.all[0];
|
||||
info->saddr = cb->val.haddr.ip;
|
||||
info->smsk = cb->val.hmask.ip;
|
||||
break;
|
||||
case O_DEST:
|
||||
cb->val.haddr.all[0] &= cb->val.hmask.all[0];
|
||||
info->daddr = cb->val.haddr.ip;
|
||||
info->dmsk = cb->val.hmask.ip;
|
||||
break;
|
||||
case O_ICMP:
|
||||
ebt_parse_icmp(cb->arg, info->icmp_type, info->icmp_code);
|
||||
break;
|
||||
case O_IGMP:
|
||||
ebt_parse_igmp(cb->arg, info->igmp_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void brip_final_check(struct xt_fcheck_call *fc)
|
||||
{
|
||||
if (!fc->xflags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"You must specify proper arguments");
|
||||
}
|
||||
|
||||
static void print_port_range(uint16_t *ports)
|
||||
{
|
||||
if (ports[0] == ports[1])
|
||||
printf("%d ", ports[0]);
|
||||
else
|
||||
printf("%d:%d ", ports[0], ports[1]);
|
||||
}
|
||||
|
||||
static void brip_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
|
||||
struct in_addr *addrp, *maskp;
|
||||
|
||||
if (info->bitmask & EBT_IP_SOURCE) {
|
||||
if (info->invflags & EBT_IP_SOURCE)
|
||||
printf("! ");
|
||||
addrp = (struct in_addr *)&info->saddr;
|
||||
maskp = (struct in_addr *)&info->smsk;
|
||||
printf("--ip-src %s%s ",
|
||||
xtables_ipaddr_to_numeric(addrp),
|
||||
xtables_ipmask_to_numeric(maskp));
|
||||
}
|
||||
if (info->bitmask & EBT_IP_DEST) {
|
||||
if (info->invflags & EBT_IP_DEST)
|
||||
printf("! ");
|
||||
addrp = (struct in_addr *)&info->daddr;
|
||||
maskp = (struct in_addr *)&info->dmsk;
|
||||
printf("--ip-dst %s%s ",
|
||||
xtables_ipaddr_to_numeric(addrp),
|
||||
xtables_ipmask_to_numeric(maskp));
|
||||
}
|
||||
if (info->bitmask & EBT_IP_TOS) {
|
||||
if (info->invflags & EBT_IP_TOS)
|
||||
printf("! ");
|
||||
printf("--ip-tos 0x%02X ", info->tos);
|
||||
}
|
||||
if (info->bitmask & EBT_IP_PROTO) {
|
||||
struct protoent *pe;
|
||||
|
||||
if (info->invflags & EBT_IP_PROTO)
|
||||
printf("! ");
|
||||
printf("--ip-proto ");
|
||||
pe = getprotobynumber(info->protocol);
|
||||
if (pe == NULL) {
|
||||
printf("%d ", info->protocol);
|
||||
} else {
|
||||
printf("%s ", pe->p_name);
|
||||
}
|
||||
}
|
||||
if (info->bitmask & EBT_IP_SPORT) {
|
||||
if (info->invflags & EBT_IP_SPORT)
|
||||
printf("! ");
|
||||
printf("--ip-sport ");
|
||||
print_port_range(info->sport);
|
||||
}
|
||||
if (info->bitmask & EBT_IP_DPORT) {
|
||||
if (info->invflags & EBT_IP_DPORT)
|
||||
printf("! ");
|
||||
printf("--ip-dport ");
|
||||
print_port_range(info->dport);
|
||||
}
|
||||
if (info->bitmask & EBT_IP_ICMP) {
|
||||
if (info->invflags & EBT_IP_ICMP)
|
||||
printf("! ");
|
||||
printf("--ip-icmp-type ");
|
||||
ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes),
|
||||
info->icmp_type, info->icmp_code);
|
||||
}
|
||||
if (info->bitmask & EBT_IP_IGMP) {
|
||||
if (info->invflags & EBT_IP_IGMP)
|
||||
printf("! ");
|
||||
printf("--ip-igmp-type ");
|
||||
ebt_print_icmp_type(igmp_types, ARRAY_SIZE(igmp_types),
|
||||
info->igmp_type, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *brip_xlate_proto_to_name(uint8_t proto)
|
||||
{
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
return "tcp";
|
||||
case IPPROTO_UDP:
|
||||
return "udp";
|
||||
case IPPROTO_UDPLITE:
|
||||
return "udplite";
|
||||
case IPPROTO_SCTP:
|
||||
return "sctp";
|
||||
case IPPROTO_DCCP:
|
||||
return "dccp";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void brip_xlate_icmp(struct xt_xlate *xl,
|
||||
const struct ebt_ip_info *info, int bit)
|
||||
{
|
||||
if ((info->bitmask & bit) == 0)
|
||||
return;
|
||||
|
||||
xt_xlate_add(xl, "icmp type ");
|
||||
if (info->invflags & bit)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
if (info->icmp_type[0] == info->icmp_type[1])
|
||||
xt_xlate_add(xl, "%d ", info->icmp_type[0]);
|
||||
else
|
||||
xt_xlate_add(xl, "%d-%d ", info->icmp_type[0],
|
||||
info->icmp_type[1]);
|
||||
if (info->icmp_code[0] == 0 &&
|
||||
info->icmp_code[1] == 0xff)
|
||||
return;
|
||||
|
||||
xt_xlate_add(xl, "icmp code ");
|
||||
if (info->invflags & bit)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
if (info->icmp_code[0] == info->icmp_code[1])
|
||||
xt_xlate_add(xl, "%d ", info->icmp_code[0]);
|
||||
else
|
||||
xt_xlate_add(xl, "%d-%d ", info->icmp_code[0],
|
||||
info->icmp_code[1]);
|
||||
}
|
||||
|
||||
static void brip_xlate_igmp(struct xt_xlate *xl,
|
||||
const struct ebt_ip_info *info, int bit)
|
||||
{
|
||||
if ((info->bitmask & bit) == 0)
|
||||
return;
|
||||
|
||||
xt_xlate_add(xl, "@th,0,8 ");
|
||||
if (info->invflags & bit)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
if (info->icmp_type[0] == info->icmp_type[1])
|
||||
xt_xlate_add(xl, "%d ", info->icmp_type[0]);
|
||||
else
|
||||
xt_xlate_add(xl, "%d-%d ", info->icmp_type[0],
|
||||
info->icmp_type[1]);
|
||||
}
|
||||
|
||||
static void brip_xlate_th(struct xt_xlate *xl,
|
||||
const struct ebt_ip_info *info, int bit,
|
||||
const char *pname)
|
||||
{
|
||||
const uint16_t *ports;
|
||||
|
||||
if ((info->bitmask & bit) == 0)
|
||||
return;
|
||||
|
||||
switch (bit) {
|
||||
case EBT_IP_SPORT:
|
||||
if (pname)
|
||||
xt_xlate_add(xl, "%s sport ", pname);
|
||||
else
|
||||
xt_xlate_add(xl, "@th,0,16 ");
|
||||
|
||||
ports = info->sport;
|
||||
break;
|
||||
case EBT_IP_DPORT:
|
||||
if (pname)
|
||||
xt_xlate_add(xl, "%s dport ", pname);
|
||||
else
|
||||
xt_xlate_add(xl, "@th,16,16 ");
|
||||
|
||||
ports = info->dport;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->invflags & bit)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
|
||||
if (ports[0] == ports[1])
|
||||
xt_xlate_add(xl, "%d ", ports[0]);
|
||||
else
|
||||
xt_xlate_add(xl, "%d-%d ", ports[0], ports[1]);
|
||||
}
|
||||
|
||||
static void brip_xlate_nh(struct xt_xlate *xl,
|
||||
const struct ebt_ip_info *info, int bit)
|
||||
{
|
||||
struct in_addr *addrp, *maskp;
|
||||
|
||||
if ((info->bitmask & bit) == 0)
|
||||
return;
|
||||
|
||||
switch (bit) {
|
||||
case EBT_IP_SOURCE:
|
||||
xt_xlate_add(xl, "ip saddr ");
|
||||
addrp = (struct in_addr *)&info->saddr;
|
||||
maskp = (struct in_addr *)&info->smsk;
|
||||
break;
|
||||
case EBT_IP_DEST:
|
||||
xt_xlate_add(xl, "ip daddr ");
|
||||
addrp = (struct in_addr *)&info->daddr;
|
||||
maskp = (struct in_addr *)&info->dmsk;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->invflags & bit)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
|
||||
xt_xlate_add(xl, "%s%s ", xtables_ipaddr_to_numeric(addrp),
|
||||
xtables_ipmask_to_numeric(maskp));
|
||||
}
|
||||
|
||||
static bool may_skip_ether_type_dep(uint8_t flags)
|
||||
{
|
||||
/* these convert to "ip (s|d)addr" matches */
|
||||
if (flags & (EBT_IP_SOURCE | EBT_IP_DEST))
|
||||
return true;
|
||||
|
||||
/* icmp match triggers implicit ether type dependency in nft */
|
||||
if (flags & EBT_IP_ICMP)
|
||||
return true;
|
||||
|
||||
/* allow if "ip protocol" match is created by brip_xlate() */
|
||||
if (flags & EBT_IP_PROTO &&
|
||||
!(flags & (EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int brip_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_mt_params *params)
|
||||
{
|
||||
const struct ebt_ip_info *info = (const void *)params->match->data;
|
||||
const char *pname = NULL;
|
||||
|
||||
brip_xlate_nh(xl, info, EBT_IP_SOURCE);
|
||||
brip_xlate_nh(xl, info, EBT_IP_DEST);
|
||||
|
||||
if (!may_skip_ether_type_dep(info->bitmask))
|
||||
xt_xlate_add(xl, "ether type ip ");
|
||||
|
||||
if (info->bitmask & EBT_IP_TOS) {
|
||||
xt_xlate_add(xl, "@nh,8,8 ");
|
||||
if (info->invflags & EBT_IP_TOS)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
xt_xlate_add(xl, "0x%02x ", info->tos);
|
||||
}
|
||||
if (info->bitmask & EBT_IP_PROTO) {
|
||||
struct protoent *pe;
|
||||
|
||||
if (info->bitmask & (EBT_IP_SPORT|EBT_IP_DPORT|EBT_IP_ICMP) &&
|
||||
(info->invflags & EBT_IP_PROTO) == 0) {
|
||||
/* port number or icmp given and not inverted, no need to print this */
|
||||
pname = brip_xlate_proto_to_name(info->protocol);
|
||||
} else {
|
||||
xt_xlate_add(xl, "ip protocol ");
|
||||
if (info->invflags & EBT_IP_PROTO)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
pe = getprotobynumber(info->protocol);
|
||||
if (pe == NULL)
|
||||
xt_xlate_add(xl, "%d ", info->protocol);
|
||||
else
|
||||
xt_xlate_add(xl, "%s ", pe->p_name);
|
||||
}
|
||||
}
|
||||
|
||||
brip_xlate_th(xl, info, EBT_IP_SPORT, pname);
|
||||
brip_xlate_th(xl, info, EBT_IP_DPORT, pname);
|
||||
|
||||
brip_xlate_icmp(xl, info, EBT_IP_ICMP);
|
||||
brip_xlate_igmp(xl, info, EBT_IP_IGMP);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_match brip_match = {
|
||||
.name = "ip",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_ip_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)),
|
||||
.help = brip_print_help,
|
||||
.x6_parse = brip_parse,
|
||||
.x6_fcheck = brip_final_check,
|
||||
.print = brip_print,
|
||||
.xlate = brip_xlate,
|
||||
.x6_options = brip_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brip_match);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
-p ip ! --ip-src 192.168.0.0/24 -j ACCEPT;-p IPv4 ! --ip-src 192.168.0.0/24 -j ACCEPT;OK
|
||||
-p IPv4 --ip-dst 10.0.0.1;=;OK
|
||||
-p IPv4 ! --ip-dst 10.0.0.1;=;OK
|
||||
-p IPv4 --ip-tos 0xFF;=;OK
|
||||
-p IPv4 ! --ip-tos 0xFF;=;OK
|
||||
-p IPv4 --ip-proto tcp --ip-dport 22;=;OK
|
||||
-p IPv4 --ip-proto udp --ip-sport 1024:65535;=;OK
|
||||
-p IPv4 --ip-proto udp --ip-sport :;-p IPv4 --ip-proto udp --ip-sport 0:65535;OK
|
||||
-p IPv4 --ip-proto udp --ip-sport :4;-p IPv4 --ip-proto udp --ip-sport 0:4;OK
|
||||
-p IPv4 --ip-proto udp --ip-sport 4:;-p IPv4 --ip-proto udp --ip-sport 4:65535;OK
|
||||
-p IPv4 --ip-proto udp --ip-sport 3:4;=;OK
|
||||
-p IPv4 --ip-proto udp --ip-sport 4:4;-p IPv4 --ip-proto udp --ip-sport 4;OK
|
||||
-p IPv4 --ip-proto udp --ip-sport 4:3;;FAIL
|
||||
-p IPv4 --ip-proto udp --ip-dport :;-p IPv4 --ip-proto udp --ip-dport 0:65535;OK
|
||||
-p IPv4 --ip-proto udp --ip-dport :4;-p IPv4 --ip-proto udp --ip-dport 0:4;OK
|
||||
-p IPv4 --ip-proto udp --ip-dport 4:;-p IPv4 --ip-proto udp --ip-dport 4:65535;OK
|
||||
-p IPv4 --ip-proto udp --ip-dport 3:4;=;OK
|
||||
-p IPv4 --ip-proto udp --ip-dport 4:4;-p IPv4 --ip-proto udp --ip-dport 4;OK
|
||||
-p IPv4 --ip-proto udp --ip-dport 4:3;;FAIL
|
||||
-p IPv4 --ip-proto 253;=;OK
|
||||
-p IPv4 ! --ip-proto 253;=;OK
|
||||
-p IPv4 --ip-proto icmp --ip-icmp-type echo-request;=;OK
|
||||
-p IPv4 --ip-proto icmp --ip-icmp-type 1/1;=;OK
|
||||
-p ip --ip-protocol icmp ! --ip-icmp-type 1:10;-p IPv4 --ip-proto icmp ! --ip-icmp-type 1:10/0:255 -j CONTINUE;OK
|
||||
--ip-proto icmp --ip-icmp-type 1/1;=;FAIL
|
||||
! -p ip --ip-proto icmp --ip-icmp-type 1/1;=;FAIL
|
||||
! -p ip --ip-proto tcp --ip-sport 22 --ip-icmp-type echo-reply;;FAIL
|
||||
! -p ip --ip-proto tcp --ip-sport 22 --ip-igmp-type membership-query;;FAIL
|
||||
! -p ip --ip-proto tcp --ip-dport 22 --ip-icmp-type echo-reply;;FAIL
|
||||
! -p ip --ip-proto tcp --ip-dport 22 --ip-igmp-type membership-query;;FAIL
|
||||
! -p ip --ip-proto icmp --ip-icmp-type echo-reply --ip-igmp-type membership-query;;FAIL
|
||||
-p IPv4 --ip-proto icmp ! --ip-icmp-type echo-reply;=;OK
|
||||
@@ -0,0 +1,26 @@
|
||||
ebtables-translate -A FORWARD -p ip ! --ip-src 192.168.0.0/24 -j ACCEPT
|
||||
nft 'add rule bridge filter FORWARD ip saddr != 192.168.0.0/24 counter accept'
|
||||
|
||||
ebtables-translate -I FORWARD -p ip --ip-dst 10.0.0.1
|
||||
nft 'insert rule bridge filter FORWARD ip daddr 10.0.0.1 counter'
|
||||
|
||||
ebtables-translate -I OUTPUT -p ip -o eth0 --ip-tos 0xff
|
||||
nft 'insert rule bridge filter OUTPUT oifname "eth0" ether type ip @nh,8,8 0xff counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip --ip-proto tcp --ip-dport 22
|
||||
nft 'add rule bridge filter FORWARD ether type ip tcp dport 22 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip --ip-proto udp --ip-sport 1024:65535
|
||||
nft 'add rule bridge filter FORWARD ether type ip udp sport 1024-65535 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip --ip-proto 253
|
||||
nft 'add rule bridge filter FORWARD ip protocol 253 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip --ip-protocol icmp --ip-icmp-type "echo-request"
|
||||
nft 'add rule bridge filter FORWARD icmp type 8 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip --ip-proto icmp --ip-icmp-type 1/1
|
||||
nft 'add rule bridge filter FORWARD icmp type 1 icmp code 1 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip --ip-protocol icmp ! --ip-icmp-type 1:10
|
||||
nft 'add rule bridge filter FORWARD icmp type != 1-10 counter'
|
||||
@@ -0,0 +1,404 @@
|
||||
/* ebt_ip6
|
||||
*
|
||||
* Authors:
|
||||
* Kuo-Lang Tseng <kuo-lang.tseng@intel.com>
|
||||
* Manohar Castelino <manohar.castelino@intel.com>
|
||||
*
|
||||
* Summary:
|
||||
* This is just a modification of the IPv4 code written by
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
* with the changes required to support IPv6
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_ip6.h>
|
||||
|
||||
#include "libxt_icmp.h"
|
||||
|
||||
/* must correspond to the bit position in EBT_IP6_* defines */
|
||||
enum {
|
||||
O_SOURCE = 0,
|
||||
O_DEST,
|
||||
O_TCLASS,
|
||||
O_PROTO,
|
||||
O_SPORT,
|
||||
O_DPORT,
|
||||
O_ICMP6,
|
||||
F_PORT = 1 << O_ICMP6,
|
||||
F_ICMP6 = 1 << O_SPORT | 1 << O_DPORT,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brip6_opts[] = {
|
||||
{ .name = "ip6-source", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_INVERT },
|
||||
{ .name = "ip6-src", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_INVERT },
|
||||
{ .name = "ip6-destination", .id = O_DEST, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_INVERT },
|
||||
{ .name = "ip6-dst", .id = O_DEST, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_INVERT },
|
||||
{ .name = "ip6-tclass", .id = O_TCLASS, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip6_info, tclass) },
|
||||
{ .name = "ip6-protocol", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip6_info, protocol) },
|
||||
{ .name = "ip6-proto", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip6_info, protocol) },
|
||||
{ .name = "ip6-source-port", .id = O_SPORT, .type = XTTYPE_PORTRC,
|
||||
.excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip6_info, sport) },
|
||||
{ .name = "ip6-sport", .id = O_SPORT, .type = XTTYPE_PORTRC,
|
||||
.excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip6_info, sport) },
|
||||
{ .name = "ip6-destination-port",.id = O_DPORT, .type = XTTYPE_PORTRC,
|
||||
.excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip6_info, dport) },
|
||||
{ .name = "ip6-dport", .id = O_DPORT, .type = XTTYPE_PORTRC,
|
||||
.excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_ip6_info, dport) },
|
||||
{ .name = "ip6-icmp-type", .id = O_ICMP6, .type = XTTYPE_STRING,
|
||||
.excl = F_ICMP6, .flags = XTOPT_INVERT },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void print_port_range(uint16_t *ports)
|
||||
{
|
||||
if (ports[0] == ports[1])
|
||||
printf("%d ", ports[0]);
|
||||
else
|
||||
printf("%d:%d ", ports[0], ports[1]);
|
||||
}
|
||||
|
||||
static void print_icmp_code(uint8_t *code)
|
||||
{
|
||||
if (code[0] == code[1])
|
||||
printf("/%"PRIu8 " ", code[0]);
|
||||
else
|
||||
printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
|
||||
}
|
||||
|
||||
static void print_icmp_type(uint8_t *type, uint8_t *code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (type[0] != type[1]) {
|
||||
printf("%"PRIu8 ":%" PRIu8, type[0], type[1]);
|
||||
print_icmp_code(code);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmpv6_codes); i++) {
|
||||
if (icmpv6_codes[i].type != type[0])
|
||||
continue;
|
||||
|
||||
if (icmpv6_codes[i].code_min == code[0] &&
|
||||
icmpv6_codes[i].code_max == code[1]) {
|
||||
printf("%s ", icmpv6_codes[i].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("%"PRIu8, type[0]);
|
||||
print_icmp_code(code);
|
||||
}
|
||||
|
||||
static void brip6_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"ip6 options:\n"
|
||||
"[!] --ip6-src address[/mask]: ipv6 source specification\n"
|
||||
"[!] --ip6-dst address[/mask]: ipv6 destination specification\n"
|
||||
"[!] --ip6-tclass tclass : ipv6 traffic class specification\n"
|
||||
"[!] --ip6-proto protocol : ipv6 protocol specification\n"
|
||||
"[!] --ip6-sport port[:port] : tcp/udp source port or port range\n"
|
||||
"[!] --ip6-dport port[:port] : tcp/udp destination port or port range\n"
|
||||
"[!] --ip6-icmp-type type[[:type]/code[:code]] : ipv6-icmp type/code or type/code range\n");
|
||||
printf("Valid ICMPv6 Types:");
|
||||
xt_print_icmp_types(icmpv6_codes, ARRAY_SIZE(icmpv6_codes));
|
||||
}
|
||||
|
||||
static void brip6_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_ip6_info *info = cb->data;
|
||||
unsigned int i;
|
||||
|
||||
/* XXX: overriding afinfo family is dangerous, but
|
||||
* required for XTTYPE_HOSTMASK parsing */
|
||||
xtables_set_nfproto(NFPROTO_IPV6);
|
||||
xtables_option_parse(cb);
|
||||
xtables_set_nfproto(NFPROTO_BRIDGE);
|
||||
|
||||
info->bitmask |= 1 << cb->entry->id;
|
||||
info->invflags |= cb->invert ? 1 << cb->entry->id : 0;
|
||||
|
||||
switch (cb->entry->id) {
|
||||
case O_SOURCE:
|
||||
for (i = 0; i < ARRAY_SIZE(cb->val.haddr.all); i++)
|
||||
cb->val.haddr.all[i] &= cb->val.hmask.all[i];
|
||||
info->saddr = cb->val.haddr.in6;
|
||||
info->smsk = cb->val.hmask.in6;
|
||||
break;
|
||||
case O_DEST:
|
||||
for (i = 0; i < ARRAY_SIZE(cb->val.haddr.all); i++)
|
||||
cb->val.haddr.all[i] &= cb->val.hmask.all[i];
|
||||
info->daddr = cb->val.haddr.in6;
|
||||
info->dmsk = cb->val.hmask.in6;
|
||||
break;
|
||||
case O_ICMP6:
|
||||
ebt_parse_icmpv6(cb->arg, info->icmpv6_type, info->icmpv6_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void brip6_final_check(struct xt_fcheck_call *fc)
|
||||
{
|
||||
if (!fc->xflags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"You must specify proper arguments");
|
||||
}
|
||||
|
||||
static void brip6_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_ip6_info *ipinfo = (struct ebt_ip6_info *)match->data;
|
||||
|
||||
if (ipinfo->bitmask & EBT_IP6_SOURCE) {
|
||||
if (ipinfo->invflags & EBT_IP6_SOURCE)
|
||||
printf("! ");
|
||||
printf("--ip6-src ");
|
||||
printf("%s", xtables_ip6addr_to_numeric(&ipinfo->saddr));
|
||||
printf("%s ", xtables_ip6mask_to_numeric(&ipinfo->smsk));
|
||||
}
|
||||
if (ipinfo->bitmask & EBT_IP6_DEST) {
|
||||
if (ipinfo->invflags & EBT_IP6_DEST)
|
||||
printf("! ");
|
||||
printf("--ip6-dst ");
|
||||
printf("%s", xtables_ip6addr_to_numeric(&ipinfo->daddr));
|
||||
printf("%s ", xtables_ip6mask_to_numeric(&ipinfo->dmsk));
|
||||
}
|
||||
if (ipinfo->bitmask & EBT_IP6_TCLASS) {
|
||||
if (ipinfo->invflags & EBT_IP6_TCLASS)
|
||||
printf("! ");
|
||||
printf("--ip6-tclass 0x%02X ", ipinfo->tclass);
|
||||
}
|
||||
if (ipinfo->bitmask & EBT_IP6_PROTO) {
|
||||
struct protoent *pe;
|
||||
|
||||
if (ipinfo->invflags & EBT_IP6_PROTO)
|
||||
printf("! ");
|
||||
printf("--ip6-proto ");
|
||||
pe = getprotobynumber(ipinfo->protocol);
|
||||
if (pe == NULL) {
|
||||
printf("%d ", ipinfo->protocol);
|
||||
} else {
|
||||
printf("%s ", pe->p_name);
|
||||
}
|
||||
}
|
||||
if (ipinfo->bitmask & EBT_IP6_SPORT) {
|
||||
if (ipinfo->invflags & EBT_IP6_SPORT)
|
||||
printf("! ");
|
||||
printf("--ip6-sport ");
|
||||
print_port_range(ipinfo->sport);
|
||||
}
|
||||
if (ipinfo->bitmask & EBT_IP6_DPORT) {
|
||||
if (ipinfo->invflags & EBT_IP6_DPORT)
|
||||
printf("! ");
|
||||
printf("--ip6-dport ");
|
||||
print_port_range(ipinfo->dport);
|
||||
}
|
||||
if (ipinfo->bitmask & EBT_IP6_ICMP6) {
|
||||
if (ipinfo->invflags & EBT_IP6_ICMP6)
|
||||
printf("! ");
|
||||
printf("--ip6-icmp-type ");
|
||||
print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code);
|
||||
}
|
||||
}
|
||||
|
||||
static void brip_xlate_th(struct xt_xlate *xl,
|
||||
const struct ebt_ip6_info *info, int bit,
|
||||
const char *pname)
|
||||
{
|
||||
const uint16_t *ports;
|
||||
|
||||
if ((info->bitmask & bit) == 0)
|
||||
return;
|
||||
|
||||
switch (bit) {
|
||||
case EBT_IP6_SPORT:
|
||||
if (pname)
|
||||
xt_xlate_add(xl, "%s sport ", pname);
|
||||
else
|
||||
xt_xlate_add(xl, "@th,0,16 ");
|
||||
|
||||
ports = info->sport;
|
||||
break;
|
||||
case EBT_IP6_DPORT:
|
||||
if (pname)
|
||||
xt_xlate_add(xl, "%s dport ", pname);
|
||||
else
|
||||
xt_xlate_add(xl, "@th,16,16 ");
|
||||
|
||||
ports = info->dport;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->invflags & bit)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
|
||||
if (ports[0] == ports[1])
|
||||
xt_xlate_add(xl, "%d ", ports[0]);
|
||||
else
|
||||
xt_xlate_add(xl, "%d-%d ", ports[0], ports[1]);
|
||||
}
|
||||
|
||||
static void brip_xlate_nh(struct xt_xlate *xl,
|
||||
const struct ebt_ip6_info *info, int bit)
|
||||
{
|
||||
struct in6_addr *addrp, *maskp;
|
||||
|
||||
if ((info->bitmask & bit) == 0)
|
||||
return;
|
||||
|
||||
switch (bit) {
|
||||
case EBT_IP6_SOURCE:
|
||||
xt_xlate_add(xl, "ip6 saddr ");
|
||||
addrp = (struct in6_addr *)&info->saddr;
|
||||
maskp = (struct in6_addr *)&info->smsk;
|
||||
break;
|
||||
case EBT_IP6_DEST:
|
||||
xt_xlate_add(xl, "ip6 daddr ");
|
||||
addrp = (struct in6_addr *)&info->daddr;
|
||||
maskp = (struct in6_addr *)&info->dmsk;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->invflags & bit)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
|
||||
xt_xlate_add(xl, "%s%s ", xtables_ip6addr_to_numeric(addrp),
|
||||
xtables_ip6mask_to_numeric(maskp));
|
||||
}
|
||||
|
||||
static const char *brip6_xlate_proto_to_name(uint8_t proto)
|
||||
{
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
return "tcp";
|
||||
case IPPROTO_UDP:
|
||||
return "udp";
|
||||
case IPPROTO_UDPLITE:
|
||||
return "udplite";
|
||||
case IPPROTO_SCTP:
|
||||
return "sctp";
|
||||
case IPPROTO_DCCP:
|
||||
return "dccp";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int brip6_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_mt_params *params)
|
||||
{
|
||||
const struct ebt_ip6_info *info = (const void *)params->match->data;
|
||||
const char *pname = NULL;
|
||||
|
||||
if ((info->bitmask & (EBT_IP6_SOURCE|EBT_IP6_DEST|EBT_IP6_ICMP6|EBT_IP6_TCLASS)) == 0)
|
||||
xt_xlate_add(xl, "ether type ip6 ");
|
||||
|
||||
brip_xlate_nh(xl, info, EBT_IP6_SOURCE);
|
||||
brip_xlate_nh(xl, info, EBT_IP6_DEST);
|
||||
|
||||
if (info->bitmask & EBT_IP6_TCLASS) {
|
||||
xt_xlate_add(xl, "ip6 dscp ");
|
||||
if (info->invflags & EBT_IP6_TCLASS)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
xt_xlate_add(xl, "0x%02x ", info->tclass & 0x3f); /* remove ECN bits */
|
||||
}
|
||||
|
||||
if (info->bitmask & EBT_IP6_PROTO) {
|
||||
struct protoent *pe;
|
||||
|
||||
if (info->bitmask & (EBT_IP6_SPORT|EBT_IP6_DPORT|EBT_IP6_ICMP6) &&
|
||||
(info->invflags & EBT_IP6_PROTO) == 0) {
|
||||
/* port number given and not inverted, no need to
|
||||
* add explicit 'meta l4proto'.
|
||||
*/
|
||||
pname = brip6_xlate_proto_to_name(info->protocol);
|
||||
} else {
|
||||
xt_xlate_add(xl, "meta l4proto ");
|
||||
if (info->invflags & EBT_IP6_PROTO)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
pe = getprotobynumber(info->protocol);
|
||||
if (pe == NULL)
|
||||
xt_xlate_add(xl, "%d ", info->protocol);
|
||||
else
|
||||
xt_xlate_add(xl, "%s ", pe->p_name);
|
||||
}
|
||||
}
|
||||
|
||||
brip_xlate_th(xl, info, EBT_IP6_SPORT, pname);
|
||||
brip_xlate_th(xl, info, EBT_IP6_DPORT, pname);
|
||||
|
||||
if (info->bitmask & EBT_IP6_ICMP6) {
|
||||
xt_xlate_add(xl, "icmpv6 type ");
|
||||
if (info->invflags & EBT_IP6_ICMP6)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
|
||||
if (info->icmpv6_type[0] == info->icmpv6_type[1])
|
||||
xt_xlate_add(xl, "%d ", info->icmpv6_type[0]);
|
||||
else
|
||||
xt_xlate_add(xl, "%d-%d ", info->icmpv6_type[0],
|
||||
info->icmpv6_type[1]);
|
||||
|
||||
if (info->icmpv6_code[0] == 0 &&
|
||||
info->icmpv6_code[1] == 0xff)
|
||||
return 1;
|
||||
|
||||
xt_xlate_add(xl, "icmpv6 code ");
|
||||
if (info->invflags & EBT_IP6_ICMP6)
|
||||
xt_xlate_add(xl, "!= ");
|
||||
|
||||
if (info->icmpv6_code[0] == info->icmpv6_code[1])
|
||||
xt_xlate_add(xl, "%d ", info->icmpv6_code[0]);
|
||||
else
|
||||
xt_xlate_add(xl, "%d-%d ", info->icmpv6_code[0],
|
||||
info->icmpv6_code[1]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_match brip6_match = {
|
||||
.name = "ip6",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_ip6_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip6_info)),
|
||||
.help = brip6_print_help,
|
||||
.x6_parse = brip6_parse,
|
||||
.x6_fcheck = brip6_final_check,
|
||||
.print = brip6_print,
|
||||
.xlate = brip6_xlate,
|
||||
.x6_options = brip6_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brip6_match);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
-p ip6 ! --ip6-src dead::beef/64 -j ACCEPT;-p IPv6 ! --ip6-src dead::/64 -j ACCEPT;OK
|
||||
-p IPv6 --ip6-dst dead:beef::/64 -j ACCEPT;=;OK
|
||||
-p IPv6 --ip6-dst f00:ba::;=;OK
|
||||
-p IPv6 ! --ip6-dst f00:ba::;=;OK
|
||||
-p IPv6 --ip6-src 10.0.0.1;;FAIL
|
||||
-p IPv6 --ip6-tclass 0xFF;=;OK
|
||||
-p IPv6 ! --ip6-tclass 0xFF;=;OK
|
||||
-p IPv6 --ip6-proto tcp --ip6-dport 22;=;OK
|
||||
-p IPv6 --ip6-proto tcp ! --ip6-dport 22;=;OK
|
||||
-p IPv6 --ip6-proto tcp ! --ip6-sport 22 --ip6-dport 22;=;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-sport 1024:65535;=;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-sport :;-p IPv6 --ip6-proto udp --ip6-sport 0:65535;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-sport :4;-p IPv6 --ip6-proto udp --ip6-sport 0:4;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-sport 4:;-p IPv6 --ip6-proto udp --ip6-sport 4:65535;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-sport 3:4;=;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-sport 4:4;-p IPv6 --ip6-proto udp --ip6-sport 4;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-sport 4:3;;FAIL
|
||||
-p IPv6 --ip6-proto udp --ip6-dport :;-p IPv6 --ip6-proto udp --ip6-dport 0:65535;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-dport :4;-p IPv6 --ip6-proto udp --ip6-dport 0:4;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-dport 4:;-p IPv6 --ip6-proto udp --ip6-dport 4:65535;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-dport 3:4;=;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-dport 4:4;-p IPv6 --ip6-proto udp --ip6-dport 4;OK
|
||||
-p IPv6 --ip6-proto udp --ip6-dport 4:3;;FAIL
|
||||
-p IPv6 --ip6-proto 253;=;OK
|
||||
-p IPv6 ! --ip6-proto 253;=;OK
|
||||
-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request -j CONTINUE;=;OK
|
||||
-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request;=;OK
|
||||
-p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type echo-request;=;OK
|
||||
-p ip6 --ip6-protocol icmpv6 --ip6-icmp-type 1/1;-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type communication-prohibited -j CONTINUE;OK
|
||||
-p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;OK
|
||||
--ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL
|
||||
! -p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL
|
||||
-p IPv6 --ip6-proto tcp --ip6-sport 22 --ip6-icmp-type echo-request;;FAIL
|
||||
-p IPv6 --ip6-proto tcp --ip6-dport 22 --ip6-icmp-type echo-request;;FAIL
|
||||
@@ -0,0 +1,29 @@
|
||||
ebtables-translate -A FORWARD -p ip6 --ip6-src ! dead::beef/64 -j ACCEPT
|
||||
nft 'add rule bridge filter FORWARD ip6 saddr != dead::/64 counter accept'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip6 ! --ip6-dst dead:beef::/64 -j ACCEPT
|
||||
nft 'add rule bridge filter FORWARD ip6 daddr != dead:beef::/64 counter accept'
|
||||
|
||||
ebtables-translate -I FORWARD -p ip6 --ip6-dst f00:ba::
|
||||
nft 'insert rule bridge filter FORWARD ip6 daddr f00:ba:: counter'
|
||||
|
||||
ebtables-translate -I OUTPUT -o eth0 -p ip6 --ip6-tclass 0xff
|
||||
nft 'insert rule bridge filter OUTPUT oifname "eth0" ip6 dscp 0x3f counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip6 --ip6-proto tcp --ip6-dport 22
|
||||
nft 'add rule bridge filter FORWARD ether type ip6 tcp dport 22 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip6 --ip6-proto udp --ip6-sport 1024:65535
|
||||
nft 'add rule bridge filter FORWARD ether type ip6 udp sport 1024-65535 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip6 --ip6-proto 253
|
||||
nft 'add rule bridge filter FORWARD ether type ip6 meta l4proto 253 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type "echo-request"
|
||||
nft 'add rule bridge filter FORWARD icmpv6 type 128 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type 1/1
|
||||
nft 'add rule bridge filter FORWARD icmpv6 type 1 icmpv6 code 1 counter'
|
||||
|
||||
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 ! --ip6-icmp-type 1:10
|
||||
nft 'add rule bridge filter FORWARD icmpv6 type != 1-10 counter'
|
||||
@@ -0,0 +1,8 @@
|
||||
ebtables-translate -A INPUT --limit 3/m --limit-burst 3
|
||||
nft 'add rule bridge filter INPUT limit rate 3/minute burst 3 packets counter'
|
||||
|
||||
ebtables-translate -A INPUT --limit 10/s --limit-burst 5
|
||||
nft 'add rule bridge filter INPUT limit rate 10/second burst 5 packets counter'
|
||||
|
||||
ebtables-translate -A INPUT --limit 10/s --limit-burst 0
|
||||
nft 'add rule bridge filter INPUT limit rate 10/second counter'
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Giuseppe Longo <giuseppelng@gmail.com> adapted the original code to the
|
||||
* xtables-compat environment in 2015.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_log.h>
|
||||
|
||||
#define LOG_DEFAULT_LEVEL LOG_INFO
|
||||
|
||||
struct code {
|
||||
char *c_name;
|
||||
int c_val;
|
||||
};
|
||||
|
||||
static struct code eight_priority[] = {
|
||||
{ "emerg", LOG_EMERG },
|
||||
{ "alert", LOG_ALERT },
|
||||
{ "crit", LOG_CRIT },
|
||||
{ "error", LOG_ERR },
|
||||
{ "warning", LOG_WARNING },
|
||||
{ "notice", LOG_NOTICE },
|
||||
{ "info", LOG_INFO },
|
||||
{ "debug", LOG_DEBUG }
|
||||
};
|
||||
|
||||
enum {
|
||||
/* first three must correspond with bit pos in respective EBT_LOG_* */
|
||||
O_LOG_IP = 0,
|
||||
O_LOG_ARP = 1,
|
||||
O_LOG_IP6 = 3,
|
||||
O_LOG_PREFIX,
|
||||
O_LOG_LEVEL,
|
||||
O_LOG_LOG,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brlog_opts[] = {
|
||||
{ .name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_log_info, prefix) },
|
||||
{ .name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_log_info, loglevel) },
|
||||
{ .name = "log-arp", .id = O_LOG_ARP, .type = XTTYPE_NONE },
|
||||
{ .name = "log-ip", .id = O_LOG_IP, .type = XTTYPE_NONE },
|
||||
{ .name = "log", .id = O_LOG_LOG, .type = XTTYPE_NONE },
|
||||
{ .name = "log-ip6", .id = O_LOG_IP6, .type = XTTYPE_NONE },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brlog_help(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(
|
||||
"log options:\n"
|
||||
"--log : use this if you're not specifying anything\n"
|
||||
"--log-level level : level = [1-8] or a string\n"
|
||||
"--log-prefix prefix : max. %d chars.\n"
|
||||
"--log-ip : put ip info. in the log for ip packets\n"
|
||||
"--log-arp : put (r)arp info. in the log for (r)arp packets\n"
|
||||
"--log-ip6 : put ip6 info. in the log for ip6 packets\n"
|
||||
, EBT_LOG_PREFIX_SIZE - 1);
|
||||
for (i = 0; i < 8; i++)
|
||||
printf("%d = %s\n", eight_priority[i].c_val,
|
||||
eight_priority[i].c_name);
|
||||
}
|
||||
|
||||
static void brlog_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ebt_log_info *loginfo = (struct ebt_log_info *)t->data;
|
||||
|
||||
loginfo->loglevel = LOG_NOTICE;
|
||||
}
|
||||
|
||||
static void brlog_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_log_info *loginfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_LOG_IP:
|
||||
case O_LOG_ARP:
|
||||
case O_LOG_IP6:
|
||||
loginfo->bitmask |= 1 << cb->entry->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void brlog_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data;
|
||||
|
||||
printf("--log-level %s", eight_priority[loginfo->loglevel].c_name);
|
||||
|
||||
if (loginfo->prefix[0])
|
||||
printf(" --log-prefix \"%s\"", loginfo->prefix);
|
||||
|
||||
if (loginfo->bitmask & EBT_LOG_IP)
|
||||
printf(" --log-ip");
|
||||
if (loginfo->bitmask & EBT_LOG_ARP)
|
||||
printf(" --log-arp");
|
||||
if (loginfo->bitmask & EBT_LOG_IP6)
|
||||
printf(" --log-ip6");
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static int brlog_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_tg_params *params)
|
||||
{
|
||||
const struct ebt_log_info *loginfo = (const void *)params->target->data;
|
||||
|
||||
xt_xlate_add(xl, "log");
|
||||
if (loginfo->prefix[0])
|
||||
xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
|
||||
|
||||
if (loginfo->loglevel != LOG_DEFAULT_LEVEL)
|
||||
xt_xlate_add(xl, " level %s", eight_priority[loginfo->loglevel].c_name);
|
||||
|
||||
/* ebt_log always decodes MAC header, nft_log always decodes upper header -
|
||||
* so set flags ether and ignore EBT_LOG_IP, EBT_LOG_ARP and EBT_LOG_IP6 */
|
||||
xt_xlate_add(xl, " flags ether ");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_target brlog_target = {
|
||||
.name = "log",
|
||||
.revision = 0,
|
||||
.ext_flags = XTABLES_EXT_WATCHER,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_log_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_log_info)),
|
||||
.init = brlog_init,
|
||||
.help = brlog_help,
|
||||
.x6_parse = brlog_parse,
|
||||
.print = brlog_print,
|
||||
.xlate = brlog_xlate,
|
||||
.x6_options = brlog_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&brlog_target);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
--log;--log-level notice;OK
|
||||
--log-level crit;=;OK
|
||||
--log-level 1;--log-level alert;OK
|
||||
--log-level emerg --log-ip --log-arp --log-ip6;=;OK
|
||||
--log-level crit --log-ip --log-arp --log-ip6 --log-prefix foo;--log-level crit --log-prefix "foo" --log-ip --log-arp --log-ip6 -j CONTINUE;OK
|
||||
@@ -0,0 +1,15 @@
|
||||
ebtables-translate -A INPUT --log
|
||||
nft 'add rule bridge filter INPUT log level notice flags ether counter'
|
||||
|
||||
ebtables-translate -A INPUT --log-level 1
|
||||
nft 'add rule bridge filter INPUT log level alert flags ether counter'
|
||||
|
||||
ebtables-translate -A INPUT --log-level crit
|
||||
nft 'add rule bridge filter INPUT log level crit flags ether counter'
|
||||
|
||||
ebtables-translate -A INPUT --log-level emerg --log-ip --log-arp --log-ip6
|
||||
nft 'add rule bridge filter INPUT log level emerg flags ether counter'
|
||||
|
||||
ebtables-translate -A INPUT --log-level crit --log-ip --log-arp --log-ip6 --log-prefix foo
|
||||
nft 'add rule bridge filter INPUT log prefix "foo" level crit flags ether counter'
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/* ebt_mark
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* July, 2002, September 2006
|
||||
*
|
||||
* Adapted by Arturo Borrero Gonzalez <arturo@debian.org>
|
||||
* to use libxtables for ebtables-compat in 2015.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_mark_t.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
enum {
|
||||
O_SET_MARK = 0,
|
||||
O_AND_MARK,
|
||||
O_OR_MARK,
|
||||
O_XOR_MARK,
|
||||
O_MARK_TARGET,
|
||||
F_SET_MARK = 1 << O_SET_MARK,
|
||||
F_AND_MARK = 1 << O_AND_MARK,
|
||||
F_OR_MARK = 1 << O_OR_MARK,
|
||||
F_XOR_MARK = 1 << O_XOR_MARK,
|
||||
F_ANY = F_SET_MARK | F_AND_MARK | F_OR_MARK | F_XOR_MARK,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brmark_opts[] = {
|
||||
{ .name = "mark-target",.id = O_MARK_TARGET, .type = XTTYPE_STRING },
|
||||
/* an oldtime messup, we should have always used the scheme
|
||||
* <extension-name>-<option> */
|
||||
{ .name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
|
||||
.excl = F_ANY },
|
||||
{ .name = "mark-set", .id = O_SET_MARK, .type = XTTYPE_UINT32,
|
||||
.excl = F_ANY },
|
||||
{ .name = "mark-or", .id = O_OR_MARK, .type = XTTYPE_UINT32,
|
||||
.excl = F_ANY },
|
||||
{ .name = "mark-and", .id = O_AND_MARK, .type = XTTYPE_UINT32,
|
||||
.excl = F_ANY },
|
||||
{ .name = "mark-xor", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
|
||||
.excl = F_ANY },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brmark_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"mark target options:\n"
|
||||
" --mark-set value : Set nfmark value\n"
|
||||
" --mark-or value : Or nfmark with value (nfmark |= value)\n"
|
||||
" --mark-and value : And nfmark with value (nfmark &= value)\n"
|
||||
" --mark-xor value : Xor nfmark with value (nfmark ^= value)\n"
|
||||
" --mark-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
|
||||
}
|
||||
|
||||
static void brmark_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data;
|
||||
|
||||
info->target = EBT_ACCEPT;
|
||||
info->mark = 0;
|
||||
}
|
||||
|
||||
static void brmark_parse(struct xt_option_call *cb)
|
||||
{
|
||||
static const unsigned long target_orval[] = {
|
||||
[O_SET_MARK] = MARK_SET_VALUE,
|
||||
[O_AND_MARK] = MARK_AND_VALUE,
|
||||
[O_OR_MARK] = MARK_OR_VALUE,
|
||||
[O_XOR_MARK] = MARK_XOR_VALUE,
|
||||
};
|
||||
struct ebt_mark_t_info *info = cb->data;
|
||||
unsigned int tmp;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_MARK_TARGET:
|
||||
if (ebt_fill_target(cb->arg, &tmp))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Illegal --mark-target target");
|
||||
/* the 4 lsb are left to designate the target */
|
||||
info->target = (info->target & ~EBT_VERDICT_BITS) |
|
||||
(tmp & EBT_VERDICT_BITS);
|
||||
return;
|
||||
case O_SET_MARK:
|
||||
case O_OR_MARK:
|
||||
case O_AND_MARK:
|
||||
case O_XOR_MARK:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
/* mutual code */
|
||||
info->mark = cb->val.u32;
|
||||
info->target = (info->target & EBT_VERDICT_BITS) |
|
||||
target_orval[cb->entry->id];
|
||||
}
|
||||
|
||||
static void brmark_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data;
|
||||
int tmp;
|
||||
|
||||
tmp = info->target & ~EBT_VERDICT_BITS;
|
||||
if (tmp == MARK_SET_VALUE)
|
||||
printf("--mark-set");
|
||||
else if (tmp == MARK_OR_VALUE)
|
||||
printf("--mark-or");
|
||||
else if (tmp == MARK_XOR_VALUE)
|
||||
printf("--mark-xor");
|
||||
else if (tmp == MARK_AND_VALUE)
|
||||
printf("--mark-and");
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM, "Unknown mark action");
|
||||
|
||||
printf(" 0x%lx", info->mark);
|
||||
tmp = info->target | ~EBT_VERDICT_BITS;
|
||||
printf(" --mark-target %s", ebt_target_name(tmp));
|
||||
}
|
||||
|
||||
static void brmark_final_check(struct xt_fcheck_call *fc)
|
||||
{
|
||||
if (!fc->xflags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"You must specify some option");
|
||||
}
|
||||
|
||||
static const char* brmark_verdict(int verdict)
|
||||
{
|
||||
switch (verdict) {
|
||||
case EBT_ACCEPT: return "accept";
|
||||
case EBT_DROP: return "drop";
|
||||
case EBT_CONTINUE: return "continue";
|
||||
case EBT_RETURN: return "return";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static int brmark_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_tg_params *params)
|
||||
{
|
||||
const struct ebt_mark_t_info *info = (const void*)params->target->data;
|
||||
int tmp;
|
||||
|
||||
tmp = info->target & ~EBT_VERDICT_BITS;
|
||||
|
||||
xt_xlate_add(xl, "meta mark set ");
|
||||
|
||||
switch (tmp) {
|
||||
case MARK_SET_VALUE:
|
||||
break;
|
||||
case MARK_OR_VALUE:
|
||||
xt_xlate_add(xl, "meta mark or ");
|
||||
break;
|
||||
case MARK_XOR_VALUE:
|
||||
xt_xlate_add(xl, "meta mark xor ");
|
||||
break;
|
||||
case MARK_AND_VALUE:
|
||||
xt_xlate_add(xl, "meta mark and ");
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = info->target | ~EBT_VERDICT_BITS;
|
||||
xt_xlate_add(xl, "0x%lx %s ", info->mark, brmark_verdict(tmp));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_target brmark_target = {
|
||||
.name = "mark",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
|
||||
.help = brmark_print_help,
|
||||
.init = brmark_init,
|
||||
.x6_parse = brmark_parse,
|
||||
.x6_fcheck = brmark_final_check,
|
||||
.print = brmark_print,
|
||||
.xlate = brmark_xlate,
|
||||
.x6_options = brmark_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&brmark_target);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
-j mark --mark-set 1;-j mark --mark-set 0x1 --mark-target ACCEPT;OK
|
||||
-j mark --mark-or 0xa --mark-target CONTINUE;=;OK
|
||||
-j mark --mark-and 0x1 --mark-target RETURN;=;OK
|
||||
-j mark --mark-xor 0x1 --mark-target CONTINUE;=;OK
|
||||
@@ -0,0 +1,11 @@
|
||||
ebtables-translate -A INPUT -j mark --mark-set 42
|
||||
nft 'add rule bridge filter INPUT counter meta mark set 0x2a accept'
|
||||
|
||||
ebtables-translate -A INPUT -j mark --mark-or 42 --mark-target RETURN
|
||||
nft 'add rule bridge filter INPUT counter meta mark set meta mark or 0x2a return'
|
||||
|
||||
ebtables-translate -A INPUT -j mark --mark-and 42 --mark-target ACCEPT
|
||||
nft 'add rule bridge filter INPUT counter meta mark set meta mark and 0x2a accept'
|
||||
|
||||
ebtables-translate -A INPUT -j mark --mark-xor 42 --mark-target DROP
|
||||
nft 'add rule bridge filter INPUT counter meta mark set meta mark xor 0x2a drop'
|
||||
@@ -0,0 +1,118 @@
|
||||
/* ebt_mark_m
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* July, 2002
|
||||
*
|
||||
* Adapted by Arturo Borrero Gonzalez <arturo@debian.org>
|
||||
* to use libxtables for ebtables-compat in 2015.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_mark_m.h>
|
||||
|
||||
enum {
|
||||
O_MARK = 0,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brmark_m_opts[] = {
|
||||
{ .name = "mark", .id = O_MARK, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_INVERT | XTOPT_MAND },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brmark_m_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"mark option:\n"
|
||||
"[!] --mark [value][/mask]: Match nfmask value (see man page)\n");
|
||||
}
|
||||
|
||||
static void brmark_m_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_mark_m_info *info = cb->data;
|
||||
char *end;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
|
||||
switch (cb->entry->id) {
|
||||
case O_MARK:
|
||||
info->invert = cb->invert;
|
||||
info->mark = strtoul(cb->arg, &end, 0);
|
||||
info->bitmask = EBT_MARK_AND;
|
||||
if (*end == '/') {
|
||||
if (end == cb->arg)
|
||||
info->bitmask = EBT_MARK_OR;
|
||||
info->mask = strtoul(end+1, &end, 0);
|
||||
} else {
|
||||
info->mask = UINT32_MAX;
|
||||
}
|
||||
if (*end != '\0' || end == cb->arg)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad mark value '%s'",
|
||||
cb->arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void brmark_m_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
|
||||
|
||||
if (info->invert)
|
||||
printf("! ");
|
||||
printf("--mark ");
|
||||
if (info->bitmask == EBT_MARK_OR)
|
||||
printf("/0x%lx ", info->mask);
|
||||
else if (info->mask != 0xffffffff)
|
||||
printf("0x%lx/0x%lx ", info->mark, info->mask);
|
||||
else
|
||||
printf("0x%lx ", info->mark);
|
||||
}
|
||||
|
||||
static int brmark_m_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_mt_params *params)
|
||||
{
|
||||
const struct ebt_mark_m_info *info = (const void*)params->match->data;
|
||||
enum xt_op op = XT_OP_EQ;
|
||||
|
||||
if (info->invert)
|
||||
op = XT_OP_NEQ;
|
||||
|
||||
xt_xlate_add(xl, "meta mark ");
|
||||
|
||||
if (info->bitmask == EBT_MARK_OR) {
|
||||
xt_xlate_add(xl, "and 0x%x %s0 ", (uint32_t)info->mask,
|
||||
info->invert ? "" : "!= ");
|
||||
} else if (info->mask != UINT32_MAX) {
|
||||
xt_xlate_add(xl, "and 0x%x %s0x%x ", (uint32_t)info->mask,
|
||||
op == XT_OP_EQ ? "" : "!= ", (uint32_t)info->mark);
|
||||
} else {
|
||||
xt_xlate_add(xl, "%s0x%x ",
|
||||
op == XT_OP_EQ ? "" : "!= ", (uint32_t)info->mark);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
static struct xtables_match brmark_m_match = {
|
||||
.name = "mark_m",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
|
||||
.help = brmark_m_print_help,
|
||||
.x6_parse = brmark_m_parse,
|
||||
.print = brmark_m_print,
|
||||
.xlate = brmark_m_xlate,
|
||||
.x6_options = brmark_m_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brmark_m_match);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
--mark 42;--mark 0x2a;OK
|
||||
! --mark 42;! --mark 0x2a;OK
|
||||
--mark 42/0xff;--mark 0x2a/0xff;OK
|
||||
! --mark 0x1/0xff;=;OK
|
||||
--mark /0x2;=;OK
|
||||
@@ -0,0 +1,14 @@
|
||||
ebtables-translate -A INPUT --mark 42
|
||||
nft 'add rule bridge filter INPUT meta mark 0x2a counter'
|
||||
|
||||
ebtables-translate -A INPUT ! --mark 42
|
||||
nft 'add rule bridge filter INPUT meta mark != 0x2a counter'
|
||||
|
||||
ebtables-translate -A INPUT --mark ! 42
|
||||
nft 'add rule bridge filter INPUT meta mark != 0x2a counter'
|
||||
|
||||
ebtables-translate -A INPUT ! --mark 0x1/0xff
|
||||
nft 'add rule bridge filter INPUT meta mark and 0xff != 0x1 counter'
|
||||
|
||||
ebtables-translate -A INPUT --mark /0x02
|
||||
nft 'add rule bridge filter INPUT meta mark and 0x2 != 0 counter'
|
||||
@@ -0,0 +1,119 @@
|
||||
/* ebt_nflog
|
||||
*
|
||||
* Authors:
|
||||
* Peter Warasin <peter@endian.com>
|
||||
*
|
||||
* February, 2008
|
||||
*
|
||||
* Based on:
|
||||
* ebt_ulog.c, (C) 2004, Bart De Schuymer <bdschuym@pandora.be>
|
||||
* libxt_NFLOG.c
|
||||
*
|
||||
* Adapted to libxtables for ebtables-compat in 2015 by
|
||||
* Arturo Borrero Gonzalez <arturo@debian.org>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
#include <linux/netfilter_bridge/ebt_nflog.h>
|
||||
|
||||
enum {
|
||||
O_GROUP = 0,
|
||||
O_PREFIX,
|
||||
O_RANGE,
|
||||
O_THRESHOLD,
|
||||
O_NFLOG,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brnflog_opts[] = {
|
||||
{ .name = "nflog-group", .id = O_GROUP, .type = XTTYPE_UINT16,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, group) },
|
||||
{ .name = "nflog-prefix", .id = O_PREFIX, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, prefix) },
|
||||
{ .name = "nflog-range", .id = O_RANGE, .type = XTTYPE_UINT32,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, len) },
|
||||
{ .name = "nflog-threshold", .id = O_THRESHOLD, .type = XTTYPE_UINT16,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nflog_info, threshold) },
|
||||
{ .name = "nflog", .id = O_NFLOG, .type = XTTYPE_NONE },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brnflog_help(void)
|
||||
{
|
||||
printf("nflog options:\n"
|
||||
"--nflog : use the default nflog parameters\n"
|
||||
"--nflog-prefix prefix : Prefix string for log message\n"
|
||||
"--nflog-group group : NETLINK group used for logging\n"
|
||||
"--nflog-range range : Number of byte to copy\n"
|
||||
"--nflog-threshold : Message threshold of"
|
||||
"in-kernel queue\n");
|
||||
}
|
||||
|
||||
static void brnflog_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ebt_nflog_info *info = (struct ebt_nflog_info *)t->data;
|
||||
|
||||
info->prefix[0] = '\0';
|
||||
info->group = EBT_NFLOG_DEFAULT_GROUP;
|
||||
info->threshold = EBT_NFLOG_DEFAULT_THRESHOLD;
|
||||
}
|
||||
|
||||
static void
|
||||
brnflog_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_nflog_info *info = (struct ebt_nflog_info *)target->data;
|
||||
|
||||
if (info->prefix[0] != '\0')
|
||||
printf("--nflog-prefix \"%s\" ", info->prefix);
|
||||
if (info->group)
|
||||
printf("--nflog-group %d ", info->group);
|
||||
if (info->len)
|
||||
printf("--nflog-range %d ", info->len);
|
||||
if (info->threshold != EBT_NFLOG_DEFAULT_THRESHOLD)
|
||||
printf("--nflog-threshold %d ", info->threshold);
|
||||
}
|
||||
|
||||
static int brnflog_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_tg_params *params)
|
||||
{
|
||||
const struct ebt_nflog_info *info = (void *)params->target->data;
|
||||
|
||||
xt_xlate_add(xl, "log ");
|
||||
if (info->prefix[0] != '\0')
|
||||
xt_xlate_add(xl, "prefix \"%s\" ", info->prefix);
|
||||
|
||||
xt_xlate_add(xl, "group %u ", info->group);
|
||||
|
||||
if (info->len)
|
||||
xt_xlate_add(xl, "snaplen %u ", info->len);
|
||||
if (info->threshold != EBT_NFLOG_DEFAULT_THRESHOLD)
|
||||
xt_xlate_add(xl, "queue-threshold %u ", info->threshold);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_target brnflog_watcher = {
|
||||
.name = "nflog",
|
||||
.revision = 0,
|
||||
.ext_flags = XTABLES_EXT_WATCHER,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_nflog_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_nflog_info)),
|
||||
.init = brnflog_init,
|
||||
.help = brnflog_help,
|
||||
.x6_parse = xtables_option_parse,
|
||||
.print = brnflog_print,
|
||||
.xlate = brnflog_xlate,
|
||||
.x6_options = brnflog_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&brnflog_watcher);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
--nflog;--nflog-group 1;OK
|
||||
--nflog-group 42;=;OK
|
||||
--nflog-range 42;--nflog-group 1 --nflog-range 42 -j CONTINUE;OK
|
||||
--nflog-threshold 100 --nflog-prefix foo;--nflog-prefix "foo" --nflog-group 1 --nflog-threshold 100 -j CONTINUE;OK
|
||||
@@ -0,0 +1,11 @@
|
||||
ebtables-translate -A INPUT --nflog
|
||||
nft 'add rule bridge filter INPUT log group 1 counter'
|
||||
|
||||
ebtables-translate -A INPUT --nflog-group 42
|
||||
nft 'add rule bridge filter INPUT log group 42 counter'
|
||||
|
||||
ebtables-translate -A INPUT --nflog-range 42
|
||||
nft 'add rule bridge filter INPUT log group 1 snaplen 42 counter'
|
||||
|
||||
ebtables-translate -A INPUT --nflog-threshold 100 --nflog-prefix foo
|
||||
nft 'add rule bridge filter INPUT log prefix "foo" group 1 queue-threshold 100 counter'
|
||||
@@ -0,0 +1,120 @@
|
||||
/* ebt_pkttype
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* April, 2003
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/netfilter_bridge/ebt_pkttype.h>
|
||||
|
||||
static const char *classes[] = {
|
||||
"host",
|
||||
"broadcast",
|
||||
"multicast",
|
||||
"otherhost",
|
||||
"outgoing",
|
||||
"loopback",
|
||||
"fastroute",
|
||||
};
|
||||
|
||||
enum {
|
||||
O_TYPE,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brpkttype_opts[] = {
|
||||
{ .name = "pkttype-type", .id = O_TYPE, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_INVERT },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brpkttype_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"pkttype options:\n"
|
||||
"[!] --pkttype-type type: class the packet belongs to\n"
|
||||
"Possible values: broadcast, multicast, host, otherhost, or any other byte value (which would be pretty useless).\n");
|
||||
}
|
||||
|
||||
|
||||
static void brpkttype_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_pkttype_info *ptinfo = cb->data;
|
||||
long int i;
|
||||
char *end;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
|
||||
switch (cb->entry->id) {
|
||||
case O_TYPE:
|
||||
ptinfo->invert = cb->invert;
|
||||
i = strtol(cb->arg, &end, 16);
|
||||
if (*end != '\0') {
|
||||
for (i = 0; i < ARRAY_SIZE(classes); i++) {
|
||||
if (!strcasecmp(cb->arg, classes[i]))
|
||||
break;
|
||||
}
|
||||
if (i >= ARRAY_SIZE(classes))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Could not parse class '%s'",
|
||||
cb->arg);
|
||||
}
|
||||
if (i < 0 || i > 255)
|
||||
xtables_error(PARAMETER_PROBLEM, "Problem with specified pkttype class");
|
||||
ptinfo->pkt_type = (uint8_t)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void brpkttype_print(const void *ip, const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
struct ebt_pkttype_info *pt = (struct ebt_pkttype_info *)match->data;
|
||||
|
||||
printf("%s--pkttype-type ", pt->invert ? "! " : "");
|
||||
|
||||
if (pt->pkt_type < ARRAY_SIZE(classes))
|
||||
printf("%s ", classes[pt->pkt_type]);
|
||||
else
|
||||
printf("%d ", pt->pkt_type);
|
||||
}
|
||||
|
||||
static int brpkttype_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_mt_params *params)
|
||||
{
|
||||
const struct ebt_pkttype_info *info = (const void*)params->match->data;
|
||||
|
||||
xt_xlate_add(xl, "meta pkttype %s", info->invert ? "!= " : "");
|
||||
|
||||
if (info->pkt_type < 3)
|
||||
xt_xlate_add(xl, "%s ", classes[info->pkt_type]);
|
||||
else if (info->pkt_type == 3)
|
||||
xt_xlate_add(xl, "other ");
|
||||
else
|
||||
xt_xlate_add(xl, "%d ", info->pkt_type);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_match brpkttype_match = {
|
||||
.name = "pkttype",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_pkttype_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_pkttype_info)),
|
||||
.help = brpkttype_print_help,
|
||||
.x6_parse = brpkttype_parse,
|
||||
.print = brpkttype_print,
|
||||
.xlate = brpkttype_xlate,
|
||||
.x6_options = brpkttype_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brpkttype_match);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
--pkttype-type ! host;! --pkttype-type host -j CONTINUE;OK
|
||||
--pkttype-type host;=;OK
|
||||
! --pkttype-type host;=;OK
|
||||
--pkttype-type broadcast;=;OK
|
||||
! --pkttype-type broadcast;=;OK
|
||||
--pkttype-type multicast;=;OK
|
||||
! --pkttype-type multicast;=;OK
|
||||
--pkttype-type otherhost;=;OK
|
||||
! --pkttype-type otherhost;=;OK
|
||||
--pkttype-type outgoing;=;OK
|
||||
! --pkttype-type outgoing;=;OK
|
||||
--pkttype-type loopback;=;OK
|
||||
! --pkttype-type loopback;=;OK
|
||||
@@ -0,0 +1,20 @@
|
||||
ebtables-translate -A INPUT --pkttype-type host
|
||||
nft 'add rule bridge filter INPUT meta pkttype host counter'
|
||||
|
||||
ebtables-translate -A INPUT ! --pkttype-type broadcast
|
||||
nft 'add rule bridge filter INPUT meta pkttype != broadcast counter'
|
||||
|
||||
ebtables-translate -A INPUT --pkttype-type ! multicast
|
||||
nft 'add rule bridge filter INPUT meta pkttype != multicast counter'
|
||||
|
||||
ebtables-translate -A INPUT --pkttype-type otherhost
|
||||
nft 'add rule bridge filter INPUT meta pkttype other counter'
|
||||
|
||||
ebtables-translate -A INPUT --pkttype-type outgoing
|
||||
nft 'add rule bridge filter INPUT meta pkttype 4 counter'
|
||||
|
||||
ebtables-translate -A INPUT --pkttype-type loopback
|
||||
nft 'add rule bridge filter INPUT meta pkttype 5 counter'
|
||||
|
||||
ebtables-translate -A INPUT --pkttype-type fastroute
|
||||
nft 'add rule bridge filter INPUT meta pkttype 6 counter'
|
||||
@@ -0,0 +1,103 @@
|
||||
/* ebt_redirect
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* April, 2002
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_redirect.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
enum {
|
||||
O_TARGET,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brredir_opts[] =
|
||||
{
|
||||
{ .name = "redirect-target", .id = O_TARGET, .type = XTTYPE_STRING },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brredir_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"redirect option:\n"
|
||||
" --redirect-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
|
||||
}
|
||||
|
||||
static void brredir_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct ebt_redirect_info *redirectinfo =
|
||||
(struct ebt_redirect_info *)target->data;
|
||||
|
||||
redirectinfo->target = EBT_ACCEPT;
|
||||
}
|
||||
|
||||
static void brredir_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_redirect_info *redirectinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
if (cb->entry->id == O_TARGET &&
|
||||
ebt_fill_target(cb->arg, (unsigned int *)&redirectinfo->target))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Illegal --redirect-target target");
|
||||
}
|
||||
|
||||
static void brredir_print(const void *ip, const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
struct ebt_redirect_info *redirectinfo =
|
||||
(struct ebt_redirect_info *)target->data;
|
||||
|
||||
if (redirectinfo->target == EBT_ACCEPT)
|
||||
return;
|
||||
printf("--redirect-target %s", ebt_target_name(redirectinfo->target));
|
||||
}
|
||||
|
||||
static const char* brredir_verdict(int verdict)
|
||||
{
|
||||
switch (verdict) {
|
||||
case EBT_ACCEPT: return "accept";
|
||||
case EBT_DROP: return "drop";
|
||||
case EBT_CONTINUE: return "continue";
|
||||
case EBT_RETURN: return "return";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static int brredir_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_tg_params *params)
|
||||
{
|
||||
const struct ebt_redirect_info *red = (const void*)params->target->data;
|
||||
|
||||
xt_xlate_add(xl, "meta pkttype set host");
|
||||
if (red->target != EBT_CONTINUE)
|
||||
xt_xlate_add(xl, " %s ", brredir_verdict(red->target));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_target brredirect_target = {
|
||||
.name = "redirect",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_redirect_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_redirect_info)),
|
||||
.help = brredir_print_help,
|
||||
.init = brredir_init,
|
||||
.x6_parse = brredir_parse,
|
||||
.print = brredir_print,
|
||||
.xlate = brredir_xlate,
|
||||
.x6_options = brredir_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&brredirect_target);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
:PREROUTING
|
||||
*nat
|
||||
-j redirect ;=;OK
|
||||
-j redirect --redirect-target RETURN;=;OK
|
||||
@@ -0,0 +1,8 @@
|
||||
ebtables-translate -t nat -A PREROUTING -d de:ad:00:00:be:ef -j redirect
|
||||
nft 'add rule bridge nat PREROUTING ether daddr de:ad:00:00:be:ef counter meta pkttype set host accept'
|
||||
|
||||
ebtables-translate -t nat -A PREROUTING -d de:ad:00:00:be:ef -j redirect --redirect-target RETURN
|
||||
nft 'add rule bridge nat PREROUTING ether daddr de:ad:00:00:be:ef counter meta pkttype set host return'
|
||||
|
||||
ebtables-translate -t nat -A PREROUTING -d de:ad:00:00:be:ef -j redirect --redirect-target CONTINUE
|
||||
nft 'add rule bridge nat PREROUTING ether daddr de:ad:00:00:be:ef counter meta pkttype set host'
|
||||
@@ -0,0 +1,136 @@
|
||||
/* ebt_nat
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* June, 2002
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_nat.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
enum {
|
||||
O_SRC,
|
||||
O_TARGET,
|
||||
O_ARP,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brsnat_opts[] =
|
||||
{
|
||||
{ .name = "to-source", .id = O_SRC, .type = XTTYPE_ETHERMAC,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
|
||||
{ .name = "to-src", .id = O_SRC, .type = XTTYPE_ETHERMAC,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ebt_nat_info, mac) },
|
||||
{ .name = "snat-target", .id = O_TARGET, .type = XTTYPE_STRING },
|
||||
{ .name = "snat-arp", .id = O_ARP, .type = XTTYPE_NONE },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brsnat_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"snat options:\n"
|
||||
" --to-src address : MAC address to map source to\n"
|
||||
" --snat-target target : ACCEPT, DROP, RETURN or CONTINUE\n"
|
||||
" --snat-arp : also change src address in arp msg\n");
|
||||
}
|
||||
|
||||
static void brsnat_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
|
||||
|
||||
natinfo->target = EBT_ACCEPT;
|
||||
}
|
||||
|
||||
static void brsnat_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_nat_info *natinfo = cb->data;
|
||||
unsigned int tmp;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TARGET:
|
||||
if (ebt_fill_target(cb->arg, &tmp))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Illegal --snat-target target");
|
||||
natinfo->target &= ~EBT_VERDICT_BITS;
|
||||
natinfo->target |= tmp & EBT_VERDICT_BITS;
|
||||
break;
|
||||
case O_ARP:
|
||||
natinfo->target ^= NAT_ARP_BIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void brsnat_final_check(struct xt_fcheck_call *fc)
|
||||
{
|
||||
if (!fc->xflags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"You must specify proper arguments");
|
||||
}
|
||||
|
||||
static void brsnat_print(const void *ip, const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
|
||||
|
||||
printf("--to-src ");
|
||||
xtables_print_mac(natinfo->mac);
|
||||
if (!(natinfo->target&NAT_ARP_BIT))
|
||||
printf(" --snat-arp");
|
||||
printf(" --snat-target %s", ebt_target_name((natinfo->target|~EBT_VERDICT_BITS)));
|
||||
}
|
||||
|
||||
static const char* brsnat_verdict(int verdict)
|
||||
{
|
||||
switch (verdict) {
|
||||
case EBT_ACCEPT: return "accept";
|
||||
case EBT_DROP: return "drop";
|
||||
case EBT_CONTINUE: return "continue";
|
||||
case EBT_RETURN: return "return";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static int brsnat_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_tg_params *params)
|
||||
{
|
||||
const struct ebt_nat_info *natinfo = (const void*)params->target->data;
|
||||
|
||||
xt_xlate_add(xl, "ether saddr set %s ",
|
||||
ether_ntoa((struct ether_addr *)natinfo->mac));
|
||||
|
||||
/* NAT_ARP_BIT set -> no arp mangling, not set -> arp mangling (yes, its inverted) */
|
||||
if (!(natinfo->target&NAT_ARP_BIT))
|
||||
return 0;
|
||||
|
||||
xt_xlate_add(xl, "%s ", brsnat_verdict(natinfo->target | ~EBT_VERDICT_BITS));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_target brsnat_target =
|
||||
{
|
||||
.name = "snat",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_nat_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_nat_info)),
|
||||
.help = brsnat_print_help,
|
||||
.init = brsnat_init,
|
||||
.x6_parse = brsnat_parse,
|
||||
.x6_fcheck = brsnat_final_check,
|
||||
.print = brsnat_print,
|
||||
.xlate = brsnat_xlate,
|
||||
.x6_options = brsnat_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&brsnat_target);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
:POSTROUTING
|
||||
*nat
|
||||
-o someport -j snat --to-source a:b:c:d:e:f;-o someport -j snat --to-src 0a:0b:0c:0d:0e:0f --snat-target ACCEPT;OK
|
||||
-o someport+ -j snat --to-src de:ad:00:be:ee:ff --snat-target CONTINUE;=;OK
|
||||
-j snat;;FAIL
|
||||
-j snat --to-src de:ad:00:be:ee:ff;-j snat --to-src de:ad:00:be:ee:ff --snat-target ACCEPT;OK
|
||||
@@ -0,0 +1,5 @@
|
||||
ebtables-translate -t nat -A POSTROUTING -s 0:0:0:0:0:0 -o someport+ -j snat --to-source de:ad:00:be:ee:ff
|
||||
nft 'add rule bridge nat POSTROUTING oifname "someport*" ether saddr 00:00:00:00:00:00 counter ether saddr set de:ad:0:be:ee:ff accept'
|
||||
|
||||
ebtables-translate -t nat -A POSTROUTING -o someport -j snat --to-src de:ad:00:be:ee:ff --snat-target CONTINUE
|
||||
nft 'add rule bridge nat POSTROUTING oifname "someport" counter ether saddr set de:ad:0:be:ee:ff continue'
|
||||
@@ -0,0 +1,40 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
-d de:ad:be:ef:00:00;=;OK
|
||||
-s 0:0:0:0:0:0;-s 00:00:00:00:00:00;OK
|
||||
-d 00:00:00:00:00:00;=;OK
|
||||
-s de:ad:be:ef:0:00 -j RETURN;-s de:ad:be:ef:00:00 -j RETURN;OK
|
||||
-d de:ad:be:ef:00:00 -j CONTINUE;=;OK
|
||||
-d de:ad:be:ef:0:00/ff:ff:ff:ff:0:0 -j DROP;-d de:ad:be:ef:00:00/ff:ff:ff:ff:00:00 -j DROP;OK
|
||||
-p ARP -j ACCEPT;=;OK
|
||||
! -p ARP -j ACCEPT;=;OK
|
||||
-p ! ARP -j ACCEPT;! -p ARP -j ACCEPT;OK
|
||||
-p 0 -j ACCEPT;=;FAIL
|
||||
-p ! 0 -j ACCEPT;=;FAIL
|
||||
:INPUT
|
||||
-i foobar;=;OK
|
||||
-o foobar;=;FAIL
|
||||
--logical-in br0;=;OK
|
||||
--logical-out br1;=;FAIL
|
||||
-i + -d 00:0f:ee:d0:ba:be;-d 00:0f:ee:d0:ba:be;OK
|
||||
-i + -p ip;-p IPv4;OK
|
||||
! -i +;=;OK
|
||||
--logical-in + -d 00:0f:ee:d0:ba:be;-d 00:0f:ee:d0:ba:be;OK
|
||||
--logical-in + -p ip;-p IPv4;OK
|
||||
! --logical-in +;=;OK
|
||||
:FORWARD
|
||||
-i foobar;=;OK
|
||||
-o foobar;=;OK
|
||||
--logical-in br0 --logical-out br1;=;OK
|
||||
:OUTPUT
|
||||
-i foobar;=;FAIL
|
||||
-o foobar;=;OK
|
||||
--logical-in br0;=;FAIL
|
||||
--logical-out br1;=;OK
|
||||
:PREROUTING
|
||||
*nat
|
||||
-i foobar;=;OK
|
||||
-o foobar;=;FAIL
|
||||
:POSTROUTING
|
||||
*nat
|
||||
-i foobar;=;FAIL
|
||||
-o foobar;=;OK
|
||||
@@ -0,0 +1,241 @@
|
||||
/* ebt_stp
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* July, 2003
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <linux/netfilter_bridge/ebt_stp.h>
|
||||
#include <xtables.h>
|
||||
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
/* These must correspond to the bit position in EBT_STP_* defines */
|
||||
enum {
|
||||
O_TYPE = 0,
|
||||
O_FLAGS,
|
||||
O_RPRIO,
|
||||
O_RADDR,
|
||||
O_RCOST,
|
||||
O_SPRIO,
|
||||
O_SADDR,
|
||||
O_PORT,
|
||||
O_MSGAGE,
|
||||
O_MAXAGE,
|
||||
O_HTIME,
|
||||
O_FWDD,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry brstp_opts[] = {
|
||||
#define ENTRY(n, i, t) { .name = n, .id = i, .type = t, .flags = XTOPT_INVERT }
|
||||
ENTRY("stp-type", O_TYPE, XTTYPE_STRING),
|
||||
ENTRY("stp-flags", O_FLAGS, XTTYPE_STRING),
|
||||
ENTRY("stp-root-prio", O_RPRIO, XTTYPE_UINT16RC),
|
||||
ENTRY("stp-root-addr", O_RADDR, XTTYPE_ETHERMACMASK),
|
||||
ENTRY("stp-root-cost", O_RCOST, XTTYPE_UINT32RC),
|
||||
ENTRY("stp-sender-prio", O_SPRIO, XTTYPE_UINT16RC),
|
||||
ENTRY("stp-sender-addr", O_SADDR, XTTYPE_ETHERMACMASK),
|
||||
ENTRY("stp-port", O_PORT, XTTYPE_UINT16RC),
|
||||
ENTRY("stp-msg-age", O_MSGAGE, XTTYPE_UINT16RC),
|
||||
ENTRY("stp-max-age", O_MAXAGE, XTTYPE_UINT16RC),
|
||||
ENTRY("stp-hello-time", O_HTIME, XTTYPE_UINT16RC),
|
||||
ENTRY("stp-forward-delay", O_FWDD, XTTYPE_UINT16RC),
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
#define BPDU_TYPE_CONFIG 0
|
||||
#define BPDU_TYPE_TCN 0x80
|
||||
#define BPDU_TYPE_CONFIG_STRING "config"
|
||||
#define BPDU_TYPE_TCN_STRING "tcn"
|
||||
|
||||
#define FLAG_TC 0x01
|
||||
#define FLAG_TC_ACK 0x80
|
||||
#define FLAG_TC_STRING "topology-change"
|
||||
#define FLAG_TC_ACK_STRING "topology-change-ack"
|
||||
|
||||
static void brstp_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"stp options:\n"
|
||||
"[!] --stp-type type : BPDU type\n"
|
||||
"[!] --stp-flags flag : control flag\n"
|
||||
"[!] --stp-root-prio prio[:prio] : root priority (16-bit) range\n"
|
||||
"[!] --stp-root-addr address[/mask] : MAC address of root\n"
|
||||
"[!] --stp-root-cost cost[:cost] : root cost (32-bit) range\n"
|
||||
"[!] --stp-sender-prio prio[:prio] : sender priority (16-bit) range\n"
|
||||
"[!] --stp-sender-addr address[/mask] : MAC address of sender\n"
|
||||
"[!] --stp-port port[:port] : port id (16-bit) range\n"
|
||||
"[!] --stp-msg-age age[:age] : message age timer (16-bit) range\n"
|
||||
"[!] --stp-max-age age[:age] : maximum age timer (16-bit) range\n"
|
||||
"[!] --stp-hello-time time[:time] : hello time timer (16-bit) range\n"
|
||||
"[!] --stp-forward-delay delay[:delay]: forward delay timer (16-bit) range\n"
|
||||
" Recognized BPDU type strings:\n"
|
||||
" \"config\": configuration BPDU (=0)\n"
|
||||
" \"tcn\" : topology change notification BPDU (=0x80)\n"
|
||||
" Recognized control flag strings:\n"
|
||||
" \"topology-change\" : topology change flag (0x01)\n"
|
||||
" \"topology-change-ack\": topology change acknowledgement flag (0x80)");
|
||||
}
|
||||
|
||||
static void print_range(unsigned int l, unsigned int u)
|
||||
{
|
||||
if (l == u)
|
||||
printf("%u", l);
|
||||
else
|
||||
printf("%u:%u", l, u);
|
||||
}
|
||||
|
||||
static void brstp_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_stp_info *stpinfo = cb->data;
|
||||
char *end = NULL;
|
||||
long int i;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
|
||||
stpinfo->bitmask |= 1 << cb->entry->id;
|
||||
if (cb->invert)
|
||||
stpinfo->invflags |= 1 << cb->entry->id;
|
||||
|
||||
switch (cb->entry->id) {
|
||||
case O_TYPE:
|
||||
i = strtol(cb->arg, &end, 0);
|
||||
if (i < 0 || i > 255 || *end != '\0') {
|
||||
if (!strcasecmp(cb->arg, BPDU_TYPE_CONFIG_STRING))
|
||||
stpinfo->type = BPDU_TYPE_CONFIG;
|
||||
else if (!strcasecmp(cb->arg, BPDU_TYPE_TCN_STRING))
|
||||
stpinfo->type = BPDU_TYPE_TCN;
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad --stp-type argument");
|
||||
} else
|
||||
stpinfo->type = i;
|
||||
break;
|
||||
case O_FLAGS:
|
||||
i = strtol(cb->arg, &end, 0);
|
||||
if (i < 0 || i > 255 || *end != '\0') {
|
||||
if (!strcasecmp(cb->arg, FLAG_TC_STRING))
|
||||
stpinfo->config.flags = FLAG_TC;
|
||||
else if (!strcasecmp(cb->arg, FLAG_TC_ACK_STRING))
|
||||
stpinfo->config.flags = FLAG_TC_ACK;
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad --stp-flags argument");
|
||||
} else
|
||||
stpinfo->config.flags = i;
|
||||
break;
|
||||
case O_RADDR:
|
||||
memcpy(stpinfo->config.root_addr, cb->val.ethermac, ETH_ALEN);
|
||||
memcpy(stpinfo->config.root_addrmsk,
|
||||
cb->val.ethermacmask, ETH_ALEN);
|
||||
break;
|
||||
case O_SADDR:
|
||||
memcpy(stpinfo->config.sender_addr, cb->val.ethermac, ETH_ALEN);
|
||||
memcpy(stpinfo->config.sender_addrmsk,
|
||||
cb->val.ethermacmask, ETH_ALEN);
|
||||
break;
|
||||
|
||||
#define RANGE_ASSIGN(fname, val) { \
|
||||
stpinfo->config.fname##l = val[0]; \
|
||||
stpinfo->config.fname##u = cb->nvals > 1 ? val[1] : val[0]; \
|
||||
}
|
||||
case O_RPRIO:
|
||||
RANGE_ASSIGN(root_prio, cb->val.u16_range);
|
||||
break;
|
||||
case O_RCOST:
|
||||
RANGE_ASSIGN(root_cost, cb->val.u32_range);
|
||||
break;
|
||||
case O_SPRIO:
|
||||
RANGE_ASSIGN(sender_prio, cb->val.u16_range);
|
||||
break;
|
||||
case O_PORT:
|
||||
RANGE_ASSIGN(port, cb->val.u16_range);
|
||||
break;
|
||||
case O_MSGAGE:
|
||||
RANGE_ASSIGN(msg_age, cb->val.u16_range);
|
||||
break;
|
||||
case O_MAXAGE:
|
||||
RANGE_ASSIGN(max_age, cb->val.u16_range);
|
||||
break;
|
||||
case O_HTIME:
|
||||
RANGE_ASSIGN(hello_time, cb->val.u16_range);
|
||||
break;
|
||||
case O_FWDD:
|
||||
RANGE_ASSIGN(forward_delay, cb->val.u16_range);
|
||||
break;
|
||||
#undef RANGE_ASSIGN
|
||||
}
|
||||
}
|
||||
|
||||
static void brstp_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)match->data;
|
||||
const struct ebt_stp_config_info *c = &(stpinfo->config);
|
||||
int i;
|
||||
|
||||
for (i = 0; (1 << i) < EBT_STP_MASK; i++) {
|
||||
if (!(stpinfo->bitmask & (1 << i)))
|
||||
continue;
|
||||
printf("%s--%s ",
|
||||
(stpinfo->invflags & (1 << i)) ? "! " : "",
|
||||
brstp_opts[i].name);
|
||||
if (EBT_STP_TYPE == (1 << i)) {
|
||||
if (stpinfo->type == BPDU_TYPE_CONFIG)
|
||||
printf("%s", BPDU_TYPE_CONFIG_STRING);
|
||||
else if (stpinfo->type == BPDU_TYPE_TCN)
|
||||
printf("%s", BPDU_TYPE_TCN_STRING);
|
||||
else
|
||||
printf("%d", stpinfo->type);
|
||||
} else if (EBT_STP_FLAGS == (1 << i)) {
|
||||
if (c->flags == FLAG_TC)
|
||||
printf("%s", FLAG_TC_STRING);
|
||||
else if (c->flags == FLAG_TC_ACK)
|
||||
printf("%s", FLAG_TC_ACK_STRING);
|
||||
else
|
||||
printf("%d", c->flags);
|
||||
} else if (EBT_STP_ROOTPRIO == (1 << i))
|
||||
print_range(c->root_priol, c->root_priou);
|
||||
else if (EBT_STP_ROOTADDR == (1 << i))
|
||||
xtables_print_mac_and_mask((unsigned char *)c->root_addr,
|
||||
(unsigned char*)c->root_addrmsk);
|
||||
else if (EBT_STP_ROOTCOST == (1 << i))
|
||||
print_range(c->root_costl, c->root_costu);
|
||||
else if (EBT_STP_SENDERPRIO == (1 << i))
|
||||
print_range(c->sender_priol, c->sender_priou);
|
||||
else if (EBT_STP_SENDERADDR == (1 << i))
|
||||
xtables_print_mac_and_mask((unsigned char *)c->sender_addr,
|
||||
(unsigned char *)c->sender_addrmsk);
|
||||
else if (EBT_STP_PORT == (1 << i))
|
||||
print_range(c->portl, c->portu);
|
||||
else if (EBT_STP_MSGAGE == (1 << i))
|
||||
print_range(c->msg_agel, c->msg_ageu);
|
||||
else if (EBT_STP_MAXAGE == (1 << i))
|
||||
print_range(c->max_agel, c->max_ageu);
|
||||
else if (EBT_STP_HELLOTIME == (1 << i))
|
||||
print_range(c->hello_timel, c->hello_timeu);
|
||||
else if (EBT_STP_FWDD == (1 << i))
|
||||
print_range(c->forward_delayl, c->forward_delayu);
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_match brstp_match = {
|
||||
.name = "stp",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = sizeof(struct ebt_stp_info),
|
||||
.help = brstp_print_help,
|
||||
.x6_parse = brstp_parse,
|
||||
.print = brstp_print,
|
||||
.x6_options = brstp_opts
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brstp_match);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
--stp-type 1;=;OK
|
||||
! --stp-type 1;=;OK
|
||||
--stp-flags 0x1;--stp-flags topology-change -j CONTINUE;OK
|
||||
! --stp-flags topology-change;=;OK
|
||||
--stp-root-prio 1 -j ACCEPT;=;OK
|
||||
! --stp-root-prio 1 -j ACCEPT;=;OK
|
||||
--stp-root-addr 0d:ea:d0:0b:ee:f0;=;OK
|
||||
! --stp-root-addr 0d:ea:d0:0b:ee:f0;=;OK
|
||||
--stp-root-addr 0d:ea:d0:00:00:00/ff:ff:ff:00:00:00;=;OK
|
||||
! --stp-root-addr 0d:ea:d0:00:00:00/ff:ff:ff:00:00:00;=;OK
|
||||
--stp-root-cost 1;=;OK
|
||||
! --stp-root-cost 1;=;OK
|
||||
--stp-sender-prio 1;=;OK
|
||||
! --stp-sender-prio 1;=;OK
|
||||
--stp-sender-addr de:ad:be:ef:00:00;=;OK
|
||||
! --stp-sender-addr de:ad:be:ef:00:00;=;OK
|
||||
--stp-sender-addr de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
|
||||
! --stp-sender-addr de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
|
||||
--stp-port 1;=;OK
|
||||
! --stp-port 1;=;OK
|
||||
--stp-msg-age 1;=;OK
|
||||
! --stp-msg-age 1;=;OK
|
||||
--stp-max-age 1;=;OK
|
||||
! --stp-max-age 1;=;OK
|
||||
--stp-hello-time 1;=;OK
|
||||
! --stp-hello-time 1;=;OK
|
||||
--stp-forward-delay 1;=;OK
|
||||
! --stp-forward-delay 1;=;OK
|
||||
--stp-root-prio :2;--stp-root-prio 0:2;OK
|
||||
--stp-root-prio 2:;--stp-root-prio 2:65535;OK
|
||||
--stp-root-prio 1:2;=;OK
|
||||
--stp-root-prio 1:1;--stp-root-prio 1;OK
|
||||
--stp-root-prio 2:1;;FAIL
|
||||
--stp-root-cost :2;--stp-root-cost 0:2;OK
|
||||
--stp-root-cost 2:;--stp-root-cost 2:4294967295;OK
|
||||
--stp-root-cost 1:2;=;OK
|
||||
--stp-root-cost 1:1;--stp-root-cost 1;OK
|
||||
--stp-root-cost 2:1;;FAIL
|
||||
--stp-sender-prio :2;--stp-sender-prio 0:2;OK
|
||||
--stp-sender-prio 2:;--stp-sender-prio 2:65535;OK
|
||||
--stp-sender-prio 1:2;=;OK
|
||||
--stp-sender-prio 1:1;--stp-sender-prio 1;OK
|
||||
--stp-sender-prio 2:1;;FAIL
|
||||
--stp-port :;--stp-port 0:65535;OK
|
||||
--stp-port :2;--stp-port 0:2;OK
|
||||
--stp-port 2:;--stp-port 2:65535;OK
|
||||
--stp-port 1:2;=;OK
|
||||
--stp-port 1:1;--stp-port 1;OK
|
||||
--stp-port 2:1;;FAIL
|
||||
--stp-msg-age :;--stp-msg-age 0:65535;OK
|
||||
--stp-msg-age :2;--stp-msg-age 0:2;OK
|
||||
--stp-msg-age 2:;--stp-msg-age 2:65535;OK
|
||||
--stp-msg-age 1:2;=;OK
|
||||
--stp-msg-age 1:1;--stp-msg-age 1;OK
|
||||
--stp-msg-age 2:1;;FAIL
|
||||
--stp-max-age :;--stp-max-age 0:65535;OK
|
||||
--stp-max-age :2;--stp-max-age 0:2;OK
|
||||
--stp-max-age 2:;--stp-max-age 2:65535;OK
|
||||
--stp-max-age 1:2;=;OK
|
||||
--stp-max-age 1:1;--stp-max-age 1;OK
|
||||
--stp-max-age 2:1;;FAIL
|
||||
--stp-hello-time :;--stp-hello-time 0:65535;OK
|
||||
--stp-hello-time :2;--stp-hello-time 0:2;OK
|
||||
--stp-hello-time 2:;--stp-hello-time 2:65535;OK
|
||||
--stp-hello-time 1:2;=;OK
|
||||
--stp-hello-time 1:1;--stp-hello-time 1;OK
|
||||
--stp-hello-time 2:1;;FAIL
|
||||
--stp-forward-delay :;--stp-forward-delay 0:65535;OK
|
||||
--stp-forward-delay :2;--stp-forward-delay 0:2;OK
|
||||
--stp-forward-delay 2:;--stp-forward-delay 2:65535;OK
|
||||
--stp-forward-delay 1:2;=;OK
|
||||
--stp-forward-delay 1:1;--stp-forward-delay 1;OK
|
||||
--stp-forward-delay 2:1;;FAIL
|
||||
@@ -0,0 +1,127 @@
|
||||
/* ebt_vlan
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
* Nick Fedchik <nick@fedchik.org.ua>
|
||||
* June, 2002
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <xtables.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <linux/netfilter_bridge/ebt_vlan.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
static const struct xt_option_entry brvlan_opts[] =
|
||||
{
|
||||
{ .name = "vlan-id", .id = EBT_VLAN_ID, .type = XTTYPE_UINT16,
|
||||
.max = 4094, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_vlan_info, id) },
|
||||
{ .name = "vlan-prio", .id = EBT_VLAN_PRIO, .type = XTTYPE_UINT8,
|
||||
.max = 7, .flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ebt_vlan_info, prio) },
|
||||
{ .name = "vlan-encap", .id = EBT_VLAN_ENCAP, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_INVERT },
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brvlan_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"vlan options:\n"
|
||||
"[!] --vlan-id id : vlan-tagged frame identifier, 0,1-4096 (integer)\n"
|
||||
"[!] --vlan-prio prio : Priority-tagged frame's user priority, 0-7 (integer)\n"
|
||||
"[!] --vlan-encap encap : Encapsulated frame protocol (hexadecimal or name)\n");
|
||||
}
|
||||
|
||||
static void brvlan_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ebt_vlan_info *vlaninfo = cb->data;
|
||||
struct xt_ethertypeent *ethent;
|
||||
char *end;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
|
||||
vlaninfo->bitmask |= cb->entry->id;
|
||||
if (cb->invert)
|
||||
vlaninfo->invflags |= cb->entry->id;
|
||||
|
||||
if (cb->entry->id == EBT_VLAN_ENCAP) {
|
||||
vlaninfo->encap = strtoul(cb->arg, &end, 16);
|
||||
if (*end != '\0') {
|
||||
ethent = xtables_getethertypebyname(cb->arg);
|
||||
if (ethent == NULL)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unknown --vlan-encap value ('%s')",
|
||||
cb->arg);
|
||||
vlaninfo->encap = ethent->e_ethertype;
|
||||
}
|
||||
if (vlaninfo->encap < ETH_ZLEN)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid --vlan-encap range ('%s')",
|
||||
cb->arg);
|
||||
vlaninfo->encap = htons(vlaninfo->encap);
|
||||
}
|
||||
}
|
||||
|
||||
static void brvlan_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) match->data;
|
||||
|
||||
if (vlaninfo->bitmask & EBT_VLAN_ID) {
|
||||
printf("%s--vlan-id %d ",
|
||||
(vlaninfo->invflags & EBT_VLAN_ID) ? "! " : "",
|
||||
vlaninfo->id);
|
||||
}
|
||||
if (vlaninfo->bitmask & EBT_VLAN_PRIO) {
|
||||
printf("%s--vlan-prio %d ",
|
||||
(vlaninfo->invflags & EBT_VLAN_PRIO) ? "! " : "",
|
||||
vlaninfo->prio);
|
||||
}
|
||||
if (vlaninfo->bitmask & EBT_VLAN_ENCAP) {
|
||||
printf("%s--vlan-encap %4.4X ",
|
||||
(vlaninfo->invflags & EBT_VLAN_ENCAP) ? "! " : "",
|
||||
ntohs(vlaninfo->encap));
|
||||
}
|
||||
}
|
||||
|
||||
static int brvlan_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_mt_params *params)
|
||||
{
|
||||
const struct ebt_vlan_info *vlaninfo = (const void*)params->match->data;
|
||||
|
||||
if (vlaninfo->bitmask & EBT_VLAN_ID)
|
||||
xt_xlate_add(xl, "vlan id %s%d ", (vlaninfo->invflags & EBT_VLAN_ID) ? "!= " : "", vlaninfo->id);
|
||||
|
||||
if (vlaninfo->bitmask & EBT_VLAN_PRIO)
|
||||
xt_xlate_add(xl, "vlan pcp %s%d ", (vlaninfo->invflags & EBT_VLAN_PRIO) ? "!= " : "", vlaninfo->prio);
|
||||
|
||||
if (vlaninfo->bitmask & EBT_VLAN_ENCAP)
|
||||
xt_xlate_add(xl, "vlan type %s0x%4.4x ", (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "!= " : "", ntohs(vlaninfo->encap));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_match brvlan_match = {
|
||||
.name = "vlan",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_vlan_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_vlan_info)),
|
||||
.help = brvlan_print_help,
|
||||
.x6_parse = brvlan_parse,
|
||||
.print = brvlan_print,
|
||||
.xlate = brvlan_xlate,
|
||||
.x6_options = brvlan_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brvlan_match);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
-p 802_1Q --vlan-id 42;=;OK
|
||||
-p 802_1Q ! --vlan-id 42;=;OK
|
||||
-p 802_1Q --vlan-prio 1;=;OK
|
||||
-p 802_1Q ! --vlan-prio 1;=;OK
|
||||
-p 802_1Q --vlan-encap ip;-p 802_1Q --vlan-encap 0800 -j CONTINUE;OK
|
||||
-p 802_1Q --vlan-encap 0800;=;OK
|
||||
-p 802_1Q ! --vlan-encap 0800;=;OK
|
||||
-p 802_1Q --vlan-encap IPv6 --vlan-id ! 1;-p 802_1Q ! --vlan-id 1 --vlan-encap 86DD -j CONTINUE;OK
|
||||
-p 802_1Q ! --vlan-id 1 --vlan-encap 86DD;=;OK
|
||||
--vlan-encap ip;=;FAIL
|
||||
--vlan-id 2;=;FAIL
|
||||
--vlan-prio 1;=;FAIL
|
||||
@@ -0,0 +1,11 @@
|
||||
ebtables-translate -A INPUT -p 802_1Q --vlan-id 42
|
||||
nft 'add rule bridge filter INPUT vlan id 42 counter'
|
||||
|
||||
ebtables-translate -A INPUT -p 802_1Q ! --vlan-prio 1
|
||||
nft 'add rule bridge filter INPUT vlan pcp != 1 counter'
|
||||
|
||||
ebtables-translate -A INPUT -p 802_1Q --vlan-encap ip
|
||||
nft 'add rule bridge filter INPUT vlan type 0x0800 counter'
|
||||
|
||||
ebtables-translate -A INPUT -p 802_1Q --vlan-encap ipv6 ! --vlan-id 1
|
||||
nft 'add rule bridge filter INPUT vlan id != 1 vlan type 0x86dd counter'
|
||||
@@ -0,0 +1,20 @@
|
||||
:PREROUTING
|
||||
*nat
|
||||
-j DNAT --to-destination dead::beef;=;OK
|
||||
-j DNAT --to-destination dead::beef-dead::fee7;=;OK
|
||||
-j DNAT --to-destination [dead::beef]:1025-65535;;FAIL
|
||||
-j DNAT --to-destination [dead::beef] --to-destination [dead::fee7];;FAIL
|
||||
-p tcp -j DNAT --to-destination [dead::beef]:1025-65535;=;OK
|
||||
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65535;=;OK
|
||||
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65536;;FAIL
|
||||
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65535 --to-destination [dead::beef-dead::fee8]:1025-65535;;FAIL
|
||||
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/1000;=;OK
|
||||
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/3000;=;OK
|
||||
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/65535;=;OK
|
||||
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/0;;FAIL
|
||||
-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/65536;;FAIL
|
||||
-p tcp -j DNAT --to-destination [dead::beef]:ssh;-p tcp -j DNAT --to-destination [dead::beef]:22;OK
|
||||
-p tcp -j DNAT --to-destination [dead::beef]:ftp-data;-p tcp -j DNAT --to-destination [dead::beef]:20;OK
|
||||
-p tcp -j DNAT --to-destination [dead::beef]:echo-ssh;;FAIL
|
||||
-p tcp -j DNAT --to-destination [dead::beef]:10-20/ftp;-p tcp -j DNAT --to-destination [dead::beef]:10-20/21;OK
|
||||
-j DNAT;;FAIL
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_NPT.h>
|
||||
|
||||
enum {
|
||||
O_SRC_PFX = 1 << 0,
|
||||
O_DST_PFX = 1 << 1,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry DNPT_options[] = {
|
||||
{ .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND },
|
||||
{ .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND },
|
||||
{ }
|
||||
};
|
||||
|
||||
static void DNPT_help(void)
|
||||
{
|
||||
printf("DNPT target options:"
|
||||
"\n"
|
||||
" --src-pfx prefix/length\n"
|
||||
" --dst-pfx prefix/length\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static void DNPT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_npt_tginfo *npt = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_SRC_PFX:
|
||||
npt->src_pfx = cb->val.haddr;
|
||||
npt->src_pfx_len = cb->val.hlen;
|
||||
break;
|
||||
case O_DST_PFX:
|
||||
npt->dst_pfx = cb->val.haddr;
|
||||
npt->dst_pfx_len = cb->val.hlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DNPT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_npt_tginfo *npt = (const void *)target->data;
|
||||
|
||||
printf(" DNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
|
||||
npt->src_pfx_len);
|
||||
printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
|
||||
npt->dst_pfx_len);
|
||||
}
|
||||
|
||||
static void DNPT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
static const struct in6_addr zero_addr;
|
||||
const struct ip6t_npt_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
|
||||
info->src_pfx_len != 0)
|
||||
printf(" --src-pfx %s/%u",
|
||||
xtables_ip6addr_to_numeric(&info->src_pfx.in6),
|
||||
info->src_pfx_len);
|
||||
if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
|
||||
info->dst_pfx_len != 0)
|
||||
printf(" --dst-pfx %s/%u",
|
||||
xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
|
||||
info->dst_pfx_len);
|
||||
}
|
||||
|
||||
static struct xtables_target snpt_tg_reg = {
|
||||
.name = "DNPT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)),
|
||||
.userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment),
|
||||
.help = DNPT_help,
|
||||
.x6_parse = DNPT_parse,
|
||||
.print = DNPT_print,
|
||||
.save = DNPT_save,
|
||||
.x6_options = DNPT_options,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&snpt_tg_reg);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
Provides stateless destination IPv6-to-IPv6 Network Prefix Translation (as
|
||||
described by RFC 6296).
|
||||
.PP
|
||||
You have to use this target in the
|
||||
.B mangle
|
||||
table, not in the
|
||||
.B nat
|
||||
table. It takes the following options:
|
||||
.TP
|
||||
\fB\-\-src\-pfx\fP [\fIprefix/\fP\fIlength]
|
||||
Set source prefix that you want to translate and length
|
||||
.TP
|
||||
\fB\-\-dst\-pfx\fP [\fIprefix/\fP\fIlength]
|
||||
Set destination prefix that you want to use in the translation and length
|
||||
.PP
|
||||
You have to use the SNPT target to undo the translation. Example:
|
||||
.IP
|
||||
ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 ! \-o vboxnet0
|
||||
\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64
|
||||
.IP
|
||||
ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64
|
||||
\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst\-pfx fd00::/64
|
||||
.PP
|
||||
You may need to enable IPv6 neighbor proxy:
|
||||
.IP
|
||||
sysctl \-w net.ipv6.conf.all.proxy_ndp=1
|
||||
.PP
|
||||
You also have to use the
|
||||
.B NOTRACK
|
||||
target to disable connection tracking for translated flows.
|
||||
@@ -0,0 +1,7 @@
|
||||
:PREROUTING
|
||||
*mangle
|
||||
-j DNPT --src-pfx dead::/64 --dst-pfx 1c3::/64;=;OK
|
||||
-j DNPT --src-pfx dead::beef --dst-pfx 1c3::/64;;FAIL
|
||||
-j DNPT --src-pfx dead::/64;;FAIL
|
||||
-j DNPT --dst-pfx dead::/64;;FAIL
|
||||
-j DNPT;;FAIL
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* IPv6 Hop Limit Target module
|
||||
* Maciej Soltysiak <solt@dns.toxicfilms.tv>
|
||||
* Based on HW's ttl target
|
||||
* This program is distributed under the terms of GNU GPL
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_HL.h>
|
||||
|
||||
enum {
|
||||
O_HL_SET = 0,
|
||||
O_HL_INC,
|
||||
O_HL_DEC,
|
||||
F_HL_SET = 1 << O_HL_SET,
|
||||
F_HL_INC = 1 << O_HL_INC,
|
||||
F_HL_DEC = 1 << O_HL_DEC,
|
||||
F_ANY = F_HL_SET | F_HL_INC | F_HL_DEC,
|
||||
};
|
||||
|
||||
#define s struct ip6t_HL_info
|
||||
static const struct xt_option_entry HL_opts[] = {
|
||||
{.name = "hl-set", .type = XTTYPE_UINT8, .id = O_HL_SET,
|
||||
.excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit)},
|
||||
{.name = "hl-dec", .type = XTTYPE_UINT8, .id = O_HL_DEC,
|
||||
.excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit),
|
||||
.min = 1},
|
||||
{.name = "hl-inc", .type = XTTYPE_UINT8, .id = O_HL_INC,
|
||||
.excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit),
|
||||
.min = 1},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void HL_help(void)
|
||||
{
|
||||
printf(
|
||||
"HL target options\n"
|
||||
" --hl-set value Set HL to <value 0-255>\n"
|
||||
" --hl-dec value Decrement HL by <value 1-255>\n"
|
||||
" --hl-inc value Increment HL by <value 1-255>\n");
|
||||
}
|
||||
|
||||
static void HL_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_HL_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_HL_SET:
|
||||
info->mode = IP6T_HL_SET;
|
||||
break;
|
||||
case O_HL_INC:
|
||||
info->mode = IP6T_HL_INC;
|
||||
break;
|
||||
case O_HL_DEC:
|
||||
info->mode = IP6T_HL_DEC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void HL_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (!(cb->xflags & F_ANY))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"HL: You must specify an action");
|
||||
}
|
||||
|
||||
static void HL_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ip6t_HL_info *info =
|
||||
(struct ip6t_HL_info *) target->data;
|
||||
|
||||
switch (info->mode) {
|
||||
case IP6T_HL_SET:
|
||||
printf(" --hl-set");
|
||||
break;
|
||||
case IP6T_HL_DEC:
|
||||
printf(" --hl-dec");
|
||||
break;
|
||||
|
||||
case IP6T_HL_INC:
|
||||
printf(" --hl-inc");
|
||||
break;
|
||||
}
|
||||
printf(" %u", info->hop_limit);
|
||||
}
|
||||
|
||||
static void HL_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_HL_info *info =
|
||||
(struct ip6t_HL_info *) target->data;
|
||||
|
||||
printf(" HL ");
|
||||
switch (info->mode) {
|
||||
case IP6T_HL_SET:
|
||||
printf("set to");
|
||||
break;
|
||||
case IP6T_HL_DEC:
|
||||
printf("decrement by");
|
||||
break;
|
||||
case IP6T_HL_INC:
|
||||
printf("increment by");
|
||||
break;
|
||||
}
|
||||
printf(" %u", info->hop_limit);
|
||||
}
|
||||
|
||||
static struct xtables_target hl_tg6_reg = {
|
||||
.name = "HL",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_HL_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_HL_info)),
|
||||
.help = HL_help,
|
||||
.print = HL_print,
|
||||
.save = HL_save,
|
||||
.x6_parse = HL_parse,
|
||||
.x6_fcheck = HL_check,
|
||||
.x6_options = HL_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&hl_tg6_reg);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
This is used to modify the Hop Limit field in IPv6 header. The Hop Limit field
|
||||
is similar to what is known as TTL value in IPv4. Setting or incrementing the
|
||||
Hop Limit field can potentially be very dangerous, so it should be avoided at
|
||||
any cost. This target is only valid in
|
||||
.B mangle
|
||||
table.
|
||||
.PP
|
||||
.B Don't ever set or increment the value on packets that leave your local network!
|
||||
.TP
|
||||
\fB\-\-hl\-set\fP \fIvalue\fP
|
||||
Set the Hop Limit to `value'.
|
||||
.TP
|
||||
\fB\-\-hl\-dec\fP \fIvalue\fP
|
||||
Decrement the Hop Limit `value' times.
|
||||
.TP
|
||||
\fB\-\-hl\-inc\fP \fIvalue\fP
|
||||
Increment the Hop Limit `value' times.
|
||||
@@ -0,0 +1,10 @@
|
||||
:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
|
||||
*mangle
|
||||
-j HL --hl-set 42;=;OK
|
||||
-j HL --hl-inc 1;=;OK
|
||||
-j HL --hl-dec 1;=;OK
|
||||
-j HL --hl-set 256;;FAIL
|
||||
-j HL --hl-inc 0;;FAIL
|
||||
-j HL --hl-dec 0;;FAIL
|
||||
-j HL --hl-dec 1 --hl-inc 1;;FAIL
|
||||
-j HL --hl-set --hl-inc 1;;FAIL
|
||||
@@ -0,0 +1,12 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
-j LOG;-j LOG;OK
|
||||
-j LOG --log-prefix "test: ";=;OK
|
||||
-j LOG --log-prefix "test: " --log-level 1;=;OK
|
||||
# iptables displays the log-level output using the number; not the string
|
||||
-j LOG --log-prefix "test: " --log-level alert;-j LOG --log-prefix "test: " --log-level 1;OK
|
||||
-j LOG --log-prefix "test: " --log-tcp-sequence;=;OK
|
||||
-j LOG --log-prefix "test: " --log-tcp-options;=;OK
|
||||
-j LOG --log-prefix "test: " --log-ip-options;=;OK
|
||||
-j LOG --log-prefix "test: " --log-uid;=;OK
|
||||
-j LOG --log-prefix "test: " --log-level bad;;FAIL
|
||||
-j LOG --log-prefix;;FAIL
|
||||
@@ -0,0 +1,8 @@
|
||||
iptables-translate -I INPUT -j LOG
|
||||
nft 'insert rule ip filter INPUT counter log'
|
||||
|
||||
ip6tables-translate -A FORWARD -p tcp -j LOG --log-level debug
|
||||
nft 'add rule ip6 filter FORWARD meta l4proto tcp counter log level debug'
|
||||
|
||||
ip6tables-translate -A FORWARD -p tcp -j LOG --log-prefix "Checking log"
|
||||
nft 'add rule ip6 filter FORWARD meta l4proto tcp counter log prefix "Checking log"'
|
||||
@@ -0,0 +1,9 @@
|
||||
:POSTROUTING
|
||||
*nat
|
||||
-j MASQUERADE;=;OK
|
||||
-j MASQUERADE --random;=;OK
|
||||
-j MASQUERADE --random-fully;=;OK
|
||||
-p tcp -j MASQUERADE --to-ports 1024;=;OK
|
||||
-p udp -j MASQUERADE --to-ports 1024-65535;=;OK
|
||||
-p udp -j MASQUERADE --to-ports 1024-65536;;FAIL
|
||||
-p udp -j MASQUERADE --to-ports -1;;FAIL
|
||||
@@ -0,0 +1,17 @@
|
||||
ip6tables-translate -t nat -A POSTROUTING -j MASQUERADE
|
||||
nft 'add rule ip6 nat POSTROUTING counter masquerade'
|
||||
|
||||
ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10
|
||||
nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10'
|
||||
|
||||
ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10-20 --random
|
||||
nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10-20 random'
|
||||
|
||||
ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random
|
||||
nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade random'
|
||||
|
||||
ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random-fully
|
||||
nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade fully-random'
|
||||
|
||||
ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random --random-fully
|
||||
nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade random,fully-random'
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 NAT
|
||||
* funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include <libiptc/libip6tc.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
#define MODULENAME "NETMAP"
|
||||
|
||||
enum {
|
||||
O_TO = 0,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry NETMAP_opts[] = {
|
||||
{.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void NETMAP_help(void)
|
||||
{
|
||||
printf(MODULENAME" target options:\n"
|
||||
" --%s address[/mask]\n"
|
||||
" Network address to map to.\n\n",
|
||||
NETMAP_opts[0].name);
|
||||
}
|
||||
|
||||
static void NETMAP_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct nf_nat_range *range = cb->data;
|
||||
unsigned int i;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
range->flags |= NF_NAT_RANGE_MAP_IPS;
|
||||
for (i = 0; i < 4; i++) {
|
||||
range->min_addr.ip6[i] = cb->val.haddr.ip6[i] &
|
||||
cb->val.hmask.ip6[i];
|
||||
range->max_addr.ip6[i] = range->min_addr.ip6[i] |
|
||||
~cb->val.hmask.ip6[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void __NETMAP_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct nf_nat_range *r = (const void *)target->data;
|
||||
struct in6_addr a;
|
||||
unsigned int i;
|
||||
int bits;
|
||||
|
||||
a = r->min_addr.in6;
|
||||
printf("%s", xtables_ip6addr_to_numeric(&a));
|
||||
for (i = 0; i < 4; i++)
|
||||
a.s6_addr32[i] = ~(r->min_addr.ip6[i] ^ r->max_addr.ip6[i]);
|
||||
bits = xtables_ip6mask_to_cidr(&a);
|
||||
if (bits < 0)
|
||||
printf("/%s", xtables_ip6addr_to_numeric(&a));
|
||||
else
|
||||
printf("/%d", bits);
|
||||
}
|
||||
|
||||
static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
printf(" to:");
|
||||
__NETMAP_print(ip, target, numeric);
|
||||
}
|
||||
|
||||
static void NETMAP_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
printf(" --%s ", NETMAP_opts[0].name);
|
||||
__NETMAP_print(ip, target, 0);
|
||||
}
|
||||
|
||||
static struct xtables_target netmap_tg_reg = {
|
||||
.name = MODULENAME,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.help = NETMAP_help,
|
||||
.x6_parse = NETMAP_parse,
|
||||
.print = NETMAP_print,
|
||||
.save = NETMAP_save,
|
||||
.x6_options = NETMAP_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&netmap_tg_reg);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
:PREROUTING,INPUT,OUTPUT,POSTROUTING
|
||||
*nat
|
||||
-j NETMAP --to dead::/64;=;OK
|
||||
-j NETMAP --to dead::beef;-j NETMAP --to dead::beef/128;OK
|
||||
@@ -0,0 +1,185 @@
|
||||
/* Shared library add-on to ip6tables to add customized REJECT support.
|
||||
*
|
||||
* (C) 2000 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* ported to IPv6 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_REJECT.h>
|
||||
|
||||
struct reject_names {
|
||||
const char *name;
|
||||
const char *alias;
|
||||
const char *desc;
|
||||
const char *xlate;
|
||||
};
|
||||
|
||||
enum {
|
||||
O_REJECT_WITH = 0,
|
||||
};
|
||||
|
||||
static const struct reject_names reject_table[] = {
|
||||
[IP6T_ICMP6_NO_ROUTE] = {
|
||||
"icmp6-no-route", "no-route",
|
||||
"ICMPv6 no route",
|
||||
"no-route",
|
||||
},
|
||||
[IP6T_ICMP6_ADM_PROHIBITED] = {
|
||||
"icmp6-adm-prohibited", "adm-prohibited",
|
||||
"ICMPv6 administratively prohibited",
|
||||
"admin-prohibited",
|
||||
},
|
||||
#if 0
|
||||
[IP6T_ICMP6_NOT_NEIGHBOR] = {
|
||||
"icmp6-not-neighbor", "not-neighbor",
|
||||
"ICMPv6 not a neighbor",
|
||||
},
|
||||
#endif
|
||||
[IP6T_ICMP6_ADDR_UNREACH] = {
|
||||
"icmp6-addr-unreachable", "addr-unreach",
|
||||
"ICMPv6 address unreachable",
|
||||
"addr-unreachable",
|
||||
},
|
||||
[IP6T_ICMP6_PORT_UNREACH] = {
|
||||
"icmp6-port-unreachable", "port-unreach",
|
||||
"ICMPv6 port unreachable",
|
||||
"port-unreachable",
|
||||
},
|
||||
#if 0
|
||||
[IP6T_ICMP6_ECHOREPLY] = {},
|
||||
#endif
|
||||
[IP6T_TCP_RESET] = {
|
||||
"tcp-reset", "tcp-reset",
|
||||
"TCP RST packet",
|
||||
"tcp reset",
|
||||
},
|
||||
[IP6T_ICMP6_POLICY_FAIL] = {
|
||||
"icmp6-policy-fail", "policy-fail",
|
||||
"ICMPv6 policy fail",
|
||||
"policy-fail",
|
||||
},
|
||||
[IP6T_ICMP6_REJECT_ROUTE] = {
|
||||
"icmp6-reject-route", "reject-route",
|
||||
"ICMPv6 reject route",
|
||||
"reject-route",
|
||||
},
|
||||
};
|
||||
|
||||
static void
|
||||
print_reject_types(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("Valid reject types:\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
|
||||
if (!reject_table[i].name)
|
||||
continue;
|
||||
printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
|
||||
printf(" %-25s\talias\n", reject_table[i].alias);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void REJECT_help(void)
|
||||
{
|
||||
printf(
|
||||
"REJECT target options:\n"
|
||||
"--reject-with type drop input packet and send back\n"
|
||||
" a reply packet according to type:\n");
|
||||
|
||||
print_reject_types();
|
||||
}
|
||||
|
||||
static const struct xt_option_entry REJECT_opts[] = {
|
||||
{.name = "reject-with", .id = O_REJECT_WITH, .type = XTTYPE_STRING},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void REJECT_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ip6t_reject_info *reject = (struct ip6t_reject_info *)t->data;
|
||||
|
||||
/* default */
|
||||
reject->with = IP6T_ICMP6_PORT_UNREACH;
|
||||
|
||||
}
|
||||
|
||||
static void REJECT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_reject_info *reject = cb->data;
|
||||
unsigned int i;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
|
||||
if (!reject_table[i].name)
|
||||
continue;
|
||||
if (strncasecmp(reject_table[i].name,
|
||||
cb->arg, strlen(cb->arg)) == 0 ||
|
||||
strncasecmp(reject_table[i].alias,
|
||||
cb->arg, strlen(cb->arg)) == 0) {
|
||||
reject->with = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"unknown reject type \"%s\"", cb->arg);
|
||||
}
|
||||
|
||||
static void REJECT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_reject_info *reject
|
||||
= (const struct ip6t_reject_info *)target->data;
|
||||
|
||||
printf(" reject-with %s", reject_table[reject->with].name);
|
||||
}
|
||||
|
||||
static void REJECT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ip6t_reject_info *reject
|
||||
= (const struct ip6t_reject_info *)target->data;
|
||||
|
||||
printf(" --reject-with %s", reject_table[reject->with].name);
|
||||
}
|
||||
|
||||
static int REJECT_xlate(struct xt_xlate *xl,
|
||||
const struct xt_xlate_tg_params *params)
|
||||
{
|
||||
const struct ip6t_reject_info *reject =
|
||||
(const struct ip6t_reject_info *)params->target->data;
|
||||
|
||||
if (reject->with == IP6T_ICMP6_PORT_UNREACH)
|
||||
xt_xlate_add(xl, "reject");
|
||||
else if (reject->with == IP6T_TCP_RESET)
|
||||
xt_xlate_add(xl, "reject with %s",
|
||||
reject_table[reject->with].xlate);
|
||||
else
|
||||
xt_xlate_add(xl, "reject with icmpv6 type %s",
|
||||
reject_table[reject->with].xlate);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct xtables_target reject_tg6_reg = {
|
||||
.name = "REJECT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_reject_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_reject_info)),
|
||||
.help = REJECT_help,
|
||||
.init = REJECT_init,
|
||||
.print = REJECT_print,
|
||||
.save = REJECT_save,
|
||||
.x6_parse = REJECT_parse,
|
||||
.x6_options = REJECT_opts,
|
||||
.xlate = REJECT_xlate,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&reject_tg6_reg);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
This is used to send back an error packet in response to the matched
|
||||
packet: otherwise it is equivalent to
|
||||
.B DROP
|
||||
so it is a terminating TARGET, ending rule traversal.
|
||||
This target is only valid in the
|
||||
.BR INPUT ,
|
||||
.B FORWARD
|
||||
and
|
||||
.B OUTPUT
|
||||
chains, and user-defined chains which are only called from those
|
||||
chains. The following option controls the nature of the error packet
|
||||
returned:
|
||||
.TP
|
||||
\fB\-\-reject\-with\fP \fItype\fP
|
||||
The type given can be
|
||||
\fBicmp6\-no\-route\fP,
|
||||
\fBno\-route\fP,
|
||||
\fBicmp6\-adm\-prohibited\fP,
|
||||
\fBadm\-prohibited\fP,
|
||||
\fBicmp6\-addr\-unreachable\fP,
|
||||
\fBaddr\-unreach\fP, or
|
||||
\fBicmp6\-port\-unreachable\fP,
|
||||
which return the appropriate ICMPv6 error message (\fBicmp6\-port\-unreachable\fP is
|
||||
the default). Finally, the option
|
||||
\fBtcp\-reset\fP
|
||||
can be used on rules which only match the TCP protocol: this causes a
|
||||
TCP RST packet to be sent back. This is mainly useful for blocking
|
||||
.I ident
|
||||
(113/tcp) probes which frequently occur when sending mail to broken mail
|
||||
hosts (which won't accept your mail otherwise).
|
||||
\fBtcp\-reset\fP
|
||||
can only be used with kernel versions 2.6.14 or later.
|
||||
.PP
|
||||
\fIWarning:\fP You should not indiscriminately apply the REJECT target to
|
||||
packets whose connection state is classified as INVALID; instead, you should
|
||||
only DROP these.
|
||||
.PP
|
||||
Consider a source host transmitting a packet P, with P experiencing so much
|
||||
delay along its path that the source host issues a retransmission, P_2, with
|
||||
P_2 being successful in reaching its destination and advancing the connection
|
||||
state normally. It is conceivable that the late-arriving P may be considered
|
||||
not to be associated with any connection tracking entry. Generating a reject
|
||||
response for a packet so classed would then terminate the healthy connection.
|
||||
.PP
|
||||
So, instead of:
|
||||
.PP
|
||||
\-A INPUT ... \-j REJECT
|
||||
.PP
|
||||
do consider using:
|
||||
.PP
|
||||
\-A INPUT ... \-m conntrack \-\-ctstate INVALID \-j DROP
|
||||
.br
|
||||
\-A INPUT ... \-j REJECT
|
||||
@@ -0,0 +1,11 @@
|
||||
:INPUT,FORWARD,OUTPUT
|
||||
-j REJECT;-j REJECT --reject-with icmp6-port-unreachable;OK
|
||||
# manpage for IPv6 variant of REJECT does not show up for some reason?
|
||||
-j REJECT --reject-with icmp6-no-route;=;OK
|
||||
-j REJECT --reject-with icmp6-adm-prohibited;=;OK
|
||||
-j REJECT --reject-with icmp6-addr-unreachable;=;OK
|
||||
-j REJECT --reject-with icmp6-port-unreachable;=;OK
|
||||
-j REJECT --reject-with icmp6-policy-fail;=;OK
|
||||
-j REJECT --reject-with icmp6-reject-route;=;OK
|
||||
-p tcp -j REJECT --reject-with tcp-reset;=;OK
|
||||
-j REJECT --reject-with tcp-reset;;FAIL
|
||||
@@ -0,0 +1,8 @@
|
||||
ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT
|
||||
nft 'add rule ip6 filter FORWARD tcp dport 22 counter reject'
|
||||
|
||||
ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with icmp6-reject-route
|
||||
nft 'add rule ip6 filter FORWARD tcp dport 22 counter reject with icmpv6 type reject-route'
|
||||
|
||||
ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
|
||||
nft 'add rule ip6 filter FORWARD tcp dport 22 counter reject with tcp reset'
|
||||
@@ -0,0 +1,17 @@
|
||||
:POSTROUTING
|
||||
*nat
|
||||
-j SNAT --to-source dead::beef;=;OK
|
||||
-j SNAT --to-source dead::beef-dead::fee7;=;OK
|
||||
-j SNAT --to-source [dead::beef]:1025-65535;;FAIL
|
||||
-j SNAT --to-source [dead::beef] --to-source [dead::fee7];;FAIL
|
||||
-j SNAT --to-source dead::beef --random;=;OK
|
||||
-j SNAT --to-source dead::beef --random-fully;=;OK
|
||||
-j SNAT --to-source dead::beef --persistent;=;OK
|
||||
-j SNAT --to-source dead::beef --random --persistent;=;OK
|
||||
-j SNAT --to-source dead::beef --random --random-fully;=;OK
|
||||
-j SNAT --to-source dead::beef --random --random-fully --persistent;=;OK
|
||||
-p tcp -j SNAT --to-source [dead::beef]:1025-65535;=;OK
|
||||
-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65535;=;OK
|
||||
-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65536;;FAIL
|
||||
-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65535 --to-source [dead::beef-dead::fee8]:1025-65535;;FAIL
|
||||
-j SNAT;;FAIL
|
||||
@@ -0,0 +1,11 @@
|
||||
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:80
|
||||
nft 'add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:80'
|
||||
|
||||
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:1-20
|
||||
nft 'add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:1-20'
|
||||
|
||||
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:123 --random
|
||||
nft 'add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:123 random'
|
||||
|
||||
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:123 --random-fully --persistent
|
||||
nft 'add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:123 fully-random,persistent'
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_NPT.h>
|
||||
|
||||
enum {
|
||||
O_SRC_PFX = 1 << 0,
|
||||
O_DST_PFX = 1 << 1,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry SNPT_options[] = {
|
||||
{ .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND },
|
||||
{ .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND },
|
||||
{ }
|
||||
};
|
||||
|
||||
static void SNPT_help(void)
|
||||
{
|
||||
printf("SNPT target options:"
|
||||
"\n"
|
||||
" --src-pfx prefix/length\n"
|
||||
" --dst-pfx prefix/length\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static void SNPT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_npt_tginfo *npt = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_SRC_PFX:
|
||||
npt->src_pfx = cb->val.haddr;
|
||||
npt->src_pfx_len = cb->val.hlen;
|
||||
break;
|
||||
case O_DST_PFX:
|
||||
npt->dst_pfx = cb->val.haddr;
|
||||
npt->dst_pfx_len = cb->val.hlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void SNPT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_npt_tginfo *npt = (const void *)target->data;
|
||||
|
||||
printf(" SNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
|
||||
npt->src_pfx_len);
|
||||
printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
|
||||
npt->dst_pfx_len);
|
||||
}
|
||||
|
||||
static void SNPT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
static const struct in6_addr zero_addr;
|
||||
const struct ip6t_npt_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
|
||||
info->src_pfx_len != 0)
|
||||
printf(" --src-pfx %s/%u",
|
||||
xtables_ip6addr_to_numeric(&info->src_pfx.in6),
|
||||
info->src_pfx_len);
|
||||
if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
|
||||
info->dst_pfx_len != 0)
|
||||
printf(" --dst-pfx %s/%u",
|
||||
xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
|
||||
info->dst_pfx_len);
|
||||
}
|
||||
|
||||
static struct xtables_target snpt_tg_reg = {
|
||||
.name = "SNPT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)),
|
||||
.userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment),
|
||||
.help = SNPT_help,
|
||||
.x6_parse = SNPT_parse,
|
||||
.print = SNPT_print,
|
||||
.save = SNPT_save,
|
||||
.x6_options = SNPT_options,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&snpt_tg_reg);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
Provides stateless source IPv6-to-IPv6 Network Prefix Translation (as described
|
||||
by RFC 6296).
|
||||
.PP
|
||||
You have to use this target in the
|
||||
.B mangle
|
||||
table, not in the
|
||||
.B nat
|
||||
table. It takes the following options:
|
||||
.TP
|
||||
\fB\-\-src\-pfx\fP [\fIprefix/\fP\fIlength]
|
||||
Set source prefix that you want to translate and length
|
||||
.TP
|
||||
\fB\-\-dst\-pfx\fP [\fIprefix/\fP\fIlength]
|
||||
Set destination prefix that you want to use in the translation and length
|
||||
.PP
|
||||
You have to use the DNPT target to undo the translation. Example:
|
||||
.IP
|
||||
ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 ! \-o vboxnet0
|
||||
\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64
|
||||
.IP
|
||||
ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64
|
||||
\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst\-pfx fd00::/64
|
||||
.PP
|
||||
You may need to enable IPv6 neighbor proxy:
|
||||
.IP
|
||||
sysctl \-w net.ipv6.conf.all.proxy_ndp=1
|
||||
.PP
|
||||
You also have to use the
|
||||
.B NOTRACK
|
||||
target to disable connection tracking for translated flows.
|
||||
@@ -0,0 +1,7 @@
|
||||
:INPUT,POSTROUTING
|
||||
*mangle
|
||||
-j SNPT --src-pfx dead::/64 --dst-pfx 1c3::/64;=;OK
|
||||
-j SNPT --src-pfx dead::beef --dst-pfx 1c3::/64;;FAIL
|
||||
-j SNPT --src-pfx dead::/64;;FAIL
|
||||
-j SNPT --dst-pfx dead::/64;;FAIL
|
||||
-j SNPT;;FAIL
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user