diff --git a/src/privsep-bpf.c b/src/privsep-bpf.c index ddd3cd82..dc4b5719 100644 --- a/src/privsep-bpf.c +++ b/src/privsep-bpf.c @@ -70,13 +70,23 @@ ps_bpf_recvbpf(void *arg) * This mechanism allows us to read each packet from the buffer. */ while (!(bpf->bpf_flags & BPF_EOF)) { len = bpf_read(bpf, buf, sizeof(buf)); - if (len == -1) - logerr(__func__); - if (len == -1 || len == 0) + if (len == 0) break; - psm.ps_flags = bpf->bpf_flags; - len = ps_sendpsmdata(psp->psp_ctx, psp->psp_ctx->ps_data_fd, - &psm, buf, (size_t)len); + if (len == -1) { + if (errno == EINTR || errno == EAGAIN) + break; + logerr(__func__); + psm.ps_cmd |= PS_ERROR; + psm.ps_flags = (unsigned long)errno; + eloop_event_delete(psp->psp_ctx->eloop, bpf->bpf_fd); + bpf_close(bpf); + len = ps_sendpsmdata(psp->psp_ctx, + psp->psp_ctx->ps_data_fd, &psm, NULL, 0); + } else { + psm.ps_flags = bpf->bpf_flags; + len = ps_sendpsmdata(psp->psp_ctx, + psp->psp_ctx->ps_data_fd, &psm, buf, (size_t)len); + } if (len == -1) logerr(__func__); if (len == -1 || len == 0) @@ -166,7 +176,7 @@ ps_bpf_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) struct iovec *iov = msg->msg_iov; struct interface *ifp; - cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP)); + cmd = (uint16_t)(psm->ps_cmd & ~PS_CMDMASK); psp = ps_findprocess(ctx, &psm->ps_id); #ifdef PRIVSEP_DEBUG @@ -295,7 +305,7 @@ ps_bpf_send(const struct interface *ifp, const struct in_addr *ia, .ps_cmd = cmd, .ps_id = { .psi_ifindex = ifp->index, - .psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)), + .psi_cmd = (uint8_t)(cmd & ~PS_CMDMASK), }, }; diff --git a/src/privsep-inet.c b/src/privsep-inet.c index 2770569f..b020ba0a 100644 --- a/src/privsep-inet.c +++ b/src/privsep-inet.c @@ -521,7 +521,7 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) int (*start_func)(void *); pid_t start; - cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP)); + cmd = (uint16_t)(psm->ps_cmd & ~PS_CMDMASK); if (cmd == psm->ps_cmd) return ps_inet_sendmsg(ctx, psm, msg); @@ -599,7 +599,7 @@ ps_inet_in_docmd(struct ipv4_addr *ia, uint16_t cmd, const struct msghdr *msg) struct ps_msghdr psm = { .ps_cmd = cmd, .ps_id = { - .psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)), + .psi_cmd = (uint8_t)(cmd & ~PS_CMDMASK), .psi_ifindex = ia->iface->index, .psi_addr.psa_in_addr = ia->addr, }, @@ -639,7 +639,7 @@ ps_inet_ifp_docmd(struct interface *ifp, uint16_t cmd, const struct msghdr *msg) struct ps_msghdr psm = { .ps_cmd = cmd, .ps_id = { - .psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)), + .psi_cmd = (uint8_t)(cmd & ~PS_CMDMASK), .psi_ifindex = ifp->index, }, }; @@ -684,7 +684,7 @@ ps_inet_in6_docmd(struct ipv6_addr *ia, uint16_t cmd, const struct msghdr *msg) struct ps_msghdr psm = { .ps_cmd = cmd, .ps_id = { - .psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)), + .psi_cmd = (uint8_t)(cmd & ~PS_CMDMASK), .psi_ifindex = ia->iface->index, .psi_addr.psa_in6_addr = ia->addr, }, diff --git a/src/privsep-root.c b/src/privsep-root.c index 770dd953..0fbc0187 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -460,7 +460,7 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) ssize_t err; bool free_rdata = false; - cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP)); + cmd = (uint16_t)(psm->ps_cmd & ~PS_CMDMASK); psp = ps_findprocess(ctx, &psm->ps_id); #ifdef PRIVSEP_DEBUG @@ -716,7 +716,21 @@ ps_root_signalcb(int sig, __unused void *arg) } } -int (*handle_interface)(void *, int, const char *); +static ssize_t +ps_root_errorcb(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm) +{ + struct interface *ifp; + + ifp = if_findindex(ctx->ifaces, psm->ps_id.psi_ifindex); + /* interface may have departed .... */ + if (ifp == NULL) + return 0; + + errno = (int)psm->ps_flags; + logerr("%s: %s", ifp->name, __func__); + dhcpcd_handleinterface(ctx, -1, ifp->name); + return 0; +} #ifdef PLUGIN_DEV static ssize_t @@ -755,6 +769,9 @@ ps_root_dispatchcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) struct dhcpcd_ctx *ctx = arg; ssize_t err; + if (psm->ps_cmd & PS_ERROR) + return ps_root_errorcb(ctx, psm); + switch(psm->ps_cmd) { #ifdef PLUGIN_DEV case PS_DEV_IFCMD: diff --git a/src/privsep.h b/src/privsep.h index 4fd33e7f..77f03d16 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -76,8 +76,10 @@ #define PS_CTL_UNPRIV 0x0005 /* Process commands */ +#define PS_ERROR 0x2000 #define PS_START 0x4000 #define PS_STOP 0x8000 +#define PS_CMDMASK (PS_ERROR | PS_START | PS_STOP) /* Max INET message size + meta data for IPC */ #define PS_BUFLEN ((64 * 1024) + \