netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC libnftnl PATCH 0/2] New mnlio functions
@ 2014-02-05 19:17 Arturo Borrero Gonzalez
  2014-02-05 19:17 ` [RFC libnftnl PATCH 1/2] src: add mnlio API functions Arturo Borrero Gonzalez
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-02-05 19:17 UTC (permalink / raw)
  To: netfilter-devel; +Cc: pablo

These functions are likely to be reused by almost all programs
that want to talk with the kernel subsystem.

We can add here to libnftnl or maybe put in a higher level library.

Let this patchset be a RFC about this subject.

An example of what means using the new mnlio approach is the
examples/nft-rule-add.c file. We save lots of LOCs.

Comments welcome.

NOTE: this patchset would require several iterations. For example,
I left behind batch_pages.
---

Arturo Borrero Gonzalez (2):
      src: add mnlio API functions
      examples: use new mnlio API in nft-rule-add.c


 examples/nft-rule-add.c      |   87 ----
 include/libnftnl/Makefile.am |    3 
 include/libnftnl/mnlio.h     |   92 ++++
 src/Makefile.am              |    1 
 src/libnftnl.map             |   37 ++
 src/mnlio.c                  |  957 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 1096 insertions(+), 81 deletions(-)
 create mode 100644 include/libnftnl/mnlio.h
 create mode 100644 src/mnlio.c

-- 
Arturo Borrero Gonzalez

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

* [RFC libnftnl PATCH 1/2] src: add mnlio API functions
  2014-02-05 19:17 [RFC libnftnl PATCH 0/2] New mnlio functions Arturo Borrero Gonzalez
@ 2014-02-05 19:17 ` Arturo Borrero Gonzalez
  2014-02-12 14:03   ` Pablo Neira Ayuso
  2014-02-05 19:17 ` [RFC libnftnl PATCH 2/2] examples: use new mnlio API in nft-rule-add.c Arturo Borrero Gonzalez
  2014-02-05 19:24 ` [RFC libnftnl PATCH 0/2] New mnlio functions Patrick McHardy
  2 siblings, 1 reply; 5+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-02-05 19:17 UTC (permalink / raw)
  To: netfilter-devel; +Cc: pablo

These functions are likely to be used by all userspace programs to interact
with the nftables kernel subsystem.

Lets put in the library, so: its easy to maintain, we can save lots of LOCs,
programmers can easily learn how to work with nftables, etc..

This patch will require several iterations: batch_pages are left behind.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
 include/libnftnl/Makefile.am |    3 
 include/libnftnl/mnlio.h     |   92 ++++
 src/Makefile.am              |    1 
 src/libnftnl.map             |   37 ++
 src/mnlio.c                  |  957 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 1089 insertions(+), 1 deletion(-)
 create mode 100644 include/libnftnl/mnlio.h
 create mode 100644 src/mnlio.c

diff --git a/include/libnftnl/Makefile.am b/include/libnftnl/Makefile.am
index a0841d2..cf703bb 100644
--- a/include/libnftnl/Makefile.am
+++ b/include/libnftnl/Makefile.am
@@ -4,4 +4,5 @@ pkginclude_HEADERS = table.h		\
 		     expr.h		\
 		     set.h		\
 		     ruleset.h		\
-		     common.h
+		     common.h		\
+		     mnlio.h
diff --git a/include/libnftnl/mnlio.h b/include/libnftnl/mnlio.h
new file mode 100644
index 0000000..e517d70
--- /dev/null
+++ b/include/libnftnl/mnlio.h
@@ -0,0 +1,92 @@
+#ifndef _LIBNFTNL_MNLIO_H_
+#define _LIBNFTNL_MNLIO_H_
+
+#include <libnftnl/ruleset.h>
+#include <libnftnl/table.h>
+#include <libnftnl/chain.h>
+#include <libnftnl/set.h>
+#include <libnftnl/rule.h>
+
+int
+nft_mnlio_talk(struct mnl_socket *nf_sock, const void *data, unsigned int len,
+	       int (*cb)(const struct nlmsghdr *nlh, void *data),
+	       void *cb_data);
+void nft_mnlio_batch_put(struct mnl_nlmsg_batch *batch, int type,
+			 uint32_t seq);
+int nft_mnlio_batch_talk(struct mnl_socket *nl, struct mnl_nlmsg_batch *b);
+void nft_mnlio_batch_begin(struct mnl_nlmsg_batch *batch);
+void nft_mnlio_batch_end(struct mnl_nlmsg_batch *batch);
+struct mnl_nlmsg_batch *nft_mnlio_batch_alloc(void);
+bool nft_mnlio_batch_ready(struct mnl_nlmsg_batch *batch);
+void nft_mnlio_batch_reset(struct mnl_nlmsg_batch *batch);
+
+int nft_mnlio_rule_add(struct nft_rule *nlr, unsigned int flags,
+		       struct mnl_nlmsg_batch *batch);
+int nft_mnlio_rule_list_add(struct nft_rule_list *nlrl, unsigned int flags,
+			    struct mnl_nlmsg_batch *batch);
+int nft_mnlio_rule_del(struct nft_rule *nlr, unsigned int flags,
+		       struct mnl_nlmsg_batch *batch);
+struct nft_rule_list *
+nft_mnlio_rule_dump(struct mnl_socket *nf_sock, int family);
+
+int nft_mnlio_chain_add(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+			unsigned int flags);
+int nft_mnlio_chain_list_add(struct mnl_socket *nf_sock,
+			     struct nft_chain_list *nlcl,
+			     unsigned int flags);
+int nft_mnlio_chain_delete(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+			   unsigned int flags);
+int nft_mnlio_chain_list_delete(struct mnl_socket *nfsock,
+				struct nft_chain_list *nlcl,
+				unsigned int flags);
+struct nft_chain_list *
+nft_mnlio_chain_dump(struct mnl_socket *nf_sock, int family);
+int nft_mnlio_chain_get(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+			unsigned int flags);
+
+int nft_mnlio_table_add(struct mnl_socket *nf_sock, struct nft_table *nlt,
+			unsigned int flags);
+int nft_mnlio_table_list_add(struct mnl_socket *nf_sock,
+			     struct nft_table_list *nltl,
+			     unsigned int flags);
+int nft_mnlio_table_delete(struct mnl_socket *nf_sock, struct nft_table *nlt,
+			   unsigned int flags);
+int nft_mnlio_table_list_delete(struct mnl_socket *nfsock,
+				struct nft_table_list *nltl,
+				unsigned int flags);
+struct nft_table_list *
+nft_mnlio_table_dump(struct mnl_socket *nf_sock, int family);
+int nft_mnlio_table_get(struct mnl_socket *nf_sock, struct nft_table *nlt,
+			unsigned int flags);
+
+int nft_mnlio_set_add(struct mnl_socket *nf_sock, struct nft_set *nls,
+		      unsigned int flags);
+int nft_mnlio_set_list_add(struct mnl_socket *nf_sock,
+			   struct nft_set_list *nlsl,
+			   unsigned int flags);
+int nft_mnlio_set_delete(struct mnl_socket *nf_sock, struct nft_set *nls,
+			 unsigned int flags);
+int nft_mnlio_set_list_delete(struct mnl_socket *nfsock,
+			      struct nft_set_list *nlsl, unsigned int flags);
+struct nft_set_list *
+nft_mnlio_set_dump(struct mnl_socket *nf_sock, int family, const char *table);
+int nft_mnlio_set_get(struct mnl_socket *nf_sock, struct nft_set *nls);
+
+int nft_mnlio_setelem_add(struct mnl_socket *nf_sock, struct nft_set *nls,
+			  unsigned int flags);
+
+int nft_mnlio_setelem_list_add(struct mnl_socket *nf_sock,
+			       struct nft_set_list *nlsl,
+			       unsigned int flags);
+int nft_mnlio_setelem_delete(struct mnl_socket *nf_sock, struct nft_set *nls,
+			     unsigned int flags);
+int nft_mnlio_setelem_get(struct mnl_socket *nf_sock, struct nft_set *nls);
+
+struct nft_ruleset *
+nft_mnlio_ruleset_dump(struct mnl_socket *nf_sock, uint32_t family);
+int nft_mnlio_ruleset_add(struct mnl_socket *nf_sock, struct nft_ruleset *rs,
+			  unsigned int tflags, unsigned int cflags,
+			  unsigned int rflags, unsigned int sflags,
+			  unsigned int seflags, struct mnl_nlmsg_batch *batch);
+
+#endif /* _LIBNFTNL_MNLIO_H_ */
diff --git a/src/Makefile.am b/src/Makefile.am
index 450279f..ba1eb49 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,6 +35,7 @@ libnftnl_la_SOURCES = utils.c		\
 		      expr/reject.c	\
 		      expr/target.c	\
 		      expr/data_reg.h	\
+		      mnlio.c		\
 		      libnftnl.map	\
 		      expr_ops.h	\
 		      internal.h
diff --git a/src/libnftnl.map b/src/libnftnl.map
index 43378ed..acc7201 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -194,5 +194,42 @@ global:
   nft_parse_err_free;
   nft_parse_perror;
 
+  nft_mnlio_talk;
+  nft_mnlio_batch_put;
+  nft_mnlio_batch_talk;
+  nft_mnlio_batch_begin;
+  nft_mnlio_batch_end;
+  nft_mnlio_batch_alloc;
+  nft_mnlio_batch_ready;
+  nft_mnlio_batch_reset;
+  nft_mnlio_rule_add;
+  nft_mnlio_rule_list_add;
+  nft_mnlio_rule_del;
+  nft_mnlio_rule_dump;
+  nft_mnlio_chain_add;
+  nft_mnlio_chain_list_add;
+  nft_mnlio_chain_delete;
+  nft_mnlio_chain_list_delete;
+  nft_mnlio_chain_dump;
+  nft_mnlio_chain_get;
+  nft_mnlio_table_add;
+  nft_mnlio_table_list_add;
+  nft_mnlio_table_delete;
+  nft_mnlio_table_list_delete;
+  nft_mnlio_table_dump;
+  nft_mnlio_table_get;
+  nft_mnlio_set_add;
+  nft_mnlio_set_list_add;
+  nft_mnlio_set_delete;
+  nft_mnlio_set_list_delete;
+  nft_mnlio_set_dump;
+  nft_mnlio_set_get;
+  nft_mnlio_setelem_add;
+  nft_mnlio_setelem_list_add;
+  nft_mnlio_setelem_delete;
+  nft_mnlio_setelem_get;
+  nft_mnlio_ruleset_dump;
+  nft_mnlio_ruleset_add;
+
 local: *;
 };
diff --git a/src/mnlio.c b/src/mnlio.c
new file mode 100644
index 0000000..8e558dd
--- /dev/null
+++ b/src/mnlio.c
@@ -0,0 +1,957 @@
+/*
+ * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include "internal.h"
+
+#include <libmnl/libmnl.h>
+#include <libnftnl/common.h>
+#include <libnftnl/ruleset.h>
+#include <libnftnl/table.h>
+#include <libnftnl/chain.h>
+#include <libnftnl/rule.h>
+#include <libnftnl/expr.h>
+#include <libnftnl/set.h>
+#include <libnftnl/mnlio.h>
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nf_tables.h>
+
+#include <errno.h>
+
+static uint32_t seq;
+
+static uint32_t nft_mnlio_seqnum_alloc(void)
+{
+	return seq++;
+}
+
+int
+nft_mnlio_talk(struct mnl_socket *nf_sock, const void *data, unsigned int len,
+	       int (*cb)(const struct nlmsghdr *nlh, void *data),
+	       void *cb_data)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	uint32_t portid = mnl_socket_get_portid(nf_sock);
+	int ret;
+
+	if (mnl_socket_sendto(nf_sock, data, len) < 0)
+		return -1;
+
+	ret = mnl_socket_recvfrom(nf_sock, buf, sizeof(buf));
+	while (ret > 0) {
+		ret = mnl_cb_run(buf, ret, seq, portid, cb, cb_data);
+		if (ret <= 0)
+			goto out;
+
+		ret = mnl_socket_recvfrom(nf_sock, buf, sizeof(buf));
+	}
+out:
+	if (ret < 0 && errno == EAGAIN)
+		return 0;
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_talk);
+
+/*
+ * Batching
+ */
+
+/* selected batch page is 256 Kbytes long to load ruleset of
+ * half a million rules without hitting -EMSGSIZE due to large
+ * iovec.
+ */
+#define BATCH_PAGE_SIZE (getpagesize() * 32)
+
+struct mnl_nlmsg_batch *nft_mnlio_batch_alloc(void)
+{
+	static char *buf;
+
+	/* libmnl needs higher buffer to handle batch overflows */
+	buf = malloc(BATCH_PAGE_SIZE + getpagesize());
+	if (buf == NULL)
+		return NULL;
+
+	return mnl_nlmsg_batch_start(buf, BATCH_PAGE_SIZE);
+}
+EXPORT_SYMBOL(nft_mnlio_batch_alloc);
+
+bool nft_mnlio_batch_ready(struct mnl_nlmsg_batch *batch)
+{
+	/* Check if the batch only contains the initial and trailing batch
+	 * messages. In that case, the batch is empty.
+	 */
+	return mnl_nlmsg_batch_size(batch) != (NLMSG_HDRLEN+sizeof(struct nfgenmsg)) * 2;
+}
+EXPORT_SYMBOL(nft_mnlio_batch_ready);
+
+void nft_mnlio_batch_reset(struct mnl_nlmsg_batch *batch)
+{
+	mnl_nlmsg_batch_reset(batch);
+}
+EXPORT_SYMBOL(nft_mnlio_batch_reset);
+
+void nft_mnlio_batch_put(struct mnl_nlmsg_batch *batch, int type,
+			 uint32_t seqnum)
+{
+	struct nlmsghdr *nlh;
+	struct nfgenmsg *nfg;
+
+	nlh = mnl_nlmsg_put_header(mnl_nlmsg_batch_current(batch));
+	nlh->nlmsg_type = type;
+	nlh->nlmsg_flags = NLM_F_REQUEST;
+	nlh->nlmsg_seq = seqnum;
+
+	nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
+	nfg->nfgen_family = AF_INET;
+	nfg->version = NFNETLINK_V0;
+	nfg->res_id = NFNL_SUBSYS_NFTABLES;
+
+	mnl_nlmsg_batch_next(batch);
+}
+EXPORT_SYMBOL(nft_mnlio_batch_put);
+
+void nft_mnlio_batch_begin(struct mnl_nlmsg_batch *b)
+{
+	nft_mnlio_batch_put(b, NFNL_MSG_BATCH_BEGIN,
+			    nft_mnlio_seqnum_alloc());
+}
+EXPORT_SYMBOL(nft_mnlio_batch_begin);
+
+void nft_mnlio_batch_end(struct mnl_nlmsg_batch *b)
+{
+	nft_mnlio_batch_put(b, NFNL_MSG_BATCH_END,
+			    nft_mnlio_seqnum_alloc());
+}
+EXPORT_SYMBOL(nft_mnlio_batch_end);
+
+int nft_mnlio_batch_talk(struct mnl_socket *nl, struct mnl_nlmsg_batch *b)
+{
+	int ret, fd = mnl_socket_get_fd(nl);
+	char rcv_buf[MNL_SOCKET_BUFFER_SIZE];
+	fd_set readfds;
+	struct timeval tv = {
+		.tv_sec		= 0,
+		.tv_usec	= 0
+	};
+
+	ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(b),
+				mnl_nlmsg_batch_size(b));
+	if (ret == -1)
+		goto err;
+
+	FD_ZERO(&readfds);
+	FD_SET(fd, &readfds);
+
+	/* receive and digest all the acknowledgments from the kernel. */
+	ret = select(fd+1, &readfds, NULL, NULL, &tv);
+	if (ret == -1)
+		goto err;
+
+	while (ret > 0 && FD_ISSET(fd, &readfds)) {
+		ret = mnl_socket_recvfrom(nl, rcv_buf, sizeof(rcv_buf));
+		if (ret == -1)
+			goto err;
+
+		ret = mnl_cb_run(rcv_buf, ret, 0, mnl_socket_get_portid(nl),
+				 NULL, NULL);
+		if (ret < 0)
+			goto err;
+
+		ret = select(fd+1, &readfds, NULL, NULL, &tv);
+		if (ret == -1)
+			goto err;
+
+		FD_ZERO(&readfds);
+		FD_SET(fd, &readfds);
+	}
+err:
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_batch_talk);
+
+/*
+ * Rule
+ */
+int nft_mnlio_rule_add(struct nft_rule *nlr, unsigned int flags,
+		       struct mnl_nlmsg_batch *batch)
+{
+	struct nlmsghdr *nlh;
+
+	nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
+			NFT_MSG_NEWRULE,
+			nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY),
+			NLM_F_CREATE | flags, nft_mnlio_seqnum_alloc());
+
+	nft_rule_nlmsg_build_payload(nlh, nlr);
+
+	return 0;
+}
+EXPORT_SYMBOL(nft_mnlio_rule_add);
+
+int nft_mnlio_rule_list_add(struct nft_rule_list *nlrl, unsigned int flags,
+			    struct mnl_nlmsg_batch *batch)
+{
+	int ret = 0;
+	struct nft_rule_list_iter *i;
+	struct nft_rule *r;
+
+	i = nft_rule_list_iter_create(nlrl);
+	if (i == NULL)
+		return -1;
+
+	r = nft_rule_list_iter_next(i);
+	while (r != NULL) {
+		ret = nft_mnlio_rule_add(r, flags, batch);
+		if (ret != 0)
+			return ret;
+
+		r = nft_rule_list_iter_next(i);
+	}
+	nft_rule_list_iter_destroy(i);
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_rule_list_add);
+
+int nft_mnlio_rule_del(struct nft_rule *nlr, unsigned int flags,
+		       struct mnl_nlmsg_batch *batch)
+{
+	struct nlmsghdr *nlh;
+
+	nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
+			NFT_MSG_DELRULE,
+			nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY),
+			0, nft_mnlio_seqnum_alloc());
+
+	nft_rule_nlmsg_build_payload(nlh, nlr);
+
+	return 0;
+}
+EXPORT_SYMBOL(nft_mnlio_rule_del);
+
+static int rule_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nft_rule_list *nlr_list = data;
+	struct nft_rule *r;
+
+	r = nft_rule_alloc();
+	if (r == NULL)
+		return -1;
+
+	if (nft_rule_nlmsg_parse(nlh, r) < 0)
+		goto err_free;
+
+	nft_rule_list_add_tail(r, nlr_list);
+	return MNL_CB_OK;
+
+err_free:
+	nft_rule_free(r);
+	return MNL_CB_OK;
+}
+
+struct nft_rule_list *
+nft_mnlio_rule_dump(struct mnl_socket *nf_sock, int family)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+	struct nft_rule_list *nlr_list;
+	int ret;
+
+	nlr_list = nft_rule_list_alloc();
+	if (nlr_list == NULL)
+		return NULL;
+
+	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family,
+				       NLM_F_DUMP, seq);
+
+	ret = nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, rule_cb, nlr_list);
+	if (ret < 0)
+		goto err;
+
+	return nlr_list;
+err:
+	nft_rule_list_free(nlr_list);
+	return NULL;
+}
+EXPORT_SYMBOL(nft_mnlio_rule_dump);
+
+/*
+ * Chain
+ */
+int nft_mnlio_chain_add(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+			unsigned int flags)
+
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
+			nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
+			NLM_F_CREATE | NLM_F_ACK | flags, seq);
+	nft_chain_nlmsg_build_payload(nlh, nlc);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
+}
+EXPORT_SYMBOL(nft_mnlio_chain_add);
+
+
+int nft_mnlio_chain_list_add(struct mnl_socket *nf_sock,
+			     struct nft_chain_list *nlcl,
+			     unsigned int flags)
+{
+	int ret = 0;
+	struct nft_chain_list_iter *i;
+	struct nft_chain *c;
+
+	i = nft_chain_list_iter_create(nlcl);
+	if (i == NULL)
+		return -1;
+
+	c = nft_chain_list_iter_next(i);
+	while (c != NULL) {
+		ret = nft_mnlio_chain_add(nf_sock, c, flags);
+
+		if (ret != 0)
+			break;
+
+		c = nft_chain_list_iter_next(i);
+	}
+	nft_chain_list_iter_destroy(i);
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_chain_list_add);
+
+int nft_mnlio_chain_delete(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+			   unsigned int flags)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN,
+			nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
+			NLM_F_ACK, seq);
+	nft_chain_nlmsg_build_payload(nlh, nlc);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
+}
+EXPORT_SYMBOL(nft_mnlio_chain_delete);
+
+int nft_mnlio_chain_list_delete(struct mnl_socket *nfsock,
+				struct nft_chain_list *nlcl,
+				unsigned int flags)
+{
+	struct nft_chain_list_iter *i;
+	struct nft_chain *c;
+	int ret = 0;
+
+	i = nft_chain_list_iter_create(nlcl);
+	if (i == NULL)
+		return -1;
+
+	c = nft_chain_list_iter_next(i);
+	while (c != NULL) {
+		ret = nft_mnlio_chain_delete(nfsock, c, flags);
+
+		if (ret < 0)
+			break;
+
+		c = nft_chain_list_iter_next(i);
+	}
+	nft_chain_list_iter_destroy(i);
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_chain_list_delete);
+
+static int chain_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nft_chain_list *nlc_list = data;
+	struct nft_chain *c;
+
+	c = nft_chain_alloc();
+	if (c == NULL)
+		return -1;
+
+	if (nft_chain_nlmsg_parse(nlh, c) < 0)
+		goto err_free;
+
+	nft_chain_list_add_tail(c, nlc_list);
+	return MNL_CB_OK;
+
+err_free:
+	nft_chain_free(c);
+	return MNL_CB_OK;
+}
+
+struct nft_chain_list *
+nft_mnlio_chain_dump(struct mnl_socket *nf_sock, int family)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+	struct nft_chain_list *nlc_list;
+	int ret;
+
+	nlc_list = nft_chain_list_alloc();
+	if (nlc_list == NULL)
+		return NULL;
+
+	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, family,
+					NLM_F_DUMP, seq);
+
+	ret = nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, chain_cb, nlc_list);
+	if (ret < 0)
+		goto err;
+
+	return nlc_list;
+err:
+	nft_chain_list_free(nlc_list);
+	return NULL;
+}
+EXPORT_SYMBOL(nft_mnlio_chain_dump);
+
+static int chain_get_cb(const struct nlmsghdr *nlh, void *data)
+{
+	nft_chain_nlmsg_parse(nlh, data);
+	return MNL_CB_OK;
+}
+
+int nft_mnlio_chain_get(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+			unsigned int flags)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN,
+			nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
+			NLM_F_ACK | flags, seq);
+	nft_chain_nlmsg_build_payload(nlh, nlc);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, chain_get_cb, nlc);
+}
+EXPORT_SYMBOL(nft_mnlio_chain_get);
+
+/*
+ * Table
+ */
+int nft_mnlio_table_add(struct mnl_socket *nf_sock, struct nft_table *nlt,
+			unsigned int flags)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE,
+			nft_table_attr_get_u32(nlt, NFT_TABLE_ATTR_FAMILY),
+			NLM_F_ACK | flags, seq);
+	nft_table_nlmsg_build_payload(nlh, nlt);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
+}
+EXPORT_SYMBOL(nft_mnlio_table_add);
+
+int nft_mnlio_table_list_add(struct mnl_socket *nf_sock,
+			     struct nft_table_list *nltl,
+			     unsigned int flags)
+{
+	int ret = 0;
+	struct nft_table_list_iter *i;
+	struct nft_table *t;
+
+	i = nft_table_list_iter_create(nltl);
+	if (i == NULL)
+		return -1;
+
+	t = nft_table_list_iter_next(i);
+	while (t != NULL) {
+		ret = nft_mnlio_table_add(nf_sock, t, flags);
+
+		if (ret != 0)
+			break;
+
+		t = nft_table_list_iter_next(i);
+	}
+	nft_table_list_iter_destroy(i);
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_table_list_add);
+
+int nft_mnlio_table_delete(struct mnl_socket *nf_sock, struct nft_table *nlt,
+			   unsigned int flags)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_DELTABLE,
+			nft_table_attr_get_u32(nlt, NFT_TABLE_ATTR_FAMILY),
+			NLM_F_ACK, seq);
+	nft_table_nlmsg_build_payload(nlh, nlt);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
+}
+EXPORT_SYMBOL(nft_mnlio_table_delete);
+
+int nft_mnlio_table_list_delete(struct mnl_socket *nfsock,
+				struct nft_table_list *nltl,
+				unsigned int flags)
+{
+	struct nft_table_list_iter *i;
+	struct nft_table *t;
+	int ret = 0;
+
+	i = nft_table_list_iter_create(nltl);
+	if (i == NULL)
+		return -1;
+
+	t = nft_table_list_iter_next(i);
+	while (t != NULL) {
+		ret = nft_mnlio_table_delete(nfsock, t, flags);
+
+		if (ret < 0)
+			break;
+
+		t = nft_table_list_iter_next(i);
+	}
+	nft_table_list_iter_destroy(i);
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_table_list_delete);
+
+static int table_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nft_table_list *nlt_list = data;
+	struct nft_table *t;
+
+	t = nft_table_alloc();
+	if (t == NULL)
+		return -1;
+
+	if (nft_table_nlmsg_parse(nlh, t) < 0)
+		goto err_free;
+
+	nft_table_list_add_tail(t, nlt_list);
+	return MNL_CB_OK;
+
+err_free:
+	nft_table_free(t);
+	return MNL_CB_OK;
+}
+
+struct nft_table_list *
+nft_mnlio_table_dump(struct mnl_socket *nf_sock, int family)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+	struct nft_table_list *nlt_list;
+	int ret;
+
+	nlt_list = nft_table_list_alloc();
+	if (nlt_list == NULL)
+		return NULL;
+
+	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family,
+					NLM_F_DUMP, seq);
+
+	ret = nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, table_cb, nlt_list);
+	if (ret < 0)
+		goto err;
+
+	return nlt_list;
+err:
+	nft_table_list_free(nlt_list);
+	return NULL;
+}
+EXPORT_SYMBOL(nft_mnlio_table_dump);
+
+static int table_get_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nft_table *t = data;
+
+	nft_table_nlmsg_parse(nlh, t);
+	return MNL_CB_OK;
+}
+
+int nft_mnlio_table_get(struct mnl_socket *nf_sock, struct nft_table *nlt,
+			unsigned int flags)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+	uint32_t family;
+
+	family = nft_table_attr_get_u32(nlt, NFT_TABLE_ATTR_FAMILY);
+	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, family,
+					NLM_F_ACK, seq);
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, table_get_cb, nlt);
+}
+EXPORT_SYMBOL(nft_mnlio_table_get);
+
+
+/*
+ * Set
+ */
+static int set_add_cb(const struct nlmsghdr *nlh, void *data)
+{
+	nft_set_nlmsg_parse(nlh, data);
+	return MNL_CB_OK;
+}
+
+int nft_mnlio_set_add(struct mnl_socket *nf_sock, struct nft_set *nls,
+		      unsigned int flags)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_NEWSET,
+			nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
+			NLM_F_CREATE | NLM_F_ACK | flags, seq);
+	nft_set_nlmsg_build_payload(nlh, nls);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, set_add_cb, nls);
+}
+EXPORT_SYMBOL(nft_mnlio_set_add);
+
+int nft_mnlio_set_list_add(struct mnl_socket *nf_sock,
+			   struct nft_set_list *nlsl,
+			   unsigned int flags)
+{
+	int ret = 0;
+	struct nft_set_list_iter *i;
+	struct nft_set *s;
+
+	i = nft_set_list_iter_create(nlsl);
+	if (i == NULL)
+		return -1;
+
+	s = nft_set_list_iter_next(i);
+	while (s != NULL) {
+		ret = nft_mnlio_set_add(nf_sock, s, flags);
+
+		if (ret != 0)
+			break;
+
+		s = nft_set_list_iter_next(i);
+	}
+	nft_set_list_iter_destroy(i);
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_set_list_add);
+
+int nft_mnlio_set_delete(struct mnl_socket *nf_sock, struct nft_set *nls,
+			 unsigned int flags)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_DELSET,
+			nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
+			flags|NLM_F_ACK, seq);
+	nft_set_nlmsg_build_payload(nlh, nls);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
+}
+EXPORT_SYMBOL(nft_mnlio_set_delete);
+
+int nft_mnlio_set_list_delete(struct mnl_socket *nfsock,
+			      struct nft_set_list *nlsl, unsigned int flags)
+{
+	struct nft_set_list_iter *i;
+	struct nft_set *s;
+	int ret = 0;
+
+	i = nft_set_list_iter_create(nlsl);
+	if (i == NULL)
+		return -1;
+
+	s = nft_set_list_iter_next(i);
+	while (s != NULL) {
+		ret = nft_mnlio_set_delete(nfsock, s, flags);
+
+		if (ret < 0)
+			break;
+
+		s = nft_set_list_iter_next(i);
+	}
+	nft_set_list_iter_destroy(i);
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_set_list_delete);
+
+static int set_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nft_set_list *nls_list = data;
+	struct nft_set *s;
+
+	s = nft_set_alloc();
+	if (s == NULL)
+		return -1;
+
+	if (nft_set_nlmsg_parse(nlh, s) < 0)
+		goto err_free;
+
+	nft_set_list_add_tail(s, nls_list);
+	return MNL_CB_OK;
+
+err_free:
+	nft_set_free(s);
+	return MNL_CB_OK;
+}
+
+struct nft_set_list *
+nft_mnlio_set_dump(struct mnl_socket *nf_sock, int family, const char *table)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+	struct nft_set *s;
+	struct nft_set_list *nls_list;
+	int ret;
+
+	s = nft_set_alloc();
+	if (s == NULL)
+		return NULL;
+
+	nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET, family,
+				      NLM_F_DUMP|NLM_F_ACK, seq);
+	if (table != NULL)
+		nft_set_attr_set(s, NFT_SET_ATTR_TABLE, table);
+	nft_set_nlmsg_build_payload(nlh, s);
+	nft_set_free(s);
+
+	nls_list = nft_set_list_alloc();
+	if (nls_list == NULL)
+		return NULL;
+
+	ret = nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, set_cb, nls_list);
+	if (ret < 0)
+		goto err;
+
+	return nls_list;
+err:
+	nft_set_list_free(nls_list);
+	return NULL;
+}
+EXPORT_SYMBOL(nft_mnlio_set_dump);
+
+static int set_get_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nft_set *s = data;
+
+	nft_set_nlmsg_parse(nlh, s);
+	return MNL_CB_OK;
+}
+
+int nft_mnlio_set_get(struct mnl_socket *nf_sock, struct nft_set *nls)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET,
+			nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
+			NLM_F_ACK, seq);
+	nft_set_nlmsg_build_payload(nlh, nls);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, set_get_cb, nls);
+}
+EXPORT_SYMBOL(nft_mnlio_set_get);
+
+/*
+ * Set elements
+ */
+int nft_mnlio_setelem_add(struct mnl_socket *nf_sock, struct nft_set *nls,
+			  unsigned int flags)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_set_elem_nlmsg_build_hdr(buf, NFT_MSG_NEWSETELEM,
+			nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
+			NLM_F_CREATE | NLM_F_ACK | flags, seq);
+	nft_set_elems_nlmsg_build_payload(nlh, nls);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
+}
+EXPORT_SYMBOL(nft_mnlio_setelem_add);
+
+int nft_mnlio_setelem_list_add(struct mnl_socket *nf_sock,
+			       struct nft_set_list *nlsl,
+			       unsigned int flags)
+{
+	int ret = 0;
+	struct nft_set_list_iter *i;
+	struct nft_set *s;
+
+	i = nft_set_list_iter_create(nlsl);
+	if (i == NULL)
+		return -1;
+
+	s = nft_set_list_iter_next(i);
+	while (s != NULL) {
+		ret = nft_mnlio_setelem_add(nf_sock, s, flags);
+
+		if (ret != 0)
+			break;
+
+		s = nft_set_list_iter_next(i);
+	}
+	nft_set_list_iter_destroy(i);
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_setelem_list_add);
+
+int nft_mnlio_setelem_delete(struct mnl_socket *nf_sock, struct nft_set *nls,
+			     unsigned int flags)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_set_elem_nlmsg_build_hdr(buf, NFT_MSG_DELSETELEM,
+			nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
+			NLM_F_ACK, seq);
+	nft_set_elems_nlmsg_build_payload(nlh, nls);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
+}
+EXPORT_SYMBOL(nft_mnlio_setelem_delete);
+
+static int set_elem_cb(const struct nlmsghdr *nlh, void *data)
+{
+	nft_set_elems_nlmsg_parse(nlh, data);
+	return MNL_CB_OK;
+}
+
+int nft_mnlio_setelem_get(struct mnl_socket *nf_sock, struct nft_set *nls)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+
+	nlh = nft_set_elem_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM,
+			nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
+			NLM_F_DUMP|NLM_F_ACK, seq);
+	nft_set_nlmsg_build_payload(nlh, nls);
+
+	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, set_elem_cb, nls);
+}
+EXPORT_SYMBOL(nft_mnlio_setelem_get);
+
+/*
+ * ruleset
+ */
+struct nft_ruleset *
+nft_mnlio_ruleset_dump(struct mnl_socket *nf_sock, uint32_t family)
+{
+	struct nft_ruleset *rs;
+	struct nft_table_list *t;
+	struct nft_chain_list *c;
+	struct nft_set_list *sl;
+	struct nft_set_list_iter *i;
+	struct nft_set *s;
+	struct nft_rule_list *r;
+	int ret = 0;
+
+	rs = nft_ruleset_alloc();
+	if (rs == NULL)
+		return NULL;
+
+	t = nft_mnlio_table_dump(nf_sock, family);
+	if (t != NULL)
+		nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_TABLELIST, t);
+
+	c = nft_mnlio_chain_dump(nf_sock, family);
+	if (c != NULL)
+		nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_CHAINLIST, c);
+
+	sl = nft_mnlio_set_dump(nf_sock, family, NULL);
+	if (sl != NULL) {
+		i = nft_set_list_iter_create(sl);
+		s = nft_set_list_iter_next(i);
+		while (s != NULL) {
+			ret = nft_mnlio_setelem_get(nf_sock, s);
+			if (ret != 0)
+				goto out;
+
+			s = nft_set_list_iter_next(i);
+		}
+		nft_set_list_iter_destroy(i);
+
+		nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_SETLIST, sl);
+	}
+
+	r = nft_mnlio_rule_dump(nf_sock, family);
+	if (r != NULL)
+		nft_ruleset_attr_set(rs, NFT_RULESET_ATTR_RULELIST, r);
+
+	if (!(nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_TABLELIST)) &&
+	    !(nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_CHAINLIST)) &&
+	    !(nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_SETLIST)) &&
+	    !(nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_RULELIST)))
+		goto out;
+
+	return rs;
+out:
+	nft_ruleset_free(rs);
+	return NULL;
+}
+EXPORT_SYMBOL(nft_mnlio_ruleset_dump);
+
+int nft_mnlio_ruleset_add(struct mnl_socket *nf_sock, struct nft_ruleset *rs,
+			  unsigned int tflags, unsigned int cflags,
+			  unsigned int rflags, unsigned int sflags,
+			  unsigned int seflags, struct mnl_nlmsg_batch *batch)
+{
+	int ret = 0;
+	struct nft_table_list *t;
+	struct nft_chain_list *c;
+	struct nft_set_list *s;
+	struct nft_rule_list *r;
+
+	if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_TABLELIST)) {
+		t = (struct nft_table_list *)
+		     nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_TABLELIST);
+		ret = nft_mnlio_table_list_add(nf_sock, t, tflags);
+		if (ret != 0)
+			return ret;
+	}
+
+	if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_CHAINLIST)) {
+		c = (struct nft_chain_list *)
+		     nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_CHAINLIST);
+		ret = nft_mnlio_chain_list_add(nf_sock, c, cflags);
+		if (ret != 0)
+			return ret;
+	}
+
+	if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_SETLIST)) {
+		s = (struct nft_set_list *)
+		     nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_SETLIST);
+		ret = nft_mnlio_set_list_add(nf_sock, s, sflags);
+		if (ret != 0)
+			return ret;
+
+		ret = nft_mnlio_setelem_list_add(nf_sock, s, seflags);
+		if (ret != 0)
+			return ret;
+
+	}
+
+	if (nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_RULELIST)) {
+		r = (struct nft_rule_list *)
+		     nft_ruleset_attr_get(rs, NFT_RULESET_ATTR_RULELIST);
+		ret = nft_mnlio_rule_list_add(r, rflags, batch);
+		if (ret != 0)
+			return ret;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(nft_mnlio_ruleset_add);


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

* [RFC libnftnl PATCH 2/2] examples: use new mnlio API in nft-rule-add.c
  2014-02-05 19:17 [RFC libnftnl PATCH 0/2] New mnlio functions Arturo Borrero Gonzalez
  2014-02-05 19:17 ` [RFC libnftnl PATCH 1/2] src: add mnlio API functions Arturo Borrero Gonzalez
