Blob Blame History Raw
From 8fcb95ed6dcd47c94a924b4018177d8a833d6983 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 17 Dec 2018 17:30:06 +0100
Subject: [PATCH] chain: Support per chain rules list

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1658533
Upstream Status: libnftnl commit e33798478176f

commit e33798478176f97edf2649cd61444e0375fdc12b
Author: Phil Sutter <phil@nwl.cc>
Date:   Thu Dec 6 17:17:51 2018 +0100

    chain: Support per chain rules list

    The implementation basically copies expr_list in struct nftnl_rule.

    Signed-off-by: Phil Sutter <phil@nwl.cc>
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/internal.h       |   1 +
 include/libnftnl/chain.h |  15 +++++++
 include/rule.h           |  26 ++++++++++++
 src/chain.c              | 104 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/libnftnl.map         |  10 +++++
 src/rule.c               |  22 ----------
 6 files changed, 155 insertions(+), 23 deletions(-)
 create mode 100644 include/rule.h

diff --git a/include/internal.h b/include/internal.h
index 7e97c4a..323f825 100644
--- a/include/internal.h
+++ b/include/internal.h
@@ -13,5 +13,6 @@
 #include "expr.h"
 #include "expr_ops.h"
 #include "buffer.h"
+#include "rule.h"
 
 #endif /* _LIBNFTNL_INTERNAL_H_ */
diff --git a/include/libnftnl/chain.h b/include/libnftnl/chain.h
index 237683e..f04f610 100644
--- a/include/libnftnl/chain.h
+++ b/include/libnftnl/chain.h
@@ -13,6 +13,7 @@ extern "C" {
 #endif
 
 struct nftnl_chain;
+struct nftnl_rule;
 
 struct nftnl_chain *nftnl_chain_alloc(void);
 void nftnl_chain_free(const struct nftnl_chain *);
@@ -54,6 +55,10 @@ uint32_t nftnl_chain_get_u32(const struct nftnl_chain *c, uint16_t attr);
 int32_t nftnl_chain_get_s32(const struct nftnl_chain *c, uint16_t attr);
 uint64_t nftnl_chain_get_u64(const struct nftnl_chain *c, uint16_t attr);
 
+void nftnl_chain_rule_add(struct nftnl_rule *rule, struct nftnl_chain *c);
+void nftnl_chain_rule_add_tail(struct nftnl_rule *rule, struct nftnl_chain *c);
+void nftnl_chain_rule_insert_at(struct nftnl_rule *rule, struct nftnl_rule *pos);
+
 struct nlmsghdr;
 
 void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_chain *t);
@@ -68,6 +73,16 @@ int nftnl_chain_fprintf(FILE *fp, const struct nftnl_chain *c, uint32_t type, ui
 #define nftnl_chain_nlmsg_build_hdr	nftnl_nlmsg_build_hdr
 int nftnl_chain_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_chain *t);
 
+int nftnl_rule_foreach(struct nftnl_chain *c,
+			  int (*cb)(struct nftnl_rule *r, void *data),
+			  void *data);
+
+struct nftnl_rule_iter;
+
+struct nftnl_rule_iter *nftnl_rule_iter_create(const struct nftnl_chain *c);
+struct nftnl_rule *nftnl_rule_iter_next(struct nftnl_rule_iter *iter);
+void nftnl_rule_iter_destroy(struct nftnl_rule_iter *iter);
+
 struct nftnl_chain_list;
 
 struct nftnl_chain_list *nftnl_chain_list_alloc(void);
diff --git a/include/rule.h b/include/rule.h
new file mode 100644
index 0000000..5edcb6c
--- /dev/null
+++ b/include/rule.h
@@ -0,0 +1,26 @@
+#ifndef _LIBNFTNL_RULE_INTERNAL_H_
+#define _LIBNFTNL_RULE_INTERNAL_H_
+
+struct nftnl_rule {
+	struct list_head head;
+
+	uint32_t	flags;
+	uint32_t	family;
+	const char	*table;
+	const char	*chain;
+	uint64_t	handle;
+	uint64_t	position;
+	uint32_t	id;
+	struct {
+			void		*data;
+			uint32_t	len;
+	} user;
+	struct {
+			uint32_t	flags;
+			uint32_t	proto;
+	} compat;
+
+	struct list_head expr_list;
+};
+
+#endif
diff --git a/src/chain.c b/src/chain.c
index eff5186..c374923 100644
--- a/src/chain.c
+++ b/src/chain.c
@@ -27,6 +27,7 @@
 #include <linux/netfilter_arp.h>
 
 #include <libnftnl/chain.h>
