import iptables-1.8.2-12.el8

This commit is contained in:
CentOS Sources 2019-08-01 17:26:06 -04:00 committed by Stepan Oksanichenko
commit 16a728d968
78 changed files with 14591 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/iptables-1.8.2.tar.bz2

1
.iptables.metadata Normal file
View File

@ -0,0 +1 @@
215c4ef4c6cd29ef0dd265b4fa5ec51a4f930c92 SOURCES/iptables-1.8.2.tar.bz2

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
From 7fe7c604d819d0b827f2abce253280b38a374cf1 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 17 Sep 2018 11:39:50 +0200
Subject: [PATCH] iptables-apply: Use mktemp instead of tempfile
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/iptables-apply | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/iptables/iptables-apply b/iptables/iptables-apply
index 819ca4a459c42..a685b6bbcd7dc 100755
--- a/iptables/iptables-apply
+++ b/iptables/iptables-apply
@@ -111,7 +111,7 @@ if [[ ! -r "$FILE" ]]; then
exit 2
fi
-COMMANDS=(tempfile "$SAVE" "$RESTORE")
+COMMANDS=(mktemp "$SAVE" "$RESTORE")
for cmd in "${COMMANDS[@]}"; do
if ! command -v $cmd >/dev/null; then
@@ -122,7 +122,7 @@ done
umask 0700
-TMPFILE=$(tempfile -p iptap)
+TMPFILE=$(mktemp)
trap "rm -f $TMPFILE" EXIT HUP INT QUIT ILL TRAP ABRT BUS \
FPE USR1 SEGV USR2 PIPE ALRM TERM
--
2.21.0

View File

