summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/relayctl/parser.c22
-rw-r--r--usr.sbin/relayctl/parser.h4
-rw-r--r--usr.sbin/relayctl/relayctl.86
-rw-r--r--usr.sbin/relayctl/relayctl.c11
-rw-r--r--usr.sbin/relayd/Makefile4
-rw-r--r--usr.sbin/relayd/check_tcp.c59
-rw-r--r--usr.sbin/relayd/config.c898
-rw-r--r--usr.sbin/relayd/control.c29
-rw-r--r--usr.sbin/relayd/hce.c78
-rw-r--r--usr.sbin/relayd/parse.y237
-rw-r--r--usr.sbin/relayd/pfe.c124
-rw-r--r--usr.sbin/relayd/pfe_filter.c19
-rw-r--r--usr.sbin/relayd/pfe_route.c51
-rw-r--r--usr.sbin/relayd/proc.c46
-rw-r--r--usr.sbin/relayd/relay.c206
-rw-r--r--usr.sbin/relayd/relayd.c522
-rw-r--r--usr.sbin/relayd/relayd.h138
-rw-r--r--usr.sbin/relayd/snmp.c92
18 files changed, 1777 insertions, 769 deletions
diff --git a/usr.sbin/relayctl/parser.c b/usr.sbin/relayctl/parser.c
index a9fa3a25814..a8a80c73f2c 100644
--- a/usr.sbin/relayctl/parser.c
+++ b/usr.sbin/relayctl/parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.c,v 1.24 2010/09/04 21:31:04 tedu Exp $ */
+/* $OpenBSD: parser.c,v 1.25 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -46,7 +46,8 @@ enum token_type {
HOSTID,
TABLEID,
RDRID,
- KEYWORD
+ KEYWORD,
+ PATH
};
struct token {
@@ -65,10 +66,12 @@ static const struct token t_rdr_id[];
static const struct token t_table_id[];
static const struct token t_host_id[];
static const struct token t_log[];
+static const struct token t_load[];
static const struct token t_main[] = {
{KEYWORD, "monitor", MONITOR, NULL},
{KEYWORD, "show", NONE, t_show},
+ {KEYWORD, "load", LOAD, t_load},
{KEYWORD, "poll", POLL, NULL},
{KEYWORD, "reload", RELOAD, NULL},
{KEYWORD, "stop", SHUTDOWN, NULL},
@@ -131,6 +134,11 @@ static const struct token t_log[] = {
{ENDTOKEN, "", NONE, NULL}
};
+static const struct token t_load[] = {
+ {PATH, "", NONE, NULL},
+ {ENDTOKEN, "", NONE, NULL}
+};
+
static const struct token *match_token(const char *, const struct token *,
struct parse_result *);
static void show_valid_args(const struct token *);
@@ -228,6 +236,13 @@ match_token(const char *word, const struct token *table,
t = &table[i];
match++;
break;
+ case PATH:
+ if (!match && word != NULL && strlen(word) > 0) {
+ res->path = strdup(word);
+ match++;
+ t = &table[i];
+ }
+ break;
case ENDTOKEN:
break;
}
@@ -268,6 +283,9 @@ show_valid_args(const struct token *table)
case HOSTID:
fprintf(stderr, " <hostid>\n");
break;
+ case PATH:
+ fprintf(stderr, " <path>\n");
+ break;
case ENDTOKEN:
break;
}
diff --git a/usr.sbin/relayctl/parser.h b/usr.sbin/relayctl/parser.h
index 8682b433c1f..5e19f9befde 100644
--- a/usr.sbin/relayctl/parser.h
+++ b/usr.sbin/relayctl/parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.h,v 1.13 2010/09/04 21:31:04 tedu Exp $ */
+/* $OpenBSD: parser.h,v 1.14 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -32,6 +32,7 @@ enum actions {
HOST_ENABLE,
SHUTDOWN,
POLL,
+ LOAD,
RELOAD,
MONITOR,
LOG_VERBOSE,
@@ -41,6 +42,7 @@ enum actions {
struct parse_result {
struct ctl_id id;
enum actions action;
+ char *path;
};
struct parse_result *parse(int, char *[]);
diff --git a/usr.sbin/relayctl/relayctl.8 b/usr.sbin/relayctl/relayctl.8
index 7de530474de..75aec549914 100644
--- a/usr.sbin/relayctl/relayctl.8
+++ b/usr.sbin/relayctl/relayctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: relayctl.8,v 1.26 2009/10/22 15:02:12 sobrado Exp $
+.\" $OpenBSD: relayctl.8,v 1.27 2011/05/19 08:56:49 reyk Exp $
.\"
.\" Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: October 22 2009 $
+.Dd $Mdocdate: May 19 2011 $
.Dt RELAYCTL 8
.Os
.Sh NAME
@@ -39,6 +39,8 @@ Treat it as though it were always down.
.It Cm host enable Op Ar name | id
Enable the host.
Start checking its health again.
+.It Cm load Ar filename
+Reload the configuration from the specified file.
.It Cm monitor
Continuously report any changes in the host checking engine and the
.Xr pf 4
diff --git a/usr.sbin/relayctl/relayctl.c b/usr.sbin/relayctl/relayctl.c
index f09dccd9709..1f83e8109ad 100644
--- a/usr.sbin/relayctl/relayctl.c
+++ b/usr.sbin/relayctl/relayctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayctl.c,v 1.43 2011/05/09 12:08:46 reyk Exp $ */
+/* $OpenBSD: relayctl.c,v 1.44 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -179,8 +179,14 @@ main(int argc, char *argv[])
case POLL:
imsg_compose(ibuf, IMSG_CTL_POLL, 0, 0, -1, NULL, 0);
break;
+ case LOAD:
+ imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1,
+ res->path, strlen(res->path));
+ done = 1;
+ break;
case RELOAD:
imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
+ done = 1;
break;
case MONITOR:
imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0);
@@ -229,13 +235,14 @@ main(int argc, char *argv[])
case HOST_DISABLE:
case HOST_ENABLE:
case POLL:
- case RELOAD:
case SHUTDOWN:
done = show_command_output(&imsg);
break;
case NONE:
case LOG_VERBOSE:
case LOG_BRIEF:
+ case RELOAD:
+ case LOAD:
break;
case MONITOR:
done = monitor(&imsg);
diff --git a/usr.sbin/relayd/Makefile b/usr.sbin/relayd/Makefile
index 158491944da..0ae2acc345b 100644
--- a/usr.sbin/relayd/Makefile
+++ b/usr.sbin/relayd/Makefile
@@ -1,10 +1,10 @@
-# $OpenBSD: Makefile,v 1.21 2011/05/09 12:08:47 reyk Exp $
+# $OpenBSD: Makefile,v 1.22 2011/05/19 08:56:49 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 proc.c
+ name2id.c snmp.c shuffle.c proc.c config.c
MAN= relayd.8 relayd.conf.5
LDADD= -levent -lssl -lcrypto -lutil
diff --git a/usr.sbin/relayd/check_tcp.c b/usr.sbin/relayd/check_tcp.c
index 92bd2cef6f2..d960f0aa6a7 100644
--- a/usr.sbin/relayd/check_tcp.c
+++ b/usr.sbin/relayd/check_tcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_tcp.c,v 1.40 2011/05/05 12:01:43 reyk Exp $ */
+/* $OpenBSD: check_tcp.c,v 1.41 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -38,7 +38,8 @@
#include "relayd.h"
void tcp_write(int, short, void *);
-void tcp_host_up(int, struct ctl_tcp_event *);
+void tcp_host_up(struct ctl_tcp_event *);
+void tcp_close(struct ctl_tcp_event *, int);
void tcp_send_req(int, short, void *);
void tcp_read_buf(int, short, void *);
@@ -99,14 +100,14 @@ check_tcp(struct ctl_tcp_event *cte)
cte->buf = NULL;
cte->host->up = HOST_UP;
+ cte->s = s;
event_del(&cte->ev);
event_set(&cte->ev, s, EV_TIMEOUT|EV_WRITE, tcp_write, cte);
event_add(&cte->ev, &tv);
return;
bad:
- close(s);
- cte->host->up = HOST_DOWN;
+ tcp_close(cte, HOST_DOWN);
hce_notify_done(cte->host, he);
}
@@ -118,8 +119,7 @@ tcp_write(int s, short event, void *arg)
socklen_t len;
if (event == EV_TIMEOUT) {
- close(s);
- cte->host->up = HOST_DOWN;
+ tcp_close(cte, HOST_DOWN);
hce_notify_done(cte->host, HCE_TCP_CONNECT_TIMEOUT);
return;
}
@@ -128,26 +128,36 @@ tcp_write(int s, short event, void *arg)
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len))
fatal("tcp_write: getsockopt");
if (err != 0) {
- close(s);
- cte->host->up = HOST_DOWN;
+ tcp_close(cte, HOST_DOWN);
hce_notify_done(cte->host, HCE_TCP_CONNECT_FAIL);
return;
}
cte->host->up = HOST_UP;
- tcp_host_up(s, cte);
+ tcp_host_up(cte);
}
void
-tcp_host_up(int s, struct ctl_tcp_event *cte)
+tcp_close(struct ctl_tcp_event *cte, int status)
{
- cte->s = s;
+ close(cte->s);
+ cte->s = -1;
+ if (status != 0)
+ cte->host->up = status;
+ if (cte->buf) {
+ ibuf_free(cte->buf);
+ cte->buf = NULL;
+ }
+}
+void
+tcp_host_up(struct ctl_tcp_event *cte)
+{
switch (cte->table->conf.check) {
case CHECK_TCP:
if (cte->table->conf.flags & F_SSL)
break;
- close(s);
+ tcp_close(cte, 0);
hce_notify_done(cte->host, HCE_TCP_CONNECT_OK);
return;
case CHECK_HTTP_CODE:
@@ -171,14 +181,14 @@ tcp_host_up(int s, struct ctl_tcp_event *cte)
if (cte->table->sendbuf != NULL) {
cte->req = cte->table->sendbuf;
- event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, tcp_send_req,
+ event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_WRITE, tcp_send_req,
&cte->tv_start, &cte->table->conf.timeout, cte);
return;
}
if ((cte->buf = ibuf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
fatalx("tcp_host_up: cannot create dynamic buffer");
- event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, tcp_read_buf,
+ event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_READ, tcp_read_buf,
&cte->tv_start, &cte->table->conf.timeout, cte);
}
@@ -190,8 +200,7 @@ tcp_send_req(int s, short event, void *arg)
int len;
if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- close(cte->s);
+ tcp_close(cte, HOST_DOWN);
hce_notify_done(cte->host, HCE_TCP_WRITE_TIMEOUT);
return;
}
@@ -202,8 +211,7 @@ tcp_send_req(int s, short event, void *arg)
if (errno == EAGAIN || errno == EINTR)
goto retry;
log_warnx("%s: cannot send request", __func__);
- cte->host->up = HOST_DOWN;
- close(cte->s);
+ tcp_close(cte, HOST_DOWN);
hce_notify_done(cte->host, HCE_TCP_WRITE_FAIL);
return;
}
@@ -230,9 +238,7 @@ tcp_read_buf(int s, short event, void *arg)
struct ctl_tcp_event *cte = arg;
if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- ibuf_free(cte->buf);
- close(s);
+ tcp_close(cte, HOST_DOWN);
hce_notify_done(cte->host, HCE_TCP_READ_TIMEOUT);
return;
}
@@ -243,16 +249,13 @@ tcp_read_buf(int s, short event, void *arg)
case -1:
if (errno == EAGAIN || errno == EINTR)
goto retry;
- cte->host->up = HOST_DOWN;
- ibuf_free(cte->buf);
- close(cte->s);
+ tcp_close(cte, HOST_DOWN);
hce_notify_done(cte->host, HCE_TCP_READ_FAIL);
return;
case 0:
cte->host->up = HOST_DOWN;
(void)cte->validate_close(cte);
- close(cte->s);
- ibuf_free(cte->buf);
+ tcp_close(cte, 0);
hce_notify_done(cte->host, cte->host->he);
return;
default:
@@ -261,9 +264,7 @@ tcp_read_buf(int s, short event, void *arg)
if (cte->validate_read != NULL) {
if (cte->validate_read(cte) != 0)
goto retry;
-
- close(cte->s);
- ibuf_free(cte->buf);
+ tcp_close(cte, 0);
hce_notify_done(cte->host, cte->host->he);
return;
}
diff --git a/usr.sbin/relayd/config.c b/usr.sbin/relayd/config.c
new file mode 100644
index 00000000000..bb91b88c364
--- /dev/null
+++ b/usr.sbin/relayd/config.c
@@ -0,0 +1,898 @@
+/* $OpenBSD: config.c,v 1.1 2011/05/19 08:56:49 reyk Exp $ */
+
+/*
+ * Copyright (c) 2011 Reyk Floeter <reyk@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
+
+#include <net/if.h>
+#include <net/pfvar.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <net/route.h>
+
+#include <ctype.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <event.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <ifaddrs.h>
+
+#include <openssl/ssl.h>
+
+#include "relayd.h"
+
+int
+config_init(struct relayd *env)
+{
+ struct privsep *ps = env->sc_ps;
+ u_int what;
+
+ /* Global configuration */
+ if (privsep_process == PROC_PARENT) {
+ env->sc_timeout.tv_sec = CHECK_TIMEOUT / 1000;
+ env->sc_timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
+ env->sc_interval.tv_sec = CHECK_INTERVAL;
+ env->sc_interval.tv_usec = 0;
+ env->sc_prefork_relay = RELAY_NUMPROC;
+ env->sc_statinterval.tv_sec = RELAY_STATINTERVAL;
+
+ ps->ps_what[PROC_PARENT] = CONFIG_ALL;
+ ps->ps_what[PROC_PFE] = CONFIG_ALL & ~CONFIG_PROTOS;
+ ps->ps_what[PROC_HCE] = CONFIG_TABLES;
+ ps->ps_what[PROC_RELAY] =
+ CONFIG_TABLES|CONFIG_RELAYS|CONFIG_PROTOS;
+ }
+
+ /* Other configuration */
+ what = ps->ps_what[privsep_process];
+ if (what & CONFIG_TABLES) {
+ if ((env->sc_tables =
+ calloc(1, sizeof(*env->sc_tables))) == NULL)
+ return (-1);
+ TAILQ_INIT(env->sc_tables);
+
+ memset(&env->sc_empty_table, 0, sizeof(env->sc_empty_table));
+ env->sc_empty_table.conf.id = EMPTY_TABLE;
+ env->sc_empty_table.conf.flags |= F_DISABLE;
+ (void)strlcpy(env->sc_empty_table.conf.name, "empty",
+ sizeof(env->sc_empty_table.conf.name));
+
+ }
+ if (what & CONFIG_RDRS) {
+ if ((env->sc_rdrs =
+ calloc(1, sizeof(*env->sc_rdrs))) == NULL)
+ return (-1);
+ TAILQ_INIT(env->sc_rdrs);
+
+ }
+ if (what & CONFIG_RELAYS) {
+ if ((env->sc_relays =
+ calloc(1, sizeof(*env->sc_relays))) == NULL)
+ return (-1);
+ TAILQ_INIT(env->sc_relays);
+ }
+ if (what & CONFIG_PROTOS) {
+ if ((env->sc_protos =
+ calloc(1, sizeof(*env->sc_protos))) == NULL)
+ return (-1);
+ TAILQ_INIT(env->sc_protos);
+
+ bzero(&env->sc_proto_default, sizeof(env->sc_proto_default));
+ env->sc_proto_default.id = EMPTY_ID;
+ env->sc_proto_default.flags = F_USED;
+ env->sc_proto_default.cache = RELAY_CACHESIZE;
+ env->sc_proto_default.tcpflags = TCPFLAG_DEFAULT;
+ env->sc_proto_default.tcpbacklog = RELAY_BACKLOG;
+ env->sc_proto_default.sslflags = SSLFLAG_DEFAULT;
+ (void)strlcpy(env->sc_proto_default.sslciphers,
+ SSLCIPHERS_DEFAULT,
+ sizeof(env->sc_proto_default.sslciphers));
+ env->sc_proto_default.type = RELAY_PROTO_TCP;
+ (void)strlcpy(env->sc_proto_default.name, "default",
+ sizeof(env->sc_proto_default.name));
+ RB_INIT(&env->sc_proto_default.request_tree);
+ RB_INIT(&env->sc_proto_default.response_tree);
+ }
+ if (what & CONFIG_RTS) {
+ if ((env->sc_rts =
+ calloc(1, sizeof(*env->sc_rts))) == NULL)
+ return (-1);
+ TAILQ_INIT(env->sc_rts);
+ }
+ if (what & CONFIG_ROUTES) {
+ if ((env->sc_routes =
+ calloc(1, sizeof(*env->sc_routes))) == NULL)
+ return (-1);
+ TAILQ_INIT(env->sc_routes);
+ }
+
+ return (0);
+}
+
+void
+config_purge(struct relayd *env, u_int reset)
+{
+ struct privsep *ps = env->sc_ps;
+ struct table *table;
+ struct rdr *rdr;
+ struct address *virt;
+ struct protocol *proto;
+ struct relay *rlay;
+ struct netroute *nr;
+ struct router *rt;
+ u_int what;
+
+ what = ps->ps_what[privsep_process] & reset;
+
+ if (what & CONFIG_TABLES && env->sc_tables != NULL) {
+ while ((table = TAILQ_FIRST(env->sc_tables)) != NULL)
+ purge_table(env->sc_tables, table);
+ env->sc_tablecount = 0;
+ }
+ if (what & CONFIG_RDRS && env->sc_rdrs != NULL) {
+ while ((rdr = TAILQ_FIRST(env->sc_rdrs)) != NULL) {
+ TAILQ_REMOVE(env->sc_rdrs, rdr, entry);
+ while ((virt = TAILQ_FIRST(&rdr->virts)) != NULL) {
+ TAILQ_REMOVE(&rdr->virts, virt, entry);
+ free(virt);
+ }
+ free(rdr);
+ }
+ env->sc_rdrcount = 0;
+ }
+ if (what & CONFIG_RELAYS && env->sc_relays != NULL) {
+ while ((rlay = TAILQ_FIRST(env->sc_relays)) != NULL)
+ purge_relay(env, rlay);
+ env->sc_relaycount = 0;
+ }
+ if (what & CONFIG_PROTOS && env->sc_protos != NULL) {
+ while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
+ TAILQ_REMOVE(env->sc_protos, proto, entry);
+ purge_tree(&proto->request_tree);
+ purge_tree(&proto->response_tree);
+ if (proto->style != NULL)
+ free(proto->style);
+ free(proto);
+ }
+ env->sc_protocount = 0;
+ }
+ if (what & CONFIG_RTS && env->sc_rts != NULL) {
+ while ((rt = TAILQ_FIRST(env->sc_rts)) != NULL) {
+ TAILQ_REMOVE(env->sc_rts, rt, rt_entry);
+ while ((nr = TAILQ_FIRST(&rt->rt_netroutes)) != NULL) {
+ TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
+ TAILQ_REMOVE(env->sc_routes, nr, nr_route);
+ free(nr);
+ env->sc_routecount--;
+ }
+ free(rt);
+ }
+ env->sc_routercount = 0;
+ }
+ if (what & CONFIG_ROUTES && env->sc_routes != NULL) {
+ while ((nr = TAILQ_FIRST(env->sc_routes)) != NULL) {
+ if ((rt = nr->nr_router) != NULL)
+ TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
+ TAILQ_REMOVE(env->sc_routes, nr, nr_route);
+ free(nr);
+ }
+ env->sc_routecount = 0;
+ }
+}
+
+int
+config_setreset(struct relayd *env, u_int reset)
+{
+ struct privsep *ps = env->sc_ps;
+ int id;
+
+ for (id = 0; id < PROC_MAX; id++) {
+ if ((reset & ps->ps_what[id]) == 0 ||
+ id == privsep_process)
+ continue;
+ proc_compose_imsg(ps, id, -1, IMSG_CTL_RESET, -1,
+ &reset, sizeof(reset));
+ }
+
+ return (0);
+}
+
+int
+config_getreset(struct relayd *env, struct imsg *imsg)
+{
+ u_int mode;
+
+ IMSG_SIZE_CHECK(imsg, &mode);
+ memcpy(&mode, imsg->data, sizeof(mode));
+
+ config_purge(env, mode);
+
+ return (0);
+}
+
+int
+config_getcfg(struct relayd *env, struct imsg *imsg)
+{
+ struct privsep *ps = env->sc_ps;
+ struct table *tb;
+ struct host *h, *ph;
+ struct ctl_flags cf;
+
+ if (IMSG_DATA_SIZE(imsg) != sizeof(cf))
+ return (0); /* ignore */
+
+ /* Update runtime flags */
+ memcpy(&cf, imsg->data, sizeof(cf));
+ env->sc_opts = cf.cf_opts;
+ env->sc_flags = cf.cf_flags;
+
+ if (ps->ps_what[privsep_process] & CONFIG_TABLES) {
+ /* Update the tables */
+ TAILQ_FOREACH(tb, env->sc_tables, entry) {
+ TAILQ_FOREACH(h, &tb->hosts, entry) {
+ if (h->conf.parentid && (ph = host_find(env,
+ h->conf.parentid)) != NULL) {
+ SLIST_INSERT_HEAD(&ph->children,
+ h, child);
+ }
+ }
+ }
+ }
+
+ if (env->sc_flags & (F_SSL|F_SSLCLIENT))
+ ssl_init(env);
+
+ if (privsep_process != PROC_PARENT)
+ proc_compose_imsg(env->sc_ps, PROC_PARENT, -1,
+ IMSG_CFG_DONE, -1, NULL, 0);
+
+ return (0);
+}
+
+int
+config_settable(struct relayd *env, struct table *tb)
+{
+ struct privsep *ps = env->sc_ps;
+ struct host *host;
+ int id, c;
+ struct iovec iov[2];
+
+ for (id = 0; id < PROC_MAX; id++) {
+ if ((ps->ps_what[id] & CONFIG_TABLES) == 0 ||
+ id == privsep_process)
+ continue;
+
+ /* XXX need to send table to pfe for control socket */
+ if (id == PROC_HCE && tb->conf.check == CHECK_NOCHECK)
+ continue;
+
+ DPRINTF("%s: sending table %s %d to %s", __func__,
+ tb->conf.name, tb->conf.id, env->sc_ps->ps_title[id]);
+
+ c = 0;
+ iov[c].iov_base = &tb->conf;
+ iov[c++].iov_len = sizeof(tb->conf);
+ if (tb->sendbuf != NULL) {
+ iov[c].iov_base = tb->sendbuf;
+ iov[c++].iov_len = strlen(tb->sendbuf);
+ }
+
+ proc_composev_imsg(ps, id, -1, IMSG_CFG_TABLE, -1, iov, c);
+
+ TAILQ_FOREACH(host, &tb->hosts, entry) {
+ proc_compose_imsg(ps, id, -1, IMSG_CFG_HOST, -1,
+ &host->conf, sizeof(host->conf));
+ }
+ }
+
+ return (0);
+}
+
+int
+config_gettable(struct relayd *env, struct imsg *imsg)
+{
+ struct table *tb;
+ size_t sb;
+ u_int8_t *p = imsg->data;
+ size_t s;
+
+ if ((tb = calloc(1, sizeof(*tb))) == NULL)
+ return (-1);
+
+ IMSG_SIZE_CHECK(imsg, &tb->conf);
+ memcpy(&tb->conf, p, sizeof(tb->conf));
+ s = sizeof(tb->conf);
+
+ sb = IMSG_DATA_SIZE(imsg) - s;
+ if (sb > 0)
+ tb->sendbuf = get_string(p + s, sb);
+
+ TAILQ_INIT(&tb->hosts);
+ TAILQ_INSERT_TAIL(env->sc_tables, tb, entry);
+
+ env->sc_tablecount++;
+
+ DPRINTF("%s: %s %d received table %d (%s)", __func__,
+ env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
+ tb->conf.id, tb->conf.name);
+
+ return (0);
+}
+
+int
+config_gethost(struct relayd *env, struct imsg *imsg)
+{
+ struct table *tb;
+ struct host *host;
+
+ if ((host = calloc(1, sizeof(*host))) == NULL)
+ return (-1);
+
+ IMSG_SIZE_CHECK(imsg, &host->conf);
+ memcpy(&host->conf, imsg->data, sizeof(host->conf));
+
+ if (host_find(env, host->conf.id) != NULL) {
+ log_debug("%s: host %d already exists",
+ __func__, host->conf.id);
+ free(host);
+ return (-1);
+ }
+
+ if ((tb = table_find(env, host->conf.tableid)) == NULL) {
+ log_debug("%s: "
+ "received host for unknown table %d", __func__,
+ host->conf.tableid);
+ free(host);
+ return (-1);
+ }
+
+ host->tablename = tb->conf.name;
+ host->cte.s = -1;
+
+ SLIST_INIT(&host->children);
+ TAILQ_INSERT_TAIL(&tb->hosts, host, entry);
+
+ DPRINTF("%s: %s %d received host %s for table %s", __func__,
+ env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
+ host->conf.name, tb->conf.name);
+
+ return (0);
+}
+
+int
+config_setrdr(struct relayd *env, struct rdr *rdr)
+{
+ struct privsep *ps = env->sc_ps;
+ struct address *virt;
+ int id;
+
+ for (id = 0; id < PROC_MAX; id++) {
+ if ((ps->ps_what[id] & CONFIG_RDRS) == 0 ||
+ id == privsep_process)
+ continue;
+
+ DPRINTF("%s: sending rdr %s to %s", __func__,
+ rdr->conf.name, ps->ps_title[id]);
+
+ proc_compose_imsg(ps, id, -1, IMSG_CFG_RDR, -1,
+ &rdr->conf, sizeof(rdr->conf));
+
+ TAILQ_FOREACH(virt, &rdr->virts, entry) {
+ virt->rdrid = rdr->conf.id;
+ proc_compose_imsg(ps, id, -1, IMSG_CFG_VIRT, -1,
+ virt, sizeof(*virt));
+ }
+ }
+
+ return (0);
+}
+
+int
+config_getrdr(struct relayd *env, struct imsg *imsg)
+{
+ struct rdr *rdr;
+
+ if ((rdr = calloc(1, sizeof(*rdr))) == NULL)
+ return (-1);
+
+ IMSG_SIZE_CHECK(imsg, &rdr->conf);
+ memcpy(&rdr->conf, imsg->data, sizeof(rdr->conf));
+
+ if ((rdr->table = table_find(env, rdr->conf.table_id)) == NULL) {
+ log_debug("%s: table not found", __func__);
+ free(rdr);
+ return (-1);
+ }
+ if ((rdr->backup = table_find(env, rdr->conf.backup_id)) == NULL) {
+ rdr->conf.backup_id = EMPTY_TABLE;
+ rdr->backup = &env->sc_empty_table;
+ }
+
+ TAILQ_INIT(&rdr->virts);
+ TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry);
+
+ env->sc_rdrcount++;
+
+ DPRINTF("%s: %s %d received rdr %s", __func__,
+ env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
+ rdr->conf.name);
+
+ return (0);
+}
+
+int
+config_getvirt(struct relayd *env, struct imsg *imsg)
+{
+ struct rdr *rdr;
+ struct address *virt;
+
+ IMSG_SIZE_CHECK(imsg, virt);
+
+ if ((virt = calloc(1, sizeof(*virt))) == NULL)
+ return (-1);
+ memcpy(virt, imsg->data, sizeof(*virt));
+
+ if ((rdr = rdr_find(env, virt->rdrid)) == NULL) {
+ log_debug("%s: rdr not found", __func__);
+ free(virt);
+ return (-1);
+ }
+
+ TAILQ_INSERT_TAIL(&rdr->virts, virt, entry);
+
+ DPRINTF("%s: %s %d received address for rdr %s", __func__,
+ env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
+ rdr->conf.name);
+
+ return (0);
+}
+
+int
+config_setrt(struct relayd *env, struct router *rt)
+{
+ struct privsep *ps = env->sc_ps;
+ struct netroute *nr;
+ int id;
+
+ for (id = 0; id < PROC_MAX; id++) {
+ if ((ps->ps_what[id] & CONFIG_RTS) == 0 ||
+ id == privsep_process)
+ continue;
+
+ DPRINTF("%s: sending router %s to %s tbl %d", __func__,
+ rt->rt_conf.name, ps->ps_title[id], rt->rt_conf.gwtable);
+
+ proc_compose_imsg(ps, id, -1, IMSG_CFG_ROUTER, -1,
+ &rt->rt_conf, sizeof(rt->rt_conf));
+
+ TAILQ_FOREACH(nr, &rt->rt_netroutes, nr_entry) {
+ proc_compose_imsg(ps, id, -1, IMSG_CFG_ROUTE, -1,
+ &nr->nr_conf, sizeof(nr->nr_conf));
+ }
+ }
+
+ return (0);
+}
+
+int
+config_getrt(struct relayd *env, struct imsg *imsg)
+{
+ struct router *rt;
+
+ if ((rt = calloc(1, sizeof(*rt))) == NULL)
+ return (-1);
+
+ IMSG_SIZE_CHECK(imsg, &rt->rt_conf);
+ memcpy(&rt->rt_conf, imsg->data, sizeof(rt->rt_conf));
+
+ if ((rt->rt_gwtable = table_find(env, rt->rt_conf.gwtable)) == NULL) {
+ log_debug("%s: table not found", __func__);
+ free(rt);
+ return (-1);
+ }
+
+ TAILQ_INIT(&rt->rt_netroutes);
+ TAILQ_INSERT_TAIL(env->sc_rts, rt, rt_entry);
+
+ env->sc_routercount++;
+
+ DPRINTF("%s: %s %d received router %s", __func__,
+ env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
+ rt->rt_conf.name);
+
+ return (0);
+}
+
+int
+config_getroute(struct relayd *env, struct imsg *imsg)
+{
+ struct router *rt;
+ struct netroute *nr;
+
+ if ((nr = calloc(1, sizeof(*nr))) == NULL)
+ return (-1);
+
+ IMSG_SIZE_CHECK(imsg, &nr->nr_conf);
+ memcpy(&nr->nr_conf, imsg->data, sizeof(nr->nr_conf));
+
+ if (route_find(env, nr->nr_conf.id) != NULL) {
+ log_debug("%s: route %d already exists",
+ __func__, nr->nr_conf.id);
+ free(nr);
+ return (-1);
+ }
+
+ if ((rt = router_find(env, nr->nr_conf.routerid)) == NULL) {
+ log_debug("%s: received route for unknown router", __func__);
+ free(nr);
+ return (-1);
+ }
+
+ nr->nr_router = rt;
+
+ TAILQ_INSERT_TAIL(env->sc_routes, nr, nr_route);
+ TAILQ_INSERT_TAIL(&rt->rt_netroutes, nr, nr_entry);
+
+ env->sc_routecount++;
+
+ DPRINTF("%s: %s %d received route %d for router %s", __func__,
+ env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
+ nr->nr_conf.id, rt->rt_conf.name);
+
+ return (0);
+}
+
+int
+config_setproto(struct relayd *env, struct protocol *proto)
+{
+ struct privsep *ps = env->sc_ps;
+ int id;
+ struct iovec iov[2];
+ size_t c;
+
+ for (id = 0; id < PROC_MAX; id++) {
+ if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
+ id == privsep_process)
+ continue;
+
+ DPRINTF("%s: sending protocol %s to %s", __func__,
+ proto->name, ps->ps_title[id]);
+
+ c = 0;
+ iov[c].iov_base = proto;
+ iov[c++].iov_len = sizeof(*proto);
+
+ if (proto->style != NULL) {
+ iov[c].iov_base = proto->style;
+ iov[c++].iov_len = strlen(proto->style);
+ }
+
+ /* XXX struct protocol should be split */
+ proc_composev_imsg(ps, id, -1, IMSG_CFG_PROTO, -1, iov, c);
+
+ /* Now send all the protocol key/value nodes */
+ if (config_setprotonode(env, id, proto,
+ RELAY_DIR_REQUEST) == -1 ||
+ config_setprotonode(env, id, proto,
+ RELAY_DIR_RESPONSE) == -1)
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+config_getproto(struct relayd *env, struct imsg *imsg)
+{
+ struct protocol *proto;
+ size_t styl;
+
+ if ((proto = calloc(1, sizeof(*proto))) == NULL)
+ return (-1);
+
+ IMSG_SIZE_CHECK(imsg, proto);
+ memcpy(proto, imsg->data, sizeof(*proto));
+
+ styl = IMSG_DATA_SIZE(imsg) - sizeof(*proto);
+ if (styl > 0)
+ proto->style = get_string((char *)imsg->data +
+ sizeof(*proto), styl);
+
+ proto->request_nodes = 0;
+ proto->response_nodes = 0;
+ RB_INIT(&proto->request_tree);
+ RB_INIT(&proto->response_tree);
+
+ TAILQ_INSERT_TAIL(env->sc_protos, proto, entry);
+
+ env->sc_protocount++;
+
+ DPRINTF("%s: %s %d received protocol %s", __func__,
+ env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
+ proto->name);
+
+ return (0);
+}
+
+int
+config_setprotonode(struct relayd *env, enum privsep_procid id,
+ struct protocol *proto, enum direction dir)
+{
+ struct privsep *ps = env->sc_ps;
+ struct iovec iov[IOV_MAX];
+ size_t c, sz;
+ struct protonode *proot, *pn;
+ struct proto_tree *tree;
+
+ if (dir == RELAY_DIR_RESPONSE)
+ tree = &proto->response_tree;
+ else
+ tree = &proto->request_tree;
+
+ sz = c = 0;
+ RB_FOREACH(proot, proto_tree, tree) {
+ PROTONODE_FOREACH(pn, proot, entry) {
+ pn->conf.protoid = proto->id;
+ pn->conf.dir = dir;
+ pn->conf.keylen = pn->key ? strlen(pn->key) : 0;
+ pn->conf.valuelen = pn->value ? strlen(pn->value) : 0;
+ pn->conf.len = sizeof(*pn) +
+ pn->conf.keylen + pn->conf.valuelen;
+
+ if (pn->conf.len > (MAX_IMSGSIZE - IMSG_HEADER_SIZE))
+ return (-1);
+
+ if (c && ((c + 3) >= IOV_MAX || (sz + pn->conf.len) >
+ (MAX_IMSGSIZE - IMSG_HEADER_SIZE))) {
+ proc_composev_imsg(ps, id, -1,
+ IMSG_CFG_PROTONODE, -1, iov, c);
+ c = sz = 0;
+ }
+
+ iov[c].iov_base = pn;
+ iov[c++].iov_len = sizeof(*pn);
+ if (pn->conf.keylen) {
+ iov[c].iov_base = pn->key;
+ iov[c++].iov_len = pn->conf.keylen;
+ }
+ if (pn->conf.valuelen) {
+ iov[c].iov_base = pn->value;
+ iov[c++].iov_len = pn->conf.valuelen;
+ }
+ sz += pn->conf.len;
+ }
+ }
+
+ if (c && sz)
+ proc_composev_imsg(ps, id, -1, IMSG_CFG_PROTONODE, -1, iov, c);
+
+ return (0);
+}
+
+int
+config_getprotonode(struct relayd *env, struct imsg *imsg)
+{
+ struct protocol *proto = NULL;
+ struct protonode pn;
+ size_t z, s, c = 0;
+ u_int8_t *p = imsg->data;
+
+ bzero(&pn, sizeof(pn));
+
+ IMSG_SIZE_CHECK(imsg, &pn);
+ for (z = 0; z < (IMSG_DATA_SIZE(imsg) - sizeof(pn)); z += pn.conf.len) {
+ s = z;
+ memcpy(&pn, p + s, sizeof(pn));
+ s += sizeof(pn);
+
+ if ((proto = proto_find(env, pn.conf.protoid)) == NULL) {
+ log_debug("%s: unknown protocol %d", __func__,
+ pn.conf.protoid);
+ return (-1);
+ }
+
+ pn.key = pn.value = NULL;
+ bzero(&pn.entry, sizeof(pn.entry));
+ bzero(&pn.nodes, sizeof(pn.nodes));
+ bzero(&pn.head, sizeof(pn.head));
+
+ if (pn.conf.keylen) {
+ pn.key = get_string(p + s, pn.conf.keylen);
+ s += pn.conf.keylen;
+ }
+ if (pn.conf.valuelen) {
+ pn.value = get_string(p + s, pn.conf.valuelen);
+ s += pn.conf.valuelen;
+ }
+
+ if (protonode_add(pn.conf.dir, proto, &pn) == -1) {
+ log_debug("%s: failed to add protocol node", __func__);
+ return (-1);
+ }
+ c++;
+ }
+
+ if (!c)
+ return (0);
+
+ DPRINTF("%s: %s %d received %d nodes for protocol %s", __func__,
+ env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
+ c, proto->name);
+
+ return (0);
+}
+
+int
+config_setrelay(struct relayd *env, struct relay *rlay)
+{
+ struct privsep *ps = env->sc_ps;
+ int id;
+ int fd, n, m;
+ struct iovec iov[4];
+ size_t c;
+
+ /* opens listening sockets etc. */
+ if (relay_privinit(rlay) == -1)
+ return (-1);
+
+ for (id = 0; id < PROC_MAX; id++) {
+ if ((ps->ps_what[id] & CONFIG_RELAYS) == 0 ||
+ id == privsep_process)
+ continue;
+
+ DPRINTF("%s: sending relay %s to %s fd %d", __func__,
+ rlay->rl_conf.name, ps->ps_title[id], rlay->rl_s);
+
+ c = 0;
+ iov[c].iov_base = &rlay->rl_conf;
+ iov[c++].iov_len = sizeof(rlay->rl_conf);
+ if (rlay->rl_conf.ssl_cert_len) {
+ iov[c].iov_base = rlay->rl_ssl_cert;
+ iov[c++].iov_len = rlay->rl_conf.ssl_cert_len;
+ }
+ if (rlay->rl_conf.ssl_key_len) {
+ iov[c].iov_base = rlay->rl_ssl_key;
+ iov[c++].iov_len = rlay->rl_conf.ssl_key_len;
+ }
+ if (rlay->rl_conf.ssl_ca_len) {
+ iov[c].iov_base = rlay->rl_ssl_ca;
+ iov[c++].iov_len = rlay->rl_conf.ssl_ca_len;
+ }
+
+ if (id == PROC_RELAY) {
+ /* XXX imsg code will close the fd after 1st call */
+ n = -1;
+ proc_range(ps, id, &n, &m);
+ for (n = 0; n < m; n++) {
+ if ((fd = dup(rlay->rl_s)) == -1)
+ return (-1);
+ proc_composev_imsg(ps, id, n,
+ IMSG_CFG_RELAY, fd, iov, c);
+ }
+ } else {
+ proc_composev_imsg(ps, id, -1, IMSG_CFG_RELAY, -1,
+ iov, c);
+ }
+ }
+
+ close(rlay->rl_s);
+ rlay->rl_s = -1;
+
+ return (0);
+}
+
+int
+config_getrelay(struct relayd *env, struct imsg *imsg)
+{
+ struct privsep *ps = env->sc_ps;
+ struct relay *rlay;
+ u_int8_t *p = imsg->data;
+ size_t s;
+
+ if ((rlay = calloc(1, sizeof(*rlay))) == NULL)
+ return (-1);
+
+ IMSG_SIZE_CHECK(imsg, &rlay->rl_conf);
+ memcpy(&rlay->rl_conf, p, sizeof(rlay->rl_conf));
+ s = sizeof(rlay->rl_conf);
+
+ rlay->rl_s = imsg->fd;
+
+ if (ps->ps_what[privsep_process] & CONFIG_PROTOS) {
+ if (rlay->rl_conf.proto == EMPTY_ID)
+ rlay->rl_proto = &env->sc_proto_default;
+ else if ((rlay->rl_proto =
+ proto_find(env, rlay->rl_conf.proto)) == NULL) {
+ log_debug("%s: unknown protocol", __func__);
+ goto fail;
+ }
+ }
+
+ if (rlay->rl_conf.dsttable != EMPTY_ID &&
+ (rlay->rl_dsttable = table_find(env,
+ rlay->rl_conf.dsttable)) == NULL) {
+ log_debug("%s: unknown table", __func__);
+ goto fail;
+ }
+
+ rlay->rl_backuptable = &env->sc_empty_table;
+ if (rlay->rl_conf.backuptable != EMPTY_ID &&
+ (rlay->rl_backuptable = table_find(env,
+ rlay->rl_conf.backuptable)) == NULL) {
+ log_debug("%s: unknown backup table", __func__);
+ goto fail;
+ }
+
+ if ((u_int)(IMSG_DATA_SIZE(imsg) - s) <
+ (rlay->rl_conf.ssl_cert_len +
+ rlay->rl_conf.ssl_key_len +
+ rlay->rl_conf.ssl_ca_len)) {
+ log_debug("%s: invalid message length", __func__);
+ goto fail;
+ }
+
+ if (rlay->rl_conf.ssl_cert_len) {
+ if ((rlay->rl_ssl_cert = get_data(p + s,
+ rlay->rl_conf.ssl_cert_len)) == NULL)
+ goto fail;
+ s += rlay->rl_conf.ssl_cert_len;
+ }
+ if (rlay->rl_conf.ssl_key_len) {
+ if ((rlay->rl_ssl_key = get_data(p + s,
+ rlay->rl_conf.ssl_key_len)) == NULL)
+ goto fail;
+ s += rlay->rl_conf.ssl_key_len;
+ }
+ if (rlay->rl_conf.ssl_ca_len) {
+ if ((rlay->rl_ssl_ca = get_data(p + s,
+ rlay->rl_conf.ssl_ca_len)) == NULL)
+ goto fail;
+ s += rlay->rl_conf.ssl_ca_len;
+ }
+
+ TAILQ_INSERT_TAIL(env->sc_relays, rlay, rl_entry);
+
+ env->sc_relaycount++;
+
+ DPRINTF("%s: %s %d received relay %s", __func__,
+ ps->ps_title[privsep_process], ps->ps_instance,
+ rlay->rl_conf.name);
+
+ return (0);
+
+ fail:
+ if (rlay->rl_ssl_cert)
+ free(rlay->rl_ssl_cert);
+ if (rlay->rl_ssl_key)
+ free(rlay->rl_ssl_key);
+ if (rlay->rl_ssl_ca)
+ free(rlay->rl_ssl_ca);
+ close(rlay->rl_s);
+ free(rlay);
+ return (-1);
+}
diff --git a/usr.sbin/relayd/control.c b/usr.sbin/relayd/control.c
index 9c9a3cc02e4..7397c34cc01 100644
--- a/usr.sbin/relayd/control.c
+++ b/usr.sbin/relayd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.38 2011/05/09 12:08:47 reyk Exp $ */
+/* $OpenBSD: control.c,v 1.39 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -327,8 +327,8 @@ control_dispatch_imsg(int fd, short event, void *arg)
}
break;
case IMSG_CTL_SHUTDOWN:
- imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
- 0, 0, -1, NULL, 0);
+ case IMSG_CTL_RELOAD:
+ proc_forward_imsg(env->sc_ps, &imsg, PROC_PARENT, -1);
break;
case IMSG_CTL_POLL:
proc_compose_imsg(env->sc_ps, PROC_HCE, -1,
@@ -336,25 +336,6 @@ control_dispatch_imsg(int fd, short event, void *arg)
imsg_compose_event(&c->iev, IMSG_CTL_OK,
0, 0, -1, NULL, 0);
break;
- case IMSG_CTL_RELOAD:
- if (env->sc_prefork_relay > 0) {
- imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
- 0, 0, -1, NULL, 0);
- break;
- }
- 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.
- *
- * so in this case, the reply relayctl gets means
- * that the reload command has been set,
- * it doesn't say whether the command succeeded or not.
- */
- imsg_compose_event(&c->iev, IMSG_CTL_OK,
- 0, 0, -1, NULL, 0);
- break;
case IMSG_CTL_NOTIFY:
if (c->flags & CTL_CONN_NOTIFY) {
log_debug("%s: "
@@ -371,8 +352,8 @@ control_dispatch_imsg(int fd, short event, void *arg)
memcpy(&verbose, imsg.data, 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_PARENT, -1);
+ proc_forward_imsg(env->sc_ps, &imsg, PROC_HCE, -1);
proc_forward_imsg(env->sc_ps, &imsg, PROC_RELAY, -1);
memcpy(imsg.data, &verbose, sizeof(verbose));
diff --git a/usr.sbin/relayd/hce.c b/usr.sbin/relayd/hce.c
index ab80166c4bb..147b272bfde 100644
--- a/usr.sbin/relayd/hce.c
+++ b/usr.sbin/relayd/hce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hce.c,v 1.59 2011/05/09 12:08:47 reyk Exp $ */
+/* $OpenBSD: hce.c,v 1.60 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -72,14 +72,15 @@ hce(struct privsep *ps, struct privsep_proc *p)
void
hce_init(struct privsep *ps, struct privsep_proc *p, void *arg)
{
- purge_config(env, PURGE_RDRS|PURGE_RELAYS|PURGE_PROTOS);
+ if (config_init(ps->ps_env) == -1)
+ fatal("failed to initialize configuration");
env->sc_id = getpid() & 0xffff;
/* Allow maximum available sockets for TCP checks */
socket_rlimit(-1);
- hce_setup_events();
+ snmp_init(env, PROC_PARENT);
}
void
@@ -88,18 +89,17 @@ hce_setup_events(void)
struct timeval tv;
struct table *table;
- snmp_init(env, PROC_PARENT);
-
- if (!TAILQ_EMPTY(env->sc_tables)) {
+ if (!(TAILQ_EMPTY(env->sc_tables) ||
+ event_initialized(&env->sc_ev))) {
evtimer_set(&env->sc_ev, hce_launch_checks, env);
bzero(&tv, sizeof(tv));
evtimer_add(&env->sc_ev, &tv);
}
if (env->sc_flags & F_SSL) {
- ssl_init(env);
TAILQ_FOREACH(table, env->sc_tables, entry) {
- if (!(table->conf.flags & F_SSL))
+ if (!(table->conf.flags & F_SSL) ||
+ table->ssl_ctx != NULL)
continue;
table->ssl_ctx = ssl_ctx_create(env);
}
@@ -116,8 +116,10 @@ hce_disable_events(void)
TAILQ_FOREACH(table, env->sc_tables, entry) {
TAILQ_FOREACH(host, &table->hosts, entry) {
host->he = HCE_ABORT;
- event_del(&host->cte.ev);
- close(host->cte.s);
+ if (event_initialized(&host->cte.ev)) {
+ event_del(&host->cte.ev);
+ close(host->cte.s);
+ }
}
}
if (env->sc_has_icmp) {
@@ -146,7 +148,11 @@ hce_launch_checks(int fd, short event, void *arg)
if ((host->flags & F_CHECK_DONE) == 0)
host->he = HCE_INTERVAL_TIMEOUT;
host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE);
- event_del(&host->cte.ev);
+ if (event_initialized(&host->cte.ev)) {
+ event_del(&host->cte.ev);
+ close(host->cte.s);
+ }
+ host->cte.s = -1;
}
}
@@ -331,9 +337,6 @@ int
hce_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
{
struct ctl_script scr;
- size_t len;
- static struct table *table = NULL;
- struct host *host, *parent;
switch (imsg->hdr.type) {
case IMSG_SCRIPT:
@@ -341,47 +344,22 @@ hce_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
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);
+ case IMSG_CFG_TABLE:
+ config_gettable(env, imsg);
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);
+ case IMSG_CFG_HOST:
+ config_gethost(env, imsg);
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);
- }
+ case IMSG_SNMPSOCK:
+ snmp_getsock(env, imsg);
break;
- case IMSG_RECONF_END:
- log_warnx("%s: configuration reloaded", __func__);
+ case IMSG_CFG_DONE:
+ config_getcfg(env, imsg);
hce_setup_events();
break;
+ case IMSG_CTL_RESET:
+ config_getreset(env, imsg);
+ break;
default:
return (-1);
}
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y
index c03b54c4264..c3a5b5b5177 100644
--- a/usr.sbin/relayd/parse.y
+++ b/usr.sbin/relayd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.155 2011/05/09 12:08:47 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.156 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -28,6 +28,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/queue.h>
+#include <sys/hash.h>
#include <net/if.h>
#include <net/pfvar.h>
@@ -86,6 +87,7 @@ char *symget(const char *);
struct relayd *conf = NULL;
static int errors = 0;
+static int loadcfg = 0;
objid_t last_rdr_id = 0;
objid_t last_table_id = 0;
objid_t last_host_id = 0;
@@ -114,6 +116,7 @@ int host_if(const char *, struct addresslist *,
int, struct portrange *, const char *, int);
int host(const char *, struct addresslist *,
int, struct portrange *, const char *, int);
+void host_free(struct addresslist *);
struct table *table_inherit(struct table *);
struct relay *relay_inherit(struct relay *, struct relay *);
@@ -323,28 +326,36 @@ varset : STRING '=' STRING {
sendbuf : NOTHING {
table->sendbuf = NULL;
- table->sendbuf_len = 0;
}
| STRING {
table->sendbuf = strdup($1);
if (table->sendbuf == NULL)
fatal("out of memory");
- table->sendbuf_len = strlen(table->sendbuf);
free($1);
}
;
main : INTERVAL NUMBER {
+ if (loadcfg)
+ break;
if ((conf->sc_interval.tv_sec = $2) < 0) {
yyerror("invalid interval: %d", $2);
YYERROR;
}
}
- | LOG loglevel { conf->sc_opts |= $2; }
+ | LOG loglevel {
+ if (loadcfg)
+ break;
+ conf->sc_opts |= $2;
+ }
| TIMEOUT timeout {
+ if (loadcfg)
+ break;
bcopy(&$2, &conf->sc_timeout, sizeof(struct timeval));
}
| PREFORK NUMBER {
+ if (loadcfg)
+ break;
if ($2 <= 0 || $2 > RELAY_MAXPROC) {
yyerror("invalid number of preforked "
"relays: %d", $2);
@@ -353,6 +364,8 @@ main : INTERVAL NUMBER {
conf->sc_prefork_relay = $2;
}
| DEMOTE STRING {
+ if (loadcfg)
+ break;
conf->sc_flags |= F_DEMOTE;
if (strlcpy(conf->sc_demote_group, $2,
sizeof(conf->sc_demote_group))
@@ -368,7 +381,11 @@ main : INTERVAL NUMBER {
YYERROR;
}
}
- | SEND TRAP { conf->sc_flags |= F_TRAP; }
+ | SEND TRAP {
+ if (loadcfg)
+ break;
+ conf->sc_flags |= F_TRAP;
+ }
;
loglevel : UPDATES { $$ = RELAYD_OPT_LOGUPDATE; }
@@ -379,6 +396,12 @@ rdr : REDIRECT STRING {
struct rdr *srv;
conf->sc_flags |= F_NEEDPF;
+
+ if (!loadcfg) {
+ free($2);
+ YYACCEPT;
+ }
+
TAILQ_FOREACH(srv, conf->sc_rdrs, entry)
if (!strcmp(srv->conf.name, $2))
break;
@@ -544,6 +567,11 @@ table : '<' STRING '>' {
tabledef : TABLE table {
struct table *tb;
+ if (!loadcfg) {
+ free($2);
+ YYACCEPT;
+ }
+
TAILQ_FOREACH(tb, conf->sc_tables, entry)
if (!strcmp(tb->conf.name, $2))
break;
@@ -701,7 +729,6 @@ tablecheck : ICMP { table->conf.check = CHECK_ICMP; }
free($3);
if (table->sendbuf == NULL)
fatal("out of memory");
- table->sendbuf_len = strlen(table->sendbuf);
}
| http_type STRING hostname digest {
if ($1) {
@@ -717,7 +744,6 @@ tablecheck : ICMP { table->conf.check = CHECK_ICMP; }
free($3);
if (table->sendbuf == NULL)
fatal("out of memory");
- table->sendbuf_len = strlen(table->sendbuf);
(void)strlcpy(table->conf.digest, $4.digest,
sizeof(table->conf.digest));
table->conf.digest_type = $4.type;
@@ -773,6 +799,11 @@ digest : DIGEST STRING
proto : relay_proto PROTO STRING {
struct protocol *p;
+ if (!loadcfg) {
+ free($3);
+ YYACCEPT;
+ }
+
if (strcmp($3, "default") == 0) {
p = &conf->sc_proto_default;
} else {
@@ -936,12 +967,14 @@ sslflags : SESSION CACHE sslcache { proto->cache = $3; }
free($2);
}
| CA FILENAME STRING {
- if (proto->sslca != NULL) {
- yyerror("sslca already specified");
+ if (strlcpy(proto->sslca, $3,
+ sizeof(proto->sslca)) >=
+ sizeof(proto->sslca)) {
+ yyerror("sslca truncated");
free($3);
YYERROR;
}
- proto->sslca = $3;
+ free($3);
}
| NO flag { proto->sslflags &= ~($2); }
| flag { proto->sslflags |= $1; }
@@ -1182,6 +1215,11 @@ sslcache : NUMBER {
relay : RELAY STRING {
struct relay *r;
+ if (!loadcfg) {
+ free($2);
+ YYACCEPT;
+ }
+
TAILQ_FOREACH(r, conf->sc_relays, rl_entry)
if (!strcmp(r->rl_conf.name, $2))
break;
@@ -1302,6 +1340,7 @@ relayoptsl : LISTEN ON STRING port optssl {
conf->sc_flags |= F_SSL;
}
tableport = h->port.val[0];
+ host_free(&al);
}
| forwardmode optsslclient TO forwardspec interface dstaf {
rlay->rl_conf.fwdmode = $1;
@@ -1384,6 +1423,7 @@ forwardspec : STRING port retry {
sizeof(rlay->rl_conf.dstss));
rlay->rl_conf.dstport = h->port.val[0];
rlay->rl_conf.dstretry = $3;
+ host_free(&al);
}
| NAT LOOKUP retry {
conf->sc_flags |= F_NEEDPF;
@@ -1398,7 +1438,6 @@ forwardspec : STRING port retry {
| tablespec {
if (rlay->rl_backuptable) {
yyerror("only one backup table is allowed");
- purge_table(conf->sc_tables, $1);
YYERROR;
}
if (rlay->rl_dsttable) {
@@ -1423,6 +1462,11 @@ dstmode : /* empty */ { $$ = RELAY_DSTMODE_DEFAULT; }
router : ROUTER STRING {
struct router *rt = NULL;
+ if (!loadcfg) {
+ free($2);
+ YYACCEPT;
+ }
+
conf->sc_flags |= F_NEEDRT;
TAILQ_FOREACH(rt, conf->sc_rts, rt_entry)
if (!strcmp(rt->rt_conf.name, $2))
@@ -1478,16 +1522,18 @@ routeopts_l : routeopts_l routeoptsl nl
routeoptsl : ROUTE address '/' NUMBER {
struct netroute *nr;
- if (router->rt_af == AF_UNSPEC)
- router->rt_af = $2.ss.ss_family;
- else if (router->rt_af != $2.ss.ss_family) {
+ if (router->rt_conf.af == AF_UNSPEC)
+ router->rt_conf.af = $2.ss.ss_family;
+ else if (router->rt_conf.af != $2.ss.ss_family) {
yyerror("router %s address family mismatch",
router->rt_conf.name);
YYERROR;
}
- if ((router->rt_af == AF_INET && ($4 > 32 || $4 < 0)) ||
- (router->rt_af == AF_INET6 && ($4 > 128 || $4 < 0))) {
+ if ((router->rt_conf.af == AF_INET &&
+ ($4 > 32 || $4 < 0)) ||
+ (router->rt_conf.af == AF_INET6 &&
+ ($4 > 128 || $4 < 0))) {
yyerror("invalid prefixlen %d", $4);
YYERROR;
}
@@ -1649,7 +1695,7 @@ hostflags : RETRY NUMBER {
;
address : STRING {
- struct address *a;
+ struct address *h;
struct addresslist al;
if (strlcpy($$.name, $1,
@@ -1666,9 +1712,9 @@ address : STRING {
YYERROR;
}
free($1);
- a = TAILQ_FIRST(&al);
- memcpy(&$$.ss, &a->ss, sizeof($$.ss));
- free(a);
+ h = TAILQ_FIRST(&al);
+ memcpy(&$$.ss, &h->ss, sizeof($$.ss));
+ host_free(&al);
}
;
@@ -2143,38 +2189,56 @@ popfile(void)
return (file ? 0 : EOF);
}
-struct relayd *
-parse_config(const char *filename, int opts)
+int
+parse_config(const char *filename, struct relayd *x_conf)
{
struct sym *sym, *next;
- struct table *nexttb;
- struct host *h, *ph;
- if ((conf = calloc(1, sizeof(*conf))) == NULL ||
- (conf->sc_tables = calloc(1, sizeof(*conf->sc_tables))) == NULL ||
- (conf->sc_relays = calloc(1, sizeof(*conf->sc_relays))) == NULL ||
- (conf->sc_protos = calloc(1, sizeof(*conf->sc_protos))) == NULL ||
- (conf->sc_routes = calloc(1, sizeof(*conf->sc_routes))) == NULL ||
- (conf->sc_rts = calloc(1, sizeof(*conf->sc_rts))) == NULL ||
- (conf->sc_rdrs = calloc(1, sizeof(*conf->sc_rdrs))) == NULL) {
- if (conf != NULL) {
- if (conf->sc_tables != NULL)
- free(conf->sc_tables);
- if (conf->sc_relays != NULL)
- free(conf->sc_relays);
- if (conf->sc_protos != NULL)
- free(conf->sc_protos);
- if (conf->sc_rdrs != NULL)
- free(conf->sc_rdrs);
- if (conf->sc_rts != NULL)
- free(conf->sc_rts);
- free(conf);
- }
- log_warn("%s: cannot allocate memory", __func__);
- return (NULL);
+ conf = x_conf;
+ if (config_init(conf) == -1) {
+ log_warn("%s: cannot initialize configuration", __func__);
+ return (-1);
}
errors = 0;
+
+ if ((file = pushfile(filename, 0)) == NULL)
+ return (-1);
+
+ topfile = file;
+ setservent(1);
+
+ yyparse();
+ errors = file->errors;
+ popfile();
+
+ endservent();
+ endprotoent();
+
+ /* Free macros */
+ for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
+ next = TAILQ_NEXT(sym, entry);
+ if (!sym->persist) {
+ free(sym->nam);
+ free(sym->val);
+ TAILQ_REMOVE(&symhead, sym, entry);
+ free(sym);
+ }
+ }
+
+ return (errors ? -1 : 0);
+}
+
+int
+load_config(const char *filename, struct relayd *x_conf)
+{
+ struct sym *sym, *next;
+ struct table *nexttb;
+ struct host *h, *ph;
+
+ conf = x_conf;
+ loadcfg = 1;
+ errors = 0;
last_host_id = last_table_id = last_rdr_id = last_proto_id =
last_relay_id = last_rt_id = last_nr_id = 0;
@@ -2184,46 +2248,9 @@ parse_config(const char *filename, int opts)
proto = NULL;
router = NULL;
- TAILQ_INIT(conf->sc_rdrs);
- TAILQ_INIT(conf->sc_tables);
- TAILQ_INIT(conf->sc_protos);
- TAILQ_INIT(conf->sc_relays);
- TAILQ_INIT(conf->sc_rts);
- TAILQ_INIT(conf->sc_routes);
-
- memset(&conf->sc_empty_table, 0, sizeof(conf->sc_empty_table));
- conf->sc_empty_table.conf.id = EMPTY_TABLE;
- conf->sc_empty_table.conf.flags |= F_DISABLE;
- (void)strlcpy(conf->sc_empty_table.conf.name, "empty",
- sizeof(conf->sc_empty_table.conf.name));
-
- bzero(&conf->sc_proto_default, sizeof(conf->sc_proto_default));
- conf->sc_proto_default.flags = F_USED;
- conf->sc_proto_default.cache = RELAY_CACHESIZE;
- conf->sc_proto_default.tcpflags = TCPFLAG_DEFAULT;
- conf->sc_proto_default.tcpbacklog = RELAY_BACKLOG;
- conf->sc_proto_default.sslflags = SSLFLAG_DEFAULT;
- (void)strlcpy(conf->sc_proto_default.sslciphers, SSLCIPHERS_DEFAULT,
- sizeof(conf->sc_proto_default.sslciphers));
- conf->sc_proto_default.type = RELAY_PROTO_TCP;
- (void)strlcpy(conf->sc_proto_default.name, "default",
- sizeof(conf->sc_proto_default.name));
- RB_INIT(&conf->sc_proto_default.request_tree);
- RB_INIT(&conf->sc_proto_default.response_tree);
-
- conf->sc_timeout.tv_sec = CHECK_TIMEOUT / 1000;
- conf->sc_timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
- conf->sc_interval.tv_sec = CHECK_INTERVAL;
- conf->sc_interval.tv_usec = 0;
- conf->sc_prefork_relay = RELAY_NUMPROC;
- conf->sc_statinterval.tv_sec = RELAY_STATINTERVAL;
- conf->sc_opts = opts;
- conf->sc_confpath = filename;
-
- if ((file = pushfile(filename, 0)) == NULL) {
- free(conf);
- return (NULL);
- }
+ if ((file = pushfile(filename, 0)) == NULL)
+ return (-1);
+
topfile = file;
setservent(1);
@@ -2322,12 +2349,7 @@ parse_config(const char *filename, int opts)
}
}
- if (errors) {
- free(conf);
- return (NULL);
- }
-
- return (conf);
+ return (errors ? -1 : 0);
}
int
@@ -2494,6 +2516,7 @@ host_dns(const char *s, struct addresslist *al, int max,
log_warnx("%s: interface name truncated",
__func__);
freeaddrinfo(res0);
+ free(h);
return (-1);
}
if (ipproto != -1)
@@ -2615,6 +2638,7 @@ host(const char *s, struct addresslist *al, int max,
sizeof(h->ifname)) {
log_warnx("%s: interface name truncated",
__func__);
+ free(h);
return (-1);
}
}
@@ -2628,6 +2652,17 @@ host(const char *s, struct addresslist *al, int max,
return (host_dns(s, al, max, port, ifname, ipproto));
}
+void
+host_free(struct addresslist *al)
+{
+ struct address *h;
+
+ while ((h = TAILQ_FIRST(al)) != NULL) {
+ TAILQ_REMOVE(al, h, entry);
+ free(h);
+ }
+}
+
struct table *
table_inherit(struct table *tb)
{
@@ -2638,23 +2673,21 @@ table_inherit(struct table *tb)
/* Get the table or table template */
if ((dsttb = table_findbyname(conf, tb->conf.name)) == NULL) {
yyerror("unknown table %s", tb->conf.name);
- purge_table(NULL, tb);
- return (NULL);
+ goto fail;
}
if (dsttb->conf.port != 0)
fatal("invalid table"); /* should not happen */
if (tb->conf.port == 0) {
yyerror("invalid port");
- purge_table(NULL, tb);
- return (NULL);
+ goto fail;
}
/* Check if a matching table already exists */
if (snprintf(pname, sizeof(pname), "%s:%u",
tb->conf.name, ntohs(tb->conf.port)) >= (int)sizeof(pname)) {
yyerror("invalid table name");
- return (NULL);
+ goto fail;
}
(void)strlcpy(tb->conf.name, pname, sizeof(tb->conf.name));
if ((oldtb = table_findbyconf(conf, tb)) != NULL) {
@@ -2666,8 +2699,7 @@ table_inherit(struct table *tb)
tb->conf.id = ++last_table_id;
if (last_table_id == INT_MAX) {
yyerror("too many tables defined");
- purge_table(NULL, tb);
- return (NULL);
+ goto fail;
}
tb->conf.flags |= dsttb->conf.flags;
@@ -2684,8 +2716,7 @@ table_inherit(struct table *tb)
h->conf.id = ++last_host_id;
if (last_host_id == INT_MAX) {
yyerror("too many hosts defined");
- purge_table(NULL, tb);
- return (NULL);
+ goto fail;
}
h->conf.tableid = tb->conf.id;
h->tablename = tb->conf.name;
@@ -2697,6 +2728,10 @@ table_inherit(struct table *tb)
TAILQ_INSERT_TAIL(conf->sc_tables, tb, entry);
return (tb);
+
+ fail:
+ purge_table(NULL, tb);
+ return (NULL);
}
struct relay *
diff --git a/usr.sbin/relayd/pfe.c b/usr.sbin/relayd/pfe.c
index ba3a6260390..4ed78c9f88d 100644
--- a/usr.sbin/relayd/pfe.c
+++ b/usr.sbin/relayd/pfe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfe.c,v 1.68 2011/05/09 12:08:47 reyk Exp $ */
+/* $OpenBSD: pfe.c,v 1.69 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -46,7 +46,7 @@ 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 *);
-static struct relayd *env = NULL;
+static struct relayd *env = NULL;
static struct privsep_proc procs[] = {
{ "parent", PROC_PARENT, pfe_dispatch_parent },
@@ -59,25 +59,23 @@ pfe(struct privsep *ps, struct privsep_proc *p)
{
env = ps->ps_env;
- init_filter(env);
- init_tables(env);
-
return (proc_run(ps, p, procs, nitems(procs), pfe_init, NULL));
}
void
pfe_init(struct privsep *ps, struct privsep_proc *p, void *arg)
{
+ if (config_init(ps->ps_env) == -1)
+ fatal("failed to initialize configuration");
+
p->p_shutdown = pfe_shutdown;
- purge_config(env, PURGE_PROTOS);
- pfe_setup_events();
- pfe_sync();
}
void
pfe_shutdown(void)
{
flush_rulesets(env);
+ config_purge(env, CONFIG_ALL);
}
void
@@ -86,9 +84,11 @@ pfe_setup_events(void)
struct timeval tv;
/* Schedule statistics timer */
- evtimer_set(&env->sc_statev, pfe_statistics, NULL);
- bcopy(&env->sc_statinterval, &tv, sizeof(tv));
- evtimer_add(&env->sc_statev, &tv);
+ if (!event_initialized(&env->sc_statev)) {
+ evtimer_set(&env->sc_statev, pfe_statistics, NULL);
+ bcopy(&env->sc_statinterval, &tv, sizeof(tv));
+ evtimer_add(&env->sc_statev, &tv);
+ }
}
void
@@ -172,88 +172,43 @@ pfe_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
int
pfe_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
{
- static struct rdr *rdr = NULL;
- static struct table *table = NULL;
- struct host *host, *parent;
- struct address *virt;
-
switch (imsg->hdr.type) {
- case IMSG_RECONF:
- IMSG_SIZE_CHECK(imsg, env);
-
- log_debug("%s: reloading configuration", __func__);
-
- 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);
+ case IMSG_CFG_TABLE:
+ config_gettable(env, imsg);
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);
+ case IMSG_CFG_HOST:
+ config_gethost(env, imsg);
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);
- }
+ case IMSG_CFG_RDR:
+ config_getrdr(env, 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);
+ case IMSG_CFG_VIRT:
+ config_getvirt(env, imsg);
+ break;
+ case IMSG_CFG_ROUTER:
+ config_getrt(env, imsg);
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);
+ case IMSG_CFG_ROUTE:
+ config_getroute(env, imsg);
break;
- case IMSG_RECONF_END:
- log_warnx("%s: configuration reloaded", __func__);
+ case IMSG_CFG_PROTO:
+ config_getproto(env, imsg);
+ break;
+ case IMSG_CFG_PROTONODE:
+ break;
+ case IMSG_CFG_RELAY:
+ config_getrelay(env, imsg);
+ break;
+ case IMSG_CFG_DONE:
+ config_getcfg(env, imsg);
+ init_filter(env, imsg->fd);
init_tables(env);
pfe_setup_events();
pfe_sync();
break;
+ case IMSG_CTL_RESET:
+ config_getreset(env, imsg);
+ break;
default:
return (-1);
}
@@ -741,6 +696,9 @@ pfe_sync(void)
}
TAILQ_FOREACH(table, env->sc_tables, entry) {
+ if (table->conf.check == CHECK_NOCHECK)
+ continue;
+
/*
* clean up change flag.
*/
diff --git a/usr.sbin/relayd/pfe_filter.c b/usr.sbin/relayd/pfe_filter.c
index 2fa53cdd3b8..02a528999b5 100644
--- a/usr.sbin/relayd/pfe_filter.c
+++ b/usr.sbin/relayd/pfe_filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfe_filter.c,v 1.46 2011/05/05 12:01:44 reyk Exp $ */
+/* $OpenBSD: pfe_filter.c,v 1.47 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -33,6 +33,7 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
#include <openssl/ssl.h>
@@ -53,17 +54,21 @@ void kill_tables(struct relayd *);
int kill_srcnodes(struct relayd *, struct table *);
void
-init_filter(struct relayd *env)
+init_filter(struct relayd *env, int s)
{
struct pf_status status;
if (!(env->sc_flags & F_NEEDPF))
return;
- if ((env->sc_pf = calloc(1, sizeof(*(env->sc_pf)))) == NULL)
- fatal("calloc");
- if ((env->sc_pf->dev = open(PF_SOCKET, O_RDWR)) == -1)
- fatal("init_filter: cannot open pf socket");
+ if (s == -1)
+ fatalx("init_filter: invalid socket");
+ if (env->sc_pf == NULL) {
+ if ((env->sc_pf = calloc(1, sizeof(*(env->sc_pf)))) == NULL)
+ fatal("calloc");
+ } else
+ close(env->sc_pf->dev);
+ env->sc_pf->dev = s;
if (ioctl(env->sc_pf->dev, DIOCGETSTATUS, &status) == -1)
fatal("init_filter: DIOCGETSTATUS");
if (!status.running)
@@ -366,7 +371,7 @@ sync_ruleset(struct relayd *env, struct rdr *rdr, int enable)
char anchor[PF_ANCHOR_NAME_SIZE];
struct table *t = rdr->table;
- if (!(env->sc_flags & F_NEEDPF))
+ if ((env->sc_flags & F_NEEDPF) == 0)
return;
bzero(anchor, sizeof(anchor));
diff --git a/usr.sbin/relayd/pfe_route.c b/usr.sbin/relayd/pfe_route.c
index 0fae0dfd0a0..e0b5066eb40 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.4 2011/05/09 12:08:47 reyk Exp $ */
+/* $OpenBSD: pfe_route.c,v 1.5 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2009 Reyk Floeter <reyk@openbsd.org>
@@ -96,9 +96,10 @@ sync_routes(struct relayd *env, struct router *rt)
HOST_ISUP(host->up) ? "up" : "down",
host->conf.priority);
- crt.id = nr->nr_conf.id;
- crt.hostid = host->conf.id;
crt.up = host->up;
+ memcpy(&crt.nr, &nr->nr_conf, sizeof(nr->nr_conf));
+ memcpy(&crt.host, &host->conf, sizeof(host->conf));
+ memcpy(&crt.rt, &rt->rt_conf, sizeof(rt->rt_conf));
proc_compose_imsg(env->sc_ps, PROC_PARENT, -1,
IMSG_RTMSG, -1, &crt, sizeof(crt));
@@ -115,19 +116,11 @@ pfe_route(struct relayd *env, struct ctl_netroute *crt)
struct sockaddr_in *s4;
struct sockaddr_in6 *s6;
size_t len = 0;
- struct netroute *nr;
- struct host *host;
char *gwname;
int i = 0;
- if ((nr = route_find(env, crt->id)) == NULL ||
- (host = host_find(env, crt->hostid)) == NULL) {
- log_debug("%s: invalid host or route id", __func__);
- return (-1);
- }
-
- gw = &host->conf.ss;
- gwname = host->conf.name;
+ gw = &crt->host.ss;
+ gwname = crt->host.name;
bzero(&rm, sizeof(rm));
bzero(&sr, sizeof(sr));
@@ -138,18 +131,18 @@ pfe_route(struct relayd *env, struct ctl_netroute *crt)
rm.rm_hdr.rtm_flags = RTF_STATIC | RTF_GATEWAY | RTF_MPATH;
rm.rm_hdr.rtm_seq = env->sc_rtseq++;
rm.rm_hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
- rm.rm_hdr.rtm_tableid = nr->nr_router->rt_conf.rtable;
- rm.rm_hdr.rtm_priority = host->conf.priority;
+ rm.rm_hdr.rtm_tableid = crt->rt.rtable;
+ rm.rm_hdr.rtm_priority = crt->host.priority;
- if (strlen(nr->nr_router->rt_conf.label)) {
+ if (strlen(crt->rt.label)) {
rm.rm_hdr.rtm_addrs |= RTA_LABEL;
sr.sr_len = sizeof(sr);
if (snprintf(sr.sr_label, sizeof(sr.sr_label),
- "%s", nr->nr_router->rt_conf.label) == -1)
+ "%s", crt->rt.label) == -1)
goto bad;
}
- if (nr->nr_conf.ss.ss_family == AF_INET) {
+ if (crt->nr.ss.ss_family == AF_INET) {
rm.rm_hdr.rtm_msglen = len =
sizeof(rm.rm_hdr) + sizeof(rm.rm_u.u4);
@@ -159,7 +152,7 @@ pfe_route(struct relayd *env, struct ctl_netroute *crt)
s4->sin_family = AF_INET;
s4->sin_len = sizeof(rm.rm_u.u4.rm_dst);
s4->sin_addr.s_addr =
- ((struct sockaddr_in *)&nr->nr_conf.ss)->sin_addr.s_addr;
+ ((struct sockaddr_in *)&crt->nr.ss)->sin_addr.s_addr;
s4 = &rm.rm_u.u4.rm_gateway;
s4->sin_family = AF_INET;
@@ -171,19 +164,19 @@ pfe_route(struct relayd *env, struct ctl_netroute *crt)
s4 = &rm.rm_u.u4.rm_netmask;
s4->sin_family = AF_INET;
s4->sin_len = sizeof(rm.rm_u.u4.rm_netmask);
- if (nr->nr_conf.prefixlen)
+ if (crt->nr.prefixlen)
s4->sin_addr.s_addr =
- htonl(0xffffffff << (32 - nr->nr_conf.prefixlen));
- else if (nr->nr_conf.prefixlen < 0)
+ htonl(0xffffffff << (32 - crt->nr.prefixlen));
+ else if (crt->nr.prefixlen < 0)
rm.rm_hdr.rtm_flags |= RTF_HOST;
- } else if (nr->nr_conf.ss.ss_family == AF_INET6) {
+ } else if (crt->nr.ss.ss_family == AF_INET6) {
rm.rm_hdr.rtm_msglen = len =
sizeof(rm.rm_hdr) + sizeof(rm.rm_u.u6);
bcopy(&sr, &rm.rm_u.u6.rm_label, sizeof(sr));
s6 = &rm.rm_u.u6.rm_dst;
- bcopy(((struct sockaddr_in6 *)&nr->nr_conf.ss),
+ bcopy(((struct sockaddr_in6 *)&crt->nr.ss),
s6, sizeof(*s6));
s6->sin6_family = AF_INET6;
s6->sin6_len = sizeof(*s6);
@@ -197,14 +190,14 @@ pfe_route(struct relayd *env, struct ctl_netroute *crt)
s6 = &rm.rm_u.u6.rm_netmask;
s6->sin6_family = AF_INET6;
s6->sin6_len = sizeof(*s6);
- if (nr->nr_conf.prefixlen) {
- for (i = 0; i < nr->nr_conf.prefixlen / 8; i++)
+ if (crt->nr.prefixlen) {
+ for (i = 0; i < crt->nr.prefixlen / 8; i++)
s6->sin6_addr.s6_addr[i] = 0xff;
- i = nr->nr_conf.prefixlen % 8;
+ i = crt->nr.prefixlen % 8;
if (i)
- s6->sin6_addr.s6_addr[nr->nr_conf.prefixlen
+ s6->sin6_addr.s6_addr[crt->nr.prefixlen
/ 8] = 0xff00 >> i;
- } else if (nr->nr_conf.prefixlen < 0)
+ } else if (crt->nr.prefixlen < 0)
rm.rm_hdr.rtm_flags |= RTF_HOST;
} else
fatal("pfe_route: invalid address family");
diff --git a/usr.sbin/relayd/proc.c b/usr.sbin/relayd/proc.c
index 2bfb76a85be..7a0ddf0512f 100644
--- a/usr.sbin/relayd/proc.c
+++ b/usr.sbin/relayd/proc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.c,v 1.1 2011/05/09 12:09:58 reyk Exp $ */
+/* $OpenBSD: proc.c,v 1.2 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2010,2011 Reyk Floeter <reyk@openbsd.org>
@@ -105,6 +105,8 @@ proc_kill(struct privsep *ps)
do {
pid = waitpid(WAIT_ANY, NULL, 0);
} while (pid != -1 || (pid == -1 && errno == EINTR));
+
+ proc_clear(ps, 1);
}
void
@@ -134,6 +136,8 @@ proc_setup(struct privsep *ps)
fatal(NULL);
for (n = 0; n < count; n++) {
+ if (ps->ps_noaction)
+ continue;
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
sockpair) == -1)
fatal("socketpair");
@@ -175,7 +179,8 @@ proc_config(struct privsep *ps, struct privsep_proc *p, u_int nproc)
ps->ps_instance == instance)
continue;
- close(ps->ps_pipes[i][j][n]);
+ if (!ps->ps_noaction)
+ close(ps->ps_pipes[i][j][n]);
ps->ps_pipes[i][j][n] = -1;
}
}
@@ -221,6 +226,35 @@ proc_config(struct privsep *ps, struct privsep_proc *p, u_int nproc)
}
void
+proc_clear(struct privsep *ps, int purge)
+{
+ u_int src = privsep_process, dst, n, count;
+
+ if (ps == NULL)
+ return;
+
+ for (dst = 0; dst < PROC_MAX; dst++) {
+ if (src == dst || ps->ps_ievs[dst] == NULL)
+ continue;
+
+ count = ps->ps_instances[src] * ps->ps_instances[dst];
+
+ for (n = 0; n < count; n++) {
+ if (ps->ps_pipes[src][dst][n] == -1)
+ continue;
+ if (purge) {
+ event_del(&(ps->ps_ievs[dst][n].ev));
+ imsg_clear(&(ps->ps_ievs[dst][n].ibuf));
+ close(ps->ps_pipes[src][dst][n]);
+ } else
+ imsg_flush(&(ps->ps_ievs[dst][n].ibuf));
+ }
+ if (purge)
+ free(ps->ps_ievs[dst]);
+ }
+}
+
+void
proc_shutdown(struct privsep_proc *p)
{
struct privsep *ps = p->p_ps;
@@ -231,6 +265,8 @@ proc_shutdown(struct privsep_proc *p)
if (p->p_shutdown != NULL)
(*p->p_shutdown)();
+ proc_clear(ps, 1);
+
log_info("%s exiting, pid %d", p->p_title, getpid());
_exit(0);
@@ -268,6 +304,9 @@ proc_run(struct privsep *ps, struct privsep_proc *p,
u_int32_t seed[256];
u_int n;
+ if (ps->ps_noaction)
+ return (0);
+
switch (pid = fork()) {
case -1:
fatal("run_proc: cannot fork");
@@ -403,7 +442,7 @@ proc_dispatch(int fd, short event, void *arg)
if (n == 0)
break;
-#ifdef DEBUG
+#if DEBUG > 1
log_debug("%s: %s %d got imsg %d from %s %d",
__func__, title, ps->ps_instance + 1,
imsg.hdr.type, p->p_title, p->p_instance);
@@ -522,6 +561,7 @@ proc_compose_imsg(struct privsep *ps, enum privsep_procid id, int n,
if (imsg_compose_event(&ps->ps_ievs[id][n],
type, -1, 0, fd, data, datalen) == -1)
return (-1);
+
return (0);
}
diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c
index d458a4de7a6..00d50e93a79 100644
--- a/usr.sbin/relayd/relay.c
+++ b/usr.sbin/relayd/relay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay.c,v 1.136 2011/05/09 12:08:47 reyk Exp $ */
+/* $OpenBSD: relay.c,v 1.137 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -54,7 +54,6 @@ 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(struct privsep *, struct privsep_proc *p, void *);
@@ -146,26 +145,13 @@ pid_t
relay(struct privsep *ps, struct privsep_proc *p)
{
env = ps->ps_env;
-
- /* Need root privileges for relay initialization */
- relay_privinit();
-
return (proc_run(ps, p, procs, nitems(procs), relay_init, NULL));
}
void
relay_shutdown(void)
{
- struct rsession *con;
-
- struct relay *rlay;
- TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
- if (rlay->rl_conf.flags & F_DISABLE)
- continue;
- close(rlay->rl_s);
- while ((con = SPLAY_ROOT(&rlay->rl_sessions)) != NULL)
- relay_close(con, "shutdown");
- }
+ config_purge(env, CONFIG_ALL);
usleep(200); /* XXX relay needs to shutdown last */
}
@@ -250,7 +236,8 @@ relay_protodebug(struct relay *rlay)
const char *name;
int i;
- fprintf(stderr, "protocol %d: name %s\n", proto->id, proto->name);
+ fprintf(stderr, "protocol %d: name %s\n",
+ proto->id, proto->name);
fprintf(stderr, "\tflags: %s, relay flags: %s\n",
printb_flags(proto->flags, F_BITS),
printb_flags(rlay->rl_conf.flags, F_BITS));
@@ -304,106 +291,56 @@ relay_protodebug(struct relay *rlay)
}
}
-void
-relay_privinit(void)
+int
+relay_privinit(struct relay *rlay)
{
- struct relay *rlay;
extern int debug;
- if (env->sc_flags & (F_SSL|F_SSLCLIENT))
- ssl_init(env);
+ log_debug("%s: adding relay %s", __func__, rlay->rl_conf.name);
- TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
- log_debug("%s: adding relay %s", __func__, rlay->rl_conf.name);
+ if (debug)
+ relay_protodebug(rlay);
- if (debug)
- relay_protodebug(rlay);
+ switch (rlay->rl_proto->type) {
+ case RELAY_PROTO_DNS:
+ relay_udp_privinit(env, rlay);
+ break;
+ case RELAY_PROTO_TCP:
+ case RELAY_PROTO_HTTP:
+ /* Use defaults */
+ break;
+ }
- switch (rlay->rl_proto->type) {
- case RELAY_PROTO_DNS:
- relay_udp_privinit(env, rlay);
- break;
- case RELAY_PROTO_TCP:
- case RELAY_PROTO_HTTP:
- /* Use defaults */
- break;
- }
+ if (rlay->rl_conf.flags & F_UDP)
+ rlay->rl_s = relay_udp_bind(&rlay->rl_conf.ss,
+ rlay->rl_conf.port, rlay->rl_proto);
+ else
+ rlay->rl_s = relay_socket_listen(&rlay->rl_conf.ss,
+ rlay->rl_conf.port, rlay->rl_proto);
+ if (rlay->rl_s == -1)
+ return (-1);
- if (rlay->rl_conf.flags & F_UDP)
- rlay->rl_s = relay_udp_bind(&rlay->rl_conf.ss,
- rlay->rl_conf.port, rlay->rl_proto);
- else
- rlay->rl_s = relay_socket_listen(&rlay->rl_conf.ss,
- rlay->rl_conf.port, rlay->rl_proto);
- if (rlay->rl_s == -1)
- fatal("relay_privinit: failed to listen");
- }
+ return (0);
}
void
relay_init(struct privsep *ps, struct privsep_proc *p, void *arg)
{
- struct relay *rlay;
- struct host *host;
struct timeval tv;
+ if (config_init(ps->ps_env) == -1)
+ fatal("failed to initialize configuration");
+
/* 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);
- TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
- if ((rlay->rl_conf.flags & (F_SSL|F_SSLCLIENT)) &&
- (rlay->rl_ssl_ctx = relay_ssl_ctx_create(rlay)) == NULL)
- fatal("relay_init: failed to create SSL context");
-
- if (rlay->rl_dsttable != NULL) {
- switch (rlay->rl_conf.dstmode) {
- case RELAY_DSTMODE_ROUNDROBIN:
- rlay->rl_dstkey = 0;
- break;
- case RELAY_DSTMODE_LOADBALANCE:
- case RELAY_DSTMODE_HASH:
- rlay->rl_dstkey =
- hash32_str(rlay->rl_conf.name, HASHINIT);
- rlay->rl_dstkey =
- hash32_str(rlay->rl_dsttable->conf.name,
- rlay->rl_dstkey);
- break;
- }
- rlay->rl_dstnhosts = 0;
- TAILQ_FOREACH(host, &rlay->rl_dsttable->hosts, entry) {
- if (rlay->rl_dstnhosts >= RELAY_MAXHOSTS)
- fatal("relay_init: "
- "too many hosts in table");
- host->idx = rlay->rl_dstnhosts;
- rlay->rl_dsthost[rlay->rl_dstnhosts++] = host;
- }
- log_info("adding %d hosts from table %s%s",
- rlay->rl_dstnhosts, rlay->rl_dsttable->conf.name,
- rlay->rl_dsttable->conf.check ? "" : " (no check)");
- }
-
- switch (rlay->rl_proto->type) {
- case RELAY_PROTO_DNS:
- relay_udp_init(rlay);
- break;
- case RELAY_PROTO_TCP:
- case RELAY_PROTO_HTTP:
- /* Use defaults */
- break;
- }
- }
-
/* Schedule statistics timer */
evtimer_set(&env->sc_statev, relay_statistics, NULL);
bcopy(&env->sc_statinterval, &tv, sizeof(tv));
evtimer_add(&env->sc_statev, &tv);
-
- relay_launch();
}
void
@@ -474,10 +411,52 @@ relay_statistics(int fd, short events, void *arg)
void
relay_launch(void)
{
- struct relay *rlay;
void (*callback)(int, short, void *);
+ struct relay *rlay;
+ struct host *host;
TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
+ if ((rlay->rl_conf.flags & (F_SSL|F_SSLCLIENT)) &&
+ (rlay->rl_ssl_ctx = relay_ssl_ctx_create(rlay)) == NULL)
+ fatal("relay_init: failed to create SSL context");
+
+ if (rlay->rl_dsttable != NULL) {
+ switch (rlay->rl_conf.dstmode) {
+ case RELAY_DSTMODE_ROUNDROBIN:
+ rlay->rl_dstkey = 0;
+ break;
+ case RELAY_DSTMODE_LOADBALANCE:
+ case RELAY_DSTMODE_HASH:
+ rlay->rl_dstkey =
+ hash32_str(rlay->rl_conf.name, HASHINIT);
+ rlay->rl_dstkey =
+ hash32_str(rlay->rl_dsttable->conf.name,
+ rlay->rl_dstkey);
+ break;
+ }
+ rlay->rl_dstnhosts = 0;
+ TAILQ_FOREACH(host, &rlay->rl_dsttable->hosts, entry) {
+ if (rlay->rl_dstnhosts >= RELAY_MAXHOSTS)
+ fatal("relay_init: "
+ "too many hosts in table");
+ host->idx = rlay->rl_dstnhosts;
+ rlay->rl_dsthost[rlay->rl_dstnhosts++] = host;
+ }
+ log_info("adding %d hosts from table %s%s",
+ rlay->rl_dstnhosts, rlay->rl_dsttable->conf.name,
+ rlay->rl_dsttable->conf.check ? "" : " (no check)");
+ }
+
+ switch (rlay->rl_proto->type) {
+ case RELAY_PROTO_DNS:
+ relay_udp_init(rlay);
+ break;
+ case RELAY_PROTO_TCP:
+ case RELAY_PROTO_HTTP:
+ /* Use defaults */
+ break;
+ }
+
log_debug("%s: running relay %s", __func__,
rlay->rl_conf.name);
@@ -2320,7 +2299,7 @@ relay_close(struct rsession *con, const char *msg)
if (con->se_out.bev != NULL)
bufferevent_disable(con->se_out.bev, EV_READ|EV_WRITE);
- if (env->sc_opts & RELAYD_OPT_LOGUPDATE) {
+ if ((env->sc_opts & RELAYD_OPT_LOGUPDATE) && msg != NULL) {
bzero(&ibuf, sizeof(ibuf));
bzero(&obuf, sizeof(obuf));
(void)print_host(&con->se_in.ss, ibuf, sizeof(ibuf));
@@ -2531,6 +2510,27 @@ relay_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
bzero(&tv, sizeof(tv));
evtimer_add(&con->se_ev, &tv);
break;
+ case IMSG_CFG_TABLE:
+ config_gettable(env, imsg);
+ break;
+ case IMSG_CFG_HOST:
+ config_gethost(env, imsg);
+ break;
+ case IMSG_CFG_PROTO:
+ config_getproto(env, imsg);
+ break;
+ case IMSG_CFG_PROTONODE:
+ return (config_getprotonode(env, imsg));
+ case IMSG_CFG_RELAY:
+ config_getrelay(env, imsg);
+ break;
+ case IMSG_CFG_DONE:
+ config_getcfg(env, imsg);
+ relay_launch();
+ break;
+ case IMSG_CTL_RESET:
+ config_getreset(env, imsg);
+ break;
default:
return (-1);
}
@@ -2578,7 +2578,7 @@ relay_ssl_ctx_create(struct relay *rlay)
if ((rlay->rl_conf.flags & F_SSLCLIENT) &&
(rlay->rl_ssl_ca != NULL)) {
if (!ssl_ctx_load_verify_memory(ctx,
- rlay->rl_ssl_ca, rlay->rl_ssl_ca_len))
+ rlay->rl_ssl_ca, rlay->rl_conf.ssl_ca_len))
goto err;
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
}
@@ -2588,12 +2588,12 @@ relay_ssl_ctx_create(struct relay *rlay)
log_debug("%s: loading certificate", __func__);
if (!ssl_ctx_use_certificate_chain(ctx,
- rlay->rl_ssl_cert, rlay->rl_ssl_cert_len))
+ rlay->rl_ssl_cert, rlay->rl_conf.ssl_cert_len))
goto err;
log_debug("%s: loading private key", __func__);
if (!ssl_ctx_use_private_key(ctx, rlay->rl_ssl_key,
- rlay->rl_ssl_key_len))
+ rlay->rl_conf.ssl_key_len))
goto err;
if (!SSL_CTX_check_private_key(ctx))
goto err;
@@ -3070,7 +3070,7 @@ relay_load_file(const char *name, off_t *len)
close(fd);
- *len = size + 1;
+ *len = size;
return (buf);
fail:
@@ -3087,9 +3087,9 @@ relay_load_certfiles(struct relay *rlay)
char certfile[PATH_MAX];
char hbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
- if ((rlay->rl_conf.flags & F_SSLCLIENT) && (proto->sslca != NULL)) {
+ if ((rlay->rl_conf.flags & F_SSLCLIENT) && strlen(proto->sslca)) {
if ((rlay->rl_ssl_ca = relay_load_file(proto->sslca,
- &rlay->rl_ssl_ca_len)) == NULL)
+ &rlay->rl_conf.ssl_ca_len)) == NULL)
return (-1);
log_debug("%s: using ca %s", __func__, proto->sslca);
}
@@ -3104,7 +3104,7 @@ relay_load_certfiles(struct relay *rlay)
"/etc/ssl/%s.crt", hbuf) == -1)
return (-1);
if ((rlay->rl_ssl_cert = relay_load_file(certfile,
- &rlay->rl_ssl_cert_len)) == NULL)
+ &rlay->rl_conf.ssl_cert_len)) == NULL)
return (-1);
log_debug("%s: using certificate %s", __func__, certfile);
@@ -3112,7 +3112,7 @@ relay_load_certfiles(struct relay *rlay)
"/etc/ssl/private/%s.key", hbuf) == -1)
return -1;
if ((rlay->rl_ssl_key = relay_load_file(certfile,
- &rlay->rl_ssl_key_len)) == NULL)
+ &rlay->rl_conf.ssl_key_len)) == NULL)
return (-1);
log_debug("%s: using private key %s", __func__, certfile);
diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c
index f3a70f57f49..8bc215646f5 100644
--- a/usr.sbin/relayd/relayd.c
+++ b/usr.sbin/relayd/relayd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.c,v 1.102 2011/05/09 12:08:47 reyk Exp $ */
+/* $OpenBSD: relayd.c,v 1.103 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -22,6 +22,7 @@
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/resource.h>
+#include <sys/hash.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -30,6 +31,7 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <fcntl.h>
#include <getopt.h>
#include <err.h>
#include <errno.h>
@@ -46,16 +48,16 @@
__dead void usage(void);
+int parent_configure(struct relayd *);
+void parent_reload(struct relayd *, u_int, const char *);
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 *);
-struct relayd *relayd_env;
+struct relayd *relayd_env;
static struct privsep_proc procs[] = {
{ "pfe", PROC_PFE, parent_dispatch_pfe, pfe },
@@ -112,7 +114,13 @@ parent_sig_handler(int sig, short event, void *arg)
parent_shutdown(ps->ps_env);
break;
case SIGHUP:
- reconfigure();
+ log_info("%s: reload requested with SIGHUP", __func__);
+
+ /*
+ * This is safe because libevent uses async signal handlers
+ * that run in the event loop and not in signal context.
+ */
+ parent_reload(ps->ps_env, CONFIG_RELOAD, NULL);
break;
case SIGPIPE:
/* ignore */
@@ -137,15 +145,11 @@ int
main(int argc, char *argv[])
{
int c;
- int debug;
- u_int32_t opts;
+ int debug = 0, verbose = 0;
+ u_int32_t opts = 0;
struct relayd *env;
struct privsep *ps;
- const char *conffile;
-
- opts = 0;
- debug = 0;
- conffile = CONF_FILE;
+ const char *conffile = CONF_FILE;
while ((c = getopt(argc, argv, "dD:nf:v")) != -1) {
switch (c) {
@@ -165,6 +169,7 @@ main(int argc, char *argv[])
conffile = optarg;
break;
case 'v':
+ verbose++;
opts |= RELAYD_OPT_VERBOSE;
break;
default:
@@ -179,18 +184,19 @@ main(int argc, char *argv[])
if (argc > 0)
usage();
- if ((env = parse_config(conffile, opts)) == NULL ||
+ if ((env = calloc(1, sizeof(*env))) == NULL ||
(ps = calloc(1, sizeof(*ps))) == NULL)
exit(1);
relayd_env = env;
env->sc_ps = ps;
ps->ps_env = env;
+ env->sc_conffile = conffile;
+ env->sc_opts = opts;
+
+ if (parse_config(env->sc_conffile, env) == -1)
+ exit(1);
- if (env->sc_opts & RELAYD_OPT_NOACTION) {
- fprintf(stderr, "configuration OK\n");
- exit(0);
- }
if (debug)
env->sc_opts |= RELAYD_OPT_LOGUPDATE;
@@ -203,13 +209,16 @@ main(int argc, char *argv[])
/* Configure the control socket */
ps->ps_csock.cs_name = RELAYD_SOCKET;
- if (!debug) {
- log_init(debug);
- if (daemon(1, 0) == -1)
- err(1, "failed to daemonize");
- }
+ log_init(debug);
+ log_verbose(verbose);
- log_info("startup");
+ if (!debug && daemon(1, 0) == -1)
+ err(1, "failed to daemonize");
+
+ if (env->sc_opts & RELAYD_OPT_NOACTION)
+ ps->ps_noaction = 1;
+ else
+ log_info("startup");
ps->ps_instances[PROC_RELAY] = env->sc_prefork_relay;
proc_init(ps, procs, nitems(procs));
@@ -231,241 +240,135 @@ main(int argc, char *argv[])
signal_add(&ps->ps_evsigpipe, NULL);
proc_config(ps, procs, nitems(procs));
+
+ if (load_config(env->sc_conffile, env) == -1) {
+ proc_kill(env->sc_ps);
+ exit(1);
+ }
+
+ if (env->sc_opts & RELAYD_OPT_NOACTION) {
+ fprintf(stderr, "configuration OK\n");
+ proc_kill(env->sc_ps);
+ exit(0);
+ }
+
+ if (env->sc_flags & (F_SSL|F_SSLCLIENT))
+ ssl_init(env);
+
+ if (parent_configure(env) == -1)
+ fatalx("configuration failed");
+
init_routes(env);
event_dispatch();
parent_shutdown(env);
/* NOTREACHED */
+
return (0);
}
-void
-parent_shutdown(struct relayd *env)
+int
+parent_configure(struct relayd *env)
{
- 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);
+ struct table *tb;
+ struct rdr *rdr;
+ struct router *rt;
+ struct protocol *proto;
+ struct relay *rlay;
+ int id;
+ struct ctl_flags cf;
+ int s, ret = -1;
- free(env->sc_ps);
- free(env);
+ TAILQ_FOREACH(tb, env->sc_tables, entry)
+ config_settable(env, tb);
+ TAILQ_FOREACH(rdr, env->sc_rdrs, entry)
+ config_setrdr(env, rdr);
+ TAILQ_FOREACH(rt, env->sc_rts, rt_entry)
+ config_setrt(env, rt);
+ TAILQ_FOREACH(proto, env->sc_protos, entry)
+ config_setproto(env, proto);
+ TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
+ config_setrelay(env, rlay);
- log_info("parent terminating, pid %d", getpid());
+ for (id = 0; id < PROC_MAX; id++) {
+ if (id == privsep_process)
+ continue;
+ cf.cf_opts = env->sc_opts;
+ cf.cf_flags = env->sc_flags;
+
+ if ((env->sc_flags & F_NEEDPF) && id == PROC_PFE) {
+ /* Send pf socket to the pf engine */
+ if ((s = open(PF_SOCKET, O_RDWR)) == -1) {
+ log_debug("%s: cannot open pf socket",
+ __func__);
+ goto done;
+ }
+ } else
+ s = -1;
- exit(0);
-}
+ env->sc_reload++;
+ proc_compose_imsg(env->sc_ps, id, -1, IMSG_CFG_DONE, s,
+ &cf, sizeof(cf));
+ }
-void
-merge_config(struct relayd *env, struct relayd *new_env)
-{
- env->sc_opts = new_env->sc_opts;
- env->sc_flags = new_env->sc_flags;
- env->sc_confpath = new_env->sc_confpath;
- env->sc_tablecount = new_env->sc_tablecount;
- env->sc_rdrcount = new_env->sc_rdrcount;
- env->sc_protocount = new_env->sc_protocount;
- env->sc_relaycount = new_env->sc_relaycount;
-
- memcpy(&env->sc_interval, &new_env->sc_interval,
- sizeof(env->sc_interval));
- memcpy(&env->sc_timeout, &new_env->sc_timeout,
- sizeof(env->sc_timeout));
- memcpy(&env->sc_empty_table, &new_env->sc_empty_table,
- sizeof(env->sc_empty_table));
- memcpy(&env->sc_proto_default, &new_env->sc_proto_default,
- sizeof(env->sc_proto_default));
- env->sc_prefork_relay = new_env->sc_prefork_relay;
- (void)strlcpy(env->sc_demote_group, new_env->sc_demote_group,
- sizeof(env->sc_demote_group));
-
- env->sc_tables = new_env->sc_tables;
- env->sc_rdrs = new_env->sc_rdrs;
- env->sc_relays = new_env->sc_relays;
- env->sc_protos = new_env->sc_protos;
-}
+ ret = 0;
+ done:
+ config_purge(env, CONFIG_ALL);
+ return (ret);
+}
void
-reconfigure(void)
+parent_reload(struct relayd *env, u_int reset, const char *filename)
{
- 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;
- struct host *host;
-
- log_info("reloading configuration");
- if ((new_env = parse_config(env->sc_confpath, env->sc_opts)) == NULL) {
- log_warnx("configuration reloading FAILED");
+ if (env->sc_reload) {
+ log_debug("%s: already in progress: %d pending",
+ __func__, env->sc_reload);
return;
}
- if (!(env->sc_flags & F_NEEDPF) && (new_env->sc_flags & F_NEEDPF)) {
- log_warnx("new configuration requires pf while it "
- "was previously disabled."
- "configuration will not be reloaded");
- purge_config(new_env, PURGE_EVERYTHING);
- free(new_env);
- return;
- }
-
- purge_config(env, PURGE_EVERYTHING);
- merge_config(env, new_env);
- free(new_env);
- log_info("configuration merge done");
-
- /*
- * first reconfigure pfe
- */
- proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF, -1, env, sizeof(*env));
- TAILQ_FOREACH(table, env->sc_tables, entry) {
- proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_TABLE, -1,
- &table->conf, sizeof(table->conf));
- TAILQ_FOREACH(host, &table->hosts, entry) {
- proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_HOST,
- -1, &host->conf, sizeof(host->conf));
- }
- }
- TAILQ_FOREACH(rdr, env->sc_rdrs, entry) {
- proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_RDR, -1,
- &rdr->conf, sizeof(rdr->conf));
- TAILQ_FOREACH(virt, &rdr->virts, entry)
- proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_VIRT,
- -1, virt, sizeof(*virt));
- }
- proc_compose_imsg(ps, PROC_PFE, -1, IMSG_RECONF_END, -1, NULL, 0);
-
- /*
- * then reconfigure hce
- */
- proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF, -1, env, sizeof(*env));
- TAILQ_FOREACH(table, env->sc_tables, entry) {
- proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF_TABLE, -1,
- &table->conf, sizeof(table->conf));
- if (table->sendbuf != NULL)
- proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF_SENDBUF,
- -1, table->sendbuf, strlen(table->sendbuf) + 1);
- TAILQ_FOREACH(host, &table->hosts, entry) {
- proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF_HOST,
- -1, &host->conf, sizeof(host->conf));
- }
- }
- proc_compose_imsg(ps, PROC_HCE, -1, IMSG_RECONF_END, -1, NULL, 0);
-}
+ /* Switch back to the default config file */
+ if (filename == NULL || *filename == '\0')
+ filename = env->sc_conffile;
-void
-purge_config(struct relayd *env, u_int8_t what)
-{
- struct table *table;
- struct rdr *rdr;
- struct address *virt;
- struct protocol *proto;
- struct relay *rlay;
- struct rsession *sess;
+ log_debug("%s: level %d config file %s", __func__, reset, filename);
- if (what & PURGE_TABLES && env->sc_tables != NULL) {
- while ((table = TAILQ_FIRST(env->sc_tables)) != NULL)
- purge_table(env->sc_tables, table);
- free(env->sc_tables);
- env->sc_tables = NULL;
- }
+ config_purge(env, CONFIG_ALL);
- if (what & PURGE_RDRS && env->sc_rdrs != NULL) {
- while ((rdr = TAILQ_FIRST(env->sc_rdrs)) != NULL) {
- TAILQ_REMOVE(env->sc_rdrs, rdr, entry);
- while ((virt = TAILQ_FIRST(&rdr->virts)) != NULL) {
- TAILQ_REMOVE(&rdr->virts, virt, entry);
- free(virt);
- }
- free(rdr);
+ if (reset == CONFIG_RELOAD) {
+ if (load_config(filename, env) == -1) {
+ log_debug("%s: failed to load config file %s",
+ __func__, filename);
}
- free(env->sc_rdrs);
- env->sc_rdrs = NULL;
- }
- if (what & PURGE_RELAYS && env->sc_relays != NULL) {
- while ((rlay = TAILQ_FIRST(env->sc_relays)) != NULL) {
- TAILQ_REMOVE(env->sc_relays, rlay, rl_entry);
- while ((sess =
- SPLAY_ROOT(&rlay->rl_sessions)) != NULL) {
- SPLAY_REMOVE(session_tree,
- &rlay->rl_sessions, sess);
- free(sess);
- }
- if (rlay->rl_bev != NULL)
- bufferevent_free(rlay->rl_bev);
- if (rlay->rl_dstbev != NULL)
- bufferevent_free(rlay->rl_dstbev);
- if (rlay->rl_ssl_ctx != NULL)
- SSL_CTX_free(rlay->rl_ssl_ctx);
- free(rlay);
- }
- free(env->sc_relays);
- env->sc_relays = NULL;
- }
+ config_setreset(env, CONFIG_ALL);
- if (what & PURGE_PROTOS && env->sc_protos != NULL) {
- while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
- TAILQ_REMOVE(env->sc_protos, proto, entry);
- purge_tree(&proto->request_tree);
- purge_tree(&proto->response_tree);
- if (proto->style != NULL)
- free(proto->style);
- free(proto);
+ if (parent_configure(env) == -1) {
+ log_debug("%s: failed to commit config from %s",
+ __func__, filename);
}
- free(env->sc_protos);
- env->sc_protos = NULL;
- }
+ } else
+ config_setreset(env, reset);
}
void
-purge_tree(struct proto_tree *tree)
+parent_shutdown(struct relayd *env)
{
- struct protonode *proot, *pn;
+ config_purge(env, CONFIG_ALL);
- while ((proot = RB_ROOT(tree)) != NULL) {
- RB_REMOVE(proto_tree, tree, proot);
- if (proot->key != NULL)
- free(proot->key);
- if (proot->value != NULL)
- free(proot->value);
- while ((pn = SIMPLEQ_FIRST(&proot->head)) != NULL) {
- SIMPLEQ_REMOVE_HEAD(&proot->head, entry);
- if (pn->key != NULL)
- free(pn->key);
- if (pn->value != NULL)
- free(pn->value);
- if (pn->label != 0)
- pn_unref(pn->label);
- free(pn);
- }
- free(proot);
- }
-}
+ 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);
-void
-purge_table(struct tablelist *head, struct table *table)
-{
- struct host *host;
+ free(env->sc_ps);
+ free(env);
- while ((host = TAILQ_FIRST(&table->hosts)) != NULL) {
- TAILQ_REMOVE(&table->hosts, host, entry);
- if (host->cte.ssl != NULL)
- SSL_free(host->cte.ssl);
- free(host);
- }
- if (table->sendbuf != NULL)
- free(table->sendbuf);
- if (table->conf.flags & F_SSL)
- SSL_CTX_free(table->ssl_ctx);
+ log_info("parent terminating, pid %d", getpid());
- if (head != NULL)
- TAILQ_REMOVE(head, table, entry);
- free(table);
+ exit(0);
}
int
@@ -474,6 +377,8 @@ parent_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg)
struct relayd *env = p->p_env;
struct ctl_demote demote;
struct ctl_netroute crt;
+ u_int v;
+ char *str = NULL;
switch (imsg->hdr.type) {
case IMSG_DEMOTE:
@@ -486,11 +391,24 @@ parent_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg)
memcpy(&crt, imsg->data, sizeof(crt));
pfe_route(env, &crt);
break;
+ case IMSG_CTL_RESET:
+ IMSG_SIZE_CHECK(imsg, &v);
+ memcpy(&v, imsg->data, sizeof(v));
+ parent_reload(env, v, NULL);
+ break;
case IMSG_CTL_RELOAD:
- /*
- * so far we only get here if no L7 (relay) is done.
- */
- reconfigure();
+ if (IMSG_DATA_SIZE(imsg) > 0)
+ str = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
+ parent_reload(env, CONFIG_RELOAD, str);
+ if (str != NULL)
+ free(str);
+ break;
+ case IMSG_CTL_SHUTDOWN:
+ parent_shutdown(env);
+ break;
+ case IMSG_CFG_DONE:
+ if (env->sc_reload)
+ env->sc_reload--;
break;
default:
return (-1);
@@ -515,7 +433,11 @@ parent_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
-1, &scr, sizeof(scr));
break;
case IMSG_SNMPSOCK:
- (void)snmp_sendsock(env, p->p_id);
+ (void)snmp_setsock(env, p->p_id);
+ break;
+ case IMSG_CFG_DONE:
+ if (env->sc_reload)
+ env->sc_reload--;
break;
default:
return (-1);
@@ -552,6 +474,10 @@ parent_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg)
proc_compose_imsg(ps, PROC_RELAY, bnd.bnd_proc,
IMSG_BINDANY, s, &bnd.bnd_id, sizeof(bnd.bnd_id));
break;
+ case IMSG_CFG_DONE:
+ if (env->sc_reload)
+ env->sc_reload--;
+ break;
default:
return (-1);
}
@@ -559,6 +485,96 @@ parent_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg)
return (0);
}
+void
+purge_tree(struct proto_tree *tree)
+{
+ struct protonode *proot, *pn;
+
+ while ((proot = RB_ROOT(tree)) != NULL) {
+ RB_REMOVE(proto_tree, tree, proot);
+ if (proot->key != NULL)
+ free(proot->key);
+ if (proot->value != NULL)
+ free(proot->value);
+ while ((pn = SIMPLEQ_FIRST(&proot->head)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&proot->head, entry);
+ if (pn->key != NULL)
+ free(pn->key);
+ if (pn->value != NULL)
+ free(pn->value);
+ if (pn->label != 0)
+ pn_unref(pn->label);
+ free(pn);
+ }
+ free(proot);
+ }
+}
+
+void
+purge_table(struct tablelist *head, struct table *table)
+{
+ struct host *host;
+
+ while ((host = TAILQ_FIRST(&table->hosts)) != NULL) {
+ TAILQ_REMOVE(&table->hosts, host, entry);
+ if (event_initialized(&host->cte.ev)) {
+ event_del(&host->cte.ev);
+ close(host->cte.s);
+ }
+ if (host->cte.buf != NULL)
+ ibuf_free(host->cte.buf);
+ if (host->cte.ssl != NULL)
+ SSL_free(host->cte.ssl);
+ free(host);
+ }
+ if (table->sendbuf != NULL)
+ free(table->sendbuf);
+ if (table->conf.flags & F_SSL)
+ SSL_CTX_free(table->ssl_ctx);
+
+ if (head != NULL)
+ TAILQ_REMOVE(head, table, entry);
+ free(table);
+}
+
+void
+purge_relay(struct relayd *env, struct relay *rlay)
+{
+ struct rsession *con;
+
+ /* shutdown and remove relay */
+ if (event_initialized(&rlay->rl_ev))
+ event_del(&rlay->rl_ev);
+ close(rlay->rl_s);
+ TAILQ_REMOVE(env->sc_relays, rlay, rl_entry);
+
+ /* cleanup sessions */
+ while ((con =
+ SPLAY_ROOT(&rlay->rl_sessions)) != NULL)
+ relay_close(con, NULL);
+
+ /* cleanup relay */
+ if (rlay->rl_bev != NULL)
+ bufferevent_free(rlay->rl_bev);
+ if (rlay->rl_dstbev != NULL)
+ bufferevent_free(rlay->rl_dstbev);
+
+ if (rlay->rl_ssl_ctx != NULL)
+ SSL_CTX_free(rlay->rl_ssl_ctx);
+ if (rlay->rl_ssl_cert != NULL)
+ free(rlay->rl_ssl_cert);
+ if (rlay->rl_ssl_key != NULL)
+ free(rlay->rl_ssl_key);
+ if (rlay->rl_ssl_ca != NULL)
+ free(rlay->rl_ssl_ca);
+
+ free(rlay);
+}
+
+/*
+ * Utility functions
+ */
+
struct host *
host_find(struct relayd *env, objid_t id)
{
@@ -605,6 +621,17 @@ relay_find(struct relayd *env, objid_t id)
return (NULL);
}
+struct protocol *
+proto_find(struct relayd *env, objid_t id)
+{
+ struct protocol *p;
+
+ TAILQ_FOREACH(p, env->sc_protos, entry)
+ if (p->id == id)
+ return (p);
+ return (NULL);
+}
+
struct rsession *
session_find(struct relayd *env, objid_t id)
{
@@ -629,6 +656,17 @@ route_find(struct relayd *env, objid_t id)
return (NULL);
}
+struct router *
+router_find(struct relayd *env, objid_t id)
+{
+ struct router *rt;
+
+ TAILQ_FOREACH(rt, env->sc_rts, rt_entry)
+ if (rt->rt_conf.id == id)
+ return (rt);
+ return (NULL);
+}
+
struct host *
host_findbyname(struct relayd *env, const char *name)
{
@@ -949,7 +987,6 @@ protonode_add(enum direction dir, struct protocol *proto,
SIMPLEQ_NEXT(proot, entry) = pn;
SIMPLEQ_INSERT_TAIL(&proot->head, pn, entry);
}
-
if (node->type == NODE_TYPE_COOKIE)
pk.key = "Cookie";
else if (node->type == NODE_TYPE_URL)
@@ -1126,3 +1163,32 @@ socket_rlimit(int maxfd)
if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
fatal("socket_rlimit: failed to set resource limit");
}
+
+char *
+get_string(u_int8_t *ptr, size_t len)
+{
+ size_t i;
+ char *str;
+
+ for (i = 0; i < len; i++)
+ if (!(isprint((char)ptr[i]) || isspace((char)ptr[i])))
+ break;
+
+ if ((str = calloc(1, i + 1)) == NULL)
+ return (NULL);
+ memcpy(str, ptr, i);
+
+ return (str);
+}
+
+void *
+get_data(u_int8_t *ptr, size_t len)
+{
+ u_int8_t *data;
+
+ if ((data = calloc(1, len)) == NULL)
+ return (NULL);
+ memcpy(data, ptr, len);
+
+ return (data);
+}
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index 330ad861cd4..8da1a96285d 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.146 2011/05/09 12:08:47 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.147 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -51,15 +51,18 @@
#define RELAY_BACKLOG 10
#define RELAY_MAXLOOKUPLEVELS 5
+#define CONFIG_RELOAD 0x00
+#define CONFIG_TABLES 0x01
+#define CONFIG_RDRS 0x02
+#define CONFIG_RELAYS 0x04
+#define CONFIG_PROTOS 0x08
+#define CONFIG_ROUTES 0x10
+#define CONFIG_RTS 0x20
+#define CONFIG_ALL 0xff
+
#define SMALL_READ_BUF_SIZE 1024
#define ICMP_BUF_SIZE 64
-#define PURGE_TABLES 0x01
-#define PURGE_RDRS 0x02
-#define PURGE_RELAYS 0x04
-#define PURGE_PROTOS 0x08
-#define PURGE_EVERYTHING 0xff
-
#define SNMP_RECONNECT_TIMEOUT { 3, 0 } /* sec, usec */
#if DEBUG > 1
@@ -77,6 +80,11 @@ struct shuffle {
typedef u_int32_t objid_t;
+struct ctl_flags {
+ u_int8_t cf_opts;
+ u_int32_t cf_flags;
+};
+
struct ctl_status {
objid_t id;
int up;
@@ -100,12 +108,6 @@ struct ctl_demote {
int level;
};
-struct ctl_netroute {
- objid_t id;
- objid_t hostid;
- int up;
-};
-
struct ctl_icmp_event {
struct relayd *env;
int s;
@@ -218,6 +220,7 @@ struct portrange {
};
struct address {
+ objid_t rdrid;
struct sockaddr_storage ss;
int ipproto;
struct portrange port;
@@ -370,7 +373,6 @@ struct table {
int skipped;
struct hostlist hosts;
SSL_CTX *ssl_ctx;
- int sendbuf_len;
char *sendbuf;
};
TAILQ_HEAD(tablelist, table);
@@ -465,16 +467,26 @@ enum noderesult {
PN_FAIL = -1
};
+struct protonode_config {
+ objid_t protoid;
+ size_t keylen;
+ size_t valuelen;
+ size_t len;
+ u_int dir;
+};
+
struct protonode {
+ struct protonode_config conf;
objid_t id;
- char *key;
enum nodeaction action;
- char *value;
u_int8_t flags;
enum nodetype type;
u_int16_t mark;
u_int16_t label;
+ char *key;
+ char *value;
+
SIMPLEQ_HEAD(, protonode) head;
SIMPLEQ_ENTRY(protonode) entry;
@@ -526,7 +538,7 @@ struct protocol {
u_int8_t tcpipminttl;
u_int8_t sslflags;
char sslciphers[768];
- char *sslca;
+ char sslca[MAXPATHLEN];
char name[MAX_NAME_SIZE];
int cache;
enum prototype type;
@@ -565,6 +577,9 @@ struct relay_config {
struct sockaddr_storage dstaf;
struct timeval timeout;
enum forwardmode fwdmode;
+ off_t ssl_cert_len;
+ off_t ssl_key_len;
+ off_t ssl_ca_len;
};
struct relay {
@@ -589,11 +604,8 @@ struct relay {
SSL_CTX *rl_ssl_ctx;
char *rl_ssl_cert;
- off_t rl_ssl_cert_len;
char *rl_ssl_key;
- off_t rl_ssl_key_len;
char *rl_ssl_ca;
- off_t rl_ssl_ca_len;
struct ctl_stats rl_stats[RELAY_MAXPROC + 1];
@@ -635,11 +647,11 @@ struct router_config {
objid_t gwtable;
in_port_t gwport;
int rtable;
+ int af;
};
struct router {
struct router_config rt_conf;
- int rt_af;
struct table *rt_gwtable;
struct netroutelist rt_netroutes;
@@ -648,6 +660,12 @@ struct router {
};
TAILQ_HEAD(routerlist, router);
+struct ctl_netroute {
+ int up;
+ struct host_config host;
+ struct netroute_config nr;
+ struct router_config rt;
+};
/* initially control.h */
struct control_sock {
@@ -718,6 +736,7 @@ enum imsg_type {
IMSG_CTL_HOST_DISABLE,
IMSG_CTL_SHUTDOWN,
IMSG_CTL_RELOAD,
+ IMSG_CTL_RESET,
IMSG_CTL_POLL,
IMSG_CTL_NOTIFY,
IMSG_CTL_RDR_STATS,
@@ -733,30 +752,28 @@ enum imsg_type {
IMSG_NATLOOK,
IMSG_DEMOTE,
IMSG_STATISTICS,
- IMSG_RECONF, /* reconfiguration notifies */
- IMSG_RECONF_TABLE,
- IMSG_RECONF_SENDBUF,
- IMSG_RECONF_HOST,
- IMSG_RECONF_RDR,
- IMSG_RECONF_VIRT,
- IMSG_RECONF_PROTO,
- IMSG_RECONF_REQUEST_TREE,
- IMSG_RECONF_RESPONSE_TREE,
- IMSG_RECONF_PNODE_KEY,
- IMSG_RECONF_PNODE_VAL,
- IMSG_RECONF_RELAY,
- IMSG_RECONF_END,
IMSG_SCRIPT,
IMSG_SNMPSOCK,
IMSG_BINDANY,
- IMSG_RTMSG /* from pfe to parent */
+ IMSG_RTMSG, /* from pfe to parent */
+ IMSG_CFG_TABLE, /* configuration from parent */
+ IMSG_CFG_HOST,
+ IMSG_CFG_RDR,
+ IMSG_CFG_VIRT,
+ IMSG_CFG_ROUTER,
+ IMSG_CFG_ROUTE,
+ IMSG_CFG_PROTO,
+ IMSG_CFG_PROTONODE,
+ IMSG_CFG_RELAY,
+ IMSG_CFG_DONE
};
enum privsep_procid {
+ PROC_ALL = -1,
PROC_PARENT = 0,
- PROC_PFE,
PROC_HCE,
PROC_RELAY,
+ PROC_PFE,
PROC_MAX
} privsep_process;
@@ -768,6 +785,7 @@ struct privsep {
struct imsgev *ps_ievs[PROC_MAX];
const char *ps_title[PROC_MAX];
pid_t ps_pid[PROC_MAX];
+ u_int8_t ps_what[PROC_MAX];
u_int ps_instances[PROC_MAX];
u_int ps_instance;
@@ -781,6 +799,7 @@ struct privsep {
struct event ps_evsighup;
struct event ps_evsigpipe;
+ int ps_noaction;
struct passwd *ps_pw;
struct relayd *ps_env;
};
@@ -802,7 +821,7 @@ struct privsep_proc {
struct relayd {
u_int8_t sc_opts;
u_int32_t sc_flags;
- const char *sc_confpath;
+ const char *sc_conffile;
struct pfdata *sc_pf;
int sc_rtsock;
int sc_rtseq;
@@ -842,6 +861,7 @@ struct relayd {
struct ctl_icmp_event sc_icmp6_recv;
struct privsep *sc_ps;
+ int sc_reload;
};
#define RELAYD_OPT_VERBOSE 0x01
@@ -863,8 +883,9 @@ void socket_set_blockmode(int, enum blockmodes);
extern struct ctl_connlist ctl_conns;
/* parse.y */
-struct relayd *parse_config(const char *, int);
-int cmdline_symset(char *);
+int parse_config(const char *, struct relayd *);
+int load_config(const char *, struct relayd *);
+int cmdline_symset(char *);
/* log.c */
const char *host_error(enum host_error);
@@ -889,7 +910,7 @@ int disable_table(struct ctl_conn *, struct ctl_id *);
int disable_host(struct ctl_conn *, struct ctl_id *, struct host *);
/* pfe_filter.c */
-void init_filter(struct relayd *);
+void init_filter(struct relayd *, int);
void init_tables(struct relayd *);
void flush_table(struct relayd *, struct rdr *);
void sync_table(struct relayd *, struct rdr *, struct table *);
@@ -910,6 +931,7 @@ void hce_notify_done(struct host *, enum host_error);
/* relay.c */
pid_t relay(struct privsep *, struct privsep_proc *);
+int relay_privinit(struct relay *);
void relay_notify_done(struct host *, const char *);
int relay_session_cmp(struct rsession *, struct rsession *);
int relay_load_certfiles(struct relay *);
@@ -962,6 +984,7 @@ struct host *host_find(struct relayd *, objid_t);
struct table *table_find(struct relayd *, objid_t);
struct rdr *rdr_find(struct relayd *, objid_t);
struct netroute *route_find(struct relayd *, objid_t);
+struct router *router_find(struct relayd *, objid_t);
struct host *host_findbyname(struct relayd *, const char *);
struct table *table_findbyname(struct relayd *, const char *);
struct table *table_findbyconf(struct relayd *, struct table *);
@@ -970,14 +993,15 @@ void event_again(struct event *, int, short,
void (*)(int, short, void *),
struct timeval *, struct timeval *, void *);
struct relay *relay_find(struct relayd *, objid_t);
+struct protocol *proto_find(struct relayd *, objid_t);
struct rsession *session_find(struct relayd *, objid_t);
struct relay *relay_findbyname(struct relayd *, const char *);
struct relay *relay_findbyaddr(struct relayd *, struct relay_config *);
int expand_string(char *, size_t, const char *, const char *);
void translate_string(char *);
-void purge_config(struct relayd *, u_int8_t);
+void purge_tree(struct proto_tree *);
void purge_table(struct tablelist *, struct table *);
-void merge_config(struct relayd *, struct relayd *);
+void purge_relay(struct relayd *, struct relay *);
char *digeststr(enum digest_type, const u_int8_t *, size_t, char *);
const char *canonicalize_host(const char *, char *, size_t);
struct protonode *protonode_header(enum direction, struct protocol *,
@@ -992,6 +1016,8 @@ 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);
void socket_rlimit(int);
+char *get_string(u_int8_t *, size_t);
+void *get_data(u_int8_t *, size_t);
/* carp.c */
int carp_demote_init(char *, int);
@@ -1008,7 +1034,8 @@ void pn_ref(u_int16_t);
/* snmp.c */
void snmp_init(struct relayd *, enum privsep_procid);
-int snmp_sendsock(struct relayd *, enum privsep_procid);
+int snmp_setsock(struct relayd *, enum privsep_procid);
+int snmp_getsock(struct relayd *, struct imsg *);
void snmp_hosttrap(struct relayd *, struct table *, struct host *);
/* shuffle.c */
@@ -1028,11 +1055,13 @@ __dead void fatalx(const char *);
/* proc.c */
void proc_init(struct privsep *, struct privsep_proc *, u_int);
void proc_kill(struct privsep *);
+void proc_clear(struct privsep *, int);
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 *);
+void proc_range(struct privsep *, enum privsep_procid, int *, int *);
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,
@@ -1047,3 +1076,26 @@ 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);
+
+/* config.c */
+int config_init(struct relayd *);
+void config_purge(struct relayd *, u_int);
+int config_setreset(struct relayd *, u_int);
+int config_getreset(struct relayd *, struct imsg *);
+int config_getcfg(struct relayd *, struct imsg *);
+int config_settable(struct relayd *, struct table *);
+int config_gettable(struct relayd *, struct imsg *);
+int config_gethost(struct relayd *, struct imsg *);
+int config_setrdr(struct relayd *, struct rdr *);
+int config_getrdr(struct relayd *, struct imsg *);
+int config_getvirt(struct relayd *, struct imsg *);
+int config_setrt(struct relayd *, struct router *);
+int config_getrt(struct relayd *, struct imsg *);
+int config_getroute(struct relayd *, struct imsg *);
+int config_setproto(struct relayd *env, struct protocol *);
+int config_getproto(struct relayd *, struct imsg *);
+int config_setprotonode(struct relayd *, enum privsep_procid,
+ struct protocol *, enum direction);
+int config_getprotonode(struct relayd *, struct imsg *);
+int config_setrelay(struct relayd *env, struct relay *);
+int config_getrelay(struct relayd *, struct imsg *);
diff --git a/usr.sbin/relayd/snmp.c b/usr.sbin/relayd/snmp.c
index f341d74bade..f21f6577455 100644
--- a/usr.sbin/relayd/snmp.c
+++ b/usr.sbin/relayd/snmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmp.c,v 1.10 2011/05/09 12:08:47 reyk Exp $ */
+/* $OpenBSD: snmp.c,v 1.11 2011/05/19 08:56:49 reyk Exp $ */
/*
* Copyright (c) 2008 Reyk Floeter <reyk@openbsd.org>
@@ -49,7 +49,6 @@ static struct imsgev *iev_snmp = NULL;
enum privsep_procid snmp_procid;
void snmp_sock(int, short, void *);
-int snmp_getsock(struct relayd *, enum privsep_procid);
int snmp_element(const char *, enum snmp_type, void *, int64_t);
void
@@ -72,80 +71,59 @@ snmp_init(struct relayd *env, enum privsep_procid id)
}
int
-snmp_sendsock(struct relayd *env, enum privsep_procid id)
+snmp_setsock(struct relayd *env, enum privsep_procid id)
{
struct imsgev tmpiev;
struct sockaddr_un sun;
int s = -1;
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
- goto fail;
+ goto done;
bzero(&sun, sizeof(sun));
sun.sun_family = AF_UNIX;
strlcpy(sun.sun_path, SNMP_SOCKET, sizeof(sun.sun_path));
- if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) == -1)
- goto fail;
+
+ if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
+ close(s);
+ s = -1;
+ goto done;
+ }
/* enable restricted snmp socket mode */
bzero(&tmpiev, sizeof(tmpiev));
imsg_init(&tmpiev.ibuf, s);
imsg_compose_event(&tmpiev, IMSG_SNMP_LOCK, 0, 0, -1, NULL, 0);
+ done:
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);
- proc_compose_imsg(env->sc_ps, id, -1, IMSG_NONE, -1, NULL, 0);
return (-1);
}
int
-snmp_getsock(struct relayd *env, enum privsep_procid id)
+snmp_getsock(struct relayd *env, struct imsg *imsg)
{
- struct imsg imsg;
- struct imsgbuf *ibuf;
- int n, s = -1, done = 0;
-
- 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) {
- 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(ibuf, &imsg)) == -1)
- fatal("snmp_getsock: failed to get imsg");
- if (n == 0)
- break;
- done = 1;
- switch (imsg.hdr.type) {
- case IMSG_SNMPSOCK:
- s = imsg.fd;
- break;
- default:
- break;
- }
- imsg_free(&imsg);
- }
- }
+ struct timeval tv = SNMP_RECONNECT_TIMEOUT;
- if (s != -1) {
- log_debug("%s: got new snmp socket %d", __func__, s);
- if (iev_snmp == NULL && (iev_snmp = (struct imsgev *)
- calloc(1, sizeof(struct imsgev))) == NULL)
- fatal("snmp_getsock: calloc");
- imsg_init(&iev_snmp->ibuf, s);
- }
+ if (imsg->fd == -1)
+ goto retry;
- return (s);
+ env->sc_snmp = imsg->fd;
+
+ log_debug("%s: got new snmp socket %d", __func__, imsg->fd);
+ if (iev_snmp == NULL && (iev_snmp = (struct imsgev *)
+ calloc(1, sizeof(struct imsgev))) == NULL)
+ fatal("snmp_getsock: calloc");
+ imsg_init(&iev_snmp->ibuf, env->sc_snmp);
+
+ event_set(&env->sc_snmpev, env->sc_snmp,
+ EV_READ|EV_TIMEOUT, snmp_sock, env);
+ event_add(&env->sc_snmpev, NULL);
+ return (0);
+ retry:
+ evtimer_set(&env->sc_snmpto, snmp_sock, env);
+ evtimer_add(&env->sc_snmpto, &tv);
+ return (0);
}
void
@@ -164,14 +142,8 @@ snmp_sock(int fd, short event, void *arg)
break;
}
- if ((env->sc_snmp = snmp_getsock(env, snmp_procid)) == -1) {
- DPRINTF("%s: failed to open snmp socket", __func__);
- goto retry;
- }
-
- event_set(&env->sc_snmpev, env->sc_snmp,
- EV_READ|EV_TIMEOUT, snmp_sock, arg);
- event_add(&env->sc_snmpev, NULL);
+ proc_compose_imsg(env->sc_ps, snmp_procid, -1,
+ IMSG_SNMPSOCK, -1, NULL, 0);
return;
retry:
evtimer_set(&env->sc_snmpto, snmp_sock, arg);