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

Reply via email to