bgpd: fix update-source for IPv6 (BZ#548)

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.
This commit is contained in:
David Lamparter 2010-02-02 20:18:23 +01:00 committed by Denis Ovsienko
parent 188506f4c6
commit 5d3c53b999

View File

@ -258,21 +258,37 @@ bgp_bind_address (int sock, struct in_addr *addr)
return 0; return 0;
} }
static struct in_addr * static int
bgp_update_address (struct interface *ifp) 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 connected *connected;
struct listnode *node; struct listnode *node;
int common;
d = sockunion2hostprefix (dst);
sel = NULL;
common = -1;
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
{ {
p = (struct prefix_ipv4 *) connected->address; p = connected->address;
if (p->family != d->family)
if (p->family == AF_INET) continue;
return &p->prefix; 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. */ /* Update source selection. */
@ -280,7 +296,7 @@ static void
bgp_update_source (struct peer *peer) bgp_update_source (struct peer *peer)
{ {
struct interface *ifp; struct interface *ifp;
struct in_addr *addr; union sockunion addr;
/* Source is specified with interface name. */ /* Source is specified with interface name. */
if (peer->update_if) if (peer->update_if)
@ -289,11 +305,10 @@ bgp_update_source (struct peer *peer)
if (! ifp) if (! ifp)
return; return;
addr = bgp_update_address (ifp); if (bgp_update_address (ifp, &peer->su, &addr))
if (! addr)
return; return;
bgp_bind_address (peer->fd, addr); sockunion_bind (peer->fd, &addr, 0, &addr);
} }
/* Source is specified with IP address. */ /* Source is specified with IP address. */