summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2026-05-28 22:03:40 +0200
committerChristian Breunig <christian@breunig.cc>2026-05-28 22:03:40 +0200
commit960e730bdde2f3561aa3cff8941e2f9db8eb32d8 (patch)
tree36b8b4a54fbfe1b5ddd60e80b2fdfdafc8466f1c
parentcd619d4c355c9158497951231b1c993f8a7d26a9 (diff)
downloadvyos-1x-960e730bdde2f3561aa3cff8941e2f9db8eb32d8.tar.gz
vyos-1x-960e730bdde2f3561aa3cff8941e2f9db8eb32d8.zip
nat: T8939: fix KeyError: 'group' exception
Prevent access to missing dictionary key by probing for availability. On removal of inbound-interface or outbound-interface name CLI node, there was a guard missing when accessing the CLI dictionary containing the config data.
-rw-r--r--python/vyos/nat.py5
-rwxr-xr-xsmoketest/scripts/cli/test_nat66.py19
2 files changed, 17 insertions, 7 deletions
diff --git a/python/vyos/nat.py b/python/vyos/nat.py
index 7be957a0c..0a252bbd8 100644
--- a/python/vyos/nat.py
+++ b/python/vyos/nat.py
@@ -37,7 +37,7 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):
operator = '!='
iiface = iiface[1:]
output.append(f'iifname {operator} {{{iiface}}}')
- else:
+ elif 'group' in rule_conf['inbound_interface']:
iiface = rule_conf['inbound_interface']['group']
if iiface[0] == '!':
operator = '!='
@@ -52,7 +52,7 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):
operator = '!='
oiface = oiface[1:]
output.append(f'oifname {operator} {{{oiface}}}')
- else:
+ elif 'group' in rule_conf['outbound_interface']:
oiface = rule_conf['outbound_interface']['group']
if oiface[0] == '!':
operator = '!='
@@ -80,7 +80,6 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):
if redirect_port:
translation_output.append(f'to {redirect_port}')
else:
-
translation_prefix = nat_type[:1]
translation_output = [f'{translation_prefix}nat']
diff --git a/smoketest/scripts/cli/test_nat66.py b/smoketest/scripts/cli/test_nat66.py
index 8bec2f998..9072e78dd 100755
--- a/smoketest/scripts/cli/test_nat66.py
+++ b/smoketest/scripts/cli/test_nat66.py
@@ -110,11 +110,13 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase):
destination_address = 'fc00::1'
translation_address = 'fc01::1'
source_address = 'fc02::1'
- self.cli_set(dst_path + ['rule', '1', 'inbound-interface', 'name', 'eth1'])
+ in_interface = 'eth1'
+
+ self.cli_set(dst_path + ['rule', '1', 'inbound-interface', 'name', in_interface])
self.cli_set(dst_path + ['rule', '1', 'destination', 'address', destination_address])
self.cli_set(dst_path + ['rule', '1', 'translation', 'address', translation_address])
- self.cli_set(dst_path + ['rule', '2', 'inbound-interface', 'name', 'eth1'])
+ self.cli_set(dst_path + ['rule', '2', 'inbound-interface', 'name', in_interface])
self.cli_set(dst_path + ['rule', '2', 'destination', 'address', destination_address])
self.cli_set(dst_path + ['rule', '2', 'source', 'address', source_address])
self.cli_set(dst_path + ['rule', '2', 'exclude'])
@@ -123,10 +125,19 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase):
self.cli_commit()
nftables_search = [
- ['iifname "eth1"', 'ip6 daddr fc00::1', 'dnat to fc01::1'],
- ['iifname "eth1"', 'ip6 saddr fc02::1', 'ip6 daddr fc00::1', 'return']
+ [f'iifname "{in_interface}"', 'ip6 daddr fc00::1', 'dnat to fc01::1'],
+ [f'iifname "{in_interface}"', 'ip6 saddr fc02::1', 'ip6 daddr fc00::1', 'return']
]
+ self.verify_nftables(nftables_search, 'ip6 vyos_nat')
+ # T8939 - remove inbound-interface name
+ self.cli_delete(dst_path + ['rule', '2', 'inbound-interface', 'name'])
+ self.cli_commit()
+
+ nftables_search = [
+ [f'iifname "{in_interface}"', 'ip6 daddr fc00::1', 'dnat to fc01::1'],
+ ['ip6 saddr fc02::1', 'ip6 daddr fc00::1', 'return']
+ ]
self.verify_nftables(nftables_search, 'ip6 vyos_nat')
def test_destination_nat66_protocol(self):