All static routes except for device ones should work and appear/disappear
when their destination comes on/off link. Deserves better testing :) See example in bird.conf.
This commit is contained in:
parent
78d06cf2bc
commit
f6bd206607
5 changed files with 133 additions and 10 deletions
4
TODO
4
TODO
|
@ -18,6 +18,10 @@ Core
|
|||
- check if all protocols set proper packet priorities and TTL's.
|
||||
- better default protocol names
|
||||
- config: comments at end of line -> explicit ';' needed?
|
||||
- remove post-config hooks?
|
||||
|
||||
- static: check validity of route destination?
|
||||
- static: device routes
|
||||
|
||||
- filter: logging of dropped routes (?)
|
||||
- limitation of memory consumption: per-process and total (?)
|
||||
|
|
|
@ -25,5 +25,8 @@ protocol kernel {
|
|||
}
|
||||
|
||||
protocol static {
|
||||
disabled
|
||||
# disabled
|
||||
# route 10.0.0.0/8 reject
|
||||
# route 10.1.0.0:255.255.255.0 via 62.168.0.3
|
||||
# route 10.2.0.0/24 via "arc0"
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ CF_HDR
|
|||
|
||||
#include "proto/static/static.h"
|
||||
|
||||
static struct static_route *this_srt;
|
||||
|
||||
CF_DECLS
|
||||
|
||||
CF_KEYWORDS(STATIC)
|
||||
CF_KEYWORDS(STATIC, ROUTE, VIA, DROP, REJECT, PROHIBIT, PREFERENCE)
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
|
@ -27,6 +29,32 @@ static_proto_start: proto_start STATIC {
|
|||
static_proto:
|
||||
static_proto_start proto_name '{'
|
||||
| static_proto proto_item ';'
|
||||
| static_proto stat_route ';'
|
||||
;
|
||||
|
||||
stat_route0: ROUTE IPA pxlen {
|
||||
this_srt = cfg_allocz(sizeof(struct static_route));
|
||||
add_tail(&((struct static_proto *) this_proto)->other_routes, &this_srt->n);
|
||||
if (!ip_is_prefix($2, $3)) cf_error("Invalid network prefix: %I/%d", $2, $3);
|
||||
this_srt->net = $2;
|
||||
this_srt->masklen = $3;
|
||||
}
|
||||
;
|
||||
|
||||
stat_route:
|
||||
stat_route0 VIA IPA {
|
||||
this_srt->dest = RTD_ROUTER;
|
||||
this_srt->via = $3;
|
||||
}
|
||||
| stat_route0 VIA TEXT {
|
||||
this_srt->dest = RTD_DEVICE;
|
||||
this_srt->if_name = $3;
|
||||
rem_node(&this_srt->n);
|
||||
add_tail(&((struct static_proto *) this_proto)->iface_routes, &this_srt->n);
|
||||
}
|
||||
| stat_route0 DROP { this_srt->dest = RTD_BLACKHOLE; }
|
||||
| stat_route0 REJECT { this_srt->dest = RTD_UNREACHABLE; }
|
||||
| stat_route0 PROHIBIT { this_srt->dest = RTD_PROHIBIT; }
|
||||
;
|
||||
|
||||
CF_CODE
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#define LOCAL_DEBUG
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "nest/iface.h"
|
||||
#include "nest/protocol.h"
|
||||
|
@ -18,22 +20,107 @@
|
|||
|
||||
#define GET_DATA struct static_proto *p = (struct static_proto *) P
|
||||
|
||||
static void
|
||||
static_install(struct static_proto *p, struct static_route *r, struct iface *ifa)
|
||||
{
|
||||
net *n;
|
||||
rta a, *aa;
|
||||
rte *e;
|
||||
|
||||
DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest);
|
||||
bzero(&a, sizeof(a));
|
||||
a.proto = &p->p;
|
||||
a.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC;
|
||||
a.scope = SCOPE_UNIVERSE;
|
||||
a.cast = RTC_UNICAST;
|
||||
a.dest = r->dest;
|
||||
a.tos = 0;
|
||||
a.gw = r->via;
|
||||
a.iface = ifa;
|
||||
aa = rta_lookup(&a);
|
||||
|
||||
n = net_get(&master_table, a.tos, r->net, r->masklen);
|
||||
e = rte_get_temp(aa);
|
||||
e->net = n;
|
||||
e->pflags = 0;
|
||||
rte_update(n, &p->p, e);
|
||||
}
|
||||
|
||||
static void
|
||||
static_remove(struct static_proto *p, struct static_route *r)
|
||||
{
|
||||
net *n;
|
||||
|
||||
DBG("Removing static route %I/%d\n", r->net, r->masklen);
|
||||
n = net_find(&master_table, 0, r->net, r->masklen);
|
||||
if (n)
|
||||
rte_update(n, &p->p, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
static_start(struct proto *P)
|
||||
{
|
||||
GET_DATA;
|
||||
struct static_route *r;
|
||||
|
||||
DBG("Static: take off!\n");
|
||||
WALK_LIST(r, p->other_routes)
|
||||
if (r->dest == RTD_ROUTER)
|
||||
{
|
||||
struct neighbor *n = neigh_find(P, &r->via, NEF_STICKY);
|
||||
if (n)
|
||||
{
|
||||
n->data = r;
|
||||
r->neigh = n;
|
||||
static_install(p, r, n->iface);
|
||||
}
|
||||
else
|
||||
log(L_ERR "Static route destination %I is invalid. Ignoring.\n", r->via);
|
||||
}
|
||||
else
|
||||
static_install(p, r, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
static_neigh_notify(struct neighbor *n)
|
||||
{
|
||||
DBG("Static: neighbor notify got, don't know why.\n");
|
||||
DBG("Static: neighbor notify for %I: iface %p\n", n->addr, n->iface);
|
||||
if (n->iface)
|
||||
static_install((struct static_proto *) n->proto, n->data, n->iface);
|
||||
else
|
||||
static_remove((struct static_proto *) n->proto, n->data);
|
||||
}
|
||||
|
||||
static void
|
||||
static_dump_rt(struct static_route *r)
|
||||
{
|
||||
debug("%16I/%2d: ", r->net, r->masklen);
|
||||
switch (r->dest)
|
||||
{
|
||||
case RTD_ROUTER:
|
||||
debug("via %I\n", r->via);
|
||||
break;
|
||||
case RTD_DEVICE:
|
||||
debug("dev %s\n", r->if_name);
|
||||
break;
|
||||
default:
|
||||
debug("rtd %d\n", r->dest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static_dump(struct proto *P)
|
||||
{
|
||||
DBG("Static: no dumps available in demo version.\n");
|
||||
GET_DATA;
|
||||
struct static_route *r;
|
||||
|
||||
debug("Independent static routes:\n");
|
||||
WALK_LIST(r, p->other_routes)
|
||||
static_dump_rt(r);
|
||||
debug("Device static routes:\n");
|
||||
WALK_LIST(r, p->iface_routes)
|
||||
static_dump_rt(r);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -45,7 +132,8 @@ static_init_instance(struct static_proto *P)
|
|||
p->start = static_start;
|
||||
p->neigh_notify = static_neigh_notify;
|
||||
p->dump = static_dump;
|
||||
/* FIXME: Should shutdown remove all routes? */
|
||||
init_list(&P->iface_routes);
|
||||
init_list(&P->other_routes);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -11,20 +11,20 @@
|
|||
|
||||
struct static_proto {
|
||||
struct proto p;
|
||||
list routes;
|
||||
list iface_routes; /* Routes to search on interface events */
|
||||
list other_routes; /* Routes hooked to neighbor cache and reject routes */
|
||||
};
|
||||
|
||||
void static_init_instance(struct static_proto *);
|
||||
|
||||
struct static_route {
|
||||
node n;
|
||||
u32 net; /* Network we route */
|
||||
ip_addr net; /* Network we route */
|
||||
int masklen; /* Mask length */
|
||||
int dest; /* Destination type (RTD_*) */
|
||||
u32 via; /* Destination router */
|
||||
ip_addr via; /* Destination router */
|
||||
struct neighbor *neigh;
|
||||
/* FIXME: Device routes, maybe via device patterns? */
|
||||
/* FIXME: More route attributes, probably via filter syntax */
|
||||
byte *if_name; /* Name for RTD_DEVICE routes */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue