summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorreyk <reyk@openbsd.org>2016-09-03 14:09:04 +0000
committerreyk <reyk@openbsd.org>2016-09-03 14:09:04 +0000
commit3d6ff6ed8b003d3e584d1f749dd81da9c40b857e (patch)
treee1ebf78e296444544d9120ff8b95203420bf826f
parentsuppress some cpuid bits for hardware we either don't support yet or (diff)
downloadwireguard-openbsd-3d6ff6ed8b003d3e584d1f749dd81da9c40b857e.tar.xz
wireguard-openbsd-3d6ff6ed8b003d3e584d1f749dd81da9c40b857e.zip
Use the fork+exec privsep model in relayd; based on rzalamena@'s work
for httpd with some (current and previous) changes for relayd. Once again, both daemons now share the same proc.c where most of the privsep "magic" happens. OK benno@ rzalamena@
-rw-r--r--usr.sbin/relayd/ca.c4
-rw-r--r--usr.sbin/relayd/hce.c4
-rw-r--r--usr.sbin/relayd/proc.c455
-rw-r--r--usr.sbin/relayd/relayd.c44
-rw-r--r--usr.sbin/relayd/relayd.h32
5 files changed, 357 insertions, 182 deletions
diff --git a/usr.sbin/relayd/ca.c b/usr.sbin/relayd/ca.c
index ed82e2197f0..13590d10fd7 100644
--- a/usr.sbin/relayd/ca.c
+++ b/usr.sbin/relayd/ca.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ca.c,v 1.21 2016/09/02 14:45:51 reyk Exp $ */
+/* $OpenBSD: ca.c,v 1.22 2016/09/03 14:09:04 reyk Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -73,7 +73,7 @@ ca(struct privsep *ps, struct privsep_proc *p)
void
ca_init(struct privsep *ps, struct privsep_proc *p, void *arg)
{
- if (pledge("stdio", NULL) == -1)
+ if (pledge("stdio recvfd", NULL) == -1)
fatal("pledge");
if (config_init(ps->ps_env) == -1)
diff --git a/usr.sbin/relayd/hce.c b/usr.sbin/relayd/hce.c
index e99ff18fbd4..33cc9ee2a45 100644
--- a/usr.sbin/relayd/hce.c
+++ b/usr.sbin/relayd/hce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hce.c,v 1.74 2016/09/02 14:45:51 reyk Exp $ */
+/* $OpenBSD: hce.c,v 1.75 2016/09/03 14:09:04 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -70,7 +70,7 @@ hce_init(struct privsep *ps, struct privsep_proc *p, void *arg)
/* Allow maximum available sockets for TCP checks */
socket_rlimit(-1);
- if (pledge("stdio inet", NULL) == -1)
+ if (pledge("stdio recvfd inet", NULL) == -1)
fatal("hce: pledge");
}
diff --git a/usr.sbin/relayd/proc.c b/usr.sbin/relayd/proc.c
index 6e2171954e4..0423a0b2ddd 100644
--- a/usr.sbin/relayd/proc.c
+++ b/usr.sbin/relayd/proc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.c,v 1.30 2016/09/02 12:14:08 reyk Exp $ */
+/* $OpenBSD: proc.c,v 1.31 2016/09/03 14:09:04 reyk Exp $ */
/*
* Copyright (c) 2010 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -34,8 +34,14 @@
#include "relayd.h"
-void proc_open(struct privsep *, struct privsep_proc *,
- struct privsep_proc *, size_t);
+void proc_exec(struct privsep *, struct privsep_proc *, unsigned int,
+ int, char **);
+void proc_connectpeer(struct privsep *, enum privsep_procid, int,
+ struct privsep_pipes *);
+void proc_setup(struct privsep *, struct privsep_proc *, unsigned int);
+void proc_open(struct privsep *, int, int);
+void proc_accept(struct privsep *, int, enum privsep_procid,
+ unsigned int);
void proc_close(struct privsep *);
int proc_ispeer(struct privsep_proc *, unsigned int, enum privsep_procid);
void proc_shutdown(struct privsep_proc *);
@@ -55,17 +61,264 @@ proc_ispeer(struct privsep_proc *procs, unsigned int nproc,
return (0);
}
+enum privsep_procid
+proc_getid(struct privsep_proc *procs, unsigned int nproc,
+ const char *proc_name)
+{
+ struct privsep_proc *p;
+ unsigned int proc;
+
+ for (proc = 0; proc < nproc; proc++) {
+ p = &procs[proc];
+ if (strcmp(p->p_title, proc_name))
+ continue;
+
+ return (p->p_id);
+ }
+
+ return (PROC_MAX);
+}
+
+void
+proc_exec(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
+ int argc, char **argv)
+{
+ unsigned int proc, nargc, i, proc_i;
+ char **nargv;
+ struct privsep_proc *p;
+ char num[32];
+ int fd;
+
+ /* Prepare the new process argv. */
+ nargv = calloc(argc + 5, sizeof(char *));
+ if (nargv == NULL)
+ fatal("%s: calloc", __func__);
+
+ /* Copy call argument first. */
+ nargc = 0;
+ nargv[nargc++] = argv[0];
+
+ /* Set process name argument and save the position. */
+ nargv[nargc++] = "-P";
+ proc_i = nargc;
+ nargc++;
+
+ /* Point process instance arg to stack and copy the original args. */
+ nargv[nargc++] = "-I";
+ nargv[nargc++] = num;
+ for (i = 1; i < (unsigned int) argc; i++)
+ nargv[nargc++] = argv[i];
+
+ nargv[nargc] = NULL;
+
+ for (proc = 0; proc < nproc; proc++) {
+ p = &procs[proc];
+
+ /* Update args with process title. */
+ nargv[proc_i] = (char *) p->p_title;
+
+ /* Fire children processes. */
+ for (i = 0; i < ps->ps_instances[p->p_id]; i++) {
+ /* Update the process instance number. */
+ snprintf(num, sizeof(num), "%u", i);
+
+ fd = ps->ps_pipes[p->p_id][i].pp_pipes[PROC_PARENT][0];
+ ps->ps_pipes[p->p_id][i].pp_pipes[PROC_PARENT][0] = -1;
+
+ switch (fork()) {
+ case -1:
+ fatal("%s: fork", __func__);
+ break;
+ case 0:
+ /* Prepare parent socket. */
+ dup2(fd, PARENT_SOCK_FILENO);
+
+ execvp(argv[0], nargv);
+ fatal("%s: execvp", __func__);
+ break;
+ default:
+ /* Close child end. */
+ close(fd);
+ break;
+ }
+ }
+ }
+ free(nargv);
+}
+
+void
+proc_connectpeer(struct privsep *ps, enum privsep_procid id, int inst,
+ struct privsep_pipes *pp)
+{
+ unsigned int i, j;
+ struct privsep_fd pf;
+
+ for (i = 0; i < PROC_MAX; i++) {
+ /* Parent is already connected with everyone. */
+ if (i == PROC_PARENT)
+ continue;
+
+ for (j = 0; j < ps->ps_instances[i]; j++) {
+ /* Don't send socket to child itself. */
+ if (i == (unsigned int)id &&
+ j == (unsigned int)inst)
+ continue;
+ if (pp->pp_pipes[i][j] == -1)
+ continue;
+
+ pf.pf_procid = i;
+ pf.pf_instance = j;
+ proc_compose_imsg(ps, id, inst, IMSG_CTL_PROCFD,
+ -1, pp->pp_pipes[i][j], &pf, sizeof(pf));
+ pp->pp_pipes[i][j] = -1;
+ }
+ }
+}
+
+/* Inter-connect all process except with ourself. */
void
-proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc)
+proc_connect(struct privsep *ps)
{
- unsigned int i, j, src, dst;
+ unsigned int src, i, j;
struct privsep_pipes *pp;
+ struct imsgev *iev;
+
+ /* Listen on appropriate pipes. */
+ src = privsep_process;
+ pp = &ps->ps_pipes[src][ps->ps_instance];
+
+ for (i = 0; i < PROC_MAX; i++) {
+ /* Don't listen to ourself. */
+ if (i == src)
+ continue;
+
+ for (j = 0; j < ps->ps_instances[i]; j++) {
+ if (pp->pp_pipes[i][j] == -1)
+ continue;
+
+ iev = &ps->ps_ievs[i][j];
+ imsg_init(&iev->ibuf, pp->pp_pipes[i][j]);
+ event_set(&iev->ev, iev->ibuf.fd, iev->events,
+ iev->handler, iev->data);
+ event_add(&iev->ev, NULL);
+ }
+ }
+
+ /* Exchange pipes between process. */
+ for (i = 0; i < PROC_MAX; i++) {
+ /* Parent is already connected with everyone. */
+ if (i == PROC_PARENT)
+ continue;
+
+ for (j = 0; j < ps->ps_instances[i]; j++)
+ proc_connectpeer(ps, i, j, &ps->ps_pipes[i][j]);
+ }
+}
+
+void
+proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc,
+ int argc, char **argv, enum privsep_procid proc_id)
+{
+ struct privsep_proc *p = NULL;
+ unsigned int proc;
+ unsigned int src, dst;
+
+ if (proc_id == PROC_PARENT) {
+ privsep_process = PROC_PARENT;
+ proc_setup(ps, procs, nproc);
+
+ /* Open socketpair()s for everyone. */
+ for (src = 0; src < PROC_MAX; src++)
+ for (dst = 0; dst < PROC_MAX; dst++)
+ proc_open(ps, src, dst);
+
+ /* Engage! */
+ proc_exec(ps, procs, nproc, argc, argv);
+ return;
+ }
+
+ /* Initialize a child */
+ for (proc = 0; proc < nproc; proc++) {
+ if (procs[proc].p_id != proc_id)
+ continue;
+ p = &procs[proc];
+ break;
+ }
+ if (p == NULL || p->p_init == NULL)
+ fatalx("%s: process %d missing process initialization",
+ __func__, proc_id);
+
+ p->p_init(ps, p);
+
+ fatalx("failed to initiate child process");
+}
+
+void
+proc_accept(struct privsep *ps, int fd, enum privsep_procid dst,
+ unsigned int n)
+{
+ struct privsep_pipes *pp = ps->ps_pp;
+ struct imsgev *iev;
+
+ if (ps->ps_ievs[dst] == NULL) {
+#if DEBUG > 1
+ log_debug("%s: %s src %d %d to dst %d %d not connected",
+ __func__, ps->ps_title[privsep_process],
+ privsep_process, ps->ps_instance + 1,
+ dst, n + 1);
+#endif
+ close(fd);
+ return;
+ }
+
+ if (pp->pp_pipes[dst][n] != -1) {
+ log_warnx("%s: duplicated descriptor", __func__);
+ close(fd);
+ return;
+ } else
+ pp->pp_pipes[dst][n] = fd;
+
+ iev = &ps->ps_ievs[dst][n];
+ imsg_init(&iev->ibuf, fd);
+ event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data);
+ event_add(&iev->ev, NULL);
+}
+
+void
+proc_setup(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc)
+{
+ unsigned int i, j, src, dst, id;
+ struct privsep_pipes *pp;
+
+ /* Initialize parent title, ps_instances and procs. */
+ ps->ps_title[PROC_PARENT] = "parent";
for (src = 0; src < PROC_MAX; src++)
/* Default to 1 process instance */
if (ps->ps_instances[src] < 1)
ps->ps_instances[src] = 1;
+ for (src = 0; src < nproc; src++) {
+ procs[src].p_ps = ps;
+ procs[src].p_env = ps->ps_env;
+ if (procs[src].p_cb == NULL)
+ procs[src].p_cb = proc_dispatch_null;
+
+ id = procs[src].p_id;
+ ps->ps_title[id] = procs[src].p_title;
+ if ((ps->ps_ievs[id] = calloc(ps->ps_instances[id],
+ sizeof(struct imsgev))) == NULL)
+ fatal(__func__);
+
+ /* With this set up, we are ready to call imsg_init(). */
+ for (i = 0; i < ps->ps_instances[id]; i++) {
+ ps->ps_ievs[id][i].handler = proc_dispatch;
+ ps->ps_ievs[id][i].events = EV_READ;
+ ps->ps_ievs[id][i].proc = &procs[src];
+ ps->ps_ievs[id][i].data = &ps->ps_ievs[id][i];
+ }
+ }
+
/*
* Allocate pipes for all process instances (incl. parent)
*
@@ -83,7 +336,7 @@ proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc)
/* Allocate destination array for each process */
if ((ps->ps_pipes[src] = calloc(ps->ps_instances[src],
sizeof(struct privsep_pipes))) == NULL)
- fatal("proc_init: calloc");
+ fatal("%s: calloc", __func__);
for (i = 0; i < ps->ps_instances[src]; i++) {
pp = &ps->ps_pipes[src][i];
@@ -93,7 +346,7 @@ proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc)
if ((pp->pp_pipes[dst] =
calloc(ps->ps_instances[dst],
sizeof(int))) == NULL)
- fatal("proc_init: calloc");
+ fatal("%s: calloc", __func__);
/* Mark fd as unused */
for (j = 0; j < ps->ps_instances[dst]; j++)
@@ -102,22 +355,7 @@ proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc)
}
}
- /*
- * Setup and run the parent and its children
- */
- privsep_process = PROC_PARENT;
- ps->ps_instances[PROC_PARENT] = 1;
- ps->ps_title[PROC_PARENT] = "parent";
- ps->ps_pp = &ps->ps_pipes[privsep_process][0];
-
- for (i = 0; i < nproc; i++)
- ps->ps_title[procs[i].p_id] = procs[i].p_title;
-
- proc_open(ps, NULL, procs, nproc);
-
- /* Engage! */
- for (i = 0; i < nproc; i++)
- (*procs[i].p_init)(ps, &procs[i]);
+ ps->ps_pp = &ps->ps_pipes[privsep_process][ps->ps_instance];
}
void
@@ -159,115 +397,30 @@ proc_kill(struct privsep *ps)
}
void
-proc_open(struct privsep *ps, struct privsep_proc *p,
- struct privsep_proc *procs, size_t nproc)
+proc_open(struct privsep *ps, int src, int dst)
{
struct privsep_pipes *pa, *pb;
int fds[2];
- unsigned int i, j, src, proc;
-
- if (p == NULL)
- src = privsep_process; /* parent */
- else
- src = p->p_id;
-
- /*
- * Open socket pairs for our peers
- */
- for (proc = 0; proc < nproc; proc++) {
- procs[proc].p_ps = ps;
- procs[proc].p_env = ps->ps_env;
- if (procs[proc].p_cb == NULL)
- procs[proc].p_cb = proc_dispatch_null;
-
- for (i = 0; i < ps->ps_instances[src]; i++) {
- for (j = 0; j < ps->ps_instances[procs[proc].p_id];
- j++) {
- pa = &ps->ps_pipes[src][i];
- pb = &ps->ps_pipes[procs[proc].p_id][j];
-
- /* Check if fds are already set by peer */
- if (pa->pp_pipes[procs[proc].p_id][j] != -1)
- continue;
-
- if (socketpair(AF_UNIX,
- SOCK_STREAM | SOCK_NONBLOCK,
- PF_UNSPEC, fds) == -1)
- fatal("socketpair");
-
- pa->pp_pipes[procs[proc].p_id][j] = fds[0];
- pb->pp_pipes[src][i] = fds[1];
- }
- }
- }
-}
+ unsigned int i, j;
-void
-proc_listen(struct privsep *ps, struct privsep_proc *procs, size_t nproc)
-{
- unsigned int i, dst, src, n, m;
- struct privsep_pipes *pp;
-
- /*
- * Close unused pipes
- */
- for (src = 0; src < PROC_MAX; src++) {
- for (n = 0; n < ps->ps_instances[src]; n++) {
- /* Ingore current process */
- if (src == (unsigned int)privsep_process &&
- n == ps->ps_instance)
+ for (i = 0; i < ps->ps_instances[src]; i++) {
+ for (j = 0; j < ps->ps_instances[dst]; j++) {
+ /* Don't create sockets for ourself. */
+ if (src == dst && i == j)
continue;
- pp = &ps->ps_pipes[src][n];
-
- for (dst = 0; dst < PROC_MAX; dst++) {
- if (src == dst)
- continue;
- for (m = 0; m < ps->ps_instances[dst]; m++) {
- if (pp->pp_pipes[dst][m] == -1)
- continue;
-
- /* Close and invalidate fd */
- close(pp->pp_pipes[dst][m]);
- pp->pp_pipes[dst][m] = -1;
- }
- }
- }
- }
-
- src = privsep_process;
- ps->ps_pp = pp = &ps->ps_pipes[src][ps->ps_instance];
-
- /*
- * Listen on appropriate pipes
- */
- for (i = 0; i < nproc; i++) {
- dst = procs[i].p_id;
-
- if (src == dst)
- fatal("proc_listen: cannot peer with oneself");
-
- if ((ps->ps_ievs[dst] = calloc(ps->ps_instances[dst],
- sizeof(struct imsgev))) == NULL)
- fatal("proc_open");
-
- for (n = 0; n < ps->ps_instances[dst]; n++) {
- if (pp->pp_pipes[dst][n] == -1)
+ pa = &ps->ps_pipes[src][i];
+ pb = &ps->ps_pipes[dst][j];
+ if (pb->pp_pipes[dst][j] != -1)
continue;
- imsg_init(&(ps->ps_ievs[dst][n].ibuf),
- pp->pp_pipes[dst][n]);
- ps->ps_ievs[dst][n].handler = proc_dispatch;
- ps->ps_ievs[dst][n].events = EV_READ;
- ps->ps_ievs[dst][n].proc = &procs[i];
- ps->ps_ievs[dst][n].data = &ps->ps_ievs[dst][n];
-
- event_set(&(ps->ps_ievs[dst][n].ev),
- ps->ps_ievs[dst][n].ibuf.fd,
- ps->ps_ievs[dst][n].events,
- ps->ps_ievs[dst][n].handler,
- ps->ps_ievs[dst][n].data);
- event_add(&(ps->ps_ievs[dst][n].ev), NULL);
+ if (socketpair(AF_UNIX,
+ SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
+ PF_UNSPEC, fds) == -1)
+ fatal(__func__);
+
+ pa->pp_pipes[dst][j] = fds[0];
+ pb->pp_pipes[src][i] = fds[1];
}
}
}
@@ -316,7 +469,7 @@ proc_shutdown(struct privsep_proc *p)
log_info("%s exiting, pid %d", p->p_title, getpid());
- _exit(0);
+ exit(0);
}
void
@@ -346,32 +499,17 @@ proc_run(struct privsep *ps, struct privsep_proc *p,
struct privsep_proc *procs, unsigned int nproc,
void (*run)(struct privsep *, struct privsep_proc *, void *), void *arg)
{
- pid_t pid;
- struct passwd *pw;
+ struct passwd *pw = ps->ps_pw;
const char *root;
struct control_sock *rcs;
- unsigned int n;
if (ps->ps_noaction)
- return;
+ exit(0);
- proc_open(ps, p, procs, nproc);
+ log_procinit(p->p_title);
- /* Fork child handlers */
- switch (pid = fork()) {
- case -1:
- fatal("proc_run: cannot fork");
- case 0:
- log_procinit(p->p_title);
-
- /* Set the process group of the current process */
- setpgid(0, 0);
- break;
- default:
- return;
- }
-
- pw = ps->ps_pw;
+ /* Set the process group of the current process */
+ setpgid(0, 0);
if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
if (control_init(ps, &ps->ps_csock) == -1)
@@ -401,19 +539,6 @@ proc_run(struct privsep *ps, struct privsep_proc *p,
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
fatal("proc_run: cannot drop privileges");
- /* Fork child handlers */
- for (n = 1; n < ps->ps_instances[p->p_id]; n++) {
- if (fork() == 0) {
- ps->ps_instance = n;
- break;
- }
- }
-
-#ifdef DEBUG
- log_debug("%s: %s %d/%d, pid %d", __func__, p->p_title,
- ps->ps_instance + 1, ps->ps_instances[p->p_id], getpid());
-#endif
-
event_init();
signal_set(&ps->ps_evsigint, SIGINT, proc_sig_handler, p);
@@ -430,8 +555,8 @@ proc_run(struct privsep *ps, struct privsep_proc *p,
signal_add(&ps->ps_evsigpipe, NULL);
signal_add(&ps->ps_evsigusr1, NULL);
- proc_listen(ps, procs, nproc);
-
+ proc_setup(ps, procs, nproc);
+ proc_accept(ps, PARENT_SOCK_FILENO, PROC_PARENT, 0);
if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
TAILQ_INIT(&ctl_conns);
if (control_listen(&ps->ps_csock) == -1)
@@ -441,6 +566,9 @@ proc_run(struct privsep *ps, struct privsep_proc *p,
fatalx(__func__);
}
+ DPRINTF("%s: %s %d/%d, pid %d", __func__, p->p_title,
+ ps->ps_instance + 1, ps->ps_instances[p->p_id], getpid());
+
if (run != NULL)
run(ps, p, arg);
@@ -460,6 +588,7 @@ proc_dispatch(int fd, short event, void *arg)
ssize_t n;
int verbose;
const char *title;
+ struct privsep_fd pf;
title = ps->ps_title[privsep_process];
ibuf = &iev->ibuf;
@@ -510,6 +639,12 @@ proc_dispatch(int fd, short event, void *arg)
memcpy(&verbose, imsg.data, sizeof(verbose));
log_verbose(verbose);
break;
+ case IMSG_CTL_PROCFD:
+ IMSG_SIZE_CHECK(&imsg, &pf);
+ memcpy(&pf, imsg.data, sizeof(pf));
+ proc_accept(ps, imsg.fd, pf.pf_procid,
+ pf.pf_instance);
+ break;
default:
log_warnx("%s: %s %d got invalid imsg %d peerid %d "
"from %s %d",
diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c
index 7c9dd6ed996..0bde01402f0 100644
--- a/usr.sbin/relayd/relayd.c
+++ b/usr.sbin/relayd/relayd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.c,v 1.159 2016/09/02 14:45:51 reyk Exp $ */
+/* $OpenBSD: relayd.c,v 1.160 2016/09/03 14:09:04 reyk Exp $ */
/*
* Copyright (c) 2007 - 2016 Reyk Floeter <reyk@openbsd.org>
@@ -121,8 +121,12 @@ main(int argc, char *argv[])
struct relayd *env;
struct privsep *ps;
const char *conffile = CONF_FILE;
+ enum privsep_procid proc_id = PROC_PARENT;
+ int proc_instance = 0;
+ const char *errp, *title = NULL;
+ int argc0 = argc;
- while ((c = getopt(argc, argv, "dD:nf:v")) != -1) {
+ while ((c = getopt(argc, argv, "dD:nI:P:f:v")) != -1) {
switch (c) {
case 'd':
debug = 2;
@@ -143,6 +147,18 @@ main(int argc, char *argv[])
verbose++;
opts |= RELAYD_OPT_VERBOSE;
break;
+ case 'P':
+ title = optarg;
+ proc_id = proc_getid(procs, nitems(procs), title);
+ if (proc_id == PROC_MAX)
+ fatalx("invalid process name");
+ break;
+ case 'I':
+ proc_instance = strtonum(optarg, 0,
+ PROC_MAX_INSTANCES, &errp);
+ if (errp)
+ fatalx("invalid process instance");
+ break;
default:
usage();
}
@@ -189,19 +205,29 @@ main(int argc, char *argv[])
log_init(debug, LOG_DAEMON);
log_verbose(verbose);
- if (!debug && daemon(1, 0) == -1)
- err(1, "failed to daemonize");
-
if (env->sc_conf.opts & RELAYD_OPT_NOACTION)
ps->ps_noaction = 1;
- else
- log_info("startup");
ps->ps_instances[PROC_RELAY] = env->sc_conf.prefork_relay;
ps->ps_instances[PROC_CA] = env->sc_conf.prefork_relay;
+ ps->ps_instance = proc_instance;
+ if (title != NULL)
+ ps->ps_title[proc_id] = title;
+
+ if (proc_id == PROC_PARENT) {
+ /* XXX the parent opens too many fds in proc_open() */
+ socket_rlimit(-1);
+ }
+
+ /* only the parent returns */
+ proc_init(ps, procs, nitems(procs), argc0, argv, proc_id);
- proc_init(ps, procs, nitems(procs));
log_procinit("parent");
+ if (!debug && daemon(1, 0) == -1)
+ err(1, "failed to daemonize");
+
+ if (ps->ps_noaction == 0)
+ log_info("startup");
event_init();
@@ -217,7 +243,7 @@ main(int argc, char *argv[])
signal_add(&ps->ps_evsigpipe, NULL);
signal_add(&ps->ps_evsigusr1, NULL);
- proc_listen(ps, procs, nitems(procs));
+ proc_connect(ps);
if (load_config(env->sc_conffile, env) == -1) {
proc_kill(env->sc_ps);
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index ddbcc8d255a..eb460bf9d78 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.231 2016/09/02 16:14:09 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.232 2016/09/03 14:09:04 reyk Exp $ */
/*
* Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org>
@@ -915,6 +915,7 @@ enum imsg_type {
IMSG_CTL_OK, /* answer to relayctl requests */
IMSG_CTL_FAIL,
IMSG_CTL_VERBOSE,
+ IMSG_CTL_PROCFD,
IMSG_CTL_END,
IMSG_CTL_RDR,
IMSG_CTL_TABLE,
@@ -987,6 +988,11 @@ enum privsep_procid {
/* Attach the control socket to the following process */
#define PROC_CONTROL PROC_PFE
+/* Define default parent socket number */
+#define PARENT_SOCK_FILENO 3
+
+#define PROC_MAX_INSTANCES 128
+
struct privsep_pipes {
int *pp_pipes[PROC_MAX];
};
@@ -1031,6 +1037,11 @@ struct privsep_proc {
struct relayd *p_env;
};
+struct privsep_fd {
+ enum privsep_procid pf_procid;
+ unsigned int pf_instance;
+};
+
struct relayd_config {
char tls_sid[SSL_MAX_SID_CTX_LENGTH];
char snmp_path[PATH_MAX];
@@ -1363,12 +1374,15 @@ __dead void fatalx(const char *, ...)
__attribute__((__format__ (printf, 1, 2)));
/* proc.c */
-void proc_init(struct privsep *, struct privsep_proc *, u_int);
+enum privsep_procid
+ proc_getid(struct privsep_proc *, unsigned int, const char *);
+void proc_init(struct privsep *, struct privsep_proc *, unsigned int,
+ int, char **, enum privsep_procid);
void proc_kill(struct privsep *);
-void proc_listen(struct privsep *, struct privsep_proc *, size_t);
+void proc_connect(struct privsep *);
void proc_dispatch(int, short event, void *);
void proc_run(struct privsep *, struct privsep_proc *,
- struct privsep_proc *, u_int,
+ struct privsep_proc *, unsigned int,
void (*)(struct privsep *, struct privsep_proc *, void *), void *);
void proc_range(struct privsep *, enum privsep_procid, int *, int *);
int proc_compose_imsg(struct privsep *, enum privsep_procid, int,
@@ -1377,18 +1391,18 @@ int proc_compose(struct privsep *, enum privsep_procid,
uint16_t, void *, uint16_t);
int proc_composev_imsg(struct privsep *, enum privsep_procid, int,
u_int16_t, u_int32_t, int, const struct iovec *, int);
-int proc_forward_imsg(struct privsep *, struct imsg *,
- enum privsep_procid, int);
int proc_composev(struct privsep *, enum privsep_procid,
uint16_t, const struct iovec *, int);
+int proc_forward_imsg(struct privsep *, struct imsg *,
+ enum privsep_procid, int);
struct imsgbuf *
proc_ibuf(struct privsep *, enum privsep_procid, int);
struct imsgev *
proc_iev(struct privsep *, enum privsep_procid, int);
void imsg_event_add(struct imsgev *);
-int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
- pid_t, int, void *, u_int16_t);
-int imsg_composev_event(struct imsgev *, u_int16_t, u_int32_t,
+int imsg_compose_event(struct imsgev *, uint16_t, uint32_t,
+ pid_t, int, void *, uint16_t);
+int imsg_composev_event(struct imsgev *, uint16_t, uint32_t,
pid_t, int, const struct iovec *, int);
/* config.c */