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:
parent
567e6c6220
commit
0804525255
3 changed files with 136 additions and 9 deletions
|
@ -26,6 +26,8 @@
|
|||
|
||||
static int krt_scan_fd = -1;
|
||||
|
||||
/* FIXME: Filtering */
|
||||
|
||||
static void
|
||||
krt_parse_entry(byte *e)
|
||||
{
|
||||
|
@ -98,6 +100,8 @@ krt_parse_entry(byte *e)
|
|||
if (!(flags & RTF_GATEWAY)) /* It's a device route */
|
||||
return;
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +112,7 @@ krt_scan_proc(void)
|
|||
byte buf[32768];
|
||||
int l, seen_hdr;
|
||||
|
||||
DBG("Scanning kernel table...\n");
|
||||
if (krt_scan_fd < 0)
|
||||
{
|
||||
krt_scan_fd = open("/proc/net/route", O_RDONLY);
|
||||
|
@ -145,15 +150,48 @@ krt_scan_proc(void)
|
|||
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
|
||||
krt_scan_fire(timer *t)
|
||||
{
|
||||
struct krt_proto *x = t->data;
|
||||
SCANOPT;
|
||||
|
||||
DBG("Scanning kernel table...\n");
|
||||
if (!krt_scan_proc())
|
||||
return;
|
||||
if (krt_scan_proc())
|
||||
krt_prune();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -185,4 +223,5 @@ krt_scan_shutdown(struct krt_proto *x)
|
|||
SCANOPT;
|
||||
|
||||
tm_stop(p->timer);
|
||||
/* FIXME: Remove all krt's? */
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#define LOCAL_DEBUG
|
||||
|
||||
|
@ -18,18 +18,102 @@
|
|||
#include "nest/iface.h"
|
||||
#include "nest/route.h"
|
||||
#include "nest/protocol.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/unix.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
|
||||
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
|
||||
krt_set_preconfig(struct krt_proto *x)
|
||||
{
|
||||
if (if_scan_sock < 0)
|
||||
die("krt set: missing socket");
|
||||
x->p.rt_notify = krt_set_notify;
|
||||
}
|
||||
|
|
|
@ -12,4 +12,8 @@
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue