summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2013-02-08 23:58:27 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2013-02-08 23:58:27 +0100
commit36da2857bc911924a250a234f38cf58c3b21f1bc (patch)
tree58e39ad7b5cff5ec2525b07c274e4d43ef01ae87 /nest
parentd214ae4fdc1e323f89efb8a80c068fef4a45758f (diff)
Implements router advertisements activated by received routes.
The RAdv protocol could be configured to change its behavior based on availability of routes, e.g., do not announce router lifetime when a default route is not available.
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;
}
}