]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_routemap.c
Revert "bgpd: Free only subattributes, not the whole attr_extra pointer"
[mirror_frr.git] / bgpd / bgp_routemap.c
index d7c56dd83a76c48de68cf62703985285629d198f..89774875b67c4b7698075b1b81942e5e785e6c6e 100644 (file)
@@ -725,6 +725,57 @@ static const struct route_map_rule_cmd
        route_match_ip_next_hop_prefix_list_free
 };
 
+/* `match ipv6 next-hop prefix-list PREFIXLIST_NAME' */
+static enum route_map_cmd_result_t
+route_match_ipv6_next_hop_prefix_list(void *rule, const struct prefix *prefix,
+                                     void *object)
+{
+       struct prefix_list *plist;
+       struct bgp_path_info *path;
+       struct prefix_ipv6 p;
+
+       if (prefix->family == AF_INET6) {
+               path = object;
+               p.family = AF_INET6;
+               p.prefix = path->attr->mp_nexthop_global;
+               p.prefixlen = IPV6_MAX_BITLEN;
+
+               plist = prefix_list_lookup(AFI_IP6, (char *)rule);
+               if (!plist)
+                       return RMAP_NOMATCH;
+
+               if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
+                       return RMAP_MATCH;
+
+               if (path->attr->mp_nexthop_len
+                   == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+                       p.prefix = path->attr->mp_nexthop_local;
+                       if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
+                               return RMAP_MATCH;
+               }
+       }
+
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_prefix_list_compile(const char *arg)
+{
+       return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ipv6_next_hop_prefix_list_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd
+               route_match_ipv6_next_hop_prefix_list_cmd = {
+       "ipv6 next-hop prefix-list",
+       route_match_ipv6_next_hop_prefix_list,
+       route_match_ipv6_next_hop_prefix_list_compile,
+       route_match_ipv6_next_hop_prefix_list_free
+};
+
 /* `match ip next-hop type <blackhole>' */
 
 static enum route_map_cmd_result_t
@@ -1148,7 +1199,7 @@ route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
        if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
                return RMAP_NOMATCH;
 
-       if (path->extra == NULL)
+       if (path->extra == NULL || path->extra->bgp_orig == NULL)
                return RMAP_NOMATCH;
 
        if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id),
@@ -1538,7 +1589,7 @@ route_match_ecommunity(void *rule, const struct prefix *prefix, void *object)
        if (!list)
                return RMAP_NOMATCH;
 
-       if (ecommunity_list_match(path->attr->ecommunity, list))
+       if (ecommunity_list_match(bgp_attr_get_ecommunity(path->attr), list))
                return RMAP_MATCH;
 
        return RMAP_NOMATCH;
@@ -2539,7 +2590,7 @@ route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
 
        if (rcs->none) {
                attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
-               attr->ecommunity = NULL;
+               bgp_attr_set_ecommunity(attr, NULL);
                return RMAP_OKAY;
        }
 
@@ -2547,7 +2598,7 @@ route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
                return RMAP_OKAY;
 
        /* We assume additive for Extended Community. */
-       old_ecom = path->attr->ecommunity;
+       old_ecom = bgp_attr_get_ecommunity(path->attr);
 
        if (old_ecom) {
                new_ecom =
@@ -2563,7 +2614,7 @@ route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
                new_ecom = ecommunity_dup(rcs->ecom);
 
        /* will be intern()'d or attr_flush()'d by bgp_update_main() */
-       path->attr->ecommunity = new_ecom;
+       bgp_attr_set_ecommunity(path->attr, new_ecom);
 
        path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
 
@@ -2713,7 +2764,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
                                     PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
 
        /* add to route or merge with existing */
-       old_ecom = path->attr->ecommunity;
+       old_ecom = bgp_attr_get_ecommunity(path->attr);
        if (old_ecom) {
                new_ecom = ecommunity_dup(old_ecom);
                ecommunity_add_val(new_ecom, &lb_eval, true, true);
@@ -2727,7 +2778,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
        }
 
        /* new_ecom will be intern()'d or attr_flush()'d in call stack */
-       path->attr->ecommunity = new_ecom;
+       bgp_attr_set_ecommunity(path->attr, new_ecom);
        path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
 
        /* Mark that route-map has set link bandwidth; used in attribute
@@ -3023,10 +3074,60 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
        route_match_ipv6_address_free
 };
 
+/* `match ipv6 next-hop ACCESSLIST6_NAME' */
+static enum route_map_cmd_result_t
+route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
+{
+       struct bgp_path_info *path;
+       struct access_list *alist;
+       struct prefix_ipv6 p;
+
+       if (prefix->family == AF_INET6) {
+               path = object;
+               p.family = AF_INET6;
+               p.prefix = path->attr->mp_nexthop_global;
+               p.prefixlen = IPV6_MAX_BITLEN;
+
+               alist = access_list_lookup(AFI_IP6, (char *)rule);
+               if (!alist)
+                       return RMAP_NOMATCH;
+
+               if (access_list_apply(alist, &p) == FILTER_PERMIT)
+                       return RMAP_MATCH;
+
+               if (path->attr->mp_nexthop_len
+                   == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+                       p.prefix = path->attr->mp_nexthop_local;
+                       if (access_list_apply(alist, &p) == FILTER_PERMIT)
+                               return RMAP_MATCH;
+               }
+       }
+
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_compile(const char *arg)
+{
+       return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ipv6_next_hop_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
+       "ipv6 next-hop",
+       route_match_ipv6_next_hop,
+       route_match_ipv6_next_hop_compile,
+       route_match_ipv6_next_hop_free
+};
+
 /* `match ipv6 next-hop IP_ADDRESS' */
 
 static enum route_map_cmd_result_t
-route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
+route_match_ipv6_next_hop_address(void *rule, const struct prefix *prefix,
+                                 void *object)
 {
        struct in6_addr *addr = rule;
        struct bgp_path_info *path;
@@ -3043,7 +3144,7 @@ route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
        return RMAP_NOMATCH;
 }
 
-static void *route_match_ipv6_next_hop_compile(const char *arg)
+static void *route_match_ipv6_next_hop_address_compile(const char *arg)
 {
        struct in6_addr *address;
        int ret;
@@ -3059,16 +3160,16 @@ static void *route_match_ipv6_next_hop_compile(const char *arg)
        return address;
 }
 
-static void route_match_ipv6_next_hop_free(void *rule)
+static void route_match_ipv6_next_hop_address_free(void *rule)
 {
        XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
 }
 
-static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
-       "ipv6 next-hop",
-       route_match_ipv6_next_hop,
-       route_match_ipv6_next_hop_compile,
-       route_match_ipv6_next_hop_free
+static const struct route_map_rule_cmd route_match_ipv6_next_hop_address_cmd = {
+       "ipv6 next-hop address",
+       route_match_ipv6_next_hop_address,
+       route_match_ipv6_next_hop_address_compile,
+       route_match_ipv6_next_hop_address_free
 };
 
 /* `match ip next-hop IP_ADDRESS' */
@@ -4004,7 +4105,7 @@ static void bgp_route_map_event(const char *rmap_name)
 
 DEFUN_YANG (match_mac_address,
            match_mac_address_cmd,
-           "match mac address WORD",
+           "match mac address ACCESSLIST_MAC_NAME",
            MATCH_STR
            "mac address\n"
            "Match address of route\n"
@@ -4024,7 +4125,7 @@ DEFUN_YANG (match_mac_address,
 
 DEFUN_YANG (no_match_mac_address,
            no_match_mac_address_cmd,
-           "no match mac address WORD",
+           "no match mac address ACCESSLIST_MAC_NAME",
            NO_STR
            MATCH_STR
            "mac\n"
@@ -4576,7 +4677,7 @@ DEFUN_YANG (no_match_probability,
 
 DEFPY_YANG (match_ip_route_source,
        match_ip_route_source_cmd,
-       "match ip route-source WORD",
+       "match ip route-source ACCESSLIST4_NAME",
        MATCH_STR
        IP_STR
        "Match advertising source address of route\n"
@@ -4600,7 +4701,7 @@ DEFPY_YANG (match_ip_route_source,
 
 DEFUN_YANG (no_match_ip_route_source,
            no_match_ip_route_source_cmd,
-           "no match ip route-source [WORD]",
+           "no match ip route-source [ACCESSLIST4_NAME]",
            NO_STR
            MATCH_STR
            IP_STR
@@ -4616,7 +4717,7 @@ DEFUN_YANG (no_match_ip_route_source,
 
 DEFUN_YANG (match_ip_route_source_prefix_list,
            match_ip_route_source_prefix_list_cmd,
-           "match ip route-source prefix-list WORD",
+           "match ip route-source prefix-list PREFIXLIST_NAME",
            MATCH_STR
            IP_STR
            "Match advertising source address of route\n"
@@ -4640,7 +4741,7 @@ DEFUN_YANG (match_ip_route_source_prefix_list,
 
 DEFUN_YANG (no_match_ip_route_source_prefix_list,
            no_match_ip_route_source_prefix_list_cmd,
-           "no match ip route-source prefix-list [WORD]",
+           "no match ip route-source prefix-list [PREFIXLIST_NAME]",
            NO_STR
            MATCH_STR
            IP_STR
@@ -6047,10 +6148,48 @@ DEFUN_YANG (no_set_aggregator_as,
 
 DEFUN_YANG (match_ipv6_next_hop,
            match_ipv6_next_hop_cmd,
-           "match ipv6 next-hop X:X::X:X",
+           "match ipv6 next-hop ACCESSLIST6_NAME",
+           MATCH_STR
+           IPV6_STR
+           "Match IPv6 next-hop address of route\n"
+           "IPv6 access-list name\n")
+{
+       const char *xpath =
+               "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
+       char xpath_value[XPATH_MAXLEN];
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+       snprintf(xpath_value, sizeof(xpath_value),
+                "%s/rmap-match-condition/list-name", xpath);
+       nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+                             argv[argc - 1]->arg);
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (no_match_ipv6_next_hop,
+           no_match_ipv6_next_hop_cmd,
+           "no match ipv6 next-hop [ACCESSLIST6_NAME]",
+           NO_STR
+           MATCH_STR
+           IPV6_STR
+           "Match IPv6 next-hop address of route\n"
+           "IPv6 access-list name\n")
+{
+       const char *xpath =
+               "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (match_ipv6_next_hop_address,
+           match_ipv6_next_hop_address_cmd,
+           "match ipv6 next-hop address X:X::X:X",
            MATCH_STR
            IPV6_STR
            "Match IPv6 next-hop address of route\n"
+           "IPv6 address\n"
            "IPv6 address of next hop\n")
 {
        const char *xpath =
@@ -6061,18 +6200,20 @@ DEFUN_YANG (match_ipv6_next_hop,
        snprintf(xpath_value, sizeof(xpath_value),
                 "%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
                 xpath);
-       nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
+       nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+                             argv[argc - 1]->arg);
 
        return nb_cli_apply_changes(vty, NULL);
 }
 
-DEFUN_YANG (no_match_ipv6_next_hop,
-           no_match_ipv6_next_hop_cmd,
-           "no match ipv6 next-hop X:X::X:X",
+DEFUN_YANG (no_match_ipv6_next_hop_address,
+           no_match_ipv6_next_hop_address_cmd,
+           "no match ipv6 next-hop address X:X::X:X",
            NO_STR
            MATCH_STR
            IPV6_STR
            "Match IPv6 next-hop address of route\n"
+           "IPv6 address\n"
            "IPv6 address of next hop\n")
 {
        const char *xpath =
@@ -6082,6 +6223,62 @@ DEFUN_YANG (no_match_ipv6_next_hop,
        return nb_cli_apply_changes(vty, NULL);
 }
 
+ALIAS_HIDDEN (match_ipv6_next_hop_address,
+             match_ipv6_next_hop_old_cmd,
+             "match ipv6 next-hop X:X::X:X",
+             MATCH_STR
+             IPV6_STR
+             "Match IPv6 next-hop address of route\n"
+             "IPv6 address of next hop\n")
+
+ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
+             no_match_ipv6_next_hop_old_cmd,
+             "no match ipv6 next-hop X:X::X:X",
+             NO_STR
+             MATCH_STR
+             IPV6_STR
+             "Match IPv6 next-hop address of route\n"
+             "IPv6 address of next hop\n")
+
+DEFUN_YANG (match_ipv6_next_hop_prefix_list,
+           match_ipv6_next_hop_prefix_list_cmd,
+           "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
+           MATCH_STR
+           IPV6_STR
+           "Match IPv6 next-hop address of route\n"
+           "Match entries by prefix-list\n"
+           "IPv6 prefix-list name\n")
+{
+       const char *xpath =
+               "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
+       char xpath_value[XPATH_MAXLEN];
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+       snprintf(xpath_value, sizeof(xpath_value),
+                "%s/rmap-match-condition/list-name", xpath);
+       nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+                             argv[argc - 1]->arg);
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
+           no_match_ipv6_next_hop_prefix_list_cmd,
+           "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
+           NO_STR
+           MATCH_STR
+           IPV6_STR
+           "Match IPv6 next-hop address of route\n"
+           "Match entries by prefix-list\n"
+           "IPv6 prefix-list name\n")
+{
+       const char *xpath =
+               "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+       return nb_cli_apply_changes(vty, NULL);
+}
+
 DEFPY_YANG (match_ipv4_next_hop,
        match_ipv4_next_hop_cmd,
        "match ip next-hop address A.B.C.D",
@@ -6441,6 +6638,9 @@ void bgp_route_map_init(void)
        route_map_match_ip_next_hop_hook(generic_match_add);
        route_map_no_match_ip_next_hop_hook(generic_match_delete);
 
+       route_map_match_ipv6_next_hop_hook(generic_match_add);
+       route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
+
        route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
        route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
 
@@ -6456,6 +6656,9 @@ void bgp_route_map_init(void)
        route_map_match_ipv6_next_hop_type_hook(generic_match_add);
        route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
 
+       route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
+       route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
+
        route_map_match_metric_hook(generic_match_add);
        route_map_no_match_metric_hook(generic_match_delete);
 
@@ -6638,6 +6841,8 @@ void bgp_route_map_init(void)
 
        route_map_install_match(&route_match_ipv6_address_cmd);
        route_map_install_match(&route_match_ipv6_next_hop_cmd);
+       route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
+       route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
        route_map_install_match(&route_match_ipv4_next_hop_cmd);
        route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
        route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
@@ -6647,7 +6852,13 @@ void bgp_route_map_init(void)
        route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
 
        install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
+       install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
+       install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
        install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
+       install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
+       install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
+       install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
+       install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
        install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
        install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
        install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);