From 261851a888028a070a11faf5ed003aa2bea71e1a Mon Sep 17 00:00:00 2001 From: Niv Bromberg Date: Thu, 3 Sep 2026 15:21:33 +0000 Subject: [PATCH] Preserve vendclass optarg when parsing enterprise number The vendclass parser split the enterprise number from its class data by writing a NUL into optarg. dhcpcd applies command-line options more than once: first while processing global options, then again when each interface is configured. That made the first pass succeed because it kept a local pointer to the bytes after the separator, but it permanently shortened the shared argv string to the enterprise number for later passes. Parse the enterprise number from a temporary NUL-terminated copy instead, leaving argv intact so the per-interface pass can still see and encode the vendor-class data. --- src/if-options.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/if-options.c b/src/if-options.c index 7b445f45..6ff4e684 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -2193,9 +2193,22 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, return -1; #else fp = strwhite(arg); - if (fp) - *fp++ = '\0'; - u = (uint32_t)strtou(arg, NULL, 0, 0, UINT32_MAX, &e); + bp = NULL; + /* Command line options are parsed globally and then replayed + * per-interface using the same argv, so do not split optarg + * in-place. Later passes still need the data after the EN. */ + if (fp) { + dl = (size_t)(fp - arg); + bp = malloc(dl + 1); + if (!bp) { + logerr(__func__); + return -1; + } + memcpy(bp, arg, dl); + bp[dl] = '\0'; + } + u = (uint32_t)strtou(bp ? bp : arg, NULL, 0, 0, UINT32_MAX, &e); + free(bp); if (e) { logerrx("invalid code: %s", arg); return -1;