* @destroy: destructor, must release inner expressions
* @set_type: function to promote type and byteorder of inner types
* @print: function to print the expression
+ * @cmp: function to compare two expressions of the same types
* @pctx_update:update protocol context
*/
struct proto_ctx;
const struct datatype *dtype,
enum byteorder byteorder);
void (*print)(const struct expr *expr);
+ bool (*cmp)(const struct expr *e1,
+ const struct expr *e2);
void (*pctx_update)(struct proto_ctx *ctx,
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);
+extern bool expr_cmp(const struct expr *e1, const struct expr *e2);
extern void expr_describe(const struct expr *expr);
extern const struct datatype *expr_basetype(const struct expr *expr);
printf("ct %s", ct_templates[expr->ct.key].token);
}
+static bool ct_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+ return e1->ct.key == e2->ct.key;
+}
+
static void ct_expr_clone(struct expr *new, const struct expr *expr)
{
new->ct.key = expr->ct.key;
.type = EXPR_CT,
.name = "ct",
.print = ct_expr_print,
+ .cmp = ct_expr_cmp,
.clone = ct_expr_clone,
.pctx_update = ct_expr_pctx_update,
};
expr->ops->print(expr);
}
+bool expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+ assert(e1->flags & EXPR_F_SINGLETON);
+ assert(e2->flags & EXPR_F_SINGLETON);
+
+ if (e1->ops->type != e2->ops->type)
+ return false;
+
+ return e1->ops->cmp(e1, e2);
+}
+
void expr_describe(const struct expr *expr)
{
const struct datatype *dtype = expr->dtype;
datatype_print(expr);
}
+static bool verdict_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+ if (e1->verdict != e2->verdict)
+ return false;
+
+ if ((e1->verdict == NFT_JUMP ||
+ e1->verdict == NFT_GOTO) &&
+ strcmp(e1->chain, e2->chain))
+ return false;
+
+ return true;
+}
+
static void verdict_expr_clone(struct expr *new, const struct expr *expr)
{
new->verdict = expr->verdict;
.type = EXPR_VERDICT,
.name = "verdict",
.print = verdict_expr_print,
+ .cmp = verdict_expr_cmp,
.clone = verdict_expr_clone,
.destroy = verdict_expr_destroy,
};
datatype_print(expr);
}
+static bool constant_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+ return expr_basetype(e1) == expr_basetype(e2) &&
+ !mpz_cmp(e1->value, e2->value);
+}
+
static void constant_expr_clone(struct expr *new, const struct expr *expr)
{
mpz_init_set(new->value, expr->value);
.type = EXPR_VALUE,
.name = "value",
.print = constant_expr_print,
+ .cmp = constant_expr_cmp,
.clone = constant_expr_clone,
.destroy = constant_expr_destroy,
};
printf("%s %s", expr->exthdr.desc->name, expr->exthdr.tmpl->token);
}
+static bool exthdr_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+ return e1->exthdr.desc == e2->exthdr.desc &&
+ e1->exthdr.tmpl == e2->exthdr.tmpl;
+}
+
static void exthdr_expr_clone(struct expr *new, const struct expr *expr)
{
new->exthdr.desc = expr->exthdr.desc;
.type = EXPR_EXTHDR,
.name = "exthdr",
.print = exthdr_expr_print,
+ .cmp = exthdr_expr_cmp,
.clone = exthdr_expr_clone,
};
}
}
+static bool meta_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+ return e1->meta.key == e2->meta.key;
+}
+
static void meta_expr_clone(struct expr *new, const struct expr *expr)
{
new->meta.key = expr->meta.key;
.type = EXPR_META,
.name = "meta",
.print = meta_expr_print,
+ .cmp = meta_expr_cmp,
.clone = meta_expr_clone,
.pctx_update = meta_expr_pctx_update,
};
expr->payload.offset, expr->len);
}
+static bool payload_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+ return e1->payload.desc == e2->payload.desc &&
+ e1->payload.tmpl == e2->payload.tmpl &&
+ e1->payload.base == e2->payload.base &&
+ e1->payload.offset == e2->payload.offset;
+}
+
static void payload_expr_clone(struct expr *new, const struct expr *expr)
{
new->payload.desc = expr->payload.desc;
.type = EXPR_PAYLOAD,
.name = "payload",
.print = payload_expr_print,
+ .cmp = payload_expr_cmp,
.clone = payload_expr_clone,
.pctx_update = payload_expr_pctx_update,
};