* [PATCH 2/5 nft] rule: use netlink_add_setelems() when creating literal sets
2016-01-19 17:52 [PATCH 1/5 nf,kernel] netfilter: nft_rbtree: allow adjacent intervals with dynamic updates Pablo Neira Ayuso
@ 2016-01-19 17:52 ` Pablo Neira Ayuso
2016-01-19 17:52 ` [PATCH 3/5 nft] segtree: when checks when qsorting from interval_map_decompose() Pablo Neira Ayuso
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-19 17:52 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber, ast
Thus, do_add_setelems() is only used for set declarations. This change
is required by the follow up patch entitled ("rule: fix use of intervals
in set declarations").
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/rule.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/rule.c b/src/rule.c
index 18ff592..1295228 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -876,7 +876,7 @@ static int do_add_set(struct netlink_ctx *ctx, const struct handle *h,
if (set->flags & SET_F_INTERVAL &&
set_to_intervals(ctx->msgs, set) < 0)
return -1;
- if (do_add_setelems(ctx, &set->handle, set->init) < 0)
+ if (netlink_add_setelems(ctx, &set->handle, set->init) < 0)
return -1;
}
return 0;
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/5 nft] segtree: when checks when qsorting from interval_map_decompose()
2016-01-19 17:52 [PATCH 1/5 nf,kernel] netfilter: nft_rbtree: allow adjacent intervals with dynamic updates Pablo Neira Ayuso
2016-01-19 17:52 ` [PATCH 2/5 nft] rule: use netlink_add_setelems() when creating literal sets Pablo Neira Ayuso
@ 2016-01-19 17:52 ` Pablo Neira Ayuso
2016-01-19 17:52 ` [PATCH 4/5 nft] segtree: pass element expression as parameter to set_to_intervals() Pablo Neira Ayuso
2016-01-19 17:52 ` [PATCH 5/5, nft] rule: allow dynamic updates for intervals in set declarations Pablo Neira Ayuso
3 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-19 17:52 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber, ast
If we have two elements with the same key, check the interval flag so we
make sure that the one with the end flag set (ie. closing interval)
comes before the one that starts it.
This is required to decompose adjacent ranges the right way when listing
sets from userspace.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/segtree.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/segtree.c b/src/segtree.c
index 060951c..86c37b4 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -483,8 +483,15 @@ static int expr_value_cmp(const void *p1, const void *p2)
{
struct expr *e1 = *(void * const *)p1;
struct expr *e2 = *(void * const *)p2;
+ int ret;
- return mpz_cmp(expr_value(e1)->value, expr_value(e2)->value);
+ ret = mpz_cmp(expr_value(e1)->value, expr_value(e2)->value);
+ if (ret == 0 && (e1->flags & EXPR_F_INTERVAL_END))
+ return -1;
+ else
+ return 1;
+
+ return ret;
}
void interval_map_decompose(struct expr *set)
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/5 nft] segtree: pass element expression as parameter to set_to_intervals()
2016-01-19 17:52 [PATCH 1/5 nf,kernel] netfilter: nft_rbtree: allow adjacent intervals with dynamic updates Pablo Neira Ayuso
2016-01-19 17:52 ` [PATCH 2/5 nft] rule: use netlink_add_setelems() when creating literal sets Pablo Neira Ayuso
2016-01-19 17:52 ` [PATCH 3/5 nft] segtree: when checks when qsorting from interval_map_decompose() Pablo Neira Ayuso
@ 2016-01-19 17:52 ` Pablo Neira Ayuso
2016-01-19 17:52 ` [PATCH 5/5, nft] rule: allow dynamic updates for intervals in set declarations Pablo Neira Ayuso
3 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-19 17:52 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber, ast
Use the existing set element definition to build the segment tree, so we
skip the elements that we already have defined in the kernel (that we
have in the set->init expression list).
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/expression.h | 3 ++-
src/rule.c | 2 +-
src/segtree.c | 15 ++++++++-------
3 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/include/expression.h b/include/expression.h
index eacbb2d..55af734 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -363,7 +363,8 @@ extern struct expr *concat_expr_alloc(const struct location *loc);
extern struct expr *list_expr_alloc(const struct location *loc);
extern struct expr *set_expr_alloc(const struct location *loc);
-extern int set_to_intervals(struct list_head *msgs, struct set *set);
+extern int set_to_intervals(struct list_head *msgs, struct set *set,
+ struct expr *init);
extern struct expr *mapping_expr_alloc(const struct location *loc,
struct expr *from, struct expr *to);
diff --git a/src/rule.c b/src/rule.c
index 1295228..8549c2b 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -874,7 +874,7 @@ static int do_add_set(struct netlink_ctx *ctx, const struct handle *h,
return -1;
if (set->init != NULL) {
if (set->flags & SET_F_INTERVAL &&
- set_to_intervals(ctx->msgs, set) < 0)
+ set_to_intervals(ctx->msgs, set, set->init) < 0)
return -1;
if (netlink_add_setelems(ctx, &set->handle, set->init) < 0)
return -1;
diff --git a/src/segtree.c b/src/segtree.c
index 86c37b4..5b1cd29 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -64,11 +64,12 @@ struct elementary_interval {
struct expr *expr;
};
-static void seg_tree_init(struct seg_tree *tree, const struct set *set)
+static void seg_tree_init(struct seg_tree *tree, const struct set *set,
+ struct expr *init)
{
struct expr *first;
- first = list_entry(set->init->expressions.next, struct expr, list);
+ first = list_entry(init->expressions.next, struct expr, list);
tree->root = RB_ROOT;
tree->keytype = set->keytype;
tree->keylen = set->keylen;
@@ -431,14 +432,14 @@ static void set_insert_interval(struct expr *set, struct seg_tree *tree,
compound_expr_add(set, expr);
}
-int set_to_intervals(struct list_head *errs, struct set *set)
+int set_to_intervals(struct list_head *errs, struct set *set, struct expr *init)
{
struct elementary_interval *ei, *next;
struct seg_tree tree;
LIST_HEAD(list);
- seg_tree_init(&tree, set);
- if (set_to_segtree(errs, set->init, &tree) < 0)
+ seg_tree_init(&tree, set, init);
+ if (set_to_segtree(errs, init, &tree) < 0)
return -1;
segtree_linearize(&list, &tree);
@@ -448,12 +449,12 @@ int set_to_intervals(struct list_head *errs, struct set *set)
2 * tree.keylen / BITS_PER_BYTE, ei->left,
2 * tree.keylen / BITS_PER_BYTE, ei->right);
}
- set_insert_interval(set->init, &tree, ei);
+ set_insert_interval(init, &tree, ei);
ei_destroy(ei);
}
if (segtree_debug()) {
- expr_print(set->init);
+ expr_print(init);
pr_gmp_debug("\n");
}
return 0;
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 5/5, nft] rule: allow dynamic updates for intervals in set declarations
2016-01-19 17:52 [PATCH 1/5 nf,kernel] netfilter: nft_rbtree: allow adjacent intervals with dynamic updates Pablo Neira Ayuso
` (2 preceding siblings ...)
2016-01-19 17:52 ` [PATCH 4/5 nft] segtree: pass element expression as parameter to set_to_intervals() Pablo Neira Ayuso
@ 2016-01-19 17:52 ` Pablo Neira Ayuso
3 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2016-01-19 17:52 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber, ast
For example:
# nft add table test
# nft add set test myset { type ipv4_addr\; flags interval\; }
# nft add element test myset { 1.2.3.0/24 }
... later on ...
# nft add element test myset { 1.2.4.0/24 }
Then the listing shows:
set myset2 {
type ipv4_addr
flags interval
elements = { 1.2.3.0/24, 1.2.4.0/24}
}
If the set contains at least one element, this skips the non-matching
segment 0.0.0.0, otherwise the kernel returns -EEXIST when updating the
extsing set definition with (more) new elements.
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=994
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/rule.c | 13 ++++++++++++-
src/segtree.c | 9 ++++++---
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/src/rule.c b/src/rule.c
index 8549c2b..a32b697 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -860,10 +860,21 @@ static int do_add_chain(struct netlink_ctx *ctx, const struct handle *h,
}
static int do_add_setelems(struct netlink_ctx *ctx, const struct handle *h,
- const struct expr *expr)
+ struct expr *expr)
{
+ struct table *table;
+ struct set *set;
+
+ table = table_lookup(h);
+ set = set_lookup(table, h->set);
+
+ if (set->flags & SET_F_INTERVAL &&
+ set_to_intervals(ctx->msgs, set, expr) < 0)
+ return -1;
+
if (netlink_add_setelems(ctx, h, expr) < 0)
return -1;
+
return 0;
}
diff --git a/src/segtree.c b/src/segtree.c
index 5b1cd29..c05eead 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -345,7 +345,8 @@ static int set_to_segtree(struct list_head *msgs, struct expr *set,
return 0;
}
-static void segtree_linearize(struct list_head *list, struct seg_tree *tree)
+static void segtree_linearize(struct list_head *list, struct seg_tree *tree,
+ bool needs_first_segment)
{
struct rb_node *node, *next;
struct elementary_interval *ei, *nei, *prev = NULL;
@@ -366,7 +367,7 @@ static void segtree_linearize(struct list_head *list, struct seg_tree *tree)
* If the first segment doesn't begin at zero, insert a
* non-matching segment to cover [0, first_left).
*/
- if (mpz_cmp_ui(ei->left, 0)) {
+ if (needs_first_segment && mpz_cmp_ui(ei->left, 0)) {
mpz_set_ui(p, 0);
mpz_sub_ui(q, ei->left, 1);
nei = ei_alloc(p, q, NULL, EI_F_INTERVAL_END);
@@ -441,7 +442,9 @@ int set_to_intervals(struct list_head *errs, struct set *set, struct expr *init)
seg_tree_init(&tree, set, init);
if (set_to_segtree(errs, init, &tree) < 0)
return -1;
- segtree_linearize(&list, &tree);
+ segtree_linearize(&list, &tree,
+ (set->flags & SET_F_ANONYMOUS) ?
+ true : set->init && set->init->size == 0);
list_for_each_entry_safe(ei, next, &list, list) {
if (segtree_debug()) {
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread