]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
set: abort on interval conflicts
authorPatrick McHardy <kaber@trash.net>
Thu, 6 Mar 2014 15:26:09 +0000 (16:26 +0100)
committerPatrick McHardy <kaber@trash.net>
Fri, 7 Mar 2014 09:20:14 +0000 (10:20 +0100)
We currently print a debug message (with debugging) and continue. Output
a proper error message and abort.

While at it, make sure we only report a conflict if there actually is one.
This is not the case similar actions, IOW in case of sets, never, in case
of maps, only if the mapping differs.

Signed-off-by: Patrick McHardy <kaber@trash.net>
include/expression.h
src/rule.c
src/segtree.c

index d974131e74042a1d6d843aa032ac154a2b397d70..edb6dc502fdf8f8a9526af9b97bf29d2f037a028 100644 (file)
@@ -341,7 +341,7 @@ 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 void set_to_intervals(struct set *set);
+extern int set_to_intervals(struct list_head *msgs, struct set *set);
 
 extern struct expr *mapping_expr_alloc(const struct location *loc,
                                       struct expr *from, struct expr *to);
index 0e04282efc9e3e02a6325d0a9b1c58a6fa49c04a..b71904013d8ac4046a2e6421dc5cece3718d90f1 100644 (file)
@@ -498,8 +498,9 @@ static int do_add_set(struct netlink_ctx *ctx, const struct handle *h,
        if (netlink_add_set(ctx, h, set) < 0)
                return -1;
        if (set->init != NULL) {
-               if (set->flags & SET_F_INTERVAL)
-                       set_to_intervals(set);
+               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)
                        return -1;
        }
index 1a21c6c175702055c5bf61650c1037231966dd12..c169f8d16bec72497320b4d387db6c0896281888 100644 (file)
@@ -329,13 +329,15 @@ static bool interval_conflict(const struct elementary_interval *e1,
 {
        if (mpz_cmp(e1->left, e2->left) <= 0 &&
            mpz_cmp(e1->right, e2->left) >= 0 &&
-           mpz_cmp(e1->size, e2->size) == 0)
+           mpz_cmp(e1->size, e2->size) == 0 &&
+           !expr_cmp(e1->expr->right, e2->expr->right))
                return true;
        else
                return false;
 }
 
-static void set_to_segtree(struct expr *set, struct seg_tree *tree)
+static int set_to_segtree(struct list_head *msgs, struct expr *set,
+                         struct seg_tree *tree)
 {
        struct elementary_interval *intervals[set->size];
        struct elementary_interval *ei;
@@ -365,14 +367,19 @@ static void set_to_segtree(struct expr *set, struct seg_tree *tree)
         * Insert elements into tree
         */
        for (n = 0; n < set->size; n++) {
-               if (n < set->size - 1 &&
+               if (set->set_flags & SET_F_MAP &&
+                   n < set->size - 1 &&
                    interval_conflict(intervals[n], intervals[n+1]))
-                       pr_debug("conflict\n");
+                       return expr_binary_error(msgs,
+                                       intervals[n]->expr,
+                                       intervals[n+1]->expr,
+                                       "conflicting intervals specified");
                ei_insert(tree, intervals[n]);
        }
 
        mpz_clear(high);
        mpz_clear(low);
+       return 0;
 }
 
 static void segtree_linearize(struct list_head *list, struct seg_tree *tree)
@@ -461,14 +468,15 @@ static void set_insert_interval(struct expr *set, struct seg_tree *tree,
        compound_expr_add(set, expr);
 }
 
-void set_to_intervals(struct set *set)
+int set_to_intervals(struct list_head *errs, struct set *set)
 {
        struct elementary_interval *ei, *next;
        struct seg_tree tree;
        LIST_HEAD(list);
 
        seg_tree_init(&tree, set);
-       set_to_segtree(set->init, &tree);
+       if (set_to_segtree(errs, set->init, &tree) < 0)
+               return -1;
        segtree_linearize(&list, &tree);
 
        list_for_each_entry_safe(ei, next, &list, list) {
@@ -485,6 +493,7 @@ void set_to_intervals(struct set *set)
                expr_print(set->init);
                pr_debug("\n");
        }
+       return 0;
 }
 
 static bool range_is_prefix(const mpz_t range)