diff options
author | Martin Mares <mj@ucw.cz> | 1998-10-19 19:52:29 +0200 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 1998-10-19 19:52:29 +0200 |
commit | 08045252553478457f923a9f941675df9992f507 (patch) | |
tree | cf34d40c0b6f3fa0697cf5164d64077eb1d849ce /sysdep/unix | |
parent | 567e6c62208d3bb05b58b8ed08c2be29d6542f2b (diff) | |
download | bird-08045252553478457f923a9f941675df9992f507.tar bird-08045252553478457f923a9f941675df9992f507.zip |
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.
Diffstat (limited to 'sysdep/unix')
-rw-r--r-- | sysdep/unix/krt-set.c | 90 | ||||
-rw-r--r-- | sysdep/unix/krt-set.h | 4 |
2 files changed, 91 insertions, 3 deletions
diff --git a/sysdep/unix/krt-set.c b/sysdep/unix/krt-set.c index 9da836d..2c355ee 100644 --- a/sysdep/unix/krt-set.c +++ b/sysdep/unix/krt-set.c @@ -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; } diff --git a/sysdep/unix/krt-set.h b/sysdep/unix/krt-set.h index 3b906ba..a2107e1 100644 --- a/sysdep/unix/krt-set.h +++ b/sysdep/unix/krt-set.h @@ -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 |