summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiaosen Wang <secretandanon@gmail.com>2026-03-09 10:50:09 -0700
committerMiaosen Wang <secretandanon@gmail.com>2026-03-09 11:03:14 -0700
commit48732ec28fc24fc54e719acb94b23abc3ddc18da (patch)
tree4443b7d254e65a5afaab713c8b7e7a4d236bf2c7
parent61ba7ee632fd2ee8fe58b636087e539da89c6e65 (diff)
downloadvyos-1x-48732ec28fc24fc54e719acb94b23abc3ddc18da.tar.gz
vyos-1x-48732ec28fc24fc54e719acb94b23abc3ddc18da.zip
T8292: `service: ndp-proxy: validate prefix mode/interface settings correctly`
Switch `verify()` to validate the real config tree (`interface -> prefix`) instead of non-existent `rule` nodes. This enforces: - `mode interface` requires `prefix ... interface` - non-`interface` modes must not set `prefix ... interface` - referenced interface exists when `mode` is `interface`
-rwxr-xr-xsmoketest/scripts/cli/test_service_ndp-proxy.py59
-rwxr-xr-xsrc/conf_mode/service_ndp-proxy.py39
2 files changed, 86 insertions, 12 deletions
diff --git a/smoketest/scripts/cli/test_service_ndp-proxy.py b/smoketest/scripts/cli/test_service_ndp-proxy.py
index d1c37bbe4..f89ea0fac 100755
--- a/smoketest/scripts/cli/test_service_ndp-proxy.py
+++ b/smoketest/scripts/cli/test_service_ndp-proxy.py
@@ -18,6 +18,7 @@ import unittest
from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.configsession import ConfigSessionError
from vyos.ifconfig import Section
from vyos.utils.process import cmd
from vyos.utils.process import process_named_running
@@ -66,5 +67,63 @@ class TestServiceNDPProxy(VyOSUnitTestSHIM.TestCase):
self.assertIn(f'timeout 500', config) # default value
self.assertIn(f'ttl 30000', config) # default value
+ def test_prefix_mode_interface_requires_interface(self):
+ interface = Section.interfaces('ethernet')[0]
+ prefix_path = base_path + ['interface', interface, 'prefix', '2001:db8::/64']
+ self.cli_set(base_path + ['interface', interface])
+ self.cli_commit()
+
+ self.cli_set(prefix_path + ['mode', 'interface'])
+
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ def test_prefix_mode_interface_with_interface(self):
+ interface = Section.interfaces('ethernet')[0]
+ prefix_path = base_path + ['interface', interface, 'prefix', '2001:db8::/64']
+ self.cli_set(base_path + ['interface', interface])
+ self.cli_set(prefix_path + ['mode', 'interface'])
+ self.cli_set(prefix_path + ['interface', interface])
+ self.cli_commit()
+
+ config = getConfigSection(f'proxy {interface}')
+ self.assertIn('rule 2001:db8::/64 {', config)
+ self.assertIn(f'iface {interface}', config)
+
+ def test_prefix_mode_auto_rejects_interface(self):
+ interface = Section.interfaces('ethernet')[0]
+ prefix_path = base_path + ['interface', interface, 'prefix', '2001:db8::/64']
+ self.cli_set(base_path + ['interface', interface])
+ self.cli_commit()
+
+ self.cli_set(prefix_path + ['mode', 'auto'])
+ self.cli_set(prefix_path + ['interface', interface])
+
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ def test_disabled_prefix_skips_validation(self):
+ interface = Section.interfaces('ethernet')[0]
+ prefix_path = base_path + ['interface', interface, 'prefix', '2001:db8::/64']
+ self.cli_set(base_path + ['interface', interface])
+ self.cli_set(prefix_path + ['mode', 'interface'])
+ self.cli_set(prefix_path + ['disable'])
+
+ self.cli_commit()
+
+ config = getConfigSection(f'proxy {interface}')
+ self.assertNotIn('rule 2001:db8::/64 {', config)
+
+ def test_disabled_interface_skips_validation(self):
+ interface = Section.interfaces('ethernet')[0]
+ prefix_path = base_path + ['interface', interface, 'prefix', '2001:db8::/64']
+ self.cli_set(base_path + ['interface', interface, 'disable'])
+ self.cli_set(prefix_path + ['mode', 'interface'])
+
+ self.cli_commit()
+
+ config = cmd(f'cat {NDPPD_CONF}')
+ self.assertNotIn(f'proxy {interface} {{', config)
+
if __name__ == '__main__':
unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on())
diff --git a/src/conf_mode/service_ndp-proxy.py b/src/conf_mode/service_ndp-proxy.py
index f42ee9be8..672f98c71 100755
--- a/src/conf_mode/service_ndp-proxy.py
+++ b/src/conf_mode/service_ndp-proxy.py
@@ -48,18 +48,33 @@ def verify(ndpp):
if not ndpp:
return None
- if 'interface' in ndpp:
- for interface, interface_config in ndpp['interface'].items():
- verify_interface_exists(ndpp, interface)
-
- if 'rule' in interface_config:
- for rule, rule_config in interface_config['rule'].items():
- if rule_config['mode'] == 'interface' and 'interface' not in rule_config:
- raise ConfigError(f'Rule "{rule}" uses interface mode but no interface defined!')
-
- if rule_config['mode'] != 'interface' and 'interface' in rule_config:
- if interface_config['mode'] != 'interface' and 'interface' in interface_config:
- raise ConfigError(f'Rule "{rule}" does not use interface mode, thus interface can not be defined!')
+ if 'interface' not in ndpp:
+ return None
+
+ for interface, interface_config in ndpp['interface'].items():
+ if 'disable' in interface_config:
+ continue
+
+ verify_interface_exists(ndpp, interface)
+
+ if 'prefix' not in interface_config:
+ continue
+
+ for prefix, prefix_config in interface_config['prefix'].items():
+ if 'disable' in prefix_config:
+ continue
+
+ mode = prefix_config.get('mode')
+ prefix_interface = prefix_config.get('interface')
+
+ if mode == 'interface':
+ if not prefix_interface:
+ raise ConfigError(f'Prefix "{prefix}" uses interface mode but no interface defined!')
+ verify_interface_exists(ndpp, prefix_interface)
+ continue
+
+ if prefix_interface:
+ raise ConfigError(f'Prefix "{prefix}" does not use interface mode, thus interface can not be defined!')
return None