summaryrefslogtreecommitdiffstats
path: root/src/parser_json.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2021-05-04 13:41:38 +0200
committerPhil Sutter <phil@nwl.cc>2021-05-19 11:52:05 +0200
commit0e3871cfd9a1e32a4ac041ce87a8057b11a89924 (patch)
tree926b57779c199024a9d8e1ceb8fd031ff28f88b7 /src/parser_json.c
parentfd81d3ec3ae8b8d1d54a708d63b2dab2c8508c90 (diff)
exthdr: Implement SCTP Chunk matching
Extend exthdr expression to support scanning through SCTP packet chunks and matching on fixed fields' values. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src/parser_json.c')
-rw-r--r--src/parser_json.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/parser_json.c b/src/parser_json.c
index 17bb10c3..9b79497c 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -11,6 +11,7 @@
#include <netlink.h>
#include <parser.h>
#include <rule.h>
+#include <sctp_chunk.h>
#include <socket.h>
#include <netdb.h>
@@ -707,6 +708,53 @@ static struct expr *json_parse_ip_option_expr(struct json_ctx *ctx,
return ipopt_expr_alloc(int_loc, descval, fieldval, 0);
}
+static int json_parse_sctp_chunk_field(const struct exthdr_desc *desc,
+ const char *name, int *val)
+{
+ unsigned int i;
+
+ for (i = 0; i < array_size(desc->templates); i++) {
+ if (desc->templates[i].token &&
+ !strcmp(desc->templates[i].token, name)) {
+ if (val)
+ *val = i;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static struct expr *json_parse_sctp_chunk_expr(struct json_ctx *ctx,
+ const char *type, json_t *root)
+{
+ const struct exthdr_desc *desc;
+ const char *name, *field;
+ struct expr *expr;
+ int fieldval;
+
+ if (json_unpack_err(ctx, root, "{s:s}", "name", &name))
+ return NULL;
+
+ desc = sctp_chunk_protocol_find(name);
+ if (!desc) {
+ json_error(ctx, "Unknown sctp chunk name '%s'.", name);
+ return NULL;
+ }
+
+ if (json_unpack(root, "{s:s}", "field", &field)) {
+ expr = sctp_chunk_expr_alloc(int_loc, desc->type,
+ SCTP_CHUNK_COMMON_TYPE);
+ expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
+
+ return expr;
+ }
+ if (json_parse_sctp_chunk_field(desc, field, &fieldval)) {
+ json_error(ctx, "Unknown sctp chunk field '%s'.", field);
+ return NULL;
+ }
+ return sctp_chunk_expr_alloc(int_loc, desc->type, fieldval);
+}
+
static const struct exthdr_desc *exthdr_lookup_byname(const char *name)
{
const struct exthdr_desc *exthdr_tbl[] = {
@@ -1412,6 +1460,7 @@ static struct expr *json_parse_expr(struct json_ctx *ctx, json_t *root)
{ "exthdr", json_parse_exthdr_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT },
{ "tcp option", json_parse_tcp_option_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_CONCAT },
{ "ip option", json_parse_ip_option_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_CONCAT },
+ { "sctp chunk", json_parse_sctp_chunk_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_CONCAT },
{ "meta", json_parse_meta_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT },
{ "osf", json_parse_osf_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_MAP | CTX_F_CONCAT },
{ "ipsec", json_parse_xfrm_expr, CTX_F_PRIMARY | CTX_F_MAP | CTX_F_CONCAT },