From c723f8ed6f8a92f12a936b0763753d78199330a9 Mon Sep 17 00:00:00 2001 From: reyk Date: Sat, 19 Jul 2008 10:52:32 +0000 Subject: [PATCH] If the new 'parent' keyword is specified for a host in a table, inherit the state from another host with the specified Id; no additional check will be for the inheriting host. This helps in scenarios with lots of IP aliases that all point to the same service on the same host (like web hosting with many SSL domains). discussed with pyr, tested in different setups --- usr.sbin/relayd/check_icmp.c | 5 ++-- usr.sbin/relayd/control.c | 6 ++-- usr.sbin/relayd/hce.c | 17 +++++++++-- usr.sbin/relayd/parse.y | 43 ++++++++++++++++++++++++---- usr.sbin/relayd/pfe.c | 54 +++++++++++++++++++++++------------ usr.sbin/relayd/relayd.conf.5 | 17 +++++++++-- usr.sbin/relayd/relayd.h | 9 ++++-- 7 files changed, 114 insertions(+), 37 deletions(-) diff --git a/usr.sbin/relayd/check_icmp.c b/usr.sbin/relayd/check_icmp.c index f16e9bd3d61..c022077f936 100644 --- a/usr.sbin/relayd/check_icmp.c +++ b/usr.sbin/relayd/check_icmp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: check_icmp.c,v 1.23 2008/01/31 09:33:39 reyk Exp $ */ +/* $OpenBSD: check_icmp.c,v 1.24 2008/07/19 10:52:32 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard @@ -197,7 +197,8 @@ send_icmp(int s, short event, void *arg) table->conf.flags & F_DISABLE) continue; TAILQ_FOREACH(host, &table->hosts, entry) { - if (host->flags & (F_DISABLE | F_CHECK_SENT)) + if (host->flags & (F_DISABLE | F_CHECK_SENT) || + host->conf.parentid) continue; if (((struct sockaddr *)&host->conf.ss)->sa_family != cie->af) diff --git a/usr.sbin/relayd/control.c b/usr.sbin/relayd/control.c index d0c7258fe7d..67be0a1a7be 100644 --- a/usr.sbin/relayd/control.c +++ b/usr.sbin/relayd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.25 2008/01/31 09:33:39 reyk Exp $ */ +/* $OpenBSD: control.c,v 1.26 2008/07/19 10:52:32 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -293,7 +293,7 @@ control_dispatch_imsg(int fd, short event, void *arg) if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id)) fatalx("invalid imsg header len"); memcpy(&id, imsg.data, sizeof(id)); - if (disable_host(c, &id)) + if (disable_host(c, &id, NULL)) imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); else { @@ -307,7 +307,7 @@ control_dispatch_imsg(int fd, short event, void *arg) if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id)) fatalx("invalid imsg header len"); memcpy(&id, imsg.data, sizeof(id)); - if (enable_host(c, &id)) + if (enable_host(c, &id, NULL)) imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); else { diff --git a/usr.sbin/relayd/hce.c b/usr.sbin/relayd/hce.c index f0cd92cfb47..262f7f646c9 100644 --- a/usr.sbin/relayd/hce.c +++ b/usr.sbin/relayd/hce.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hce.c,v 1.41 2008/03/12 10:50:44 pyr Exp $ */ +/* $OpenBSD: hce.c,v 1.42 2008/07/19 10:52:32 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard @@ -240,7 +240,7 @@ hce_launch_checks(int fd, short event, void *arg) fatalx("hce_launch_checks: unknown check type"); TAILQ_FOREACH(host, &table->hosts, entry) { - if (host->flags & F_DISABLE) + if (host->flags & F_DISABLE || host->conf.parentid) continue; switch (table->conf.check) { case CHECK_ICMP: @@ -276,6 +276,10 @@ hce_notify_done(struct host *host, const char *msg) struct timeval tv_now, tv_dur; u_long duration; u_int logopt; + struct host *h; + int hostup; + + hostup = host->up; if (host->up == HOST_DOWN && host->retry_cnt) { log_debug("hce_notify_done: host %s retry %d", @@ -327,6 +331,15 @@ hce_notify_done(struct host *host, const char *msg) snmp_hosttrap(table, host); host->last_up = host->up; + + if (TAILQ_EMPTY(&host->children)) + return; + + /* Notify for all other hosts that inherit the state from this one */ + TAILQ_FOREACH(h, &host->children, child) { + h->up = hostup; + hce_notify_done(h, msg); + } } void diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y index 3c7cb2b61a7..9a881ed0f2a 100644 --- a/usr.sbin/relayd/parse.y +++ b/usr.sbin/relayd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.119 2008/07/17 16:41:06 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.120 2008/07/19 10:52:32 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter @@ -130,11 +130,11 @@ typedef struct { %token ON PATH PORT PREFORK PROTO QUERYSTR REAL REDIRECT RELAY REMOVE TRAP %token REQUEST RESPONSE RETRY RETURN ROUNDROBIN SACK SCRIPT SEND SESSION %token SOCKET SSL STICKYADDR STYLE TABLE TAG TCP TIMEOUT TO UPDATES URL -%token VIRTUAL WITH ERROR ROUTE TRANSPARENT +%token VIRTUAL WITH ERROR ROUTE TRANSPARENT PARENT %token STRING %token NUMBER %type interface hostname table -%type port http_type loglevel sslcache optssl mark +%type port http_type loglevel sslcache optssl mark parent %type proto_type dstmode retry log flag direction forwardmode %type host %type timeout @@ -1238,7 +1238,7 @@ interface : /*empty*/ { $$ = NULL; } | INTERFACE STRING { $$ = $2; } ; -host : STRING retry { +host : STRING retry parent { struct address *a; struct addresslist al; @@ -1266,6 +1266,8 @@ host : STRING retry { free($1); $$->conf.id = 0; /* will be set later */ $$->conf.retry = $2; + $$->conf.parentid = $3; + TAILQ_INIT(&$$->children); } ; @@ -1278,6 +1280,15 @@ retry : /* nothing */ { $$ = 0; } } ; +parent : /* nothing */ { $$ = 0; } + | PARENT NUMBER { + if (($$ = $2) < 0) { + yyerror("invalid parent value: %d\n", $2); + YYERROR; + } + } + ; + timeout : NUMBER { if ($1 < 0) { @@ -1378,6 +1389,7 @@ lookup(char *s) { "nodelay", NODELAY }, { "nothing", NOTHING }, { "on", ON }, + { "parent", PARENT }, { "path", PATH }, { "port", PORT }, { "prefork", PREFORK }, @@ -1729,7 +1741,7 @@ parse_config(const char *filename, int opts) { struct sym *sym, *next; struct table *nexttb; - struct host *h; + struct host *h, *ph; if ((conf = calloc(1, sizeof(*conf))) == NULL || (conf->sc_tables = calloc(1, sizeof(*conf->sc_tables))) == NULL || @@ -1833,6 +1845,26 @@ parse_config(const char *filename, int opts) free(table); continue; } + + TAILQ_FOREACH(h, &table->hosts, entry) { + if (h->conf.parentid) { + ph = host_find(conf, h->conf.parentid); + + /* Validate the parent id */ + if (h->conf.id == h->conf.parentid || + ph == NULL || ph->conf.parentid) + ph = NULL; + + if (ph == NULL) { + log_warnx("host parent id %d invalid", + h->conf.parentid); + errors++; + } else + TAILQ_INSERT_TAIL(&ph->children, + h, child); + } + } + if (!(table->conf.flags & F_USED)) { log_warnx("unused table: %s", table->conf.name); errors++; @@ -2135,6 +2167,7 @@ table_inherit(struct table *tb) } h->conf.tableid = tb->conf.id; h->tablename = tb->conf.name; + TAILQ_INIT(&h->children); TAILQ_INSERT_TAIL(&tb->hosts, h, entry); } diff --git a/usr.sbin/relayd/pfe.c b/usr.sbin/relayd/pfe.c index f905f4f85d9..f06432a6b6b 100644 --- a/usr.sbin/relayd/pfe.c +++ b/usr.sbin/relayd/pfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfe.c,v 1.48 2008/01/31 09:56:28 reyk Exp $ */ +/* $OpenBSD: pfe.c,v 1.49 2008/07/19 10:52:32 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard @@ -749,18 +749,20 @@ enable_table(struct ctl_conn *c, struct ctl_id *id) } int -disable_host(struct ctl_conn *c, struct ctl_id *id) +disable_host(struct ctl_conn *c, struct ctl_id *id, struct host *host) { - struct host *host; + struct host *h; struct table *table; int n; - if (id->id == EMPTY_ID) - host = host_findbyname(env, id->name); - else - host = host_find(env, id->id); - if (host == NULL) - return (-1); + if (host == NULL) { + if (id->id == EMPTY_ID) + host = host_findbyname(env, id->name); + else + host = host_find(env, id->id); + if (host == NULL || host->conf.parentid) + return (-1); + } id->id = host->conf.id; if (host->flags & F_DISABLE) @@ -788,22 +790,30 @@ disable_host(struct ctl_conn *c, struct ctl_id *id) IMSG_HOST_DISABLE, 0, 0, -1, &host->conf.id, sizeof(host->conf.id)); log_debug("disable_host: disabled host %d", host->conf.id); - pfe_sync(); + + /* Disable all children */ + TAILQ_FOREACH(h, &host->children, child) + disable_host(c, id, h); + + if (!host->conf.parentid) + pfe_sync(); return (0); } int -enable_host(struct ctl_conn *c, struct ctl_id *id) +enable_host(struct ctl_conn *c, struct ctl_id *id, struct host *host) { - struct host *host; + struct host *h; int n; - if (id->id == EMPTY_ID) - host = host_findbyname(env, id->name); - else - host = host_find(env, id->id); - if (host == NULL) - return (-1); + if (host == NULL) { + if (id->id == EMPTY_ID) + host = host_findbyname(env, id->name); + else + host = host_find(env, id->id); + if (host == NULL || host->conf.parentid) + return (-1); + } id->id = host->conf.id; if (!(host->flags & F_DISABLE)) @@ -822,7 +832,13 @@ enable_host(struct ctl_conn *c, struct ctl_id *id) IMSG_HOST_ENABLE, 0, 0, -1, &host->conf.id, sizeof(host->conf.id)); log_debug("enable_host: enabled host %d", host->conf.id); - pfe_sync(); + + /* Enable all children */ + TAILQ_FOREACH(h, &host->children, child) + enable_host(c, id, h); + + if (!host->conf.parentid) + pfe_sync(); return (0); } diff --git a/usr.sbin/relayd/relayd.conf.5 b/usr.sbin/relayd/relayd.conf.5 index 16c609b0f69..2611a531000 100644 --- a/usr.sbin/relayd/relayd.conf.5 +++ b/usr.sbin/relayd/relayd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: relayd.conf.5,v 1.88 2008/06/11 18:21:20 reyk Exp $ +.\" $OpenBSD: relayd.conf.5,v 1.89 2008/07/19 10:52:32 reyk Exp $ .\" .\" Copyright (c) 2006, 2007 Reyk Floeter .\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard @@ -15,7 +15,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: June 11 2008 $ +.Dd $Mdocdate: July 19 2008 $ .Dt RELAYD.CONF 5 .Os .Sh NAME @@ -183,7 +183,7 @@ The table can be later enabled through .El Each table must contain at least one host; multiple hosts are separated by newline, comma, or whitespace. -Host entries may be defined with the following attribute: +Host entries may be defined with the following attributes: .Bl -tag -width retry .It Ic retry Ar number The optional retry option adds a tolerance for failed host checks; @@ -192,6 +192,17 @@ the check will be retried for more times before setting the host state to down. If this table is used by a relay, it will also specify the number of retries for outgoing connection attempts. +.It Ic parent Ar number +The optional parent option allows to inherit the state from a parent +host with the specified identifier. +The check will be skipped for this host and copied from the parent host. +This can be used to prevent multiple checks on hosts with multiple IP +addresses for the same service. +The host identifiers are sequentially assigned to the configured hosts +starting with 1; it can be figured out with the +.Xr relayctl 8 +.Ic show summary +commands. .El .Pp For example: diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h index 1979e4285fa..763a4f58709 100644 --- a/usr.sbin/relayd/relayd.h +++ b/usr.sbin/relayd/relayd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.h,v 1.106 2008/07/09 17:16:51 reyk Exp $ */ +/* $OpenBSD: relayd.h,v 1.107 2008/07/19 10:52:32 reyk Exp $ */ /* * Copyright (c) 2006, 2007 Pierre-Yves Ritschard @@ -345,6 +345,7 @@ enum forwardmode { struct host_config { objid_t id; + objid_t parentid; objid_t tableid; int retry; char name[MAXHOSTNAMELEN]; @@ -353,6 +354,8 @@ struct host_config { struct host { TAILQ_ENTRY(host) entry; + TAILQ_ENTRY(host) child; + TAILQ_HEAD(,host) children; struct host_config conf; u_int32_t flags; char *tablename; @@ -766,10 +769,10 @@ void show(struct ctl_conn *); void show_sessions(struct ctl_conn *); int enable_rdr(struct ctl_conn *, struct ctl_id *); int enable_table(struct ctl_conn *, struct ctl_id *); -int enable_host(struct ctl_conn *, struct ctl_id *); +int enable_host(struct ctl_conn *, struct ctl_id *, struct host *); int disable_rdr(struct ctl_conn *, struct ctl_id *); int disable_table(struct ctl_conn *, struct ctl_id *); -int disable_host(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 *); -- 2.20.1