From 4c10010010ec7859d022bc32b94db2ebb2136696 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 21:13:27 +0100 Subject: [PATCH 01/30] Add support for Darwin / macOS SOCK_SEQPACKET is not supported for socketpair, so use SOCK_STREAM. Rename svc_* to srv_* so we don't conflict with svc_run RPC command. Detect setproctitle and supply compat for reallocarray. Fixes #1. --- .gitignore | 3 +- config-null.mk | 2 - configure | 54 +++++++++++----- src/common.c | 74 +++++++++++++++++---- src/common.h | 1 + src/dhcpsd.c | 11 ++-- src/dhcpsd.h | 4 +- src/eloop.c | 8 ++- src/if.c | 18 ++---- src/plugin.h | 4 +- src/plugins/Makefile | 17 ++--- src/plugins/ethers.c | 9 ++- src/plugins/lua.c | 38 +++++------ src/service.c | 149 +++++++++++++++++++++++-------------------- src/service.h | 34 +++++----- src/unpriv.c | 16 ++--- src/unpriv.h | 6 +- 17 files changed, 263 insertions(+), 185 deletions(-) diff --git a/.gitignore b/.gitignore index 00e80ba..31198e4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,9 @@ config.mk config.h config.log +*.dSYM/** *.o -*.So +*.soo *.so *.tar.xz diff --git a/config-null.mk b/config-null.mk index c7a8de3..6bf701d 100644 --- a/config-null.mk +++ b/config-null.mk @@ -1,3 +1 @@ # This space left intentionally blank - -DHCPCD_SRCS+= dhcpcd-embedded.c diff --git a/configure b/configure index 9f1e879..a1a3216 100755 --- a/configure +++ b/configure @@ -327,13 +327,16 @@ EOF else echo "no" fi - rm -rf _test.c _test + rm -rf _test.* _test fi else echo "CPPFLAGS+= -DNDEBUG" >>$CONFIG_MK fi case "$OS" in +darwin*) + echo "LDFLAGS_SO+= -Wl,-undefined,dynamic_lookup" >>$CONFIG_MK + ;; freebsd*|kfreebsd*) # FreeBSD hide some newer POSIX APIs behind _GNU_SOURCE ... echo "CPPFLAGS+= -D_GNU_SOURCE" >>$CONFIG_MK @@ -381,7 +384,7 @@ _CC=false if $XCC _test.c -o _test >/dev/null 2>&3; then [ -x _test ] && _CC=true fi -rm -f _test.c _test +rm -rf _test.* _test if ! $_CC; then echo $XCC echo "$CC does not create executables" >&2 @@ -394,8 +397,7 @@ $CC --version | $SED -e '1!d' if [ -z "$DHCPSD_USER" ]; then printf "Detecting a suitable user for dhcpsd ... " for x in _dhcpsd dhcpsd _dhcpd dhcpd; do - home=$(getent passwd $x 2>/dev/null | cut -d: -f6) - if [ -d "$home" ]; then + if id "$x" >/dev/null 2>&1; then DHCPSD_USER="$x" echo "$DHCPSD_USER" break @@ -430,7 +432,7 @@ if $XCC _capsicum.c -o _capsicum -lcasper -lcap_net 2>&3; then else echo "no" fi - rm -f _capsicum.c _capsicum + rm -rf _capsicum.* _capsicum fi if [ -z "$SANDBOX" ]; then @@ -448,7 +450,7 @@ EOF else echo "no" fi - rm -f _pledge.c _pledge + rm -rf _pledge.* _pledge fi abort=false @@ -474,7 +476,7 @@ else echo "libc support for getifaddrs is required - aborting" >&2 abort=true fi -rm -f _getifaddrs.c _getifaddrs +rm -rf _getifaddrs.* _getifaddrs $abort && exit 1 printf "Testing for clock_gettime ... " @@ -495,7 +497,7 @@ else echo "libc support for clock_getttime is required - aborting" >&2 abort=true fi -rm -f _clock_gettime.c _clock_gettime +rm -rf _clock_gettime.* _clock_gettime $abort && exit 1 if [ -z "$ARC4RANDOM" ]; then @@ -512,7 +514,7 @@ EOF ARC4RANDOM=no fi echo "$ARC4RANDOM" - rm -f _arc4random.c _arc4random + rm -rf _arc4random.* _arc4random fi if [ "$ARC4RANDOM" = no ]; then echo "COMPAT_SRCS+= compat/arc4random.c" >>$CONFIG_MK @@ -536,7 +538,7 @@ EOF fi echo "$CLOSEFROM" fi -rm -f _closefrom.c _closefrom +rm -rf _closefrom.* _closefrom if [ "$CLOSEFROM" = no ]; then echo "COMPAT_SRCS+= compat/closefrom.c" >>$CONFIG_MK echo "#include \"compat/closefrom.h\"" >>$CONFIG_H @@ -561,7 +563,7 @@ echo "$IOCTL_REQ" if [ "$IOCTL_REQ" != "unsigned long" ]; then echo "#define IOCTL_REQUEST_TYPE $IOCTL_REQ" >>$CONFIG_H fi -rm -f _ioctl.c _ioctl +rm -rf _ioctl.* _ioctl printf "Testing for inet_ntoa ... " cat <_inet_ntoa.c @@ -586,9 +588,31 @@ else echo "libc support for inet_ntoa is required - aborting" >&2 abort=true fi -rm -f _inet_ntoa.c _inet_ntoa +rm -rf _inet_ntoa.* _inet_ntoa $abort && exit 1 +if [ -z "$SETPROCTITLE" ]; then + printf "Testing for setproctitle ... " + cat << EOF >_setproctitle.c +#include +#include +int main(void) { + setproctitle("foo"); + return 0; +} +EOF + if $XCC _setproctitle.c -o _setproctitle 2>&3; then + SETPROCTITLE=yes + else + SETPROCTITLE=no + fi + echo "$SETPROCTITLE" + rm -rf _setproctitle.* _setproctitle +fi +if [ "$SETPROCTITLE" != no ]; then + echo "#define HAVE_SETPROCTITLE" >>$CONFIG_H +fi + if [ -z "$STRLCPY" ]; then printf "Testing for strlcpy ... " cat <_strlcpy.c @@ -605,7 +629,7 @@ EOF STRLCPY=no fi echo "$STRLCPY" - rm -f _strlcpy.c _strlcpy + rm -rf _strlcpy.* _strlcpy fi if [ "$STRLCPY" = no ]; then echo "COMPAT_SRCS+= compat/strlcpy.c" >>$CONFIG_MK @@ -629,7 +653,7 @@ EOF RBTREE=no fi echo "$RBTREE" - rm -f _rbtree.c _rbtree + rm -rf _rbtree.* _rbtree fi if [ "$RBTREE" = no ]; then echo "VENDOR_SRCS+= vendor/rbtree.c" >>$CONFIG_MK @@ -659,7 +683,7 @@ EOF REALLOCARRAY=no fi echo "$REALLOCARRAY" - rm -f _reallocarray.c _reallocarray + rm -rf _reallocarray.* _reallocarray fi if [ "$REALLOCARRAY" = no ]; then echo "COMPAT_SRCS+= compat/reallocarray.c" >>$CONFIG_MK diff --git a/src/common.c b/src/common.c index 3848d58..bafc032 100644 --- a/src/common.c +++ b/src/common.c @@ -461,12 +461,40 @@ sa_pton(struct sockaddr *sa, const char *src) return inet_pton(sa->sa_family, src, addr); } +#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) +static int +xsetfd(int fd, int flags) +{ + int xflags, oflags; + + oflags = fcntl(fd, F_GETFD); + if (oflags == -1) + return -1; + + xflags = oflags; + +#ifndef HAVE_SOCK_CLOEXEC + if (flags & SOCK_CLOEXEC) + xflags |= FD_CLOEXEC; +#endif +#ifndef HAVE_SOCK_NONBLOCK + if (flags & SOCK_NONBLOCK) + xflags |= O_NONBLOCK; +#endif + + if (xflags == oflags) + return 0; + + return fcntl(fd, F_SETFD, xflags); +} +#endif + int xsocket(int domain, int type, int protocol) { int s; #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) - int xflags, xtype = type; + int xtype = type; #endif #ifndef HAVE_SOCK_CLOEXEC @@ -481,24 +509,44 @@ xsocket(int domain, int type, int protocol) if ((s = socket(domain, type, protocol)) == -1) return -1; +#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) + if (xtype != type && xsetfd(s, xtype) == -1) { + close(s); + return -1; + } +#endif + + return s; +} + +int +xsocketpair(int domain, int type, int protocol, int fdset[2]) +{ + int s; +#if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) + int xtype = type; +#endif + #ifndef HAVE_SOCK_CLOEXEC - if ((xtype & SOCK_CLOEXEC) && - ((xflags = fcntl(s, F_GETFD)) == -1 || - fcntl(s, F_SETFD, xflags | FD_CLOEXEC) == -1)) - goto out; + if (xtype & SOCK_CLOEXEC) + type &= ~SOCK_CLOEXEC; #endif #ifndef HAVE_SOCK_NONBLOCK - if ((xtype & SOCK_NONBLOCK) && - ((xflags = fcntl(s, F_GETFL)) == -1 || - fcntl(s, F_SETFL, xflags | O_NONBLOCK) == -1)) - goto out; + if (xtype & SOCK_NONBLOCK) + type &= ~SOCK_NONBLOCK; #endif - return s; + if ((s = socketpair(domain, type, protocol, fdset)) == -1) + return -1; #if !defined(HAVE_SOCK_CLOEXEC) || !defined(HAVE_SOCK_NONBLOCK) -out: - close(s); - return -1; + if (xtype != type && + (xsetfd(fdset[0], xtype) == -1 || xsetfd(fdset[1], xtype) == -1)) { + close(fdset[0]); + close(fdset[1]); + return -1; + } #endif + + return s; } diff --git a/src/common.h b/src/common.h index 7514fd6..f500dc0 100644 --- a/src/common.h +++ b/src/common.h @@ -134,4 +134,5 @@ hash_fnv1a(const void *key, size_t len) #define SOCK_CXNB SOCK_CLOEXEC | SOCK_NONBLOCK #endif int xsocket(int, int, int); +int xsocketpair(int, int, int, int[2]); #endif diff --git a/src/dhcpsd.c b/src/dhcpsd.c index e5b425f..9feecc0 100644 --- a/src/dhcpsd.c +++ b/src/dhcpsd.c @@ -129,7 +129,7 @@ dhcpsd_dropperms(int do_chroot) UNUSED(do_chroot); #endif - if (initgroups(DHCPSD_USER, pw->pw_gid) == -1 || + if (initgroups(DHCPSD_USER, (int)pw->pw_gid) == -1 || setgid(pw->pw_gid) == -1 || setuid(pw->pw_uid) == -1) { logerr("%s: error dropping privileges", __func__); return -1; @@ -197,8 +197,7 @@ dhcpsd_fork(struct ctx *ctx) cap_rights_t rights; #endif - if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, - 0, fork_fd) == -1) { + if (xsocketpair(PF_LOCAL, SOCK_STREAM | SOCK_CXNB, 0, fork_fd) == -1) { logerr("socketpair"); return -1; } @@ -250,7 +249,7 @@ dhcpsd_fork(struct ctx *ctx) } break; default: -#ifdef BSD +#ifdef HAVE_SETPROCTITLE setproctitle("[launcher]"); #endif ctx->ctx_options &= ~DHCPSD_MAIN; @@ -489,7 +488,7 @@ main(int argc, char **argv) if (dhcpsd_dropperms(1) == -1) goto exit; -#ifdef BSD +#ifdef HAVE_SETPROCTITLE setproctitle("DHCP Server Daemon"); #endif @@ -606,7 +605,7 @@ main(int argc, char **argv) dhcp_free(ctx.ctx_dhcp); eloop_free(ctx.ctx_eloop); ctx.ctx_eloop = NULL; - svc_free(ctx.ctx_unpriv); + srv_free(ctx.ctx_unpriv); #ifdef HAVE_CASPER if (ctx.ctx_capnet) cap_close(ctx.ctx_capnet); diff --git a/src/dhcpsd.h b/src/dhcpsd.h index a622b9f..acea3ef 100644 --- a/src/dhcpsd.h +++ b/src/dhcpsd.h @@ -35,7 +35,7 @@ struct ifaddrs; struct dhcp_ctx; struct eloop; struct if_head; -struct svc_ctx; +struct srv_ctx; struct plugin; #ifdef HAVE_CASPER typedef struct cap_channel cap_channel_t; @@ -47,7 +47,7 @@ struct ctx { struct eloop *ctx_eloop; struct if_head *ctx_ifaces; - struct svc_ctx *ctx_unpriv; + struct srv_ctx *ctx_unpriv; struct plugin *ctx_plugins; size_t ctx_nplugins; diff --git a/src/eloop.c b/src/eloop.c index 52dd206..01e2655 100644 --- a/src/eloop.c +++ b/src/eloop.c @@ -36,7 +36,7 @@ * On Linux use epoll(7) * Everywhere else use ppoll(2) */ -#ifdef BSD +#if defined(BSD) || defined(__APPLE__) #include #define USE_KQUEUE #if defined(__NetBSD__) @@ -625,6 +625,8 @@ eloop_open(struct eloop *eloop) fd = kqueue1(O_CLOEXEC); #elif defined(KQUEUE_CLOEXEC) fd = kqueuex(KQUEUE_CLOEXEC); +#elif defined(USE_KQUEUE) && defined(__APPLE__) + fd = kqueue(); #elif defined(USE_KQUEUE) int flags; @@ -871,7 +873,7 @@ eloop_waitfd(int fd) struct pollfd pfd = { .fd = fd, .events = POLLIN }; int err; - err = ppoll(&pfd, 1, NULL, NULL); + err = poll(&pfd, 1, -1); if (err == -1 || err == 0) return err; @@ -1092,4 +1094,4 @@ eloop_start(struct eloop *eloop) } return eloop->exitcode; -} +} \ No newline at end of file diff --git a/src/if.c b/src/if.c index 6c82950..ed16ecb 100644 --- a/src/if.c +++ b/src/if.c @@ -64,12 +64,12 @@ if_learnifaces(struct ctx *ctx) struct ifaddrs *ifa; struct interface *ifp; #ifdef AF_LINK - const struct sockaddr_dl *sdl; + struct sockaddr_dl *sdl; #ifdef IFLR_ACTIVE struct if_laddrreq iflr = { .flags = IFLR_PREFIX }; #endif #elif defined(AF_PACKET) - const struct sockaddr_ll *sll; + struct sockaddr_ll *sll; #endif for (ifa = ctx->ctx_ifa; ifa; ifa = ifa->ifa_next) { @@ -84,7 +84,7 @@ if_learnifaces(struct ctx *ctx) #endif #ifdef IFLR_ACTIVE - sdl = (const void *)ifa->ifa_addr; + sdl = (void *)ifa->ifa_addr; /* We need to check for active address */ strlcpy(iflr.iflr_name, ifa->ifa_name, sizeof(iflr.iflr_name)); @@ -107,7 +107,7 @@ if_learnifaces(struct ctx *ctx) #ifdef AF_LINK #ifndef IFLR_ACTIVE - sdl = (const void *)ifa->ifa_addr; + sdl = (void *)ifa->ifa_addr; #endif switch (sdl->sdl_type) { @@ -150,22 +150,16 @@ if_learnifaces(struct ctx *ctx) } ifp->if_index = sdl->sdl_index; ifp->if_hwlen = sdl->sdl_alen; - if (ifp->if_hwlen != 0) { -#ifdef CLLADDR - memcpy(ifp->if_hwaddr, CLLADDR(sdl), ifp->if_hwlen); -#else + if (ifp->if_hwlen != 0) memcpy(ifp->if_hwaddr, LLADDR(sdl), ifp->if_hwlen); -#endif - } #elif defined(AF_PACKET) - sll = (const void *)ifa->ifa_addr; + sll = (void *)ifa->ifa_addr; ifp->if_index = (unsigned int)sll->sll_ifindex; ifp->if_hwtype = sll->sll_hatype; ifp->if_hwlen = sll->sll_halen; if (ifp->if_hwlen != 0) memcpy(ifp->if_hwaddr, sll->sll_addr, ifp->if_hwlen); #endif - switch (ifp->if_hwtype) { case ARPHRD_ETHER: ifp->if_output = if_ether_output; diff --git a/src/plugin.h b/src/plugin.h index 3966945..550a2ae 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -33,7 +33,7 @@ struct ctx; struct interface; -struct svc_ctx; +struct srv_ctx; struct bootp; struct dhcp_pool; struct dhcp_lease; @@ -66,7 +66,7 @@ struct plugin { const struct bootp *, size_t, unsigned int *); int (*p_expire_lease)(struct plugin *, const struct dhcp_lease *); int (*p_store_leases)(struct plugin *); - ssize_t (*p_dispatch)(struct plugin *, struct svc_ctx *, unsigned int, + ssize_t (*p_dispatch)(struct plugin *, struct srv_ctx *, unsigned int, const void *, size_t); int p_unpriv; }; diff --git a/src/plugins/Makefile b/src/plugins/Makefile index 0c0fe9b..393b252 100644 --- a/src/plugins/Makefile +++ b/src/plugins/Makefile @@ -25,13 +25,14 @@ MAN8+= ${LUA_MAN8} CLEANFILES+= ${OBJS} ${SOBJS} ${PLUGS} CLEANFILES+= dhcpsd_leasefile.8 ${LUA_MAN8} -.SUFFIXES: .So .so .in +.SUFFIXES: .soo .so .in +.INTERMEDIATE: icmp.soo lua.soo -.c.So: +.c.soo: ${CC} ${PICFLAG} -DPIC ${CFLAGS} ${CDBGFLAGS} ${CPPFLAGS} -c $< -o $@ -.So.so: - ${CC} ${LDFLAGS} -shared -Wl,-x -o $@ -Wl,-soname,$@ $< ${LIBS} +.soo.so: + ${CC} ${LDFLAGS} ${LDFLAGS_SO} -shared -Wl,-x -o $@ $< ${LIBS} .in: ${SED} ${SED_CONFDIR} ${SED_DBDIR} ${SED_PLUGINDIR} $< > $@ @@ -39,14 +40,14 @@ CLEANFILES+= dhcpsd_leasefile.8 ${LUA_MAN8} all: ${PLUGS} ${MAN8} # verstable.h has a few compiler warnings so we hide it away -icmp.So: +icmp.soo: icmp.c ${CC} ${PICFLAG} -DPIC ${CFLAGS} ${CPPFLAGS} ${VERSTABLE_CFLAGS} -c icmp.c -o $@ -lua.So: +lua.soo: lua.c ${CC} ${PICFLAG} -DPIC ${CFLAGS} ${CDBGFLAGS} ${LUA_CFLAGS} ${CPPFLAGS} -c lua.c -o $@ -lua.so: lua.So - ${CC} ${LDFLAGS} -shared -Wl,-x -o $@ -Wl,-soname,$@ lua.So ${LUA_LIBS} +lua.so: lua.soo + ${CC} ${LDFLAGS} ${LDFLAGS_SO} -shared -Wl,-x -o $@ lua.soo ${LUA_LIBS} lint: _lint diff --git a/src/plugins/ethers.c b/src/plugins/ethers.c index 478f8c7..be6af3f 100644 --- a/src/plugins/ethers.c +++ b/src/plugins/ethers.c @@ -49,7 +49,6 @@ #include "common.h" #include "dhcp.h" #include "dhcpsd.h" -#include "logerr.h" #include "plugin.h" #include "service.h" @@ -60,7 +59,7 @@ static const char ethers_description[] = #define E_LOOKUPHOSTNAME 1U static ssize_t -ethers_run_lookup_hostname(struct plugin *p, struct svc_ctx *sctx, +ethers_run_lookup_hostname(struct plugin *p, struct srv_ctx *sctx, const void *data, size_t datalen) { struct ether_addr *ether_addr = (struct ether_addr *)UNCONST(data); @@ -82,11 +81,11 @@ ethers_run_lookup_hostname(struct plugin *p, struct svc_ctx *sctx, hnamelen = strlen(hname) + 1; out: - return svc_send(sctx, p, E_LOOKUPHOSTNAME, err, hname, hnamelen); + return srv_send(sctx, p, E_LOOKUPHOSTNAME, err, hname, hnamelen); } static ssize_t -ethers_dispatch(struct plugin *p, struct svc_ctx *sctx, unsigned int cmd, +ethers_dispatch(struct plugin *p, struct srv_ctx *sctx, unsigned int cmd, const void *data, size_t len) { switch (cmd) { @@ -113,7 +112,7 @@ ethers_lookup_hostname(struct plugin *p, char *hostname, } memcpy(&ea, bootp->chaddr, sizeof(ea)); - err = svc_run(p->p_ctx->ctx_unpriv, p, E_LOOKUPHOSTNAME, &ea, + err = srv_run(p->p_ctx->ctx_unpriv, p, E_LOOKUPHOSTNAME, &ea, sizeof(ea), &result, &hname, &hnamelen); if (err == -1 || result != 0) return -1; diff --git a/src/plugins/lua.c b/src/plugins/lua.c index 210d02c..9bb4e97 100644 --- a/src/plugins/lua.c +++ b/src/plugins/lua.c @@ -84,7 +84,7 @@ static struct lua_ctx lua_ctx; #define L_EXPIRELEASE 6U static ssize_t -lua_run_configure_pools(struct plugin *p, struct svc_ctx *sctx, +lua_run_configure_pools(struct plugin *p, struct srv_ctx *sctx, const char *ifname, size_t ifnamelen) { struct lua_ctx *l = p->p_pctx; @@ -222,14 +222,14 @@ lua_run_configure_pools(struct plugin *p, struct svc_ctx *sctx, err = (ssize_t)npools; out: - err = svc_send(sctx, p, L_CONFIGUREPOOLS, err, pools, + err = srv_send(sctx, p, L_CONFIGUREPOOLS, err, pools, sizeof(*pool) * npools); free(pools); return err; } static ssize_t -lua_run_lookup_hostname(struct plugin *p, struct svc_ctx *sctx, +lua_run_lookup_hostname(struct plugin *p, struct srv_ctx *sctx, const void *data, size_t len) { ssize_t err = -1; @@ -270,11 +270,11 @@ lua_run_lookup_hostname(struct plugin *p, struct svc_ctx *sctx, err = 0; out: - return svc_send(sctx, p, L_LOOKUPADDR, err, hname, hnamelen); + return srv_send(sctx, p, L_LOOKUPADDR, err, hname, hnamelen); } static ssize_t -lua_run_lookup_addr(struct plugin *p, struct svc_ctx *sctx, const void *data, +lua_run_lookup_addr(struct plugin *p, struct srv_ctx *sctx, const void *data, size_t len) { ssize_t err = -1; @@ -347,7 +347,7 @@ lua_run_lookup_addr(struct plugin *p, struct svc_ctx *sctx, const void *data, err = 0; out: - return svc_sendv(sctx, p, L_LOOKUPADDR, err, iov, ARRAYCOUNT(iov)); + return srv_sendv(sctx, p, L_LOOKUPADDR, err, iov, ARRAYCOUNT(iov)); } static int @@ -613,7 +613,7 @@ lua_add_dhcp_domain(lua_State *L) } static ssize_t -lua_run_add_dhcp_options(struct plugin *p, struct svc_ctx *sctx, +lua_run_add_dhcp_options(struct plugin *p, struct srv_ctx *sctx, const void *dhcp, size_t dhcplen) { struct lua_ctx *l = p->p_pctx; @@ -655,13 +655,13 @@ lua_run_add_dhcp_options(struct plugin *p, struct svc_ctx *sctx, ldo->ldo_optslen = (size_t)(l->l_p - ldo->ldo_opts); out: - return svc_send(sctx, p, L_ADDDHCPOPTIONS, err, &l->l_dhcp, + return srv_send(sctx, p, L_ADDDHCPOPTIONS, err, &l->l_dhcp, offsetof(struct lua_dhcp_opts, ldo_optslen) + sizeof(l->l_dhcp.ldo_optslen) + l->l_dhcp.ldo_optslen); } static ssize_t -lua_run_expire_lease(struct plugin *p, struct svc_ctx *sctx, +lua_run_expire_lease(struct plugin *p, struct srv_ctx *sctx, const void *payload, size_t payloadlen) { const struct dhcp_lease *dl = payload; @@ -712,11 +712,11 @@ lua_run_expire_lease(struct plugin *p, struct svc_ctx *sctx, err = (ssize_t)lua_tointeger(L, -1); out: - return svc_send(sctx, p, L_EXPIRELEASE, err, NULL, 0); + return srv_send(sctx, p, L_EXPIRELEASE, err, NULL, 0); } static ssize_t -lua_run_commit_lease(struct plugin *p, struct svc_ctx *sctx, +lua_run_commit_lease(struct plugin *p, struct srv_ctx *sctx, const void *payload, size_t payloadlen) { struct dhcp_lease dl; @@ -796,7 +796,7 @@ lua_run_commit_lease(struct plugin *p, struct svc_ctx *sctx, err = (ssize_t)lua_tointeger(L, -1); out: - return svc_send(sctx, p, L_COMMITLEASE, err, &f, sizeof(f)); + return srv_send(sctx, p, L_COMMITLEASE, err, &f, sizeof(f)); } static int @@ -880,7 +880,7 @@ lua_lookup_hostname(struct plugin *p, char *hostname, const struct bootp *bootp, void *hname; size_t hnamelen; - err = svc_run(p->p_ctx->ctx_unpriv, p, L_LOOKUPHOSTNAME, bootp, + err = srv_run(p->p_ctx->ctx_unpriv, p, L_LOOKUPHOSTNAME, bootp, bootplen, &result, &hname, &hnamelen); if (err == -1 || result == -1) @@ -913,7 +913,7 @@ lua_lookup_addr(struct plugin *p, struct sockaddr *sa, uint32_t *ltime, if (hostname != NULL) strlcpy(hname, hostname, sizeof(hname)); - err = svc_runv(p->p_ctx->ctx_unpriv, p, L_LOOKUPADDR, iov, + err = srv_runv(p->p_ctx->ctx_unpriv, p, L_LOOKUPADDR, iov, ARRAYCOUNT(iov), &result, &data, &len); if (err == -1 || result == -1) @@ -937,7 +937,7 @@ lua_configure_pools(struct plugin *p, struct interface *ifp) size_t poolslen, npools; struct dhcp_pool *pool; - err = svc_run(p->p_ctx->ctx_unpriv, p, L_CONFIGUREPOOLS, ifp->if_name, + err = srv_run(p->p_ctx->ctx_unpriv, p, L_CONFIGUREPOOLS, ifp->if_name, strlen(ifp->if_name) + 1, &result, &_pools, &poolslen); if (err == -1 || result == -1) return -1; @@ -966,7 +966,7 @@ lua_add_dhcp_options(struct plugin *plug, struct bootp *bootp, uint8_t **p, size_t optslen; struct lua_dhcp_opts *ldo; - err = svc_run(plug->p_ctx->ctx_unpriv, plug, L_ADDDHCPOPTIONS, req, + err = srv_run(plug->p_ctx->ctx_unpriv, plug, L_ADDDHCPOPTIONS, req, reqlen, &result, &opts, &optslen); if (err == -1 || result == -1) return -1; @@ -1006,7 +1006,7 @@ lua_commit_lease(struct plugin *p, const struct dhcp_lease *lease, unsigned int *f = NULL; size_t flen; - err = svc_runv(p->p_ctx->ctx_unpriv, p, L_COMMITLEASE, iov, + err = srv_runv(p->p_ctx->ctx_unpriv, p, L_COMMITLEASE, iov, ARRAYCOUNT(iov), &result, (void *)&f, &flen); if (err == -1) return -1; @@ -1020,7 +1020,7 @@ lua_expire_lease(struct plugin *p, const struct dhcp_lease *lease) { ssize_t err, result; - err = svc_run(p->p_ctx->ctx_unpriv, p, L_EXPIRELEASE, lease, + err = srv_run(p->p_ctx->ctx_unpriv, p, L_EXPIRELEASE, lease, sizeof(*lease), &result, NULL, NULL); if (err == -1) return -1; @@ -1028,7 +1028,7 @@ lua_expire_lease(struct plugin *p, const struct dhcp_lease *lease) } static ssize_t -lua_dispatch(struct plugin *p, struct svc_ctx *sctx, unsigned int cmd, +lua_dispatch(struct plugin *p, struct srv_ctx *sctx, unsigned int cmd, const void *data, size_t len) { switch (cmd) { diff --git a/src/service.c b/src/service.c index 2e3f0f9..fb38e08 100644 --- a/src/service.c +++ b/src/service.c @@ -43,7 +43,7 @@ #include "logerr.h" #include "service.h" -struct svc_cmd { +struct srv_cmd { uintptr_t sc_plugin; unsigned int sc_cmd; int sc_errno; @@ -52,24 +52,23 @@ struct svc_cmd { }; static void -svc_recv(void *arg, unsigned short e) +srv_recv(void *arg, unsigned short e) { - struct svc_ctx *sctx = arg; - struct svc_result *sr = &sctx->svc_result; - struct svc_cmd cmd; + struct srv_ctx *sctx = arg; + struct srv_result *sr = &sctx->srv_result; + struct srv_cmd cmd; struct iovec iov[] = { { .iov_base = &cmd, .iov_len = sizeof(cmd), }, - { .iov_base = NULL, .iov_len = 0 }, }; struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1 }; ssize_t nread; if (e & ELE_HANGUP) { hangup: - eloop_exit(sctx->svc_ctx->ctx_eloop, EXIT_SUCCESS); + eloop_exit(sctx->srv_ctx->ctx_eloop, EXIT_SUCCESS); return; } if (e != ELE_READ) { @@ -77,7 +76,7 @@ svc_recv(void *arg, unsigned short e) return; } - nread = recvmsg(sctx->svc_fd, &msg, MSG_WAITALL | MSG_PEEK); + nread = recvmsg(sctx->srv_fd, &msg, MSG_WAITALL); if (nread == 0) goto hangup; if (nread == -1) { @@ -89,48 +88,49 @@ svc_recv(void *arg, unsigned short e) return; } - if (sctx->svc_buflen < cmd.sc_datalen) { - void *nbuf = realloc(sctx->svc_buf, cmd.sc_datalen); - if (nbuf == NULL) { - logerr("%s: realloc", __func__); - return; + if (cmd.sc_datalen != 0) { + if (sctx->srv_buflen < cmd.sc_datalen) { + void *nbuf = realloc(sctx->srv_buf, cmd.sc_datalen); + if (nbuf == NULL) { + logerr("%s: realloc", __func__); + return; + } + sctx->srv_buf = nbuf; + sctx->srv_buflen = cmd.sc_datalen; } - sctx->svc_buf = nbuf; - sctx->svc_buflen = cmd.sc_datalen; - } - iov[1].iov_base = sctx->svc_buf; - iov[1].iov_len = sctx->svc_buflen; - msg.msg_iovlen = 2; + iov[0].iov_base = sctx->srv_buf; + iov[0].iov_len = cmd.sc_datalen; - sr->sr_result = cmd.sc_result; - sr->sr_errno = cmd.sc_errno; + sr->sr_result = cmd.sc_result; + sr->sr_errno = cmd.sc_errno; - nread = recvmsg(sctx->svc_fd, &msg, 0); - if (nread == -1) { - logerr("%s: recvmsg cmd", __func__); - return; - } - if ((size_t)nread != sizeof(cmd) + cmd.sc_datalen) { - logerrx("%s: read datalen mismatch: %zd != %zd", __func__, - nread, sizeof(cmd) + cmd.sc_datalen); - return; + nread = recvmsg(sctx->srv_fd, &msg, MSG_WAITALL); + if (nread == -1) { + logerr("%s: recvmsg cmd", __func__); + return; + } + if ((size_t)nread != cmd.sc_datalen) { + logerrx("%s: read datalen mismatch: %zd != %zd", + __func__, nread, sizeof(cmd) + cmd.sc_datalen); + return; + } } sr->sr_datalen = cmd.sc_datalen; - sr->sr_data = sr->sr_datalen != 0 ? sctx->svc_buf : NULL; + sr->sr_data = sr->sr_datalen != 0 ? sctx->srv_buf : NULL; /* We are either a dispatcher for the helper, or a blocking loop for a * response */ - if (sctx->svc_dispatch != NULL) - sctx->svc_dispatch(sctx, (struct plugin *)cmd.sc_plugin, - cmd.sc_cmd, sctx->svc_buf, cmd.sc_datalen); + if (sctx->srv_dispatch != NULL) + sctx->srv_dispatch(sctx, (struct plugin *)cmd.sc_plugin, + cmd.sc_cmd, sctx->srv_buf, cmd.sc_datalen); } ssize_t -svc_sendv(struct svc_ctx *sctx, struct plugin *p, unsigned int cmd, +srv_sendv(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, ssize_t result, struct iovec *iov, int iovlen) { - struct svc_cmd sc = { + struct srv_cmd sc = { .sc_plugin = (uintptr_t)p, .sc_cmd = cmd, .sc_result = result, @@ -160,37 +160,37 @@ svc_sendv(struct svc_ctx *sctx, struct plugin *p, unsigned int cmd, sc.sc_datalen += iov[i].iov_len; } - ssize_t err = sendmsg(sctx->svc_fd, &msg, MSG_EOR); + ssize_t err = sendmsg(sctx->srv_fd, &msg, 0); return err; } ssize_t -svc_send(struct svc_ctx *sctx, struct plugin *p, unsigned int cmd, +srv_send(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, ssize_t result, const void *data, size_t len) { struct iovec iov[] = { { .iov_base = UNCONST(data), .iov_len = len }, }; - return svc_sendv(sctx, p, cmd, result, iov, len == 0 ? 0 : 1); + return srv_sendv(sctx, p, cmd, result, iov, len == 0 ? 0 : 1); } int -svc_runv(struct svc_ctx *sctx, struct plugin *p, unsigned int cmd, +srv_runv(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, struct iovec *iov, int iovlen, ssize_t *res, void **rdata, size_t *rlen) { - struct svc_result *result = &sctx->svc_result; + struct srv_result *result = &sctx->srv_result; int events; - if (svc_sendv(sctx, p, cmd, 0, iov, iovlen) == -1) { - logerr("%s: svc_write", __func__); + if (srv_sendv(sctx, p, cmd, 0, iov, iovlen) == -1) { + logerr("%s: srv_write", __func__); return -1; } - events = eloop_waitfd(sctx->svc_fd); + events = eloop_waitfd(sctx->srv_fd); if (events == -1) return -1; - svc_recv(sctx, (unsigned short)events); + srv_recv(sctx, (unsigned short)events); if (result->sr_result == -1) errno = result->sr_errno; @@ -204,22 +204,34 @@ svc_runv(struct svc_ctx *sctx, struct plugin *p, unsigned int cmd, } int -svc_run(struct svc_ctx *sctx, struct plugin *p, unsigned int cmd, +srv_run(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, const void *data, size_t len, ssize_t *res, void **rdata, size_t *rlen) { struct iovec iov[] = { { .iov_base = UNCONST(data), .iov_len = len }, }; - return svc_runv(sctx, p, cmd, iov, len == 0 ? 0 : 1, res, rdata, rlen); + return srv_runv(sctx, p, cmd, iov, len == 0 ? 0 : 1, res, rdata, rlen); } -struct svc_ctx * -svc_init(struct ctx *ctx, const char *name, - ssize_t (*dispatch)(struct svc_ctx *, struct plugin *, unsigned int, +int +svc_run(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, + const void *data, size_t len, ssize_t *res, void **rdata, size_t *rlen) +{ + struct iovec iov[] = { + { .iov_base = UNCONST(data), .iov_len = len }, + }; + + loginfo("SVC RUN"); + return srv_runv(sctx, p, cmd, iov, len == 0 ? 0 : 1, res, rdata, rlen); +} + +struct srv_ctx * +srv_init(struct ctx *ctx, const char *name, + ssize_t (*dispatch)(struct srv_ctx *, struct plugin *, unsigned int, const void *, size_t)) { - struct svc_ctx *sctx; + struct srv_ctx *sctx; int fdset[2], fd; pid_t pid; unsigned int logopts; @@ -230,19 +242,18 @@ svc_init(struct ctx *ctx, const char *name, return NULL; } - sctx->svc_ctx = ctx; - sctx->svc_fd = -1; - sctx->svc_dispatch = NULL; + sctx->srv_ctx = ctx; + sctx->srv_fd = -1; + sctx->srv_dispatch = NULL; - sctx->svc_buflen = 1024; - sctx->svc_buf = malloc(sctx->svc_buflen); - if (sctx->svc_buf == NULL) { + sctx->srv_buflen = 1024; + sctx->srv_buf = malloc(sctx->srv_buflen); + if (sctx->srv_buf == NULL) { logerr("%s: malloc", __func__); goto error; } - if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, - 0, fdset) == -1) { + if (xsocketpair(PF_LOCAL, SOCK_STREAM | SOCK_CXNB, 0, fdset) == -1) { logerr("%s: socketpair", __func__); goto error; } @@ -251,15 +262,13 @@ svc_init(struct ctx *ctx, const char *name, switch (pid) { case -1: logerr("%s: fork", __func__); - close(fdset[0]); - close(fdset[1]); goto error; case 0: - sctx->svc_fd = fdset[1]; + sctx->srv_fd = fdset[1]; close(fdset[0]); break; default: - sctx->svc_fd = fdset[0]; + sctx->srv_fd = fdset[0]; close(fdset[1]); logdebugx("service: spawned %s on pid %ld", name, (long)pid); return sctx; @@ -267,14 +276,14 @@ svc_init(struct ctx *ctx, const char *name, ctx->ctx_options &= ~DHCPSD_MAIN; ctx->ctx_options |= DHCPSD_UNPRIV | DHCPSD_RUN; - sctx->svc_dispatch = dispatch; + sctx->srv_dispatch = dispatch; if (eloop_forked(ctx->ctx_eloop, ELF_KEEP_SIGNALS) == -1) { logerr("%s: eloop_forked", __func__); goto error; } - if (eloop_event_add(ctx->ctx_eloop, sctx->svc_fd, ELE_READ, svc_recv, + if (eloop_event_add(ctx->ctx_eloop, sctx->srv_fd, ELE_READ, srv_recv, sctx) == -1) { logerr("%s: eloop_event_add", __func__); goto error; @@ -306,18 +315,18 @@ svc_init(struct ctx *ctx, const char *name, return sctx; error: - svc_free(sctx); + srv_free(sctx); return NULL; } void -svc_free(struct svc_ctx *ctx) +srv_free(struct srv_ctx *ctx) { if (ctx == NULL) return; - if (ctx->svc_fd != -1) - close(ctx->svc_fd); - free(ctx->svc_buf); + if (ctx->srv_fd != -1) + close(ctx->srv_fd); + free(ctx->srv_buf); free(ctx); } diff --git a/src/service.h b/src/service.h index 2236e67..6df6307 100644 --- a/src/service.h +++ b/src/service.h @@ -36,35 +36,37 @@ struct plugin; -struct svc_result { +struct srv_result { ssize_t sr_result; int sr_errno; void *sr_data; size_t sr_datalen; }; -struct svc_ctx { - struct ctx *svc_ctx; - int svc_fd; - void *svc_buf; - size_t svc_buflen; - struct svc_result svc_result; - ssize_t (*svc_dispatch)(struct svc_ctx *, struct plugin *, unsigned int, +struct srv_ctx { + struct ctx *srv_ctx; + int srv_fd; + void *srv_buf; + size_t srv_buflen; + struct srv_result srv_result; + ssize_t (*srv_dispatch)(struct srv_ctx *, struct plugin *, unsigned int, const void *, size_t); }; -struct svc_ctx *svc_init(struct ctx *, const char *, - ssize_t (*dispatch)(struct svc_ctx *, struct plugin *, unsigned int, +struct srv_ctx *srv_init(struct ctx *, const char *, + ssize_t (*dispatch)(struct srv_ctx *, struct plugin *, unsigned int, const void *, size_t)); -void svc_free(struct svc_ctx *); -#define svc_dropperms dhcpsd_dropperms -ssize_t svc_send(struct svc_ctx *, struct plugin *, unsigned int, ssize_t, +void srv_free(struct srv_ctx *); +#define srv_dropperms dhcpsd_dropperms +ssize_t srv_send(struct srv_ctx *, struct plugin *, unsigned int, ssize_t, const void *, size_t); -ssize_t svc_sendv(struct svc_ctx *, struct plugin *, unsigned int, ssize_t, +ssize_t srv_sendv(struct srv_ctx *, struct plugin *, unsigned int, ssize_t, struct iovec *, int); -int svc_run(struct svc_ctx *, struct plugin *, unsigned int, const void *, +int srv_run(struct srv_ctx *, struct plugin *, unsigned int, const void *, size_t, ssize_t *, void **, size_t *); -int svc_runv(struct svc_ctx *, struct plugin *, unsigned int, struct iovec *, +int svc_run(struct srv_ctx *, struct plugin *, unsigned int, const void *, + size_t, ssize_t *, void **, size_t *); +int srv_runv(struct srv_ctx *, struct plugin *, unsigned int, struct iovec *, int, ssize_t *, void **, size_t *); #endif diff --git a/src/unpriv.c b/src/unpriv.c index eb51b61..3377dad 100644 --- a/src/unpriv.c +++ b/src/unpriv.c @@ -64,7 +64,7 @@ struct unpriv_getaddrinfo { }; int -unpriv_getaddrinfo(struct svc_ctx *ctx, const char *hostname, +unpriv_getaddrinfo(struct srv_ctx *ctx, const char *hostname, const char *servname, struct addrinfo *hints, struct addrinfo **restrict res) { @@ -94,7 +94,7 @@ unpriv_getaddrinfo(struct svc_ctx *ctx, const char *hostname, u_gai.u_gai_hints.u_ai_protocol = hints->ai_protocol; } - err = svc_run(ctx, 0, U_GETADDRINFO, &u_gai, sizeof(u_gai), &result, + err = srv_run(ctx, 0, U_GETADDRINFO, &u_gai, sizeof(u_gai), &result, &rdata, &rdata_len); if (err == -1) return -1; @@ -155,7 +155,7 @@ unpriv_getaddrinfo(struct svc_ctx *ctx, const char *hostname, } static ssize_t -unpriv_dispatch(struct svc_ctx *sctx, struct plugin *p, unsigned int cmd, +unpriv_dispatch(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, const void *data, size_t len) { const struct unpriv_getaddrinfo *u_gai = data; @@ -227,7 +227,7 @@ unpriv_dispatch(struct svc_ctx *sctx, struct plugin *p, unsigned int cmd, freeaddrinfo(ai_result); - res = svc_send(sctx, NULL, U_GETADDRINFO, err, reply, + res = srv_send(sctx, NULL, U_GETADDRINFO, err, reply, sizeof(*reply) * n); free(reply); return res; @@ -235,15 +235,15 @@ unpriv_dispatch(struct svc_ctx *sctx, struct plugin *p, unsigned int cmd, err: freeaddrinfo(ai_result); free(reply); - return svc_send(sctx, NULL, cmd, err, NULL, 0); + return srv_send(sctx, NULL, cmd, err, NULL, 0); } -struct svc_ctx * +struct srv_ctx * unpriv_init(struct ctx *ctx) { if (ctx->ctx_unpriv != NULL) goto out; - ctx->ctx_unpriv = svc_init(ctx, "unprivileged helper", unpriv_dispatch); + ctx->ctx_unpriv = srv_init(ctx, "unprivileged helper", unpriv_dispatch); if (ctx->ctx_unpriv == NULL) return NULL; @@ -251,7 +251,7 @@ unpriv_init(struct ctx *ctx) if (ctx->ctx_options & DHCPSD_RUN) { ctx->ctx_options |= DHCPSD_UNPRIV; dhcpsd_dropperms(0); -#ifdef BSD +#ifdef HAVE_SETPROCTITLE setproctitle("unprivileged helper"); #endif } diff --git a/src/unpriv.h b/src/unpriv.h index 00cf974..121116d 100644 --- a/src/unpriv.h +++ b/src/unpriv.h @@ -29,11 +29,11 @@ #ifndef UNPRIV_H #define UNPRIV_H -struct svc_ctx; +struct srv_ctx; struct addrinfo; -struct svc_ctx *unpriv_init(struct ctx *); -int unpriv_getaddrinfo(struct svc_ctx *, const char *, const char *, +struct srv_ctx *unpriv_init(struct ctx *); +int unpriv_getaddrinfo(struct srv_ctx *, const char *, const char *, struct addrinfo *, struct addrinfo **restrict); void unpriv_freeaddrinfo(struct addrinfo *); #endif From e920e7fece96b1e978abc905a80a9676fe50c613 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 21:24:41 +0100 Subject: [PATCH 02/30] Add reallocarray --- compat/reallocarray.c | 60 +++++++++++++++++++++++++++++++++++++++++++ compat/reallocarray.h | 39 ++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 compat/reallocarray.c create mode 100644 compat/reallocarray.h diff --git a/compat/reallocarray.c b/compat/reallocarray.c new file mode 100644 index 0000000..9ff9c20 --- /dev/null +++ b/compat/reallocarray.c @@ -0,0 +1,60 @@ +/* $NetBSD: reallocarr.c,v 1.4 2015/08/20 20:08:04 joerg Exp $ */ + +/*- + * Copyright (c) 2015 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +/* + * To be clear, this is NetBSD's more refined reallocarr(3) function + * made to look like OpenBSD's more useable reallocarray(3) interface. + */ +#include "reallocarray.h" + +#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2)) +void * +reallocarray(void *ptr, size_t n, size_t size) +{ + + /* + * Try to avoid division here. + * + * It isn't possible to overflow during multiplication if neither + * operand uses any of the most significant half of the bits. + */ + if ((n | size) >= SQRT_SIZE_MAX && n > SIZE_MAX / size) { + errno = EOVERFLOW; + return NULL; + } + return realloc(ptr, n * size); +} diff --git a/compat/reallocarray.h b/compat/reallocarray.h new file mode 100644 index 0000000..3bc34a3 --- /dev/null +++ b/compat/reallocarray.h @@ -0,0 +1,39 @@ +/* $NetBSD: reallocarr.c,v 1.4 2015/08/20 20:08:04 joerg Exp $ */ + +/*- + * Copyright (c) 2015 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef REALLOCARRAY_H +#define REALLOCARRAY_H + +#include + +void *reallocarray(void *, size_t, size_t); + +#endif From 441de7ab126b1461726c87b239d738f89519c1a9 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 21:26:16 +0100 Subject: [PATCH 03/30] Csat away a compile warning. --- src/plugins/lua.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/lua.c b/src/plugins/lua.c index 9bb4e97..1607384 100644 --- a/src/plugins/lua.c +++ b/src/plugins/lua.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -526,7 +527,7 @@ lua_add_dhcp_uint16(lua_State *L) return 0; } - u16 = htons(data); + u16 = htons((uint16_t)data); DHCP_PUT_U16(&l->l_p, l->l_e, (uint8_t)optn, u16); return 0; } @@ -553,7 +554,7 @@ lua_add_dhcp_uint32(lua_State *L) return 0; } - u32 = htonl(data); + u32 = htonl((uint32_t)data); DHCP_PUT_U32(&l->l_p, l->l_e, (uint8_t)optn, u32); return 0; } From eb8dc1e943764b69367a6ce9e0ef9a2da3645ef6 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 21:40:01 +0100 Subject: [PATCH 04/30] Solve initgroups compile warning on all OS. --- src/dhcpsd.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/dhcpsd.c b/src/dhcpsd.c index 9feecc0..4a4b395 100644 --- a/src/dhcpsd.c +++ b/src/dhcpsd.c @@ -129,7 +129,14 @@ dhcpsd_dropperms(int do_chroot) UNUSED(do_chroot); #endif - if (initgroups(DHCPSD_USER, (int)pw->pw_gid) == -1 || +/* Avoid a compile warnings on Darwin. */ +#ifdef __APPLE__ +#define INITGROUPS_GID(gid) (int)(gid) +#else +#define INITGROUPS_GID(gid) (gid) +#endif + + if (initgroups(DHCPSD_USER, INITGROUPS_GID(pw->pw_gid)) == -1 || setgid(pw->pw_gid) == -1 || setuid(pw->pw_uid) == -1) { logerr("%s: error dropping privileges", __func__); return -1; @@ -279,9 +286,8 @@ dhcpsd_send_launcher(struct ctx *ctx, int exit_code) { if (ctx->ctx_fork_fd == -1) return; - if (send(ctx->ctx_fork_fd, &exit_code, sizeof(exit_code), MSG_EOR) == - -1) - logerr("%s: sendmsg", __func__); + if (send(ctx->ctx_fork_fd, &exit_code, sizeof(exit_code), 0) == -1) + logerr("%s: send", __func__); close(ctx->ctx_fork_fd); ctx->ctx_fork_fd = -1; } From 837d25f8137e202c4e57f673dce5b84afa478752 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 21:50:34 +0100 Subject: [PATCH 05/30] Fixup xsetfd --- src/common.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/common.c b/src/common.c index bafc032..ed0751f 100644 --- a/src/common.c +++ b/src/common.c @@ -465,27 +465,31 @@ sa_pton(struct sockaddr *sa, const char *src) static int xsetfd(int fd, int flags) { - int xflags, oflags; - - oflags = fcntl(fd, F_GETFD); - if (oflags == -1) - return -1; - - xflags = oflags; + int oflags; #ifndef HAVE_SOCK_CLOEXEC - if (flags & SOCK_CLOEXEC) - xflags |= FD_CLOEXEC; + if (flags & SOCK_CLOEXEC) { + oflags = fcntl(fd, F_GETFD); + if (oflags == -1) + return -1; + if (!(oflags & FD_CLOEXEC) && + fcntl(fd, F_SETFD, oflags | O_NONBLOCK) == -1) + return -1; + } #endif + #ifndef HAVE_SOCK_NONBLOCK - if (flags & SOCK_NONBLOCK) - xflags |= O_NONBLOCK; + if (flags & SOCK_NONBLOCK) { + oflags = fcntl(fd, F_GETFL); + if (oflags == -1) + return -1; + if (!(oflags & O_NONBLOCK) && + fcntl(fd, F_SETFL, oflags | O_NONBLOCK) == -1) + return -1; + } #endif - if (xflags == oflags) - return 0; - - return fcntl(fd, F_SETFD, xflags); + return 0; } #endif From c9c891b1335bea66ce3c54705d466ee3da9c8ac4 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 21:52:44 +0100 Subject: [PATCH 06/30] Remove debug --- src/service.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/service.c b/src/service.c index fb38e08..6cd2332 100644 --- a/src/service.c +++ b/src/service.c @@ -222,7 +222,6 @@ svc_run(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, { .iov_base = UNCONST(data), .iov_len = len }, }; - loginfo("SVC RUN"); return srv_runv(sctx, p, cmd, iov, len == 0 ? 0 : 1, res, rdata, rlen); } From bf8283af8f79ae971e999caefcf1f4b11865805e Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 21:55:49 +0100 Subject: [PATCH 07/30] lua: correct message type --- src/plugins/lua.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/lua.c b/src/plugins/lua.c index 1607384..9413a4a 100644 --- a/src/plugins/lua.c +++ b/src/plugins/lua.c @@ -271,7 +271,7 @@ lua_run_lookup_hostname(struct plugin *p, struct srv_ctx *sctx, err = 0; out: - return srv_send(sctx, p, L_LOOKUPADDR, err, hname, hnamelen); + return srv_send(sctx, p, L_LOOKUPHOSTNAME, err, hname, hnamelen); } static ssize_t From f6cd3bccfc256573d3182615ddef9c31d822ed00 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 21:57:36 +0100 Subject: [PATCH 08/30] remove old svc_run --- src/service.c | 11 ----------- src/service.h | 2 -- 2 files changed, 13 deletions(-) diff --git a/src/service.c b/src/service.c index 6cd2332..3e6fcde 100644 --- a/src/service.c +++ b/src/service.c @@ -214,17 +214,6 @@ srv_run(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, return srv_runv(sctx, p, cmd, iov, len == 0 ? 0 : 1, res, rdata, rlen); } -int -svc_run(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, - const void *data, size_t len, ssize_t *res, void **rdata, size_t *rlen) -{ - struct iovec iov[] = { - { .iov_base = UNCONST(data), .iov_len = len }, - }; - - return srv_runv(sctx, p, cmd, iov, len == 0 ? 0 : 1, res, rdata, rlen); -} - struct srv_ctx * srv_init(struct ctx *ctx, const char *name, ssize_t (*dispatch)(struct srv_ctx *, struct plugin *, unsigned int, diff --git a/src/service.h b/src/service.h index 6df6307..4b93b28 100644 --- a/src/service.h +++ b/src/service.h @@ -64,8 +64,6 @@ ssize_t srv_sendv(struct srv_ctx *, struct plugin *, unsigned int, ssize_t, struct iovec *, int); int srv_run(struct srv_ctx *, struct plugin *, unsigned int, const void *, size_t, ssize_t *, void **, size_t *); -int svc_run(struct srv_ctx *, struct plugin *, unsigned int, const void *, - size_t, ssize_t *, void **, size_t *); int srv_runv(struct srv_ctx *, struct plugin *, unsigned int, struct iovec *, int, ssize_t *, void **, size_t *); From d04a15a621564d990994b785baa3da3f0e9f54d9 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 21:58:52 +0100 Subject: [PATCH 09/30] Remove dup define --- src/unpriv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/unpriv.c b/src/unpriv.c index 3377dad..b3e1d39 100644 --- a/src/unpriv.c +++ b/src/unpriv.c @@ -44,7 +44,6 @@ #include "service.h" #include "unpriv.h" -#define U_GETADDRINFO 1 #define U_GETADDRINFO 1 struct unpriv_addrinfo { From dd14a8731bf194e4d39f42d7b3e6ea452957ddfe Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 22:59:09 +0100 Subject: [PATCH 10/30] lua: improve hostname lookup --- src/plugins/lua.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/plugins/lua.c b/src/plugins/lua.c index 9413a4a..4aef0b9 100644 --- a/src/plugins/lua.c +++ b/src/plugins/lua.c @@ -282,16 +282,32 @@ lua_run_lookup_addr(struct plugin *p, struct srv_ctx *sctx, const void *data, struct lua_ctx *l = p->p_pctx; lua_State *L = l->L; const char *addr; + char *datap = UNCONST(data); + size_t hostname_len; char hostname[DHCP_HOSTNAME_LEN]; - memcpy(hostname, data, sizeof(hostname)); + char chaddr[sizeof(((struct bootp *)0)->chaddr) * 3]; + + if (len < sizeof(hostname_len)) { + errno = EINVAL; + goto out; + } + memcpy(&hostname_len, datap, sizeof(hostname_len)); + datap += sizeof(hostname_len); + len -= sizeof(hostname_len); + + if (len < hostname_len) { + errno = EINVAL; + goto out; + } + memcpy(hostname, datap, hostname_len); + datap += hostname_len; + len -= hostname_len; + /* Aligns bootp */ - memmove(UNCONST(data), (const char *)data + sizeof(hostname), - len - sizeof(hostname)); - len -= sizeof(hostname); + memmove(UNCONST(data), datap, len); l->l_req = data; l->l_reqlen = len; - char chaddr[l->l_req->hlen * 3]; struct sockaddr_in sin = { .sin_family = AF_INET, #ifdef BSD @@ -902,9 +918,13 @@ static int lua_lookup_addr(struct plugin *p, struct sockaddr *sa, uint32_t *ltime, const char *hostname, const struct bootp *bootp, size_t bootplen) { - char hname[DHCP_HOSTNAME_LEN] = { '\0' }; + size_t hostname_len = hostname ? strlen(hostname) + 1 : 0; struct iovec iov[] = { - { .iov_base = hname, .iov_len = sizeof(hname) }, + { + .iov_base = &hostname_len, + .iov_len = sizeof(hostname_len), + }, + { .iov_base = UNCONST(hostname), .iov_len = hostname_len }, { .iov_base = UNCONST(bootp), .iov_len = bootplen }, }; ssize_t err, result; @@ -912,8 +932,6 @@ lua_lookup_addr(struct plugin *p, struct sockaddr *sa, uint32_t *ltime, uint8_t *dp; size_t len; - if (hostname != NULL) - strlcpy(hname, hostname, sizeof(hname)); err = srv_runv(p->p_ctx->ctx_unpriv, p, L_LOOKUPADDR, iov, ARRAYCOUNT(iov), &result, &data, &len); From 3bdae24547ed32d0cd27b51c4401f880988ad4be Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 23:02:18 +0100 Subject: [PATCH 11/30] lua: fix payload len guard --- src/plugins/lua.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/lua.c b/src/plugins/lua.c index 4aef0b9..5945a18 100644 --- a/src/plugins/lua.c +++ b/src/plugins/lua.c @@ -689,7 +689,7 @@ lua_run_expire_lease(struct plugin *p, struct srv_ctx *sctx, char ipbuf[INET_ADDRSTRLEN]; const char *ip, *flags; - if (payloadlen < sizeof(dl)) { + if (payloadlen < sizeof(*dl)) { errno = EINVAL; goto out; } From d2034e5a9e1af90c3ad099e8bc5bf62b8bc17ad2 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 23:33:23 +0100 Subject: [PATCH 12/30] lua: more fixes --- src/plugins/lua.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/plugins/lua.c b/src/plugins/lua.c index 5945a18..6d8824f 100644 --- a/src/plugins/lua.c +++ b/src/plugins/lua.c @@ -286,6 +286,18 @@ lua_run_lookup_addr(struct plugin *p, struct srv_ctx *sctx, const void *data, size_t hostname_len; char hostname[DHCP_HOSTNAME_LEN]; char chaddr[sizeof(((struct bootp *)0)->chaddr) * 3]; + struct sockaddr_in sin = { + .sin_family = AF_INET, +#ifdef BSD + .sin_len = sizeof(sin), +#endif + }; + struct sockaddr *sa = (struct sockaddr *)&sin; + uint32_t ltime = 0; + struct iovec iov[] = { + { .iov_base = <ime, .iov_len = sizeof(ltime) }, + { .iov_base = &sin, .iov_len = sizeof(sin) }, + }; if (len < sizeof(hostname_len)) { errno = EINVAL; @@ -295,31 +307,26 @@ lua_run_lookup_addr(struct plugin *p, struct srv_ctx *sctx, const void *data, datap += sizeof(hostname_len); len -= sizeof(hostname_len); - if (len < hostname_len) { + if (hostname_len != 0) { + if (len < hostname_len) { + errno = EINVAL; + goto out; + } + memcpy(hostname, datap, hostname_len); + datap += hostname_len; + len -= hostname_len; + } else + hostname[0] = '\0'; + + if (len < sizeof(*l->l_req)) { errno = EINVAL; goto out; } - memcpy(hostname, datap, hostname_len); - datap += hostname_len; - len -= hostname_len; - /* Aligns bootp */ memmove(UNCONST(data), datap, len); l->l_req = data; l->l_reqlen = len; - struct sockaddr_in sin = { - .sin_family = AF_INET, -#ifdef BSD - .sin_len = sizeof(sin), -#endif - }; - struct sockaddr *sa = (struct sockaddr *)&sin; - uint32_t ltime = 0; - struct iovec iov[] = { - { .iov_base = <ime, .iov_len = sizeof(ltime) }, - { .iov_base = &sin, .iov_len = sizeof(sin) }, - }; lua_pop(L, lua_gettop(L)); From 44b199882b8b186beb3080bfa02301d4d8e15ff7 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 6 Apr 2026 23:47:08 +0100 Subject: [PATCH 13/30] use blocking sockets --- src/dhcpsd.c | 3 ++- src/service.c | 9 ++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dhcpsd.c b/src/dhcpsd.c index 4a4b395..8b6c999 100644 --- a/src/dhcpsd.c +++ b/src/dhcpsd.c @@ -204,7 +204,8 @@ dhcpsd_fork(struct ctx *ctx) cap_rights_t rights; #endif - if (xsocketpair(PF_LOCAL, SOCK_STREAM | SOCK_CXNB, 0, fork_fd) == -1) { + if (xsocketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, fork_fd) == + -1) { logerr("socketpair"); return -1; } diff --git a/src/service.c b/src/service.c index 3e6fcde..593dd4e 100644 --- a/src/service.c +++ b/src/service.c @@ -101,9 +101,6 @@ srv_recv(void *arg, unsigned short e) iov[0].iov_base = sctx->srv_buf; iov[0].iov_len = cmd.sc_datalen; - sr->sr_result = cmd.sc_result; - sr->sr_errno = cmd.sc_errno; - nread = recvmsg(sctx->srv_fd, &msg, MSG_WAITALL); if (nread == -1) { logerr("%s: recvmsg cmd", __func__); @@ -116,8 +113,10 @@ srv_recv(void *arg, unsigned short e) } } - sr->sr_datalen = cmd.sc_datalen; + sr->sr_result = cmd.sc_result; + sr->sr_errno = cmd.sc_errno; sr->sr_data = sr->sr_datalen != 0 ? sctx->srv_buf : NULL; + sr->sr_datalen = cmd.sc_datalen; /* We are either a dispatcher for the helper, or a blocking loop for a * response */ @@ -241,7 +240,7 @@ srv_init(struct ctx *ctx, const char *name, goto error; } - if (xsocketpair(PF_LOCAL, SOCK_STREAM | SOCK_CXNB, 0, fdset) == -1) { + if (xsocketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, fdset) == -1) { logerr("%s: socketpair", __func__); goto error; } From e1c159c189805a78d757cf6dbd356840ad25933d Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 09:10:33 +0100 Subject: [PATCH 14/30] Fix returning service data --- src/service.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/service.c b/src/service.c index 593dd4e..de4e3b1 100644 --- a/src/service.c +++ b/src/service.c @@ -51,10 +51,9 @@ struct srv_cmd { size_t sc_datalen; }; -static void -srv_recv(void *arg, unsigned short e) +static ssize_t +srv_recv(struct srv_ctx *sctx, unsigned short e) { - struct srv_ctx *sctx = arg; struct srv_result *sr = &sctx->srv_result; struct srv_cmd cmd; struct iovec iov[] = { @@ -69,11 +68,11 @@ srv_recv(void *arg, unsigned short e) if (e & ELE_HANGUP) { hangup: eloop_exit(sctx->srv_ctx->ctx_eloop, EXIT_SUCCESS); - return; + return -1; } if (e != ELE_READ) { logerrx("%s: unexpected operation %u", __func__, e); - return; + return -1; } nread = recvmsg(sctx->srv_fd, &msg, MSG_WAITALL); @@ -81,11 +80,11 @@ srv_recv(void *arg, unsigned short e) goto hangup; if (nread == -1) { logerr("%s: recvmsg cmd", __func__); - return; + return -1; } if (nread != sizeof(cmd)) { logerrx("%s: invalid read len: %zd", __func__, nread); - return; + return -1; } if (cmd.sc_datalen != 0) { @@ -93,7 +92,7 @@ srv_recv(void *arg, unsigned short e) void *nbuf = realloc(sctx->srv_buf, cmd.sc_datalen); if (nbuf == NULL) { logerr("%s: realloc", __func__); - return; + return -1; } sctx->srv_buf = nbuf; sctx->srv_buflen = cmd.sc_datalen; @@ -104,25 +103,34 @@ srv_recv(void *arg, unsigned short e) nread = recvmsg(sctx->srv_fd, &msg, MSG_WAITALL); if (nread == -1) { logerr("%s: recvmsg cmd", __func__); - return; + return -1; } if ((size_t)nread != cmd.sc_datalen) { logerrx("%s: read datalen mismatch: %zd != %zd", __func__, nread, sizeof(cmd) + cmd.sc_datalen); - return; + return -1; } } sr->sr_result = cmd.sc_result; sr->sr_errno = cmd.sc_errno; - sr->sr_data = sr->sr_datalen != 0 ? sctx->srv_buf : NULL; + sr->sr_data = cmd.sc_datalen != 0 ? sctx->srv_buf : NULL; sr->sr_datalen = cmd.sc_datalen; /* We are either a dispatcher for the helper, or a blocking loop for a * response */ if (sctx->srv_dispatch != NULL) sctx->srv_dispatch(sctx, (struct plugin *)cmd.sc_plugin, - cmd.sc_cmd, sctx->srv_buf, cmd.sc_datalen); + cmd.sc_cmd, cmd.sc_datalen ? sctx->srv_buf : NULL, + cmd.sc_datalen); + + return (ssize_t)cmd.sc_datalen; +} + +static void +srv_recvl(void *arg, unsigned short e) +{ + srv_recv(arg, e); } ssize_t @@ -189,7 +197,8 @@ srv_runv(struct srv_ctx *sctx, struct plugin *p, unsigned int cmd, events = eloop_waitfd(sctx->srv_fd); if (events == -1) return -1; - srv_recv(sctx, (unsigned short)events); + if (srv_recv(sctx, (unsigned short)events) == -1) + return -1; if (result->sr_result == -1) errno = result->sr_errno; @@ -270,7 +279,7 @@ srv_init(struct ctx *ctx, const char *name, goto error; } - if (eloop_event_add(ctx->ctx_eloop, sctx->srv_fd, ELE_READ, srv_recv, + if (eloop_event_add(ctx->ctx_eloop, sctx->srv_fd, ELE_READ, srv_recvl, sctx) == -1) { logerr("%s: eloop_event_add", __func__); goto error; From 19d1d3ee8000ace5ec804d673dd5c3b76b1841f9 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 09:35:27 +0100 Subject: [PATCH 15/30] Abort eloop if service watcher fails. --- src/service.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index de4e3b1..e425dd2 100644 --- a/src/service.c +++ b/src/service.c @@ -130,7 +130,10 @@ srv_recv(struct srv_ctx *sctx, unsigned short e) static void srv_recvl(void *arg, unsigned short e) { - srv_recv(arg, e); + struct srv_ctx *sctx = arg; + + if (srv_recv(sctx, e) == -1) + eloop_exit(sctx->srv_ctx->ctx_eloop, EXIT_FAILURE); } ssize_t From 5da02fe6342e22ed5d785149cd11790b2e866638 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 09:44:40 +0100 Subject: [PATCH 16/30] Add macos to github actions --- .github/workflows/build.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a9b4ddb..59af5ae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,33 @@ jobs: - name: Build run: make + macos: + strategy: + matrix: + os: [ macos-latest, macos-arm64-latest ] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + + - name: Set up Homebrew + id: set-up-homebrew + uses: Homebrew/actions/setup-homebrew@main + + - name: Install Lua + run: | + brew install lua pkgconf + + - name: Configure + run: ./configure + + - name: Build + run: make + +# The BSDs are currently broken on github + openbsd: + if: false runs-on: ubuntu-latest steps: - name: Bootstrap OpenBSD-latest @@ -50,6 +76,7 @@ jobs: make freebsd: + if: false runs-on: ubuntu-latest steps: - name: Bootstrap FreeBSD-latest @@ -69,6 +96,7 @@ jobs: make netbsd: + if: false runs-on: ubuntu-latest steps: - name: Bootstrap NetBSD-latest From 7e6dad8ea39c9a5e2b758141b0631b859dd35b60 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 09:47:18 +0100 Subject: [PATCH 17/30] Fix macos arm64 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 59af5ae..5c9e4e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,7 +33,7 @@ jobs: macos: strategy: matrix: - os: [ macos-latest, macos-arm64-latest ] + os: [ macos-latest, macos-latest-arm64 ] runs-on: ${{ matrix.os }} steps: From c450118e15227c8ad1f1fe44b3d9d7093356cdd0 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 09:51:54 +0100 Subject: [PATCH 18/30] Just build on latest OS --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5c9e4e9..810de7f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: ubuntu: strategy: matrix: - os: [ ubuntu-latest, ubuntu-22.04 ] + os: [ ubuntu-latest ] runs-on: ${{ matrix.os }} steps: @@ -33,7 +33,7 @@ jobs: macos: strategy: matrix: - os: [ macos-latest, macos-latest-arm64 ] + os: [ macos-latest ] runs-on: ${{ matrix.os }} steps: From 8a67a9a2dbe8753c44629523fd28ba3b5729f456 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 09:54:56 +0100 Subject: [PATCH 19/30] Fix diagnostic message --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index e425dd2..8512c10 100644 --- a/src/service.c +++ b/src/service.c @@ -107,7 +107,7 @@ srv_recv(struct srv_ctx *sctx, unsigned short e) } if ((size_t)nread != cmd.sc_datalen) { logerrx("%s: read datalen mismatch: %zd != %zd", - __func__, nread, sizeof(cmd) + cmd.sc_datalen); + __func__, nread, cmd.sc_datalen); return -1; } } From 65a26025b48346df59a3c9890f7e8fc272339919 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 09:55:10 +0100 Subject: [PATCH 20/30] Use latest checkout --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 810de7f..994fe5c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Lua run: | @@ -37,7 +37,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Homebrew id: set-up-homebrew From bdf082327c2decd5ac1ff5aeda3aaa7a5ad67d45 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 10:08:37 +0100 Subject: [PATCH 21/30] Brew and pkgconf are already installed. --- .github/workflows/build.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 994fe5c..c711cda 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,13 +39,9 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Homebrew - id: set-up-homebrew - uses: Homebrew/actions/setup-homebrew@main - - name: Install Lua run: | - brew install lua pkgconf + brew install lua - name: Configure run: ./configure From 6a590c6337e8d2b54924e23c203cfac557afeccd Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 10:11:31 +0100 Subject: [PATCH 22/30] Latest checkout --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c711cda..c0fc055 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Lua run: | @@ -37,7 +37,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Lua run: | From ea815b0a5c2be65e0fe178ec8f5a8f0094147199 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 10:17:42 +0100 Subject: [PATCH 23/30] Don't exit on hangup as we already have --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index 8512c10..980fe11 100644 --- a/src/service.c +++ b/src/service.c @@ -132,7 +132,7 @@ srv_recvl(void *arg, unsigned short e) { struct srv_ctx *sctx = arg; - if (srv_recv(sctx, e) == -1) + if (srv_recv(sctx, e) == -1 && !(e & ELE_HANGUP)) eloop_exit(sctx->srv_ctx->ctx_eloop, EXIT_FAILURE); } From f7ee065b692826932e4ec53786d75af31ec43666 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 10:30:22 +0100 Subject: [PATCH 24/30] eloop: rationalise not setting cloexec on macos --- src/eloop.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/eloop.c b/src/eloop.c index 01e2655..b5cdd05 100644 --- a/src/eloop.c +++ b/src/eloop.c @@ -626,6 +626,10 @@ eloop_open(struct eloop *eloop) #elif defined(KQUEUE_CLOEXEC) fd = kqueuex(KQUEUE_CLOEXEC); #elif defined(USE_KQUEUE) && defined(__APPLE__) + /* macOS does not allow setting CLOEXEC on kqueue. + * This should not be a problem because eloop consumers + * fork and exec rather than just exec and kqueue is + * automatically closed on fork. */ fd = kqueue(); #elif defined(USE_KQUEUE) int flags; From f18a138a32e9301bd90e318b3f4056235b4db495 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 10:33:27 +0100 Subject: [PATCH 25/30] lua: ensure we have space to copyout hostname. --- src/plugins/lua.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/lua.c b/src/plugins/lua.c index 6d8824f..caa4ddc 100644 --- a/src/plugins/lua.c +++ b/src/plugins/lua.c @@ -308,7 +308,7 @@ lua_run_lookup_addr(struct plugin *p, struct srv_ctx *sctx, const void *data, len -= sizeof(hostname_len); if (hostname_len != 0) { - if (len < hostname_len) { + if (len < hostname_len || hostname_len > sizeof(hostname)) { errno = EINVAL; goto out; } From b346ca95192156e9d45376d8444d039b29b8430a Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 14:12:44 +0100 Subject: [PATCH 26/30] Fix xsetfd, close eloop fd with epoll and correct a diagnositic message. --- src/common.c | 2 +- src/eloop.c | 6 +++++- src/service.c | 6 +++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/common.c b/src/common.c index ed0751f..b60f0a9 100644 --- a/src/common.c +++ b/src/common.c @@ -473,7 +473,7 @@ xsetfd(int fd, int flags) if (oflags == -1) return -1; if (!(oflags & FD_CLOEXEC) && - fcntl(fd, F_SETFD, oflags | O_NONBLOCK) == -1) + fcntl(fd, F_SETFD, oflags | FD_CLOEXEC) == -1) return -1; } #endif diff --git a/src/eloop.c b/src/eloop.c index b5cdd05..9956461 100644 --- a/src/eloop.c +++ b/src/eloop.c @@ -700,7 +700,11 @@ eloop_forked(struct eloop *eloop, unsigned short flags) unsigned short events; int err; - /* The fd is invalid after a fork, no need to close it. */ +/* kqueue invalidates the fd on fork. + * epoll shares state across fork, so we close the old and create a new one. */ +#ifdef USE_EPOLL + close(eloop->fd); +#endif eloop->fd = -1; if (flags && eloop_open(eloop) == -1) return -1; diff --git a/src/service.c b/src/service.c index 980fe11..510ee67 100644 --- a/src/service.c +++ b/src/service.c @@ -102,12 +102,12 @@ srv_recv(struct srv_ctx *sctx, unsigned short e) nread = recvmsg(sctx->srv_fd, &msg, MSG_WAITALL); if (nread == -1) { - logerr("%s: recvmsg cmd", __func__); + logerr("%s: recvmsg data", __func__); return -1; } if ((size_t)nread != cmd.sc_datalen) { - logerrx("%s: read datalen mismatch: %zd != %zd", - __func__, nread, cmd.sc_datalen); + logerrx("%s: read datalen mismatch: %zu != %zu", + __func__, (size_t)nread, cmd.sc_datalen); return -1; } } From d10a94f5a7605be3351eafcd8fccc56e841bc3c9 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 14:56:02 +0100 Subject: [PATCH 27/30] Fix on bsd --- src/plugins/Makefile | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/plugins/Makefile b/src/plugins/Makefile index 393b252..eb70a54 100644 --- a/src/plugins/Makefile +++ b/src/plugins/Makefile @@ -1,5 +1,4 @@ TOP= ../../ -include ${TOP}/Makefile.inc include ${TOP}/iconfig.mk CFLAGS?= -O2 @@ -14,7 +13,6 @@ PLUGINS+= addrinfo ethers PLUGINS+= ${LUA_PLUGIN} SRCS= ${PLUGINS:=.c} OBJS= ${SRCS:.c=.o} -SOBJS= ${OBJS:.o=.So} PLUGS= ${PLUGINS:=.so} MAN8= dhcpsd_auto.8 dhcpsd_leasefile.8 @@ -22,16 +20,15 @@ MAN8+= dhcpsd_addrinfo.8 dhcpsd_ethers.8 MAN8+= dhcpsd_icmp.8 MAN8+= ${LUA_MAN8} -CLEANFILES+= ${OBJS} ${SOBJS} ${PLUGS} +CLEANFILES+= ${OBJS} ${PLUGS} CLEANFILES+= dhcpsd_leasefile.8 ${LUA_MAN8} -.SUFFIXES: .soo .so .in -.INTERMEDIATE: icmp.soo lua.soo +.SUFFIXES: .in .so -.c.soo: +.c.o: ${CC} ${PICFLAG} -DPIC ${CFLAGS} ${CDBGFLAGS} ${CPPFLAGS} -c $< -o $@ -.soo.so: +.o.so: ${CC} ${LDFLAGS} ${LDFLAGS_SO} -shared -Wl,-x -o $@ $< ${LIBS} .in: @@ -40,13 +37,13 @@ CLEANFILES+= dhcpsd_leasefile.8 ${LUA_MAN8} all: ${PLUGS} ${MAN8} # verstable.h has a few compiler warnings so we hide it away -icmp.soo: icmp.c +icmp.o: icmp.c ${CC} ${PICFLAG} -DPIC ${CFLAGS} ${CPPFLAGS} ${VERSTABLE_CFLAGS} -c icmp.c -o $@ -lua.soo: lua.c +lua.o: lua.c ${CC} ${PICFLAG} -DPIC ${CFLAGS} ${CDBGFLAGS} ${LUA_CFLAGS} ${CPPFLAGS} -c lua.c -o $@ -lua.so: lua.soo +lua.so: lua.o ${CC} ${LDFLAGS} ${LDFLAGS_SO} -shared -Wl,-x -o $@ lua.soo ${LUA_LIBS} lint: _lint From 0853b1f878381ad7a53db865d2566909cdcdc9db Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 14:57:26 +0100 Subject: [PATCH 28/30] Fix again, lol --- src/plugins/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/Makefile b/src/plugins/Makefile index eb70a54..2e8a0fb 100644 --- a/src/plugins/Makefile +++ b/src/plugins/Makefile @@ -44,7 +44,7 @@ lua.o: lua.c ${CC} ${PICFLAG} -DPIC ${CFLAGS} ${CDBGFLAGS} ${LUA_CFLAGS} ${CPPFLAGS} -c lua.c -o $@ lua.so: lua.o - ${CC} ${LDFLAGS} ${LDFLAGS_SO} -shared -Wl,-x -o $@ lua.soo ${LUA_LIBS} + ${CC} ${LDFLAGS} ${LDFLAGS_SO} -shared -Wl,-x -o $@ lua.o ${LUA_LIBS} lint: _lint From 2824fd2efc195c88fd4d98b20b56f321b8c19d2d Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 20:11:39 +0100 Subject: [PATCH 29/30] reallocarray: fix errno and avoid div by zero. --- compat/reallocarray.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compat/reallocarray.c b/compat/reallocarray.c index 9ff9c20..0374515 100644 --- a/compat/reallocarray.c +++ b/compat/reallocarray.c @@ -45,6 +45,8 @@ void * reallocarray(void *ptr, size_t n, size_t size) { + if (n == 0 || size == 0) + return realloc(ptr, 0); /* * Try to avoid division here. @@ -53,7 +55,7 @@ reallocarray(void *ptr, size_t n, size_t size) * operand uses any of the most significant half of the bits. */ if ((n | size) >= SQRT_SIZE_MAX && n > SIZE_MAX / size) { - errno = EOVERFLOW; + errno = ENOMEM; return NULL; } return realloc(ptr, n * size); From be6a688a07768f7bf23521b0c9dcd0bcfc0c6387 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 7 Apr 2026 20:17:39 +0100 Subject: [PATCH 30/30] Build on macos-15 and macos-26 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c0fc055..57ed6e3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,7 +33,7 @@ jobs: macos: strategy: matrix: - os: [ macos-latest ] + os: [ macos-15, macos-26 ] runs-on: ${{ matrix.os }} steps: