syslog(LOG_ERR, "%s: %s: %m", __func__, ifp->name);
return;
}
- eloop_event_add(ifp->ctx->eloop,
- state->arp_fd, arp_packet, ifp);
+ eloop_event_add(ifp->ctx->eloop, state->arp_fd,
+ arp_packet, ifp, NULL, NULL);
}
if (++state->claims < ANNOUNCE_NUM)
syslog(LOG_DEBUG,
timernorm(&tv);
eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_discover, ifp);
} else {
- eloop_event_delete(ifp->ctx->eloop, state->arp_fd);
+ eloop_event_delete(ifp->ctx->eloop, state->arp_fd, 0);
close(state->arp_fd);
state->arp_fd = -1;
}
return;
}
eloop_event_add(ifp->ctx->eloop,
- state->arp_fd, arp_packet, ifp);
+ state->arp_fd, arp_packet, ifp, NULL, NULL);
}
if (state->arping_index < ifp->options->arping_len) {
return;
if (state->arp_fd != -1) {
- eloop_event_delete(ifp->ctx->eloop, state->arp_fd);
+ eloop_event_delete(ifp->ctx->eloop, state->arp_fd, 0);
close(state->arp_fd);
state->arp_fd = -1;
}
last = NULL;
for (lp = l->ctx->control_fds; lp; lp = lp->next) {
if (lp == l) {
- eloop_event_delete(lp->ctx->eloop, lp->fd);
+ eloop_event_delete(lp->ctx->eloop, lp->fd, 0);
close(lp->fd);
if (last == NULL)
lp->ctx->control_fds = lp->next;
l->listener = 0;
l->next = ctx->control_fds;
ctx->control_fds = l;
- eloop_event_add(ctx->eloop, l->fd, control_handle_data, l);
+ eloop_event_add(ctx->eloop, l->fd,
+ control_handle_data, l, NULL, NULL);
} else
close(fd);
}
unlink(ctx->control_sock);
return -1;
}
- eloop_event_add(ctx->eloop, ctx->control_fd, control_handle, ctx);
+ eloop_event_add(ctx->eloop, ctx->control_fd,
+ control_handle, ctx, NULL, NULL);
return ctx->control_fd;
}
if (ctx->control_fd == -1)
return 0;
- eloop_event_delete(ctx->eloop, ctx->control_fd);
+ eloop_event_delete(ctx->eloop, ctx->control_fd, 0);
if (shutdown(ctx->control_fd, SHUT_RDWR) == -1)
retval = 1;
close(ctx->control_fd);
l = ctx->control_fds;
while (l != NULL) {
ctx->control_fds = l->next;
- eloop_event_delete(ctx->eloop, l->fd);
+ eloop_event_delete(ctx->eloop, l->fd, 0);
shutdown(l->fd, SHUT_RDWR);
close(l->fd);
free(l);
return;
if (state->arp_fd != -1) {
- eloop_event_delete(ifp->ctx->eloop, state->arp_fd);
+ eloop_event_delete(ifp->ctx->eloop, state->arp_fd, 0);
close(state->arp_fd);
state->arp_fd = -1;
}
if (state->raw_fd != -1) {
- eloop_event_delete(ifp->ctx->eloop, state->raw_fd);
+ eloop_event_delete(ifp->ctx->eloop, state->raw_fd, 0);
close(state->raw_fd);
state->raw_fd = -1;
}
* from the raw fd */
if (read(ctx->udp_fd, buffer, sizeof(buffer)) == -1) {
syslog(LOG_ERR, "%s: %m", __func__);
- eloop_event_delete(ctx->eloop, ctx->udp_fd);
+ eloop_event_delete(ctx->eloop, ctx->udp_fd, 0);
close(ctx->udp_fd);
ctx->udp_fd = -1;
}
return -1;
}
eloop_event_add(ifp->ctx->eloop,
- state->raw_fd, dhcp_handlepacket, ifp);
+ state->raw_fd, dhcp_handlepacket, ifp, NULL, NULL);
}
return 0;
}
}
if (ifp == NULL) {
if (ctx->udp_fd != -1) {
- eloop_event_delete(ctx->eloop, ctx->udp_fd);
+ eloop_event_delete(ctx->eloop, ctx->udp_fd, 0);
close(ctx->udp_fd);
ctx->udp_fd = -1;
}
return;
}
eloop_event_add(ifp->ctx->eloop,
- ifp->ctx->udp_fd, dhcp_handleudp, ifp->ctx);
+ ifp->ctx->udp_fd, dhcp_handleudp, ifp->ctx, NULL, NULL);
}
if (dhcp_init(ifp) == -1) {
if (bytes == -1 || bytes == 0) {
syslog(LOG_ERR, "recvmsg: %m");
close(ctx->dhcp_fd);
- eloop_event_delete(dhcpcd_ctx->eloop, ctx->dhcp_fd);
+ eloop_event_delete(dhcpcd_ctx->eloop, ctx->dhcp_fd, 0);
ctx->dhcp_fd = -1;
return;
}
&n, sizeof(n)) == -1)
goto errexit;
- eloop_event_add(dctx->eloop, ctx->dhcp_fd, dhcp6_handledata, dctx);
+ eloop_event_add(dctx->eloop, ctx->dhcp_fd,
+ dhcp6_handledata, dctx, NULL, NULL);
return 0;
errexit:
}
if (ifp == NULL && ctx->ipv6) {
if (ctx->ipv6->dhcp_fd != -1) {
- eloop_event_delete(ctx->eloop, ctx->ipv6->dhcp_fd);
+ eloop_event_delete(ctx->eloop, ctx->ipv6->dhcp_fd, 0);
close(ctx->ipv6->dhcp_fd);
ctx->ipv6->dhcp_fd = -1;
}
ctx = arg;
if (if_managelink(ctx) == -1) {
syslog(LOG_ERR, "if_managelink: %m");
- eloop_event_delete(ctx->eloop, ctx->link_fd);
+ eloop_event_delete(ctx->eloop, ctx->link_fd, 0);
close(ctx->link_fd);
ctx->link_fd = -1;
}
}
#endif
+static void
+dhcpcd_version(void *arg)
+{
+ struct fd_list *fd = arg;
+ size_t len;
+ struct iovec iov[2];
+
+ len = strlen(VERSION) + 1;
+ iov[0].iov_base = &len;
+ iov[0].iov_len = sizeof(ssize_t);
+ iov[1].iov_base = UNCONST(VERSION);
+ iov[1].iov_len = len;
+ if (writev(fd->fd, iov, 2) == -1)
+ syslog(LOG_ERR, "%s: writev: %m", __func__);
+ else
+ eloop_event_delete(fd->ctx->eloop, fd->fd, 1);
+}
+
+static void
+dhcpcd_getconfigfile(void *arg)
+{
+ struct fd_list *fd = arg;
+ size_t len;
+ struct iovec iov[2];
+
+ len = strlen(fd->ctx->cffile) + 1;
+ iov[0].iov_base = &len;
+ iov[0].iov_len = sizeof(ssize_t);
+ iov[1].iov_base = UNCONST(fd->ctx->cffile);
+ iov[1].iov_len = len;
+ if (writev(fd->fd, iov, 2) == -1)
+ syslog(LOG_ERR, "%s: writev: %m", __func__);
+ else
+ eloop_event_delete(fd->ctx->eloop, fd->fd, 1);
+}
+
+static void
+dhcpcd_getinterfaces(void *arg)
+{
+ struct fd_list *fd = arg;
+ struct interface *ifp;
+ size_t len;
+
+ len = 0;
+ TAILQ_FOREACH(ifp, fd->ctx->ifaces, next) {
+ len++;
+ if (D_STATE_RUNNING(ifp))
+ len++;
+ if (D6_STATE_RUNNING(ifp))
+ len++;
+ if (ipv6nd_hasra(ifp))
+ len++;
+ }
+ if (write(fd->fd, &len, sizeof(len)) != sizeof(len))
+ return;
+ TAILQ_FOREACH(ifp, fd->ctx->ifaces, next) {
+ if (send_interface(fd->fd, ifp) == -1)
+ syslog(LOG_ERR, "send_interface %d: %m", fd->fd);
+ }
+ eloop_event_delete(fd->ctx->eloop, fd->fd, 1);
+}
+
int
dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
int argc, char **argv)
int do_exit = 0, do_release = 0, do_reboot = 0;
int opt, oi = 0;
size_t len, l;
- struct iovec iov[2];
char *tmp, *p;
if (fd != NULL) {
- /* Special commands for our control socket */
+ /* Special commands for our control socket
+ * as the other end should be blocking until it gets the
+ * expected reply we should be safely able just to change the
+ * write callback on the fd */
if (strcmp(*argv, "--version") == 0) {
- len = strlen(VERSION) + 1;
- iov[0].iov_base = &len;
- iov[0].iov_len = sizeof(ssize_t);
- iov[1].iov_base = UNCONST(VERSION);
- iov[1].iov_len = len;
- if (writev(fd->fd, iov, 2) == -1) {
- syslog(LOG_ERR, "writev: %m");
- return -1;
- }
+ eloop_event_add(fd->ctx->eloop, fd->fd, NULL, NULL,
+ dhcpcd_version, fd);
return 0;
} else if (strcmp(*argv, "--getconfigfile") == 0) {
- len = strlen(ctx->cffile) + 1;
- iov[0].iov_base = &len;
- iov[0].iov_len = sizeof(ssize_t);
- iov[1].iov_base = UNCONST(ctx->cffile);
- iov[1].iov_len = len;
- if (writev(fd->fd, iov, 2) == -1) {
- syslog(LOG_ERR, "writev: %m");
- return -1;
- }
+ eloop_event_add(fd->ctx->eloop, fd->fd, NULL, NULL,
+ dhcpcd_getconfigfile, fd);
return 0;
} else if (strcmp(*argv, "--getinterfaces") == 0) {
- len = 0;
- TAILQ_FOREACH(ifp, ctx->ifaces, next) {
- len++;
- if (D_STATE_RUNNING(ifp))
- len++;
- if (D6_STATE_RUNNING(ifp))
- len++;
- if (ipv6nd_hasra(ifp))
- len++;
- }
- if (write(fd->fd, &len, sizeof(len)) !=
- sizeof(len))
- return -1;
- TAILQ_FOREACH(ifp, ctx->ifaces, next) {
- if (send_interface(fd->fd, ifp) == -1)
- syslog(LOG_ERR,
- "send_interface %d: %m",
- fd->fd);
- }
+ eloop_event_add(fd->ctx->eloop, fd->fd, NULL, NULL,
+ dhcpcd_getinterfaces, fd);
return 0;
} else if (strcmp(*argv, "--listen") == 0) {
fd->listener = 1;
if (ctx.link_fd == -1)
syslog(LOG_ERR, "open_link_socket: %m");
else
- eloop_event_add(ctx.eloop, ctx.link_fd, handle_link, &ctx);
+ eloop_event_add(ctx.eloop, ctx.link_fd,
+ handle_link, &ctx, NULL, NULL);
/* Start any dev listening plugin which may want to
* change the interface name provided by the kernel */
}
free(ctx.duid);
if (ctx.link_fd != -1) {
- eloop_event_delete(ctx.eloop, ctx.link_fd);
+ eloop_event_delete(ctx.eloop, ctx.link_fd, 0);
close(ctx.link_fd);
}
i = 0;
TAILQ_FOREACH(e, &ctx->events, next) {
ctx->fds[i].fd = e->fd;
- ctx->fds[i].events = POLLIN;
+ ctx->fds[i].events = 0;
+ if (e->read_cb)
+ ctx->fds[i].events |= POLLIN;
+ if (e->write_cb)
+ ctx->fds[i].events |= POLLOUT;
ctx->fds[i].revents = 0;
e->pollfd = &ctx->fds[i];
i++;
}
int
-eloop_event_add(struct eloop_ctx *ctx,
- int fd, void (*callback)(void *), void *arg)
+eloop_event_add(struct eloop_ctx *ctx, int fd,
+ void (*read_cb)(void *), void *read_cb_arg,
+ void (*write_cb)(void *), void *write_cb_arg)
{
struct eloop_event *e;
struct pollfd *nfds;
/* We should only have one callback monitoring the fd */
TAILQ_FOREACH(e, &ctx->events, next) {
if (e->fd == fd) {
- e->callback = callback;
- e->arg = arg;
+ if (read_cb) {
+ e->read_cb = read_cb;
+ e->read_cb_arg = read_cb_arg;
+ }
+ if (write_cb) {
+ e->write_cb = write_cb;
+ e->write_cb_arg = write_cb_arg;
+ }
+ eloop_event_setup_fds(ctx);
return 0;
}
}
/* Now populate the structure and add it to the list */
e->fd = fd;
- e->callback = callback;
- e->arg = arg;
+ e->read_cb = read_cb;
+ e->read_cb_arg = read_cb_arg;
+ e->write_cb = write_cb;
+ e->write_cb_arg = write_cb_arg;
/* The order of events should not matter.
* However, some PPP servers love to close the link right after
* sending their final message. So to ensure dhcpcd processes this
}
void
-eloop_event_delete(struct eloop_ctx *ctx, int fd)
+eloop_event_delete(struct eloop_ctx *ctx, int fd, int write_only)
{
struct eloop_event *e;
TAILQ_FOREACH(e, &ctx->events, next) {
if (e->fd == fd) {
- TAILQ_REMOVE(&ctx->events, e, next);
- TAILQ_INSERT_TAIL(&ctx->free_events, e, next);
- ctx->events_len--;
+ if (write_only) {
+ e->write_cb = NULL;
+ e->write_cb_arg = NULL;
+ } else {
+ TAILQ_REMOVE(&ctx->events, e, next);
+ TAILQ_INSERT_TAIL(&ctx->free_events, e, next);
+ ctx->events_len--;
+ }
eloop_event_setup_fds(ctx);
break;
}
/* Process any triggered events. */
if (n > 0) {
TAILQ_FOREACH(e, &ctx->events, next) {
+ if (e->pollfd->revents & POLLOUT &&
+ e->write_cb)
+ {
+ e->write_cb(e->write_cb_arg);
+ /* We need to break here as the
+ * callback could destroy the next
+ * fd to process. */
+ break;
+ }
if (e->pollfd->revents) {
- e->callback(e->arg);
+ e->read_cb(e->read_cb_arg);
/* We need to break here as the
* callback could destroy the next
* fd to process. */
struct eloop_event {
TAILQ_ENTRY(eloop_event) next;
int fd;
- void (*callback)(void *);
- void *arg;
+ void (*read_cb)(void *);
+ void *read_cb_arg;
+ void (*write_cb)(void *);
+ void *write_cb_arg;
struct pollfd *pollfd;
};
#define eloop_timeouts_delete(a, b, ...) \
eloop_q_timeouts_delete(a, ELOOP_QUEUE, b, __VA_ARGS__)
-int eloop_event_add(struct eloop_ctx *, int, void (*)(void *), void *);
-void eloop_event_delete(struct eloop_ctx *, int);
+int eloop_event_add(struct eloop_ctx *, int,
+ void (*)(void *), void *,
+ void (*)(void *), void *);
+void eloop_event_delete(struct eloop_ctx *, int, int);
int eloop_q_timeout_add_sec(struct eloop_ctx *, int queue,
time_t, void (*)(void *), void *);
int eloop_q_timeout_add_tv(struct eloop_ctx *, int queue,
&filt, sizeof(filt)) == -1)
goto eexit;
- eloop_event_add(dctx->eloop, ctx->nd_fd, ipv6nd_handledata, dctx);
+ eloop_event_add(dctx->eloop, ctx->nd_fd,
+ ipv6nd_handledata, dctx, NULL, NULL);
return ctx->nd_fd;
eexit:
if (ctx->nd_fd != -1) {
- eloop_event_delete(dctx->eloop, ctx->nd_fd);
+ eloop_event_delete(dctx->eloop, ctx->nd_fd, 0);
close(ctx->nd_fd);
ctx->nd_fd = -1;
}
}
if (ifp == NULL) {
if (ctx->ipv6->nd_fd != -1) {
- eloop_event_delete(ctx->eloop, ctx->ipv6->nd_fd);
+ eloop_event_delete(ctx->eloop, ctx->ipv6->nd_fd, 0);
close(ctx->ipv6->nd_fd);
ctx->ipv6->nd_fd = -1;
}
len = recvmsg(ctx->nd_fd, &ctx->rcvhdr, 0);
if (len == -1 || len == 0) {
syslog(LOG_ERR, "recvmsg: %m");
- eloop_event_delete(dhcpcd_ctx->eloop, ctx->nd_fd);
+ eloop_event_delete(dhcpcd_ctx->eloop, ctx->nd_fd, 0);
close(ctx->nd_fd);
ctx->nd_fd = -1;
return;