diff options
| author | Miaosen Wang <secretandanon@gmail.com> | 2026-03-09 10:50:09 -0700 |
|---|---|---|
| committer | Miaosen Wang <secretandanon@gmail.com> | 2026-03-09 11:03:14 -0700 |
| commit | 48732ec28fc24fc54e719acb94b23abc3ddc18da (patch) | |
| tree | 4443b7d254e65a5afaab713c8b7e7a4d236bf2c7 | |
| parent | 61ba7ee632fd2ee8fe58b636087e539da89c6e65 (diff) | |
| download | vyos-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-x | smoketest/scripts/cli/test_service_ndp-proxy.py | 59 | ||||
| -rwxr-xr-x | src/conf_mode/service_ndp-proxy.py | 39 |
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 |