@ -0,0 +1,61 @@
From 7e63dd95957a264d15eefdda3ea9449a6c72eb86 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adam=20Go=C5=82=C4=99biowski?= <adamg@pld-linux.org>
Date: Wed, 14 Nov 2018 07:35:28 +0100
Subject: [PATCH] extensions: format-security fixes in libip[6]t_icmp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
commit 61d6c3834de3 ("xtables: add 'printf' attribute to xlate_add")
introduced support for gcc feature to check format string against passed
argument. This commit adds missing bits to extenstions's libipt_icmp.c
and libip6t_icmp6.c that were causing build to fail.
Fixes: 61d6c3834de3 ("xtables: add 'printf' attribute to xlate_add")
Signed-off-by: Adam Gołębiowski <adamg@pld-linux.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 907e429d7548157016cd51aba4adc5d0c7d9f816)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libip6t_icmp6.c | 4 ++--
extensions/libipt_icmp.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/extensions/libip6t_icmp6.c b/extensions/libip6t_icmp6.c
index 45a71875722c4..cc7bfaeb72fd7 100644
--- a/extensions/libip6t_icmp6.c
+++ b/extensions/libip6t_icmp6.c
@@ -230,7 +230,7 @@ static unsigned int type_xlate_print(struct xt_xlate *xl, unsigned int icmptype,
type_name = icmp6_type_xlate(icmptype);
if (type_name) {
- xt_xlate_add(xl, type_name);
+ xt_xlate_add(xl, "%s", type_name);
} else {
for (i = 0; i < ARRAY_SIZE(icmpv6_codes); ++i)
if (icmpv6_codes[i].type == icmptype &&
@@ -239,7 +239,7 @@ static unsigned int type_xlate_print(struct xt_xlate *xl, unsigned int icmptype,
break;
if (i != ARRAY_SIZE(icmpv6_codes))
- xt_xlate_add(xl, icmpv6_codes[i].name);
+ xt_xlate_add(xl, "%s", icmpv6_codes[i].name);
else
return 0;
}
diff --git a/extensions/libipt_icmp.c b/extensions/libipt_icmp.c
index 5418997668d4c..e76257c54708c 100644
--- a/extensions/libipt_icmp.c
+++ b/extensions/libipt_icmp.c
@@ -236,7 +236,7 @@ static unsigned int type_xlate_print(struct xt_xlate *xl, unsigned int icmptype,
if (icmp_codes[i].type == icmptype &&
icmp_codes[i].code_min == code_min &&
icmp_codes[i].code_max == code_max) {
- xt_xlate_add(xl, icmp_codes[i].name);
+ xt_xlate_add(xl, "%s", icmp_codes[i].name);
return 1;
}
}
--
2.21.0

View File

@ -0,0 +1,190 @@
From abf79e364e9ef2dc355eb52d07d160b1f6c0f8c4 Mon Sep 17 00:00:00 2001
From: Florian Westphal <fw@strlen.de>
Date: Sun, 18 Nov 2018 12:31:33 +0100
Subject: [PATCH] arptables-nft: use generic expression parsing function
since commit d9c6a5d0977a6d8bbe772dbc31a2c4f58eec1708
("xtables: merge {ip,arp}tables_command_state structs") arptables
uses the shared representation.
With only minor changes (e.g., use generic counters in command_state),
in print/save functions we can use the shared nftnl expression parser
too.
arptables-legacy prints (-L) the jump target first, i.e.:
-j MARK -d 0.0.0.0/8 --h-length 6 ...
... so keep that here too.
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit aa5d3c5b16e94036ac0dc6d44194db7b009ced53)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libarpt_standard.t | 4 +-
iptables/nft-arp.c | 92 ++++-------------------------------
2 files changed, 12 insertions(+), 84 deletions(-)
diff --git a/extensions/libarpt_standard.t b/extensions/libarpt_standard.t
index bef682afec374..195865929c8d3 100644
--- a/extensions/libarpt_standard.t
+++ b/extensions/libarpt_standard.t
@@ -5,8 +5,8 @@
-d 192.168.0.1;=;OK
! -d 0.0.0.0;=;OK
-d 0.0.0.0/24;=;OK
--i lo;=;OK
-! -i lo;=;OK
+-i lo -j DROP;-i lo --h-length 6 --h-type 1 -j DROP;OK
+! -i lo -j ACCEPT;! -i lo --h-length 6 --h-type 1 -j ACCEPT;OK
-i ppp+;=;OK
! -i ppp+;=;OK
-i lo --destination-mac 11:22:33:44:55:66;-i lo --dst-mac 11:22:33:44:55:66;OK
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index 1a98996f94bda..37850bd328b71 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -412,56 +412,6 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
}
}
-static void nft_arp_rule_to_cs(const struct nftnl_rule *r,
- struct iptables_command_state *cs)
-{
- struct nftnl_expr_iter *iter;
- struct nftnl_expr *expr;
- int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
- struct nft_xt_ctx ctx = {
- .cs = cs,
- .family = family,
- };
-
- iter = nftnl_expr_iter_create(r);
- if (iter == NULL)
- return;
-
- ctx.iter = iter;
- expr = nftnl_expr_iter_next(iter);
- while (expr != NULL) {
- const char *name =
- nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
-
- if (strcmp(name, "counter") == 0)
- nft_parse_counter(expr, &ctx.cs->arp.counters);
- else if (strcmp(name, "payload") == 0)
- nft_parse_payload(&ctx, expr);
- else if (strcmp(name, "meta") == 0)
- nft_parse_meta(&ctx, expr);
- else if (strcmp(name, "bitwise") == 0)
- nft_parse_bitwise(&ctx, expr);
- else if (strcmp(name, "cmp") == 0)
- nft_parse_cmp(&ctx, expr);
- else if (strcmp(name, "immediate") == 0)
- nft_parse_immediate(&ctx, expr);
- else if (strcmp(name, "target") == 0)
- nft_parse_target(&ctx, expr);
-
- expr = nftnl_expr_iter_next(iter);
- }
-
- nftnl_expr_iter_destroy(iter);
-
- if (cs->jumpto != NULL)
- return;
-
- if (cs->target != NULL && cs->target->name != NULL)
- cs->target = xtables_find_target(cs->target->name, XTF_TRY_LOAD);
- else
- cs->jumpto = "";
-}
-
static void nft_arp_print_header(unsigned int format, const char *chain,
const char *pol,
const struct xt_counters *counters,
@@ -627,14 +577,6 @@ after_devdst:
}
}
-static void nft_arp_save_counters(const void *data)
-{
- const struct iptables_command_state *cs = data;
-
- printf("[%llu:%llu] ", (unsigned long long)cs->arp.counters.pcnt,
- (unsigned long long)cs->arp.counters.bcnt);
-}
-
static void
nft_arp_save_rule(const void *data, unsigned int format)
{
@@ -643,17 +585,7 @@ nft_arp_save_rule(const void *data, unsigned int format)
format |= FMT_NUMERIC;
nft_arp_print_rule_details(&cs->arp, format);
-
- if (cs->jumpto != NULL && strcmp(cs->jumpto, "") != 0) {
- printf("-j %s", cs->jumpto);
- } else if (cs->target) {
- printf("-j %s", cs->target->name);
- if (cs->target->save != NULL)
- cs->target->save(&cs->arp, cs->target->t);
- }
-
- if (!(format & FMT_NONEWLINE))
- fputc('\n', stdout);
+ save_matches_and_target(cs, false, &cs->arp, format);
}
static void
@@ -664,22 +596,18 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format)
if (format & FMT_LINENUMBERS)
printf("%u ", num);
- nft_arp_rule_to_cs(r, &cs);
+ nft_rule_to_iptables_command_state(r, &cs);
+ if (cs.jumpto)
+ printf("-j %s ", cs.jumpto);
nft_arp_print_rule_details(&cs.arp, format);
-
- if (cs.jumpto != NULL && strcmp(cs.jumpto, "") != 0) {
- printf("-j %s", cs.jumpto);
- } else if (cs.target) {
- printf("-j %s", cs.target->name);
- cs.target->print(&cs.arp, cs.target->t, format & FMT_NUMERIC);
- }
+ print_matches_and_target(&cs, format);
if (!(format & FMT_NOCOUNTS)) {
printf(", pcnt=");
- xtables_print_num(cs.arp.counters.pcnt, format);
+ xtables_print_num(cs.counters.pcnt, format);
printf("-- bcnt=");
- xtables_print_num(cs.arp.counters.bcnt, format);
+ xtables_print_num(cs.counters.bcnt, format);
}
if (!(format & FMT_NONEWLINE))
@@ -720,7 +648,7 @@ static bool nft_arp_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r,
struct iptables_command_state this = {};
/* Delete by matching rule case */
- nft_arp_rule_to_cs(r, &this);
+ nft_rule_to_iptables_command_state(r, &this);
if (!nft_arp_is_same(&cs->arp, &this.arp))
return false;
@@ -751,10 +679,10 @@ struct nft_family_ops nft_family_ops_arp = {
.print_header = nft_arp_print_header,
.print_rule = nft_arp_print_rule,
.save_rule = nft_arp_save_rule,
- .save_counters = nft_arp_save_counters,
+ .save_counters = save_counters,
.save_chain = nft_arp_save_chain,
.post_parse = NULL,
- .rule_to_cs = nft_arp_rule_to_cs,
+ .rule_to_cs = nft_rule_to_iptables_command_state,
.clear_cs = nft_clear_iptables_command_state,
.rule_find = nft_arp_rule_find,
.parse_target = nft_ipv46_parse_target,
--
2.21.0

View File

@ -0,0 +1,143 @@
From b7556207b12decbe4e79bf218ec5bff073a04ad2 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Tue, 27 Nov 2018 20:07:11 +0100
Subject: [PATCH] xtables: Don't use native nftables comments
The problem with converting libxt_comment into nftables comment is that
rules change when parsing from kernel due to comment match being moved
to the end of the match list. And since match ordering matters, the rule
may not be found anymore when checking or deleting. Apart from that,
iptables-nft didn't support multiple comments per rule anymore. This is
a compatibility issue without technical reason.
Leave conversion from nftables comment to libxt_comment in place so we
don't break running systems during an update.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit ccf154d7420c07b6e6febc1c3b8b31d2bd1adbe6)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libxt_comment.t | 2 ++
iptables/nft-ipv4.c | 14 +++-----------
iptables/nft-ipv6.c | 14 +++-----------
iptables/nft.c | 27 ---------------------------
iptables/nft.h | 1 -
5 files changed, 8 insertions(+), 50 deletions(-)
diff --git a/extensions/libxt_comment.t b/extensions/libxt_comment.t
index f12cd66841e7f..f0c8fb999401b 100644
--- a/extensions/libxt_comment.t
+++ b/extensions/libxt_comment.t
@@ -1,6 +1,8 @@
:INPUT,FORWARD,OUTPUT
-m comment;;FAIL
-m comment --comment;;FAIL
+-p tcp -m tcp --dport 22 -m comment --comment foo;=;OK
+-p tcp -m comment --comment foo -m tcp --dport 22;=;OK
#
# it fails with 256 characters
#
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index ffb439b4a1128..4497eb9b9347c 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -77,17 +77,9 @@ static int nft_ipv4_add(struct nftnl_rule *r, void *data)
add_compat(r, cs->fw.ip.proto, cs->fw.ip.invflags & XT_INV_PROTO);
for (matchp = cs->matches; matchp; matchp = matchp->next) {
- /* Use nft built-in comments support instead of comment match */
- if (strcmp(matchp->match->name, "comment") == 0) {
- ret = add_comment(r, (char *)matchp->match->m->data);
- if (ret < 0)
- goto try_match;
- } else {
-try_match:
- ret = add_match(r, matchp->match->m);
- if (ret < 0)
- return ret;
- }
+ ret = add_match(r, matchp->match->m);
+ if (ret < 0)
+ return ret;
}
/* Counters need to me added before the target, otherwise they are
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 7bacee4ab3a21..cacb1c9e141f2 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -66,17 +66,9 @@ static int nft_ipv6_add(struct nftnl_rule *r, void *data)
add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags & XT_INV_PROTO);
for (matchp = cs->matches; matchp; matchp = matchp->next) {
- /* Use nft built-in comments support instead of comment match */
- if (strcmp(matchp->match->name, "comment") == 0) {
- ret = add_comment(r, (char *)matchp->match->m->data);
- if (ret < 0)
- goto try_match;
- } else {
-try_match:
- ret = add_match(r, matchp->match->m);
- if (ret < 0)
- return ret;
- }
+ ret = add_match(r, matchp->match->m);
+ if (ret < 0)
+ return ret;
}
/* Counters need to me added before the target, otherwise they are
diff --git a/iptables/nft.c b/iptables/nft.c
index e8538d38e0109..6863d851e44c2 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1107,33 +1107,6 @@ enum udata_type {
};
#define UDATA_TYPE_MAX (__UDATA_TYPE_MAX - 1)
-int add_comment(struct nftnl_rule *r, const char *comment)
-{
- struct nftnl_udata_buf *udata;
- uint32_t len;
-
- if (nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len))
- return -EALREADY;
-
- udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
- if (!udata)
- return -ENOMEM;
-
- if (strnlen(comment, 255) == 255)
- return -ENOSPC;
-
- if (!nftnl_udata_put_strz(udata, UDATA_TYPE_COMMENT, comment))
- return -ENOMEM;
-
- nftnl_rule_set_data(r, NFTNL_RULE_USERDATA,
- nftnl_udata_buf_data(udata),
- nftnl_udata_buf_len(udata));
-
- nftnl_udata_buf_free(udata);
-
- return 0;
-}
-
static int parse_udata_cb(const struct nftnl_udata *attr, void *data)
{
unsigned char *value = nftnl_udata_get(attr);
diff --git a/iptables/nft.h b/iptables/nft.h
index 9b4ba5f9a63eb..052105fc6f3cd 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -116,7 +116,6 @@ int add_match(struct nftnl_rule *r, struct xt_entry_match *m);
int add_target(struct nftnl_rule *r, struct xt_entry_target *t);
int add_jumpto(struct nftnl_rule *r, const char *name, int verdict);
int add_action(struct nftnl_rule *r, struct iptables_command_state *cs, bool goto_set);
-int add_comment(struct nftnl_rule *r, const char *comment);
char *get_comment(const void *data, uint32_t data_len);
enum nft_rule_print {
--
2.21.0

View File

@ -0,0 +1,592 @@
From a09e8ae2a1e2ff589af839ad3460493fc04306d7 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 15 Nov 2018 14:53:02 +0100
Subject: [PATCH] xtables: Introduce per table chain caches
Being able to omit the previously obligatory table name check when
iterating over the chain cache might help restore performance with large
rulesets in xtables-save and -restore.
There is one subtle quirk in the code: flush_chain_cache() did free the
global chain cache if not called with a table name but didn't if a table
name was given even if it emptied the chain cache. In other places,
chain_cache being non-NULL prevented a cache update from happening, so
this patch establishes the same behaviour (for each individual chain
cache) since otherwise unexpected cache updates lead to weird problems.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit c58ecf9f8bcb7619a27ef8ffaddf847a562475a5)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-shared.h | 3 +-
iptables/nft.c | 160 +++++++++++++++++--------------------
iptables/nft.h | 10 ++-
iptables/xtables-restore.c | 16 ++--
iptables/xtables-save.c | 12 +--
5 files changed, 95 insertions(+), 106 deletions(-)
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index e3ecdb4d23df3..9a61d8d2863e3 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -251,7 +251,8 @@ struct nftnl_chain_list;
struct nft_xt_restore_cb {
void (*table_new)(struct nft_handle *h, const char *table);
- struct nftnl_chain_list *(*chain_list)(struct nft_handle *h);
+ struct nftnl_chain_list *(*chain_list)(struct nft_handle *h,
+ const char *table);
void (*chain_del)(struct nftnl_chain_list *clist, const char *curtable,
const char *chain);
int (*chain_user_flush)(struct nft_handle *h,
diff --git a/iptables/nft.c b/iptables/nft.c
index 6863d851e44c2..36529048a0ca6 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -673,15 +673,17 @@ nft_chain_builtin_find(struct builtin_table *t, const char *chain)
static void nft_chain_builtin_init(struct nft_handle *h,
struct builtin_table *table)
{
- struct nftnl_chain_list *list = nft_chain_list_get(h);
+ struct nftnl_chain_list *list = nft_chain_list_get(h, table->name);
struct nftnl_chain *c;
int i;
+ if (!list)
+ return;
+
/* Initialize built-in chains if they don't exist yet */
for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) {
- c = nft_chain_list_find(list, table->name,
- table->chains[i].name);
+ c = nft_chain_list_find(list, table->chains[i].name);
if (c != NULL)
continue;
@@ -782,27 +784,33 @@ static void flush_rule_cache(struct nft_handle *h, const char *tablename)
static int __flush_chain_cache(struct nftnl_chain *c, void *data)
{
- const char *tablename = data;
-
- if (!strcmp(nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), tablename)) {
- nftnl_chain_list_del(c);
- nftnl_chain_free(c);
- }
+ nftnl_chain_list_del(c);
+ nftnl_chain_free(c);
return 0;
}
static void flush_chain_cache(struct nft_handle *h, const char *tablename)
{
- if (!h->chain_cache)
- return;
+ int i;
- if (tablename) {
- nftnl_chain_list_foreach(h->chain_cache, __flush_chain_cache,
- (void *)tablename);
- } else {
- nftnl_chain_list_free(h->chain_cache);
- h->chain_cache = NULL;
+ for (i = 0; i < NFT_TABLE_MAX; i++) {
+ if (h->tables[i].name == NULL)
+ continue;
+
+ if (tablename && strcmp(h->tables[i].name, tablename))
+ continue;
+
+ if (h->tables[i].chain_cache) {
+ if (tablename) {
+ nftnl_chain_list_foreach(h->tables[i].chain_cache,
+ __flush_chain_cache, NULL);
+ break;
+ } else {
+ nftnl_chain_list_free(h->tables[i].chain_cache);
+ h->tables[i].chain_cache = NULL;
+ }
+ }
}
}
@@ -1244,8 +1252,9 @@ nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
{
+ struct nft_handle *h = data;
+ struct builtin_table *t;
struct nftnl_chain *c;
- struct nftnl_chain_list *list = data;
c = nftnl_chain_alloc();
if (c == NULL)
@@ -1254,7 +1263,18 @@ static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
if (nftnl_chain_nlmsg_parse(nlh, c) < 0)
goto out;
- nftnl_chain_list_add_tail(c, list);
+ t = nft_table_builtin_find(h,
+ nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE));
+ if (!t)
+ goto out;
+
+ if (!t->chain_cache) {
+ t->chain_cache = nftnl_chain_list_alloc();
+ if (!t->chain_cache)
+ goto out;
+ }
+
+ nftnl_chain_list_add_tail(c, t->chain_cache);
return MNL_CB_OK;
out:
@@ -1263,35 +1283,34 @@ err:
return MNL_CB_OK;
}
-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h)
+struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
+ const char *table)
{
char buf[16536];
struct nlmsghdr *nlh;
- struct nftnl_chain_list *list;
+ struct builtin_table *t;
int ret;
- if (h->chain_cache)
- return h->chain_cache;
-retry:
- list = nftnl_chain_list_alloc();
- if (list == NULL) {
- errno = ENOMEM;
+ t = nft_table_builtin_find(h, table);
+ if (!t)
return NULL;
- }
+ if (t->chain_cache)
+ return t->chain_cache;
+retry:
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
NLM_F_DUMP, h->seq);
- ret = mnl_talk(h, nlh, nftnl_chain_list_cb, list);
+ ret = mnl_talk(h, nlh, nftnl_chain_list_cb, h);
if (ret < 0 && errno == EINTR) {
assert(nft_restart(h) >= 0);
- nftnl_chain_list_free(list);
goto retry;
}
- h->chain_cache = list;
+ if (!t->chain_cache)
+ t->chain_cache = nftnl_chain_list_alloc();
- return list;
+ return t->chain_cache;
}
static const char *policy_name[NF_ACCEPT+1] = {
@@ -1299,8 +1318,7 @@ static const char *policy_name[NF_ACCEPT+1] = {
[NF_ACCEPT] = "ACCEPT",
};
-int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list,
- const char *table)
+int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list)
{
struct nftnl_chain_list_iter *iter;
struct nft_family_ops *ops;
@@ -1314,13 +1332,8 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list,
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
- const char *chain_table =
- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
const char *policy = NULL;
- if (strcmp(table, chain_table) != 0)
- goto next;
-
if (nft_chain_builtin(c)) {
uint32_t pol = NF_ACCEPT;
@@ -1331,7 +1344,7 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list,
if (ops->save_chain)
ops->save_chain(c, policy);
-next:
+
c = nftnl_chain_list_iter_next(iter);
}
@@ -1502,7 +1515,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
nft_fn = nft_rule_flush;
- list = nft_chain_list_get(h);
+ list = nft_chain_list_get(h, table);
if (list == NULL) {
ret = 1;
goto err;
@@ -1516,21 +1529,16 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
- const char *table_name =
- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
const char *chain_name =
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- if (strcmp(table, table_name) != 0)
- goto next;
-
if (chain != NULL && strcmp(chain, chain_name) != 0)
goto next;
if (verbose)
fprintf(stdout, "Flushing chain `%s'\n", chain_name);
- __nft_rule_flush(h, table_name, chain_name);
+ __nft_rule_flush(h, table, chain_name);
if (chain != NULL)
break;
@@ -1546,6 +1554,7 @@ err:
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table)
{
+ struct nftnl_chain_list *list;
struct nftnl_chain *c;
int ret;
@@ -1564,9 +1573,9 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
- nft_chain_list_get(h);
-
- nftnl_chain_list_add(c, h->chain_cache);
+ list = nft_chain_list_get(h, table);
+ if (list)
+ nftnl_chain_list_add(c, list);
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
@@ -1588,7 +1597,7 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain,
nft_fn = nft_chain_user_del;
- list = nft_chain_list_get(h);
+ list = nft_chain_list_get(h, table);
if (list == NULL)
goto err;
@@ -1598,8 +1607,6 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain,
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
- const char *table_name =
- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
const char *chain_name =
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
@@ -1607,9 +1614,6 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain,
if (nft_chain_builtin(c))
goto next;
- if (strcmp(table, table_name) != 0)
- goto next;
-
if (chain != NULL && strcmp(chain, chain_name) != 0)
goto next;
@@ -1644,8 +1648,7 @@ err:
}
struct nftnl_chain *
-nft_chain_list_find(struct nftnl_chain_list *list,
- const char *table, const char *chain)
+nft_chain_list_find(struct nftnl_chain_list *list, const char *chain)
{
struct nftnl_chain_list_iter *iter;
struct nftnl_chain *c;
@@ -1656,14 +1659,9 @@ nft_chain_list_find(struct nftnl_chain_list *list,
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
- const char *table_name =
- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
const char *chain_name =
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- if (strcmp(table, table_name) != 0)
- goto next;
-
if (strcmp(chain, chain_name) != 0)
goto next;
@@ -1681,11 +1679,11 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
{
struct nftnl_chain_list *list;
- list = nft_chain_list_get(h);
+ list = nft_chain_list_get(h, table);
if (list == NULL)
return NULL;
- return nft_chain_list_find(list, table, chain);
+ return nft_chain_list_find(list, chain);
}
bool nft_chain_exists(struct nft_handle *h,
@@ -2297,7 +2295,9 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
return 1;
}
- list = nft_chain_list_get(h);
+ list = nft_chain_list_get(h, table);
+ if (!list)
+ goto err; /* XXX: return 0 instead? */
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
@@ -2308,8 +2308,6 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
- const char *chain_table =
- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
const char *chain_name =
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
uint32_t policy =
@@ -2326,8 +2324,6 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM))
basechain = true;
- if (strcmp(table, chain_table) != 0)
- goto next;
if (chain) {
if (strcmp(chain, chain_name) != 0)
goto next;
@@ -2442,7 +2438,9 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
return 0;
}
- list = nft_chain_list_get(h);
+ list = nft_chain_list_get(h, table);
+ if (!list)
+ goto err; /* XXX: correct? */
/* Dump policies and custom chains first */
if (!rulenum)
@@ -2460,13 +2458,9 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
- const char *chain_table =
- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
const char *chain_name =
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- if (strcmp(table, chain_table) != 0)
- goto next;
if (chain && strcmp(chain, chain_name) != 0)
goto next;
@@ -3045,7 +3039,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
struct nftnl_chain *c;
int ret = 0;
- list = nft_chain_list_get(h);
+ list = nft_chain_list_get(h, table);
if (list == NULL)
goto err;
@@ -3057,11 +3051,6 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
while (c != NULL) {
const char *chain_name =
nftnl_chain_get(c, NFTNL_CHAIN_NAME);
- const char *chain_table =
- nftnl_chain_get(c, NFTNL_CHAIN_TABLE);
-
- if (strcmp(table, chain_table) != 0)
- goto next;
if (chain != NULL && strcmp(chain, chain_name) != 0)
goto next;
@@ -3202,7 +3191,7 @@ static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename
struct nftnl_chain *chain;
int ret = 0;
- list = nft_chain_list_get(h);
+ list = nft_chain_list_get(h, tablename);
if (list == NULL)
return -1;
@@ -3212,12 +3201,7 @@ static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename
chain = nftnl_chain_list_iter_next(iter);
while (chain != NULL) {
- const char *chain_table;
-
- chain_table = nftnl_chain_get_str(chain, NFTNL_CHAIN_TABLE);
-
- if (strcmp(chain_table, tablename) ||
- !nft_chain_builtin(chain))
+ if (!nft_chain_builtin(chain))
goto next;
ret = nft_is_chain_compatible(h, chain);
diff --git a/iptables/nft.h b/iptables/nft.h
index 052105fc6f3cd..6229221bd51f7 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -25,6 +25,7 @@ struct builtin_table {
const char *name;
struct builtin_chain chains[NF_INET_NUMHOOKS];
bool initialized;
+ struct nftnl_chain_list *chain_cache;
};
struct nft_handle {
@@ -38,7 +39,6 @@ struct nft_handle {
struct list_head err_list;
struct nft_family_ops *ops;
struct builtin_table *tables;
- struct nftnl_chain_list *chain_cache;
struct nftnl_rule_list *rule_cache;
bool restore;
int8_t config_done;
@@ -78,9 +78,11 @@ struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *t
struct nftnl_chain;
int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters);
-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h);
-struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, const char *table, const char *chain);
-int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, const char *table);
+struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
+ const char *table);
+struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list,
+ const char *chain);
+int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list);
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table);
int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose);
int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index f529774054215..a46a92955a01a 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -56,11 +56,12 @@ static void print_usage(const char *name, const char *version)
" [ --ipv6 ]\n", name);
}
-static struct nftnl_chain_list *get_chain_list(struct nft_handle *h)
+static struct nftnl_chain_list *get_chain_list(struct nft_handle *h,
+ const char *table)
{
struct nftnl_chain_list *chain_list;
- chain_list = nft_chain_list_get(h);
+ chain_list = nft_chain_list_get(h, table);
if (chain_list == NULL)
xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n");
@@ -72,7 +73,7 @@ static void chain_delete(struct nftnl_chain_list *clist, const char *curtable,
{
struct nftnl_chain *chain_obj;
- chain_obj = nft_chain_list_find(clist, curtable, chain);
+ chain_obj = nft_chain_list_find(clist, chain);
/* This chain has been found, delete from list. Later
* on, unvisited chains will be purged out.
*/
@@ -112,9 +113,6 @@ void xtables_restore_parse(struct nft_handle *h,
line = 0;
- if (cb->chain_list)
- chain_list = cb->chain_list(h);
-
/* Grab standard input. */
while (fgets(buffer, sizeof(buffer), p->in)) {
int ret = 0;
@@ -165,6 +163,9 @@ void xtables_restore_parse(struct nft_handle *h,
if (p->tablename && (strcmp(p->tablename, table) != 0))
continue;
+ if (cb->chain_list)
+ chain_list = cb->chain_list(h, table);
+
if (noflush == 0) {
DEBUGP("Cleaning all chains of table '%s'\n",
table);
@@ -197,8 +198,7 @@ void xtables_restore_parse(struct nft_handle *h,
if (cb->chain_del)
cb->chain_del(chain_list, curtable->name,
chain);
- } else if (nft_chain_list_find(chain_list,
- curtable->name, chain)) {
+ } else if (nft_chain_list_find(chain_list, chain)) {
chain_exists = true;
/* Apparently -n still flushes existing user
* defined chains that are redefined. Otherwise,
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index bed3ee0318995..d121d50e180ff 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -73,7 +73,9 @@ __do_output(struct nft_handle *h, const char *tablename, bool counters)
return 0;
}
- chain_list = nft_chain_list_get(h);
+ chain_list = nft_chain_list_get(h, tablename);
+ if (!chain_list)
+ return 0;
time_t now = time(NULL);
@@ -83,7 +85,7 @@ __do_output(struct nft_handle *h, const char *tablename, bool counters)
/* Dump out chain names first,
* thereby preventing dependency conflicts */
- nft_chain_save(h, chain_list, tablename);
+ nft_chain_save(h, chain_list);
nft_rule_save(h, tablename, counters ? 0 : FMT_NOCOUNTS);
now = time(NULL);
@@ -257,7 +259,7 @@ static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters
return 0;
}
- chain_list = nft_chain_list_get(h);
+ chain_list = nft_chain_list_get(h, tablename);
if (first) {
now = time(NULL);
@@ -272,7 +274,7 @@ static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters
/* Dump out chain names first,
* thereby preventing dependency conflicts */
- nft_chain_save(h, chain_list, tablename);
+ nft_chain_save(h, chain_list);
nft_rule_save(h, tablename, format);
printf("\n");
return 0;
@@ -399,7 +401,7 @@ int xtables_arp_save_main(int argc, char **argv)
}
printf("*filter\n");
- nft_chain_save(&h, nft_chain_list_get(&h), "filter");
+ nft_chain_save(&h, nft_chain_list_get(&h, "filter"));
nft_rule_save(&h, "filter", show_counters ? 0 : FMT_NOCOUNTS);
printf("\n");
nft_fini(&h);
--
2.21.0

View File

@ -0,0 +1,99 @@
From 312897725486bf4a3014076f3659cc1d8ce294ce Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Sat, 17 Nov 2018 18:10:15 +0100
Subject: [PATCH] nft: add type field to builtin_table
Use enum nft_table_type to set the new type field in the structure that
define tables.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 9847abe6fbb91621f6494df8243ff96f04efdc4a)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 8 ++++++++
iptables/nft.h | 1 +
2 files changed, 9 insertions(+)
diff --git a/iptables/nft.c b/iptables/nft.c
index 36529048a0ca6..f0a60e1f568af 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -379,6 +379,7 @@ static int batch_rule_add(struct nft_handle *h, enum obj_update_type type,
struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
[NFT_TABLE_RAW] = {
.name = "raw",
+ .type = NFT_TABLE_RAW,
.chains = {
{
.name = "PREROUTING",
@@ -396,6 +397,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
},
[NFT_TABLE_MANGLE] = {
.name = "mangle",
+ .type = NFT_TABLE_MANGLE,
.chains = {
{
.name = "PREROUTING",
@@ -431,6 +433,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
},
[NFT_TABLE_FILTER] = {
.name = "filter",
+ .type = NFT_TABLE_FILTER,
.chains = {
{
.name = "INPUT",
@@ -454,6 +457,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
},
[NFT_TABLE_SECURITY] = {
.name = "security",
+ .type = NFT_TABLE_SECURITY,
.chains = {
{
.name = "INPUT",
@@ -477,6 +481,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
},
[NFT_TABLE_NAT] = {
.name = "nat",
+ .type = NFT_TABLE_NAT,
.chains = {
{
.name = "PREROUTING",
@@ -511,6 +516,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
struct builtin_table xtables_arp[NFT_TABLE_MAX] = {
[NFT_TABLE_FILTER] = {
.name = "filter",
+ .type = NFT_TABLE_FILTER,
.chains = {
{
.name = "INPUT",
@@ -533,6 +539,7 @@ struct builtin_table xtables_arp[NFT_TABLE_MAX] = {
struct builtin_table xtables_bridge[NFT_TABLE_MAX] = {
[NFT_TABLE_FILTER] = {
.name = "filter",
+ .type = NFT_TABLE_FILTER,
.chains = {
{
.name = "INPUT",
@@ -556,6 +563,7 @@ struct builtin_table xtables_bridge[NFT_TABLE_MAX] = {
},
[NFT_TABLE_NAT] = {
.name = "nat",
+ .type = NFT_TABLE_NAT,
.chains = {
{
.name = "PREROUTING",
diff --git a/iptables/nft.h b/iptables/nft.h
index 6229221bd51f7..85c894e80e02e 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -23,6 +23,7 @@ struct builtin_chain {
struct builtin_table {
const char *name;
+ enum nft_table_type type;
struct builtin_chain chains[NF_INET_NUMHOOKS];
bool initialized;
struct nftnl_chain_list *chain_cache;
--
2.21.0

View File

@ -0,0 +1,106 @@
From 48455efdfbee0df02c724a594cf8af8c440ded7d Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Sat, 17 Nov 2018 18:16:45 +0100
Subject: [PATCH] nft: move chain_cache back to struct nft_handle
Place this back into the structure that stores the state information.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 1847d9db753825b0bd1cd450b549f4e39f7bcc31)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 26 +++++++++++++-------------
iptables/nft.h | 4 +++-
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index f0a60e1f568af..fdb4ead55a873 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -809,14 +809,14 @@ static void flush_chain_cache(struct nft_handle *h, const char *tablename)
if (tablename && strcmp(h->tables[i].name, tablename))
continue;
- if (h->tables[i].chain_cache) {
+ if (h->table[i].chain_cache) {
if (tablename) {
- nftnl_chain_list_foreach(h->tables[i].chain_cache,
+ nftnl_chain_list_foreach(h->table[i].chain_cache,
__flush_chain_cache, NULL);
break;
} else {
- nftnl_chain_list_free(h->tables[i].chain_cache);
- h->tables[i].chain_cache = NULL;
+ nftnl_chain_list_free(h->table[i].chain_cache);
+ h->table[i].chain_cache = NULL;
}
}
}
@@ -1276,13 +1276,13 @@ static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
if (!t)
goto out;
- if (!t->chain_cache) {
- t->chain_cache = nftnl_chain_list_alloc();
- if (!t->chain_cache)
+ if (!h->table[t->type].chain_cache) {
+ h->table[t->type].chain_cache = nftnl_chain_list_alloc();
+ if (!h->table[t->type].chain_cache)
goto out;
}
- nftnl_chain_list_add_tail(c, t->chain_cache);
+ nftnl_chain_list_add_tail(c, h->table[t->type].chain_cache);
return MNL_CB_OK;
out:
@@ -1303,8 +1303,8 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
if (!t)
return NULL;
- if (t->chain_cache)
- return t->chain_cache;
+ if (h->table[t->type].chain_cache)
+ return h->table[t->type].chain_cache;
retry:
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
NLM_F_DUMP, h->seq);
@@ -1315,10 +1315,10 @@ retry:
goto retry;
}
- if (!t->chain_cache)
- t->chain_cache = nftnl_chain_list_alloc();
+ if (!h->table[t->type].chain_cache)
+ h->table[t->type].chain_cache = nftnl_chain_list_alloc();
- return t->chain_cache;
+ return h->table[t->type].chain_cache;
}
static const char *policy_name[NF_ACCEPT+1] = {
diff --git a/iptables/nft.h b/iptables/nft.h
index 85c894e80e02e..1c028206221c4 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -26,7 +26,6 @@ struct builtin_table {
enum nft_table_type type;
struct builtin_chain chains[NF_INET_NUMHOOKS];
bool initialized;
- struct nftnl_chain_list *chain_cache;
};
struct nft_handle {
@@ -40,6 +39,9 @@ struct nft_handle {
struct list_head err_list;
struct nft_family_ops *ops;
struct builtin_table *tables;
+ struct {
+ struct nftnl_chain_list *chain_cache;
+ } table[NFT_TABLE_MAX];
struct nftnl_rule_list *rule_cache;
bool restore;
int8_t config_done;
--
2.21.0

View File

@ -0,0 +1,91 @@
From 6186853420f23e500e0b9a234cc446697cca16a7 Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Sat, 17 Nov 2018 18:38:30 +0100
Subject: [PATCH] nft: move initialize to struct nft_handle
Move this to the structure that stores, stateful information. Introduce
nft_table_initialized() and use it.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 5016d1eb84f951d84f5a0c18f994f40677ad0643)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 14 ++++++++++----
iptables/nft.h | 2 +-
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index fdb4ead55a873..9b479307a2fbc 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -587,13 +587,19 @@ struct builtin_table xtables_bridge[NFT_TABLE_MAX] = {
},
};
+static bool nft_table_initialized(const struct nft_handle *h,
+ enum nft_table_type type)
+{
+ return h->table[type].initialized;
+}
+
static int nft_table_builtin_add(struct nft_handle *h,
struct builtin_table *_t)
{
struct nftnl_table *t;
int ret;
- if (_t->initialized)
+ if (nft_table_initialized(h, _t->type))
return 0;
t = nftnl_table_alloc();
@@ -707,7 +713,7 @@ static int nft_xt_builtin_init(struct nft_handle *h, const char *table)
if (t == NULL)
return -1;
- if (t->initialized)
+ if (nft_table_initialized(h, t->type))
return 0;
if (nft_table_builtin_add(h, t) < 0)
@@ -715,7 +721,7 @@ static int nft_xt_builtin_init(struct nft_handle *h, const char *table)
nft_chain_builtin_init(h, t);
- t->initialized = true;
+ h->table[t->type].initialized = true;
return 0;
}
@@ -1875,7 +1881,7 @@ static int __nft_table_flush(struct nft_handle *h, const char *table)
_t = nft_table_builtin_find(h, table);
assert(_t);
- _t->initialized = false;
+ h->table[_t->type].initialized = false;
flush_chain_cache(h, table);
flush_rule_cache(h, table);
diff --git a/iptables/nft.h b/iptables/nft.h
index 1c028206221c4..b9ba66b110042 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -25,7 +25,6 @@ struct builtin_table {
const char *name;
enum nft_table_type type;
struct builtin_chain chains[NF_INET_NUMHOOKS];
- bool initialized;
};
struct nft_handle {
@@ -41,6 +40,7 @@ struct nft_handle {
struct builtin_table *tables;
struct {
struct nftnl_chain_list *chain_cache;
+ bool initialized;
} table[NFT_TABLE_MAX];
struct nftnl_rule_list *rule_cache;
bool restore;
--
2.21.0

View File

@ -0,0 +1,287 @@
From e73749ba27388068af05e78ed6cb03b1824182c0 Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Sat, 17 Nov 2018 18:25:58 +0100
Subject: [PATCH] xtables: constify struct builtin_table and struct
builtin_chain
These definitions should be const, propagate this to all existing users.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 3c7ea26c85b95a4c62355c359030d6bbdf2f8df0)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 42 ++++++++++++++++++------------------
iptables/nft.h | 14 ++++++------
iptables/xtables-restore.c | 4 ++--
iptables/xtables-save.c | 2 +-
iptables/xtables-translate.c | 2 +-
5 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 9b479307a2fbc..7b6fb2b10686d 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -376,7 +376,7 @@ static int batch_rule_add(struct nft_handle *h, enum obj_update_type type,
return batch_add(h, type, r);
}
-struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
+const struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
[NFT_TABLE_RAW] = {
.name = "raw",
.type = NFT_TABLE_RAW,
@@ -513,7 +513,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
#include <linux/netfilter_arp.h>
-struct builtin_table xtables_arp[NFT_TABLE_MAX] = {
+const struct builtin_table xtables_arp[NFT_TABLE_MAX] = {
[NFT_TABLE_FILTER] = {
.name = "filter",
.type = NFT_TABLE_FILTER,
@@ -536,7 +536,7 @@ struct builtin_table xtables_arp[NFT_TABLE_MAX] = {
#include <linux/netfilter_bridge.h>
-struct builtin_table xtables_bridge[NFT_TABLE_MAX] = {
+const struct builtin_table xtables_bridge[NFT_TABLE_MAX] = {
[NFT_TABLE_FILTER] = {
.name = "filter",
.type = NFT_TABLE_FILTER,
@@ -594,7 +594,7 @@ static bool nft_table_initialized(const struct nft_handle *h,
}
static int nft_table_builtin_add(struct nft_handle *h,
- struct builtin_table *_t)
+ const struct builtin_table *_t)
{
struct nftnl_table *t;
int ret;
@@ -614,8 +614,8 @@ static int nft_table_builtin_add(struct nft_handle *h,
}
static struct nftnl_chain *
-nft_chain_builtin_alloc(struct builtin_table *table,
- struct builtin_chain *chain, int policy)
+nft_chain_builtin_alloc(const struct builtin_table *table,
+ const struct builtin_chain *chain, int policy)
{
struct nftnl_chain *c;
@@ -634,8 +634,8 @@ nft_chain_builtin_alloc(struct builtin_table *table,
}
static void nft_chain_builtin_add(struct nft_handle *h,
- struct builtin_table *table,
- struct builtin_chain *chain)
+ const struct builtin_table *table,
+ const struct builtin_chain *chain)
{
struct nftnl_chain *c;
@@ -647,7 +647,7 @@ static void nft_chain_builtin_add(struct nft_handle *h,
}
/* find if built-in table already exists */
-struct builtin_table *
+const struct builtin_table *
nft_table_builtin_find(struct nft_handle *h, const char *table)
{
int i;
@@ -668,8 +668,8 @@ nft_table_builtin_find(struct nft_handle *h, const char *table)
}
/* find if built-in chain already exists */
-struct builtin_chain *
-nft_chain_builtin_find(struct builtin_table *t, const char *chain)
+const struct builtin_chain *
+nft_chain_builtin_find(const struct builtin_table *t, const char *chain)
{
int i;
bool found = false;
@@ -685,7 +685,7 @@ nft_chain_builtin_find(struct builtin_table *t, const char *chain)
}
static void nft_chain_builtin_init(struct nft_handle *h,
- struct builtin_table *table)
+ const struct builtin_table *table)
{
struct nftnl_chain_list *list = nft_chain_list_get(h, table->name);
struct nftnl_chain *c;
@@ -707,7 +707,7 @@ static void nft_chain_builtin_init(struct nft_handle *h,
static int nft_xt_builtin_init(struct nft_handle *h, const char *table)
{
- struct builtin_table *t;
+ const struct builtin_table *t;
t = nft_table_builtin_find(h, table);
if (t == NULL)
@@ -750,7 +750,7 @@ static int nft_restart(struct nft_handle *h)
return 0;
}
-int nft_init(struct nft_handle *h, struct builtin_table *t)
+int nft_init(struct nft_handle *h, const struct builtin_table *t)
{
h->nl = mnl_socket_open(NETLINK_NETFILTER);
if (h->nl == NULL)
@@ -852,8 +852,8 @@ static struct nftnl_chain *nft_chain_new(struct nft_handle *h,
const struct xt_counters *counters)
{
struct nftnl_chain *c;
- struct builtin_table *_t;
- struct builtin_chain *_c;
+ const struct builtin_table *_t;
+ const struct builtin_chain *_c;
_t = nft_table_builtin_find(h, table);
if (!_t) {
@@ -1267,7 +1267,7 @@ nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nft_handle *h = data;
- struct builtin_table *t;
+ const struct builtin_table *t;
struct nftnl_chain *c;
c = nftnl_chain_alloc();
@@ -1302,7 +1302,7 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
{
char buf[16536];
struct nlmsghdr *nlh;
- struct builtin_table *t;
+ const struct builtin_table *t;
int ret;
t = nft_table_builtin_find(h, table);
@@ -1703,7 +1703,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
bool nft_chain_exists(struct nft_handle *h,
const char *table, const char *chain)
{
- struct builtin_table *t = nft_table_builtin_find(h, table);
+ const struct builtin_table *t = nft_table_builtin_find(h, table);
/* xtables does not support custom tables */
if (!t)
@@ -1868,7 +1868,7 @@ int nft_for_each_table(struct nft_handle *h,
static int __nft_table_flush(struct nft_handle *h, const char *table)
{
- struct builtin_table *_t;
+ const struct builtin_table *_t;
struct nftnl_table *t;
t = nftnl_table_alloc();
@@ -3166,7 +3166,7 @@ static int nft_is_chain_compatible(const struct nft_handle *h,
const struct nftnl_chain *chain)
{
const char *table, *name, *type, *cur_table;
- struct builtin_chain *chains;
+ const struct builtin_chain *chains;
int i, j, prio;
enum nf_inet_hooks hook;
diff --git a/iptables/nft.h b/iptables/nft.h
index b9ba66b110042..bf60ab3943659 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -37,7 +37,7 @@ struct nft_handle {
struct nftnl_batch *batch;
struct list_head err_list;
struct nft_family_ops *ops;
- struct builtin_table *tables;
+ const struct builtin_table *tables;
struct {
struct nftnl_chain_list *chain_cache;
bool initialized;
@@ -52,14 +52,14 @@ struct nft_handle {
} error;
};
-extern struct builtin_table xtables_ipv4[NFT_TABLE_MAX];
-extern struct builtin_table xtables_arp[NFT_TABLE_MAX];
-extern struct builtin_table xtables_bridge[NFT_TABLE_MAX];
+extern const struct builtin_table xtables_ipv4[NFT_TABLE_MAX];
+extern const struct builtin_table xtables_arp[NFT_TABLE_MAX];
+extern const struct builtin_table xtables_bridge[NFT_TABLE_MAX];
int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
int (*cb)(const struct nlmsghdr *nlh, void *data),
void *data);
-int nft_init(struct nft_handle *h, struct builtin_table *t);
+int nft_init(struct nft_handle *h, const struct builtin_table *t);
void nft_fini(struct nft_handle *h);
/*
@@ -73,7 +73,7 @@ bool nft_table_find(struct nft_handle *h, const char *tablename);
int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nftnl_chain_list *list);
int nft_table_flush(struct nft_handle *h, const char *table);
void nft_table_new(struct nft_handle *h, const char *table);
-struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table);
+const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table);
/*
* Operations with chains.
@@ -92,7 +92,7 @@ int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
const char *chain, const char *table);
int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *table, const char *newname);
int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table, bool verbose);
-struct builtin_chain *nft_chain_builtin_find(struct builtin_table *t, const char *chain);
+const struct builtin_chain *nft_chain_builtin_find(const struct builtin_table *t, const char *chain);
bool nft_chain_exists(struct nft_handle *h, const char *table, const char *chain);
/*
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index a46a92955a01a..642876d6c70ac 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -105,9 +105,9 @@ void xtables_restore_parse(struct nft_handle *h,
struct nft_xt_restore_cb *cb,
int argc, char *argv[])
{
+ const struct builtin_table *curtable = NULL;
char buffer[10240];
int in_table = 0;
- struct builtin_table *curtable = NULL;
const struct xtc_ops *ops = &xtc_ops;
struct nftnl_chain_list *chain_list = NULL;
@@ -359,7 +359,7 @@ void xtables_restore_parse(struct nft_handle *h,
static int
xtables_restore_main(int family, const char *progname, int argc, char *argv[])
{
- struct builtin_table *tables;
+ const struct builtin_table *tables;
struct nft_handle h = {
.family = family,
.restore = true,
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index d121d50e180ff..414a864b6196b 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -122,7 +122,7 @@ do_output(struct nft_handle *h, const char *tablename, bool counters)
static int
xtables_save_main(int family, const char *progname, int argc, char *argv[])
{
- struct builtin_table *tables;
+ const struct builtin_table *tables;
const char *tablename = NULL;
bool dump = false;
struct nft_handle h = {
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index 849c53f30e155..e1d2a7d6cce88 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -426,7 +426,7 @@ static int xtables_xlate_main_common(struct nft_handle *h,
int family,
const char *progname)
{
- struct builtin_table *tables;
+ const struct builtin_table *tables;
int ret;
xtables_globals.program_name = progname;
--
2.21.0

View File

@ -0,0 +1,60 @@
From 014b6acbb382f42dd20577fa1ff6e013526a57d5 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:02 +0100
Subject: [PATCH] nft: Simplify nftnl_rule_list_chain_save()
Since there are per table chain caches, The chain list passed to that
function is comprised of chains belonging to the right table only.
Therefore the table name check can safely be skipped.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 71f9e474d467dd59582d7a3920eded9613b99000)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 7b6fb2b10686d..9d20eb0eac2db 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2381,8 +2381,7 @@ list_save(struct nftnl_rule *r, unsigned int num, unsigned int format)
static int
nftnl_rule_list_chain_save(struct nft_handle *h, const char *chain,
- const char *table, struct nftnl_chain_list *list,
- int counters)
+ struct nftnl_chain_list *list, int counters)
{
struct nftnl_chain_list_iter *iter;
struct nftnl_chain *c;
@@ -2393,15 +2392,12 @@ nftnl_rule_list_chain_save(struct nft_handle *h, const char *chain,
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
- const char *chain_table =
- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
const char *chain_name =
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
uint32_t policy =
nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
- if (strcmp(table, chain_table) != 0 ||
- (chain && strcmp(chain, chain_name) != 0))
+ if (chain && strcmp(chain, chain_name) != 0)
goto next;
/* this is a base chain */
@@ -2458,7 +2454,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
/* Dump policies and custom chains first */
if (!rulenum)
- nftnl_rule_list_chain_save(h, chain, table, list, counters);
+ nftnl_rule_list_chain_save(h, chain, list, counters);
/* Now dump out rules in this table */
iter = nftnl_chain_list_iter_create(list);
--
2.21.0

View File

@ -0,0 +1,43 @@
From d54baa487a93f54d192de82704e1fba9675fcadc Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:03 +0100
Subject: [PATCH] nft: Review unclear return points
When converting to per table chain caches, these two error returns were
marked for review but apparently forgotten. Make sure error condition is
propagated when returning at those points.
Fixes: c58ecf9f8bcb7 ("xtables: Introduce per table chain caches")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 7e09582a57440f13796bdd5bd70466ef0913345b)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 9d20eb0eac2db..1fca1f17147f6 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2311,7 +2311,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
list = nft_chain_list_get(h, table);
if (!list)
- goto err; /* XXX: return 0 instead? */
+ return 0;
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
@@ -2450,7 +2450,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
list = nft_chain_list_get(h, table);
if (!list)
- goto err; /* XXX: correct? */
+ goto err;
/* Dump policies and custom chains first */
if (!rulenum)
--
2.21.0

View File

@ -0,0 +1,172 @@
From 757b84e866dc1f288c54ad5ca9868b1765da3948 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:04 +0100
Subject: [PATCH] xtables-restore: Review chain handling
There is no need to "delete" (actually, remove from cache) a chain if
noflush wasn't given: While handling the corresponding table line,
'table_flush' callback has already taken care of that.
This .chain_del indirection is not required since d1eb4d587297
("iptables-compat: chains are purge out already from table flush").
Streamlining the code further, move syntax checks to the top. If these
concede, there are three cases to distinguish:
A) Given chain name matches a builtin one in current table, so assume it
exists already and just set policy and counters.
B) Noflush was given and the (custom) chain exists already, flush it.
C) Custom chain was either flushed (noflush not given) or didn't exist
before, create it.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 9523b2e9dee3d9b4439214092c496542ce9f434e)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-shared.h | 2 --
iptables/xtables-restore.c | 68 +++++++++++---------------------------
2 files changed, 19 insertions(+), 51 deletions(-)
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 9a61d8d2863e3..17fff984ba312 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -253,8 +253,6 @@ struct nft_xt_restore_cb {
void (*table_new)(struct nft_handle *h, const char *table);
struct nftnl_chain_list *(*chain_list)(struct nft_handle *h,
const char *table);
- void (*chain_del)(struct nftnl_chain_list *clist, const char *curtable,
- const char *chain);
int (*chain_user_flush)(struct nft_handle *h,
struct nftnl_chain_list *clist,
const char *table, const char *chain);
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 642876d6c70ac..4e00ed86be06d 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -68,21 +68,6 @@ static struct nftnl_chain_list *get_chain_list(struct nft_handle *h,
return chain_list;
}
-static void chain_delete(struct nftnl_chain_list *clist, const char *curtable,
- const char *chain)
-{
- struct nftnl_chain *chain_obj;
-
- chain_obj = nft_chain_list_find(clist, chain);
- /* This chain has been found, delete from list. Later
- * on, unvisited chains will be purged out.
- */
- if (chain_obj != NULL) {
- nftnl_chain_list_del(chain_obj);
- nftnl_chain_free(chain_obj);
- }
-}
-
struct nft_xt_restore_cb restore_cb = {
.chain_list = get_chain_list,
.commit = nft_commit,
@@ -90,7 +75,6 @@ struct nft_xt_restore_cb restore_cb = {
.table_new = nft_table_new,
.table_flush = nft_table_flush,
.chain_user_flush = nft_chain_user_flush,
- .chain_del = chain_delete,
.do_command = do_commandx,
.chain_set = nft_chain_set,
.chain_user_add = nft_chain_user_add,
@@ -183,7 +167,6 @@ void xtables_restore_parse(struct nft_handle *h,
/* New chain. */
char *policy, *chain = NULL;
struct xt_counters count = {};
- bool chain_exists = false;
chain = strtok(buffer+1, " \t\n");
DEBUGP("line %u, chain '%s'\n", line, chain);
@@ -194,21 +177,6 @@ void xtables_restore_parse(struct nft_handle *h,
exit(1);
}
- if (noflush == 0) {
- if (cb->chain_del)
- cb->chain_del(chain_list, curtable->name,
- chain);
- } else if (nft_chain_list_find(chain_list, chain)) {
- chain_exists = true;
- /* Apparently -n still flushes existing user
- * defined chains that are redefined. Otherwise,
- * leave them as is.
- */
- if (cb->chain_user_flush)
- cb->chain_user_flush(h, chain_list,
- curtable->name, chain);
- }
-
if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
"Invalid chain name `%s' "
@@ -246,24 +214,28 @@ void xtables_restore_parse(struct nft_handle *h,
}
DEBUGP("Setting policy of chain %s to %s\n",
chain, policy);
- ret = 1;
- } else {
- if (!chain_exists &&
- cb->chain_user_add &&
- cb->chain_user_add(h, chain,
- curtable->name) < 0) {
- if (errno == EEXIST)
- continue;
+ } else if (noflush &&
+ nftnl_chain_list_lookup_byname(chain_list, chain)) {
+ /* Apparently -n still flushes existing user
+ * defined chains that are redefined. Otherwise,
+ * leave them as is.
+ */
+ if (cb->chain_user_flush)
+ cb->chain_user_flush(h, chain_list,
+ curtable->name, chain);
+ } else if (cb->chain_user_add &&
+ cb->chain_user_add(h, chain,
+ curtable->name) < 0) {
+ if (errno == EEXIST)
+ continue;
- xtables_error(PARAMETER_PROBLEM,
- "cannot create chain "
- "'%s' (%s)\n", chain,
- strerror(errno));
- }
- continue;
+ xtables_error(PARAMETER_PROBLEM,
+ "cannot create chain "
+ "'%s' (%s)\n", chain,
+ strerror(errno));
}
-
+ ret = 1;
} else if (in_table) {
int a;
char *pcnt = NULL;
@@ -496,7 +468,6 @@ struct nft_xt_restore_cb ebt_restore_cb = {
.table_new = nft_table_new,
.table_flush = nft_table_flush,
.chain_user_flush = nft_chain_user_flush,
- .chain_del = chain_delete,
.do_command = do_commandeb,
.chain_set = nft_chain_set,
.chain_user_add = nft_chain_user_add,
@@ -542,7 +513,6 @@ struct nft_xt_restore_cb arp_restore_cb = {
.table_new = nft_table_new,
.table_flush = nft_table_flush,
.chain_user_flush = nft_chain_user_flush,
- .chain_del = chain_delete,
.do_command = do_commandarp,
.chain_set = nft_chain_set,
.chain_user_add = nft_chain_user_add,
--
2.21.0

View File

@ -0,0 +1,233 @@
From 109b8f2d637b5e4b1a6ff6994297203834e4e77a Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:05 +0100
Subject: [PATCH] nft: Review is_*_compatible() routines
- Call to nft_table_builtin_find() in nft_is_table_compatible() is not
needed, as it is repeated in the latter call to nft_chain_list_get()
by nft_are_chains_compatible().
- Turn nft_is_chain_compatible(), nft_is_rule_compatible() and
nft_is_expr_compatible() into callbacks for use with respective
foreach functions.
- nft_are_chains_compatible() is not needed anymore due to foreach
function use.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit e774b15299c271a4c7570899591cf1b7960477ea)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 153 ++++++++++++++++++-------------------------------
1 file changed, 55 insertions(+), 98 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 1fca1f17147f6..5032c718b33a9 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -3115,7 +3115,7 @@ static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
};
-static int nft_is_expr_compatible(const struct nftnl_expr *expr)
+static int nft_is_expr_compatible(struct nftnl_expr *expr, void *data)
{
const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
int i;
@@ -3130,138 +3130,95 @@ static int nft_is_expr_compatible(const struct nftnl_expr *expr)
nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_FLAGS) == 0)
return 0;
- return 1;
+ return -1;
}
-static bool nft_is_rule_compatible(struct nftnl_rule *rule)
-{
- struct nftnl_expr_iter *iter;
- struct nftnl_expr *expr;
- bool compatible = false;
-
- iter = nftnl_expr_iter_create(rule);
- if (iter == NULL)
- return false;
+struct nft_is_rule_compatible_data {
+ const char *tablename;
+};
- expr = nftnl_expr_iter_next(iter);
- while (expr != NULL) {
- if (nft_is_expr_compatible(expr) == 0) {
- expr = nftnl_expr_iter_next(iter);
- continue;
- }
+static int nft_is_rule_compatible(struct nftnl_rule *rule, void *data)
+{
+ const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE);
+ struct nft_is_rule_compatible_data *d = data;
- compatible = true;
- break;
- }
+ /* ignore rules belonging to a different table */
+ if (strcmp(table, d->tablename))
+ return 0;
- nftnl_expr_iter_destroy(iter);
- return compatible;
+ return nftnl_expr_foreach(rule, nft_is_expr_compatible, NULL);
}
-static int nft_is_chain_compatible(const struct nft_handle *h,
- const struct nftnl_chain *chain)
+static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
{
- const char *table, *name, *type, *cur_table;
- const struct builtin_chain *chains;
- int i, j, prio;
+ const struct builtin_chain *chains = NULL, *chain = NULL;
+ const char *table, *name, *type;
+ struct nft_handle *h = data;
enum nf_inet_hooks hook;
+ int i, prio;
- table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE);
- name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME);
- type = nftnl_chain_get(chain, NFTNL_CHAIN_TYPE);
- prio = nftnl_chain_get_u32(chain, NFTNL_CHAIN_PRIO);
- hook = nftnl_chain_get_u32(chain, NFTNL_CHAIN_HOOKNUM);
+ if (!nft_chain_builtin(c))
+ return 0;
+ /* find chain's table in builtin tables */
+ table = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
for (i = 0; i < NFT_TABLE_MAX; i++) {
- cur_table = h->tables[i].name;
- chains = h->tables[i].chains;
+ const char *cur_table = h->tables[i].name;
- if (!cur_table || strcmp(table, cur_table) != 0)
+ if (!cur_table || strcmp(cur_table, table))
continue;
- for (j = 0; j < NF_INET_NUMHOOKS && chains[j].name; j++) {
- if (strcmp(name, chains[j].name) != 0)
- continue;
-
- if (strcmp(type, chains[j].type) == 0 &&
- prio == chains[j].prio &&
- hook == chains[j].hook)
- return 0;
- break;
- }
+ chains = h->tables[i].chains;
+ break;
}
-
- return 1;
-}
-
-static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename)
-{
- struct nftnl_chain_list *list;
- struct nftnl_chain_list_iter *iter;
- struct nftnl_chain *chain;
- int ret = 0;
-
- list = nft_chain_list_get(h, tablename);
- if (list == NULL)
- return -1;
-
- iter = nftnl_chain_list_iter_create(list);
- if (iter == NULL)
+ if (!chains)
return -1;
- chain = nftnl_chain_list_iter_next(iter);
- while (chain != NULL) {
- if (!nft_chain_builtin(chain))
- goto next;
+ /* find chain in builtin chain list */
+ name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+ for (i = 0; i < NF_INET_NUMHOOKS && chains[i].name; i++) {
+ if (strcmp(name, chains[i].name))
+ continue;
- ret = nft_is_chain_compatible(h, chain);
- if (ret != 0)
- break;
-next:
- chain = nftnl_chain_list_iter_next(iter);
+ chain = &chains[i];
+ break;
}
+ if (!chain)
+ return -1;
- nftnl_chain_list_iter_destroy(iter);
+ /* compare properties */
+ type = nftnl_chain_get_str(c, NFTNL_CHAIN_TYPE);
+ prio = nftnl_chain_get_u32(c, NFTNL_CHAIN_PRIO);
+ hook = nftnl_chain_get_u32(c, NFTNL_CHAIN_HOOKNUM);
+ if (strcmp(type, chain->type) ||
+ prio != chain->prio ||
+ hook != chain->hook)
+ return -1;
- return ret;
+ return 0;
}
bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
{
+ struct nft_is_rule_compatible_data rcd = {
+ .tablename = tablename
+ };
+ struct nftnl_chain_list *clist;
struct nftnl_rule_list *list;
- struct nftnl_rule_list_iter *iter;
- struct nftnl_rule *rule;
- int ret = 0;
- if (!nft_table_builtin_find(h, tablename))
+ clist = nft_chain_list_get(h, tablename);
+ if (clist == NULL)
return false;
- ret = nft_are_chains_compatible(h, tablename);
- if (ret != 0)
+ if (nftnl_chain_list_foreach(clist, nft_is_chain_compatible, h))
return false;
list = nft_rule_list_get(h);
if (list == NULL)
return true;
- iter = nftnl_rule_list_iter_create(list);
- if (iter == NULL)
- return true;
-
- rule = nftnl_rule_list_iter_next(iter);
- while (rule != NULL) {
- const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE);
-
- if (strcmp(table, tablename))
- goto next_rule;
-
- ret = nft_is_rule_compatible(rule);
- if (ret != 0)
- break;
-next_rule:
- rule = nftnl_rule_list_iter_next(iter);
- }
+ if (nftnl_rule_list_foreach(list, nft_is_rule_compatible, &rcd))
+ return false;
- nftnl_rule_list_iter_destroy(iter);
- return ret == 0;
+ return true;
}
--
2.21.0

View File

@ -0,0 +1,51 @@
From 0e260c69746ea4ff101b6f66bf40de8426cfccbd Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:06 +0100
Subject: [PATCH] nft: Reduce __nft_rule_del() signature
The function does not use passed struct nftnl_rule_list, so remove it
from its parameters.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 9975b6da9f926994bcea8ae788e47aab4b5b235e)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 5032c718b33a9..befd9f4dd9026 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1946,8 +1946,7 @@ void nft_table_new(struct nft_handle *h, const char *table)
nft_xt_builtin_init(h, table);
}
-static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule_list *list,
- struct nftnl_rule *r)
+static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r)
{
int ret;
@@ -2046,7 +2045,7 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
r = nft_rule_find(h, list, chain, table, data, -1);
if (r != NULL) {
- ret =__nft_rule_del(h, list, r);
+ ret =__nft_rule_del(h, r);
if (ret < 0)
errno = ENOMEM;
if (verbose)
@@ -2151,7 +2150,7 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain,
r = nft_rule_find(h, list, chain, table, NULL, rulenum);
if (r != NULL) {
DEBUGP("deleting rule by number %d\n", rulenum);
- ret = __nft_rule_del(h, list, r);
+ ret = __nft_rule_del(h, r);
if (ret < 0)
errno = ENOMEM;
} else
--
2.21.0

View File

@ -0,0 +1,60 @@
From 3614b4bee283ea6d08207ccc5e2efa3ebfad321c Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:07 +0100
Subject: [PATCH] nft: Reduce indenting level in flush_chain_cache()
Instead of doing all in one go, make two separate decisions:
1) If table has no chain cache, either continue or return depending on
whether we're flushing for a specific table.
2) With chain cache present, flushing strategy once more depends on
whether we're flushing for a specific table: If given, just remove
all rules and return. If not, free the cache and set to NULL (so that
it will be repopulated later), then continue the loop.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit d4b0d248cc057e39608c7c1c1203dd3f1ea96645)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index befd9f4dd9026..997d7bc58fd00 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -815,16 +815,20 @@ static void flush_chain_cache(struct nft_handle *h, const char *tablename)
if (tablename && strcmp(h->tables[i].name, tablename))
continue;
- if (h->table[i].chain_cache) {
- if (tablename) {
- nftnl_chain_list_foreach(h->table[i].chain_cache,
- __flush_chain_cache, NULL);
- break;
- } else {
- nftnl_chain_list_free(h->table[i].chain_cache);
- h->table[i].chain_cache = NULL;
- }
+ if (!h->table[i].chain_cache) {
+ if (tablename)
+ return;
+ continue;
}
+
+ if (tablename) {
+ nftnl_chain_list_foreach(h->table[i].chain_cache,
+ __flush_chain_cache, NULL);
+ return;
+ }
+
+ nftnl_chain_list_free(h->table[i].chain_cache);
+ h->table[i].chain_cache = NULL;
}
}
--
2.21.0

View File

@ -0,0 +1,86 @@
From eafa37433c920c6613bd351017d31cfd6e4cc397 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:08 +0100
Subject: [PATCH] nft: Simplify per table chain cache update
Previously, each table's chain cache was potentially unallocated until
nftnl_chain_list_cb() saw a chain for it. This means such callback had to
check the chain_cache pointer for each chain belonging to that table.
In addition to the above, nft_chain_list_get() had to cover for the
possibility that a given table didn't have any chains at all in kernel,
so check requested table's chain cache once more and allocate it if
NULL.
Instead, simply iterate over all tables and preallocate their chain
caches prior to requesting the chain list from kernel. The only caveat
is to flush the chain cache completely before retrying in case of EINTR.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 402dac2190e6011d4f4ad81c2992b7126b3d79d9)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 997d7bc58fd00..7d08a0884adde 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1286,12 +1286,6 @@ static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
if (!t)
goto out;
- if (!h->table[t->type].chain_cache) {
- h->table[t->type].chain_cache = nftnl_chain_list_alloc();
- if (!h->table[t->type].chain_cache)
- goto out;
- }
-
nftnl_chain_list_add_tail(c, h->table[t->type].chain_cache);
return MNL_CB_OK;
@@ -1307,7 +1301,7 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
char buf[16536];
struct nlmsghdr *nlh;
const struct builtin_table *t;
- int ret;
+ int i, ret;
t = nft_table_builtin_find(h, table);
if (!t)
@@ -1316,18 +1310,27 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
if (h->table[t->type].chain_cache)
return h->table[t->type].chain_cache;
retry:
+ for (i = 0; i < NFT_TABLE_MAX; i++) {
+ enum nft_table_type type = h->tables[i].type;
+
+ if (!h->tables[i].name)
+ continue;
+
+ h->table[type].chain_cache = nftnl_chain_list_alloc();
+ if (!h->table[type].chain_cache)
+ return NULL;
+ }
+
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nftnl_chain_list_cb, h);
if (ret < 0 && errno == EINTR) {
assert(nft_restart(h) >= 0);
+ flush_chain_cache(h, NULL);
goto retry;
}
- if (!h->table[t->type].chain_cache)
- h->table[t->type].chain_cache = nftnl_chain_list_alloc();
-
return h->table[t->type].chain_cache;
}
--
2.21.0

View File

@ -0,0 +1,49 @@
From 8ae498f20e89ae11f8cbde9a16e0e5397a274a8c Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:09 +0100
Subject: [PATCH] nft: Simplify nft_rule_insert() a bit
Fetch rule list right on top instead of in each branch separately.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 88bd4f28878bc7d41daa23098d68bf1bf6f5cea2)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 7d08a0884adde..469448f42cd6d 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2091,8 +2091,8 @@ nft_rule_add(struct nft_handle *h, const char *chain,
int nft_rule_insert(struct nft_handle *h, const char *chain,
const char *table, void *data, int rulenum, bool verbose)
{
+ struct nftnl_rule_list *list = nft_rule_list_get(h);
struct nftnl_rule *r, *new_rule;
- struct nftnl_rule_list *list;
uint64_t handle = 0;
/* If built-in chains don't exist for this table, create them */
@@ -2102,7 +2102,6 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
nft_fn = nft_rule_insert;
if (rulenum > 0) {
- list = nft_rule_list_get(h);
if (list == NULL)
goto err;
@@ -2123,8 +2122,6 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE);
DEBUGP("adding after rule handle %"PRIu64"\n", handle);
- } else {
- nft_rule_list_get(h);
}
new_rule = nft_rule_add(h, chain, table, data, handle, verbose);
--
2.21.0

View File

@ -0,0 +1,76 @@
From 0e72e49c0f220a9223de85574b878114bf8ceff3 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:10 +0100
Subject: [PATCH] nft: Introduce fetch_chain_cache()
Move chain cache population from nft_chain_list_get() into a dedicated
function.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 8bae620abf9ac81794acca43d305ca74f15a13ff)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 469448f42cd6d..b425577798679 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1295,20 +1295,12 @@ err:
return MNL_CB_OK;
}
-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
- const char *table)
+static int fetch_chain_cache(struct nft_handle *h)
{
char buf[16536];
struct nlmsghdr *nlh;
- const struct builtin_table *t;
int i, ret;
- t = nft_table_builtin_find(h, table);
- if (!t)
- return NULL;
-
- if (h->table[t->type].chain_cache)
- return h->table[t->type].chain_cache;
retry:
for (i = 0; i < NFT_TABLE_MAX; i++) {
enum nft_table_type type = h->tables[i].type;
@@ -1318,7 +1310,7 @@ retry:
h->table[type].chain_cache = nftnl_chain_list_alloc();
if (!h->table[type].chain_cache)
- return NULL;
+ return -1;
}
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
@@ -1331,6 +1323,21 @@ retry:
goto retry;
}
+ return ret;
+}
+
+struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
+ const char *table)
+{
+ const struct builtin_table *t;
+
+ t = nft_table_builtin_find(h, table);
+ if (!t)
+ return NULL;
+
+ if (!h->table[t->type].chain_cache)
+ fetch_chain_cache(h);
+
return h->table[t->type].chain_cache;
}
--
2.21.0

View File

@ -0,0 +1,149 @@
From e3624bf4de451c53a3b42e1b83adab3051c03500 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:11 +0100
Subject: [PATCH] nft: Move nft_rule_list_get() above nft_chain_list_get()
Later when introducing per chain rule caches, nft_rule_list_get() will
be removed. But nftnl_rule_list_cb() which it uses will be reused to
update each chain's rule cache from inside nftnl_chain_list_get(), so
move both into position.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit eb13831f1c41c0efa626ab85d4448fb8ce4c87a2)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 110 ++++++++++++++++++++++++-------------------------
1 file changed, 55 insertions(+), 55 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index b425577798679..1840561f2e531 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1326,61 +1326,6 @@ retry:
return ret;
}
-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
- const char *table)
-{
- const struct builtin_table *t;
-
- t = nft_table_builtin_find(h, table);
- if (!t)
- return NULL;
-
- if (!h->table[t->type].chain_cache)
- fetch_chain_cache(h);
-
- return h->table[t->type].chain_cache;
-}
-
-static const char *policy_name[NF_ACCEPT+1] = {
- [NF_DROP] = "DROP",
- [NF_ACCEPT] = "ACCEPT",
-};
-
-int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list)
-{
- struct nftnl_chain_list_iter *iter;
- struct nft_family_ops *ops;
- struct nftnl_chain *c;
-
- ops = nft_family_ops_lookup(h->family);
-
- iter = nftnl_chain_list_iter_create(list);
- if (iter == NULL)
- return 0;
-
- c = nftnl_chain_list_iter_next(iter);
- while (c != NULL) {
- const char *policy = NULL;
-
- if (nft_chain_builtin(c)) {
- uint32_t pol = NF_ACCEPT;
-
- if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY))
- pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
- policy = policy_name[pol];
- }
-
- if (ops->save_chain)
- ops->save_chain(c, policy);
-
- c = nftnl_chain_list_iter_next(iter);
- }
-
- nftnl_chain_list_iter_destroy(iter);
-
- return 1;
-}
-
static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nftnl_rule *r;
@@ -1437,6 +1382,61 @@ retry:
return list;
}
+struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
+ const char *table)
+{
+ const struct builtin_table *t;
+
+ t = nft_table_builtin_find(h, table);
+ if (!t)
+ return NULL;
+
+ if (!h->table[t->type].chain_cache)
+ fetch_chain_cache(h);
+
+ return h->table[t->type].chain_cache;
+}
+
+static const char *policy_name[NF_ACCEPT+1] = {
+ [NF_DROP] = "DROP",
+ [NF_ACCEPT] = "ACCEPT",
+};
+
+int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list)
+{
+ struct nftnl_chain_list_iter *iter;
+ struct nft_family_ops *ops;
+ struct nftnl_chain *c;
+
+ ops = nft_family_ops_lookup(h->family);
+
+ iter = nftnl_chain_list_iter_create(list);
+ if (iter == NULL)
+ return 0;
+
+ c = nftnl_chain_list_iter_next(iter);
+ while (c != NULL) {
+ const char *policy = NULL;
+
+ if (nft_chain_builtin(c)) {
+ uint32_t pol = NF_ACCEPT;
+
+ if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY))
+ pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
+ policy = policy_name[pol];
+ }
+
+ if (ops->save_chain)
+ ops->save_chain(c, policy);
+
+ c = nftnl_chain_list_iter_next(iter);
+ }
+
+ nftnl_chain_list_iter_destroy(iter);
+
+ return 1;
+}
+
int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
{
struct nftnl_rule_list *list;
--
2.21.0

View File

@ -0,0 +1,802 @@
From 56521a8270d740184510f660492e2c9f8588afbf Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:12 +0100
Subject: [PATCH] xtables: Implement per chain rule cache
Use recently introduced support for rules inside chains in libnftnl to
introduce a rule cache per chain instead of a global one.
A tricky bit is to decide if cache should be updated or not. Previously,
the global rule cache was populated just once and then reused unless
being flushed completely (via call to flush_rule_cache() with
NULL-pointer table argument). Resemble this behaviour by introducing a
boolean indicating cache status and fetch rules for all chains when
updating the chain cache in nft_chain_list_get().
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 947c51c95edbbf08d6b3c105177ac5cfa238aade)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 386 +++++++++++++++++++++----------------------------
iptables/nft.h | 2 +-
2 files changed, 166 insertions(+), 222 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 1840561f2e531..842ed2b805bee 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -772,28 +772,15 @@ int nft_init(struct nft_handle *h, const struct builtin_table *t)
static int __flush_rule_cache(struct nftnl_rule *r, void *data)
{
- const char *tablename = data;
-
- if (!strcmp(nftnl_rule_get_str(r, NFTNL_RULE_TABLE), tablename)) {
- nftnl_rule_list_del(r);
- nftnl_rule_free(r);
- }
+ nftnl_rule_list_del(r);
+ nftnl_rule_free(r);
return 0;
}
-static void flush_rule_cache(struct nft_handle *h, const char *tablename)
+static void flush_rule_cache(struct nftnl_chain *c)
{
- if (!h->rule_cache)
- return;
-
- if (tablename) {
- nftnl_rule_list_foreach(h->rule_cache, __flush_rule_cache,
- (void *)tablename);
- } else {
- nftnl_rule_list_free(h->rule_cache);
- h->rule_cache = NULL;
- }
+ nftnl_rule_foreach(c, __flush_rule_cache, NULL);
}
static int __flush_chain_cache(struct nftnl_chain *c, void *data)
@@ -830,12 +817,12 @@ static void flush_chain_cache(struct nft_handle *h, const char *tablename)
nftnl_chain_list_free(h->table[i].chain_cache);
h->table[i].chain_cache = NULL;
}
+ h->have_cache = false;
}
void nft_fini(struct nft_handle *h)
{
flush_chain_cache(h, NULL);
- flush_rule_cache(h, NULL);
mnl_socket_close(h->nl);
}
@@ -1195,12 +1182,14 @@ err:
return NULL;
}
-static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h);
+static struct nftnl_chain *
+nft_chain_find(struct nft_handle *h, const char *table, const char *chain);
int
nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
void *data, uint64_t handle, bool verbose)
{
+ struct nftnl_chain *c;
struct nftnl_rule *r;
int type;
@@ -1228,10 +1217,9 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
- if (!nft_rule_list_get(h))
- return 0;
-
- nftnl_rule_list_add_tail(r, h->rule_cache);
+ c = nft_chain_find(h, table, chain);
+ if (c)
+ nftnl_chain_rule_add_tail(r, c);
return 1;
}
@@ -1328,58 +1316,75 @@ retry:
static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data)
{
+ struct nftnl_chain *c = data;
struct nftnl_rule *r;
- struct nftnl_rule_list *list = data;
r = nftnl_rule_alloc();
if (r == NULL)
- goto err;
-
- if (nftnl_rule_nlmsg_parse(nlh, r) < 0)
- goto out;
+ return MNL_CB_OK;
- nftnl_rule_list_add_tail(r, list);
+ if (nftnl_rule_nlmsg_parse(nlh, r) < 0) {
+ nftnl_rule_free(r);
+ return MNL_CB_OK;
+ }
- return MNL_CB_OK;
-out:
- nftnl_rule_free(r);
- nftnl_rule_list_free(list);
-err:
+ nftnl_chain_rule_add_tail(r, c);
return MNL_CB_OK;
}
-static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h)
+static int nft_rule_list_update(struct nftnl_chain *c, void *data)
{
+ struct nft_handle *h = data;
char buf[16536];
struct nlmsghdr *nlh;
- struct nftnl_rule_list *list;
+ struct nftnl_rule *rule;
int ret;
- if (h->rule_cache)
- return h->rule_cache;
+ rule = nftnl_rule_alloc();
+ if (!rule)
+ return -1;
-retry:
- list = nftnl_rule_list_alloc();
- if (list == NULL)
- return 0;
+ nftnl_rule_set_str(rule, NFTNL_RULE_TABLE,
+ nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE));
+ nftnl_rule_set_str(rule, NFTNL_RULE_CHAIN,
+ nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
+retry:
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
NLM_F_DUMP, h->seq);
+ nftnl_rule_nlmsg_build_payload(nlh, rule);
- ret = mnl_talk(h, nlh, nftnl_rule_list_cb, list);
+ ret = mnl_talk(h, nlh, nftnl_rule_list_cb, c);
if (ret < 0) {
+ flush_rule_cache(c);
+
if (errno == EINTR) {
assert(nft_restart(h) >= 0);
- nftnl_rule_list_free(list);
goto retry;
}
-
- nftnl_rule_list_free(list);
- return NULL;
+ nftnl_rule_free(rule);
+ return -1;
}
- h->rule_cache = list;
- return list;
+ nftnl_rule_free(rule);
+ return 0;
+}
+
+static int fetch_rule_cache(struct nft_handle *h)
+{
+ int i;
+
+ for (i = 0; i < NFT_TABLE_MAX; i++) {
+ enum nft_table_type type = h->tables[i].type;
+
+ if (!h->tables[i].name)
+ continue;
+
+ if (nftnl_chain_list_foreach(h->table[type].chain_cache,
+ nft_rule_list_update, h))
+ return -1;
+ }
+ return 0;
}
struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
@@ -1391,8 +1396,11 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
if (!t)
return NULL;
- if (!h->table[t->type].chain_cache)
+ if (!h->have_cache) {
fetch_chain_cache(h);
+ fetch_rule_cache(h);
+ h->have_cache = true;
+ }
return h->table[t->type].chain_cache;
}
@@ -1437,38 +1445,54 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list)
return 1;
}
-int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
+static int nft_chain_save_rules(struct nft_handle *h,
+ struct nftnl_chain *c, unsigned int format)
{
- struct nftnl_rule_list *list;
- struct nftnl_rule_list_iter *iter;
+ struct nftnl_rule_iter *iter;
struct nftnl_rule *r;
- list = nft_rule_list_get(h);
- if (list == NULL)
- return 0;
-
- iter = nftnl_rule_list_iter_create(list);
+ iter = nftnl_rule_iter_create(c);
if (iter == NULL)
- return 0;
+ return 1;
- r = nftnl_rule_list_iter_next(iter);
+ r = nftnl_rule_iter_next(iter);
while (r != NULL) {
- const char *rule_table =
- nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
+ nft_rule_print_save(r, NFT_RULE_APPEND, format);
+ r = nftnl_rule_iter_next(iter);
+ }
- if (strcmp(table, rule_table) != 0)
- goto next;
+ nftnl_rule_iter_destroy(iter);
+ return 0;
+}
- nft_rule_print_save(r, NFT_RULE_APPEND, format);
+int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
+{
+ struct nftnl_chain_list_iter *iter;
+ struct nftnl_chain_list *list;
+ struct nftnl_chain *c;
+ int ret = 0;
-next:
- r = nftnl_rule_list_iter_next(iter);
+ list = nft_chain_list_get(h, table);
+ if (!list)
+ return 0;
+
+ iter = nftnl_chain_list_iter_create(list);
+ if (!iter)
+ return 0;
+
+ c = nftnl_chain_list_iter_next(iter);
+ while (c) {
+ ret = nft_chain_save_rules(h, c, format);
+ if (ret != 0)
+ break;
+
+ c = nftnl_chain_list_iter_next(iter);
}
- nftnl_rule_list_iter_destroy(iter);
+ nftnl_chain_list_iter_destroy(iter);
/* the core expects 1 for success and 0 for error */
- return 1;
+ return ret == 0 ? 1 : 0;
}
static void
@@ -1567,6 +1591,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
fprintf(stdout, "Flushing chain `%s'\n", chain_name);
__nft_rule_flush(h, table, chain_name);
+ flush_rule_cache(c);
if (chain != NULL)
break;
@@ -1574,7 +1599,6 @@ next:
c = nftnl_chain_list_iter_next(iter);
}
nftnl_chain_list_iter_destroy(iter);
- flush_rule_cache(h, table);
err:
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
@@ -1898,7 +1922,6 @@ static int __nft_table_flush(struct nft_handle *h, const char *table)
h->table[_t->type].initialized = false;
flush_chain_cache(h, table);
- flush_rule_cache(h, table);
return 0;
}
@@ -1939,12 +1962,6 @@ next:
t = nftnl_table_list_iter_next(iter);
}
- if (!h->rule_cache) {
- h->rule_cache = nftnl_rule_list_alloc();
- if (h->rule_cache == NULL)
- return -1;
- }
-
err_table_iter:
nftnl_table_list_iter_destroy(iter);
err_table_list:
@@ -1975,31 +1992,19 @@ static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r)
}
static struct nftnl_rule *
-nft_rule_find(struct nft_handle *h, struct nftnl_rule_list *list,
- const char *chain, const char *table, void *data, int rulenum)
+nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulenum)
{
struct nftnl_rule *r;
- struct nftnl_rule_list_iter *iter;
+ struct nftnl_rule_iter *iter;
int rule_ctr = 0;
bool found = false;
- iter = nftnl_rule_list_iter_create(list);
+ iter = nftnl_rule_iter_create(c);
if (iter == NULL)
return 0;
- r = nftnl_rule_list_iter_next(iter);
+ r = nftnl_rule_iter_next(iter);
while (r != NULL) {
- const char *rule_table =
- nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
- const char *rule_chain =
- nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
-
- if (strcmp(table, rule_table) != 0 ||
- strcmp(chain, rule_chain) != 0) {
- DEBUGP("different chain / table\n");
- goto next;
- }
-
if (rulenum >= 0) {
/* Delete by rule number case */
if (rule_ctr == rulenum) {
@@ -2012,11 +2017,10 @@ nft_rule_find(struct nft_handle *h, struct nftnl_rule_list *list,
break;
}
rule_ctr++;
-next:
- r = nftnl_rule_list_iter_next(iter);
+ r = nftnl_rule_iter_next(iter);
}
- nftnl_rule_list_iter_destroy(iter);
+ nftnl_rule_iter_destroy(iter);
return found ? r : NULL;
}
@@ -2024,16 +2028,16 @@ next:
int nft_rule_check(struct nft_handle *h, const char *chain,
const char *table, void *data, bool verbose)
{
- struct nftnl_rule_list *list;
+ struct nftnl_chain *c;
struct nftnl_rule *r;
nft_fn = nft_rule_check;
- list = nft_rule_list_get(h);
- if (list == NULL)
+ c = nft_chain_find(h, table, chain);
+ if (!c)
return 0;
- r = nft_rule_find(h, list, chain, table, data, -1);
+ r = nft_rule_find(h, c, data, -1);
if (r == NULL) {
errno = ENOENT;
return 0;
@@ -2048,16 +2052,18 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
const char *table, void *data, bool verbose)
{
int ret = 0;
+ struct nftnl_chain *c;
struct nftnl_rule *r;
- struct nftnl_rule_list *list;
nft_fn = nft_rule_delete;
- list = nft_rule_list_get(h);
- if (list == NULL)
+ c = nft_chain_find(h, table, chain);
+ if (!c) {
+ errno = ENOENT;
return 0;
+ }
- r = nft_rule_find(h, list, chain, table, data, -1);
+ r = nft_rule_find(h, c, data, -1);
if (r != NULL) {
ret =__nft_rule_del(h, r);
if (ret < 0)
@@ -2098,8 +2104,8 @@ nft_rule_add(struct nft_handle *h, const char *chain,
int nft_rule_insert(struct nft_handle *h, const char *chain,
const char *table, void *data, int rulenum, bool verbose)
{
- struct nftnl_rule_list *list = nft_rule_list_get(h);
struct nftnl_rule *r, *new_rule;
+ struct nftnl_chain *c;
uint64_t handle = 0;
/* If built-in chains don't exist for this table, create them */
@@ -2108,17 +2114,19 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
nft_fn = nft_rule_insert;
- if (rulenum > 0) {
- if (list == NULL)
- goto err;
+ c = nft_chain_find(h, table, chain);
+ if (!c) {
+ errno = ENOENT;
+ goto err;
+ }
- r = nft_rule_find(h, list, chain, table, data, rulenum);
+ if (rulenum > 0) {
+ r = nft_rule_find(h, c, data, rulenum);
if (r == NULL) {
/* special case: iptables allows to insert into
* rule_count + 1 position.
*/
- r = nft_rule_find(h, list, chain, table, data,
- rulenum - 1);
+ r = nft_rule_find(h, c, data, rulenum - 1);
if (r != NULL)
return nft_rule_append(h, chain, table, data,
0, verbose);
@@ -2136,9 +2144,9 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
goto err;
if (handle)
- nftnl_rule_list_insert_at(new_rule, r);
+ nftnl_chain_rule_insert_at(new_rule, r);
else
- nftnl_rule_list_add(new_rule, h->rule_cache);
+ nftnl_chain_rule_add(new_rule, c);
return 1;
err:
@@ -2149,16 +2157,18 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain,
const char *table, int rulenum, bool verbose)
{
int ret = 0;
+ struct nftnl_chain *c;
struct nftnl_rule *r;
- struct nftnl_rule_list *list;
nft_fn = nft_rule_delete_num;
- list = nft_rule_list_get(h);
- if (list == NULL)
+ c = nft_chain_find(h, table, chain);
+ if (!c) {
+ errno = ENOENT;
return 0;
+ }
- r = nft_rule_find(h, list, chain, table, NULL, rulenum);
+ r = nft_rule_find(h, c, NULL, rulenum);
if (r != NULL) {
DEBUGP("deleting rule by number %d\n", rulenum);
ret = __nft_rule_del(h, r);
@@ -2174,16 +2184,18 @@ int nft_rule_replace(struct nft_handle *h, const char *chain,
const char *table, void *data, int rulenum, bool verbose)
{
int ret = 0;
+ struct nftnl_chain *c;
struct nftnl_rule *r;
- struct nftnl_rule_list *list;
nft_fn = nft_rule_replace;
- list = nft_rule_list_get(h);
- if (list == NULL)
+ c = nft_chain_find(h, table, chain);
+ if (!c) {
+ errno = ENOENT;
return 0;
+ }
- r = nft_rule_find(h, list, chain, table, data, rulenum);
+ r = nft_rule_find(h, c, data, rulenum);
if (r != NULL) {
DEBUGP("replacing rule with handle=%llu\n",
(unsigned long long)
@@ -2201,35 +2213,21 @@ int nft_rule_replace(struct nft_handle *h, const char *chain,
}
static int
-__nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
+__nft_rule_list(struct nft_handle *h, struct nftnl_chain *c,
int rulenum, unsigned int format,
void (*cb)(struct nftnl_rule *r, unsigned int num,
unsigned int format))
{
- struct nftnl_rule_list *list;
- struct nftnl_rule_list_iter *iter;
+ struct nftnl_rule_iter *iter;
struct nftnl_rule *r;
int rule_ctr = 0;
- list = nft_rule_list_get(h);
- if (list == NULL)
- return 0;
-
- iter = nftnl_rule_list_iter_create(list);
+ iter = nftnl_rule_iter_create(c);
if (iter == NULL)
return 0;
- r = nftnl_rule_list_iter_next(iter);
+ r = nftnl_rule_iter_next(iter);
while (r != NULL) {
- const char *rule_table =
- nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
- const char *rule_chain =
- nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
-
- if (strcmp(table, rule_table) != 0 ||
- strcmp(chain, rule_chain) != 0)
- goto next;
-
rule_ctr++;
if (rulenum > 0 && rule_ctr != rulenum) {
@@ -2242,46 +2240,30 @@ __nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
break;
next:
- r = nftnl_rule_list_iter_next(iter);
+ r = nftnl_rule_iter_next(iter);
}
- nftnl_rule_list_iter_destroy(iter);
+ nftnl_rule_iter_destroy(iter);
return 1;
}
-static int nft_rule_count(struct nft_handle *h,
- const char *chain, const char *table)
+static int nft_rule_count(struct nft_handle *h, struct nftnl_chain *c)
{
- struct nftnl_rule_list_iter *iter;
- struct nftnl_rule_list *list;
+ struct nftnl_rule_iter *iter;
struct nftnl_rule *r;
int rule_ctr = 0;
- list = nft_rule_list_get(h);
- if (list == NULL)
- return 0;
-
- iter = nftnl_rule_list_iter_create(list);
+ iter = nftnl_rule_iter_create(c);
if (iter == NULL)
return 0;
- r = nftnl_rule_list_iter_next(iter);
+ r = nftnl_rule_iter_next(iter);
while (r != NULL) {
- const char *rule_table =
- nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
- const char *rule_chain =
- nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
-
- if (strcmp(table, rule_table) != 0 ||
- strcmp(chain, rule_chain) != 0)
- goto next;
-
rule_ctr++;
-next:
- r = nftnl_rule_list_iter_next(iter);
+ r = nftnl_rule_iter_next(iter);
}
- nftnl_rule_list_iter_destroy(iter);
+ nftnl_rule_iter_destroy(iter);
return rule_ctr;
}
@@ -2314,8 +2296,11 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
}
if (chain && rulenum) {
- __nft_rule_list(h, chain, table,
- rulenum, format, ops->print_rule);
+ c = nft_chain_find(h, table, chain);
+ if (!c)
+ return 0;
+
+ __nft_rule_list(h, c, rulenum, format, ops->print_rule);
return 1;
}
@@ -2358,12 +2343,11 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
if (found)
printf("\n");
- entries = nft_rule_count(h, chain_name, table);
+ entries = nft_rule_count(h, c);
ops->print_header(format, chain_name, policy_name[policy],
&ctrs, basechain, refs - entries, entries);
- __nft_rule_list(h, chain_name, table,
- rulenum, format, ops->print_rule);
+ __nft_rule_list(h, c, rulenum, format, ops->print_rule);
found = true;
@@ -2484,8 +2468,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
if (chain && strcmp(chain, chain_name) != 0)
goto next;
- ret = __nft_rule_list(h, chain_name, table, rulenum,
- format, list_save);
+ ret = __nft_rule_list(h, c, rulenum, format, list_save);
/* we printed the chain we wanted, stop processing. */
if (chain)
@@ -2503,17 +2486,17 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
const char *table, int rulenum)
{
struct iptables_command_state cs = {};
- struct nftnl_rule_list *list;
+ struct nftnl_chain *c;
struct nftnl_rule *r;
int ret = 0;
nft_fn = nft_rule_delete;
- list = nft_rule_list_get(h);
- if (list == NULL)
+ c = nft_chain_find(h, table, chain);
+ if (!c)
return 0;
- r = nft_rule_find(h, list, chain, table, NULL, rulenum);
+ r = nft_rule_find(h, c, NULL, rulenum);
if (r == NULL) {
errno = ENOENT;
ret = 1;
@@ -2982,38 +2965,19 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
static void nft_chain_zero_rule_counters(struct nft_handle *h,
struct nftnl_chain *c)
{
- struct nftnl_rule_list_iter *iter;
- struct nftnl_rule_list *list;
- const char *table_name;
- const char *chain_name;
+ struct nftnl_rule_iter *iter;
struct nftnl_rule *r;
- list = nft_rule_list_get(h);
- if (list == NULL)
- return;
- iter = nftnl_rule_list_iter_create(list);
+ iter = nftnl_rule_iter_create(c);
if (iter == NULL)
return;
- table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
- chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
-
- r = nftnl_rule_list_iter_next(iter);
+ r = nftnl_rule_iter_next(iter);
while (r != NULL) {
struct nftnl_expr_iter *ei;
- const char *table_chain;
- const char *rule_chain;
struct nftnl_expr *e;
bool zero_needed;
- table_chain = nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
- if (strcmp(table_chain, table_name))
- goto next;
-
- rule_chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
- if (strcmp(rule_chain, chain_name))
- goto next;
-
ei = nftnl_expr_iter_create(r);
if (!ei)
break;
@@ -3044,11 +3008,10 @@ static void nft_chain_zero_rule_counters(struct nft_handle *h,
nftnl_rule_unset(r, NFTNL_RULE_POSITION);
batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r);
}
-next:
- r = nftnl_rule_list_iter_next(iter);
+ r = nftnl_rule_iter_next(iter);
}
- nftnl_rule_list_iter_destroy(iter);
+ nftnl_rule_iter_destroy(iter);
}
int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
@@ -3143,19 +3106,8 @@ static int nft_is_expr_compatible(struct nftnl_expr *expr, void *data)
return -1;
}
-struct nft_is_rule_compatible_data {
- const char *tablename;
-};
-
static int nft_is_rule_compatible(struct nftnl_rule *rule, void *data)
{
- const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE);
- struct nft_is_rule_compatible_data *d = data;
-
- /* ignore rules belonging to a different table */
- if (strcmp(table, d->tablename))
- return 0;
-
return nftnl_expr_foreach(rule, nft_is_expr_compatible, NULL);
}
@@ -3167,6 +3119,9 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
enum nf_inet_hooks hook;
int i, prio;
+ if (nftnl_rule_foreach(c, nft_is_rule_compatible, NULL))
+ return -1;
+
if (!nft_chain_builtin(c))
return 0;
@@ -3210,11 +3165,7 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
{
- struct nft_is_rule_compatible_data rcd = {
- .tablename = tablename
- };
struct nftnl_chain_list *clist;
- struct nftnl_rule_list *list;
clist = nft_chain_list_get(h, tablename);
if (clist == NULL)
@@ -3223,12 +3174,5 @@ bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
if (nftnl_chain_list_foreach(clist, nft_is_chain_compatible, h))
return false;
- list = nft_rule_list_get(h);
- if (list == NULL)
- return true;
-
- if (nftnl_rule_list_foreach(list, nft_is_rule_compatible, &rcd))
- return false;
-
return true;
}
diff --git a/iptables/nft.h b/iptables/nft.h
index bf60ab3943659..6568257feddc7 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -42,7 +42,7 @@ struct nft_handle {
struct nftnl_chain_list *chain_cache;
bool initialized;
} table[NFT_TABLE_MAX];
- struct nftnl_rule_list *rule_cache;
+ bool have_cache;
bool restore;
int8_t config_done;
--
2.21.0

View File

@ -0,0 +1,89 @@
From 4255a54501f8588b4bd346cd36379cccd6e0abc7 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:13 +0100
Subject: [PATCH] nft: Drop nft_chain_list_find()
Replace the function by nftnl_chain_list_lookup_byname() as provided by
libnftnl.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 63dc7a0d86a1b86b10c5e04dd910497b9d8fcfaf)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 31 ++-----------------------------
iptables/nft.h | 2 --
2 files changed, 2 insertions(+), 31 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 842ed2b805bee..883fb3db2c671 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -697,7 +697,7 @@ static void nft_chain_builtin_init(struct nft_handle *h,
/* Initialize built-in chains if they don't exist yet */
for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) {
- c = nft_chain_list_find(list, table->chains[i].name);
+ c = nftnl_chain_list_lookup_byname(list, table->chains[i].name);
if (c != NULL)
continue;
@@ -1699,33 +1699,6 @@ err:
return ret == 0 ? 1 : 0;
}
-struct nftnl_chain *
-nft_chain_list_find(struct nftnl_chain_list *list, const char *chain)
-{
- struct nftnl_chain_list_iter *iter;
- struct nftnl_chain *c;
-
- iter = nftnl_chain_list_iter_create(list);
- if (iter == NULL)
- return NULL;
-
- c = nftnl_chain_list_iter_next(iter);
- while (c != NULL) {
- const char *chain_name =
- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
-
- if (strcmp(chain, chain_name) != 0)
- goto next;
-
- nftnl_chain_list_iter_destroy(iter);
- return c;
-next:
- c = nftnl_chain_list_iter_next(iter);
- }
- nftnl_chain_list_iter_destroy(iter);
- return NULL;
-}
-
static struct nftnl_chain *
nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
{
@@ -1735,7 +1708,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
if (list == NULL)
return NULL;
- return nft_chain_list_find(list, chain);
+ return nftnl_chain_list_lookup_byname(list, chain);
}
bool nft_chain_exists(struct nft_handle *h,
diff --git a/iptables/nft.h b/iptables/nft.h
index 6568257feddc7..dfdffd69342db 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -83,8 +83,6 @@ struct nftnl_chain;
int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters);
struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
const char *table);
-struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list,
- const char *chain);
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list);
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table);
int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose);
--
2.21.0

View File

@ -0,0 +1,85 @@
From 0497d24ecbc4414274bbfa33762de90b28c57be9 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:14 +0100
Subject: [PATCH] xtables: Optimize flushing a specific chain
If a chain name is given to nft_rule_flush(), make use of
nftnl_chain_list_lookup_byname().
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 196841c9597eff536b59655b60df088ee1929904)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 883fb3db2c671..a23acbcc9b100 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1496,10 +1496,14 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
}
static void
-__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
+__nft_rule_flush(struct nft_handle *h, const char *table,
+ const char *chain, bool verbose)
{
struct nftnl_rule *r;
+ if (verbose)
+ fprintf(stdout, "Flushing chain `%s'\n", chain);
+
r = nftnl_rule_alloc();
if (r == NULL)
return;
@@ -1533,7 +1537,7 @@ static int __nft_chain_user_flush(struct nftnl_chain *c, void *data)
return 0;
if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM))
- __nft_rule_flush(h, table, chain);
+ __nft_rule_flush(h, table, chain, false);
return 0;
}
@@ -1573,6 +1577,16 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
goto err;
}
+ if (chain) {
+ c = nftnl_chain_list_lookup_byname(list, chain);
+ if (!c)
+ return 0;
+
+ __nft_rule_flush(h, table, chain, verbose);
+ flush_rule_cache(c);
+ return 1;
+ }
+
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL) {
ret = 1;
@@ -1584,18 +1598,8 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
const char *chain_name =
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- if (chain != NULL && strcmp(chain, chain_name) != 0)
- goto next;
-
- if (verbose)
- fprintf(stdout, "Flushing chain `%s'\n", chain_name);
-
- __nft_rule_flush(h, table, chain_name);
+ __nft_rule_flush(h, table, chain_name, verbose);
flush_rule_cache(c);
-
- if (chain != NULL)
- break;
-next:
c = nftnl_chain_list_iter_next(iter);
}
nftnl_chain_list_iter_destroy(iter);
--
2.21.0

View File

@ -0,0 +1,136 @@
From 25eff54c9a82ad816f7a4c274d39daf2e1aaf3a7 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:15 +0100
Subject: [PATCH] xtables: Optimize nft_chain_zero_counters()
If a chain name was given, make use of nftnl_chain_list_lookup_byname().
Streamline nft_chain_zero_rule_counters() to be suitable for calling
from nftnl_chain_list_foreach().
There is an unrelated optimization in here, too: Add batch job
NFT_COMPAT_CHAIN_ZERO only if it is a base chain. Since user-defined
chains don't have counters, there is no need to do anything for them.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit a6ce0c65d3a390bfff16e834c18650beedecf40c)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 72 +++++++++++++++++++++++++-------------------------
1 file changed, 36 insertions(+), 36 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index a23acbcc9b100..9951bf3212197 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2939,15 +2939,36 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
return h->config_done;
}
-static void nft_chain_zero_rule_counters(struct nft_handle *h,
- struct nftnl_chain *c)
+struct chain_zero_data {
+ struct nft_handle *handle;
+ bool verbose;
+};
+
+static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data)
{
+ struct chain_zero_data *d = data;
+ struct nft_handle *h = d->handle;
struct nftnl_rule_iter *iter;
struct nftnl_rule *r;
+ int ret = 0;
+
+ if (d->verbose)
+ fprintf(stdout, "Zeroing chain `%s'\n",
+ nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
+
+ if (nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) {
+ /* zero base chain counters. */
+ nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
+ nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
+ nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
+ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c);
+ if (ret)
+ return -1;
+ }
iter = nftnl_rule_iter_create(c);
if (iter == NULL)
- return;
+ return -1;
r = nftnl_rule_iter_next(iter);
while (r != NULL) {
@@ -2989,13 +3010,17 @@ static void nft_chain_zero_rule_counters(struct nft_handle *h,
}
nftnl_rule_iter_destroy(iter);
+ return 0;
}
int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
const char *table, bool verbose)
{
struct nftnl_chain_list *list;
- struct nftnl_chain_list_iter *iter;
+ struct chain_zero_data d = {
+ .handle = h,
+ .verbose = verbose,
+ };
struct nftnl_chain *c;
int ret = 0;
@@ -3003,41 +3028,16 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
if (list == NULL)
goto err;
- iter = nftnl_chain_list_iter_create(list);
- if (iter == NULL)
- goto err;
-
- c = nftnl_chain_list_iter_next(iter);
- while (c != NULL) {
- const char *chain_name =
- nftnl_chain_get(c, NFTNL_CHAIN_NAME);
-
- if (chain != NULL && strcmp(chain, chain_name) != 0)
- goto next;
-
- if (verbose)
- fprintf(stdout, "Zeroing chain `%s'\n", chain_name);
-
- if (nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) {
- /* zero base chain counters. */
- nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
- nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
- }
-
- nft_chain_zero_rule_counters(h, c);
-
- nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
-
- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c);
+ if (chain) {
+ c = nftnl_chain_list_lookup_byname(list, chain);
+ if (!c)
+ return 0;
- if (chain != NULL)
- break;
-next:
- c = nftnl_chain_list_iter_next(iter);
+ ret = __nft_chain_zero_counters(c, &d);
+ goto err;
}
- nftnl_chain_list_iter_destroy(iter);
-
+ ret = nftnl_chain_list_foreach(list, __nft_chain_zero_counters, &d);
err:
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
--
2.21.0

View File

@ -0,0 +1,79 @@
From 9cc2fc0be5adc8f828fc8fd62951f7773148b7f0 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:16 +0100
Subject: [PATCH] tests: Extend verbose output and return code tests
Recent changes to chain flush and zero routines incorporate proper error
propagation so trying to flush or zero a non-existent chain results in
an error. This is consistent with iptables-legacy, extend tests to make
sure it stays this way.
Also extend verbose output test to make these recent changes didn't mess
it up.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit e80f7fe56e4c64e05da426418bc2fae7ca221c49)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
.../shell/testcases/iptables/0002-verbose-output_0 | 13 +++++++++----
.../shell/testcases/iptables/0004-return-codes_0 | 6 ++++++
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/iptables/tests/shell/testcases/iptables/0002-verbose-output_0 b/iptables/tests/shell/testcases/iptables/0002-verbose-output_0
index 2e8059536ea7b..b1ef91f61f481 100755
--- a/iptables/tests/shell/testcases/iptables/0002-verbose-output_0
+++ b/iptables/tests/shell/testcases/iptables/0002-verbose-output_0
@@ -29,23 +29,28 @@ Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -v -n -L)
+[[ -z $($XT_MULTI iptables -v -N foobar) ]] || exit 1
+
diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI iptables -v -D FORWARD $RULE1)
diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI iptables -v -D FORWARD $RULE2)
EXPECT="Flushing chain \`INPUT'
Flushing chain \`FORWARD'
-Flushing chain \`OUTPUT'"
+Flushing chain \`OUTPUT'
+Flushing chain \`foobar'"
diff -u <(echo -e "$EXPECT") <($XT_MULTI iptables -v -F)
EXPECT="Zeroing chain \`INPUT'
Zeroing chain \`FORWARD'
-Zeroing chain \`OUTPUT'"
+Zeroing chain \`OUTPUT'
+Zeroing chain \`foobar'"
diff -u <(echo -e "$EXPECT") <($XT_MULTI iptables -v -Z)
diff -u <(echo "Flushing chain \`OUTPUT'") <($XT_MULTI iptables -v -F OUTPUT)
diff -u <(echo "Zeroing chain \`OUTPUT'") <($XT_MULTI iptables -v -Z OUTPUT)
+diff -u <(echo "Flushing chain \`foobar'") <($XT_MULTI iptables -v -F foobar)
+diff -u <(echo "Zeroing chain \`foobar'") <($XT_MULTI iptables -v -Z foobar)
-$XT_MULTI iptables -N foo
-diff -u <(echo "Deleting chain \`foo'") <($XT_MULTI iptables -v -X foo)
+diff -u <(echo "Deleting chain \`foobar'") <($XT_MULTI iptables -v -X foobar)
diff --git a/iptables/tests/shell/testcases/iptables/0004-return-codes_0 b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
index 5b6e1f6f1bc7a..9d2493992bd69 100755
--- a/iptables/tests/shell/testcases/iptables/0004-return-codes_0
+++ b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
@@ -23,6 +23,12 @@ cmd 1 iptables -N foo
# iptables-nft allows this - bug or feature?
#cmd 2 iptables -N "invalid name"
+# test chain flushing/zeroing
+cmd 0 iptables -F foo
+cmd 0 iptables -Z foo
+cmd 1 iptables -F bar
+cmd 1 iptables -Z bar
+
# test chain rename
cmd 0 iptables -E foo bar
cmd 1 iptables -E foo bar
--
2.21.0

View File

@ -0,0 +1,134 @@
From c9db6c26efce63e052b1a35ba1f4d529c2294c93 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:17 +0100
Subject: [PATCH] xtables: Optimize user-defined chain deletion
Make use of nftnl_chain_list_lookup_byname() if a chain name was given.
Move the actual chain deleting code into a callback suitable for passing
to nftnl_chain_list_foreach().
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 0b950ed4549308ef23ffc7561567df86c90cfed9)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 89 ++++++++++++++++++++++++++------------------------
1 file changed, 46 insertions(+), 43 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 9951bf3212197..162d91e82115b 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1642,63 +1642,66 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
#endif
+struct chain_user_del_data {
+ struct nft_handle *handle;
+ bool verbose;
+ int builtin_err;
+};
+
+static int __nft_chain_user_del(struct nftnl_chain *c, void *data)
+{
+ struct chain_user_del_data *d = data;
+ struct nft_handle *h = d->handle;
+ int ret;
+
+ /* don't delete built-in chain */
+ if (nft_chain_builtin(c))
+ return d->builtin_err;
+
+ if (d->verbose)
+ fprintf(stdout, "Deleting chain `%s'\n",
+ nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
+
+ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
+ if (ret)
+ return -1;
+
+ nftnl_chain_list_del(c);
+ return 0;
+}
+
int nft_chain_user_del(struct nft_handle *h, const char *chain,
const char *table, bool verbose)
{
+ struct chain_user_del_data d = {
+ .handle = h,
+ .verbose = verbose,
+ };
struct nftnl_chain_list *list;
- struct nftnl_chain_list_iter *iter;
struct nftnl_chain *c;
int ret = 0;
- int deleted_ctr = 0;
nft_fn = nft_chain_user_del;
list = nft_chain_list_get(h, table);
if (list == NULL)
- goto err;
-
- iter = nftnl_chain_list_iter_create(list);
- if (iter == NULL)
- goto err;
-
- c = nftnl_chain_list_iter_next(iter);
- while (c != NULL) {
- const char *chain_name =
- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
-
- /* don't delete built-in chain */
- if (nft_chain_builtin(c))
- goto next;
-
- if (chain != NULL && strcmp(chain, chain_name) != 0)
- goto next;
-
- if (verbose)
- fprintf(stdout, "Deleting chain `%s'\n", chain);
-
- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
-
- if (ret < 0)
- break;
-
- deleted_ctr++;
- nftnl_chain_list_del(c);
-
- if (chain != NULL)
- break;
-next:
- c = nftnl_chain_list_iter_next(iter);
- }
-
- nftnl_chain_list_iter_destroy(iter);
-err:
+ return 0;
- /* chain not found */
- if (chain != NULL && deleted_ctr == 0) {
- ret = -1;
- errno = ENOENT;
+ if (chain) {
+ c = nftnl_chain_list_lookup_byname(list, chain);
+ if (!c) {
+ errno = ENOENT;
+ return 0;
+ }
+ d.builtin_err = -2;
+ ret = __nft_chain_user_del(c, &d);
+ if (ret == -2)
+ errno = EINVAL;
+ goto out;
}
+ ret = nftnl_chain_list_foreach(list, __nft_chain_user_del, &d);
+out:
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
}
--
2.21.0

View File

@ -0,0 +1,139 @@
From 8b38ab8ead7829569ab6a3c9fa7a193d568b707a Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:18 +0100
Subject: [PATCH] xtables: Optimize list command with given chain
Make use of nftnl_chain_list_lookup_byname() even if not listing a
specific rule. Introduce __nft_print_header() to consolidate chain value
extraction for printing with ops->print_header().
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 11cbd7291f37fbfd5ebe6ffa1730f7d198ed2ac0)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 78 +++++++++++++++++++++-----------------------------
1 file changed, 32 insertions(+), 46 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 162d91e82115b..e1c997836cb97 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2247,6 +2247,24 @@ static int nft_rule_count(struct nft_handle *h, struct nftnl_chain *c)
return rule_ctr;
}
+static void __nft_print_header(struct nft_handle *h,
+ const struct nft_family_ops *ops,
+ struct nftnl_chain *c, unsigned int format)
+{
+ const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+ uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
+ bool basechain = !!nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM);
+ uint32_t refs = nftnl_chain_get_u32(c, NFTNL_CHAIN_USE);
+ uint32_t entries = nft_rule_count(h, c);
+ struct xt_counters ctrs = {
+ .pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
+ .bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES),
+ };
+
+ ops->print_header(format, chain_name, policy_name[policy],
+ &ctrs, basechain, refs - entries, entries);
+}
+
int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
int rulenum, unsigned int format)
{
@@ -2275,75 +2293,43 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
return 0;
}
- if (chain && rulenum) {
- c = nft_chain_find(h, table, chain);
+ list = nft_chain_list_get(h, table);
+ if (!list)
+ return 0;
+
+ if (chain) {
+ c = nftnl_chain_list_lookup_byname(list, chain);
if (!c)
return 0;
+ if (!rulenum) {
+ if (ops->print_table_header)
+ ops->print_table_header(table);
+ __nft_print_header(h, ops, c, format);
+ }
__nft_rule_list(h, c, rulenum, format, ops->print_rule);
return 1;
}
- list = nft_chain_list_get(h, table);
- if (!list)
- return 0;
-
iter = nftnl_chain_list_iter_create(list);
if (iter == NULL)
- goto err;
+ return 0;
- if (!chain && ops->print_table_header)
+ if (ops->print_table_header)
ops->print_table_header(table);
c = nftnl_chain_list_iter_next(iter);
while (c != NULL) {
- const char *chain_name =
- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- uint32_t policy =
- nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
- uint32_t refs =
- nftnl_chain_get_u32(c, NFTNL_CHAIN_USE);
- struct xt_counters ctrs = {
- .pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
- .bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES),
- };
- bool basechain = false;
- uint32_t entries;
-
- if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM))
- basechain = true;
-
- if (chain) {
- if (strcmp(chain, chain_name) != 0)
- goto next;
- else if (ops->print_table_header)
- ops->print_table_header(table);
- }
-
if (found)
printf("\n");
- entries = nft_rule_count(h, c);
- ops->print_header(format, chain_name, policy_name[policy],
- &ctrs, basechain, refs - entries, entries);
-
+ __nft_print_header(h, ops, c, format);
__nft_rule_list(h, c, rulenum, format, ops->print_rule);
found = true;
-
- /* we printed the chain we wanted, stop processing. */
- if (chain)
- break;
-
-next:
c = nftnl_chain_list_iter_next(iter);
}
-
nftnl_chain_list_iter_destroy(iter);
-err:
- if (chain && !found)
- return 0;
-
return 1;
}
--
2.21.0

