]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_route.c
bgpd: fix memory leak in aggregate path info
[mirror_frr.git] / bgpd / bgp_route.c
index 65f7ce16438ef00f278167af198d9ae1381c7368..2624ae013fec181c47793e1f9171370765831af7 100644 (file)
@@ -3087,10 +3087,13 @@ static bool bgp_lu_need_null_label(struct bgp *bgp,
 need_null_label:
        if (label == NULL)
                return true;
-       if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL))
-               /* Disable PHP : explicit-null */
-               *label = afi == AFI_IP ? MPLS_LABEL_IPV4_EXPLICIT_NULL
-                                      : MPLS_LABEL_IPV6_EXPLICIT_NULL;
+       /* Disable PHP : explicit-null */
+       if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV4_EXPLICIT_NULL) &&
+           afi == AFI_IP)
+               *label = MPLS_LABEL_IPV4_EXPLICIT_NULL;
+       else if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV6_EXPLICIT_NULL) &&
+                afi == AFI_IP6)
+               *label = MPLS_LABEL_IPV6_EXPLICIT_NULL;
        else
                /* Enforced PHP popping: implicit-null */
                *label = MPLS_LABEL_IMPLICIT_NULL;
@@ -4065,17 +4068,24 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
        if (has_valid_label)
                assert(label != NULL);
 
-       /* Update overlay index of the attribute */
-       if (afi == AFI_L2VPN && evpn)
-               memcpy(&attr->evpn_overlay, evpn,
-                      sizeof(struct bgp_route_evpn));
 
        /* When peer's soft reconfiguration enabled.  Record input packet in
           Adj-RIBs-In.  */
-       if (!soft_reconfig
-           && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
-           && peer != bgp->peer_self)
+       if (!soft_reconfig &&
+           CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) &&
+           peer != bgp->peer_self) {
+               /*
+                * If the trigger is not from soft_reconfig and if
+                * PEER_FLAG_SOFT_RECONFIG is enabled for the peer, then attr
+                * will not be interned. In which case, it is ok to update the
+                * attr->evpn_overlay, so that, this can be stored in adj_in.
+                */
+               if ((afi == AFI_L2VPN) && evpn) {
+                       memcpy(&attr->evpn_overlay, evpn,
+                              sizeof(struct bgp_route_evpn));
+               }
                bgp_adj_in_set(dest, peer, attr, addpath_id);
+       }
 
        /* Update permitted loop count */
        if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
@@ -4166,6 +4176,21 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
                goto filtered;
        }
 
+       /* If the route has Node Target Extended Communities, check
+        * if it's allowed to be installed locally.
+        */
+       if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
+               struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
+
+               if (ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
+                                     ECOMMUNITY_NODE_TARGET) &&
+                   !ecommunity_node_target_match(ecomm, &peer->local_id)) {
+                       reason =
+                               "Node-Target Extended Communities do not contain own BGP Identifier;";
+                       goto filtered;
+               }
+       }
+
        /* 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
@@ -4203,6 +4228,15 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
                }
 
        new_attr = *attr;
+       /*
+        * If bgp_update is called with soft_reconfig set then
+        * attr is interned. In this case, do not overwrite the
+        * attr->evpn_overlay with evpn directly. Instead memcpy
+        * evpn to new_atr.evpn_overlay before it is interned.
+        */
+       if (soft_reconfig && (afi == AFI_L2VPN) && evpn)
+               memcpy(&new_attr.evpn_overlay, evpn,
+                      sizeof(struct bgp_route_evpn));
 
        /* Apply incoming route-map.
         * NB: new_attr may now contain newly allocated values from route-map
@@ -7022,8 +7056,8 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
                bgp_static->label = label;
                bgp_static->prd = prd;
 
-               if (rd_str)
-                       bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
+               bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
+
                if (rmap_str) {
                        XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
                        route_map_counter_decrement(bgp_static->rmap.map);
@@ -7384,7 +7418,7 @@ static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
 
        asnotation = bgp_get_asnotation(NULL);
 
-       if (!ae)
+       if (!aspath)
                ae = aspath_empty(asnotation);
 
        if (!pi)
@@ -7443,8 +7477,8 @@ static void bgp_aggregate_install(
                 * If the aggregate information has not changed
                 * no need to re-install it again.
                 */
