]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
eloop: Make the API more like native poll/kqueue/epoll
authorRoy Marples <roy@marples.name>
Tue, 2 Feb 2021 14:41:54 +0000 (14:41 +0000)
committerRoy Marples <roy@marples.name>
Tue, 2 Feb 2021 14:41:54 +0000 (14:41 +0000)
Just have the one callback, but return an abstracted event mask
to work out if we can read/write have something else.
Log diagnostics if the event mask is unexpected.

While here add more logging if we fail to register an event to
monitor.

14 files changed:
src/arp.c
src/control.c
src/dhcp.c
src/dhcp6.c
src/dhcpcd.c
src/eloop.c
src/eloop.h
src/ipv6nd.c
src/privsep-bpf.c
src/privsep-control.c
src/privsep-inet.c
src/privsep-root.c
src/privsep.c
src/privsep.h

index e8a27f42257b22b635d48c19f4d004d3b449e145..5445e757344986b2cbf08b35d40dee0db266a687 100644 (file)
--- a/src/arp.c
+++ b/src/arp.c
@@ -299,7 +299,7 @@ arp_packet(struct interface *ifp, uint8_t *data, size_t len,
 }
 
 static void
-arp_read(void *arg)
+arp_read(void *arg, unsigned short events)
 {
        struct arp_state *astate = arg;
        struct bpf *bpf = astate->bpf;
@@ -308,6 +308,9 @@ arp_read(void *arg)
        ssize_t bytes;
        struct in_addr addr = astate->addr;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        /* Some RAW mechanisms are generic file descriptors, not sockets.
         * This means we have no kernel call to just get one packet,
         * so we have to process the entire buffer. */
@@ -532,7 +535,7 @@ arp_new(struct interface *ifp, const struct in_addr *addr)
        struct arp_state *astate;
 
        if ((state = ARP_STATE(ifp)) == NULL) {
-               ifp->if_data[IF_DATA_ARP] = malloc(sizeof(*state));
+               ifp->if_data[IF_DATA_ARP] = malloc(sizeof(*state));
                state = ARP_STATE(ifp);
                if (state == NULL) {
                        logerr(__func__);
@@ -567,8 +570,9 @@ arp_new(struct interface *ifp, const struct in_addr *addr)
                        free(astate);
                        return NULL;
                }
-               eloop_event_add(ifp->ctx->eloop, astate->bpf->bpf_fd,
-                   arp_read, astate);
+               if (eloop_event_add(ifp->ctx->eloop, astate->bpf->bpf_fd, ELE_READ,
+                   arp_read, astate) == -1)
+                       logerr("%s: eloop_event_add", __func__);
        }
 
 
index 928465118b5f7f3897b09d2fd780bb53cb2f98b6..ab75fe4803da1a7230abf19ded43b4ced36d1eed 100644 (file)
@@ -53,6 +53,8 @@
            (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
 #endif
 
+static void control_handle_data(void *, unsigned short);
+
 static void
 control_queue_free(struct fd_list *fd)
 {
@@ -84,9 +86,10 @@ control_free(struct fd_list *fd)
                fd->ctx->ps_control_client = NULL;
 #endif
 
-       if (eloop_event_remove_writecb(fd->ctx->eloop, fd->fd) == -1 &&
-           errno != ENOENT)
-               logerr(__func__);
+       /* Remove ELE_WRITE */
+       if (eloop_event_add(fd->ctx->eloop, fd->fd, ELE_READ,
+           control_handle_data, fd) == -1)
+               logerr("%s: eloop_event_add", __func__);
        TAILQ_REMOVE(&fd->ctx->control_fds, fd, next);
        control_queue_free(fd);
        free(fd);
@@ -107,9 +110,8 @@ control_delete(struct fd_list *fd)
 }
 
 static void
-control_handle_data(void *arg)
+control_handle_read(struct fd_list *fd)
 {
-       struct fd_list *fd = arg;
        char buffer[1024];
        ssize_t bytes;
 
@@ -145,6 +147,78 @@ control_handle_data(void *arg)
        control_recvdata(fd, buffer, (size_t)bytes);
 }
 
+static void
+control_handle_write(struct fd_list *fd)
+{
+       struct iovec iov[2];
+       int iov_len;
+       struct fd_data *data;
+
+       data = TAILQ_FIRST(&fd->queue);
+
+       if (data->data_flags & FD_SENDLEN) {
+               iov[0].iov_base = &data->data_len;
+               iov[0].iov_len = sizeof(size_t);
+               iov[1].iov_base = data->data;
+               iov[1].iov_len = data->data_len;
+               iov_len = 2;
+       } else {
+               iov[0].iov_base = data->data;
+               iov[0].iov_len = data->data_len;
+               iov_len = 1;
+       }
+
+       if (writev(fd->fd, iov, iov_len) == -1) {
+               logerr("%s: write", __func__);
+               control_delete(fd);
+               return;
+       }
+
+       TAILQ_REMOVE(&fd->queue, data, next);
+#ifdef CTL_FREE_LIST
+       TAILQ_INSERT_TAIL(&fd->free_queue, data, next);
+#else
+       if (data->data_size != 0)
+               free(data->data);
+       free(data);
+#endif
+
+       if (TAILQ_FIRST(&fd->queue) != NULL)
+               return;
+
+       /* Remove ELE_WRITE */
+       if (fd->flags & FD_LISTEN) {
+               if (eloop_event_add(fd->ctx->eloop, fd->fd, ELE_READ,
+                   control_handle_data, fd) == -1)
+                       logerr("%s: eloop_event_add", __func__);
+       } else {
+               if (eloop_event_delete(fd->ctx->eloop, fd->fd) == -1)
+                       logerr("%s: eloop_event_add", __func__);
+       }
+#ifdef PRIVSEP
+       if (IN_PRIVSEP_SE(fd->ctx) && !(fd->flags & FD_LISTEN)) {
+               if (ps_ctl_sendeof(fd) == -1)
+                       logerr(__func__);
+               control_free(fd);
+       }
+#endif
+}
+
+
+static void
+control_handle_data(void *arg, unsigned short events)
+{
+       struct fd_list *fd = arg;
+
+       if (events != ELE_READ && events != ELE_WRITE)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
+       if (events & ELE_WRITE)
+               control_handle_write(fd);
+       if (events & ELE_READ)
+               control_handle_read(fd);
+}
+
 void
 control_recvdata(struct fd_list *fd, char *data, size_t len)
 {
@@ -221,13 +295,17 @@ control_new(struct dhcpcd_ctx *ctx, int fd, unsigned int flags)
 }
 
 static void
-control_handle1(struct dhcpcd_ctx *ctx, int lfd, unsigned int fd_flags)
+control_handle1(struct dhcpcd_ctx *ctx, int lfd, unsigned int fd_flags,
+    unsigned short events)
 {
        struct sockaddr_un run;
        socklen_t len;
        struct fd_list *l;
        int fd, flags;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        len = sizeof(run);
        if ((fd = accept(lfd, (struct sockaddr *)&run, &len)) == -1)
                goto error;
@@ -249,8 +327,9 @@ control_handle1(struct dhcpcd_ctx *ctx, int lfd, unsigned int fd_flags)
        if (l == NULL)
                goto error;
 
-       if (eloop_event_add(ctx->eloop, l->fd, control_handle_data, l) == -1)
-               logerr(__func__);
+       if (eloop_event_add(ctx->eloop, l->fd, ELE_READ,
+           control_handle_data, l) == -1)
+               logerr("%s: eloop_event_add", __func__);
        return;
 
 error:
@@ -260,19 +339,19 @@ error:
 }
 
 static void
-control_handle(void *arg)
+control_handle(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       control_handle1(ctx, ctx->control_fd, 0);
+       control_handle1(ctx, ctx->control_fd, 0, events);
 }
 
 static void
-control_handle_unpriv(void *arg)
+control_handle_unpriv(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       control_handle1(ctx, ctx->control_unpriv_fd, FD_UNPRIV);
+       control_handle1(ctx, ctx->control_unpriv_fd, FD_UNPRIV, events);
 }
 
 static int
@@ -381,11 +460,15 @@ control_start(struct dhcpcd_ctx *ctx, const char *ifname, sa_family_t family)
                return -1;
 
        ctx->control_fd = fd;
-       eloop_event_add(ctx->eloop, fd, control_handle, ctx);
+       if (eloop_event_add(ctx->eloop, fd, ELE_READ,
+           control_handle, ctx) == -1)
+               logerr("%s: eloop_event_add", __func__);
 
        if ((fd = control_start1(ctx, ifname, family, S_UNPRIV)) != -1) {
                ctx->control_unpriv_fd = fd;
-               eloop_event_add(ctx->eloop, fd, control_handle_unpriv, ctx);
+               if (eloop_event_add(ctx->eloop, fd, ELE_READ,
+                   control_handle_unpriv, ctx) == -1)
+                       logerr("%s: eloop_event_add", __func__);
        }
        return ctx->control_fd;
 }
@@ -490,62 +573,11 @@ control_send(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
        return write(ctx->control_fd, buffer, len);
 }
 
-static void
-control_writeone(void *arg)
-{
-       struct fd_list *fd;
-       struct iovec iov[2];
-       int iov_len;
-       struct fd_data *data;
-
-       fd = arg;
-       data = TAILQ_FIRST(&fd->queue);
-
-       if (data->data_flags & FD_SENDLEN) {
-               iov[0].iov_base = &data->data_len;
-               iov[0].iov_len = sizeof(size_t);
-               iov[1].iov_base = data->data;
-               iov[1].iov_len = data->data_len;
-               iov_len = 2;
-       } else {
-               iov[0].iov_base = data->data;
-               iov[0].iov_len = data->data_len;
-               iov_len = 1;
-       }
-
-       if (writev(fd->fd, iov, iov_len) == -1) {
-               logerr("%s: write", __func__);
-               control_delete(fd);
-               return;
-       }
-
-       TAILQ_REMOVE(&fd->queue, data, next);
-#ifdef CTL_FREE_LIST
-       TAILQ_INSERT_TAIL(&fd->free_queue, data, next);
-#else
-       if (data->data_size != 0)
-               free(data->data);
-       free(data);
-#endif
-
-       if (TAILQ_FIRST(&fd->queue) != NULL)
-               return;
-
-       if (eloop_event_remove_writecb(fd->ctx->eloop, fd->fd) == -1)
-               logerr(__func__);
-#ifdef PRIVSEP
-       if (IN_PRIVSEP_SE(fd->ctx) && !(fd->flags & FD_LISTEN)) {
-               if (ps_ctl_sendeof(fd) == -1)
-                       logerr(__func__);
-               control_free(fd);
-       }
-#endif
-}
-
 int
 control_queue(struct fd_list *fd, void *data, size_t data_len)
 {
        struct fd_data *d;
+       unsigned short events;
 
        if (data_len == 0) {
                errno = EINVAL;
@@ -590,6 +622,9 @@ control_queue(struct fd_list *fd, void *data, size_t data_len)
        d->data_flags = fd->flags & FD_SENDLEN;
 
        TAILQ_INSERT_TAIL(&fd->queue, d, next);
-       eloop_event_add_w(fd->ctx->eloop, fd->fd, control_writeone, fd);
-       return 0;
+       events = ELE_WRITE;
+       if (fd->flags & FD_LISTEN)
+               events |= ELE_READ;
+       return eloop_event_add(fd->ctx->eloop, fd->fd, events,
+           control_handle_data, fd);
 }
index fdd926b7eec1eaff77e6394ff3280817b87a19d4..5b1eb2693ed84be7635f4a3217ddcad7efff4b48 100644 (file)
@@ -137,7 +137,7 @@ static void dhcp_arp_found(struct arp_state *, const struct arp_msg *);
 #endif
 static void dhcp_handledhcp(struct interface *, struct bootp *, size_t,
     const struct in_addr *);
-static void dhcp_handleifudp(void *);
+static void dhcp_handleifudp(void *, unsigned short);
 static int dhcp_initstate(struct interface *);
 
 void
@@ -2406,7 +2406,9 @@ openudp:
                dhcp_openbpf(ifp);
                return;
        }
-       eloop_event_add(ctx->eloop, state->udp_rfd, dhcp_handleifudp, ifp);
+       if (eloop_event_add(ctx->eloop, state->udp_rfd, ELE_READ,
+           dhcp_handleifudp, ifp) == -1)
+               logerr("%s: eloop_event_add", __func__);
 }
 
 static size_t
