]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
json: Add ct timeout support
authorPhil Sutter <phil@nwl.cc>
Thu, 11 Oct 2018 15:48:56 +0000 (17:48 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 15 Oct 2018 11:37:51 +0000 (13:37 +0200)
Add support for printing and parsing ct timeout objects to JSON API.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/json.c
src/parser_json.c
tests/py/ip/objects.t.json

index 0191a2ea7df0daf2395ee819df3e0077ce9cc031..b8d9333e877a8edddaffb170d5ee91f3729d40a3 100644 (file)
@@ -235,6 +235,23 @@ static json_t *proto_name_json(uint8_t proto)
        return json_integer(proto);
 }
 
+static json_t *timeout_policy_json(uint8_t l4, const uint32_t *timeout)
+{
+       json_t *root = NULL;
+       unsigned int i;
+
+       for (i = 0; i < timeout_protocol[l4].array_size; i++) {
+               if (timeout[i] == timeout_protocol[l4].dflt_timeout[i])
+                       continue;
+
+               if (!root)
+                       root = json_object();
+               json_object_set(root, timeout_protocol[l4].state_to_name[i],
+                               json_integer(timeout[i]));
+       }
+       return root ? : json_null();
+}
+
 static json_t *obj_print_json(struct output_ctx *octx, const struct obj *obj)
 {
        const char *rate_unit = NULL, *burst_unit = NULL;
@@ -273,6 +290,18 @@ static json_t *obj_print_json(struct output_ctx *octx, const struct obj *obj)
                json_object_update(root, tmp);
                json_decref(tmp);
                break;
+       case NFT_OBJECT_CT_TIMEOUT:
+               type = "ct timeout";
+               tmp = timeout_policy_json(obj->ct_timeout.l4proto,
+                                         obj->ct_timeout.timeout);
+               tmp = json_pack("{s:o, s:s, s:o}",
+                               "protocol",
+                               proto_name_json(obj->ct_timeout.l4proto),
+                               "l3proto", family2str(obj->ct_timeout.l3proto),
+                               "policy", tmp);
+               json_object_update(root, tmp);
+               json_decref(tmp);
+               break;
        case NFT_OBJECT_LIMIT:
                rate = obj->limit.rate;
                burst = obj->limit.burst;
index 9aadc33ed93a0543d3ac79ba9a468b31aa24f4db..35464c9a83c830a30a60d83570fd246bfae6a0e3 100644 (file)
@@ -2106,7 +2106,22 @@ static struct stmt *json_parse_cthelper_stmt(struct json_ctx *ctx,
        stmt->objref.type = NFT_OBJECT_CT_HELPER;
        stmt->objref.expr = json_parse_stmt_expr(ctx, value);
        if (!stmt->objref.expr) {
-               json_error(ctx, "Invalid cthelper reference.");
+               json_error(ctx, "Invalid ct helper reference.");
+               stmt_free(stmt);
+               return NULL;
+       }
+       return stmt;
+}
+
+static struct stmt *json_parse_cttimeout_stmt(struct json_ctx *ctx,
+                                            const char *key, json_t *value)
+{
+       struct stmt *stmt = objref_stmt_alloc(int_loc);
+
+       stmt->objref.type = NFT_OBJECT_CT_TIMEOUT;
+       stmt->objref.expr = json_parse_stmt_expr(ctx, value);
+       if (!stmt->objref.expr) {
+               json_error(ctx, "Invalid ct timeout reference.");
                stmt_free(stmt);
                return NULL;
        }
@@ -2257,6 +2272,7 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root)
                { "set", json_parse_set_stmt },
                { "log", json_parse_log_stmt },
                { "ct helper", json_parse_cthelper_stmt },
+               { "ct timeout", json_parse_cttimeout_stmt },
                { "meter", json_parse_meter_stmt },
                { "queue", json_parse_queue_stmt },
                { "ct count", json_parse_connlimit_stmt },
@@ -2737,6 +2753,39 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx,
        return cmd_alloc(op, cmd_obj, &h, int_loc, flowtable);
 }
 
+static int json_parse_ct_timeout_policy(struct json_ctx *ctx,
+                                       json_t *root, struct obj *obj)
+{
+       json_t *tmp, *val;
+       const char *key;
+
+       if (!json_unpack(root, "{s:o}", "policy", &tmp))
+               return 0;
+
+       if (json_is_object(tmp)) {
+               json_error(ctx, "Invalid ct timeout policy.");
+               return 1;
+       }
+
+       init_list_head(&obj->ct_timeout.timeout_list);
+       json_object_foreach(tmp, key, val) {
+               struct timeout_state *ts;
+
+               if (!json_is_integer(val)) {
+                       json_error(ctx, "Invalid ct timeout policy value for '%s'.", key);
+                       return 1;
+               }
+
+               ts = xzalloc(sizeof(*ts));
+               ts->timeout_str = xstrdup(key);
+               ts->timeout_value = json_integer_value(val);
+               ts->location = *int_loc;
+               init_list_head(&ts->head);
+               list_add_tail(&ts->head, &obj->ct_timeout.timeout_list);
+       }
+       return 0;
+}
+
 static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
                                             json_t *root, enum cmd_ops op,
                                             enum cmd_obj cmd_obj)
@@ -2834,6 +2883,37 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
                        obj->ct_helper.l3proto = NFPROTO_IPV4;
                }
                break;
+       case NFT_OBJECT_CT_TIMEOUT:
+               cmd_obj = CMD_OBJ_CT_TIMEOUT;
+               obj->type = NFT_OBJECT_CT_TIMEOUT;
+               if (!json_unpack(root, "{s:s}", "protocol", &tmp)) {
+                       if (!strcmp(tmp, "tcp")) {
+                               obj->ct_timeout.l4proto = IPPROTO_TCP;
+                       } else if (!strcmp(tmp, "udp")) {
+                               obj->ct_timeout.l4proto = IPPROTO_UDP;
+                       } else {
+                               json_error(ctx, "Invalid ct timeout protocol '%s'.", tmp);
+                               obj_free(obj);
+                               return NULL;
+                       }
+               }
+               if (!json_unpack(root, "{s:s}", "l3proto", &tmp)) {
+                       int family = parse_family(tmp);
+
+                       if (family < 0) {
+                               json_error(ctx, "Invalid ct timeout l3proto '%s'.", tmp);
+                               obj_free(obj);
+                               return NULL;
+                       }
+                       obj->ct_timeout.l3proto = family;
+               } else {
+                       obj->ct_timeout.l3proto = NFPROTO_IPV4;
+               }
+               if (json_parse_ct_timeout_policy(ctx, root, obj)) {
+                       obj_free(obj);
+                       return NULL;
+               }
+               break;
        case CMD_OBJ_LIMIT:
                obj->type = NFT_OBJECT_LIMIT;
                if (json_unpack_err(ctx, root, "{s:I, s:s}",
index 8e838cf41439790741f20022e25163aea59606ba..a98d73c5f3157d63a1960877178635acdfd3a7fb 100644 (file)
     }
 ]
 
+# ct timeout set "cttime1"
+[
+    {
+        "ct timeout": "cttime1"
+    }
+]
+