summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-08-29 16:23:28 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-08-30 12:19:36 +0200
commit49e0f1dc6e52e791f5e0ba21097aea17d5950d38 (patch)
tree00215046781f409c62974cd57bf75f96ad265a51
parent90d4ee087171e75d5313359ad6b6f1341e51ddc5 (diff)
JSON: Add metainfo object to all output
Right now this object merely contains the nftables version and release name as well as a JSON schema version, but it could be extended arbitrarily. In the future, this will also allow for non-compatible schema changes should the need for this arise. Adjust the parser to accept metainfo objects and make it verify json_schema_version to be less than or equal to the one hard-coded in the library. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--doc/libnftables-json.adoc25
-rw-r--r--include/json.h2
-rw-r--r--src/json.c19
-rw-r--r--src/parser_json.c27
4 files changed, 68 insertions, 5 deletions
diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc
index c174a354..59bac17f 100644
--- a/doc/libnftables-json.adoc
+++ b/doc/libnftables-json.adoc
@@ -16,13 +16,14 @@ libnftables-json - Supported JSON schema by libnftables
'CMD_OBJECTS' := 'CMD_OBJECT' [ *,* 'CMD_OBJECTS' ]
-'CMD_OBJECT' := *{* 'CMD'*:* 'LIST_OBJECT' *}*
+'CMD_OBJECT' := *{* 'CMD'*:* 'LIST_OBJECT' *}* | 'METAINFO_OBJECT'
'CMD' := *"add"* | *"replace"* | *"create"* | *"insert"* | *"delete"* |
*"list"* | *"reset"* | *"flush"* | *"rename"*
'LIST_OBJECT' := 'TABLE' | 'CHAIN' | 'RULE' | 'SET' | 'MAP' | 'ELEMENT' |
- 'FLOWTABLE' | 'COUNTER' | 'QUOTA' | 'CT_HELPER' | 'LIMIT'
+ 'FLOWTABLE' | 'COUNTER' | 'QUOTA' | 'CT_HELPER' | 'LIMIT' |
+ 'METAINFO_OBJECT'
== DESCRIPTION
libnftables supports JSON formatted input and output. This is implemented as an
@@ -47,6 +48,26 @@ It's value is a ruleset element - basically identical to output elements apart
from certain properties which may be interpreted differently or are required
when output generally omits them.
+== METAINFO OBJECT
+In output, the first object in *nftables* array is a special one containing
+library information. Its content is as follows:
+
+[verse]
+*{ "metainfo": {
+ "version":* 'STRING'*,
+ "release_name":* 'STRING'*,
+ "json_schema_version":* 'NUMBER'
+*}}*
+
+The values of *version* and *release_name* properties are equal to the package
+version and release name as printed by *nft -v*. The value of
+*json_schema_version* property is an integer indicating the schema version.
+
+If supplied in library input, the parser will verify *json_schema_version* value
+to not exceed the internally hardcoded one (to make sure the given schema is
+fully understood). In future, a lower number than the internal one may activate
+compatibility mode to parse outdated and incompatible JSON input.
+
== COMMAND OBJECTS
The structure accepts an arbitrary amount of commands which are interpreted in
order of appearance. For instance, the following standard syntax input:
diff --git a/include/json.h b/include/json.h
index e64151de..66f60e76 100644
--- a/include/json.h
+++ b/include/json.h
@@ -15,6 +15,8 @@ struct table;
#ifdef HAVE_LIBJANSSON
+#define JSON_SCHEMA_VERSION 1
+
#include <jansson.h>
json_t *binop_expr_json(const struct expr *expr, struct output_ctx *octx);
diff --git a/src/json.c b/src/json.c
index 2a13dfe7..84bdaa39 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1530,6 +1530,14 @@ static json_t *do_list_flowtables_json(struct netlink_ctx *ctx, struct cmd *cmd)
return root;
}
+static json_t *generate_json_metainfo(void)
+{
+ return json_pack("{s: {s:s, s:s, s:i}}", "metainfo",
+ "version", PACKAGE_VERSION,
+ "release_name", RELEASE_NAME,
+ "json_schema_version", JSON_SCHEMA_VERSION);
+}
+
int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd)
{
struct table *table = NULL;
@@ -1596,10 +1604,15 @@ int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd)
BUG("invalid command object type %u\n", cmd->obj);
}
- if (json_is_array(root) && !json_array_size(root)) {
- json_decref(root);
- root = json_null();
+ if (!json_is_array(root)) {
+ json_t *tmp = json_array();
+
+ json_array_append_new(tmp, root);
+ root = tmp;
}
+
+ json_array_insert_new(root, 0, generate_json_metainfo());
+
root = json_pack("{s:o}", "nftables", root);
json_dumpf(root, ctx->octx->output_fp, 0);
json_decref(root);
diff --git a/src/parser_json.c b/src/parser_json.c
index 6870434e..6af9d075 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -3118,6 +3118,22 @@ static struct cmd *json_parse_cmd(struct json_ctx *ctx, json_t *root)
return NULL;
}
+static int json_verify_metainfo(struct json_ctx *ctx, json_t *root)
+{
+ int schema_version;
+
+ if (!json_unpack(root, "{s:i}", "json_schema_version", &schema_version))
+ return 0;
+
+ if (schema_version > JSON_SCHEMA_VERSION) {
+ json_error(ctx, "Schema version %d not supported, maximum supported version is %d\n",
+ schema_version, JSON_SCHEMA_VERSION);
+ return 1;
+ }
+
+ return 0;
+}
+
static int __json_parse(struct json_ctx *ctx, json_t *root)
{
struct eval_ctx ectx = {
@@ -3142,11 +3158,22 @@ static int __json_parse(struct json_ctx *ctx, json_t *root)
/* this is more or less from parser_bison.y:716 */
LIST_HEAD(list);
struct cmd *cmd;
+ json_t *tmp2;
if (!json_is_object(value)) {
json_error(ctx, "Unexpected command array element of type %s, expected object.", json_typename(value));
return -1;
}
+
+ tmp2 = json_object_get(value, "metainfo");
+ if (tmp2) {
+ if (json_verify_metainfo(ctx, tmp2)) {
+ json_error(ctx, "Metainfo verification failed.");
+ return -1;
+ }
+ continue;
+ }
+
cmd = json_parse_cmd(ctx, value);
if (!cmd) {