View File

@ -0,0 +1,158 @@
From 23ef58d88034cdd5c972b9392944a772cccd61f9 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:19 +0100
Subject: [PATCH] xtables: Optimize list rules command with given chain
If a chain name was given, make use of nftnl_chain_list_lookup_byname().
Likewise in nftnl_rule_list_chain_save(), but introduce
__nftnl_rule_list_chain_save() suitable for passing to
nftnl_chain_list_foreach().
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 6b1871914e4f3717c7e6324727b80cf1d5d985b1)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 93 +++++++++++++++++++++++---------------------------
1 file changed, 43 insertions(+), 50 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index e1c997836cb97..e0455eabda77a 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2339,46 +2339,44 @@ list_save(struct nftnl_rule *r, unsigned int num, unsigned int format)
nft_rule_print_save(r, NFT_RULE_APPEND, format);
}
+static int __nftnl_rule_list_chain_save(struct nftnl_chain *c, void *data)
+{
+ const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+ uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
+ int *counters = data;
+
+ if (!nft_chain_builtin(c)) {
+ printf("-N %s\n", chain_name);
+ return 0;
+ }
+
+ /* this is a base chain */
+
+ printf("-P %s %s", chain_name, policy_name[policy]);
+ if (*counters)
+ printf(" -c %"PRIu64" %"PRIu64,
+ nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
+ nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES));
+ printf("\n");
+ return 0;
+}
+
static int
nftnl_rule_list_chain_save(struct nft_handle *h, const char *chain,
struct nftnl_chain_list *list, int counters)
{
- struct nftnl_chain_list_iter *iter;
struct nftnl_chain *c;
- iter = nftnl_chain_list_iter_create(list);
- if (iter == NULL)
- return 0;
-
- c = nftnl_chain_list_iter_next(iter);
- while (c != NULL) {
- const char *chain_name =
- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- uint32_t policy =
- nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
-
- if (chain && strcmp(chain, chain_name) != 0)
- goto next;
+ if (chain) {
+ c = nftnl_chain_list_lookup_byname(list, chain);
+ if (!c)
+ return 0;
- /* this is a base chain */
- if (nft_chain_builtin(c)) {
- printf("-P %s %s", chain_name, policy_name[policy]);
-
- if (counters) {
- printf(" -c %"PRIu64" %"PRIu64"\n",
- nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
- nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES));
- } else
- printf("\n");
- } else {
- printf("-N %s\n", chain_name);
- }
-next:
- c = nftnl_chain_list_iter_next(iter);
+ __nftnl_rule_list_chain_save(c, &counters);
+ return 1;
}
- nftnl_chain_list_iter_destroy(iter);
-
+ nftnl_chain_list_foreach(list, __nftnl_rule_list_chain_save, &counters);
return 1;
}
@@ -2410,41 +2408,36 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
list = nft_chain_list_get(h, table);
if (!list)
- goto err;
+ return 0;
/* Dump policies and custom chains first */
if (!rulenum)
nftnl_rule_list_chain_save(h, chain, list, counters);
- /* Now dump out rules in this table */
- iter = nftnl_chain_list_iter_create(list);
- if (iter == NULL)
- goto err;
-
if (counters < 0)
format = FMT_C_COUNTS;
else if (counters == 0)
format = FMT_NOCOUNTS;
- c = nftnl_chain_list_iter_next(iter);
- while (c != NULL) {
- const char *chain_name =
- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+ if (chain) {
+ c = nftnl_chain_list_lookup_byname(list, chain);
+ if (!c)
+ return 0;
- if (chain && strcmp(chain, chain_name) != 0)
- goto next;
+ return __nft_rule_list(h, c, rulenum, format, list_save);
+ }
- ret = __nft_rule_list(h, c, rulenum, format, list_save);
+ /* Now dump out rules in this table */
+ iter = nftnl_chain_list_iter_create(list);
+ if (iter == NULL)
+ return 0;
- /* we printed the chain we wanted, stop processing. */
- if (chain)
- break;
-next:
+ c = nftnl_chain_list_iter_next(iter);
+ while (c != NULL) {
+ ret = __nft_rule_list(h, c, rulenum, format, list_save);
c = nftnl_chain_list_iter_next(iter);
}
-
nftnl_chain_list_iter_destroy(iter);
-err:
return ret;
}
--
2.21.0

