* [PATCH nft 1/3] tests: json: add missing test case output
2020-11-03 18:20 [PATCH nft 0/3] json: resolve multiple test case failures Florian Westphal
@ 2020-11-03 18:20 ` Florian Westphal
2020-11-03 18:20 ` [PATCH nft 2/3] tests: avoid warning and add missing json test cases Florian Westphal
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2020-11-03 18:20 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
Fix warnings and errors when running nf-test.py -j due to missing json test case updates.
This also makes bridge/reject.t pass in json mode.
No code changes.
Fixes: 8615ed93f6e4c4 ("evaluate: enable reject with 802.1q")
Fixes: fae0a0972d7a71 ("tests: py: Enable anonymous set rule with concatenated ranges in inet/sets.t")
Fixes: 2a20b5bdbde8a1 ("datatype: add frag-needed (ipv4) to reject options")
Signed-off-by: Florian Westphal <fw@strlen.de>
---
tests/py/bridge/reject.t | 2 +-
tests/py/bridge/reject.t.json | 72 +++++++++++++++++++++++++++++++++
tests/py/inet/sets.t.json | 74 ++++++++++++++++++++++++++++++++++
tests/py/ip/icmp.t.json | 4 +-
tests/py/ip/icmp.t.json.output | 2 +-
5 files changed, 150 insertions(+), 4 deletions(-)
diff --git a/tests/py/bridge/reject.t b/tests/py/bridge/reject.t
index f5ed203815e5..ee33af77eab6 100644
--- a/tests/py/bridge/reject.t
+++ b/tests/py/bridge/reject.t
@@ -32,7 +32,7 @@ ether type ip6 reject with icmp type host-unreachable;fail
ether type ip reject with icmpv6 type no-route;fail
ether type vlan reject;ok
ether type arp reject;fail
-ether type vlan reject with tcp reset;ok
+ether type vlan reject with tcp reset;ok;meta l4proto 6 ether type vlan reject with tcp reset
ether type arp reject with tcp reset;fail
ip protocol udp reject with tcp reset;fail
diff --git a/tests/py/bridge/reject.t.json b/tests/py/bridge/reject.t.json
index d20a1d8b5f9e..aea871f70907 100644
--- a/tests/py/bridge/reject.t.json
+++ b/tests/py/bridge/reject.t.json
@@ -267,3 +267,75 @@
}
]
+# ether type vlan reject with tcp reset
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "l4proto"
+ }
+ },
+ "op": "==",
+ "right": 6
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "vlan"
+ }
+ },
+ {
+ "reject": {
+ "type": "tcp reset"
+ }
+ }
+]
+
+# ether type vlan reject
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "vlan"
+ }
+ },
+ {
+ "reject": null
+ }
+]
+
+# ether type vlan reject with icmpx type admin-prohibited
+[
+ {
+ "match": {
+ "left": {
+ "payload": {
+ "field": "type",
+ "protocol": "ether"
+ }
+ },
+ "op": "==",
+ "right": "vlan"
+ }
+ },
+ {
+ "reject": {
+ "expr": "admin-prohibited",
+ "type": "icmpx"
+ }
+ }
+]
diff --git a/tests/py/inet/sets.t.json b/tests/py/inet/sets.t.json
index 58e19ef64705..ef0cedca8159 100644
--- a/tests/py/inet/sets.t.json
+++ b/tests/py/inet/sets.t.json
@@ -71,3 +71,77 @@
}
]
+# ip daddr . tcp dport { 10.0.0.0/8 . 10-23, 192.168.1.1-192.168.3.8 . 80-443 } accept
+[
+ {
+ "match": {
+ "left": {
+ "meta": {
+ "key": "nfproto"
+ }
+ },
+ "op": "==",
+ "right": "ipv4"
+ }
+ },
+ {
+ "match": {
+ "left": {
+ "concat": [
+ {
+ "payload": {
+ "field": "daddr",
+ "protocol": "ip"
+ }
+ },
+ {
+ "payload": {
+ "field": "dport",
+ "protocol": "tcp"
+ }
+ }
+ ]
+ },
+ "op": "==",
+ "right": {
+ "set": [
+ {
+ "concat": [
+ {
+ "prefix": {
+ "addr": "10.0.0.0",
+ "len": 8
+ }
+ },
+ {
+ "range": [
+ 10,
+ 23
+ ]
+ }
+ ]
+ },
+ {
+ "concat": [
+ {
+ "range": [
+ "192.168.1.1",
+ "192.168.3.8"
+ ]
+ },
+ {
+ "range": [
+ 80,
+ 443
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "accept": null
+ }
+]
diff --git a/tests/py/ip/icmp.t.json b/tests/py/ip/icmp.t.json
index 4e1727458779..965eb10be9ed 100644
--- a/tests/py/ip/icmp.t.json
+++ b/tests/py/ip/icmp.t.json
@@ -480,7 +480,7 @@
}
]
-# icmp code != { prot-unreachable, 4, 33, 54, 56}
+# icmp code != { prot-unreachable, frag-needed, 33, 54, 56}
[
{
"match": {
@@ -494,7 +494,7 @@
"right": {
"set": [
"prot-unreachable",
- 4,
+ "frag-needed",
33,
54,
56
diff --git a/tests/py/ip/icmp.t.json.output b/tests/py/ip/icmp.t.json.output
index e8045bb8182e..2391983ab826 100644
--- a/tests/py/ip/icmp.t.json.output
+++ b/tests/py/ip/icmp.t.json.output
@@ -49,7 +49,7 @@
"right": {
"set": [
"prot-unreachable",
- 4,
+ "frag-needed",
33,
54,
56
--
2.26.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH nft 3/3] json: add missing nat_type flag and netmap nat flag
2020-11-03 18:20 [PATCH nft 0/3] json: resolve multiple test case failures Florian Westphal
2020-11-03 18:20 ` [PATCH nft 1/3] tests: json: add missing test case output Florian Westphal
2020-11-03 18:20 ` [PATCH nft 2/3] tests: avoid warning and add missing json test cases Florian Westphal
@ 2020-11-03 18:20 ` Florian Westphal
2020-11-04 13:03 ` [PATCH nft 0/3] json: resolve multiple test case failures Pablo Neira Ayuso
3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2020-11-03 18:20 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
JSON in/output doesn't know about nat_type and thus cannot save/restore
nat mappings involving prefixes or concatenations because the snat
statement lacks the prefix/concat/interval type flags.
Furthermore, bison parser was extended to support netmap.
This is done with an internal 'netmap' flag that is passed to the
kernel. We need to dump/restore that as well.
Also make sure ip/snat.t passes in json mode.
Fixes: 35a6b10c1bc4 ("src: add netmap support")
Fixes: 9599d9d25a6b ("src: NAT support for intervals in maps")
Signed-off-by: Florian Westphal <fw@strlen.de>
---
src/json.c | 43 +++++++++++++---
src/parser_json.c | 70 +++++++++++++++++++++++++-
tests/py/ip/snat.t.json | 108 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 211 insertions(+), 10 deletions(-)
diff --git a/src/json.c b/src/json.c
index a8824d3fc05a..3c4654d6dada 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1288,7 +1288,7 @@ json_t *log_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
return json_pack("{s:o}", "log", root);
}
-static json_t *nat_flags_json(int flags)
+static json_t *nat_flags_json(uint32_t flags)
{
json_t *array = json_array();
@@ -1298,9 +1298,37 @@ static json_t *nat_flags_json(int flags)
json_array_append_new(array, json_string("fully-random"));
if (flags & NF_NAT_RANGE_PERSISTENT)
json_array_append_new(array, json_string("persistent"));
+ if (flags & NF_NAT_RANGE_NETMAP)
+ json_array_append_new(array, json_string("netmap"));
return array;
}
+static json_t *nat_type_flags_json(uint32_t type_flags)
+{
+ json_t *array = json_array();
+
+ if (type_flags & STMT_NAT_F_INTERVAL)
+ json_array_append_new(array, json_string("interval"));
+ if (type_flags & STMT_NAT_F_PREFIX)
+ json_array_append_new(array, json_string("prefix"));
+ if (type_flags & STMT_NAT_F_CONCAT)
+ json_array_append_new(array, json_string("concat"));
+
+ return array;
+}
+
+static void nat_stmt_add_array(json_t *root, const char *name, json_t *array)
+{
+ if (json_array_size(array) > 1) {
+ json_object_set_new(root, name, array);
+ } else {
+ if (json_array_size(array))
+ json_object_set(root, name,
+ json_array_get(array, 0));
+ json_decref(array);
+ }
+}
+
json_t *nat_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
{
json_t *root = json_object();
@@ -1322,13 +1350,12 @@ json_t *nat_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
json_object_set_new(root, "port",
expr_print_json(stmt->nat.proto, octx));
- if (json_array_size(array) > 1) {
- json_object_set_new(root, "flags", array);
- } else {
- if (json_array_size(array))
- json_object_set(root, "flags",
- json_array_get(array, 0));
- json_decref(array);
+ nat_stmt_add_array(root, "flags", array);
+
+ if (stmt->nat.type_flags) {
+ array = nat_type_flags_json(stmt->nat.type_flags);
+
+ nat_stmt_add_array(root, "type_flags", array);
}
if (!json_object_size(root)) {
diff --git a/src/parser_json.c b/src/parser_json.c
index ac89166ec8a9..136239121427 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -1358,8 +1358,8 @@ static struct expr *json_parse_expr(struct json_ctx *ctx, json_t *root)
{ "set", json_parse_set_expr, CTX_F_RHS | CTX_F_STMT }, /* allow this as stmt expr because that allows set references */
{ "map", json_parse_map_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS },
/* below three are multiton_rhs_expr */
- { "prefix", json_parse_prefix_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_CONCAT },
- { "range", json_parse_range_expr, CTX_F_RHS | CTX_F_STMT | CTX_F_CONCAT },
+ { "prefix", json_parse_prefix_expr, CTX_F_RHS | CTX_F_SET_RHS | CTX_F_STMT | CTX_F_CONCAT },
+ { "range", json_parse_range_expr, CTX_F_RHS | CTX_F_SET_RHS | CTX_F_STMT | CTX_F_CONCAT },
{ "payload", json_parse_payload_expr, CTX_F_STMT | CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT },
{ "exthdr", json_parse_exthdr_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_SES | CTX_F_MAP | CTX_F_CONCAT },
{ "tcp option", json_parse_tcp_option_expr, CTX_F_PRIMARY | CTX_F_SET_RHS | CTX_F_MANGLE | CTX_F_SES | CTX_F_CONCAT },
@@ -1861,6 +1861,7 @@ static int json_parse_nat_flag(struct json_ctx *ctx,
{ "random", NF_NAT_RANGE_PROTO_RANDOM },
{ "fully-random", NF_NAT_RANGE_PROTO_RANDOM_FULLY },
{ "persistent", NF_NAT_RANGE_PERSISTENT },
+ { "netmap", NF_NAT_RANGE_NETMAP },
};
const char *flag;
unsigned int i;
@@ -1905,6 +1906,60 @@ static int json_parse_nat_flags(struct json_ctx *ctx, json_t *root)
return flags;
}
+static int json_parse_nat_type_flag(struct json_ctx *ctx,
+ json_t *root, int *flags)
+{
+ const struct {
+ const char *flag;
+ int val;
+ } flag_tbl[] = {
+ { "interval", STMT_NAT_F_INTERVAL },
+ { "prefix", STMT_NAT_F_PREFIX },
+ { "concat", STMT_NAT_F_CONCAT },
+ };
+ const char *flag;
+ unsigned int i;
+
+ assert(flags);
+
+ if (!json_is_string(root)) {
+ json_error(ctx, "Invalid nat type flag type %s, expected string.",
+ json_typename(root));
+ return 1;
+ }
+ flag = json_string_value(root);
+ for (i = 0; i < array_size(flag_tbl); i++) {
+ if (!strcmp(flag, flag_tbl[i].flag)) {
+ *flags |= flag_tbl[i].val;
+ return 0;
+ }
+ }
+ json_error(ctx, "Unknown nat type flag '%s'.", flag);
+ return 1;
+}
+
+static int json_parse_nat_type_flags(struct json_ctx *ctx, json_t *root)
+{
+ int flags = 0;
+ json_t *value;
+ size_t index;
+
+ if (json_is_string(root)) {
+ json_parse_nat_type_flag(ctx, root, &flags);
+ return flags;
+ } else if (!json_is_array(root)) {
+ json_error(ctx, "Invalid nat flags type %s.",
+ json_typename(root));
+ return -1;
+ }
+ json_array_foreach(root, index, value) {
+ if (json_parse_nat_type_flag(ctx, value, &flags))
+ json_error(ctx, "Parsing nat type flag at index %zu failed.",
+ index);
+ }
+ return flags;
+}
+
static int nat_type_parse(const char *type)
{
const char * const nat_etypes[] = {
@@ -1967,6 +2022,17 @@ static struct stmt *json_parse_nat_stmt(struct json_ctx *ctx,
}
stmt->nat.flags = flags;
}
+
+ if (!json_unpack(value, "{s:o}", "type_flags", &tmp)) {
+ int flags = json_parse_nat_type_flags(ctx, tmp);
+
+ if (flags < 0) {
+ stmt_free(stmt);
+ return NULL;
+ }
+ stmt->nat.type_flags = flags;
+ }
+
return stmt;
}
diff --git a/tests/py/ip/snat.t.json b/tests/py/ip/snat.t.json
index e87b524ee667..62c6e61bea7c 100644
--- a/tests/py/ip/snat.t.json
+++ b/tests/py/ip/snat.t.json
@@ -166,3 +166,111 @@
}
]
+# snat ip addr . port to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "10.141.11.4",
+ {
+ "concat": [
+ "192.168.2.3",
+ 80
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip",
+ "type_flags": "concat"
+ }
+ }
+]
+
+# snat ip interval to ip saddr map { 10.141.11.4 : 192.168.2.2-192.168.2.4 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ "10.141.11.4",
+ {
+ "range": [
+ "192.168.2.2",
+ "192.168.2.4"
+ ]
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip",
+ "type_flags": "interval"
+ }
+ }
+]
+
+# snat ip prefix to ip saddr map { 10.141.11.0/24 : 192.168.2.0/24 }
+[
+ {
+ "snat": {
+ "addr": {
+ "map": {
+ "data": {
+ "set": [
+ [
+ {
+ "prefix": {
+ "addr": "10.141.11.0",
+ "len": 24
+ }
+ },
+ {
+ "prefix": {
+ "addr": "192.168.2.0",
+ "len": 24
+ }
+ }
+ ]
+ ]
+ },
+ "key": {
+ "payload": {
+ "field": "saddr",
+ "protocol": "ip"
+ }
+ }
+ }
+ },
+ "family": "ip",
+ "flags": "netmap",
+ "type_flags": [
+ "interval",
+ "prefix"
+ ]
+ }
+ }
+]
+
--
2.26.2
^ permalink raw reply related [flat|nested] 5+ messages in thread