commit - dbef7d4f82e95c334a131206f7d2ac02d3ef21bd
commit + 591e6ab59d9901a8a5a1eec8f4593ffc39656829
blob - 158491944da3175eea0b36906f2bc3308f1e4a12
blob + 0ae2acc345b861080a38dfedca582ad28093bb61
--- Makefile
+++ Makefile
-# $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
blob - 92bd2cef6f2845b02f1d5ccd45a7a678f44bde90
blob + d960f0aa6a73342dce84bdb9fa3da5e90a5ccbea
--- check_tcp.c
+++ check_tcp.c
-/* $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>
#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 *);
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);
}
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;
}
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:
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);
}
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;
}
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;
}
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;
}
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:
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;
}
blob - 9c9a3cc02e48c12fb72d8d325335093a1522a2f1
blob + 7397c34cc013a41c1b724196ba4f90529e8b9c3e
--- control.c
+++ control.c
-/* $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>
}
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,
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: "
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));
blob - /dev/null
blob + bb91b88c3646185a20c2f2aa4263e388e52fa452 (mode 644)
--- /dev/null
+++ config.c
+/* $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);
+}
blob - ab80166c4bb7927bacf7f67946bd0f9f98a0a9d4
blob + 147b272bfdefdfaaa6b6a509b4393b6dd180efc0
--- hce.c
+++ hce.c
-/* $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>
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
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);
}
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) {
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;
}
}
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:
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);
+ 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_SENDBUF:
- len = imsg->hdr.len - IMSG_HEADER_SIZE;
- table->sendbuf = calloc(1, len);
- (void)strlcpy(table->sendbuf, (char *)imsg->data, len);
+ case IMSG_SNMPSOCK:
+ snmp_getsock(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);
- }
- 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);
}
blob - c03b54c4264e2e3e86043000ab8664981b16ae50
blob + c3a5b5b5177b3754300a6de674a7ea673d6bd0ee
--- parse.y
+++ parse.y
-/* $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>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/queue.h>
+#include <sys/hash.h>
#include <net/if.h>
#include <net/pfvar.h>
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;
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 *);
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);
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))
YYERROR;
}
}
- | SEND TRAP { conf->sc_flags |= F_TRAP; }
+ | SEND TRAP {
+ if (loadcfg)
+ break;
+ conf->sc_flags |= F_TRAP;
+ }
;
loglevel : UPDATES { $$ = RELAYD_OPT_LOGUPDATE; }
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;
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;
free($3);
if (table->sendbuf == NULL)
fatal("out of memory");
- table->sendbuf_len = strlen(table->sendbuf);
}
| http_type STRING hostname digest {
if ($1) {
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;
proto : relay_proto PROTO STRING {
struct protocol *p;
+ if (!loadcfg) {
+ free($3);
+ YYACCEPT;
+ }
+
if (strcmp($3, "default") == 0) {
p = &conf->sc_proto_default;
} else {
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; }
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;
conf->sc_flags |= F_SSL;
}
tableport = h->port.val[0];
+ host_free(&al);
}
| forwardmode optsslclient TO forwardspec interface dstaf {
rlay->rl_conf.fwdmode = $1;
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;
| tablespec {
if (rlay->rl_backuptable) {
yyerror("only one backup table is allowed");
- purge_table(conf->sc_tables, $1);
YYERROR;
}
if (rlay->rl_dsttable) {
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))
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;
}
;
address : STRING {
- struct address *a;
+ struct address *h;
struct addresslist al;
if (strlcpy($$.name, $1,
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);
}
;
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;
+
+ 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;
- 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;
+ 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;
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);
+ if ((file = pushfile(filename, 0)) == NULL)
+ return (-1);
- 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);
- }
topfile = file;
setservent(1);
}
}
- if (errors) {
- free(conf);
- return (NULL);
- }
-
- return (conf);
+ return (errors ? -1 : 0);
}
int
log_warnx("%s: interface name truncated",
__func__);
freeaddrinfo(res0);
+ free(h);
return (-1);
}
if (ipproto != -1)
sizeof(h->ifname)) {
log_warnx("%s: interface name truncated",
__func__);
+ free(h);
return (-1);
}
}
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)
{
/* 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) {
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;
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;
TAILQ_INSERT_TAIL(conf->sc_tables, tb, entry);
return (tb);
+
+ fail:
+ purge_table(NULL, tb);
+ return (NULL);
}
struct relay *
blob - ba3a6260390e37cf546a675d139e7ada36208f62
blob + 4ed78c9f88de32da2593422d4eb71a5f52719717
--- pfe.c
+++ pfe.c
-/* $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>
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 },
{
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
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
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_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_ROUTER:
+ config_getrt(env, imsg);
break;
- case IMSG_RECONF_END:
- log_warnx("%s: configuration reloaded", __func__);
+ case IMSG_CFG_ROUTE:
+ config_getroute(env, imsg);
+ break;
+ 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);
}
}
TAILQ_FOREACH(table, env->sc_tables, entry) {
+ if (table->conf.check == CHECK_NOCHECK)
+ continue;
+
/*
* clean up change flag.
*/
blob - 2fa53cdd3b857ca53161a8fcaf9b101a85bfc990
blob + 02a528999b5e988b1da6c4ec649bf60c5adc88ef
--- pfe_filter.c
+++ pfe_filter.c
-/* $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>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
#include <openssl/ssl.h>
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)
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));
blob - 0fae0dfd0a065c2b10d47febb03cf2687fb0725c
blob + e0b5066eb404806d8e76813345133c75f60ff43c
--- pfe_route.c
+++ pfe_route.c
-/* $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>
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));
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 = &crt->host.ss;
+ gwname = crt->host.name;
- gw = &host->conf.ss;
- gwname = host->conf.name;
-
bzero(&rm, sizeof(rm));
bzero(&sr, sizeof(sr));
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);
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;
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);
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");
blob - 2bfb76a85beb75a49796af5891d0b49ebe88a227
blob + 7a0ddf0512fc590281db3e5b352552a7d1c06660
--- proc.c
+++ proc.c
-/* $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>
do {
pid = waitpid(WAIT_ANY, NULL, 0);
} while (pid != -1 || (pid == -1 && errno == EINTR));
+
+ proc_clear(ps, 1);
}
void
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");
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;
}
}
}
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;
if (p->p_shutdown != NULL)
(*p->p_shutdown)();
+ proc_clear(ps, 1);
+
log_info("%s exiting, pid %d", p->p_title, getpid());
_exit(0);
u_int32_t seed[256];
u_int n;
+ if (ps->ps_noaction)
+ return (0);
+
switch (pid = fork()) {
case -1:
fatal("run_proc: cannot fork");
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);
if (imsg_compose_event(&ps->ps_ievs[id][n],
type, -1, 0, fd, data, datalen) == -1)
return (-1);
+
return (0);
}
blob - d458a4de7a6ef21a6b30c053be1ee56ce854485c
blob + 00d50e93a797ff994f8e75f64c8afebeb7f4f67d
--- relay.c
+++ relay.c
-/* $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>
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 *);
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 */
}
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));
}
}
-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;
- }
-
- 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");
+ 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);
+
+ 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
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);
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));
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);
}
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);
}
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;
close(fd);
- *len = size + 1;
+ *len = size;
return (buf);
fail:
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);
}
"/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);
"/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);
blob - f3a70f57f497e7743103bdba779d769df0319533
blob + 8bc215646f53ca390be3ad305a6ffa82b6628613
--- relayd.c
+++ relayd.c
-/* $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>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/resource.h>
+#include <sys/hash.h>
#include <net/if.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <fcntl.h>
#include <getopt.h>
#include <err.h>
#include <errno.h>
__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 },
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 */
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;
+ const char *conffile = CONF_FILE;
- opts = 0;
- debug = 0;
- conffile = CONF_FILE;
-
while ((c = getopt(argc, argv, "dD:nf:v")) != -1) {
switch (c) {
case 'd':
conffile = optarg;
break;
case 'v':
+ verbose++;
opts |= RELAYD_OPT_VERBOSE;
break;
default:
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 (env->sc_opts & RELAYD_OPT_NOACTION) {
- fprintf(stderr, "configuration OK\n");
- exit(0);
- }
+ if (parse_config(env->sc_conffile, env) == -1)
+ exit(1);
+
if (debug)
env->sc_opts |= RELAYD_OPT_LOGUPDATE;
/* 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));
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);
}
+int
+parent_configure(struct relayd *env)
+{
+ 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;
+
+ 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);
+
+ 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;
+
+ env->sc_reload++;
+ proc_compose_imsg(env->sc_ps, id, -1, IMSG_CFG_DONE, s,
+ &cf, sizeof(cf));
+ }
+
+ ret = 0;
+
+ done:
+ config_purge(env, CONFIG_ALL);
+ return (ret);
+}
+
void
+parent_reload(struct relayd *env, u_int reset, const char *filename)
+{
+ if (env->sc_reload) {
+ log_debug("%s: already in progress: %d pending",
+ __func__, env->sc_reload);
+ return;
+ }
+
+ /* Switch back to the default config file */
+ if (filename == NULL || *filename == '\0')
+ filename = env->sc_conffile;
+
+ log_debug("%s: level %d config file %s", __func__, reset, filename);
+
+ config_purge(env, CONFIG_ALL);
+
+ if (reset == CONFIG_RELOAD) {
+ if (load_config(filename, env) == -1) {
+ log_debug("%s: failed to load config file %s",
+ __func__, filename);
+ }
+
+ config_setreset(env, CONFIG_ALL);
+
+ if (parent_configure(env) == -1) {
+ log_debug("%s: failed to commit config from %s",
+ __func__, filename);
+ }
+ } else
+ config_setreset(env, reset);
+}
+
+void
parent_shutdown(struct relayd *env)
{
+ config_purge(env, CONFIG_ALL);
+
proc_kill(env->sc_ps);
control_cleanup(&env->sc_ps->ps_csock);
carp_demote_shutdown();
exit(0);
}
-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;
-}
-
-
-void
-reconfigure(void)
-{
- struct relayd *env = relayd_env;
- struct relayd *new_env = NULL;
- struct privsep *ps = env->sc_ps;
- struct rdr *rdr;
- struct address *virt;
- struct table *table;
- struct host *host;
-
- log_info("reloading configuration");
- if ((new_env = parse_config(env->sc_confpath, env->sc_opts)) == NULL) {
- log_warnx("configuration reloading FAILED");
- 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);
-}
-
-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;
-
- 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;
- }
-
- 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);
- }
- 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;
- }
-
- 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);
- }
- free(env->sc_protos);
- env->sc_protos = NULL;
- }
-}
-
-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 (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);
-}
-
int
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:
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);
}
-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);
}
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);
}
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)
{
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)
{
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)
{
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)
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);
+}
blob - 330ad861cd45bb65cdef3bc41e0891384f525abb
blob + 8da1a96285da2f415af4c3bd2eb77c941464660e
--- relayd.h
+++ relayd.h
-/* $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>
#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
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;
int level;
};
-struct ctl_netroute {
- objid_t id;
- objid_t hostid;
- int up;
-};
-
struct ctl_icmp_event {
struct relayd *env;
int s;
};
struct address {
+ objid_t rdrid;
struct sockaddr_storage ss;
int ipproto;
struct portrange port;
int skipped;
struct hostlist hosts;
SSL_CTX *ssl_ctx;
- int sendbuf_len;
char *sendbuf;
};
TAILQ_HEAD(tablelist, table);
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;
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;
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 {
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];
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;
};
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 {
IMSG_CTL_HOST_DISABLE,
IMSG_CTL_SHUTDOWN,
IMSG_CTL_RELOAD,
+ IMSG_CTL_RESET,
IMSG_CTL_POLL,
IMSG_CTL_NOTIFY,
IMSG_CTL_RDR_STATS,
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;
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;
struct event ps_evsighup;
struct event ps_evsigpipe;
+ int ps_noaction;
struct passwd *ps_pw;
struct relayd *ps_env;
};
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;
struct ctl_icmp_event sc_icmp6_recv;
struct privsep *sc_ps;
+ int sc_reload;
};
#define RELAYD_OPT_VERBOSE 0x01
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);
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 *);
/* 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 *);
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 *);
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 *,
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);
/* 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 */
/* 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,
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 *);
blob - f341d74bade61f7ee70a0cac160412171e5bb379
blob + f21f657745507b45df62c770f5e3d28f83318d5e
--- snmp.c
+++ snmp.c
-/* $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>
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
}
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;
+ struct timeval tv = SNMP_RECONNECT_TIMEOUT;
- 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);
+ if (imsg->fd == -1)
+ goto retry;
- 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);
- }
- }
+ env->sc_snmp = imsg->fd;
- 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);
- }
+ 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);
- return (s);
+ 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
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);