-               if (bgp_aggregate_info_same(orig, origin, aspath, community,
-                                           ecommunity, lcommunity)) {
+               if (pi && bgp_aggregate_info_same(pi, origin, aspath, community,
+                                                 ecommunity, lcommunity)) {
                        bgp_dest_unlock_node(dest);
 
                        if (aspath)
@@ -8642,12 +8676,16 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
         */
        assert(attr.aspath);
 
+       if (p->family == AF_INET6)
+               UNSET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
+
        switch (nhtype) {
        case NEXTHOP_TYPE_IFINDEX:
                switch (p->family) {
                case AF_INET:
                        attr.nexthop.s_addr = INADDR_ANY;
                        attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
+                       attr.mp_nexthop_global_in.s_addr = INADDR_ANY;
                        break;
                case AF_INET6:
                        memset(&attr.mp_nexthop_global, 0,
@@ -8660,6 +8698,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
        case NEXTHOP_TYPE_IPV4_IFINDEX:
                attr.nexthop = nexthop->ipv4;
                attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
+               attr.mp_nexthop_global_in = nexthop->ipv4;
                break;
        case NEXTHOP_TYPE_IPV6:
        case NEXTHOP_TYPE_IPV6_IFINDEX:
@@ -8671,6 +8710,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
                case AF_INET:
                        attr.nexthop.s_addr = INADDR_ANY;
                        attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
+                       attr.mp_nexthop_global_in.s_addr = INADDR_ANY;
                        break;
                case AF_INET6:
                        memset(&attr.mp_nexthop_global, 0,
@@ -14246,7 +14286,6 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
                        for (ain = dest->adj_in; ain; ain = ain->next) {
                                if (ain->peer != peer)
                                        continue;
-
                                show_adj_route_header(vty, peer, table, header1,
                                                      header2, json, json_scode,
                                                      json_ocode, wide, detail);
@@ -14297,9 +14336,23 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
                                        if (use_json)
                                                json_net =
                                                        json_object_new_object();
+
+                                       struct bgp_path_info bpi;
+                                       struct bgp_dest buildit = *dest;
+                                       struct bgp_dest *pass_in;
+
+                                       if (route_filtered ||
+                                           ret == RMAP_DENY) {
+                                               bpi.attr = &attr;
+                                               bpi.peer = peer;
+                                               buildit.info = &bpi;
+
+                                               pass_in = &buildit;
+                                       } else
+                                               pass_in = dest;
                                        bgp_show_path_info(
-                                               NULL /* prefix_rd */, dest, vty,
-                                               bgp, afi, safi, json_net,
+                                               NULL, pass_in, vty, bgp, afi,
+                                               safi, json_net,
                                                BGP_PATH_SHOW_ALL, &display,
                                                RPKI_NOT_BEING_USED);
                                        if (use_json)
@@ -14894,35 +14947,42 @@ static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
                        RPKI_NOT_BEING_USED);
 }
 
-DEFUN (show_ip_bgp_flowspec_routes_detailed,
-       show_ip_bgp_flowspec_routes_detailed_cmd,
-       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
-       SHOW_STR
-       IP_STR
-       BGP_STR
-       BGP_INSTANCE_HELP_STR
-       BGP_AFI_HELP_STR
-       "SAFI Flowspec\n"
-       "Detailed information on flowspec entries\n"
-       JSON_STR)
+/*
+ * Used for "detailed" output for cmds like show bgp <afi> <safi> (or)
+ * show bgp <vrf> (or) show bgp <vrf> <afi> <safi>
+ */
+DEFPY(show_ip_bgp_vrf_afi_safi_routes_detailed,
+      show_ip_bgp_vrf_afi_safi_routes_detailed_cmd,
+      "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf_name] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] detail [json$uj]",
+      SHOW_STR
+      IP_STR
+      BGP_STR
+      BGP_INSTANCE_HELP_STR
+      BGP_AFI_HELP_STR
+      BGP_SAFI_WITH_LABEL_HELP_STR
+      "Detailed information\n"
+      JSON_STR)
 {
        afi_t afi = AFI_IP6;
        safi_t safi = SAFI_UNICAST;
        struct bgp *bgp = NULL;
        int idx = 0;
-       bool uj = use_json(argc, argv);
        uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
 
-       if (uj) {
-               argc--;
+       if (uj)
                SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
-       }
 
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
                                            &bgp, uj);
        if (!idx)
                return CMD_WARNING;
+       /* 'vrf all' case to iterate all vrfs & show output per vrf instance */
+       if (vrf_name && strmatch(vrf_name, "all")) {
+               bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
+               return CMD_SUCCESS;
+       }
 
+       /* All other cases except vrf all */
        return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
                        show_flags, RPKI_NOT_BEING_USED);
 }
@@ -16038,8 +16098,9 @@ void bgp_route_init(void)
        install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
        install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
 
-       /* show bgp ipv4 flowspec detailed */
-       install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
+       /* show bgp vrf <afi> <safi> detailed */
+       install_element(VIEW_NODE,
+                       &show_ip_bgp_vrf_afi_safi_routes_detailed_cmd);
 
        install_element(VIEW_NODE, &show_bgp_listeners_cmd);
        install_element(VIEW_NODE, &show_bgp_peerhash_cmd);