summaryrefslogtreecommitdiffstats
path: root/tests/json_echo
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-10-26 15:01:38 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-10-29 11:15:08 +0100
commitbb32d8db9a125d9676f87866e48ffbf0221ec16a (patch)
treebfbeaf0ffb248aad38fab54b7630e2fe67e64ca7 /tests/json_echo
parent21d678639b28b99c301262c163128fdf67397ca6 (diff)
JSON: Add support for echo option
The basic principle is to not return a JSON object freshly created from netlink responses, but just update the existing user-provided one to make sure callers get back exactly what they expect. To achieve that, keep the parsed JSON object around in a global variable ('cur_root') and provide a custom callback to insert handles into it from received netlink messages. The tricky bit here is updating rules since unique identification is problematic. Therefore drop possibly present handles from input and later assume updates are received in order so the first rule not having a handle set is the right one. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'tests/json_echo')
-rwxr-xr-xtests/json_echo/run-test.py211
1 files changed, 211 insertions, 0 deletions
diff --git a/tests/json_echo/run-test.py b/tests/json_echo/run-test.py
new file mode 100755
index 00000000..dcef3f1b
--- /dev/null
+++ b/tests/json_echo/run-test.py
@@ -0,0 +1,211 @@
+#!/usr/bin/python2
+
+import sys
+import os
+import json
+
+TESTS_PATH = os.path.dirname(os.path.abspath(__file__))
+sys.path.insert(0, os.path.join(TESTS_PATH, '../../py/'))
+
+from nftables import Nftables
+
+# Change working directory to repository root
+os.chdir(TESTS_PATH + "/../..")
+
+if not os.path.exists('src/.libs/libnftables.so'):
+ print "The nftables library does not exist. " \
+ "You need to build the project."
+ sys.exit(1)
+
+nftables = Nftables(sofile = 'src/.libs/libnftables.so')
+nftables.set_echo_output(True)
+
+# various commands to work with
+
+flush_ruleset = { "flush": { "ruleset": None } }
+
+add_table = { "add": {
+ "table": {
+ "family": "inet",
+ "name": "t",
+ }
+}}
+
+add_chain = { "add": {
+ "chain": {
+ "family": "inet",
+ "table": "t",
+ "name": "c"
+ }
+}}
+
+add_set = { "add": {
+ "set": {
+ "family": "inet",
+ "table": "t",
+ "name": "s",
+ "type": "inet_service"
+ }
+}}
+
+add_rule = { "add": {
+ "rule": {
+ "family": "inet",
+ "table": "t",
+ "chain": "c",
+ "expr": [ { "accept": None } ]
+ }
+}}
+
+add_counter = { "add": {
+ "counter": {
+ "family": "inet",
+ "table": "t",
+ "name": "c"
+ }
+}}
+
+add_quota = { "add": {
+ "quota": {
+ "family": "inet",
+ "table": "t",
+ "name": "q",
+ "bytes": 65536
+ }
+}}
+
+# helper functions
+
+def exit_err(msg):
+ print "Error: %s" % msg
+ sys.exit(1)
+
+def exit_dump(e, obj):
+ print "FAIL: %s" % e
+ print "Output was:"
+ json.dumps(out, sort_keys = True, indent = 4, separators = (',', ': '))
+ sys.exit(1)
+
+def do_flush():
+ rc, out, err = nftables.json_cmd({ "nftables": [flush_ruleset] })
+ if not rc is 0:
+ exit_err("flush ruleset failed: %s" % err)
+
+def do_command(cmd):
+ if not type(cmd) is list:
+ cmd = [cmd]
+ rc, out, err = nftables.json_cmd({ "nftables": cmd })
+ if not rc is 0:
+ exit_err("command failed: %s" % err)
+ return out
+
+# single commands first
+
+do_flush()
+
+print "Adding table t"
+out = do_command(add_table)
+try:
+ table_out = out["nftables"][0]
+ table_handle = out["nftables"][0]["add"]["table"]["handle"]
+except Exception as e:
+ exit_dump(e, out)
+
+print "Adding chain c"
+out = do_command(add_chain)
+try:
+ chain_out = out["nftables"][0]
+ chain_handle = out["nftables"][0]["add"]["chain"]["handle"]
+except Exception as e:
+ exit_dump(e, out)
+
+print "Adding set s"
+out = do_command(add_set)
+try:
+ set_out = out["nftables"][0]
+ set_handle = out["nftables"][0]["add"]["set"]["handle"]
+except Exception as e:
+ exit_dump(e, out)
+
+print "Adding rule"
+out = do_command(add_rule)
+try:
+ rule_out = out["nftables"][0]
+ rule_handle = out["nftables"][0]["add"]["rule"]["handle"]
+except Exception as e:
+ exit_dump(e, out)
+
+print "Adding counter"
+out = do_command(add_counter)
+try:
+ counter_out = out["nftables"][0]
+ counter_handle = out["nftables"][0]["add"]["counter"]["handle"]
+except Exception as e:
+ exit_dump(e, out)
+
+print "Adding quota"
+out = do_command(add_quota)
+try:
+ quota_out = out["nftables"][0]
+ quota_handle = out["nftables"][0]["add"]["quota"]["handle"]
+except Exception as e:
+ exit_dump(e, out)
+
+# adjust names and add items again
+# Note: Add second chain to same table, otherwise it's handle will be the same
+# as before. Same for the set and the rule. Bug?
+
+table_out["add"]["table"]["name"] = "t2"
+#chain_out["add"]["chain"]["table"] = "t2"
+chain_out["add"]["chain"]["name"] = "c2"
+#set_out["add"]["set"]["table"] = "t2"
+set_out["add"]["set"]["name"] = "s2"
+#rule_out["add"]["rule"]["table"] = "t2"
+#rule_out["add"]["rule"]["chain"] = "c2"
+counter_out["add"]["counter"]["name"] = "c2"
+quota_out["add"]["quota"]["name"] = "q2"
+
+print "Adding table t2"
+out = do_command(table_out)
+if out["nftables"][0]["add"]["table"]["handle"] == table_handle:
+ exit_err("handle not changed in re-added table!")
+
+print "Adding chain c2"
+out = do_command(chain_out)
+if out["nftables"][0]["add"]["chain"]["handle"] == chain_handle:
+ exit_err("handle not changed in re-added chain!")
+
+print "Adding set s2"
+out = do_command(set_out)
+if out["nftables"][0]["add"]["set"]["handle"] == set_handle:
+ exit_err("handle not changed in re-added set!")
+
+print "Adding rule again"
+out = do_command(rule_out)
+if out["nftables"][0]["add"]["rule"]["handle"] == rule_handle:
+ exit_err("handle not changed in re-added rule!")
+
+print "Adding counter c2"
+out = do_command(counter_out)
+if out["nftables"][0]["add"]["counter"]["handle"] == counter_handle:
+ exit_err("handle not changed in re-added counter!")
+
+print "Adding quota q2"
+out = do_command(quota_out)
+if out["nftables"][0]["add"]["quota"]["handle"] == quota_handle:
+ exit_err("handle not changed in re-added quota!")
+
+# now multiple commands
+
+do_flush()
+
+print "doing multi add"
+add_multi = [ add_table, add_chain, add_set, add_rule ]
+out = do_command(add_multi)
+out = out["nftables"]
+
+if not "handle" in out[0]["add"]["table"] or \
+ not "handle" in out[1]["add"]["chain"] or \
+ not "handle" in out[2]["add"]["set"] or \
+ not "handle" in out[3]["add"]["rule"]:
+ exit_err("handle(s) missing in multi cmd output!")