diff options
| author | cblackburn-igl <chris.blackburn@infinitivegroup.co.uk> | 2025-10-28 15:38:43 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-28 15:38:43 +0000 |
| commit | 1737b16dd87778358266222e2ef061eb15d63019 (patch) | |
| tree | 0e127460ae080ad35a06b4e719d261ab3f7a1805 /src | |
| parent | ecc4c85b799047f51e4a32ae5b0590017a6ce374 (diff) | |
| download | vyos-1x-1737b16dd87778358266222e2ef061eb15d63019.tar.gz vyos-1x-1737b16dd87778358266222e2ef061eb15d63019.zip | |
dhcp-server: T3936: Added support for DHCP Option 82 (#4665)
* dhcp-server: T3936: Added support for DHCP Option 82
This commit adds support in both the CLI and the underlying code for
DHCP Option 82 to be used to filter/route DHCP address assignments.
The primary use case for this is to support enterprise switches which
can "tag" DHCP requests with physical real world informaiton such as
which switch first saw the request and which port it originated from
(known in this context as remote-id and circuit-id). Once
client-classes have been defined they can be assigned to subnets or
ranges so that only certain addresses get assigned to specific
requests.
There is also a corresponding documentation update which pairs with
this code change.
(cherry picked from commit 326b5e713cb363a2b9f69e2204c4ee2ccd9939bb)
* Update src/conf_mode/service_dhcp-server.py
Co-authored-by: Nataliia S. <81954790+natali-rs1985@users.noreply.github.com>
* Update src/conf_mode/service_dhcp-server.py
Co-authored-by: Nataliia S. <81954790+natali-rs1985@users.noreply.github.com>
* Update interface-definitions/include/dhcp/dhcp-server-common-config.xml.i
Co-authored-by: Nataliia S. <81954790+natali-rs1985@users.noreply.github.com>
---------
Co-authored-by: Daniil Baturin <daniil@baturin.org>
Co-authored-by: Nataliia S. <81954790+natali-rs1985@users.noreply.github.com>
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/service_dhcp-server.py | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/conf_mode/service_dhcp-server.py b/src/conf_mode/service_dhcp-server.py index e4730f8a8..144739372 100755 --- a/src/conf_mode/service_dhcp-server.py +++ b/src/conf_mode/service_dhcp-server.py @@ -15,6 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os +import re from sys import exit from sys import argv @@ -287,6 +288,12 @@ def verify(dhcp): f'DHCP static-route "{route}" requires router to be defined!' ) + # If a client class has been specified then it must exist + if 'client_class' in subnet_config: + client_class = subnet_config['client_class'] + if client_class not in dhcp.get('client_class', {}): + raise ConfigError(f'Client class "{client_class}" set in subnet "{subnet}" but does not exist') + # Check if DHCP address range is inside configured subnet declaration if 'range' in subnet_config: networks = [] @@ -296,6 +303,12 @@ def verify(dhcp): f'DHCP range "{range}" start and stop address must be defined!' ) + # If a client class has been specified then it must exist + if 'client_class' in range_config: + client_class = range_config['client_class'] + if client_class not in dhcp.get('client_class', {}): + raise ConfigError(f'Client class "{client_class}" set in range "{range}" but does not exist') + # Start/Stop address must be inside network for key in ['start', 'stop']: if ip_address(range_config[key]) not in ip_network(subnet): @@ -504,6 +517,26 @@ def verify(dhcp): if 'reverse_domain' in ddns: verify_ddns_domain_servers('Reverse', ddns['reverse_domain']) + if 'client_class' in dhcp: + # Check client class values are valid + for class_name, class_config in dhcp['client_class'].items(): + if 'relay_agent_information' in class_config: + relay_agent_information_config = class_config['relay_agent_information'] + # Compile a regex that will scan for valid inputs. Input can be + # either hex in the form 0x0123456789ABCDEF or a string that + # does *not* start with 0x. i.e. 0xHELLOWORLD is bad + pattern = re.compile(r'^(?:0x[0-9A-Fa-f]+|(?!0x).+)$') + + if 'circuit_id' in relay_agent_information_config: + circuit_id = relay_agent_information_config['circuit_id'] + if not pattern.match(circuit_id): + raise ConfigError(f'Invalid circuit-id "{circuit_id}" must be either text literal or hex string starting with 0x') + + if 'remote_id' in relay_agent_information_config: + remote_id = relay_agent_information_config['remote_id'] + if not pattern.match(remote_id): + raise ConfigError(f'Invalid remote-id "{remote_id}" must be either text literal or hex string starting with 0x') + return None |