+#include <libnftnl/rule.h>
 #include <buffer.h>
 
 struct nftnl_chain {
@@ -45,6 +46,8 @@ struct nftnl_chain {
 	uint64_t	bytes;
 	uint64_t	handle;
 	uint32_t	flags;
+
+	struct list_head rule_list;
 };
 
 static const char *nftnl_hooknum2str(int family, int hooknum)
@@ -90,12 +93,25 @@ static const char *nftnl_hooknum2str(int family, int hooknum)
 EXPORT_SYMBOL(nftnl_chain_alloc);
 struct nftnl_chain *nftnl_chain_alloc(void)
 {
-	return calloc(1, sizeof(struct nftnl_chain));
+	struct nftnl_chain *c;
+
+	c = calloc(1, sizeof(struct nftnl_chain));
+	if (c == NULL)
+		return NULL;
+
+	INIT_LIST_HEAD(&c->rule_list);
+
+	return c;
 }
 
 EXPORT_SYMBOL(nftnl_chain_free);
 void nftnl_chain_free(const struct nftnl_chain *c)
 {
+	struct nftnl_rule *r, *tmp;
+
+	list_for_each_entry_safe(r, tmp, &c->rule_list, head)
+		nftnl_rule_free(r);
+
 	if (c->flags & (1 << NFTNL_CHAIN_NAME))
 		xfree(c->name);
 	if (c->flags & (1 << NFTNL_CHAIN_TABLE))
@@ -406,6 +422,24 @@ void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_ch
 		mnl_attr_put_strz(nlh, NFTA_CHAIN_TYPE, c->type);
 }
 
+EXPORT_SYMBOL(nftnl_chain_rule_add);
+void nftnl_chain_rule_add(struct nftnl_rule *rule, struct nftnl_chain *c)
+{
+	list_add(&rule->head, &c->rule_list);
+}
+
+EXPORT_SYMBOL(nftnl_chain_rule_add_tail);
+void nftnl_chain_rule_add_tail(struct nftnl_rule *rule, struct nftnl_chain *c)
+{
+	list_add_tail(&rule->head, &c->rule_list);
+}
+
+EXPORT_SYMBOL(nftnl_chain_rule_insert_at);
+void nftnl_chain_rule_insert_at(struct nftnl_rule *rule, struct nftnl_rule *pos)
+{
+	list_add(&rule->head, &pos->head);
+}
+
 static int nftnl_chain_parse_attr_cb(const struct nlattr *attr, void *data)
 {
 	const struct nlattr **tb = data;
@@ -875,6 +909,74 @@ int nftnl_chain_fprintf(FILE *fp, const struct nftnl_chain *c, uint32_t type,
 			   nftnl_chain_do_snprintf);
 }
 
+EXPORT_SYMBOL(nftnl_rule_foreach);
+int nftnl_rule_foreach(struct nftnl_chain *c,
+                          int (*cb)(struct nftnl_rule *r, void *data),
+                          void *data)
+{
+       struct nftnl_rule *cur, *tmp;
+       int ret;
+
+       list_for_each_entry_safe(cur, tmp, &c->rule_list, head) {
+               ret = cb(cur, data);
+               if (ret < 0)
+                       return ret;
+       }
+       return 0;
+}
+
+struct nftnl_rule_iter {
+	const struct nftnl_chain	*c;
+	struct nftnl_rule		*cur;
+};
+
+static void nftnl_rule_iter_init(const struct nftnl_chain *c,
+				 struct nftnl_rule_iter *iter)
+{
+	iter->c = c;
+	if (list_empty(&c->rule_list))
+		iter->cur = NULL;
+	else
+		iter->cur = list_entry(c->rule_list.next, struct nftnl_rule,
+				       head);
+}
+
+EXPORT_SYMBOL(nftnl_rule_iter_create);
+struct nftnl_rule_iter *nftnl_rule_iter_create(const struct nftnl_chain *c)
+{
+	struct nftnl_rule_iter *iter;
+
+	iter = calloc(1, sizeof(struct nftnl_rule_iter));
+	if (iter == NULL)
+		return NULL;
+
+	nftnl_rule_iter_init(c, iter);
+
+	return iter;
+}
+
+EXPORT_SYMBOL(nftnl_rule_iter_next);
+struct nftnl_rule *nftnl_rule_iter_next(struct nftnl_rule_iter *iter)
+{
+	struct nftnl_rule *rule = iter->cur;
+
+	if (rule == NULL)
+		return NULL;
+
+	/* get next rule, if any */
+	iter->cur = list_entry(iter->cur->head.next, struct nftnl_rule, head);
+	if (&iter->cur->head == iter->c->rule_list.next)
+		return NULL;
+
+	return rule;
+}
+
+EXPORT_SYMBOL(nftnl_rule_iter_destroy);
+void nftnl_rule_iter_destroy(struct nftnl_rule_iter *iter)
+{
+	xfree(iter);
+}
+
 struct nftnl_chain_list {
 	struct list_head list;
 };
diff --git a/src/libnftnl.map b/src/libnftnl.map
index 89414f2..96d5b5f 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -336,3 +336,13 @@ global:
 
 local: *;
 };
+
+LIBNFTNL_12 {
+  nftnl_chain_rule_add;
+  nftnl_chain_rule_add_tail;
+  nftnl_chain_rule_insert_at;
+  nftnl_rule_foreach;
+  nftnl_rule_iter_create;
+  nftnl_rule_iter_next;
+  nftnl_rule_iter_destroy;
+} LIBNFTNL_11;
diff --git a/src/rule.c b/src/rule.c
index 2c70420..6a43d3e 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -30,28 +30,6 @@
 #include <libnftnl/set.h>
 #include <libnftnl/expr.h>
 
-struct nftnl_rule {
-	struct list_head head;
-
-	uint32_t	flags;
-	uint32_t	family;
-	const char	*table;
-	const char	*chain;
-	uint64_t	handle;
-	uint64_t	position;
-	uint32_t	id;
-	struct {
-			void		*data;
-			uint32_t	len;
-	} user;
-	struct {
-			uint32_t	flags;
-			uint32_t	proto;
-	} compat;
-
-	struct list_head expr_list;
-};
-
 EXPORT_SYMBOL(nftnl_rule_alloc);
 struct nftnl_rule *nftnl_rule_alloc(void)
 {
-- 
1.8.3.1