@@ -3622,7 +3624,7 @@ dhcp_packet(struct interface *ifp, uint8_t *data, size_t len,
 }
 
 static void
-dhcp_readbpf(void *arg)
+dhcp_readbpf(void *arg, unsigned short events)
 {
        struct interface *ifp = arg;
        uint8_t buf[FRAMELEN_MAX];
@@ -3630,6 +3632,9 @@ dhcp_readbpf(void *arg)
        struct dhcp_state *state = D_STATE(ifp);
        struct bpf *bpf = state->bpf;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        bpf->bpf_flags &= ~BPF_EOF;
        while (!(bpf->bpf_flags & BPF_EOF)) {
                bytes = bpf_read(bpf, buf, sizeof(buf));
@@ -3693,7 +3698,8 @@ dhcp_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
 }
 
 static void
-dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp)
+dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp,
+    unsigned short events)
 {
        const struct dhcp_state *state;
        struct sockaddr_in from;
@@ -3721,6 +3727,9 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp)
        int s;
        ssize_t bytes;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        if (ifp != NULL) {
                state = D_CSTATE(ifp);
                s = state->udp_rfd;
@@ -3738,19 +3747,19 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp)
 }
 
 static void
-dhcp_handleudp(void *arg)
+dhcp_handleudp(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       dhcp_readudp(ctx, NULL);
+       dhcp_readudp(ctx, NULL, events);
 }
 
 static void
-dhcp_handleifudp(void *arg)
+dhcp_handleifudp(void *arg, unsigned short events)
 {
        struct interface *ifp = arg;
 
-       dhcp_readudp(ifp->ctx, ifp);
+       dhcp_readudp(ifp->ctx, ifp, events);
 }
 
 static int
@@ -3785,8 +3794,9 @@ dhcp_openbpf(struct interface *ifp)
                return -1;
        }
 
-       eloop_event_add(ifp->ctx->eloop,
-           state->bpf->bpf_fd, dhcp_readbpf, ifp);
+       if (eloop_event_add(ifp->ctx->eloop, state->bpf->bpf_fd, ELE_READ,
+           dhcp_readbpf, ifp) == -1)
+               logerr("%s: eloop_event_add", __func__);
        return 0;
 }
 
@@ -3962,7 +3972,9 @@ dhcp_start1(void *arg)
                        logerr(__func__);
                        return;
                }
-               eloop_event_add(ctx->eloop, ctx->udp_rfd, dhcp_handleudp, ctx);
+               if (eloop_event_add(ctx->eloop, ctx->udp_rfd, ELE_READ,
+                   dhcp_handleudp, ctx) == -1)
+                       logerr("%s: eloop_event_add", __func__);
        }
        if (!IN_PRIVSEP(ctx) && ctx->udp_wfd == -1) {
                ctx->udp_wfd = xsocket(PF_INET, SOCK_RAW|SOCK_CXNB,IPPROTO_UDP);
index a7722f23f1efa95e3d2953f5881df3f383c89a2c..4fd119c579bd55407697e0c3dacb298aec63a8c5 100644 (file)
@@ -173,7 +173,7 @@ static const char * const dhcp6_statuses[] = {
 
 static void dhcp6_bind(struct interface *, const char *, const char *);
 static void dhcp6_failinform(void *);
-static void dhcp6_recvaddr(void *);
+static void dhcp6_recvaddr(void *, unsigned short);
 static void dhcp6_startdecline(struct interface *);
 
 #ifdef SMALL
@@ -2243,8 +2243,8 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid,
                        if (!(a->flags & IPV6_AF_DELEGATEDPFX))
                                a->flags |= IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX;
                        a->flags &= ~(IPV6_AF_STALE |
-                                     IPV6_AF_EXTENDED |
-                                     IPV6_AF_REQUEST);
+                                     IPV6_AF_EXTENDED |
+                                     IPV6_AF_REQUEST);
                        if (a->prefix_vltime != pdp.vltime)
                                a->flags |= IPV6_AF_NEW;
                }
@@ -2396,7 +2396,7 @@ dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l,
                                logwarnx("%s: IAID %s T1(%d) > T2(%d) from %s",
                                    ifp->name,
                                    hwaddr_ntoa(iaid, sizeof(iaid), buf,
-                                               sizeof(buf)),
+                                               sizeof(buf)),
                                    ia.t1, ia.t2, sfrom);
                                continue;
                        }
@@ -2829,7 +2829,7 @@ dhcp6_script_try_run(struct interface *ifp, int delegated)
                if (ap->flags & IPV6_AF_ONLINK) {
                        if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
                            ipv6_iffindaddr(ap->iface, &ap->addr,
-                                           IN6_IFF_TENTATIVE))
+                                           IN6_IFF_TENTATIVE))
                                ap->flags |= IPV6_AF_DADCOMPLETED;
                        if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0
 #ifndef SMALL
@@ -3073,7 +3073,7 @@ dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom)
                if (state->reason == NULL)
                        state->reason = "INFORM6";
                o = dhcp6_findmoption(state->new, state->new_len,
-                                     D6_OPTION_INFO_REFRESH_TIME, &ol);
+                                     D6_OPTION_INFO_REFRESH_TIME, &ol);
                if (o == NULL || ol != sizeof(uint32_t))
                        state->renew = IRT_DEFAULT;
                else {
@@ -3693,7 +3693,7 @@ recvif:
 }
 
 static void
-dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
+dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia, unsigned short events)
 {
        struct sockaddr_in6 from;
        union {
@@ -3715,6 +3715,9 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
        int s;
        ssize_t bytes;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        s = ia != NULL ? ia->dhcp6_fd : ctx->dhcp6_rfd;
        bytes = recvmsg(s, &msg, 0);
        if (bytes == -1) {
@@ -3727,19 +3730,20 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
 }
 
 static void
-dhcp6_recvaddr(void *arg)
+
+dhcp6_recvaddr(void *arg, unsigned short events)
 {
        struct ipv6_addr *ia = arg;
 
-       dhcp6_recv(ia->iface->ctx, ia);
+       dhcp6_recv(ia->iface->ctx, ia, events);
 }
 
 static void
-dhcp6_recvctx(void *arg)
+dhcp6_recvctx(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       dhcp6_recv(ctx, NULL);
+       dhcp6_recv(ctx, NULL, events);
 }
 
 int
@@ -3860,7 +3864,9 @@ dhcp6_start1(void *arg)
                        logerr(__func__);
                        return;
                }
-               eloop_event_add(ctx->eloop, ctx->dhcp6_rfd, dhcp6_recvctx, ctx);
+               if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd, ELE_READ,
+                   dhcp6_recvctx, ctx) == -1)
+                       logerr("%s: eloop_event_add", __func__);
        }
 
        if (!IN_PRIVSEP(ctx) && ctx->dhcp6_wfd == -1) {
@@ -4172,13 +4178,13 @@ dhcp6_handleifa(int cmd, struct ipv6_addr *ia, pid_t pid)
                        if (ia->dhcp6_fd == -1)
                                ia->dhcp6_fd = dhcp6_openudp(ia->iface->index,
                                    &ia->addr);
-                       if (ia->dhcp6_fd != -1)
-                               eloop_event_add(ia->iface->ctx->eloop,
-                               ia->dhcp6_fd, dhcp6_recvaddr, ia);
+                       if (ia->dhcp6_fd != -1 &&
+                           eloop_event_add(ia->iface->ctx->eloop,
+                           ia->dhcp6_fd, ELE_READ, dhcp6_recvaddr, ia) == -1)
+                               logerr("%s: eloop_event_add", __func__);
                }
        }
 
-
        if ((state = D6_STATE(ifp)) != NULL)
                ipv6_handleifa_addrs(cmd, &state->addrs, ia, pid);
 }
@@ -4289,7 +4295,7 @@ dhcp6_env(FILE *fp, const char *prefix, const struct interface *ifp,
 
 delegated:
 #ifndef SMALL
-        /* Needed for Delegated Prefixes */
+       /* Needed for Delegated Prefixes */
        state = D6_CSTATE(ifp);
        TAILQ_FOREACH(ap, &state->addrs, next) {
                if (ap->delegating_prefix)
@@ -4308,7 +4314,7 @@ delegated:
                }
                if (fprintf(fp, "%s", ap->saddr) == -1)
                        return -1;
-        }
+       }
        if (fputc('\0', fp) == EOF)
                return -1;
 #endif
index 8b0e5e63c522142562a176297a09ed9de69a89fc..d23ce3fd0e1b29400f51f42f9d45ab983df056da 100644 (file)
@@ -1110,10 +1110,13 @@ out:
 }
 
 static void