View File

@ -0,0 +1,76 @@
From 4af07f53926f4bf65caa3804adbadb726e3dc301 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:20 +0100
Subject: [PATCH] nft: Make use of nftnl_rule_lookup_byindex()
Use the function where suitable to potentially speedup rule cache lookup
by rule number.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 039b04896521026d1cb52d60dbacb6ee5226c02d)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index e0455eabda77a..1fd3837f2d334 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1976,27 +1976,21 @@ nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulen
{
struct nftnl_rule *r;
struct nftnl_rule_iter *iter;
- int rule_ctr = 0;
bool found = false;
+ if (rulenum >= 0)
+ /* Delete by rule number case */
+ return nftnl_rule_lookup_byindex(c, rulenum);
+
iter = nftnl_rule_iter_create(c);
if (iter == NULL)
return 0;
r = nftnl_rule_iter_next(iter);
while (r != NULL) {
- if (rulenum >= 0) {
- /* Delete by rule number case */
- if (rule_ctr == rulenum) {
- found = true;
- break;
- }
- } else {
- found = h->ops->rule_find(h->ops, r, data);
- if (found)
- break;
- }
- rule_ctr++;
+ found = h->ops->rule_find(h->ops, r, data);
+ if (found)
+ break;
r = nftnl_rule_iter_next(iter);
}
@@ -2202,6 +2196,17 @@ __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c,
struct nftnl_rule *r;
int rule_ctr = 0;
+ if (rulenum > 0) {
+ r = nftnl_rule_lookup_byindex(c, rulenum - 1);
+ if (!r)
+ /* iptables-legacy returns 0 when listing for
+ * valid chain but invalid rule number
+ */
+ return 1;
+ cb(r, rulenum, format);
+ return 1;
+ }
+
iter = nftnl_rule_iter_create(c);
if (iter == NULL)
return 0;
--
2.21.0

View File

@ -0,0 +1,80 @@
From b8d3fdae853c391312b2a0be533fd4a91bf80e8e Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Sun, 30 Dec 2018 20:06:08 +0100
Subject: [PATCH] nft: Simplify nft_is_chain_compatible()
Make use of nft_{table,chain}_builtin_find() instead of open-coding the
list traversal. Since code is pretty obvious now, drop the comments
added earlier.
Fixes: e774b15299c27 ("nft: Review is_*_compatible() routines")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit fae77a24634365b18687a5f09357dbf4aaee2bc0)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 34 +++++++++-------------------------
1 file changed, 9 insertions(+), 25 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 1fd3837f2d334..25e538b7e35d7 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -3077,11 +3077,12 @@ static int nft_is_rule_compatible(struct nftnl_rule *rule, void *data)
static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
{
- const struct builtin_chain *chains = NULL, *chain = NULL;
- const char *table, *name, *type;
+ const struct builtin_table *table;
+ const struct builtin_chain *chain;
+ const char *tname, *cname, *type;
struct nft_handle *h = data;
enum nf_inet_hooks hook;
- int i, prio;
+ int prio;
if (nftnl_rule_foreach(c, nft_is_rule_compatible, NULL))
return -1;
@@ -3089,33 +3090,16 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data)
if (!nft_chain_builtin(c))
return 0;
- /* find chain's table in builtin tables */
- table = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
- for (i = 0; i < NFT_TABLE_MAX; i++) {
- const char *cur_table = h->tables[i].name;
-
- if (!cur_table || strcmp(cur_table, table))
- continue;
-
- chains = h->tables[i].chains;
- break;
- }
- if (!chains)
+ tname = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
+ table = nft_table_builtin_find(h, tname);
+ if (!table)
return -1;
- /* find chain in builtin chain list */
- name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- for (i = 0; i < NF_INET_NUMHOOKS && chains[i].name; i++) {
- if (strcmp(name, chains[i].name))
- continue;
-
- chain = &chains[i];
- break;
- }
+ cname = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+ chain = nft_chain_builtin_find(table, cname);
if (!chain)
return -1;
- /* compare properties */
type = nftnl_chain_get_str(c, NFTNL_CHAIN_TYPE);
prio = nftnl_chain_get_u32(c, NFTNL_CHAIN_PRIO);
hook = nftnl_chain_get_u32(c, NFTNL_CHAIN_HOOKNUM);
--
2.21.0

View File

@ -0,0 +1,66 @@
From 1ad5112b216c46fdf799fa7c8fbf6508f0f4afc9 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Sun, 30 Dec 2018 20:06:09 +0100
Subject: [PATCH] nft: Simplify flush_chain_cache()
With all the checks for 'tablename' being non-NULL, this code was rather
stupid and really hard to read. And the fix is indeed quite simple: If a
table name was given, use nft_table_builtin_find() and just flush its
chain cache. Otherwise iterate over all builtin tables without any
conditionals for 'tablename'.
Fixes: d4b0d248cc057 ("nft: Reduce indenting level in flush_chain_cache()")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 4441b7da7995ed87741164ef39e99f1065eb9637)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 25e538b7e35d7..dafb879ebd6f0 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -793,27 +793,25 @@ static int __flush_chain_cache(struct nftnl_chain *c, void *data)
static void flush_chain_cache(struct nft_handle *h, const char *tablename)
{
+ const struct builtin_table *table;
int i;
+ if (tablename) {
+ table = nft_table_builtin_find(h, tablename);
+ if (!table || !h->table[table->type].chain_cache)
+ return;
+ nftnl_chain_list_foreach(h->table[table->type].chain_cache,
+ __flush_chain_cache, NULL);
+ return;
+ }
+
for (i = 0; i < NFT_TABLE_MAX; i++) {
if (h->tables[i].name == NULL)
continue;
- if (tablename && strcmp(h->tables[i].name, tablename))
+ if (!h->table[i].chain_cache)
continue;
- if (!h->table[i].chain_cache) {
- if (tablename)
- return;
- continue;
- }
-
- if (tablename) {
- nftnl_chain_list_foreach(h->table[i].chain_cache,
- __flush_chain_cache, NULL);
- return;
- }
-
nftnl_chain_list_free(h->table[i].chain_cache);
h->table[i].chain_cache = NULL;
}
--
2.21.0

View File

@ -0,0 +1,68 @@
From 276b4dba9aa9d52cafe8df2546050d4591ac5b01 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Sun, 30 Dec 2018 20:06:10 +0100
Subject: [PATCH] xtables: Set errno in nft_rule_check() if chain not found
With this, the explicit check for chain existence can be removed from
xtables.c since all related commands do this now.
Note that this effectively changes the error message printed by
iptables-nft when given a non-existing chain, but the new error
message(s) conform with those printed by legacy iptables.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 41358d474357a39d616302c03cd7f943e19969a2)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 12 +++++++-----
iptables/xtables.c | 4 ----
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index dafb879ebd6f0..1ce1ecdd276be 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2007,17 +2007,19 @@ int nft_rule_check(struct nft_handle *h, const char *chain,
c = nft_chain_find(h, table, chain);
if (!c)
- return 0;
+ goto fail_enoent;
r = nft_rule_find(h, c, data, -1);
- if (r == NULL) {
- errno = ENOENT;
- return 0;
- }
+ if (r == NULL)
+ goto fail_enoent;
+
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
return 1;
+fail_enoent:
+ errno = ENOENT;
+ return 0;
}
int nft_rule_delete(struct nft_handle *h, const char *chain,
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 24a6e234bcf4b..da11e8cc159a0 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -1064,10 +1064,6 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
p->chain);
}
- if (!p->xlate && !nft_chain_exists(h, p->table, p->chain))
- xtables_error(OTHER_PROBLEM,
- "Chain '%s' does not exist", p->chain);
-
if (!p->xlate && !cs->target && strlen(cs->jumpto) > 0 &&
!nft_chain_exists(h, p->table, cs->jumpto))
xtables_error(PARAMETER_PROBLEM,
--
2.21.0

View File

@ -0,0 +1,34 @@
From 27bc424993e8138e26d7db1d7f902baaf269dd7c Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Wed, 12 Dec 2018 20:04:12 +0100
Subject: [PATCH] xtables: Speed up chain deletion in large rulesets
Kernel prefers to identify chain by handle if it was given which causes
manual traversal of the chain list. In contrast, chain lookup by name in
kernel makes use of a hash table so is considerably faster. Force this
code path by removing the cached chain's handle when removing it.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit a5f517a41d72794fae3d1332e6e0e413a5cd16c1)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/iptables/nft.c b/iptables/nft.c
index 1ce1ecdd276be..9c0ad9a2d054f 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1660,6 +1660,8 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data)
fprintf(stdout, "Deleting chain `%s'\n",
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
+ /* XXX This triggers a fast lookup from the kernel. */
+ nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
if (ret)
return -1;
--
2.21.0

View File

@ -0,0 +1,32 @@
From 922b572f262469c9332ea9a7f18808033129b017 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 31 Jan 2019 16:12:50 +0100
Subject: [PATCH] arptables-nft: Fix listing rules without target
Don't try to print cs.jumpto if it is an empty string, otherwise listing
(and verbose output) contains '-j' flag without argument.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 043bf38bc9ee020bbf1a9789773050d47f83b807)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-arp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index 37850bd328b71..56021223bdbe6 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -598,7 +598,7 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format)
nft_rule_to_iptables_command_state(r, &cs);
- if (cs.jumpto)
+ if (strlen(cs.jumpto))
printf("-j %s ", cs.jumpto);
nft_arp_print_rule_details(&cs.arp, format);
print_matches_and_target(&cs, format);
--
2.21.0

View File

