Basic kernel routing table syncing implemented. Learning of routes installed

by other programs or the kernel itself is not supported yet, but it's not
needed for development of other protocols.
This commit is contained in:
Martin Mares 1998-10-19 17:52:29 +00:00
parent 567e6c6220
commit 0804525255
3 changed files with 136 additions and 9 deletions

View file

@ -26,6 +26,8 @@
static int krt_scan_fd = -1; static int krt_scan_fd = -1;
/* FIXME: Filtering */
static void static void
krt_parse_entry(byte *e) krt_parse_entry(byte *e)
{ {
@ -98,6 +100,8 @@ krt_parse_entry(byte *e)
if (!(flags & RTF_GATEWAY)) /* It's a device route */ if (!(flags & RTF_GATEWAY)) /* It's a device route */
return; return;
#endif #endif
DBG("krt_parse_entry: kernel reporting unknown route %I/%d\n", dest, masklen);
/* FIXME: should be able to learn kernel routes */
net->n.flags |= KRF_UPDATE; net->n.flags |= KRF_UPDATE;
} }
} }
@ -108,6 +112,7 @@ krt_scan_proc(void)
byte buf[32768]; byte buf[32768];
int l, seen_hdr; int l, seen_hdr;
DBG("Scanning kernel table...\n");
if (krt_scan_fd < 0) if (krt_scan_fd < 0)
{ {
krt_scan_fd = open("/proc/net/route", O_RDONLY); krt_scan_fd = open("/proc/net/route", O_RDONLY);
@ -145,15 +150,48 @@ krt_scan_proc(void)
return 1; return 1;
} }
static void
krt_prune(void)
{
struct rtable *t = &master_table;
struct fib_node *f;
DBG("Pruning routes...\n");
while (t && t->tos)
t = t->sibling;
if (!t)
return;
FIB_WALK(&t->fib, f)
{
net *n = (net *) f;
switch (f->flags)
{
case KRF_UPDATE:
DBG("krt_prune: removing %I/%d\n", n->n.prefix, n->n.pxlen);
krt_remove_route(n, NULL);
/* Fall-thru */
case 0:
if (n->routes)
{
DBG("krt_prune: reinstalling %I/%d\n", n->n.prefix, n->n.pxlen);
krt_add_route(n, n->routes);
}
break;
case KRF_SEEN:
break;
default:
die("krt_prune: invalid route status");
}
f->flags = 0;
}
FIB_WALK_END;
}
static void static void
krt_scan_fire(timer *t) krt_scan_fire(timer *t)
{ {
struct krt_proto *x = t->data; if (krt_scan_proc())
SCANOPT; krt_prune();
DBG("Scanning kernel table...\n");
if (!krt_scan_proc())
return;
} }
void void
@ -185,4 +223,5 @@ krt_scan_shutdown(struct krt_proto *x)
SCANOPT; SCANOPT;
tm_stop(p->timer); tm_stop(p->timer);
/* FIXME: Remove all krt's? */
} }

View file

@ -10,7 +10,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <errno.h> #include <net/route.h>
#define LOCAL_DEBUG #define LOCAL_DEBUG
@ -18,18 +18,102 @@
#include "nest/iface.h" #include "nest/iface.h"
#include "nest/route.h" #include "nest/route.h"
#include "nest/protocol.h" #include "nest/protocol.h"
#include "lib/timer.h"
#include "lib/unix.h" #include "lib/unix.h"
#include "lib/krt.h" #include "lib/krt.h"
int
krt_capable(net *net, rte *e)
{
rta *a = e->attrs;
return
a->cast == RTC_UNICAST &&
(a->dest == RTD_ROUTER
#ifndef CONFIG_AUTO_ROUTES
|| a->dest == RTD_DEVICE
#endif
#ifdef RTF_REJECT
|| a->dest == RTD_UNREACHABLE
#endif
) &&
!a->tos;
}
void
krt_remove_route(net *net, rte *old)
{
struct rtentry re;
if (old && !krt_capable(net, old))
{
DBG("krt_remove_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
return;
}
DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
bzero(&re, sizeof(re));
fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0);
fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0);
if (ioctl(if_scan_sock, SIOCDELRT, &re) < 0)
log(L_ERR "SIOCDELRT(%I/%d): %m", net->n.prefix, net->n.pxlen);
}
void
krt_add_route(net *net, rte *new)
{
struct rtentry re;
rta *a = new->attrs;
if (!krt_capable(net, new))
{
DBG("krt_add_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
return;
}
DBG("krt_add_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
bzero(&re, sizeof(re));
fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0);
fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0);
re.rt_flags = RTF_UP;
if (net->n.pxlen == 32)
re.rt_flags |= RTF_HOST;
switch (a->dest)
{
case RTD_ROUTER:
fill_in_sockaddr((struct sockaddr_in *) &re.rt_gateway, a->gw, 0);
re.rt_flags |= RTF_GATEWAY;
break;
#ifndef CONFIG_AUTO_ROUTES
case RTD_DEVICE:
re.rt_dev = a->iface->name;
break;
#endif
#ifdef RTF_REJECT
case RTD_UNREACHABLE:
re.rt_flags |= RTF_REJECT;
break;
#endif
default:
die("krt set: unknown flags, but not filtered");
}
if (ioctl(if_scan_sock, SIOCADDRT, &re) < 0)
log(L_ERR "SIOCADDRT(%I/%d): %m", net->n.prefix, net->n.pxlen);
}
void void
krt_set_notify(struct proto *x, net *net, rte *new, rte *old) krt_set_notify(struct proto *x, net *net, rte *new, rte *old)
{ {
DBG("krt_set_notify(%I/%d)\n", net->n.prefix, net->n.pxlen); if (x->state != PRS_UP)
return;
if (old)
krt_remove_route(net, old);
if (new)
krt_add_route(net, new);
} }
void void
krt_set_preconfig(struct krt_proto *x) krt_set_preconfig(struct krt_proto *x)
{ {
if (if_scan_sock < 0)
die("krt set: missing socket");
x->p.rt_notify = krt_set_notify; x->p.rt_notify = krt_set_notify;
} }

View file

@ -12,4 +12,8 @@
struct krt_set_params { struct krt_set_params {
}; };
void krt_remove_route(net *net, rte *old);
void krt_add_route(net *net, rte *new);
int krt_capable(net *net, rte *e);
#endif #endif