}
}
+ /* 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));
}
}
+ /* 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) {
}
}
+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)
{
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,
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,
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,
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,
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);
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
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");
/* 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 */