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:
Martin Mares 1998-12-06 23:13:31 +00:00
parent 78d06cf2bc
commit f6bd206607
5 changed files with 133 additions and 10 deletions

4
TODO
View file

@ -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 (?)

View file

@ -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"
} }

View file

@ -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

View file

@ -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

View file

@ -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