]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Implement RFC8212
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Thu, 7 Feb 2019 08:49:04 +0000 (10:49 +0200)
committerDonatas Abraitis <donatas.abraitis@gmail.com>
Sun, 17 Feb 2019 21:17:00 +0000 (23:17 +0200)
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index 59ca223a2d8f3a997a3a60e77b43bd7838866fee..d02d74736115a3eeffadbc20bb87078b5e53ca1d 100644 (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. */
        if (rmap) {
                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 (peer->sort == BGP_PEER_IBGP
                    || 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,
                              safi_t safi)
 {
index 97d4aaeeba3ced0fda7d9b2c7d6ff33154fabe7a..85325a93cf638c474feeb3550a7aa006be512e79 100644 (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_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,
index a6d985ab9f5e051c55780683d4cc408f75d5c89c..c3bd6f83b7cc8f1c3a41eadc5aab54794df84c32 100644 (file)
@@ -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,
@@ -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,
@@ -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,
@@ -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);
index aceb990534c1de4f50c15b240a47b1066d73f364..8032bf59afd18822454219839ca3d8d5260a9ab9 100644 (file)
@@ -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
@@ -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");
index e58c46e2401a9d63103f896926f6febd34930e3d..dde1501d3062770fff51ec892f87a71da97d2875 100644 (file)
@@ -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 */