diff --git a/nest/protocol.h b/nest/protocol.h index 7ba44192..f08b3bc3 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -125,7 +125,7 @@ struct proto { void (*if_notify)(struct proto *, unsigned flags, struct iface *i); void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a); - void (*rt_notify)(struct proto *, struct network *net, struct rte *new, struct rte *old, struct ea_list *tmpa); + void (*rt_notify)(struct proto *, struct network *net, struct rte *new, struct rte *old, struct ea_list *attrs); void (*neigh_notify)(struct neighbor *neigh); struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool); void (*store_tmp_attrs)(struct rte *rt, struct ea_list *attrs); diff --git a/nest/rt-table.c b/nest/rt-table.c index d1594b32..cfaa8937 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -123,10 +123,10 @@ do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list * struct proto *p = a->proto; rte *new0 = new; rte *old0 = old; + int ok; if (new) { - int ok; if ((class & IADDR_SCOPE_MASK) < p->min_scope) { rte_trace_out(D_FILTERS, p, new, "out of scope"); @@ -148,13 +148,13 @@ do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list * } if (old && p->out_filter) { - /* FIXME: Do we really need to filter old routes? */ if (p->out_filter == FILTER_REJECT) old = NULL; else { ea_list *tmpb = p->make_tmp_attrs ? p->make_tmp_attrs(old, rte_update_pool) : NULL; - if (f_run(p->out_filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT) + ok = p->import_control ? p->import_control(p, &old, &tmpb, rte_update_pool) : 0; + if (ok < 0 || (!ok && f_run(p->out_filter, &old, &tmpb, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)) old = NULL; } } @@ -167,8 +167,20 @@ do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list * else if (old) rte_trace_out(D_ROUTES, p, old, "removed"); } - if (new || old) - p->rt_notify(p, net, new, old, tmpa); + if (!new && !old) + return; + if (!new) + p->rt_notify(p, net, NULL, old, NULL); + else if (tmpa) + { + while (tmpa->next) + tmpa = tmpa->next; + tmpa->next = new->attrs->eattrs; + p->rt_notify(p, net, new, old, tmpa); + tmpa->next = NULL; + } + else + p->rt_notify(p, net, new, old, new->attrs->eattrs); if (new && new != new0) /* Discard temporary rte's */ rte_free(new); if (old && old != old0)