Merge pull request #3746 from ton31337/feature/rfc_8212

bgpd: Implement RFC8212
This commit is contained in:
David Lamparter 2019-02-19 13:54:23 +01:00 committed by GitHub
commit cbcaac3fb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 114 additions and 0 deletions

View File

@ -1224,6 +1224,20 @@ static int bgp_input_modifier(struct peer *peer, struct prefix *p,
} }
} }
/* RFC 8212 to prevent route leaks.
* This specification intends to improve this situation by requiring the
* explicit configuration of both BGP Import and Export Policies for any
* External BGP (EBGP) session such as customers, peers, or
* confederation boundaries for all enabled address families. Through
* codification of the aforementioned requirement, operators will
* benefit from consistent behavior across different BGP
* implementations.
*/
if (peer->bgp->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED)
if (!bgp_inbound_policy_exists(peer, filter))
return RMAP_DENY;
/* Route map apply. */ /* Route map apply. */
if (rmap) { if (rmap) {
memset(&rmap_path, 0, sizeof(struct bgp_path_info)); memset(&rmap_path, 0, sizeof(struct bgp_path_info));
@ -1777,6 +1791,20 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
} }
} }
/* RFC 8212 to prevent route leaks.
* This specification intends to improve this situation by requiring the
* explicit configuration of both BGP Import and Export Policies for any
* External BGP (EBGP) session such as customers, peers, or
* confederation boundaries for all enabled address families. Through
* codification of the aforementioned requirement, operators will
* benefit from consistent behavior across different BGP
* implementations.
*/
if (peer->bgp->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED)
if (!bgp_outbound_policy_exists(peer, filter))
return 0;
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) { if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
if (peer->sort == BGP_PEER_IBGP if (peer->sort == BGP_PEER_IBGP
|| peer->sort == BGP_PEER_CONFED) { || peer->sort == BGP_PEER_CONFED) {
@ -4160,6 +4188,26 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
} }
} }
int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
{
if (peer->sort == BGP_PEER_EBGP
&& (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
|| FILTER_LIST_OUT_NAME(filter)
|| DISTRIBUTE_OUT_NAME(filter)))
return 1;
return 0;
}
int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
{
if (peer->sort == BGP_PEER_EBGP
&& (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
|| FILTER_LIST_IN_NAME(filter)
|| DISTRIBUTE_IN_NAME(filter)))
return 1;
return 0;
}
static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
safi_t safi) safi_t safi)
{ {

View File

@ -357,6 +357,8 @@ extern void bgp_clear_route(struct peer *, afi_t, safi_t);
extern void bgp_clear_route_all(struct peer *); extern void bgp_clear_route_all(struct peer *);
extern void bgp_clear_adj_in(struct peer *, afi_t, safi_t); extern void bgp_clear_adj_in(struct peer *, afi_t, safi_t);
extern void bgp_clear_stale_route(struct peer *, afi_t, safi_t); extern void bgp_clear_stale_route(struct peer *, afi_t, safi_t);
extern int bgp_outbound_policy_exists(struct peer *, struct bgp_filter *);
extern int bgp_inbound_policy_exists(struct peer *, struct bgp_filter *);
extern struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, extern struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
safi_t safi, struct prefix *p, safi_t safi, struct prefix *p,

View File

@ -1860,6 +1860,29 @@ DEFUN (no_bgp_always_compare_med,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(bgp_ebgp_requires_policy, bgp_ebgp_requires_policy_cmd,
"bgp ebgp-requires-policy",
"BGP specific commands\n"
"Require in and out policy for eBGP peers (RFC8212)\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
bgp->ebgp_requires_policy = DEFAULT_EBGP_POLICY_ENABLED;
return CMD_SUCCESS;
}
DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd,
"no bgp ebgp-requires-policy",
NO_STR
"BGP specific commands\n"
"Require in and out policy for eBGP peers (RFC8212)\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
bgp->ebgp_requires_policy = DEFAULT_EBGP_POLICY_DISABLED;
return CMD_SUCCESS;
}
/* "bgp deterministic-med" configuration. */ /* "bgp deterministic-med" configuration. */
DEFUN (bgp_deterministic_med, DEFUN (bgp_deterministic_med,
bgp_deterministic_med_cmd, bgp_deterministic_med_cmd,
@ -8829,6 +8852,20 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
json_addr, "routeMapForOutgoingAdvertisements", json_addr, "routeMapForOutgoingAdvertisements",
filter->map[RMAP_OUT].name); filter->map[RMAP_OUT].name);
/* ebgp-requires-policy (inbound) */
if (p->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED
&& !bgp_inbound_policy_exists(p, filter))
json_object_string_add(
json_addr, "inboundEbgpRequiresPolicy",
"Inbound updates discarded due to missing policy");
/* ebgp-requires-policy (outbound) */
if (p->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED
&& (!bgp_outbound_policy_exists(p, filter)))
json_object_string_add(
json_addr, "outboundEbgpRequiresPolicy",
"Outbound updates discarded due to missing policy");
/* unsuppress-map */ /* unsuppress-map */
if (filter->usmap.name) if (filter->usmap.name)
json_object_string_add(json_addr, json_object_string_add(json_addr,
@ -9105,6 +9142,18 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
filter->map[RMAP_OUT].map ? "*" : "", filter->map[RMAP_OUT].map ? "*" : "",
filter->map[RMAP_OUT].name); filter->map[RMAP_OUT].name);
/* ebgp-requires-policy (inbound) */
if (p->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED
&& !bgp_inbound_policy_exists(p, filter))
vty_out(vty,
" Inbound updates discarded due to missing policy\n");
/* ebgp-requires-policy (outbound) */
if (p->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED
&& !bgp_outbound_policy_exists(p, filter))
vty_out(vty,
" Outbound updates discarded due to missing policy\n");
/* unsuppress-map */ /* unsuppress-map */
if (filter->usmap.name) if (filter->usmap.name)
vty_out(vty, vty_out(vty,
@ -12823,6 +12872,10 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_always_compare_med_cmd); install_element(BGP_NODE, &bgp_always_compare_med_cmd);
install_element(BGP_NODE, &no_bgp_always_compare_med_cmd); install_element(BGP_NODE, &no_bgp_always_compare_med_cmd);
/* bgp ebgp-requires-policy */
install_element(BGP_NODE, &bgp_ebgp_requires_policy_cmd);
install_element(BGP_NODE, &no_bgp_ebgp_requires_policy_cmd);
/* "bgp deterministic-med" commands */ /* "bgp deterministic-med" commands */
install_element(BGP_NODE, &bgp_deterministic_med_cmd); install_element(BGP_NODE, &bgp_deterministic_med_cmd);
install_element(BGP_NODE, &no_bgp_deterministic_med_cmd); install_element(BGP_NODE, &no_bgp_deterministic_med_cmd);

View File

@ -2936,6 +2936,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
bgp->dynamic_neighbors_count = 0; bgp->dynamic_neighbors_count = 0;
bgp->ebgp_requires_policy = DEFAULT_EBGP_POLICY_DISABLED;
#if DFLT_BGP_IMPORT_CHECK #if DFLT_BGP_IMPORT_CHECK
bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK); bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK);
#endif #endif
@ -7577,6 +7578,11 @@ int bgp_config_write(struct vty *vty)
if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)) if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
vty_out(vty, " bgp always-compare-med\n"); vty_out(vty, " bgp always-compare-med\n");
/* RFC8212 default eBGP policy. */
if (bgp->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED)
vty_out(vty, " bgp ebgp-requires-policy\n");
/* BGP default ipv4-unicast. */ /* BGP default ipv4-unicast. */
if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4)) if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4))
vty_out(vty, " no bgp default ipv4-unicast\n"); vty_out(vty, " no bgp default ipv4-unicast\n");

View File

@ -487,6 +487,11 @@ struct bgp {
/* EVPN enable - advertise local VNIs and their MACs etc. */ /* EVPN enable - advertise local VNIs and their MACs etc. */
int advertise_all_vni; int advertise_all_vni;
/* RFC 8212 - prevent route leaks. */
int ebgp_requires_policy;
#define DEFAULT_EBGP_POLICY_DISABLED 0
#define DEFAULT_EBGP_POLICY_ENABLED 1
struct bgp_evpn_info *evpn_info; struct bgp_evpn_info *evpn_info;
/* EVPN - use RFC 8365 to auto-derive RT */ /* EVPN - use RFC 8365 to auto-derive RT */