summaryrefslogtreecommitdiffstats
path: root/src/segtree.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2022-04-09 15:58:28 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2022-04-13 13:43:35 +0200
commit2fb4d7ead460ec4fb00bd317d93a5e076f825b39 (patch)
treefb50ec5e275ba6148a30ff93152ec5a77674251f /src/segtree.c
parent403936c1ffa34bc597d7ee0792154fc6c6b483f2 (diff)
src: make interval sets work with string datatypes
Allows to interface names in interval sets: table inet filter { set s { type ifname flags interval elements = { eth*, foo } } Concatenations are not yet supported, also, listing is broken, those strings will not be printed back because the values will remain in big-endian order. Followup patch will extend segtree to translate this back to host byte order. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/segtree.c')
-rw-r--r--src/segtree.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/src/segtree.c b/src/segtree.c
index 188cafed..b4e76bf5 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -70,12 +70,30 @@ struct elementary_interval {
struct expr *expr;
};
+static enum byteorder get_key_byteorder(const struct expr *e)
+{
+ enum datatypes basetype = expr_basetype(e)->type;
+
+ switch (basetype) {
+ case TYPE_INTEGER:
+ /* For ranges, integers MUST be in BYTEORDER_BIG_ENDIAN.
+ * If the LHS (lookup key, e.g. 'meta mark', is host endian,
+ * a byteorder expression is injected to convert the register
+ * content before lookup.
+ */
+ return BYTEORDER_BIG_ENDIAN;
+ case TYPE_STRING:
+ return BYTEORDER_HOST_ENDIAN;
+ default:
+ break;
+ }
+
+ return BYTEORDER_INVALID;
+}
+
static void seg_tree_init(struct seg_tree *tree, const struct set *set,
struct expr *init, unsigned int debug_mask)
{
- struct expr *first;
-
- first = list_entry(init->expressions.next, struct expr, list);
tree->root = RB_ROOT;
tree->keytype = set->key->dtype;
tree->keylen = set->key->len;
@@ -85,7 +103,8 @@ static void seg_tree_init(struct seg_tree *tree, const struct set *set,
tree->datatype = set->data->dtype;
tree->datalen = set->data->len;
}
- tree->byteorder = first->byteorder;
+
+ tree->byteorder = get_key_byteorder(set->key);
tree->debug_mask = debug_mask;
}
@@ -608,6 +627,9 @@ static void set_insert_interval(struct expr *set, struct seg_tree *tree,
expr = constant_expr_alloc(&internal_location, tree->keytype,
tree->byteorder, tree->keylen, NULL);
mpz_set(expr->value, ei->left);
+ if (tree->byteorder == BYTEORDER_HOST_ENDIAN)
+ mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
+
expr = set_elem_expr_alloc(&internal_location, expr);
if (ei->expr != NULL) {