netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iptables-nftables 1/3] iptables: nft: generalize batch infrastructure
@ 2014-06-10  9:30 Pablo Neira Ayuso
  2014-06-10  9:30 ` [PATCH iptables-nftables 2/3] iptables: nft: remove unused code Pablo Neira Ayuso
  2014-06-10  9:30 ` [PATCH iptables-nftables 3/3] iptables: nft: add tables and chains to the batch Pablo Neira Ayuso
  0 siblings, 2 replies; 3+ messages in thread
From: Pablo Neira Ayuso @ 2014-06-10  9:30 UTC (permalink / raw)
  To: netfilter-devel

Prepare inclusion of tables and chain objects in the batch.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 iptables/nft.c |   82 ++++++++++++++++++++++++++++----------------------------
 iptables/nft.h |    4 +--
 2 files changed, 43 insertions(+), 43 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index f3ec526..919b64d 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -615,7 +615,7 @@ int nft_init(struct nft_handle *h, struct builtin_table *t)
 	h->portid = mnl_socket_get_portid(h->nl);
 	h->tables = t;
 
-	INIT_LIST_HEAD(&h->rule_list);
+	INIT_LIST_HEAD(&h->obj_list);
 
 	h->batch = mnl_nft_batch_alloc();
 
@@ -949,37 +949,37 @@ err:
 	return NULL;
 }
 
