summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRuben Herold <ruben@puettmann.net>2026-08-31 12:49:24 +0200
committerViacheslav Hletenko <seversss265@gmail.com>2026-10-15 16:05:57 +0300
commit2e5ea7a8304ed6ce504b3928e3b2f52574a61397 (patch)
tree1eff85f00c83e0ba087850a13bbbf952ba7eabaa /python
parenta06aab8262d6ef3fba6d4f73b699a46500546a1a (diff)
downloadvyos-1x-2e5ea7a8304ed6ce504b3928e3b2f52574a61397.tar.gz
vyos-1x-2e5ea7a8304ed6ce504b3928e3b2f52574a61397.zip
dhcp-server: T9267: add client-class matching on hostname/vendor-class-id
Client classes could previously only match on relay agent information (Option 82). Add matching on the client-sent hostname (Option 12) and vendor class identifier (Option 60), each with an exact-value or substring form, so clients sharing a subnet can be told apart by e.g. device model without splitting the subnet into per-model pools. Also let a client-class deliver its own options (reusing the existing subnet/range option syntax), so a match can directly hand out a model-specific value such as a provisioning URL, independent of which pool the client's lease is drawn from.
Diffstat (limited to 'python')
-rw-r--r--python/vyos/kea.py35
-rwxr-xr-xpython/vyos/template.py10
2 files changed, 41 insertions, 4 deletions
diff --git a/python/vyos/kea.py b/python/vyos/kea.py
index 436c134c8..e42bb6e1c 100644
--- a/python/vyos/kea.py
+++ b/python/vyos/kea.py
@@ -725,11 +725,32 @@ def kea_get_server_leases(
return data
-def _build_relay_hex_condition(sub_option_index, value):
+def _kea_hex_literal(value):
if value.startswith('0x'):
- return f'relay4[{sub_option_index}].hex == {value}'
- else:
- return f'relay4[{sub_option_index}].hex == 0x{value.encode().hex().lower()}'
+ return value
+ return f'0x{value.encode().hex().lower()}'
+
+
+def _build_hex_condition(kea_path, value):
+ return f'{kea_path}.hex == {_kea_hex_literal(value)}'
+
+
+def _build_relay_hex_condition(sub_option_index, value):
+ return _build_hex_condition(f'relay4[{sub_option_index}]', value)
+
+
+def _build_option_match_condition(option_number, match_config):
+ kea_path = f'option[{option_number}]'
+
+ if 'substring' in match_config:
+ substring_config = match_config['substring']
+ offset = substring_config.get('offset', '0')
+ value_hex = _kea_hex_literal(substring_config['value'])
+ # length is expressed in bytes; a hex literal is '0x' + 2 hex digits per byte
+ length = substring_config.get('length') or str((len(value_hex) - 2) // 2)
+ return f'substring({kea_path}.hex, {offset}, {length}) == {value_hex}'
+
+ return _build_hex_condition(kea_path, match_config['value'])
def kea_build_client_class_test(config):
@@ -749,6 +770,12 @@ def kea_build_client_class_test(config):
)
)
+ if 'hostname' in config:
+ conditions.append(_build_option_match_condition(12, config['hostname']))
+
+ if 'vendor_class_id' in config:
+ conditions.append(_build_option_match_condition(60, config['vendor_class_id']))
+
test = ' and '.join(conditions)
return test
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 2c07d79da..6323657ed 100755
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -982,6 +982,7 @@ def kea_high_availability_json(config):
@register_filter('kea_client_class_json')
def kea_client_class_json(client_classes):
from vyos.kea import kea_build_client_class_test
+ from vyos.kea import kea_parse_options
from json import dumps
out = []
@@ -994,6 +995,15 @@ def kea_client_class_json(client_classes):
'test': kea_build_client_class_test(config)
}
+ if 'option' in config:
+ client_class['option-data'] = kea_parse_options(config['option'])
+
+ if 'bootfile_name' in config['option']:
+ client_class['boot-file-name'] = config['option']['bootfile_name']
+
+ if 'bootfile_server' in config['option']:
+ client_class['next-server'] = config['option']['bootfile_server']
+
out.append(client_class)
return dumps(out, indent=4)