From cd11fe1224af5dba5a04aaadf68ad5ca982177f5 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 29 Aug 2018 11:37:41 +0200 Subject: src: tproxy: add json support Signed-off-by: Florian Westphal --- include/json.h | 2 + src/json.c | 26 +++++++++++++ src/parser_json.c | 43 +++++++++++++++++++++ src/statement.c | 1 + tests/py/inet/tproxy.t.json | 90 +++++++++++++++++++++++++++++++++++++++++++ tests/py/ip/tproxy.t.json | 93 +++++++++++++++++++++++++++++++++++++++++++++ tests/py/ip6/tproxy.t.json | 90 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 345 insertions(+) create mode 100644 tests/py/inet/tproxy.t.json create mode 100644 tests/py/ip/tproxy.t.json create mode 100644 tests/py/ip6/tproxy.t.json diff --git a/include/json.h b/include/json.h index 78c026a7..e64151de 100644 --- a/include/json.h +++ b/include/json.h @@ -76,6 +76,7 @@ json_t *meter_stmt_json(const struct stmt *stmt, struct output_ctx *octx); json_t *queue_stmt_json(const struct stmt *stmt, struct output_ctx *octx); json_t *verdict_stmt_json(const struct stmt *stmt, struct output_ctx *octx); json_t *connlimit_stmt_json(const struct stmt *stmt, struct output_ctx *octx); +json_t *tproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx); int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd); @@ -153,6 +154,7 @@ STMT_PRINT_STUB(meter) STMT_PRINT_STUB(queue) STMT_PRINT_STUB(verdict) STMT_PRINT_STUB(connlimit) +STMT_PRINT_STUB(tproxy) #undef STMT_PRINT_STUB #undef EXPR_PRINT_STUB diff --git a/src/json.c b/src/json.c index eac7a3a0..e8870a13 100644 --- a/src/json.c +++ b/src/json.c @@ -1297,6 +1297,32 @@ json_t *connlimit_stmt_json(const struct stmt *stmt, struct output_ctx *octx) return json_pack("{s:o}", "ct count", root); } +json_t *tproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx) +{ + json_t *root = json_object(); + + if (stmt->tproxy.addr) { + int family; + json_t *tmp; + + family = stmt->tproxy.table_family; + if (family == NFPROTO_INET) + family = stmt->tproxy.family; + + tmp = json_string(family2str(family)); + json_object_set_new(root, "family", tmp); + + tmp = expr_print_json(stmt->tproxy.addr, octx); + json_object_set_new(root, "addr", tmp); + } + + if (stmt->tproxy.port) + json_object_set_new(root, "port", + expr_print_json(stmt->tproxy.port, octx)); + + return json_pack("{s:o}", "tproxy", root); +} + static json_t *table_print_json_full(struct netlink_ctx *ctx, struct table *table) { diff --git a/src/parser_json.c b/src/parser_json.c index 6d8cda97..3d96000b 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -1796,6 +1796,48 @@ static struct stmt *json_parse_nat_stmt(struct json_ctx *ctx, return stmt; } +static struct stmt *json_parse_tproxy_stmt(struct json_ctx *ctx, + const char *key, json_t *value) +{ + json_t *jaddr, *tmp; + const char *family; + struct stmt *stmt; + int familyval; + + stmt = tproxy_stmt_alloc(int_loc); + + if (json_unpack(value, "{s:s, s:o}", + "family", &family, "addr", &jaddr)) + goto try_port; + + familyval = parse_family(family); + if (familyval != NFPROTO_IPV4 && + familyval != NFPROTO_IPV6) { + json_error(ctx, "Invalid family '%s'.", family); + goto out_free; + } + stmt->tproxy.family = familyval; + + stmt->tproxy.addr = json_parse_stmt_expr(ctx, jaddr); + if (!stmt->tproxy.addr) { + json_error(ctx, "Invalid addr."); + goto out_free; + } +try_port: + if (!json_unpack(value, "{s:o}", "port", &tmp)) { + stmt->tproxy.port = json_parse_stmt_expr(ctx, tmp); + if (!stmt->tproxy.port) { + json_error(ctx, "Invalid port."); + goto out_free; + } + } + return stmt; + +out_free: + stmt_free(stmt); + return NULL; +} + static struct stmt *json_parse_reject_stmt(struct json_ctx *ctx, const char *key, json_t *value) { @@ -2150,6 +2192,7 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root) { "meter", json_parse_meter_stmt }, { "queue", json_parse_queue_stmt }, { "ct count", json_parse_connlimit_stmt }, + { "tproxy", json_parse_tproxy_stmt }, }; const char *type; unsigned int i; diff --git a/src/statement.c b/src/statement.c index 98e56844..45d2067c 100644 --- a/src/statement.c +++ b/src/statement.c @@ -810,6 +810,7 @@ static const struct stmt_ops tproxy_stmt_ops = { .type = STMT_TPROXY, .name = "tproxy", .print = tproxy_stmt_print, + .json = tproxy_stmt_json, .destroy = tproxy_stmt_destroy, }; diff --git a/tests/py/inet/tproxy.t.json b/tests/py/inet/tproxy.t.json new file mode 100644 index 00000000..88304206 --- /dev/null +++ b/tests/py/inet/tproxy.t.json @@ -0,0 +1,90 @@ +# meta l4proto 17 tproxy ip to 192.0.2.1 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 17 + } + }, + { + "tproxy": { + "addr": "192.0.2.1", + "family": "ip" + } + } +] + +# meta l4proto 6 tproxy ip to 192.0.2.1:50080 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 6 + } + }, + { + "tproxy": { + "addr": "192.0.2.1", + "family": "ip", + "port": 50080 + } + } +] + +# meta l4proto 6 tproxy ip6 to [2001:db8::1] +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 6 + } + }, + { + "tproxy": { + "addr": "2001:db8::1", + "family": "ip6" + } + } +] + +# meta l4proto 17 tproxy ip6 to [2001:db8::1]:50080 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 17 + } + }, + { + "tproxy": { + "addr": "2001:db8::1", + "family": "ip6", + "port": 50080 + } + } +] + +# meta l4proto 17 tproxy to :50080 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 17 + } + }, + { + "tproxy": { + "port": 50080 + } + } +] diff --git a/tests/py/ip/tproxy.t.json b/tests/py/ip/tproxy.t.json new file mode 100644 index 00000000..81b7c188 --- /dev/null +++ b/tests/py/ip/tproxy.t.json @@ -0,0 +1,93 @@ +# meta l4proto 17 tproxy to 192.0.2.1 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 17 + } + }, + { + "tproxy": { + "addr": "192.0.2.1", + "family": "ip" + } + } +] + +# meta l4proto 6 tproxy to 192.0.2.1:50080 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 6 + } + }, + { + "tproxy": { + "addr": "192.0.2.1", + "family": "ip", + "port": 50080 + } + } +] + +# ip protocol 6 tproxy to :50080 +[ + { + "match": { + "left": { + "payload": { + "field": "protocol", + "name": "ip" + } + }, + "right": 6 + } + }, + { + "tproxy": { + "port": 50080 + } + } +] + +# meta l4proto 17 tproxy ip to 192.0.2.1 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 17 + } + }, + { + "tproxy": { + "addr": "192.0.2.1", + "family": "ip" + } + } +] + +# meta l4proto 6 tproxy ip to 192.0.2.1:50080 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 6 + } + }, + { + "tproxy": { + "addr": "192.0.2.1", + "family": "ip", + "port": 50080 + } + } +] diff --git a/tests/py/ip6/tproxy.t.json b/tests/py/ip6/tproxy.t.json new file mode 100644 index 00000000..b627b20e --- /dev/null +++ b/tests/py/ip6/tproxy.t.json @@ -0,0 +1,90 @@ +# meta l4proto 6 tproxy to [2001:db8::1] +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 6 + } + }, + { + "tproxy": { + "addr": "2001:db8::1", + "family": "ip6" + } + } +] + +# meta l4proto 17 tproxy to [2001:db8::1]:50080 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 17 + } + }, + { + "tproxy": { + "addr": "2001:db8::1", + "family": "ip6", + "port": 50080 + } + } +] + +# meta l4proto 6 tproxy to :50080 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 6 + } + }, + { + "tproxy": { + "port": 50080 + } + } +] + +# meta l4proto 6 tproxy ip6 to [2001:db8::1] +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 6 + } + }, + { + "tproxy": { + "addr": "2001:db8::1", + "family": "ip6" + } + } +] + +# meta l4proto 17 tproxy ip6 to [2001:db8::1]:50080 +[ + { + "match": { + "left": { + "meta": "l4proto" + }, + "right": 17 + } + }, + { + "tproxy": { + "addr": "2001:db8::1", + "family": "ip6", + "port": 50080 + } + } +] -- cgit v1.2.3