@ -0,0 +1,155 @@
From 0b6b93e52f2a862c23206f9ad9fc48aadc06fbd2 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 31 Jan 2019 16:12:51 +0100
Subject: [PATCH] arptables-nft: Fix MARK target parsing and printing
Legacy arptables parses mark values in hex no matter if prefixed with
'0x' or not. Sadly, this is not easily achievable with guided option
parser. Hence fall back to the old 'parse' callback. The introduced
target definition is valid only for revision 2, but that's consistent
with legacy arptables.
When printing, use --set-mark option instead of --set-xmark.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit f7fa88020f3bc4ec646ce2a48731a1f5fa2aa0a9)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libxt_MARK.c | 95 +++++++++++++++++++
.../arptables/0001-arptables-save-restore_0 | 2 +-
2 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/extensions/libxt_MARK.c b/extensions/libxt_MARK.c
index 43aa977924b12..b765af6c35304 100644
--- a/extensions/libxt_MARK.c
+++ b/extensions/libxt_MARK.c
@@ -1,3 +1,4 @@
+#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <xtables.h>
@@ -245,6 +246,87 @@ static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
printf(" --set-xmark 0x%x/0x%x", info->mark, info->mask);
}
+static void mark_tg_arp_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_mark_tginfo2 *info = (const void *)target->data;
+
+ if (info->mark == 0)
+ printf(" --and-mark %x", (unsigned int)(uint32_t)~info->mask);
+ else if (info->mark == info->mask)
+ printf(" --or-mark %x", info->mark);
+ else
+ printf(" --set-mark %x", info->mark);
+}
+
+static void mark_tg_arp_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ mark_tg_arp_save(ip, target);
+}
+
+#define MARK_OPT 1
+#define AND_MARK_OPT 2
+#define OR_MARK_OPT 3
+
+static struct option mark_tg_arp_opts[] = {
+ { .name = "set-mark", .has_arg = required_argument, .flag = 0, .val = MARK_OPT },
+ { .name = "and-mark", .has_arg = required_argument, .flag = 0, .val = AND_MARK_OPT },
+ { .name = "or-mark", .has_arg = required_argument, .flag = 0, .val = OR_MARK_OPT },
+ { .name = NULL}
+};
+
+static int
+mark_tg_arp_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_mark_tginfo2 *info =
+ (struct xt_mark_tginfo2 *)(*target)->data;
+ int i;
+
+ switch (c) {
+ case MARK_OPT:
+ if (sscanf(argv[optind-1], "%x", &i) != 1) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad mark value `%s'", optarg);
+ return 0;
+ }
+ info->mark = i;
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "MARK: Can't specify --set-mark twice");
+ *flags = 1;
+ break;
+ case AND_MARK_OPT:
+ if (sscanf(argv[optind-1], "%x", &i) != 1) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad mark value `%s'", optarg);
+ return 0;
+ }
+ info->mark = 0;
+ info->mask = ~i;
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "MARK: Can't specify --and-mark twice");
+ *flags = 1;
+ break;
+ case OR_MARK_OPT:
+ if (sscanf(argv[optind-1], "%x", &i) != 1) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad mark value `%s'", optarg);
+ return 0;
+ }
+ info->mark = info->mask = i;
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "MARK: Can't specify --or-mark twice");
+ *flags = 1;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
static int mark_tg_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
@@ -335,6 +417,19 @@ static struct xtables_target mark_tg_reg[] = {
.x6_options = mark_tg_opts,
.xlate = mark_tg_xlate,
},
+ {
+ .version = XTABLES_VERSION,
+ .name = "MARK",
+ .revision = 2,
+ .family = NFPROTO_ARP,
+ .size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
+ .help = mark_tg_help,
+ .print = mark_tg_arp_print,
+ .save = mark_tg_arp_save,
+ .parse = mark_tg_arp_parse,
+ .extra_opts = mark_tg_arp_opts,
+ },
};
void _init(void)
diff --git a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
index 73b3b0cf88e18..f8629551b0ba9 100755
--- a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
+++ b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
@@ -47,7 +47,7 @@ DUMP='*filter
-A OUTPUT -o eth432 --h-length 6 --opcode 1 --h-type 1 -j CLASSIFY --set-class feed:babe
-A foo -i lo --h-length 6 --h-type 1 -j ACCEPT
-A foo --h-length 6 --h-type 1 -j ACCEPT
--A foo --h-length 6 --h-type 1 -j MARK --set-xmark 0x3039/0xffffffff
+-A foo --h-length 6 --h-type 1 -j MARK --set-mark 12345
-A foo --h-length 6 --opcode 1 --h-type 1 -j ACCEPT
-A foo --h-length 6 --h-type 1 --proto-type 0x800 -j ACCEPT
-A foo -i lo --h-length 6 --opcode 1 --h-type 1 --proto-type 0x800 -j ACCEPT
--
2.21.0

View File

@ -0,0 +1,99 @@
From fabed9f23311cdf42180613123309307b5c6add5 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 31 Jan 2019 16:12:52 +0100
Subject: [PATCH] arptables-nft: Fix CLASSIFY target printing
In legacy arptables, CLASSIFY target is not printed with fixed hex
number lengths. Counter this by introducing a dedicated target
definition for NFPROTO_ARP only having own print/save callbacks.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 756bea26a3dad89c467c703725ce6d3c6b29c871)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libxt_CLASSIFY.c | 59 +++++++++++++++++++++++++++++--------
1 file changed, 46 insertions(+), 13 deletions(-)
diff --git a/extensions/libxt_CLASSIFY.c b/extensions/libxt_CLASSIFY.c
index f90082dc7c50e..75aaf0c41b61a 100644
--- a/extensions/libxt_CLASSIFY.c
+++ b/extensions/libxt_CLASSIFY.c
@@ -73,6 +73,24 @@ CLASSIFY_save(const void *ip, const struct xt_entry_target *target)
TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority));
}
+static void
+CLASSIFY_arp_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_classify_target_info *clinfo =
+ (const struct xt_classify_target_info *)target->data;
+
+ printf(" --set-class %x:%x",
+ TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority));
+}
+
+static void
+CLASSIFY_arp_print(const void *ip,
+ const struct xt_entry_target *target,
+ int numeric)
+{
+ CLASSIFY_arp_save(ip, target);
+}
+
static int CLASSIFY_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
@@ -98,21 +116,36 @@ static int CLASSIFY_xlate(struct xt_xlate *xl,
return 1;
}
-static struct xtables_target classify_target = {
- .family = NFPROTO_UNSPEC,
- .name = "CLASSIFY",
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct xt_classify_target_info)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)),
- .help = CLASSIFY_help,
- .print = CLASSIFY_print,
- .save = CLASSIFY_save,
- .x6_parse = CLASSIFY_parse,
- .x6_options = CLASSIFY_opts,
- .xlate = CLASSIFY_xlate,
+static struct xtables_target classify_tg_reg[] = {
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "CLASSIFY",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_classify_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)),
+ .help = CLASSIFY_help,
+ .print = CLASSIFY_print,
+ .save = CLASSIFY_save,
+ .x6_parse = CLASSIFY_parse,
+ .x6_options = CLASSIFY_opts,
+ .xlate = CLASSIFY_xlate,
+ },
+ {
+ .family = NFPROTO_ARP,
+ .name = "CLASSIFY",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_classify_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)),
+ .help = CLASSIFY_help,
+ .print = CLASSIFY_arp_print,
+ .save = CLASSIFY_arp_save,
+ .x6_parse = CLASSIFY_parse,
+ .x6_options = CLASSIFY_opts,
+ .xlate = CLASSIFY_xlate,
+ }
};
void _init(void)
{
- xtables_register_target(&classify_target);
+ xtables_register_targets(classify_tg_reg, ARRAY_SIZE(classify_tg_reg));
}
--
2.21.0

View File

@ -0,0 +1,35 @@
From 44e633b17e257f1915c4b33d9249f2e45f0a39cc Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 31 Jan 2019 16:12:53 +0100
Subject: [PATCH] arptables-nft: Remove space between *cnt= and value
When printing rule counters, call xtables_print_num() with FMT_NOTABLE
bit set to avoid spaces between equal sign and value.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 9421327926a529ec8300d37f3be8a6cfab701786)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-arp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index 56021223bdbe6..f357fc4a43c4c 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -605,9 +605,9 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format)
if (!(format & FMT_NOCOUNTS)) {
printf(", pcnt=");
- xtables_print_num(cs.counters.pcnt, format);
+ xtables_print_num(cs.counters.pcnt, format | FMT_NOTABLE);
printf("-- bcnt=");
- xtables_print_num(cs.counters.bcnt, format);
+ xtables_print_num(cs.counters.bcnt, format | FMT_NOTABLE);
}
if (!(format & FMT_NONEWLINE))
--
2.21.0

View File

@ -0,0 +1,296 @@
From f521f424e5ab298d0dd2146677ea4f0170a9dfd0 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 31 Jan 2019 16:12:54 +0100
Subject: [PATCH] arptables-nft-save: Fix position of -j option
Legacy arptables-save (just like arptables itself) prints verdict as
first option, then matches and finally any target options.
To achieve this without introducing double/trailing spaces everywhere,
integrate target ('-j') option printing into
nft_arp_print_rule_details() and make it print separating whitespace
before each option.
In nft_arp_save_rule(), replace the call to save_matches_and_target() by
by a direct call to cs->target->save() since the former prints '-j'
option itself. Since there are no match extensions in arptables, any
other code from that function is not needed.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 2c3f7a2cd6fd8325b3a84e280cce945c6c20b87f)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-arp.c | 65 +++++++++++--------
.../arptables/0001-arptables-save-restore_0 | 32 ++++-----
.../0002-arptables-restore-defaults_0 | 6 +-
3 files changed, 58 insertions(+), 45 deletions(-)
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index f357fc4a43c4c..2cbdf23214049 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -434,14 +434,21 @@ static void nft_arp_print_header(unsigned int format, const char *chain,
}
}
-static void nft_arp_print_rule_details(const struct arpt_entry *fw,
+static void nft_arp_print_rule_details(const struct iptables_command_state *cs,
unsigned int format)
{
+ const struct arpt_entry *fw = &cs->arp;
char buf[BUFSIZ];
char iface[IFNAMSIZ+2];
+ const char *sep = "";
int print_iface = 0;
int i;
+ if (strlen(cs->jumpto)) {
+ printf("%s-j %s", sep, cs->jumpto);
+ sep = " ";
+ }
+
iface[0] = '\0';
if (fw->arp.iniface[0] != '\0') {
@@ -453,9 +460,11 @@ static void nft_arp_print_rule_details(const struct arpt_entry *fw,
if (format & FMT_NUMERIC) strcat(iface, "*");
else strcat(iface, "any");
}
- if (print_iface)
- printf("%s-i %s ", fw->arp.invflags & ARPT_INV_VIA_IN ?
+ if (print_iface) {
+ printf("%s%s-i %s", sep, fw->arp.invflags & ARPT_INV_VIA_IN ?
"! " : "", iface);
+ sep = " ";
+ }
print_iface = 0;
iface[0] = '\0';
@@ -469,12 +478,14 @@ static void nft_arp_print_rule_details(const struct arpt_entry *fw,
if (format & FMT_NUMERIC) strcat(iface, "*");
else strcat(iface, "any");
}
- if (print_iface)
- printf("%s-o %s ", fw->arp.invflags & ARPT_INV_VIA_OUT ?
+ if (print_iface) {
+ printf("%s%s-o %s", sep, fw->arp.invflags & ARPT_INV_VIA_OUT ?
"! " : "", iface);
+ sep = " ";
+ }
if (fw->arp.smsk.s_addr != 0L) {
- printf("%s", fw->arp.invflags & ARPT_INV_SRCIP
+ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_SRCIP
? "! " : "");
if (format & FMT_NUMERIC)
sprintf(buf, "%s", addr_to_dotted(&(fw->arp.src)));
@@ -482,7 +493,8 @@ static void nft_arp_print_rule_details(const struct arpt_entry *fw,
sprintf(buf, "%s", addr_to_anyname(&(fw->arp.src)));
strncat(buf, mask_to_dotted(&(fw->arp.smsk)),
sizeof(buf) - strlen(buf) - 1);
- printf("-s %s ", buf);
+ printf("-s %s", buf);
+ sep = " ";
}
for (i = 0; i < ARPT_DEV_ADDR_LEN_MAX; i++)
@@ -490,16 +502,16 @@ static void nft_arp_print_rule_details(const struct arpt_entry *fw,
break;
if (i == ARPT_DEV_ADDR_LEN_MAX)
goto after_devsrc;
- printf("%s", fw->arp.invflags & ARPT_INV_SRCDEVADDR
+ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_SRCDEVADDR
? "! " : "");
printf("--src-mac ");
print_mac_and_mask((unsigned char *)fw->arp.src_devaddr.addr,
(unsigned char *)fw->arp.src_devaddr.mask, ETH_ALEN);
- printf(" ");
+ sep = " ";
after_devsrc:
if (fw->arp.tmsk.s_addr != 0L) {
- printf("%s", fw->arp.invflags & ARPT_INV_TGTIP
+ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_TGTIP
? "! " : "");
if (format & FMT_NUMERIC)
sprintf(buf, "%s", addr_to_dotted(&(fw->arp.tgt)));
@@ -507,7 +519,8 @@ after_devsrc:
sprintf(buf, "%s", addr_to_anyname(&(fw->arp.tgt)));
strncat(buf, mask_to_dotted(&(fw->arp.tmsk)),
sizeof(buf) - strlen(buf) - 1);
- printf("-d %s ", buf);
+ printf("-d %s", buf);
+ sep = " ";
}
for (i = 0; i <ARPT_DEV_ADDR_LEN_MAX; i++)
@@ -515,28 +528,28 @@ after_devsrc:
break;
if (i == ARPT_DEV_ADDR_LEN_MAX)
goto after_devdst;
- printf("%s", fw->arp.invflags & ARPT_INV_TGTDEVADDR
+ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_TGTDEVADDR
? "! " : "");
printf("--dst-mac ");
print_mac_and_mask((unsigned char *)fw->arp.tgt_devaddr.addr,
(unsigned char *)fw->arp.tgt_devaddr.mask, ETH_ALEN);
- printf(" ");
+ sep = " ";
after_devdst:
if (fw->arp.arhln_mask != 0) {
- printf("%s", fw->arp.invflags & ARPT_INV_ARPHLN
+ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHLN
? "! " : "");
printf("--h-length %d", fw->arp.arhln);
if (fw->arp.arhln_mask != 255)
printf("/%d", fw->arp.arhln_mask);
- printf(" ");
+ sep = " ";
}
if (fw->arp.arpop_mask != 0) {
int tmp = ntohs(fw->arp.arpop);
- printf("%s", fw->arp.invflags & ARPT_INV_ARPOP
+ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPOP
? "! " : "");
if (tmp <= NUMOPCODES && !(format & FMT_NUMERIC))
printf("--opcode %s", opcodes[tmp-1]);
@@ -545,13 +558,13 @@ after_devdst:
if (fw->arp.arpop_mask != 65535)
printf("/%d", ntohs(fw->arp.arpop_mask));
- printf(" ");
+ sep = " ";
}
if (fw->arp.arhrd_mask != 0) {
uint16_t tmp = ntohs(fw->arp.arhrd);
- printf("%s", fw->arp.invflags & ARPT_INV_ARPHRD
+ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHRD
? "! " : "");
if (tmp == 1 && !(format & FMT_NUMERIC))
printf("--h-type %s", "Ethernet");
@@ -559,13 +572,13 @@ after_devdst:
printf("--h-type %u", tmp);
if (fw->arp.arhrd_mask != 65535)
printf("/%d", ntohs(fw->arp.arhrd_mask));
- printf(" ");
+ sep = " ";
}
if (fw->arp.arpro_mask != 0) {
int tmp = ntohs(fw->arp.arpro);
- printf("%s", fw->arp.invflags & ARPT_INV_ARPPRO
+ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPPRO
? "! " : "");
if (tmp == 0x0800 && !(format & FMT_NUMERIC))
printf("--proto-type %s", "IPv4");
@@ -573,7 +586,7 @@ after_devdst:
printf("--proto-type 0x%x", tmp);
if (fw->arp.arpro_mask != 65535)
printf("/%x", ntohs(fw->arp.arpro_mask));
- printf(" ");
+ sep = " ";
}
}
@@ -584,8 +597,10 @@ nft_arp_save_rule(const void *data, unsigned int format)
format |= FMT_NUMERIC;
- nft_arp_print_rule_details(&cs->arp, format);
- save_matches_and_target(cs, false, &cs->arp, format);
+ nft_arp_print_rule_details(cs, format);
+ if (cs->target && cs->target->save)
+ cs->target->save(&cs->fw, cs->target->t);
+ printf("\n");
}
static void
@@ -598,9 +613,7 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format)
nft_rule_to_iptables_command_state(r, &cs);
- if (strlen(cs.jumpto))
- printf("-j %s ", cs.jumpto);
- nft_arp_print_rule_details(&cs.arp, format);
+ nft_arp_print_rule_details(&cs, format);
print_matches_and_target(&cs, format);
if (!(format & FMT_NOCOUNTS)) {
diff --git a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
index f8629551b0ba9..0664e3b38d5e8 100755
--- a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
+++ b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
@@ -35,22 +35,22 @@ DUMP='*filter
:INPUT ACCEPT
:OUTPUT DROP
:foo -
--A INPUT -s 10.0.0.0/8 --h-length 6 --h-type 1 -j ACCEPT
--A INPUT -d 192.168.123.1 --h-length 6 --h-type 1 -j ACCEPT
--A INPUT --src-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 -j ACCEPT
--A INPUT --dst-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 -j ACCEPT
--A INPUT --h-length 6 --h-type 1 -j foo
--A INPUT --h-length 6 --h-type 1
--A OUTPUT -o lo --h-length 6 --h-type 1 -j ACCEPT
--A OUTPUT -o eth134 --h-length 6 --h-type 1 -j mangle --mangle-ip-s 10.0.0.1
--A OUTPUT -o eth432 --h-length 6 --h-type 1 -j CLASSIFY --set-class feed:babe
--A OUTPUT -o eth432 --h-length 6 --opcode 1 --h-type 1 -j CLASSIFY --set-class feed:babe
--A foo -i lo --h-length 6 --h-type 1 -j ACCEPT
--A foo --h-length 6 --h-type 1 -j ACCEPT
--A foo --h-length 6 --h-type 1 -j MARK --set-mark 12345
--A foo --h-length 6 --opcode 1 --h-type 1 -j ACCEPT
--A foo --h-length 6 --h-type 1 --proto-type 0x800 -j ACCEPT
--A foo -i lo --h-length 6 --opcode 1 --h-type 1 --proto-type 0x800 -j ACCEPT
+-A INPUT -j ACCEPT -s 10.0.0.0/8 --h-length 6 --h-type 1
+-A INPUT -j ACCEPT -d 192.168.123.1 --h-length 6 --h-type 1
+-A INPUT -j ACCEPT --src-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1
+-A INPUT -j ACCEPT --dst-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1
+-A INPUT -j foo --h-length 6 --h-type 1
+-A INPUT --h-length 6 --h-type 1
+-A OUTPUT -j ACCEPT -o lo --h-length 6 --h-type 1
+-A OUTPUT -j mangle -o eth134 --h-length 6 --h-type 1 --mangle-ip-s 10.0.0.1
+-A OUTPUT -j CLASSIFY -o eth432 --h-length 6 --h-type 1 --set-class feed:babe
+-A OUTPUT -j CLASSIFY -o eth432 --h-length 6 --opcode 1 --h-type 1 --set-class feed:babe
+-A foo -j ACCEPT -i lo --h-length 6 --h-type 1
+-A foo -j ACCEPT --h-length 6 --h-type 1
+-A foo -j MARK --h-length 6 --h-type 1 --set-mark 12345
+-A foo -j ACCEPT --h-length 6 --opcode 1 --h-type 1
+-A foo -j ACCEPT --h-length 6 --h-type 1 --proto-type 0x800
+-A foo -j ACCEPT -i lo --h-length 6 --opcode 1 --h-type 1 --proto-type 0x800
'
diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save)
diff --git a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0
index ee17da0023b82..d742c3d506305 100755
--- a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0
+++ b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0
@@ -11,7 +11,7 @@ set -e
DUMP='*filter
:OUTPUT ACCEPT
-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1
--A OUTPUT --h-length 6 --h-type 1 -j mangle --mangle-ip-d 10.0.0.2
+-A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-d 10.0.0.2
'
# note how mangle-ip-s is unset in second rule
@@ -19,8 +19,8 @@ DUMP='*filter
EXPECT='*filter
:INPUT ACCEPT
:OUTPUT ACCEPT
--A OUTPUT --h-length 6 --h-type 1 -j mangle --mangle-ip-s 10.0.0.1
--A OUTPUT --h-length 6 --h-type 1 -j mangle --mangle-ip-d 10.0.0.2
+-A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-s 10.0.0.1
+-A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-d 10.0.0.2
'
$XT_MULTI arptables -F
--
2.21.0

View File

@ -0,0 +1,116 @@
From 3013545255719fcda031c227570c498c4fc7cc35 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 31 Jan 2019 16:12:55 +0100
Subject: [PATCH] arptables-nft: Don't print default h-len/h-type values
Default values for --h-len and --h-type being printed for rules where
user didn't provide them is unexpected and confusing. The drawback is
the opposite: If user provided either of them with their default value,
they are later omitted when listing rules. Though since unlike legacy
arptables we can't distinguish between not specified and specified with
default value, we can't fix both - so choose to optimize for the more
likely case.
Fixes: 5aecb2d8bfdda ("arptables: pre-init hlen and ethertype")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 84331e3ed3f8eb9d53c00c221113ad16b209968a)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-arp.c | 4 +--
.../arptables/0001-arptables-save-restore_0 | 32 +++++++++----------
.../0002-arptables-restore-defaults_0 | 6 ++--
3 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index 2cbdf23214049..37b0985377bef 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -537,7 +537,7 @@ after_devsrc:
after_devdst:
- if (fw->arp.arhln_mask != 0) {
+ if (fw->arp.arhln_mask != 255 || fw->arp.arhln != 6) {
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHLN
? "! " : "");
printf("--h-length %d", fw->arp.arhln);
@@ -561,7 +561,7 @@ after_devdst:
sep = " ";
}
- if (fw->arp.arhrd_mask != 0) {
+ if (fw->arp.arhrd_mask != 65535 || fw->arp.arhrd != htons(1)) {
uint16_t tmp = ntohs(fw->arp.arhrd);
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHRD
diff --git a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
index 0664e3b38d5e8..e10f61cc8f95b 100755
--- a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
+++ b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0
@@ -35,22 +35,22 @@ DUMP='*filter
:INPUT ACCEPT
:OUTPUT DROP
:foo -
--A INPUT -j ACCEPT -s 10.0.0.0/8 --h-length 6 --h-type 1
--A INPUT -j ACCEPT -d 192.168.123.1 --h-length 6 --h-type 1
--A INPUT -j ACCEPT --src-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1
--A INPUT -j ACCEPT --dst-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1
--A INPUT -j foo --h-length 6 --h-type 1
--A INPUT --h-length 6 --h-type 1
--A OUTPUT -j ACCEPT -o lo --h-length 6 --h-type 1
--A OUTPUT -j mangle -o eth134 --h-length 6 --h-type 1 --mangle-ip-s 10.0.0.1
--A OUTPUT -j CLASSIFY -o eth432 --h-length 6 --h-type 1 --set-class feed:babe
--A OUTPUT -j CLASSIFY -o eth432 --h-length 6 --opcode 1 --h-type 1 --set-class feed:babe
--A foo -j ACCEPT -i lo --h-length 6 --h-type 1
--A foo -j ACCEPT --h-length 6 --h-type 1
--A foo -j MARK --h-length 6 --h-type 1 --set-mark 12345
--A foo -j ACCEPT --h-length 6 --opcode 1 --h-type 1
--A foo -j ACCEPT --h-length 6 --h-type 1 --proto-type 0x800
--A foo -j ACCEPT -i lo --h-length 6 --opcode 1 --h-type 1 --proto-type 0x800
+-A INPUT -j ACCEPT -s 10.0.0.0/8
+-A INPUT -j ACCEPT -d 192.168.123.1
+-A INPUT -j ACCEPT --src-mac fe:ed:ba:be:00:01
+-A INPUT -j ACCEPT --dst-mac fe:ed:ba:be:00:01
+-A INPUT -j foo
+-A INPUT
+-A OUTPUT -j ACCEPT -o lo
+-A OUTPUT -j mangle -o eth134 --mangle-ip-s 10.0.0.1
+-A OUTPUT -j CLASSIFY -o eth432 --set-class feed:babe
+-A OUTPUT -j CLASSIFY -o eth432 --opcode 1 --set-class feed:babe
+-A foo -j ACCEPT -i lo
+-A foo -j ACCEPT
+-A foo -j MARK --set-mark 12345
+-A foo -j ACCEPT --opcode 1
+-A foo -j ACCEPT --proto-type 0x800
+-A foo -j ACCEPT -i lo --opcode 1 --proto-type 0x800
'
diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save)
diff --git a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0
index d742c3d506305..b2ed95e87bb40 100755
--- a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0
+++ b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0
@@ -11,7 +11,7 @@ set -e
DUMP='*filter
:OUTPUT ACCEPT
-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1
--A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-d 10.0.0.2
+-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2
'
# note how mangle-ip-s is unset in second rule
@@ -19,8 +19,8 @@ DUMP='*filter
EXPECT='*filter
:INPUT ACCEPT
:OUTPUT ACCEPT
--A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-s 10.0.0.1
--A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-d 10.0.0.2
+-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1
+-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2
'
$XT_MULTI arptables -F
--
2.21.0

View File

@ -0,0 +1,90 @@
From bf2b28732579e44bf4c77869be586ee7d73bdabb Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 31 Jan 2019 16:12:56 +0100
Subject: [PATCH] tests: shell: Add arptables-nft verbose output test
With arptables-nft output being in a very good state now, add a test to
ensure it stays that way.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 3d8f261c565a024c13d627b18a0fcafc76de8f2c)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
.../arptables/0003-arptables-verbose-output_0 | 64 +++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100755 iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0
diff --git a/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 b/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0
new file mode 100755
index 0000000000000..35126fa7d717c
--- /dev/null
+++ b/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+set -e
+set -x
+
+# there is no legacy backend to test
+[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
+
+$XT_MULTI arptables -N foo
+
+# check verbose output matches expectations
+
+RULE1='-i eth23 -j ACCEPT'
+VOUT1='-j ACCEPT -i eth23 -o *'
+
+RULE2='-i eth23'
+VOUT2='-i eth23 -o *'
+
+RULE3='-i eth23 -j MARK --set-mark 42'
+VOUT3='-j MARK -i eth23 -o * --set-mark 42'
+
+RULE4='-o eth23 -j CLASSIFY --set-class 23:42'
+VOUT4='-j CLASSIFY -i * -o eth23 --set-class 23:42'
+
+RULE5='-o eth23 -j foo'
+VOUT5='-j foo -i * -o eth23'
+
+RULE6='-o eth23 -j mangle --mangle-ip-s 10.0.0.1'
+VOUT6='-j mangle -i * -o eth23 --mangle-ip-s 10.0.0.1'
+
+diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI arptables -v -A INPUT $RULE1)
+diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI arptables -v -A INPUT $RULE2)
+diff -u -Z <(echo -e "$VOUT3") <($XT_MULTI arptables -v -A INPUT $RULE3)
+diff -u -Z <(echo -e "$VOUT4") <($XT_MULTI arptables -v -A OUTPUT $RULE4)
+diff -u -Z <(echo -e "$VOUT5") <($XT_MULTI arptables -v -A OUTPUT $RULE5)
+diff -u -Z <(echo -e "$VOUT6") <($XT_MULTI arptables -v -A foo $RULE6)
+
+EXPECT='Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
+-j ACCEPT -i eth23 -o *, pcnt=0 -- bcnt=0
+-i eth23 -o *, pcnt=0 -- bcnt=0
+-j MARK -i eth23 -o * --set-mark 42, pcnt=0 -- bcnt=0
+
+Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
+-j CLASSIFY -i * -o eth23 --set-class 23:42, pcnt=0 -- bcnt=0
+-j foo -i * -o eth23, pcnt=0 -- bcnt=0
+
+Chain foo (1 references)
+-j mangle -i * -o eth23 --mangle-ip-s 10.0.0.1, pcnt=0 -- bcnt=0'
+
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI arptables -v -n -L)
+
+EXPECT='*filter
+:INPUT ACCEPT
+:OUTPUT ACCEPT
+:foo -
+-A INPUT -j ACCEPT -i eth23
+-A INPUT -i eth23
+-A INPUT -j MARK -i eth23 --set-mark 42
+-A OUTPUT -j CLASSIFY -o eth23 --set-class 23:42
+-A OUTPUT -j foo -o eth23
+-A foo -j mangle -o eth23 --mangle-ip-s 10.0.0.1
+'
+
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI arptables-save)
--
2.21.0

View File

@ -0,0 +1,40 @@
From 2fb13e8bdc9649c3910c6c1341dc4dd483767c0c Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Fri, 1 Feb 2019 17:06:18 +0100
Subject: [PATCH] arptables-nft: Set h-type/h-length masks by default, too
These masks are not used in nftables backend, but mangle extension
checks arhln_mask value to make sure --h-length was given (which is
implicitly the case).
Fixes: 5aecb2d8bfdda ("arptables: pre-init hlen and ethertype")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit a1da179b0ff3783badca352a42808f4398dd1a98)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/xtables-arp.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index 819e7e6c94034..2dce1a52f16fd 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -909,8 +909,12 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
{
struct iptables_command_state cs = {
.jumpto = "",
- .arp.arp.arhln = 6,
- .arp.arp.arhrd = htons(ARPHRD_ETHER),
+ .arp.arp = {
+ .arhln = 6,
+ .arhln_mask = 255,
+ .arhrd = htons(ARPHRD_ETHER),
+ .arhrd_mask = 65535,
+ },
};
int invert = 0;
unsigned int nsaddrs = 0, ndaddrs = 0;
--
2.21.0

View File

@ -0,0 +1,95 @@
From e3dacaff9e1d6f5be93afeb705cd24b38c8ff6f2 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Tue, 15 Jan 2019 23:23:03 +0100
Subject: [PATCH] nft: Add new builtin chains to cache immediately
Newly created builtin chains missing from cache was the sole reason for
the immediate calls to nft_commit(). With nft_chain_builtin_add()
inserting the new chain into the table's chain list, this is not needed
anymore. Just make sure batch_obj_del() doesn't free the payload of
NFT_COMPAT_CHAIN_ADD jobs since it contains the new chain which has
been added to cache.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 2b801fc515ae094d04207e840ed191196292b968)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 30 +++++++++---------------------
1 file changed, 9 insertions(+), 21 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 9c0ad9a2d054f..c2af1a6fd0985 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -644,6 +644,7 @@ static void nft_chain_builtin_add(struct nft_handle *h,
return;
batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
+ nftnl_chain_list_add_tail(c, h->table[table->type].chain_cache);
}
/* find if built-in table already exists */
@@ -1216,8 +1217,11 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
c = nft_chain_find(h, table, chain);
- if (c)
- nftnl_chain_rule_add_tail(r, c);
+ if (!c) {
+ errno = ENOENT;
+ return 0;
+ }
+ nftnl_chain_rule_add_tail(r, c);
return 1;
}
@@ -2282,16 +2286,8 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
bool found = false;
/* If built-in chains don't exist for this table, create them */
- if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) {
+ if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
- /* Force table and chain creation, otherwise first iptables -L
- * lists no table/chains.
- */
- if (!list_empty(&h->obj_list)) {
- nft_commit(h);
- flush_chain_cache(h, NULL);
- }
- }
ops = nft_family_ops_lookup(h->family);
@@ -2397,16 +2393,8 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
int ret = 0;
/* If built-in chains don't exist for this table, create them */
- if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) {
+ if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
nft_xt_builtin_init(h, table);
- /* Force table and chain creation, otherwise first iptables -L
- * lists no table/chains.
- */
- if (!list_empty(&h->obj_list)) {
- nft_commit(h);
- flush_chain_cache(h, NULL);
- }
- }
if (!nft_is_table_compatible(h, table)) {
xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table);
@@ -2525,8 +2513,8 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o)
break;
case NFT_COMPAT_CHAIN_ZERO:
case NFT_COMPAT_CHAIN_USER_ADD:
- break;
case NFT_COMPAT_CHAIN_ADD:
+ break;
case NFT_COMPAT_CHAIN_USER_DEL:
case NFT_COMPAT_CHAIN_USER_FLUSH:
case NFT_COMPAT_CHAIN_UPDATE:
--
2.21.0

View File

@ -0,0 +1,168 @@
From 892eaf39a4bd14ad25e55e5c0d4ef3dc163183da Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Tue, 15 Jan 2019 23:23:04 +0100
Subject: [PATCH] xtables: Fix position of replaced rules in cache
When replacing a rule, the replacement was simply appended to the
chain's rule list. Instead, insert it where the rule it replaces was.
This also fixes for zero counters command to remove the old rule from
cache.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 5ca9acf51adf9dcc8e0d82cd8f5b9b2514f900ee)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 34 +++++++++++++++++-----------------
iptables/nft.h | 2 +-
iptables/xtables-arp.c | 2 +-
iptables/xtables-eb.c | 2 +-
iptables/xtables.c | 4 ++--
5 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index c2af1a6fd0985..76764fde4e9fb 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1186,7 +1186,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain);
int
nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
- void *data, uint64_t handle, bool verbose)
+ void *data, struct nftnl_rule *ref, bool verbose)
{
struct nftnl_chain *c;
struct nftnl_rule *r;
@@ -1202,8 +1202,9 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
if (r == NULL)
return 0;
- if (handle > 0) {
- nftnl_rule_set(r, NFTNL_RULE_HANDLE, &handle);
+ if (ref) {
+ nftnl_rule_set_u64(r, NFTNL_RULE_HANDLE,
+ nftnl_rule_get_u64(ref, NFTNL_RULE_HANDLE));
type = NFT_COMPAT_RULE_REPLACE;
} else
type = NFT_COMPAT_RULE_APPEND;
@@ -1216,12 +1217,17 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
if (verbose)
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
- c = nft_chain_find(h, table, chain);
- if (!c) {
- errno = ENOENT;
- return 0;
+ if (ref) {
+ nftnl_chain_rule_insert_at(r, ref);
+ nftnl_chain_rule_del(r);
+ } else {
+ c = nft_chain_find(h, table, chain);
+ if (!c) {
+ errno = ENOENT;
+ return 0;
+ }
+ nftnl_chain_rule_add_tail(r, c);
}
- nftnl_chain_rule_add_tail(r, c);
return 1;
}
@@ -2109,7 +2115,7 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
r = nft_rule_find(h, c, data, rulenum - 1);
if (r != NULL)
return nft_rule_append(h, chain, table, data,
- 0, verbose);
+ NULL, verbose);
errno = ENOENT;
goto err;
@@ -2181,11 +2187,7 @@ int nft_rule_replace(struct nft_handle *h, const char *chain,
(unsigned long long)
nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE));
- nftnl_rule_list_del(r);
-
- ret = nft_rule_append(h, chain, table, data,
- nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE),
- verbose);
+ ret = nft_rule_append(h, chain, table, data, r, verbose);
} else
errno = ENOENT;
@@ -2461,9 +2463,7 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
cs.counters.pcnt = cs.counters.bcnt = 0;
- ret = nft_rule_append(h, chain, table, &cs,
- nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE),
- false);
+ ret = nft_rule_append(h, chain, table, &cs, r, false);
error:
return ret;
diff --git a/iptables/nft.h b/iptables/nft.h
index dfdffd69342db..97d73c8b534be 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -98,7 +98,7 @@ bool nft_chain_exists(struct nft_handle *h, const char *table, const char *chain
*/
struct nftnl_rule;
-int nft_rule_append(struct nft_handle *h, const char *chain, const char *table, void *data, uint64_t handle, bool verbose);
+int nft_rule_append(struct nft_handle *h, const char *chain, const char *table, void *data, struct nftnl_rule *ref, bool verbose);
int nft_rule_insert(struct nft_handle *h, const char *chain, const char *table, void *data, int rulenum, bool verbose);
int nft_rule_check(struct nft_handle *h, const char *chain, const char *table, void *data, bool verbose);
int nft_rule_delete(struct nft_handle *h, const char *chain, const char *table, void *data, bool verbose);
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index 2dce1a52f16fd..18cdced627c55 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -825,7 +825,7 @@ append_entry(struct nft_handle *h,
for (j = 0; j < ndaddrs; j++) {
cs->arp.arp.tgt.s_addr = daddrs[j].s_addr;
if (append) {
- ret = nft_rule_append(h, chain, table, cs, 0,
+ ret = nft_rule_append(h, chain, table, cs, NULL,
verbose);
} else {
ret = nft_rule_insert(h, chain, table, cs,
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 871891442e431..4c52c29aa4817 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -171,7 +171,7 @@ append_entry(struct nft_handle *h,
int ret = 1;
if (append)
- ret = nft_rule_append(h, chain, table, cs, 0, verbose);
+ ret = nft_rule_append(h, chain, table, cs, NULL, verbose);
else
ret = nft_rule_insert(h, chain, table, cs, rule_nr, verbose);
diff --git a/iptables/xtables.c b/iptables/xtables.c
index da11e8cc159a0..d0167e6396975 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -406,7 +406,7 @@ add_entry(const char *chain,
if (append) {
ret = nft_rule_append(h, chain, table,
- cs, 0,
+ cs, NULL,
verbose);
} else {
ret = nft_rule_insert(h, chain, table,
@@ -426,7 +426,7 @@ add_entry(const char *chain,
&d.mask.v6[j], sizeof(struct in6_addr));
if (append) {
ret = nft_rule_append(h, chain, table,
- cs, 0,
+ cs, NULL,
verbose);
} else {
ret = nft_rule_insert(h, chain, table,
--
2.21.0

View File

@ -0,0 +1,282 @@
From 3c0eab01c78ff0215cafc124fd76d67f39f2b4ca Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Tue, 15 Jan 2019 23:23:05 +0100
Subject: [PATCH] xtables: Fix for inserting rule at wrong position
iptables-restore allows to insert rules at a certain position which is
problematic for iptables-nft to realize since rule position is not
determined by number but handle of previous or following rule and in
case the rules surrounding the new one are new as well, they don't have
a handle to refer to yet.
Fix this by making use of NFTNL_RULE_POSITION_ID attribute: When
inserting before a rule which does not have a handle, refer to it using
its NFTNL_RULE_ID value. If the latter doesn't exist either, assign a
new one to it.
The last used rule ID value is tracked in a new field of struct
nft_handle which is incremented before each use.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 7ea0b7d809229973d950ed99845bdd0b2eb4cbb7)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 30 +++--
iptables/nft.h | 1 +
.../ipt-restore/0003-restore-ordering_0 | 117 ++++++++++++++++++
.../testcases/iptables/0005-rule-replace_0 | 38 ++++++
4 files changed, 176 insertions(+), 10 deletions(-)
create mode 100755 iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0
create mode 100755 iptables/tests/shell/testcases/iptables/0005-rule-replace_0
diff --git a/iptables/nft.c b/iptables/nft.c
index 76764fde4e9fb..2fa973cf03975 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2065,16 +2065,30 @@ int nft_rule_delete(struct nft_handle *h, const char *chain,
static struct nftnl_rule *
nft_rule_add(struct nft_handle *h, const char *chain,
const char *table, struct iptables_command_state *cs,
- uint64_t handle, bool verbose)
+ struct nftnl_rule *ref, bool verbose)
{
struct nftnl_rule *r;
+ uint64_t ref_id;
r = nft_rule_new(h, chain, table, cs);
if (r == NULL)
return NULL;
- if (handle > 0)
- nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle);
+ if (ref) {
+ ref_id = nftnl_rule_get_u64(ref, NFTNL_RULE_HANDLE);
+ if (ref_id > 0) {
+ nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, ref_id);
+ DEBUGP("adding after rule handle %"PRIu64"\n", ref_id);
+ } else {
+ ref_id = nftnl_rule_get_u32(ref, NFTNL_RULE_ID);
+ if (!ref_id) {
+ ref_id = ++h->rule_id;
+ nftnl_rule_set_u32(ref, NFTNL_RULE_ID, ref_id);
+ }
+ nftnl_rule_set_u32(r, NFTNL_RULE_POSITION_ID, ref_id);
+ DEBUGP("adding after rule ID %"PRIu64"\n", ref_id);
+ }
+ }
if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) {
nftnl_rule_free(r);
@@ -2090,9 +2104,8 @@ nft_rule_add(struct nft_handle *h, const char *chain,
int nft_rule_insert(struct nft_handle *h, const char *chain,
const char *table, void *data, int rulenum, bool verbose)
{
- struct nftnl_rule *r, *new_rule;
+ struct nftnl_rule *r = NULL, *new_rule;
struct nftnl_chain *c;
- uint64_t handle = 0;
/* If built-in chains don't exist for this table, create them */
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
@@ -2120,16 +2133,13 @@ int nft_rule_insert(struct nft_handle *h, const char *chain,
errno = ENOENT;
goto err;
}
-
- handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE);
- DEBUGP("adding after rule handle %"PRIu64"\n", handle);
}
- new_rule = nft_rule_add(h, chain, table, data, handle, verbose);
+ new_rule = nft_rule_add(h, chain, table, data, r, verbose);
if (!new_rule)
goto err;
- if (handle)
+ if (r)
nftnl_chain_rule_insert_at(new_rule, r);
else
nftnl_chain_rule_add(new_rule, c);
diff --git a/iptables/nft.h b/iptables/nft.h
index 97d73c8b534be..0726923a63dd4 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -32,6 +32,7 @@ struct nft_handle {
struct mnl_socket *nl;
uint32_t portid;
uint32_t seq;
+ uint32_t rule_id;
struct list_head obj_list;
int obj_list_num;
struct nftnl_batch *batch;
diff --git a/iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0 b/iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0
new file mode 100755
index 0000000000000..51f2422e15259
--- /dev/null
+++ b/iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+# Make sure iptables-restore does the right thing
+# when encountering INSERT rules with index.
+
+set -e
+
+# show rules, drop uninteresting policy settings
+ipt_show() {
+ $XT_MULTI iptables -S | grep -v '^-P'
+}
+
+# basic issue reproducer
+
+$XT_MULTI iptables-restore <<EOF
+*filter
+-A FORWARD -m comment --comment "appended rule" -j ACCEPT
+-I FORWARD 1 -m comment --comment "rule 1" -j ACCEPT
+-I FORWARD 2 -m comment --comment "rule 2" -j ACCEPT
+-I FORWARD 3 -m comment --comment "rule 3" -j ACCEPT
+COMMIT
+EOF
+
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
+-A FORWARD -m comment --comment "rule 2" -j ACCEPT
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
+-A FORWARD -m comment --comment "appended rule" -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
+
+# insert rules into existing ruleset
+
+$XT_MULTI iptables-restore --noflush <<EOF
+*filter
+-I FORWARD 1 -m comment --comment "rule 0.5" -j ACCEPT
+-I FORWARD 3 -m comment --comment "rule 1.5" -j ACCEPT
+-I FORWARD 5 -m comment --comment "rule 2.5" -j ACCEPT
+-I FORWARD 7 -m comment --comment "rule 3.5" -j ACCEPT
+-I FORWARD 9 -m comment --comment "appended rule 2" -j ACCEPT
+COMMIT
+EOF
+
+EXPECT='-A FORWARD -m comment --comment "rule 0.5" -j ACCEPT
+-A FORWARD -m comment --comment "rule 1" -j ACCEPT
+-A FORWARD -m comment --comment "rule 1.5" -j ACCEPT
+-A FORWARD -m comment --comment "rule 2" -j ACCEPT
+-A FORWARD -m comment --comment "rule 2.5" -j ACCEPT
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
+-A FORWARD -m comment --comment "rule 3.5" -j ACCEPT
+-A FORWARD -m comment --comment "appended rule" -j ACCEPT
+-A FORWARD -m comment --comment "appended rule 2" -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
+
+# insert rules in between added ones
+
+$XT_MULTI iptables-restore <<EOF
+*filter
+-A FORWARD -m comment --comment "appended rule 1" -j ACCEPT
+-A FORWARD -m comment --comment "appended rule 2" -j ACCEPT
+-A FORWARD -m comment --comment "appended rule 3" -j ACCEPT
+-I FORWARD 1 -m comment --comment "rule 1" -j ACCEPT
+-I FORWARD 3 -m comment --comment "rule 2" -j ACCEPT
+-I FORWARD 5 -m comment --comment "rule 3" -j ACCEPT
+COMMIT
+EOF
+
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
+-A FORWARD -m comment --comment "appended rule 1" -j ACCEPT
+-A FORWARD -m comment --comment "rule 2" -j ACCEPT
+-A FORWARD -m comment --comment "appended rule 2" -j ACCEPT
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
+-A FORWARD -m comment --comment "appended rule 3" -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
+
+# test rule deletion in dump files
+
+$XT_MULTI iptables-restore --noflush <<EOF
+*filter
+-D FORWARD -m comment --comment "appended rule 1" -j ACCEPT
+-D FORWARD 3
+-I FORWARD 3 -m comment --comment "manually replaced rule 2" -j ACCEPT
+COMMIT
+EOF
+
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
+-A FORWARD -m comment --comment "rule 2" -j ACCEPT
+-A FORWARD -m comment --comment "manually replaced rule 2" -j ACCEPT
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
+-A FORWARD -m comment --comment "appended rule 3" -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
+
+# test rule replacement in dump files
+
+$XT_MULTI iptables-restore <<EOF
+*filter
+-A FORWARD -m comment --comment "rule 1" -j ACCEPT
+-A FORWARD -m comment --comment "rule to be replaced" -j ACCEPT
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT
+COMMIT
+EOF
+
+$XT_MULTI iptables-restore --noflush <<EOF
+*filter
+-R FORWARD 2 -m comment --comment "replacement" -j ACCEPT
+-I FORWARD 2 -m comment --comment "insert referencing replaced rule" -j ACCEPT
+COMMIT
+EOF
+
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
+-A FORWARD -m comment --comment "insert referencing replaced rule" -j ACCEPT
+-A FORWARD -m comment --comment replacement -j ACCEPT
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
diff --git a/iptables/tests/shell/testcases/iptables/0005-rule-replace_0 b/iptables/tests/shell/testcases/iptables/0005-rule-replace_0
new file mode 100755
index 0000000000000..5a3e922e50672
--- /dev/null
+++ b/iptables/tests/shell/testcases/iptables/0005-rule-replace_0
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# test rule replacement
+
+set -e
+
+# show rules, drop uninteresting policy settings
+ipt_show() {
+ $XT_MULTI iptables -S | grep -v '^-P'
+}
+
+$XT_MULTI iptables -A FORWARD -m comment --comment "rule 1" -j ACCEPT
+$XT_MULTI iptables -A FORWARD -m comment --comment "rule 2" -j ACCEPT
+$XT_MULTI iptables -A FORWARD -m comment --comment "rule 3" -j ACCEPT
+
+$XT_MULTI iptables -R FORWARD 2 -m comment --comment "replaced 2" -j ACCEPT
+
+EXPECT='-A FORWARD -m comment --comment "rule 1" -j ACCEPT
+-A FORWARD -m comment --comment "replaced 2" -j ACCEPT
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
+
+$XT_MULTI iptables -R FORWARD 1 -m comment --comment "replaced 1" -j ACCEPT
+
+EXPECT='-A FORWARD -m comment --comment "replaced 1" -j ACCEPT
+-A FORWARD -m comment --comment "replaced 2" -j ACCEPT
+-A FORWARD -m comment --comment "rule 3" -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
+
+$XT_MULTI iptables -R FORWARD 3 -m comment --comment "replaced 3" -j ACCEPT
+
+EXPECT='-A FORWARD -m comment --comment "replaced 1" -j ACCEPT
+-A FORWARD -m comment --comment "replaced 2" -j ACCEPT
+-A FORWARD -m comment --comment "replaced 3" -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <(ipt_show)
--
2.21.0

View File

@ -0,0 +1,97 @@
From b029ccdc27297b60348492ab98376789ea53fa01 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Fri, 1 Feb 2019 19:17:50 +0100
Subject: [PATCH] xtables: Fix for crash when comparing rules with standard
target
When parsing an nftnl_rule with a standard verdict,
nft_rule_to_iptables_command_state() initialized cs->target but didn't
care about cs->target->t. When later comparing that rule to another,
compare_targets() crashed due to unconditional access to t's fields.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit a880cc28358a32f96467e248266973b6ab83f080)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-shared.c | 23 +++++++++++++++----
.../testcases/iptables/0005-delete-rules_0 | 7 ++++++
iptables/xtables.c | 4 +++-
3 files changed, 29 insertions(+), 5 deletions(-)
create mode 100755 iptables/tests/shell/testcases/iptables/0005-delete-rules_0
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 7b8ca5e4becaf..dfc1c803cb68d 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -660,19 +660,34 @@ void nft_rule_to_iptables_command_state(const struct nftnl_rule *r,
match->m = m;
}
- if (cs->target != NULL)
+ if (cs->target != NULL) {
cs->jumpto = cs->target->name;
- else if (cs->jumpto != NULL)
+ } else if (cs->jumpto != NULL) {
+ struct xt_entry_target *t;
+ uint32_t size;
+
cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
- else
+ if (!cs->target)
+ return;
+
+ size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size;
+ t = xtables_calloc(1, size);
+ t->u.target_size = size;
+ t->u.user.revision = cs->target->revision;
+ strcpy(t->u.user.name, cs->jumpto);
+ cs->target->t = t;
+ } else {
cs->jumpto = "";
+ }
}
void nft_clear_iptables_command_state(struct iptables_command_state *cs)
{
xtables_rule_matches_free(&cs->matches);
- if (cs->target)
+ if (cs->target) {
free(cs->target->t);
+ cs->target->t = NULL;
+ }
}
void print_header(unsigned int format, const char *chain, const char *pol,
diff --git a/iptables/tests/shell/testcases/iptables/0005-delete-rules_0 b/iptables/tests/shell/testcases/iptables/0005-delete-rules_0
new file mode 100755
index 0000000000000..9312fd53c3437
--- /dev/null
+++ b/iptables/tests/shell/testcases/iptables/0005-delete-rules_0
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# test for crash when comparing rules with standard target
+
+$XT_MULTI iptables -A FORWARD -i eth23 -o eth42 -j DROP
+$XT_MULTI iptables -D FORWARD -i eth23 -o eth42 -j REJECT
+[[ $? -eq 1 ]] || exit 1
diff --git a/iptables/xtables.c b/iptables/xtables.c
index d0167e6396975..eaa9fedeb03bb 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -1185,8 +1185,10 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
*table = p.table;
xtables_rule_matches_free(&cs.matches);
- if (cs.target)
+ if (cs.target) {
free(cs.target->t);
+ cs.target->t = NULL;
+ }
if (h->family == AF_INET) {
free(args.s.addr.v4);
--
2.21.0

View File

@ -0,0 +1,258 @@
From 27b68bd11b99429d1b830dbe76fc0148b5a24a16 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Mon, 4 Feb 2019 21:52:53 +0100
Subject: [PATCH] xtables: Fix for false-positive rule matching
When comparing two rules with non-standard targets, differences in
targets' payloads wasn't respected.
The cause is a rather hideous one: Unlike xtables_find_match(),
xtables_find_target() did not care whether the found target was already
in use or not, so the same target instance was assigned to both rules
and therefore payload comparison happened over the same memory location.
With legacy iptables it is not possible to reuse a target: The only case
where two rules (i.e., iptables_command_state instances) could exist at
the same time is when comparing rules, but that's handled using libiptc.
The above change clashes with ebtables-nft's reuse of target objects:
While input parsing still just assigns the object from xtables_targets
list, rule conversion from nftnl to iptables_command_state allocates new
data. To fix this, make ebtables-nft input parsing use the common
command_jump() routine instead of its own simplified copy. In turn, this
also eliminates the ebtables-nft-specific variants of parse_target(),
though with a slight change of behaviour: Names of user-defined chains
are no longer allowed to contain up to 31 but merely 28 characters.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 148131f20421046fea028e638581e938ec985783)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-bridge.c | 10 ++++
iptables/nft-bridge.h | 2 -
iptables/nft-shared.c | 5 ++
.../testcases/iptables/0005-delete-rules_0 | 7 +++
iptables/xtables-eb-translate.c | 24 +---------
iptables/xtables-eb.c | 47 +------------------
libxtables/xtables.c | 18 ++++++-
7 files changed, 41 insertions(+), 72 deletions(-)
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index ad583a60c424d..140fcf0a31b84 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -45,6 +45,16 @@ void ebt_cs_clean(struct iptables_command_state *cs)
free(m);
m = nm;
}
+
+ if (cs->target) {
+ free(cs->target->t);
+ cs->target->t = NULL;
+
+ if (cs->target == cs->target->next) {
+ free(cs->target);
+ cs->target = NULL;
+ }
+ }
}
static void ebt_print_mac(const unsigned char *mac)
diff --git a/iptables/nft-bridge.h b/iptables/nft-bridge.h
index de52cd7195bbb..d90066f1030a2 100644
--- a/iptables/nft-bridge.h
+++ b/iptables/nft-bridge.h
@@ -32,7 +32,6 @@ int ebt_get_mac_and_mask(const char *from, unsigned char *to, unsigned char *mas
*/
#define EBT_TABLE_MAXNAMELEN 32
-#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
/* verdicts >0 are "branches" */
@@ -122,6 +121,5 @@ void ebt_add_match(struct xtables_match *m,
void ebt_add_watcher(struct xtables_target *watcher,
struct iptables_command_state *cs);
int ebt_command_default(struct iptables_command_state *cs);
-struct xtables_target *ebt_command_jump(const char *jumpto);
#endif
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index dfc1c803cb68d..ce40787f92f7d 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -687,6 +687,11 @@ void nft_clear_iptables_command_state(struct iptables_command_state *cs)
if (cs->target) {
free(cs->target->t);
cs->target->t = NULL;
+
+ if (cs->target == cs->target->next) {
+ free(cs->target);
+ cs->target = NULL;
+ }
}
}
diff --git a/iptables/tests/shell/testcases/iptables/0005-delete-rules_0 b/iptables/tests/shell/testcases/iptables/0005-delete-rules_0
index 9312fd53c3437..5038cbce5a5cf 100755
--- a/iptables/tests/shell/testcases/iptables/0005-delete-rules_0
+++ b/iptables/tests/shell/testcases/iptables/0005-delete-rules_0
@@ -5,3 +5,10 @@
$XT_MULTI iptables -A FORWARD -i eth23 -o eth42 -j DROP
$XT_MULTI iptables -D FORWARD -i eth23 -o eth42 -j REJECT
[[ $? -eq 1 ]] || exit 1
+
+# test incorrect deletion of rules with deviating payload
+# in non-standard target
+
+$XT_MULTI iptables -A FORWARD -i eth23 -o eth42 -j MARK --set-mark 23
+$XT_MULTI iptables -D FORWARD -i eth23 -o eth42 -j MARK --set-mark 42
+[[ $? -eq 1 ]] || exit 1
diff --git a/iptables/xtables-eb-translate.c b/iptables/xtables-eb-translate.c
index f98c385555eb1..0fe14d2d0db32 100644
--- a/iptables/xtables-eb-translate.c
+++ b/iptables/xtables-eb-translate.c
@@ -64,27 +64,6 @@ static int parse_rule_number(const char *rule)
return rule_nr;
}
-static const char *
-parse_target(const char *targetname)
-{
- const char *ptr;
-
- if (strlen(targetname) < 1)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid target name (too short)");
-
- if (strlen(targetname)+1 > EBT_CHAIN_MAXNAMELEN)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid target '%s' (%d chars max)",
- targetname, EBT_CHAIN_MAXNAMELEN);
-
- for (ptr = targetname; *ptr; ptr++)
- if (isspace(*ptr))
- xtables_error(PARAMETER_PROBLEM,
- "Invalid target name `%s'", targetname);
- return targetname;
-}
-
static int get_current_chain(const char *chain)
{
if (strcmp(chain, "PREROUTING") == 0)
@@ -411,8 +390,7 @@ print_zero:
break;
} else if (c == 'j') {
ebt_check_option2(&flags, OPT_JUMP);
- cs.jumpto = parse_target(optarg);
- cs.target = ebt_command_jump(cs.jumpto);
+ command_jump(&cs);
break;
} else if (c == 's') {
ebt_check_option2(&flags, OPT_SOURCE);
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 4c52c29aa4817..55cb0fe204748 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -139,27 +139,6 @@ static int parse_rule_number(const char *rule)
return rule_nr;
}
-static const char *
-parse_target(const char *targetname)
-{
- const char *ptr;
-
- if (strlen(targetname) < 1)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid target name (too short)");
-
- if (strlen(targetname)+1 > EBT_CHAIN_MAXNAMELEN)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid target '%s' (%d chars max)",
- targetname, EBT_CHAIN_MAXNAMELEN);
-
- for (ptr = targetname; *ptr; ptr++)
- if (isspace(*ptr))
- xtables_error(PARAMETER_PROBLEM,
- "Invalid target name `%s'", targetname);
- return targetname;
-}
-
static int
append_entry(struct nft_handle *h,
const char *chain,
@@ -376,29 +355,6 @@ static struct option *merge_options(struct option *oldopts,
return merge;
}
-/*
- * More glue code.
- */
-struct xtables_target *ebt_command_jump(const char *jumpto)
-{
- struct xtables_target *target;
- unsigned int verdict;
-
- /* Standard target? */
- if (!ebt_fill_target(jumpto, &verdict))
- jumpto = "standard";
-
- /* For ebtables, all targets are preloaded. Hence it is either in
- * xtables_targets or a custom chain to jump to, in which case
- * returning NULL is fine. */
- for (target = xtables_targets; target; target = target->next) {
- if (!strcmp(target->name, jumpto))
- break;
- }
-
- return target;
-}
-
static void print_help(const struct xtables_target *t,
const struct xtables_rule_match *m, const char *table)
{
@@ -1066,8 +1022,7 @@ print_zero:
} else if (c == 'j') {
ebt_check_option2(&flags, OPT_JUMP);
if (strcmp(optarg, "CONTINUE") != 0) {
- cs.jumpto = parse_target(optarg);
- cs.target = ebt_command_jump(cs.jumpto);
+ command_jump(&cs);
}
break;
} else if (c == 's') {
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index ea9bb102c8eb4..895f6988eaf57 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -756,8 +756,24 @@ xtables_find_target(const char *name, enum xtables_tryload tryload)
}
for (ptr = xtables_targets; ptr; ptr = ptr->next) {
- if (extension_cmp(name, ptr->name, ptr->family))
+ if (extension_cmp(name, ptr->name, ptr->family)) {
+ struct xtables_target *clone;
+
+ /* First target of this type: */
+ if (ptr->t == NULL)
+ break;
+
+ /* Second and subsequent clones */
+ clone = xtables_malloc(sizeof(struct xtables_target));
+ memcpy(clone, ptr, sizeof(struct xtables_target));
+ clone->udata = NULL;
+ clone->tflags = 0;
+ /* This is a clone: */
+ clone->next = clone;
+
+ ptr = clone;
break;
+ }
}
#ifndef NO_SHARED_LIBS
--
2.21.0

View File

@ -0,0 +1,75 @@
From b321a8af45e3040ae46091fef2c35d5533ab83bc Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Mon, 21 Jan 2019 17:43:34 +0100
Subject: [PATCH] ebtables: Fix rule listing with counters
This is a partial revert of commit 583b27eabcad6 ("ebtables-save: add -c
option, using xtables-style counters") which broke ruleset listing with
'--Lc' flag turned on:
| # ebtables-nft -L --Lc
| Bridge table: filter
|
| Bridge chain: INPUT, entries: 0, policy: ACCEPT
|
| Bridge chain: FORWARD, entries: 2, policy: ACCEPT
| -j foo
| , pcnt = 0 -- bcnt = 0-j ACCEPT
| , pcnt = 0 -- bcnt = 0
| Bridge chain: OUTPUT, entries: 0, policy: ACCEPT
|
| Bridge chain: foo, entries: 1, policy: RETURN
| -j ACCEPT
| , pcnt = 0 -- bcnt = 0%
(That percentage sign means no newline after last line of output and
doesn't belong to ebtables-nft's output.)
Problem was that nft_bridge_print_rule() printed the counters after
nft_bridge_save_rule() had already printed the newline character.
Note also that there is no need to remove FMT_EBT_SAVE bit from 'format'
variable: It is set only by ebtables-nft-save which doesn't call
nft_bridge_print_rule().
Fixes: 583b27eabcad6 ("ebtables-save: add -c option, using xtables-style counters")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 32ebc39f71e8107d6069a9f6fba8338a2823889d)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-bridge.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 140fcf0a31b84..43b3e3e9649b8 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -479,6 +479,11 @@ static void nft_bridge_save_rule(const void *data, unsigned int format)
(uint64_t)cs->counters.pcnt,
(uint64_t)cs->counters.bcnt);
+ if (!(format & FMT_NOCOUNTS))
+ printf(" , pcnt = %"PRIu64" -- bcnt = %"PRIu64"",
+ (uint64_t)cs->counters.pcnt,
+ (uint64_t)cs->counters.bcnt);
+
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
}
@@ -492,11 +497,7 @@ static void nft_bridge_print_rule(struct nftnl_rule *r, unsigned int num,
printf("%d ", num);
nft_rule_to_ebtables_command_state(r, &cs);
- nft_bridge_save_rule(&cs, format & ~FMT_EBT_SAVE);
- if (!(format & FMT_NOCOUNTS))
- printf(" , pcnt = %"PRIu64" -- bcnt = %"PRIu64"",
- (uint64_t)cs.counters.pcnt,
- (uint64_t)cs.counters.bcnt);
+ nft_bridge_save_rule(&cs, format);
ebt_cs_clean(&cs);
}
--
2.21.0

