summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-10-11 17:48:56 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-10-15 13:37:51 +0200
commitc82a26ebf7e9f5caf74fa4005da8eb7007cd940c (patch)
tree23d83898735f2b233ba2fd4ddecf48c9db4cdd17
parentdf21b75ae20092e36e5aa6fc19c9c96a3f629751 (diff)
json: Add ct timeout support
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>
-rw-r--r--src/json.c29
-rw-r--r--src/parser_json.c82
-rw-r--r--tests/py/ip/objects.t.json7
3 files changed, 117 insertions, 1 deletions
diff --git a/src/json.c b/src/json.c
index 0191a2ea..b8d9333e 100644
--- a/src/json.c
+++ b/src/json.c
@@ -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;
diff --git a/src/parser_json.c b/src/parser_json.c
index 9aadc33e..35464c9a 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -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}",
diff --git a/tests/py/ip/objects.t.json b/tests/py/ip/objects.t.json
index 8e838cf4..a98d73c5 100644
--- a/tests/py/ip/objects.t.json
+++ b/tests/py/ip/objects.t.json
@@ -186,3 +186,10 @@
}
]
+# ct timeout set "cttime1"
+[
+ {
+ "ct timeout": "cttime1"
+ }
+]
+