diff options
Diffstat (limited to 'nest/rt-table.c')
-rw-r--r-- | nest/rt-table.c | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c index 9e9d4c7a..eb9dc3a5 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -50,7 +50,7 @@ static linpool *rte_update_pool; static list routing_tables; -static void rt_format_via(rte *e, byte *via); +static byte *rt_format_via(rte *e); static void rt_free_hostcache(rtable *tab); static void rt_notify_hostcache(rtable *tab, net *net); static void rt_update_hostcache(rtable *tab); @@ -346,10 +346,7 @@ rte_mergable(rte *pri, rte *sec) static void rte_trace(struct proto *p, rte *e, int dir, char *msg) { - byte via[IPA_MAX_TEXT_LENGTH+32]; - - rt_format_via(e, via); - log(L_TRACE "%s %c %s %N %s", p->name, dir, msg, e->net->n.addr, via); + log(L_TRACE "%s %c %s %N %s", p->name, dir, msg, e->net->n.addr, rt_format_via(e)); } static inline void @@ -367,7 +364,7 @@ rte_trace_out(uint flag, struct proto *p, rte *e, char *msg) } static rte * -export_filter(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, int silent) +export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpool *pool, int silent) { struct proto *p = c->proto; struct filter *filter = c->out_filter; @@ -382,9 +379,9 @@ export_filter(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, int si if (!tmpa) tmpa = &tmpb; - *tmpa = make_tmp_attrs(rt, rte_update_pool); + *tmpa = make_tmp_attrs(rt, pool); - v = p->import_control ? p->import_control(p, &rt, tmpa, rte_update_pool) : 0; + v = p->import_control ? p->import_control(p, &rt, tmpa, pool) : 0; if (v < 0) { if (silent) @@ -403,7 +400,7 @@ export_filter(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, int si } v = filter && ((filter == FILTER_REJECT) || - (f_run(filter, &rt, tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)); + (f_run(filter, &rt, tmpa, pool, FF_FORCE_TMPATTR) > F_ACCEPT)); if (v) { if (silent) @@ -426,6 +423,12 @@ export_filter(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, int si return NULL; } +static inline rte * +export_filter(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, int silent) +{ + return export_filter_(c, rt0, rt_free, tmpa, rte_update_pool, silent); +} + static void do_rt_notify(struct channel *c, net *net, rte *new, rte *old, ea_list *tmpa, int refeed) { @@ -706,7 +709,7 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang static struct mpnh * -mpnh_merge_rta(struct mpnh *nhs, rta *a, int max) +mpnh_merge_rta(struct mpnh *nhs, rta *a, linpool *pool, int max) { struct mpnh nh = { .gw = a->gw, .iface = a->iface }; struct mpnh *nh2 = (a->dest == RTD_MULTIPATH) ? a->nexthops : &nh; @@ -714,7 +717,7 @@ mpnh_merge_rta(struct mpnh *nhs, rta *a, int max) } rte * -rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, int silent) +rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, linpool *pool, int silent) { // struct proto *p = c->proto; struct mpnh *nhs = NULL; @@ -726,7 +729,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, int if (!rte_is_valid(best0)) return NULL; - best = export_filter(c, best0, rt_free, tmpa, silent); + best = export_filter_(c, best0, rt_free, tmpa, pool, silent); if (!best || !rte_is_reachable(best)) return best; @@ -736,13 +739,13 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, int if (!rte_mergable(best0, rt0)) continue; - rt = export_filter(c, rt0, &tmp, NULL, 1); + rt = export_filter_(c, rt0, &tmp, NULL, pool, 1); if (!rt) continue; if (rte_is_reachable(rt)) - nhs = mpnh_merge_rta(nhs, rt->attrs, c->merge_limit); + nhs = mpnh_merge_rta(nhs, rt->attrs, pool, c->merge_limit); if (tmp) rte_free(tmp); @@ -750,11 +753,11 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, int if (nhs) { - nhs = mpnh_merge_rta(nhs, best->attrs, c->merge_limit); + nhs = mpnh_merge_rta(nhs, best->attrs, pool, c->merge_limit); if (nhs->next) { - best = rte_cow_rta(best, rte_update_pool); + best = rte_cow_rta(best, pool); best->attrs->dest = RTD_MULTIPATH; best->attrs->nexthops = nhs; } @@ -805,7 +808,7 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed /* Prepare new merged route */ if (new_best) - new_best = rt_export_merged(c, net, &new_best_free, &tmpa, 0); + new_best = rt_export_merged(c, net, &new_best_free, &tmpa, rte_update_pool, 0); /* Prepare old merged route (without proper merged next hops) */ /* There are some issues with running filter on old route - see rt_notify_basic() */ @@ -919,6 +922,13 @@ rte_validate(rte *e) return 0; } + if ((e->attrs->dest == RTD_MULTIPATH) && !mpnh_is_sorted(e->attrs->nexthops)) + { + log(L_WARN "Ignoring unsorted multipath route %N received via %s", + n->n.addr, e->sender->proto->name); + return 0; + } + return 1; } @@ -1848,7 +1858,7 @@ rt_next_hop_update_net(rtable *tab, net *n) /* FIXME: Better announcement of merged routes */ rte_announce_i(tab, RA_MERGED, n, new, old_best, new, old_best); - if (free_old_best) + if (free_old_best) rte_free_quick(old_best); return count; @@ -2426,11 +2436,14 @@ rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_add * CLI commands */ -static void -rt_format_via(rte *e, byte *via) +static byte * +rt_format_via(rte *e) { rta *a = e->attrs; + /* Max text length w/o IP addr and interface name is 16 */ + static byte via[IPA_MAX_TEXT_LENGTH+sizeof(a->iface->name)+16]; + switch (a->dest) { case RTD_ROUTER: bsprintf(via, "via %I on %s", a->gw, a->iface->name); break; @@ -2441,12 +2454,12 @@ rt_format_via(rte *e, byte *via) case RTD_MULTIPATH: bsprintf(via, "multipath"); break; default: bsprintf(via, "???"); } + return via; } static void rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa) { - byte via[IPA_MAX_TEXT_LENGTH+32]; byte from[IPA_MAX_TEXT_LENGTH+8]; byte tm[TM_DATETIME_BUFFER_SIZE], info[256]; rta *a = e->attrs; @@ -2455,7 +2468,6 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); struct mpnh *nh; - rt_format_via(e, via); tm_format_datetime(tm, &config->tf_route, e->lastmod); if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw)) bsprintf(from, " from %I", a->from); @@ -2476,7 +2488,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm get_route_info(e, info, tmpa); else bsprintf(info, " (%d)", e->pref); - cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, via, a->src->proto->name, + cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, rt_format_via(e), a->src->proto->name, tm, from, primary ? (sync_error ? " !" : " *") : "", info); for (nh = a->nexthops; nh; nh = nh->next) cli_printf(c, -1007, "\tvia %I on %s weight %d", nh->gw, nh->iface->name, nh->weight + 1); @@ -2517,7 +2529,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_MERGED)) { rte *rt_free; - e = rt_export_merged(ec, n, &rt_free, &tmpa, 1); + e = rt_export_merged(ec, n, &rt_free, &tmpa, rte_update_pool, 1); pass = 1; if (!e) |