View File

@ -0,0 +1,534 @@
From af890b239555d52c269d224ada6382381320585d Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Tue, 5 Feb 2019 18:18:02 +0100
Subject: [PATCH] Revert "ebtables: use extrapositioned negation consistently"
This reverts commit 5f508b76a0cebaf91965ffa678089222e2d47964.
While attempts at unifying syntax between arp-, eb- and iptables-nft
increase the opportunity for more code-sharing, they are problematic
when it comes to compatibility. Accepting the old syntax on input helps,
but due to the fact that neither arptables nor ebtables support --check
command we must expect for users to test existence of a rule by
comparing input with output. If that happens in a script, deviating from
the old syntax in output has a high chance of breaking it.
Therefore revert Florian's patch changing inversion character position
in output and review the old code for consistency - the only thing
changed on top of the actual revert is ebtables' own copy of
print_iface() to make it adhere to the intrapositioned negation scheme
used throughout ebtables.
Added extension tests by the reverted commit have been kept.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 35b22e82fa62e10950d8e0fa53a755d4abadf346)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libebt_802_3.c | 4 ++--
extensions/libebt_802_3.t | 2 +-
extensions/libebt_arp.c | 14 +++++++-------
extensions/libebt_arp.t | 8 ++++----
extensions/libebt_ip.c | 16 ++++++++--------
extensions/libebt_ip.t | 6 +++---
extensions/libebt_ip6.c | 14 +++++++-------
extensions/libebt_ip6.t | 6 +++---
extensions/libebt_mark_m.c | 2 +-
extensions/libebt_mark_m.t | 4 ++--
extensions/libebt_pkttype.c | 5 +----
extensions/libebt_pkttype.t | 13 +++++++------
extensions/libebt_standard.t | 4 ++--
extensions/libebt_stp.c | 5 ++---
extensions/libebt_vlan.c | 13 ++++---------
extensions/libebt_vlan.t | 10 +++++-----
iptables/nft-bridge.c | 6 +++---
17 files changed, 62 insertions(+), 70 deletions(-)
diff --git a/extensions/libebt_802_3.c b/extensions/libebt_802_3.c
index 9e91d05262591..f05d02ead5a4a 100644
--- a/extensions/libebt_802_3.c
+++ b/extensions/libebt_802_3.c
@@ -98,15 +98,15 @@ static void br802_3_print(const void *ip, const struct xt_entry_match *match,
struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data;
if (info->bitmask & EBT_802_3_SAP) {
+ printf("--802_3-sap ");
if (info->invflags & EBT_802_3_SAP)
printf("! ");
- printf("--802_3-sap ");
printf("0x%.2x ", info->sap);
}
if (info->bitmask & EBT_802_3_TYPE) {
+ printf("--802_3-type ");
if (info->invflags & EBT_802_3_TYPE)
printf("! ");
- printf("--802_3-type ");
printf("0x%.4x ", ntohs(info->type));
}
}
diff --git a/extensions/libebt_802_3.t b/extensions/libebt_802_3.t
index 61081bd6983a8..ddfb2f0a72baf 100644
--- a/extensions/libebt_802_3.t
+++ b/extensions/libebt_802_3.t
@@ -1,3 +1,3 @@
:INPUT,FORWARD,OUTPUT
-! --802_3-sap 0x0a -j CONTINUE;=;OK
+--802_3-sap ! 0x0a -j CONTINUE;=;OK
--802_3-type 0x000a -j RETURN;=;OK
diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c
index c1b0ab1db0cf1..a062b7e7e5864 100644
--- a/extensions/libebt_arp.c
+++ b/extensions/libebt_arp.c
@@ -338,51 +338,51 @@ static void brarp_print(const void *ip, const struct xt_entry_match *match, int
if (arpinfo->bitmask & EBT_ARP_OPCODE) {
int opcode = ntohs(arpinfo->opcode);
+ printf("--arp-op ");
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) {
+ printf("--arp-htype ");
if (arpinfo->invflags & EBT_ARP_HTYPE)
printf("! ");
- printf("--arp-htype ");
printf("%d ", ntohs(arpinfo->htype));
}
if (arpinfo->bitmask & EBT_ARP_PTYPE) {
+ printf("--arp-ptype ");
if (arpinfo->invflags & EBT_ARP_PTYPE)
printf("! ");
- printf("--arp-ptype ");
printf("0x%x ", ntohs(arpinfo->ptype));
}
if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
+ printf("--arp-ip-src ");
if (arpinfo->invflags & EBT_ARP_SRC_IP)
printf("! ");
- printf("--arp-ip-src ");
printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->saddr),
xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->smsk));
}
if (arpinfo->bitmask & EBT_ARP_DST_IP) {
+ printf("--arp-ip-dst ");
if (arpinfo->invflags & EBT_ARP_DST_IP)
printf("! ");
- printf("--arp-ip-dst ");
printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->daddr),
xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->dmsk));
}
if (arpinfo->bitmask & EBT_ARP_SRC_MAC) {
+ printf("--arp-mac-src ");
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) {
+ printf("--arp-mac-dst ");
if (arpinfo->invflags & EBT_ARP_DST_MAC)
printf("! ");
- printf("--arp-mac-dst ");
xtables_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk);
printf(" ");
}
diff --git a/extensions/libebt_arp.t b/extensions/libebt_arp.t
index a05ab12dc566f..14ff0f097cfd8 100644
--- a/extensions/libebt_arp.t
+++ b/extensions/libebt_arp.t
@@ -1,11 +1,11 @@
:INPUT,FORWARD,OUTPUT
-p ARP --arp-op Request;=;OK
--p ARP ! --arp-htype 1;=;OK
+-p ARP --arp-htype ! 1;=;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;=;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-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-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-gratuitous;=;OK
diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index d48704fe1c802..acb9bfcdbbd9f 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -472,35 +472,35 @@ static void brip_print(const void *ip, const struct xt_entry_match *match,
struct in_addr *addrp, *maskp;
if (info->bitmask & EBT_IP_SOURCE) {
+ printf("--ip-src ");
if (info->invflags & EBT_IP_SOURCE)
printf("! ");
- printf("--ip-src ");
addrp = (struct in_addr *)&info->saddr;
maskp = (struct in_addr *)&info->smsk;
printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
xtables_ipmask_to_numeric(maskp));
}
if (info->bitmask & EBT_IP_DEST) {
+ printf("--ip-dst ");
if (info->invflags & EBT_IP_DEST)
printf("! ");
- printf("--ip-dst ");
addrp = (struct in_addr *)&info->daddr;
maskp = (struct in_addr *)&info->dmsk;
printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
xtables_ipmask_to_numeric(maskp));
}
if (info->bitmask & EBT_IP_TOS) {
+ printf("--ip-tos ");
if (info->invflags & EBT_IP_TOS)
printf("! ");
- printf("--ip-tos ");
printf("0x%02X ", info->tos);
}
if (info->bitmask & EBT_IP_PROTO) {
struct protoent *pe;
+ printf("--ip-proto ");
if (info->invflags & EBT_IP_PROTO)
printf("! ");
- printf("--ip-proto ");
pe = getprotobynumber(info->protocol);
if (pe == NULL) {
printf("%d ", info->protocol);
@@ -509,28 +509,28 @@ static void brip_print(const void *ip, const struct xt_entry_match *match,
}
}
if (info->bitmask & EBT_IP_SPORT) {
+ printf("--ip-sport ");
if (info->invflags & EBT_IP_SPORT)
printf("! ");
- printf("--ip-sport ");
print_port_range(info->sport);
}
if (info->bitmask & EBT_IP_DPORT) {
+ printf("--ip-dport ");
if (info->invflags & EBT_IP_DPORT)
printf("! ");
- printf("--ip-dport ");
print_port_range(info->dport);
}
if (info->bitmask & EBT_IP_ICMP) {
+ printf("--ip-icmp-type ");
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) {
+ printf("--ip-igmp-type ");
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);
}
diff --git a/extensions/libebt_ip.t b/extensions/libebt_ip.t
index 01a91a7385fcc..8be5dfbb22309 100644
--- a/extensions/libebt_ip.t
+++ b/extensions/libebt_ip.t
@@ -1,13 +1,13 @@
: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 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-tos 0xFF;=;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 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
+-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
diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c
index b727764903ffa..b8a5a5d8c3a92 100644
--- a/extensions/libebt_ip6.c
+++ b/extensions/libebt_ip6.c
@@ -399,31 +399,31 @@ static void brip6_print(const void *ip, const struct xt_entry_match *match,
struct ebt_ip6_info *ipinfo = (struct ebt_ip6_info *)match->data;
if (ipinfo->bitmask & EBT_IP6_SOURCE) {
+ printf("--ip6-src ");
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) {
+ printf("--ip6-dst ");
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) {
+ printf("--ip6-tclass ");
if (ipinfo->invflags & EBT_IP6_TCLASS)
printf("! ");
- printf("--ip6-tclass ");
printf("0x%02X ", ipinfo->tclass);
}
if (ipinfo->bitmask & EBT_IP6_PROTO) {
struct protoent *pe;
+ printf("--ip6-proto ");
if (ipinfo->invflags & EBT_IP6_PROTO)
printf("! ");
- printf("--ip6-proto ");
pe = getprotobynumber(ipinfo->protocol);
if (pe == NULL) {
printf("%d ", ipinfo->protocol);
@@ -432,21 +432,21 @@ static void brip6_print(const void *ip, const struct xt_entry_match *match,
}
}
if (ipinfo->bitmask & EBT_IP6_SPORT) {
+ printf("--ip6-sport ");
if (ipinfo->invflags & EBT_IP6_SPORT)
printf("! ");
- printf("--ip6-sport ");
print_port_range(ipinfo->sport);
}
if (ipinfo->bitmask & EBT_IP6_DPORT) {
+ printf("--ip6-dport ");
if (ipinfo->invflags & EBT_IP6_DPORT)
printf("! ");
- printf("--ip6-dport ");
print_port_range(ipinfo->dport);
}
if (ipinfo->bitmask & EBT_IP6_ICMP6) {
+ printf("--ip6-icmp-type ");
if (ipinfo->invflags & EBT_IP6_ICMP6)
printf("! ");
- printf("--ip6-icmp-type ");
print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code);
}
}
diff --git a/extensions/libebt_ip6.t b/extensions/libebt_ip6.t
index 6b3221ea58f62..fa1038af25649 100644
--- a/extensions/libebt_ip6.t
+++ b/extensions/libebt_ip6.t
@@ -1,15 +1,15 @@
:INPUT,FORWARD,OUTPUT
--p ip6 ! --ip6-src dead::beef/64 -j ACCEPT;-p IPv6 ! --ip6-src dead::/64 -j ACCEPT;OK
+-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-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-dport ! 22;=;OK
-p IPv6 --ip6-proto udp --ip6-sport 1024:65535;=;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 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
+-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
diff --git a/extensions/libebt_mark_m.c b/extensions/libebt_mark_m.c
index 64ad926f19959..2462d0af7d0bc 100644
--- a/extensions/libebt_mark_m.c
+++ b/extensions/libebt_mark_m.c
@@ -86,9 +86,9 @@ static void brmark_m_print(const void *ip, const struct xt_entry_match *match,
{
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
+ printf("--mark ");
if (info->invert)
printf("! ");
- printf("--mark ");
if (info->bitmask == EBT_MARK_OR)
printf("/0x%lx ", info->mask);
else if (info->mask != 0xffffffff)
diff --git a/extensions/libebt_mark_m.t b/extensions/libebt_mark_m.t
index 9ad41704fbb82..00035427f8b6e 100644
--- a/extensions/libebt_mark_m.t
+++ b/extensions/libebt_mark_m.t
@@ -1,6 +1,6 @@
:INPUT,FORWARD,OUTPUT
--mark 42;--mark 0x2a;OK
---mark ! 42;! --mark 0x2a;OK
+--mark ! 42;--mark ! 0x2a;OK
--mark 42/0xff;--mark 0x2a/0xff;OK
-! --mark 0x1/0xff;=;OK
+--mark ! 0x1/0xff;=;OK
--mark /0x2;=;OK
diff --git a/extensions/libebt_pkttype.c b/extensions/libebt_pkttype.c
index 265674d19bde6..4e2d19de7983b 100644
--- a/extensions/libebt_pkttype.c
+++ b/extensions/libebt_pkttype.c
@@ -75,10 +75,7 @@ static void brpkttype_print(const void *ip, const struct xt_entry_match *match,
{
struct ebt_pkttype_info *pt = (struct ebt_pkttype_info *)match->data;
- if (pt->invert)
- printf("! ");
-
- printf("--pkttype-type ");
+ printf("--pkttype-type %s", pt->invert ? "! " : "");
if (pt->pkt_type < ARRAY_SIZE(classes))
printf("%s ", classes[pt->pkt_type]);
diff --git a/extensions/libebt_pkttype.t b/extensions/libebt_pkttype.t
index f870f5c7f05c4..e3b95ded4903e 100644
--- a/extensions/libebt_pkttype.t
+++ b/extensions/libebt_pkttype.t
@@ -1,13 +1,14 @@
:INPUT,FORWARD,OUTPUT
+! --pkttype-type host;--pkttype-type ! host -j CONTINUE;OK
--pkttype-type host;=;OK
-! --pkttype-type host;=;OK
+--pkttype-type ! host;=;OK
--pkttype-type broadcast;=;OK
-! --pkttype-type broadcast;=;OK
+--pkttype-type ! broadcast;=;OK
--pkttype-type multicast;=;OK
-! --pkttype-type multicast;=;OK
+--pkttype-type ! multicast;=;OK
--pkttype-type otherhost;=;OK
-! --pkttype-type otherhost;=;OK
+--pkttype-type ! otherhost;=;OK
--pkttype-type outgoing;=;OK
-! --pkttype-type outgoing;=;OK
+--pkttype-type ! outgoing;=;OK
--pkttype-type loopback;=;OK
-! --pkttype-type loopback;=;OK
+--pkttype-type ! loopback;=;OK
diff --git a/extensions/libebt_standard.t b/extensions/libebt_standard.t
index 72081fd6575a0..0d678fb23c439 100644
--- a/extensions/libebt_standard.t
+++ b/extensions/libebt_standard.t
@@ -6,6 +6,6 @@
-d de:ad:be:ef:00:00 -j CONTINUE;=;OK
-d de:ad:be:ef:0:00/ff:ff:ff:ff:0:0 -j DROP;-d de:ad:be:ef:00:00/ff:ff:ff:ff:00:00 -j DROP;OK
-p ARP -j ACCEPT;=;OK
-! -p ARP -j ACCEPT;=;OK
+-p ! ARP -j ACCEPT;=;OK
-p 0 -j ACCEPT;=;FAIL
-! -p 0 -j ACCEPT;=;FAIL
+-p ! 0 -j ACCEPT;=;FAIL
diff --git a/extensions/libebt_stp.c b/extensions/libebt_stp.c
index 33e4c8d9c615d..06cf93b8d8449 100644
--- a/extensions/libebt_stp.c
+++ b/extensions/libebt_stp.c
@@ -307,9 +307,8 @@ static void brstp_print(const void *ip, const struct xt_entry_match *match,
for (i = 0; i < STP_NUMOPS; i++) {
if (!(stpinfo->bitmask & (1 << i)))
continue;
- if (stpinfo->invflags & (1 << i))
- printf("! ");
- printf("--%s ", brstp_opts[i].name);
+ printf("--%s %s", brstp_opts[i].name,
+ (stpinfo->invflags & (1 << i)) ? "! " : "");
if (EBT_STP_TYPE == (1 << i)) {
if (stpinfo->type == BPDU_TYPE_CONFIG)
printf("%s", BPDU_TYPE_CONFIG_STRING);
diff --git a/extensions/libebt_vlan.c b/extensions/libebt_vlan.c
index 4a2eb7126895e..a2a9dcce531ce 100644
--- a/extensions/libebt_vlan.c
+++ b/extensions/libebt_vlan.c
@@ -108,19 +108,14 @@ static void brvlan_print(const void *ip, const struct xt_entry_match *match,
struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) match->data;
if (vlaninfo->bitmask & EBT_VLAN_ID) {
- if (vlaninfo->invflags & EBT_VLAN_ID)
- printf("! ");
- printf("--vlan-id %d ", vlaninfo->id);
+ printf("--vlan-id %s%d ", (vlaninfo->invflags & EBT_VLAN_ID) ? "! " : "", vlaninfo->id);
}
if (vlaninfo->bitmask & EBT_VLAN_PRIO) {
- if (vlaninfo->invflags & EBT_VLAN_PRIO)
- printf("! ");
- printf("--vlan-prio %d ", vlaninfo->prio);
+ printf("--vlan-prio %s%d ", (vlaninfo->invflags & EBT_VLAN_PRIO) ? "! " : "", vlaninfo->prio);
}
if (vlaninfo->bitmask & EBT_VLAN_ENCAP) {
- if (vlaninfo->invflags & EBT_VLAN_ENCAP)
- printf("! ");
- printf("--vlan-encap %4.4X ", ntohs(vlaninfo->encap));
+ printf("--vlan-encap %s", (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "! " : "");
+ printf("%4.4X ", ntohs(vlaninfo->encap));
}
}
diff --git a/extensions/libebt_vlan.t b/extensions/libebt_vlan.t
index 106374cd9cb80..81c795854fca0 100644
--- a/extensions/libebt_vlan.t
+++ b/extensions/libebt_vlan.t
@@ -1,13 +1,13 @@
:INPUT,FORWARD,OUTPUT
-p 802_1Q --vlan-id 42;=;OK
--p 802_1Q ! --vlan-id 42;=;OK
+-p 802_1Q --vlan-id ! 42;=;OK
-p 802_1Q --vlan-prio 1;=;OK
--p 802_1Q ! --vlan-prio 1;=;OK
+-p 802_1Q --vlan-prio ! 1;=;OK
-p 802_1Q --vlan-encap ip;-p 802_1Q --vlan-encap 0800 -j CONTINUE;OK
-p 802_1Q --vlan-encap 0800 ;=;OK
--p 802_1Q ! --vlan-encap 0800 ;=;OK
--p 802_1Q --vlan-encap IPv6 ! --vlan-id 1;-p 802_1Q ! --vlan-id 1 --vlan-encap 86DD -j CONTINUE;OK
--p 802_1Q ! --vlan-id 1 --vlan-encap 86DD;=;OK
+-p 802_1Q --vlan-encap ! 0800 ;=;OK
+-p 802_1Q --vlan-encap IPv6 ! --vlan-id 1;-p 802_1Q --vlan-id ! 1 --vlan-encap 86DD -j CONTINUE;OK
+-p 802_1Q --vlan-id ! 1 --vlan-encap 86DD;=;OK
--vlan-encap ip;=;FAIL
--vlan-id 2;=;FAIL
--vlan-prio 1;=;FAIL
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 43b3e3e9649b8..2b79ca951cd92 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -344,7 +344,7 @@ static void nft_rule_to_ebtables_command_state(const struct nftnl_rule *r,
static void print_iface(const char *option, const char *name, bool invert)
{
if (*name)
- printf("%s%s %s ", invert ? "! " : "", option, name);
+ printf("%s%s %s ", option, invert ? " !" : "", name);
}
static void nft_bridge_print_table_header(const char *tablename)
@@ -389,9 +389,9 @@ static void print_mac(char option, const unsigned char *mac,
const unsigned char *mask,
bool invert)
{
+ printf("-%c ", option);
if (invert)
printf("! ");
- printf("-%c ", option);
ebt_print_mac_and_mask(mac, mask);
printf(" ");
}
@@ -406,9 +406,9 @@ static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
if (bitmask & EBT_NOPROTO)
return;
+ printf("-p ");
if (invert)
printf("! ");
- printf("-p ");
if (bitmask & EBT_802_3) {
printf("length ");
--
2.21.0

View File

@ -0,0 +1,42 @@
From a4412aa91dff87ab27e4ad6e27f2a6c03ed0b5fb Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 22 Nov 2018 20:50:13 +0100
Subject: [PATCH] arptables: Support --set-counters option
Relevant code for this was already present (short option '-c'), just the
long option definition was missing.
While being at it, add '-c' to help text.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit b0466ae6fbc0a93b69591171c54aa79063e23f3d)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/xtables-arp.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index 18cdced627c55..85bcc841b21f5 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -144,6 +144,7 @@ static struct option original_opts[] = {
{ "help", 2, 0, 'h' },
{ "line-numbers", 0, 0, '0' },
{ "modprobe", 1, 0, 'M' },
+ { "set-counters", 1, 0, 'c' },
{ 0 }
};
@@ -481,7 +482,7 @@ exit_printhelp(void)
" --line-numbers print line numbers when listing\n"
" --exact -x expand numbers (display exact values)\n"
" --modprobe=<command> try to insert modules using this command\n"
-" --set-counters PKTS BYTES set the counter during insert/append\n"
+" --set-counters -c PKTS BYTES set the counter during insert/append\n"
"[!] --version -V print package version.\n");
printf(" opcode strings: \n");
for (i = 0; i < NUMOPCODES; i++)
--
2.21.0

View File

@ -0,0 +1,136 @@
From 715e2fa36e08f0ee800347d8abea039e5347b1dc Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Tue, 5 Feb 2019 17:01:42 +0100
Subject: [PATCH] xshared: Explicitly pass target to command_jump()
The use of global 'optarg' variable inside that function is a mess, but
most importantly it limits its applicability to input parsers. Fix this
by having it take the option argument as a parameter.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 932d5c3fb94acc499c8a6264e354ab1e33316b72)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/ip6tables.c | 2 +-
iptables/iptables.c | 2 +-
iptables/xshared.c | 4 ++--
iptables/xshared.h | 2 +-
iptables/xtables-arp.c | 2 +-
iptables/xtables-eb-translate.c | 2 +-
iptables/xtables-eb.c | 2 +-
iptables/xtables.c | 2 +-
8 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
index fe089de4c85d7..050afa9a36458 100644
--- a/iptables/ip6tables.c
+++ b/iptables/ip6tables.c
@@ -1441,7 +1441,7 @@ int do_command6(int argc, char *argv[], char **table,
case 'j':
set_option(&cs.options, OPT_JUMP, &cs.fw6.ipv6.invflags,
cs.invert);
- command_jump(&cs);
+ command_jump(&cs, optarg);
break;
diff --git a/iptables/iptables.c b/iptables/iptables.c
index f8041f56ce70d..38c4bfe8ecf5c 100644
--- a/iptables/iptables.c
+++ b/iptables/iptables.c
@@ -1421,7 +1421,7 @@ int do_command4(int argc, char *argv[], char **table,
case 'j':
set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags,
cs.invert);
- command_jump(&cs);
+ command_jump(&cs, optarg);
break;
diff --git a/iptables/xshared.c b/iptables/xshared.c
index b16f5fa68e569..fb186fb1ac657 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -653,12 +653,12 @@ const char *xt_parse_target(const char *targetname)
return targetname;
}
-void command_jump(struct iptables_command_state *cs)
+void command_jump(struct iptables_command_state *cs, const char *jumpto)
{
struct option *opts = xt_params->opts;
size_t size;
- cs->jumpto = xt_parse_target(optarg);
+ cs->jumpto = xt_parse_target(jumpto);
/* TRY_LOAD (may be chain name) */
cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
diff --git a/iptables/xshared.h b/iptables/xshared.h
index db499f29236ed..fd1f96bad1b98 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -176,6 +176,6 @@ void print_ifaces(const char *iniface, const char *outiface, uint8_t invflags,
void command_match(struct iptables_command_state *cs);
const char *xt_parse_target(const char *targetname);
-void command_jump(struct iptables_command_state *cs);
+void command_jump(struct iptables_command_state *cs, const char *jumpto);
#endif /* IPTABLES_XSHARED_H */
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index 85bcc841b21f5..4a873b15c6833 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -1161,7 +1161,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
case 'j':
set_option(&options, OPT_JUMP, &cs.arp.arp.invflags,
invert);
- command_jump(&cs);
+ command_jump(&cs, optarg);
break;
case 'i':
diff --git a/iptables/xtables-eb-translate.c b/iptables/xtables-eb-translate.c
index 0fe14d2d0db32..96b2730fa97ed 100644
--- a/iptables/xtables-eb-translate.c
+++ b/iptables/xtables-eb-translate.c
@@ -390,7 +390,7 @@ print_zero:
break;
} else if (c == 'j') {
ebt_check_option2(&flags, OPT_JUMP);
- command_jump(&cs);
+ command_jump(&cs, optarg);
break;
} else if (c == 's') {
ebt_check_option2(&flags, OPT_SOURCE);
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 55cb0fe204748..21344843a365a 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -1022,7 +1022,7 @@ print_zero:
} else if (c == 'j') {
ebt_check_option2(&flags, OPT_JUMP);
if (strcmp(optarg, "CONTINUE") != 0) {
- command_jump(&cs);
+ command_jump(&cs, optarg);
}
break;
} else if (c == 's') {
diff --git a/iptables/xtables.c b/iptables/xtables.c
index eaa9fedeb03bb..1d777554076d7 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -820,7 +820,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
case 'j':
set_option(&cs->options, OPT_JUMP, &cs->fw.ip.invflags,
cs->invert);
- command_jump(cs);
+ command_jump(cs, optarg);
break;
--
2.21.0

View File

@ -0,0 +1,72 @@
From e78321d1a719a5dc1b340292fc1971d4daf7e472 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 7 Feb 2019 22:08:53 +0100
Subject: [PATCH] nft: Don't assume NFTNL_RULE_USERDATA holds a comment
If this rule attribute is present but does not contain a comment,
get_comment() returns NULL which is then fed into strncpy() causing a
crash.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit d1df0a36b0486c780211cfa574301132bf55f194)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-shared.c | 39 ++++++++++++++++++++++-----------------
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index ce40787f92f7d..fc484b49e2318 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -639,25 +639,30 @@ void nft_rule_to_iptables_command_state(const struct nftnl_rule *r,
if (nftnl_rule_is_set(r, NFTNL_RULE_USERDATA)) {
const void *data;
uint32_t len, size;
- struct xtables_match *match;
- struct xt_entry_match *m;
+ const char *comment;
data = nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len);
- match = xtables_find_match("comment", XTF_TRY_LOAD,
- &cs->matches);
- if (match == NULL)
- return;
-
- size = XT_ALIGN(sizeof(struct xt_entry_match)) + match->size;
- m = xtables_calloc(1, size);
-
- strncpy((char *)m->data, get_comment(data, len),
- match->size - 1);
- m->u.match_size = size;
- m->u.user.revision = 0;
- strcpy(m->u.user.name, match->name);
-
- match->m = m;
+ comment = get_comment(data, len);
+ if (comment) {
+ struct xtables_match *match;
+ struct xt_entry_match *m;
+
+ match = xtables_find_match("comment", XTF_TRY_LOAD,
+ &cs->matches);
+ if (match == NULL)
+ return;
+
+ size = XT_ALIGN(sizeof(struct xt_entry_match))
+ + match->size;
+ m = xtables_calloc(1, size);
+
+ strncpy((char *)m->data, comment, match->size - 1);
+ m->u.match_size = size;
+ m->u.user.revision = 0;
+ strcpy(m->u.user.name, match->name);
+
+ match->m = m;
+ }
}
if (cs->target != NULL) {
--
2.21.0

View File

@ -0,0 +1,41 @@
From d418438f72d340866be241ca3867cf3ce3e04cf8 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 7 Feb 2019 22:08:54 +0100
Subject: [PATCH] nft: Introduce UDATA_TYPE_EBTABLES_POLICY
This will be used later to identify ebtables user-defined chain policy
rules.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit b06cc4e0f67f4beba7560fc329d20f108c87b5fb)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/iptables/nft.c b/iptables/nft.c
index 2fa973cf03975..6129afdbad281 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1115,6 +1115,7 @@ int add_counters(struct nftnl_rule *r, uint64_t packets, uint64_t bytes)
enum udata_type {
UDATA_TYPE_COMMENT,
+ UDATA_TYPE_EBTABLES_POLICY,
__UDATA_TYPE_MAX,
};
#define UDATA_TYPE_MAX (__UDATA_TYPE_MAX - 1)
@@ -1131,6 +1132,8 @@ static int parse_udata_cb(const struct nftnl_udata *attr, void *data)
if (value[len - 1] != '\0')
return -1;
break;
+ case UDATA_TYPE_EBTABLES_POLICY:
+ break;
default:
return 0;
}
--
2.21.0

View File

@ -0,0 +1,506 @@
From bbbebb7449605e62a0901b8d81ea2ed45044088b Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 7 Feb 2019 22:08:55 +0100
Subject: [PATCH] ebtables-nft: Support user-defined chain policies
Legacy ebtables supports policies for user-defined chains - and what's
worse, they default to ACCEPT unlike anywhere else. So lack of support
for this braindead feature in ebtables-nft is actually a change of
behaviour which very likely affects all ebtables users out there.
The solution implemented here uses an implicit (and transparent) last
rule in all user-defined ebtables-nft chains with policy other than
RETURN. This rule is identified by an nft comment
"XTABLES_EB_INTERNAL_POLICY_RULE" (since commit ccf154d7420c0 ("xtables:
Don't use native nftables comments") nft comments are not used
otherwise).
To minimize interference with existing code, this policy rule is removed
from chains during cache population and the policy is saved in
NFTNL_CHAIN_POLICY attribute. When committing changes to the kernel,
nft_commit() traverses through the list of chains and (re-)creates
policy rules if required.
In ebtables-nft-restore, table flushes are problematic. To avoid weird
kernel error responses, introduce a custom 'table_flush' callback which
removes any pending policy rule add/remove jobs prior to creating the
NFT_COMPAT_TABLE_FLUSH one.
I've hidden all this mess behind checks for h->family, so hopefully
impact on {ip,ip6,arp}tables-nft should be negligible.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit aff1162b3e4b7ef805425a40306044c7d7dddc67)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-bridge.c | 2 +-
iptables/nft.c | 228 +++++++++++++++++-
iptables/nft.h | 4 +
.../ebtables/0002-ebtables-save-restore_0 | 7 +
iptables/xtables-eb.c | 20 +-
iptables/xtables-restore.c | 23 +-
6 files changed, 265 insertions(+), 19 deletions(-)
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 2b79ca951cd92..a51792ef03ae1 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -358,7 +358,7 @@ static void nft_bridge_print_header(unsigned int format, const char *chain,
bool basechain, uint32_t refs, uint32_t entries)
{
printf("Bridge chain: %s, entries: %u, policy: %s\n",
- chain, entries, basechain ? pol : "RETURN");
+ chain, entries, pol ?: "RETURN");
}
static void print_matches_and_watchers(const struct iptables_command_state *cs,
diff --git a/iptables/nft.c b/iptables/nft.c
index 6129afdbad281..4fdc789d99928 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -55,6 +55,7 @@
#include "nft.h"
#include "xshared.h" /* proto_to_name */
#include "nft-shared.h"
+#include "nft-bridge.h" /* EBT_NOPROTO */
#include "xtables-config-parser.h"
static void *nft_fn;
@@ -1325,6 +1326,87 @@ retry:
return ret;
}
+static bool nft_rule_is_policy_rule(struct nftnl_rule *r)
+{
+ const struct nftnl_udata *tb[UDATA_TYPE_MAX + 1] = {};
+ const void *data;
+ uint32_t len;
+
+ if (!nftnl_rule_is_set(r, NFTNL_RULE_USERDATA))
+ return false;
+
+ data = nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len);
+ if (nftnl_udata_parse(data, len, parse_udata_cb, tb) < 0)
+ return NULL;
+
+ if (!tb[UDATA_TYPE_EBTABLES_POLICY] ||
+ nftnl_udata_get_u32(tb[UDATA_TYPE_EBTABLES_POLICY]) != 1)
+ return false;
+
+ return true;
+}
+
+static struct nftnl_rule *nft_chain_last_rule(struct nftnl_chain *c)
+{
+ struct nftnl_rule *r = NULL, *last;
+ struct nftnl_rule_iter *iter;
+
+ iter = nftnl_rule_iter_create(c);
+ if (!iter)
+ return NULL;
+
+ do {
+ last = r;
+ r = nftnl_rule_iter_next(iter);
+ } while (r);
+ nftnl_rule_iter_destroy(iter);
+
+ return last;
+}
+
+static void nft_bridge_chain_postprocess(struct nft_handle *h,
+ struct nftnl_chain *c)
+{
+ struct nftnl_rule *last = nft_chain_last_rule(c);
+ struct nftnl_expr_iter *iter;
+ struct nftnl_expr *expr;
+ int verdict;
+
+ if (!last || !nft_rule_is_policy_rule(last))
+ return;
+
+ iter = nftnl_expr_iter_create(last);
+ if (!iter)
+ return;
+
+ expr = nftnl_expr_iter_next(iter);
+ if (!expr ||
+ strcmp("counter", nftnl_expr_get_str(expr, NFTNL_EXPR_NAME)))
+ goto out_iter;
+
+ expr = nftnl_expr_iter_next(iter);
+ if (!expr ||
+ strcmp("immediate", nftnl_expr_get_str(expr, NFTNL_EXPR_NAME)) ||
+ !nftnl_expr_is_set(expr, NFTNL_EXPR_IMM_VERDICT))
+ goto out_iter;
+
+ verdict = nftnl_expr_get_u32(expr, NFTNL_EXPR_IMM_VERDICT);
+ switch (verdict) {
+ case NF_ACCEPT:
+ case NF_DROP:
+ break;
+ default:
+ goto out_iter;
+ }
+
+ nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, verdict);
+ if (batch_rule_add(h, NFT_COMPAT_RULE_DELETE, last) < 0)
+ fprintf(stderr, "Failed to delete old policy rule\n");
+ nftnl_chain_rule_del(last);
+out_iter:
+ nftnl_expr_iter_destroy(iter);
+}
+
static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nftnl_chain *c = data;
@@ -1378,6 +1460,10 @@ retry:
}
nftnl_rule_free(rule);
+
+ if (h->family == NFPROTO_BRIDGE)
+ nft_bridge_chain_postprocess(h, c);
+
return 0;
}
@@ -1443,6 +1529,15 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list)
if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY))
pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
policy = policy_name[pol];
+ } else if (h->family == NFPROTO_BRIDGE) {
+ if (nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY)) {
+ uint32_t pol;
+
+ pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
+ policy = policy_name[pol];
+ } else {
+ policy = "RETURN";
+ }
}
if (ops->save_chain)
@@ -1637,6 +1732,8 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain);
+ if (h->family == NFPROTO_BRIDGE)
+ nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT);
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
@@ -2278,7 +2375,6 @@ static void __nft_print_header(struct nft_handle *h,
struct nftnl_chain *c, unsigned int format)
{
const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
bool basechain = !!nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM);
uint32_t refs = nftnl_chain_get_u32(c, NFTNL_CHAIN_USE);
uint32_t entries = nft_rule_count(h, c);
@@ -2286,8 +2382,12 @@ static void __nft_print_header(struct nft_handle *h,
.pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
.bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES),
};
+ const char *pname = NULL;
- ops->print_header(format, chain_name, policy_name[policy],
+ if (nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY))
+ pname = policy_name[nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY)];
+
+ ops->print_header(format, chain_name, pname,
&ctrs, basechain, refs - entries, entries);
}
@@ -2671,8 +2771,111 @@ static int nft_action(struct nft_handle *h, int action)
return ret == 0 ? 1 : 0;
}
+static int ebt_add_policy_rule(struct nftnl_chain *c, void *data)
+{
+ uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
+ struct iptables_command_state cs = {
+ .eb.bitmask = EBT_NOPROTO,
+ };
+ struct nftnl_udata_buf *udata;
+ struct nft_handle *h = data;
+ struct nftnl_rule *r;
+ const char *pname;
+
+ if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM))
+ return 0; /* ignore base chains */
+
+ if (!nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY))
+ return 0;
+
+ nftnl_chain_unset(c, NFTNL_CHAIN_POLICY);
+
+ switch (policy) {
+ case NFT_RETURN:
+ return 0; /* return policy is default for nft chains */
+ case NF_ACCEPT:
+ pname = "ACCEPT";
+ break;
+ case NF_DROP:
+ pname = "DROP";
+ break;
+ default:
+ return -1;
+ }
+
+ command_jump(&cs, pname);
+
+ r = nft_rule_new(h, nftnl_chain_get_str(c, NFTNL_CHAIN_NAME),
+ nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), &cs);
+ if (!r)
+ return -1;
+
+ udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
+ if (!udata)
+ return -1;
+
+ if (!nftnl_udata_put_u32(udata, UDATA_TYPE_EBTABLES_POLICY, 1))
+ return -1;
+
+ nftnl_rule_set_data(r, NFTNL_RULE_USERDATA,
+ nftnl_udata_buf_data(udata),
+ nftnl_udata_buf_len(udata));
+ nftnl_udata_buf_free(udata);
+
+ if (batch_rule_add(h, NFT_COMPAT_RULE_APPEND, r) < 0) {
+ nftnl_rule_free(r);
+ return -1;
+ }
+
+ return 0;
+}
+
+int ebt_set_user_chain_policy(struct nft_handle *h, const char *table,
+ const char *chain, const char *policy)
+{
+ struct nftnl_chain *c = nft_chain_find(h, table, chain);
+ int pval;
+
+ if (!c)
+ return 0;
+
+ if (!strcmp(policy, "DROP"))
+ pval = NF_DROP;
+ else if (!strcmp(policy, "ACCEPT"))
+ pval = NF_ACCEPT;
+ else if (!strcmp(policy, "RETURN"))
+ pval = NFT_RETURN;
+ else
+ return 0;
+
+ nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, pval);
+ return 1;
+}
+
+static void nft_bridge_commit_prepare(struct nft_handle *h)
+{
+ const struct builtin_table *t;
+ struct nftnl_chain_list *list;
+ int i;
+
+ for (i = 0; i < NFT_TABLE_MAX; i++) {
+ t = &h->tables[i];
+
+ if (!t->name)
+ continue;
+
+ list = h->table[t->type].chain_cache;
+ if (!list)
+ continue;
+
+ nftnl_chain_list_foreach(list, ebt_add_policy_rule, h);
+ }
+}
+
int nft_commit(struct nft_handle *h)
{
+ if (h->family == NFPROTO_BRIDGE)
+ nft_bridge_commit_prepare(h);
return nft_action(h, NFT_COMPAT_COMMIT);
}
@@ -2681,6 +2884,27 @@ int nft_abort(struct nft_handle *h)
return nft_action(h, NFT_COMPAT_ABORT);
}
+int nft_abort_policy_rule(struct nft_handle *h, const char *table)
+{
+ struct obj_update *n, *tmp;
+
+ list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
+ if (n->type != NFT_COMPAT_RULE_APPEND &&
+ n->type != NFT_COMPAT_RULE_DELETE)
+ continue;
+
+ if (strcmp(table,
+ nftnl_rule_get_str(n->rule, NFTNL_RULE_TABLE)))
+ continue;
+
+ if (!nft_rule_is_policy_rule(n->rule))
+ continue;
+
+ batch_obj_del(h, n);
+ }
+ return 0;
+}
+
int nft_compatible_revision(const char *name, uint8_t rev, int opt)
{
struct mnl_socket *nl;
diff --git a/iptables/nft.h b/iptables/nft.h
index 0726923a63dd4..56dc207608855 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -137,6 +137,7 @@ uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag);
*/
int nft_commit(struct nft_handle *h);
int nft_abort(struct nft_handle *h);
+int nft_abort_policy_rule(struct nft_handle *h, const char *table);
/*
* revision compatibility.
@@ -203,4 +204,7 @@ void nft_rule_to_arpt_entry(struct nftnl_rule *r, struct arpt_entry *fw);
bool nft_is_table_compatible(struct nft_handle *h, const char *name);
+int ebt_set_user_chain_policy(struct nft_handle *h, const char *table,
+ const char *chain, const char *policy);
+
#endif
diff --git a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0
index b23c1ee18c8ae..080ba49a4974d 100755
--- a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0
+++ b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0
@@ -50,6 +50,9 @@ $XT_MULTI ebtables -A foo --pkttype-type multicast --limit 100 -j ACCEPT
$XT_MULTI ebtables -A FORWARD -j foo
+$XT_MULTI ebtables -N bar
+$XT_MULTI ebtables -P bar RETURN
+
$XT_MULTI ebtables -t nat -A PREROUTING --redirect-target ACCEPT
#$XT_MULTI ebtables -t nat -A PREROUTING --to-src fe:ed:ba:be:00:01
@@ -59,6 +62,8 @@ $XT_MULTI ebtables -t nat -P OUTPUT DROP
$XT_MULTI ebtables -t nat -A POSTROUTING -j ACCEPT
#$XT_MULTI ebtables -t nat -A POSTROUTING --to-dst fe:ed:ba:be:00:01 --dnat-target ACCEPT
+$XT_MULTI ebtables -t nat -N nat_foo -P DROP
+
# compare against stored ebtables dump
DUMP='*filter
@@ -66,6 +71,7 @@ DUMP='*filter
:FORWARD DROP
:OUTPUT ACCEPT
:foo ACCEPT
+:bar RETURN
-A INPUT -p IPv4 -i lo -j ACCEPT
-A FORWARD -j foo
-A OUTPUT -s Broadcast -j DROP
@@ -98,6 +104,7 @@ DUMP='*filter
:PREROUTING ACCEPT
:OUTPUT DROP
:POSTROUTING ACCEPT
+:nat_foo DROP
-A PREROUTING -j redirect
-A OUTPUT -j ACCEPT
-A POSTROUTING -j ACCEPT
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 21344843a365a..d0f0026e9c538 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -811,7 +811,6 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table,
case 'E': /* Rename chain */
case 'X': /* Delete chain */
/* We allow -N chainname -P policy */
- /* XXX: Not in ebtables-compat */
if (command == 'N' && c == 'P') {
command = c;
optind--; /* No table specified */
@@ -1236,17 +1235,16 @@ print_zero:
if (command == 'P') {
if (selected_chain < 0) {
- xtables_error(PARAMETER_PROBLEM,
- "Policy %s not allowed for user defined chains",
- policy);
- }
- if (strcmp(policy, "RETURN") == 0) {
- xtables_error(PARAMETER_PROBLEM,
- "Policy RETURN only allowed for user defined chains");
+ ret = ebt_set_user_chain_policy(h, *table, chain, policy);
+ } else {
+ if (strcmp(policy, "RETURN") == 0) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Policy RETURN only allowed for user defined chains");
+ }
+ ret = nft_chain_set(h, *table, chain, policy, NULL);
+ if (ret < 0)
+ xtables_error(PARAMETER_PROBLEM, "Wrong policy");
}
- ret = nft_chain_set(h, *table, chain, policy, NULL);
- if (ret < 0)
- xtables_error(PARAMETER_PROBLEM, "Wrong policy");
} else if (command == 'L') {
ret = list_rules(h, chain, *table, rule_nr,
0,
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 4e00ed86be06d..6e6daffc9a1df 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -226,14 +226,20 @@ void xtables_restore_parse(struct nft_handle *h,
curtable->name, chain);
} else if (cb->chain_user_add &&
cb->chain_user_add(h, chain,
- curtable->name) < 0) {
- if (errno == EEXIST)
- continue;
-
+ curtable->name) < 0 &&
+ errno != EEXIST) {
xtables_error(PARAMETER_PROBLEM,
"cannot create chain "
"'%s' (%s)\n", chain,
strerror(errno));
+ } else if (h->family == NFPROTO_BRIDGE &&
+ !ebt_set_user_chain_policy(h, curtable->name,
+ chain, policy)) {
+ xtables_error(OTHER_PROBLEM,
+ "Can't set policy `%s'"
+ " on `%s' line %u: %s\n",
+ policy, chain, line,
+ ops->strerror(errno));
}
ret = 1;
} else if (in_table) {
@@ -462,11 +468,18 @@ int xtables_ip6_restore_main(int argc, char *argv[])
argc, argv);
}
+static int ebt_table_flush(struct nft_handle *h, const char *table)
+{
+ /* drop any pending policy rule add/removal jobs */
+ nft_abort_policy_rule(h, table);
+ return nft_table_flush(h, table);
+}
+
struct nft_xt_restore_cb ebt_restore_cb = {
.chain_list = get_chain_list,
.commit = nft_commit,
.table_new = nft_table_new,
- .table_flush = nft_table_flush,
+ .table_flush = ebt_table_flush,
.chain_user_flush = nft_chain_user_flush,
.do_command = do_commandeb,
.chain_set = nft_chain_set,
--
2.21.0

View File

@ -0,0 +1,30 @@
From 8b69d66b21f3699ee64c572bfba5df033ce768e0 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Mon, 3 Dec 2018 14:52:28 +0100
Subject: [PATCH] extensions: libipt_realm: Document allowed realm values
Older versions of iptables allowed for negative realm values by accident
(they would be cast to unsigned). While this was clearly a bug, document
the fixed behaviour.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 290d76b443bf24999d9caacb3fdd027d6e7112a1)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libipt_realm.man | 2 ++
1 file changed, 2 insertions(+)
diff --git a/extensions/libipt_realm.man b/extensions/libipt_realm.man
index a40b1adc72ba2..72dff9b2e4212 100644
--- a/extensions/libipt_realm.man
+++ b/extensions/libipt_realm.man
@@ -5,3 +5,5 @@ setups involving dynamic routing protocols like BGP.
Matches a given realm number (and optionally mask). If not a number, value
can be a named realm from /etc/iproute2/rt_realms (mask can not be used in
that case).
+Both value and mask are four byte unsigned integers and may be specified in
+decimal, hex (by prefixing with "0x") or octal (if a leading zero is given).
--
2.21.0

