]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
json: Support nat in inet family
authorPhil Sutter <phil@nwl.cc>
Thu, 9 May 2019 11:35:37 +0000 (13:35 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 9 May 2019 15:19:50 +0000 (17:19 +0200)
Add the missing bits to JSON parser, printer, man page and testsuite.

Fixes: fbe27464dee45 ("src: add nat support for the inet family")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
doc/libnftables-json.adoc
src/json.c
src/parser_json.c
tests/py/inet/dnat.t.json [new file with mode: 0644]
tests/py/inet/snat.t.json [new file with mode: 0644]

index dbe5ac33d999e9d326faeda0a68765ab4fee46d3..429f530db913c933112d40a4f4f62d6edbe3a493 100644 (file)
@@ -808,12 +808,14 @@ Duplicate a packet to a different destination.
 ____
 *{ "snat": {
        "addr":* 'EXPRESSION'*,
+       "family":* 'STRING'*,
        "port":* 'EXPRESSION'*,
        "flags":* 'FLAGS'
 *}}*
 
 *{ "dnat": {
        "addr":* 'EXPRESSION'*,
+       "family":* 'STRING'*,
        "port":* 'EXPRESSION'*,
        "flags":* 'FLAGS'
 *}}*
@@ -837,6 +839,9 @@ Perform Network Address Translation.
 
 *addr*::
        Address to translate to.
+*family*::
+       Family of *addr*, either *ip* or *ip6*. Required in *inet*
+       table family.
 *port*::
        Port to translate to.
 *flags*::
index 4900c02336b56c8e3dd73e1af92af00ef1d430e8..a8538bdca973bb7a17bca0007fe1130eabf5cfe2 100644 (file)
@@ -1260,6 +1260,14 @@ json_t *nat_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
        json_t *root = json_object();
        json_t *array = nat_flags_json(stmt->nat.flags);
 
+       switch (stmt->nat.family) {
+       case NFPROTO_IPV4:
+       case NFPROTO_IPV6:
+               json_object_set_new(root, "family",
+                                   json_string(family2str(stmt->nat.family)));
+               break;
+       }
+
        if (stmt->nat.addr)
                json_object_set_new(root, "addr",
                                    expr_print_json(stmt->nat.addr, octx));
index 3dc3a5c5f93ce284bbec98cc13e90265e0932877..b83c94d8fb1d94bcabf83431427ca652a13127b8 100644 (file)
@@ -1840,9 +1840,9 @@ static int nat_type_parse(const char *type)
 static struct stmt *json_parse_nat_stmt(struct json_ctx *ctx,
                                        const char *key, json_t *value)
 {
+       int type, familyval;
        struct stmt *stmt;
        json_t *tmp;
-       int type;
 
        type = nat_type_parse(key);
        if (type < 0) {
@@ -1850,7 +1850,12 @@ static struct stmt *json_parse_nat_stmt(struct json_ctx *ctx,
                return NULL;
        }
 
+       familyval = json_parse_family(ctx, value);
+       if (familyval < 0)
+               return NULL;
+
        stmt = nat_stmt_alloc(int_loc, type);
+       stmt->nat.family = familyval;
 
        if (!json_unpack(value, "{s:o}", "addr", &tmp)) {
                stmt->nat.addr = json_parse_stmt_expr(ctx, tmp);
diff --git a/tests/py/inet/dnat.t.json b/tests/py/inet/dnat.t.json
new file mode 100644 (file)
index 0000000..ac6dac6
--- /dev/null
@@ -0,0 +1,166 @@
+# iifname "foo" tcp dport 80 redirect to :8080
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "iifname"
+                }
+            },
+            "op": "==",
+            "right": "foo"
+        }
+    },
+    {
+        "match": {
+            "left": {
+                "payload": {
+                    "field": "dport",
+                    "protocol": "tcp"
+                }
+            },
+            "op": "==",
+            "right": 80
+        }
+    },
+    {
+        "redirect": {
+            "port": 8080
+        }
+    }
+]
+
+# iifname "eth0" tcp dport 443 dnat ip to 192.168.3.2
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "iifname"
+                }
+            },
+            "op": "==",
+            "right": "eth0"
+        }
+    },
+    {
+        "match": {
+            "left": {
+                "payload": {
+                    "field": "dport",
+                    "protocol": "tcp"
+                }
+            },
+            "op": "==",
+            "right": 443
+        }
+    },
+    {
+        "dnat": {
+            "addr": "192.168.3.2",
+            "family": "ip"
+        }
+    }
+]
+
+# iifname "eth0" tcp dport 443 dnat ip6 to [dead::beef]:4443
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "iifname"
+                }
+            },
+            "op": "==",
+            "right": "eth0"
+        }
+    },
+    {
+        "match": {
+            "left": {
+                "payload": {
+                    "field": "dport",
+                    "protocol": "tcp"
+                }
+            },
+            "op": "==",
+            "right": 443
+        }
+    },
+    {
+        "dnat": {
+            "addr": "dead::beef",
+            "family": "ip6",
+            "port": 4443
+        }
+    }
+]
+
+# dnat ip to ct mark map { 0x00000014 : 1.2.3.4}
+[
+    {
+        "dnat": {
+            "addr": {
+                "map": {
+                    "data": {
+                        "set": [
+                            [
+                                20,
+                                "1.2.3.4"
+                            ]
+                        ]
+                    },
+                    "key": {
+                        "ct": {
+                            "key": "mark"
+                        }
+                    }
+                }
+            },
+            "family": "ip"
+        }
+    }
+]
+
+# dnat ip to ct mark . ip daddr map { 0x00000014 . 1.1.1.1 : 1.2.3.4}
+[
+    {
+        "dnat": {
+            "addr": {
+                "map": {
+                    "data": {
+                        "set": [
+                            [
+                                {
+                                    "concat": [
+                                        20,
+                                        "1.1.1.1"
+                                    ]
+                                },
+                                "1.2.3.4"
+                            ]
+                        ]
+                    },
+                    "key": {
+                        "concat": [
+                            {
+                                "ct": {
+                                    "key": "mark"
+                                }
+                            },
+                            {
+                                "payload": {
+                                    "field": "daddr",
+                                    "protocol": "ip"
+                                }
+                            }
+                        ]
+                    }
+                }
+            },
+            "family": "ip"
+        }
+    }
+]
+
diff --git a/tests/py/inet/snat.t.json b/tests/py/inet/snat.t.json
new file mode 100644 (file)
index 0000000..4671625
--- /dev/null
@@ -0,0 +1,131 @@
+# iifname "eth0" tcp dport 81 snat ip to 192.168.3.2
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "iifname"
+                }
+            },
+            "op": "==",
+            "right": "eth0"
+        }
+    },
+    {
+        "match": {
+            "left": {
+                "payload": {
+                    "field": "dport",
+                    "protocol": "tcp"
+                }
+            },
+            "op": "==",
+            "right": 81
+        }
+    },
+    {
+        "snat": {
+            "addr": "192.168.3.2",
+            "family": "ip"
+        }
+    }
+]
+
+# iifname "eth0" tcp dport 81 ip saddr 10.1.1.1 snat to 192.168.3.2
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "iifname"
+                }
+            },
+            "op": "==",
+            "right": "eth0"
+        }
+    },
+    {
+        "match": {
+            "left": {
+                "payload": {
+                    "field": "dport",
+                    "protocol": "tcp"
+                }
+            },
+            "op": "==",
+            "right": 81
+        }
+    },
+    {
+        "match": {
+            "left": {
+                "payload": {
+                    "field": "saddr",
+                    "protocol": "ip"
+                }
+            },
+            "op": "==",
+            "right": "10.1.1.1"
+        }
+    },
+    {
+        "snat": {
+            "addr": "192.168.3.2",
+            "family": "ip"
+        }
+    }
+]
+
+# iifname "eth0" tcp dport 81 snat ip6 to dead::beef
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "iifname"
+                }
+            },
+            "op": "==",
+            "right": "eth0"
+        }
+    },
+    {
+        "match": {
+            "left": {
+                "payload": {
+                    "field": "dport",
+                    "protocol": "tcp"
+                }
+            },
+            "op": "==",
+            "right": 81
+        }
+    },
+    {
+        "snat": {
+            "addr": "dead::beef",
+            "family": "ip6"
+        }
+    }
+]
+
+# iifname "foo" masquerade random
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "iifname"
+                }
+            },
+            "op": "==",
+            "right": "foo"
+        }
+    },
+    {
+        "masquerade": {
+            "flags": "random"
+        }
+    }
+]
+