diff options
-rw-r--r-- | doc/bird.conf.example | 5 | ||||
-rw-r--r-- | nest/config.Y | 4 | ||||
-rw-r--r-- | nest/proto.c | 7 | ||||
-rw-r--r-- | nest/protocol.h | 5 | ||||
-rw-r--r-- | nest/rt-table.c | 25 |
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); |