]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Basic kernel routing table syncing implemented. Learning of routes installed
authorMartin Mares <mj@ucw.cz>
Mon, 19 Oct 1998 17:52:29 +0000 (17:52 +0000)
committerMartin Mares <mj@ucw.cz>
Mon, 19 Oct 1998 17:52:29 +0000 (17:52 +0000)
by other programs or the kernel itself is not supported yet, but it's not
needed for development of other protocols.

sysdep/linux/krt-scan.c
sysdep/unix/krt-set.c
sysdep/unix/krt-set.h

index efc8e93024442a45bf4a8656d3a4350ca8937014..1b0063603d082397d66977773e885cc6537b4874 100644 (file)
@@ -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);
@@ -146,14 +151,47 @@ krt_scan_proc(void)
 }
 
 static void
-krt_scan_fire(timer *t)
+krt_prune(void)
 {
-  struct krt_proto *x = t->data;
-  SCANOPT;
+  struct rtable *t = &master_table;
+  struct fib_node *f;
 
-  DBG("Scanning kernel table...\n");
-  if (!krt_scan_proc())
+  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)
+{
+  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? */
 }
index 9da836d8d6e7505e97c8529cdedacff2c65a665e..2c355eeee6c03f0095f19d3b15d257b15619dcdf 100644 (file)
@@ -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
 
 #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;
 }
index 3b906bafdabd58244185a279e9297df559e533b8..a2107e12737308f33c17434470e01973a3e69a13 100644 (file)
@@ -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