diff options
Diffstat (limited to 'src/intervals.c')
-rw-r--r-- | src/intervals.c | 59 |
1 files changed, 36 insertions, 23 deletions
diff --git a/src/intervals.c b/src/intervals.c index 13009ca1..ff202be9 100644 --- a/src/intervals.c +++ b/src/intervals.c @@ -6,11 +6,15 @@ * later) as published by the Free Software Foundation. */ +#include <nft.h> + #include <nftables.h> #include <expression.h> #include <intervals.h> #include <rule.h> +static void set_to_range(struct expr *init); + static void setelem_expr_to_range(struct expr *expr) { unsigned char data[sizeof(struct in6_addr) * BITS_PER_BYTE]; @@ -24,6 +28,9 @@ static void setelem_expr_to_range(struct expr *expr) case EXPR_RANGE: break; case EXPR_PREFIX: + if (expr->key->prefix->etype != EXPR_VALUE) + BUG("Prefix for unexpected type %d", expr->key->prefix->etype); + mpz_init(rop); mpz_bitmask(rop, expr->key->len - expr->key->prefix_len); if (expr_basetype(expr)->type == TYPE_STRING) @@ -125,7 +132,7 @@ static void set_sort_splice(struct expr *init, struct set *set) set_to_range(init); list_expr_sort(&init->expressions); - if (!existing_set) + if (!existing_set || existing_set->errors) return; if (existing_set->init) { @@ -213,7 +220,7 @@ static struct expr *interval_expr_key(struct expr *i) return elem; } -void set_to_range(struct expr *init) +static void set_to_range(struct expr *init) { struct expr *i, *elem; @@ -376,7 +383,7 @@ static int setelem_delete(struct list_head *msgs, struct set *set, struct expr *purge, struct expr *elems, unsigned int debug_mask) { - struct expr *i, *next, *prev = NULL; + struct expr *i, *next, *elem, *prev = NULL; struct range range, prev_range; int err = 0; mpz_t rop; @@ -387,21 +394,26 @@ static int setelem_delete(struct list_head *msgs, struct set *set, mpz_init(range.high); mpz_init(rop); - list_for_each_entry_safe(i, next, &elems->expressions, list) { - if (i->key->etype == EXPR_SET_ELEM_CATCHALL) - continue; + list_for_each_entry_safe(elem, next, &elems->expressions, list) { + i = interval_expr_key(elem); - range_expr_value_low(range.low, i); - range_expr_value_high(range.high, i); + if (i->key->etype == EXPR_SET_ELEM_CATCHALL) { + /* Assume max value to simplify handling. */ + mpz_bitmask(range.low, i->len); + mpz_bitmask(range.high, i->len); + } else { + range_expr_value_low(range.low, i); + range_expr_value_high(range.high, i); + } - if (!prev && i->flags & EXPR_F_REMOVE) { + if (!prev && elem->flags & EXPR_F_REMOVE) { expr_error(msgs, i, "element does not exist"); err = -1; goto err; } - if (!(i->flags & EXPR_F_REMOVE)) { - prev = i; + if (!(elem->flags & EXPR_F_REMOVE)) { + prev = elem; mpz_set(prev_range.low, range.low); mpz_set(prev_range.high, range.high); continue; @@ -409,19 +421,20 @@ static int setelem_delete(struct list_head *msgs, struct set *set, if (mpz_cmp(prev_range.low, range.low) == 0 && mpz_cmp(prev_range.high, range.high) == 0) { - if (i->flags & EXPR_F_REMOVE) { + if (elem->flags & EXPR_F_REMOVE) { if (prev->flags & EXPR_F_KERNEL) list_move_tail(&prev->list, &purge->expressions); - list_del(&i->list); - expr_free(i); + list_del(&elem->list); + expr_free(elem); } - } else if (set->automerge && - setelem_adjust(set, purge, &prev_range, &range, prev, i) < 0) { - expr_error(msgs, i, "element does not exist"); - err = -1; - goto err; - } else if (i->flags & EXPR_F_REMOVE) { + } else if (set->automerge) { + if (setelem_adjust(set, purge, &prev_range, &range, prev, i) < 0) { + expr_error(msgs, i, "element does not exist"); + err = -1; + goto err; + } + } else if (elem->flags & EXPR_F_REMOVE) { expr_error(msgs, i, "element does not exist"); err = -1; goto err; @@ -458,7 +471,7 @@ static int __set_delete(struct list_head *msgs, struct expr *i, struct set *set, unsigned int debug_mask) { i->flags |= EXPR_F_REMOVE; - list_move(&i->list, &existing_set->init->expressions); + list_move_tail(&i->list, &existing_set->init->expressions); list_expr_sort(&existing_set->init->expressions); return setelem_delete(msgs, set, init, existing_set->init, debug_mask); @@ -708,9 +721,9 @@ int set_to_intervals(const struct set *set, struct expr *init, bool add) if (set->key->byteorder == BYTEORDER_HOST_ENDIAN) mpz_switch_byteorder(expr->value, set->key->len / BITS_PER_BYTE); - newelem = set_elem_expr_alloc(&internal_location, expr); + newelem = set_elem_expr_alloc(&expr->location, expr); if (i->etype == EXPR_MAPPING) { - newelem = mapping_expr_alloc(&internal_location, + newelem = mapping_expr_alloc(&expr->location, newelem, expr_get(i->right)); } |