diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..d62b428c --- /dev/null +++ b/INSTALL @@ -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. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..d0ba059c --- /dev/null +++ b/Makefile.am @@ -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 diff --git a/README.OpenSource b/README.OpenSource index c0bbe9d3..14f5b824 100644 --- a/README.OpenSource +++ b/README.OpenSource @@ -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." } diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..a0c4395f --- /dev/null +++ b/autogen.sh @@ -0,0 +1,4 @@ +#!/bin/sh -e + +autoreconf -fi; +rm -Rf autom4te*.cache; diff --git a/backport-Improve-error-messages-for-unsupported-extensions.patch b/backport-Improve-error-messages-for-unsupported-extensions.patch deleted file mode 100644 index 778d1035..00000000 --- a/backport-Improve-error-messages-for-unsupported-extensions.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 17534cb18ed0a5052dc45c117401251359dba6aa Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 - diff --git a/backport-ebtables-translate-Print-flush-command-after-parsing-is-finished.patch b/backport-ebtables-translate-Print-flush-command-after-parsing-is-finished.patch deleted file mode 100644 index ea1bb050..00000000 --- a/backport-ebtables-translate-Print-flush-command-after-parsing-is-finished.patch +++ /dev/null @@ -1,51 +0,0 @@ -From b51aef061378b34fa9544b1af34021d89a76547a Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 diff --git a/backport-extensions-among-Fix-for-use-with-ebtables-restore.patch b/backport-extensions-among-Fix-for-use-with-ebtables-restore.patch deleted file mode 100644 index d0145de8..00000000 --- a/backport-extensions-among-Fix-for-use-with-ebtables-restore.patch +++ /dev/null @@ -1,58 +0,0 @@ -From fca04aa7a53252464c289997e71de10189971da6 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 diff --git a/backport-extensions-libebt_redirect-Fix-xlate-return-code.patch b/backport-extensions-libebt_redirect-Fix-xlate-return-code.patch deleted file mode 100644 index ae177986..00000000 --- a/backport-extensions-libebt_redirect-Fix-xlate-return-code.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 8543b6f2f4a3a15a5ece7dd1b320b477ce36a8d5 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 diff --git a/backport-extensions-libipt_ttl-Sanitize-xlate-callback.patch b/backport-extensions-libipt_ttl-Sanitize-xlate-callback.patch deleted file mode 100644 index e9ca5f4d..00000000 --- a/backport-extensions-libipt_ttl-Sanitize-xlate-callback.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 800bed28b2b7bbd931166c7426640ae619f03342 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 diff --git a/backport-iptables-Fix-handling-of-non-existent-chains.patch b/backport-iptables-Fix-handling-of-non-existent-chains.patch deleted file mode 100644 index e952b6a7..00000000 --- a/backport-iptables-Fix-handling-of-non-existent-chains.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 82ccfb488eeac5507471099b9b4e6d136cc06e3b Mon Sep 17 00:00:00 2001 -From: Jacek Tomasiak -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 -Signed-off-by: Jacek Tomasiak -Signed-off-by: Phil Sutter - -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 - diff --git a/backport-iptables-Plug-memleaks-in-print_firewall.patch b/backport-iptables-Plug-memleaks-in-print_firewall.patch deleted file mode 100644 index 0b718759..00000000 --- a/backport-iptables-Plug-memleaks-in-print_firewall.patch +++ /dev/null @@ -1,92 +0,0 @@ -From fb63f8b7337aa11a667537e6a3b399062ede2eb5 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 diff --git a/backport-iptables-restore-Free-handle-with-test-also.patch b/backport-iptables-restore-Free-handle-with-test-also.patch deleted file mode 100644 index c753ec2f..00000000 --- a/backport-iptables-restore-Free-handle-with-test-also.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 18880dbde615449d00a3e38f3713a19d4566258e Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 diff --git a/backport-libxtables-Register-only-the-highest-revision-extension.patch b/backport-libxtables-Register-only-the-highest-revision-extension.patch deleted file mode 100644 index 361bdc9d..00000000 --- a/backport-libxtables-Register-only-the-highest-revision-extension.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 2dbb49d15fb44ddd521a734eca3be3f940b7c1ba Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 diff --git a/backport-nft-Expand-extended-error-reporting-to-nft_cmd-too.patch b/backport-nft-Expand-extended-error-reporting-to-nft_cmd-too.patch deleted file mode 100644 index d7074261..00000000 --- a/backport-nft-Expand-extended-error-reporting-to-nft_cmd-too.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0257293c68913dd5993c1cac44f2ee80af6d9792 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 < ---- - 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 - diff --git a/backport-nft-Fix-EPERM-handling-for-extensions-without-rev-0.patch b/backport-nft-Fix-EPERM-handling-for-extensions-without-rev-0.patch deleted file mode 100644 index 6bfb8688..00000000 --- a/backport-nft-Fix-EPERM-handling-for-extensions-without-rev-0.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 8468fd4f7c85c21ab375402bc80d0188412b6cbf Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 - diff --git a/backport-nft-Plug-memleak-in-nft_rule_zero_counters.patch b/backport-nft-Plug-memleak-in-nft_rule_zero_counters.patch deleted file mode 100644 index 8081963b..00000000 --- a/backport-nft-Plug-memleak-in-nft_rule_zero_counters.patch +++ /dev/null @@ -1,52 +0,0 @@ -From aa0c54030300441e9fd66c7016d0090f6736d449 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 ---- - 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 diff --git a/backport-xshared-Fix-response-to-unprivileged-users.patch b/backport-xshared-Fix-response-to-unprivileged-users.patch deleted file mode 100644 index e5f574b9..00000000 --- a/backport-xshared-Fix-response-to-unprivileged-users.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 26ecdf53960658771c0fc582f72a4025e2887f75 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 -Reviewed-by: Florian Westphal ---- - 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 - diff --git a/backport-xtables-eb-fix-crash-when-opts-isn-t-reallocated.patch b/backport-xtables-eb-fix-crash-when-opts-isn-t-reallocated.patch deleted file mode 100644 index 71dc49b0..00000000 --- a/backport-xtables-eb-fix-crash-when-opts-isn-t-reallocated.patch +++ /dev/null @@ -1,32 +0,0 @@ -From e900d40afdb731d2270a5110833ae49192974355 Mon Sep 17 00:00:00 2001 -From: Florian Westphal -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 ---- - 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 diff --git a/backport-xtables-restore-Extend-failure-error-message.patch b/backport-xtables-restore-Extend-failure-error-message.patch deleted file mode 100644 index 4849e5ff..00000000 --- a/backport-xtables-restore-Extend-failure-error-message.patch +++ /dev/null @@ -1,44 +0,0 @@ -From c70a33d219ccb43e6f59aa1b9bbab5dcb13f3443 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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 < ---- - 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 - diff --git a/bugfix-add-check-fw-in-entry.patch b/bugfix-add-check-fw-in-entry.patch deleted file mode 100644 index 36617912..00000000 --- a/bugfix-add-check-fw-in-entry.patch +++ /dev/null @@ -1,135 +0,0 @@ -From cbc3a30711701f0e8d7f5df14f84adfb2c9fec1f Mon Sep 17 00:00:00 2001 -From: majun -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 - diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..2d38a4d4 --- /dev/null +++ b/configure.ac @@ -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 ]) + +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 ]], + [[ + #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" diff --git a/enabled-makecheck-in-extensions.patch b/enabled-makecheck-in-extensions.patch deleted file mode 100644 index a80465ae..00000000 --- a/enabled-makecheck-in-extensions.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 54c670ada541aa61ab9ab7907ab245718137efb8 Mon Sep 17 00:00:00 2001 -From: huangyu -Date: Sat, 26 Nov 2022 18:08:31 +0800 -Subject: [PATCH] enable makecheck in extensions - -Signed-off-by: huangyu ---- - 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 - diff --git a/etc/ethertypes b/etc/ethertypes new file mode 100644 index 00000000..813177b7 --- /dev/null +++ b/etc/ethertypes @@ -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 +# +# ... #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 diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in new file mode 100644 index 00000000..20c2b7bc --- /dev/null +++ b/extensions/GNUmakefile.in @@ -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: diff --git a/extensions/dscp_helper.c b/extensions/dscp_helper.c new file mode 100644 index 00000000..1f20b2a5 --- /dev/null +++ b/extensions/dscp_helper.c @@ -0,0 +1,79 @@ +/* + * DiffServ classname <-> DiffServ codepoint mapping functions. + * + * The latest list of the mappings can be found at: + * + * + * This code is released under the GNU GPL v2, 1991 + * + * Author: Iain Barnes + */ + +#include +#include +#include + + +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 + diff --git a/extensions/generic.txlate b/extensions/generic.txlate new file mode 100644 index 00000000..9ad1266d --- /dev/null +++ b/extensions/generic.txlate @@ -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' diff --git a/extensions/iptables.t b/extensions/iptables.t new file mode 100644 index 00000000..2817c3fb --- /dev/null +++ b/extensions/iptables.t @@ -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 diff --git a/extensions/libarpt_CLASSIFY.t b/extensions/libarpt_CLASSIFY.t new file mode 100644 index 00000000..0cf0f2ce --- /dev/null +++ b/extensions/libarpt_CLASSIFY.t @@ -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 diff --git a/extensions/libarpt_MARK.t b/extensions/libarpt_MARK.t new file mode 100644 index 00000000..3b13d44f --- /dev/null +++ b/extensions/libarpt_MARK.t @@ -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 diff --git a/extensions/libarpt_mangle.c b/extensions/libarpt_mangle.c new file mode 100644 index 00000000..283bb132 --- /dev/null +++ b/extensions/libarpt_mangle.c @@ -0,0 +1,199 @@ +/* + * Arturo Borrero Gonzalez adapted + * this code to libxtables for arptables-compat in 2015 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/extensions/libarpt_mangle.t b/extensions/libarpt_mangle.t new file mode 100644 index 00000000..7a639ee1 --- /dev/null +++ b/extensions/libarpt_mangle.t @@ -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 diff --git a/extensions/libarpt_mangle.txlate b/extensions/libarpt_mangle.txlate new file mode 100644 index 00000000..e884d328 --- /dev/null +++ b/extensions/libarpt_mangle.txlate @@ -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' diff --git a/extensions/libarpt_standard.t b/extensions/libarpt_standard.t new file mode 100644 index 00000000..d6eaced3 --- /dev/null +++ b/extensions/libarpt_standard.t @@ -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 diff --git a/extensions/libebt_802_3.c b/extensions/libebt_802_3.c new file mode 100644 index 00000000..489185e9 --- /dev/null +++ b/extensions/libebt_802_3.c @@ -0,0 +1,86 @@ +/* 802_3 + * + * Author: + * Chris Vitale + * + * May 2003 + * + * Adapted by Arturo Borrero Gonzalez + * to use libxtables for ebtables-compat + */ + +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/extensions/libebt_802_3.t b/extensions/libebt_802_3.t new file mode 100644 index 00000000..d1e19795 --- /dev/null +++ b/extensions/libebt_802_3.t @@ -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 diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c new file mode 100644 index 00000000..85f9bee4 --- /dev/null +++ b/extensions/libebt_among.c @@ -0,0 +1,241 @@ +/* ebt_among + * + * Authors: + * Grzegorz Borowiak + * + * August, 2003 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/extensions/libebt_among.t b/extensions/libebt_among.t new file mode 100644 index 00000000..aef07acf --- /dev/null +++ b/extensions/libebt_among.t @@ -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 diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c new file mode 100644 index 00000000..50ce32be --- /dev/null +++ b/extensions/libebt_arp.c @@ -0,0 +1,230 @@ +/* ebt_arp + * + * Authors: + * Bart De Schuymer + * Tim Gardner + * + * April, 2002 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#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); +} diff --git a/extensions/libebt_arp.t b/extensions/libebt_arp.t new file mode 100644 index 00000000..ea006f25 --- /dev/null +++ b/extensions/libebt_arp.t @@ -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 diff --git a/extensions/libebt_arpreply.c b/extensions/libebt_arpreply.c new file mode 100644 index 00000000..1d6ba36a --- /dev/null +++ b/extensions/libebt_arpreply.c @@ -0,0 +1,85 @@ +/* ebt_arpreply + * + * Authors: + * Grzegorz Borowiak + * Bart De Schuymer + * + * August, 2003 + */ + +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/extensions/libebt_arpreply.t b/extensions/libebt_arpreply.t new file mode 100644 index 00000000..66103e16 --- /dev/null +++ b/extensions/libebt_arpreply.t @@ -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 diff --git a/extensions/libebt_dnat.c b/extensions/libebt_dnat.c new file mode 100644 index 00000000..447ff105 --- /dev/null +++ b/extensions/libebt_dnat.c @@ -0,0 +1,119 @@ +/* ebt_nat + * + * Authors: + * Bart De Schuymer + * + * June, 2002 + */ + +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/extensions/libebt_dnat.t b/extensions/libebt_dnat.t new file mode 100644 index 00000000..9428d237 --- /dev/null +++ b/extensions/libebt_dnat.t @@ -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 diff --git a/extensions/libebt_dnat.txlate b/extensions/libebt_dnat.txlate new file mode 100644 index 00000000..531a22aa --- /dev/null +++ b/extensions/libebt_dnat.txlate @@ -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' diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c new file mode 100644 index 00000000..3ed852ad --- /dev/null +++ b/extensions/libebt_ip.c @@ -0,0 +1,461 @@ +/* ebt_ip + * + * Authors: + * Bart De Schuymer + * + * Changes: + * added ip-sport and ip-dport; parsing of port arguments is + * based on code from iptables-1.2.7a + * Innominate Security Technologies AG + * September, 2002 + * + * Adapted by Arturo Borrero Gonzalez + * to use libxtables for ebtables-compat in 2015. + */ + +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/extensions/libebt_ip.t b/extensions/libebt_ip.t new file mode 100644 index 00000000..a9b5b8b5 --- /dev/null +++ b/extensions/libebt_ip.t @@ -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 diff --git a/extensions/libebt_ip.txlate b/extensions/libebt_ip.txlate new file mode 100644 index 00000000..712ba3d1 --- /dev/null +++ b/extensions/libebt_ip.txlate @@ -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' diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c new file mode 100644 index 00000000..247a99eb --- /dev/null +++ b/extensions/libebt_ip6.c @@ -0,0 +1,404 @@ +/* ebt_ip6 + * + * Authors: + * Kuo-Lang Tseng + * Manohar Castelino + * + * Summary: + * This is just a modification of the IPv4 code written by + * Bart De Schuymer + * with the changes required to support IPv6 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/extensions/libebt_ip6.t b/extensions/libebt_ip6.t new file mode 100644 index 00000000..cb1be9e3 --- /dev/null +++ b/extensions/libebt_ip6.t @@ -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 diff --git a/extensions/libebt_ip6.txlate b/extensions/libebt_ip6.txlate new file mode 100644 index 00000000..13d57e3a --- /dev/null +++ b/extensions/libebt_ip6.txlate @@ -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' diff --git a/extensions/libebt_limit.txlate b/extensions/libebt_limit.txlate new file mode 100644 index 00000000..adcce3ed --- /dev/null +++ b/extensions/libebt_limit.txlate @@ -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' diff --git a/extensions/libebt_log.c b/extensions/libebt_log.c new file mode 100644 index 00000000..dc2357c0 --- /dev/null +++ b/extensions/libebt_log.c @@ -0,0 +1,156 @@ +/* + * Bart De Schuymer + * + * 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 adapted the original code to the + * xtables-compat environment in 2015. + * + */ + +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/extensions/libebt_log.t b/extensions/libebt_log.t new file mode 100644 index 00000000..e6adbd3b --- /dev/null +++ b/extensions/libebt_log.t @@ -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 diff --git a/extensions/libebt_log.txlate b/extensions/libebt_log.txlate new file mode 100644 index 00000000..9847e4c1 --- /dev/null +++ b/extensions/libebt_log.txlate @@ -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' + diff --git a/extensions/libebt_mark.c b/extensions/libebt_mark.c new file mode 100644 index 00000000..0dc598fe --- /dev/null +++ b/extensions/libebt_mark.c @@ -0,0 +1,196 @@ +/* ebt_mark + * + * Authors: + * Bart De Schuymer + * + * July, 2002, September 2006 + * + * Adapted by Arturo Borrero Gonzalez + * to use libxtables for ebtables-compat in 2015. + */ + +#include +#include +#include +#include +#include +#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 + * -