summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2026-06-12 22:16:21 +0200
committerGitHub <noreply@github.com>2026-06-12 22:16:21 +0200
commitc2f87f243a1f813fbdd319b1004fd3a26397ab3e (patch)
treeec111a25e045df879841370cb96ff184653ae349
parente1a2ab00be9af2e3050b474f4538ac86f65f357e (diff)
parent474ff8bffec4d7c096921beeb507c74a6de63ec1 (diff)
downloadvyos-1x-c2f87f243a1f813fbdd319b1004fd3a26397ab3e.tar.gz
vyos-1x-c2f87f243a1f813fbdd319b1004fd3a26397ab3e.zip
Merge pull request #5269 from natali-rs1985/T8953
dhcpv6: T8953: Add validation for duplicate static-mapping address and prefix
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcpv6-server.py38
-rwxr-xr-xsrc/conf_mode/service_dhcpv6-server.py13
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 '