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.
|
- check if all protocols set proper packet priorities and TTL's.
|
||||||
- better default protocol names
|
- better default protocol names
|
||||||
- config: comments at end of line -> explicit ';' needed?
|
- 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 (?)
|
- filter: logging of dropped routes (?)
|
||||||
- limitation of memory consumption: per-process and total (?)
|
- limitation of memory consumption: per-process and total (?)
|
||||||
|
|
|
@ -25,5 +25,8 @@ protocol kernel {
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol static {
|
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"
|
#include "proto/static/static.h"
|
||||||
|
|
||||||
|
static struct static_route *this_srt;
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(STATIC)
|
CF_KEYWORDS(STATIC, ROUTE, VIA, DROP, REJECT, PROHIBIT, PREFERENCE)
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
|
@ -27,6 +29,32 @@ static_proto_start: proto_start STATIC {
|
||||||
static_proto:
|
static_proto:
|
||||||
static_proto_start proto_name '{'
|
static_proto_start proto_name '{'
|
||||||
| static_proto proto_item ';'
|
| 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
|
CF_CODE
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#define LOCAL_DEBUG
|
#define LOCAL_DEBUG
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
|
@ -18,22 +20,107 @@
|
||||||
|
|
||||||
#define GET_DATA struct static_proto *p = (struct static_proto *) P
|
#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 void
|
||||||
static_start(struct proto *P)
|
static_start(struct proto *P)
|
||||||
{
|
{
|
||||||
|
GET_DATA;
|
||||||
|
struct static_route *r;
|
||||||
|
|
||||||
DBG("Static: take off!\n");
|
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 void
|
||||||
static_neigh_notify(struct neighbor *n)
|
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 void
|
||||||
static_dump(struct proto *P)
|
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
|
void
|
||||||
|
@ -45,7 +132,8 @@ static_init_instance(struct static_proto *P)
|
||||||
p->start = static_start;
|
p->start = static_start;
|
||||||
p->neigh_notify = static_neigh_notify;
|
p->neigh_notify = static_neigh_notify;
|
||||||
p->dump = static_dump;
|
p->dump = static_dump;
|
||||||
/* FIXME: Should shutdown remove all routes? */
|
init_list(&P->iface_routes);
|
||||||
|
init_list(&P->other_routes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -11,20 +11,20 @@
|
||||||
|
|
||||||
struct static_proto {
|
struct static_proto {
|
||||||
struct proto p;
|
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 *);
|
void static_init_instance(struct static_proto *);
|
||||||
|
|
||||||
struct static_route {
|
struct static_route {
|
||||||
node n;
|
node n;
|
||||||
u32 net; /* Network we route */
|
ip_addr net; /* Network we route */
|
||||||
int masklen; /* Mask length */
|
int masklen; /* Mask length */
|
||||||
int dest; /* Destination type (RTD_*) */
|
int dest; /* Destination type (RTD_*) */
|
||||||
u32 via; /* Destination router */
|
ip_addr via; /* Destination router */
|
||||||
struct neighbor *neigh;
|
struct neighbor *neigh;
|
||||||
/* FIXME: Device routes, maybe via device patterns? */
|
byte *if_name; /* Name for RTD_DEVICE routes */
|
||||||
/* FIXME: More route attributes, probably via filter syntax */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue