netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH libnftables] examples: nft-rule-add: use existing batch infrastructure
@ 2013-12-10 17:18 Pablo Neira Ayuso
  2014-01-01 22:39 ` Eric Leblond
  0 siblings, 1 reply; 3+ messages in thread
From: Pablo Neira Ayuso @ 2013-12-10 17:18 UTC (permalink / raw)
  To: netfilter-devel; +Cc: arturo.borrero.glez

From: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>

This patch reworks the existing example to add the rule:

  nft add rule ip filter input tcp dport 22 counter

It uses the existing nfnl batching approach using the generic mnl
netlink message batching infrastructure. It also removed the code
that uses xtables compat code.

Based on original patch by Arturo Borrero Gonzalez.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 examples/nft-rule-add.c             |  257 ++++++++++++++++++++---------------
 include/linux/netfilter/nfnetlink.h |    5 +
 2 files changed, 152 insertions(+), 110 deletions(-)

diff --git a/examples/nft-rule-add.c b/examples/nft-rule-add.c
index f896bc0..0534fa5 100644
--- a/examples/nft-rule-add.c
+++ b/examples/nft-rule-add.c
@@ -14,126 +14,178 @@
 #include <string.h>
 #include <stddef.h>	/* for offsetof */
 #include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
 #include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
 
 #include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nf_tables.h>
 
 #include <libmnl/libmnl.h>
 #include <libnftables/rule.h>
 #include <libnftables/expr.h>
 
-#include <linux/netfilter_ipv4/ipt_LOG.h>
-#include <linux/netfilter/xt_iprange.h>
-
-#include <netinet/ip.h>
-
-static void add_target_log(struct nft_rule_expr *e)
+static void add_payload(struct nft_rule *r, uint32_t base, uint32_t dreg,
+			uint32_t offset, uint32_t len)
 {
-	struct ipt_log_info *info;
+	struct nft_rule_expr *e;
 
-	nft_rule_expr_set(e, NFT_EXPR_TG_NAME, "LOG", strlen("LOG"));
-	nft_rule_expr_set_u32(e, NFT_EXPR_TG_REV, 0);
-
-	info = calloc(1, sizeof(struct ipt_log_info));
-	if (info == NULL)
-		return;
+	e = nft_rule_expr_alloc("payload");
+	if (e == NULL) {
+		perror("expr payload oom");
+		exit(EXIT_FAILURE);
+	}
 
-	sprintf(info->prefix, "test: ");
-	info->prefix[sizeof(info->prefix)-1] = '\0';
-	info->logflags = 0x0f;
-	info->level = 5;
+	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_BASE, base);
+	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_DREG, dreg);
+	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_OFFSET, offset);
+	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_LEN, len);
 
-	nft_rule_expr_set(e, NFT_EXPR_TG_INFO, info, sizeof(*info));
+	nft_rule_add_expr(r, e);
 }
 
-static void add_expr_target(struct nft_rule *r)
+static void add_cmp(struct nft_rule *r, uint32_t sreg, uint32_t op,
+		    const void *data, uint32_t data_len)
 {
-	struct nft_rule_expr *expr;
+	struct nft_rule_expr *e;
 
-	expr = nft_rule_expr_alloc("target");
-	if (expr == NULL)
-		return;
+	e = nft_rule_expr_alloc("cmp");
+	if (e == NULL) {
+		perror("expr cmp oom");
+		exit(EXIT_FAILURE);
+	}
 
-	add_target_log(expr);
+	nft_rule_expr_set_u32(e, NFT_EXPR_CMP_SREG, sreg);
+	nft_rule_expr_set_u32(e, NFT_EXPR_CMP_OP, op);
+	nft_rule_expr_set(e, NFT_EXPR_CMP_DATA, data, data_len);
 
-	nft_rule_add_expr(r, expr);
+	nft_rule_add_expr(r, e);
 }
 
-static void add_match_iprange(struct nft_rule_expr *e)
+static void add_counter(struct nft_rule *r)
 {
-	struct xt_iprange_mtinfo *info;
-
-	nft_rule_expr_set(e, NFT_EXPR_MT_NAME, "iprange", strlen("iprange"));
-	nft_rule_expr_set_u32(e, NFT_EXPR_MT_REV, 1);
+	struct nft_rule_expr *e;
 
-	info = calloc(1, sizeof(struct xt_iprange_mtinfo));
-	if (info == NULL)
-		return;
-
-	info->src_min.ip = info->dst_min.ip = inet_addr("127.0.0.1");
-	info->src_max.ip = info->dst_max.ip = inet_addr("127.0.0.1");
-	info->flags = IPRANGE_SRC;
+	e = nft_rule_expr_alloc("counter");
+	if (e == NULL) {
+		perror("expr counter oom");
+		exit(EXIT_FAILURE);
+	}
 
-	nft_rule_expr_set(e, NFT_EXPR_MT_INFO, info, sizeof(*info));
+	nft_rule_add_expr(r, e);
 }
 
-static void add_expr_match(struct nft_rule *r)
+static struct nft_rule *setup_rule(uint8_t family, const char *table,
+				   const char *chain)
 {
-	struct nft_rule_expr *expr;
+	struct nft_rule *r = NULL;
+	uint8_t proto;
+	uint16_t dport;
 
-	expr = nft_rule_expr_alloc("match");
-	if (expr == NULL)
-		return;
+	r = nft_rule_alloc();
+	if (r == NULL) {
+		perror("OOM");
+		exit(EXIT_FAILURE);
+	}
 
-	add_match_iprange(expr);
+	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, table);
+	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, chain);
+	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, family);
 
-	nft_rule_add_expr(r, expr);
-}
+	proto = IPPROTO_TCP;
+	add_payload(r, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1,
+		    offsetof(struct iphdr, protocol), sizeof(uint8_t));
+	add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &proto, sizeof(uint8_t));
 
-#define field_sizeof(t, f)	(sizeof(((t *)NULL)->f))
+	dport = htons(22);
+	add_payload(r, NFT_PAYLOAD_TRANSPORT_HEADER, NFT_REG_1,
+		    offsetof(struct tcphdr, dest), sizeof(uint16_t));
+	add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &dport, sizeof(uint16_t));
 
-static void add_payload2(struct nft_rule_expr *e)
-{
-	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_BASE,
-			      NFT_PAYLOAD_NETWORK_HEADER);
-	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_DREG, NFT_REG_1);
-	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_OFFSET,
-			      offsetof(struct iphdr, protocol));
-	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_LEN, 1);
+	add_counter(r);
+
+	return r;
 }
 
-static void add_payload(struct nft_rule *r)
+static int seq;
+
+static void nft_mnl_batch_put(struct mnl_nlmsg_batch *batch, int type)
 {
-	struct nft_rule_expr *expr;
+	struct nlmsghdr *nlh;
+	struct nfgenmsg *nfg;
 
-	expr = nft_rule_expr_alloc("payload");
-	if (expr == NULL)
-		return;
+	nlh = mnl_nlmsg_put_header(mnl_nlmsg_batch_current(batch));
+	nlh->nlmsg_type = type;
+	nlh->nlmsg_flags = NLM_F_REQUEST;
+	nlh->nlmsg_seq = seq++;
 
-	add_payload2(expr);
+	nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
+	nfg->nfgen_family = AF_INET;
+	nfg->version = NFNETLINK_V0;
+	nfg->res_id = NFNL_SUBSYS_NFTABLES;
 
-	nft_rule_add_expr(r, expr);
+	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;
-	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nft_rule *r;
 	struct nlmsghdr *nlh;
-	uint32_t portid, seq;
-	struct nft_rule *r = NULL;
-	int ret, family;
+	struct mnl_nlmsg_batch *batch;
+	uint8_t family;
+	char buf[4096];
 
 	if (argc != 4) {
-		fprintf(stderr, "Usage: %s <family> <table> <chain>\n",
-			argv[0]);
-		exit(EXIT_FAILURE);
-	}
-
-	r = nft_rule_alloc();
-	if (r == NULL) {
-		perror("OOM");
+		fprintf(stderr, "Usage: %s <family> <table> <chain>\n", argv[0]);
 		exit(EXIT_FAILURE);
 	}
 
@@ -141,32 +193,12 @@ int main(int argc, char *argv[])
 		family = NFPROTO_IPV4;
 	else if (strcmp(argv[1], "ip6") == 0)
 		family = NFPROTO_IPV6;
-	else if (strcmp(argv[1], "bridge") == 0)
-		family = NFPROTO_BRIDGE;
-	else if (strcmp(argv[1], "arp") == 0)
-		family = NFPROTO_ARP;
 	else {
-		fprintf(stderr, "Unknown family: ip, ip6, bridge, arp\n");
+		fprintf(stderr, "Unknown family: ip, ip6\n");
 		exit(EXIT_FAILURE);
 	}
 
-	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, argv[2]);
-	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, argv[3]);
-
-	add_expr_match(r);
-	add_payload(r);
-	add_expr_target(r);
-
-	char tmp[1024];
-	nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
-	printf("%s\n", tmp);
-
-	seq = time(NULL);
-	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, family,
-					NLM_F_APPEND|NLM_F_ACK|NLM_F_CREATE,
-					seq);
-	nft_rule_nlmsg_build_payload(nlh, r);
-	nft_rule_free(r);
+	r = setup_rule(family, argv[2], argv[3]);
 
 	nl = mnl_socket_open(NETLINK_NETFILTER);
 	if (nl == NULL) {
@@ -178,24 +210,29 @@ int main(int argc, char *argv[])
 		perror("mnl_socket_bind");
 		exit(EXIT_FAILURE);
 	}
-	portid = mnl_socket_get_portid(nl);
 
-	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
-		perror("mnl_socket_send");
-		exit(EXIT_FAILURE);
-	}
+	batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
 
-	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
-	while (ret > 0) {
-		ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
-		if (ret <= 0)
-			break;
-		ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
-	}
-	if (ret == -1) {
-		perror("error");
+	nft_mnl_batch_put(batch, NFNL_MSG_BATCH_BEGIN);
+
+	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_rule_free(r);
+	mnl_nlmsg_batch_next(batch);
+
+	nft_mnl_batch_put(batch, NFNL_MSG_BATCH_END);
+
+	if (nft_mnl_batch_talk(nl, batch) < 0) {
+		perror("Netlink problem");
 		exit(EXIT_FAILURE);
 	}
+
+	mnl_nlmsg_batch_stop(batch);
+
 	mnl_socket_close(nl);
 
 	return EXIT_SUCCESS;
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 91eebab..336c10c 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -97,4 +97,9 @@ extern void nfnl_unlock(void);
 	MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys))
 
 #endif	/* __KERNEL__ */
+
+/* Reserved control nfnetlink messages */
+#define NFNL_MSG_BATCH_BEGIN            NLMSG_MIN_TYPE
+#define NFNL_MSG_BATCH_END              NLMSG_MIN_TYPE+1
+
 #endif	/* _NFNETLINK_H */
-- 
1.7.10.4


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

* Re: [PATCH libnftables] examples: nft-rule-add: use existing batch infrastructure
  2013-12-10 17:18 [PATCH libnftables] examples: nft-rule-add: use existing batch infrastructure Pablo Neira Ayuso
@ 2014-01-01 22:39 ` Eric Leblond
       [not found]   ` <CAOkSjBj7i8J9kDoW--QkFeq8bU8f5USFSyDefXg6CmOU1AGaNw@mail.gmail.com>
  0 siblings, 1 reply; 3+ messages in thread
From: Eric Leblond @ 2014-01-01 22:39 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel, arturo.borrero.glez

Hello,

On Tue, 2013-12-10 at 18:18 +0100, Pablo Neira Ayuso wrote:
> From: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
> 
> This patch reworks the existing example to add the rule:
> 
>   nft add rule ip filter input tcp dport 22 counter
> 
> It uses the existing nfnl batching approach using the generic mnl
> netlink message batching infrastructure. It also removed the code
> that uses xtables compat code.

I don't see this patch in any of the branch. Is there any issue with
it ?

It seems really useful as existing examples are using really old code.

BR,

> 
> Based on original patch by Arturo Borrero Gonzalez.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
>  examples/nft-rule-add.c             |  257 ++++++++++++++++++++---------------
>  include/linux/netfilter/nfnetlink.h |    5 +
>  2 files changed, 152 insertions(+), 110 deletions(-)
> 
> diff --git a/examples/nft-rule-add.c b/examples/nft-rule-add.c
> index f896bc0..0534fa5 100644
> --- a/examples/nft-rule-add.c
> +++ b/examples/nft-rule-add.c
> @@ -14,126 +14,178 @@
>  #include <string.h>
>  #include <stddef.h>	/* for offsetof */
>  #include <netinet/in.h>
> +#include <netinet/ip.h>
> +#include <netinet/tcp.h>
>  #include <arpa/inet.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <errno.h>
>  
>  #include <linux/netfilter.h>
> +#include <linux/netfilter/nfnetlink.h>
>  #include <linux/netfilter/nf_tables.h>
>  
>  #include <libmnl/libmnl.h>
>  #include <libnftables/rule.h>
>  #include <libnftables/expr.h>
>  
> -#include <linux/netfilter_ipv4/ipt_LOG.h>
> -#include <linux/netfilter/xt_iprange.h>
> -
> -#include <netinet/ip.h>
> -
> -static void add_target_log(struct nft_rule_expr *e)
> +static void add_payload(struct nft_rule *r, uint32_t base, uint32_t dreg,
> +			uint32_t offset, uint32_t len)
>  {
> -	struct ipt_log_info *info;
> +	struct nft_rule_expr *e;
>  
> -	nft_rule_expr_set(e, NFT_EXPR_TG_NAME, "LOG", strlen("LOG"));
> -	nft_rule_expr_set_u32(e, NFT_EXPR_TG_REV, 0);
> -
> -	info = calloc(1, sizeof(struct ipt_log_info));
> -	if (info == NULL)
> -		return;
> +	e = nft_rule_expr_alloc("payload");
> +	if (e == NULL) {
> +		perror("expr payload oom");
> +		exit(EXIT_FAILURE);
> +	}
>  
> -	sprintf(info->prefix, "test: ");
> -	info->prefix[sizeof(info->prefix)-1] = '\0';
> -	info->logflags = 0x0f;
> -	info->level = 5;
> +	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_BASE, base);
> +	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_DREG, dreg);
> +	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_OFFSET, offset);
> +	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_LEN, len);
>  
> -	nft_rule_expr_set(e, NFT_EXPR_TG_INFO, info, sizeof(*info));
> +	nft_rule_add_expr(r, e);
>  }
>  
> -static void add_expr_target(struct nft_rule *r)
> +static void add_cmp(struct nft_rule *r, uint32_t sreg, uint32_t op,
> +		    const void *data, uint32_t data_len)
>  {
> -	struct nft_rule_expr *expr;
> +	struct nft_rule_expr *e;
>  
> -	expr = nft_rule_expr_alloc("target");
> -	if (expr == NULL)
> -		return;
> +	e = nft_rule_expr_alloc("cmp");
> +	if (e == NULL) {
> +		perror("expr cmp oom");
> +		exit(EXIT_FAILURE);
> +	}
>  
> -	add_target_log(expr);
> +	nft_rule_expr_set_u32(e, NFT_EXPR_CMP_SREG, sreg);
> +	nft_rule_expr_set_u32(e, NFT_EXPR_CMP_OP, op);
> +	nft_rule_expr_set(e, NFT_EXPR_CMP_DATA, data, data_len);
>  
> -	nft_rule_add_expr(r, expr);
> +	nft_rule_add_expr(r, e);
>  }
>  
> -static void add_match_iprange(struct nft_rule_expr *e)
> +static void add_counter(struct nft_rule *r)
>  {
> -	struct xt_iprange_mtinfo *info;
> -
> -	nft_rule_expr_set(e, NFT_EXPR_MT_NAME, "iprange", strlen("iprange"));
> -	nft_rule_expr_set_u32(e, NFT_EXPR_MT_REV, 1);
> +	struct nft_rule_expr *e;
>  
> -	info = calloc(1, sizeof(struct xt_iprange_mtinfo));
> -	if (info == NULL)
> -		return;
> -
> -	info->src_min.ip = info->dst_min.ip = inet_addr("127.0.0.1");
> -	info->src_max.ip = info->dst_max.ip = inet_addr("127.0.0.1");
> -	info->flags = IPRANGE_SRC;
> +	e = nft_rule_expr_alloc("counter");
> +	if (e == NULL) {
> +		perror("expr counter oom");
> +		exit(EXIT_FAILURE);
> +	}
>  
> -	nft_rule_expr_set(e, NFT_EXPR_MT_INFO, info, sizeof(*info));
> +	nft_rule_add_expr(r, e);
>  }
>  
> -static void add_expr_match(struct nft_rule *r)
> +static struct nft_rule *setup_rule(uint8_t family, const char *table,
> +				   const char *chain)
>  {
> -	struct nft_rule_expr *expr;
> +	struct nft_rule *r = NULL;
> +	uint8_t proto;
> +	uint16_t dport;
>  
> -	expr = nft_rule_expr_alloc("match");
> -	if (expr == NULL)
> -		return;
> +	r = nft_rule_alloc();
> +	if (r == NULL) {
> +		perror("OOM");
> +		exit(EXIT_FAILURE);
> +	}
>  
> -	add_match_iprange(expr);
> +	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, table);
> +	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, chain);
> +	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, family);
>  
> -	nft_rule_add_expr(r, expr);
> -}
> +	proto = IPPROTO_TCP;
> +	add_payload(r, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1,
> +		    offsetof(struct iphdr, protocol), sizeof(uint8_t));
> +	add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &proto, sizeof(uint8_t));
>  
> -#define field_sizeof(t, f)	(sizeof(((t *)NULL)->f))
> +	dport = htons(22);
> +	add_payload(r, NFT_PAYLOAD_TRANSPORT_HEADER, NFT_REG_1,
> +		    offsetof(struct tcphdr, dest), sizeof(uint16_t));
> +	add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &dport, sizeof(uint16_t));
>  
> -static void add_payload2(struct nft_rule_expr *e)
> -{
> -	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_BASE,
> -			      NFT_PAYLOAD_NETWORK_HEADER);
> -	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_DREG, NFT_REG_1);
> -	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_OFFSET,
> -			      offsetof(struct iphdr, protocol));
> -	nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_LEN, 1);
> +	add_counter(r);
> +
> +	return r;
>  }
>  
> -static void add_payload(struct nft_rule *r)
> +static int seq;
> +
> +static void nft_mnl_batch_put(struct mnl_nlmsg_batch *batch, int type)
>  {
> -	struct nft_rule_expr *expr;
> +	struct nlmsghdr *nlh;
> +	struct nfgenmsg *nfg;
>  
> -	expr = nft_rule_expr_alloc("payload");
> -	if (expr == NULL)
> -		return;
> +	nlh = mnl_nlmsg_put_header(mnl_nlmsg_batch_current(batch));
> +	nlh->nlmsg_type = type;
> +	nlh->nlmsg_flags = NLM_F_REQUEST;
> +	nlh->nlmsg_seq = seq++;
>  
> -	add_payload2(expr);
> +	nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
> +	nfg->nfgen_family = AF_INET;
> +	nfg->version = NFNETLINK_V0;
> +	nfg->res_id = NFNL_SUBSYS_NFTABLES;
>  
> -	nft_rule_add_expr(r, expr);
> +	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;
> -	char buf[MNL_SOCKET_BUFFER_SIZE];
> +	struct nft_rule *r;
>  	struct nlmsghdr *nlh;
> -	uint32_t portid, seq;
> -	struct nft_rule *r = NULL;
> -	int ret, family;
> +	struct mnl_nlmsg_batch *batch;
> +	uint8_t family;
> +	char buf[4096];
>  
>  	if (argc != 4) {
> -		fprintf(stderr, "Usage: %s <family> <table> <chain>\n",
> -			argv[0]);
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	r = nft_rule_alloc();
> -	if (r == NULL) {
> -		perror("OOM");
> +		fprintf(stderr, "Usage: %s <family> <table> <chain>\n", argv[0]);
>  		exit(EXIT_FAILURE);
>  	}
>  
> @@ -141,32 +193,12 @@ int main(int argc, char *argv[])
>  		family = NFPROTO_IPV4;
>  	else if (strcmp(argv[1], "ip6") == 0)
>  		family = NFPROTO_IPV6;
> -	else if (strcmp(argv[1], "bridge") == 0)
> -		family = NFPROTO_BRIDGE;
> -	else if (strcmp(argv[1], "arp") == 0)
> -		family = NFPROTO_ARP;
>  	else {
> -		fprintf(stderr, "Unknown family: ip, ip6, bridge, arp\n");
> +		fprintf(stderr, "Unknown family: ip, ip6\n");
>  		exit(EXIT_FAILURE);
>  	}
>  
> -	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, argv[2]);
> -	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, argv[3]);
> -
> -	add_expr_match(r);
> -	add_payload(r);
> -	add_expr_target(r);
> -
> -	char tmp[1024];
> -	nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
> -	printf("%s\n", tmp);
> -
> -	seq = time(NULL);
> -	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, family,
> -					NLM_F_APPEND|NLM_F_ACK|NLM_F_CREATE,
> -					seq);
> -	nft_rule_nlmsg_build_payload(nlh, r);
> -	nft_rule_free(r);
> +	r = setup_rule(family, argv[2], argv[3]);
>  
>  	nl = mnl_socket_open(NETLINK_NETFILTER);
>  	if (nl == NULL) {
> @@ -178,24 +210,29 @@ int main(int argc, char *argv[])
>  		perror("mnl_socket_bind");
>  		exit(EXIT_FAILURE);
>  	}
> -	portid = mnl_socket_get_portid(nl);
>  
> -	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
> -		perror("mnl_socket_send");
> -		exit(EXIT_FAILURE);
> -	}
> +	batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
>  
> -	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
> -	while (ret > 0) {
> -		ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
> -		if (ret <= 0)
> -			break;
> -		ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
> -	}
> -	if (ret == -1) {
> -		perror("error");
> +	nft_mnl_batch_put(batch, NFNL_MSG_BATCH_BEGIN);
> +
> +	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_rule_free(r);
> +	mnl_nlmsg_batch_next(batch);
> +
> +	nft_mnl_batch_put(batch, NFNL_MSG_BATCH_END);
> +
> +	if (nft_mnl_batch_talk(nl, batch) < 0) {
> +		perror("Netlink problem");
>  		exit(EXIT_FAILURE);
>  	}
> +
> +	mnl_nlmsg_batch_stop(batch);
> +
>  	mnl_socket_close(nl);
>  
>  	return EXIT_SUCCESS;
> diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
> index 91eebab..336c10c 100644
> --- a/include/linux/netfilter/nfnetlink.h
> +++ b/include/linux/netfilter/nfnetlink.h
> @@ -97,4 +97,9 @@ extern void nfnl_unlock(void);
>  	MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys))
>  
>  #endif	/* __KERNEL__ */
> +
> +/* Reserved control nfnetlink messages */
> +#define NFNL_MSG_BATCH_BEGIN            NLMSG_MIN_TYPE
> +#define NFNL_MSG_BATCH_END              NLMSG_MIN_TYPE+1
> +
>  #endif	/* _NFNETLINK_H */

-- 
Eric Leblond <eric@regit.org>


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

* Re: [PATCH libnftables] examples: nft-rule-add: use existing batch infrastructure
       [not found]   ` <CAOkSjBj7i8J9kDoW--QkFeq8bU8f5USFSyDefXg6CmOU1AGaNw@mail.gmail.com>