-enum rule_update_type {
-       NFT_DO_APPEND,
-       NFT_DO_INSERT,
-       NFT_DO_REPLACE,
-       NFT_DO_DELETE,
-       NFT_DO_FLUSH,
-       NFT_DO_COMMIT,
-       NFT_DO_ABORT,
+enum obj_update_type {
+	NFT_COMPAT_RULE_APPEND,
+	NFT_COMPAT_RULE_INSERT,
+	NFT_COMPAT_RULE_REPLACE,
+	NFT_COMPAT_RULE_DELETE,
+	NFT_COMPAT_RULE_FLUSH,
+	NFT_COMPAT_COMMIT,
+	NFT_COMPAT_ABORT,
 };
 
-struct rule_update {
-       struct list_head        head;
-       enum rule_update_type   type;
-       struct nft_rule	       *rule;
+struct obj_update {
+       struct list_head		head;
+       enum obj_update_type	type;
+       struct nft_rule		*rule;
 };
 
-static int rule_update_add(struct nft_handle *h, enum rule_update_type type,
+static int batch_rule_add(struct nft_handle *h, enum obj_update_type type,
 			  struct nft_rule *r)
 {
-       struct rule_update *rupd;
+	struct obj_update *obj;
 
-       rupd = calloc(1, sizeof(struct rule_update));
-       if (rupd == NULL)
-	       return -1;
+	obj = calloc(1, sizeof(struct obj_update));
+	if (obj == NULL)
+		return -1;
 
-       rupd->rule = r;
-       rupd->type = type;
-       list_add_tail(&rupd->head, &h->rule_list);
-       h->rule_list_num++;
+	obj->rule = r;
+	obj->type = type;
+	list_add_tail(&obj->head, &h->obj_list);
+	h->obj_list_num++;
 
-       return 0;
+	return 0;
 }
 
 int
@@ -1001,11 +1001,11 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
 
 	if (handle > 0) {
 		nft_rule_attr_set(r, NFT_RULE_ATTR_HANDLE, &handle);
-		type = NFT_DO_REPLACE;
+		type = NFT_COMPAT_RULE_REPLACE;
 	} else
-		type = NFT_DO_APPEND;
+		type = NFT_COMPAT_RULE_APPEND;
 
-	if (rule_update_add(h, type, r) < 0)
+	if (batch_rule_add(h, type, r) < 0)
 		nft_rule_free(r);
 
 	return 1;
@@ -1243,7 +1243,7 @@ __nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
 	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
 	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
 
-	if (rule_update_add(h, NFT_DO_FLUSH, r) < 0)
+	if (batch_rule_add(h, NFT_COMPAT_RULE_FLUSH, r) < 0)
 		nft_rule_free(r);
 }
 
@@ -1630,7 +1630,7 @@ static int __nft_rule_del(struct nft_handle *h, struct nft_rule_list *list,
 
 	nft_rule_list_del(r);
 
-	ret = rule_update_add(h, NFT_DO_DELETE, r);
+	ret = batch_rule_add(h, NFT_COMPAT_RULE_DELETE, r);
 	if (ret < 0) {
 		nft_rule_free(r);
 		return -1;
@@ -1756,7 +1756,7 @@ nft_rule_add(struct nft_handle *h, const char *chain,
 	if (handle > 0)
 		nft_rule_attr_set_u64(r, NFT_RULE_ATTR_POSITION, handle);
 
-	if (rule_update_add(h, NFT_DO_INSERT, r) < 0) {
+	if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) {
 		nft_rule_free(r);
 		return 0;
 	}
@@ -2180,28 +2180,28 @@ error:
 static int nft_action(struct nft_handle *h, int action)
 {
 	int flags = NLM_F_CREATE, type;
-	struct rule_update *n, *tmp;
+	struct obj_update *n, *tmp;
 	struct nlmsghdr *nlh;
 	uint32_t seq = 1;
 	int ret;
 
 	mnl_nft_batch_begin(h->batch, seq++);
 
-	list_for_each_entry_safe(n, tmp, &h->rule_list, head) {
+	list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
 		switch (n->type) {
-		case NFT_DO_APPEND:
+		case NFT_COMPAT_RULE_APPEND:
 			type = NFT_MSG_NEWRULE;
 			flags |= NLM_F_APPEND;
 			break;
-		case NFT_DO_INSERT:
+		case NFT_COMPAT_RULE_INSERT:
 			type = NFT_MSG_NEWRULE;
 			break;
-		case NFT_DO_REPLACE:
+		case NFT_COMPAT_RULE_REPLACE:
 			type = NFT_MSG_NEWRULE;
 			flags |= NLM_F_REPLACE;
 			break;
-		case NFT_DO_DELETE:
-		case NFT_DO_FLUSH:
+		case NFT_COMPAT_RULE_DELETE:
+		case NFT_COMPAT_RULE_FLUSH:
 			type = NFT_MSG_DELRULE;
 			break;
 		default:
@@ -2213,7 +2213,7 @@ static int nft_action(struct nft_handle *h, int action)
 		nft_rule_nlmsg_build_payload(nlh, n->rule);
 		nft_rule_print_debug(n->rule, nlh);
 
-		h->rule_list_num--;
+		h->obj_list_num--;
 		list_del(&n->head);
 		nft_rule_free(n->rule);
 		free(n);
@@ -2223,10 +2223,10 @@ static int nft_action(struct nft_handle *h, int action)
 	}
 
 	switch (action) {
-	case NFT_DO_COMMIT:
+	case NFT_COMPAT_COMMIT:
 		mnl_nft_batch_end(h->batch, seq++);
 		break;
-	case NFT_DO_ABORT:
+	case NFT_COMPAT_ABORT:
 		break;
 	}
 
@@ -2244,12 +2244,12 @@ static int nft_action(struct nft_handle *h, int action)
 
 int nft_commit(struct nft_handle *h)
 {
-	return nft_action(h, NFT_DO_COMMIT);
+	return nft_action(h, NFT_COMPAT_COMMIT);
 }
 
 int nft_abort(struct nft_handle *h)
 {
-	return nft_action(h, NFT_DO_ABORT);
+	return nft_action(h, NFT_COMPAT_ABORT);
 }
 
 int nft_compatible_revision(const char *name, uint8_t rev, int opt)
diff --git a/iptables/nft.h b/iptables/nft.h
index c31371c..ddc5201 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -30,8 +30,8 @@ struct nft_handle {
 	struct mnl_socket	*nl;
 	uint32_t		portid;
 	uint32_t		seq;
-	struct list_head	rule_list;
-	int			rule_list_num;
+	struct list_head	obj_list;
+	int			obj_list_num;
 	struct mnl_nlmsg_batch	*batch;
 	struct nft_family_ops	*ops;
 	struct builtin_table	*tables;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH iptables-nftables 2/3] iptables: nft: remove unused code
  2014-06-10  9:30 [PATCH iptables-nftables 1/3] iptables: nft: generalize batch infrastructure Pablo Neira Ayuso
@ 2014-06-10  9:30 ` Pablo Neira Ayuso
  2014-06-10  9:30 ` [PATCH iptables-nftables 3/3] iptables: nft: add tables and chains to the batch Pablo Neira Ayuso
  1 sibling, 0 replies; 3+ messages in thread
From: Pablo Neira Ayuso @ 2014-06-10  9:30 UTC (permalink / raw)
  To: netfilter-devel

Remove code to set table in dormant state, this is not required from
the iptables over nft compatibility layer.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 iptables/nft.c |   56 ++++----------------------------------------------------
 iptables/nft.h |    3 ---
 2 files changed, 4 insertions(+), 55 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index 919b64d..884462c 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -427,9 +427,8 @@ struct builtin_table xtables_arp[TABLES_MAX] = {
 	},
 };
 
-int
-nft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t,
-			bool dormant)
+static int nft_table_builtin_add(struct nft_handle *h,
+				 struct builtin_table *_t)
 {
 	char buf[MNL_SOCKET_BUFFER_SIZE];
 	struct nlmsghdr *nlh;
@@ -444,10 +443,6 @@ 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, h->family,
 					NLM_F_ACK|NLM_F_EXCL, h->seq);
@@ -582,7 +577,7 @@ nft_chain_builtin_init(struct nft_handle *h, const char *table,
 		ret = -1;
 		goto out;
 	}
-	if (nft_table_builtin_add(h, t, false) < 0) {
+	if (nft_table_builtin_add(h, t) < 0) {
 		/* Built-in table already initialized, skip. */
 		if (errno == EEXIST)
 			goto out;
@@ -653,49 +648,6 @@ 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(h, 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, h->family,
-					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
@@ -721,7 +673,7 @@ __nft_chain_set(struct nft_handle *h, const char *table,
 	_t = nft_table_builtin_find(h, table);
 	/* if this built-in table does not exists, create it */
 	if (_t != NULL)
-		nft_table_builtin_add(h, _t, false);
+		nft_table_builtin_add(h, _t);
 
 	_c = nft_chain_builtin_find(_t, chain);
 	if (_c != NULL) {
diff --git a/iptables/nft.h b/iptables/nft.h
index ddc5201..1e78edd 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -53,13 +53,10 @@ void nft_fini(struct nft_handle *h);
 struct nft_table;
 struct nft_chain_list;
 
-int nft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t, bool dormant);
 struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *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);
 int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nft_chain_list *list);
 
 /*
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH iptables-nftables 3/3] iptables: nft: add tables and chains to the batch
  2014-06-10  9:30 [PATCH iptables-nftables 1/3] iptables: nft: generalize batch infrastructure Pablo Neira Ayuso
  2014-06-10  9:30 ` [PATCH iptables-nftables 2/3] iptables: nft: remove unused code Pablo Neira Ayuso
@ 2014-06-10  9:30 ` Pablo Neira Ayuso
  1 sibling, 0 replies; 3+ messages in thread
From: Pablo Neira Ayuso @ 2014-06-10  9:30 UTC (permalink / raw)
  To: netfilter-devel

Since kernel changes:

55dd6f9 ("netfilter: nf_tables: use new transaction infrastructure
to handle table").
91c7b38 ("netfilter: nf_tables: use new transaction infrastructure
to handle chain").

it is possible to put tables and chains in the same batch (which was
already including rules). This patch probes the kernel to check if
if the new transaction is available, otherwise it falls back to the
previous non-transactional approach to handle these two objects.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 iptables/nft.c |  367 +++++++++++++++++++++++++++++++++++++-------------------
 iptables/nft.h |    5 +-
 2 files changed, 249 insertions(+), 123 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index 884462c..2a5f0b9 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -42,6 +42,7 @@
 #include <libnftnl/chain.h>
 #include <libnftnl/rule.h>
 #include <libnftnl/expr.h>
+#include <libnftnl/set.h>
 
 #include <netinet/in.h>	/* inet_ntoa */
 #include <arpa/inet.h>
@@ -269,6 +270,67 @@ static void mnl_nft_batch_end(struct mnl_nlmsg_batch *batch, uint32_t seq)
 	mnl_nft_batch_put(batch, NFNL_MSG_BATCH_END, seq);
 }
 
+enum obj_update_type {
+	NFT_COMPAT_TABLE_ADD,
+	NFT_COMPAT_CHAIN_ADD,
+	NFT_COMPAT_CHAIN_UPDATE,
+	NFT_COMPAT_RULE_APPEND,
+	NFT_COMPAT_RULE_INSERT,
+	NFT_COMPAT_RULE_REPLACE,
+	NFT_COMPAT_RULE_DELETE,
+	NFT_COMPAT_RULE_FLUSH,
+};
+
+enum obj_action {
+	NFT_COMPAT_COMMIT,
+	NFT_COMPAT_ABORT,
+};
+
+struct obj_update {
+	struct list_head	head;
+	enum obj_update_type	type;
+	union {
+		struct nft_table	*table;
+		struct nft_chain	*chain;
+		struct nft_rule		*rule;
+		void			*ptr;
+	};
+};
+
+static int batch_add(struct nft_handle *h, enum obj_update_type type, void *ptr)
+{
+	struct obj_update *obj;
+
+	obj = calloc(1, sizeof(struct obj_update));
+	if (obj == NULL)
+		return -1;
+
+	obj->ptr = ptr;
+	obj->type = type;
+	list_add_tail(&obj->head, &h->obj_list);
+	h->obj_list_num++;
+
+	return 0;
+}
+
+static int batch_table_add(struct nft_handle *h, enum obj_update_type type,
+			   struct nft_table *t)
+{
+	return batch_add(h, type, t);
+}
+
+static int batch_chain_add(struct nft_handle *h, enum obj_update_type type,
+			   struct nft_chain *c)
+{
+	return batch_add(h, type, c);
+}
+
+static int batch_rule_add(struct nft_handle *h, enum obj_update_type type,
+			  struct nft_rule *r)
+{
+	return batch_add(h, type, r);
+}
+
 struct builtin_table xtables_ipv4[TABLES_MAX] = {
 	[RAW] = {
 		.name	= "raw",
@@ -427,25 +489,14 @@ struct builtin_table xtables_arp[TABLES_MAX] = {
 	},
 };
 
-static int nft_table_builtin_add(struct nft_handle *h,
-				 struct builtin_table *_t)
+int nft_table_add(struct nft_handle *h, struct nft_table *t, uint16_t flags)
 {
 	char buf[MNL_SOCKET_BUFFER_SIZE];
 	struct nlmsghdr *nlh;
-	struct nft_table *t;
 	int ret;
 
-	if (_t->initialized)
-		return 0;
-
-	t = nft_table_alloc();
-	if (t == NULL)
-		return -1;
-
-	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)_t->name);
-
 	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
-					NLM_F_ACK|NLM_F_EXCL, h->seq);
+					NLM_F_ACK|flags, h->seq);
 	nft_table_nlmsg_build_payload(nlh, t);
 	nft_table_free(t);
 
@@ -458,7 +509,31 @@ static int nft_table_builtin_add(struct nft_handle *h,
 #endif
 
 	ret = mnl_talk(h, nlh, NULL, NULL);
-	if (ret == 0 || errno == EEXIST)
+
+	return (ret == 0 || (ret == -1 && errno == EEXIST)) ? 0 : -1;
+}
+
+static int nft_table_builtin_add(struct nft_handle *h,
+				 struct builtin_table *_t)
+{
+	struct nft_table *t;
+	int ret;
+
+	if (_t->initialized)
+		return 0;
+
+	t = nft_table_alloc();
+	if (t == NULL)
+		return -1;
+
+	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)_t->name);
+
+	if (h->batch_support)
+		ret = batch_table_add(h, NFT_COMPAT_TABLE_ADD, t);
+	else
+		ret = nft_table_add(h, t, NLM_F_EXCL);
+
+	if (ret == 0)
 		_t->initialized = true;
 
 	return ret;
@@ -484,26 +559,42 @@ nft_chain_builtin_alloc(struct builtin_table *table,
 	return c;
 }
 
-void
-nft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table,
-		      struct builtin_chain *chain, int policy)
+int nft_chain_add(struct nft_handle *h, struct nft_chain *c, uint16_t flags)
 {
 	char buf[MNL_SOCKET_BUFFER_SIZE];
 	struct nlmsghdr *nlh;
-	struct nft_chain *c;
-
-	c = nft_chain_builtin_alloc(table, chain, policy);
-	if (c == NULL)
-		return;
 
 	/* NLM_F_CREATE requests module autoloading */
 	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
-					NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE,
+					NLM_F_ACK|flags|NLM_F_CREATE,
 					h->seq);
 	nft_chain_nlmsg_build_payload(nlh, c);
 	nft_chain_free(c);
 
-	mnl_talk(h, nlh, NULL, NULL);
+#ifdef NLDEBUG
+	char tmp[1024];
+
+	nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
+	printf("DEBUG: chain: %s\n", tmp);
+	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
+#endif
+
+	return mnl_talk(h, nlh, NULL, NULL);
+}
+
+void nft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table,
+			   struct builtin_chain *chain, int policy)
+{
+	struct nft_chain *c;
+
+	c = nft_chain_builtin_alloc(table, chain, policy);
+	if (c == NULL)
+		return;
+
+	if (h->batch_support)
+		batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
+	else
+		nft_chain_add(h, c, NLM_F_EXCL);
 }
 
 /* find if built-in table already exists */
