diff --git a/src/dhcp.c b/src/dhcp.c index 8591257..6ae485d 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -368,9 +368,20 @@ dhcp_outputipudp(struct interface *ifp, const struct in_addr *src, in_cksum(&udp, sizeof(udp), &sum); udp.uh_sum = in_cksum(bootp, len, &sum); - nbytes = priv_sendbpf(ifp, iov, ARRAYCOUNT(iov)); - if (nbytes == -1) - logerr("%s: priv_sendbpf: %s", __func__, ifp->if_name); + if (ctx->dhcp_ctx->ctx_options & DHCPSD_WAITIF) { + nbytes = priv_sendbpf(ifp, iov, ARRAYCOUNT(iov)); + if (nbytes == -1) + logerr("%s: priv_sendbpf: %s", __func__, ifp->if_name); + } else if (ifp->if_bpf != NULL) { + nbytes = ifp->if_output(ifp, ifp->if_bpf->bpf_fd, iov, + ARRAYCOUNT(iov)); + if (nbytes == -1) + logerr("%s: if_output: %s", __func__, ifp->if_name); + } else { + errno = ENXIO; + logerr("%s: %s", __func__, ifp->if_name); + nbytes = -1; + } return nbytes; } diff --git a/src/dhcpsd.8.in b/src/dhcpsd.8.in index 039b306..bba01fe 100644 --- a/src/dhcpsd.8.in +++ b/src/dhcpsd.8.in @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 16, 2026 +.Dd April 21, 2026 .Dt DHCPSD 8 .Os .Sh NAME @@ -87,6 +87,8 @@ to work with dynamically created interfaces that are in the ready state. If an interface is marked down or departs then .Nm will deactivate the interface. +This requires a privileged helper process to open a BPF socket for each +interface when required. .El .Sh NOTES .Nm diff --git a/src/dhcpsd.c b/src/dhcpsd.c index 82385d8..f64d0df 100644 --- a/src/dhcpsd.c +++ b/src/dhcpsd.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -324,8 +325,14 @@ dhcpsd_configure_pools(struct interface *ifp) continue; /* XXX When we grow DHCPv6 only open BPF if we configure * a DHCPv4 pool. */ - if (priv_openbpf(ifp) == -1) - return -1; + if (ctx->ctx_options & DHCPSD_WAITIF) { + if (priv_openbpf(ifp) == -1) + return -1; + } else { + ifp->if_bpf = bpf_open(ifp, bpf_bootp, O_WRONLY); + if (ifp->if_bpf == NULL) + return -1; + } /* First plugin with config wins */ npools += n; break; @@ -429,12 +436,16 @@ main(int argc, char **argv) ctx.ctx_argc = argc; ctx.ctx_argv = argv; - if (priv_init(&ctx) == NULL) { - logerr("%s: priv_init", __func__); - goto exit; + /* Waiting for interfaces requires a privileged helper + * to open BPF sockets. */ + if (ctx.ctx_options & DHCPSD_WAITIF) { + if (priv_init(&ctx) == NULL) { + logerr("%s: priv_init", __func__); + goto exit; + } + if (ctx.ctx_options & DHCPSD_RUN) + goto open_pf_inet; } - if (ctx.ctx_options & DHCPSD_RUN) - goto open_pf_inet; if (unpriv_init(&ctx) == NULL) { logerr("%s: unpriv_init", __func__); diff --git a/src/if.c b/src/if.c index 1090ee4..33d5ae7 100644 --- a/src/if.c +++ b/src/if.c @@ -233,7 +233,8 @@ if_learnifaces(struct ctx *ctx) if_update(ifp, ifa->ifa_addr); if_update_output(ifp); if (if_update_mtu(ifp) == -1) { - logerr("%s: if_update_mtu: %s", __func__, ifa->ifa_name); + logerr("%s: if_update_mtu: %s", __func__, + ifa->ifa_name); free(ifp); continue; } @@ -384,10 +385,12 @@ if_free(struct interface *ifp) srv_if_free = options & DHCPSD_MAIN && !(options & DHCPSD_EXITING); if (srv_if_free) { - if (options & DHCPSD_WAITIF) + if (options & DHCPSD_WAITIF) { loginfox("%s: deactiving interface", ifp->if_name); - if (priv_freeif(ifp) == -1 && errno != ESRCH) - logerr("%s: priv_freeif: %s", __func__, ifp->if_name); + if (priv_freeif(ifp) == -1 && errno != ESRCH) + logerr("%s: priv_freeif: %s", __func__, + ifp->if_name); + } if (unpriv_freeif(ifp) == -1 && errno != ESRCH) logerr("%s: unpriv_freeif: %s", __func__, ifp->if_name); }