summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/bird.conf.example5
-rw-r--r--nest/config.Y4
-rw-r--r--nest/proto.c7
-rw-r--r--nest/protocol.h5
-rw-r--r--nest/rt-table.c25
5 files changed, 42 insertions, 4 deletions
diff --git a/doc/bird.conf.example b/doc/bird.conf.example
index 9f5907d..1d8203d 100644
--- a/doc/bird.conf.example
+++ b/doc/bird.conf.example
@@ -8,6 +8,9 @@
#define xyzzy = 120+10
+#filter sink { reject; }
+#filter okay { accept; }
+
#protocol rip MyRIP_test {
# preference xyzzy
# debug all
@@ -25,6 +28,8 @@ protocol kernel {
scan time 10 # Scan kernel tables every 10 seconds
route scan time 20 # But routes only every 20 seconds
# async off # Netlink: Disable asynchronous events
+# input filter sink
+# output filter okay
}
protocol static {
diff --git a/nest/config.Y b/nest/config.Y
index a19cce6..8300132 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -17,7 +17,7 @@ void rt_dev_add_iface(char *);
CF_DECLS
CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DEVICE)
-CF_KEYWORDS(INTERFACE)
+CF_KEYWORDS(INTERFACE, INPUT, OUTPUT, FILTER)
%type <i> idval
@@ -67,6 +67,8 @@ proto_item:
| DEBUG expr { this_proto->debug = $2; }
| DEBUG ALL { this_proto->debug = ~0; }
| DEBUG OFF { this_proto->debug = 0; }
+ | INPUT FILTER filter { this_proto->in_filter = $3; }
+ | OUTPUT FILTER filter { this_proto->out_filter = $3; }
;
/* Device protocol */
diff --git a/nest/proto.c b/nest/proto.c
index 4df625f..431c47d 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -18,6 +18,7 @@
#include "conf/conf.h"
#include "nest/route.h"
#include "nest/iface.h"
+#include "filter/filter.h"
static pool *proto_pool;
@@ -85,6 +86,8 @@ proto_new(struct proto_config *c, unsigned size)
p->preference = c->preference;
p->disabled = c->disabled;
p->proto = pr;
+ p->in_filter = c->in_filter;
+ p->out_filter = c->out_filter;
return p;
}
@@ -242,6 +245,10 @@ protos_dump_all(void)
{
debug(" protocol %s (pri=%d): state %s/%s\n", p->name, p->proto->priority,
p_states[p->proto_state], c_states[p->core_state]);
+ if (p->in_filter)
+ debug("\tInput filter: %s\n", p->in_filter->name);
+ if (p->out_filter)
+ debug("\tOutput filter: %s\n", p->out_filter->name);
if (p->disabled)
debug("\tDISABLED\n");
else if (p->proto->dump)
diff --git a/nest/protocol.h b/nest/protocol.h
index a168b41..1e641a5 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -70,6 +70,7 @@ struct proto_config {
struct protocol *proto; /* Protocol */
char *name;
unsigned debug, preference, disabled; /* Generic parameters */
+ struct filter *in_filter, *out_filter; /* Attached filters */
/* Protocol-specific data follow... */
};
@@ -97,7 +98,9 @@ struct proto {
void (*rte_insert)(struct network *, struct rte *);
void (*rte_remove)(struct network *, struct rte *);
- /* Input/output filters */
+ struct filter *in_filter; /* Input filter */
+ struct filter *out_filter; /* Output filter */
+
/* Connection to routing tables? */
/* Hic sunt protocol-specific data */
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 4da6807..756141c 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -15,6 +15,7 @@
#include "nest/protocol.h"
#include "lib/resource.h"
#include "lib/event.h"
+#include "filter/filter.h"
rtable master_table;
static slab *rte_slab;
@@ -115,6 +116,20 @@ rte_better(rte *new, rte *old)
return 0;
}
+static inline void
+do_rte_announce(struct proto *p, net *net, rte *new, rte *old)
+{
+ if (p->out_filter)
+ {
+ if (old && f_run(p->out_filter, old, NULL) != F_ACCEPT)
+ old = NULL;
+ if (new && f_run(p->out_filter, new, NULL) != F_ACCEPT)
+ new = NULL;
+ }
+ if (new || old)
+ p->rt_notify(p, net, new, old);
+}
+
void
rte_announce(net *net, rte *new, rte *old)
{
@@ -124,7 +139,7 @@ rte_announce(net *net, rte *new, rte *old)
{
ASSERT(p->core_state == FS_HAPPY);
if (p->rt_notify)
- p->rt_notify(p, net, new, old);
+ do_rte_announce(p, net, new, old);
}
}
@@ -143,7 +158,7 @@ rt_feed_baby(struct proto *p)
net *n = (net *) fn;
rte *e;
for(e=n->routes; e; e=e->next)
- p->rt_notify(p, n, e, NULL);
+ do_rte_announce(p, n, e, NULL);
}
FIB_WALK_END;
t = t->sibling;
@@ -172,6 +187,12 @@ rte_update(net *net, struct proto *p, rte *new)
rte *old = NULL;
rte **k, *r, *s;
+ if (new && p->in_filter && f_run(p->in_filter, new, NULL) != F_ACCEPT)
+ {
+ rte_free(new);
+ return;
+ }
+
if (new && !(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
new->attrs = rta_lookup(new->attrs);