@@ -595,6 +686,49 @@ static bool nft_chain_builtin(struct nft_chain *c)
 	return nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM) != NULL;
 }
 
+static bool mnl_batch_supported(struct nft_handle *h)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	uint32_t seq = 1;
+	int ret;
+
+	mnl_nft_batch_begin(h->batch, seq++);
+
+	nft_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
+				NFT_MSG_NEWSET, AF_INET,
+				NLM_F_ACK, seq++);
+	mnl_nlmsg_batch_next(h->batch);
+
+	mnl_nft_batch_end(h->batch, seq++);
+
+	ret = mnl_socket_sendto(h->nl, mnl_nlmsg_batch_head(h->batch),
+				mnl_nlmsg_batch_size(h->batch));
+	if (ret < 0)
+		goto err;
+
+	mnl_nlmsg_batch_reset(h->batch);
+
+	ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
+	while (ret > 0) {
+		ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(h->nl),
+				 NULL, NULL);
+		if (ret <= 0)
+			break;
+
+		ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
+	}
+
+	/* We're sending an incomplete message to see if the kernel supports
+	 * set messages in batches. EINVAL means that we sent an incomplete
+	 * message with missing attributes. The kernel just ignores messages
+	 * that we cannot include in the batch.
+	 */
+	return (ret == -1 && errno == EINVAL) ? true : false;
+err:
+	mnl_nlmsg_batch_reset(h->batch);
+	return ret;
+}
+
 int nft_init(struct nft_handle *h, struct builtin_table *t)
 {
 	h->nl = mnl_socket_open(NETLINK_NETFILTER);
@@ -613,6 +747,7 @@ int nft_init(struct nft_handle *h, struct builtin_table *t)
 	INIT_LIST_HEAD(&h->obj_list);
 
 	h->batch = mnl_nft_batch_alloc();
+	h->batch_support = mnl_batch_supported(h);
 
 	return 0;
 }
