struct peer *peer;
char buf[BUFSIZ];
char buf2[BUFSIZ];
+ struct bgp_filter *filter;
s = stream_dup(pkt->buffer);
peer = PAF_PEER(paf);
afi_t nhafi;
int route_map_sets_nh;
nhlen = stream_getc_from(s, vec->offset);
+ filter = &peer->filter[paf->afi][paf->safi];
+
if (peer_cap_enhe(peer, paf->afi, paf->safi))
nhafi = AFI_IP6;
else
mod_v4nh = &v4nh;
/*
- * If route-map has set the nexthop, that is always
- * used; if it is
- * specified as peer-address, the peering address is
- * picked up.
- * Otherwise, if NH is unavailable from attribute, the
- * peering addr
- * is picked up; the "NH unavailable" case also covers
- * next-hop-self
- * and some other scenarios -- see
- * subgroup_announce_check(). In
- * all other cases, use the nexthop carried in the
- * attribute unless
- * it is EBGP non-multiaccess and there is no
- * next-hop-unchanged setting.
+ * If route-map has set the nexthop, that is normally
+ * used; if it is specified as peer-address, the peering
+ * address is picked up. Otherwise, if NH is unavailable
+ * from attribute, the peering addr is picked up; the
+ * "NH unavailable" case also covers next-hop-self and
+ * some other scenarios - see subgroup_announce_check().
+ * In all other cases, use the nexthop carried in the
+ * attribute unless it is EBGP non-multiaccess and there
+ * is no next-hop-unchanged setting or the peer is EBGP
+ * and the route-map that changed the next-hop value
+ * was applied inbound rather than outbound. Updates to
+ * an EBGP peer should only modify the next-hop if it
+ * was set in an outbound route-map to that peer.
* Note: It is assumed route-map cannot set the nexthop
- * to an
- * invalid value.
+ * to an invalid value.
*/
- if (route_map_sets_nh) {
+ if (route_map_sets_nh
+ && ((peer->sort != BGP_PEER_EBGP)
+ || ROUTE_MAP_OUT(filter))) {
if (CHECK_FLAG(
vec->flags,
BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) {
stream_get_from(&v6nhglobal, s, offset_nhglobal,
IPV6_MAX_BYTELEN);
- if (route_map_sets_nh) {
+
+ /*
+ * Updates to an EBGP peer should only modify the
+ * next-hop if it was set in an outbound route-map
+ * to that peer.
+ */
+ if (route_map_sets_nh
+ && ((peer->sort != BGP_PEER_EBGP)
+ || ROUTE_MAP_OUT(filter))) {
if (CHECK_FLAG(
vec->flags,
BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) {