summaryrefslogtreecommitdiffstats
path: root/proto/static/static.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/static/static.c')
-rw-r--r--proto/static/static.c94
1 files changed, 91 insertions, 3 deletions
diff --git a/proto/static/static.c b/proto/static/static.c
index 679ee6e..bc060cd 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -8,6 +8,8 @@
#define LOCAL_DEBUG
+#include <string.h>
+
#include "nest/bird.h"
#include "nest/iface.h"
#include "nest/protocol.h"
@@ -19,21 +21,106 @@
#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