View File

@ -0,0 +1,51 @@
From 39808343b03078f992bc5e831ccdd843312f0714 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Tue, 18 Dec 2018 12:16:30 +0100
Subject: [PATCH] extensions: TRACE: Point at xtables-monitor in documentation
With iptables-nft, logging of trace events is different from legacy.
Explain why and hint at how to receive events in this case.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 9ac39888722ee9c7e97d9b8cb9eb4f33b582130a)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libxt_TRACE.man | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/extensions/libxt_TRACE.man b/extensions/libxt_TRACE.man
index 8d590a52e26f8..5187a8d22802f 100644
--- a/extensions/libxt_TRACE.man
+++ b/extensions/libxt_TRACE.man
@@ -1,13 +1,20 @@
This target marks packets so that the kernel will log every rule which match
-the packets as those traverse the tables, chains, rules.
+the packets as those traverse the tables, chains, rules. It can only be used in
+the
+.BR raw
+table.
.PP
-A logging backend, such as ip(6)t_LOG or nfnetlink_log, must be loaded for this
-to be visible.
+With iptables-legacy, a logging backend, such as ip(6)t_LOG or nfnetlink_log,
+must be loaded for this to be visible.
The packets are logged with the string prefix:
"TRACE: tablename:chainname:type:rulenum " where type can be "rule" for
plain rule, "return" for implicit rule at the end of a user defined chain
and "policy" for the policy of the built in chains.
-.br
-It can only be used in the
-.BR raw
-table.
+.PP
+With iptables-nft, the target is translated into nftables'
+.B "meta nftrace"
+expression. Hence the kernel sends trace events via netlink to userspace where
+they may be displayed using
+.B "xtables-monitor --trace"
+command. For details, refer to
+.BR xtables-monitor (8).
--
2.21.0

View File

@ -0,0 +1,33 @@
From 4a6f89b263a62f078e73cbc01d09330a217a23c7 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Sat, 15 Dec 2018 19:25:04 +0100
Subject: [PATCH] xtables: Catch errors when zeroing rule rounters
Covscan complained about call to batch_rule_add() not being checked.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 4c54c892443c20a1d0e1212d541da0e81647058a)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 4fdc789d99928..2d527358cc7f2 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -3218,7 +3218,9 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data)
* rule based on its handle only.
*/
nftnl_rule_unset(r, NFTNL_RULE_POSITION);
- batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r);
+ ret = batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r);
+ if (ret)
+ return -1;
}
r = nftnl_rule_iter_next(iter);
}
--
2.21.0

View File

@ -0,0 +1,37 @@
From a63cf723111d323afab642e6f6b12a5da660fd5b Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 7 Feb 2019 22:13:31 +0100
Subject: [PATCH] xtables-save: Fix table not found error message
First of all, this error message should not appear on stdout, otherwise
it may end in dump files. Next, with completely empty ruleset, even
valid table names cause errors. To avoid this, continue operation if the
not found table is a builtin one.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 2478b6cbb8112f940cec61ec1e62a598472d33d0)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/xtables-save.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index 414a864b6196b..87ebb913f33b7 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -105,8 +105,9 @@ do_output(struct nft_handle *h, const char *tablename, bool counters)
return !!ret;
}
- if (!nft_table_find(h, tablename)) {
- printf("Table `%s' does not exist\n", tablename);
+ if (!nft_table_find(h, tablename) &&
+ !nft_table_builtin_find(h, tablename)) {
+ fprintf(stderr, "Table `%s' does not exist\n", tablename);
return 1;
}
--
2.21.0

View File

@ -0,0 +1,49 @@
From dc38548e6f745bcfb141324b36307dbfa941eabd Mon Sep 17 00:00:00 2001
From: Florian Westphal <fw@strlen.de>
Date: Fri, 22 Feb 2019 13:26:05 +0100
Subject: [PATCH] arptables-nft: fix decoding of hlen on bigendian platforms
The existing test fail with:
extensions/libarpt_standard.t: ERROR: line 2 (cannot find: arptables -I INPUT -s 192.168.0.1)
... because hlen is 0 instead of expected "6".
The rule is correct, i.e. this is a decode/display bug: arp_hlen is
specified as 'unsigned short' instead of uint8_t.
On LSB systems, this doesn't matter but on MSB the value then is '0x600'
instead of '0x006' which becomes 0 when assignment to the u8 header field.
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Phil Sutter <phil@nwl.cc>
(cherry picked from commit d68672a641439b72bccfcb39d50f26fe3f915c19)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/nft-arp.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index 37b0985377bef..b436570291b7c 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -338,7 +338,8 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
struct iptables_command_state *cs = data;
struct arpt_entry *fw = &cs->arp;
struct in_addr addr;
- unsigned short int ar_hrd, ar_pro, ar_op, ar_hln;
+ uint16_t ar_hrd, ar_pro, ar_op;
+ uint8_t ar_hln;
bool inv;
switch (ctx->payload.offset) {
@@ -364,7 +365,7 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
fw->arp.invflags |= ARPT_INV_ARPOP;
break;
case offsetof(struct arphdr, ar_hln):
- get_cmp_data(e, &ar_hln, sizeof(ar_op), &inv);
+ get_cmp_data(e, &ar_hln, sizeof(ar_hln), &inv);
fw->arp.arhln = ar_hln;
fw->arp.arhln_mask = 0xff;
if (inv)
--
2.21.0

View File

@ -0,0 +1,32 @@
From a1e2de039a97f5ee8f5d7ebd34c82ff48c0fa345 Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Mon, 19 Nov 2018 14:09:20 +0100
Subject: [PATCH] extensions: libip6t_mh: fix bogus translation error
libip6t_mh.txlate: Fail
src: ip6tables-translate -A INPUT -p mh --mh-type 1 -j ACCEPT
exp: nft add rule ip6 filter INPUT meta l4proto 135 mh type 1 counter accept
res: nft add rule ip6 filter INPUT meta l4proto mobility-header mh type 1 counter accept
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 5839d7fe62ff667af7132fc7d589b386951f27b3)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libip6t_mh.txlate | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/extensions/libip6t_mh.txlate b/extensions/libip6t_mh.txlate
index ccc07c3d5ecb1..f5d638c09ca8a 100644
--- a/extensions/libip6t_mh.txlate
+++ b/extensions/libip6t_mh.txlate
@@ -1,5 +1,5 @@
ip6tables-translate -A INPUT -p mh --mh-type 1 -j ACCEPT
-nft add rule ip6 filter INPUT meta l4proto 135 mh type 1 counter accept
+nft add rule ip6 filter INPUT meta l4proto mobility-header mh type 1 counter accept
ip6tables-translate -A INPUT -p mh --mh-type 1:3 -j ACCEPT
-nft add rule ip6 filter INPUT meta l4proto 135 mh type 1-3 counter accept
+nft add rule ip6 filter INPUT meta l4proto mobility-header mh type 1-3 counter accept
--
2.21.0

View File

@ -0,0 +1,50 @@
From 8a192868ba7dd55a0465f07d8fb42d26dff566d3 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Wed, 13 Mar 2019 20:46:17 +0100
Subject: [PATCH] xtables-save: Point at existing man page in help text
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit 934479aa1f1576afba97b137a101a60d8534370c)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/xtables-save.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index 87ebb913f33b7..2cc5a7c7540be 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -187,7 +187,8 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
exit(0);
default:
fprintf(stderr,
- "Look at manual page `xtables-save.8' for more information.\n");
+ "Look at manual page `%s.8' for more information.\n",
+ prog_name);
exit(1);
}
}
@@ -333,7 +334,8 @@ int xtables_eb_save_main(int argc_, char *argv_[])
exit(0);
default:
fprintf(stderr,
- "Look at manual page `xtables-save.8' for more information.\n");
+ "Look at manual page `%s.8' for more information.\n",
+ prog_name);
exit(1);
}
}
@@ -380,7 +382,8 @@ int xtables_arp_save_main(int argc, char **argv)
exit(0);
default:
fprintf(stderr,
- "Look at manual page `xtables-save.8' for more information.\n");
+ "Look at manual page `%s.8' for more information.\n",
+ prog_name);
exit(1);
}
}
--
2.21.0

View File