@@ -624,30 +759,6 @@ void nft_fini(struct nft_handle *h)
 	mnl_nlmsg_batch_stop(h->batch);
 }
 
-int nft_table_add(struct nft_handle *h, const struct nft_table *t)
-{
-	char buf[MNL_SOCKET_BUFFER_SIZE];
-	struct nlmsghdr *nlh;
-
-	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
-					NLM_F_ACK|NLM_F_EXCL, h->seq);
-	nft_table_nlmsg_build_payload(nlh, t);
-
-	return mnl_talk(h, nlh, NULL, NULL);
-}
-
-int nft_chain_add(struct nft_handle *h, const struct nft_chain *c)
-{
-	char buf[MNL_SOCKET_BUFFER_SIZE];
-	struct nlmsghdr *nlh;
-
-	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
-					NLM_F_ACK|NLM_F_EXCL, h->seq);
-	nft_chain_nlmsg_build_payload(nlh, c);
-
-	return mnl_talk(h, nlh, NULL, NULL);
-}
-
 static void nft_chain_print_debug(struct nft_chain *c, struct nlmsghdr *nlh)
 {
 #ifdef NLDEBUG
@@ -659,13 +770,11 @@ static void nft_chain_print_debug(struct nft_chain *c, struct nlmsghdr *nlh)
 #endif
 }
 
