new file mode 100755
@@ -0,0 +1,140 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_json)
+#
+# Regression test for JSON delete of ct timeout, ct expectation and tunnel
+# objects. Prior to the fix, json_parse_cmd_add_object() passed the raw
+# NFT_OBJECT_* kernel constant to cmd_alloc() on the delete/list/destroy
+# early-return path instead of the correct CMD_OBJ_* userspace enum value.
+# For ct timeout NFT_OBJECT_CT_TIMEOUT=7 aliased to CMD_OBJ_CHAIN=7, causing
+# the kernel to return EINVAL.
+
+set -e
+
+$NFT flush ruleset
+
+$NFT -j -f - << 'EOF'
+{"nftables": [{"add": {"table": {"family": "inet", "name": "t"}}}]}
+EOF
+
+# ===== ct timeout =====
+
+if [ "$NFT_TEST_HAVE_cttimeout" != n ]; then
+
+ echo "Test 1: JSON add ct timeout"
+ $NFT -j -f - << 'EOF'
+{"nftables": [{"add": {"ct timeout": {"family": "inet", "table": "t", "name": "ctto", "protocol": "udp", "policy": {"unreplied": 30, "replied": 60}}}}]}
+EOF
+
+ if ! $NFT list ct timeout inet t ctto > /dev/null 2>&1; then
+ echo "Test 1 failed: ct timeout not created"
+ exit 1
+ fi
+
+ echo "Test 2: JSON delete ct timeout by name"
+ $NFT -j -f - << 'EOF'
+{"nftables": [{"delete": {"ct timeout": {"family": "inet", "table": "t", "name": "ctto"}}}]}
+EOF
+
+ if $NFT list ct timeout inet t ctto > /dev/null 2>&1; then
+ echo "Test 2 failed: ct timeout not deleted"
+ exit 1
+ fi
+
+ echo "Test 3: JSON add + delete ct timeout by handle"
+ $NFT -j -f - << 'EOF'
+{"nftables": [{"add": {"ct timeout": {"family": "inet", "table": "t", "name": "ctto2", "protocol": "tcp", "policy": {"established": 120}}}}]}
+EOF
+
+ HANDLE=$($NFT -a list ct timeout inet t ctto2 | sed -n 's/.*# handle \([0-9]\+\).*/\1/p')
+ if [ -z "$HANDLE" ]; then
+ echo "Test 3 failed: could not get ct timeout handle"
+ exit 1
+ fi
+
+ $NFT -j -f - << EOF
+{"nftables": [{"delete": {"ct timeout": {"family": "inet", "table": "t", "handle": $HANDLE}}}]}
+EOF
+
+ if $NFT list ct timeout inet t ctto2 > /dev/null 2>&1; then
+ echo "Test 3 failed: ct timeout not deleted by handle"
+ exit 1
+ fi
+
+fi
+
+# ===== ct expectation =====
+
+if [ "$NFT_TEST_HAVE_ctexpect" != n ]; then
+
+ $NFT -j -f - << 'EOF'
+{"nftables": [{"add": {"table": {"family": "ip", "name": "t"}}}]}
+EOF
+
+ echo "Test 4: JSON add ct expectation"
+ $NFT -j -f - << 'EOF'
+{"nftables": [{"add": {"ct expectation": {"family": "ip", "table": "t", "name": "ctex", "protocol": "tcp", "dport": 2121, "timeout": 300000, "size": 12}}}]}
+EOF
+
+ if ! $NFT list ct expectation ip t ctex > /dev/null 2>&1; then
+ echo "Test 4 failed: ct expectation not created"
+ exit 1
+ fi
+
+ echo "Test 5: JSON delete ct expectation by name"
+ $NFT -j -f - << 'EOF'
+{"nftables": [{"delete": {"ct expectation": {"family": "ip", "table": "t", "name": "ctex"}}}]}
+EOF
+
+ if $NFT list ct expectation ip t ctex > /dev/null 2>&1; then
+ echo "Test 5 failed: ct expectation not deleted"
+ exit 1
+ fi
+
+ $NFT -j -f - << 'EOF'
+{"nftables": [{"delete": {"table": {"family": "ip", "name": "t"}}}]}
+EOF
+
+fi
+
+# ===== tunnel =====
+#
+# Tunnel objects must be created and deleted in the same batch as the table
+# when using JSON (kernel lookup limitation with separate add commands).
+
+if [ "$NFT_TEST_HAVE_tunnel" != n ]; then
+
+ echo "Test 6: JSON add+delete tunnel object in batch"
+ $NFT -j -f - << 'EOF'
+{"nftables": [
+ {"add": {"table": {"family": "netdev", "name": "t"}}},
+ {"add": {"tunnel": {"family": "netdev", "table": "t", "name": "tun0", "id": 20, "src-ipv4": "192.168.2.20", "dst-ipv4": "192.168.2.21", "sport": 0, "dport": 4789, "tos": 0, "ttl": 255}}}
+]}
+EOF
+
+ if ! $NFT list tunnel netdev t tun0 > /dev/null 2>&1; then
+ echo "Test 6 failed: tunnel not created"
+ exit 1
+ fi
+
+ echo "Test 7: JSON delete tunnel by name"
+ $NFT -j -f - << 'EOF'
+{"nftables": [{"delete": {"tunnel": {"family": "netdev", "table": "t", "name": "tun0"}}}]}
+EOF
+
+ if $NFT list tunnel netdev t tun0 > /dev/null 2>&1; then
+ echo "Test 7 failed: tunnel not deleted"
+ exit 1
+ fi
+
+ $NFT -j -f - << 'EOF'
+{"nftables": [{"delete": {"table": {"family": "netdev", "name": "t"}}}]}
+EOF
+
+fi
+
+$NFT -j -f - << 'EOF'
+{"nftables": [{"delete": {"table": {"family": "inet", "name": "t"}}}]}
+EOF
+
+echo "All tests passed!"
Verify that JSON delete commands work correctly for ct timeout, ct expectation and tunnel stateful objects. These were broken before the previous fix due to a CMD_OBJ/NFT_OBJECT mismatch in the delete path of json_parse_cmd_add_object(). Signed-off-by: Gergely Palotas <palotasgergely@gmail.com> --- .../json/0009json_delete_ct_objects_0 | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100755 tests/shell/testcases/json/0009json_delete_ct_objects_0