summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--doc/bird.conf.example1
-rw-r--r--sysdep/cf/linux-20.h4
-rw-r--r--sysdep/linux/Modules3
-rw-r--r--sysdep/linux/krt-scan.Y33
-rw-r--r--sysdep/linux/krt-scan.c188
-rw-r--r--sysdep/linux/krt-scan.h5
-rw-r--r--sysdep/linux/netlink/Modules8
-rw-r--r--sysdep/linux/netlink/krt-iface.h26
-rw-r--r--sysdep/linux/netlink/krt-scan.h26
-rw-r--r--sysdep/linux/netlink/krt-set.h26
-rw-r--r--sysdep/linux/netlink/krt.Y46
-rw-r--r--sysdep/linux/netlink/krt.h30
-rw-r--r--sysdep/linux/netlink/netlink.Y25
-rw-r--r--sysdep/linux/netlink/netlink.c (renamed from sysdep/linux/netlink/krt.c)113
-rw-r--r--sysdep/unix/Modules16
-rw-r--r--sysdep/unix/krt-iface.Y30
-rw-r--r--sysdep/unix/krt-iface.c (renamed from sysdep/unix/sync-if.c)42
-rw-r--r--sysdep/unix/krt-iface.h5
-rw-r--r--sysdep/unix/krt-set.Y29
-rw-r--r--sysdep/unix/krt-set.c26
-rw-r--r--sysdep/unix/krt-set.h8
-rw-r--r--sysdep/unix/krt.Y15
-rw-r--r--sysdep/unix/krt.c291
-rw-r--r--sysdep/unix/krt.h43
-rw-r--r--sysdep/unix/main.c2
-rw-r--r--sysdep/unix/sync-rt.c76
27 files changed, 546 insertions, 572 deletions
diff --git a/TODO b/TODO
index 8045604..1544345 100644
--- a/TODO
+++ b/TODO
@@ -14,6 +14,7 @@ Core
- static: check validity of route destination?
- device: configuration of interface patterns
+- device: what to do if we need to shut down this protocol?
- adding of route: check whether all bits not covered by masklen are zero
diff --git a/doc/bird.conf.example b/doc/bird.conf.example
index 15fd844..9f5907d 100644
--- a/doc/bird.conf.example
+++ b/doc/bird.conf.example
@@ -24,6 +24,7 @@ protocol kernel {
persist # Don't remove routes on bird shutdown
scan time 10 # Scan kernel tables every 10 seconds
route scan time 20 # But routes only every 20 seconds
+# async off # Netlink: Disable asynchronous events
}
protocol static {
diff --git a/sysdep/cf/linux-20.h b/sysdep/cf/linux-20.h
index 807ddcd..e514218 100644
--- a/sysdep/cf/linux-20.h
+++ b/sysdep/cf/linux-20.h
@@ -12,6 +12,10 @@
#undef CONFIG_AUTO_ROUTES
#define CONFIG_ALL_MULTICAST
+#define CONFIG_UNIX_IFACE
+#define CONFIG_UNIX_SET
+#define CONFIG_LINUX_SCAN
+
/*
Link: sysdep/linux
Link: sysdep/unix
diff --git a/sysdep/linux/Modules b/sysdep/linux/Modules
index 03d032d..4a99916 100644
--- a/sysdep/linux/Modules
+++ b/sysdep/linux/Modules
@@ -1,5 +1,4 @@
-#ifndef CONFIG_NETLINK
+#ifdef CONFIG_LINUX_SCAN
krt-scan.c
krt-scan.h
-krt-scan.Y
#endif
diff --git a/sysdep/linux/krt-scan.Y b/sysdep/linux/krt-scan.Y
deleted file mode 100644
index 5833989..0000000
--- a/sysdep/linux/krt-scan.Y
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * BIRD -- Linux Kernel Syncer Configuration
- *
- * (c) 1998 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-CF_HDR
-
-#include "lib/krt-scan.h"
-
-CF_DECLS
-
-CF_KEYWORDS(LEARN, ROUTE, SCAN, TIME)
-
-CF_GRAMMAR
-
-CF_ADDTO(kern_proto, kern_proto krt_scan_item ';')
-
-krt_scan_item:
- LEARN bool {
- ((struct krt_config *) this_proto)->scanopt.learn = $2;
- }
- | ROUTE SCAN TIME expr {
- /* Scan time of 0 means scan on startup only */
- ((struct krt_config *) this_proto)->scanopt.scan_time = $4;
- }
- ;
-
-CF_CODE
-
-CF_END
diff --git a/sysdep/linux/krt-scan.c b/sysdep/linux/krt-scan.c
index 1428a7a..3e5a240 100644
--- a/sysdep/linux/krt-scan.c
+++ b/sysdep/linux/krt-scan.c
@@ -23,60 +23,34 @@
#include "lib/unix.h"
#include "lib/krt.h"
-#define SCANOPT struct krt_scan_params *p = &(((struct krt_config *)(x->p.cf))->scanopt)
-#define SCANSTAT struct krt_scan_status *s = &x->scanstat
-
static int krt_scan_fd = -1;
-/* FIXME: Filtering */
-
struct iface *
-krt_temp_iface(struct krt_proto *x, char *name)
+krt_temp_iface(struct krt_proto *p, char *name)
{
- SCANOPT;
- SCANSTAT;
struct iface *i;
- WALK_LIST(i, s->temp_ifs)
+ WALK_LIST(i, p->scan.temp_ifs)
if (!strcmp(i->name, name))
return i;
- i = mb_alloc(x->p.pool, sizeof(struct iface));
+ i = mb_alloc(p->p.pool, sizeof(struct iface));
bzero(i, sizeof(*i));
strcpy(i->name, name);
- add_tail(&s->temp_ifs, &i->n);
+ add_tail(&p->scan.temp_ifs, &i->n);
return i;
}
-static int
-krt_uptodate(rte *k, rte *e)
-{
- rta *ka = k->attrs, *ea = e->attrs;
-
- if (ka->dest != ea->dest)
- return 0;
- switch (ka->dest)
- {
- case RTD_ROUTER:
- return ipa_equal(ka->gw, ea->gw);
- case RTD_DEVICE:
- return !strcmp(ka->iface->name, ea->iface->name);
- default:
- return 1;
- }
-}
-
static void
-krt_parse_entry(byte *ent, struct krt_proto *x)
+krt_parse_entry(byte *ent, struct krt_proto *p)
{
- SCANOPT;
u32 dest0, gw0, mask0;
ip_addr dest, gw, mask;
- unsigned int flags, verdict;
+ unsigned int flags;
int masklen;
net *net;
byte *iface = ent;
rta a;
- rte *e, *old;
+ rte *e;
if (sscanf(ent, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4)
{
@@ -114,14 +88,8 @@ krt_parse_entry(byte *ent, struct krt_proto *x)
}
net = net_get(&master_table, 0, dest, masklen);
- if (net->n.flags)
- {
- /* Route to this destination was already seen. Strange, but it happens... */
- DBG("Already seen.\n");
- return;
- }
- a.proto = &x->p;
+ a.proto = &p->p;
a.source = RTS_INHERIT;
a.scope = SCOPE_UNIVERSE;
a.cast = RTC_UNICAST;
@@ -132,7 +100,7 @@ krt_parse_entry(byte *ent, struct krt_proto *x)
if (flags & RTF_GATEWAY)
{
- neighbor *ng = neigh_find(&x->p, &gw, 0);
+ neighbor *ng = neigh_find(&p->p, &gw, 0);
if (ng)
a.iface = ng->iface;
else
@@ -150,7 +118,7 @@ krt_parse_entry(byte *ent, struct krt_proto *x)
{
a.dest = RTD_DEVICE;
a.gw = IPA_NONE;
- a.iface = krt_temp_iface(x, iface);
+ a.iface = krt_temp_iface(p, iface);
}
else
{
@@ -160,43 +128,15 @@ krt_parse_entry(byte *ent, struct krt_proto *x)
e = rte_get_temp(&a);
e->net = net;
- old = net->routes;
- if (old && !krt_capable(old))
- old = NULL;
- if (old)
- {
- if (krt_uptodate(e, net->routes))
- verdict = KRF_SEEN;
- else
- verdict = KRF_UPDATE;
- }
- else if (p->learn && !net->routes)
- verdict = KRF_LEARN;
- else
- verdict = KRF_DELETE;
-
- DBG("krt_parse_entry: verdict=%s\n", ((char *[]) { "CREATE", "SEEN", "UPDATE", "DELETE", "LEARN" }) [verdict]);
-
- net->n.flags = verdict;
- if (verdict != KRF_SEEN)
- {
- /* Get a cached copy of attributes and link the route */
- a.source = RTS_DUMMY;
- e->attrs = rta_lookup(&a);
- e->next = net->routes;
- net->routes = e;
- }
- else
- rte_free(e);
+ krt_got_route(p, e);
}
-static int
-krt_scan_proc(struct krt_proto *p)
+void
+krt_scan_fire(struct krt_proto *p)
{
byte buf[32768];
int l, seen_hdr;
- DBG("Scanning kernel routing table...\n");
if (krt_scan_fd < 0)
{
krt_scan_fd = open("/proc/net/route", O_RDONLY);
@@ -206,7 +146,7 @@ krt_scan_proc(struct krt_proto *p)
else if (lseek(krt_scan_fd, 0, SEEK_SET) < 0)
{
log(L_ERR "krt seek: %m");
- return 0;
+ return;
}
seen_hdr = 0;
while ((l = read(krt_scan_fd, buf, sizeof(buf))) > 0)
@@ -215,7 +155,7 @@ krt_scan_proc(struct krt_proto *p)
if (l & 127)
{
log(L_ERR "krt read: misaligned entry: l=%d", l);
- return 0;
+ return;
}
while (l >= 128)
{
@@ -228,114 +168,20 @@ krt_scan_proc(struct krt_proto *p)
if (l < 0)
{
log(L_ERR "krt read: %m");
- return 0;
+ return;
}
DBG("KRT scan done, seen %d lines\n", seen_hdr);
- return 1;
-}
-
-static void
-krt_prune(struct krt_proto *p)
-{
- 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;
- int verdict = f->flags;
- rte *new, *old;
-
- if (verdict != KRF_CREATE && verdict != KRF_SEEN)
- {
- old = n->routes;
- n->routes = old->next;
- }
- else
- old = NULL;
- new = n->routes;
-
- switch (verdict)
- {
- case KRF_CREATE:
- if (new)
- {
- if (new->attrs->source == RTS_INHERIT)
- {
- DBG("krt_prune: removing inherited %I/%d\n", n->n.prefix, n->n.pxlen);
- rte_update(n, &p->p, NULL);
- }
- else
- {
- DBG("krt_prune: reinstalling %I/%d\n", n->n.prefix, n->n.pxlen);
- krt_add_route(new);
- }
- }
- break;
- case KRF_SEEN:
- /* Nothing happens */
- break;
- case KRF_UPDATE:
- DBG("krt_prune: updating %I/%d\n", n->n.prefix, n->n.pxlen);
- krt_remove_route(old);
- krt_add_route(new);
- break;
- case KRF_DELETE:
- DBG("krt_prune: deleting %I/%d\n", n->n.prefix, n->n.pxlen);
- krt_remove_route(old);
- break;
- case KRF_LEARN:
- DBG("krt_prune: learning %I/%d\n", n->n.prefix, n->n.pxlen);
- rte_update(n, &p->p, new);
- break;
- default:
- bug("krt_prune: invalid route status");
- }
-
- if (old)
- rte_free(old);
- f->flags = 0;
- }
- FIB_WALK_END;
-}
-
-void
-krt_scan_ifaces_done(struct krt_proto *x)
-{
- SCANOPT;
- SCANSTAT;
-
- s->accum_time += ((struct krt_config *) x->p.cf)->ifopt.scan_time;
- if (p->scan_time && s->accum_time >= p->scan_time)
- {
- s->accum_time %= p->scan_time;
- if (krt_scan_proc(x))
- krt_prune(x);
- }
}
void
krt_scan_preconfig(struct krt_config *c)
{
- c->scanopt.scan_time = 60;
- c->scanopt.learn = 0;
}
void
krt_scan_start(struct krt_proto *x)
{
- SCANOPT;
- SCANSTAT;
-
- /* Force krt scan after first interface scan */
- s->accum_time = p->scan_time - ((struct krt_config *) x->p.cf)->ifopt.scan_time;
-
- init_list(&s->temp_ifs);
+ init_list(&x->scan.temp_ifs);
}
void
diff --git a/sysdep/linux/krt-scan.h b/sysdep/linux/krt-scan.h
index ef1f729..c5bf588 100644
--- a/sysdep/linux/krt-scan.h
+++ b/sysdep/linux/krt-scan.h
@@ -1,5 +1,5 @@
/*
- * BIRD -- Linux Kernel Route Syncer -- Scanning Parameters
+ * BIRD -- Linux Kernel Route Syncer -- Scanning
*
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
*
@@ -10,13 +10,10 @@
#define _BIRD_KRT_SCAN_H_
struct krt_scan_params {
- int learn; /* Should we learn routes from the kernel? */
- int scan_time; /* How often should we scan krt, 0=only on startup */
};
struct krt_scan_status {
list temp_ifs; /* Temporary interfaces */
- int accum_time; /* Accumulated scanning time */
};
#endif
diff --git a/sysdep/linux/netlink/Modules b/sysdep/linux/netlink/Modules
index 8033810..c26f7f7 100644
--- a/sysdep/linux/netlink/Modules
+++ b/sysdep/linux/netlink/Modules
@@ -1,3 +1,5 @@
-krt.c
-krt.h
-krt.Y
+krt-iface.h
+krt-set.h
+krt-scan.h
+netlink.c
+netlink.Y
diff --git a/sysdep/linux/netlink/krt-iface.h b/sysdep/linux/netlink/krt-iface.h
new file mode 100644
index 0000000..5dfb934
--- /dev/null
+++ b/sysdep/linux/netlink/krt-iface.h
@@ -0,0 +1,26 @@
+/*
+ * BIRD -- Unix Kernel Netlink Interface Syncer -- Dummy Include File
+ *
+ * (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_KRT_IFACE_H_
+#define _BIRD_KRT_IFACE_H_
+
+/*
+ * We don't have split iface/scan/set parts. See krt-scan.h.
+ */
+
+struct krt_if_params {
+};
+
+struct krt_if_status {
+};
+
+static inline void krt_if_preconfig(struct krt_config *c) { };
+static inline void krt_if_start(struct krt_proto *p) { };
+static inline void krt_if_shutdown(struct krt_proto *p) { };
+
+#endif
diff --git a/sysdep/linux/netlink/krt-scan.h b/sysdep/linux/netlink/krt-scan.h
new file mode 100644
index 0000000..cd118de
--- /dev/null
+++ b/sysdep/linux/netlink/krt-scan.h
@@ -0,0 +1,26 @@
+/*
+ * BIRD -- Linux Kernel Netlink Route Syncer -- Scanning
+ *
+ * (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_KRT_SCAN_H_
+#define _BIRD_KRT_SCAN_H_
+
+/*
+ * We don't have split iface/scan/set for Netlink. All options
+ * and run-time parameters are declared here instead of splitting
+ * to krt-set.h, krt-iface.h and this file.
+ */
+
+struct krt_scan_params {
+ int async; /* Allow asynchronous events */
+};
+
+struct krt_scan_status {
+ list temp_ifs; /* Temporary interfaces */
+};
+
+#endif
diff --git a/sysdep/linux/netlink/krt-set.h b/sysdep/linux/netlink/krt-set.h
new file mode 100644
index 0000000..32fdad0
--- /dev/null
+++ b/sysdep/linux/netlink/krt-set.h
@@ -0,0 +1,26 @@
+/*
+ * BIRD -- Unix Kernel Netlink Route Syncer -- Dummy Include File
+ *
+ * (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_KRT_SET_H_
+#define _BIRD_KRT_SET_H_
+
+/*
+ * We don't have split iface/scan/set parts. See krt-scan.h.
+ */
+
+struct krt_set_params {
+};
+
+struct krt_set_status {
+};
+
+static inline void krt_set_preconfig(struct krt_config *c) { };
+static inline void krt_set_start(struct krt_proto *p) { };
+static inline void krt_set_shutdown(struct krt_proto *p) { };
+
+#endif
diff --git a/sysdep/linux/netlink/krt.Y b/sysdep/linux/netlink/krt.Y
deleted file mode 100644
index c572640..0000000
--- a/sysdep/linux/netlink/krt.Y
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * BIRD -- Netlink Interface Configuration
- *
- * (c) 1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-CF_HDR
-
-#include "lib/krt.h"
-
-#define KRT_PROTO ((struct krt_config *) this_proto)
-
-CF_DECLS
-
-CF_KEYWORDS(KERNEL, PERSIST, ROUTE, SCAN, TIME, LEARN)
-
-CF_GRAMMAR
-
-/* Kernel protocol */
-
-CF_ADDTO(proto, kern_proto '}')
-
-kern_proto_start: proto_start KERNEL {
- if (!(this_proto = cf_krt)) cf_error("Kernel protocol already defined");
- cf_krt = NULL;
- }
- ;
-
-kern_proto:
- kern_proto_start '{'
- | kern_proto proto_item ';'
- | kern_proto kern_item ';'
- ;
-
-kern_item:
- PERSIST bool { KRT_PROTO->persist = $2; }
- | SCAN TIME expr { KRT_PROTO->scan_time = $3; }
- | LEARN bool { KRT_PROTO->learn = $2; }
- | ROUTE SCAN TIME expr { KRT_PROTO->route_scan_time = $4; }
- ;
-
-CF_CODE
-
-CF_END
diff --git a/sysdep/linux/netlink/krt.h b/sysdep/linux/netlink/krt.h
deleted file mode 100644
index 8dd55cc..0000000
--- a/sysdep/linux/netlink/krt.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * BIRD -- Linux Netlink Interface
- *
- * (c) 1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_NETLINK_KRT_H_
-#define _BIRD_NETLINK_KRT_H_
-
-extern struct protocol proto_unix_kernel;
-
-struct krt_config {
- struct proto_config c;
- int persist; /* Keep routes when we exit */
- int scan_time; /* How often we re-scan interfaces */
- int route_scan_time; /* How often we re-scan routes */
- int learn; /* Learn routes from other sources */
-};
-
-extern struct proto_config *cf_krt;
-
-struct krt_proto {
- struct proto p;
-};
-
-void scan_if_init(void);
-
-#endif
diff --git a/sysdep/linux/netlink/netlink.Y b/sysdep/linux/netlink/netlink.Y
new file mode 100644
index 0000000..b5c45f2
--- /dev/null
+++ b/sysdep/linux/netlink/netlink.Y
@@ -0,0 +1,25 @@
+/*
+ * BIRD -- Linux Netlink Configuration
+ *
+ * (c) 1999 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+CF_HDR
+
+CF_DECLS
+
+CF_KEYWORDS(ASYNC)
+
+CF_GRAMMAR
+
+CF_ADDTO(kern_proto, kern_proto nl_item ';')
+
+nl_item:
+ ASYNC bool { THIS_KRT->scan.async = $2; }
+ ;
+
+CF_CODE
+
+CF_END
diff --git a/sysdep/linux/netlink/krt.c b/sysdep/linux/netlink/netlink.c
index c399e20..6e6fafd 100644
--- a/sysdep/linux/netlink/krt.c
+++ b/sysdep/linux/netlink/netlink.c
@@ -15,8 +15,6 @@
#define LOCAL_DEBUG
-#undef ASYNC_NETLINK /* Define if async notifications should be used (debug) */
-
#include "nest/bird.h"
#include "nest/route.h"
#include "nest/protocol.h"
@@ -46,13 +44,11 @@
#define MSG_TRUNC 0x20
#endif
-struct proto_config *cf_krt;
-
/*
* Synchronous Netlink interface
*/
-static int nl_sync_fd; /* Unix socket for synchronous netlink actions */
+static int nl_sync_fd = -1; /* Unix socket for synchronous netlink actions */
static u32 nl_sync_seq; /* Sequence number of last request sent */
static byte *nl_rx_buffer; /* Receive buffer */
@@ -62,6 +58,19 @@ static struct nlmsghdr *nl_last_hdr; /* Recently received packet */
static unsigned int nl_last_size;
static void
+nl_open(void)
+{
+ if (nl_sync_fd < 0)
+ {
+ nl_sync_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (nl_sync_fd < 0)
+ die("Unable to open rtnetlink socket: %m");
+ nl_sync_seq = now;
+ nl_rx_buffer = xmalloc(nl_rx_size);
+ }
+}
+
+static void
nl_send(void *rq, int size)
{
struct nlmsghdr *nh = rq;
@@ -327,8 +336,8 @@ nl_parse_addr(struct nlmsghdr *h)
if_update(&f);
}
-static void
-nl_scan_ifaces(void)
+void
+krt_if_scan(struct krt_proto *p)
{
struct nlmsghdr *h;
@@ -352,46 +361,48 @@ nl_scan_ifaces(void)
}
/*
- * Asynchronous Netlink interface
+ * Routes
*/
-static sock *nl_async_sk; /* BIRD socket for asynchronous notifications */
+int
+krt_capable(rte *e)
+{
+ return 1; /* FIXME */
+}
-static int
-nl_async_hook(sock *sk, int size)
+void
+krt_set_notify(struct proto *p, net *n, rte *new, rte *old)
+{
+ /* FIXME */
+}
+
+void
+krt_scan_fire(struct krt_proto *p)
{
- DBG("nl_async_hook\n");
- return 0;
}
/*
- * Protocol core
+ * Asynchronous Netlink interface
*/
-static void
-krt_preconfig(struct protocol *x, struct config *c)
-{
- struct krt_config *z = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config));
-
- cf_krt = &z->c;
- z->c.preference = DEF_PREF_UKR;
-}
+static sock *nl_async_sk; /* BIRD socket for asynchronous notifications */
-static struct proto *
-krt_init(struct proto_config *c)
+static int
+nl_async_hook(sock *sk, int size)
{
- struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
-
- return &p->p;
+ DBG("nl_async_hook\n");
+ return 0;
}
static void
-nl_open_async(struct proto *p)
+nl_open_async(struct krt_proto *p)
{
sock *sk;
struct sockaddr_nl sa;
- sk = nl_async_sk = sk_new(p->pool);
+ DBG("KRT: Opening async netlink socket\n");
+
+ sk = nl_async_sk = sk_new(p->p.pool);
sk->type = SK_MAGIC;
sk->rx_hook = nl_async_hook;
sk->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
@@ -405,43 +416,25 @@ nl_open_async(struct proto *p)
die("Unable to bind secondary rtnetlink socket: %m");
}
-static int
-krt_start(struct proto *p)
-{
-#ifdef ASYNC_NETLINK
- nl_open_async(p);
-#endif
-
- /* FIXME: Filter kernel routing table etc. */
+/*
+ * Interface to the UNIX krt module
+ */
- return PS_UP;
+void
+krt_scan_preconfig(struct krt_config *x)
+{
+ x->scan.async = 1;
}
-static int
-krt_shutdown(struct proto *p)
+void
+krt_scan_start(struct krt_proto *p)
{
- /* FIXME: Remove all our routes from the kernel */
-
- return PS_DOWN;
+ nl_open();
+ if (KRT_CF->scan.async)
+ nl_open_async(p);
}
void
-scan_if_init(void)
+krt_scan_shutdown(struct krt_proto *p)
{
- nl_sync_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (nl_sync_fd < 0)
- die("Unable to open rtnetlink socket: %m");
- nl_sync_seq = now;
- nl_rx_buffer = xmalloc(nl_rx_size);
- /* FIXME: Should we fetch our local address and compare it with addresses of all incoming messages? */
-
- nl_scan_ifaces();
}
-
-struct protocol proto_unix_kernel = {
- name: "Kernel",
- preconfig: krt_preconfig,
- init: krt_init,
- start: krt_start,
- shutdown: krt_shutdown
-};
diff --git a/sysdep/unix/Modules b/sysdep/unix/Modules
index e2ff0f8..bb0385d 100644
--- a/sysdep/unix/Modules
+++ b/sysdep/unix/Modules
@@ -4,14 +4,16 @@ timer.h
io.c
unix.h
-#ifndef CONFIG_NETLINK
-sync-if.c
-sync-rt.c
-krt.Y
+krt.c
krt.h
+krt.Y
+
+#ifdef CONFIG_UNIX_IFACE
+krt-iface.c
+krt-iface.h
+#endif
+
+#ifdef CONFIG_UNIX_SET
krt-set.c
krt-set.h
-krt-set.Y
-krt-iface.h
-krt-iface.Y
#endif
diff --git a/sysdep/unix/krt-iface.Y b/sysdep/unix/krt-iface.Y
deleted file mode 100644
index c74eb02..0000000
--- a/sysdep/unix/krt-iface.Y
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * BIRD -- UNIX Interface Syncer Configuration
- *
- * (c) 1998 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-CF_HDR
-
-#include "lib/krt-scan.h"
-
-CF_DECLS
-
-CF_KEYWORDS(LEARN, ROUTE, SCAN, TIME)
-
-CF_GRAMMAR
-
-CF_ADDTO(kern_proto, kern_proto krt_if_item ';')
-
-krt_if_item:
- SCAN TIME expr {
- /* Scan time of 0 means scan on startup only */
- ((struct krt_config *) this_proto)->ifopt.scan_time = $3;
- }
- ;
-
-CF_CODE
-
-CF_END
diff --git a/sysdep/unix/sync-if.c b/sysdep/unix/krt-iface.c
index 3dfa4f0..3b665a4 100644
--- a/sysdep/unix/sync-if.c
+++ b/sysdep/unix/krt-iface.c
@@ -24,9 +24,7 @@
#include "unix.h"
-int if_scan_sock;
-
-static timer *if_scan_timer;
+int if_scan_sock = -1;
static void
scan_ifs(struct ifreq *r, int cnt)
@@ -132,15 +130,13 @@ scan_ifs(struct ifreq *r, int cnt)
if_end_update();
}
-static void
-scan_if(timer *t)
+void
+krt_if_scan(struct krt_proto *p)
{
struct ifconf ic;
static int last_ifbuf_size = 4*sizeof(struct ifreq);
int res;
- struct krt_proto *p = t->data;
- DBG("It's interface scan time...\n");
for(;;)
{
if (last_ifbuf_size)
@@ -173,40 +169,26 @@ scan_if(timer *t)
DBG("Increased ifconf buffer size to %d\n", last_ifbuf_size);
#endif
}
- krt_scan_ifaces_done(p);
-}
-
-void
-krt_if_start(struct krt_proto *p)
-{
- struct krt_config *c = (struct krt_config *) p->p.cf;
-
- if_scan_timer = tm_new(p->p.pool);
- if_scan_timer->hook = scan_if;
- if_scan_timer->data = p;
- if_scan_timer->recurrent = c->ifopt.scan_time;
- scan_if(if_scan_timer);
- tm_start(if_scan_timer, c->ifopt.scan_time);
}
void
krt_if_preconfig(struct krt_config *c)
{
- c->ifopt.scan_time = 60;
}
void
-krt_if_shutdown(struct krt_proto *p)
+krt_if_start(struct krt_proto *p)
{
- tm_stop(if_scan_timer);
- /* FIXME: What should we do with interfaces? */
+ if (if_scan_sock < 0)
+ {
+ if_scan_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+ DBG("Using socket %d for interface and route scanning\n", if_scan_sock);
+ if (if_scan_sock < 0)
+ die("Cannot create scanning socket: %m");
+ }
}
void
-scan_if_init(void)
+krt_if_shutdown(struct krt_proto *p)
{
- if_scan_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
- DBG("Using socket %d for interface and route scanning\n", if_scan_sock);
- if (if_scan_sock < 0)
- die("Cannot create scanning socket: %m");
}
diff --git a/sysdep/unix/krt-iface.h b/sysdep/unix/krt-iface.h
index 87c8851..b27e86d 100644
--- a/sysdep/unix/krt-iface.h
+++ b/sysdep/unix/krt-iface.h
@@ -1,5 +1,5 @@
/*
- * BIRD -- Unix Kernel Interface Syncer -- Setting Parameters
+ * BIRD -- Unix Kernel Interface Syncer
*
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
*
@@ -10,10 +10,11 @@
#define _BIRD_KRT_IFACE_H_
struct krt_if_params {
- int scan_time;
};
struct krt_if_status {
};
+extern int if_scan_sock;
+
#endif
diff --git a/sysdep/unix/krt-set.Y b/sysdep/unix/krt-set.Y
deleted file mode 100644
index 551ee16..0000000
--- a/sysdep/unix/krt-set.Y
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * BIRD -- UNIX Kernel Syncer Configuration
- *
- * (c) 1998--1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-CF_HDR
-
-#include "lib/krt-scan.h"
-
-CF_DECLS
-
-CF_KEYWORDS(PERSIST)
-
-CF_GRAMMAR
-
-CF_ADDTO(kern_proto, kern_proto krt_set_item ';')
-
-krt_set_item:
- PERSIST bool {
- ((struct krt_config *) this_proto)->setopt.persist = $2;
- }
- ;
-
-CF_CODE
-
-CF_END
diff --git a/sysdep/unix/krt-set.c b/sysdep/unix/krt-set.c
index e77015b..dae01f4 100644
--- a/sysdep/unix/krt-set.c
+++ b/sysdep/unix/krt-set.c
@@ -84,7 +84,7 @@ krt_ioctl(int ioc, rte *e, char *name)
log(L_ERR "%s(%I/%d): %m", name, net->n.prefix, net->n.pxlen);
}
-void
+static void
krt_remove_route(rte *old)
{
net *net = old->net;
@@ -98,7 +98,7 @@ krt_remove_route(rte *old)
krt_ioctl(SIOCDELRT, old, "SIOCDELRT");
}
-void
+static void
krt_add_route(rte *new)
{
net *net = new->net;
@@ -126,7 +126,6 @@ krt_set_start(struct krt_proto *x)
{
if (if_scan_sock < 0)
bug("krt set: missing socket");
- x->p.rt_notify = krt_set_notify;
}
void
@@ -137,25 +136,4 @@ krt_set_preconfig(struct krt_config *c)
void
krt_set_shutdown(struct krt_proto *x)
{
- struct rtable *t = &master_table;
-
- if (((struct krt_config *) x->p.cf)->setopt.persist)
- return;
- DBG("Flushing kernel routes...\n");
- while (t && t->tos)
- t = t->sibling;
- if (!t)
- return;
- FIB_WALK(&t->fib, f)
- {
- net *n = (net *) f;
- rte *e = n->routes;
- if (e)
- {
- rta *a = e->attrs;
- if (a->source != RTS_DEVICE && a->source != RTS_INHERIT)
- krt_remove_route(e);
- }
- }
- FIB_WALK_END;
}
diff --git a/sysdep/unix/krt-set.h b/sysdep/unix/krt-set.h
index ec96e65..cfa5fb7 100644
--- a/sysdep/unix/krt-set.h
+++ b/sysdep/unix/krt-set.h
@@ -1,5 +1,5 @@
/*
- * BIRD -- Unix Kernel Route Syncer -- Setting Parameters
+ * BIRD -- Unix Kernel Route Syncer -- Setting
*
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
*
@@ -10,15 +10,9 @@
#define _BIRD_KRT_SET_H_
struct krt_set_params {
- int persist;
};
struct krt_set_status {
};
-void krt_remove_route(rte *old);
-void krt_add_route(rte *new);
-int krt_capable(rte *e);
-void krt_set_notify(struct proto *x, net *net, rte *new, rte *old);
-
#endif
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index 7711f3b..661e505 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -10,9 +10,11 @@ CF_HDR
#include "lib/krt.h"
+#define THIS_KRT ((struct krt_config *) this_proto)
+
CF_DECLS
-CF_KEYWORDS(KERNEL)
+CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, ROUTE, LEARN)
CF_GRAMMAR
@@ -28,6 +30,17 @@ kern_proto_start: proto_start KERNEL {
CF_ADDTO(kern_proto, kern_proto_start '{')
CF_ADDTO(kern_proto, kern_proto proto_item ';')
+CF_ADDTO(kern_proto, kern_proto kern_item ';')
+
+kern_item:
+ PERSIST bool { THIS_KRT->persist = $2; }
+ | SCAN TIME expr {
+ /* Scan time of 0 means scan on startup only */
+ THIS_KRT->scan_time = $3;
+ }
+ | ROUTE SCAN TIME expr { THIS_KRT->route_scan_time = $4; }
+ | LEARN bool { THIS_KRT->learn = $2; }
+ ;
CF_CODE
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
new file mode 100644
index 0000000..d44a57d
--- /dev/null
+++ b/sysdep/unix/krt.c
@@ -0,0 +1,291 @@
+/*
+ * BIRD -- UNIX Kernel Synchronization
+ *
+ * (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#define LOCAL_DEBUG
+
+#include "nest/bird.h"
+#include "nest/iface.h"
+#include "nest/route.h"
+#include "nest/protocol.h"
+#include "lib/timer.h"
+
+#include "unix.h"
+#include "krt.h"
+
+struct proto_config *cf_krt;
+
+/*
+ * Routes
+ */
+
+static void
+krt_flush_routes(struct krt_proto *p)
+{
+ struct rtable *t = &master_table;
+
+ DBG("Flushing kernel routes...\n");
+ while (t && t->tos)
+ t = t->sibling;
+ if (!t)
+ return;
+ FIB_WALK(&t->fib, f)
+ {
+ net *n = (net *) f;
+ rte *e = n->routes;
+ if (e)
+ {
+ rta *a = e->attrs;
+ if (a->source != RTS_DEVICE && a->source != RTS_INHERIT)
+ krt_set_notify(&p->p, e->net, e, NULL);
+ }
+ }
+ FIB_WALK_END;
+}
+
+/* FIXME: Inbound/outbound route filtering? */
+/* FIXME: Synchronization of multiple routing tables? */
+
+static int
+krt_uptodate(rte *k, rte *e)
+{
+ rta *ka = k->attrs, *ea = e->attrs;
+
+ if (ka->dest != ea->dest)
+ return 0;
+ switch (ka->dest)
+ {
+ case RTD_ROUTER:
+ return ipa_equal(ka->gw, ea->gw);
+ case RTD_DEVICE:
+ return !strcmp(ka->iface->name, ea->iface->name);
+ default:
+ return 1;
+ }
+}
+
+/*
+ * This gets called back when the low-level scanning code discovers a route.
+ * We expect that the route is a temporary rte and its attributes are uncached.
+ */
+
+void
+krt_got_route(struct krt_proto *p, rte *e)
+{
+ rte *old;
+ net *net = e->net;
+ int verdict;
+
+ if (net->n.flags)
+ {
+ /* Route to this destination was already seen. Strange, but it happens... */
+ DBG("Already seen.\n");
+ return;
+ }
+
+ old = net->routes;
+ if (old && !krt_capable(old))
+ old = NULL;
+ if (old)
+ {
+ if (krt_uptodate(e, net->routes))
+ verdict = KRF_SEEN;
+ else
+ verdict = KRF_UPDATE;
+ }
+ else if (KRT_CF->learn && !net->routes)
+ verdict = KRF_LEARN;
+ else
+ verdict = KRF_DELETE;
+
+ DBG("krt_parse_entry: verdict=%s\n", ((char *[]) { "CREATE", "SEEN", "UPDATE", "DELETE", "LEARN" }) [verdict]);
+
+ net->n.flags = verdict;
+ if (verdict != KRF_SEEN)
+ {
+ /* Get a cached copy of attributes and link the route */
+ rta *a = e->attrs;
+ a->source = RTS_DUMMY;
+ e->attrs = rta_lookup(a);
+ e->next = net->routes;
+ net->routes = e;
+ }
+ else
+ rte_free(e);
+}
+
+static void
+krt_prune(struct krt_proto *p)
+{
+ struct proto *pp = &p->p;
+ 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;
+ int verdict = f->flags;
+ rte *new, *old;
+
+ if (verdict != KRF_CREATE && verdict != KRF_SEEN)
+ {
+ old = n->routes;
+ n->routes = old->next;
+ }
+ else
+ old = NULL;
+ new = n->routes;
+
+ switch (verdict)
+ {
+ case KRF_CREATE:
+ if (new)
+ {
+ if (new->attrs->source == RTS_INHERIT)
+ {
+ DBG("krt_prune: removing inherited %I/%d\n", n->n.prefix, n->n.pxlen);
+ rte_update(n, pp, NULL);
+ }
+ else
+ {
+ DBG("krt_prune: reinstalling %I/%d\n", n->n.prefix, n->n.pxlen);
+ krt_set_notify(pp, n, new, NULL);
+ }
+ }
+ break;
+ case KRF_SEEN:
+ /* Nothing happens */
+ break;
+ case KRF_UPDATE:
+ DBG("krt_prune: updating %I/%d\n", n->n.prefix, n->n.pxlen);
+ krt_set_notify(pp, n, new, old);
+ break;
+ case KRF_DELETE:
+ DBG("krt_prune: deleting %I/%d\n", n->n.prefix, n->n.pxlen);
+ krt_set_notify(pp, n, NULL, old);
+ break;
+ case KRF_LEARN:
+ DBG("krt_prune: learning %I/%d\n", n->n.prefix, n->n.pxlen);
+ rte_update(n, pp, new);
+ break;
+ default:
+ bug("krt_prune: invalid route status");
+ }
+
+ if (old)
+ rte_free(old);
+ f->flags = 0;
+ }
+ FIB_WALK_END;
+}
+
+/*
+ * Periodic scanning
+ */
+
+static timer *krt_scan_timer;
+
+static void
+krt_scan(timer *t)
+{
+ struct krt_proto *p = t->data;
+
+ DBG("KRT: It's scan time...\n");
+ krt_if_scan(p);
+
+ p->accum_time += KRT_CF->scan_time;
+ if (KRT_CF->route_scan_time && p->accum_time >= KRT_CF->route_scan_time)
+ {
+ p->accum_time %= KRT_CF->route_scan_time;
+ DBG("Scanning kernel routing table...\n");
+ krt_scan_fire(p);
+ krt_prune(p);
+ }
+}
+
+/*
+ * Protocol glue
+ */
+
+static int
+krt_start(struct proto *P)
+{
+ struct krt_proto *p = (struct krt_proto *) P;
+
+ p->accum_time = 0;
+
+ krt_if_start(p);
+ krt_scan_start(p);
+ krt_set_start(p);
+
+ /* Start periodic interface scanning */
+ krt_scan_timer = tm_new(P->pool);
+ krt_scan_timer->hook = krt_scan;
+ krt_scan_timer->data = p;
+ krt_scan_timer->recurrent = KRT_CF->scan_time;
+ krt_scan(krt_scan_timer);
+ tm_start(krt_scan_timer, KRT_CF->scan_time);
+
+ return PS_UP;
+}
+
+int
+krt_shutdown(struct proto *P)
+{
+ struct krt_proto *p = (struct krt_proto *) P;
+
+ if (!KRT_CF->persist)
+ krt_flush_routes(p);
+
+ krt_set_shutdown(p);
+ krt_scan_shutdown(p);
+
+ /* Stop periodic interface scans */
+ tm_stop(krt_scan_timer);
+ krt_if_shutdown(p);
+ /* FIXME: What should we do with interfaces? */
+
+ return PS_DOWN;
+}
+
+static void
+krt_preconfig(struct protocol *x, struct config *c)
+{
+ struct krt_config *z = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config));
+
+ cf_krt = &z->c;
+ z->c.preference = DEF_PREF_UKR;
+ z->scan_time = z->route_scan_time = 60;
+ z->learn = z->persist = 0;
+
+ krt_scan_preconfig(z);
+ krt_set_preconfig(z);
+ krt_if_preconfig(z);
+}
+
+static struct proto *
+krt_init(struct proto_config *c)
+{
+ struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
+
+ p->p.rt_notify = krt_set_notify;
+ return &p->p;
+}
+
+struct protocol proto_unix_kernel = {
+ name: "Kernel",
+ priority: 90,
+ preconfig: krt_preconfig,
+ init: krt_init,
+ start: krt_start,
+ shutdown: krt_shutdown,
+};
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index cebf335..1c59799 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -1,7 +1,7 @@
/*
- * BIRD -- Unix Kernel Route Syncer
+ * BIRD -- UNIX Kernel Route Syncer
*
- * (c) 1998 Martin Mares <mj@ucw.cz>
+ * (c) 1998--1999 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -9,6 +9,9 @@
#ifndef _BIRD_KRT_H_
#define _BIRD_KRT_H_
+struct krt_config;
+struct krt_proto;
+
#include "lib/krt-scan.h"
#include "lib/krt-set.h"
#include "lib/krt-iface.h"
@@ -21,32 +24,42 @@
#define KRF_DELETE 3 /* Should be deleted */
#define KRF_LEARN 4 /* We should learn this route */
-/* sync-rt.c */
+/* krt.c */
extern struct protocol proto_unix_kernel;
struct krt_config {
struct proto_config c;
- struct krt_set_params setopt;
- struct krt_scan_params scanopt;
- struct krt_if_params ifopt;
+ struct krt_set_params set;
+ struct krt_scan_params scan;
+ struct krt_if_params iface;
+ int persist; /* Keep routes when we exit */
+ int scan_time; /* How often we re-scan interfaces */
+ int route_scan_time; /* How often we re-scan routes */
+ int learn; /* Learn routes from other sources */
};
struct krt_proto {
struct proto p;
- struct krt_set_status setstat;
- struct krt_scan_status scanstat;
- struct krt_if_status ifstat;
+ struct krt_set_status set;
+ struct krt_scan_status scan;
+ struct krt_if_status iface;
+ int accum_time; /* Accumulated route scanning time */
};
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);
+
/* krt-scan.c */
void krt_scan_preconfig(struct krt_config *);
void krt_scan_start(struct krt_proto *);
void krt_scan_shutdown(struct krt_proto *);
-void krt_scan_ifaces_done(struct krt_proto *);
+
+void krt_scan_fire(struct krt_proto *);
/* krt-set.c */
@@ -54,15 +67,15 @@ void krt_set_preconfig(struct krt_config *);
void krt_set_start(struct krt_proto *);
void krt_set_shutdown(struct krt_proto *);
-/* sync-if.c */
-
-extern int if_scan_sock;
-extern int if_scan_period;
+int krt_capable(rte *e);
+void krt_set_notify(struct proto *x, net *net, rte *new, rte *old);
-void scan_if_init(void);
+/* krt-iface.c */
void krt_if_preconfig(struct krt_config *);
void krt_if_start(struct krt_proto *);
void krt_if_shutdown(struct krt_proto *);
+void krt_if_scan(struct krt_proto *);
+
#endif
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 71bb712..e5e9934 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -204,8 +204,6 @@ main(int argc, char **argv)
signal_init();
- scan_if_init();
-
protos_start();
ev_run_list(&global_event_list);
diff --git a/sysdep/unix/sync-rt.c b/sysdep/unix/sync-rt.c
deleted file mode 100644
index 99ef92a..0000000
--- a/sysdep/unix/sync-rt.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * BIRD -- Unix Routing Table Scanning and Syncing
- *
- * (c) 1998--1999 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 <errno.h>
-
-#define LOCAL_DEBUG
-
-#include "nest/bird.h"
-#include "nest/iface.h"
-#include "nest/route.h"
-#include "nest/protocol.h"
-#include "lib/timer.h"
-
-#include "unix.h"
-#include "krt.h"
-
-struct proto_config *cf_krt;
-
-static int
-krt_start(struct proto *p)
-{
- struct krt_proto *k = (struct krt_proto *) p;
-
- krt_scan_start(k);
- krt_set_start(k);
- krt_if_start(k);
- return PS_UP;
-}
-
-int
-krt_shutdown(struct proto *p)
-{
- struct krt_proto *k = (struct krt_proto *) p;
-
- krt_scan_shutdown(k);
- krt_if_shutdown(k);
- krt_set_shutdown(k);
- return PS_DOWN;
-}
-
-static void
-krt_preconfig(struct protocol *x, struct config *c)
-{
- struct krt_config *z = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config));
-
- cf_krt = &z->c;
- z->c.preference = DEF_PREF_UKR;
- krt_scan_preconfig(z);
- krt_set_preconfig(z);
- krt_if_preconfig(z);
-}
-
-static struct proto *
-krt_init(struct proto_config *c)
-{
- struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
-
- return &p->p;
-}
-
-struct protocol proto_unix_kernel = {
- name: "Kernel",
- preconfig: krt_preconfig,
- init: krt_init,
- start: krt_start,
- shutdown: krt_shutdown,
-};