-static int
-__nft_chain_set(struct nft_handle *h, const char *table,
-		const char *chain, int policy,
-		const struct xt_counters *counters)
+static struct nft_chain *nft_chain_new(struct nft_handle *h,
+				       const char *table, const char *chain,
+				       int policy,
+				       const struct xt_counters *counters)
 {
-	char buf[MNL_SOCKET_BUFFER_SIZE];
-	struct nlmsghdr *nlh;
 	struct nft_chain *c;
 	struct builtin_table *_t;
 	struct builtin_chain *_c;
@@ -680,10 +789,10 @@ __nft_chain_set(struct nft_handle *h, const char *table,
 		/* This is a built-in chain */
 		c = nft_chain_builtin_alloc(_t, _c, policy);
 		if (c == NULL)
-			return -1;
+			return NULL;
 	} else {
 		errno = ENOENT;
-		return -1;
+		return NULL;
 	}
 
 	if (counters) {
@@ -693,30 +802,30 @@ __nft_chain_set(struct nft_handle *h, const char *table,
 					counters->pcnt);
 	}
 
-	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
-					h->restore ? NLM_F_ACK|NLM_F_CREATE :
-					NLM_F_ACK, h->seq);
-	nft_chain_nlmsg_build_payload(nlh, c);
-
-	nft_chain_print_debug(c, nlh);
-
-	nft_chain_free(c);
-
-	return mnl_talk(h, nlh, NULL, NULL);
+	return c;
 }
 
 int nft_chain_set(struct nft_handle *h, const char *table,
 		  const char *chain, const char *policy,
 		  const struct xt_counters *counters)
 {
-	int ret = -1;
+	struct nft_chain *c = NULL;
+	int ret;
 
 	nft_fn = nft_chain_set;
 
 	if (strcmp(policy, "DROP") == 0)
-		ret = __nft_chain_set(h, table, chain, NF_DROP, counters);
+		c = nft_chain_new(h, table, chain, NF_DROP, counters);
 	else if (strcmp(policy, "ACCEPT") == 0)
-		ret = __nft_chain_set(h, table, chain, NF_ACCEPT, counters);
+		c = nft_chain_new(h, table, chain, NF_ACCEPT, counters);
+
+	if (c == NULL)
+		return 0;
+
+	if (h->batch_support)
+		ret = batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c);
+	else
+		ret = nft_chain_add(h, c, 0);
 
 	/* the core expects 1 for success and 0 for error */
 	return ret == 0 ? 1 : 0;
