diff options
Diffstat (limited to 'proto')
-rw-r--r-- | proto/pipe/config.Y | 7 | ||||
-rw-r--r-- | proto/pipe/pipe.c | 32 | ||||
-rw-r--r-- | proto/pipe/pipe.h | 2 |
3 files changed, 26 insertions, 15 deletions
diff --git a/proto/pipe/config.Y b/proto/pipe/config.Y index 1202c169..c869de9f 100644 --- a/proto/pipe/config.Y +++ b/proto/pipe/config.Y @@ -16,7 +16,7 @@ CF_DEFINES CF_DECLS -CF_KEYWORDS(PIPE, PEER, TABLE) +CF_KEYWORDS(PIPE, PEER, TABLE, MAX, GENERATION) CF_GRAMMAR @@ -25,6 +25,7 @@ proto: pipe_proto '}' { this_channel = NULL; } ; pipe_proto_start: proto_start PIPE { this_proto = proto_config_new(&proto_pipe, $1); + PIPE_CFG->max_generation = 16; } proto_name { @@ -41,6 +42,10 @@ pipe_proto: | pipe_proto proto_item ';' | pipe_proto channel_item_ ';' | pipe_proto PEER TABLE rtable ';' { PIPE_CFG->peer = $4; } + | pipe_proto MAX GENERATION expr ';' { + if (($4 < 1) || ($4 > 254)) cf_error("Max generation must be in range 1..254, got %u", $4); + PIPE_CFG->max_generation = $4; + } ; CF_CODE diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index 3caa85d0..7604cc79 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -56,15 +56,6 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, const net_addr *n, rte * if (!new && !old) return; - if (dst->table->pipe_busy) - { - log(L_ERR "Pipe loop detected when sending %N to table %s", - n, dst->table->name); - return; - } - - src_ch->table->pipe_busy = 1; - if (new) { rta *a = alloca(rta_size(new->attrs)); @@ -76,23 +67,34 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, const net_addr *n, rte * rte e0 = { .attrs = a, .src = new->src, + .generation = new->generation + 1, }; rte_update(dst, n, &e0, new->src); } else rte_update(dst, n, NULL, old->src); - - src_ch->table->pipe_busy = 0; } static int pipe_preexport(struct channel *c, rte *e) { - struct proto *pp = e->sender->proto; + struct pipe_proto *p = (void *) c->proto; + + /* Avoid direct loopbacks */ + if (e->sender == c) + return -1; - if (pp == c->proto) - return -1; /* Avoid local loops automatically */ + /* Indirection check */ + uint max_generation = ((struct pipe_config *) p->p.cf)->max_generation; + if (e->generation >= max_generation) + { + log_rl(&p->rl_gen, L_ERR "Route overpiped (%u hops of %u configured in %s) in table %s: %N %s/%u:%u", + e->generation, max_generation, c->proto->name, + c->table->name, e->net, e->src->proto->name, e->src->private_id, e->src->global_id); + + return -1; + } return 0; } @@ -177,6 +179,8 @@ pipe_init(struct proto_config *CF) P->preexport = pipe_preexport; P->reload_routes = pipe_reload_routes; + p->rl_gen = (struct tbf) TBF_DEFAULT_LOG_LIMITS; + pipe_configure_channels(p, cf); return P; diff --git a/proto/pipe/pipe.h b/proto/pipe/pipe.h index 038c6666..60c857eb 100644 --- a/proto/pipe/pipe.h +++ b/proto/pipe/pipe.h @@ -12,12 +12,14 @@ struct pipe_config { struct proto_config c; struct rtable_config *peer; /* Table we're connected to */ + u8 max_generation; }; struct pipe_proto { struct proto p; struct channel *pri; struct channel *sec; + struct tbf rl_gen; }; #endif |