Package: bird Version: 1.3.6-1 Severity: normal Tags: patch I have a VPN which creates and tears down tunnel interfaces as peers arrive and depart; to help keep things straight, particularly with firewall rules, the VPN renames its interfaces after the peer associated with the interface, rather than leaving them as `tun0', etc. Alas, BIRD gets confused by this, and fails to notice when the interface is brought up, and therefore won't propagate routes to the peer site.
What's going on, then? The problem is in `nest/iface.c' (`if_update'). This function is given an interface structure describing the new state of an interface, and is meant to alter its master record of the interface to match, and notify other parts of the program as necessary. The `if_update' function treats the interface's /name/ as being its primary identifier. It therefore searches through its list for an interface with the right name, updating it if it finds one, or appending a new interface node if it doesn't. There's a wrinkle here: if `if_update' decides that the change is `too big', it unlinks the node and then falls through to the `new interface' case, which relinks the node back onto the end of the list. This interacts badly with the Linux netlink-client code in `sysdep/linux/netlink/netlink.c', which applies updates to interface addresses by searching the interface list for an interface with a matching kernel-supplied index. Changing the index of an interface is a `big' change, which causes the interface node to be moved to the end of the list. Therefore, what happens after a change of interface name is like this. * There's an existing interface, `tun0', say, with index N. * The interface is renamed, to `vpn-terror', say. * BIRD receives the update from its netlink socket, and calls `if_update', reporting an interface called `vpn-terror' with index N. * If there's already an interface called `vpn-terror' (maybe this peer has been connected before), its node is unlinked and relinked; otherwise `if_update' creates a new node and links it. Either way, the `vpn-terror' interface node is now at the end of the list. * Either way, there's still an interface node for `tun0', also with index N. Future changes applied to this interface will find this old node instead of the new one. I've made a unpleasant patch to fix this situation, which I've included. This adds an extra pass to `if_update', moving interface nodes with the same index as the new node after the new node in the list. It'd be easier just to link the new node to the front of the list, though I suspect that upstream like the current ordering in their client output. I don't think this is the cleanest way of fixing the bug, but it works. --- /tmp/mdw/bird-1.3.6/nest/iface.c 2012-01-10 12:42:47.000000000 +0000 +++ ./nest/iface.c 2012-03-10 01:10:59.000000000 +0000 if_update(struct iface *new) { - struct iface *i; + struct iface *i, *j, *jj; unsigned c; WALK_LIST(i, iface_list) @@ -305,6 +306,26 @@ init_list(&i->neighbors); i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */ add_tail(&iface_list, &i->n); + + /* If we're unlucky then what just happened is that an interface had its + * name changed. In that case, we've just invented a new iface node with + * the new name, but with the same index number as an existing node, and + * we've just arranged so that a search by index will find the old node and + * not the new one. This isn't good, so trawl through the list again, + * picking out nodes with colliding indices and moving them to the end of + * the list. + */ + WALK_LIST_DELSAFE(j, jj, iface_list) + { + if (i == j) + break; + else if (i->index == j->index) + { + rem_node(&j->n); + add_tail(&iface_list, &j->n); + } + } + return i; } -- System Information: Debian Release: wheezy/sid APT prefers testing APT policy: (990, 'testing'), (500, 'unstable'), (500, 'stable') Architecture: i386 (i686) Kernel: Linux 3.0.0-1-686-pae (SMP w/1 CPU core) Locale: LANG=en_GB.utf8, LC_CTYPE=en_GB.utf8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages bird depends on: ii libc6 2.13-21 ii libncurses5 5.9-2 ii libreadline6 6.2-7 ii libtinfo5 5.9-2 Versions of packages bird recommends: pn bird6 <none> bird suggests no packages. -- Configuration Files: /etc/bird.conf [Errno 13] Permission denied: u'/etc/bird.conf' -- no debconf information -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org