@ 2014-02-05 19:17 ` Arturo Borrero Gonzalez
  2014-02-05 19:24 ` [RFC libnftnl PATCH 0/2] New mnlio functions Patrick McHardy
  2 siblings, 0 replies; 5+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-02-05 19:17 UTC (permalink / raw)
  To: netfilter-devel; +Cc: pablo

Update this example to use the new mnlio API.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
 examples/nft-rule-add.c |   87 ++++-------------------------------------------
 1 file changed, 7 insertions(+), 80 deletions(-)

diff --git a/examples/nft-rule-add.c b/examples/nft-rule-add.c
index dbe93f5..7ee73d1 100644
--- a/examples/nft-rule-add.c
+++ b/examples/nft-rule-add.c
@@ -28,6 +28,7 @@
 #include <libmnl/libmnl.h>
 #include <libnftnl/rule.h>
 #include <libnftnl/expr.h>
+#include <libnftnl/mnlio.h>
 
 static void add_payload(struct nft_rule *r, uint32_t base, uint32_t dreg,
 			uint32_t offset, uint32_t len)
@@ -111,78 +112,12 @@ static struct nft_rule *setup_rule(uint8_t family, const char *table,
 	return r;
 }
 
-static int seq;
-
-static void nft_mnl_batch_put(struct mnl_nlmsg_batch *batch, int type)
-{
-	struct nlmsghdr *nlh;
-	struct nfgenmsg *nfg;
-
-	nlh = mnl_nlmsg_put_header(mnl_nlmsg_batch_current(batch));
-	nlh->nlmsg_type = type;
-	nlh->nlmsg_flags = NLM_F_REQUEST;
-	nlh->nlmsg_seq = seq++;
-
-	nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
-	nfg->nfgen_family = AF_INET;
-	nfg->version = NFNETLINK_V0;
-	nfg->res_id = NFNL_SUBSYS_NFTABLES;
-
-	mnl_nlmsg_batch_next(batch);
-}
-
-static int nft_mnl_batch_talk(struct mnl_socket *nl, struct mnl_nlmsg_batch *b)
-{
-	int ret, fd = mnl_socket_get_fd(nl);
-	char rcv_buf[MNL_SOCKET_BUFFER_SIZE];
-	fd_set readfds;
-	struct timeval tv = {
-		.tv_sec		= 0,
-		.tv_usec	= 0
-	};
-
-	ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(b),
-				mnl_nlmsg_batch_size(b));
-	if (ret == -1)
-		goto err;
-
-	FD_ZERO(&readfds);
-	FD_SET(fd, &readfds);
-
-	/* receive and digest all the acknowledgments from the kernel. */
-	ret = select(fd+1, &readfds, NULL, NULL, &tv);
-	if (ret == -1)
-		goto err;
-
-	while (ret > 0 && FD_ISSET(fd, &readfds)) {
-		ret = mnl_socket_recvfrom(nl, rcv_buf, sizeof(rcv_buf));
-		if (ret == -1)
-			goto err;
-
-		ret = mnl_cb_run(rcv_buf, ret, 0, mnl_socket_get_portid(nl),
-				 NULL, NULL);
-		if (ret < 0)
-			goto err;
-
-		ret = select(fd+1, &readfds, NULL, NULL, &tv);
-		if (ret == -1)
-			goto err;
-
-		FD_ZERO(&readfds);
-		FD_SET(fd, &readfds);
-	}
-err:
-	return ret;
-}
-
 int main(int argc, char *argv[])
 {
 	struct mnl_socket *nl;
 	struct nft_rule *r;
-	struct nlmsghdr *nlh;
-	struct mnl_nlmsg_batch *batch;
+	struct mnl_nlmsg_batch *batch = nft_mnlio_batch_alloc();
 	uint8_t family;
-	char buf[4096];
 
 	if (argc != 4) {
 		fprintf(stderr, "Usage: %s <family> <table> <chain>\n", argv[0]);
@@ -211,28 +146,20 @@ int main(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
-
-	nft_mnl_batch_put(batch, NFNL_MSG_BATCH_BEGIN);
+	nft_mnlio_batch_begin(batch);
 
-	nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
-			NFT_MSG_NEWRULE,
-			nft_rule_attr_get_u32(r, NFT_RULE_ATTR_FAMILY),
-			NLM_F_APPEND|NLM_F_CREATE, seq);
-
-	nft_rule_nlmsg_build_payload(nlh, r);
+	nft_mnlio_rule_add(r, NLM_F_APPEND, batch);
 	nft_rule_free(r);
-	mnl_nlmsg_batch_next(batch);
 
-	nft_mnl_batch_put(batch, NFNL_MSG_BATCH_END);
+	mnl_nlmsg_batch_next(batch);
+	nft_mnlio_batch_end(batch);
 
-	if (nft_mnl_batch_talk(nl, batch) < 0) {
+	if (nft_mnlio_batch_talk(nl, batch) < 0) {
 		perror("Netlink problem");
 		exit(EXIT_FAILURE);
 	}
 
 	mnl_nlmsg_batch_stop(batch);
-
 	mnl_socket_close(nl);
 
 	return EXIT_SUCCESS;


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

* Re: [RFC libnftnl PATCH 0/2] New mnlio functions
  2014-02-05 19:17 [RFC libnftnl PATCH 0/2] New mnlio functions Arturo Borrero Gonzalez
  2014-02-05 19:17 ` [RFC libnftnl PATCH 1/2] src: add mnlio API functions Arturo Borrero Gonzalez
  2014-02-05 19:17 ` [RFC libnftnl PATCH 2/2] examples: use new mnlio API in nft-rule-add.c Arturo Borrero Gonzalez
@ 2014-02-05 19:24 ` Patrick McHardy
  2 siblings, 0 replies; 5+ messages in thread
From: Patrick McHardy @ 2014-02-05 19:24 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel, pablo

On Wed, Feb 05, 2014 at 08:17:41PM +0100, Arturo Borrero Gonzalez wrote:
> These functions are likely to be reused by almost all programs
> that want to talk with the kernel subsystem.
> 
> We can add here to libnftnl or maybe put in a higher level library.
> 
> Let this patchset be a RFC about this subject.
> 
> An example of what means using the new mnlio approach is the
> examples/nft-rule-add.c file. We save lots of LOCs.
> 
> Comments welcome.

I agree, they belong in libnftnl. Thanks for doing this work.

> 
> NOTE: this patchset would require several iterations. For example,
> I left behind batch_pages.
> ---
> 
> Arturo Borrero Gonzalez (2):
>       src: add mnlio API functions
>       examples: use new mnlio API in nft-rule-add.c
> 
> 
>  examples/nft-rule-add.c      |   87 ----
>  include/libnftnl/Makefile.am |    3 
>  include/libnftnl/mnlio.h     |   92 ++++
>  src/Makefile.am              |    1 
>  src/libnftnl.map             |   37 ++
>  src/mnlio.c                  |  957 ++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 1096 insertions(+), 81 deletions(-)
>  create mode 100644 include/libnftnl/mnlio.h
>  create mode 100644 src/mnlio.c

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

* Re: [RFC libnftnl PATCH 1/2] src: add mnlio API functions
  2014-02-05 19:17 ` [RFC libnftnl PATCH 1/2] src: add mnlio API functions Arturo Borrero Gonzalez
@ 2014-02-12 14:03   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2014-02-12 14:03 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel

Hi Arturo,

On Wed, Feb 05, 2014 at 08:17:47PM +0100, Arturo Borrero Gonzalez wrote:
> These functions are likely to be used by all userspace programs to interact
> with the nftables kernel subsystem.
> 
> Lets put in the library, so: its easy to maintain, we can save lots of LOCs,
> programmers can easily learn how to work with nftables, etc..

See comments below.

[...]

> +void nft_mnlio_batch_put(struct mnl_nlmsg_batch *batch, int type,
> +			 uint32_t seqnum)
> +{
> +	struct nlmsghdr *nlh;
> +	struct nfgenmsg *nfg;
> +
> +	nlh = mnl_nlmsg_put_header(mnl_nlmsg_batch_current(batch));
> +	nlh->nlmsg_type = type;
> +	nlh->nlmsg_flags = NLM_F_REQUEST;
> +	nlh->nlmsg_seq = seqnum;
> +
> +	nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
> +	nfg->nfgen_family = AF_INET;
> +	nfg->version = NFNETLINK_V0;
> +	nfg->res_id = NFNL_SUBSYS_NFTABLES;
> +
> +	mnl_nlmsg_batch_next(batch);
> +}
> +EXPORT_SYMBOL(nft_mnlio_batch_put);

You can rename and export this as: nft_batch_nlmsg_build_hdr, it
should take a 'void *buf' instead of struct mnl_nlmsg_batch *batch, so
we don't force people to use libmnl batching infrastructure. The type
should be uint16_t. Add this function to src/batch.c.

> +/*
> + * Rule
> + */
> +int nft_mnlio_rule_add(struct nft_rule *nlr, unsigned int flags,

use fixed types, ie. uint32_t instead of unsigned int.

> +		       struct mnl_nlmsg_batch *batch)

use void *buf instead of the struct mnl_nlmsg_batch *batch, so we can
pass a simple char buf[...] or mnl_nlmsg_batch_current(batch).

> +{
> +	struct nlmsghdr *nlh;
> +
> +	nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
> +			NFT_MSG_NEWRULE,
> +			nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY),
> +			NLM_F_CREATE | flags, nft_mnlio_seqnum_alloc());
                        ^----------^
                   no assumptions on any flag, just pass flags.

> +
> +	nft_rule_nlmsg_build_payload(nlh, nlr);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(nft_mnlio_rule_add);

Rename this function to nft_rule_build_msg, add it to src/rule.c

[...]
> +int nft_mnlio_rule_del(struct nft_rule *nlr, unsigned int flags,
> +		       struct mnl_nlmsg_batch *batch)

similar comments like in nft_mnlio_rule_add.

> +{
> +	struct nlmsghdr *nlh;
> +
> +	nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
> +			NFT_MSG_DELRULE,
> +			nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY),
> +			0, nft_mnlio_seqnum_alloc());
> +
> +	nft_rule_nlmsg_build_payload(nlh, nlr);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(nft_mnlio_rule_del);
>
[...]
>
> +int nft_mnlio_chain_add(struct mnl_socket *nf_sock, struct nft_chain *nlc,
> +			unsigned int flags)

> +
> +{
> +	char buf[MNL_SOCKET_BUFFER_SIZE];
> +	struct nlmsghdr *nlh;
> +
> +	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
> +			nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
> +			NLM_F_CREATE | NLM_F_ACK | flags, seq);
> +	nft_chain_nlmsg_build_payload(nlh, nlc);

Better add nft_chain_build_msg, similar to nft_rule_build_msg.

Same with tables, rules and so on.

> +
> +	return nft_mnlio_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);

So remove this _talk call. Thus, the netlink interaction is decoupled,
which is more flexible when doing complex stuff.

Let's start with those functions first, you can send incremental
patches for other functions that you're including in this patch that
you believe that can be useful to others so we can discuss them.

I detected problems in the rulelist to batch handling in your patch,
you may run out of the batch boundary that may lead to a memory
corruption.

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

end of thread, other threads:[~2014-02-12 14:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-05 19:17 [RFC libnftnl PATCH 0/2] New mnlio functions Arturo Borrero Gonzalez
2014-02-05 19:17 ` [RFC libnftnl PATCH 1/2] src: add mnlio API functions Arturo Borrero Gonzalez
2014-02-12 14:03   ` Pablo Neira Ayuso
2014-02-05 19:17 ` [RFC libnftnl PATCH 2/2] examples: use new mnlio API in nft-rule-add.c Arturo Borrero Gonzalez
2014-02-05 19:24 ` [RFC libnftnl PATCH 0/2] New mnlio functions Patrick McHardy

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).