if (peer->sort == BGP_PEER_EBGP
&& attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
{
- if (ri->peer != bgp->peer_self && ! transparent
+ if (from != bgp->peer_self && ! transparent
&& ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC));
}
* the peer (group) is configured to receive link-local nexthop unchanged
* and it is available in the prefix OR we're not reflecting the route and
* the peer (group) to whom we're going to announce is on a shared network
+ * and this is either a self-originated route or the peer is EBGP.
*/
if (p->family == AF_INET6 || peer_cap_enhe(peer))
{
if ((CHECK_FLAG (peer->af_flags[afi][safi],
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) &&
IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_local)) ||
- (!reflect && peer->shared_network))
+ (!reflect && peer->shared_network &&
+ (from == bgp->peer_self || peer->sort == BGP_PEER_EBGP)))
{
attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
}
if (!paf)
subgroup_announce_reset_nhop ((peer_cap_enhe(peer) ? AF_INET6 : p->family), attr);
}
+ /* If IPv6/MP and nexthop does not have any override and happens to
+ * be a link-local address, reset it so that we don't pass along the
+ * source's link-local IPv6 address to recipients who may not be on
+ * the same interface.
+ */
+ if (p->family == AF_INET6 || peer_cap_enhe(peer))
+ {
+ if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
+ subgroup_announce_reset_nhop (AF_INET6, attr);
+ }
}
return 1;
/* IPv6 nexthop*/
ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
- /* There is no global nexthop. */
if (!ret)
- if_get_ipv6_local (ifp, &nexthop->v6_global);
+ {
+ /* There is no global nexthop. Use link-local address as both the
+ * global and link-local nexthop. In this scenario, the expectation
+ * for interop is that the network admin would use a route-map to
+ * specify the global IPv6 nexthop.
+ */
+ if_get_ipv6_local (ifp, &nexthop->v6_global);
+ memcpy (&nexthop->v6_local, &nexthop->v6_global,
+ IPV6_MAX_BYTELEN);
+ }
else
if_get_ipv6_local (ifp, &nexthop->v6_local);
+
+ if (if_lookup_by_ipv4 (&remote->sin.sin_addr))
+ peer->shared_network = 1;
+ else
+ peer->shared_network = 0;
#endif /* HAVE_IPV6 */
}
memcpy (&nexthop->v6_local, &local->sin6.sin6_addr,
IPV6_MAX_BYTELEN);
}
- }
- if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
- if_lookup_by_ipv6 (&remote->sin6.sin6_addr, remote->sin6.sin6_scope_id))
- peer->shared_network = 1;
- else
- peer->shared_network = 0;
+ if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
+ if_lookup_by_ipv6 (&remote->sin6.sin6_addr, remote->sin6.sin6_scope_id))
+ peer->shared_network = 1;
+ else
+ peer->shared_network = 0;
+ }
/* KAME stack specific treatment. */
#ifdef KAME