@@ -901,39 +1010,6 @@ err:
 	return NULL;
 }
 
-enum obj_update_type {
-	NFT_COMPAT_RULE_APPEND,
-	NFT_COMPAT_RULE_INSERT,
-	NFT_COMPAT_RULE_REPLACE,
-	NFT_COMPAT_RULE_DELETE,
-	NFT_COMPAT_RULE_FLUSH,
-	NFT_COMPAT_COMMIT,
-	NFT_COMPAT_ABORT,
-};
-
-struct obj_update {
-       struct list_head		head;
-       enum obj_update_type	type;
-       struct nft_rule		*rule;
-};
-
-static int batch_rule_add(struct nft_handle *h, enum obj_update_type type,
-			  struct nft_rule *r)
-{
-	struct obj_update *obj;
-
-	obj = calloc(1, sizeof(struct obj_update));
-	if (obj == NULL)
-		return -1;
-
-	obj->rule = r;
-	obj->type = type;
-	list_add_tail(&obj->head, &h->obj_list);
-	h->obj_list_num++;
-
-	return 0;
-}
-
 int
 nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
 		void *data, uint64_t handle, bool verbose)
@@ -2129,45 +2205,94 @@ error:
 	return ret;
 }
 
+static void nft_compat_table_batch_add(struct nft_handle *h, uint16_t type,
+				       uint16_t flags, uint32_t seq,
+				       struct nft_table *table)
+{
+	struct nlmsghdr *nlh;
+
+	nlh = nft_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
+					type, h->family, flags, seq);
+	nft_table_nlmsg_build_payload(nlh, table);
+	nft_table_free(table);
+}
+
+static void nft_compat_chain_batch_add(struct nft_handle *h, uint16_t type,
+				       uint16_t flags, uint32_t seq,
+				       struct nft_chain *chain)
+{
+	struct nlmsghdr *nlh;
+
+	nlh = nft_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
+					type, h->family, flags, seq);
+	nft_chain_nlmsg_build_payload(nlh, chain);
+	nft_chain_print_debug(chain, nlh);
+	nft_chain_free(chain);
+}
+
+static void nft_compat_rule_batch_add(struct nft_handle *h, uint16_t type,
+				      uint16_t flags, uint32_t seq,
+				      struct nft_rule *rule)
+{
+	struct nlmsghdr *nlh;
+
+	nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
+				       type, h->family, flags, seq);
+	nft_rule_nlmsg_build_payload(nlh, rule);
+	nft_rule_print_debug(rule, nlh);
+	nft_rule_free(rule);
+}
+
 static int nft_action(struct nft_handle *h, int action)
 {
-	int flags = NLM_F_CREATE, type;
 	struct obj_update *n, *tmp;
-	struct nlmsghdr *nlh;
 	uint32_t seq = 1;
-	int ret;
+	int ret = 0;
 
 	mnl_nft_batch_begin(h->batch, seq++);
 
 	list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
 		switch (n->type) {
+		case NFT_COMPAT_TABLE_ADD:
+			nft_compat_table_batch_add(h, NFT_MSG_NEWTABLE,
+						   NLM_F_CREATE, seq++,
+						   n->table);
+			break;
+		case NFT_COMPAT_CHAIN_ADD:
+			nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
+						   NLM_F_CREATE, seq++,
+						   n->chain);
+			break;
+		case NFT_COMPAT_CHAIN_UPDATE:
+			nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
+						   h->restore ?
+						     NLM_F_CREATE : 0,
+						   seq++, n->chain);
+			break;
 		case NFT_COMPAT_RULE_APPEND:
