From d5e67f48a76dfd7b48b5ce84f08246d2a6c48489 Mon Sep 17 00:00:00 2001 From: Nataliia Solomko Date: Fri, 30 Oct 2026 13:34:13 +0200 Subject: nat64: T9536: Fix check for only one source rule The verify step was meant to allow only one NAT64 netfilter instance, but it looked for a "mode" node that does not exist in the CLI, so it never matched. A second source rule was accepted and Jool created a second netfilter instance without error, although the Jool documentation states that only one is allowed per network namespace. Which instance translates traffic is then undefined. Every rule is created with the netfilter framework, so verify now counts all configured source rules and rejects the commit when there is more than one. A dead check that tried to recreate an instance on a "mode" change is removed for the same reason. --- smoketest/scripts/cli/test_nat64.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'smoketest/scripts/cli') diff --git a/smoketest/scripts/cli/test_nat64.py b/smoketest/scripts/cli/test_nat64.py index dc0eb0abc..1a0172ccd 100755 --- a/smoketest/scripts/cli/test_nat64.py +++ b/smoketest/scripts/cli/test_nat64.py @@ -108,6 +108,39 @@ class TestNAT64(VyOSUnitTestSHIM.TestCase): else: self.fail(f'Unexpected protocol: {protocol}') + def test_snat64_single_instance(self): + # Pool ports must not overlap the kernel's local port range + tmp = sysctl_read(['net', 'ipv4', 'ip_local_port_range']) + _, local_port_max = map(int, tmp.split()) + pool_port = f'{local_port_max +1}-{local_port_max +1000}' + + rule_100_path = src_path + ['rule', '100'] + self.cli_set(rule_100_path + ['source', 'prefix', '64:ff9b::/96']) + self.cli_set( + rule_100_path + ['translation', 'pool', '10', 'address', '192.0.2.10'] + ) + self.cli_set(rule_100_path + ['translation', 'pool', '10', 'port', pool_port]) + + rule_200_path = src_path + ['rule', '200'] + self.cli_set(rule_200_path + ['source', 'prefix', '64:ff9c::/96']) + self.cli_set( + rule_200_path + ['translation', 'pool', '10', 'address', '192.0.2.20'] + ) + self.cli_set(rule_200_path + ['translation', 'pool', '10', 'port', pool_port]) + + # Jool supports only one netfilter NAT64 instance per network namespace, + # but does not refuse a second one - verify has to reject it + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + # Removing the second rule must make the config valid + self.cli_delete(rule_200_path) + self.cli_commit() + + # The rejected commit must not have left an instance for rule 200 behind + self.assertTrue(os.path.exists('/run/jool/instance-100.json')) + self.assertFalse(os.path.exists('/run/jool/instance-200.json')) + if __name__ == '__main__': unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on()) -- cgit v1.2.3