summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2019-04-23 15:16:20 +0200
committerFlorian Westphal <fw@strlen.de>2019-04-27 01:08:08 +0200
commit0baa08fed43fa318eaa6ffe02673289343ac9cc0 (patch)
tree3060ebde032b213641fe62211ae9bf4f02d91785
parent31dd3780a64935e3bcf83efb1a4354eed41f59ee (diff)
xtables: unify user chain add/flush for restore case
The idea here is to move the 'flush' decision into the core, rather than have the decision in the frontend. This will be required later when "generation id" is passed to kernel. In this case, we might have to add the flush when re-trying the transaction. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--iptables/nft-shared.h7
-rw-r--r--iptables/nft.c82
-rw-r--r--iptables/nft.h4
-rw-r--r--iptables/xtables-restore.c38
-rw-r--r--iptables/xtables-translate.c6
5 files changed, 59 insertions, 78 deletions
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 019c1f20..de889ead 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -245,14 +245,11 @@ 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);
- int (*chain_user_flush)(struct nft_handle *h,
- struct nftnl_chain_list *clist,
- const char *table, const char *chain);
int (*chain_set)(struct nft_handle *h, const char *table,
const char *chain, const char *policy,
const struct xt_counters *counters);
- int (*chain_user_add)(struct nft_handle *h, const char *chain,
- const char *table);
+ int (*chain_restore)(struct nft_handle *h, const char *chain,
+ const char *table);
int (*table_flush)(struct nft_handle *h, const char *table);
diff --git a/iptables/nft.c b/iptables/nft.c
index a297d985..16d7b795 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1621,49 +1621,6 @@ __nft_rule_flush(struct nft_handle *h, const char *table,
nftnl_rule_free(r);
}
-struct chain_user_flush_data {
- struct nft_handle *handle;
- const char *table;
- const char *chain;
-};
-
-static int __nft_chain_user_flush(struct nftnl_chain *c, void *data)
-{
- const char *table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
- const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- struct chain_user_flush_data *d = data;
- struct nft_handle *h = d->handle;
- const char *table = d->table;
- const char *chain = d->chain;
-
- if (strcmp(table, table_name) != 0)
- return 0;
-
- if (strcmp(chain, chain_name) != 0)
- return 0;
-
- if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM))
- __nft_rule_flush(h, table, chain, false);
-
- return 0;
-}
-
-int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
- const char *table, const char *chain)
-{
- struct chain_user_flush_data d = {
- .handle = h,
- .table = table,
- .chain = chain,
- };
-
- nft_fn = nft_chain_user_flush;
-
- nftnl_chain_list_foreach(list, __nft_chain_user_flush, &d);
-
- return 1;
-}
-
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
bool verbose)
{
@@ -1750,6 +1707,45 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
return ret == 0 ? 1 : 0;
}
+int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table)
+{
+ struct nftnl_chain_list *list;
+ struct nftnl_chain *c;
+ bool created = false;
+ int ret;
+
+ c = nft_chain_find(h, table, chain);
+ if (c) {
+ /* Apparently -n still flushes existing user defined
+ * chains that are redefined.
+ */
+ if (h->noflush)
+ __nft_rule_flush(h, table, chain, false);
+ } else {
+ c = nftnl_chain_alloc();
+ if (!c)
+ return -1;
+
+ nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
+ nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain);
+ created = true;
+ }
+
+ if (h->family == NFPROTO_BRIDGE)
+ nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT);
+
+ if (!created)
+ return 0;
+
+ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
+
+ list = nft_chain_list_get(h, table);
+ if (list)
+ nftnl_chain_list_add(c, list);
+
+ return ret;
+}
+
/* From linux/netlink.h */
#ifndef NLM_F_NONREC
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
diff --git a/iptables/nft.h b/iptables/nft.h
index 56dc2076..d428287b 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -45,6 +45,7 @@ struct nft_handle {
} table[NFT_TABLE_MAX];
bool have_cache;
bool restore;
+ bool noflush;
int8_t config_done;
/* meta data, for error reporting */
@@ -87,8 +88,7 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
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,
- const char *chain, const char *table);
+int nft_chain_restore(struct nft_handle *h, 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);
const struct builtin_chain *nft_chain_builtin_find(const struct builtin_table *t, const char *chain);
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 6e6daffc..b12ab6a6 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -19,7 +19,7 @@
#include "nft-bridge.h"
#include <libnftnl/chain.h>
-static int counters, verbose, noflush;
+static int counters, verbose;
/* Keeping track of external matches and targets. */
static const struct option options[] = {
@@ -74,10 +74,9 @@ struct nft_xt_restore_cb restore_cb = {
.abort = nft_abort,
.table_new = nft_table_new,
.table_flush = nft_table_flush,
- .chain_user_flush = nft_chain_user_flush,
.do_command = do_commandx,
.chain_set = nft_chain_set,
- .chain_user_add = nft_chain_user_add,
+ .chain_restore = nft_chain_restore,
};
static const struct xtc_ops xtc_ops = {
@@ -93,7 +92,6 @@ void xtables_restore_parse(struct nft_handle *h,
char buffer[10240];
int in_table = 0;
const struct xtc_ops *ops = &xtc_ops;
- struct nftnl_chain_list *chain_list = NULL;
line = 0;
@@ -147,10 +145,12 @@ 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);
+ /* Fixme: Needed to init chain cache.
+ * Should create explicit function to do this.
+ */
+ nft_chain_list_get(h, table);
- if (noflush == 0) {
+ if (h->noflush == 0) {
DEBUGP("Cleaning all chains of table '%s'\n",
table);
if (cb->table_flush)
@@ -214,19 +214,7 @@ void xtables_restore_parse(struct nft_handle *h,
}
DEBUGP("Setting policy of chain %s to %s\n",
chain, policy);
-
- } 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 &&
+ } else if (cb->chain_restore(h, chain, curtable->name) < 0 &&
errno != EEXIST) {
xtables_error(PARAMETER_PROBLEM,
"cannot create chain "
@@ -380,7 +368,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
IPTABLES_VERSION);
exit(0);
case 'n':
- noflush = 1;
+ h.noflush = 1;
break;
case 'M':
xtables_modprobe_program = optarg;
@@ -480,10 +468,9 @@ struct nft_xt_restore_cb ebt_restore_cb = {
.commit = nft_commit,
.table_new = nft_table_new,
.table_flush = ebt_table_flush,
- .chain_user_flush = nft_chain_user_flush,
.do_command = do_commandeb,
.chain_set = nft_chain_set,
- .chain_user_add = nft_chain_user_add,
+ .chain_restore = nft_chain_restore,
};
static const struct option ebt_restore_options[] = {
@@ -496,6 +483,7 @@ int xtables_eb_restore_main(int argc, char *argv[])
struct nft_xt_restore_parse p = {
.in = stdin,
};
+ bool noflush = false;
struct nft_handle h;
int c;
@@ -514,6 +502,7 @@ int xtables_eb_restore_main(int argc, char *argv[])
}
nft_init_eb(&h, "ebtables-restore");
+ h.noflush = noflush;
xtables_restore_parse(&h, &p, &ebt_restore_cb, argc, argv);
nft_fini(&h);
@@ -525,10 +514,9 @@ struct nft_xt_restore_cb arp_restore_cb = {
.commit = nft_commit,
.table_new = nft_table_new,
.table_flush = nft_table_flush,
- .chain_user_flush = nft_chain_user_flush,
.do_command = do_commandarp,
.chain_set = nft_chain_set,
- .chain_user_add = nft_chain_user_add,
+ .chain_restore = nft_chain_restore,
};
int xtables_arp_restore_main(int argc, char *argv[])
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index e1d2a7d6..eb35890a 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -329,8 +329,8 @@ static const struct option options[] = {
{ NULL },
};
-static int xlate_chain_user_add(struct nft_handle *h, const char *chain,
- const char *table)
+static int xlate_chain_user_restore(struct nft_handle *h, const char *chain,
+ const char *table)
{
printf("add chain %s %s %s\n", family2str[h->family], table, chain);
return 0;
@@ -416,7 +416,7 @@ static int dummy_compat_rev(const char *name, uint8_t rev, int opt)
static struct nft_xt_restore_cb cb_xlate = {
.table_new = xlate_table_new,
.chain_set = xlate_chain_set,
- .chain_user_add = xlate_chain_user_add,
+ .chain_restore = xlate_chain_user_restore,
.do_command = do_command_xlate,
.commit = commit,
.abort = commit,