-dhcpcd_handlelink(void *arg)
+dhcpcd_handlelink(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        if (if_handlelink(ctx) == -1) {
                if (errno == ENOBUFS || errno == ENOMEM) {
                        dhcpcd_linkoverflow(ctx);
@@ -1648,15 +1651,18 @@ dumperr:
        return 0;
 }
 
-static void dhcpcd_readdump1(void *);
+static void dhcpcd_readdump1(void *, unsigned short);
 
 static void
-dhcpcd_readdump2(void *arg)
+dhcpcd_readdump2(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
        ssize_t len;
        int exit_code = EXIT_FAILURE;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        len = read(ctx->control_fd, ctx->ctl_buf + ctx->ctl_bufpos,
            ctx->ctl_buflen - ctx->ctl_bufpos);
        if (len == -1) {
@@ -1675,8 +1681,9 @@ dhcpcd_readdump2(void *arg)
        fflush(stdout);
        if (--ctx->ctl_extra != 0) {
                putchar('\n');
-               eloop_event_add(ctx->eloop, ctx->control_fd,
-                   dhcpcd_readdump1, ctx);
+               if (eloop_event_add(ctx->eloop, ctx->control_fd, ELE_READ,
+                   dhcpcd_readdump1, ctx) == -1)
+                       logerr("%s: eloop_event_add", __func__);
                return;
        }
        exit_code = EXIT_SUCCESS;
@@ -1687,11 +1694,14 @@ finished:
 }
 
 static void
-dhcpcd_readdump1(void *arg)
+dhcpcd_readdump1(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
        ssize_t len;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        len = read(ctx->control_fd, &ctx->ctl_buflen, sizeof(ctx->ctl_buflen));
        if (len != sizeof(ctx->ctl_buflen)) {
                if (len != -1)
@@ -1709,8 +1719,9 @@ dhcpcd_readdump1(void *arg)
                goto err;
 
        ctx->ctl_bufpos = 0;
-       eloop_event_add(ctx->eloop, ctx->control_fd,
-           dhcpcd_readdump2, ctx);
+       if (eloop_event_add(ctx->eloop, ctx->control_fd, ELE_READ,
+           dhcpcd_readdump2, ctx) == -1)
+               logerr("%s: eloop_event_add", __func__);
        return;
 
 err:
@@ -1719,11 +1730,14 @@ err:
 }
 
 static void
-dhcpcd_readdump0(void *arg)
+dhcpcd_readdump0(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
        ssize_t len;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        len = read(ctx->control_fd, &ctx->ctl_extra, sizeof(ctx->ctl_extra));
        if (len != sizeof(ctx->ctl_extra)) {
                if (len != -1)
@@ -1738,8 +1752,9 @@ dhcpcd_readdump0(void *arg)
                return;
        }
 
-       eloop_event_add(ctx->eloop, ctx->control_fd,
-           dhcpcd_readdump1, ctx);
+       if (eloop_event_add(ctx->eloop, ctx->control_fd, ELE_READ,
+           dhcpcd_readdump1, ctx) == -1)
+               logerr("%s: eloop_event_add", __func__);
 }
 
 static void
@@ -1759,17 +1774,20 @@ dhcpcd_readdump(struct dhcpcd_ctx *ctx)
        if (eloop_timeout_add_sec(ctx->eloop, 5,
            dhcpcd_readdumptimeout, ctx) == -1)
                return -1;
-       return eloop_event_add(ctx->eloop, ctx->control_fd,
+       return eloop_event_add(ctx->eloop, ctx->control_fd, ELE_READ,
            dhcpcd_readdump0, ctx);
 }
 
 static void
-dhcpcd_fork_cb(void *arg)
+dhcpcd_fork_cb(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
        int exit_code;
        ssize_t len;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        len = read(ctx->fork_fd, &exit_code, sizeof(exit_code));
        if (len == -1) {
                logerr(__func__);
@@ -1786,12 +1804,15 @@ dhcpcd_fork_cb(void *arg)
 }
 
 static void
-dhcpcd_stderr_cb(void *arg)
+dhcpcd_stderr_cb(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
        char log[BUFSIZ];
        ssize_t len;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        len = read(ctx->stderr_fd, log, sizeof(log));
        if (len == -1) {
                if (errno != ECONNRESET)
@@ -2306,7 +2327,9 @@ printpidfile:
                        goto exit_failure;
                }
 #endif
-               eloop_event_add(ctx.eloop, ctx.fork_fd, dhcpcd_fork_cb, &ctx);
+               if (eloop_event_add(ctx.eloop, ctx.fork_fd, ELE_READ,
+                   dhcpcd_fork_cb, &ctx) == -1)
+                       logerr("%s: eloop_event_add", __func__);
 
                /*
                 * Redirect stderr to the stderr socketpair.
@@ -2354,7 +2377,9 @@ printpidfile:
                        goto exit_failure;
                }
 #endif
-               eloop_event_add(ctx.eloop, ctx.fork_fd, dhcpcd_fork_cb, &ctx);
+               if (eloop_event_add(ctx.eloop, ctx.fork_fd, ELE_READ,
+                   dhcpcd_fork_cb, &ctx) == -1)
+                       logerr("%s: eloop_event_add", __func__);
 
                if (ctx.stderr_valid) {
                        ctx.stderr_fd = stderr_fd[0];
@@ -2365,8 +2390,9 @@ printpidfile:
                                goto exit_failure;
                        }
 #endif
-                       eloop_event_add(ctx.eloop, ctx.stderr_fd,
-                           dhcpcd_stderr_cb, &ctx);
+                       if (eloop_event_add(ctx.eloop, ctx.stderr_fd, ELE_READ,
+                           dhcpcd_stderr_cb, &ctx) == -1)
+                               logerr("%s: eloop_event_add", __func__);
                }
 #ifdef PRIVSEP
                if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx, NULL) == -1)
@@ -2448,7 +2474,9 @@ start_master:
 
        /* Start handling kernel messages for interfaces, addresses and
         * routes. */
-       eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx);
+       if (eloop_event_add(ctx.eloop, ctx.link_fd, ELE_READ,
+           dhcpcd_handlelink, &ctx) == -1)
+               logerr("%s: eloop_event_add", __func__);
 
 #ifdef PRIVSEP
        if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx, "stdio route") == -1)
index 16f1b05dce9bada2d2f1412a86ffe8490fdec5d6..ab8d289cfac7f9907dab05e6c7c1cabaa80b09ae 100644 (file)
  * Basically for a small number of fd's (total, not max fd)
  * of say a few hundred, ppoll(2) performs just fine, if not faster than others.
  * It also has the smallest memory and binary size footprint.
- * ppoll(2) is available on all modern OS my software runs on.
+ * ppoll(2) is available on all modern OS my software runs on and should be
+ * an up and coming POSIX standard interface.
  * If ppoll is not available, then pselect(2) can be used instead which has
  * even smaller memory and binary size footprint.
  * However, this difference is quite tiny and the ppoll API is superior.
+ * pselect cannot return error conditions such as EOF for example.
  *
  * Both epoll(7) and kqueue(2) require an extra fd per process to manage
  * their respective list of interest AND syscalls to manage it.
 struct eloop_event {
        TAILQ_ENTRY(eloop_event) next;
        int fd;
-       void (*read_cb)(void *);
-       void *read_cb_arg;
-       void (*write_cb)(void *);
-       void *write_cb_arg;
+       void (*cb)(void *, unsigned short);
+       void *cb_arg;
+       unsigned short events;
 #ifdef HAVE_PPOLL
        struct pollfd *pollfd;
 #endif
@@ -245,73 +246,6 @@ eloop_realloca(void *ptr, size_t n, size_t size)
 }
 #endif
 
-unsigned long long
-eloop_timespec_diff(const struct timespec *tsp, const struct timespec *usp,
-    unsigned int *nsp)
-{
-       unsigned long long tsecs, usecs, secs;
-       long nsecs;
-
-       if (tsp->tv_sec < 0) /* time wreapped */
-               tsecs = UTIME_MAX - (unsigned long long)(-tsp->tv_sec);
-       else
-               tsecs = (unsigned long long)tsp->tv_sec;
-       if (usp->tv_sec < 0) /* time wrapped */
-               usecs = UTIME_MAX - (unsigned long long)(-usp->tv_sec);
-       else
-               usecs = (unsigned long long)usp->tv_sec;
-
-       if (usecs > tsecs) /* time wrapped */
-               secs = (UTIME_MAX - usecs) + tsecs;
-       else
-               secs = tsecs - usecs;
-
-       nsecs = tsp->tv_nsec - usp->tv_nsec;
-       if (nsecs < 0) {
-               if (secs == 0)
-                       nsecs = 0;
-               else {
-                       secs--;
-                       nsecs += NSEC_PER_SEC;
-               }
-       }
-       if (nsp != NULL)
-               *nsp = (unsigned int)nsecs;
-       return secs;
-}
-
-static void
-eloop_reduce_timers(struct eloop *eloop)
-{
-       struct timespec now;
-       unsigned long long secs;
-       unsigned int nsecs;
-       struct eloop_timeout *t;
-
-       clock_gettime(CLOCK_MONOTONIC, &now);
-       secs = eloop_timespec_diff(&now, &eloop->now, &nsecs);
-
-       TAILQ_FOREACH(t, &eloop->timeouts, next) {
-               if (secs > t->seconds) {
-                       t->seconds = 0;
-                       t->nseconds = 0;
-               } else {
-                       t->seconds -= (unsigned int)secs;
-                       if (nsecs > t->nseconds) {
-                               if (t->seconds == 0)
-                                       t->nseconds = 0;
-                               else {
-                                       t->seconds--;
-                                       t->nseconds = NSEC_PER_SEC
-                                           - (nsecs - t->nseconds);
-                               }
-                       } else
-                               t->nseconds -= nsecs;
-               }
-       }
-
-       eloop->now = now;
-}
 
 static int
 eloop_event_setup_fds(struct eloop *eloop)
@@ -348,17 +282,13 @@ eloop_event_setup_fds(struct eloop *eloop)
                        TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
                        continue;
                }
-#ifdef ELOOP_DEBUG
-               fprintf(stderr, "%s(%d) fd=%d, rcb=%p, wcb=%p\n",
-                   __func__, getpid(), e->fd, e->read_cb, e->write_cb);
-#endif
 #ifdef HAVE_PPOLL
                e->pollfd = pfd;
                pfd->fd = e->fd;
                pfd->events = 0;
-               if (e->read_cb != NULL)
+               if (e->events & ELE_READ)
                        pfd->events |= POLLIN;
-               if (e->write_cb != NULL)
+               if (e->events & ELE_WRITE)
                        pfd->events |= POLLOUT;
                pfd->revents = 0;
                pfd++;
@@ -377,14 +307,13 @@ eloop_event_count(const struct eloop *eloop)
 }
 
 int
-eloop_event_add_rw(struct eloop *eloop, int fd,
-    void (*read_cb)(void *), void *read_cb_arg,
-    void (*write_cb)(void *), void *write_cb_arg)
+eloop_event_add(struct eloop *eloop, int fd, unsigned short events,
+    void (*cb)(void *, unsigned short), void *cb_arg)
 {
        struct eloop_event *e;
        bool added;
 #if defined(HAVE_KQUEUE)
-       struct kevent ke[2];
+       struct kevent ke[2], *kep = &ke[0];
        size_t n;
 #elif defined(HAVE_EPOLL)
        struct epoll_event epe;
@@ -392,8 +321,8 @@ eloop_event_add_rw(struct eloop *eloop, int fd,
 #endif
 
        assert(eloop != NULL);
-       assert(read_cb != NULL || write_cb != NULL);
-       if (fd == -1) {
+       assert(cb != NULL && cb_arg != NULL);
+       if (fd == -1 || !(events & (ELE_READ | ELE_WRITE))) {
                errno = EINVAL;
                return -1;
        }
@@ -417,32 +346,28 @@ eloop_event_add_rw(struct eloop *eloop, int fd,
                TAILQ_INSERT_HEAD(&eloop->events, e, next);
                eloop->nevents++;
                e->fd = fd;
-               e->read_cb = read_cb;
-               e->read_cb_arg = read_cb_arg;
-               e->write_cb = write_cb;
-               e->write_cb_arg = write_cb_arg;
-               goto setup;
+               e->events = 0;
        } else
                added = false;
 
-       if (read_cb != NULL) {
-               e->read_cb = read_cb;
-               e->read_cb_arg = read_cb_arg;
-       }
-       if (write_cb != NULL) {
-               e->write_cb = write_cb;
-               e->write_cb_arg = write_cb_arg;
-       }
+       e->cb = cb;
+       e->cb_arg = cb_arg;
 
-setup:
 #if defined(HAVE_KQUEUE)
-       EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, EV_ADD, 0, 0, e);
-       if (e->write_cb != NULL) {
-               EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, EV_ADD, 0, 0, e);
-               n = 2;
-       } else
-               n = 1;
-       if (_kevent(eloop->fd, ke, n, NULL, 0, NULL) == -1) {
+       n = 2;
+       if (events & ELE_READ && !(e->events & ELE_READ))
+               EV_SET(kep++, (uintptr_t)fd, EVFILT_READ, EV_ADD, 0, 0, e);
+       else if (!(events & ELE_READ) && e->events & ELE_READ)
+               EV_SET(kep++, (uintptr_t)fd, EVFILT_READ, EV_DELETE, 0, 0, e);
+       else
+               n--;
+       if (events & ELE_WRITE && !(e->events & ELE_WRITE))
+               EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_ADD, 0, 0, e);
+       else if (!(events & ELE_WRITE) && e->events & ELE_WRITE)
+               EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_DELETE, 0, 0, e);
+       else
+               n--;
+       if (n != 0 && _kevent(eloop->fd, ke, n, NULL, 0, NULL) == -1) {
                if (added) {
                        TAILQ_REMOVE(&eloop->events, e, next);
                        TAILQ_INSERT_TAIL(&eloop->free_events, e, next);
@@ -452,9 +377,9 @@ setup:
 #elif defined(HAVE_EPOLL)
        memset(&epe, 0, sizeof(epe));
        epe.data.ptr = e;
-       if (e->read_cb != NULL)
+       if (e->events & ELE_READ)
                epe.events |= EPOLLIN;
-       if (e->write_cb != NULL)
+       if (e->events & ELE_WRITE)
                epe.events |= EPOLLOUT;
 
        op = added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
@@ -471,32 +396,15 @@ setup:
 #else
        UNUSED(added);
 #endif
+       e->events = events;
        eloop->events_need_setup = true;
        return 0;
 }
 
 int
-eloop_event_add(struct eloop *eloop, int fd,
-    void (*read_cb)(void *), void *read_cb_arg)
-{
-
-       return eloop_event_add_rw(eloop, fd, read_cb, read_cb_arg, NULL, NULL);
-}
-
-int
-eloop_event_add_w(struct eloop *eloop, int fd,
-    void (*write_cb)(void *), void *write_cb_arg)
-{
-
-       return eloop_event_add_rw(eloop, fd, NULL,NULL, write_cb, write_cb_arg);
-}
-
-int
-eloop_event_delete_write(struct eloop *eloop, int fd, int write_only)
+eloop_event_delete(struct eloop *eloop, int fd)
 {
        struct eloop_event *e;
-#ifdef HAVE_KQUEUE
-#endif
 
        assert(eloop != NULL);
        if (fd == -1) {
@@ -513,44 +421,78 @@ eloop_event_delete_write(struct eloop *eloop, int fd, int write_only)
                return -1;
        }
 
-       if (write_only) {
-#if defined(HAVE_KQUEUE)
-               if (e->write_cb != NULL) {
-                       struct kevent ke;
+       e->fd = -1;
+       eloop->nevents--;
+       eloop->events_need_setup = true;
+       return 1;
+}
 
-                       EV_SET(&ke, (uintptr_t)e->fd,
-                           EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
-                       if (_kevent(eloop->fd, &ke, 1, NULL, 0, NULL) == -1)
-                               return -1;
-               }
-#elif defined(HAVE_EPOLL)
-               if (e->write_cb != NULL) {
-                       struct epoll_event epe;
-
-                       memset(&epe, 0, sizeof(epe));
-                       epe.data.ptr = e;
-                       if (e->read_cb != NULL)
-                           epe.events |= EPOLLIN;
-                       if (epoll_ctl(eloop->fd,
-                           e->read_cb != NULL ? EPOLL_CTL_MOD : EPOLL_CTL_DEL,
-                           e->fd, &epe) == -1)
-                               return -1;
+unsigned long long
+eloop_timespec_diff(const struct timespec *tsp, const struct timespec *usp,
+    unsigned int *nsp)
+{
+       unsigned long long tsecs, usecs, secs;
+       long nsecs;
+
+       if (tsp->tv_sec < 0) /* time wreapped */
+               tsecs = UTIME_MAX - (unsigned long long)(-tsp->tv_sec);
+       else
+               tsecs = (unsigned long long)tsp->tv_sec;
+       if (usp->tv_sec < 0) /* time wrapped */
+               usecs = UTIME_MAX - (unsigned long long)(-usp->tv_sec);
+       else
+               usecs = (unsigned long long)usp->tv_sec;
+
+       if (usecs > tsecs) /* time wrapped */
+               secs = (UTIME_MAX - usecs) + tsecs;
+       else
+               secs = tsecs - usecs;
+
+       nsecs = tsp->tv_nsec - usp->tv_nsec;
+       if (nsecs < 0) {
+               if (secs == 0)
+                       nsecs = 0;
+               else {
+                       secs--;
+                       nsecs += NSEC_PER_SEC;
                }
-#elif defined(HAVE_PPOLL)
-               if (e->pollfd != NULL) {
-                       e->pollfd->events &= ~POLLOUT;
-                       e->pollfd->revents &= ~POLLOUT;
+       }
+       if (nsp != NULL)
+               *nsp = (unsigned int)nsecs;
+       return secs;
+}
+
+static void
+eloop_reduce_timers(struct eloop *eloop)
+{
+       struct timespec now;
+       unsigned long long secs;
+       unsigned int nsecs;
+       struct eloop_timeout *t;
+
+       clock_gettime(CLOCK_MONOTONIC, &now);
+       secs = eloop_timespec_diff(&now, &eloop->now, &nsecs);
+
+       TAILQ_FOREACH(t, &eloop->timeouts, next) {
+               if (secs > t->seconds) {
+                       t->seconds = 0;
+                       t->nseconds = 0;
+               } else {
+                       t->seconds -= (unsigned int)secs;
+                       if (nsecs > t->nseconds) {
+                               if (t->seconds == 0)
+                                       t->nseconds = 0;
+                               else {
+                                       t->seconds--;
+                                       t->nseconds = NSEC_PER_SEC
+                                           - (nsecs - t->nseconds);
+                               }
+                       } else
+                               t->nseconds -= nsecs;
                }
-#endif
-               e->write_cb = NULL;
-               e->write_cb_arg = NULL;
-               return 0;
        }
 
-       e->fd = -1;
-       eloop->nevents--;
-       eloop->events_need_setup = true;
-       return 1;
+       eloop->now = now;
 }
 
 /*
@@ -734,12 +676,12 @@ eloop_forked(struct eloop *eloop)
                if (e->fd == -1)
                        continue;
 #if defined(HAVE_KQUEUE)
-               if (e->read_cb != NULL) {
+               if (e->events & ELE_READ) {
                        EV_SET(pfd++, (uintptr_t)e->fd,
                            EVFILT_READ, EV_ADD, 0, 0, e);
                        i++;
                }
-               if (e->write_cb != NULL) {
+               if (e->events & ELE_WRITE) {
                        EV_SET(pfd++, (uintptr_t)e->fd,
                            EVFILT_WRITE, EV_ADD, 0, 0, e);
                        i++;
@@ -1006,6 +948,7 @@ eloop_run_kqueue(struct eloop *eloop, const struct timespec *ts)
        int n, nn;
        struct kevent *ke;
        struct eloop_event *e;
+       unsigned short events;
 
        n = _kevent(eloop->fd, NULL, 0, eloop->fds, eloop->nevents, ts);
        if (n == -1)
@@ -1015,25 +958,22 @@ eloop_run_kqueue(struct eloop *eloop, const struct timespec *ts)
                if (eloop->cleared)
                        break;
                e = (struct eloop_event *)ke->udata;
-#if 0
-               /* What to do with this?
-                * Currently we behave like ppoll and just try the
-                * socket and get the error there. */
-               if (ke->flags & EV_ERROR)
-                       errno = (int)ke->data;
-#endif
-               switch (ke->filter) {
-               case EVFILT_SIGNAL:
+               if (ke->filter == EVFILT_SIGNAL) {
                        eloop->signal_cb((int)ke->ident,
                            eloop->signal_cb_ctx);
-                       break;
-               case EVFILT_WRITE:
-                       e->write_cb(e->write_cb_arg);
-                       break;
-               case EVFILT_READ:
-                       e->read_cb(e->read_cb_arg);
-                       break;
+                       continue;
                }
+               if (ke->filter == EVFILT_READ)
+                       events = ELE_READ;
+               else if (ke->filter == EVFILT_WRITE)
+                       events = ELE_WRITE;
+               else
+                       continue; /* assert? */
+               if (ke->flags & EV_EOF)
+                       events |= ELE_HANGUP;
+               if (ke->flags & EV_ERROR)
+                       events |= ELE_ERROR;
+               e->cb(e->cb_arg, events);
        }
        return n;
 }
@@ -1047,6 +987,7 @@ eloop_run_epoll(struct eloop *eloop,
        int timeout, n, nn;
        struct epoll_event *epe;
        struct eloop_event *e;
+       unsigned short events;
 
        if (ts != NULL) {
                if (ts->tv_sec > INT_MAX / 1000 ||
@@ -1072,12 +1013,18 @@ eloop_run_epoll(struct eloop *eloop,
                if (eloop->cleared)
                        break;
                e = (struct eloop_event *)epe->data.ptr;
-               if (epe->events & EPOLLOUT &&
-                   e->fd != -1 && e->write_cb != NULL)
-                       e->write_cb(e->write_cb_arg);
-               if (epe->events & (EPOLLIN | EPOLLERR | EPOLLHUP) &&
-                   e->fd != -1 && e->read_cb != NULL)
-                       e->read_cb(e->read_cb_arg);
+               if (e->fd == -1)
+                       continue;
+               events = 0;
+               if (epe->events & EPOLLIN)
+                       events |= ELE_READ;
+               if (epe->events & EPOLLOUT)
+                       events |= ELE_WRITE;
+               if (epe->events & EPOLLHUP)
+                       events |= ELE_HANGUP;
+               if (epe->events & EPOLLERR)
+                       events |= ELE_ERROR;
+               e->cb(e->cb_arg, events);
        }
        return n;
 }
@@ -1090,6 +1037,8 @@ eloop_run_ppoll(struct eloop *eloop,
 {
        int n, nn;
        struct eloop_event *e;
+       struct pollfd *pfd;
+       unsigned short events;
 
        n = ppoll(eloop->fds, (nfds_t)eloop->nevents, ts, signals);
        if (n == -1 || n == 0)
@@ -1100,17 +1049,24 @@ eloop_run_ppoll(struct eloop *eloop,
                if (eloop->cleared)
                        break;
                /* Skip freshly added events */
-               if (e->pollfd == NULL)
+               if ((pfd = e->pollfd) == NULL)
                        continue;
-               if (e->pollfd->revents)
+               if (e->pollfd->revents) {
                        nn--;
-               if (e->fd != -1 && e->pollfd->revents & POLLOUT &&
-                   e->write_cb != NULL)
-                       e->write_cb(e->write_cb_arg);
-               if (e->fd != -1 &&
-                   e->pollfd != NULL && e->pollfd->revents &&
-                   e->read_cb != NULL)
-                       e->read_cb(e->read_cb_arg);
+                       events = 0;
+                       if (pfd->revents & POLLIN)
+                               events |= ELE_READ;
+                       if (pfd->revents & POLLOUT)
+                               events |= ELE_WRITE;
+                       if (pfd->revents & POLLHUP)
+                               events |= ELE_HANGUP;
+                       if (pfd->revents & POLLERR)
+                               events |= ELE_ERROR;
+                       if (pfd->revents & POLLNVAL)
+                               events |= ELE_NVAL;
+                       if (events)
+                               e->cb(e->cb_arg, events);
+               }
                if (nn == 0)
                        break;
        }
@@ -1126,6 +1082,7 @@ eloop_run_pselect(struct eloop *eloop,
        fd_set read_fds, write_fds;
        int maxfd, n;
        struct eloop_event *e;
+       unsigned short events;
 
        FD_ZERO(&read_fds);
        FD_ZERO(&write_fds);
@@ -1133,18 +1090,19 @@ eloop_run_pselect(struct eloop *eloop,
        TAILQ_FOREACH(e, &eloop->events, next) {
                if (e->fd == -1)
                        continue;
-               if (e->read_cb != NULL) {
+               if (e->events & ELE_READ) {
                        FD_SET(e->fd, &read_fds);
                        if (e->fd > maxfd)
                                maxfd = e->fd;
                }
-               if (e->write_cb != NULL) {
+               if (e->events & ELE_WRITE) {
                        FD_SET(e->fd, &write_fds);
                        if (e->fd > maxfd)
                                maxfd = e->fd;
                }
        }
 
+       /* except_fd's is for STREAMS devices which we don't use. */
        n = pselect(maxfd + 1, &read_fds, &write_fds, NULL, ts, sigmask);
        if (n == -1 || n == 0)
                return n;
@@ -1154,10 +1112,13 @@ eloop_run_pselect(struct eloop *eloop,
                        break;
                if (e->fd == -1)
                        continue;
-               if (e->write_cb != NULL && FD_ISSET(e->fd, &write_fds))
-                       e->write_cb(e->write_cb_arg);
-               if (e->read_cb != NULL && FD_ISSET(e->fd, &read_fds))
-                       e->read_cb(e->read_cb_arg);
+               events = 0;
+               if (FD_ISSET(e->fd, &read_fds))
+                       events |= ELE_READ;
+               if (FD_ISSET(e->fd, &write_fds))
+                       events |= ELE_WRITE;
+               if (events)
+                       e->cb(e->cb_arg, events);
        }
 
        return n;
@@ -1172,7 +1133,7 @@ eloop_start(struct eloop *eloop, sigset_t *signals)
        struct timespec ts, *tsp;
 
        assert(eloop != NULL);
-#if defined(HAVE_KQUEUE)
+#ifdef HAVE_KQUEUE
        UNUSED(signals);
 #endif
 
index a86d825c67d02dec4f260f2b9231d7a61cf0f36c..27f95bae1e9cd3a366ee1f6ecc98a830116c5b60 100644 (file)
 /* Forward declare eloop - the content should be invisible to the outside */
 struct eloop;
 
-unsigned long long eloop_timespec_diff(const struct timespec *tsp,
-    const struct timespec *usp, unsigned int *nsp);
+#define        ELE_READ        0x0001
+#define        ELE_WRITE       0x0002
+#define        ELE_ERROR       0x0100
+#define        ELE_HANGUP      0x0200
+#define        ELE_NVAL        0x0400
+
 size_t eloop_event_count(const struct eloop  *);
-int eloop_event_add_rw(struct eloop *, int,
-    void (*)(void *), void *,
-    void (*)(void *), void *);
-int eloop_event_add(struct eloop *, int,
-    void (*)(void *), void *);
-int eloop_event_add_w(struct eloop *, int,
-    void (*)(void *), void *);
-#define eloop_event_delete(eloop, fd) \
-    eloop_event_delete_write((eloop), (fd), 0)
-#define eloop_event_remove_writecb(eloop, fd) \
-    eloop_event_delete_write((eloop), (fd), 1)
-int eloop_event_delete_write(struct eloop *, int, int);
+int eloop_event_add(struct eloop *, int, unsigned short,
+    void (*)(void *, unsigned short), void *);
+int eloop_event_delete(struct eloop *, int);
 
+unsigned long long eloop_timespec_diff(const struct timespec *tsp,
+    const struct timespec *usp, unsigned int *nsp);
 #define eloop_timeout_add_tv(eloop, tv, cb, ctx) \
     eloop_q_timeout_add_tv((eloop), ELOOP_QUEUE, (tv), (cb), (ctx))
 #define eloop_timeout_add_sec(eloop, tv, cb, ctx) \
index b0174a775de6b93c2811260b3dfd98b3025352fb..4b9c735df44d3442007665ed95732958e079b4b0 100644 (file)
@@ -78,7 +78,7 @@ struct nd_opt_rdnss {           /* RDNSS option RFC 6106 */
        uint8_t         nd_opt_rdnss_len;
        uint16_t        nd_opt_rdnss_reserved;
        uint32_t        nd_opt_rdnss_lifetime;
-        /* followed by list of IP prefixes */
+       /* followed by list of IP prefixes */
 };
 __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
 #endif
@@ -131,7 +131,7 @@ __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
 //#define DEBUG_NS
 //
 
-static void ipv6nd_handledata(void *);
+static void ipv6nd_handledata(void *, unsigned short);
 
 /*
  * Android ships buggy ICMP6 filter headers.
@@ -281,8 +281,14 @@ ipv6nd_openif(struct interface *ifp)
                return -1;
        }
 
+       if (eloop_event_add(ifp->ctx->eloop, fd, ELE_READ,
+           ipv6nd_handledata, ifp) == -1)
+       {
+               close(fd);
+               return -1;
+       }
+
        state->nd_fd = fd;
-       eloop_event_add(ifp->ctx->eloop, fd, ipv6nd_handledata, ifp);
        return fd;
 }
 #endif
@@ -388,7 +394,9 @@ ipv6nd_sendrsprobe(void *arg)
                        logerr(__func__);
                        return;
                }
-               eloop_event_add(ctx->eloop, ctx->nd_fd, ipv6nd_handledata, ctx);
+               if (eloop_event_add(ctx->eloop, ctx->nd_fd, ELE_READ,
+                   ipv6nd_handledata, ctx) == -1)
+                       logerr("%s: eloop_event_add", __func__);
        }
        s = ifp->ctx->nd_fd;
 #endif
@@ -1977,7 +1985,7 @@ ipv6nd_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
 }
 
 static void
-ipv6nd_handledata(void *arg)
+ipv6nd_handledata(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx;
        int fd;
@@ -2013,6 +2021,10 @@ ipv6nd_handledata(void *arg)
        ctx = arg;
        fd = ctx->nd_fd;
 #endif
+
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        len = recvmsg(fd, &msg, 0);
        if (len == -1) {
                logerr(__func__);
index f402ea18307108b8cf50fe1e75bdc06fcab8b4e6..f0088568466c9018fc2b616c787bfdb2d857895b 100644 (file)
@@ -54,7 +54,7 @@
 #include "privsep.h"
 
 static void
-ps_bpf_recvbpf(void *arg)
+ps_bpf_recvbpf(void *arg, unsigned short events)
 {
        struct ps_process *psp = arg;
        struct bpf *bpf = psp->psp_bpf;
@@ -65,6 +65,9 @@ ps_bpf_recvbpf(void *arg)
                .ps_cmd = psp->psp_id.psi_cmd,
        };
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        bpf->bpf_flags &= ~BPF_EOF;
        /* A BPF read can read more than one filtered packet at time.
         * This mechanism allows us to read each packet from the buffer. */
@@ -131,11 +134,11 @@ ps_bpf_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
 }
 
 static void
-ps_bpf_recvmsg(void *arg)
+ps_bpf_recvmsg(void *arg, unsigned short events)
 {
        struct ps_process *psp = arg;
 
-       if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd,
+       if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events,
            ps_bpf_recvmsgcb, arg) == -1)
                logerr(__func__);
 }
@@ -164,8 +167,8 @@ ps_bpf_start_bpf(void *arg)
        else if (ps_rights_limit_fd(psp->psp_bpf->bpf_fd) == -1)
                logerr("%s: ps_rights_limit_fd", __func__);
 #endif
-       else if (eloop_event_add(ctx->eloop,
-           psp->psp_bpf->bpf_fd, ps_bpf_recvbpf, psp) == -1)
+       else if (eloop_event_add(ctx->eloop, psp->psp_bpf->bpf_fd, ELE_READ,
+           ps_bpf_recvbpf, psp) == -1)
                logerr("%s: eloop_event_add", __func__);
        else {
                psp->psp_work_fd = psp->psp_bpf->bpf_fd;
index f5f8cfdd3502619010502531ec37c3220204a040..389c5ad2f804b75c9d7175c6778994750116caba 100644 (file)
@@ -82,11 +82,12 @@ ps_ctl_recvmsgcb(void *arg, struct ps_msghdr *psm, __unused struct msghdr *msg)
 }
 
 static void
-ps_ctl_recvmsg(void *arg)
+ps_ctl_recvmsg(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       if (ps_recvpsmsg(ctx, ctx->ps_control_fd, ps_ctl_recvmsgcb, ctx) == -1)
+       if (ps_recvpsmsg(ctx, ctx->ps_control_fd, events,
+           ps_ctl_recvmsgcb, ctx) == -1)
                logerr(__func__);
 }
 
@@ -161,21 +162,25 @@ ps_ctl_dispatch(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
 }
 
 static void
-ps_ctl_dodispatch(void *arg)
+ps_ctl_dodispatch(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       if (ps_recvpsmsg(ctx, ctx->ps_control_fd, ps_ctl_dispatch, ctx) == -1)
+       if (ps_recvpsmsg(ctx, ctx->ps_control_fd, events,
+           ps_ctl_dispatch, ctx) == -1)
                logerr(__func__);
 }
 
 static void
-ps_ctl_recv(void *arg)
+ps_ctl_recv(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
        char buf[BUFSIZ];
        ssize_t len;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        errno = 0;
        len = read(ctx->ps_control_data_fd, buf, sizeof(buf));
        if (len == -1 || len == 0) {
@@ -191,13 +196,16 @@ ps_ctl_recv(void *arg)
 }
 
 static void
-ps_ctl_listen(void *arg)
+ps_ctl_listen(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
        char buf[BUFSIZ];
        ssize_t len;
        struct fd_list *fd;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        errno = 0;
        len = read(ctx->ps_control->fd, buf, sizeof(buf));
        if (len == -1 || len == 0) {
@@ -250,7 +258,7 @@ ps_ctl_start(struct dhcpcd_ctx *ctx)
 
        ctx->ps_control_data_fd = data_fd[0];
        close(data_fd[1]);
-       if (eloop_event_add(ctx->eloop, ctx->ps_control_data_fd,
+       if (eloop_event_add(ctx->eloop, ctx->ps_control_data_fd, ELE_READ,
            ps_ctl_recv, ctx) == -1)
                return -1;
 
@@ -259,7 +267,7 @@ ps_ctl_start(struct dhcpcd_ctx *ctx)
        close(listen_fd[1]);
        if (ctx->ps_control == NULL)
                return -1;
-       if (eloop_event_add(ctx->eloop, ctx->ps_control->fd,
+       if (eloop_event_add(ctx->eloop, ctx->ps_control->fd, ELE_READ,
            ps_ctl_listen, ctx) == -1)
                return -1;
 
index b98e19adf3ffa8cc9ccc6c624f58af869cae4040..bad4ea10311416afccd371654f5dfe9fb6e1ca49 100644 (file)
 
 #ifdef INET
 static void
-ps_inet_recvbootp(void *arg)
+ps_inet_recvbootp(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       if (ps_recvmsg(ctx, ctx->udp_rfd, PS_BOOTP, ctx->ps_inet_fd) == -1)
+       if (ps_recvmsg(ctx, ctx->udp_rfd, events,
+           PS_BOOTP, ctx->ps_inet_fd) == -1)
                logerr(__func__);
 }
 #endif
 
 #ifdef INET6
 static void
-ps_inet_recvra(void *arg)
+ps_inet_recvra(void *arg, unsigned short events)
 {
 #ifdef __sun
        struct interface *ifp = arg;
        struct rs_state *state = RS_STATE(ifp);
        struct dhcpcd_ctx *ctx = ifp->ctx;
 
-       if (ps_recvmsg(ctx, state->nd_fd, PS_ND, ctx->ps_inet_fd) == -1)
+       if (ps_recvmsg(ctx, state->nd_fd, events,
+           PS_ND, ctx->ps_inet_fd) == -1)
                logerr(__func__);
 #else
        struct dhcpcd_ctx *ctx = arg;
 
-       if (ps_recvmsg(ctx, ctx->nd_fd, PS_ND, ctx->ps_inet_fd) == -1)
+       if (ps_recvmsg(ctx, ctx->nd_fd, events,
+           PS_ND, ctx->ps_inet_fd) == -1)
                logerr(__func__);
 #endif
 }
@@ -80,11 +83,12 @@ ps_inet_recvra(void *arg)
 
 #ifdef DHCP6
 static void
-ps_inet_recvdhcp6(void *arg)
+ps_inet_recvdhcp6(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       if (ps_recvmsg(ctx, ctx->dhcp6_rfd, PS_DHCP6, ctx->ps_inet_fd) == -1)
+       if (ps_recvmsg(ctx, ctx->dhcp6_rfd, events,
+           PS_DHCP6, ctx->ps_inet_fd) == -1)
                logerr(__func__);
 }
 #endif
@@ -145,7 +149,7 @@ ps_inet_startcb(void *arg)
                        ctx->udp_rfd = -1;
                }
 #endif
-               else if (eloop_event_add(ctx->eloop, ctx->udp_rfd,
+               else if (eloop_event_add(ctx->eloop, ctx->udp_rfd, ELE_READ,
                    ps_inet_recvbootp, ctx) == -1)
                {
                        logerr("%s: eloop_event_add DHCP", __func__);
@@ -167,7 +171,7 @@ ps_inet_startcb(void *arg)
                        ctx->nd_fd = -1;
                }
 #endif
-               else if (eloop_event_add(ctx->eloop, ctx->nd_fd,
+               else if (eloop_event_add(ctx->eloop, ctx->nd_fd, ELE_READ,
                    ps_inet_recvra, ctx) == -1)
                {
                        logerr("%s: eloop_event_add RA", __func__);
@@ -191,7 +195,7 @@ ps_inet_startcb(void *arg)
                        ctx->dhcp6_rfd = -1;
                }
 #endif
-               else if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd,
+               else if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd, ELE_READ,
                    ps_inet_recvdhcp6, ctx) == -1)
                {
                        logerr("%s: eloop_event_add DHCP6", __func__);
@@ -299,12 +303,12 @@ dosend:
 }
 
 static void
-ps_inet_recvmsg(void *arg)
+ps_inet_recvmsg(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
        /* Receive shutdown */
-       if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, NULL, NULL) == -1)
+       if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, events, NULL, NULL) == -1)
                logerr(__func__);
 }
 
@@ -337,11 +341,12 @@ ps_inet_dispatch(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
 }
 
 static void
-ps_inet_dodispatch(void *arg)
+ps_inet_dodispatch(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, ps_inet_dispatch, ctx) == -1)
+       if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, events,
+           ps_inet_dispatch, ctx) == -1)
                logerr(__func__);
 }
 
@@ -370,11 +375,11 @@ ps_inet_stop(struct dhcpcd_ctx *ctx)
 
 #ifdef INET
 static void
-ps_inet_recvinbootp(void *arg)
+ps_inet_recvinbootp(void *arg, unsigned short events)
 {
        struct ps_process *psp = arg;
 
-       if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd,
+       if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd, events,
            PS_BOOTP, psp->psp_ctx->ps_data_fd) == -1)
                logerr(__func__);
 }
@@ -402,7 +407,7 @@ ps_inet_listenin(void *arg)
        }
 #endif
 
-       if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd,
+       if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, ELE_READ,
            ps_inet_recvinbootp, psp) == -1)
        {
                logerr("%s: eloop_event_add DHCP", __func__);
@@ -459,11 +464,11 @@ ps_inet_listennd(void *arg)
 
 #ifdef DHCP6
 static void
-ps_inet_recvin6dhcp6(void *arg)
+ps_inet_recvin6dhcp6(void *arg, unsigned short events)
 {
        struct ps_process *psp = arg;
 
-       if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd,
+       if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd, events,
            PS_DHCP6, psp->psp_ctx->ps_data_fd) == -1)
                logerr(__func__);
 }
@@ -491,7 +496,7 @@ ps_inet_listenin6(void *arg)
        }
 #endif
 
-       if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd,
+       if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, ELE_READ,
            ps_inet_recvin6dhcp6, psp) == -1)
        {
                logerr("%s: eloop_event_add DHCP", __func__);
@@ -504,12 +509,12 @@ ps_inet_listenin6(void *arg)
 #endif
 
 static void
-ps_inet_recvmsgpsp(void *arg)
+ps_inet_recvmsgpsp(void *arg, unsigned short events)
 {
        struct ps_process *psp = arg;
 
        /* Receive shutdown. */
-       if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, NULL, NULL) == -1)
+       if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events, NULL, NULL) == -1)
                logerr(__func__);
 }
 
