summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2011-05-09 12:08:48 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2011-05-09 12:08:48 +0000
commit3fe6727c8a01992e5184fdb1f1330d867e249abd (patch)
tree329873c80f595e57dc3b87e303d657b6ad375e84 /usr.sbin/relayd
parent14b60d7f2a3b692fe6e022d46f3f406e34dbfdcd (diff)
Reorganize the relayd code to use the proc.c privsep API/commodity
functions that are based on work for iked and smtpd. This simplifies the setup of privsep processes and moves some redundant and repeated code to a single place - which is always good from a quality and security point of view. The relayd version of proc.c is different to the current version in iked because it uses 1:N communications between processes, eg. a single parent process is talking to many forked relay children while iked only needs 1:1 communications. ok sthen@ pyr@
Diffstat (limited to 'usr.sbin/relayd')
-rw-r--r--usr.sbin/relayd/Makefile4
-rw-r--r--usr.sbin/relayd/check_icmp.c4
-rw-r--r--usr.sbin/relayd/check_script.c10
-rw-r--r--usr.sbin/relayd/control.c93
-rw-r--r--usr.sbin/relayd/hce.c421
-rw-r--r--usr.sbin/relayd/parse.y3
-rw-r--r--usr.sbin/relayd/pfe.c687
-rw-r--r--usr.sbin/relayd/pfe_route.c8
-rw-r--r--usr.sbin/relayd/relay.c461
-rw-r--r--usr.sbin/relayd/relay_udp.c7
-rw-r--r--usr.sbin/relayd/relayd.c574
-rw-r--r--usr.sbin/relayd/relayd.h234
-rw-r--r--usr.sbin/relayd/snmp.c54
13 files changed, 897 insertions, 1663 deletions
diff --git a/usr.sbin/relayd/Makefile b/usr.sbin/relayd/Makefile
index 30a7fa88d41..158491944da 100644
--- a/usr.sbin/relayd/Makefile
+++ b/usr.sbin/relayd/Makefile
@@ -1,10 +1,10 @@
-# $OpenBSD: Makefile,v 1.20 2010/05/26 16:44:32 nicm Exp $
+# $OpenBSD: Makefile,v 1.21 2011/05/09 12:08:47 reyk Exp $
PROG= relayd
SRCS= parse.y log.c control.c ssl.c ssl_privsep.c \
relayd.c pfe.c pfe_filter.c pfe_route.c hce.c relay.c \
relay_udp.c carp.c check_icmp.c check_tcp.c check_script.c \
- name2id.c snmp.c shuffle.c
+ name2id.c snmp.c shuffle.c proc.c
MAN= relayd.8 relayd.conf.5
LDADD= -levent -lssl -lcrypto -lutil
diff --git a/usr.sbin/relayd/check_icmp.c b/usr.sbin/relayd/check_icmp.c
index 9a399a784c0..df017f01a5f 100644
--- a/usr.sbin/relayd/check_icmp.c
+++ b/usr.sbin/relayd/check_icmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_icmp.c,v 1.30 2011/05/05 12:01:43 reyk Exp $ */
+/* $OpenBSD: check_icmp.c,v 1.31 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -59,7 +59,7 @@ icmp_setup(struct relayd *env, struct ctl_icmp_event *cie, int af)
proto = IPPROTO_ICMPV6;
if ((cie->s = socket(af, SOCK_RAW, proto)) < 0)
fatal("icmp_init: socket");
- session_socket_blockmode(cie->s, BM_NONBLOCK);
+ socket_set_blockmode(cie->s, BM_NONBLOCK);
cie->env = env;
cie->af = af;
}
diff --git a/usr.sbin/relayd/check_script.c b/usr.sbin/relayd/check_script.c
index fff3998e75a..5dff88d0113 100644
--- a/usr.sbin/relayd/check_script.c
+++ b/usr.sbin/relayd/check_script.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_script.c,v 1.11 2011/02/28 00:09:11 sthen Exp $ */
+/* $OpenBSD: check_script.c,v 1.12 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -39,11 +39,10 @@
void script_sig_alarm(int);
-extern struct imsgev *iev_main;
-pid_t child = -1;
+pid_t child = -1;
void
-check_script(struct host *host)
+check_script(struct relayd *env, struct host *host)
{
struct ctl_script scr;
@@ -51,7 +50,8 @@ check_script(struct host *host)
host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE);
scr.host = host->conf.id;
- imsg_compose_event(iev_main, IMSG_SCRIPT, 0, 0, -1, &scr, sizeof(scr));
+ proc_compose_imsg(env->sc_ps, PROC_PARENT, 0, IMSG_SCRIPT,
+ -1, &scr, sizeof(scr));
}
void
diff --git a/usr.sbin/relayd/control.c b/usr.sbin/relayd/control.c
index 8b1d8da936b..9c9a3cc02e4 100644
--- a/usr.sbin/relayd/control.c
+++ b/usr.sbin/relayd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.37 2011/05/05 12:01:43 reyk Exp $ */
+/* $OpenBSD: control.c,v 1.38 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -40,18 +40,19 @@
struct ctl_connlist ctl_conns;
-struct ctl_conn *control_connbyfd(int);
+void control_accept(int, short, void *);
void control_close(int);
-struct imsgev *iev_main = NULL;
-struct imsgev *iev_hce = NULL;
-
int
-control_init(void)
+control_init(struct privsep *ps, struct control_sock *cs)
{
+ struct relayd *env = ps->ps_env;
struct sockaddr_un sun;
int fd;
- mode_t old_umask;
+ mode_t old_umask, mode;
+
+ if (cs->cs_name == NULL)
+ return (0);
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
log_warn("%s: socket", __func__);
@@ -59,67 +60,74 @@ control_init(void)
}
sun.sun_family = AF_UNIX;
- if (strlcpy(sun.sun_path, RELAYD_SOCKET,
+ if (strlcpy(sun.sun_path, cs->cs_name,
sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
- log_warn("%s: %s name too long", __func__, RELAYD_SOCKET);
+ log_warn("%s: %s name too long", __func__, cs->cs_name);
close(fd);
return (-1);
}
- if (unlink(RELAYD_SOCKET) == -1)
+ if (unlink(cs->cs_name) == -1)
if (errno != ENOENT) {
- log_warn("%s: unlink %s", __func__, RELAYD_SOCKET);
+ log_warn("%s: unlink %s", __func__, cs->cs_name);
close(fd);
return (-1);
}
- old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
+ if (cs->cs_restricted) {
+ old_umask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
+ mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+ } else {
+ old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
+ mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
+ }
+
if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
- log_warn("%s: bind: %s", __func__, RELAYD_SOCKET);
+ log_warn("%s: bind: %s", __func__, cs->cs_name);
close(fd);
(void)umask(old_umask);
return (-1);
}
(void)umask(old_umask);
- if (chmod(RELAYD_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
+ if (chmod(cs->cs_name, mode) == -1) {
log_warn("%s: chmod", __func__);
close(fd);
- (void)unlink(RELAYD_SOCKET);
+ (void)unlink(cs->cs_name);
return (-1);
}
- session_socket_blockmode(fd, BM_NONBLOCK);
- control_state.fd = fd;
- TAILQ_INIT(&ctl_conns);
+ socket_set_blockmode(fd, BM_NONBLOCK);
+ cs->cs_fd = fd;
+ cs->cs_env = env;
return (0);
}
int
-control_listen(struct relayd *env, struct imsgev *i_main,
- struct imsgev *i_hce)
+control_listen(struct control_sock *cs)
{
+ if (cs->cs_name == NULL)
+ return (0);
- iev_main = i_main;
- iev_hce = i_hce;
-
- if (listen(control_state.fd, CONTROL_BACKLOG) == -1) {
+ if (listen(cs->cs_fd, CONTROL_BACKLOG) == -1) {
log_warn("%s: listen", __func__);
return (-1);
}
- event_set(&control_state.ev, control_state.fd, EV_READ | EV_PERSIST,
- control_accept, env);
- event_add(&control_state.ev, NULL);
+ event_set(&cs->cs_ev, cs->cs_fd, EV_READ | EV_PERSIST,
+ control_accept, cs->cs_env);
+ event_add(&cs->cs_ev, NULL);
return (0);
}
void
-control_cleanup(void)
+control_cleanup(struct control_sock *cs)
{
- (void)unlink(RELAYD_SOCKET);
+ if (cs->cs_name == NULL)
+ return;
+ (void)unlink(cs->cs_name);
}
/* ARGSUSED */
@@ -140,7 +148,7 @@ control_accept(int listenfd, short event, void *arg)
return;
}
- session_socket_blockmode(connfd, BM_NONBLOCK);
+ socket_set_blockmode(connfd, BM_NONBLOCK);
if ((c = calloc(1, sizeof(struct ctl_conn))) == NULL) {
close(connfd);
@@ -323,8 +331,8 @@ control_dispatch_imsg(int fd, short event, void *arg)
0, 0, -1, NULL, 0);
break;
case IMSG_CTL_POLL:
- imsg_compose_event(iev_hce, IMSG_CTL_POLL,
- 0, 0,-1, NULL, 0);
+ proc_compose_imsg(env->sc_ps, PROC_HCE, -1,
+ IMSG_CTL_POLL, -1, NULL, 0);
imsg_compose_event(&c->iev, IMSG_CTL_OK,
0, 0, -1, NULL, 0);
break;
@@ -334,8 +342,8 @@ control_dispatch_imsg(int fd, short event, void *arg)
0, 0, -1, NULL, 0);
break;
}
- imsg_compose_event(iev_main, IMSG_CTL_RELOAD,
- 0, 0, -1, NULL, 0);
+ proc_compose_imsg(env->sc_ps, PROC_PARENT, -1, IMSG_CTL_RELOAD,
+ -1, NULL, 0);
/*
* we unconditionnaly return a CTL_OK imsg because
* we have no choice.
@@ -358,20 +366,17 @@ control_dispatch_imsg(int fd, short event, void *arg)
}
c->flags |= CTL_CONN_NOTIFY;
break;
- case IMSG_CTL_LOG_VERBOSE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(verbose))
- break;
+ case IMSG_CTL_VERBOSE:
+ IMSG_SIZE_CHECK(&imsg, &verbose);
memcpy(&verbose, imsg.data, sizeof(verbose));
- imsg_compose_event(iev_hce, IMSG_CTL_LOG_VERBOSE,
- 0, 0, -1, &verbose, sizeof(verbose));
- imsg_compose_event(iev_main, IMSG_CTL_LOG_VERBOSE,
- 0, 0, -1, &verbose, sizeof(verbose));
+ proc_forward_imsg(env->sc_ps, &imsg, PROC_PARENT, 0);
+ proc_forward_imsg(env->sc_ps, &imsg, PROC_HCE, 0);
+ proc_forward_imsg(env->sc_ps, &imsg, PROC_RELAY, -1);
+
memcpy(imsg.data, &verbose, sizeof(verbose));
control_imsg_forward(&imsg);
-
log_verbose(verbose);
break;
default:
@@ -398,7 +403,7 @@ control_imsg_forward(struct imsg *imsg)
}
void
-session_socket_blockmode(int fd, enum blockmodes bm)
+socket_set_blockmode(int fd, enum blockmodes bm)
{
int flags;
diff --git a/usr.sbin/relayd/hce.c b/usr.sbin/relayd/hce.c
index 2eb5b0c5542..ab80166c4bb 100644
--- a/usr.sbin/relayd/hce.c
+++ b/usr.sbin/relayd/hce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hce.c,v 1.58 2011/05/05 12:01:43 reyk Exp $ */
+/* $OpenBSD: hce.c,v 1.59 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -41,135 +41,45 @@
#include "relayd.h"
-__dead void hce_shutdown(void);
-void hce_sig_handler(int sig, short, void *);
-void hce_dispatch_imsg(int, short, void *);
-void hce_dispatch_parent(int, short, void *);
-void hce_launch_checks(int, short, void *);
-void hce_setup_events(void);
-void hce_disable_events(void);
+void hce_init(struct privsep *, struct privsep_proc *p, void *);
+void hce_sig_handler(int sig, short, void *);
+void hce_launch_checks(int, short, void *);
+void hce_setup_events(void);
+void hce_disable_events(void);
+
+int hce_dispatch_parent(int, struct privsep_proc *, struct imsg *);
+int hce_dispatch_pfe(int, struct privsep_proc *, struct imsg *);
static struct relayd *env = NULL;
-struct imsgev *iev_pfe;
-struct imsgev *iev_main;
int running = 0;
-void
-hce_sig_handler(int sig, short event, void *arg)
-{
- switch (sig) {
- case SIGINT:
- case SIGTERM:
- hce_shutdown();
- break;
- case SIGCHLD:
- case SIGHUP:
- case SIGPIPE:
- /* ignore */
- break;
- default:
- fatalx("hce_sig_handler: unexpected signal");
- }
-}
+static struct privsep_proc procs[] = {
+ { "parent", PROC_PARENT, hce_dispatch_parent },
+ { "pfe", PROC_PFE, hce_dispatch_pfe },
+};
pid_t
-hce(struct relayd *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
- int pipe_parent2relay[RELAY_MAXPROC][2], int pipe_pfe2hce[2],
- int pipe_pfe2relay[RELAY_MAXPROC][2])
+hce(struct privsep *ps, struct privsep_proc *p)
{
- pid_t pid;
- struct passwd *pw;
- int i;
-
- switch (pid = fork()) {
- case -1:
- fatal("hce: cannot fork");
- case 0:
- break;
- default:
- return (pid);
- }
-
- env = x_env;
- purge_config(env, PURGE_RDRS|PURGE_RELAYS|PURGE_PROTOS);
-
- if ((pw = getpwnam(RELAYD_USER)) == NULL)
- fatal("hce: getpwnam");
-
-#ifndef DEBUG
- if (chroot(pw->pw_dir) == -1)
- fatal("hce: chroot");
- if (chdir("/") == -1)
- fatal("hce: chdir(\"/\")");
-#else
-#warning disabling privilege revocation and chroot in DEBUG mode
-#endif
-
- setproctitle("host check engine");
- relayd_process = PROC_HCE;
+ env = ps->ps_env;
/* this is needed for icmp tests */
icmp_init(env);
-#ifndef DEBUG
- if (setgroups(1, &pw->pw_gid) ||
- setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
- setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
- fatal("hce: can't drop privileges");
-#endif
+ return (proc_run(ps, p, procs, nitems(procs), hce_init, NULL));
+}
- event_init();
+void
+hce_init(struct privsep *ps, struct privsep_proc *p, void *arg)
+{
+ purge_config(env, PURGE_RDRS|PURGE_RELAYS|PURGE_PROTOS);
+
+ env->sc_id = getpid() & 0xffff;
/* Allow maximum available sockets for TCP checks */
socket_rlimit(-1);
- if ((iev_pfe = calloc(1, sizeof(struct imsgev))) == NULL ||
- (iev_main = calloc(1, sizeof(struct imsgev))) == NULL)
- fatal("hce");
- imsg_init(&iev_pfe->ibuf, pipe_pfe2hce[0]);
- iev_pfe->handler = hce_dispatch_imsg;
- imsg_init(&iev_main->ibuf, pipe_parent2hce[1]);
- iev_main->handler = hce_dispatch_parent;
-
- iev_pfe->events = EV_READ;
- event_set(&iev_pfe->ev, iev_pfe->ibuf.fd, iev_pfe->events,
- iev_pfe->handler, iev_pfe);
- event_add(&iev_pfe->ev, NULL);
-
- iev_main->events = EV_READ;
- event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
- iev_main->handler, iev_main);
- event_add(&iev_main->ev, NULL);
-
- signal_set(&env->sc_evsigint, SIGINT, hce_sig_handler, env);
- signal_set(&env->sc_evsigterm, SIGTERM, hce_sig_handler, env);
- signal_set(&env->sc_evsigchld, SIGCHLD, hce_sig_handler, env);
- signal_set(&env->sc_evsighup, SIGHUP, hce_sig_handler, env);
- signal_set(&env->sc_evsigpipe, SIGPIPE, hce_sig_handler, env);
-
- signal_add(&env->sc_evsigint, NULL);
- signal_add(&env->sc_evsigterm, NULL);
- signal_add(&env->sc_evsigchld, NULL);
- signal_add(&env->sc_evsighup, NULL);
- signal_add(&env->sc_evsigpipe, NULL);
-
- /* setup pipes */
- close(pipe_pfe2hce[1]);
- close(pipe_parent2hce[0]);
- close(pipe_parent2pfe[0]);
- close(pipe_parent2pfe[1]);
- for (i = 0; i < env->sc_prefork_relay; i++) {
- close(pipe_parent2relay[i][0]);
- close(pipe_parent2relay[i][1]);
- close(pipe_pfe2relay[i][0]);
- close(pipe_pfe2relay[i][1]);
- }
-
hce_setup_events();
- event_dispatch();
- hce_shutdown();
-
- return (0);
}
void
@@ -178,7 +88,7 @@ hce_setup_events(void)
struct timeval tv;
struct table *table;
- snmp_init(env, iev_main);
+ snmp_init(env, PROC_PARENT);
if (!TAILQ_EMPTY(env->sc_tables)) {
evtimer_set(&env->sc_ev, hce_launch_checks, env);
@@ -230,7 +140,7 @@ hce_launch_checks(int fd, short event, void *arg)
/*
* notify pfe checks are done and schedule next check
*/
- imsg_compose_event(iev_pfe, IMSG_SYNC, 0, 0, -1, NULL, 0);
+ proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_SYNC, -1, NULL, 0);
TAILQ_FOREACH(table, env->sc_tables, entry) {
TAILQ_FOREACH(host, &table->hosts, entry) {
if ((host->flags & F_CHECK_DONE) == 0)
@@ -265,7 +175,7 @@ hce_launch_checks(int fd, short event, void *arg)
schedule_icmp(env, host);
break;
case CHECK_SCRIPT:
- check_script(host);
+ check_script(env, host);
break;
default:
/* Any other TCP-style checks */
@@ -320,8 +230,8 @@ hce_notify_done(struct host *host, enum host_error he)
if (msg)
log_debug("%s: %s (%s)", __func__, host->conf.name, msg);
- imsg_compose_event(iev_pfe, IMSG_HOST_STATUS,
- 0, 0, -1, &st, sizeof(st));
+ proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_HOST_STATUS,
+ -1, &st, sizeof(st));
if (host->up != host->last_up)
logopt = RELAYD_OPT_LOGUPDATE;
else
@@ -348,7 +258,7 @@ hce_notify_done(struct host *host, enum host_error he)
}
if (host->last_up != host->up)
- snmp_hosttrap(table, host);
+ snmp_hosttrap(env, table, host);
host->last_up = host->up;
@@ -362,200 +272,119 @@ hce_notify_done(struct host *host, enum host_error he)
}
}
-void
-hce_shutdown(void)
-{
- log_info("host check engine exiting");
- _exit(0);
-}
-
-void
-hce_dispatch_imsg(int fd, short event, void *ptr)
+int
+hce_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
objid_t id;
struct host *host;
struct table *table;
- int verbose;
-
- iev = ptr;
- ibuf = &iev->ibuf;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("hce_dispatch_imsg: imsg_read_error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
- }
- }
-
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("hce_dispatch_imsg: msgbuf_write");
- }
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("hce_dispatch_imsg: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_HOST_DISABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((host = host_find(env, id)) == NULL)
- fatalx("hce_dispatch_imsg: desynchronized");
- host->flags |= F_DISABLE;
+ switch (imsg->hdr.type) {
+ case IMSG_HOST_DISABLE:
+ memcpy(&id, imsg->data, sizeof(id));
+ if ((host = host_find(env, id)) == NULL)
+ fatalx("hce_dispatch_imsg: desynchronized");
+ host->flags |= F_DISABLE;
+ host->up = HOST_UNKNOWN;
+ host->check_cnt = 0;
+ host->up_cnt = 0;
+ host->he = HCE_NONE;
+ break;
+ case IMSG_HOST_ENABLE:
+ memcpy(&id, imsg->data, sizeof(id));
+ if ((host = host_find(env, id)) == NULL)
+ fatalx("hce_dispatch_imsg: desynchronized");
+ host->flags &= ~(F_DISABLE);
+ host->up = HOST_UNKNOWN;
+ host->he = HCE_NONE;
+ break;
+ case IMSG_TABLE_DISABLE:
+ memcpy(&id, imsg->data, sizeof(id));
+ if ((table = table_find(env, id)) == NULL)
+ fatalx("hce_dispatch_imsg: desynchronized");
+ table->conf.flags |= F_DISABLE;
+ TAILQ_FOREACH(host, &table->hosts, entry)
host->up = HOST_UNKNOWN;
- host->check_cnt = 0;
- host->up_cnt = 0;
- host->he = HCE_NONE;
- break;
- case IMSG_HOST_ENABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((host = host_find(env, id)) == NULL)
- fatalx("hce_dispatch_imsg: desynchronized");
- host->flags &= ~(F_DISABLE);
+ break;
+ case IMSG_TABLE_ENABLE:
+ memcpy(&id, imsg->data, sizeof(id));
+ if ((table = table_find(env, id)) == NULL)
+ fatalx("hce_dispatch_imsg: desynchronized");
+ table->conf.flags &= ~(F_DISABLE);
+ TAILQ_FOREACH(host, &table->hosts, entry)
host->up = HOST_UNKNOWN;
- host->he = HCE_NONE;
- break;
- case IMSG_TABLE_DISABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((table = table_find(env, id)) == NULL)
- fatalx("hce_dispatch_imsg: desynchronized");
- table->conf.flags |= F_DISABLE;
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->up = HOST_UNKNOWN;
- break;
- case IMSG_TABLE_ENABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((table = table_find(env, id)) == NULL)
- fatalx("hce_dispatch_imsg: desynchronized");
- table->conf.flags &= ~(F_DISABLE);
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->up = HOST_UNKNOWN;
- break;
- case IMSG_CTL_POLL:
- evtimer_del(&env->sc_ev);
- TAILQ_FOREACH(table, env->sc_tables, entry)
- table->skipped = 0;
- hce_launch_checks(-1, EV_TIMEOUT, env);
- break;
- case IMSG_CTL_LOG_VERBOSE:
- memcpy(&verbose, imsg.data, sizeof(verbose));
- log_verbose(verbose);
- break;
- default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
+ break;
+ case IMSG_CTL_POLL:
+ evtimer_del(&env->sc_ev);
+ TAILQ_FOREACH(table, env->sc_tables, entry)
+ table->skipped = 0;
+ hce_launch_checks(-1, EV_TIMEOUT, env);
+ break;
+ default:
+ return (-1);
}
- imsg_event_add(iev);
+
+ return (0);
}
-void
-hce_dispatch_parent(int fd, short event, void * ptr)
+int
+hce_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
struct ctl_script scr;
- ssize_t n;
size_t len;
static struct table *table = NULL;
struct host *host, *parent;
- iev = ptr;
- ibuf = &iev->ibuf;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("hce_dispatch_parent: imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
+ switch (imsg->hdr.type) {
+ case IMSG_SCRIPT:
+ IMSG_SIZE_CHECK(imsg, &scr);
+ bcopy(imsg->data, &scr, sizeof(scr));
+ script_done(env, &scr);
+ break;
+ case IMSG_RECONF:
+ IMSG_SIZE_CHECK(imsg, env);
+ log_debug("%s: reloading configuration", __func__);
+ hce_disable_events();
+ purge_config(env, PURGE_TABLES);
+ merge_config(env, (struct relayd *)imsg->data);
+
+ env->sc_tables = calloc(1, sizeof(*env->sc_tables));
+ if (env->sc_tables == NULL)
+ fatal(NULL);
+
+ TAILQ_INIT(env->sc_tables);
+ break;
+ case IMSG_RECONF_TABLE:
+ if ((table = calloc(1, sizeof(*table))) == NULL)
+ fatal(NULL);
+ memcpy(&table->conf, imsg->data, sizeof(table->conf));
+ TAILQ_INIT(&table->hosts);
+ TAILQ_INSERT_TAIL(env->sc_tables, table, entry);
+ break;
+ case IMSG_RECONF_SENDBUF:
+ len = imsg->hdr.len - IMSG_HEADER_SIZE;
+ table->sendbuf = calloc(1, len);
+ (void)strlcpy(table->sendbuf, (char *)imsg->data, len);
+ break;
+ case IMSG_RECONF_HOST:
+ if ((host = calloc(1, sizeof(*host))) == NULL)
+ fatal(NULL);
+ memcpy(&host->conf, imsg->data, sizeof(host->conf));
+ host->tablename = table->conf.name;
+ TAILQ_INSERT_TAIL(&table->hosts, host, entry);
+ if (host->conf.parentid) {
+ parent = host_find(env, host->conf.parentid);
+ SLIST_INSERT_HEAD(&parent->children,
+ host, child);
}
+ break;
+ case IMSG_RECONF_END:
+ log_warnx("%s: configuration reloaded", __func__);
+ hce_setup_events();
+ break;
+ default:
+ return (-1);
}
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("hce_dispatch_parent: msgbuf_write");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("hce_dispatch_parent: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_SCRIPT:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(scr))
- fatalx("hce_dispatch_parent: "
- "invalid size of script request");
- bcopy(imsg.data, &scr, sizeof(scr));
- script_done(env, &scr);
- break;
- case IMSG_RECONF:
- log_debug("%s: reloading configuration", __func__);
- if (imsg.hdr.len !=
- sizeof(struct relayd) + IMSG_HEADER_SIZE)
- fatalx("corrupted reload data");
- hce_disable_events();
- purge_config(env, PURGE_TABLES);
- merge_config(env, (struct relayd *)imsg.data);
-
- env->sc_tables = calloc(1, sizeof(*env->sc_tables));
- if (env->sc_tables == NULL)
- fatal(NULL);
-
- TAILQ_INIT(env->sc_tables);
- break;
- case IMSG_RECONF_TABLE:
- if ((table = calloc(1, sizeof(*table))) == NULL)
- fatal(NULL);
- memcpy(&table->conf, imsg.data, sizeof(table->conf));
- TAILQ_INIT(&table->hosts);
- TAILQ_INSERT_TAIL(env->sc_tables, table, entry);
- break;
- case IMSG_RECONF_SENDBUF:
- len = imsg.hdr.len - IMSG_HEADER_SIZE;
- table->sendbuf = calloc(1, len);
- (void)strlcpy(table->sendbuf, (char *)imsg.data, len);
- break;
- case IMSG_RECONF_HOST:
- if ((host = calloc(1, sizeof(*host))) == NULL)
- fatal(NULL);
- memcpy(&host->conf, imsg.data, sizeof(host->conf));
- host->tablename = table->conf.name;
- TAILQ_INSERT_TAIL(&table->hosts, host, entry);
- if (host->conf.parentid) {
- parent = host_find(env, host->conf.parentid);
- SLIST_INSERT_HEAD(&parent->children,
- host, child);
- }
- break;
- case IMSG_RECONF_END:
- log_warnx("%s: configuration reloaded", __func__);
- hce_setup_events();
- break;
- default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(iev);
+ return (0);
}
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y
index fcb0b55f9c5..c03b54c4264 100644
--- a/usr.sbin/relayd/parse.y
+++ b/usr.sbin/relayd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.154 2011/05/05 12:01:43 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.155 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -1253,6 +1253,7 @@ relay : RELAY STRING {
conf->sc_relaycount++;
SPLAY_INIT(&rlay->rl_sessions);
TAILQ_INSERT_TAIL(conf->sc_relays, rlay, rl_entry);
+
tableport = 0;
while ((r = TAILQ_FIRST(&relays)) != NULL) {
diff --git a/usr.sbin/relayd/pfe.c b/usr.sbin/relayd/pfe.c
index a9d376d42e1..ba3a6260390 100644
--- a/usr.sbin/relayd/pfe.c
+++ b/usr.sbin/relayd/pfe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfe.c,v 1.67 2011/05/05 12:01:43 reyk Exp $ */
+/* $OpenBSD: pfe.c,v 1.68 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -35,180 +35,56 @@
#include "relayd.h"
-void pfe_sig_handler(int sig, short, void *);
-void pfe_shutdown(void);
-void pfe_setup_events(void);
-void pfe_disable_events(void);
-void pfe_dispatch_imsg(int, short, void *);
-void pfe_dispatch_parent(int, short, void *);
-void pfe_dispatch_relay(int, short, void *);
-void pfe_sync(void);
-void pfe_statistics(int, short, void *);
+void pfe_init(struct privsep *, struct privsep_proc *p, void *);
+void pfe_shutdown(void);
+void pfe_setup_events(void);
+void pfe_disable_events(void);
+void pfe_sync(void);
+void pfe_statistics(int, short, void *);
-static struct relayd *env = NULL;
+int pfe_dispatch_parent(int, struct privsep_proc *, struct imsg *);
+int pfe_dispatch_hce(int, struct privsep_proc *, struct imsg *);
+int pfe_dispatch_relay(int, struct privsep_proc *, struct imsg *);
-struct imsgev *iev_main;
-struct imsgev *iev_hce;
-struct imsgev *iev_relay;
+static struct relayd *env = NULL;
-void
-pfe_sig_handler(int sig, short event, void *arg)
-{
- switch (sig) {
- case SIGINT:
- case SIGTERM:
- pfe_shutdown();
- break;
- case SIGCHLD:
- case SIGHUP:
- case SIGPIPE:
- /* ignore */
- break;
- default:
- fatalx("pfe_sig_handler: unexpected signal");
- }
-}
+static struct privsep_proc procs[] = {
+ { "parent", PROC_PARENT, pfe_dispatch_parent },
+ { "relay", PROC_RELAY, pfe_dispatch_relay },
+ { "hce", PROC_HCE, pfe_dispatch_hce }
+};
pid_t
-pfe(struct relayd *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
- int pipe_parent2relay[RELAY_MAXPROC][2], int pipe_pfe2hce[2],
- int pipe_pfe2relay[RELAY_MAXPROC][2])
+pfe(struct privsep *ps, struct privsep_proc *p)
{
- pid_t pid;
- struct passwd *pw;
- int i;
- size_t size;
-
- switch (pid = fork()) {
- case -1:
- fatal("pfe: cannot fork");
- case 0:
- break;
- default:
- return (pid);
- }
-
- env = x_env;
- purge_config(env, PURGE_PROTOS);
-
- if (control_init() == -1)
- fatalx("pfe: control socket setup failed");
+ env = ps->ps_env;
init_filter(env);
init_tables(env);
- if ((pw = getpwnam(RELAYD_USER)) == NULL)
- fatal("pfe: getpwnam");
-
-#ifndef DEBUG
- if (chroot(pw->pw_dir) == -1)
- fatal("pfe: chroot");
- if (chdir("/") == -1)
- fatal("pfe: chdir(\"/\")");
-#else
-#warning disabling privilege revocation and chroot in DEBUG mode
-#endif
-
- setproctitle("pf update engine");
- relayd_process = PROC_PFE;
-
-#ifndef DEBUG
- if (setgroups(1, &pw->pw_gid) ||
- setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
- setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
- fatal("pfe: cannot drop privileges");
-#endif
-
- event_init();
-
- signal_set(&env->sc_evsigint, SIGINT, pfe_sig_handler, env);
- signal_set(&env->sc_evsigterm, SIGTERM, pfe_sig_handler, env);
- signal_set(&env->sc_evsigchld, SIGCHLD, pfe_sig_handler, env);
- signal_set(&env->sc_evsighup, SIGHUP, pfe_sig_handler, env);
- signal_set(&env->sc_evsigpipe, SIGPIPE, pfe_sig_handler, env);
-
- signal_add(&env->sc_evsigint, NULL);
- signal_add(&env->sc_evsigterm, NULL);
- signal_add(&env->sc_evsigchld, NULL);
- signal_add(&env->sc_evsighup, NULL);
- signal_add(&env->sc_evsigpipe, NULL);
-
- /* setup pipes */
- close(pipe_pfe2hce[0]);
- close(pipe_parent2pfe[0]);
- close(pipe_parent2hce[0]);
- close(pipe_parent2hce[1]);
- for (i = 0; i < env->sc_prefork_relay; i++) {
- close(pipe_parent2relay[i][0]);
- close(pipe_parent2relay[i][1]);
- close(pipe_pfe2relay[i][0]);
- }
-
- size = sizeof(struct imsgev);
- if ((iev_hce = calloc(1, size)) == NULL ||
- (iev_relay = calloc(env->sc_prefork_relay, size)) == NULL ||
- (iev_main = calloc(1, size)) == NULL)
- fatal("pfe");
-
- imsg_init(&iev_hce->ibuf, pipe_pfe2hce[1]);
- iev_hce->handler = pfe_dispatch_imsg;
- imsg_init(&iev_main->ibuf, pipe_parent2pfe[1]);
- iev_main->handler = pfe_dispatch_parent;
- for (i = 0; i < env->sc_prefork_relay; i++) {
- imsg_init(&iev_relay[i].ibuf, pipe_pfe2relay[i][1]);
- iev_relay[i].handler = pfe_dispatch_relay;
- }
-
- iev_main->events = EV_READ;
- event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
- iev_main->handler, iev_main);
- event_add(&iev_main->ev, NULL);
+ return (proc_run(ps, p, procs, nitems(procs), pfe_init, NULL));
+}
+void
+pfe_init(struct privsep *ps, struct privsep_proc *p, void *arg)
+{
+ p->p_shutdown = pfe_shutdown;
+ purge_config(env, PURGE_PROTOS);
pfe_setup_events();
-
- TAILQ_INIT(&ctl_conns);
-
- if (control_listen(env, iev_main, iev_hce) == -1)
- fatalx("pfe: control socket listen failed");
-
- /* Initial sync */
pfe_sync();
-
- event_dispatch();
- pfe_shutdown();
-
- return (0);
}
void
pfe_shutdown(void)
{
flush_rulesets(env);
- log_info("pf update engine exiting");
- _exit(0);
}
void
pfe_setup_events(void)
{
- int i;
- struct imsgev *iev;
struct timeval tv;
- iev_hce->events = EV_READ;
- event_set(&iev_hce->ev, iev_hce->ibuf.fd, iev_hce->events,
- iev_hce->handler, iev_hce);
- event_add(&iev_hce->ev, NULL);
-
- for (i = 0; i < env->sc_prefork_relay; i++) {
- iev = &iev_relay[i];
-
- iev->events = EV_READ;
- event_set(&iev->ev, iev->ibuf.fd, iev->events,
- iev->handler, iev);
- event_add(&iev->ev, NULL);
- }
-
/* Schedule statistics timer */
evtimer_set(&env->sc_statev, pfe_statistics, NULL);
bcopy(&env->sc_statinterval, &tv, sizeof(tv));
@@ -218,318 +94,209 @@ pfe_setup_events(void)
void
pfe_disable_events(void)
{
- int i;
-
- event_del(&iev_hce->ev);
-
- for (i = 0; i < env->sc_prefork_relay; i++)
- event_del(&iev_relay[i].ev);
-
event_del(&env->sc_statev);
}
-void
-pfe_dispatch_imsg(int fd, short event, void *ptr)
+int
+pfe_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
-
struct host *host;
struct table *table;
struct ctl_status st;
- iev = ptr;
- ibuf = &iev->ibuf;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("pfe_dispatch_imsg: imsg_read_error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
- }
- }
+ control_imsg_forward(imsg);
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("pfe_dispatch_imsg: msgbuf_write");
- }
+ switch (imsg->hdr.type) {
+ case IMSG_HOST_STATUS:
+ IMSG_SIZE_CHECK(imsg, &st);
+ memcpy(&st, imsg->data, sizeof(st));
+ if ((host = host_find(env, st.id)) == NULL)
+ fatalx("pfe_dispatch_imsg: invalid host id");
+ host->he = st.he;
+ if (host->flags & F_DISABLE)
+ break;
+ host->retry_cnt = st.retry_cnt;
+ if (st.up != HOST_UNKNOWN) {
+ host->check_cnt++;
+ if (st.up == HOST_UP)
+ host->up_cnt++;
+ }
+ if (host->check_cnt != st.check_cnt) {
+ log_debug("%s: host %d => %d", __func__,
+ host->conf.id, host->up);
+ fatalx("pfe_dispatch_imsg: desynchronized");
+ }
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("pfe_dispatch_imsg: imsg_read error");
- if (n == 0)
+ if (host->up == st.up)
break;
- control_imsg_forward(&imsg);
- switch (imsg.hdr.type) {
- case IMSG_HOST_STATUS:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(st))
- fatalx("pfe_dispatch_imsg: invalid request");
- memcpy(&st, imsg.data, sizeof(st));
- if ((host = host_find(env, st.id)) == NULL)
- fatalx("pfe_dispatch_imsg: invalid host id");
- host->he = st.he;
- if (host->flags & F_DISABLE)
- break;
- host->retry_cnt = st.retry_cnt;
- if (st.up != HOST_UNKNOWN) {
- host->check_cnt++;
- if (st.up == HOST_UP)
- host->up_cnt++;
- }
- if (host->check_cnt != st.check_cnt) {
- log_debug("%s: host %d => %d", __func__,
- host->conf.id, host->up);
- fatalx("pfe_dispatch_imsg: desynchronized");
- }
+ /* Forward to relay engine(s) */
+ proc_compose_imsg(env->sc_ps, PROC_RELAY, -1,
+ IMSG_HOST_STATUS, -1, &st, sizeof(st));
- if (host->up == st.up)
- break;
-
- /* Forward to relay engine(s) */
- for (n = 0; n < env->sc_prefork_relay; n++)
- imsg_compose_event(&iev_relay[n],
- IMSG_HOST_STATUS, 0, 0, -1, &st,
- sizeof(st));
-
- if ((table = table_find(env, host->conf.tableid))
- == NULL)
- fatalx("pfe_dispatch_imsg: invalid table id");
-
- log_debug("%s: state %d for host %u %s", __func__,
- st.up, host->conf.id, host->conf.name);
-
- /*
- * Do not change the table state when the host
- * state switches between UNKNOWN and DOWN.
- */
- if (HOST_ISUP(st.up)) {
- table->conf.flags |= F_CHANGED;
- table->up++;
- host->flags |= F_ADD;
- host->flags &= ~(F_DEL);
- } else if (HOST_ISUP(host->up)) {
- table->up--;
- table->conf.flags |= F_CHANGED;
- host->flags |= F_DEL;
- host->flags &= ~(F_ADD);
- }
+ if ((table = table_find(env, host->conf.tableid))
+ == NULL)
+ fatalx("pfe_dispatch_imsg: invalid table id");
- host->up = st.up;
- break;
- case IMSG_SYNC:
- pfe_sync();
- break;
- default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
- break;
+ log_debug("%s: state %d for host %u %s", __func__,
+ st.up, host->conf.id, host->conf.name);
+
+ /*
+ * Do not change the table state when the host
+ * state switches between UNKNOWN and DOWN.
+ */
+ if (HOST_ISUP(st.up)) {
+ table->conf.flags |= F_CHANGED;
+ table->up++;
+ host->flags |= F_ADD;
+ host->flags &= ~(F_DEL);
+ } else if (HOST_ISUP(host->up)) {
+ table->up--;
+ table->conf.flags |= F_CHANGED;
+ host->flags |= F_DEL;
+ host->flags &= ~(F_ADD);
}
- imsg_free(&imsg);
+
+ host->up = st.up;
+ break;
+ case IMSG_SYNC:
+ pfe_sync();
+ break;
+ default:
+ return (-1);
}
- imsg_event_add(iev);
+
+ return (0);
}
-void
-pfe_dispatch_parent(int fd, short event, void * ptr)
+int
+pfe_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
-
static struct rdr *rdr = NULL;
static struct table *table = NULL;
struct host *host, *parent;
struct address *virt;
- iev = ptr;
- ibuf = &iev->ibuf;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
- }
- }
+ switch (imsg->hdr.type) {
+ case IMSG_RECONF:
+ IMSG_SIZE_CHECK(imsg, env);
+ log_debug("%s: reloading configuration", __func__);
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
- }
+ pfe_disable_events();
+ purge_config(env, PURGE_RDRS|PURGE_TABLES);
+ merge_config(env, (struct relayd *)imsg->data);
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("pfe_dispatch_parent: imsg_read error");
- if (n == 0)
- break;
+ /*
+ * no relays when reconfiguring yet.
+ */
+ env->sc_relays = NULL;
+ env->sc_protos = NULL;
- switch (imsg.hdr.type) {
- case IMSG_RECONF:
- log_debug("%s: reloading configuration", __func__);
- if (imsg.hdr.len !=
- sizeof(struct relayd) + IMSG_HEADER_SIZE)
- fatalx("corrupted reload data");
- pfe_disable_events();
- purge_config(env, PURGE_RDRS|PURGE_TABLES);
- merge_config(env, (struct relayd *)imsg.data);
- /*
- * no relays when reconfiguring yet.
- */
- env->sc_relays = NULL;
- env->sc_protos = NULL;
-
- env->sc_tables = calloc(1, sizeof(*env->sc_tables));
- env->sc_rdrs = calloc(1, sizeof(*env->sc_rdrs));
- if (env->sc_tables == NULL || env->sc_rdrs == NULL)
- fatal(NULL);
-
- TAILQ_INIT(env->sc_tables);
- TAILQ_INIT(env->sc_rdrs);
- break;
- case IMSG_RECONF_TABLE:
- if ((table = calloc(1, sizeof(*table))) == NULL)
- fatal(NULL);
- memcpy(&table->conf, imsg.data, sizeof(table->conf));
- TAILQ_INIT(&table->hosts);
- TAILQ_INSERT_TAIL(env->sc_tables, table, entry);
- break;
- case IMSG_RECONF_HOST:
- if ((host = calloc(1, sizeof(*host))) == NULL)
- fatal(NULL);
- memcpy(&host->conf, imsg.data, sizeof(host->conf));
- host->tablename = table->conf.name;
- TAILQ_INSERT_TAIL(&table->hosts, host, entry);
- if (host->conf.parentid) {
- parent = host_find(env, host->conf.parentid);
- SLIST_INSERT_HEAD(&parent->children,
- host, child);
- }
- break;
- case IMSG_RECONF_RDR:
- if ((rdr = calloc(1, sizeof(*rdr))) == NULL)
- fatal(NULL);
- memcpy(&rdr->conf, imsg.data,
- sizeof(rdr->conf));
- rdr->table = table_find(env,
- rdr->conf.table_id);
- if (rdr->conf.backup_id == EMPTY_TABLE)
- rdr->backup = &env->sc_empty_table;
- else
- rdr->backup = table_find(env,
- rdr->conf.backup_id);
- if (rdr->table == NULL || rdr->backup == NULL)
- fatal("pfe_dispatch_parent:"
- " corrupted configuration");
- log_debug("%s: redirect table %s, backup %s",
- __func__,
- rdr->table->conf.name,
- rdr->backup->conf.name);
- TAILQ_INIT(&rdr->virts);
- TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry);
- break;
- case IMSG_RECONF_VIRT:
- if ((virt = calloc(1, sizeof(*virt))) == NULL)
- fatal(NULL);
- memcpy(virt, imsg.data, sizeof(*virt));
- TAILQ_INSERT_TAIL(&rdr->virts, virt, entry);
- break;
- case IMSG_RECONF_END:
- log_warnx("%s: configuration reloaded", __func__);
- init_tables(env);
- pfe_setup_events();
- pfe_sync();
- break;
- default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
- break;
+ env->sc_tables = calloc(1, sizeof(*env->sc_tables));
+ env->sc_rdrs = calloc(1, sizeof(*env->sc_rdrs));
+ if (env->sc_tables == NULL || env->sc_rdrs == NULL)
+ fatal(NULL);
+
+ TAILQ_INIT(env->sc_tables);
+ TAILQ_INIT(env->sc_rdrs);
+ break;
+ case IMSG_RECONF_TABLE:
+ if ((table = calloc(1, sizeof(*table))) == NULL)
+ fatal(NULL);
+ memcpy(&table->conf, imsg->data, sizeof(table->conf));
+ TAILQ_INIT(&table->hosts);
+ TAILQ_INSERT_TAIL(env->sc_tables, table, entry);
+ break;
+ case IMSG_RECONF_HOST:
+ if ((host = calloc(1, sizeof(*host))) == NULL)
+ fatal(NULL);
+ memcpy(&host->conf, imsg->data, sizeof(host->conf));
+ host->tablename = table->conf.name;
+ TAILQ_INSERT_TAIL(&table->hosts, host, entry);
+ if (host->conf.parentid) {
+ parent = host_find(env, host->conf.parentid);
+ SLIST_INSERT_HEAD(&parent->children,
+ host, child);
}
- imsg_free(&imsg);
+ break;
+ case IMSG_RECONF_RDR:
+ if ((rdr = calloc(1, sizeof(*rdr))) == NULL)
+ fatal(NULL);
+ memcpy(&rdr->conf, imsg->data,
+ sizeof(rdr->conf));
+ rdr->table = table_find(env,
+ rdr->conf.table_id);
+ if (rdr->conf.backup_id == EMPTY_TABLE)
+ rdr->backup = &env->sc_empty_table;
+ else
+ rdr->backup = table_find(env,
+ rdr->conf.backup_id);
+ if (rdr->table == NULL || rdr->backup == NULL)
+ fatal("pfe_dispatch_parent:"
+ " corrupted configuration");
+ log_debug("%s: redirect table %s, backup %s",
+ __func__,
+ rdr->table->conf.name,
+ rdr->backup->conf.name);
+ TAILQ_INIT(&rdr->virts);
+ TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry);
+ break;
+ case IMSG_RECONF_VIRT:
+ if ((virt = calloc(1, sizeof(*virt))) == NULL)
+ fatal(NULL);
+ memcpy(virt, imsg->data, sizeof(*virt));
+ TAILQ_INSERT_TAIL(&rdr->virts, virt, entry);
+ break;
+ case IMSG_RECONF_END:
+ log_warnx("%s: configuration reloaded", __func__);
+ init_tables(env);
+ pfe_setup_events();
+ pfe_sync();
+ break;
+ default:
+ return (-1);
}
- imsg_event_add(iev);
+
+ return (0);
}
-void
-pfe_dispatch_relay(int fd, short event, void * ptr)
+int
+pfe_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
struct ctl_natlook cnl;
struct ctl_stats crs;
struct relay *rlay;
- iev = ptr;
- ibuf = &iev->ibuf;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
- }
- }
-
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
+ switch (imsg->hdr.type) {
+ case IMSG_NATLOOK:
+ IMSG_SIZE_CHECK(imsg, &cnl);
+ bcopy(imsg->data, &cnl, sizeof(cnl));
+ if (cnl.proc > env->sc_prefork_relay)
+ fatalx("pfe_dispatch_relay: "
+ "invalid relay proc");
+ if (natlook(env, &cnl) != 0)
+ cnl.in = -1;
+ proc_compose_imsg(env->sc_ps, PROC_RELAY, cnl.proc,
+ IMSG_NATLOOK, -1, &cnl, sizeof(cnl));
+ break;
+ case IMSG_STATISTICS:
+ IMSG_SIZE_CHECK(imsg, &crs);
+ bcopy(imsg->data, &crs, sizeof(crs));
+ if (crs.proc > env->sc_prefork_relay)
+ fatalx("pfe_dispatch_relay: "
+ "invalid relay proc");
+ if ((rlay = relay_find(env, crs.id)) == NULL)
+ fatalx("pfe_dispatch_relay: invalid relay id");
+ bcopy(&crs, &rlay->rl_stats[crs.proc], sizeof(crs));
+ rlay->rl_stats[crs.proc].interval =
+ env->sc_statinterval.tv_sec;
+ break;
+ default:
+ return (-1);
}
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("pfe_dispatch_relay: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_NATLOOK:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(cnl))
- fatalx("invalid imsg header len");
- bcopy(imsg.data, &cnl, sizeof(cnl));
- if (cnl.proc > env->sc_prefork_relay)
- fatalx("pfe_dispatch_relay: "
- "invalid relay proc");
- if (natlook(env, &cnl) != 0)
- cnl.in = -1;
- imsg_compose_event(&iev_relay[cnl.proc], IMSG_NATLOOK,
- 0, 0, -1, &cnl, sizeof(cnl));
- break;
- case IMSG_STATISTICS:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(crs))
- fatalx("invalid imsg header len");
- bcopy(imsg.data, &crs, sizeof(crs));
- if (crs.proc > env->sc_prefork_relay)
- fatalx("pfe_dispatch_relay: "
- "invalid relay proc");
- if ((rlay = relay_find(env, crs.id)) == NULL)
- fatalx("pfe_dispatch_relay: invalid relay id");
- bcopy(&crs, &rlay->rl_stats[crs.proc], sizeof(crs));
- rlay->rl_stats[crs.proc].interval =
- env->sc_statinterval.tv_sec;
- break;
- default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(iev);
+ return (0);
}
void
@@ -624,19 +391,21 @@ end:
void
show_sessions(struct ctl_conn *c)
{
- int n, proc, done;
- struct imsg imsg;
+ int n, proc, done;
+ struct imsg imsg;
+ struct imsgbuf *ibuf;
+ struct rsession con;
for (proc = 0; proc < env->sc_prefork_relay; proc++) {
+ ibuf = proc_ibuf(env->sc_ps, PROC_RELAY, proc);
+
/*
* Request all the running sessions from the process
*/
- imsg_compose_event(&iev_relay[proc],
- IMSG_CTL_SESSION, 0, 0, -1, NULL, 0);
- while (iev_relay[proc].ibuf.w.queued)
- if (msgbuf_write(&iev_relay[proc].ibuf.w) < 0)
- fatalx("write error");
-
+ proc_compose_imsg(env->sc_ps, PROC_RELAY, proc,
+ IMSG_CTL_SESSION, -1, NULL, 0);
+ proc_flush_imsg(env->sc_ps, PROC_RELAY, proc);
+
/*
* Wait for the reply and forward the messages to the
* control connection.
@@ -644,20 +413,23 @@ show_sessions(struct ctl_conn *c)
done = 0;
while (!done) {
do {
- if ((n = imsg_read(&iev_relay[proc].ibuf)) == -1)
+ if ((n = imsg_read(ibuf)) == -1)
fatalx("imsg_read error");
} while (n == -2); /* handle non-blocking I/O */
while (!done) {
- if ((n = imsg_get(&iev_relay[proc].ibuf,
- &imsg)) == -1)
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
fatalx("imsg_get error");
if (n == 0)
break;
+
switch (imsg.hdr.type) {
case IMSG_CTL_SESSION:
+ IMSG_SIZE_CHECK(&imsg, &con);
+ memcpy(&con, imsg.data, sizeof(con));
+
imsg_compose_event(&c->iev,
- IMSG_CTL_SESSION, proc, 0, -1,
- imsg.data, sizeof(struct rsession));
+ IMSG_CTL_SESSION, 0, 0, -1,
+ &con, sizeof(con));
break;
case IMSG_CTL_END:
done = 1;
@@ -740,7 +512,6 @@ disable_table(struct ctl_conn *c, struct ctl_id *id)
{
struct table *table;
struct host *host;
- int n;
if (id->id == EMPTY_ID)
table = table_findbyname(env, id->name);
@@ -758,13 +529,13 @@ disable_table(struct ctl_conn *c, struct ctl_id *id)
table->up = 0;
TAILQ_FOREACH(host, &table->hosts, entry)
host->up = HOST_UNKNOWN;
- imsg_compose_event(iev_hce, IMSG_TABLE_DISABLE, 0, 0, -1,
+ proc_compose_imsg(env->sc_ps, PROC_HCE, -1, IMSG_TABLE_DISABLE, -1,
&table->conf.id, sizeof(table->conf.id));
+
/* Forward to relay engine(s) */
- for (n = 0; n < env->sc_prefork_relay; n++)
- imsg_compose_event(&iev_relay[n],
- IMSG_TABLE_DISABLE, 0, 0, -1,
- &table->conf.id, sizeof(table->conf.id));
+ proc_compose_imsg(env->sc_ps, PROC_RELAY, -1, IMSG_TABLE_DISABLE, -1,
+ &table->conf.id, sizeof(table->conf.id));
+
log_debug("%s: table %d", __func__, table->conf.id);
pfe_sync();
return (0);
@@ -775,7 +546,6 @@ enable_table(struct ctl_conn *c, struct ctl_id *id)
{
struct table *table;
struct host *host;
- int n;
if (id->id == EMPTY_ID)
table = table_findbyname(env, id->name);
@@ -795,13 +565,13 @@ enable_table(struct ctl_conn *c, struct ctl_id *id)
table->up = 0;
TAILQ_FOREACH(host, &table->hosts, entry)
host->up = HOST_UNKNOWN;
- imsg_compose_event(iev_hce, IMSG_TABLE_ENABLE, 0, 0, -1,
+ proc_compose_imsg(env->sc_ps, PROC_HCE, -1, IMSG_TABLE_ENABLE, -1,
&table->conf.id, sizeof(table->conf.id));
+
/* Forward to relay engine(s) */
- for (n = 0; n < env->sc_prefork_relay; n++)
- imsg_compose_event(&iev_relay[n],
- IMSG_TABLE_ENABLE, 0, 0, -1,
- &table->conf.id, sizeof(table->conf.id));
+ proc_compose_imsg(env->sc_ps, PROC_RELAY, -1, IMSG_TABLE_ENABLE, -1,
+ &table->conf.id, sizeof(table->conf.id));
+
log_debug("%s: table %d", __func__, table->conf.id);
pfe_sync();
return (0);
@@ -812,7 +582,6 @@ disable_host(struct ctl_conn *c, struct ctl_id *id, struct host *host)
{
struct host *h;
struct table *table;
- int n;
if (host == NULL) {
if (id->id == EMPTY_ID)
@@ -841,13 +610,12 @@ disable_host(struct ctl_conn *c, struct ctl_id *id, struct host *host)
host->check_cnt = 0;
host->up_cnt = 0;
- imsg_compose_event(iev_hce, IMSG_HOST_DISABLE, 0, 0, -1,
+ proc_compose_imsg(env->sc_ps, PROC_HCE, -1, IMSG_HOST_DISABLE, -1,
&host->conf.id, sizeof(host->conf.id));
+
/* Forward to relay engine(s) */
- for (n = 0; n < env->sc_prefork_relay; n++)
- imsg_compose_event(&iev_relay[n],
- IMSG_HOST_DISABLE, 0, 0, -1,
- &host->conf.id, sizeof(host->conf.id));
+ proc_compose_imsg(env->sc_ps, PROC_RELAY, -1, IMSG_HOST_DISABLE, -1,
+ &host->conf.id, sizeof(host->conf.id));
log_debug("%s: host %d", __func__, host->conf.id);
if (!host->conf.parentid) {
@@ -863,7 +631,6 @@ int
enable_host(struct ctl_conn *c, struct ctl_id *id, struct host *host)
{
struct host *h;
- int n;
if (host == NULL) {
if (id->id == EMPTY_ID)
@@ -883,13 +650,13 @@ enable_host(struct ctl_conn *c, struct ctl_id *id, struct host *host)
host->flags &= ~(F_DEL);
host->flags &= ~(F_ADD);
- imsg_compose_event(iev_hce, IMSG_HOST_ENABLE, 0, 0, -1,
+ proc_compose_imsg(env->sc_ps, PROC_HCE, -1, IMSG_HOST_ENABLE, -1,
&host->conf.id, sizeof (host->conf.id));
+
/* Forward to relay engine(s) */
- for (n = 0; n < env->sc_prefork_relay; n++)
- imsg_compose_event(&iev_relay[n],
- IMSG_HOST_ENABLE, 0, 0, -1,
- &host->conf.id, sizeof(host->conf.id));
+ proc_compose_imsg(env->sc_ps, PROC_RELAY, -1, IMSG_HOST_ENABLE, -1,
+ &host->conf.id, sizeof(host->conf.id));
+
log_debug("%s: host %d", __func__, host->conf.id);
if (!host->conf.parentid) {
@@ -999,7 +766,7 @@ pfe_sync(void)
demote.level, table->conf.name, table->conf.demote_group);
(void)strlcpy(demote.group, table->conf.demote_group,
sizeof(demote.group));
- imsg_compose_event(iev_main, IMSG_DEMOTE, 0, 0, -1,
+ proc_compose_imsg(env->sc_ps, PROC_PARENT, -1, IMSG_DEMOTE, -1,
&demote, sizeof(demote));
}
}
diff --git a/usr.sbin/relayd/pfe_route.c b/usr.sbin/relayd/pfe_route.c
index ef16d7e4302..0fae0dfd0a0 100644
--- a/usr.sbin/relayd/pfe_route.c
+++ b/usr.sbin/relayd/pfe_route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfe_route.c,v 1.3 2011/05/05 12:01:44 reyk Exp $ */
+/* $OpenBSD: pfe_route.c,v 1.4 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2009 Reyk Floeter <reyk@openbsd.org>
@@ -36,8 +36,6 @@
#include "relayd.h"
-extern struct imsgev *iev_main;
-
struct relay_rtmsg {
struct rt_msghdr rm_hdr;
union {
@@ -102,8 +100,8 @@ sync_routes(struct relayd *env, struct router *rt)
crt.hostid = host->conf.id;
crt.up = host->up;
- imsg_compose_event(iev_main, IMSG_RTMSG,
- 0, 0, -1, &crt, sizeof(crt));
+ proc_compose_imsg(env->sc_ps, PROC_PARENT, -1,
+ IMSG_RTMSG, -1, &crt, sizeof(crt));
}
}
}
diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c
index 2fa1a144d74..d458a4de7a6 100644
--- a/usr.sbin/relayd/relay.c
+++ b/usr.sbin/relayd/relay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay.c,v 1.135 2011/05/05 12:01:44 reyk Exp $ */
+/* $OpenBSD: relay.c,v 1.136 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -47,16 +47,17 @@
#include "relayd.h"
-void relay_sig_handler(int sig, short, void *);
void relay_statistics(int, short, void *);
-void relay_dispatch_pfe(int, short, void *);
-void relay_dispatch_parent(int, short, void *);
+int relay_dispatch_parent(int, struct privsep_proc *,
+ struct imsg *);
+int relay_dispatch_pfe(int, struct privsep_proc *,
+ struct imsg *);
void relay_shutdown(void);
void relay_privinit(void);
void relay_nodedebug(const char *, struct protonode *);
void relay_protodebug(struct relay *);
-void relay_init(void);
+void relay_init(struct privsep *, struct privsep_proc *p, void *);
void relay_launch(void);
int relay_socket(struct sockaddr_storage *, in_port_t,
struct protocol *, int, int);
@@ -134,142 +135,22 @@ volatile sig_atomic_t relay_sessions;
objid_t relay_conid;
static struct relayd *env = NULL;
-struct imsgev *iev_pfe;
-struct imsgev *iev_main;
int proc_id;
-void
-relay_sig_handler(int sig, short event, void *arg)
-{
- switch (sig) {
- case SIGTERM:
- case SIGINT:
- (void)event_loopexit(NULL);
- break;
- case SIGCHLD:
- case SIGHUP:
- case SIGPIPE:
- /* ignore */
- break;
- default:
- fatalx("relay_sig_handler: unexpected signal");
- }
-}
+static struct privsep_proc procs[] = {
+ { "parent", PROC_PARENT, relay_dispatch_parent },
+ { "pfe", PROC_PFE, relay_dispatch_pfe },
+};
pid_t
-relay(struct relayd *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
- int pipe_parent2relay[RELAY_MAXPROC][2], int pipe_pfe2hce[2],
- int pipe_pfe2relay[RELAY_MAXPROC][2])
+relay(struct privsep *ps, struct privsep_proc *p)
{
- pid_t pid;
- struct passwd *pw;
- int i;
-
- switch (pid = fork()) {
- case -1:
- fatal("relay: cannot fork");
- case 0:
- break;
- default:
- return (pid);
- }
-
- env = x_env;
- purge_config(env, PURGE_RDRS);
+ env = ps->ps_env;
/* Need root privileges for relay initialization */
relay_privinit();
- if ((pw = getpwnam(RELAYD_USER)) == NULL)
- fatal("relay: getpwnam");
-
-#ifndef DEBUG
- if (chroot(pw->pw_dir) == -1)
- fatal("relay: chroot");
- if (chdir("/") == -1)
- fatal("relay: chdir(\"/\")");
-
-#else
-#warning disabling privilege revocation and chroot in DEBUG mode
-#endif
-
- setproctitle("socket relay engine");
- relayd_process = PROC_RELAY;
-
-#ifndef DEBUG
- if (setgroups(1, &pw->pw_gid) ||
- setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
- setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
- fatal("relay: can't drop privileges");
-#endif
-
- /* Fork child handlers */
- for (i = 1; i < env->sc_prefork_relay; i++) {
- if (fork() == 0) {
- proc_id = i;
- break;
- }
- }
-
- event_init();
-
- /* Per-child initialization */
- relay_init();
-
- signal_set(&env->sc_evsigint, SIGINT, relay_sig_handler, env);
- signal_set(&env->sc_evsigterm, SIGTERM, relay_sig_handler, env);
- signal_set(&env->sc_evsigchld, SIGCHLD, relay_sig_handler, env);
- signal_set(&env->sc_evsighup, SIGHUP, relay_sig_handler, env);
- signal_set(&env->sc_evsigpipe, SIGPIPE, relay_sig_handler, env);
-
- signal_add(&env->sc_evsigint, NULL);
- signal_add(&env->sc_evsigterm, NULL);
- signal_add(&env->sc_evsigchld, NULL);
- signal_add(&env->sc_evsighup, NULL);
- signal_add(&env->sc_evsigpipe, NULL);
-
- /* setup pipes */
- close(pipe_pfe2hce[0]);
- close(pipe_pfe2hce[1]);
- close(pipe_parent2hce[0]);
- close(pipe_parent2hce[1]);
- close(pipe_parent2pfe[0]);
- close(pipe_parent2pfe[1]);
- for (i = 0; i < env->sc_prefork_relay; i++) {
- if (i == proc_id)
- continue;
- close(pipe_parent2relay[i][0]);
- close(pipe_parent2relay[i][1]);
- close(pipe_pfe2relay[i][0]);
- close(pipe_pfe2relay[i][1]);
- }
- close(pipe_parent2relay[proc_id][1]);
- close(pipe_pfe2relay[proc_id][1]);
-
- if ((iev_pfe = calloc(1, sizeof(struct imsgev))) == NULL ||
- (iev_main = calloc(1, sizeof(struct imsgev))) == NULL)
- fatal("relay");
- imsg_init(&iev_pfe->ibuf, pipe_pfe2relay[proc_id][0]);
- imsg_init(&iev_main->ibuf, pipe_parent2relay[proc_id][0]);
- iev_pfe->handler = relay_dispatch_pfe;
- iev_main->handler = relay_dispatch_parent;
-
- iev_pfe->events = EV_READ;
- event_set(&iev_pfe->ev, iev_pfe->ibuf.fd, iev_pfe->events,
- iev_pfe->handler, iev_pfe);
- event_add(&iev_pfe->ev, NULL);
-
- iev_main->events = EV_READ;
- event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
- iev_main->handler, iev_main);
- event_add(&iev_main->ev, NULL);
-
- relay_launch();
-
- event_dispatch();
- relay_shutdown();
-
- return (0);
+ return (proc_run(ps, p, procs, nitems(procs), relay_init, NULL));
}
void
@@ -286,8 +167,6 @@ relay_shutdown(void)
relay_close(con, "shutdown");
}
usleep(200); /* XXX relay needs to shutdown last */
- log_info("socket relay engine exiting");
- _exit(0);
}
void
@@ -462,12 +341,17 @@ relay_privinit(void)
}
void
-relay_init(void)
+relay_init(struct privsep *ps, struct privsep_proc *p, void *arg)
{
struct relay *rlay;
struct host *host;
struct timeval tv;
+ /* We use a custom shutdown callback */
+ p->p_shutdown = relay_shutdown;
+
+ purge_config(env, PURGE_RDRS);
+
/* Unlimited file descriptors (use system limits) */
socket_rlimit(-1);
@@ -518,6 +402,8 @@ relay_init(void)
evtimer_set(&env->sc_statev, relay_statistics, NULL);
bcopy(&env->sc_statinterval, &tv, sizeof(tv));
evtimer_add(&env->sc_statev, &tv);
+
+ relay_launch();
}
void
@@ -566,7 +452,7 @@ relay_statistics(int fd, short events, void *arg)
crs.id = rlay->rl_conf.id;
crs.proc = proc_id;
- imsg_compose_event(iev_pfe, IMSG_STATISTICS, 0, 0, -1,
+ proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_STATISTICS, -1,
&crs, sizeof(crs));
for (con = SPLAY_ROOT(&rlay->rl_sessions);
@@ -2151,7 +2037,7 @@ relay_accept(int fd, short sig, void *arg)
return;
}
- imsg_compose_event(iev_pfe, IMSG_NATLOOK, 0, 0, -1, cnl,
+ proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_NATLOOK, -1, cnl,
sizeof(*cnl));
/* Schedule timeout */
@@ -2330,8 +2216,8 @@ relay_bindanyreq(struct rsession *con, in_port_t port, int proto)
bnd.bnd_port = port;
bnd.bnd_proto = proto;
bcopy(&con->se_in.ss, &bnd.bnd_ss, sizeof(bnd.bnd_ss));
- imsg_compose_event(iev_main, IMSG_BINDANY,
- 0, 0, -1, &bnd, sizeof(bnd));
+ proc_compose_imsg(env->sc_ps, PROC_PARENT, -1, IMSG_BINDANY,
+ -1, &bnd, sizeof(bnd));
/* Schedule timeout */
evtimer_set(&con->se_ev, relay_bindany, con);
@@ -2442,7 +2328,8 @@ relay_close(struct rsession *con, const char *msg)
if (EVBUFFER_LENGTH(con->se_log) &&
evbuffer_add_printf(con->se_log, "\r\n") != -1)
ptr = evbuffer_readline(con->se_log);
- log_info("relay %s, session %d (%d active), %d, %s -> %s:%d, "
+ log_info("relay %s, "
+ "session %d (%d active), %d, %s -> %s:%d, "
"%s%s%s", rlay->rl_conf.name, con->se_id, relay_sessions,
con->se_mark, ibuf, obuf, ntohs(con->se_out.port), msg,
ptr == NULL ? "" : ",", ptr == NULL ? "" : ptr);
@@ -2495,7 +2382,7 @@ relay_close(struct rsession *con, const char *msg)
if (con->se_cnl != NULL) {
#if 0
- imsg_compose_event(iev_pfe, IMSG_KILLSTATES, 0, 0, -1,
+ proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_KILLSTATES, -1,
cnl, sizeof(*cnl));
#endif
free(con->se_cnl);
@@ -2505,13 +2392,9 @@ relay_close(struct rsession *con, const char *msg)
relay_sessions--;
}
-void
-relay_dispatch_pfe(int fd, short event, void *ptr)
+int
+relay_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
struct relay *rlay;
struct rsession *con;
struct ctl_natlook cnl;
@@ -2520,203 +2403,139 @@ relay_dispatch_pfe(int fd, short event, void *ptr)
struct table *table;
struct ctl_status st;
objid_t id;
- int verbose;
-
- iev = ptr;
- ibuf = &iev->ibuf;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("relay_dispatch_pfe: imsg_read_error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
- }
- }
-
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("relay_dispatch_pfe: msgbuf_write");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("relay_dispatch_pfe: imsg_read error");
- if (n == 0)
- break;
- switch (imsg.hdr.type) {
- case IMSG_HOST_DISABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((host = host_find(env, id)) == NULL)
- fatalx("relay_dispatch_pfe: desynchronized");
- if ((table = table_find(env, host->conf.tableid)) ==
- NULL)
- fatalx("relay_dispatch_pfe: invalid table id");
- if (host->up == HOST_UP)
- table->up--;
- host->flags |= F_DISABLE;
+ switch (imsg->hdr.type) {
+ case IMSG_HOST_DISABLE:
+ memcpy(&id, imsg->data, sizeof(id));
+ if ((host = host_find(env, id)) == NULL)
+ fatalx("relay_dispatch_pfe: desynchronized");
+ if ((table = table_find(env, host->conf.tableid)) ==
+ NULL)
+ fatalx("relay_dispatch_pfe: invalid table id");
+ if (host->up == HOST_UP)
+ table->up--;
+ host->flags |= F_DISABLE;
+ host->up = HOST_UNKNOWN;
+ break;
+ case IMSG_HOST_ENABLE:
+ memcpy(&id, imsg->data, sizeof(id));
+ if ((host = host_find(env, id)) == NULL)
+ fatalx("relay_dispatch_pfe: desynchronized");
+ host->flags &= ~(F_DISABLE);
+ host->up = HOST_UNKNOWN;
+ break;
+ case IMSG_TABLE_DISABLE:
+ memcpy(&id, imsg->data, sizeof(id));
+ if ((table = table_find(env, id)) == NULL)
+ fatalx("relay_dispatch_pfe: desynchronized");
+ table->conf.flags |= F_DISABLE;
+ table->up = 0;
+ TAILQ_FOREACH(host, &table->hosts, entry)
host->up = HOST_UNKNOWN;
- break;
- case IMSG_HOST_ENABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((host = host_find(env, id)) == NULL)
- fatalx("relay_dispatch_pfe: desynchronized");
- host->flags &= ~(F_DISABLE);
+ break;
+ case IMSG_TABLE_ENABLE:
+ memcpy(&id, imsg->data, sizeof(id));
+ if ((table = table_find(env, id)) == NULL)
+ fatalx("relay_dispatch_pfe: desynchronized");
+ table->conf.flags &= ~(F_DISABLE);
+ table->up = 0;
+ TAILQ_FOREACH(host, &table->hosts, entry)
host->up = HOST_UNKNOWN;
+ break;
+ case IMSG_HOST_STATUS:
+ IMSG_SIZE_CHECK(imsg, &st);
+ memcpy(&st, imsg->data, sizeof(st));
+ if ((host = host_find(env, st.id)) == NULL)
+ fatalx("relay_dispatch_pfe: invalid host id");
+ if (host->flags & F_DISABLE)
break;
- case IMSG_TABLE_DISABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((table = table_find(env, id)) == NULL)
- fatalx("relay_dispatch_pfe: desynchronized");
- table->conf.flags |= F_DISABLE;
- table->up = 0;
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->up = HOST_UNKNOWN;
- break;
- case IMSG_TABLE_ENABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((table = table_find(env, id)) == NULL)
- fatalx("relay_dispatch_pfe: desynchronized");
- table->conf.flags &= ~(F_DISABLE);
- table->up = 0;
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->up = HOST_UNKNOWN;
- break;
- case IMSG_HOST_STATUS:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(st))
- fatalx("relay_dispatch_pfe: invalid request");
- memcpy(&st, imsg.data, sizeof(st));
- if ((host = host_find(env, st.id)) == NULL)
- fatalx("relay_dispatch_pfe: invalid host id");
- if (host->flags & F_DISABLE)
- break;
- if (host->up == st.up) {
- log_debug("%s: host %d => %d", __func__,
- host->conf.id, host->up);
- fatalx("relay_dispatch_pfe: desynchronized");
- }
+ if (host->up == st.up) {
+ log_debug("%s: host %d => %d", __func__,
+ host->conf.id, host->up);
+ fatalx("relay_dispatch_pfe: desynchronized");
+ }
- if ((table = table_find(env, host->conf.tableid))
- == NULL)
- fatalx("relay_dispatch_pfe: invalid table id");
+ if ((table = table_find(env, host->conf.tableid))
+ == NULL)
+ fatalx("relay_dispatch_pfe: invalid table id");
- DPRINTF("%s: [%d] state %d for "
- "host %u %s", __func__, proc_id, st.up,
- host->conf.id, host->conf.name);
+ DPRINTF("%s: [%d] state %d for "
+ "host %u %s", __func__, proc_id, st.up,
+ host->conf.id, host->conf.name);
- if ((st.up == HOST_UNKNOWN && host->up == HOST_DOWN) ||
- (st.up == HOST_DOWN && host->up == HOST_UNKNOWN)) {
- host->up = st.up;
- break;
- }
- if (st.up == HOST_UP)
- table->up++;
- else
- table->up--;
+ if ((st.up == HOST_UNKNOWN && host->up == HOST_DOWN) ||
+ (st.up == HOST_DOWN && host->up == HOST_UNKNOWN)) {
host->up = st.up;
break;
- case IMSG_NATLOOK:
- bcopy(imsg.data, &cnl, sizeof(cnl));
- if ((con = session_find(env, cnl.id)) == NULL ||
- con->se_cnl == NULL) {
- log_debug("%s: session %d: expired",
- __func__, cnl.id);
- break;
- }
- bcopy(&cnl, con->se_cnl, sizeof(*con->se_cnl));
- evtimer_del(&con->se_ev);
- evtimer_set(&con->se_ev, relay_natlook, con);
- bzero(&tv, sizeof(tv));
- evtimer_add(&con->se_ev, &tv);
- break;
- case IMSG_CTL_SESSION:
- TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
- SPLAY_FOREACH(con, session_tree,
- &rlay->rl_sessions)
- imsg_compose_event(iev,
- IMSG_CTL_SESSION,
- 0, 0, -1, con, sizeof(*con));
- imsg_compose_event(iev, IMSG_CTL_END,
- 0, 0, -1, NULL, 0);
- break;
- case IMSG_CTL_LOG_VERBOSE:
- memcpy(&verbose, imsg.data, sizeof(verbose));
- log_verbose(verbose);
- break;
- default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
+ }
+ if (st.up == HOST_UP)
+ table->up++;
+ else
+ table->up--;
+ host->up = st.up;
+ break;
+ case IMSG_NATLOOK:
+ bcopy(imsg->data, &cnl, sizeof(cnl));
+ if ((con = session_find(env, cnl.id)) == NULL ||
+ con->se_cnl == NULL) {
+ log_debug("%s: session %d: expired",
+ __func__, cnl.id);
break;
}
- imsg_free(&imsg);
+ bcopy(&cnl, con->se_cnl, sizeof(*con->se_cnl));
+ evtimer_del(&con->se_ev);
+ evtimer_set(&con->se_ev, relay_natlook, con);
+ bzero(&tv, sizeof(tv));
+ evtimer_add(&con->se_ev, &tv);
+ break;
+ case IMSG_CTL_SESSION:
+ TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
+ SPLAY_FOREACH(con, session_tree,
+ &rlay->rl_sessions) {
+ proc_compose_imsg(env->sc_ps, p->p_id, -1,
+ IMSG_CTL_SESSION,
+ -1, con, sizeof(*con));
+ }
+ }
+ proc_compose_imsg(env->sc_ps, p->p_id, -1, IMSG_CTL_END,
+ -1, NULL, 0);
+ break;
+ default:
+ return (-1);
}
- imsg_event_add(iev);
+
+ return (0);
}
-void
-relay_dispatch_parent(int fd, short event, void * ptr)
+int
+relay_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
{
struct rsession *con;
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
struct timeval tv;
objid_t id;
- iev = ptr;
- ibuf = &iev->ibuf;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("relay_dispatch_parent: imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
- }
- }
-
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("relay_dispatch_parent: msgbuf_write");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("relay_dispatch_parent: imsg_read error");
- if (n == 0)
+ switch (imsg->hdr.type) {
+ case IMSG_BINDANY:
+ bcopy(imsg->data, &id, sizeof(id));
+ if ((con = session_find(env, id)) == NULL) {
+ log_debug("%s: session %d: expired",
+ __func__, id);
break;
+ }
- switch (imsg.hdr.type) {
- case IMSG_BINDANY:
- bcopy(imsg.data, &id, sizeof(id));
- if ((con = session_find(env, id)) == NULL) {
- log_debug("%s: session %d: expired",
- __func__, id);
- break;
- }
-
- /* Will validate the result later */
- con->se_bnds = imsg.fd;
+ /* Will validate the result later */
+ con->se_bnds = imsg->fd;
- evtimer_del(&con->se_ev);
- evtimer_set(&con->se_ev, relay_bindany, con);
- bzero(&tv, sizeof(tv));
- evtimer_add(&con->se_ev, &tv);
- break;
- default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
+ evtimer_del(&con->se_ev);
+ evtimer_set(&con->se_ev, relay_bindany, con);
+ bzero(&tv, sizeof(tv));
+ evtimer_add(&con->se_ev, &tv);
+ break;
+ default:
+ return (-1);
}
- imsg_event_add(iev);
+
+ return (0);
}
SSL_CTX *
diff --git a/usr.sbin/relayd/relay_udp.c b/usr.sbin/relayd/relay_udp.c
index 7c83d795152..3fe658a3f0b 100644
--- a/usr.sbin/relayd/relay_udp.c
+++ b/usr.sbin/relayd/relay_udp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay_udp.c,v 1.23 2011/05/05 12:01:44 reyk Exp $ */
+/* $OpenBSD: relay_udp.c,v 1.24 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -50,7 +50,6 @@
extern volatile sig_atomic_t relay_sessions;
extern objid_t relay_conid;
extern int proc_id;
-extern struct imsgev *iev_pfe;
extern int debug;
struct relayd *env = NULL;
@@ -321,8 +320,8 @@ relay_udp_server(int fd, short sig, void *arg)
cnl->proto = IPPROTO_UDP;
bcopy(&con->se_in.ss, &cnl->src, sizeof(cnl->src));
bcopy(&rlay->rl_conf.ss, &cnl->dst, sizeof(cnl->dst));
- imsg_compose_event(iev_pfe, IMSG_NATLOOK, 0, 0, -1, cnl,
- sizeof(*cnl));
+ proc_compose_imsg(env->sc_ps, PROC_PFE, -1,
+ IMSG_NATLOOK, -1, cnl, sizeof(*cnl));
/* Schedule timeout */
evtimer_set(&con->se_ev, relay_natlook, con);
diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c
index 8194db2ce53..f3a70f57f49 100644
--- a/usr.sbin/relayd/relayd.c
+++ b/usr.sbin/relayd/relayd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.c,v 1.101 2011/05/05 12:01:44 reyk Exp $ */
+/* $OpenBSD: relayd.c,v 1.102 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -34,7 +34,6 @@
#include <err.h>
#include <errno.h>
#include <event.h>
-#include <signal.h>
#include <unistd.h>
#include <ctype.h>
#include <pwd.h>
@@ -47,39 +46,30 @@
__dead void usage(void);
-void main_sig_handler(int, short, void *);
-void main_shutdown(struct relayd *);
-void main_dispatch_pfe(int, short, void *);
-void main_dispatch_hce(int, short, void *);
-void main_dispatch_relay(int, short, void *);
-int check_child(pid_t, const char *);
-int send_all(struct relayd *, enum imsg_type,
- void *, u_int16_t);
+void parent_sig_handler(int, short, void *);
+void parent_shutdown(struct relayd *);
+int parent_dispatch_pfe(int, struct privsep_proc *, struct imsg *);
+int parent_dispatch_hce(int, struct privsep_proc *, struct imsg *);
+int parent_dispatch_relay(int, struct privsep_proc *, struct imsg *);
void reconfigure(void);
void purge_tree(struct proto_tree *);
int bindany(struct ctl_bindany *);
-int pipe_parent2pfe[2];
-int pipe_parent2hce[2];
-int pipe_pfe2hce[2];
-int pipe_parent2relay[RELAY_MAXPROC][2];
-int pipe_pfe2relay[RELAY_MAXPROC][2];
-
struct relayd *relayd_env;
-struct imsgev *iev_pfe;
-struct imsgev *iev_hce;
-struct imsgev *iev_relay;
-
-pid_t pfe_pid = 0;
-pid_t hce_pid = 0;
-pid_t relay_pid = 0;
+static struct privsep_proc procs[] = {
+ { "pfe", PROC_PFE, parent_dispatch_pfe, pfe },
+ { "hce", PROC_HCE, parent_dispatch_hce, hce },
+ { "relay", PROC_RELAY, parent_dispatch_relay, relay }
+};
void
-main_sig_handler(int sig, short event, void *arg)
+parent_sig_handler(int sig, short event, void *arg)
{
- struct relayd *env = arg;
- int die = 0;
+ struct privsep *ps = arg;
+ int die = 0, status, fail, id;
+ pid_t pid;
+ char *cause;
switch (sig) {
case SIGTERM:
@@ -87,20 +77,39 @@ main_sig_handler(int sig, short event, void *arg)
die = 1;
/* FALLTHROUGH */
case SIGCHLD:
- if (check_child(pfe_pid, "pf update engine")) {
- pfe_pid = 0;
- die = 1;
- }
- if (check_child(hce_pid, "host check engine")) {
- hce_pid = 0;
- die = 1;
- }
- if (check_child(relay_pid, "socket relay engine")) {
- relay_pid = 0;
- die = 1;
- }
+ do {
+ pid = waitpid(WAIT_ANY, &status, WNOHANG);
+ if (pid <= 0)
+ continue;
+
+ fail = 0;
+ if (WIFSIGNALED(status)) {
+ fail = 1;
+ asprintf(&cause, "terminated; signal %d",
+ WTERMSIG(status));
+ } else if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) != 0) {
+ fail = 1;
+ asprintf(&cause, "exited abnormally");
+ } else
+ asprintf(&cause, "exited okay");
+ } else
+ fatalx("unexpected cause of SIGCHLD");
+
+ die = 1;
+
+ for (id = 0; id < PROC_MAX; id++)
+ if (pid == ps->ps_pid[id]) {
+ log_warnx("lost child: %s %s",
+ ps->ps_title[id], cause);
+ break;
+ }
+
+ free(cause);
+ } while (pid > 0 || (pid == -1 && errno == EINTR));
+
if (die)
- main_shutdown(env);
+ parent_shutdown(ps->ps_env);
break;
case SIGHUP:
reconfigure();
@@ -131,8 +140,8 @@ main(int argc, char *argv[])
int debug;
u_int32_t opts;
struct relayd *env;
+ struct privsep *ps;
const char *conffile;
- struct imsgev *iev;
opts = 0;
debug = 0;
@@ -170,9 +179,13 @@ main(int argc, char *argv[])
if (argc > 0)
usage();
- if ((env = parse_config(conffile, opts)) == NULL)
+ if ((env = parse_config(conffile, opts)) == NULL ||
+ (ps = calloc(1, sizeof(*ps))) == NULL)
exit(1);
+
relayd_env = env;
+ env->sc_ps = ps;
+ ps->ps_env = env;
if (env->sc_opts & RELAYD_OPT_NOACTION) {
fprintf(stderr, "configuration OK\n");
@@ -184,9 +197,12 @@ main(int argc, char *argv[])
if (geteuid())
errx(1, "need root privileges");
- if (getpwnam(RELAYD_USER) == NULL)
+ if ((ps->ps_pw = getpwnam(RELAYD_USER)) == NULL)
errx(1, "unknown user %s", RELAYD_USER);
+ /* Configure the control socket */
+ ps->ps_csock.cs_name = RELAYD_SOCKET;
+
if (!debug) {
log_init(debug);
if (daemon(1, 0) == -1)
@@ -195,179 +211,50 @@ main(int argc, char *argv[])
log_info("startup");
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_parent2pfe) == -1)
- fatal("socketpair");
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_parent2hce) == -1)
- fatal("socketpair");
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_pfe2hce) == -1)
- fatal("socketpair");
- for (c = 0; c < env->sc_prefork_relay; c++) {
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_parent2relay[c]) == -1)
- fatal("socketpair");
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_pfe2relay[c]) == -1)
- fatal("socketpair");
- session_socket_blockmode(pipe_pfe2relay[c][0], BM_NONBLOCK);
- session_socket_blockmode(pipe_pfe2relay[c][1], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2relay[c][0], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2relay[c][1], BM_NONBLOCK);
- }
-
- session_socket_blockmode(pipe_parent2pfe[0], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2pfe[1], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2hce[0], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2hce[1], BM_NONBLOCK);
- session_socket_blockmode(pipe_pfe2hce[0], BM_NONBLOCK);
- session_socket_blockmode(pipe_pfe2hce[1], BM_NONBLOCK);
-
- pfe_pid = pfe(env, pipe_parent2pfe, pipe_parent2hce,
- pipe_parent2relay, pipe_pfe2hce, pipe_pfe2relay);
- hce_pid = hce(env, pipe_parent2pfe, pipe_parent2hce,
- pipe_parent2relay, pipe_pfe2hce, pipe_pfe2relay);
- if (env->sc_prefork_relay > 0)
- relay_pid = relay(env, pipe_parent2pfe, pipe_parent2hce,
- pipe_parent2relay, pipe_pfe2hce, pipe_pfe2relay);
+ ps->ps_instances[PROC_RELAY] = env->sc_prefork_relay;
+ proc_init(ps, procs, nitems(procs));
setproctitle("parent");
event_init();
- signal_set(&env->sc_evsigint, SIGINT, main_sig_handler, env);
- signal_set(&env->sc_evsigterm, SIGTERM, main_sig_handler, env);
- signal_set(&env->sc_evsigchld, SIGCHLD, main_sig_handler, env);
- signal_set(&env->sc_evsighup, SIGHUP, main_sig_handler, env);
- signal_set(&env->sc_evsigpipe, SIGPIPE, main_sig_handler, env);
-
- signal_add(&env->sc_evsigint, NULL);
- signal_add(&env->sc_evsigterm, NULL);
- signal_add(&env->sc_evsigchld, NULL);
- signal_add(&env->sc_evsighup, NULL);
- signal_add(&env->sc_evsigpipe, NULL);
-
- close(pipe_parent2pfe[1]);
- close(pipe_parent2hce[1]);
- close(pipe_pfe2hce[0]);
- close(pipe_pfe2hce[1]);
- for (c = 0; c < env->sc_prefork_relay; c++) {
- close(pipe_pfe2relay[c][0]);
- close(pipe_pfe2relay[c][1]);
- close(pipe_parent2relay[c][0]);
- }
-
- if ((iev_pfe = calloc(1, sizeof(struct imsgev))) == NULL ||
- (iev_hce = calloc(1, sizeof(struct imsgev))) == NULL)
- fatal(NULL);
-
- if (env->sc_prefork_relay > 0) {
- if ((iev_relay = calloc(env->sc_prefork_relay,
- sizeof(struct imsgev))) == NULL)
- fatal(NULL);
- }
-
- imsg_init(&iev_pfe->ibuf, pipe_parent2pfe[0]);
- imsg_init(&iev_hce->ibuf, pipe_parent2hce[0]);
- iev_pfe->handler = main_dispatch_pfe;
- iev_pfe->data = env;
- iev_hce->handler = main_dispatch_hce;
- iev_hce->data = env;
-
- for (c = 0; c < env->sc_prefork_relay; c++) {
- iev = &iev_relay[c];
- imsg_init(&iev->ibuf, pipe_parent2relay[c][1]);
- iev->handler = main_dispatch_relay;
- iev->events = EV_READ;
- event_set(&iev->ev, iev->ibuf.fd, iev->events,
- iev->handler, iev);
- event_add(&iev->ev, NULL);
- }
-
- iev_pfe->events = EV_READ;
- event_set(&iev_pfe->ev, iev_pfe->ibuf.fd, iev_pfe->events,
- iev_pfe->handler, iev_pfe);
- event_add(&iev_pfe->ev, NULL);
+ signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps);
+ signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps);
+ signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps);
+ signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps);
+ signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps);
- iev_hce->events = EV_READ;
- event_set(&iev_hce->ev, iev_hce->ibuf.fd, iev_hce->events,
- iev_hce->handler, iev_hce);
- event_add(&iev_hce->ev, NULL);
-
- if (env->sc_flags & F_DEMOTE)
- carp_demote_reset(env->sc_demote_group, 0);
+ signal_add(&ps->ps_evsigint, NULL);
+ signal_add(&ps->ps_evsigterm, NULL);
+ signal_add(&ps->ps_evsigchld, NULL);
+ signal_add(&ps->ps_evsighup, NULL);
+ signal_add(&ps->ps_evsigpipe, NULL);
+ proc_config(ps, procs, nitems(procs));
init_routes(env);
event_dispatch();
- main_shutdown(env);
+ parent_shutdown(env);
/* NOTREACHED */
return (0);
}
void
-main_shutdown(struct relayd *env)
+parent_shutdown(struct relayd *env)
{
- pid_t pid;
-
- if (pfe_pid)
- kill(pfe_pid, SIGTERM);
- if (hce_pid)
- kill(hce_pid, SIGTERM);
- if (relay_pid)
- kill(relay_pid, SIGTERM);
-
- do {
- if ((pid = wait(NULL)) == -1 &&
- errno != EINTR && errno != ECHILD)
- fatal("wait");
- } while (pid != -1 || (pid == -1 && errno == EINTR));
-
- control_cleanup();
+ proc_kill(env->sc_ps);
+ control_cleanup(&env->sc_ps->ps_csock);
carp_demote_shutdown();
if (env->sc_flags & F_DEMOTE)
carp_demote_reset(env->sc_demote_group, 128);
- log_info("terminating");
- exit(0);
-}
-
-int
-check_child(pid_t pid, const char *pname)
-{
- int status;
-
- if (waitpid(pid, &status, WNOHANG) > 0) {
- if (WIFEXITED(status)) {
- log_warnx("%s: lost child: %s exited", __func__, pname);
- return (1);
- }
- if (WIFSIGNALED(status)) {
- log_warnx("%s: lost child: %s terminated; "
- "signal %d", __func__, pname, WTERMSIG(status));
- return (1);
- }
- }
- return (0);
-}
+ free(env->sc_ps);
+ free(env);
-int
-send_all(struct relayd *env, enum imsg_type type, void *buf, u_int16_t len)
-{
- int i;
+ log_info("parent terminating, pid %d", getpid());
- if (imsg_compose_event(iev_pfe, type, 0, 0, -1, buf, len) == -1)
- return (-1);
- if (imsg_compose_event(iev_hce, type, 0, 0, -1, buf, len) == -1)
- return (-1);
- for (i = 0; i < env->sc_prefork_relay; i++) {
- if (imsg_compose_event(&iev_relay[i], type, 0, 0, -1, buf, len)
- == -1)
- return (-1);
- }
- return (0);
+ exit(0);
}
void
@@ -405,6 +292,7 @@ reconfigure(void)
{
struct relayd *env = relayd_env;
struct relayd *new_env = NULL;
+ struct privsep *ps = env->sc_ps;
struct rdr *rdr;
struct address *virt;
struct table *table;
@@ -433,41 +321,40 @@ reconfigure(void)
/*
* first reconfigure pfe
*/
- imsg_compose_event(iev_pfe, IMSG_RECONF, 0, 0, -1, env, sizeof(*env));
+ proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF, -1, env, sizeof(*env));
TAILQ_FOREACH(table, env->sc_tables, entry) {
- imsg_compose_event(iev_pfe, IMSG_RECONF_TABLE, 0, 0, -1,
+ proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_TABLE, -1,
&table->conf, sizeof(table->conf));
TAILQ_FOREACH(host, &table->hosts, entry) {
- imsg_compose_event(iev_pfe, IMSG_RECONF_HOST, 0, 0, -1,
- &host->conf, sizeof(host->conf));
+ proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_HOST,
+ -1, &host->conf, sizeof(host->conf));
}
}
TAILQ_FOREACH(rdr, env->sc_rdrs, entry) {
- imsg_compose_event(iev_pfe, IMSG_RECONF_RDR, 0, 0, -1,
+ proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_RDR, -1,
&rdr->conf, sizeof(rdr->conf));
TAILQ_FOREACH(virt, &rdr->virts, entry)
- imsg_compose_event(iev_pfe, IMSG_RECONF_VIRT, 0, 0, -1,
- virt, sizeof(*virt));
+ proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_VIRT,
+ -1, virt, sizeof(*virt));
}
- imsg_compose_event(iev_pfe, IMSG_RECONF_END, 0, 0, -1, NULL, 0);
+ proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_END, -1, NULL, 0);
/*
* then reconfigure hce
*/
- imsg_compose_event(iev_hce, IMSG_RECONF, 0, 0, -1, env, sizeof(*env));
+ proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF, -1, env, sizeof(*env));
TAILQ_FOREACH(table, env->sc_tables, entry) {
- imsg_compose_event(iev_hce, IMSG_RECONF_TABLE, 0, 0, -1,
+ proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF_TABLE, -1,
&table->conf, sizeof(table->conf));
if (table->sendbuf != NULL)
- imsg_compose_event(iev_hce, IMSG_RECONF_SENDBUF,
- 0, 0, -1, table->sendbuf,
- strlen(table->sendbuf) + 1);
+ proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF_SENDBUF,
+ -1, table->sendbuf, strlen(table->sendbuf) + 1);
TAILQ_FOREACH(host, &table->hosts, entry) {
- imsg_compose_event(iev_hce, IMSG_RECONF_HOST, 0, 0, -1,
- &host->conf, sizeof(host->conf));
+ proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF_HOST,
+ -1, &host->conf, sizeof(host->conf));
}
}
- imsg_compose_event(iev_hce, IMSG_RECONF_END, 0, 0, -1, NULL, 0);
+ proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF_END, -1, NULL, 0);
}
void
@@ -581,236 +468,95 @@ purge_table(struct tablelist *head, struct table *table)
free(table);
}
-void
-imsg_event_add(struct imsgev *iev)
-{
- if (iev->handler == NULL) {
- imsg_flush(&iev->ibuf);
- return;
- }
-
- iev->events = EV_READ;
- if (iev->ibuf.w.queued)
- iev->events |= EV_WRITE;
-
- event_del(&iev->ev);
- event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
- event_add(&iev->ev, NULL);
-}
-
int
-imsg_compose_event(struct imsgev *iev, u_int16_t type,
- u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen)
-{
- int ret;
-
- if ((ret = imsg_compose(&iev->ibuf, type, peerid,
- pid, fd, data, datalen)) != -1)
- imsg_event_add(iev);
- return (ret);
-}
-
-void
-main_dispatch_pfe(int fd, short event, void *ptr)
+parent_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
+ struct relayd *env = p->p_env;
struct ctl_demote demote;
struct ctl_netroute crt;
- struct relayd *env;
- int verbose;
-
- iev = ptr;
- ibuf = &iev->ibuf;
- env = (struct relayd *)iev->data;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read_error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
- }
- }
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
+ switch (imsg->hdr.type) {
+ case IMSG_DEMOTE:
+ IMSG_SIZE_CHECK(imsg, &demote);
+ memcpy(&demote, imsg->data, sizeof(demote));
+ carp_demote_set(demote.group, demote.level);
+ break;
+ case IMSG_RTMSG:
+ IMSG_SIZE_CHECK(imsg, &crt);
+ memcpy(&crt, imsg->data, sizeof(crt));
+ pfe_route(env, &crt);
+ break;
+ case IMSG_CTL_RELOAD:
+ /*
+ * so far we only get here if no L7 (relay) is done.
+ */
+ reconfigure();
+ break;
+ default:
+ return (-1);
}
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("main_dispatch_pfe: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_DEMOTE:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(demote))
- fatalx("main_dispatch_pfe: "
- "invalid size of demote request");
- memcpy(&demote, imsg.data, sizeof(demote));
- carp_demote_set(demote.group, demote.level);
- break;
- case IMSG_RTMSG:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(crt))
- fatalx("main_dispatch_pfe: "
- "invalid size of rtmsg request");
- memcpy(&crt, imsg.data, sizeof(crt));
- pfe_route(env, &crt);
- break;
- case IMSG_CTL_RELOAD:
- /*
- * so far we only get here if no L7 (relay) is done.
- */
- reconfigure();
- break;
- case IMSG_CTL_LOG_VERBOSE:
- memcpy(&verbose, imsg.data, sizeof(verbose));
- log_verbose(verbose);
- break;
- default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(iev);
+ return (0);
}
-void
-main_dispatch_hce(int fd, short event, void * ptr)
+int
+parent_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
+ struct relayd *env = p->p_env;
+ struct privsep *ps = env->sc_ps;
struct ctl_script scr;
- struct relayd *env;
- env = relayd_env;
- iev = ptr;
- ibuf = &iev->ibuf;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
- }
- }
-
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
+ switch (imsg->hdr.type) {
+ case IMSG_SCRIPT:
+ IMSG_SIZE_CHECK(imsg, &scr);
+ bcopy(imsg->data, &scr, sizeof(scr));
+ scr.retval = script_exec(env, &scr);
+ proc_compose_imsg(ps, PROC_HCE, -1, IMSG_SCRIPT,
+ -1, &scr, sizeof(scr));
+ break;
+ case IMSG_SNMPSOCK:
+ (void)snmp_sendsock(env, p->p_id);
+ break;
+ default:
+ return (-1);
}
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("main_dispatch_hce: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_SCRIPT:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(scr))
- fatalx("main_dispatch_hce: "
- "invalid size of script request");
- bcopy(imsg.data, &scr, sizeof(scr));
- scr.retval = script_exec(env, &scr);
- imsg_compose_event(iev_hce, IMSG_SCRIPT,
- 0, 0, -1, &scr, sizeof(scr));
- break;
- case IMSG_SNMPSOCK:
- (void)snmp_sendsock(iev);
- break;
- default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(iev);
+ return (0);
}
-void
-main_dispatch_relay(int fd, short event, void * ptr)
+int
+parent_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- struct relayd *env = relayd_env;
- struct imsgev *iev;
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
+ struct relayd *env = p->p_env;
+ struct privsep *ps = env->sc_ps;
struct ctl_bindany bnd;
int s;
- iev = ptr;
- ibuf = &iev->ibuf;
-
- if (event & EV_READ) {
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&iev->ev);
- event_loopexit(NULL);
- return;
- }
- }
-
- if (event & EV_WRITE) {
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("main_dispatch_relay: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_BINDANY:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(bnd))
- fatalx("invalid imsg header len");
- bcopy(imsg.data, &bnd, sizeof(bnd));
- if (bnd.bnd_proc > env->sc_prefork_relay)
- fatalx("pfe_dispatch_relay: "
- "invalid relay proc");
- switch (bnd.bnd_proto) {
- case IPPROTO_TCP:
- case IPPROTO_UDP:
- break;
- default:
- fatalx("pfe_dispatch_relay: requested socket "
- "for invalid protocol");
- /* NOTREACHED */
- }
- s = bindany(&bnd);
- imsg_compose_event(&iev_relay[bnd.bnd_proc],
- IMSG_BINDANY,
- 0, 0, s, &bnd.bnd_id, sizeof(bnd.bnd_id));
+ switch (imsg->hdr.type) {
+ case IMSG_BINDANY:
+ IMSG_SIZE_CHECK(imsg, &bnd);
+ bcopy(imsg->data, &bnd, sizeof(bnd));
+ if (bnd.bnd_proc > env->sc_prefork_relay)
+ fatalx("pfe_dispatch_relay: "
+ "invalid relay proc");
+ switch (bnd.bnd_proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
break;
default:
- log_debug("%s: unexpected imsg %d", __func__,
- imsg.hdr.type);
- break;
+ fatalx("pfe_dispatch_relay: requested socket "
+ "for invalid protocol");
+ /* NOTREACHED */
}
- imsg_free(&imsg);
+ s = bindany(&bnd);
+ proc_compose_imsg(ps, PROC_RELAY, bnd.bnd_proc,
+ IMSG_BINDANY, s, &bnd.bnd_id, sizeof(bnd.bnd_id));
+ break;
+ default:
+ return (-1);
}
- imsg_event_add(iev);
+
+ return (0);
}
struct host *
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index b5511948632..330ad861cd4 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.145 2011/05/05 10:20:24 phessler Exp $ */
+/* $OpenBSD: relayd.h,v 1.146 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -648,70 +648,16 @@ struct router {
};
TAILQ_HEAD(routerlist, router);
-enum {
- PROC_MAIN,
- PROC_PFE,
- PROC_HCE,
- PROC_RELAY
-} relayd_process;
-
-struct relayd {
- u_int8_t sc_opts;
- u_int32_t sc_flags;
- const char *sc_confpath;
- struct pfdata *sc_pf;
- int sc_rtsock;
- int sc_rtseq;
- int sc_tablecount;
- int sc_rdrcount;
- int sc_protocount;
- int sc_relaycount;
- int sc_routercount;
- int sc_routecount;
- struct timeval sc_interval;
- struct timeval sc_timeout;
- struct table sc_empty_table;
- struct protocol sc_proto_default;
- struct event sc_ev;
- struct tablelist *sc_tables;
- struct rdrlist *sc_rdrs;
- struct protolist *sc_protos;
- struct relaylist *sc_relays;
- struct routerlist *sc_rts;
- struct netroutelist *sc_routes;
- u_int16_t sc_prefork_relay;
- char sc_demote_group[IFNAMSIZ];
- u_int16_t sc_id;
- struct event sc_statev;
- struct timeval sc_statinterval;
-
- int sc_snmp;
- struct event sc_snmpto;
- struct event sc_snmpev;
-
- int sc_has_icmp;
- int sc_has_icmp6;
- struct ctl_icmp_event sc_icmp_send;
- struct ctl_icmp_event sc_icmp_recv;
- struct ctl_icmp_event sc_icmp6_send;
- struct ctl_icmp_event sc_icmp6_recv;
-
- /* Event and signal handlers */
- struct event sc_evsigint;
- struct event sc_evsigterm;
- struct event sc_evsigchld;
- struct event sc_evsighup;
- struct event sc_evsigpipe;
+/* initially control.h */
+struct control_sock {
+ const char *cs_name;
+ struct event cs_ev;
+ int cs_fd;
+ int cs_restricted;
+ void *cs_env;
};
-#define RELAYD_OPT_VERBOSE 0x01
-#define RELAYD_OPT_NOACTION 0x04
-#define RELAYD_OPT_LOGUPDATE 0x08
-#define RELAYD_OPT_LOGNOTIFY 0x10
-#define RELAYD_OPT_LOGALL 0x18
-
-/* initially control.h */
struct {
struct event ev;
int fd;
@@ -722,14 +668,22 @@ enum blockmodes {
BM_NONBLOCK
};
+
struct imsgev {
struct imsgbuf ibuf;
void (*handler)(int, short, void *);
struct event ev;
+ struct privsep_proc *proc;
void *data;
short events;
};
+#define IMSG_SIZE_CHECK(imsg, p) do { \
+ if (IMSG_DATA_SIZE(imsg) < sizeof(*p)) \
+ fatalx("bad length imsg received"); \
+} while (0)
+#define IMSG_DATA_SIZE(imsg) ((imsg)->hdr.len - IMSG_HEADER_SIZE)
+
struct ctl_conn {
TAILQ_ENTRY(ctl_conn) entry;
u_int8_t flags;
@@ -743,6 +697,7 @@ enum imsg_type {
IMSG_NONE,
IMSG_CTL_OK, /* answer to relayctl requests */
IMSG_CTL_FAIL,
+ IMSG_CTL_VERBOSE,
IMSG_CTL_END,
IMSG_CTL_RDR,
IMSG_CTL_TABLE,
@@ -767,7 +722,6 @@ enum imsg_type {
IMSG_CTL_NOTIFY,
IMSG_CTL_RDR_STATS,
IMSG_CTL_RELAY_STATS,
- IMSG_CTL_LOG_VERBOSE,
IMSG_RDR_ENABLE, /* notifies from pfe to hce */
IMSG_RDR_DISABLE,
IMSG_TABLE_ENABLE,
@@ -798,15 +752,113 @@ enum imsg_type {
IMSG_RTMSG /* from pfe to parent */
};
-/* control.c */
-int control_init(void);
-int control_listen(struct relayd *, struct imsgev *, struct imsgev *);
-void control_accept(int, short, void *);
-void control_dispatch_imsg(int, short, void *);
-void control_imsg_forward(struct imsg *);
-void control_cleanup(void);
+enum privsep_procid {
+ PROC_PARENT = 0,
+ PROC_PFE,
+ PROC_HCE,
+ PROC_RELAY,
+ PROC_MAX
+} privsep_process;
+
+/* Attach the control socket to the following process */
+#define PROC_CONTROL PROC_PFE
+
+struct privsep {
+ int *ps_pipes[PROC_MAX][PROC_MAX];
+ struct imsgev *ps_ievs[PROC_MAX];
+ const char *ps_title[PROC_MAX];
+ pid_t ps_pid[PROC_MAX];
-void session_socket_blockmode(int, enum blockmodes);
+ u_int ps_instances[PROC_MAX];
+ u_int ps_instance;
+
+ struct control_sock ps_csock;
+
+ /* Event and signal handlers */
+ struct event ps_evsigint;
+ struct event ps_evsigterm;
+ struct event ps_evsigchld;
+ struct event ps_evsighup;
+ struct event ps_evsigpipe;
+
+ struct passwd *ps_pw;
+ struct relayd *ps_env;
+};
+
+struct privsep_proc {
+ const char *p_title;
+ enum privsep_procid p_id;
+ int (*p_cb)(int, struct privsep_proc *,
+ struct imsg *);
+ pid_t (*p_init)(struct privsep *,
+ struct privsep_proc *);
+ void (*p_shutdown)(void);
+ u_int p_instance;
+ const char *p_chroot;
+ struct privsep *p_ps;
+ struct relayd *p_env;
+};
+
+struct relayd {
+ u_int8_t sc_opts;
+ u_int32_t sc_flags;
+ const char *sc_confpath;
+ struct pfdata *sc_pf;
+ int sc_rtsock;
+ int sc_rtseq;
+ int sc_tablecount;
+ int sc_rdrcount;
+ int sc_protocount;
+ int sc_relaycount;
+ int sc_routercount;
+ int sc_routecount;
+ struct timeval sc_interval;
+ struct timeval sc_timeout;
+ struct table sc_empty_table;
+ struct protocol sc_proto_default;
+ struct event sc_ev;
+ struct tablelist *sc_tables;
+ struct rdrlist *sc_rdrs;
+ struct protolist *sc_protos;
+ struct relaylist *sc_relays;
+ struct routerlist *sc_rts;
+ struct netroutelist *sc_routes;
+ u_int16_t sc_prefork_relay;
+ char sc_demote_group[IFNAMSIZ];
+ u_int16_t sc_id;
+
+ struct event sc_statev;
+ struct timeval sc_statinterval;
+
+ int sc_snmp;
+ struct event sc_snmpto;
+ struct event sc_snmpev;
+
+ int sc_has_icmp;
+ int sc_has_icmp6;
+ struct ctl_icmp_event sc_icmp_send;
+ struct ctl_icmp_event sc_icmp_recv;
+ struct ctl_icmp_event sc_icmp6_send;
+ struct ctl_icmp_event sc_icmp6_recv;
+
+ struct privsep *sc_ps;
+};
+
+#define RELAYD_OPT_VERBOSE 0x01
+#define RELAYD_OPT_NOACTION 0x04
+#define RELAYD_OPT_LOGUPDATE 0x08
+#define RELAYD_OPT_LOGNOTIFY 0x10
+#define RELAYD_OPT_LOGALL 0x18
+
+/* control.c */
+int control_init(struct privsep *, struct control_sock *);
+int control_listen(struct control_sock *);
+void control_cleanup(struct control_sock *);
+void control_dispatch_imsg(int, short, void *);
+void control_imsg_forward(struct imsg *);
+struct ctl_conn *
+ control_connbyfd(int);
+void socket_set_blockmode(int, enum blockmodes);
extern struct ctl_connlist ctl_conns;
@@ -826,8 +878,7 @@ const char *printb_flags(const u_int32_t, const char *);
/* pfe.c */
-pid_t pfe(struct relayd *, int [2], int [2], int [RELAY_MAXPROC][2],
- int [2], int [RELAY_MAXPROC][2]);
+pid_t pfe(struct privsep *, struct privsep_proc *);
void show(struct ctl_conn *);
void show_sessions(struct ctl_conn *);
int enable_rdr(struct ctl_conn *, struct ctl_id *);
@@ -854,13 +905,11 @@ void sync_routes(struct relayd *, struct router *);
int pfe_route(struct relayd *, struct ctl_netroute *);
/* hce.c */
-pid_t hce(struct relayd *, int [2], int [2], int [RELAY_MAXPROC][2],
- int [2], int [RELAY_MAXPROC][2]);
+pid_t hce(struct privsep *, struct privsep_proc *);
void hce_notify_done(struct host *, enum host_error);
/* relay.c */
-pid_t relay(struct relayd *, int [2], int [2], int [RELAY_MAXPROC][2],
- int [2], int [RELAY_MAXPROC][2]);
+pid_t relay(struct privsep *, struct privsep_proc *);
void relay_notify_done(struct host *, const char *);
int relay_session_cmp(struct rsession *, struct rsession *);
int relay_load_certfiles(struct relay *);
@@ -893,7 +942,7 @@ void check_icmp(struct relayd *, struct timeval *);
void check_tcp(struct ctl_tcp_event *);
/* check_script.c */
-void check_script(struct host *);
+void check_script(struct relayd *, struct host *);
void script_done(struct relayd *, struct ctl_script *);
int script_exec(struct relayd *, struct ctl_script *);
@@ -958,9 +1007,9 @@ void pn_unref(u_int16_t);
void pn_ref(u_int16_t);
/* snmp.c */
-void snmp_init(struct relayd *, struct imsgev *);
-int snmp_sendsock(struct imsgev *);
-void snmp_hosttrap(struct table *, struct host *);
+void snmp_init(struct relayd *, enum privsep_procid);
+int snmp_sendsock(struct relayd *, enum privsep_procid);
+void snmp_hosttrap(struct relayd *, struct table *, struct host *);
/* shuffle.c */
void shuffle_init(struct shuffle *);
@@ -975,3 +1024,26 @@ void log_info(const char *, ...);
void log_debug(const char *, ...);
__dead void fatal(const char *);
__dead void fatalx(const char *);
+
+/* 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_dispatch(int, short event, void *);
+pid_t proc_run(struct privsep *, struct privsep_proc *,
+ struct privsep_proc *, u_int,
+ void (*)(struct privsep *, struct privsep_proc *, void *), void *);
+int proc_compose_imsg(struct privsep *, enum privsep_procid, int,
+ u_int16_t, int, void *, u_int16_t);
+int proc_composev_imsg(struct privsep *, enum privsep_procid, int,
+ u_int16_t, int, const struct iovec *, int);
+int proc_forward_imsg(struct privsep *, struct imsg *,
+ enum privsep_procid, int);
+void proc_flush_imsg(struct privsep *, enum privsep_procid, int);
+struct imsgbuf *
+ proc_ibuf(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,
+ pid_t, int, const struct iovec *, int);
diff --git a/usr.sbin/relayd/snmp.c b/usr.sbin/relayd/snmp.c
index e8a4ba42860..f341d74bade 100644
--- a/usr.sbin/relayd/snmp.c
+++ b/usr.sbin/relayd/snmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmp.c,v 1.9 2011/05/05 12:01:44 reyk Exp $ */
+/* $OpenBSD: snmp.c,v 1.10 2011/05/09 12:08:47 reyk Exp $ */
/*
* Copyright (c) 2008 Reyk Floeter <reyk@openbsd.org>
@@ -46,19 +46,15 @@
} while (0)
static struct imsgev *iev_snmp = NULL;
-static struct imsgev *iev_main = NULL;
-static struct relayd *env = NULL;
+enum privsep_procid snmp_procid;
void snmp_sock(int, short, void *);
-int snmp_getsock(struct imsgev *);
+int snmp_getsock(struct relayd *, enum privsep_procid);
int snmp_element(const char *, enum snmp_type, void *, int64_t);
void
-snmp_init(struct relayd *x_env, struct imsgev *iev)
+snmp_init(struct relayd *env, enum privsep_procid id)
{
- env = x_env;
- iev_main = iev;
-
if (event_initialized(&env->sc_snmpev))
event_del(&env->sc_snmpev);
if (event_initialized(&env->sc_snmpto))
@@ -68,16 +64,15 @@ snmp_init(struct relayd *x_env, struct imsgev *iev)
env->sc_snmp = -1;
}
- if ((env->sc_flags & F_TRAP) == 0) {
- iev_main = NULL;
+ if ((env->sc_flags & F_TRAP) == 0)
return;
- }
- snmp_sock(-1, -1, iev);
+ snmp_procid = id;
+ snmp_sock(-1, -1, env);
}
int
-snmp_sendsock(struct imsgev *iev)
+snmp_sendsock(struct relayd *env, enum privsep_procid id)
{
struct imsgev tmpiev;
struct sockaddr_un sun;
@@ -97,34 +92,36 @@ snmp_sendsock(struct imsgev *iev)
imsg_init(&tmpiev.ibuf, s);
imsg_compose_event(&tmpiev, IMSG_SNMP_LOCK, 0, 0, -1, NULL, 0);
- imsg_compose_event(iev, IMSG_SNMPSOCK, 0, 0, s, NULL, 0);
- imsg_flush(&iev->ibuf); /* need to send the socket now */
+ proc_compose_imsg(env->sc_ps, id, -1, IMSG_SNMPSOCK, s, NULL, 0);
+ proc_flush_imsg(env->sc_ps, id, -1); /* need to send the socket now */
close(s);
return (0);
fail:
if (s != -1)
close(s);
- imsg_compose_event(iev, IMSG_NONE, 0, 0, -1, NULL, 0);
+ proc_compose_imsg(env->sc_ps, id, -1, IMSG_NONE, -1, NULL, 0);
return (-1);
}
int
-snmp_getsock(struct imsgev *iev)
+snmp_getsock(struct relayd *env, enum privsep_procid id)
{
struct imsg imsg;
+ struct imsgbuf *ibuf;
int n, s = -1, done = 0;
- imsg_compose_event(iev, IMSG_SNMPSOCK, 0, 0, -1, NULL, 0);
- imsg_flush(&iev->ibuf);
+ ibuf = proc_ibuf(env->sc_ps, id, -1);
+ proc_compose_imsg(env->sc_ps, id, -1, IMSG_SNMPSOCK, -1, NULL, 0);
+ proc_flush_imsg(env->sc_ps, id, -1);
while (!done) {
- if ((n = imsg_read(&iev->ibuf)) == -1)
- fatal("snmp_getsock: failed to read imsg");
- if (n == 0)
- fatal("snmp_getsock: pipe closed");
+ do {
+ if ((n = imsg_read(ibuf)) == -1)
+ fatalx("snmp_getsock: imsg_read error");
+ } while (n == -2); /* handle non-blocking I/O */
while (!done) {
- if ((n = imsg_get(&iev->ibuf, &imsg)) == -1)
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
fatal("snmp_getsock: failed to get imsg");
if (n == 0)
break;
@@ -154,7 +151,8 @@ snmp_getsock(struct imsgev *iev)
void
snmp_sock(int fd, short event, void *arg)
{
- struct timeval tv = SNMP_RECONNECT_TIMEOUT;
+ struct relayd *env = arg;
+ struct timeval tv = SNMP_RECONNECT_TIMEOUT;
switch (event) {
case -1:
@@ -166,7 +164,7 @@ snmp_sock(int fd, short event, void *arg)
break;
}
- if ((env->sc_snmp = snmp_getsock(iev_main)) == -1) {
+ if ((env->sc_snmp = snmp_getsock(env, snmp_procid)) == -1) {
DPRINTF("%s: failed to open snmp socket", __func__);
goto retry;
}
@@ -176,7 +174,7 @@ snmp_sock(int fd, short event, void *arg)
event_add(&env->sc_snmpev, NULL);
return;
retry:
- evtimer_set(&env->sc_snmpto, snmp_sock, env);
+ evtimer_set(&env->sc_snmpto, snmp_sock, arg);
evtimer_add(&env->sc_snmpto, &tv);
}
@@ -248,7 +246,7 @@ snmp_element(const char *oid, enum snmp_type type, void *buf, int64_t val)
*/
void
-snmp_hosttrap(struct table *table, struct host *host)
+snmp_hosttrap(struct relayd *env, struct table *table, struct host *host)
{
if (iev_snmp == NULL || env->sc_snmp == -1)
return;