[PATCH nft 3/4] src: convert set to list expression

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

 



The following definition:

 define xyz = { "dummy0", "dummy1" }

is represented as a set expression to ease integration with sets.

However, this definition can be used in chains and flowtables to specify
the devices, for instance:

  table netdev x {
    chain y {
      type filter hook ingress devices = $xyz priority 0; policy drop;
    }
  }

in this context, $xyz defines a _list_ of devices, not a set.

Transform the set to list expression from the evaluation step for chains
and flowtables.

This patch also handles:

 define xyz = { "dummy0", $abc }

where $abc is also transformed to a list expression in the context of
chains and flowtables.

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 src/evaluate.c | 66 +++++++++++++++++++++++++++++++++++++++++++-------
 src/mnl.c      |  1 -
 2 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index f4f72ee4a4f7..fb6c4e06ae32 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -5393,9 +5393,54 @@ static bool evaluate_expr_variable(struct eval_ctx *ctx, struct expr **exprp)
 	return true;
 }
 
-static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
+static struct expr *expr_set_to_list(struct eval_ctx *ctx, struct expr *dev_expr)
 {
 	struct expr *expr, *next, *key;
+	struct location loc;
+	LIST_HEAD(tmp);
+
+	list_for_each_entry_safe(expr, next, &dev_expr->expressions, list) {
+		list_del(&expr->list);
+
+		switch (expr->etype) {
+		case EXPR_VARIABLE:
+			expr_set_context(&ctx->ectx, &ifname_type,
+					 IFNAMSIZ * BITS_PER_BYTE);
+			if (!evaluate_expr_variable(ctx, &expr))
+				return false;
+
+			if (expr->etype == EXPR_SET) {
+				expr = expr_set_to_list(ctx, expr);
+				list_splice_init(&expr->expressions, &tmp);
+				expr_free(expr);
+				continue;
+			}
+			break;
+		case EXPR_SET_ELEM:
+			key = expr_clone(expr->key);
+			expr_free(expr);
+			expr = key;
+			break;
+		case EXPR_VALUE:
+			break;
+		default:
+			break;
+		}
+
+		list_add(&expr->list, &tmp);
+	}
+
+	loc = dev_expr->location;
+	expr_free(dev_expr);
+	dev_expr = compound_expr_alloc(&loc, EXPR_LIST);
+	list_splice_init(&tmp, &dev_expr->expressions);
+
+	return dev_expr;
+}
+
+static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
+{
+	struct expr *expr, *next;
 	LIST_HEAD(tmp);
 
 	if ((*dev_expr)->etype == EXPR_VARIABLE) {
@@ -5405,9 +5450,10 @@ static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
 			return false;
 	}
 
-	if ((*dev_expr)->etype != EXPR_SET &&
-	    (*dev_expr)->etype != EXPR_LIST)
-		return true;
+	if ((*dev_expr)->etype == EXPR_SET)
+		*dev_expr = expr_set_to_list(ctx, *dev_expr);
+
+	assert((*dev_expr)->etype == EXPR_LIST);
 
 	list_for_each_entry_safe(expr, next, &(*dev_expr)->expressions, list) {
 		list_del(&expr->list);
@@ -5418,11 +5464,13 @@ static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
 					 IFNAMSIZ * BITS_PER_BYTE);
 			if (!evaluate_expr_variable(ctx, &expr))
 				return false;
-			break;
-		case EXPR_SET_ELEM:
-			key = expr_clone(expr->key);
-			expr_free(expr);
-			expr = key;
+
+			if (expr->etype == EXPR_SET) {
+				expr = expr_set_to_list(ctx, expr);
+				list_splice_init(&expr->expressions, &tmp);
+				expr_free(expr);
+				continue;
+			}
 			break;
 		case EXPR_VALUE:
 			break;
diff --git a/src/mnl.c b/src/mnl.c
index 8a8dc4d6ef1c..cc20908fd636 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -757,7 +757,6 @@ static struct nft_dev *nft_dev_array(const struct expr *dev_expr, int *num_devs)
 	struct expr *expr;
 
 	switch (dev_expr->etype) {
-	case EXPR_SET:
 	case EXPR_LIST:
 		list_for_each_entry(expr, &dev_expr->expressions, list)
 			len++;
-- 
2.30.2





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

  Powered by Linux