diff options
| author | Ruben Herold <ruben@puettmann.net> | 2026-08-31 12:49:24 +0200 |
|---|---|---|
| committer | Viacheslav Hletenko <seversss265@gmail.com> | 2026-10-15 16:05:57 +0300 |
| commit | 2e5ea7a8304ed6ce504b3928e3b2f52574a61397 (patch) | |
| tree | 1eff85f00c83e0ba087850a13bbbf952ba7eabaa /python | |
| parent | a06aab8262d6ef3fba6d4f73b699a46500546a1a (diff) | |
| download | vyos-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.py | 35 | ||||
| -rwxr-xr-x | python/vyos/template.py | 10 |
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) |