@ 2014-01-02  0:26     ` Eric Leblond
  0 siblings, 0 replies; 3+ messages in thread
From: Eric Leblond @ 2014-01-02  0:26 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez
  Cc: Pablo Neira Ayuso, Netfilter Development Mailing list

Hello,

On Thu, 2014-01-02 at 01:06 +0100, Arturo Borrero Gonzalez wrote:
> 
> El 01/01/2014 23:39, "Eric Leblond" <eric@regit.org> escribió:
> >
> > I don't see this patch in any of the branch. Is there any issue with
> > it ?
> >
> > It seems really useful as existing examples are using really old
> code.
> >
> 
> I think you are looking for
> http://git.netfilter.org/libnftables/commit/examples/nft-rule-add.c?id=0b3161731262d3a8c6110c17fd818af325dbf491

Indeed! Sorry for the noise.

New year resolution: double check my git commands before mailing ;)

BR,
-- 
Eric Leblond <eric@regit.org>

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2014-01-02  0:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-10 17:18 [PATCH libnftables] examples: nft-rule-add: use existing batch infrastructure Pablo Neira Ayuso
2014-01-01 22:39 ` Eric Leblond
     [not found]   ` <CAOkSjBj7i8J9kDoW--QkFeq8bU8f5USFSyDefXg6CmOU1AGaNw@mail.gmail.com>
2014-01-02  0:26     ` Eric Leblond

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