If the new 'parent' keyword is specified for a host in a table,
authorreyk <reyk@openbsd.org>
Sat, 19 Jul 2008 10:52:32 +0000 (10:52 +0000)
committerreyk <reyk@openbsd.org>
Sat, 19 Jul 2008 10:52:32 +0000 (10:52 +0000)
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
usr.sbin/relayd/control.c
usr.sbin/relayd/hce.c
usr.sbin/relayd/parse.y
usr.sbin/relayd/pfe.c
usr.sbin/relayd/relayd.conf.5
usr.sbin/relayd/relayd.h

index f16e9bd..c022077 100644 (file)
@@ -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 <pyr@openbsd.org>
@@ -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)
index d0c7258..67be0a1 100644 (file)
@@ -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 <henning@openbsd.org>
@@ -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 {
index f0cd92c..262f7f6 100644 (file)
@@ -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 <pyr@openbsd.org>
@@ -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
index 3c7cb2b..9a881ed 100644 (file)
@@ -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 <reyk@openbsd.org>
@@ -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 <v.string>      STRING
 %token  <v.number>     NUMBER
 %type  <v.string>      interface hostname table
-%type  <v.number>      port http_type loglevel sslcache optssl mark
+%type  <v.number>      port http_type loglevel sslcache optssl mark parent
 %type  <v.number>      proto_type dstmode retry log flag direction forwardmode
 %type  <v.host>        host
 %type  <v.tv>          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);
        }
 
index f905f4f..f06432a 100644 (file)
@@ -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 <pyr@openbsd.org>
@@ -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);
 }
 
index 16c609b..2611a53 100644 (file)
@@ -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 <reyk@openbsd.org>
 .\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -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:
index 1979e42..763a4f5 100644 (file)
@@ -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 <pyr@openbsd.org>
@@ -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 *);