This patch adds the generic infrastructure is used to describe the
transformation from abstract syntax tree to target internal
representation.
The target has to define the transformation callbacks:
struct nft_ast_xfrm_desc {
const struct nft_ast_proto_desc *proto_desc;
const struct nft_ast_meta_desc *meta_desc;
};
The protocol and meta description structure provide the callback to
transform internal representation to the corresponding target.
struct nft_ast_{proto,meta}_desc {
int (*xfrm)(const struct nft_ast_expr *dlexpr,
struct nft_ast_xfrm_state *state, void *data);
};
Signed-off-by: Pablo Neira Ayuso <[email protected]>
---
include/net/netfilter/nf_tables_jit.h | 39 +++++++++++++++++++
net/netfilter/nf_tables_jit.c | 71 +++++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+)
diff --git a/include/net/netfilter/nf_tables_jit.h
b/include/net/netfilter/nf_tables_jit.h
index 124d3da91b0d..dff3af7ad420 100644
--- a/include/net/netfilter/nf_tables_jit.h
+++ b/include/net/netfilter/nf_tables_jit.h
@@ -81,4 +81,43 @@ void nft_ast_stmt_list_print(struct list_head *stmt_list);
int nft_delinearize(struct list_head *ast_stmt_list, struct nft_rule *rule);
+/*
+ * Tree of transformation callback definitions.
+ */
+struct nft_ast_xfrm_state;
+
+/**
+ * struct nft_ast_proto_desc - nf_tables protocol transformation
description
+ *
+ * @xfrm: transformation callback
+ */
+struct nft_ast_proto_desc {
+ int (*xfrm)(const struct nft_ast_expr *dlexpr,
+ struct nft_ast_xfrm_state *state, void *data);
+};
+
+/**
+ * struct nft_ast_meta_desc - nf_tables meta transformation description
+ *
+ * @xfrm: transformation callback
+ */
+struct nft_ast_meta_desc {
+ int (*xfrm)(const struct nft_ast_expr *dlexpr,
+ struct nft_ast_xfrm_state *state, void *data);
+};
+
+/**
+ * struct nft_ast_xfrm_desc - nf_tables generic transformation description
+ *
+ * @key: meta key
+ * @xfrm: transformation callback
+ */
+struct nft_ast_xfrm_desc {
+ const struct nft_ast_proto_desc *proto_desc;
+ const struct nft_ast_meta_desc *meta_desc;
+};
+
+int nft_ast_xfrm(const struct list_head *ast_stmt_list,
+ const struct nft_ast_xfrm_desc *base_desc, void *data);
+
#endif
diff --git a/net/netfilter/nf_tables_jit.c b/net/netfilter/nf_tables_jit.c
index e971b94bbc69..63673ea42be8 100644
--- a/net/netfilter/nf_tables_jit.c
+++ b/net/netfilter/nf_tables_jit.c
@@ -134,3 +134,74 @@ void nft_ast_stmt_list_print(struct list_head *stmt_list)
}
}
EXPORT_SYMBOL_GPL(nft_ast_stmt_list_print);
+
+struct nft_ast_xfrm_state {
+ const struct nft_ast_xfrm_desc *xfrm_desc;
+ void *data;
+};
+
+static int nft_ast_xfrm_relational(const struct nft_ast_expr *dlexpr,
+ struct nft_ast_xfrm_state *state)
+{
+ const struct nft_ast_expr *left = dlexpr->relational.left;
+ const struct nft_ast_expr *right = dlexpr->relational.right;
+ const struct nft_ast_xfrm_desc *xfrm_desc = state->xfrm_desc;
+ int err;
+
+ if (right->type != NFT_AST_EXPR_VALUE)
+ return -EOPNOTSUPP;
+
+ switch (left->type) {
+ case NFT_AST_EXPR_META:
+ err = xfrm_desc->meta_desc->xfrm(dlexpr, state, state->data);
+ break;
+ case NFT_AST_EXPR_PAYLOAD:
+ err = xfrm_desc->proto_desc->xfrm(dlexpr, state, state->data);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
+static int nft_ast_xfrm_expr(const struct nft_ast_expr *dlexpr,
+ struct nft_ast_xfrm_state *state)
+{
+ int err;
+
+ switch (dlexpr->type) {
+ case NFT_AST_EXPR_RELATIONAL:
+ err = nft_ast_xfrm_relational(dlexpr, state);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
+int nft_ast_xfrm(const struct list_head *ast_stmt_list,
+ const struct nft_ast_xfrm_desc *xfrm_desc, void *data)
+{
+ struct nft_ast_xfrm_state state = {
+ .xfrm_desc = xfrm_desc,
+ .data = data,
+ };
+ struct nft_ast_stmt *stmt;
+ int err = 0;
+
+ list_for_each_entry(stmt, ast_stmt_list, list) {
+ switch (stmt->type) {
+ case NFT_AST_STMT_EXPR:
+ err = nft_ast_xfrm_expr(stmt->expr, &state);
+ if (err < 0)
+ return err;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(nft_ast_xfrm);
--
2.11.0