[quagga-dev 8775] [PATCH 2/3] bgpd: bug #537: find proper source address for interface update-source

David Lamparter equinox at diac24.net
Wed Aug 31 16:25:42 BST 2011


if update-source was given as interface name, bgpd was unconditionally
trying to bind to an IPv4 address from that interface.

change function to find the best-matching (number of address bits)
same-family address on the interface.
---
 bgpd/bgp_network.c |   39 +++++++++++++++++++++++++++------------
 1 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 570cc3b..511b954 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -263,21 +263,37 @@ bgp_bind_address (int sock, struct in_addr *addr)
   return 0;
 }
 
-static struct in_addr *
-bgp_update_address (struct interface *ifp)
+static int
+bgp_update_address (struct interface *ifp, const union sockunion *dst,
+		    union sockunion *addr)
 {
-  struct prefix_ipv4 *p;
+  struct prefix *p, *sel, *d;
   struct connected *connected;
   struct listnode *node;
+  int common;
+
+  d = sockunion2hostprefix (dst);
+  sel = NULL;
+  common = -1;
 
   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
     {
-      p = (struct prefix_ipv4 *) connected->address;
-
-      if (p->family == AF_INET)
-	return &p->prefix;
+      p = connected->address;
+      if (p->family != d->family)
+	continue;
+      if (prefix_common_bits (p, d) > common)
+	{
+	  sel = p;
+	  common = prefix_common_bits (sel, d);
+	}
     }
-  return NULL;
+
+  prefix_free (d);
+  if (!sel)
+    return 1;
+
+  prefix2sockunion (sel, addr);
+  return 0;
 }
 
 /* Update source selection.  */
@@ -285,7 +301,7 @@ static void
 bgp_update_source (struct peer *peer)
 {
   struct interface *ifp;
-  struct in_addr *addr;
+  union sockunion addr;
 
   /* Source is specified with interface name.  */
   if (peer->update_if)
@@ -294,11 +310,10 @@ bgp_update_source (struct peer *peer)
       if (! ifp)
 	return;
 
-      addr = bgp_update_address (ifp);
-      if (! addr)
+      if (bgp_update_address (ifp, &peer->su, &addr))
 	return;
 
-      bgp_bind_address (peer->fd, addr);
+      sockunion_bind (peer->fd, &addr, 0, &addr);
     }
 
   /* Source is specified with IP address.  */
-- 
1.7.6




More information about the Quagga-dev mailing list