summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/route.h7
-rw-r--r--nest/rt-table.c37
2 files changed, 40 insertions, 4 deletions
diff --git a/nest/route.h b/nest/route.h
index 177baa38..8fd01a66 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -235,6 +235,12 @@ static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED);
#define RA_ACCEPTED 2 /* Announcement of first accepted route */
#define RA_ANY 3 /* Announcement of any route change */
+/* Return value of import_control() callback */
+#define RIC_ACCEPT 1 /* Accepted by protocol */
+#define RIC_PROCESS 0 /* Process it through import filter */
+#define RIC_REJECT -1 /* Rejected by protocol */
+#define RIC_DROP -2 /* Silently dropped by protocol */
+
struct config;
void rt_init(void);
@@ -250,6 +256,7 @@ rte *rte_get_temp(struct rta *);
void rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src);
static inline void rte_update(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new) { rte_update2(p->main_ahook, net, new, src); }
void rte_discard(rtable *tab, rte *old);
+int rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter *filter);
void rte_dump(rte *);
void rte_free(rte *);
rte *rte_do_cow(rte *);
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 99175448..75bfa6ba 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -213,7 +213,8 @@ export_filter(struct announce_hook *ah, rte *rt0, rte **rt_free, ea_list **tmpa,
goto reject;
stats->exp_updates_rejected++;
- rte_trace_out(D_FILTERS, p, rt, "rejected by protocol");
+ if (v == RIC_REJECT)
+ rte_trace_out(D_FILTERS, p, rt, "rejected by protocol");
goto reject;
}
if (v > 0)
@@ -1042,6 +1043,34 @@ rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during gar
rte_update_unlock();
}
+/* Check rtable for best route to given net whether it would be exported do p */
+int
+rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter *filter)
+{
+ net *n = net_find(t, prefix, pxlen);
+ rte *rt = n ? n->routes : NULL;
+
+ if (!rte_is_valid(rt))
+ return 0;
+
+ rte_update_lock();
+
+ /* Rest is stripped down export_filter() */
+ struct proto *src = rt->attrs->proto;
+ ea_list *tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(rt, rte_update_pool) : NULL;
+ int v = p->import_control ? p->import_control(p, &rt, &tmpa, rte_update_pool) : 0;
+ if (v == RIC_PROCESS)
+ v = (f_run(filter, &rt, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
+
+ /* Discard temporary rte */
+ if (rt != n->routes)
+ rte_free(rt);
+
+ rte_update_unlock();
+
+ return v > 0;
+}
+
/**
* rte_dump - dump a route
* @e: &rte to be dumped
@@ -2081,7 +2110,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
ee = e;
rte_update_lock(); /* We use the update buffer for filtering */
tmpa = p0->make_tmp_attrs ? p0->make_tmp_attrs(e, rte_update_pool) : NULL;
- ok = (d->filter == FILTER_ACCEPT || f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
+ ok = f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT;
if (p2 && p2 != p0) ok = 0;
if (ok && d->export_mode)
{
@@ -2095,8 +2124,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
'configure soft' command may change the export filter
and do not update routes */
- if ((a = proto_find_announce_hook(p1, d->table)) && ((a->out_filter == FILTER_REJECT) ||
- (a->out_filter && f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)))
+ if ((a = proto_find_announce_hook(p1, d->table)) &&
+ (f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
ok = 0;
}
}