}
static void
-arp_read(void *arg)
+arp_read(void *arg, unsigned short events)
{
struct arp_state *astate = arg;
struct bpf *bpf = astate->bpf;
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. */
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__);
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__);
}
(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)
{
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);
}
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;
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)
{
}
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;
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:
}
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
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;
}
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;
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);
}
#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
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
}
static void
-dhcp_readbpf(void *arg)
+dhcp_readbpf(void *arg, unsigned short events)
{
struct interface *ifp = arg;
uint8_t buf[FRAMELEN_MAX];
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));
}
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;
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;
}
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
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;
}
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);
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
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;
}
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;
}
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
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 {
}
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 {
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) {
}
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
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) {
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);
}
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)
}
if (fprintf(fp, "%s", ap->saddr) == -1)
return -1;
- }
+ }
if (fputc('\0', fp) == EOF)
return -1;
#endif
}
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);
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) {
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;
}
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)
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:
}
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)
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
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__);
}
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)
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.
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];
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)
/* 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)
* 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
}
#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)
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++;
}
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;
#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;
}
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);
#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;
#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) {
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;
}
/*
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++;
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)
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;
}
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 ||
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;
}
{
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)
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;
}
fd_set read_fds, write_fds;
int maxfd, n;
struct eloop_event *e;
+ unsigned short events;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
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;
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;
struct timespec ts, *tsp;
assert(eloop != NULL);
-#if defined(HAVE_KQUEUE)
+#ifdef HAVE_KQUEUE
UNUSED(signals);
#endif
/* 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) \
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
//#define DEBUG_NS
//
-static void ipv6nd_handledata(void *);
+static void ipv6nd_handledata(void *, unsigned short);
/*
* Android ships buggy ICMP6 filter headers.
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
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
}
static void
-ipv6nd_handledata(void *arg)
+ipv6nd_handledata(void *arg, unsigned short events)
{
struct dhcpcd_ctx *ctx;
int fd;
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__);
#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;
.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. */
}
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__);
}
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;
}
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__);
}
}
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) {
}
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) {
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;
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;
#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
}
#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
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__);
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__);
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__);
}
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__);
}
}
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__);
}
#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__);
}
}
#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__);
#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__);
}
}
#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__);
#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__);
}
};
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;
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; \
.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;
#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;
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);
/* 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__);
}
}
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__);
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]);
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;
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)
{
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__);
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;
}
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 };
.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__);
}
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)
{
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);
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. */
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);