Needs more testing.
+If:
+ PathMatch: src/dev/.*\.c
+CompileFlags:
+ Add: [-I.., -I../.., -I../../compat]
+---
If:
PathMatch: src/.*\.c
CompileFlags:
- Add: [-I., -I.., -I../compat]
+ Add: [-I.., -I../compat]
+---
+CompileFlags:
+ Add: [-DINET, -DARP, -DARPING, -DIPV4LL, -DINET6, -DDHCP6, -DPLUGIN_DEV, -DAUTH, -DPRIVSEP]
# Set this for eloop
echo "#define HAVE_REALLOCARRAY" >>$CONFIG_H
-# Detect a polling mechanism.
-# See src/eloop.c as to why we only detect ppoll, pollts and pselect and
-# not others like epoll or kqueue.
-if [ -z "$POLL" ]; then
- printf "Testing for ppoll ... "
- cat <<EOF >_ppoll.c
-#include <poll.h>
-#include <stddef.h>
-int main(void) {
- struct pollfd fds;
- return ppoll(&fds, 1, NULL, NULL);
-}
-EOF
- if $XCC _ppoll.c -o _ppoll 2>&3; then
- POLL=ppoll
- echo "yes"
- else
- echo "no"
- fi
- rm -f _ppoll.c _ppoll
-fi
-if [ -z "$POLL" ]; then
- printf "Testing for pollts ... "
- cat <<EOF >_pollts.c
-#include <poll.h>
-#include <stddef.h>
-int main(void) {
- struct pollfd fds;
- return pollts(&fds, 1, NULL, NULL);
-}
-EOF
- if $XCC _pollts.c -o _pollts 2>&3; then
- POLL=pollts
- echo "yes"
- else
- echo "no"
- fi
- rm -f _pollts.c _pollts
-fi
-if [ -z "$POLL" ]; then
- printf "Testing for pselect ... "
- cat <<EOF >_pselect.c
-#include <sys/select.h>
-#include <stdlib.h>
-int main(void) {
- return pselect(0, NULL, NULL, NULL, NULL, NULL);
-}
-EOF
- if $XCC _pselect.c -o _pselect 2>&3; then
- POLL=pselect
- echo "yes"
- else
- echo "no"
- fi
- rm -f _pselect.c _pselect
-fi
-case "$POLL" in
-kqueue1)
- echo "#define HAVE_KQUEUE" >>$CONFIG_H
- echo "#define HAVE_KQUEUE1" >>$CONFIG_H
- POLL=kqueue
- ;;
-kqueue)
- echo "#define HAVE_KQUEUE" >>$CONFIG_H
- ;;
-epoll)
- echo "#define HAVE_EPOLL" >>$CONFIG_H
- ;;
-ppoll)
- echo "#define HAVE_PPOLL" >>$CONFIG_H
- ;;
-pollts)
- echo "#define HAVE_POLLTS" >>$CONFIG_H
- ;;
-pselect)
- echo "#define HAVE_PSELECT" >>$CONFIG_H
- ;;
-*)
- echo "No suitable polling function is available, not even pselect" >&2
- exit 1
- ;;
-esac
-
if [ -z "$BE64ENC" ]; then
printf "Testing for be64enc ... "
cat <<EOF >_be64enc.c
return;
}
- if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) {
- if (sig != SIGHUP &&
+ if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED)
+ {
+ if (ctx->fork_fd != -1 && sig != SIGHUP &&
send(ctx->fork_fd, &sig, sizeof(sig), MSG_EOR) == -1)
logerr("%s: send", __func__);
return;
eloop_signal_set_cb(ctx.eloop,
dhcpcd_signals, dhcpcd_signals_len,
dhcpcd_signal_cb, &ctx);
- if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) {
+ if (eloop_signal_mask(ctx.eloop) == -1) {
logerr("%s: eloop_signal_mask", __func__);
goto exit_failure;
}
logerr("socketpair");
goto exit_failure;
}
+
switch (pid = fork()) {
case -1:
logerr("fork");
goto exit_failure;
}
#endif
- if (eloop_event_add(ctx.eloop, ctx.fork_fd, ELE_READ,
- dhcpcd_fork_cb, &ctx) == -1)
- logerr("%s: eloop_event_add", __func__);
-
if (setsid() == -1) {
logerr("%s: setsid", __func__);
goto exit_failure;
}
/* Ensure we can never get a controlling terminal */
- switch (pid = fork()) {
- case -1:
+ pid = fork();
+ if (pid == -1) {
logerr("fork");
goto exit_failure;
- case 0:
- eloop_forked(ctx.eloop);
- break;
- default:
+ }
+ /* setsid again to ensure our child processes have the
+ * correct ppid */
+ if (pid == 0 && setsid() == -1) {
+ logerr("%s: setsid", __func__);
+ goto exit_failure;
+ }
+ if (eloop_forked(ctx.eloop, ELF_KEEP_ALL) == -1) {
+ logerr("%s: eloop_forked", __func__);
+ goto exit_failure;
+ }
+ if (eloop_event_add(ctx.eloop, ctx.fork_fd, ELE_READ,
+ dhcpcd_fork_cb, &ctx) == -1)
+ {
+ logerr("%s: eloop_event_add", __func__);
+ goto exit_failure;
+ }
+ if (pid != 0) {
ctx.options |= DHCPCD_FORKED; /* A lie */
i = EXIT_SUCCESS;
goto exit1;
}
run_loop:
- i = eloop_start(ctx.eloop, &ctx.sigset);
+ i = eloop_start(ctx.eloop);
if (i < 0) {
logerr("%s: eloop_start", __func__);
goto exit_failure;
int seq; /* route message sequence no */
int sseq; /* successful seq no sent */
-#ifdef USE_SIGNALS
- sigset_t sigset;
-#endif
struct eloop *eloop;
char *script;
addr != NULL ? " " : "", addr != NULL ? addr : "");
start = ps_startprocess(psp, ps_bpf_recvmsg, NULL,
- ps_bpf_start_bpf, NULL, PSF_DROPPRIVS);
+ ps_bpf_start_bpf, PSF_DROPPRIVS);
+
switch (start) {
case -1:
ps_freeprocess(psp);
psp = ctx->ps_ctl = ps_newprocess(ctx, &id);
strlcpy(psp->psp_name, "control proxy", sizeof(psp->psp_name));
pid = ps_startprocess(psp, ps_ctl_recvmsg, ps_ctl_dodispatch,
- ps_ctl_startcb, NULL, PSF_DROPPRIVS);
+ ps_ctl_startcb, PSF_DROPPRIVS);
if (pid == -1)
return -1;
strlcpy(psp->psp_name, "network proxy", sizeof(psp->psp_name));
pid = ps_startprocess(psp, ps_inet_recvmsg, ps_inet_dodispatch,
- ps_inet_startcb, NULL, PSF_DROPPRIVS);
+ ps_inet_startcb, PSF_DROPPRIVS);
if (pid == 0)
ps_entersandbox("stdio", NULL);
"%s proxy %s", psp->psp_protostr,
inet_ntop(psa->psa_family, ia, buf, sizeof(buf)));
start = ps_startprocess(psp, ps_inet_recvmsgpsp, NULL,
- start_func, NULL, PSF_DROPPRIVS);
+ start_func, PSF_DROPPRIVS);
switch (start) {
case -1:
ps_freeprocess(psp);
ssize_t len;
int exit_code = EXIT_FAILURE;
+ if (events & ELE_HANGUP)
+ goto out;
+
if (events != ELE_READ)
logerrx("%s: unexpected event 0x%04x", __func__, events);
ssize_t
ps_root_readerror(struct dhcpcd_ctx *ctx, void *data, size_t len)
{
- struct psr_ctx psr_ctx = {
- .psr_ctx = ctx,
- .psr_data = data, .psr_datalen = len,
- };
- int fd = PS_ROOT_FD(ctx);
+ struct psr_ctx *pc = ctx->ps_root->psp_data;
+ int err;
- if (eloop_event_add(ctx->ps_eloop, fd, ELE_READ,
- ps_root_readerrorcb, &psr_ctx) == -1)
- return -1;
-
- eloop_enter(ctx->ps_eloop);
- eloop_start(ctx->ps_eloop, &ctx->sigset);
- eloop_event_delete(ctx->ps_eloop, fd);
+ pc->psr_data = data;
+ pc->psr_datalen = len;
+ err = eloop_start(ctx->ps_eloop);
+ if (err < 0)
+ return err;
- errno = psr_ctx.psr_error.psr_errno;
- return psr_ctx.psr_error.psr_result;
+ errno = pc->psr_error.psr_errno;
+ return pc->psr_error.psr_result;
}
#ifdef PRIVSEP_GETIFADDRS
struct psr_ctx psr_ctx = {
.psr_ctx = ctx,
};
- int fd = PS_ROOT_FD(ctx);
+ int fd = PS_ROOT_FD(ctx), err;
if (eloop_event_add(ctx->ps_eloop, fd, ELE_READ,
ps_root_mreaderrorcb, &psr_ctx) == -1)
return -1;
- eloop_enter(ctx->ps_eloop);
- eloop_start(ctx->ps_eloop, &ctx->sigset);
- eloop_event_delete(ctx->ps_eloop, fd);
+ err = eloop_start(ctx->ps_eloop, &ctx->sigset);
+ if (err < 0)
+ return err;
errno = psr_ctx.psr_error.psr_errno;
*data = psr_ctx.psr_data;
.psi_cmd = PS_ROOT,
};
struct ps_process *psp;
- int logfd[2], datafd[2];
+ int logfd[2] = { -1, -1}, datafd[2] = { -1, -1};
pid_t pid;
+ struct psr_ctx *pc;
if (xsocketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CXNB, 0, logfd) == -1)
return -1;
return -1;
#endif
+
+ pc = malloc(sizeof(*pc));
+ if (pc == NULL)
+ return -1;
+ pc->psr_ctx = ctx;
+
psp = ctx->ps_root = ps_newprocess(ctx, &id);
+ if (psp == NULL)
+ {
+ free(pc);
+ return -1;
+ }
strlcpy(psp->psp_name, "privileged proxy", sizeof(psp->psp_name));
pid = ps_startprocess(psp, ps_root_recvmsg, NULL,
- ps_root_startcb, ps_root_signalcb, PSF_ELOOP);
+ ps_root_startcb, PSF_ELOOP);
+ if (pid == -1) {
+ free(pc);
+ return -1;
+ }
+
+ psp->psp_data = pc;
+ if (eloop_event_add(ctx->ps_eloop, psp->psp_fd, ELE_READ,
+ ps_root_readerrorcb, pc) == -1)
+ return -1;
if (pid == 0) {
ctx->ps_log_fd = logfd[0]; /* Keep open to pass to processes */
close(datafd[1]);
if (eloop_event_add(ctx->eloop, ctx->ps_data_fd, ELE_READ,
ps_root_dispatch, ctx) == -1)
- return 1;
+ return -1;
return pid;
}
ps_startprocess(struct ps_process *psp,
void (*recv_msg)(void *, unsigned short),
void (*recv_unpriv_msg)(void *, unsigned short),
- int (*callback)(struct ps_process *), void (*signal_cb)(int, void *),
+ int (*callback)(struct ps_process *),
unsigned int flags)
{
struct dhcpcd_ctx *ctx = psp->psp_ctx;
getpid(), ctx->ps_log_fd, ctx->ps_data_fd, psp->psp_fd);
#endif
- eloop_clear(ctx->eloop, -1);
- eloop_forked(ctx->eloop);
- eloop_signal_set_cb(ctx->eloop,
- dhcpcd_signals, dhcpcd_signals_len, signal_cb, ctx);
- /* ctx->sigset aready has the initial sigmask set in main() */
- if (eloop_signal_mask(ctx->eloop, NULL) == -1) {
- logerr("%s: eloop_signal_mask", __func__);
- goto errexit;
- }
-
if (ctx->fork_fd != -1) {
- /* Already removed from eloop thanks to above clear. */
close(ctx->fork_fd);
ctx->fork_fd = -1;
}
- /* This process has no need of the blocking inner eloop. */
- if (!(flags & PSF_ELOOP)) {
- eloop_free(ctx->ps_eloop);
- ctx->ps_eloop = NULL;
- } else
- eloop_forked(ctx->ps_eloop);
+ if (eloop_forked(ctx->eloop, ELF_KEEP_SIGNALS) == -1) {
+ logerr("%s: eloop_forked", __func__);
+ goto errexit;
+ }
+ if (ctx->ps_eloop != NULL) {
+ if (eloop_forked(ctx->ps_eloop, ELF_KEEP_SIGNALS) == -1) {
+ logerr("%s: eloop_forked", __func__);
+ goto errexit;
+ }
+ if (!(flags & PSF_ELOOP)) {
+ eloop_free(ctx->ps_eloop);
+ ctx->ps_eloop = NULL;
+ }
+ }
pidfile_clean();
ps_freeprocesses(ctx, psp);
if (eloop_event_add(ctx->eloop, psp->psp_fd, ELE_READ,
recv_msg, psp) == -1)
{
- logerr("%d %s: eloop_event_add XX fd %d", getpid(), __func__, psp->psp_fd);
+ logerr("%s: eloop_event_add", __func__);
goto errexit;
}
TAILQ_INIT(&ctx->ps_processes);
/* We need an inner eloop to block with. */
- if ((ctx->ps_eloop = eloop_new()) == NULL)
+ if ((ctx->ps_eloop = eloop_new_with_signals(ctx->eloop)) == NULL)
return -1;
- eloop_signal_set_cb(ctx->ps_eloop,
- dhcpcd_signals, dhcpcd_signals_len,
- dhcpcd_signal_cb, ctx);
switch (pid = ps_root_start(ctx)) {
case -1:
if (eloop_timeout_add_sec(ctx->ps_eloop, PS_PROCESS_TIMEOUT,
ps_process_timeout, ctx) == -1)
logerr("%s: eloop_timeout_add_sec", __func__);
- eloop_enter(ctx->ps_eloop);
#ifdef HAVE_CAPSICUM
struct ps_process *psp;
}
#endif
- error = eloop_start(ctx->ps_eloop, &ctx->sigset);
+ error = eloop_start(ctx->ps_eloop);
if (error != EXIT_SUCCESS)
logerr("%s: eloop_start", __func__);
char psp_name[PSP_NAMESIZE];
uint16_t psp_proto;
const char *psp_protostr;
+ void *psp_data;
bool psp_started;
#ifdef INET
pid_t ps_startprocess(struct ps_process *,
void (*recv_msg)(void *, unsigned short),
void (*recv_unpriv_msg)(void *, unsigned short),
- int (*callback)(struct ps_process *), void (*)(int, void *),
+ int (*callback)(struct ps_process *),
unsigned int);
int ps_stopprocess(struct ps_process *);
struct ps_process *ps_findprocess(struct dhcpcd_ctx *, struct ps_id *);