From 46e06d8fd1f1dd378c128fe87549bdba165f640a Mon Sep 17 00:00:00 2001 From: Ruben Herold Date: Fri, 4 Sep 2026 11:17:26 +0200 Subject: dhcp-server: T9267: make client-class substring matching contains-anywhere The Mikrotik configuration referenced by T9267 uses matching-type=substring, documented to match the value anywhere within the option string. This PR's "substring" match instead compared a fixed-length slice at a fixed byte offset (default 0) for exact equality - effectively an anchored prefix match, not a substring search - which does not reliably reproduce the ticket's own use case of picking a device model string (e.g. "T42S") out of a longer, variably-formatted hostname. Rebuild "hostname substring"/"vendor-class-id substring" on Kea's match()+lcase() instead of substring()==, so a configured value now matches anywhere in the option content and case-insensitively (options like vendor-class-id are not guaranteed to arrive in a fixed case). Drop the "offset" leaf together with it, since it has no remaining purpose once matching is no longer anchored to a fixed position, and there is no released behavior to preserve. Raw hex input and values containing a literal single quote are rejected for substring matching in verify(), since neither can be safely embedded into the generated Kea regular expression; exact "value" matching is unaffected and still accepts both. Reported by alexk37 in review of PR #5436. --- src/conf_mode/service_dhcp-server.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/conf_mode/service_dhcp-server.py b/src/conf_mode/service_dhcp-server.py index 6572b4b7f..46fd0a7bc 100755 --- a/src/conf_mode/service_dhcp-server.py +++ b/src/conf_mode/service_dhcp-server.py @@ -597,9 +597,15 @@ def verify(dhcp): f'Client class "{class_name}": "{option_label} substring" requires a value' ) value = match_config['substring']['value'] - if not pattern.match(value): + if value.startswith('0x'): + raise ConfigError( + f'Client class "{class_name}": "{option_label} substring" only supports ' + f'plain text values, not raw hex' + ) + if "'" in value: raise ConfigError( - f'Invalid {option_label} substring value "{value}" must be either text literal or hex string starting with 0x' + f'Client class "{class_name}": "{option_label} substring" value must not ' + f"contain a single quote (')" ) return None -- cgit v1.2.3