@ -0,0 +1,86 @@
From 4c351ba82a79b2781fc580f3f5473da0e5a276b8 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Sat, 8 Jun 2019 19:34:13 +0200
Subject: [PATCH] xtables-restore: Fix program names in help texts
Avoid referring to wrong or even non-existent commands:
* When calling xtables_restore_main(), pass the actual program name
taken from argv[0].
* Use 'prog_name' in unknown parameter and help output instead of
'xtables-restore' which probably doesn't exist.
* While being at it, fix false whitespace in help text.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit ac531b4681d1a0309a738d7bc3408fc2270eaa03)
Conflicts:
iptables/xtables-restore.c
-> missing commit 093cec72e7f77 ("src: replace IPTABLES_VERSION by PACKAGE_VERSION")
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
iptables/xtables-restore.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 6e6daffc9a1df..7c2759a3c5932 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -7,6 +7,7 @@
#include <getopt.h>
#include <errno.h>
+#include <libgen.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
@@ -51,7 +52,7 @@ static void print_usage(const char *name, const char *version)
" [ --help ]\n"
" [ --noflush ]\n"
" [ --table=<TABLE> ]\n"
- " [ --modprobe=<command> ]\n"
+ " [ --modprobe=<command> ]\n"
" [ --ipv4 ]\n"
" [ --ipv6 ]\n", name);
}
@@ -376,8 +377,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
p.testing = 1;
break;
case 'h':
- print_usage("xtables-restore",
- IPTABLES_VERSION);
+ print_usage(prog_name, IPTABLES_VERSION);
exit(0);
case 'n':
noflush = 1;
@@ -402,7 +402,8 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
break;
default:
fprintf(stderr,
- "Try `xtables-restore -h' for more information.\n");
+ "Try `%s -h' for more information.\n",
+ prog_name);
exit(1);
}
}
@@ -458,13 +459,13 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
int xtables_ip4_restore_main(int argc, char *argv[])
{
- return xtables_restore_main(NFPROTO_IPV4, "iptables-restore",
+ return xtables_restore_main(NFPROTO_IPV4, basename(*argv),
argc, argv);
}
int xtables_ip6_restore_main(int argc, char *argv[])
{
- return xtables_restore_main(NFPROTO_IPV6, "ip6tables-restore",
+ return xtables_restore_main(NFPROTO_IPV6, basename(*argv),
argc, argv);
}
--
2.21.0

View File

@ -0,0 +1,37 @@
From 31695c75575f3998ac0c5d466d0b85276289a730 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 21 Feb 2019 15:38:47 +0100
Subject: [PATCH] extensions: AUDIT: Document ineffective --type option
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
(cherry picked from commit dffb5ec2a8c7f91351e2a1029a757cb1f41f2d02)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
extensions/libxt_AUDIT.man | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/extensions/libxt_AUDIT.man b/extensions/libxt_AUDIT.man
index cd796967c431a..4f5562e8ca425 100644
--- a/extensions/libxt_AUDIT.man
+++ b/extensions/libxt_AUDIT.man
@@ -3,12 +3,14 @@ It can be used to record accepted, dropped, and rejected packets. See
auditd(8) for additional details.
.TP
\fB\-\-type\fP {\fBaccept\fP|\fBdrop\fP|\fBreject\fP}
-Set type of audit record.
+Set type of audit record. Starting with linux-4.12, this option has no effect
+on generated audit messages anymore. It is still accepted by iptables for
+compatibility reasons, but ignored.
.PP
Example:
.IP
iptables \-N AUDIT_DROP
.IP
-iptables \-A AUDIT_DROP \-j AUDIT \-\-type drop
+iptables \-A AUDIT_DROP \-j AUDIT
.IP
iptables \-A AUDIT_DROP \-j DROP
--
2.21.0

View File

@ -0,0 +1,140 @@
From b3d9e7d73221e1f7efe9bd7052e85163e5de65aa Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Wed, 16 Jan 2019 22:47:59 +0100
Subject: [PATCH] utils: Add a manpage for nfbpf_compile
Content is rather sparse, but still better than no manpage at all.
Cc: Willem de Bruijn <willemb@google.com>
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 032dc4a18ab86173847b6016baf0819ccd7641c5)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
configure.ac | 3 +-
utils/.gitignore | 1 +
utils/Makefile.am | 3 +-
utils/nfbpf_compile.8.in | 70 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 75 insertions(+), 2 deletions(-)
create mode 100644 utils/nfbpf_compile.8.in
diff --git a/configure.ac b/configure.ac
index 448ec918fd89b..e6c9832fa43ba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -252,7 +252,8 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
libxtables/Makefile utils/Makefile
include/xtables-version.h include/iptables/internal.h
iptables/xtables-monitor.8
- utils/nfnl_osf.8])
+ utils/nfnl_osf.8
+ utils/nfbpf_compile.8])
AC_OUTPUT
diff --git a/utils/.gitignore b/utils/.gitignore
index 7c6afbf4e6a52..6300812b1701b 100644
--- a/utils/.gitignore
+++ b/utils/.gitignore
@@ -1,3 +1,4 @@
/nfnl_osf
/nfnl_osf.8
/nfbpf_compile
+/nfbpf_compile.8
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 80029e303ff3b..d09a69749b85f 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -17,6 +17,7 @@ nfnl_osf_LDADD = ${libnfnetlink_LIBS}
endif
if ENABLE_BPFC
+man_MANS += nfbpf_compile.8
sbin_PROGRAMS += nfbpf_compile
nfbpf_compile_LDADD = -lpcap
endif
@@ -26,4 +27,4 @@ sbin_PROGRAMS += nfsynproxy
nfsynproxy_LDADD = -lpcap
endif
-CLEANFILES = nfnl_osf.8
+CLEANFILES = nfnl_osf.8 nfbpf_compile.8
diff --git a/utils/nfbpf_compile.8.in b/utils/nfbpf_compile.8.in
new file mode 100644
index 0000000000000..d02979a5143ef
--- /dev/null
+++ b/utils/nfbpf_compile.8.in
@@ -0,0 +1,70 @@
+.TH NFBPF_COMPILE 8 "" "@PACKAGE_STRING@" "@PACKAGE_STRING@"
+
+.SH NAME
+nfbpf_compile \- generate bytecode for use with xt_bpf
+.SH SYNOPSIS
+
+.ad l
+.in +8
+.ti -8
+.B nfbpf_compile
+[
+.I LLTYPE
+]
+.I PROGRAM
+
+.ti -8
+.I LLTYPE
+:= {
+.BR EN10MB " | " RAW " | " SLIP " | "
+.I ...
+}
+
+.SH DESCRIPTION
+The
+.B nfbpf_compile
+utility aids in generating BPF byte code suitable for passing to
+the iptables
+.B bpf
+match.
+
+.SH OPTIONS
+
+.TP
+.I LLTYPE
+Link-layer header type to operate on. This is a name as defined in
+.RB < pcap/dlt.h >
+but with the leading
+.B DLT_
+prefix stripped. For use with iptables,
+.B RAW
+should be the right choice (it's also the default if not specified).
+
+.TP
+.I PROGRAM
+The BPF expression to compile, see
+.BR pcap-filter (7)
+for a description of the language.
+
+.SH EXIT STATUS
+The program returns 0 on success, 1 otherwise.
+
+.SH EXAMPLE
+Match incoming TCP packets with size bigger than 100 bytes:
+.P
+.in +8
+.EE
+bpf=$(nfbpf_compile 'tcp and greater 100')
+.br
+iptables -A INPUT -m bpf --bytecode "$bpf" -j ACCEPT
+.RE
+.P
+The description of
+.B bpf
+match in
+.BR iptables-extensions (8)
+lists a few more examples.
+
+.SH SEE ALSO
+.BR iptables-extensions (8),
+.BR pcap-filter (7)
--
2.21.0

89
SOURCES/arptables-helper Normal file
View File

@ -0,0 +1,89 @@
#!/bin/bash
# config: /etc/sysconfig/arptables
# Source 'em up
. /etc/init.d/functions
ARPTABLES_CONFIG=/etc/sysconfig/arptables
flush_delete_chains() {
echo -n $"Flushing all chains: "
if arptables -F; then
success
else
failure
fi
echo
echo -n $"Removing user defined chains: "
if arptables -X; then
success
else
failure
fi
echo
}
start() {
if [ ! -x /usr/sbin/arptables ]; then
exit 4
fi
# don't do squat if we don't have the config file
if [ -f $ARPTABLES_CONFIG ]; then
# If we don't clear these first, we might be adding to
# pre-existing rules.
flush_delete_chains
arptables -Z
echo -n $"Applying arptables firewall rules: "
/usr/sbin/arptables-restore < $ARPTABLES_CONFIG && \
success || \
failure
echo
touch /var/lock/subsys/arptables
else
failure
echo
echo $"Configuration file /etc/sysconfig/arptables missing"
exit 6
fi
}
stop() {
flush_delete_chains
echo -n $"Resetting built-in chains to the default ACCEPT policy:"
arptables -P INPUT ACCEPT && \
arptables -P OUTPUT ACCEPT && \
success || \
failure
echo
rm -f /var/lock/subsys/arptables
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
# "restart" is really just "start" as this isn't a daemon,
# and "start" clears any pre-defined rules anyway.
# This is really only here to make those who expect it happy
start
;;
condrestart|try-restart|force-reload)
[ -e /var/lock/subsys/arptables ] && start
;;
*)
exit 2
esac
exit 0

330
SOURCES/arptables.8 Normal file
View File

@ -0,0 +1,330 @@
.TH ARPTABLES 8 "November 2011"
.\"
.\" Man page originally written by Jochen Friedrich <jochen@scram.de>,
.\" maintained by Bart De Schuymer.
.\" It is based on the iptables man page.
.\"
.\" Iptables page by Herve Eychenne March 2000.
.\"
.\" This program is free software; you can redistribute it and/or modify
.\" it under the terms of the GNU General Public License as published by
.\" the Free Software Foundation; either version 2 of the License, or
.\" (at your option) any later version.
.\"
.\" This program is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with this program; if not, write to the Free Software
.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
.\"
.\"
.SH NAME
arptables \- ARP table administration
.SH SYNOPSIS
.BR "arptables " [ "-t table" ] " -" [ AD ] " chain rule-specification " [ options ]
.br
.BR "arptables " [ "-t table" ] " -" [ RI ] " chain rulenum rule-specification " [ options ]
.br
.BR "arptables " [ "-t table" ] " -D chain rulenum " [ options ]
.br
.BR "arptables " [ "-t table" ] " -" [ "LFZ" ] " " [ chain ] " " [ options ]
.br
.BR "arptables " [ "-t table" ] " -" [ "NX" ] " chain"
.br
.BR "arptables " [ "-t table" ] " -E old-chain-name new-chain-name"
.br
.BR "arptables " [ "-t table" ] " -P chain target " [ options ]
.SH DESCRIPTION
.B arptables
is a user space tool, it is used to set up and maintain the
tables of ARP rules in the Linux kernel. These rules inspect
the ARP frames which they see.
.B arptables
is analogous to the
.B iptables
user space tool, but
.B arptables
is less complicated.
.SS CHAINS
The kernel table is used to divide functionality into
different sets of rules. Each set of rules is called a chain.
Each chain is an ordered list of rules that can match ARP frames. If a
rule matches an ARP frame, then a processing specification tells
what to do with that matching frame. The processing specification is
called a 'target'. However, if the frame does not match the current
rule in the chain, then the next rule in the chain is examined and so forth.
The user can create new (user-defined) chains which can be used as the 'target' of a rule.
.SS TARGETS
A firewall rule specifies criteria for an ARP frame and a frame
processing specification called a target. When a frame matches a rule,
then the next action performed by the kernel is specified by the target.
The target can be one of these values:
.IR ACCEPT ,
.IR DROP ,
.IR CONTINUE ,
.IR RETURN ,
an 'extension' (see below) or a user-defined chain.
.PP
.I ACCEPT
means to let the frame through.
.I DROP
means the frame has to be dropped.
.I CONTINUE
means the next rule has to be checked. This can be handy to know how many
frames pass a certain point in the chain or to log those frames.
.I RETURN
means stop traversing this chain and resume at the next rule in the
previous (calling) chain.
For the extension targets please see the
.B "TARGET EXTENSIONS"
section of this man page.
.SS TABLES
There is only one ARP table in the Linux
kernel. The table is
.BR filter.
You can drop the '-t filter' argument to the arptables command.
The -t argument must be the
first argument on the arptables command line, if used.
.TP
.B "-t, --table"
.br
.BR filter ,
is the only table and contains two built-in chains:
.B INPUT
(for frames destined for the host) and
.B OUTPUT
(for locally-generated frames).
.br
.br
.SH ARPTABLES COMMAND LINE ARGUMENTS
After the initial arptables command line argument, the remaining
arguments can be divided into several different groups. These groups
are commands, miscellaneous commands, rule-specifications, match-extensions,
and watcher-extensions.
.SS COMMANDS
The arptables command arguments specify the actions to perform on the table
defined with the -t argument. If you do not use the -t argument to name
a table, the commands apply to the default filter table.
With the exception of the
.B "-Z"
command, only one command may be used on the command line at a time.
.TP
.B "-A, --append"
Append a rule to the end of the selected chain.
.TP
.B "-D, --delete"
Delete the specified rule from the selected chain. There are two ways to
use this command. The first is by specifying an interval of rule numbers
to delete, syntax: start_nr[:end_nr]. Using negative numbers is allowed, for more
details about using negative numbers, see the -I command. The second usage is by
specifying the complete rule as it would have been specified when it was added.
.TP
.B "-I, --insert"
Insert the specified rule into the selected chain at the specified rule number.
If the current number of rules equals N, then the specified number can be
between -N and N+1. For a positive number i, it holds that i and i-N-1 specify the
same place in the chain where the rule should be inserted. The number 0 specifies
the place past the last rule in the chain and using this number is therefore
equivalent with using the -A command.
.TP
.B "-R, --replace"
Replaces the specified rule into the selected chain at the specified rule number.
If the current number of rules equals N, then the specified number can be
between 1 and N. i specifies the place in the chain where the rule should be replaced.
.TP
.B "-P, --policy"
Set the policy for the chain to the given target. The policy can be
.BR ACCEPT ", " DROP " or " RETURN .
.TP
.B "-F, --flush"
Flush the selected chain. If no chain is selected, then every chain will be
flushed. Flushing the chain does not change the policy of the
chain, however.
.TP
.B "-Z, --zero"
Set the counters of the selected chain to zero. If no chain is selected, all the counters
are set to zero. The
.B "-Z"
command can be used in conjunction with the
.B "-L"
command.
When both the
.B "-Z"
and
.B "-L"
commands are used together in this way, the rule counters are printed on the screen
before they are set to zero.
.TP
.B "-L, --list"
List all rules in the selected chain. If no chain is selected, all chains
are listed.
.TP
.B "-N, --new-chain"
Create a new user-defined chain with the given name. The number of
user-defined chains is unlimited. A user-defined chain name has maximum
length of 31 characters.
.TP
.B "-X, --delete-chain"
Delete the specified user-defined chain. There must be no remaining references
to the specified chain, otherwise
.B arptables
will refuse to delete it. If no chain is specified, all user-defined
chains that aren't referenced will be removed.
.TP
.B "-E, --rename-chain"
Rename the specified chain to a new name. Besides renaming a user-defined
chain, you may rename a standard chain name to a name that suits your
taste. For example, if you like PREBRIDGING more than PREROUTING,
then you can use the -E command to rename the PREROUTING chain. If you do
rename one of the standard
.B arptables
chain names, please be sure to mention
this fact should you post a question on the
.B arptables
mailing lists.
It would be wise to use the standard name in your post. Renaming a standard
.B arptables
chain in this fashion has no effect on the structure or function
of the
.B arptables
kernel table.
.SS MISCELLANOUS COMMANDS
.TP
.B "-V, --version"
Show the version of the arptables userspace program.
.TP
.B "-h, --help"
Give a brief description of the command syntax.
.TP
.BR "-j, --jump " "\fItarget\fP"
The target of the rule. This is one of the following values:
.BR ACCEPT ,
.BR DROP ,
.BR CONTINUE ,
.BR RETURN ,
a target extension (see
.BR "TARGET EXTENSIONS" ")"
or a user-defined chain name.
.TP
.BI "-c, --set-counters " "PKTS BYTES"
This enables the administrator to initialize the packet and byte
counters of a rule (during
.B INSERT,
.B APPEND,
.B REPLACE
operations).
.SS RULE-SPECIFICATIONS
The following command line arguments make up a rule specification (as used
in the add and delete commands). A "!" option before the specification
inverts the test for that specification. Apart from these standard rule
specifications there are some other command line arguments of interest.
.TP
.BR "-s, --source-ip " "[!] \fIaddress\fP[/\fImask]\fP"
The Source IP specification.
.TP
.BR "-d, --destination-ip " "[!] \fIaddress\fP[/\fImask]\fP"
The Destination IP specification.
.TP
.BR "--source-mac " "[!] \fIaddress\fP[/\fImask\fP]"
The source mac address. Both mask and address are written as 6 hexadecimal
numbers separated by colons.
.TP
.BR "--destination-mac " "[!] \fIaddress\fP[/\fImask\fP]"
The destination mac address. Both mask and address are written as 6 hexadecimal
numbers separated by colons.
.TP
.BR "-i, --in-interface " "[!] \fIname\fP"
The interface via which a frame is received (for the
.B INPUT
chain). The flag
.B --in-if
is an alias for this option.
.TP
.BR "-o, --out-interface " "[!] \fIname\fP"
The interface via which a frame is going to be sent (for the
.B OUTPUT
chain). The flag
.B --out-if
is an alias for this option.
.TP
.BR "-l, --h-length " "\fIlength\fP[/\fImask\fP]"
The hardware length (nr of bytes)
.TP
.BR "--opcode " "\fIcode\fP[/\fImask\fP]
The operation code (2 bytes). Available values are:
.BR 1 = Request
.BR 2 = Reply
.BR 3 = Request_Reverse
.BR 4 = Reply_Reverse
.BR 5 = DRARP_Request
.BR 6 = DRARP_Reply
.BR 7 = DRARP_Error
.BR 8 = InARP_Request
.BR 9 = ARP_NAK .
.TP
.BR "--h-type " "\fItype\fP[/\fImask\fP]"
The hardware type (2 bytes, hexadecimal). Available values are:
.BR 1 = Ethernet .
.TP
.BR "--proto-type " "\fItype\fP[/\fImask\fP]"
The protocol type (2 bytes). Available values are:
.BR 0x800 = IPv4 .
.SS TARGET-EXTENSIONS
.B arptables
extensions are precompiled into the userspace tool. So there is no need
to explicitly load them with a -m option like in
.BR iptables .
However, these
extensions deal with functionality supported by supplemental kernel modules.
.SS mangle
.TP
.BR "--mangle-ip-s IP address"
Mangles Source IP Address to given value.
.TP
.BR "--mangle-ip-d IP address"
Mangles Destination IP Address to given value.
.TP
.BR "--mangle-mac-s MAC address"
Mangles Source MAC Address to given value.
.TP
.BR "--mangle-mac-d MAC address"
Mangles Destination MAC Address to given value.
.TP
.BR "--mangle-target target "
Target of ARP mangle operation
.BR "" ( DROP ", " CONTINUE " or " ACCEPT " -- default is " ACCEPT ).
.SS CLASSIFY
This module allows you to set the skb->priority value (and thus clas-
sify the packet into a specific CBQ class).
.TP
.BR "--set-class major:minor"
Set the major and minor class value. The values are always
interpreted as hexadecimal even if no 0x prefix is given.
.SH NOTES
In this nft-based version of
.BR arptables ,
support for
.B FORWARD
chain has not been implemented. Since ARP packets are "forwarded" only by Linux
bridges, the same may be achieved using
.B FORWARD
chain in
.BR ebtables .
.SH MAILINGLISTS
.BR "" "See " http://netfilter.org/mailinglists.html
.SH SEE ALSO
.BR xtables-nft "(8), " iptables "(8), " ebtables "(8), " arp "(8), " rarp "(8), " ifconfig "(8), " route (8)
.PP
.BR "" "See " http://ebtables.sf.net

12
SOURCES/arptables.service Normal file
View File

@ -0,0 +1,12 @@
[Unit]
Description=Automates a packet filtering firewall with arptables
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/libexec/arptables-helper start
ExecStop=/usr/libexec/arptables-helper stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

11
SOURCES/ebtables-config Normal file
View File

@ -0,0 +1,11 @@
# Save current firewall rules on stop.
# Value: yes|no, default: no
# Saves all firewall rules if firewall gets stopped
# (e.g. on system shutdown).
EBTABLES_SAVE_ON_STOP="no"
# Save (and restore) rule counters.
# Value: yes|no, default: no
# Save rule counters when saving a kernel table to a file. If the
# rule counters were saved, they will be restored when restoring the table.
EBTABLES_SAVE_COUNTER="no"

1096
SOURCES/ebtables.8 Normal file

File diff suppressed because it is too large Load Diff

11
SOURCES/ebtables.service Normal file
View File

@ -0,0 +1,11 @@
[Unit]
Description=Ethernet Bridge Filtering tables
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/ebtables start
ExecStop=/usr/libexec/ebtables stop
[Install]
WantedBy=multi-user.target

71
SOURCES/ebtables.systemd Normal file
View File

@ -0,0 +1,71 @@
#!/bin/bash
RETVAL=0
EBTCONF=/etc/sysconfig/ebtables
initialize() {
# Initialize $TYPE tables
echo -n $" $TYPE tables: "
if [ -r /etc/sysconfig/ebtables.$TYPE ]; then
/sbin/ebtables -t $TYPE --atomic-file /etc/sysconfig/ebtables.$TYPE --atomic-commit > /dev/null || RETVAL=1
else
echo -n "not configured"
fi
if [ $RETVAL -eq 0 ]; then
echo -n $"[ OK ]"
echo -ne "\r"
else
echo -n $"[FAILED]"
echo -ne "\r"
fi
}
case $1 in
start)
if [[ -r $EBTCONF ]]; then
ebtables-restore <$EBTCONF
RETVAL=$?
else
echo -n "not configured"
fi
if [ $RETVAL -eq 0 ]; then
echo -n $"[ OK ]"
echo -ne "\r"
else
echo -n $"[FAILED]"
echo -ne "\r"
fi
;;
stop)
[[ $EBTABLES_SAVE_ON_STOP == "yes" ]] && $0 save
/sbin/ebtables --init-table
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
echo -n $"[ OK ]"
echo -ne "\r"
else
echo -n $"[FAILED]"
echo -ne "\r"
fi
;;
save)
echo -n $"Saving Ethernet bridge filtering (ebtables): "
ebtables-save >$EBTCONF
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
echo -n $"[ OK ]"
echo -ne "\r"
else
echo -n $"[FAILED]"
echo -ne "\r"
fi
;;
*)
echo "usage: ${0##*/} {start|stop|save}" >&2
exit 1
;;
esac
# vim:set ts=2 sw=2 ft=sh et:

59
SOURCES/iptables-config Normal file
View File

@ -0,0 +1,59 @@
# Load additional iptables modules (nat helpers)
# Default: -none-
# Space separated list of nat helpers (e.g. 'ip_nat_ftp ip_nat_irc'), which
# are loaded after the firewall rules are applied. Options for the helpers are
# stored in /etc/modprobe.conf.
IPTABLES_MODULES=""
# Save current firewall rules on stop.
# Value: yes|no, default: no
# Saves all firewall rules to /etc/sysconfig/iptables if firewall gets stopped
# (e.g. on system shutdown).
IPTABLES_SAVE_ON_STOP="no"
# Save current firewall rules on restart.
# Value: yes|no, default: no
# Saves all firewall rules to /etc/sysconfig/iptables if firewall gets
# restarted.
IPTABLES_SAVE_ON_RESTART="no"
# Save (and restore) rule and chain counter.
# Value: yes|no, default: no
# Save counters for rules and chains to /etc/sysconfig/iptables if
# 'service iptables save' is called or on stop or restart if SAVE_ON_STOP or
# SAVE_ON_RESTART is enabled.
IPTABLES_SAVE_COUNTER="no"
# Numeric status output
# Value: yes|no, default: yes
# Print IP addresses and port numbers in numeric format in the status output.
IPTABLES_STATUS_NUMERIC="yes"
# Verbose status output
# Value: yes|no, default: yes
# Print info about the number of packets and bytes plus the "input-" and
# "outputdevice" in the status output.
IPTABLES_STATUS_VERBOSE="no"
# Status output with numbered lines
# Value: yes|no, default: yes
# Print a counter/number for every rule in the status output.
IPTABLES_STATUS_LINENUMBERS="yes"
# Reload sysctl settings on start and restart
# Default: -none-
# Space separated list of sysctl items which are to be reloaded on start.
# List items will be matched by fgrep.
#IPTABLES_SYSCTL_LOAD_LIST=".nf_conntrack .bridge-nf"
# Set wait option for iptables-restore calls in seconds
# Default: 600
# Set to 0 to deactivate the wait.
#IPTABLES_RESTORE_WAIT=600
# Set wait interval option for iptables-restore calls in microseconds
# Default: 1000000
# Set to 100000 to try to get the lock every 100000 microseconds, 10 times a
# second.
# Only usable with IPTABLES_RESTORE_WAIT > 0
#IPTABLES_RESTORE_WAIT_INTERVAL=1000000

374
SOURCES/iptables.init Executable file
View File

@ -0,0 +1,374 @@
#!/bin/bash
#
# iptables Start iptables firewall
#
# chkconfig: 2345 08 92
# description: Starts, stops and saves iptables firewall
#
# config: /etc/sysconfig/iptables
# config: /etc/sysconfig/iptables-config
#
### BEGIN INIT INFO
# Provides: iptables
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop iptables firewall
# Description: Start, stop and save iptables firewall
### END INIT INFO
# Source function library.
. /etc/init.d/functions
IPTABLES=iptables
IPTABLES_DATA=/etc/sysconfig/$IPTABLES
IPTABLES_FALLBACK_DATA=${IPTABLES_DATA}.fallback
IPTABLES_CONFIG=/etc/sysconfig/${IPTABLES}-config
IPV=${IPTABLES%tables} # ip for ipv4 | ip6 for ipv6
[ "$IPV" = "ip" ] && _IPV="ipv4" || _IPV="ipv6"
VAR_SUBSYS_IPTABLES=/var/lock/subsys/$IPTABLES
# only usable for root
if [ $EUID != 0 ]; then
echo -n $"${IPTABLES}: Only usable by root."; warning; echo
exit 4
fi
if [ ! -x /sbin/$IPTABLES ]; then
echo -n $"${IPTABLES}: /sbin/$IPTABLES does not exist."; warning; echo
exit 5
fi
# Default firewall configuration:
IPTABLES_MODULES=""
IPTABLES_SAVE_ON_STOP="no"
IPTABLES_SAVE_ON_RESTART="no"
IPTABLES_SAVE_COUNTER="no"
IPTABLES_STATUS_NUMERIC="yes"
IPTABLES_STATUS_VERBOSE="no"
IPTABLES_STATUS_LINENUMBERS="yes"
IPTABLES_SYSCTL_LOAD_LIST=""
IPTABLES_RESTORE_WAIT=600
IPTABLES_RESTORE_WAIT_INTERVAL=1000000
# Load firewall configuration.
[ -f "$IPTABLES_CONFIG" ] && . "$IPTABLES_CONFIG"
# explicitly omit security table from this list as
# it should be reserved for SELinux use
NF_TABLES="raw mangle filter nat"
flush_n_delete() {
# Flush firewall rules and delete chains.
echo -n $"${IPTABLES}: Flushing firewall rules: "
ret=0
# For all tables
for i in $NF_TABLES; do
# Flush firewall rules.
$IPTABLES -t $i -F;
let ret+=$?;
# Delete firewall chains.
$IPTABLES -t $i -X;
let ret+=$?;
# Set counter to zero.
$IPTABLES -t $i -Z;
let ret+=$?;
done
[ $ret -eq 0 ] && success || failure
echo
return $ret
}
set_policy() {
# Set policy for configured tables.
policy=$1
echo -n $"${IPTABLES}: Setting chains to policy $policy: "
ret=0
for i in $NF_TABLES; do
echo -n "$i "
case "$i" in
raw)
$IPTABLES -t raw -P PREROUTING $policy \
&& $IPTABLES -t raw -P OUTPUT $policy \
|| let ret+=1
;;
filter)
$IPTABLES -t filter -P INPUT $policy \
&& $IPTABLES -t filter -P OUTPUT $policy \
&& $IPTABLES -t filter -P FORWARD $policy \
|| let ret+=1
;;
nat)
$IPTABLES -t nat -P PREROUTING $policy \
&& $IPTABLES -t nat -P POSTROUTING $policy \
&& $IPTABLES -t nat -P OUTPUT $policy \
|| let ret+=1
;;
mangle)
$IPTABLES -t mangle -P PREROUTING $policy \
&& $IPTABLES -t mangle -P POSTROUTING $policy \
&& $IPTABLES -t mangle -P INPUT $policy \
&& $IPTABLES -t mangle -P OUTPUT $policy \
&& $IPTABLES -t mangle -P FORWARD $policy \
|| let ret+=1
;;
*)
let ret+=1
;;
esac
done
[ $ret -eq 0 ] && success || failure
echo
return $ret
}
load_sysctl() {
# load matched sysctl values
if [ -n "$IPTABLES_SYSCTL_LOAD_LIST" ]; then
echo -n $"Loading sysctl settings: "
ret=0
for item in $IPTABLES_SYSCTL_LOAD_LIST; do
fgrep -hs $item /etc/sysctl.d/* | sysctl -p - >/dev/null
let ret+=$?;
done
[ $ret -eq 0 ] && success || failure
echo
fi
return $ret
}
start() {
# Do not start if there is no config file.
if [ ! -f "$IPTABLES_DATA" ]; then
echo -n $"${IPTABLES}: No config file."; warning; echo
return 6
fi
# check if ipv6 module load is deactivated
if [ "${_IPV}" = "ipv6" ] \
&& grep -qIsE "^install[[:space:]]+${_IPV}[[:space:]]+/bin/(true|false)" /etc/modprobe.conf /etc/modprobe.d/* ; then
echo $"${IPTABLES}: ${_IPV} is disabled."
return 150
fi
echo -n $"${IPTABLES}: Applying firewall rules: "
OPT=
[ "x$IPTABLES_SAVE_COUNTER" = "xyes" ] && OPT="-c"
if [ $IPTABLES_RESTORE_WAIT -ne 0 ]; then
OPT="${OPT} --wait ${IPTABLES_RESTORE_WAIT}"
if [ $IPTABLES_RESTORE_WAIT_INTERVAL -lt 1000000 ]; then
OPT="${OPT} --wait-interval ${IPTABLES_RESTORE_WAIT_INTERVAL}"
fi
fi
$IPTABLES-restore $OPT $IPTABLES_DATA
if [ $? -eq 0 ]; then
success; echo
else
failure; echo;
if [ -f "$IPTABLES_FALLBACK_DATA" ]; then
echo -n $"${IPTABLES}: Applying firewall fallback rules: "
$IPTABLES-restore $OPT $IPTABLES_FALLBACK_DATA
if [ $? -eq 0 ]; then
success; echo
else
failure; echo; return 1
fi
else
return 1
fi
fi
# Load additional modules (helpers)
if [ -n "$IPTABLES_MODULES" ]; then
echo -n $"${IPTABLES}: Loading additional modules: "
ret=0
for mod in $IPTABLES_MODULES; do
echo -n "$mod "
modprobe $mod > /dev/null 2>&1
let ret+=$?;
done
[ $ret -eq 0 ] && success || failure
echo
fi
# Load sysctl settings
load_sysctl
touch $VAR_SUBSYS_IPTABLES
return $ret
}
stop() {
# Set default chain policy to ACCEPT, in order to not break shutdown
# on systems where the default policy is DROP and root device is
# network-based (i.e.: iSCSI, NFS)
set_policy ACCEPT
# And then, flush the rules and delete chains
flush_n_delete
rm -f $VAR_SUBSYS_IPTABLES
return $ret
}
save() {
echo -n $"${IPTABLES}: Saving firewall rules to $IPTABLES_DATA: "
OPT=
[ "x$IPTABLES_SAVE_COUNTER" = "xyes" ] && OPT="-c"
ret=0
TMP_FILE=$(/bin/mktemp -q $IPTABLES_DATA.XXXXXX) \
&& chmod 600 "$TMP_FILE" \
&& $IPTABLES-save $OPT > $TMP_FILE 2>/dev/null \
&& size=$(stat -c '%s' $TMP_FILE) && [ $size -gt 0 ] \
|| ret=1
if [ $ret -eq 0 ]; then
if [ -e $IPTABLES_DATA ]; then
cp -f $IPTABLES_DATA $IPTABLES_DATA.save \
&& chmod 600 $IPTABLES_DATA.save \
&& restorecon $IPTABLES_DATA.save \
|| ret=1
fi
if [ $ret -eq 0 ]; then
mv -f $TMP_FILE $IPTABLES_DATA \
&& chmod 600 $IPTABLES_DATA \
&& restorecon $IPTABLES_DATA \
|| ret=1
fi
fi
rm -f $TMP_FILE
[ $ret -eq 0 ] && success || failure
echo
return $ret
}
status() {
if [ ! -f "$VAR_SUBSYS_IPTABLES" ]; then
echo $"${IPTABLES}: Firewall is not running."
return 3
fi
NUM=
[ "x$IPTABLES_STATUS_NUMERIC" = "xyes" ] && NUM="-n"
VERBOSE=
[ "x$IPTABLES_STATUS_VERBOSE" = "xyes" ] && VERBOSE="--verbose"
COUNT=
[ "x$IPTABLES_STATUS_LINENUMBERS" = "xyes" ] && COUNT="--line-numbers"
for table in $NF_TABLES; do
echo $"Table: $table"
$IPTABLES -t $table --list $NUM $VERBOSE $COUNT && echo
done
return 0
}
reload() {
# Do not reload if there is no config file.
if [ ! -f "$IPTABLES_DATA" ]; then
echo -n $"${IPTABLES}: No config file."; warning; echo
return 6
fi
# check if ipv6 module load is deactivated
if [ "${_IPV}" = "ipv6" ] \
&& grep -qIsE "^install[[:space:]]+${_IPV}[[:space:]]+/bin/(true|false)" /etc/modprobe.conf /etc/modprobe.d/* ; then
echo $"${IPTABLES}: ${_IPV} is disabled."
return 150
fi
echo -n $"${IPTABLES}: Trying to reload firewall rules: "
OPT=
[ "x$IPTABLES_SAVE_COUNTER" = "xyes" ] && OPT="-c"
if [ $IPTABLES_RESTORE_WAIT -ne 0 ]; then
OPT="${OPT} --wait ${IPTABLES_RESTORE_WAIT}"
if [ $IPTABLES_RESTORE_WAIT_INTERVAL -lt 1000000 ]; then
OPT="${OPT} --wait-interval ${IPTABLES_RESTORE_WAIT_INTERVAL}"
fi
fi
$IPTABLES-restore $OPT $IPTABLES_DATA
if [ $? -eq 0 ]; then
success; echo
else
failure; echo; echo "Firewall rules are not changed."; return 1
fi
# Load additional modules (helpers)
if [ -n "$IPTABLES_MODULES" ]; then
echo -n $"${IPTABLES}: Loading additional modules: "
ret=0
for mod in $IPTABLES_MODULES; do
echo -n "$mod "
modprobe $mod > /dev/null 2>&1
let ret+=$?;
done
[ $ret -eq 0 ] && success || failure
echo
fi
# Load sysctl settings
load_sysctl
return $ret
}
restart() {
[ "x$IPTABLES_SAVE_ON_RESTART" = "xyes" ] && save
stop
start
}
case "$1" in
start)
[ -f "$VAR_SUBSYS_IPTABLES" ] && exit 0
start
RETVAL=$?
;;
stop)
[ "x$IPTABLES_SAVE_ON_STOP" = "xyes" ] && save
stop
RETVAL=$?
;;
restart|force-reload)
restart
RETVAL=$?
;;
reload)
[ -e "$VAR_SUBSYS_IPTABLES" ] && reload
RETVAL=$?
;;
condrestart|try-restart)
[ ! -e "$VAR_SUBSYS_IPTABLES" ] && exit 0
restart
RETVAL=$?
;;
status)
status
RETVAL=$?
;;
panic)
set_policy DROP
RETVAL=$?
;;
save)
save
RETVAL=$?
;;
*)
echo $"Usage: ${IPTABLES} {start|stop|reload|restart|condrestart|status|panic|save}"
RETVAL=2
;;
esac
exit $RETVAL

18
SOURCES/iptables.service Normal file
View File

@ -0,0 +1,18 @@
[Unit]
Description=IPv4 firewall with iptables
After=syslog.target
AssertPathExists=/etc/sysconfig/iptables
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/iptables/iptables.init start
ExecReload=/usr/libexec/iptables/iptables.init reload
ExecStop=/usr/libexec/iptables/iptables.init stop
Environment=BOOTUP=serial
Environment=CONSOLETYPE=serial
StandardOutput=syslog
StandardError=syslog
[Install]
WantedBy=basic.target

View File

@ -0,0 +1,15 @@
# sample configuration for ip6tables service
# you can edit this manually or use system-config-firewall
# please do not ask us to add additional ports/services to this default configuration
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p ipv6-icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -d fe80::/64 -p udp -m udp --dport 546 -m state --state NEW -j ACCEPT
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited
COMMIT

View File

@ -0,0 +1,14 @@
# sample configuration for iptables service
# you can edit this manually or use system-config-firewall
# please do not ask us to add additional ports/services to this default configuration
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

1604
SPECS/iptables.spec Normal file

File diff suppressed because it is too large Load Diff