diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2011-05-09 12:08:48 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2011-05-09 12:08:48 +0000 |
commit | 3fe6727c8a01992e5184fdb1f1330d867e249abd (patch) | |
tree | 329873c80f595e57dc3b87e303d657b6ad375e84 | |
parent | 14b60d7f2a3b692fe6e022d46f3f406e34dbfdcd (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@
-rw-r--r-- | usr.sbin/relayctl/relayctl.c | 4 | ||||
-rw-r--r-- | usr.sbin/relayd/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/relayd/check_icmp.c | 4 | ||||
-rw-r--r-- | usr.sbin/relayd/check_script.c | 10 | ||||
-rw-r--r-- | usr.sbin/relayd/control.c | 93 | ||||
-rw-r--r-- | usr.sbin/relayd/hce.c | 421 | ||||
-rw-r--r-- | usr.sbin/relayd/parse.y | 3 | ||||
-rw-r--r-- | usr.sbin/relayd/pfe.c | 687 | ||||
-rw-r--r-- | usr.sbin/relayd/pfe_route.c | 8 | ||||
-rw-r--r-- | usr.sbin/relayd/relay.c | 461 | ||||
-rw-r--r-- | usr.sbin/relayd/relay_udp.c | 7 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.c | 574 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.h | 234 | ||||
-rw-r--r-- | usr.sbin/relayd/snmp.c | 54 |
14 files changed, 899 insertions, 1665 deletions
diff --git a/usr.sbin/relayctl/relayctl.c b/usr.sbin/relayctl/relayctl.c index 9054f8a7214..f09dccd9709 100644 --- a/usr.sbin/relayctl/relayctl.c +++ b/usr.sbin/relayctl/relayctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: relayctl.c,v 1.42 2010/12/31 21:22:42 guenther Exp $ */ +/* $OpenBSD: relayctl.c,v 1.43 2011/05/09 12:08:46 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -189,7 +189,7 @@ main(int argc, char *argv[]) verbose = 2; /* FALLTHROUGH */ case LOG_BRIEF: - imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, + imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &verbose, sizeof(verbose)); printf("logging request sent.\n"); done = 1; 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; |