8e66a0ebb9
o Interface syncing is now a part of krt and it can have configurable parameters. Actually, the only one is scan rate now :) o Kernel routing table syncing is now synchronized with interface syncing (we need the most recent version of the interface list to prevent lots of routes to non-existent destinations from appearing). Instead of its own timer, we just check if it's route scan time after each iface list scan. o Syncing of device routes implemented. o CONFIG_AUTO_ROUTES should control syncing of automatic device routes. o Rewrote krt_remove_route() to really remove routes :) o Better diagnostics. o Fixed a couple of bugs.
132 lines
2.6 KiB
C
132 lines
2.6 KiB
C
/*
|
|
* BIRD -- Unix Routing Table Syncing
|
|
*
|
|
* (c) 1998 Martin Mares <mj@ucw.cz>
|
|
*
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/ioctl.h>
|
|
#include <net/route.h>
|
|
|
|
#define LOCAL_DEBUG
|
|
|
|
#include "nest/bird.h"
|
|
#include "nest/iface.h"
|
|
#include "nest/route.h"
|
|
#include "nest/protocol.h"
|
|
#include "lib/unix.h"
|
|
#include "lib/krt.h"
|
|
|
|
int
|
|
krt_capable(rte *e)
|
|
{
|
|
rta *a = e->attrs;
|
|
|
|
return
|
|
a->cast == RTC_UNICAST &&
|
|
(a->dest == RTD_ROUTER
|
|
|| a->dest == RTD_DEVICE
|
|
#ifdef RTF_REJECT
|
|
|| a->dest == RTD_UNREACHABLE
|
|
#endif
|
|
) &&
|
|
!a->tos;
|
|
}
|
|
|
|
static inline int
|
|
krt_capable_op(rte *e)
|
|
{
|
|
rta *a = e->attrs;
|
|
|
|
#ifdef CONFIG_AUTO_ROUTES
|
|
if (a->dest == RTD_ROUTER && a->source == RTS_DEVICE)
|
|
return 0;
|
|
#endif
|
|
return krt_capable(e);
|
|
}
|
|
|
|
static void
|
|
krt_ioctl(int ioc, rte *e, char *name)
|
|
{
|
|
net *net = e->net;
|
|
struct rtentry re;
|
|
rta *a = e->attrs;
|
|
|
|
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;
|
|
case RTD_DEVICE:
|
|
re.rt_dev = a->iface->name;
|
|
break;
|
|
#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, ioc, &re) < 0)
|
|
log(L_ERR "%s(%I/%d): %m", name, net->n.prefix, net->n.pxlen);
|
|
}
|
|
|
|
void
|
|
krt_remove_route(rte *old)
|
|
{
|
|
net *net = old->net;
|
|
|
|
if (!krt_capable_op(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);
|
|
krt_ioctl(SIOCDELRT, old, "SIOCDELRT");
|
|
}
|
|
|
|
void
|
|
krt_add_route(rte *new)
|
|
{
|
|
net *net = new->net;
|
|
|
|
if (!krt_capable_op(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);
|
|
krt_ioctl(SIOCADDRT, new, "SIOCADDRT");
|
|
}
|
|
|
|
void
|
|
krt_set_notify(struct proto *x, net *net, rte *new, rte *old)
|
|
{
|
|
if (x->state != PRS_UP)
|
|
return;
|
|
if (old)
|
|
krt_remove_route(old);
|
|
if (new)
|
|
krt_add_route(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;
|
|
}
|