From: Donald Sharp Date: Fri, 12 Jun 2015 14:59:09 +0000 (-0700) Subject: If the received MP nexthop is a martian address, treat the update as X-Git-Tag: frr-2.0-rc1~1335 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=c265ee22c8a076ba56a05a2f7279066eb0129bea;p=matthieu%2Ffrr.git If the received MP nexthop is a martian address, treat the update as an implicit withdraw as is done for the NEXT_HOP attribute in the update itself. Note: Check is implemented only for IPv6 for the global nexthop. The code will quietly ignore an invalid IPv6 link-local nexthop, if present; this is the existing behavior and is not changed. Signed-off-by: Vivek Venkataraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton --- diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 4e2e89cec8..a72c5e6dee 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2409,6 +2409,59 @@ bgp_info_addpath_rx_str(struct bgp_info *ri, char *buf) sprintf(buf, " with addpath ID %d", ri->addpath_rx_id); } +/* Check if received nexthop is valid or not. */ +static int +bgp_update_martian_nexthop (afi_t afi, safi_t safi, struct attr *attr) +{ + struct attr_extra *attre = attr->extra; + int ret = 0; + + /* Only validated for unicast and multicast currently. */ + if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST) + return 0; + + /* If NEXT_HOP is present, validate it. */ + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) + { + if (attr->nexthop.s_addr == 0 || + IPV4_CLASS_DE (ntohl (attr->nexthop.s_addr)) || + bgp_nexthop_self (attr)) + ret = 1; + } + + /* If MP_NEXTHOP is present, validate it. */ + /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop; + * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if + * it is not an IPv6 link-local address. + */ + if (attre && attre->mp_nexthop_len) + { + switch (attre->mp_nexthop_len) + { + case BGP_ATTR_NHLEN_IPV4: + case BGP_ATTR_NHLEN_VPNV4: + ret = (attre->mp_nexthop_global_in.s_addr == 0 || + IPV4_CLASS_DE (ntohl (attre->mp_nexthop_global_in.s_addr))); + break; + +#ifdef HAVE_IPV6 + case BGP_ATTR_NHLEN_IPV6_GLOBAL: + case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: + ret = (IN6_IS_ADDR_UNSPECIFIED(&attre->mp_nexthop_global) || + IN6_IS_ADDR_LOOPBACK(&attre->mp_nexthop_global) || + IN6_IS_ADDR_MULTICAST(&attre->mp_nexthop_global)); + break; +#endif /* HAVE_IPV6 */ + + default: + ret = 1; + break; + } + } + + return ret; +} + static void bgp_update_rsclient (struct peer *rsclient, u_int32_t addpath_id, afi_t afi, safi_t safi, struct attr *attr, @@ -2480,19 +2533,12 @@ bgp_update_rsclient (struct peer *rsclient, u_int32_t addpath_id, attr_new = bgp_attr_intern (&new_attr); bgp_attr_unintern (&attr_new2); - /* IPv4 unicast next hop check. */ - if ((afi == AFI_IP) && ((safi == SAFI_UNICAST && !peer_cap_enhe(peer)) - || safi == SAFI_MULTICAST)) + /* next hop check. */ + if (bgp_update_martian_nexthop (afi, safi, &new_attr)) { - /* Next hop must not be 0.0.0.0 nor Class D/E address. */ - if (new_attr.nexthop.s_addr == 0 - || IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr))) - { - bgp_attr_unintern (&attr_new); - - reason = "martian next-hop;"; - goto filtered; - } + bgp_attr_unintern (&attr_new); + reason = "martian next-hop;"; + goto filtered; } /* If the update is implicit withdraw. */ @@ -2730,25 +2776,12 @@ bgp_update_main (struct peer *peer, struct prefix *p, u_int32_t addpath_id, goto filtered; } - /* IPv4 unicast next hop check. */ - if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer)) + /* next hop check. */ + if (bgp_update_martian_nexthop (afi, safi, &new_attr)) { - /* Next hop must not be 0.0.0.0 nor Class D/E address. */ - if (new_attr.nexthop.s_addr == 0 - || IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr))) - { - reason = "martian next-hop;"; - bgp_attr_flush (&new_attr); - goto filtered; - } - - /* Next hop must not be my own address. */ - if (bgp_nexthop_self (&new_attr)) - { - reason = "local IP next-hop;"; - bgp_attr_flush (&new_attr); - goto filtered; - } + reason = "martian or self next-hop;"; + bgp_attr_flush (&new_attr); + goto filtered; } attr_new = bgp_attr_intern (&new_attr);