From e16155ae4aaee5d9ba7b6940f8312b36707718e4 Mon Sep 17 00:00:00 2001
From: Martin Mares <mj@ucw.cz>
Date: Thu, 4 Mar 1999 18:36:18 +0000
Subject: KRT: Implemented asynchronous route / interface state notifications
 (via Netlink). Tweaked kernel synchronization rules a bit. Discovered locking
 bug in kernel Netlink :-)

Future plans: Hunt all the bugs and solve all the FIXME's.
---
 sysdep/unix/krt-set.c |  3 ++-
 sysdep/unix/krt.c     | 38 +++++++++++++++++++++++++++++++++++++-
 sysdep/unix/krt.h     |  7 +++++++
 3 files changed, 46 insertions(+), 2 deletions(-)

(limited to 'sysdep/unix')

diff --git a/sysdep/unix/krt-set.c b/sysdep/unix/krt-set.c
index dae01f46..2165255e 100644
--- a/sysdep/unix/krt-set.c
+++ b/sysdep/unix/krt-set.c
@@ -43,7 +43,7 @@ krt_capable_op(rte *e)
   rta *a = e->attrs;
 
 #ifdef CONFIG_AUTO_ROUTES
-  if (a->dest == RTD_ROUTER && a->source == RTS_DEVICE)
+  if (a->source == RTS_DEVICE)
     return 0;
 #endif
   return krt_capable(e);
@@ -115,6 +115,7 @@ krt_add_route(rte *new)
 void
 krt_set_notify(struct proto *x, net *net, rte *new, rte *old)
 {
+  /* FIXME: Fold remove/add route here */
   if (old)
     krt_remove_route(old);
   if (new)
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 5fbd52c7..aa875ccf 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -78,6 +78,7 @@ krt_got_route(struct krt_proto *p, rte *e)
 {
   rte *old;
   net *net = e->net;
+  int src = e->u.krt_sync.src;
   int verdict;
 
   if (net->n.flags)
@@ -97,7 +98,7 @@ krt_got_route(struct krt_proto *p, rte *e)
       else
 	verdict = KRF_UPDATE;
     }
-  else if (KRT_CF->learn && !net->routes)
+  else if (KRT_CF->learn && !net->routes && (src == KRT_SRC_ALIEN || src < 0))
     verdict = KRF_LEARN;
   else
     verdict = KRF_DELETE;
@@ -188,6 +189,41 @@ krt_prune(struct krt_proto *p)
   FIB_WALK_END;
 }
 
+void
+krt_got_route_async(struct krt_proto *p, rte *e, int new)
+{
+  net *net = e->net;
+  rte *old = net->routes;
+  int src = e->u.krt_sync.src;
+
+  switch (src)
+    {
+    case KRT_SRC_BIRD:
+      ASSERT(0);
+    case KRT_SRC_REDIRECT:
+      DBG("It's a redirect, kill him! Kill! Kill!\n");
+      krt_set_notify(&p->p, net, NULL, e);
+      break;
+    default:	/* Alien or unspecified */
+      if (KRT_CF->learn && new)
+	{
+	  /*
+	   * FIXME: This is limited to one inherited route per destination as we
+	   * use single protocol for all inherited routes. Probably leave it
+	   * as-is (and document it :)), because the correct solution is to
+	   * multiple kernel tables anyway.
+	   */
+	  DBG("Learning\n");
+	  rte_update(net, &p->p, e);
+	}
+      else
+	{
+	  DBG("Discarding\n");
+	  rte_update(net, &p->p, NULL);
+	}
+    }
+}
+
 /*
  *	Periodic scanning
  */
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index 1c59799f..02814c68 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -52,6 +52,13 @@ extern struct proto_config *cf_krt;
 #define KRT_CF ((struct krt_config *)p->p.cf)
 
 void krt_got_route(struct krt_proto *p, struct rte *e);
+void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
+
+/* Values for rte->u.krt_sync.src */
+#define KRT_SRC_UNKNOWN	-1	/* Nobody knows */
+#define KRT_SRC_BIRD	 0	/* Our route (not passed in async mode) */
+#define KRT_SRC_REDIRECT 1	/* Redirect route, delete it */
+#define KRT_SRC_ALIEN	 2	/* Route installed by someone else */
 
 /* krt-scan.c */
 
-- 
cgit v1.2.3