diff options
author | Jeremy Sowden <jeremy@azazel.net> | 2022-09-18 18:22:12 +0100 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2022-09-21 13:57:09 +0200 |
commit | 7e6be917987c3ab0261bf543eb307cbb2679294f (patch) | |
tree | 34d83ccfceb653b19ed762ebdee18cd66fef71fd /src/segtree.c | |
parent | d899df24826c268c764edb07c3a3ed3f2c90b253 (diff) |
segtree: fix decomposition of unclosed intervals containing address prefixes
The code which decomposes unclosed intervals doesn't check for prefixes. This
leads to incorrect output for sets which contain these. For example,
# nft -f - <<END
table ip t {
chain c {
ip saddr 192.0.0.0/2 drop
ip saddr 10.0.0.0/8 drop
ip saddr { 192.0.0.0/2, 10.0.0.0/8 } drop
}
}
table ip6 t {
chain c {
ip6 saddr ff00::/8 drop
ip6 saddr fe80::/10 drop
ip6 saddr { ff00::/8, fe80::/10 } drop
}
}
END
# nft list table ip6 t
table ip6 t {
chain c {
ip6 saddr ff00::/8 drop
ip6 saddr fe80::/10 drop
ip6 saddr { fe80::/10, ff00::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff } drop
}
}
# nft list table ip t
table ip t {
chain c {
ip saddr 192.0.0.0/2 drop
ip saddr 10.0.0.0/8 drop
ip saddr { 10.0.0.0/8, 192.0.0.0-255.255.255.255 } drop
}
}
Instead of treating the final unclosed interval as a special case, reuse the
code which correctly handles closed intervals.
Add a shell test-case.
Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1018156
Fixes: 86b965bdab8d ("segtree: fix decomposition of unclosed intervals")
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src/segtree.c')
-rw-r--r-- | src/segtree.c | 24 |
1 files changed, 8 insertions, 16 deletions
diff --git a/src/segtree.c b/src/segtree.c index d15c39f3..0e3d111f 100644 --- a/src/segtree.c +++ b/src/segtree.c @@ -158,6 +158,8 @@ static struct expr *expr_value(struct expr *expr) return expr->left->key; case EXPR_SET_ELEM: return expr->key; + case EXPR_VALUE: + return expr; default: BUG("invalid expression type %s\n", expr_name(expr)); } @@ -503,7 +505,8 @@ add_interval(struct expr *set, struct expr *low, struct expr *i) mpz_init(p); mpz_sub(range, expr_value(i)->value, expr_value(low)->value); - mpz_sub_ui(range, range, 1); + if (i->etype != EXPR_VALUE) + mpz_sub_ui(range, range, 1); mpz_and(p, expr_value(low)->value, range); @@ -618,25 +621,14 @@ void interval_map_decompose(struct expr *set) mpz_bitmask(i->value, i->len); if (!mpz_cmp(i->value, expr_value(low)->value)) { - expr_free(i); - i = low; + compound_expr_add(set, low); } else { - i = range_expr_alloc(&low->location, - expr_clone(expr_value(low)), i); - i = set_elem_expr_alloc(&low->location, i); - if (low->etype == EXPR_MAPPING) { - i = mapping_expr_alloc(&i->location, i, - expr_clone(low->right)); - interval_expr_copy(i->left, low->left); - } else { - interval_expr_copy(i, low); - } - i->flags |= EXPR_F_KERNEL; - + add_interval(set, low, i); expr_free(low); } - compound_expr_add(set, i); + expr_free(i); + out: if (catchall) compound_expr_add(set, catchall); |