]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
json: Support typeof in set and map types
authorPhil Sutter <phil@nwl.cc>
Fri, 27 Sep 2024 22:55:34 +0000 (00:55 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 23 Jan 2025 00:35:37 +0000 (01:35 +0100)
commit bb6312484af93a83a9ec8716f3887a43566a775a upstream.

Implement this as a special "type" property value which is an object
with sole property "typeof". The latter's value is the JSON
representation of the expression in set->key, so for concatenated
typeofs it is a concat expression.

All this is a bit clumsy right now but it works and it should be
possible to tear it down a bit for more user-friendliness in a
compatible way by either replacing the concat expression by the array it
contains or even the whole "typeof" object - the parser would just
assume any object (or objects in an array) in the "type" property value
are expressions to extract a type from.

Signed-off-by: Phil Sutter <phil@nwl.cc>
doc/libnftables-json.adoc
src/json.c
src/parser_json.c

index 1cce0e69301bac97c1aa1d48209398b091eb755e..10c17fa11e5c3c9600800baf0953caa57618b209 100644 (file)
@@ -332,7 +332,7 @@ ____
        "auto-merge":* 'BOOLEAN'
 *}}*
 
-'SET_TYPE' := 'STRING' | *[* 'SET_TYPE_LIST' *]*
+'SET_TYPE' := 'STRING' | *[* 'SET_TYPE_LIST' *]* | *{ "typeof":* 'EXPRESSION' *}*
 'SET_TYPE_LIST' := 'STRING' [*,* 'SET_TYPE_LIST' ]
 'SET_POLICY' := *"performance"* | *"memory"*
 'SET_FLAG_LIST' := 'SET_FLAG' [*,* 'SET_FLAG_LIST' ]
@@ -372,8 +372,9 @@ that they translate a unique key to a value.
        Automatic merging of adjacent/overlapping set elements in interval sets.
 
 ==== TYPE
-The set type might be a string, such as *"ipv4_addr"* or an array
-consisting of strings (for concatenated types).
+The set type might be a string, such as *"ipv4_addr"*, an array
+consisting of strings (for concatenated types) or a *typeof* object containing
+an expression to extract the type from.
 
 ==== ELEM
 A single set element might be given as string, integer or boolean value for
index e950157f1cd74dd6ffb332c787bb169dec4de58c..9e4e1c1f750748baea85fd39bf587b43da98df1b 100644 (file)
@@ -86,6 +86,17 @@ static json_t *set_dtype_json(const struct expr *key)
        return root;
 }
 
+static json_t *set_key_dtype_json(const struct set *set,
+                                 struct output_ctx *octx)
+{
+       bool use_typeof = set->key_typeof_valid;
+
+       if (!use_typeof)
+               return set_dtype_json(set->key);
+
+       return json_pack("{s:o}", "typeof", expr_print_json(set->key, octx));
+}
+
 static json_t *stmt_print_json(const struct stmt *stmt, struct output_ctx *octx)
 {
        char buf[1024];
@@ -148,7 +159,7 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
                        "family", family2str(set->handle.family),
                        "name", set->handle.set.name,
                        "table", set->handle.table.name,
-                       "type", set_dtype_json(set->key),
+                       "type", set_key_dtype_json(set, octx),
                        "handle", set->handle.handle.id);
 
        if (set->comment)
index 5f66a38b3b81c83b1ceba84a3bfa39174719cba5..f37304ad7fff9d15fa6298eebc8e8fb4f6d990b7 100644 (file)
@@ -1657,7 +1657,16 @@ static struct expr *json_parse_dtype_expr(struct json_ctx *ctx, json_t *root)
                        compound_expr_add(expr, i);
                }
                return expr;
+       } else if (json_is_object(root)) {
+               const char *key;
+               json_t *val;
+
+               if (!json_unpack_stmt(ctx, root, &key, &val) &&
+                   !strcmp(key, "typeof")) {
+                       return json_parse_expr(ctx, val);
+               }
        }
+
        json_error(ctx, "Invalid set datatype.");
        return NULL;
 }