summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcblackburn-igl <chris.blackburn@infinitivegroup.co.uk>2025-10-28 15:38:43 +0000
committerGitHub <noreply@github.com>2025-10-28 15:38:43 +0000
commit1737b16dd87778358266222e2ef061eb15d63019 (patch)
tree0e127460ae080ad35a06b4e719d261ab3f7a1805 /src
parentecc4c85b799047f51e4a32ae5b0590017a6ce374 (diff)
downloadvyos-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-xsrc/conf_mode/service_dhcp-server.py33
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