diff options
| -rwxr-xr-x | smoketest/scripts/cli/test_service_dhcpv6-server.py | 38 | ||||
| -rwxr-xr-x | src/conf_mode/service_dhcpv6-server.py | 13 |
2 files changed, 51 insertions, 0 deletions
diff --git a/smoketest/scripts/cli/test_service_dhcpv6-server.py b/smoketest/scripts/cli/test_service_dhcpv6-server.py index 04aa014b0..762216930 100755 --- a/smoketest/scripts/cli/test_service_dhcpv6-server.py +++ b/smoketest/scripts/cli/test_service_dhcpv6-server.py @@ -368,6 +368,44 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase): # Check for running process self.assertTrue(process_named_running(PROCESS_NAME)) + def test_static_mapping_duplicate_address_prefix(self): + shared_net_name = 'SMOKE-DUP' + pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet] + mapping = pool + ['static-mapping'] + + self.cli_set(pool + ['subnet-id', '1']) + duid1 = '00:01:00:01:12:34:56:78:aa:bb:cc:dd:ee:01' + duid2 = '00:01:00:01:12:34:56:78:aa:bb:cc:dd:ee:02' + dup_addr = inc_ip(subnet, 10) + dup_prefix = inc_ip(subnet, 1 << 64) + '/64' + + # commit valid config with a single address mapping + self.cli_set(mapping + ['client1', 'duid', duid1]) + self.cli_set(mapping + ['client1', 'ipv6-address', dup_addr]) + self.cli_commit() + + # adding a second mapping with the same address must fail + self.cli_set(mapping + ['client2', 'duid', duid2]) + self.cli_set(mapping + ['client2', 'ipv6-address', dup_addr]) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_delete(mapping + ['client1']) + self.cli_commit() + + # commit valid config with a single prefix mapping + self.cli_set(mapping + ['client1', 'duid', duid1]) + self.cli_set(mapping + ['client1', 'ipv6-prefix', dup_prefix]) + self.cli_commit() + + # adding a second mapping with the same prefix must fail + self.cli_set(mapping + ['client2', 'ipv6-prefix', dup_prefix]) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_delete(mapping + ['client1']) + self.cli_commit() + if __name__ == '__main__': unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on()) diff --git a/src/conf_mode/service_dhcpv6-server.py b/src/conf_mode/service_dhcpv6-server.py index 01bbf3096..ccdecb410 100755 --- a/src/conf_mode/service_dhcpv6-server.py +++ b/src/conf_mode/service_dhcpv6-server.py @@ -223,12 +223,25 @@ def verify(dhcpv6): # Static mappings don't require anything (but check if IP is in subnet if it's set) if 'static_mapping' in subnet_config: + reserved_addresses = [] + reserved_prefixes = [] for mapping, mapping_config in subnet_config['static_mapping'].items(): if 'ipv6_address' in mapping_config: # Static address must be in subnet for address in mapping_config['ipv6_address']: if ip_address(address) not in ip_network(subnet): raise ConfigError(f'static-mapping address for mapping "{mapping}" is not in subnet "{subnet}"!') + if address in reserved_addresses: + raise ConfigError(f'Duplicate IPv6 address "{address}" in static-mapping "{mapping}" ' + f'within shared-network "{network}", subnet "{subnet}"!') + reserved_addresses.append(address) + + if 'ipv6_prefix' in mapping_config: + for prefix in mapping_config['ipv6_prefix']: + if prefix in reserved_prefixes: + raise ConfigError(f'Duplicate IPv6 prefix "{prefix}" in static-mapping "{mapping}" ' + f'within shared-network "{network}", subnet "{subnet}"!') + reserved_prefixes.append(prefix) if ('ipv6_address' not in mapping_config and 'ipv6_prefix' not in mapping_config): raise ConfigError('Either IPv6 address or IPv6 prefix must be set for static mapping ' |
