summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuben Herold <ruben@puettmann.net>2026-08-04 13:17:20 +0200
committerRuben Herold <ruben@puettmann.net>2026-08-04 13:17:20 +0200
commit57115dba2fae263b8923cdc5f4a827f49fa680e4 (patch)
tree9e9a77a18ef6d6278a6a43298c60cbe75bb80dcc /src
parentdd2673bf9ad36ea7ecb6998b71f318516b95e8d8 (diff)
downloadvyos-1x-57115dba2fae263b8923cdc5f4a827f49fa680e4.tar.gz
vyos-1x-57115dba2fae263b8923cdc5f4a827f49fa680e4.zip
nat: T9162: fix KeyError when show nat rules has no inbound-interface
_get_formatted_output_rules() and _get_formatted_output_statistics() detected an interface match by checking whether *any* expr in the rule has a left.meta field, then unconditionally read expr[0]'s match.right as the interface. Both assumptions are wrong: meta is also used for non-interface matches (e.g. meta l4proto from a protocol match), and the interface match is not guaranteed to be first. For a rule with a protocol match but no inbound-interface, this read the address/port match's right-hand side (a dict) as if it were the interface string, raising KeyError: 0 on interface[0] instead of falling back to 'any'. Search expr entries explicitly for a left.meta.key == 'iifname' match instead, and guard the '@' set-name stripping with a type check.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/op_mode/nat.py20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/op_mode/nat.py b/src/op_mode/nat.py
index 434273622..32b62481e 100755
--- a/src/op_mode/nat.py
+++ b/src/op_mode/nat.py
@@ -142,9 +142,13 @@ def _get_formatted_output_rules(data, direction, family):
rule_number = comment.split('-')[-1]
rule_number = rule_number.split(' ')[0]
if 'expr' in rule['rule']:
- interface = rule.get('rule').get('expr')[0].get('match').get('right') \
- if jmespath.search('rule.expr[*].match.left.meta', rule) else 'any'
- if interface[0] == '@':
+ interface = 'any'
+ for expr in rule.get('rule').get('expr'):
+ match = expr.get('match')
+ if match and jmespath.search('left.meta.key', match) == 'iifname':
+ interface = match.get('right')
+ break
+ if isinstance(interface, str) and interface.startswith('@'):
interface = interface[3:]
for index, match in enumerate(jmespath.search('rule.expr[*].match', rule)):
if 'payload' in match['left']:
@@ -257,8 +261,14 @@ def _get_formatted_output_statistics(data, direction):
rule_number = comment.split('-')[-1]
rule_number = rule_number.split(' ')[0]
if 'expr' in rule['rule']:
- interface = rule.get('rule').get('expr')[0].get('match').get('right') \
- if jmespath.search('rule.expr[*].match.left.meta', rule) else 'any'
+ interface = 'any'
+ for expr in rule.get('rule').get('expr'):
+ match = expr.get('match')
+ if match and jmespath.search('left.meta.key', match) == 'iifname':
+ interface = match.get('right')
+ break
+ if isinstance(interface, str) and interface.startswith('@'):
+ interface = interface[3:]
packets = jmespath.search('rule.expr[*].counter.packets | [0]', rule)
_bytes = jmespath.search('rule.expr[*].counter.bytes | [0]', rule)
data_entries.append([rule_number, packets, _bytes, interface])