Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bgpd: Implement RFC8212 #3746

Merged
merged 1 commit into from Feb 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 48 additions & 0 deletions bgpd/bgp_route.c
Expand Up @@ -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. */
if (rmap) {
memset(&rmap_path, 0, sizeof(struct bgp_path_info));
Expand Down Expand Up @@ -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 (peer->sort == BGP_PEER_IBGP
|| peer->sort == BGP_PEER_CONFED) {
Expand Down Expand Up @@ -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,
safi_t safi)
{
Expand Down
2 changes: 2 additions & 0 deletions bgpd/bgp_route.h
Expand Up @@ -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_adj_in(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,
safi_t safi, struct prefix *p,
Expand Down
53 changes: 53 additions & 0 deletions bgpd/bgp_vty.c
Expand Up @@ -1860,6 +1860,29 @@ DEFUN (no_bgp_always_compare_med,
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. */
DEFUN (bgp_deterministic_med,
bgp_deterministic_med_cmd,
Expand Down Expand Up @@ -8829,6 +8852,20 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
json_addr, "routeMapForOutgoingAdvertisements",
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 */
if (filter->usmap.name)
json_object_string_add(json_addr,
Expand Down Expand Up @@ -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].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 */
if (filter->usmap.name)
vty_out(vty,
Expand Down Expand Up @@ -12823,6 +12872,10 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &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 */
install_element(BGP_NODE, &bgp_deterministic_med_cmd);
install_element(BGP_NODE, &no_bgp_deterministic_med_cmd);
Expand Down
6 changes: 6 additions & 0 deletions bgpd/bgpd.c
Expand Up @@ -2936,6 +2936,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
bgp->dynamic_neighbors_count = 0;
bgp->ebgp_requires_policy = DEFAULT_EBGP_POLICY_DISABLED;
#if DFLT_BGP_IMPORT_CHECK
bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK);
#endif
Expand Down Expand Up @@ -7577,6 +7578,11 @@ int bgp_config_write(struct vty *vty)
if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
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. */
if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4))
vty_out(vty, " no bgp default ipv4-unicast\n");
Expand Down
5 changes: 5 additions & 0 deletions bgpd/bgpd.h
Expand Up @@ -487,6 +487,11 @@ struct bgp {
/* EVPN enable - advertise local VNIs and their MACs etc. */
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;

/* EVPN - use RFC 8365 to auto-derive RT */
Expand Down