On 2025/12/22 10:48, Courtney Hicks wrote: > I recently updated my router to the latest -current as well as ports, > which upgraded my previous version of dhcpcd 10.2.4v0 to 10.3.0v0. I > eventually realized I was no longer getting IPv6 addresses on my > clients. I checked my logs and got a bunch of "no buffer space > available" messages on my LAN interfaces that I have PDs going to. > > dhcpcd[55787]: if_getmtu: No buffer space available > > I also noticed that this was messing with arp info too for some reason. > This is my config: > > ipv6only > noipv6rs > duid > persistent > option rapid_commit > require dhcp_server_identifier > > script "" > > allowinterfaces igc0 ixl0 vlan5 > interface igc0 > ipv6rs > ia_na 1 > ia_pd 2/::/60 ixl0/1/64 vlan5/2/64 > > I built dhcpcd 10.2.4v0 and replaced 10.3.0v0 and everything is working > as expected. I imagine this is a dhcpcd bug, but I wanted to bring this > up here on the ports list. > > Courtney > > PS: I hope Thunderbird formats my line width to 72 correctly. My > apologies if it does not and breaks netiquette >
On 2025/12/27 14:43, Zack Newman wrote: > Yeah, this is a known issue[^1]. If you compile the code yourself with > the proposed patch, it should work[^2]. Note I don't run -current, so > I'm merely speaking as a reader. I recommend staying in the loop with > upstream seeing how disruptive issues with dhcpcd can be. I always look > at the issues on GitHub before updating it. > > [^1]: https://github.com/NetworkConfiguration/dhcpcd/issues/555 > [^2]: > https://github.com/NetworkConfiguration/dhcpcd/issues/555#issuecomment-3546211800 > Can you try this please? It is the result of the set of patches from https://github.com/NetworkConfiguration/dhcpcd/pull/556 Would be good to comment on the upstream PR if it helps too. Index: Makefile =================================================================== RCS file: /cvs/ports/net/dhcpcd/Makefile,v diff -u -p -r1.119 Makefile --- Makefile 17 Nov 2025 18:36:41 -0000 1.119 +++ Makefile 28 Dec 2025 14:39:02 -0000 @@ -1,6 +1,7 @@ COMMENT= DHCPv4/IPv4LL/IPv6RS/DHCPv6 quad stack client V= 10.3.0 +REVISION= 0 DISTNAME= dhcpcd-$V EXTRACT_SUFX= .tar.xz Index: patches/patch-src_privsep-root_c =================================================================== RCS file: patches/patch-src_privsep-root_c diff -N patches/patch-src_privsep-root_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_privsep-root_c 28 Dec 2025 14:39:02 -0000 @@ -0,0 +1,253 @@ +https://patch-diff.githubusercontent.com/raw/NetworkConfiguration/dhcpcd/pull/556.patch + +Index: src/privsep-root.c +--- src/privsep-root.c.orig ++++ src/privsep-root.c +@@ -71,21 +71,20 @@ struct psr_ctx { + struct psr_error psr_error; + size_t psr_datalen; + void *psr_data; +- size_t psr_mdatalen; +- void *psr_mdata; +- bool psr_usemdata; ++ bool psr_mallocdata; + }; + + static ssize_t +-ps_root_readerrorcb(struct psr_ctx *psr_ctx) ++ps_root_readerrorcb(struct psr_ctx *pc) + { +- struct dhcpcd_ctx *ctx = psr_ctx->psr_ctx; ++ struct dhcpcd_ctx *ctx = pc->psr_ctx; + int fd = PS_ROOT_FD(ctx); +- struct psr_error *psr_error = &psr_ctx->psr_error; ++ struct psr_error *psr_error = &pc->psr_error; + struct iovec iov[] = { + { .iov_base = psr_error, .iov_len = sizeof(*psr_error) }, +- { .iov_base = NULL, .iov_len = 0 }, ++ { .iov_base = pc->psr_data, .iov_len = pc->psr_datalen }, + }; ++ struct msghdr msg = { .msg_iov = iov, .msg_iovlen = __arraycount(iov) }; + ssize_t len; + + #define PSR_ERROR(e) \ +@@ -98,81 +97,84 @@ ps_root_readerrorcb(struct psr_ctx *psr_ctx) + if (eloop_waitfd(fd) == -1) + PSR_ERROR(errno); + +- len = recv(fd, psr_error, sizeof(*psr_error), MSG_PEEK); ++ if (!pc->psr_mallocdata) ++ goto recv; ++ ++ /* We peek at the psr_error structure to tell us how much of a buffer ++ * we need to read the whole packet. */ ++ msg.msg_iovlen--; ++ len = recvmsg(fd, &msg, MSG_PEEK | MSG_WAITALL); + if (len == -1) + PSR_ERROR(errno); +- else if ((size_t)len < sizeof(*psr_error)) +- PSR_ERROR(EINVAL); + +- if (psr_error->psr_datalen > SSIZE_MAX) +- PSR_ERROR(ENOBUFS); +- if (psr_ctx->psr_usemdata && +- psr_error->psr_datalen > psr_ctx->psr_mdatalen) +- { +- void *d = realloc(psr_ctx->psr_mdata, psr_error->psr_datalen); +- if (d == NULL) +- PSR_ERROR(errno); +- psr_ctx->psr_mdata = d; +- psr_ctx->psr_mdatalen = psr_error->psr_datalen; ++ /* After this point, we MUST do another recvmsg even on a failure ++ * to remove the message after peeking. */ ++ if ((size_t)len < sizeof(*psr_error)) { ++ /* We can't use the header to work out buffers, so ++ * remove the message and bail. */ ++ (void)recvmsg(fd, &msg, MSG_WAITALL); ++ PSR_ERROR(EINVAL); + } +- if (psr_error->psr_datalen != 0) { +- if (psr_ctx->psr_usemdata) +- iov[1].iov_base = psr_ctx->psr_mdata; +- else { +- if (psr_error->psr_datalen > psr_ctx->psr_datalen) +- PSR_ERROR(ENOBUFS); +- iov[1].iov_base = psr_ctx->psr_data; +- } ++ ++ /* No data to read? Unlikely but ... */ ++ if (psr_error->psr_datalen == 0) ++ goto recv; ++ ++ pc->psr_data = malloc(psr_error->psr_datalen); ++ if (pc->psr_data != NULL) { ++ iov[1].iov_base = pc->psr_data; + iov[1].iov_len = psr_error->psr_datalen; ++ msg.msg_iovlen++; + } + +- len = readv(fd, iov, __arraycount(iov)); ++recv: ++ len = recvmsg(fd, &msg, MSG_WAITALL); + if (len == -1) + PSR_ERROR(errno); +- else if ((size_t)len != sizeof(*psr_error) + psr_error->psr_datalen) ++ else if ((size_t)len < sizeof(*psr_error)) + PSR_ERROR(EINVAL); ++ else if (msg.msg_flags & MSG_TRUNC) ++ PSR_ERROR(ENOBUFS); ++ else if ((size_t)len != sizeof(*psr_error) + psr_error->psr_datalen) { ++ logerrx("%s: recvmsg returned %zd, expecting %zu", __func__, ++ len, sizeof(*psr_error) + psr_error->psr_datalen); ++ PSR_ERROR(EBADMSG); ++ } + return len; + } + + ssize_t + ps_root_readerror(struct dhcpcd_ctx *ctx, void *data, size_t len) + { +- struct psr_ctx *pc = ctx->ps_root->psp_data; ++ struct psr_ctx pc = { ++ .psr_ctx = ctx, ++ .psr_data = data, ++ .psr_datalen = len, ++ .psr_mallocdata = false ++ }; + +- pc->psr_data = data; +- pc->psr_datalen = len; +- pc->psr_usemdata = false; +- ps_root_readerrorcb(pc); ++ ps_root_readerrorcb(&pc); + +- errno = pc->psr_error.psr_errno; +- return pc->psr_error.psr_result; ++ errno = pc.psr_error.psr_errno; ++ return pc.psr_error.psr_result; + } + + ssize_t + ps_root_mreaderror(struct dhcpcd_ctx *ctx, void **data, size_t *len) + { +- struct psr_ctx *pc = ctx->ps_root->psp_data; +- void *d; ++ struct psr_ctx pc = { ++ .psr_ctx = ctx, ++ .psr_data = NULL, ++ .psr_datalen = 0, ++ .psr_mallocdata = true ++ }; + +- pc->psr_usemdata = true; +- ps_root_readerrorcb(pc); ++ ps_root_readerrorcb(&pc); + +- if (pc->psr_error.psr_datalen != 0) { +- if (pc->psr_error.psr_datalen > pc->psr_mdatalen) { +- errno = EINVAL; +- return -1; +- } +- d = malloc(pc->psr_error.psr_datalen); +- if (d == NULL) +- return -1; +- memcpy(d, pc->psr_mdata, pc->psr_error.psr_datalen); +- } else +- d = NULL; +- +- errno = pc->psr_error.psr_errno; +- *data = d; +- *len = pc->psr_error.psr_datalen; +- return pc->psr_error.psr_result; ++ errno = pc.psr_error.psr_errno; ++ *data = pc.psr_data; ++ *len = pc.psr_error.psr_datalen; ++ return pc.psr_error.psr_result; + } + + static ssize_t +@@ -196,6 +198,8 @@ ps_root_writeerror(struct dhcpcd_ctx *ctx, ssize_t res + logdebugx("%s: result %zd errno %d", __func__, result, errno); + #endif + ++ if (len == 0) ++ msg.msg_iovlen = 1; + err = sendmsg(fd, &msg, MSG_EOR); + + /* Error sending the message? Try sending the error of sending. */ +@@ -204,8 +208,8 @@ ps_root_writeerror(struct dhcpcd_ctx *ctx, ssize_t res + __func__, result, data, len); + psr.psr_result = err; + psr.psr_errno = errno; +- iov[1].iov_base = NULL; +- iov[1].iov_len = 0; ++ psr.psr_datalen = 0; ++ msg.msg_iovlen = 1; + err = sendmsg(fd, &msg, MSG_EOR); + } + +@@ -602,7 +606,7 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, st + break; + } + +- err = ps_root_writeerror(ctx, err, rlen != 0 ? rdata : 0, rlen); ++ err = ps_root_writeerror(ctx, err, rdata, rlen); + if (free_rdata) + free(rdata); + return err; +@@ -843,17 +847,6 @@ ps_root_log(void *arg, unsigned short events) + logerr(__func__); + } + +-static void +-ps_root_freepsdata(void *arg) +-{ +- struct psr_ctx *pc = arg; +- +- if (pc == NULL) +- return; +- free(pc->psr_mdata); +- free(pc); +-} +- + pid_t + ps_root_start(struct dhcpcd_ctx *ctx) + { +@@ -864,7 +857,6 @@ ps_root_start(struct dhcpcd_ctx *ctx) + struct ps_process *psp; + int logfd[2] = { -1, -1}, datafd[2] = { -1, -1}; + pid_t pid; +- struct psr_ctx *pc; + + if (xsocketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CXNB, 0, logfd) == -1) + return -1; +@@ -883,27 +875,15 @@ ps_root_start(struct dhcpcd_ctx *ctx) + return -1; + #endif + +- pc = calloc(1, sizeof(*pc)); +- if (pc == NULL) +- return -1; +- pc->psr_ctx = ctx; +- + psp = ctx->ps_root = ps_newprocess(ctx, &id); + if (psp == NULL) +- { +- free(pc); + return -1; +- } +- psp->psp_freedata = ps_root_freepsdata; ++ + strlcpy(psp->psp_name, "privileged proxy", sizeof(psp->psp_name)); + pid = ps_startprocess(psp, ps_root_recvmsg, NULL, + ps_root_startcb, PSF_ELOOP); +- if (pid == -1) { +- free(pc); ++ if (pid == -1) + return -1; +- } +- +- psp->psp_data = pc; + + if (pid == 0) { + ctx->ps_log_fd = logfd[0]; /* Keep open to pass to processes */ Index: patches/patch-src_privsep_c =================================================================== RCS file: patches/patch-src_privsep_c diff -N patches/patch-src_privsep_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_privsep_c 28 Dec 2025 14:39:02 -0000 @@ -0,0 +1,17 @@ +https://patch-diff.githubusercontent.com/raw/NetworkConfiguration/dhcpcd/pull/556.patch + +Index: src/privsep.c +--- src/privsep.c.orig ++++ src/privsep.c +@@ -761,11 +761,6 @@ ps_freeprocess(struct ps_process *psp) + + TAILQ_REMOVE(&ctx->ps_processes, psp, next); + +- if (psp->psp_freedata != NULL) +- psp->psp_freedata(psp->psp_data); +- else +- free(psp->psp_data); +- + if (psp->psp_fd != -1) { + eloop_event_delete(ctx->eloop, psp->psp_fd); + close(psp->psp_fd); Index: patches/patch-src_privsep_h =================================================================== RCS file: patches/patch-src_privsep_h diff -N patches/patch-src_privsep_h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_privsep_h 28 Dec 2025 14:39:02 -0000 @@ -0,0 +1,14 @@ +https://patch-diff.githubusercontent.com/raw/NetworkConfiguration/dhcpcd/pull/556.patch + +Index: src/privsep.h +--- src/privsep.h.orig ++++ src/privsep.h +@@ -184,8 +184,6 @@ struct ps_process { + char psp_name[PSP_NAMESIZE]; + uint16_t psp_proto; + const char *psp_protostr; +- void *psp_data; +- void (*psp_freedata)(void *); + bool psp_started; + + #ifdef INET