-			type = NFT_MSG_NEWRULE;
-			flags |= NLM_F_APPEND;
+			nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
+						  NLM_F_CREATE | NLM_F_APPEND,
+						  seq++, n->rule);
 			break;
 		case NFT_COMPAT_RULE_INSERT:
-			type = NFT_MSG_NEWRULE;
+			nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
+						  NLM_F_CREATE, seq++,
+						  n->rule);
 			break;
 		case NFT_COMPAT_RULE_REPLACE:
-			type = NFT_MSG_NEWRULE;
-			flags |= NLM_F_REPLACE;
+			nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
+						  NLM_F_CREATE | NLM_F_REPLACE,
+						  seq++, n->rule);
 			break;
 		case NFT_COMPAT_RULE_DELETE:
 		case NFT_COMPAT_RULE_FLUSH:
-			type = NFT_MSG_DELRULE;
+			nft_compat_rule_batch_add(h, NFT_MSG_DELRULE, 0,
+						  seq++, n->rule);
 			break;
-		default:
-			return 0;
 		}
 
-		nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
-					       type, h->family, flags, seq++);
-		nft_rule_nlmsg_build_payload(nlh, n->rule);
-		nft_rule_print_debug(n->rule, nlh);
-
 		h->obj_list_num--;
 		list_del(&n->head);
