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 */