summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/expression.h3
-rw-r--r--src/ct.c6
-rw-r--r--src/expression.c93
-rw-r--r--src/exthdr.c7
-rw-r--r--src/meta.c6
-rw-r--r--src/payload.c10
6 files changed, 125 insertions, 0 deletions
diff --git a/include/expression.h b/include/expression.h
index d4222060..b0084c07 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -106,6 +106,7 @@ static inline void expr_set_context(struct expr_ctx *ctx,
*
* @type: expression type
* @name: expression name for diagnostics
+ * @clone: function to clone type specific data
* @destroy: destructor, must release inner expressions
* @set_type: function to promote type and byteorder of inner types
* @print: function to print the expression
@@ -113,6 +114,7 @@ static inline void expr_set_context(struct expr_ctx *ctx,
struct expr_ops {
enum expr_types type;
const char *name;
+ void (*clone)(struct expr *new, const struct expr *expr);
void (*destroy)(struct expr *expr);
void (*set_type)(const struct expr *expr,
const struct datatype *dtype,
@@ -238,6 +240,7 @@ extern struct expr *expr_alloc(const struct location *loc,
const struct expr_ops *ops,
const struct datatype *dtype,
enum byteorder byteorder, unsigned int len);
+extern struct expr *expr_clone(const struct expr *expr);
extern struct expr *expr_get(struct expr *expr);
extern void expr_free(struct expr *expr);
extern void expr_print(const struct expr *expr);
diff --git a/src/ct.c b/src/ct.c
index 00895394..43dd9878 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -131,10 +131,16 @@ static void ct_expr_print(const struct expr *expr)
printf("ct %s", ct_templates[expr->ct.key].token);
}
+static void ct_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->ct.key = expr->ct.key;
+}
+
static const struct expr_ops ct_expr_ops = {
.type = EXPR_CT,
.name = "ct",
.print = ct_expr_print,
+ .clone = ct_expr_clone,
};
struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key)
diff --git a/src/expression.c b/src/expression.c
index 4b3e1e04..dba5331d 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -39,6 +39,18 @@ struct expr *expr_alloc(const struct location *loc, const struct expr_ops *ops,
return expr;
}
+struct expr *expr_clone(const struct expr *expr)
+{
+ struct expr *new;
+
+ new = expr_alloc(&expr->location, expr->ops, expr->dtype,
+ expr->byteorder, expr->len);
+ new->flags = expr->flags;
+ new->op = expr->op;
+ expr->ops->clone(new, expr);
+ return new;
+}
+
struct expr *expr_get(struct expr *expr)
{
expr->refcnt++;
@@ -134,6 +146,13 @@ static void verdict_expr_print(const struct expr *expr)
datatype_print(expr);
}
+static void verdict_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->verdict = expr->verdict;
+ if (expr->chain != NULL)
+ new->chain = xstrdup(expr->chain);
+}
+
static void verdict_expr_destroy(struct expr *expr)
{
xfree(expr->chain);
@@ -143,6 +162,7 @@ static const struct expr_ops verdict_expr_ops = {
.type = EXPR_VERDICT,
.name = "verdict",
.print = verdict_expr_print,
+ .clone = verdict_expr_clone,
.destroy = verdict_expr_destroy,
};
@@ -165,6 +185,13 @@ static void symbol_expr_print(const struct expr *expr)
printf("%s%s", expr->scope != NULL ? "$" : "", expr->identifier);
}
+static void symbol_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->sym_type = expr->sym_type;
+ new->scope = expr->scope;
+ new->identifier = xstrdup(expr->identifier);
+}
+
static void symbol_expr_destroy(struct expr *expr)
{
xfree(expr->identifier);
@@ -174,6 +201,7 @@ static const struct expr_ops symbol_expr_ops = {
.type = EXPR_SYMBOL,
.name = "symbol",
.print = symbol_expr_print,
+ .clone = symbol_expr_clone,
.destroy = symbol_expr_destroy,
};
@@ -193,6 +221,11 @@ static void constant_expr_print(const struct expr *expr)
datatype_print(expr);
}
+static void constant_expr_clone(struct expr *new, const struct expr *expr)
+{
+ mpz_init_set(new->value, expr->value);
+}
+
static void constant_expr_destroy(struct expr *expr)
{
mpz_clear(expr->value);
@@ -202,6 +235,7 @@ static const struct expr_ops constant_expr_ops = {
.type = EXPR_VALUE,
.name = "value",
.print = constant_expr_print,
+ .clone = constant_expr_clone,
.destroy = constant_expr_destroy,
};
@@ -275,11 +309,24 @@ static void prefix_expr_set_type(const struct expr *expr,
expr_set_type(expr->expr, type, byteorder);
}
+static void prefix_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->expr = expr_clone(expr->expr);
+ new->prefix_len = expr->prefix_len;
+}
+
+static void prefix_expr_destroy(struct expr *expr)
+{
+ expr_free(expr->expr);
+}
+
static const struct expr_ops prefix_expr_ops = {
.type = EXPR_PREFIX,
.name = "prefix",
.print = prefix_expr_print,
.set_type = prefix_expr_set_type,
+ .clone = prefix_expr_clone,
+ .destroy = prefix_expr_destroy,
};
struct expr *prefix_expr_alloc(const struct location *loc,
@@ -321,6 +368,11 @@ static void unary_expr_print(const struct expr *expr)
printf(")");
}
+static void unary_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->arg = expr_clone(expr->expr);
+}
+
static void unary_expr_destroy(struct expr *expr)
{
expr_free(expr->arg);
@@ -330,6 +382,7 @@ static const struct expr_ops unary_expr_ops = {
.type = EXPR_UNARY,
.name = "unary",
.print = unary_expr_print,
+ .clone = unary_expr_clone,
.destroy = unary_expr_destroy,
};
@@ -355,6 +408,12 @@ static void binop_expr_print(const struct expr *expr)
expr_print(expr->right);
}
+static void binop_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->left = expr_clone(expr->left);
+ new->right = expr_clone(expr->right);
+}
+
static void binop_expr_destroy(struct expr *expr)
{
expr_free(expr->left);
@@ -365,6 +424,7 @@ static const struct expr_ops binop_expr_ops = {
.type = EXPR_BINOP,
.name = "binop",
.print = binop_expr_print,
+ .clone = binop_expr_clone,
.destroy = binop_expr_destroy,
};
@@ -408,6 +468,12 @@ static void range_expr_print(const struct expr *expr)
expr_print(expr->right);
}
+static void range_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->left = expr_clone(expr->left);
+ new->right = expr_clone(expr->right);
+}
+
static void range_expr_destroy(struct expr *expr)
{
expr_free(expr->left);
@@ -426,6 +492,7 @@ static const struct expr_ops range_expr_ops = {
.type = EXPR_RANGE,
.name = "range",
.print = range_expr_print,
+ .clone = range_expr_clone,
.destroy = range_expr_destroy,
.set_type = range_expr_set_type,
};
@@ -452,6 +519,15 @@ static struct expr *compound_expr_alloc(const struct location *loc,
return expr;
}
+static void compound_expr_clone(struct expr *new, const struct expr *expr)
+{
+ struct expr *i;
+
+ init_list_head(&new->expressions);
+ list_for_each_entry(i, &expr->expressions, list)
+ compound_expr_add(new, expr_clone(i));
+}
+
static void compound_expr_destroy(struct expr *expr)
{
struct expr *i, *next;
@@ -493,6 +569,7 @@ static const struct expr_ops concat_expr_ops = {
.type = EXPR_CONCAT,
.name = "concat",
.print = concat_expr_print,
+ .clone = compound_expr_clone,
.destroy = compound_expr_destroy,
};
@@ -510,6 +587,7 @@ static const struct expr_ops list_expr_ops = {
.type = EXPR_LIST,
.name = "list",
.print = list_expr_print,
+ .clone = compound_expr_clone,
.destroy = compound_expr_destroy,
};
@@ -540,6 +618,7 @@ static const struct expr_ops set_expr_ops = {
.name = "set",
.print = set_expr_print,
.set_type = set_expr_set_type,
+ .clone = compound_expr_clone,
.destroy = compound_expr_destroy,
};
@@ -562,6 +641,12 @@ static void mapping_expr_set_type(const struct expr *expr,
expr_set_type(expr->left, dtype, byteorder);
}
+static void mapping_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->left = expr_clone(expr->left);
+ new->right = expr_clone(expr->right);
+}
+
static void mapping_expr_destroy(struct expr *expr)
{
expr_free(expr->left);
@@ -573,6 +658,7 @@ static const struct expr_ops mapping_expr_ops = {
.name = "mapping",
.print = mapping_expr_print,
.set_type = mapping_expr_set_type,
+ .clone = mapping_expr_clone,
.destroy = mapping_expr_destroy,
};
@@ -595,6 +681,12 @@ static void map_expr_print(const struct expr *expr)
expr_print(expr->mappings);
}
+static void map_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->expr = expr_clone(expr->expr);
+ new->mappings = expr_clone(expr->mappings);
+}
+
static void map_expr_destroy(struct expr *expr)
{
expr_free(expr->expr);
@@ -605,6 +697,7 @@ static const struct expr_ops map_expr_ops = {
.type = EXPR_MAP,
.name = "map",
.print = map_expr_print,
+ .clone = map_expr_clone,
.destroy = map_expr_destroy,
};
diff --git a/src/exthdr.c b/src/exthdr.c
index 2defc7cb..718979a5 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -27,10 +27,17 @@ static void exthdr_expr_print(const struct expr *expr)
printf("%s %s", expr->exthdr.desc->name, expr->exthdr.tmpl->token);
}
+static void exthdr_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->exthdr.desc = expr->exthdr.desc;
+ new->exthdr.tmpl = expr->exthdr.tmpl;
+}
+
static const struct expr_ops exthdr_expr_ops = {
.type = EXPR_EXTHDR,
.name = "exthdr",
.print = exthdr_expr_print,
+ .clone = exthdr_expr_clone,
};
static const struct payload_template exthdr_unknown_template =
diff --git a/src/meta.c b/src/meta.c
index cb9e495c..5998d09c 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -305,10 +305,16 @@ static void meta_expr_print(const struct expr *expr)
printf("meta %s", meta_templates[expr->meta.key].token);
}
+static void meta_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->meta.key = expr->meta.key;
+}
+
static const struct expr_ops meta_expr_ops = {
.type = EXPR_META,
.name = "meta",
.print = meta_expr_print,
+ .clone = meta_expr_clone,
};
struct expr *meta_expr_alloc(const struct location *loc, enum nft_meta_keys key)
diff --git a/src/payload.c b/src/payload.c
index b7fbcb36..f76586e3 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -63,10 +63,20 @@ static void payload_expr_print(const struct expr *expr)
expr->payload.offset, expr->len);
}
+static void payload_expr_clone(struct expr *new, const struct expr *expr)
+{
+ new->payload.desc = expr->payload.desc;
+ new->payload.tmpl = expr->payload.tmpl;
+ new->payload.base = expr->payload.base;
+ new->payload.offset = expr->payload.offset;
+ new->payload.flags = expr->payload.flags;
+}
+
static const struct expr_ops payload_expr_ops = {
.type = EXPR_PAYLOAD,
.name = "payload",
.print = payload_expr_print,
+ .clone = payload_expr_clone,
};
struct expr *payload_expr_alloc(const struct location *loc,