[PATCH nftables 5/9] src: make interval sets work with string datatypes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 src/expression.c |  8 ++++++--
 src/segtree.c    | 30 ++++++++++++++++++++++++++----
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/src/expression.c b/src/expression.c
index deb649e1847b..5d879b535990 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -1442,7 +1442,11 @@ void range_expr_value_low(mpz_t rop, const struct expr *expr)
 {
 	switch (expr->etype) {
 	case EXPR_VALUE:
-		return mpz_set(rop, expr->value);
+		mpz_set(rop, expr->value);
+		if (expr->byteorder == BYTEORDER_HOST_ENDIAN &&
+		    expr_basetype(expr)->type == TYPE_STRING)
+			mpz_switch_byteorder(rop, expr->len / BITS_PER_BYTE);
+		return;
 	case EXPR_PREFIX:
 		return range_expr_value_low(rop, expr->prefix);
 	case EXPR_RANGE:
@@ -1462,7 +1466,7 @@ void range_expr_value_high(mpz_t rop, const struct expr *expr)
 
 	switch (expr->etype) {
 	case EXPR_VALUE:
-		return mpz_set(rop, expr->value);
+		return range_expr_value_low(rop, expr);
 	case EXPR_PREFIX:
 		range_expr_value_low(rop, expr->prefix);
 		assert(expr->len >= expr->prefix_len);
diff --git a/src/segtree.c b/src/segtree.c
index 188cafedce45..b4e76bf530d6 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) {
-- 
2.35.1




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux