summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2008-10-26 23:09:46 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2008-10-26 23:09:46 +0100
commit1567edea8d3da7da08092eef15bb3bd4544c6464 (patch)
tree40b780e35e0cb216e32c9fc985d83fc0afe0dada
parentb6bf284a905412cfe107b4967e55649e6194187e (diff)
downloadbird-1567edea8d3da7da08092eef15bb3bd4544c6464.tar
bird-1567edea8d3da7da08092eef15bb3bd4544c6464.zip
Bugfix for routing table breaking bug.
Here is a patch fixing a bug that causes breakage of a local routing table during shutdown of Bird. The problem was caused by shutdown of 'device' protocol before shutdown of 'kernel' protocol. When 'device' protocol went down, the route (with local network prefix) From different protocol (BGP or OSPF) became preferred and installed to the kernel routing table. Such routes were broken (like 192.168.1.0/24 via 192.168.1.2). I think it is also the cause of problem reported by Martin Kraus. The patch disables updating of kernel routing table during shutdown of Bird. I am not sure whether this is the best way to fix it, I would prefer to forbid 'kernel' protocol to overwrite routes with 'proto kernel'. The patch also fixes a problem that during shutdown sometimes routes created by Bird remained in the kernel routing table.
-rw-r--r--conf/conf.c5
-rw-r--r--sysdep/linux/netlink/netlink.c9
-rw-r--r--sysdep/unix/krt-set.c2
-rw-r--r--sysdep/unix/krt.c2
4 files changed, 10 insertions, 8 deletions
diff --git a/conf/conf.c b/conf/conf.c
index a744dca..fefcac5 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -266,7 +266,7 @@ config_commit(struct config *c)
}
if (old_config) /* Reconfiguration already in progress */
{
- if (shutting_down)
+ if (shutting_down == 2)
{
log(L_INFO "New configuration discarded due to shutdown");
config_free(c);
@@ -314,8 +314,9 @@ order_shutdown(void)
init_list(&c->protos);
init_list(&c->tables);
c->shutdown = 1;
- config_commit(c);
shutting_down = 1;
+ config_commit(c);
+ shutting_down = 2;
}
/**
diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c
index a70428e..98c63f0 100644
--- a/sysdep/linux/netlink/netlink.c
+++ b/sysdep/linux/netlink/netlink.c
@@ -498,6 +498,8 @@ nl_send_route(struct krt_proto *p, rte *e, int new)
nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
break;
case RTD_DEVICE:
+ if (!a->iface)
+ return;
r.r.rtm_type = RTN_UNICAST;
nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
break;
@@ -531,11 +533,8 @@ krt_set_notify(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
else
{
if (old)
- {
- if (!old->attrs->iface || (old->attrs->iface->flags & IF_UP))
- nl_send_route(p, old, 0);
- /* else the kernel has already flushed it */
- }
+ nl_send_route(p, old, 0);
+
if (new)
nl_send_route(p, new, 1);
}
diff --git a/sysdep/unix/krt-set.c b/sysdep/unix/krt-set.c
index bd56448..23cbe5c 100644
--- a/sysdep/unix/krt-set.c
+++ b/sysdep/unix/krt-set.c
@@ -61,6 +61,8 @@ krt_ioctl(int ioc, rte *e, char *name)
re.rt_flags |= RTF_GATEWAY;
break;
case RTD_DEVICE:
+ if (!a->iface)
+ return;
re.rt_dev = a->iface->name;
break;
#ifdef RTF_REJECT
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index a6d1727..5269eb7 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -684,7 +684,7 @@ krt_notify(struct proto *P, net *net, rte *new, rte *old, struct ea_list *attrs
{
struct krt_proto *p = (struct krt_proto *) P;
- if (shutting_down && KRT_CF->persist)
+ if (shutting_down)
return;
if (new && (!krt_capable(new) || new->attrs->source == RTS_INHERIT))
new = NULL;