index adcbd640cfcade893f095b2aebcb5aa20086c2c8..03f682661a91cd12a5ea63bd3293769f5852e64d 100644 (file)
@@ -74,7 +74,7 @@ struct psr_ctx {
 };
 
 static void
-ps_root_readerrorcb(void *arg)
+ps_root_readerrorcb(void *arg, unsigned short events)
 {
        struct psr_ctx *psr_ctx = arg;
        struct dhcpcd_ctx *ctx = psr_ctx->psr_ctx;
@@ -87,6 +87,9 @@ ps_root_readerrorcb(void *arg)
        ssize_t len;
        int exit_code = EXIT_FAILURE;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
 #define PSR_ERROR(e)                           \
        do {                                    \
                psr_error->psr_result = -1;     \
@@ -113,7 +116,7 @@ ps_root_readerror(struct dhcpcd_ctx *ctx, void *data, size_t len)
            .psr_data = data, .psr_datalen = len,
        };
 
-       if (eloop_event_add(ctx->ps_eloop, ctx->ps_root_fd,
+       if (eloop_event_add(ctx->ps_eloop, ctx->ps_root_fd, ELE_READ,
            ps_root_readerrorcb, &psr_ctx) == -1)
                return -1;
 
@@ -126,7 +129,7 @@ ps_root_readerror(struct dhcpcd_ctx *ctx, void *data, size_t len)
 
 #ifdef PRIVSEP_GETIFADDRS
 static void
-ps_root_mreaderrorcb(void *arg)
+ps_root_mreaderrorcb(void *arg, unsigned short events)
 {
        struct psr_ctx *psr_ctx = arg;
        struct dhcpcd_ctx *ctx = psr_ctx->psr_ctx;
@@ -138,6 +141,9 @@ ps_root_mreaderrorcb(void *arg)
        ssize_t len;
        int exit_code = EXIT_FAILURE;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        len = recv(ctx->ps_root_fd, psr_error, sizeof(*psr_error), MSG_PEEK);
        if (len == -1)
                PSR_ERROR(errno);
@@ -605,11 +611,12 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
 
 /* Receive from state engine, do an action. */
 static void
-ps_root_recvmsg(void *arg)
+ps_root_recvmsg(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       if (ps_recvpsmsg(ctx, ctx->ps_root_fd, ps_root_recvmsgcb, ctx) == -1)
+       if (ps_recvpsmsg(ctx, ctx->ps_root_fd, events,
+           ps_root_recvmsgcb, ctx) == -1)
                logerr(__func__);
 }
 
@@ -775,19 +782,23 @@ ps_root_dispatchcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
 }
 
 static void
-ps_root_dispatch(void *arg)
+ps_root_dispatch(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       if (ps_recvpsmsg(ctx, ctx->ps_data_fd, ps_root_dispatchcb, ctx) == -1)
+       if (ps_recvpsmsg(ctx, ctx->ps_data_fd, events,
+           ps_root_dispatchcb, ctx) == -1)
                logerr(__func__);
 }
 
 static void
-ps_root_log(void *arg)
+ps_root_log(void *arg, unsigned short events)
 {
        struct dhcpcd_ctx *ctx = arg;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        /* OpenBSD reports connection reset when dhcpcd exits ... */
        if (logreadfd(ctx->ps_log_fd) == -1 && errno != ECONNRESET)
                logerr(__func__);
@@ -821,7 +832,7 @@ ps_root_start(struct dhcpcd_ctx *ctx)
 
        if (pid == 0) {
                ctx->ps_log_fd = logfd[1];
-               if (eloop_event_add(ctx->eloop, ctx->ps_log_fd,
+               if (eloop_event_add(ctx->eloop, ctx->ps_log_fd, ELE_READ,
                    ps_root_log, ctx) == -1)
                        return -1;
                close(logfd[0]);
@@ -836,7 +847,7 @@ ps_root_start(struct dhcpcd_ctx *ctx)
 
        ctx->ps_data_fd = datafd[0];
        close(datafd[1]);
-       if (eloop_event_add(ctx->eloop, ctx->ps_data_fd,
+       if (eloop_event_add(ctx->eloop, ctx->ps_data_fd, ELE_READ,
            ps_root_dispatch, ctx) == -1)
                return -1;
 
index 01a5d308351f953494388115c37f2a2425532dd1..52599df12914fded7c72fd5b147ffacc3ee9cb6b 100644 (file)
@@ -320,7 +320,8 @@ ps_rights_limit_stdio(struct dhcpcd_ctx *ctx)
 pid_t
 ps_dostart(struct dhcpcd_ctx *ctx,
     pid_t *priv_pid, int *priv_fd,
-    void (*recv_msg)(void *), void (*recv_unpriv_msg),
+    void (*recv_msg)(void *, unsigned short),
+    void (*recv_unpriv_msg)(void *, unsigned short),
     void *recv_ctx, int (*callback)(void *), void (*signal_cb)(int, void *),
     unsigned int flags)
 {
@@ -356,7 +357,7 @@ ps_dostart(struct dhcpcd_ctx *ctx,
                close(fd[1]);
                if (recv_unpriv_msg == NULL)
                        ;
-               else if (eloop_event_add(ctx->eloop, *priv_fd,
+               else if (eloop_event_add(ctx->eloop, *priv_fd, ELE_READ,
                    recv_unpriv_msg, recv_ctx) == -1)
                {
                        logerr("%s: eloop_event_add", __func__);
@@ -404,7 +405,8 @@ ps_dostart(struct dhcpcd_ctx *ctx,
                ctx->ps_inet_fd = -1;
        }
 
-       if (eloop_event_add(ctx->eloop, *priv_fd, recv_msg, recv_ctx) == -1)
+       if (eloop_event_add(ctx->eloop, *priv_fd, ELE_READ,
+           recv_msg, recv_ctx) == -1)
        {
                logerr("%s: eloop_event_add", __func__);
                goto errexit;
@@ -865,7 +867,8 @@ nobufs:
 }
 
 ssize_t
-ps_recvmsg(struct dhcpcd_ctx *ctx, int rfd, uint16_t cmd, int wfd)
+ps_recvmsg(struct dhcpcd_ctx *ctx, int rfd, unsigned short events,
+    uint16_t cmd, int wfd)
 {
        struct sockaddr_storage ss = { .ss_family = AF_UNSPEC };
        uint8_t controlbuf[sizeof(struct sockaddr_storage)] = { 0 };
@@ -878,8 +881,12 @@ ps_recvmsg(struct dhcpcd_ctx *ctx, int rfd, uint16_t cmd, int wfd)
                .msg_control = controlbuf, .msg_controllen = sizeof(controlbuf),
                .msg_iov = iov, .msg_iovlen = 1,
        };
+       ssize_t len;
+
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
 
-       ssize_t len = recvmsg(rfd, &msg, 0);
+       len = recvmsg(rfd, &msg, 0);
 
        if (len == -1)
                logerr("%s: recvmsg", __func__);
@@ -903,7 +910,7 @@ ps_recvmsg(struct dhcpcd_ctx *ctx, int rfd, uint16_t cmd, int wfd)
 }
 
 ssize_t
-ps_recvpsmsg(struct dhcpcd_ctx *ctx, int fd,
+ps_recvpsmsg(struct dhcpcd_ctx *ctx, int fd, unsigned short events,
     ssize_t (*callback)(void *, struct ps_msghdr *, struct msghdr *),
     void *cbctx)
 {
@@ -914,6 +921,9 @@ ps_recvpsmsg(struct dhcpcd_ctx *ctx, int fd,
        struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1 };
        bool stop = false;
 
+       if (events != ELE_READ)
+               logerrx("%s: unexpected event 0x%04x", __func__, events);
+
        len = read(fd, &psm, sizeof(psm));
 #ifdef PRIVSEP_DEBUG
        logdebugx("%s: %zd", __func__, len);
index c74bf25cba352f405cb84def76db9c46770ef8b5..3391627436311993fe80bfa5fedbd209d0f03ccb 100644 (file)
@@ -187,8 +187,8 @@ ssize_t ps_sendmsg(struct dhcpcd_ctx *, int, uint16_t, unsigned long,
     const struct msghdr *);
 ssize_t ps_sendcmd(struct dhcpcd_ctx *, int, uint16_t, unsigned long,
     const void *data, size_t len);
-ssize_t ps_recvmsg(struct dhcpcd_ctx *, int, uint16_t, int);
-ssize_t ps_recvpsmsg(struct dhcpcd_ctx *, int,
+ssize_t ps_recvmsg(struct dhcpcd_ctx *, int, unsigned short, uint16_t, int);
+ssize_t ps_recvpsmsg(struct dhcpcd_ctx *, int, unsigned short,
     ssize_t (*callback)(void *, struct ps_msghdr *, struct msghdr *), void *);
 
 /* Internal privsep functions. */
@@ -209,7 +209,8 @@ int ps_seccomp_enter(void);
 
 pid_t ps_dostart(struct dhcpcd_ctx * ctx,
     pid_t *priv_pid, int *priv_fd,
-    void (*recv_msg)(void *), void (*recv_unpriv_msg),
+    void (*recv_msg)(void *, unsigned short),
+    void (*recv_unpriv_msg)(void *, unsigned short),
     void *recv_ctx, int (*callback)(void *), void (*)(int, void *),
     unsigned int);
 int ps_dostop(struct dhcpcd_ctx *ctx, pid_t *pid, int *fd);