Hi,

any more feedback on this diff?  I will move forward and commit this
diff soon if nobody complains before.

Reyk

On Tue, Sep 25, 2012 at 05:29:31PM +0200, Reyk Floeter wrote:
> Hi!
> 
> During n2k12, I started working on partially rewriting the relay HTTP
> handling and filter language.  The filter language will introduce a
> new grammar, better flexibility, and a reworked code path in the
> daemon itself.  One goal is to allow selection of the forwarding
> target or table with the filters, for example to send requests for
> "/images" to a different destination.
> 
> The attached diff is just a small part of the work which can go in
> seperately, but I'd like to get some feedback if it doesn't break
> anything.  The only functional difference to -current relayd is that
> it allows multiple backup tables in relay sections, eg. 
> 
> relay foo {
>       listen on 127.0.0.1 port 81
>       protocol httpfoo
> 
>       forward to <master> port 80 check tcp
>       forward to <backup_a> port 80 check tcp
> 
>       # New: if backup_a goes down, backup_b is used and so on...
>       forward to <backup_b> port 80 check tcp
>       forward to <backup_c> port 80 check tcp
> }
> 
> reyk
> 
> Index: usr.sbin/relayd/config.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/config.c,v
> retrieving revision 1.3
> diff -u -p -r1.3 config.c
> --- usr.sbin/relayd/config.c  8 May 2012 15:10:15 -0000       1.3
> +++ usr.sbin/relayd/config.c  25 Sep 2012 15:22:23 -0000
> @@ -792,11 +792,13 @@ config_getprotonode(struct relayd *env, 
>  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;
> +     struct privsep          *ps = env->sc_ps;
> +     struct ctl_relaytable    crt;
> +     struct relay_table      *rlt;
> +     int                      id;
> +     int                      fd, n, m;
> +     struct iovec             iov[4];
> +     size_t                   c;
>  
>       /* opens listening sockets etc. */
>       if (relay_privinit(rlay) == -1)
> @@ -840,6 +842,20 @@ config_setrelay(struct relayd *env, stru
>                       proc_composev_imsg(ps, id, -1, IMSG_CFG_RELAY, -1,
>                           iov, c);
>               }
> +
> +             /* Now send the tables associated to this relay */
> +             TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
> +                     crt.id = rlt->rlt_table->conf.id;
> +                     crt.relayid = rlay->rl_conf.id;
> +                     crt.mode = rlt->rlt_mode;
> +
> +                     c = 0;
> +                     iov[c].iov_base = &crt;
> +                     iov[c++].iov_len = sizeof(crt);
> +
> +                     proc_composev_imsg(ps, id, -1,
> +                         IMSG_CFG_RELAY_TABLE, -1, iov, c);
> +             }
>       }
>  
>       close(rlay->rl_s);
> @@ -875,21 +891,6 @@ config_getrelay(struct relayd *env, stru
>               }
>       }
>  
> -     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 +
> @@ -917,6 +918,7 @@ config_getrelay(struct relayd *env, stru
>               s += rlay->rl_conf.ssl_ca_len;
>       }
>  
> +     TAILQ_INIT(&rlay->rl_tables);
>       TAILQ_INSERT_TAIL(env->sc_relays, rlay, rl_entry);
>  
>       env->sc_relaycount++;
> @@ -936,5 +938,49 @@ config_getrelay(struct relayd *env, stru
>               free(rlay->rl_ssl_ca);
>       close(rlay->rl_s);
>       free(rlay);
> +     return (-1);
> +}
> +
> +int
> +config_getrelaytable(struct relayd *env, struct imsg *imsg)
> +{
> +     struct relay_table      *rlt = NULL;
> +     struct ctl_relaytable    crt;
> +     struct relay            *rlay;
> +     struct table            *table;
> +     u_int8_t                *p = imsg->data;
> +     size_t                   s;
> +
> +     IMSG_SIZE_CHECK(imsg, &crt);
> +     memcpy(&crt, p, sizeof(crt));
> +     s = sizeof(crt);
> +
> +     if ((rlay = relay_find(env, crt.relayid)) == NULL) {
> +             log_debug("%s: unknown relay", __func__);
> +             goto fail;
> +     }
> +
> +     if ((table = table_find(env, crt.id)) == NULL) {
> +             log_debug("%s: unknown table", __func__);
> +             goto fail;
> +     }
> +
> +     if ((rlt = calloc(1, sizeof(*rlt))) == NULL)
> +             goto fail;
> +
> +     rlt->rlt_table = table;
> +     rlt->rlt_mode = crt.mode;
> +
> +     TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry);
> +
> +     DPRINTF("%s: %s %d received relay table %s for relay %s", __func__,
> +         env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
> +         table->conf.name, rlay->rl_conf.name);
> +
> +     return (0);
> +
> + fail:
> +     if (rlt != NULL)
> +             free(rlt);
>       return (-1);
>  }
> Index: usr.sbin/relayd/parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/parse.y,v
> retrieving revision 1.164
> diff -u -p -r1.164 parse.y
> --- usr.sbin/relayd/parse.y   29 May 2012 23:46:50 -0000      1.164
> +++ usr.sbin/relayd/parse.y   25 Sep 2012 15:22:24 -0000
> @@ -108,6 +108,7 @@ static struct router      *router = NULL;
>  static u_int16_t      label = 0;
>  static in_port_t      tableport = 0;
>  static int            nodedirection;
> +static int            dstmode;
>  
>  struct address       *host_v4(const char *);
>  struct address       *host_v6(const char *);
> @@ -576,6 +577,7 @@ tabledef  : TABLE table           {
>                           sizeof(struct timeval));
>                       TAILQ_INIT(&tb->hosts);
>                       table = tb;
> +                     dstmode = RELAY_DSTMODE_DEFAULT;
>               } tabledefopts_l        {
>                       if (TAILQ_EMPTY(&table->hosts)) {
>                               yyerror("table %s has no hosts",
> @@ -679,8 +681,7 @@ tableopts : CHECK tablecheck
>                               }
>                               /* FALLTHROUGH */
>                       case RELAY_DSTMODE_ROUNDROBIN:
> -                             if (rlay != NULL)
> -                                     rlay->rl_conf.dstmode = $2;
> +                             dstmode = $2;
>                               break;
>                       }
>               }
> @@ -1223,14 +1224,14 @@ relay         : RELAY STRING  {
>                       r->rl_conf.timeout.tv_sec = RELAY_TIMEOUT;
>                       r->rl_proto = NULL;
>                       r->rl_conf.proto = EMPTY_ID;
> -                     r->rl_conf.dsttable = EMPTY_ID;
> -                     r->rl_conf.dstmode = RELAY_DSTMODE_DEFAULT;
>                       r->rl_conf.dstretry = 0;
> +                     TAILQ_INIT(&r->rl_tables);
>                       if (last_relay_id == INT_MAX) {
>                               yyerror("too many relays defined");
>                               free(r);
>                               YYERROR;
>                       }
> +                     dstmode = RELAY_DSTMODE_DEFAULT;
>                       rlay = r;
>               } '{' optnl relayopts_l '}'     {
>                       struct relay    *r;
> @@ -1248,16 +1249,11 @@ relay         : RELAY STRING  {
>                       }
>                       if ((rlay->rl_conf.flags & (F_NATLOOK|F_DIVERT)) == 0 &&
>                           rlay->rl_conf.dstss.ss_family == AF_UNSPEC &&
> -                         rlay->rl_conf.dsttable == EMPTY_ID) {
> +                         TAILQ_EMPTY(&rlay->rl_tables)) {
>                               yyerror("relay %s has no target, rdr, "
>                                   "or table", rlay->rl_conf.name);
>                               YYERROR;
>                       }
> -                     if (rlay->rl_backuptable == NULL) {
> -                             rlay->rl_conf.backuptable =
> -                                 conf->sc_empty_table.conf.id;
> -                             rlay->rl_backuptable = &conf->sc_empty_table;
> -                     }
>                       if (rlay->rl_conf.proto == EMPTY_ID) {
>                               rlay->rl_proto = &conf->sc_proto_default;
>                               rlay->rl_conf.proto = conf->sc_proto_default.id;
> @@ -1415,20 +1411,21 @@ forwardspec   : STRING port retry     {
>                       rlay->rl_conf.dstretry = $2;
>               }
>               | tablespec     {
> -                     if (rlay->rl_backuptable) {
> -                             yyerror("only one backup table is allowed");
> +                     struct relay_table      *rlt;
> +
> +                     if ((rlt = calloc(1, sizeof(*rlt))) == NULL) {
> +                             yyerror("failed to allocate table reference");
>                               YYERROR;
>                       }
> -                     if (rlay->rl_dsttable) {
> -                             rlay->rl_backuptable = $1;
> -                             rlay->rl_backuptable->conf.flags |= F_USED;
> -                             rlay->rl_conf.backuptable = $1->conf.id;
> -                     } else {
> -                             rlay->rl_dsttable = $1;
> -                             rlay->rl_dsttable->conf.flags |= F_USED;
> -                             rlay->rl_conf.dsttable = $1->conf.id;
> -                             rlay->rl_conf.dstport = $1->conf.port;
> -                     }
> +
> +                     rlt->rlt_table = $1;
> +                     rlt->rlt_table->conf.flags |= F_USED;
> +                     rlt->rlt_mode = dstmode;
> +                     rlt->rlt_flags = F_USED;
> +                     if (!TAILQ_EMPTY(&rlay->rl_tables))
> +                             rlt->rlt_flags |= F_BACKUP;
> +
> +                     TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry);
>               }
>               ;
>  
> @@ -2211,9 +2208,10 @@ parse_config(const char *filename, struc
>  int
>  load_config(const char *filename, struct relayd *x_conf)
>  {
> -     struct sym      *sym, *next;
> -     struct table    *nexttb;
> -     struct host     *h, *ph;
> +     struct sym              *sym, *next;
> +     struct table            *nexttb;
> +     struct host             *h, *ph;
> +     struct relay_table      *rlt;
>  
>       conf = x_conf;
>       conf->sc_flags = 0;
> @@ -2266,6 +2264,10 @@ load_config(const char *filename, struct
>       /* Cleanup relay list to inherit */
>       while ((rlay = TAILQ_FIRST(&relays)) != NULL) {
>               TAILQ_REMOVE(&relays, rlay, rl_entry);
> +             while ((rlt = TAILQ_FIRST(&rlay->rl_tables))) {
> +                     TAILQ_REMOVE(&rlay->rl_tables, rlt, rlt_entry);
> +                     free(rlt);
> +             }
>               free(rlay);
>       }
>  
> @@ -2717,6 +2719,7 @@ struct relay *
>  relay_inherit(struct relay *ra, struct relay *rb)
>  {
>       struct relay_config      rc;
> +     struct relay_table      *rta, *rtb;
>  
>       bcopy(&rb->rl_conf, &rc, sizeof(rc));
>       bcopy(ra, rb, sizeof(*rb));
> @@ -2725,6 +2728,7 @@ relay_inherit(struct relay *ra, struct r
>       rb->rl_conf.port = rc.port;
>       rb->rl_conf.flags =
>           (ra->rl_conf.flags & ~F_SSL) | (rc.flags & F_SSL);
> +     TAILQ_INIT(&rb->rl_tables);
>  
>       rb->rl_conf.id = ++last_relay_id;
>       if (last_relay_id == INT_MAX) {
> @@ -2750,6 +2754,17 @@ relay_inherit(struct relay *ra, struct r
>               goto err;
>       }
>  
> +     TAILQ_FOREACH(rta, &ra->rl_tables, rlt_entry) {
> +             if ((rtb = calloc(1, sizeof(*rtb))) == NULL) {
> +                     yyerror("cannot allocate relay table");
> +                     goto err;
> +             }
> +             rtb->rlt_table = rta->rlt_table;
> +             rtb->rlt_mode = rta->rlt_mode;
> +
> +             TAILQ_INSERT_TAIL(&rb->rl_tables, rtb, rlt_entry);
> +     }
> +
>       conf->sc_relaycount++;
>       SPLAY_INIT(&rlay->rl_sessions);
>       TAILQ_INSERT_TAIL(conf->sc_relays, rb, rl_entry);
> @@ -2757,6 +2772,10 @@ relay_inherit(struct relay *ra, struct r
>       return (rb);
>  
>   err:
> +     while ((rtb = TAILQ_FIRST(&rb->rl_tables))) {
> +             TAILQ_REMOVE(&rb->rl_tables, rtb, rlt_entry);
> +             free(rtb);
> +     }
>       free(rb);
>       return (NULL);
>  }
> Index: usr.sbin/relayd/pfe.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/pfe.c,v
> retrieving revision 1.72
> diff -u -p -r1.72 pfe.c
> --- usr.sbin/relayd/pfe.c     21 Jan 2012 13:40:48 -0000      1.72
> +++ usr.sbin/relayd/pfe.c     25 Sep 2012 15:22:24 -0000
> @@ -199,6 +199,9 @@ pfe_dispatch_parent(int fd, struct privs
>       case IMSG_CFG_RELAY:
>               config_getrelay(env, imsg);
>               break;
> +     case IMSG_CFG_RELAY_TABLE:
> +             config_getrelaytable(env, imsg);
> +             break;
>       case IMSG_CFG_DONE:
>               config_getcfg(env, imsg);
>               init_filter(env, imsg->fd);
> @@ -291,11 +294,12 @@ pfe_dispatch_relay(int fd, struct privse
>  void
>  show(struct ctl_conn *c)
>  {
> -     struct rdr      *rdr;
> -     struct host     *host;
> -     struct relay    *rlay;
> -     struct router   *rt;
> -     struct netroute *nr;
> +     struct rdr              *rdr;
> +     struct host             *host;
> +     struct relay            *rlay;
> +     struct router           *rt;
> +     struct netroute         *nr;
> +     struct relay_table      *rlt;
>  
>       if (env->sc_rdrs == NULL)
>               goto relays;
> @@ -334,23 +338,16 @@ relays:
>               imsg_compose_event(&c->iev, IMSG_CTL_RELAY_STATS, 0, 0, -1,
>                   &rlay->rl_stats, sizeof(rlay->rl_stats));
>  
> -             if (rlay->rl_dsttable == NULL)
> -                     continue;
> -             imsg_compose_event(&c->iev, IMSG_CTL_TABLE, 0, 0, -1,
> -                 rlay->rl_dsttable, sizeof(*rlay->rl_dsttable));
> -             if (!(rlay->rl_dsttable->conf.flags & F_DISABLE))
> -                     TAILQ_FOREACH(host, &rlay->rl_dsttable->hosts, entry)
> -                             imsg_compose_event(&c->iev, IMSG_CTL_HOST,
> -                                 0, 0, -1, host, sizeof(*host));
> -
> -             if (rlay->rl_conf.backuptable == EMPTY_TABLE)
> -                     continue;
> -             imsg_compose_event(&c->iev, IMSG_CTL_TABLE, 0, 0, -1,
> -                 rlay->rl_backuptable, sizeof(*rlay->rl_backuptable));
> -             if (!(rlay->rl_backuptable->conf.flags & F_DISABLE))
> -                     TAILQ_FOREACH(host, &rlay->rl_backuptable->hosts, entry)
> -                             imsg_compose_event(&c->iev, IMSG_CTL_HOST,
> -                                 0, 0, -1, host, sizeof(*host));
> +             TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
> +                     imsg_compose_event(&c->iev, IMSG_CTL_TABLE, 0, 0, -1,
> +                         rlt->rlt_table, sizeof(*rlt->rlt_table));
> +                     if (!(rlt->rlt_table->conf.flags & F_DISABLE))
> +                             TAILQ_FOREACH(host,
> +                                 &rlt->rlt_table->hosts, entry)
> +                                     imsg_compose_event(&c->iev,
> +                                         IMSG_CTL_HOST, 0, 0, -1,
> +                                         host, sizeof(*host));
> +             }
>       }
>  
>  routers:
> Index: usr.sbin/relayd/relay.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/relay.c,v
> retrieving revision 1.153
> diff -u -p -r1.153 relay.c
> --- usr.sbin/relayd/relay.c   21 Sep 2012 09:56:27 -0000      1.153
> +++ usr.sbin/relayd/relay.c   25 Sep 2012 15:22:24 -0000
> @@ -374,40 +374,41 @@ relay_statistics(int fd, short events, v
>  void
>  relay_launch(void)
>  {
> -     void            (*callback)(int, short, void *);
> -     struct relay    *rlay;
> -     struct host     *host;
> +     void                    (*callback)(int, short, void *);
> +     struct relay            *rlay;
> +     struct host             *host;
> +     struct relay_table      *rlt;
>  
>       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) {
> +             TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
> +                     switch (rlt->rlt_mode) {
>                       case RELAY_DSTMODE_ROUNDROBIN:
> -                             rlay->rl_dstkey = 0;
> +                             rlt->rlt_key = 0;
>                               break;
>                       case RELAY_DSTMODE_LOADBALANCE:
>                       case RELAY_DSTMODE_HASH:
> -                             rlay->rl_dstkey =
> +                             rlt->rlt_key =
>                                   hash32_str(rlay->rl_conf.name, HASHINIT);
> -                             rlay->rl_dstkey =
> -                                 hash32_str(rlay->rl_dsttable->conf.name,
> -                                 rlay->rl_dstkey);
> +                             rlt->rlt_key =
> +                                 hash32_str(rlt->rlt_table->conf.name,
> +                                 rlt->rlt_key);
>                               break;
>                       }
> -                     rlay->rl_dstnhosts = 0;
> -                     TAILQ_FOREACH(host, &rlay->rl_dsttable->hosts, entry) {
> -                             if (rlay->rl_dstnhosts >= RELAY_MAXHOSTS)
> +                     rlt->rlt_nhosts = 0;
> +                     TAILQ_FOREACH(host, &rlt->rlt_table->hosts, entry) {
> +                             if (rlt->rlt_nhosts >= RELAY_MAXHOSTS)
>                                       fatal("relay_init: "
>                                           "too many hosts in table");
> -                             host->idx = rlay->rl_dstnhosts;
> -                             rlay->rl_dsthost[rlay->rl_dstnhosts++] = host;
> +                             host->idx = rlt->rlt_nhosts;
> +                             rlt->rlt_host[rlt->rlt_nhosts++] = 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)");
> +                         rlt->rlt_nhosts, rlt->rlt_table->conf.name,
> +                         rlt->rlt_table->conf.check ? "" : " (no check)");
>               }
>  
>               switch (rlay->rl_proto->type) {
> @@ -976,7 +977,6 @@ relay_accept(int fd, short event, void *
>       con->se_id = ++relay_conid;
>       con->se_relayid = rlay->rl_conf.id;
>       con->se_pid = getpid();
> -     con->se_hashkey = rlay->rl_dstkey;
>       con->se_in.tree = &proto->request_tree;
>       con->se_out.tree = &proto->response_tree;
>       con->se_in.dir = RELAY_DIR_REQUEST;
> @@ -1104,22 +1104,46 @@ relay_from_table(struct rsession *con)
>  {
>       struct relay            *rlay = (struct relay *)con->se_relay;
>       struct host             *host;
> -     struct table            *table = rlay->rl_dsttable;
> +     struct relay_table      *rlt = NULL;
> +     struct table            *table = NULL;
>       u_int32_t                p = con->se_hashkey;
>       int                      idx = 0;
>  
> -     if (table->conf.check && !table->up && !rlay->rl_backuptable->up) {
> -             log_debug("%s: no active hosts", __func__);
> +     /* the table is already selected */
> +     if (con->se_table != NULL) {
> +             rlt = con->se_table;
> +             table = rlt->rlt_table;
> +             if (table->conf.check && !table->up)
> +                     table = NULL;
> +             goto gottable;
> +     }
> +
> +     /* otherwise grep the first active table */
> +     TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
> +             table = rlt->rlt_table;
> +             if ((rlt->rlt_flags & F_USED == 0) ||
> +                 (table->conf.check && !table->up))
> +                     table = NULL;
> +             else
> +                     break;
> +     }
> +
> + gottable:
> +     if (table == NULL) {
> +             log_debug("%s: session %d: no active hosts",
> +                 __func__, con->se_id);
>               return (-1);
> -     } else if (!table->up && rlay->rl_backuptable->up) {
> -             table = rlay->rl_backuptable;
> +     }
> +     if (!con->se_hashkeyset) {
> +             p = con->se_hashkey = rlt->rlt_key;
> +             con->se_hashkeyset = 1;
>       }
>  
> -     switch (rlay->rl_conf.dstmode) {
> +     switch (rlt->rlt_mode) {
>       case RELAY_DSTMODE_ROUNDROBIN:
> -             if ((int)rlay->rl_dstkey >= rlay->rl_dstnhosts)
> -                     rlay->rl_dstkey = 0;
> -             idx = (int)rlay->rl_dstkey;
> +             if ((int)rlt->rlt_key >= rlt->rlt_nhosts)
> +                     rlt->rlt_key = 0;
> +             idx = (int)rlt->rlt_key;
>               break;
>       case RELAY_DSTMODE_LOADBALANCE:
>               p = relay_hash_addr(&con->se_in.ss, p);
> @@ -1128,14 +1152,15 @@ relay_from_table(struct rsession *con)
>               p = relay_hash_addr(&rlay->rl_conf.ss, p);
>               p = hash32_buf(&rlay->rl_conf.port,
>                   sizeof(rlay->rl_conf.port), p);
> -             if ((idx = p % rlay->rl_dstnhosts) >= RELAY_MAXHOSTS)
> +             if ((idx = p % rlt->rlt_nhosts) >= RELAY_MAXHOSTS)
>                       return (-1);
>       }
> -     host = rlay->rl_dsthost[idx];
> -     DPRINTF("%s: host %s, p 0x%08x, idx %d", __func__,
> -         host->conf.name, p, idx);
> +     host = rlt->rlt_host[idx];
> +     DPRINTF("%s: session %d: table %s host %s, p 0x%08x, idx %d",
> +         __func__, con->se_id, table->conf.name, host->conf.name, p, idx);
>       while (host != NULL) {
> -             DPRINTF("%s: host %s", __func__, host->conf.name);
> +             DPRINTF("%s: session %d: host %s", __func__,
> +                 con->se_id, host->conf.name);
>               if (!table->conf.check || host->up == HOST_UP)
>                       goto found;
>               host = TAILQ_NEXT(host, entry);
> @@ -1150,8 +1175,8 @@ relay_from_table(struct rsession *con)
>       fatalx("relay_from_table: no active hosts, desynchronized");
>  
>   found:
> -     if (rlay->rl_conf.dstmode == RELAY_DSTMODE_ROUNDROBIN)
> -             rlay->rl_dstkey = host->idx + 1;
> +     if (rlt->rlt_mode == RELAY_DSTMODE_ROUNDROBIN)
> +             rlt->rlt_key = host->idx + 1;
>       con->se_retry = host->conf.retry;
>       con->se_out.port = table->conf.port;
>       bcopy(&host->conf.ss, &con->se_out.ss, sizeof(con->se_out.ss));
> @@ -1171,7 +1196,7 @@ relay_natlook(int fd, short event, void 
>  
>       if (con->se_out.ss.ss_family == AF_UNSPEC && cnl->in == -1 &&
>           rlay->rl_conf.dstss.ss_family == AF_UNSPEC &&
> -         rlay->rl_dsttable == NULL) {
> +         TAILQ_EMPTY(&rlay->rl_tables)) {
>               relay_close(con, "session NAT lookup failed");
>               return;
>       }
> @@ -1355,7 +1380,7 @@ relay_connect(struct rsession *con)
>       if (gettimeofday(&con->se_tv_start, NULL) == -1)
>               return (-1);
>  
> -     if (rlay->rl_dsttable != NULL) {
> +     if (!TAILQ_EMPTY(&rlay->rl_tables)) {
>               if (relay_from_table(con) != 0)
>                       return (-1);
>       } else if (con->se_out.ss.ss_family == AF_UNSPEC) {
> @@ -1690,6 +1715,9 @@ relay_dispatch_parent(int fd, struct pri
>               return (config_getprotonode(env, imsg));
>       case IMSG_CFG_RELAY:
>               config_getrelay(env, imsg);
> +             break;
> +     case IMSG_CFG_RELAY_TABLE:
> +             config_getrelaytable(env, imsg);
>               break;
>       case IMSG_CFG_DONE:
>               config_getcfg(env, imsg);
> Index: usr.sbin/relayd/relay_udp.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/relay_udp.c,v
> retrieving revision 1.24
> diff -u -p -r1.24 relay_udp.c
> --- usr.sbin/relayd/relay_udp.c       9 May 2011 12:08:47 -0000       1.24
> +++ usr.sbin/relayd/relay_udp.c       25 Sep 2012 15:22:24 -0000
> @@ -249,7 +249,6 @@ relay_udp_server(int fd, short sig, void
>       con->se_in.con = con;
>       con->se_out.con = con;
>       con->se_relay = rlay;
> -     con->se_hashkey = rlay->rl_dstkey;
>       con->se_id = ++relay_conid;
>       con->se_in.tree = &proto->request_tree;
>       con->se_out.tree = &proto->response_tree;
> @@ -474,7 +473,7 @@ relay_dns_request(struct rsession *con)
>       if (gettimeofday(&con->se_tv_start, NULL) == -1)
>               return (-1);
>  
> -     if (rlay->rl_dsttable != NULL) {
> +     if (!TAILQ_EMPTY(&rlay->rl_tables)) {
>               if (relay_from_table(con) != 0)
>                       return (-1);
>       } else if (con->se_out.ss.ss_family == AF_UNSPEC) {
> Index: usr.sbin/relayd/relayd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/relayd.c,v
> retrieving revision 1.109
> diff -u -p -r1.109 relayd.c
> --- usr.sbin/relayd/relayd.c  21 Sep 2012 09:56:27 -0000      1.109
> +++ usr.sbin/relayd/relayd.c  25 Sep 2012 15:22:25 -0000
> @@ -564,6 +564,7 @@ void
>  purge_relay(struct relayd *env, struct relay *rlay)
>  {
>       struct rsession         *con;
> +     struct relay_table      *rlt;
>  
>       /* shutdown and remove relay */
>       if (event_initialized(&rlay->rl_ev))
> @@ -590,6 +591,11 @@ purge_relay(struct relayd *env, struct r
>               free(rlay->rl_ssl_key);
>       if (rlay->rl_ssl_ca != NULL)
>               free(rlay->rl_ssl_ca);
> +
> +     while ((rlt = TAILQ_FIRST(&rlay->rl_tables))) {
> +             TAILQ_REMOVE(&rlay->rl_tables, rlt, rlt_entry);
> +             free(rlt);
> +     }
>  
>       free(rlay);
>  }
> Index: usr.sbin/relayd/relayd.conf.5
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/relayd.conf.5,v
> retrieving revision 1.129
> diff -u -p -r1.129 relayd.conf.5
> --- usr.sbin/relayd/relayd.conf.5     24 Aug 2012 20:13:03 -0000      1.129
> +++ usr.sbin/relayd/relayd.conf.5     25 Sep 2012 15:22:25 -0000
> @@ -596,8 +596,9 @@ Like the previous directive, but connect
>  table; see the
>  .Sx TABLES
>  section above for information about table options.
> -This directive can be specified twice \(en the second entry will be used
> -as the backup table if all hosts in the main table are down.
> +This directive can be specified multiple times \(en subsequent entries
> +will be used as the backup table if all hosts in the previous table
> +are down.
>  At least one entry for the main table is mandatory.
>  .It Xo
>  .Ic forward to
> Index: usr.sbin/relayd/relayd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v
> retrieving revision 1.158
> diff -u -p -r1.158 relayd.h
> --- usr.sbin/relayd/relayd.h  21 Sep 2012 09:56:27 -0000      1.158
> +++ usr.sbin/relayd/relayd.h  25 Sep 2012 15:22:25 -0000
> @@ -108,6 +108,12 @@ struct ctl_id {
>       char             name[MAX_NAME_SIZE];
>  };
>  
> +struct ctl_relaytable {
> +     objid_t          id;
> +     objid_t          relayid;
> +     int              mode;
> +};
> +
>  struct ctl_script {
>       objid_t          host;
>       int              retval;
> @@ -430,6 +436,8 @@ struct rsession {
>       struct ctl_relay_event           se_out;
>       void                            *se_priv;
>       u_int32_t                        se_hashkey;
> +     int                              se_hashkeyset;
> +     struct relay_table              *se_table;
>       struct event                     se_ev;
>       struct timeval                   se_timeout;
>       struct timeval                   se_tv_start;
> @@ -580,6 +588,17 @@ struct protocol {
>  };
>  TAILQ_HEAD(protolist, protocol);
>  
> +struct relay_table {
> +     struct table            *rlt_table;
> +     u_int32_t                rlt_flags;
> +     int                      rlt_mode;
> +     u_int32_t                rlt_key;
> +     struct host             *rlt_host[RELAY_MAXHOSTS];
> +     int                      rlt_nhosts;
> +     TAILQ_ENTRY(relay_table) rlt_entry;
> +};
> +TAILQ_HEAD(relaytables, relay_table);
> +
>  struct relay_config {
>       objid_t                  id;
>       u_int32_t                flags;
> @@ -588,10 +607,7 @@ struct relay_config {
>       char                     ifname[IFNAMSIZ];
>       in_port_t                port;
>       in_port_t                dstport;
> -     int                      dstmode;
>       int                      dstretry;
> -     objid_t                  dsttable;
> -     objid_t                  backuptable;
>       struct sockaddr_storage  ss;
>       struct sockaddr_storage  dstss;
>       struct sockaddr_storage  dstaf;
> @@ -614,11 +630,7 @@ struct relay {
>       int                      rl_dsts;
>       struct bufferevent      *rl_dstbev;
>  
> -     struct table            *rl_dsttable;
> -     struct table            *rl_backuptable;
> -     u_int32_t                rl_dstkey;
> -     struct host             *rl_dsthost[RELAY_MAXHOSTS];
> -     int                      rl_dstnhosts;
> +     struct relaytables       rl_tables;
>  
>       struct event             rl_ev;
>       struct event             rl_evt;
> @@ -789,6 +801,7 @@ enum imsg_type {
>       IMSG_CFG_PROTO,
>       IMSG_CFG_PROTONODE,
>       IMSG_CFG_RELAY,
> +     IMSG_CFG_RELAY_TABLE,
>       IMSG_CFG_DONE
>  };
>  
> @@ -1148,5 +1161,6 @@ int      config_setprotonode(struct relayd *
>  int   config_getprotonode(struct relayd *, struct imsg *);
>  int   config_setrelay(struct relayd *env, struct relay *);
>  int   config_getrelay(struct relayd *, struct imsg *);
> +int   config_getrelaytable(struct relayd *, struct imsg *);
>  
>  #endif /* _RELAYD_H */

Reply via email to