summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-11-19 15:32:18 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2013-12-30 23:50:21 +0100
commit5705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57 (patch)
tree8bf9943f0eee5b64acbc1e49ee5ce5c59f56d87b
parent890fd9ef76ad0c11695fb0d09a88169e6e46584f (diff)
xtables-restore: add support for dormant tables
This patch adds support for dormant tables for xtables-restore. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/linux/netfilter/nf_tables.h10
-rw-r--r--iptables/nft.c55
-rw-r--r--iptables/nft.h2
-rw-r--r--iptables/xtables-restore.c8
4 files changed, 71 insertions, 4 deletions
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 542b6549..837bab32 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -53,9 +53,19 @@ enum nft_hook_attributes {
};
#define NFTA_HOOK_MAX (__NFTA_HOOK_MAX - 1)
+/**
+ * enum nft_table_flags - nf_tables table flags
+ *
+ * @NFT_TABLE_F_DORMANT: this table is not active
+ */
+enum nft_table_flags {
+ NFT_TABLE_F_DORMANT = 0x1,
+};
+
enum nft_table_attributes {
NFTA_TABLE_UNSPEC,
NFTA_TABLE_NAME,
+ NFTA_TABLE_FLAGS,
__NFTA_TABLE_MAX
};
#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
diff --git a/iptables/nft.c b/iptables/nft.c
index 24301200..1f5ecb70 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -229,7 +229,9 @@ static struct builtin_table {
},
};
-static int nft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t)
+static int
+nft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t,
+ bool dormant)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
@@ -241,6 +243,10 @@ static int nft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t)
return -1;
nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)_t->name);
+ if (dormant) {
+ nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS,
+ NFT_TABLE_F_DORMANT);
+ }
nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET,
NLM_F_ACK|NLM_F_EXCL, h->seq);
@@ -367,7 +373,7 @@ nft_chain_builtin_init(struct nft_handle *h, const char *table,
ret = -1;
goto out;
}
- if (nft_table_builtin_add(h, t) < 0) {
+ if (nft_table_builtin_add(h, t, false) < 0) {
/* Built-in table already initialized, skip. */
if (errno == EEXIST)
goto out;
@@ -423,6 +429,49 @@ int nft_chain_add(struct nft_handle *h, const struct nft_chain *c)
return mnl_talk(h, nlh, NULL, NULL);
}
+int nft_table_set_dormant(struct nft_handle *h, const char *table)
+{
+ int ret = 0, i;
+ struct builtin_table *t;
+
+ t = nft_table_builtin_find(table);
+ if (t == NULL) {
+ ret = -1;
+ goto out;
+ }
+ /* Add this table as dormant */
+ if (nft_table_builtin_add(h, t, true) < 0) {
+ /* Built-in table already initialized, skip. */
+ if (errno == EEXIST)
+ goto out;
+ }
+ for (i=0; t->chains[i].name != NULL && i<NF_INET_NUMHOOKS; i++)
+ __nft_chain_builtin_init(h, t, t->chains[i].name, NF_ACCEPT);
+out:
+ return ret;
+}
+
+int nft_table_wake_dormant(struct nft_handle *h, const char *table)
+{
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
+ struct nft_table *t;
+
+ t = nft_table_alloc();
+ if (t == NULL)
+ return -1;
+
+ nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)table);
+ nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS, 0);
+
+ nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET,
+ NLM_F_ACK, h->seq);
+ nft_table_nlmsg_build_payload(nlh, t);
+ nft_table_free(t);
+
+ return mnl_talk(h, nlh, NULL, NULL);
+}
+
static void nft_chain_print_debug(struct nft_chain *c, struct nlmsghdr *nlh)
{
#ifdef NLDEBUG
@@ -449,7 +498,7 @@ __nft_chain_set(struct nft_handle *h, const char *table,
_t = nft_table_builtin_find(table);
/* if this built-in table does not exists, create it */
if (_t != NULL)
- nft_table_builtin_add(h, _t);
+ nft_table_builtin_add(h, _t, false);
_c = nft_chain_builtin_find(_t, chain);
if (_c != NULL) {
diff --git a/iptables/nft.h b/iptables/nft.h
index aa458f8c..aed2498b 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -20,6 +20,8 @@ struct nft_table;
int nft_table_add(struct nft_handle *h, const struct nft_table *t);
int nft_for_each_table(struct nft_handle *h, int (*func)(struct nft_handle *h, const char *tablename, bool counters), bool counters);
bool nft_table_find(struct nft_handle *h, const char *tablename);
+int nft_table_set_dormant(struct nft_handle *h, const char *table);
+int nft_table_wake_dormant(struct nft_handle *h, const char *table);
/*
* Operations with chains.
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 09922a0c..30ea813c 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -243,11 +243,16 @@ xtables_restore_main(int argc, char *argv[])
fputs(buffer, stdout);
continue;
} else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
- /* FIXME commit/testing operation not supported */
if (!testing) {
+ if (nft_table_wake_dormant(&h, curtable) < 0) {
+ fprintf(stderr, "Failed to wake up "
+ "dormant table `%s'\n",
+ curtable);
+ }
DEBUGP("Calling commit\n");
ret = 1;
} else {
+ /* FIXME -t needs to be fixed */
DEBUGP("Not calling commit, testing\n");
ret = 1;
}
@@ -270,6 +275,7 @@ xtables_restore_main(int argc, char *argv[])
if (tablename && (strcmp(tablename, table) != 0))
continue;
+ nft_table_set_dormant(&h, table);
if (noflush == 0) {
DEBUGP("Cleaning all chains of table '%s'\n",
table);