From: "Carlos Falgueras García" <carlosfg@riseup.net>
To: netfilter-devel@vger.kernel.org
Cc: pablo@netfilter.org
Subject: [PATCH 2/4, V3, libnftnl] Implement rule comparison
Date: Wed, 10 Aug 2016 11:48:55 +0200 [thread overview]
Message-ID: <20160810094857.14227-2-carlosfg@riseup.net> (raw)
In-Reply-To: <20160810094857.14227-1-carlosfg@riseup.net>
This patch implements the function 'bool nftnl_rule_cmp(const struct
nftnl_rule *r, const struct nftnl_rule *r2)' for rule comparison.
Expressions within rules need to be compared, so also has been created the
function 'nftnl_expr_cmp' which calls new field within
'nfntl_expr_<expression>': a function pointer to a comparator. The
expressions that can be compared with memcmp have this new field set to
NULL, otherwise they have implemented a comparator.
Signed-off-by: Carlos Falgueras García <carlosfg@riseup.net>
---
include/data_reg.h | 3 +++
include/expr_ops.h | 1 +
include/libnftnl/expr.h | 2 ++
include/libnftnl/rule.h | 2 ++
src/expr.c | 14 ++++++++++++++
src/expr/data_reg.c | 16 ++++++++++++++++
src/expr/dynset.c | 16 ++++++++++++++++
src/expr/immediate.c | 17 +++++++++++++++++
src/expr/log.c | 15 +++++++++++++++
src/expr/lookup.c | 14 ++++++++++++++
src/expr/match.c | 13 +++++++++++++
src/expr/target.c | 13 +++++++++++++
src/libnftnl.map | 5 +++++
src/rule.c | 30 ++++++++++++++++++++++++++++++
14 files changed, 161 insertions(+)
diff --git a/include/data_reg.h b/include/data_reg.h
index e749b5b..3fec7cd 100644
--- a/include/data_reg.h
+++ b/include/data_reg.h
@@ -3,6 +3,7 @@
#include <linux/netfilter/nf_tables.h>
#include <stdint.h>
+#include <stdbool.h>
#include <unistd.h>
enum {
@@ -27,6 +28,8 @@ int nftnl_data_reg_snprintf(char *buf, size_t size,
const union nftnl_data_reg *reg,
uint32_t output_format, uint32_t flags,
int reg_type);
+bool nftnl_data_reg_cmp(const union nftnl_data_reg *r1,
+ const union nftnl_data_reg *r2, int reg_type);
struct nlattr;
int nftnl_parse_data(union nftnl_data_reg *data, struct nlattr *attr, int *type);
diff --git a/include/expr_ops.h b/include/expr_ops.h
index 3c0cb18..a334732 100644
--- a/include/expr_ops.h
+++ b/include/expr_ops.h
@@ -13,6 +13,7 @@ struct expr_ops {
uint32_t alloc_len;
int max_attr;
void (*free)(const struct nftnl_expr *e);
+ bool (*cmp)(const struct nftnl_expr *e1, const struct nftnl_expr *e2);
int (*set)(struct nftnl_expr *e, uint16_t type, const void *data, uint32_t data_len);
const void *(*get)(const struct nftnl_expr *e, uint16_t type, uint32_t *data_len);
int (*parse)(struct nftnl_expr *e, struct nlattr *attr);
diff --git a/include/libnftnl/expr.h b/include/libnftnl/expr.h
index 17f60bd..8ae6f57 100644
--- a/include/libnftnl/expr.h
+++ b/include/libnftnl/expr.h
@@ -36,6 +36,8 @@ uint32_t nftnl_expr_get_u32(const struct nftnl_expr *expr, uint16_t type);
uint64_t nftnl_expr_get_u64(const struct nftnl_expr *expr, uint16_t type);
const char *nftnl_expr_get_str(const struct nftnl_expr *expr, uint16_t type);
+bool nftnl_expr_cmp(const struct nftnl_expr *e1, const struct nftnl_expr *e2);
+
int nftnl_expr_snprintf(char *buf, size_t buflen, const struct nftnl_expr *expr, uint32_t type, uint32_t flags);
enum {
diff --git a/include/libnftnl/rule.h b/include/libnftnl/rule.h
index e3bd6b8..adeedf2 100644
--- a/include/libnftnl/rule.h
+++ b/include/libnftnl/rule.h
@@ -50,6 +50,8 @@ uint64_t nftnl_rule_get_u64(const struct nftnl_rule *r, uint16_t attr);
void nftnl_rule_add_expr(struct nftnl_rule *r, struct nftnl_expr *expr);
+bool nftnl_rule_cmp(const struct nftnl_rule *r1, const struct nftnl_rule *r2);
+
struct nlmsghdr;
void nftnl_rule_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_rule *t);
diff --git a/src/expr.c b/src/expr.c
index e5c1dd3..7f32055 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -203,6 +203,20 @@ const char *nftnl_expr_get_str(const struct nftnl_expr *expr, uint16_t type)
}
EXPORT_SYMBOL_ALIAS(nftnl_expr_get_str, nft_rule_expr_get_str);
+bool nftnl_expr_cmp(const struct nftnl_expr *e1, const struct nftnl_expr *e2)
+{
+ if (e1->flags != e2->flags)
+ return false;
+
+ if (strcmp(e1->ops->name, e2->ops->name))
+ return false;
+ if (e1->ops->cmp)
+ return e1->ops->cmp(e1, e2);
+ else
+ return !memcmp(e1->data, e2->data, e1->ops->alloc_len);
+}
+EXPORT_SYMBOL(nftnl_expr_cmp);
+
void
nftnl_expr_build_payload(struct nlmsghdr *nlh, struct nftnl_expr *expr)
{
diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c
index 688823b..a954e95 100644
--- a/src/expr/data_reg.c
+++ b/src/expr/data_reg.c
@@ -379,6 +379,22 @@ int nftnl_data_reg_snprintf(char *buf, size_t size,
return -1;
}
+bool nftnl_data_reg_cmp(const union nftnl_data_reg *r1,
+ const union nftnl_data_reg *r2, int reg_type)
+{
+ switch (reg_type) {
+ case DATA_VALUE:
+ return r1->len == r2->len &&
+ !memcmp(r1->val, r2->val, r1->len);
+ case DATA_VERDICT:
+ case DATA_CHAIN:
+ return r1->verdict == r2->verdict &&
+ !strcmp(r1->chain, r2->chain);
+ default:
+ return false;
+ }
+}
+
static int nftnl_data_parse_cb(const struct nlattr *attr, void *data)
{
const struct nlattr **tb = data;
diff --git a/src/expr/dynset.c b/src/expr/dynset.c
index 0eaa409..83311f1 100644
--- a/src/expr/dynset.c
+++ b/src/expr/dynset.c
@@ -370,11 +370,27 @@ static void nftnl_expr_dynset_free(const struct nftnl_expr *e)
xfree(dynset->set_name);
}
+static bool nftnl_expr_dynset_cmp(const struct nftnl_expr *e1,
+ const struct nftnl_expr *e2)
+{
+ struct nftnl_expr_dynset *d1 = nftnl_expr_data(e1);
+ struct nftnl_expr_dynset *d2 = nftnl_expr_data(e2);
+
+ return d1->sreg_key == d2->sreg_key &&
+ d1->sreg_data == d2->sreg_data &&
+ d1->op == d2->op &&
+ d1->timeout == d2->timeout &&
+ nftnl_expr_cmp(d1->expr, d2->expr) &&
+ !strcmp(d1->set_name, d2->set_name) &&
+ d1->set_id == d2->set_id;
+}
+
struct expr_ops expr_ops_dynset = {
.name = "dynset",
.alloc_len = sizeof(struct nftnl_expr_dynset),
.max_attr = NFTA_DYNSET_MAX,
.free = nftnl_expr_dynset_free,
+ .cmp = nftnl_expr_dynset_cmp,
.set = nftnl_expr_dynset_set,
.get = nftnl_expr_dynset_get,
.parse = nftnl_expr_dynset_parse,
diff --git a/src/expr/immediate.c b/src/expr/immediate.c
index 22ec864..ec0613d 100644
--- a/src/expr/immediate.c
+++ b/src/expr/immediate.c
@@ -320,11 +320,28 @@ static void nftnl_expr_immediate_free(const struct nftnl_expr *e)
nftnl_free_verdict(&imm->data);
}
+static bool nftnl_expr_immediate_cmp(const struct nftnl_expr *e1,
+ const struct nftnl_expr *e2)
+{
+ struct nftnl_expr_immediate *i1 = nftnl_expr_data(e1);
+ struct nftnl_expr_immediate *i2 = nftnl_expr_data(e2);
+ int reg_type;
+
+ if (e1->flags & (1 << NFTNL_EXPR_IMM_VERDICT))
+ reg_type = DATA_VERDICT;
+ else
+ reg_type = DATA_VALUE;
+
+ return i1->dreg == i2->dreg &&
+ nftnl_data_reg_cmp(&i1->data, &i2->data, reg_type);
+}
+
struct expr_ops expr_ops_immediate = {
.name = "immediate",
.alloc_len = sizeof(struct nftnl_expr_immediate),
.max_attr = NFTA_IMMEDIATE_MAX,
.free = nftnl_expr_immediate_free,
+ .cmp = nftnl_expr_immediate_cmp,
.set = nftnl_expr_immediate_set,
.get = nftnl_expr_immediate_get,
.parse = nftnl_expr_immediate_parse,
diff --git a/src/expr/log.c b/src/expr/log.c
index b9b3951..d8e2572 100644
--- a/src/expr/log.c
+++ b/src/expr/log.c
@@ -336,11 +336,26 @@ static void nftnl_expr_log_free(const struct nftnl_expr *e)
xfree(log->prefix);
}
+static bool nftnl_expr_log_cmp(const struct nftnl_expr *e1,
+ const struct nftnl_expr *e2)
+{
+ struct nftnl_expr_log *l1 = nftnl_expr_data(e1);
+ struct nftnl_expr_log *l2 = nftnl_expr_data(e2);
+
+ return l1->snaplen == l2->snaplen &&
+ l1->group == l2->group &&
+ l1->qthreshold == l2->qthreshold &&
+ l1->level == l2->level &&
+ l1->flags == l2->flags &&
+ !strcmp(l1->prefix, l2->prefix);
+}
+
struct expr_ops expr_ops_log = {
.name = "log",
.alloc_len = sizeof(struct nftnl_expr_log),
.max_attr = NFTA_LOG_MAX,
.free = nftnl_expr_log_free,
+ .cmp = nftnl_expr_log_cmp,
.set = nftnl_expr_log_set,
.get = nftnl_expr_log_get,
.parse = nftnl_expr_log_parse,
diff --git a/src/expr/lookup.c b/src/expr/lookup.c
index 97478c2..5e5d3d4 100644
--- a/src/expr/lookup.c
+++ b/src/expr/lookup.c
@@ -296,11 +296,25 @@ static void nftnl_expr_lookup_free(const struct nftnl_expr *e)
xfree(lookup->set_name);
}
+static bool nftnl_expr_lookup_cmp(const struct nftnl_expr *e1,
+ const struct nftnl_expr *e2)
+{
+ struct nftnl_expr_lookup *l1 = nftnl_expr_data(e1);
+ struct nftnl_expr_lookup *l2 = nftnl_expr_data(e2);
+
+ return l1->sreg == l2->sreg &&
+ l1->dreg == l2->dreg &&
+ !strcmp(l1->set_name, l2->set_name) &&
+ l1->set_id == l2->set_id &&
+ l1->flags == l2->flags;
+}
+
struct expr_ops expr_ops_lookup = {
.name = "lookup",
.alloc_len = sizeof(struct nftnl_expr_lookup),
.max_attr = NFTA_LOOKUP_MAX,
.free = nftnl_expr_lookup_free,
+ .cmp = nftnl_expr_lookup_cmp,
.set = nftnl_expr_lookup_set,
.get = nftnl_expr_lookup_get,
.parse = nftnl_expr_lookup_parse,
diff --git a/src/expr/match.c b/src/expr/match.c
index 3342e2c..8d9001f 100644
--- a/src/expr/match.c
+++ b/src/expr/match.c
@@ -240,11 +240,24 @@ static void nftnl_expr_match_free(const struct nftnl_expr *e)
xfree(match->data);
}
+static bool nftnl_expr_match_cmp(const struct nftnl_expr *e1,
+ const struct nftnl_expr *e2)
+{
+ struct nftnl_expr_match *m1 = nftnl_expr_data(e1);
+ struct nftnl_expr_match *m2 = nftnl_expr_data(e2);
+
+ return !strcmp(m1->name, m2->name) &&
+ m1->rev == m2->rev &&
+ m1->data_len == m2->data_len &&
+ !memcmp(m1->data, m2->data, m1->data_len);
+}
+
struct expr_ops expr_ops_match = {
.name = "match",
.alloc_len = sizeof(struct nftnl_expr_match),
.max_attr = NFTA_MATCH_MAX,
.free = nftnl_expr_match_free,
+ .cmp = nftnl_expr_match_cmp,
.set = nftnl_expr_match_set,
.get = nftnl_expr_match_get,
.parse = nftnl_expr_match_parse,
diff --git a/src/expr/target.c b/src/expr/target.c
index d4c0091..55a0af3 100644
--- a/src/expr/target.c
+++ b/src/expr/target.c
@@ -241,11 +241,24 @@ static void nftnl_expr_target_free(const struct nftnl_expr *e)
xfree(target->data);
}
+static bool nftnl_expr_target_cmp(const struct nftnl_expr *e1,
+ const struct nftnl_expr *e2)
+{
+ struct nftnl_expr_target *t1 = nftnl_expr_data(e1);
+ struct nftnl_expr_target *t2 = nftnl_expr_data(e2);
+
+ return !strcmp(t1->name, t2->name) &&
+ t1->rev == t2->rev &&
+ t1->data_len == t2->data_len &&
+ !memcmp(t1->data, t2->data, t1->data_len);
+}
+
struct expr_ops expr_ops_target = {
.name = "target",
.alloc_len = sizeof(struct nftnl_expr_target),
.max_attr = NFTA_TARGET_MAX,
.free = nftnl_expr_target_free,
+ .cmp = nftnl_expr_target_cmp,
.set = nftnl_expr_target_set,
.get = nftnl_expr_target_get,
.parse = nftnl_expr_target_parse,
diff --git a/src/libnftnl.map b/src/libnftnl.map
index c38e081..abed8b9 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -528,3 +528,8 @@ LIBNFTNL_4.1 {
nftnl_udata_next;
nftnl_udata_parse;
} LIBNFTNL_4;
+
+LIBNFTNL_4.2 {
+ nftnl_rule_cmp;
+ nftnl_expr_cmp;
+} LIBNFTNL_4.1;
diff --git a/src/rule.c b/src/rule.c
index 69ffc7e..d4c3a6b 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -339,6 +339,36 @@ void nftnl_rule_add_expr(struct nftnl_rule *r, struct nftnl_expr *expr)
}
EXPORT_SYMBOL_ALIAS(nftnl_rule_add_expr, nft_rule_add_expr);
+bool nftnl_rule_cmp(const struct nftnl_rule *r1, const struct nftnl_rule *r2)
+{
+ struct nftnl_expr_iter it1, it2;
+ struct nftnl_expr *e1, *e2;
+ unsigned int eq = 1;
+
+ if (r1->flags & r1->flags & (1 << NFTNL_RULE_TABLE))
+ eq &= !strcmp(r1->table, r2->table);
+ if (r1->flags & r1->flags & (1 << NFTNL_RULE_CHAIN))
+ eq &= !strcmp(r1->chain, r2->chain);
+ if (r1->flags & r1->flags & (1 << NFTNL_RULE_COMPAT_FLAGS))
+ eq &= r1->compat.flags == r2->compat.flags;
+ if (r1->flags & r1->flags & (1 << NFTNL_RULE_COMPAT_PROTO))
+ eq &= r1->compat.proto == r2->compat.proto;
+
+ nftnl_expr_iter_init(r1, &it1);
+ nftnl_expr_iter_init(r2, &it2);
+ e1 = nftnl_expr_iter_next(&it1);
+ e2 = nftnl_expr_iter_next(&it2);
+ while (eq && e1 && e2) {
+ eq = nftnl_expr_cmp(e1, e2);
+
+ e1 = nftnl_expr_iter_next(&it1);
+ e2 = nftnl_expr_iter_next(&it2);
+ }
+
+ return eq;
+}
+EXPORT_SYMBOL(nftnl_rule_cmp);
+
static int nftnl_rule_parse_attr_cb(const struct nlattr *attr, void *data)
{
const struct nlattr **tb = data;
--
2.8.3
next prev parent reply other threads:[~2016-08-10 19:12 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-08 11:17 [PATCH 1/4, libnftnl] rule: Implement internal expression iterator Carlos Falgueras García
2016-08-08 11:17 ` [PATCH 2/4, libnfntl] Implement rule comparison Carlos Falgueras García
2016-08-08 11:32 ` Pablo Neira Ayuso
2016-08-08 11:49 ` Carlos Falgueras García
2016-08-12 0:17 ` Pablo Neira Ayuso
2016-08-08 11:17 ` [PATCH 3/4, nft] Simplify parser rule_spec tree Carlos Falgueras García
2016-08-08 11:17 ` [PATCH 4/4, nft] Implement deleting rule by description Carlos Falgueras García
2016-08-08 11:25 ` [PATCH 1/4, libnftnl] rule: Implement internal expression iterator Pablo Neira Ayuso
2016-08-08 11:49 ` Carlos Falgueras García
2016-08-08 12:42 ` [PATCH 1/5, V2, libnftnl] rule: Add const modifier to rule field of " Carlos Falgueras García
2016-08-08 12:42 ` [PATCH 2/5, V2, libnftnl] rule: Implement internal " Carlos Falgueras García
2016-08-08 12:42 ` [PATCH 3/5, V2, libnftnl] Implement rule comparison Carlos Falgueras García
2016-08-08 14:50 ` Pablo Neira Ayuso
2016-08-08 12:42 ` [PATCH 4/5, V2, nft] Simplify parser rule_spec tree Carlos Falgueras García
2016-08-08 14:54 ` Pablo Neira Ayuso
2016-08-08 17:02 ` Carlos Falgueras García
2016-08-08 12:42 ` [PATCH 5/5, V2, nft] Implement deleting rule by description Carlos Falgueras García
2016-08-08 14:46 ` Pablo Neira Ayuso
2016-08-08 14:48 ` [PATCH 1/5, V2, libnftnl] rule: Add const modifier to rule field of expression iterator Pablo Neira Ayuso
2016-08-08 18:10 ` [PATCH] rule: Constify rule iterators Carlos Falgueras García
2016-08-09 7:17 ` Pablo Neira Ayuso
2016-08-09 11:42 ` [PATCH, v2] Constify iterators Carlos Falgueras García
2016-08-10 8:30 ` Pablo Neira Ayuso
2016-08-10 9:48 ` [PATCH 1/4, V3, libnftnl] rule: Implement internal expression iterator Carlos Falgueras García
2016-08-10 9:48 ` Carlos Falgueras García [this message]
2016-08-10 11:35 ` [PATCH 2/4, V3, libnftnl] Implement rule comparison Pablo Neira Ayuso
2016-08-10 9:48 ` [PATCH 3/4, V3, nft] Simplify parser rule_spec tree Carlos Falgueras García
2016-08-12 12:11 ` Pablo Neira Ayuso
2016-08-10 9:48 ` [PATCH 4/4, V3, nft] Implement deleting rule by description Carlos Falgueras García
2016-08-10 11:41 ` [PATCH 1/4, V3, libnftnl] rule: Implement internal expression iterator Pablo Neira Ayuso
2016-08-10 11:56 ` Carlos Falgueras García
2016-08-10 12:08 ` Pablo Neira Ayuso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160810094857.14227-2-carlosfg@riseup.net \
--to=carlosfg@riseup.net \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).