Package: dhcpcd Version: 1:10.3.0-1 Severity: normal Tags: patch pending Dear maintainer,
I've prepared an NMU for dhcpcd (versioned as 1:10.3.0-1.1) and uploaded it to DELAYED/5. LMK if you have any concerns. --Daniel
diffstat for dhcpcd-10.3.0 dhcpcd-10.3.0 changelog | 10 dhcpcd.dhcpcd.init | 2 dhcpcd.dhcpcd.service | 2 [email protected] | 3 patches/manager-Fix-loosing-iface-options-on-CARRIER.patch | 217 +++++++++++++ patches/series | 1 6 files changed, 232 insertions(+), 3 deletions(-) diff -Nru dhcpcd-10.3.0/debian/changelog dhcpcd-10.3.0/debian/changelog --- dhcpcd-10.3.0/debian/changelog 2025-11-14 20:14:38.000000000 +0100 +++ dhcpcd-10.3.0/debian/changelog 2025-11-19 15:39:30.000000000 +0100 @@ -1,3 +1,13 @@ +dhcpcd (1:10.3.0-1.1) unstable; urgency=medium + + * Non-maintainer upload. + * Add patch "manager: Fix loosing iface options on CARRIER". + (Closes: #1121014) + * Run Before=networking.service for ifupdown interoperability. + (Closes: #1121016) + + -- Daniel Gröber <[email protected]> Wed, 19 Nov 2025 15:39:30 +0100 + dhcpcd (1:10.3.0-1) unstable; urgency=low * New upstream version. diff -Nru dhcpcd-10.3.0/debian/dhcpcd.dhcpcd.init dhcpcd-10.3.0/debian/dhcpcd.dhcpcd.init --- dhcpcd-10.3.0/debian/dhcpcd.dhcpcd.init 2025-11-14 20:14:38.000000000 +0100 +++ dhcpcd-10.3.0/debian/dhcpcd.dhcpcd.init 2025-11-19 15:39:30.000000000 +0100 @@ -3,7 +3,7 @@ # Provides: dhcpcd # Required-Start: $local_fs $remote_fs # Required-Stop: $local_fs $remote_fs -# Should-Start: networking +# X-Start-Before: networking # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 diff -Nru dhcpcd-10.3.0/debian/dhcpcd.dhcpcd.service dhcpcd-10.3.0/debian/dhcpcd.dhcpcd.service --- dhcpcd-10.3.0/debian/dhcpcd.dhcpcd.service 2025-11-14 20:14:38.000000000 +0100 +++ dhcpcd-10.3.0/debian/dhcpcd.dhcpcd.service 2025-11-19 15:39:30.000000000 +0100 @@ -2,7 +2,7 @@ [Unit] Description=DHCP Client Daemon on all interfaces Wants=network.target -After=networking.service +Before=networking.service Before=network.target Documentation=man:dhcpcd(8) diff -Nru dhcpcd-10.3.0/debian/[email protected] dhcpcd-10.3.0/debian/[email protected] --- dhcpcd-10.3.0/debian/[email protected] 2025-11-14 20:14:38.000000000 +0100 +++ dhcpcd-10.3.0/debian/[email protected] 2025-11-19 15:39:30.000000000 +0100 @@ -2,7 +2,8 @@ [Unit] Description=DHCP Client Daemon on %I Wants=network.target -After=networking.service sys-subsystem-net-devices-%i.device +After=sys-subsystem-net-devices-%i.device +Before=networking.service Before=network.target BindsTo=sys-subsystem-net-devices-%i.device Documentation=man:dhcpcd(8) diff -Nru dhcpcd-10.3.0/debian/patches/manager-Fix-loosing-iface-options-on-CARRIER.patch dhcpcd-10.3.0/debian/patches/manager-Fix-loosing-iface-options-on-CARRIER.patch --- dhcpcd-10.3.0/debian/patches/manager-Fix-loosing-iface-options-on-CARRIER.patch 1970-01-01 01:00:00.000000000 +0100 +++ dhcpcd-10.3.0/debian/patches/manager-Fix-loosing-iface-options-on-CARRIER.patch 2025-11-19 15:39:30.000000000 +0100 @@ -0,0 +1,217 @@ +From 112cc12b8dabef6ca41558016e97bfa03b71df0d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= <[email protected]> +Date: Thu, 6 Nov 2025 14:50:15 +0100 +Subject: manager: Fix loosing iface options on CARRIER + +When an interface (re-)gains carrier dhcpcd_handlecarrier() runs +dhcpcd_initstate() to kick off profile re-selection. Previously this used +args originally passed when starting the manager (ctx->argv). + +However interfaces started via the manager control +interface (dhcpcd_initstate1() in dhcpcd_handleargs()) may be started with +different args. + +For example if we start a manager with + + dhcpcd -M --inactive + +and then start only IPv4 on an interface with + + dhcpcd -4 iface0 + +a subsequent CARRIER event will reset the interface to what amounts to +"default config + `-M --inactive`" which in this case will enable ipv6 +also! + +To fix this we keep a copy of the arguments used to start an interface in +the manager (dhcpcd_handleargs()) code path around around (ifp->argv). + +In the current implementation args passed for renew following the initial +interface start will not be persisted. This causes the interface to reset +to a state of "defaults + config + profile + start-cmdline". + +For example (continuing the scenario above) after enabling ipv6 with -n: + + $ dhcpcd -6 -n iface0 + +A subsequent CARRIER event will disable ipv6 again as the effective +arguments remain `-4 iface0` as passed during interface start. + +Note the per-interface daemon code path wasn't affected as ctx->args +already contains the interface start args. +--- + src/dhcpcd.c | 21 +++++++++++++---- + src/dhcpcd.h | 3 +++ + src/if-options.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ + src/if-options.h | 3 +++ + src/if.c | 2 ++ + 5 files changed, 84 insertions(+), 5 deletions(-) + +--- a/src/dhcpcd.c ++++ b/src/dhcpcd.c +@@ -729,7 +729,10 @@ static void + dhcpcd_initstate(struct interface *ifp, unsigned long long options) + { + +- dhcpcd_initstate1(ifp, ifp->ctx->argc, ifp->ctx->argv, options); ++ dhcpcd_initstate1(ifp, ++ ifp->argc ?: ifp->ctx->argc, ++ ifp->argv ?: ifp->ctx->argv, ++ options); + } + + static void +@@ -1364,7 +1367,7 @@ if_reboot(struct interface *ifp, int arg + oldopts = ifp->options->options; + #endif + script_runreason(ifp, "RECONFIGURE"); +- dhcpcd_initstate1(ifp, argc, argv, 0); ++ dhcpcd_initstate1(ifp, argc, argv, 0); // control or main argv + #ifdef INET + if (ifp->options->options & DHCPCD_DHCP) + dhcp_reboot_newopts(ifp, oldopts); +@@ -1419,8 +1422,16 @@ reconf_reboot(struct dhcpcd_ctx *ctx, in + ipv4_applyaddr(ifp); + #endif + } else if (i != argc) { ++ /* iface wasnt found above -> it's new. start it. */ + ifp->active = IF_ACTIVE_USER; +- dhcpcd_initstate1(ifp, argc, argv, 0); ++ dhcpcd_initstate1(ifp, argc, argv, 0); // control cmd args ++ ++ if (ifp->argv) ++ free_argv_copy(ifp->argv); ++ ifp->argv = copy_argv(argc, argv); ++ if (ifp->argv) ++ ifp->argc = argc; ++ + run_preinit(ifp); + dhcpcd_prestartinterface(ifp); + } +@@ -1773,7 +1784,7 @@ dumperr: + } + + reload_config(ctx); +- /* XXX: Respect initial commandline options? */ ++ /* Respect control cmd options! */ + reconf_reboot(ctx, do_reboot, argc, argv, oifind); + return 0; + } +@@ -2680,7 +2691,7 @@ start_manager: + + TAILQ_FOREACH(ifp, ctx.ifaces, next) { + if (ifp->active) +- dhcpcd_initstate1(ifp, argc, argv, 0); ++ dhcpcd_initstate1(ifp, argc, argv, 0); // main argv + } + if_learnaddrs(&ctx, ctx.ifaces, &ifaddrs); + if_freeifaddrs(&ctx, &ifaddrs); +--- a/src/dhcpcd.h ++++ b/src/dhcpcd.h +@@ -85,6 +85,9 @@ struct interface { + uint8_t ssid[IF_SSIDLEN]; + unsigned int ssid_len; + ++ int argc; ++ char **argv; ++ + char profile[PROFILE_LEN]; + struct if_options *options; + void *if_data[IF_DATA_MAX]; +--- a/src/if-options.c ++++ b/src/if-options.c +@@ -44,6 +44,7 @@ + #include <string.h> + #include <unistd.h> + #include <time.h> ++#include <assert.h> + + #include "config.h" + #include "common.h" +@@ -2986,6 +2987,65 @@ add_options(struct dhcpcd_ctx *ctx, cons + return r; + } + ++#define ARGV_COPY_MAGIC ((char *)0x5a54292d273f3d34) ++/*^ intentional truncation on 32bit arches */ ++ ++char **copy_argv(int argc, char **argv) ++{ ++ int i; ++ size_t strslen = 0; ++ for (i = 0; i < argc; i++) { ++ strslen += strlen(argv[i]) + 1; ++ } ++ if (strslen == 0) // also handles argc < 0 ++ return NULL; ++ ++ unsigned nptrs = 1 + (unsigned)argc + 1; ++ size_t ptrslen = nptrs * sizeof(char *); ++ void *buf = malloc(ptrslen + strslen); ++ char **ptrs = buf; ++ if (!buf) ++ return NULL; ++ ++ ptrs[0] = ARGV_COPY_MAGIC; ++ ptrs[nptrs - 1] = NULL; ++ ++ if (argc == 0) ++ goto out; ++ ++ char *strsp = (char *)&ptrs[nptrs]; ++ for (i = 0; i < argc; i++) { ++ size_t len = strlcpy(strsp, argv[i], strslen); ++ if (len >= strslen) // truncated ++ goto err; ++ ++ ptrs[1 + i] = strsp; ++ ++ strsp += len + 1; ++ if (strslen < len + 1) ++ goto err; ++ strslen -= len + 1; ++ } ++ ++ assert(strslen == 0); ++ assert(ptrs[nptrs - 1] == NULL); ++out: ++ return &ptrs[1]; ++ ++err: ++ free(buf); ++ return NULL; ++} ++ ++void free_argv_copy(char **argv) ++{ ++ assert(argv[-1] == ARGV_COPY_MAGIC); ++ if (argv[-1] != ARGV_COPY_MAGIC) { ++ logerrx("%s: invalid argv", __func__); ++ } else ++ free(&argv[-1]); ++} ++ + void + free_options(struct dhcpcd_ctx *ctx, struct if_options *ifo) + { +--- a/src/if-options.h ++++ b/src/if-options.h +@@ -322,4 +322,7 @@ int add_options(struct dhcpcd_ctx *, con + void free_dhcp_opt_embenc(struct dhcp_opt *); + void free_options(struct dhcpcd_ctx *, struct if_options *); + ++char **copy_argv(int argc, char **argv); ++void free_argv_copy(char **argv); ++ + #endif +--- a/src/if.c ++++ b/src/if.c +@@ -100,6 +100,8 @@ if_free(struct interface *ifp) + #endif + rt_freeif(ifp); + free_options(ifp->ctx, ifp->options); ++ if (ifp->argv) ++ free_argv_copy(ifp->argv); + free(ifp); + } + diff -Nru dhcpcd-10.3.0/debian/patches/series dhcpcd-10.3.0/debian/patches/series --- dhcpcd-10.3.0/debian/patches/series 2025-11-14 20:14:38.000000000 +0100 +++ dhcpcd-10.3.0/debian/patches/series 2025-11-19 15:39:30.000000000 +0100 @@ -1 +1,2 @@ Debian_uncomment_hostname_in_dhcpcd_conf.patch +manager-Fix-loosing-iface-options-on-CARRIER.patch
signature.asc
Description: PGP signature

