Less differences, less code to audit.
ok mikeb@
-/* $OpenBSD: ca.c,v 1.26 2014/02/17 15:07:23 markus Exp $ */
+/* $OpenBSD: ca.c,v 1.27 2014/04/22 12:00:03 reyk Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
#include "iked.h"
#include "ikev2.h"
-void ca_reset(struct privsep *, void *);
+void ca_reset(struct privsep *, struct privsep_proc *, void *);
int ca_reload(struct iked *);
int ca_getreq(struct iked *, struct imsg *);
}
void
-ca_reset(struct privsep *ps, void *arg)
+ca_reset(struct privsep *ps, struct privsep_proc *p, void *arg)
{
struct iked *env = ps->ps_env;
struct ca_store *store = arg;
memcpy(&mode, imsg->data, sizeof(mode));
if (mode == RESET_ALL || mode == RESET_CA) {
log_debug("%s: config reload", __func__);
- ca_reset(&env->sc_ps, store);
+ ca_reset(&env->sc_ps, p, store);
}
break;
case IMSG_OCSP_FD:
iov[iovcnt].iov_len = len;
iovcnt++;
- if (proc_composev_imsg(env, procid, IMSG_CERT, -1, iov, iovcnt) == -1)
+ if (proc_composev_imsg(&env->sc_ps, procid, -1,
+ IMSG_CERT, -1, iov, iovcnt) == -1)
return (-1);
return (0);
}
iov[iovcnt].iov_len = len;
iovcnt++;
- if (proc_composev_imsg(env, procid,
+ if (proc_composev_imsg(&env->sc_ps, procid, -1,
IMSG_CERTREQ, -1, iov, iovcnt) == -1)
goto done;
log_debug("%s: auth length %zu", __func__, ibuf_size(authmsg));
}
- if (proc_composev_imsg(env, id, IMSG_AUTH, -1, iov, iovcnt) == -1)
+ if (proc_composev_imsg(&env->sc_ps, id, -1,
+ IMSG_AUTH, -1, iov, iovcnt) == -1)
return (-1);
return (0);
}
iov[1].iov_base = &type;
iov[1].iov_len = sizeof(type);
- if (proc_composev_imsg(env, PROC_IKEV2, cmd, -1, iov, iovcnt) == -1)
+ if (proc_composev_imsg(&env->sc_ps, PROC_IKEV2, -1,
+ cmd, -1, iov, iovcnt) == -1)
return (-1);
return (0);
}
ibuf_length(env->sc_certreq) == SHA_DIGEST_LENGTH ?
"" : "s");
- (void)proc_composev_imsg(env, PROC_IKEV2, IMSG_CERTREQ, -1,
- iov, iovcnt);
+ (void)proc_composev_imsg(&env->sc_ps, PROC_IKEV2, -1,
+ IMSG_CERTREQ, -1, iov, iovcnt);
}
/*
iov[0].iov_base = &env->sc_certreqtype;
iov[0].iov_len = sizeof(env->sc_certreqtype);
- (void)proc_composev_imsg(env, PROC_IKEV2, IMSG_CERTREQ, -1,
- iov, iovcnt);
+ (void)proc_composev_imsg(&env->sc_ps, PROC_IKEV2, -1,
+ IMSG_CERTREQ, -1, iov, iovcnt);
return (0);
}
-/* $OpenBSD: config.c,v 1.26 2014/02/17 15:53:46 markus Exp $ */
+/* $OpenBSD: config.c,v 1.27 2014/04/22 12:00:03 reyk Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
u_int type;
type = couple ? IMSG_CTL_COUPLE : IMSG_CTL_DECOUPLE;
- proc_compose_imsg(env, PROC_IKEV1, type, -1, NULL, 0);
- proc_compose_imsg(env, PROC_IKEV2, type, -1, NULL, 0);
+ proc_compose_imsg(&env->sc_ps, PROC_IKEV1, -1, type, -1, NULL, 0);
+ proc_compose_imsg(&env->sc_ps, PROC_IKEV2, -1, type, -1, NULL, 0);
return (0);
}
u_int type;
type = passive ? IMSG_CTL_PASSIVE : IMSG_CTL_ACTIVE;
- proc_compose_imsg(env, PROC_IKEV1, type, -1, NULL, 0);
- proc_compose_imsg(env, PROC_IKEV2, type, -1, NULL, 0);
+ proc_compose_imsg(&env->sc_ps, PROC_IKEV1, -1, type, -1, NULL, 0);
+ proc_compose_imsg(&env->sc_ps, PROC_IKEV2, -1, type, -1, NULL, 0);
return (0);
}
int
config_setreset(struct iked *env, u_int mode, enum privsep_procid id)
{
- proc_compose_imsg(env, id, IMSG_CTL_RESET, -1, &mode, sizeof(mode));
+ proc_compose_imsg(&env->sc_ps, id, -1,
+ IMSG_CTL_RESET, -1, &mode, sizeof(mode));
return (0);
}
if ((s = udp_bind((struct sockaddr *)ss, port)) == -1)
return (-1);
- proc_compose_imsg(env, id, IMSG_UDP_SOCKET, s,
- ss, sizeof(*ss));
+ proc_compose_imsg(&env->sc_ps, id, -1,
+ IMSG_UDP_SOCKET, s, ss, sizeof(*ss));
return (0);
}
if ((s = pfkey_socket()) == -1)
return (-1);
- proc_compose_imsg(env, id, IMSG_PFKEY_SOCKET, s, NULL, 0);
+ proc_compose_imsg(&env->sc_ps, id, -1,
+ IMSG_PFKEY_SOCKET, s, NULL, 0);
return (0);
}
return (0);
}
- proc_compose_imsg(env, id, IMSG_CFG_USER, -1, usr, sizeof(*usr));
+ proc_compose_imsg(&env->sc_ps, id, -1,
+ IMSG_CFG_USER, -1, usr, sizeof(*usr));
return (0);
}
return (0);
}
- if (proc_composev_imsg(env, id, IMSG_CFG_POLICY, -1,
- iov, iovcnt) == -1)
+ if (proc_composev_imsg(&env->sc_ps, id, -1,
+ IMSG_CFG_POLICY, -1, iov, iovcnt) == -1)
return (-1);
return (0);
if (env->sc_opts & IKED_OPT_NOACTION)
return (0);
- proc_compose_imsg(env, id, IMSG_COMPILE, -1, NULL, 0);
+ proc_compose_imsg(&env->sc_ps, id, -1,
+ IMSG_COMPILE, -1, NULL, 0);
return (0);
}
{
if (env->sc_opts & IKED_OPT_NOACTION)
return (0);
- proc_compose_imsg(env, PROC_CERT, IMSG_OCSP_URL, -1, env->sc_ocsp_url,
+ proc_compose_imsg(&env->sc_ps, PROC_CERT, -1,
+ IMSG_OCSP_URL, -1, env->sc_ocsp_url,
env->sc_ocsp_url ? strlen(env->sc_ocsp_url) : 0);
return (0);
-/* $OpenBSD: control.c,v 1.13 2013/11/15 12:30:19 mikeb Exp $ */
+/* $OpenBSD: control.c,v 1.14 2014/04/22 12:00:03 reyk Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
memcpy(&v, imsg.data, sizeof(v));
log_verbose(v);
- proc_forward_imsg(env, &imsg, PROC_PARENT);
- proc_forward_imsg(env, &imsg, PROC_IKEV2);
- proc_forward_imsg(env, &imsg, PROC_IKEV1);
+ proc_forward_imsg(&env->sc_ps, &imsg, PROC_PARENT, -1);
+ proc_forward_imsg(&env->sc_ps, &imsg, PROC_IKEV2, -1);
+ proc_forward_imsg(&env->sc_ps, &imsg, PROC_IKEV1, -1);
break;
case IMSG_CTL_RELOAD:
case IMSG_CTL_RESET:
case IMSG_CTL_DECOUPLE:
case IMSG_CTL_ACTIVE:
case IMSG_CTL_PASSIVE:
- proc_forward_imsg(env, &imsg, PROC_PARENT);
+ proc_forward_imsg(&env->sc_ps, &imsg, PROC_PARENT, -1);
break;
default:
log_debug("%s: error handling imsg %d",
-/* $OpenBSD: iked.c,v 1.19 2014/02/17 15:07:23 markus Exp $ */
+/* $OpenBSD: iked.c,v 1.20 2014/04/22 12:00:03 reyk Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
err(1, "failed to daemonize");
group_init();
+
+ ps->ps_ninstances = 1;
proc_init(ps, procs, nitems(procs));
setproctitle("parent");
signal_add(&ps->ps_evsighup, NULL);
signal_add(&ps->ps_evsigpipe, NULL);
- proc_config(ps, procs, nitems(procs));
+ proc_listen(ps, procs, nitems(procs));
if (parent_configure(env) == -1)
fatalx("configuration failed");
case IMSG_CTL_DECOUPLE:
case IMSG_CTL_ACTIVE:
case IMSG_CTL_PASSIVE:
- proc_compose_imsg(env, PROC_IKEV1, type, -1, NULL, 0);
- proc_compose_imsg(env, PROC_IKEV2, type, -1, NULL, 0);
+ proc_compose_imsg(&env->sc_ps, PROC_IKEV1, -1,
+ type, -1, NULL, 0);
+ proc_compose_imsg(&env->sc_ps, PROC_IKEV2, -1,
+ type, -1, NULL, 0);
break;
case IMSG_CTL_RELOAD:
if (IMSG_DATA_SIZE(imsg) > 0)
-/* $OpenBSD: iked.h,v 1.71 2014/04/10 16:08:02 reyk Exp $ */
+/* $OpenBSD: iked.h,v 1.72 2014/04/22 12:00:03 reyk Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
struct imsgbuf ibuf;
void (*handler)(int, short, void *);
struct event ev;
+ struct privsep_proc *proc;
void *data;
short events;
const char *name;
};
RB_HEAD(iked_users, iked_user);
+struct privsep_pipes {
+ int *pp_pipes[PROC_MAX];
+};
+
struct privsep {
- int ps_pipes[PROC_MAX][PROC_MAX];
- struct imsgev ps_ievs[PROC_MAX];
+ struct privsep_pipes *ps_pipes[PROC_MAX];
+ struct privsep_pipes *ps_pp;
+
+ struct imsgev *ps_ievs[PROC_MAX];
const char *ps_title[PROC_MAX];
pid_t ps_pid[PROC_MAX];
struct passwd *ps_pw;
+ int ps_noaction;
struct control_sock ps_csock;
+ u_int ps_instances[PROC_MAX];
+ u_int ps_ninstances;
+ u_int ps_instance;
+
/* Event and signal handlers */
struct event ps_evsigint;
struct event ps_evsigterm;
const char *p_chroot;
struct privsep *p_ps;
struct iked *p_env;
+ void (*p_shutdown)(void);
+ u_int p_instance;
};
struct iked_ocsp_entry {
/* proc.c */
void proc_init(struct privsep *, struct privsep_proc *, u_int);
void proc_kill(struct privsep *);
-void proc_config(struct privsep *, struct privsep_proc *, u_int);
+void proc_listen(struct privsep *, struct privsep_proc *, size_t);
void proc_dispatch(int, short event, void *);
pid_t proc_run(struct privsep *, struct privsep_proc *,
struct privsep_proc *, u_int,
- void (*)(struct privsep *, void *), void *);
+ void (*)(struct privsep *, struct privsep_proc *, void *), void *);
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,
pid_t, int, const struct iovec *, int);
-int proc_compose_imsg(struct iked *, enum privsep_procid,
+int proc_compose_imsg(struct privsep *, enum privsep_procid, int,
u_int16_t, int, void *, u_int16_t);
-int proc_composev_imsg(struct iked *, enum privsep_procid,
+int proc_composev_imsg(struct privsep *, enum privsep_procid, int,
u_int16_t, int, const struct iovec *, int);
-int proc_forward_imsg(struct iked *, struct imsg *,
- enum privsep_procid);
+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);
/* util.c */
void socket_set_blockmode(int, enum blockmodes);
-/* $OpenBSD: ikev1.c,v 1.14 2014/02/17 11:00:14 reyk Exp $ */
+/* $OpenBSD: ikev1.c,v 1.15 2014/04/22 12:00:03 reyk Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
iov[1].iov_base = buf;
iov[1].iov_len = len;
- proc_composev_imsg(env, PROC_IKEV2, IMSG_IKE_MESSAGE, -1,
- iov, 2);
+ proc_composev_imsg(&env->sc_ps, PROC_IKEV2, -1,
+ IMSG_IKE_MESSAGE, -1, iov, 2);
goto done;
}
-/* $OpenBSD: ikev2_msg.c,v 1.30 2014/04/10 16:08:02 reyk Exp $ */
+/* $OpenBSD: ikev2_msg.c,v 1.31 2014/04/22 12:00:03 reyk Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
iov[1].iov_base = buf;
iov[1].iov_len = len;
- proc_composev_imsg(env, PROC_IKEV1, IMSG_IKE_MESSAGE, -1,
- iov, 2);
+ proc_composev_imsg(&env->sc_ps, PROC_IKEV1, -1,
+ IMSG_IKE_MESSAGE, -1, iov, 2);
goto done;
}
TAILQ_INIT(&msg.msg_proposals);
/* the imsg framework will close the FD after send */
iov[0].iov_base = oc->oc_path;
iov[0].iov_len = strlen(oc->oc_path);
- ret = proc_composev_imsg(env, PROC_CERT, IMSG_OCSP_FD, fd,
- iov, iovcnt);
+ ret = proc_composev_imsg(&env->sc_ps, PROC_CERT, -1,
+ IMSG_OCSP_FD, fd, iov, iovcnt);
} else {
- ret = proc_compose_imsg(env, PROC_CERT, IMSG_OCSP_FD, -1,
- NULL, 0);
+ ret = proc_compose_imsg(&env->sc_ps, PROC_CERT, -1,
+ IMSG_OCSP_FD, -1, NULL, 0);
if (fd >= 0)
close(fd);
}
TAILQ_INSERT_TAIL(&env->sc_ocsp, ioe, ioe_entry);
/* request connection to ocsp-responder */
- proc_compose_imsg(env, PROC_PARENT, IMSG_OCSP_FD, -1, NULL, 0);
+ proc_compose_imsg(&env->sc_ps, PROC_PARENT, -1,
+ IMSG_OCSP_FD, -1, NULL, 0);
return (0);
err:
int
ocsp_validate_finish(struct iked_ocsp *ocsp, int valid)
{
+ struct iked *env = ocsp->ocsp_env;
struct iovec iov[2];
int iovcnt = 2, ret, cmd;
iov[1].iov_len = sizeof(ocsp->ocsp_type);
cmd = valid ? IMSG_CERTVALID : IMSG_CERTINVALID;
- ret = proc_composev_imsg(ocsp->ocsp_env, PROC_IKEV2, cmd, -1, iov,
- iovcnt);
+ ret = proc_composev_imsg(&env->sc_ps, PROC_IKEV2, -1,
+ cmd, -1, iov, iovcnt);
ocsp_free(ocsp);
return (ret);
-/* $OpenBSD: proc.c,v 1.13 2014/04/18 21:29:20 tedu Exp $ */
+/* $OpenBSD: proc.c,v 1.14 2014/04/22 12:00:03 reyk Exp $ */
/*
- * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2010 - 2014 Reyk Floeter <reyk@openbsd.org>
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
#include <sys/param.h>
#include <sys/queue.h>
-#include <sys/tree.h>
-#include <sys/wait.h>
#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/tree.h>
+
+#include <net/if.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <event.h>
#include <openssl/rand.h>
+#include <openssl/ssl.h>
#include "iked.h"
-void proc_setup(struct privsep *);
+void proc_open(struct privsep *, struct privsep_proc *,
+ struct privsep_proc *, size_t);
+void proc_close(struct privsep *);
+int proc_ispeer(struct privsep_proc *, u_int, enum privsep_procid);
void proc_shutdown(struct privsep_proc *);
void proc_sig_handler(int, short, void *);
+void proc_range(struct privsep *, enum privsep_procid, int *, int *);
+
+int
+proc_ispeer(struct privsep_proc *procs, u_int nproc, enum privsep_procid type)
+{
+ u_int i;
+
+ for (i = 0; i < nproc; i++)
+ if (procs[i].p_id == type)
+ return (1);
+ return (0);
+}
void
-proc_init(struct privsep *ps, struct privsep_proc *p, u_int nproc)
+proc_init(struct privsep *ps, struct privsep_proc *procs, u_int nproc)
{
- u_int i;
+ u_int i, j, src, dst;
+ struct privsep_pipes *pp;
/*
- * Called from parent
+ * Allocate pipes for all process instances (incl. parent)
+ *
+ * - ps->ps_pipes: N:M mapping
+ * N source processes connected to M destination processes:
+ * [src][instances][dst][instances], for example
+ * [PROC_RELAY][3][PROC_CA][3]
+ *
+ * - ps->ps_pp: per-process 1:M part of ps->ps_pipes
+ * Each process instance has a destination array of socketpair fds:
+ * [dst][instances], for example
+ * [PROC_PARENT][0]
+ */
+ for (src = 0; src < PROC_MAX; src++) {
+ /* Allocate destination array for each process */
+ if ((ps->ps_pipes[src] = calloc(ps->ps_ninstances,
+ sizeof(struct privsep_pipes))) == NULL)
+ fatal("proc_init: calloc");
+
+ for (i = 0; i < ps->ps_ninstances; i++) {
+ pp = &ps->ps_pipes[src][i];
+
+ for (dst = 0; dst < PROC_MAX; dst++) {
+ /* Allocate maximum fd integers */
+ if ((pp->pp_pipes[dst] =
+ calloc(ps->ps_ninstances,
+ sizeof(int))) == NULL)
+ fatal("proc_init: calloc");
+
+ /* Mark fd as unused */
+ for (j = 0; j < ps->ps_ninstances; j++)
+ pp->pp_pipes[dst][j] = -1;
+ }
+ }
+ }
+
+ /*
+ * 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_pid[PROC_PARENT] = getpid();
+ ps->ps_pp = &ps->ps_pipes[privsep_process][0];
- proc_setup(ps);
+ for (i = 0; i < nproc; i++) {
+ /* Default to 1 process instance */
+ if (ps->ps_instances[procs[i].p_id] < 1)
+ ps->ps_instances[procs[i].p_id] = 1;
+ ps->ps_title[procs[i].p_id] = procs[i].p_title;
+ }
+
+ proc_open(ps, NULL, procs, nproc);
/* Engage! */
- for (i = 0; i < nproc; i++, p++) {
- ps->ps_title[p->p_id] = p->p_title;
- ps->ps_pid[p->p_id] = (*p->p_init)(ps, p);
- }
+ for (i = 0; i < nproc; i++)
+ ps->ps_pid[procs[i].p_id] = (*procs[i].p_init)(ps, &procs[i]);
}
void
for (i = 0; i < PROC_MAX; i++) {
if (ps->ps_pid[i] == 0)
continue;
- kill(ps->ps_pid[i], SIGTERM);
+ killpg(ps->ps_pid[i], SIGTERM);
}
do {
pid = waitpid(WAIT_ANY, NULL, 0);
} while (pid != -1 || (pid == -1 && errno == EINTR));
+
+ proc_close(ps);
}
void
-proc_setup(struct privsep *ps)
+proc_open(struct privsep *ps, struct privsep_proc *p,
+ struct privsep_proc *procs, size_t nproc)
{
- int i, j, sockpair[2];
-
- for (i = 0; i < PROC_MAX; i++)
- for (j = 0; j < PROC_MAX; j++) {
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- sockpair) == -1)
- fatal("sockpair");
- ps->ps_pipes[i][j] = sockpair[0];
- ps->ps_pipes[j][i] = sockpair[1];
- socket_set_blockmode(ps->ps_pipes[i][j],
- BM_NONBLOCK);
- socket_set_blockmode(ps->ps_pipes[j][i],
- BM_NONBLOCK);
+ struct privsep_pipes *pa, *pb;
+ int fds[2];
+ u_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;
+
+ 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,
+ PF_UNSPEC, fds) == -1)
+ fatal("socketpair");
+
+ socket_set_blockmode(fds[0], BM_NONBLOCK);
+ socket_set_blockmode(fds[1], BM_NONBLOCK);
+
+ pa->pp_pipes[procs[proc].p_id][j] = fds[0];
+ pb->pp_pipes[src][i] = fds[1];
+ }
}
+ }
}
void
-proc_config(struct privsep *ps, struct privsep_proc *p, u_int nproc)
+proc_listen(struct privsep *ps, struct privsep_proc *procs, size_t nproc)
{
- u_int src, dst, i, j, k, found;
-
- src = privsep_process;
+ u_int i, dst, src, n, m;
+ struct privsep_pipes *pp;
/*
- * close unused pipes
+ * Close unused pipes
*/
- for (i = 0; i < PROC_MAX; i++) {
- if (i != privsep_process) {
- for (j = 0; j < PROC_MAX; j++) {
- close(ps->ps_pipes[i][j]);
- ps->ps_pipes[i][j] = -1;
- }
- } else {
- for (j = found = 0; j < PROC_MAX; j++, found = 0) {
- for (k = 0; k < nproc; k++) {
- if (p[k].p_id == j)
- found++;
- }
- if (!found) {
- close(ps->ps_pipes[i][j]);
- ps->ps_pipes[i][j] = -1;
+ for (src = 0; src < PROC_MAX; src++) {
+ for (n = 0; n < ps->ps_instances[src]; n++) {
+ /* Ingore current process */
+ if (src == (u_int)privsep_process &&
+ n == ps->ps_instance)
+ 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
+ * Listen on appropriate pipes
*/
- for (i = 0; i < nproc; i++, p++) {
- dst = p->p_id;
- p->p_ps = ps;
- p->p_env = ps->ps_env;
-
- imsg_init(&ps->ps_ievs[dst].ibuf,
- ps->ps_pipes[src][dst]);
- ps->ps_ievs[dst].handler = proc_dispatch;
- ps->ps_ievs[dst].events = EV_READ;
- ps->ps_ievs[dst].data = p;
- ps->ps_ievs[dst].name = p->p_title;
- event_set(&ps->ps_ievs[dst].ev,
- ps->ps_ievs[dst].ibuf.fd,
- ps->ps_ievs[dst].events,
- ps->ps_ievs[dst].handler,
- ps->ps_ievs[dst].data);
- event_add(&ps->ps_ievs[dst].ev, NULL);
+ 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)
+ 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];
+ procs[i].p_instance = 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);
+ }
+ }
+}
+
+void
+proc_close(struct privsep *ps)
+{
+ u_int dst, n;
+ struct privsep_pipes *pp;
+
+ if (ps == NULL)
+ return;
+
+ pp = ps->ps_pp;
+
+ for (dst = 0; dst < PROC_MAX; dst++) {
+ if (ps->ps_ievs[dst] == NULL)
+ continue;
+
+ for (n = 0; n < ps->ps_instances[dst]; n++) {
+ if (pp->pp_pipes[dst][n] == -1)
+ continue;
+
+ /* Cancel the fd, close and invalidate the fd */
+ event_del(&(ps->ps_ievs[dst][n].ev));
+ imsg_clear(&(ps->ps_ievs[dst][n].ibuf));
+ close(pp->pp_pipes[dst][n]);
+ pp->pp_pipes[dst][n] = -1;
+ }
+ free(ps->ps_ievs[dst]);
}
}
if (p->p_id == PROC_CONTROL && ps)
control_cleanup(&ps->ps_csock);
- log_info("%s exiting", p->p_title);
+ if (p->p_shutdown != NULL)
+ (*p->p_shutdown)();
+
+ proc_close(ps);
+
+ log_info("%s exiting, pid %d", p->p_title, getpid());
+
_exit(0);
}
pid_t
proc_run(struct privsep *ps, struct privsep_proc *p,
struct privsep_proc *procs, u_int nproc,
- void (*init)(struct privsep *, void *), void *arg)
+ void (*init)(struct privsep *, struct privsep_proc *, void *), void *arg)
{
pid_t pid;
struct passwd *pw;
const char *root;
+ u_int n;
+
+ if (ps->ps_noaction)
+ return (0);
+ proc_open(ps, p, procs, nproc);
+
+ /* Fork child handlers */
switch (pid = fork()) {
case -1:
fatal("proc_run: cannot fork");
case 0:
+ /* Set the process group of the current process */
+ setpgrp(0, getpid());
break;
default:
return (pid);
pw = ps->ps_pw;
- if (p->p_id == PROC_CONTROL) {
+ if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
if (control_init(ps, &ps->ps_csock) == -1)
fatalx(p->p_title);
}
fatal("proc_run: cannot drop privileges");
#endif
+ /* Fork child handlers */
+ for (n = 1; n < ps->ps_instances[p->p_id]; n++) {
+ if (fork() == 0) {
+ ps->ps_instance = p->p_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);
signal_add(&ps->ps_evsighup, NULL);
signal_add(&ps->ps_evsigpipe, NULL);
- proc_config(ps, procs, nproc);
+ proc_listen(ps, procs, nproc);
- if (p->p_id == PROC_CONTROL) {
+ if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
TAILQ_INIT(&ctl_conns);
if (control_listen(&ps->ps_csock) == -1)
fatalx(p->p_title);
}
if (init != NULL)
- init(ps, arg);
+ init(ps, p, arg);
event_dispatch();
void
proc_dispatch(int fd, short event, void *arg)
{
- struct privsep_proc *p = (struct privsep_proc *)arg;
+ struct imsgev *iev = arg;
+ struct privsep_proc *p = iev->proc;
struct privsep *ps = p->p_ps;
- struct imsgev *iev;
struct imsgbuf *ibuf;
struct imsg imsg;
ssize_t n;
const char *title;
title = ps->ps_title[privsep_process];
- iev = &ps->ps_ievs[p->p_id];
ibuf = &iev->ibuf;
if (event & EV_READ) {
}
if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
+ if (msgbuf_write(&ibuf->w) == -1 && errno != EAGAIN)
fatal(title);
}
if (n == 0)
break;
+#if DEBUG > 1
+ log_debug("%s: %s %d got imsg %d from %s %d",
+ __func__, title, ps->ps_instance + 1,
+ imsg.hdr.type, p->p_title, p->p_instance);
+#endif
+
/*
* Check the message with the program callback
*/
switch (imsg.hdr.type) {
case IMSG_CTL_VERBOSE:
IMSG_SIZE_CHECK(&imsg, &verbose);
-
memcpy(&verbose, imsg.data, sizeof(verbose));
log_verbose(verbose);
break;
default:
- log_warnx("%s: %s got imsg %d", __func__, p->p_title,
- imsg.hdr.type);
+ log_warnx("%s: %s %d got invalid imsg %d from %s %d",
+ __func__, title, ps->ps_instance + 1,
+ imsg.hdr.type, p->p_title, p->p_instance);
fatalx(title);
}
imsg_free(&imsg);
imsg_event_add(iev);
}
+/*
+ * imsg helper functions
+ */
+
void
imsg_event_add(struct imsgev *iev)
{
return (ret);
}
+void
+proc_range(struct privsep *ps, enum privsep_procid id, int *n, int *m)
+{
+ if (*n == -1) {
+ /* Use a range of all target instances */
+ *n = 0;
+ *m = ps->ps_instances[id];
+ } else {
+ /* Use only a single slot of the specified peer process */
+ *m = *n + 1;
+ }
+}
+
int
-proc_compose_imsg(struct iked *env, enum privsep_procid id,
+proc_compose_imsg(struct privsep *ps, enum privsep_procid id, int n,
u_int16_t type, int fd, void *data, u_int16_t datalen)
{
- return (imsg_compose_event(&env->sc_ps.ps_ievs[id],
- type, -1, 0, fd, data, datalen));
+ int m;
+
+ proc_range(ps, id, &n, &m);
+ for (; n < m; n++) {
+ if (imsg_compose_event(&ps->ps_ievs[id][n],
+ type, -1, 0, fd, data, datalen) == -1)
+ return (-1);
+ }
+
+ return (0);
}
int
-proc_composev_imsg(struct iked *env, enum privsep_procid id,
+proc_composev_imsg(struct privsep *ps, enum privsep_procid id, int n,
u_int16_t type, int fd, const struct iovec *iov, int iovcnt)
{
- return (imsg_composev_event(&env->sc_ps.ps_ievs[id],
- type, -1, 0, fd, iov, iovcnt));
+ int m;
+
+ proc_range(ps, id, &n, &m);
+ for (; n < m; n++)
+ if (imsg_composev_event(&ps->ps_ievs[id][n],
+ type, -1, 0, fd, iov, iovcnt) == -1)
+ return (-1);
+
+ return (0);
}
int
-proc_forward_imsg(struct iked *env, struct imsg *imsg,
- enum privsep_procid id)
+proc_forward_imsg(struct privsep *ps, struct imsg *imsg,
+ enum privsep_procid id, int n)
{
- return (proc_compose_imsg(env, id, imsg->hdr.type,
+ return (proc_compose_imsg(ps, id, n, imsg->hdr.type,
imsg->fd, imsg->data, IMSG_DATA_SIZE(imsg)));
}
+
+struct imsgbuf *
+proc_ibuf(struct privsep *ps, enum privsep_procid id, int n)
+{
+ int m;
+
+ proc_range(ps, id, &n, &m);
+ return (&ps->ps_ievs[id][n].ibuf);
+}
+
+struct imsgev *
+proc_iev(struct privsep *ps, enum privsep_procid id, int n)
+{
+ int m;
+
+ proc_range(ps, id, &n, &m);
+ return (&ps->ps_ievs[id][n]);
+}