-		nft_rule_free(n->rule);
 		free(n);
 
 		if (!mnl_nlmsg_batch_next(h->batch))
@@ -2364,7 +2489,7 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
 
 		found = true;
 
-		if (nft_table_add(h, table) < 0) {
+		if (batch_table_add(h, NFT_COMPAT_TABLE_ADD, table) < 0) {
 			if (errno == EEXIST) {
 				xtables_config_perror(flags,
 					"table `%s' already exists, skipping\n",
@@ -2395,7 +2520,7 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
 		if (h->family != chain_family)
 			continue;
 
-		if (nft_chain_add(h, chain) < 0) {
+		if (batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, chain) < 0) {
 			if (errno == EEXIST) {
 				xtables_config_perror(flags,
 					"chain `%s' already exists in table `%s', skipping\n",
diff --git a/iptables/nft.h b/iptables/nft.h
index 1e78edd..339d7bc 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -36,6 +36,7 @@ struct nft_handle {
 	struct nft_family_ops	*ops;
 	struct builtin_table	*tables;
 	bool			restore;
+	bool			batch_support;
 };
 
 extern struct builtin_table xtables_ipv4[TABLES_MAX];
@@ -54,7 +55,7 @@ struct nft_table;
 struct nft_chain_list;
 
 struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table);
-int nft_table_add(struct nft_handle *h, const struct nft_table *t);
+int nft_table_add(struct nft_handle *h, struct nft_table *t, uint16_t flags);
 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_purge_chains(struct nft_handle *h, const char *table, struct nft_chain_list *list);
@@ -68,7 +69,7 @@ struct nft_chain *nft_chain_builtin_alloc(struct builtin_table *table, struct bu
 void nft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table, struct builtin_chain *chain, int policy);
 struct builtin_chain *nft_chain_builtin_find(struct builtin_table *t, const char *chain);
 int nft_chain_builtin_init(struct nft_handle *h, const char *table, const char *chain, int policy);
-int nft_chain_add(struct nft_handle *h, const struct nft_chain *c);
+int nft_chain_add(struct nft_handle *h, struct nft_chain *c, uint16_t flags);
 int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters);
 struct nft_chain_list *nft_chain_dump(struct nft_handle *h);
 struct nft_chain *nft_chain_list_find(struct nft_chain_list *list, const char *table, const char *chain);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-06-10  9:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-10  9:30 [PATCH iptables-nftables 1/3] iptables: nft: generalize batch infrastructure Pablo Neira Ayuso
2014-06-10  9:30 ` [PATCH iptables-nftables 2/3] iptables: nft: remove unused code Pablo Neira Ayuso
2014-06-10  9:30 ` [PATCH iptables-nftables 3/3] iptables: nft: add tables and chains to the batch Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).