back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_routemap.c (source / functions) Hit Total Coverage
Test: test_bgp_set_aspath_replace.py::BGPSetAspathReplace Lines: 365 2742 13.3 %
Date: 2023-02-24 18:37:49 Functions: 18 293 6.1 %

          Line data    Source code
       1             : /* Route map function of bgpd.
       2             :  * Copyright (C) 1998, 1999 Kunihiro Ishiguro
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "prefix.h"
      24             : #include "filter.h"
      25             : #include "routemap.h"
      26             : #include "command.h"
      27             : #include "linklist.h"
      28             : #include "plist.h"
      29             : #include "memory.h"
      30             : #include "log.h"
      31             : #include "frrlua.h"
      32             : #include "frrscript.h"
      33             : #ifdef HAVE_LIBPCRE2_POSIX
      34             : #ifndef _FRR_PCRE2_POSIX
      35             : #define _FRR_PCRE2_POSIX
      36             : #include <pcre2posix.h>
      37             : #endif /* _FRR_PCRE2_POSIX */
      38             : #elif defined(HAVE_LIBPCREPOSIX)
      39             : #include <pcreposix.h>
      40             : #else
      41             : #include <regex.h>
      42             : #endif /* HAVE_LIBPCRE2_POSIX */
      43             : #include "buffer.h"
      44             : #include "sockunion.h"
      45             : #include "hash.h"
      46             : #include "queue.h"
      47             : #include "frrstr.h"
      48             : #include "network.h"
      49             : #include "lib/northbound_cli.h"
      50             : 
      51             : #include "bgpd/bgpd.h"
      52             : #include "bgpd/bgp_table.h"
      53             : #include "bgpd/bgp_attr.h"
      54             : #include "bgpd/bgp_aspath.h"
      55             : #include "bgpd/bgp_packet.h"
      56             : #include "bgpd/bgp_route.h"
      57             : #include "bgpd/bgp_zebra.h"
      58             : #include "bgpd/bgp_regex.h"
      59             : #include "bgpd/bgp_community.h"
      60             : #include "bgpd/bgp_community_alias.h"
      61             : #include "bgpd/bgp_clist.h"
      62             : #include "bgpd/bgp_filter.h"
      63             : #include "bgpd/bgp_mplsvpn.h"
      64             : #include "bgpd/bgp_ecommunity.h"
      65             : #include "bgpd/bgp_lcommunity.h"
      66             : #include "bgpd/bgp_vty.h"
      67             : #include "bgpd/bgp_debug.h"
      68             : #include "bgpd/bgp_evpn.h"
      69             : #include "bgpd/bgp_evpn_private.h"
      70             : #include "bgpd/bgp_evpn_vty.h"
      71             : #include "bgpd/bgp_mplsvpn.h"
      72             : #include "bgpd/bgp_pbr.h"
      73             : #include "bgpd/bgp_flowspec_util.h"
      74             : #include "bgpd/bgp_encap_types.h"
      75             : #include "bgpd/bgp_mpath.h"
      76             : #include "bgpd/bgp_script.h"
      77             : 
      78             : #ifdef ENABLE_BGP_VNC
      79             : #include "bgpd/rfapi/bgp_rfapi_cfg.h"
      80             : #endif
      81             : 
      82             : #include "bgpd/bgp_routemap_clippy.c"
      83             : 
      84             : /* Memo of route-map commands.
      85             : 
      86             : o Cisco route-map
      87             : 
      88             :  match as-path          :  Done
      89             :        community        :  Done
      90             :        interface        :  Done
      91             :        ip address       :  Done
      92             :        ip next-hop      :  Done
      93             :        ip route-source  :  Done
      94             :        ip prefix-list   :  Done
      95             :        ipv6 address     :  Done
      96             :        ipv6 next-hop    :  Done
      97             :        ipv6 route-source:  (This will not be implemented by bgpd)
      98             :        ipv6 prefix-list :  Done
      99             :        length           :  (This will not be implemented by bgpd)
     100             :        metric           :  Done
     101             :        route-type       :  (This will not be implemented by bgpd)
     102             :        tag              :  Done
     103             :        local-preference :  Done
     104             : 
     105             :  set  as-path prepend   :  Done
     106             :       as-path tag       :  Not yet
     107             :       automatic-tag     :  (This will not be implemented by bgpd)
     108             :       community         :  Done
     109             :       large-community   :  Done
     110             :       large-comm-list   :  Done
     111             :       comm-list         :  Not yet
     112             :       dampning          :  Not yet
     113             :       default           :  (This will not be implemented by bgpd)
     114             :       interface         :  (This will not be implemented by bgpd)
     115             :       ip default        :  (This will not be implemented by bgpd)
     116             :       ip next-hop       :  Done
     117             :       ip precedence     :  (This will not be implemented by bgpd)
     118             :       ip tos            :  (This will not be implemented by bgpd)
     119             :       level             :  (This will not be implemented by bgpd)
     120             :       local-preference  :  Done
     121             :       metric            :  Done
     122             :       metric-type       :  Not yet
     123             :       origin            :  Done
     124             :       tag               :  Done
     125             :       weight            :  Done
     126             :       table             :  Done
     127             : 
     128             : o Local extensions
     129             : 
     130             :   set ipv6 next-hop global: Done
     131             :   set ipv6 next-hop prefer-global: Done
     132             :   set ipv6 next-hop local : Done
     133             :   set as-path exclude     : Done
     134             : 
     135             : */
     136             : 
     137             : /* generic value manipulation to be shared in multiple rules */
     138             : 
     139             : #define RMAP_VALUE_SET 0
     140             : #define RMAP_VALUE_ADD 1
     141             : #define RMAP_VALUE_SUB 2
     142             : 
     143             : struct rmap_value {
     144             :         uint8_t action;
     145             :         uint8_t variable;
     146             :         uint32_t value;
     147             : };
     148             : 
     149           0 : static int route_value_match(struct rmap_value *rv, uint32_t value)
     150             : {
     151           0 :         if (rv->variable == 0 && value == rv->value)
     152             :                 return RMAP_MATCH;
     153             : 
     154             :         return RMAP_NOMATCH;
     155             : }
     156             : 
     157           0 : static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
     158             :                                    struct peer *peer)
     159             : {
     160           0 :         uint32_t value;
     161             : 
     162           0 :         switch (rv->variable) {
     163           0 :         case 1:
     164           0 :                 value = peer->rtt;
     165           0 :                 break;
     166           0 :         default:
     167           0 :                 value = rv->value;
     168           0 :                 break;
     169             :         }
     170             : 
     171           0 :         switch (rv->action) {
     172           0 :         case RMAP_VALUE_ADD:
     173           0 :                 if (current > UINT32_MAX - value)
     174             :                         return UINT32_MAX;
     175           0 :                 return current + value;
     176           0 :         case RMAP_VALUE_SUB:
     177           0 :                 if (current <= value)
     178             :                         return 0;
     179           0 :                 return current - value;
     180             :         default:
     181             :                 return value;
     182             :         }
     183             : }
     184             : 
     185           0 : static void *route_value_compile(const char *arg)
     186             : {
     187           0 :         uint8_t action = RMAP_VALUE_SET, var = 0;
     188           0 :         unsigned long larg = 0;
     189           0 :         char *endptr = NULL;
     190           0 :         struct rmap_value *rv;
     191             : 
     192           0 :         if (arg[0] == '+') {
     193           0 :                 action = RMAP_VALUE_ADD;
     194           0 :                 arg++;
     195           0 :         } else if (arg[0] == '-') {
     196           0 :                 action = RMAP_VALUE_SUB;
     197           0 :                 arg++;
     198             :         }
     199             : 
     200           0 :         if (all_digit(arg)) {
     201           0 :                 errno = 0;
     202           0 :                 larg = strtoul(arg, &endptr, 10);
     203           0 :                 if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
     204             :                         return NULL;
     205             :         } else {
     206           0 :                 if (strcmp(arg, "rtt") == 0)
     207             :                         var = 1;
     208             :                 else
     209             :                         return NULL;
     210             :         }
     211             : 
     212           0 :         rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
     213             : 
     214           0 :         rv->action = action;
     215           0 :         rv->variable = var;
     216           0 :         rv->value = larg;
     217           0 :         return rv;
     218             : }
     219             : 
     220           0 : static void route_value_free(void *rule)
     221             : {
     222           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     223           0 : }
     224             : 
     225             : /* generic as path object to be shared in multiple rules */
     226             : 
     227           0 : static void *route_aspath_compile(const char *arg)
     228             : {
     229           0 :         struct aspath *aspath;
     230             : 
     231           0 :         aspath = aspath_str2aspath(arg);
     232           0 :         if (!aspath)
     233             :                 return NULL;
     234             :         return aspath;
     235             : }
     236             : 
     237           0 : static void route_aspath_free(void *rule)
     238             : {
     239           0 :         struct aspath *aspath = rule;
     240           0 :         aspath_free(aspath);
     241           0 : }
     242             : 
     243             : struct bgp_match_peer_compiled {
     244             :         char *interface;
     245             :         union sockunion su;
     246             : };
     247             : 
     248             : /* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
     249             : 
     250             : /* Compares the peer specified in the 'match peer' clause with the peer
     251             :     received in bgp_path_info->peer. If it is the same, or if the peer structure
     252             :     received is a peer_group containing it, returns RMAP_MATCH. */
     253             : static enum route_map_cmd_result_t
     254           0 : route_match_peer(void *rule, const struct prefix *prefix, void *object)
     255             : {
     256           0 :         struct bgp_match_peer_compiled *pc;
     257           0 :         union sockunion *su;
     258           0 :         union sockunion su_def = {
     259             :                 .sin = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY}};
     260           0 :         struct peer_group *group;
     261           0 :         struct peer *peer;
     262           0 :         struct listnode *node, *nnode;
     263             : 
     264           0 :         pc = rule;
     265           0 :         su = &pc->su;
     266           0 :         peer = ((struct bgp_path_info *)object)->peer;
     267             : 
     268           0 :         if (pc->interface) {
     269           0 :                 if (!peer->conf_if || !peer->group)
     270             :                         return RMAP_NOMATCH;
     271             : 
     272           0 :                 if (peer->conf_if && strcmp(peer->conf_if, pc->interface) == 0)
     273             :                         return RMAP_MATCH;
     274             : 
     275           0 :                 if (peer->group &&
     276           0 :                     strcmp(peer->group->name, pc->interface) == 0)
     277             :                         return RMAP_MATCH;
     278             : 
     279             :                 return RMAP_NOMATCH;
     280             :         }
     281             : 
     282             :         /* If su='0.0.0.0' (command 'match peer local'), and it's a
     283             :            NETWORK,
     284             :            REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
     285             :            => return RMAP_MATCH
     286             :         */
     287           0 :         if (sockunion_same(su, &su_def)) {
     288           0 :                 int ret;
     289           0 :                 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
     290             :                     || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE)
     291             :                     || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_AGGREGATE)
     292             :                     || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_DEFAULT))
     293             :                         ret = RMAP_MATCH;
     294             :                 else
     295           0 :                         ret = RMAP_NOMATCH;
     296           0 :                 return ret;
     297             :         }
     298             : 
     299           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
     300           0 :                 if (sockunion_same(su, &peer->su))
     301             :                         return RMAP_MATCH;
     302             : 
     303             :                 return RMAP_NOMATCH;
     304             :         } else {
     305           0 :                 group = peer->group;
     306           0 :                 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
     307           0 :                         if (sockunion_same(su, &peer->su))
     308             :                                 return RMAP_MATCH;
     309             :                 }
     310             :                 return RMAP_NOMATCH;
     311             :         }
     312             : 
     313             :         return RMAP_NOMATCH;
     314             : }
     315             : 
     316           0 : static void *route_match_peer_compile(const char *arg)
     317             : {
     318           0 :         struct bgp_match_peer_compiled *pc;
     319           0 :         int ret;
     320             : 
     321           0 :         pc = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
     322             :                      sizeof(struct bgp_match_peer_compiled));
     323             : 
     324           0 :         ret = str2sockunion(strcmp(arg, "local") ? arg : "0.0.0.0", &pc->su);
     325           0 :         if (ret < 0) {
     326           0 :                 pc->interface = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     327           0 :                 return pc;
     328             :         }
     329             : 
     330             :         return pc;
     331             : }
     332             : 
     333             : /* Free route map's compiled `ip address' value. */
     334           0 : static void route_match_peer_free(void *rule)
     335             : {
     336           0 :         struct bgp_match_peer_compiled *pc = rule;
     337             : 
     338           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
     339             : 
     340           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     341           0 : }
     342             : 
     343             : /* Route map commands for ip address matching. */
     344             : static const struct route_map_rule_cmd route_match_peer_cmd = {
     345             :         "peer",
     346             :         route_match_peer,
     347             :         route_match_peer_compile,
     348             :         route_match_peer_free
     349             : };
     350             : 
     351             : #ifdef HAVE_SCRIPTING
     352             : 
     353             : enum frrlua_rm_status {
     354             :         /*
     355             :          * Script function run failure.  This will translate into a deny
     356             :          */
     357             :         LUA_RM_FAILURE = 0,
     358             :         /*
     359             :          * No Match was found for the route map function
     360             :          */
     361             :         LUA_RM_NOMATCH,
     362             :         /*
     363             :          * Match was found but no changes were made to the incoming data.
     364             :          */
     365             :         LUA_RM_MATCH,
     366             :         /*
     367             :          * Match was found and data was modified, so figure out what changed
     368             :          */
     369             :         LUA_RM_MATCH_AND_CHANGE,
     370             : };
     371             : 
     372             : static enum route_map_cmd_result_t
     373             : route_match_script(void *rule, const struct prefix *prefix, void *object)
     374             : {
     375             :         const char *scriptname = rule;
     376             :         const char *routematch_function = "route_match";
     377             :         struct bgp_path_info *path = (struct bgp_path_info *)object;
     378             : 
     379             :         struct frrscript *fs = frrscript_new(scriptname);
     380             : 
     381             :         if (frrscript_load(fs, routematch_function, NULL)) {
     382             :                 zlog_err(
     383             :                         "Issue loading script or function; defaulting to no match");
     384             :                 return RMAP_NOMATCH;
     385             :         }
     386             : 
     387             :         struct attr newattr = *path->attr;
     388             : 
     389             :         int result = frrscript_call(
     390             :                 fs, routematch_function, ("prefix", prefix),
     391             :                 ("attributes", &newattr), ("peer", path->peer),
     392             :                 ("RM_FAILURE", LUA_RM_FAILURE), ("RM_NOMATCH", LUA_RM_NOMATCH),
     393             :                 ("RM_MATCH", LUA_RM_MATCH),
     394             :                 ("RM_MATCH_AND_CHANGE", LUA_RM_MATCH_AND_CHANGE));
     395             : 
     396             :         if (result) {
     397             :                 zlog_err("Issue running script rule; defaulting to no match");
     398             :                 return RMAP_NOMATCH;
     399             :         }
     400             : 
     401             :         long long *action = frrscript_get_result(fs, routematch_function,
     402             :                                                  "action", lua_tointegerp);
     403             : 
     404             :         int status = RMAP_NOMATCH;
     405             : 
     406             :         switch (*action) {
     407             :         case LUA_RM_FAILURE:
     408             :                 zlog_err(
     409             :                         "Executing route-map match script '%s' failed; defaulting to no match",
     410             :                         scriptname);
     411             :                 status = RMAP_NOMATCH;
     412             :                 break;
     413             :         case LUA_RM_NOMATCH:
     414             :                 status = RMAP_NOMATCH;
     415             :                 break;
     416             :         case LUA_RM_MATCH_AND_CHANGE:
     417             :                 status = RMAP_MATCH;
     418             :                 zlog_debug("Updating attribute based on script's values");
     419             : 
     420             :                 uint32_t locpref = 0;
     421             : 
     422             :                 path->attr->med = newattr.med;
     423             : 
     424             :                 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
     425             :                         locpref = path->attr->local_pref;
     426             :                 if (locpref != newattr.local_pref) {
     427             :                         SET_FLAG(path->attr->flag,
     428             :                                  ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF));
     429             :                         path->attr->local_pref = newattr.local_pref;
     430             :                 }
     431             :                 break;
     432             :         case LUA_RM_MATCH:
     433             :                 status = RMAP_MATCH;
     434             :                 break;
     435             :         }
     436             : 
     437             :         XFREE(MTYPE_SCRIPT_RES, action);
     438             : 
     439             :         frrscript_delete(fs);
     440             : 
     441             :         return status;
     442             : }
     443             : 
     444             : static void *route_match_script_compile(const char *arg)
     445             : {
     446             :         char *scriptname;
     447             : 
     448             :         scriptname = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     449             : 
     450             :         return scriptname;
     451             : }
     452             : 
     453             : static void route_match_script_free(void *rule)
     454             : {
     455             :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     456             : }
     457             : 
     458             : static const struct route_map_rule_cmd route_match_script_cmd = {
     459             :         "script",
     460             :         route_match_script,
     461             :         route_match_script_compile,
     462             :         route_match_script_free
     463             : };
     464             : 
     465             : #endif /* HAVE_SCRIPTING */
     466             : 
     467             : /* `match ip address IP_ACCESS_LIST' */
     468             : 
     469             : /* Match function should return 1 if match is success else return
     470             :    zero. */
     471             : static enum route_map_cmd_result_t
     472           0 : route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
     473             : {
     474           0 :         struct access_list *alist;
     475             : 
     476           0 :         if (prefix->family == AF_INET) {
     477           0 :                 alist = access_list_lookup(AFI_IP, (char *)rule);
     478           0 :                 if (alist == NULL)
     479             :                         return RMAP_NOMATCH;
     480             : 
     481           0 :                 return (access_list_apply(alist, prefix) == FILTER_DENY
     482             :                                 ? RMAP_NOMATCH
     483           0 :                                 : RMAP_MATCH);
     484             :         }
     485             :         return RMAP_NOMATCH;
     486             : }
     487             : 
     488             : /* Route map `ip address' match statement.  `arg' should be
     489             :    access-list name. */
     490           0 : static void *route_match_ip_address_compile(const char *arg)
     491             : {
     492           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     493             : }
     494             : 
     495             : /* Free route map's compiled `ip address' value. */
     496           0 : static void route_match_ip_address_free(void *rule)
     497             : {
     498           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     499           0 : }
     500             : 
     501             : /* Route map commands for ip address matching. */
     502             : static const struct route_map_rule_cmd route_match_ip_address_cmd = {
     503             :         "ip address",
     504             :         route_match_ip_address,
     505             :         route_match_ip_address_compile,
     506             :         route_match_ip_address_free
     507             : };
     508             : 
     509             : /* `match ip next-hop IP_ADDRESS' */
     510             : 
     511             : /* Match function return 1 if match is success else return zero. */
     512             : static enum route_map_cmd_result_t
     513           0 : route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
     514             : {
     515           0 :         struct access_list *alist;
     516           0 :         struct bgp_path_info *path;
     517           0 :         struct prefix_ipv4 p;
     518             : 
     519           0 :         if (prefix->family == AF_INET) {
     520           0 :                 path = object;
     521           0 :                 p.family = AF_INET;
     522           0 :                 p.prefix = path->attr->nexthop;
     523           0 :                 p.prefixlen = IPV4_MAX_BITLEN;
     524             : 
     525           0 :                 alist = access_list_lookup(AFI_IP, (char *)rule);
     526           0 :                 if (alist == NULL)
     527             :                         return RMAP_NOMATCH;
     528             : 
     529           0 :                 return (access_list_apply(alist, &p) == FILTER_DENY
     530             :                                 ? RMAP_NOMATCH
     531           0 :                                 : RMAP_MATCH);
     532             :         }
     533             :         return RMAP_NOMATCH;
     534             : }
     535             : 
     536             : /* Route map `ip next-hop' match statement. `arg' is
     537             :    access-list name. */
     538           0 : static void *route_match_ip_next_hop_compile(const char *arg)
     539             : {
     540           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     541             : }
     542             : 
     543             : /* Free route map's compiled `ip address' value. */
     544           0 : static void route_match_ip_next_hop_free(void *rule)
     545             : {
     546           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     547           0 : }
     548             : 
     549             : /* Route map commands for ip next-hop matching. */
     550             : static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
     551             :         "ip next-hop",
     552             :         route_match_ip_next_hop,
     553             :         route_match_ip_next_hop_compile,
     554             :         route_match_ip_next_hop_free
     555             : };
     556             : 
     557             : /* `match ip route-source ACCESS-LIST' */
     558             : 
     559             : /* Match function return 1 if match is success else return zero. */
     560             : static enum route_map_cmd_result_t
     561           0 : route_match_ip_route_source(void *rule, const struct prefix *pfx, void *object)
     562             : {
     563           0 :         struct access_list *alist;
     564           0 :         struct bgp_path_info *path;
     565           0 :         struct peer *peer;
     566           0 :         struct prefix_ipv4 p;
     567             : 
     568           0 :         if (pfx->family == AF_INET) {
     569           0 :                 path = object;
     570           0 :                 peer = path->peer;
     571             : 
     572           0 :                 if (!peer || sockunion_family(&peer->su) != AF_INET)
     573             :                         return RMAP_NOMATCH;
     574             : 
     575           0 :                 p.family = AF_INET;
     576           0 :                 p.prefix = peer->su.sin.sin_addr;
     577           0 :                 p.prefixlen = IPV4_MAX_BITLEN;
     578             : 
     579           0 :                 alist = access_list_lookup(AFI_IP, (char *)rule);
     580           0 :                 if (alist == NULL)
     581             :                         return RMAP_NOMATCH;
     582             : 
     583           0 :                 return (access_list_apply(alist, &p) == FILTER_DENY
     584             :                                 ? RMAP_NOMATCH
     585           0 :                                 : RMAP_MATCH);
     586             :         }
     587             :         return RMAP_NOMATCH;
     588             : }
     589             : 
     590             : /* Route map `ip route-source' match statement. `arg' is
     591             :    access-list name. */
     592           0 : static void *route_match_ip_route_source_compile(const char *arg)
     593             : {
     594           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     595             : }
     596             : 
     597             : /* Free route map's compiled `ip address' value. */
     598           0 : static void route_match_ip_route_source_free(void *rule)
     599             : {
     600           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     601           0 : }
     602             : 
     603             : /* Route map commands for ip route-source matching. */
     604             : static const struct route_map_rule_cmd route_match_ip_route_source_cmd = {
     605             :         "ip route-source",
     606             :         route_match_ip_route_source,
     607             :         route_match_ip_route_source_compile,
     608             :         route_match_ip_route_source_free
     609             : };
     610             : 
     611             : static enum route_map_cmd_result_t
     612           0 : route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist,
     613             :                                  const struct prefix *p)
     614             : {
     615           0 :         int ret;
     616           0 :         struct bgp_pbr_entry_main api;
     617             : 
     618           0 :         memset(&api, 0, sizeof(api));
     619             : 
     620           0 :         if (family2afi(p->u.prefix_flowspec.family) != afi)
     621             :                 return RMAP_NOMATCH;
     622             : 
     623             :         /* extract match from flowspec entries */
     624           0 :         ret = bgp_flowspec_match_rules_fill(
     625           0 :                                             (uint8_t *)p->u.prefix_flowspec.ptr,
     626           0 :                                             p->u.prefix_flowspec.prefixlen, &api,
     627             :                                             afi);
     628           0 :         if (ret < 0)
     629             :                 return RMAP_NOMATCH;
     630           0 :         if (api.match_bitmask & PREFIX_DST_PRESENT ||
     631           0 :             api.match_bitmask_iprule & PREFIX_DST_PRESENT) {
     632           0 :                 if (family2afi((&api.dst_prefix)->family) != afi)
     633             :                         return RMAP_NOMATCH;
     634           0 :                 return prefix_list_apply(plist, &api.dst_prefix) == PREFIX_DENY
     635             :                         ? RMAP_NOMATCH
     636           0 :                         : RMAP_MATCH;
     637           0 :         } else if (api.match_bitmask & PREFIX_SRC_PRESENT ||
     638             :                    api.match_bitmask_iprule & PREFIX_SRC_PRESENT) {
     639           0 :                 if (family2afi((&api.src_prefix)->family) != afi)
     640             :                         return RMAP_NOMATCH;
     641           0 :                 return (prefix_list_apply(plist, &api.src_prefix) == PREFIX_DENY
     642             :                         ? RMAP_NOMATCH
     643           0 :                         : RMAP_MATCH);
     644             :         }
     645             :         return RMAP_NOMATCH;
     646             : }
     647             : 
     648             : static enum route_map_cmd_result_t
     649           0 : route_match_prefix_list_evpn(afi_t afi, struct prefix_list *plist,
     650             :                              const struct prefix *p)
     651             : {
     652             :         /* Convert to match a general plist */
     653           0 :         struct prefix new;
     654             : 
     655           0 :         if (evpn_prefix2prefix(p, &new))
     656             :                 return RMAP_NOMATCH;
     657             : 
     658           0 :         return (prefix_list_apply(plist, &new) == PREFIX_DENY ? RMAP_NOMATCH
     659           0 :                                                               : RMAP_MATCH);
     660             : }
     661             : 
     662             : static enum route_map_cmd_result_t
     663           1 : route_match_address_prefix_list(void *rule, afi_t afi,
     664             :                                 const struct prefix *prefix, void *object)
     665             : {
     666           1 :         struct prefix_list *plist;
     667             : 
     668           1 :         plist = prefix_list_lookup(afi, (char *)rule);
     669           1 :         if (plist == NULL)
     670             :                 return RMAP_NOMATCH;
     671             : 
     672           1 :         if (prefix->family == AF_FLOWSPEC)
     673           0 :                 return route_match_prefix_list_flowspec(afi, plist,
     674             :                                                         prefix);
     675             : 
     676           1 :         else if (prefix->family == AF_EVPN)
     677           0 :                 return route_match_prefix_list_evpn(afi, plist, prefix);
     678             : 
     679           1 :         return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
     680           1 :                                                                 : RMAP_MATCH);
     681             : }
     682             : 
     683             : static enum route_map_cmd_result_t
     684           1 : route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
     685             :                                    void *object)
     686             : {
     687           1 :         return route_match_address_prefix_list(rule, AFI_IP, prefix, object);
     688             : }
     689             : 
     690           1 : static void *route_match_ip_address_prefix_list_compile(const char *arg)
     691             : {
     692           1 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     693             : }
     694             : 
     695           1 : static void route_match_ip_address_prefix_list_free(void *rule)
     696             : {
     697           1 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     698           1 : }
     699             : 
     700             : static const struct route_map_rule_cmd
     701             :                 route_match_ip_address_prefix_list_cmd = {
     702             :         "ip address prefix-list",
     703             :         route_match_ip_address_prefix_list,
     704             :         route_match_ip_address_prefix_list_compile,
     705             :         route_match_ip_address_prefix_list_free
     706             : };
     707             : 
     708             : /* `match ip next-hop prefix-list PREFIX_LIST' */
     709             : 
     710             : static enum route_map_cmd_result_t
     711           0 : route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
     712             :                                     void *object)
     713             : {
     714           0 :         struct prefix_list *plist;
     715           0 :         struct bgp_path_info *path;
     716           0 :         struct prefix_ipv4 p;
     717             : 
     718           0 :         if (prefix->family == AF_INET) {
     719           0 :                 path = object;
     720           0 :                 p.family = AF_INET;
     721           0 :                 p.prefix = path->attr->nexthop;
     722           0 :                 p.prefixlen = IPV4_MAX_BITLEN;
     723             : 
     724           0 :                 plist = prefix_list_lookup(AFI_IP, (char *)rule);
     725           0 :                 if (plist == NULL)
     726             :                         return RMAP_NOMATCH;
     727             : 
     728           0 :                 return (prefix_list_apply(plist, &p) == PREFIX_DENY
     729             :                                 ? RMAP_NOMATCH
     730           0 :                                 : RMAP_MATCH);
     731             :         }
     732             :         return RMAP_NOMATCH;
     733             : }
     734             : 
     735           0 : static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
     736             : {
     737           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     738             : }
     739             : 
     740           0 : static void route_match_ip_next_hop_prefix_list_free(void *rule)
     741             : {
     742           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     743           0 : }
     744             : 
     745             : static const struct route_map_rule_cmd
     746             :                 route_match_ip_next_hop_prefix_list_cmd = {
     747             :         "ip next-hop prefix-list",
     748             :         route_match_ip_next_hop_prefix_list,
     749             :         route_match_ip_next_hop_prefix_list_compile,
     750             :         route_match_ip_next_hop_prefix_list_free
     751             : };
     752             : 
     753             : /* `match ipv6 next-hop prefix-list PREFIXLIST_NAME' */
     754             : static enum route_map_cmd_result_t
     755           0 : route_match_ipv6_next_hop_prefix_list(void *rule, const struct prefix *prefix,
     756             :                                       void *object)
     757             : {
     758           0 :         struct prefix_list *plist;
     759           0 :         struct bgp_path_info *path;
     760           0 :         struct prefix_ipv6 p;
     761             : 
     762           0 :         if (prefix->family == AF_INET6) {
     763           0 :                 path = object;
     764           0 :                 p.family = AF_INET6;
     765           0 :                 p.prefix = path->attr->mp_nexthop_global;
     766           0 :                 p.prefixlen = IPV6_MAX_BITLEN;
     767             : 
     768           0 :                 plist = prefix_list_lookup(AFI_IP6, (char *)rule);
     769           0 :                 if (!plist)
     770             :                         return RMAP_NOMATCH;
     771             : 
     772           0 :                 if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
     773             :                         return RMAP_MATCH;
     774             : 
     775           0 :                 if (path->attr->mp_nexthop_len
     776             :                     == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
     777           0 :                         p.prefix = path->attr->mp_nexthop_local;
     778           0 :                         if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
     779             :                                 return RMAP_MATCH;
     780             :                 }
     781             :         }
     782             : 
     783             :         return RMAP_NOMATCH;
     784             : }
     785             : 
     786           0 : static void *route_match_ipv6_next_hop_prefix_list_compile(const char *arg)
     787             : {
     788           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     789             : }
     790             : 
     791           0 : static void route_match_ipv6_next_hop_prefix_list_free(void *rule)
     792             : {
     793           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     794           0 : }
     795             : 
     796             : static const struct route_map_rule_cmd
     797             :                 route_match_ipv6_next_hop_prefix_list_cmd = {
     798             :         "ipv6 next-hop prefix-list",
     799             :         route_match_ipv6_next_hop_prefix_list,
     800             :         route_match_ipv6_next_hop_prefix_list_compile,
     801             :         route_match_ipv6_next_hop_prefix_list_free
     802             : };
     803             : 
     804             : /* `match ip next-hop type <blackhole>' */
     805             : 
     806             : static enum route_map_cmd_result_t
     807           0 : route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
     808             :                              void *object)
     809             : {
     810           0 :         struct bgp_path_info *path;
     811             : 
     812           0 :         if (prefix->family == AF_INET) {
     813           0 :                 path = (struct bgp_path_info *)object;
     814           0 :                 if (!path)
     815             :                         return RMAP_NOMATCH;
     816             : 
     817             :                 /* If nexthop interface's index can't be resolved and nexthop is
     818             :                    set to any address then mark it as type `blackhole`.
     819             :                    This logic works for matching kernel/static routes like:
     820             :                    `ip route add blackhole 10.0.0.1`. */
     821           0 :                 if (path->attr->nexthop.s_addr == INADDR_ANY
     822           0 :                     && !path->attr->nh_ifindex)
     823           0 :                         return RMAP_MATCH;
     824             :         }
     825             :         return RMAP_NOMATCH;
     826             : }
     827             : 
     828           0 : static void *route_match_ip_next_hop_type_compile(const char *arg)
     829             : {
     830           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     831             : }
     832             : 
     833           0 : static void route_match_ip_next_hop_type_free(void *rule)
     834             : {
     835           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     836           0 : }
     837             : 
     838             : static const struct route_map_rule_cmd
     839             :                 route_match_ip_next_hop_type_cmd = {
     840             :         "ip next-hop type",
     841             :         route_match_ip_next_hop_type,
     842             :         route_match_ip_next_hop_type_compile,
     843             :         route_match_ip_next_hop_type_free
     844             : };
     845             : 
     846             : /* `match ip route-source prefix-list PREFIX_LIST' */
     847             : 
     848             : static enum route_map_cmd_result_t
     849           0 : route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix,
     850             :                                         void *object)
     851             : {
     852           0 :         struct prefix_list *plist;
     853           0 :         struct bgp_path_info *path;
     854           0 :         struct peer *peer;
     855           0 :         struct prefix_ipv4 p;
     856             : 
     857           0 :         if (prefix->family == AF_INET) {
     858           0 :                 path = object;
     859           0 :                 peer = path->peer;
     860             : 
     861           0 :                 if (!peer || sockunion_family(&peer->su) != AF_INET)
     862             :                         return RMAP_NOMATCH;
     863             : 
     864           0 :                 p.family = AF_INET;
     865           0 :                 p.prefix = peer->su.sin.sin_addr;
     866           0 :                 p.prefixlen = IPV4_MAX_BITLEN;
     867             : 
     868           0 :                 plist = prefix_list_lookup(AFI_IP, (char *)rule);
     869           0 :                 if (plist == NULL)
     870             :                         return RMAP_NOMATCH;
     871             : 
     872           0 :                 return (prefix_list_apply(plist, &p) == PREFIX_DENY
     873             :                                 ? RMAP_NOMATCH
     874           0 :                                 : RMAP_MATCH);
     875             :         }
     876             :         return RMAP_NOMATCH;
     877             : }
     878             : 
     879           0 : static void *route_match_ip_route_source_prefix_list_compile(const char *arg)
     880             : {
     881           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     882             : }
     883             : 
     884           0 : static void route_match_ip_route_source_prefix_list_free(void *rule)
     885             : {
     886           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     887           0 : }
     888             : 
     889             : static const struct route_map_rule_cmd
     890             :                 route_match_ip_route_source_prefix_list_cmd = {
     891             :         "ip route-source prefix-list",
     892             :         route_match_ip_route_source_prefix_list,
     893             :         route_match_ip_route_source_prefix_list_compile,
     894             :         route_match_ip_route_source_prefix_list_free
     895             : };
     896             : 
     897             : /* `match evpn default-route' */
     898             : 
     899             : /* Match function should return 1 if match is success else 0 */
     900             : static enum route_map_cmd_result_t
     901           0 : route_match_evpn_default_route(void *rule, const struct prefix *p, void *object)
     902             : {
     903           0 :         if (is_evpn_prefix_default(p))
     904           0 :                 return RMAP_MATCH;
     905             : 
     906             :         return RMAP_NOMATCH;
     907             : }
     908             : 
     909             : /* Route map commands for default-route matching. */
     910             : static const struct route_map_rule_cmd
     911             :                 route_match_evpn_default_route_cmd = {
     912             :         "evpn default-route",
     913             :         route_match_evpn_default_route,
     914             :         NULL,
     915             :         NULL
     916             : };
     917             : 
     918             : /* `match mac address MAC_ACCESS_LIST' */
     919             : 
     920             : /* Match function should return 1 if match is success else return
     921             :    zero. */
     922             : static enum route_map_cmd_result_t
     923           0 : route_match_mac_address(void *rule, const struct prefix *prefix, void *object)
     924             : {
     925           0 :         struct access_list *alist;
     926           0 :         struct prefix p;
     927             : 
     928           0 :         alist = access_list_lookup(AFI_L2VPN, (char *)rule);
     929           0 :         if (alist == NULL)
     930             :                 return RMAP_NOMATCH;
     931             : 
     932           0 :         if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE)
     933             :                 return RMAP_NOMATCH;
     934             : 
     935           0 :         p.family = AF_ETHERNET;
     936           0 :         p.prefixlen = ETH_ALEN * 8;
     937           0 :         p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
     938             : 
     939           0 :         return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
     940           0 :                                                             : RMAP_MATCH);
     941             : }
     942             : 
     943             : /* Route map `mac address' match statement.  `arg' should be
     944             :    access-list name. */
     945           0 : static void *route_match_mac_address_compile(const char *arg)
     946             : {
     947           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     948             : }
     949             : 
     950             : /* Free route map's compiled `ip address' value. */
     951           0 : static void route_match_mac_address_free(void *rule)
     952             : {
     953           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     954           0 : }
     955             : 
     956             : /* Route map commands for mac address matching. */
     957             : static const struct route_map_rule_cmd route_match_mac_address_cmd = {
     958             :         "mac address",
     959             :         route_match_mac_address,
     960             :         route_match_mac_address_compile,
     961             :         route_match_mac_address_free
     962             : };
     963             : 
     964             : /*
     965             :  * Match function returns:
     966             :  * ...RMAP_MATCH if match is found.
     967             :  * ...RMAP_NOMATCH if match is not found.
     968             :  * ...RMAP_NOOP to ignore this match check.
     969             :  */
     970             : static enum route_map_cmd_result_t
     971           0 : route_match_vni(void *rule, const struct prefix *prefix, void *object)
     972             : {
     973           0 :         vni_t vni = 0;
     974           0 :         unsigned int label_cnt = 0;
     975           0 :         struct bgp_path_info *path = NULL;
     976           0 :         struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
     977             : 
     978           0 :         vni = *((vni_t *)rule);
     979           0 :         path = (struct bgp_path_info *)object;
     980             : 
     981             :         /*
     982             :          * This rmap filter is valid for vxlan tunnel type only.
     983             :          * For any other tunnel type, return noop to ignore
     984             :          * this check.
     985             :          */
     986           0 :         if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN)
     987             :                 return RMAP_NOOP;
     988             : 
     989             :         /*
     990             :          * Apply filter to type 1, 2, 5 routes only.
     991             :          * Other route types do not have vni label.
     992             :          */
     993           0 :         if (evp
     994           0 :             && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE
     995             :                 && evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
     996           0 :                 && evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
     997             :                 return RMAP_NOOP;
     998             : 
     999           0 :         if (path->extra == NULL)
    1000             :                 return RMAP_NOMATCH;
    1001             : 
    1002             :         for (;
    1003           0 :              label_cnt < BGP_MAX_LABELS && label_cnt < path->extra->num_labels;
    1004           0 :              label_cnt++) {
    1005           0 :                 if (vni == label2vni(&path->extra->label[label_cnt]))
    1006             :                         return RMAP_MATCH;
    1007             :         }
    1008             : 
    1009             :         return RMAP_NOMATCH;
    1010             : }
    1011             : 
    1012             : /* Route map `vni' match statement. */
    1013           0 : static void *route_match_vni_compile(const char *arg)
    1014             : {
    1015           0 :         vni_t *vni = NULL;
    1016           0 :         char *end = NULL;
    1017             : 
    1018           0 :         vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
    1019             : 
    1020           0 :         *vni = strtoul(arg, &end, 10);
    1021           0 :         if (*end != '\0') {
    1022           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, vni);
    1023           0 :                 return NULL;
    1024             :         }
    1025             : 
    1026             :         return vni;
    1027             : }
    1028             : 
    1029             : /* Free route map's compiled `vni' value. */
    1030           0 : static void route_match_vni_free(void *rule)
    1031             : {
    1032           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1033           0 : }
    1034             : 
    1035             : /* Route map commands for vni matching. */
    1036             : static const struct route_map_rule_cmd route_match_evpn_vni_cmd = {
    1037             :         "evpn vni",
    1038             :         route_match_vni,
    1039             :         route_match_vni_compile,
    1040             :         route_match_vni_free
    1041             : };
    1042             : 
    1043             : /* `match evpn route-type' */
    1044             : 
    1045             : /* Match function should return 1 if match is success else return
    1046             :    zero. */
    1047             : static enum route_map_cmd_result_t
    1048           0 : route_match_evpn_route_type(void *rule, const struct prefix *pfx, void *object)
    1049             : {
    1050           0 :         uint8_t route_type = 0;
    1051             : 
    1052           0 :         route_type = *((uint8_t *)rule);
    1053             : 
    1054           0 :         if (route_type == pfx->u.prefix_evpn.route_type)
    1055           0 :                 return RMAP_MATCH;
    1056             : 
    1057             :         return RMAP_NOMATCH;
    1058             : }
    1059             : 
    1060             : /* Route map `route-type' match statement. */
    1061           0 : static void *route_match_evpn_route_type_compile(const char *arg)
    1062             : {
    1063           0 :         uint8_t *route_type = NULL;
    1064             : 
    1065           0 :         route_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
    1066             : 
    1067           0 :         if (strncmp(arg, "ea", 2) == 0)
    1068           0 :                 *route_type = BGP_EVPN_AD_ROUTE;
    1069           0 :         else if (strncmp(arg, "ma", 2) == 0)
    1070           0 :                 *route_type = BGP_EVPN_MAC_IP_ROUTE;
    1071           0 :         else if (strncmp(arg, "mu", 2) == 0)
    1072           0 :                 *route_type = BGP_EVPN_IMET_ROUTE;
    1073           0 :         else if (strncmp(arg, "es", 2) == 0)
    1074           0 :                 *route_type = BGP_EVPN_ES_ROUTE;
    1075             :         else
    1076           0 :                 *route_type = BGP_EVPN_IP_PREFIX_ROUTE;
    1077             : 
    1078           0 :         return route_type;
    1079             : }
    1080             : 
    1081             : /* Free route map's compiled `route-type' value. */
    1082           0 : static void route_match_evpn_route_type_free(void *rule)
    1083             : {
    1084           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1085           0 : }
    1086             : 
    1087             : /* Route map commands for evpn route-type  matching. */
    1088             : static const struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
    1089             :         "evpn route-type",
    1090             :         route_match_evpn_route_type,
    1091             :         route_match_evpn_route_type_compile,
    1092             :         route_match_evpn_route_type_free
    1093             : };
    1094             : 
    1095             : /* `match rd' */
    1096             : 
    1097             : /* Match function should return 1 if match is success else return zero. */
    1098             : static enum route_map_cmd_result_t
    1099           0 : route_match_rd(void *rule, const struct prefix *prefix, void *object)
    1100             : {
    1101           0 :         struct prefix_rd *prd_rule = NULL;
    1102           0 :         const struct prefix_rd *prd_route = NULL;
    1103           0 :         struct bgp_path_info *path = NULL;
    1104             : 
    1105           0 :         if (prefix->family != AF_EVPN)
    1106             :                 return RMAP_NOMATCH;
    1107             : 
    1108           0 :         prd_rule = (struct prefix_rd *)rule;
    1109           0 :         path = (struct bgp_path_info *)object;
    1110             : 
    1111           0 :         if (path->net == NULL || path->net->pdest == NULL)
    1112             :                 return RMAP_NOMATCH;
    1113             : 
    1114           0 :         prd_route = (struct prefix_rd *)bgp_dest_get_prefix(path->net->pdest);
    1115           0 :         if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0)
    1116           0 :                 return RMAP_MATCH;
    1117             : 
    1118             :         return RMAP_NOMATCH;
    1119             : }
    1120             : 
    1121             : /* Route map `rd' match statement. */
    1122           0 : static void *route_match_rd_compile(const char *arg)
    1123             : {
    1124           0 :         struct prefix_rd *prd;
    1125           0 :         int ret;
    1126             : 
    1127           0 :         prd = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct prefix_rd));
    1128             : 
    1129           0 :         ret = str2prefix_rd(arg, prd);
    1130           0 :         if (!ret) {
    1131           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, prd);
    1132           0 :                 return NULL;
    1133             :         }
    1134             : 
    1135             :         return prd;
    1136             : }
    1137             : 
    1138             : /* Free route map's compiled `rd' value. */
    1139           0 : static void route_match_rd_free(void *rule)
    1140             : {
    1141           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1142           0 : }
    1143             : 
    1144             : /* Route map commands for rd matching. */
    1145             : static const struct route_map_rule_cmd route_match_evpn_rd_cmd = {
    1146             :         "evpn rd",
    1147             :         route_match_rd,
    1148             :         route_match_rd_compile,
    1149             :         route_match_rd_free
    1150             : };
    1151             : 
    1152             : static enum route_map_cmd_result_t
    1153           0 : route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object)
    1154             : {
    1155           0 :         struct ipaddr *gw_ip = rule;
    1156           0 :         struct bgp_path_info *path;
    1157           0 :         struct prefix_evpn *evp;
    1158             : 
    1159           0 :         if (prefix->family != AF_EVPN)
    1160             :                 return RMAP_OKAY;
    1161             : 
    1162           0 :         evp = (struct prefix_evpn *)prefix;
    1163           0 :         if (evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)
    1164             :                 return RMAP_OKAY;
    1165             : 
    1166           0 :         if ((is_evpn_prefix_ipaddr_v4(evp) && IPADDRSZ(gw_ip) != 4)
    1167           0 :             || (is_evpn_prefix_ipaddr_v6(evp) && IPADDRSZ(gw_ip) != 16))
    1168             :                 return RMAP_OKAY;
    1169             : 
    1170           0 :         path = object;
    1171             : 
    1172             :         /* Set gateway-ip value. */
    1173           0 :         path->attr->evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
    1174           0 :         memcpy(&path->attr->evpn_overlay.gw_ip, &gw_ip->ip.addr,
    1175           0 :                IPADDRSZ(gw_ip));
    1176             : 
    1177           0 :         return RMAP_OKAY;
    1178             : }
    1179             : 
    1180             : /*
    1181             :  * Route map `evpn gateway-ip' compile function.
    1182             :  * Given string is converted to struct ipaddr structure
    1183             :  */
    1184           0 : static void *route_set_evpn_gateway_ip_compile(const char *arg)
    1185             : {
    1186           0 :         struct ipaddr *gw_ip = NULL;
    1187           0 :         int ret;
    1188             : 
    1189           0 :         gw_ip = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct ipaddr));
    1190             : 
    1191           0 :         ret = str2ipaddr(arg, gw_ip);
    1192           0 :         if (ret < 0) {
    1193           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
    1194           0 :                 return NULL;
    1195             :         }
    1196             :         return gw_ip;
    1197             : }
    1198             : 
    1199             : /* Free route map's compiled `evpn gateway_ip' value. */
    1200           0 : static void route_set_evpn_gateway_ip_free(void *rule)
    1201             : {
    1202           0 :         struct ipaddr *gw_ip = rule;
    1203             : 
    1204           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
    1205           0 : }
    1206             : 
    1207             : /* Route map commands for set evpn gateway-ip ipv4. */
    1208             : struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv4_cmd = {
    1209             :         "evpn gateway-ip ipv4", route_set_evpn_gateway_ip,
    1210             :         route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
    1211             : 
    1212             : /* Route map commands for set evpn gateway-ip ipv6. */
    1213             : struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv6_cmd = {
    1214             :         "evpn gateway-ip ipv6", route_set_evpn_gateway_ip,
    1215             :         route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
    1216             : 
    1217             : /* Route map commands for VRF route leak with source vrf matching */
    1218             : static enum route_map_cmd_result_t
    1219           0 : route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
    1220             :                            void *object)
    1221             : {
    1222           0 :         struct bgp_path_info *path;
    1223           0 :         char *vrf_name;
    1224             : 
    1225           0 :         vrf_name = rule;
    1226           0 :         path = (struct bgp_path_info *)object;
    1227             : 
    1228           0 :         if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
    1229             :                 return RMAP_NOMATCH;
    1230             : 
    1231           0 :         if (path->extra == NULL || path->extra->bgp_orig == NULL)
    1232             :                 return RMAP_NOMATCH;
    1233             : 
    1234           0 :         if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id),
    1235             :                     VRF_NAMSIZ)
    1236             :             == 0)
    1237             :                 return RMAP_MATCH;
    1238             : 
    1239             :         return RMAP_NOMATCH;
    1240             : }
    1241             : 
    1242           0 : static void *route_match_vrl_source_vrf_compile(const char *arg)
    1243             : {
    1244           0 :         uint8_t *vrf_name = NULL;
    1245             : 
    1246           0 :         vrf_name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1247             : 
    1248           0 :         return vrf_name;
    1249             : }
    1250             : 
    1251             : /* Free route map's compiled `route-type' value. */
    1252           0 : static void route_match_vrl_source_vrf_free(void *rule)
    1253             : {
    1254           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1255           0 : }
    1256             : 
    1257             : static const struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
    1258             :         "source-vrf",
    1259             :         route_match_vrl_source_vrf,
    1260             :         route_match_vrl_source_vrf_compile,
    1261             :         route_match_vrl_source_vrf_free
    1262             : };
    1263             : 
    1264             : /* `match alias` */
    1265             : static enum route_map_cmd_result_t
    1266           0 : route_match_alias(void *rule, const struct prefix *prefix, void *object)
    1267             : {
    1268           0 :         char *alias = rule;
    1269           0 :         struct bgp_path_info *path = object;
    1270           0 :         char **communities;
    1271           0 :         int num;
    1272           0 :         bool found;
    1273             : 
    1274           0 :         if (bgp_attr_get_community(path->attr)) {
    1275           0 :                 found = false;
    1276           0 :                 frrstr_split(bgp_attr_get_community(path->attr)->str, " ",
    1277             :                              &communities, &num);
    1278           0 :                 for (int i = 0; i < num; i++) {
    1279           0 :                         const char *com2alias =
    1280           0 :                                 bgp_community2alias(communities[i]);
    1281           0 :                         if (!found && strcmp(alias, com2alias) == 0)
    1282           0 :                                 found = true;
    1283           0 :                         XFREE(MTYPE_TMP, communities[i]);
    1284             :                 }
    1285           0 :                 XFREE(MTYPE_TMP, communities);
    1286           0 :                 if (found)
    1287             :                         return RMAP_MATCH;
    1288             :         }
    1289             : 
    1290           0 :         if (bgp_attr_get_lcommunity(path->attr)) {
    1291           0 :                 found = false;
    1292           0 :                 frrstr_split(bgp_attr_get_lcommunity(path->attr)->str, " ",
    1293             :                              &communities, &num);
    1294           0 :                 for (int i = 0; i < num; i++) {
    1295           0 :                         const char *com2alias =
    1296           0 :                                 bgp_community2alias(communities[i]);
    1297           0 :                         if (!found && strcmp(alias, com2alias) == 0)
    1298           0 :                                 found = true;
    1299           0 :                         XFREE(MTYPE_TMP, communities[i]);
    1300             :                 }
    1301           0 :                 XFREE(MTYPE_TMP, communities);
    1302           0 :                 if (found)
    1303             :                         return RMAP_MATCH;
    1304             :         }
    1305             : 
    1306             :         return RMAP_NOMATCH;
    1307             : }
    1308             : 
    1309           0 : static void *route_match_alias_compile(const char *arg)
    1310             : {
    1311             : 
    1312           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1313             : }
    1314             : 
    1315           0 : static void route_match_alias_free(void *rule)
    1316             : {
    1317           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1318           0 : }
    1319             : 
    1320             : static const struct route_map_rule_cmd route_match_alias_cmd = {
    1321             :         "alias", route_match_alias, route_match_alias_compile,
    1322             :         route_match_alias_free};
    1323             : 
    1324             : /* `match local-preference LOCAL-PREF' */
    1325             : 
    1326             : /* Match function return 1 if match is success else return zero. */
    1327             : static enum route_map_cmd_result_t
    1328           0 : route_match_local_pref(void *rule, const struct prefix *prefix, void *object)
    1329             : {
    1330           0 :         uint32_t *local_pref;
    1331           0 :         struct bgp_path_info *path;
    1332             : 
    1333           0 :         local_pref = rule;
    1334           0 :         path = object;
    1335             : 
    1336           0 :         if (path->attr->local_pref == *local_pref)
    1337             :                 return RMAP_MATCH;
    1338             :         else
    1339           0 :                 return RMAP_NOMATCH;
    1340             : }
    1341             : 
    1342             : /*
    1343             :  * Route map `match local-preference' match statement.
    1344             :  * `arg' is local-pref value
    1345             :  */
    1346           0 : static void *route_match_local_pref_compile(const char *arg)
    1347             : {
    1348           0 :         uint32_t *local_pref;
    1349           0 :         char *endptr = NULL;
    1350           0 :         unsigned long tmpval;
    1351             : 
    1352             :         /* Locpref value shoud be integer. */
    1353           0 :         if (!all_digit(arg))
    1354             :                 return NULL;
    1355             : 
    1356           0 :         errno = 0;
    1357           0 :         tmpval = strtoul(arg, &endptr, 10);
    1358           0 :         if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
    1359             :                 return NULL;
    1360             : 
    1361           0 :         local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
    1362             : 
    1363           0 :         *local_pref = tmpval;
    1364           0 :         return local_pref;
    1365             : }
    1366             : 
    1367             : /* Free route map's compiled `match local-preference' value. */
    1368           0 : static void route_match_local_pref_free(void *rule)
    1369             : {
    1370           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1371           0 : }
    1372             : 
    1373             : /* Route map commands for metric matching. */
    1374             : static const struct route_map_rule_cmd route_match_local_pref_cmd = {
    1375             :         "local-preference",
    1376             :         route_match_local_pref,
    1377             :         route_match_local_pref_compile,
    1378             :         route_match_local_pref_free
    1379             : };
    1380             : 
    1381             : /* `match metric METRIC' */
    1382             : 
    1383             : /* Match function return 1 if match is success else return zero. */
    1384             : static enum route_map_cmd_result_t
    1385           0 : route_match_metric(void *rule, const struct prefix *prefix, void *object)
    1386             : {
    1387           0 :         struct rmap_value *rv;
    1388           0 :         struct bgp_path_info *path;
    1389             : 
    1390           0 :         rv = rule;
    1391           0 :         path = object;
    1392           0 :         return route_value_match(rv, path->attr->med);
    1393             : }
    1394             : 
    1395             : /* Route map commands for metric matching. */
    1396             : static const struct route_map_rule_cmd route_match_metric_cmd = {
    1397             :         "metric",
    1398             :         route_match_metric,
    1399             :         route_value_compile,
    1400             :         route_value_free,
    1401             : };
    1402             : 
    1403             : /* `match as-path ASPATH' */
    1404             : 
    1405             : /* Match function for as-path match.  I assume given object is */
    1406             : static enum route_map_cmd_result_t
    1407           0 : route_match_aspath(void *rule, const struct prefix *prefix, void *object)
    1408             : {
    1409             : 
    1410           0 :         struct as_list *as_list;
    1411           0 :         struct bgp_path_info *path;
    1412             : 
    1413           0 :         as_list = as_list_lookup((char *)rule);
    1414           0 :         if (as_list == NULL)
    1415             :                 return RMAP_NOMATCH;
    1416             : 
    1417           0 :         path = object;
    1418             : 
    1419             :         /* Perform match. */
    1420           0 :         return ((as_list_apply(as_list, path->attr->aspath) == AS_FILTER_DENY)
    1421             :                         ? RMAP_NOMATCH
    1422           0 :                         : RMAP_MATCH);
    1423             : }
    1424             : 
    1425             : /* Compile function for as-path match. */
    1426           0 : static void *route_match_aspath_compile(const char *arg)
    1427             : {
    1428           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1429             : }
    1430             : 
    1431             : /* Compile function for as-path match. */
    1432           0 : static void route_match_aspath_free(void *rule)
    1433             : {
    1434           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1435           0 : }
    1436             : 
    1437             : /* Route map commands for aspath matching. */
    1438             : static const struct route_map_rule_cmd route_match_aspath_cmd = {
    1439             :         "as-path",
    1440             :         route_match_aspath,
    1441             :         route_match_aspath_compile,
    1442             :         route_match_aspath_free
    1443             : };
    1444             : 
    1445             : /* `match community COMMUNIY' */
    1446             : struct rmap_community {
    1447             :         char *name;
    1448             :         uint32_t name_hash;
    1449             :         int exact;
    1450             : };
    1451             : 
    1452             : /* Match function for community match. */
    1453             : static enum route_map_cmd_result_t
    1454           0 : route_match_community(void *rule, const struct prefix *prefix, void *object)
    1455             : {
    1456           0 :         struct community_list *list;
    1457           0 :         struct bgp_path_info *path;
    1458           0 :         struct rmap_community *rcom = rule;
    1459             : 
    1460           0 :         path = object;
    1461           0 :         rcom = rule;
    1462             : 
    1463           0 :         list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
    1464             :                                      COMMUNITY_LIST_MASTER);
    1465           0 :         if (!list)
    1466             :                 return RMAP_NOMATCH;
    1467             : 
    1468           0 :         if (rcom->exact) {
    1469           0 :                 if (community_list_exact_match(
    1470           0 :                             bgp_attr_get_community(path->attr), list))
    1471             :                         return RMAP_MATCH;
    1472             :         } else {
    1473           0 :                 if (community_list_match(bgp_attr_get_community(path->attr),
    1474             :                                          list))
    1475             :                         return RMAP_MATCH;
    1476             :         }
    1477             : 
    1478             :         return RMAP_NOMATCH;
    1479             : }
    1480             : 
    1481             : /* Compile function for community match. */
    1482           0 : static void *route_match_community_compile(const char *arg)
    1483             : {
    1484           0 :         struct rmap_community *rcom;
    1485           0 :         int len;
    1486           0 :         char *p;
    1487             : 
    1488           0 :         rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
    1489             : 
    1490           0 :         p = strchr(arg, ' ');
    1491           0 :         if (p) {
    1492           0 :                 len = p - arg;
    1493           0 :                 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
    1494           0 :                 memcpy(rcom->name, arg, len);
    1495           0 :                 rcom->exact = 1;
    1496             :         } else {
    1497           0 :                 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1498           0 :                 rcom->exact = 0;
    1499             :         }
    1500             : 
    1501           0 :         rcom->name_hash = bgp_clist_hash_key(rcom->name);
    1502           0 :         return rcom;
    1503             : }
    1504             : 
    1505             : /* Compile function for community match. */
    1506           0 : static void route_match_community_free(void *rule)
    1507             : {
    1508           0 :         struct rmap_community *rcom = rule;
    1509             : 
    1510           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
    1511           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
    1512           0 : }
    1513             : 
    1514             : /*
    1515             :  * In routemap processing there is a need to add the
    1516             :  * name as a rule_key in the dependency table. Routemap
    1517             :  * lib is unaware of rule_key when exact-match clause
    1518             :  * is in use. routemap lib uses the compiled output to
    1519             :  * get the rule_key value.
    1520             :  */
    1521           0 : static void *route_match_get_community_key(void *rule)
    1522             : {
    1523           0 :         struct rmap_community *rcom;
    1524             : 
    1525           0 :         rcom = rule;
    1526           0 :         return rcom->name;
    1527             : }
    1528             : 
    1529             : 
    1530             : /* Route map commands for community matching. */
    1531             : static const struct route_map_rule_cmd route_match_community_cmd = {
    1532             :         "community",
    1533             :         route_match_community,
    1534             :         route_match_community_compile,
    1535             :         route_match_community_free,
    1536             :         route_match_get_community_key
    1537             : };
    1538             : 
    1539             : /* Match function for lcommunity match. */
    1540             : static enum route_map_cmd_result_t
    1541           0 : route_match_lcommunity(void *rule, const struct prefix *prefix, void *object)
    1542             : {
    1543           0 :         struct community_list *list;
    1544           0 :         struct bgp_path_info *path;
    1545           0 :         struct rmap_community *rcom = rule;
    1546             : 
    1547           0 :         path = object;
    1548             : 
    1549           0 :         list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
    1550             :                                      LARGE_COMMUNITY_LIST_MASTER);
    1551           0 :         if (!list)
    1552             :                 return RMAP_NOMATCH;
    1553             : 
    1554           0 :         if (rcom->exact) {
    1555           0 :                 if (lcommunity_list_exact_match(
    1556           0 :                             bgp_attr_get_lcommunity(path->attr), list))
    1557             :                         return RMAP_MATCH;
    1558             :         } else {
    1559           0 :                 if (lcommunity_list_match(bgp_attr_get_lcommunity(path->attr),
    1560             :                                           list))
    1561             :                         return RMAP_MATCH;
    1562             :         }
    1563             : 
    1564             :         return RMAP_NOMATCH;
    1565             : }
    1566             : 
    1567             : /* Compile function for community match. */
    1568           0 : static void *route_match_lcommunity_compile(const char *arg)
    1569             : {
    1570           0 :         struct rmap_community *rcom;
    1571           0 :         int len;
    1572           0 :         char *p;
    1573             : 
    1574           0 :         rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
    1575             : 
    1576           0 :         p = strchr(arg, ' ');
    1577           0 :         if (p) {
    1578           0 :                 len = p - arg;
    1579           0 :                 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
    1580           0 :                 memcpy(rcom->name, arg, len);
    1581           0 :                 rcom->exact = 1;
    1582             :         } else {
    1583           0 :                 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1584           0 :                 rcom->exact = 0;
    1585             :         }
    1586             : 
    1587           0 :         rcom->name_hash = bgp_clist_hash_key(rcom->name);
    1588           0 :         return rcom;
    1589             : }
    1590             : 
    1591             : /* Compile function for community match. */
    1592           0 : static void route_match_lcommunity_free(void *rule)
    1593             : {
    1594           0 :         struct rmap_community *rcom = rule;
    1595             : 
    1596           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
    1597           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
    1598           0 : }
    1599             : 
    1600             : /* Route map commands for community matching. */
    1601             : static const struct route_map_rule_cmd route_match_lcommunity_cmd = {
    1602             :         "large-community",
    1603             :         route_match_lcommunity,
    1604             :         route_match_lcommunity_compile,
    1605             :         route_match_lcommunity_free,
    1606             :         route_match_get_community_key
    1607             : };
    1608             : 
    1609             : 
    1610             : /* Match function for extcommunity match. */
    1611             : static enum route_map_cmd_result_t
    1612           0 : route_match_ecommunity(void *rule, const struct prefix *prefix, void *object)
    1613             : {
    1614           0 :         struct community_list *list;
    1615           0 :         struct bgp_path_info *path;
    1616           0 :         struct rmap_community *rcom = rule;
    1617             : 
    1618           0 :         path = object;
    1619             : 
    1620           0 :         list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
    1621             :                                      EXTCOMMUNITY_LIST_MASTER);
    1622           0 :         if (!list)
    1623             :                 return RMAP_NOMATCH;
    1624             : 
    1625           0 :         if (ecommunity_list_match(bgp_attr_get_ecommunity(path->attr), list))
    1626             :                 return RMAP_MATCH;
    1627             : 
    1628             :         return RMAP_NOMATCH;
    1629             : }
    1630             : 
    1631             : /* Compile function for extcommunity match. */
    1632           0 : static void *route_match_ecommunity_compile(const char *arg)
    1633             : {
    1634           0 :         struct rmap_community *rcom;
    1635             : 
    1636           0 :         rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
    1637           0 :         rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1638           0 :         rcom->name_hash = bgp_clist_hash_key(rcom->name);
    1639             : 
    1640           0 :         return rcom;
    1641             : }
    1642             : 
    1643             : /* Compile function for extcommunity match. */
    1644           0 : static void route_match_ecommunity_free(void *rule)
    1645             : {
    1646           0 :         struct rmap_community *rcom = rule;
    1647             : 
    1648           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
    1649           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
    1650           0 : }
    1651             : 
    1652             : /* Route map commands for community matching. */
    1653             : static const struct route_map_rule_cmd route_match_ecommunity_cmd = {
    1654             :         "extcommunity",
    1655             :         route_match_ecommunity,
    1656             :         route_match_ecommunity_compile,
    1657             :         route_match_ecommunity_free
    1658             : };
    1659             : 
    1660             : /* `match nlri` and `set nlri` are replaced by `address-family ipv4`
    1661             :    and `address-family vpnv4'.  */
    1662             : 
    1663             : /* `match origin' */
    1664             : static enum route_map_cmd_result_t
    1665           0 : route_match_origin(void *rule, const struct prefix *prefix, void *object)
    1666             : {
    1667           0 :         uint8_t *origin;
    1668           0 :         struct bgp_path_info *path;
    1669             : 
    1670           0 :         origin = rule;
    1671           0 :         path = object;
    1672             : 
    1673           0 :         if (path->attr->origin == *origin)
    1674           0 :                 return RMAP_MATCH;
    1675             : 
    1676             :         return RMAP_NOMATCH;
    1677             : }
    1678             : 
    1679           0 : static void *route_match_origin_compile(const char *arg)
    1680             : {
    1681           0 :         uint8_t *origin;
    1682             : 
    1683           0 :         origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
    1684             : 
    1685           0 :         if (strcmp(arg, "igp") == 0)
    1686           0 :                 *origin = 0;
    1687           0 :         else if (strcmp(arg, "egp") == 0)
    1688           0 :                 *origin = 1;
    1689             :         else
    1690           0 :                 *origin = 2;
    1691             : 
    1692           0 :         return origin;
    1693             : }
    1694             : 
    1695             : /* Free route map's compiled `ip address' value. */
    1696           0 : static void route_match_origin_free(void *rule)
    1697             : {
    1698           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1699           0 : }
    1700             : 
    1701             : /* Route map commands for origin matching. */
    1702             : static const struct route_map_rule_cmd route_match_origin_cmd = {
    1703             :         "origin",
    1704             :         route_match_origin,
    1705             :         route_match_origin_compile,
    1706             :         route_match_origin_free
    1707             : };
    1708             : 
    1709             : /* match probability  { */
    1710             : 
    1711             : static enum route_map_cmd_result_t
    1712           0 : route_match_probability(void *rule, const struct prefix *prefix, void *object)
    1713             : {
    1714           0 :         long r = frr_weak_random();
    1715             : 
    1716           0 :         switch (*(long *)rule) {
    1717             :         case 0:
    1718             :                 break;
    1719             :         case RAND_MAX:
    1720             :                 return RMAP_MATCH;
    1721           0 :         default:
    1722           0 :                 if (r < *(long *)rule) {
    1723             :                         return RMAP_MATCH;
    1724             :                 }
    1725             :         }
    1726             : 
    1727             :         return RMAP_NOMATCH;
    1728             : }
    1729             : 
    1730           0 : static void *route_match_probability_compile(const char *arg)
    1731             : {
    1732           0 :         long *lobule;
    1733           0 :         unsigned perc;
    1734             : 
    1735           0 :         perc = atoi(arg);
    1736           0 :         lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long));
    1737             : 
    1738           0 :         switch (perc) {
    1739           0 :         case 0:
    1740           0 :                 *lobule = 0;
    1741           0 :                 break;
    1742           0 :         case 100:
    1743           0 :                 *lobule = RAND_MAX;
    1744           0 :                 break;
    1745           0 :         default:
    1746           0 :                 *lobule = RAND_MAX / 100 * perc;
    1747             :         }
    1748             : 
    1749           0 :         return lobule;
    1750             : }
    1751             : 
    1752           0 : static void route_match_probability_free(void *rule)
    1753             : {
    1754           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1755           0 : }
    1756             : 
    1757             : static const struct route_map_rule_cmd route_match_probability_cmd = {
    1758             :         "probability",
    1759             :         route_match_probability,
    1760             :         route_match_probability_compile,
    1761             :         route_match_probability_free
    1762             : };
    1763             : 
    1764             : /* `match interface IFNAME' */
    1765             : /* Match function should return 1 if match is success else return
    1766             :    zero. */
    1767             : static enum route_map_cmd_result_t
    1768           0 : route_match_interface(void *rule, const struct prefix *prefix, void *object)
    1769             : {
    1770           0 :         struct interface *ifp;
    1771           0 :         struct bgp_path_info *path;
    1772             : 
    1773           0 :         path = object;
    1774             : 
    1775           0 :         if (!path || !path->peer || !path->peer->bgp)
    1776             :                 return RMAP_NOMATCH;
    1777             : 
    1778           0 :         ifp = if_lookup_by_name((char *)rule, path->peer->bgp->vrf_id);
    1779             : 
    1780           0 :         if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
    1781             :                 return RMAP_NOMATCH;
    1782             : 
    1783             :         return RMAP_MATCH;
    1784             : }
    1785             : 
    1786             : /* Route map `interface' match statement.  `arg' should be
    1787             :    interface name. */
    1788           0 : static void *route_match_interface_compile(const char *arg)
    1789             : {
    1790           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1791             : }
    1792             : 
    1793             : /* Free route map's compiled `interface' value. */
    1794           0 : static void route_match_interface_free(void *rule)
    1795             : {
    1796           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1797           0 : }
    1798             : 
    1799             : /* Route map commands for ip address matching. */
    1800             : static const struct route_map_rule_cmd route_match_interface_cmd = {
    1801             :         "interface",
    1802             :         route_match_interface,
    1803             :         route_match_interface_compile,
    1804             :         route_match_interface_free
    1805             : };
    1806             : 
    1807             : /* } */
    1808             : 
    1809             : /* `set ip next-hop IP_ADDRESS' */
    1810             : 
    1811             : /* Match function return 1 if match is success else return zero. */
    1812             : static enum route_map_cmd_result_t
    1813           0 : route_match_tag(void *rule, const struct prefix *prefix, void *object)
    1814             : {
    1815           0 :         route_tag_t *tag;
    1816           0 :         struct bgp_path_info *path;
    1817             : 
    1818           0 :         tag = rule;
    1819           0 :         path = object;
    1820             : 
    1821           0 :         return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
    1822             : }
    1823             : 
    1824             : 
    1825             : /* Route map commands for tag matching. */
    1826             : static const struct route_map_rule_cmd route_match_tag_cmd = {
    1827             :         "tag",
    1828             :         route_match_tag,
    1829             :         route_map_rule_tag_compile,
    1830             :         route_map_rule_tag_free,
    1831             : };
    1832             : 
    1833             : static enum route_map_cmd_result_t
    1834           0 : route_set_srte_color(void *rule, const struct prefix *prefix, void *object)
    1835             : {
    1836           0 :         uint32_t *srte_color = rule;
    1837           0 :         struct bgp_path_info *path;
    1838             : 
    1839           0 :         path = object;
    1840             : 
    1841           0 :         path->attr->srte_color = *srte_color;
    1842           0 :         path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
    1843             : 
    1844           0 :         return RMAP_OKAY;
    1845             : }
    1846             : 
    1847             : /* Route map `sr-te color' compile function */
    1848           0 : static void *route_set_srte_color_compile(const char *arg)
    1849             : {
    1850           0 :         uint32_t *color;
    1851             : 
    1852           0 :         color = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
    1853           0 :         *color = atoi(arg);
    1854             : 
    1855           0 :         return color;
    1856             : }
    1857             : 
    1858             : /* Free route map's compiled `sr-te color' value. */
    1859           0 : static void route_set_srte_color_free(void *rule)
    1860             : {
    1861           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1862           0 : }
    1863             : 
    1864             : /* Route map commands for sr-te color set. */
    1865             : struct route_map_rule_cmd route_set_srte_color_cmd = {
    1866             :         "sr-te color", route_set_srte_color, route_set_srte_color_compile,
    1867             :         route_set_srte_color_free};
    1868             : 
    1869             : /* Set nexthop to object.  object must be pointer to struct attr. */
    1870             : struct rmap_ip_nexthop_set {
    1871             :         struct in_addr *address;
    1872             :         int peer_address;
    1873             :         int unchanged;
    1874             : };
    1875             : 
    1876             : static enum route_map_cmd_result_t
    1877           0 : route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
    1878             : {
    1879           0 :         struct rmap_ip_nexthop_set *rins = rule;
    1880           0 :         struct bgp_path_info *path;
    1881           0 :         struct peer *peer;
    1882             : 
    1883           0 :         if (prefix->family == AF_INET6)
    1884             :                 return RMAP_OKAY;
    1885             : 
    1886           0 :         path = object;
    1887           0 :         peer = path->peer;
    1888             : 
    1889           0 :         if (rins->unchanged) {
    1890           0 :                 SET_FLAG(path->attr->rmap_change_flags,
    1891             :                          BATTR_RMAP_NEXTHOP_UNCHANGED);
    1892           0 :         } else if (rins->peer_address) {
    1893           0 :                 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
    1894             :                      || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
    1895           0 :                     && peer->su_remote
    1896           0 :                     && sockunion_family(peer->su_remote) == AF_INET) {
    1897           0 :                         path->attr->nexthop.s_addr =
    1898           0 :                                 sockunion2ip(peer->su_remote);
    1899           0 :                         path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
    1900           0 :                 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
    1901             :                         /* The next hop value will be set as part of
    1902             :                          * packet rewrite.  Set the flags here to indicate
    1903             :                          * that rewrite needs to be done.
    1904             :                          * Also, clear the value.
    1905             :                          */
    1906           0 :                         SET_FLAG(path->attr->rmap_change_flags,
    1907             :                                  BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
    1908           0 :                         path->attr->nexthop.s_addr = INADDR_ANY;
    1909             :                 }
    1910             :         } else {
    1911             :                 /* Set next hop value. */
    1912           0 :                 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
    1913           0 :                 path->attr->nexthop = *rins->address;
    1914           0 :                 SET_FLAG(path->attr->rmap_change_flags,
    1915             :                          BATTR_RMAP_IPV4_NHOP_CHANGED);
    1916             :                 /* case for MP-BGP : MPLS VPN */
    1917           0 :                 path->attr->mp_nexthop_global_in = *rins->address;
    1918           0 :                 path->attr->mp_nexthop_len = sizeof(*rins->address);
    1919             :         }
    1920             : 
    1921             :         return RMAP_OKAY;
    1922             : }
    1923             : 
    1924             : /* Route map `ip nexthop' compile function.  Given string is converted
    1925             :    to struct in_addr structure. */
    1926           0 : static void *route_set_ip_nexthop_compile(const char *arg)
    1927             : {
    1928           0 :         struct rmap_ip_nexthop_set *rins;
    1929           0 :         struct in_addr *address = NULL;
    1930           0 :         int peer_address = 0;
    1931           0 :         int unchanged = 0;
    1932           0 :         int ret;
    1933             : 
    1934           0 :         if (strcmp(arg, "peer-address") == 0)
    1935             :                 peer_address = 1;
    1936           0 :         else if (strcmp(arg, "unchanged") == 0)
    1937             :                 unchanged = 1;
    1938             :         else {
    1939           0 :                 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
    1940             :                                   sizeof(struct in_addr));
    1941           0 :                 ret = inet_aton(arg, address);
    1942             : 
    1943           0 :                 if (ret == 0) {
    1944           0 :                         XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
    1945           0 :                         return NULL;
    1946             :                 }
    1947             :         }
    1948             : 
    1949           0 :         rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
    1950             :                        sizeof(struct rmap_ip_nexthop_set));
    1951             : 
    1952           0 :         rins->address = address;
    1953           0 :         rins->peer_address = peer_address;
    1954           0 :         rins->unchanged = unchanged;
    1955             : 
    1956           0 :         return rins;
    1957             : }
    1958             : 
    1959             : /* Free route map's compiled `ip nexthop' value. */
    1960           0 : static void route_set_ip_nexthop_free(void *rule)
    1961             : {
    1962           0 :         struct rmap_ip_nexthop_set *rins = rule;
    1963             : 
    1964           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
    1965             : 
    1966           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
    1967           0 : }
    1968             : 
    1969             : /* Route map commands for ip nexthop set. */
    1970             : static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
    1971             :         "ip next-hop",
    1972             :         route_set_ip_nexthop,
    1973             :         route_set_ip_nexthop_compile,
    1974             :         route_set_ip_nexthop_free
    1975             : };
    1976             : 
    1977             : /* `set l3vpn next-hop encapsulation l3vpn gre' */
    1978             : 
    1979             : /* Set nexthop to object */
    1980             : struct rmap_l3vpn_nexthop_encapsulation_set {
    1981             :         uint8_t protocol;
    1982             : };
    1983             : 
    1984             : static enum route_map_cmd_result_t
    1985           0 : route_set_l3vpn_nexthop_encapsulation(void *rule, const struct prefix *prefix,
    1986             :                                       void *object)
    1987             : {
    1988           0 :         struct rmap_l3vpn_nexthop_encapsulation_set *rins = rule;
    1989           0 :         struct bgp_path_info *path;
    1990             : 
    1991           0 :         path = object;
    1992             : 
    1993           0 :         if (rins->protocol != IPPROTO_GRE)
    1994             :                 return RMAP_OKAY;
    1995             : 
    1996           0 :         SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRE);
    1997           0 :         return RMAP_OKAY;
    1998             : }
    1999             : 
    2000             : /* Route map `l3vpn nexthop encapsulation' compile function. */
    2001           0 : static void *route_set_l3vpn_nexthop_encapsulation_compile(const char *arg)
    2002             : {
    2003           0 :         struct rmap_l3vpn_nexthop_encapsulation_set *rins;
    2004             : 
    2005           0 :         rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
    2006             :                        sizeof(struct rmap_l3vpn_nexthop_encapsulation_set));
    2007             : 
    2008             :         /* XXX ALL GRE modes are accepted for now: gre or ip6gre */
    2009           0 :         rins->protocol = IPPROTO_GRE;
    2010             : 
    2011           0 :         return rins;
    2012             : }
    2013             : 
    2014             : /* Free route map's compiled `ip nexthop' value. */
    2015           0 : static void route_set_l3vpn_nexthop_encapsulation_free(void *rule)
    2016             : {
    2017           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    2018           0 : }
    2019             : 
    2020             : /* Route map commands for l3vpn next-hop encapsulation set. */
    2021             : static const struct route_map_rule_cmd
    2022             :         route_set_l3vpn_nexthop_encapsulation_cmd = {
    2023             :                 "l3vpn next-hop encapsulation",
    2024             :                 route_set_l3vpn_nexthop_encapsulation,
    2025             :                 route_set_l3vpn_nexthop_encapsulation_compile,
    2026             :                 route_set_l3vpn_nexthop_encapsulation_free};
    2027             : 
    2028             : /* `set local-preference LOCAL_PREF' */
    2029             : 
    2030             : /* Set local preference. */
    2031             : static enum route_map_cmd_result_t
    2032           0 : route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
    2033             : {
    2034           0 :         struct rmap_value *rv;
    2035           0 :         struct bgp_path_info *path;
    2036           0 :         uint32_t locpref = 0;
    2037             : 
    2038             :         /* Fetch routemap's rule information. */
    2039           0 :         rv = rule;
    2040           0 :         path = object;
    2041             : 
    2042             :         /* Set local preference value. */
    2043           0 :         if (path->attr->local_pref)
    2044             :                 locpref = path->attr->local_pref;
    2045             : 
    2046           0 :         path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
    2047           0 :         path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
    2048             : 
    2049           0 :         return RMAP_OKAY;
    2050             : }
    2051             : 
    2052             : /* Set local preference rule structure. */
    2053             : static const struct route_map_rule_cmd route_set_local_pref_cmd = {
    2054             :         "local-preference",
    2055             :         route_set_local_pref,
    2056             :         route_value_compile,
    2057             :         route_value_free,
    2058             : };
    2059             : 
    2060             : /* `set weight WEIGHT' */
    2061             : 
    2062             : /* Set weight. */
    2063             : static enum route_map_cmd_result_t
    2064           0 : route_set_weight(void *rule, const struct prefix *prefix, void *object)
    2065             : {
    2066           0 :         struct rmap_value *rv;
    2067           0 :         struct bgp_path_info *path;
    2068             : 
    2069             :         /* Fetch routemap's rule information. */
    2070           0 :         rv = rule;
    2071           0 :         path = object;
    2072             : 
    2073             :         /* Set weight value. */
    2074           0 :         path->attr->weight = route_value_adjust(rv, 0, path->peer);
    2075             : 
    2076           0 :         return RMAP_OKAY;
    2077             : }
    2078             : 
    2079             : /* Set local preference rule structure. */
    2080             : static const struct route_map_rule_cmd route_set_weight_cmd = {
    2081             :         "weight",
    2082             :         route_set_weight,
    2083             :         route_value_compile,
    2084             :         route_value_free,
    2085             : };
    2086             : 
    2087             : /* `set distance DISTANCE */
    2088             : static enum route_map_cmd_result_t
    2089           0 : route_set_distance(void *rule, const struct prefix *prefix, void *object)
    2090             : {
    2091           0 :         struct bgp_path_info *path = object;
    2092           0 :         struct rmap_value *rv = rule;
    2093             : 
    2094           0 :         path->attr->distance = rv->value;
    2095             : 
    2096           0 :         return RMAP_OKAY;
    2097             : }
    2098             : 
    2099             : /* set distance rule structure */
    2100             : static const struct route_map_rule_cmd route_set_distance_cmd = {
    2101             :         "distance",
    2102             :         route_set_distance,
    2103             :         route_value_compile,
    2104             :         route_value_free,
    2105             : };
    2106             : 
    2107             : /* `set metric METRIC' */
    2108             : 
    2109             : /* Set metric to attribute. */
    2110             : static enum route_map_cmd_result_t
    2111           0 : route_set_metric(void *rule, const struct prefix *prefix, void *object)
    2112             : {
    2113           0 :         struct rmap_value *rv;
    2114           0 :         struct bgp_path_info *path;
    2115           0 :         uint32_t med = 0;
    2116             : 
    2117             :         /* Fetch routemap's rule information. */
    2118           0 :         rv = rule;
    2119           0 :         path = object;
    2120             : 
    2121           0 :         if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
    2122           0 :                 med = path->attr->med;
    2123             : 
    2124           0 :         path->attr->med = route_value_adjust(rv, med, path->peer);
    2125           0 :         path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
    2126             : 
    2127           0 :         return RMAP_OKAY;
    2128             : }
    2129             : 
    2130             : /* Set metric rule structure. */
    2131             : static const struct route_map_rule_cmd route_set_metric_cmd = {
    2132             :         "metric",
    2133             :         route_set_metric,
    2134             :         route_value_compile,
    2135             :         route_value_free,
    2136             : };
    2137             : 
    2138             : /* `set table (1-4294967295)' */
    2139             : 
    2140             : static enum route_map_cmd_result_t
    2141           0 : route_set_table_id(void *rule, const struct prefix *prefix,
    2142             : 
    2143             :                    void *object)
    2144             : {
    2145           0 :         struct rmap_value *rv;
    2146           0 :         struct bgp_path_info *path;
    2147             : 
    2148             :         /* Fetch routemap's rule information. */
    2149           0 :         rv = rule;
    2150           0 :         path = object;
    2151             : 
    2152           0 :         path->attr->rmap_table_id = rv->value;
    2153             : 
    2154           0 :         return RMAP_OKAY;
    2155             : }
    2156             : 
    2157             : /* Set table_id rule structure. */
    2158             : static const struct route_map_rule_cmd route_set_table_id_cmd = {
    2159             :         "table",
    2160             :         route_set_table_id,
    2161             :         route_value_compile,
    2162             :         route_value_free
    2163             : };
    2164             : 
    2165             : /* `set as-path prepend ASPATH' */
    2166             : 
    2167             : /* For AS path prepend mechanism. */
    2168             : static enum route_map_cmd_result_t
    2169           0 : route_set_aspath_prepend(void *rule, const struct prefix *prefix, void *object)
    2170             : {
    2171           0 :         struct aspath *aspath;
    2172           0 :         struct aspath *new;
    2173           0 :         struct bgp_path_info *path;
    2174             : 
    2175           0 :         path = object;
    2176             : 
    2177           0 :         if (path->attr->aspath->refcnt)
    2178           0 :                 new = aspath_dup(path->attr->aspath);
    2179             :         else
    2180             :                 new = path->attr->aspath;
    2181             : 
    2182           0 :         if ((uintptr_t)rule > 10) {
    2183           0 :                 aspath = rule;
    2184           0 :                 aspath_prepend(aspath, new);
    2185             :         } else {
    2186           0 :                 as_t as = aspath_leftmost(new);
    2187           0 :                 if (as)
    2188           0 :                         new = aspath_add_seq_n(new, as, (uintptr_t)rule);
    2189             :         }
    2190             : 
    2191           0 :         path->attr->aspath = new;
    2192             : 
    2193           0 :         return RMAP_OKAY;
    2194             : }
    2195             : 
    2196           0 : static void *route_set_aspath_prepend_compile(const char *arg)
    2197             : {
    2198           0 :         unsigned int num;
    2199             : 
    2200           0 :         if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
    2201           0 :                 return (void *)(uintptr_t)num;
    2202             : 
    2203           0 :         return route_aspath_compile(arg);
    2204             : }
    2205             : 
    2206           0 : static void route_set_aspath_prepend_free(void *rule)
    2207             : {
    2208           0 :         if ((uintptr_t)rule > 10)
    2209           0 :                 route_aspath_free(rule);
    2210           0 : }
    2211             : 
    2212             : 
    2213             : /* Set as-path prepend rule structure. */
    2214             : static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
    2215             :         "as-path prepend",
    2216             :         route_set_aspath_prepend,
    2217             :         route_set_aspath_prepend_compile,
    2218             :         route_set_aspath_prepend_free,
    2219             : };
    2220             : 
    2221             : /* `set as-path exclude ASn' */
    2222             : 
    2223             : /* For ASN exclude mechanism.
    2224             :  * Iterate over ASns requested and filter them from the given AS_PATH one by
    2225             :  * one.
    2226             :  * Make a deep copy of existing AS_PATH, but for the first ASn only.
    2227             :  */
    2228             : static enum route_map_cmd_result_t
    2229           0 : route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
    2230             : {
    2231           0 :         struct aspath *new_path, *exclude_path;
    2232           0 :         struct bgp_path_info *path;
    2233             : 
    2234           0 :         exclude_path = rule;
    2235           0 :         path = object;
    2236           0 :         if (path->attr->aspath->refcnt)
    2237           0 :                 new_path = aspath_dup(path->attr->aspath);
    2238             :         else
    2239             :                 new_path = path->attr->aspath;
    2240           0 :         path->attr->aspath = aspath_filter_exclude(new_path, exclude_path);
    2241             : 
    2242           0 :         return RMAP_OKAY;
    2243             : }
    2244             : 
    2245             : /* Set ASn exlude rule structure. */
    2246             : static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
    2247             :         "as-path exclude",
    2248             :         route_set_aspath_exclude,
    2249             :         route_aspath_compile,
    2250             :         route_aspath_free,
    2251             : };
    2252             : 
    2253             : /* `set as-path replace AS-PATH` */
    2254           2 : static void *route_aspath_replace_compile(const char *arg)
    2255             : {
    2256           2 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    2257             : }
    2258             : 
    2259           2 : static void route_aspath_replace_free(void *rule)
    2260             : {
    2261           2 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    2262           2 : }
    2263             : 
    2264             : static enum route_map_cmd_result_t
    2265           4 : route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
    2266             : {
    2267           4 :         struct aspath *aspath_new;
    2268           4 :         const char *replace = rule;
    2269           4 :         struct bgp_path_info *path = object;
    2270           8 :         as_t own_asn = path->peer->change_local_as ? path->peer->change_local_as
    2271           4 :                                                    : path->peer->local_as;
    2272             : 
    2273           4 :         if (path->peer->sort != BGP_PEER_EBGP) {
    2274           0 :                 zlog_warn(
    2275             :                         "`set as-path replace` is supported only for EBGP peers");
    2276           0 :                 return RMAP_NOOP;
    2277             :         }
    2278             : 
    2279           4 :         if (path->attr->aspath->refcnt)
    2280           4 :                 aspath_new = aspath_dup(path->attr->aspath);
    2281             :         else
    2282             :                 aspath_new = path->attr->aspath;
    2283             : 
    2284           4 :         if (strmatch(replace, "any")) {
    2285           3 :                 path->attr->aspath =
    2286           3 :                         aspath_replace_all_asn(aspath_new, own_asn);
    2287             :         } else {
    2288           1 :                 as_t replace_asn = strtoul(replace, NULL, 10);
    2289             : 
    2290           1 :                 path->attr->aspath = aspath_replace_specific_asn(
    2291             :                         aspath_new, replace_asn, own_asn);
    2292             :         }
    2293             : 
    2294           4 :         aspath_free(aspath_new);
    2295             : 
    2296           4 :         return RMAP_OKAY;
    2297             : }
    2298             : 
    2299             : static const struct route_map_rule_cmd route_set_aspath_replace_cmd = {
    2300             :         "as-path replace",
    2301             :         route_set_aspath_replace,
    2302             :         route_aspath_replace_compile,
    2303             :         route_aspath_replace_free,
    2304             : };
    2305             : 
    2306             : /* `set community COMMUNITY' */
    2307             : struct rmap_com_set {
    2308             :         struct community *com;
    2309             :         int additive;
    2310             :         int none;
    2311             : };
    2312             : 
    2313             : /* For community set mechanism. */
    2314             : static enum route_map_cmd_result_t
    2315           0 : route_set_community(void *rule, const struct prefix *prefix, void *object)
    2316             : {
    2317           0 :         struct rmap_com_set *rcs;
    2318           0 :         struct bgp_path_info *path;
    2319           0 :         struct attr *attr;
    2320           0 :         struct community *new = NULL;
    2321           0 :         struct community *old;
    2322           0 :         struct community *merge;
    2323             : 
    2324           0 :         rcs = rule;
    2325           0 :         path = object;
    2326           0 :         attr = path->attr;
    2327           0 :         old = bgp_attr_get_community(attr);
    2328             : 
    2329             :         /* "none" case.  */
    2330           0 :         if (rcs->none) {
    2331           0 :                 bgp_attr_set_community(attr, NULL);
    2332             :                 /* See the longer comment down below. */
    2333           0 :                 if (old && old->refcnt == 0)
    2334           0 :                         community_free(&old);
    2335           0 :                 return RMAP_OKAY;
    2336             :         }
    2337             : 
    2338             :         /* "additive" case.  */
    2339           0 :         if (rcs->additive && old) {
    2340           0 :                 merge = community_merge(community_dup(old), rcs->com);
    2341             : 
    2342           0 :                 new = community_uniq_sort(merge);
    2343           0 :                 community_free(&merge);
    2344             :         } else
    2345           0 :                 new = community_dup(rcs->com);
    2346             : 
    2347             :         /* HACK: if the old community is not intern'd,
    2348             :          * we should free it here, or all reference to it may be
    2349             :          * lost.
    2350             :          * Really need to cleanup attribute caching sometime.
    2351             :          */
    2352           0 :         if (old && old->refcnt == 0)
    2353           0 :                 community_free(&old);
    2354             : 
    2355             :         /* will be interned by caller if required */
    2356           0 :         bgp_attr_set_community(attr, new);
    2357             : 
    2358             :         return RMAP_OKAY;
    2359             : }
    2360             : 
    2361             : /* Compile function for set community. */
    2362           0 : static void *route_set_community_compile(const char *arg)
    2363             : {
    2364           0 :         struct rmap_com_set *rcs;
    2365           0 :         struct community *com = NULL;
    2366           0 :         char *sp;
    2367           0 :         int additive = 0;
    2368           0 :         int none = 0;
    2369             : 
    2370           0 :         if (strcmp(arg, "none") == 0)
    2371             :                 none = 1;
    2372             :         else {
    2373           0 :                 sp = strstr(arg, "additive");
    2374             : 
    2375           0 :                 if (sp && sp > arg) {
    2376             :                         /* "additive" keyword is included.  */
    2377           0 :                         additive = 1;
    2378           0 :                         *(sp - 1) = '\0';
    2379             :                 }
    2380             : 
    2381           0 :                 com = community_str2com(arg);
    2382             : 
    2383           0 :                 if (additive)
    2384           0 :                         *(sp - 1) = ' ';
    2385             : 
    2386           0 :                 if (!com)
    2387             :                         return NULL;
    2388             :         }
    2389             : 
    2390           0 :         rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
    2391           0 :         rcs->com = com;
    2392           0 :         rcs->additive = additive;
    2393           0 :         rcs->none = none;
    2394             : 
    2395           0 :         return rcs;
    2396             : }
    2397             : 
    2398             : /* Free function for set community. */
    2399           0 : static void route_set_community_free(void *rule)
    2400             : {
    2401           0 :         struct rmap_com_set *rcs = rule;
    2402             : 
    2403           0 :         if (rcs->com)
    2404           0 :                 community_free(&rcs->com);
    2405           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
    2406           0 : }
    2407             : 
    2408             : /* Set community rule structure. */
    2409             : static const struct route_map_rule_cmd route_set_community_cmd = {
    2410             :         "community",
    2411             :         route_set_community,
    2412             :         route_set_community_compile,
    2413             :         route_set_community_free,
    2414             : };
    2415             : 
    2416             : /* `set community COMMUNITY' */
    2417             : struct rmap_lcom_set {
    2418             :         struct lcommunity *lcom;
    2419             :         int additive;
    2420             :         int none;
    2421             : };
    2422             : 
    2423             : 
    2424             : /* For lcommunity set mechanism. */
    2425             : static enum route_map_cmd_result_t
    2426           0 : route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
    2427             : {
    2428           0 :         struct rmap_lcom_set *rcs;
    2429           0 :         struct bgp_path_info *path;
    2430           0 :         struct attr *attr;
    2431           0 :         struct lcommunity *new = NULL;
    2432           0 :         struct lcommunity *old;
    2433           0 :         struct lcommunity *merge;
    2434             : 
    2435           0 :         rcs = rule;
    2436           0 :         path = object;
    2437           0 :         attr = path->attr;
    2438           0 :         old = bgp_attr_get_lcommunity(attr);
    2439             : 
    2440             :         /* "none" case.  */
    2441           0 :         if (rcs->none) {
    2442           0 :                 bgp_attr_set_lcommunity(attr, NULL);
    2443             : 
    2444             :                 /* See the longer comment down below. */
    2445           0 :                 if (old && old->refcnt == 0)
    2446           0 :                         lcommunity_free(&old);
    2447           0 :                 return RMAP_OKAY;
    2448             :         }
    2449             : 
    2450           0 :         if (rcs->additive && old) {
    2451           0 :                 merge = lcommunity_merge(lcommunity_dup(old), rcs->lcom);
    2452             : 
    2453           0 :                 new = lcommunity_uniq_sort(merge);
    2454           0 :                 lcommunity_free(&merge);
    2455             :         } else
    2456           0 :                 new = lcommunity_dup(rcs->lcom);
    2457             : 
    2458             :         /* HACK: if the old large-community is not intern'd,
    2459             :          * we should free it here, or all reference to it may be
    2460             :          * lost.
    2461             :          * Really need to cleanup attribute caching sometime.
    2462             :          */
    2463           0 :         if (old && old->refcnt == 0)
    2464           0 :                 lcommunity_free(&old);
    2465             : 
    2466             :         /* will be intern()'d or attr_flush()'d by bgp_update_main() */
    2467           0 :         bgp_attr_set_lcommunity(attr, new);
    2468             : 
    2469             :         return RMAP_OKAY;
    2470             : }
    2471             : 
    2472             : /* Compile function for set community. */
    2473           0 : static void *route_set_lcommunity_compile(const char *arg)
    2474             : {
    2475           0 :         struct rmap_lcom_set *rcs;
    2476           0 :         struct lcommunity *lcom = NULL;
    2477           0 :         char *sp;
    2478           0 :         int additive = 0;
    2479           0 :         int none = 0;
    2480             : 
    2481           0 :         if (strcmp(arg, "none") == 0)
    2482             :                 none = 1;
    2483             :         else {
    2484           0 :                 sp = strstr(arg, "additive");
    2485             : 
    2486           0 :                 if (sp && sp > arg) {
    2487             :                         /* "additive" keyworkd is included.  */
    2488           0 :                         additive = 1;
    2489           0 :                         *(sp - 1) = '\0';
    2490             :                 }
    2491             : 
    2492           0 :                 lcom = lcommunity_str2com(arg);
    2493             : 
    2494           0 :                 if (additive)
    2495           0 :                         *(sp - 1) = ' ';
    2496             : 
    2497           0 :                 if (!lcom)
    2498             :                         return NULL;
    2499             :         }
    2500             : 
    2501           0 :         rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
    2502           0 :         rcs->lcom = lcom;
    2503           0 :         rcs->additive = additive;
    2504           0 :         rcs->none = none;
    2505             : 
    2506           0 :         return rcs;
    2507             : }
    2508             : 
    2509             : /* Free function for set lcommunity. */
    2510           0 : static void route_set_lcommunity_free(void *rule)
    2511             : {
    2512           0 :         struct rmap_lcom_set *rcs = rule;
    2513             : 
    2514           0 :         if (rcs->lcom) {
    2515           0 :                 lcommunity_free(&rcs->lcom);
    2516             :         }
    2517           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
    2518           0 : }
    2519             : 
    2520             : /* Set community rule structure. */
    2521             : static const struct route_map_rule_cmd route_set_lcommunity_cmd = {
    2522             :         "large-community",
    2523             :         route_set_lcommunity,
    2524             :         route_set_lcommunity_compile,
    2525             :         route_set_lcommunity_free,
    2526             : };
    2527             : 
    2528             : /* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
    2529             : 
    2530             : /* For large community set mechanism. */
    2531             : static enum route_map_cmd_result_t
    2532           0 : route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object)
    2533             : {
    2534           0 :         struct community_list *list;
    2535           0 :         struct lcommunity *merge;
    2536           0 :         struct lcommunity *new;
    2537           0 :         struct lcommunity *old;
    2538           0 :         struct bgp_path_info *path;
    2539           0 :         struct rmap_community *rcom = rule;
    2540             : 
    2541           0 :         if (!rcom)
    2542             :                 return RMAP_OKAY;
    2543             : 
    2544           0 :         path = object;
    2545           0 :         list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
    2546             :                                      LARGE_COMMUNITY_LIST_MASTER);
    2547           0 :         old = bgp_attr_get_lcommunity(path->attr);
    2548             : 
    2549           0 :         if (list && old) {
    2550           0 :                 merge = lcommunity_list_match_delete(lcommunity_dup(old), list);
    2551           0 :                 new = lcommunity_uniq_sort(merge);
    2552           0 :                 lcommunity_free(&merge);
    2553             : 
    2554             :                 /* HACK: if the old community is not intern'd,
    2555             :                  * we should free it here, or all reference to it may be
    2556             :                  * lost.
    2557             :                  * Really need to cleanup attribute caching sometime.
    2558             :                  */
    2559           0 :                 if (old->refcnt == 0)
    2560           0 :                         lcommunity_free(&old);
    2561             : 
    2562           0 :                 if (new->size == 0) {
    2563           0 :                         bgp_attr_set_lcommunity(path->attr, NULL);
    2564           0 :                         lcommunity_free(&new);
    2565             :                 } else {
    2566           0 :                         bgp_attr_set_lcommunity(path->attr, new);
    2567             :                 }
    2568             :         }
    2569             : 
    2570             :         return RMAP_OKAY;
    2571             : }
    2572             : 
    2573             : /* Compile function for set lcommunity. */
    2574           0 : static void *route_set_lcommunity_delete_compile(const char *arg)
    2575             : {
    2576           0 :         struct rmap_community *rcom;
    2577           0 :         char **splits;
    2578           0 :         int num;
    2579             : 
    2580           0 :         frrstr_split(arg, " ", &splits, &num);
    2581             : 
    2582           0 :         rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
    2583           0 :         rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
    2584           0 :         rcom->name_hash = bgp_clist_hash_key(rcom->name);
    2585             : 
    2586           0 :         for (int i = 0; i < num; i++)
    2587           0 :                 XFREE(MTYPE_TMP, splits[i]);
    2588           0 :         XFREE(MTYPE_TMP, splits);
    2589             : 
    2590           0 :         return rcom;
    2591             : }
    2592             : 
    2593             : /* Free function for set lcommunity. */
    2594           0 : static void route_set_lcommunity_delete_free(void *rule)
    2595             : {
    2596           0 :         struct rmap_community *rcom = rule;
    2597             : 
    2598           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
    2599           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
    2600           0 : }
    2601             : 
    2602             : /* Set lcommunity rule structure. */
    2603             : static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
    2604             :         "large-comm-list",
    2605             :         route_set_lcommunity_delete,
    2606             :         route_set_lcommunity_delete_compile,
    2607             :         route_set_lcommunity_delete_free,
    2608             : };
    2609             : 
    2610             : 
    2611             : /* `set comm-list (<1-99>|<100-500>|WORD) delete' */
    2612             : 
    2613             : /* For community set mechanism. */
    2614             : static enum route_map_cmd_result_t
    2615           0 : route_set_community_delete(void *rule, const struct prefix *prefix,
    2616             :                            void *object)
    2617             : {
    2618           0 :         struct community_list *list;
    2619           0 :         struct community *merge;
    2620           0 :         struct community *new;
    2621           0 :         struct community *old;
    2622           0 :         struct bgp_path_info *path;
    2623           0 :         struct rmap_community *rcom = rule;
    2624             : 
    2625           0 :         if (!rcom)
    2626             :                 return RMAP_OKAY;
    2627             : 
    2628           0 :         path = object;
    2629           0 :         list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
    2630             :                                      COMMUNITY_LIST_MASTER);
    2631           0 :         old = bgp_attr_get_community(path->attr);
    2632             : 
    2633           0 :         if (list && old) {
    2634           0 :                 merge = community_list_match_delete(community_dup(old), list);
    2635           0 :                 new = community_uniq_sort(merge);
    2636           0 :                 community_free(&merge);
    2637             : 
    2638             :                 /* HACK: if the old community is not intern'd,
    2639             :                  * we should free it here, or all reference to it may be
    2640             :                  * lost.
    2641             :                  * Really need to cleanup attribute caching sometime.
    2642             :                  */
    2643           0 :                 if (old->refcnt == 0)
    2644           0 :                         community_free(&old);
    2645             : 
    2646           0 :                 if (new->size == 0) {
    2647           0 :                         bgp_attr_set_community(path->attr, NULL);
    2648           0 :                         community_free(&new);
    2649             :                 } else {
    2650           0 :                         bgp_attr_set_community(path->attr, new);
    2651             :                 }
    2652             :         }
    2653             : 
    2654             :         return RMAP_OKAY;
    2655             : }
    2656             : 
    2657             : /* Compile function for set community. */
    2658           0 : static void *route_set_community_delete_compile(const char *arg)
    2659             : {
    2660           0 :         struct rmap_community *rcom;
    2661           0 :         char **splits;
    2662           0 :         int num;
    2663             : 
    2664           0 :         frrstr_split(arg, " ", &splits, &num);
    2665             : 
    2666           0 :         rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
    2667           0 :         rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
    2668           0 :         rcom->name_hash = bgp_clist_hash_key(rcom->name);
    2669             : 
    2670           0 :         for (int i = 0; i < num; i++)
    2671           0 :                 XFREE(MTYPE_TMP, splits[i]);
    2672           0 :         XFREE(MTYPE_TMP, splits);
    2673             : 
    2674           0 :         return rcom;
    2675             : }
    2676             : 
    2677             : /* Free function for set community. */
    2678           0 : static void route_set_community_delete_free(void *rule)
    2679             : {
    2680           0 :         struct rmap_community *rcom = rule;
    2681             : 
    2682           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
    2683           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
    2684           0 : }
    2685             : 
    2686             : /* Set community rule structure. */
    2687             : static const struct route_map_rule_cmd route_set_community_delete_cmd = {
    2688             :         "comm-list",
    2689             :         route_set_community_delete,
    2690             :         route_set_community_delete_compile,
    2691             :         route_set_community_delete_free,
    2692             : };
    2693             : 
    2694             : /* `set extcommunity rt COMMUNITY' */
    2695             : 
    2696             : struct rmap_ecom_set {
    2697             :         struct ecommunity *ecom;
    2698             :         bool none;
    2699             : };
    2700             : 
    2701             : /* For community set mechanism.  Used by _rt and _soo. */
    2702             : static enum route_map_cmd_result_t
    2703           0 : route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
    2704             : {
    2705           0 :         struct rmap_ecom_set *rcs;
    2706           0 :         struct ecommunity *new_ecom;
    2707           0 :         struct ecommunity *old_ecom;
    2708           0 :         struct bgp_path_info *path;
    2709           0 :         struct attr *attr;
    2710             : 
    2711           0 :         rcs = rule;
    2712           0 :         path = object;
    2713           0 :         attr = path->attr;
    2714             : 
    2715           0 :         if (rcs->none) {
    2716           0 :                 bgp_attr_set_ecommunity(attr, NULL);
    2717           0 :                 return RMAP_OKAY;
    2718             :         }
    2719             : 
    2720           0 :         if (!rcs->ecom)
    2721             :                 return RMAP_OKAY;
    2722             : 
    2723             :         /* We assume additive for Extended Community. */
    2724           0 :         old_ecom = bgp_attr_get_ecommunity(path->attr);
    2725             : 
    2726           0 :         if (old_ecom) {
    2727           0 :                 new_ecom =
    2728           0 :                         ecommunity_merge(ecommunity_dup(old_ecom), rcs->ecom);
    2729             : 
    2730             :                 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
    2731             :                  * bgp_update_receive()
    2732             :                  *         ->refcnt = 0 => set by a previous route-map
    2733             :                  * statement */
    2734           0 :                 if (!old_ecom->refcnt)
    2735           0 :                         ecommunity_free(&old_ecom);
    2736             :         } else
    2737           0 :                 new_ecom = ecommunity_dup(rcs->ecom);
    2738             : 
    2739             :         /* will be intern()'d or attr_flush()'d by bgp_update_main() */
    2740           0 :         bgp_attr_set_ecommunity(path->attr, new_ecom);
    2741             : 
    2742             :         return RMAP_OKAY;
    2743             : }
    2744             : 
    2745           0 : static void *route_set_ecommunity_none_compile(const char *arg)
    2746             : {
    2747           0 :         struct rmap_ecom_set *rcs;
    2748           0 :         bool none = false;
    2749             : 
    2750           0 :         if (strncmp(arg, "none", 4) == 0)
    2751           0 :                 none = true;
    2752             : 
    2753           0 :         rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
    2754           0 :         rcs->ecom = NULL;
    2755           0 :         rcs->none = none;
    2756             : 
    2757           0 :         return rcs;
    2758             : }
    2759             : 
    2760           0 : static void *route_set_ecommunity_rt_compile(const char *arg)
    2761             : {
    2762           0 :         struct rmap_ecom_set *rcs;
    2763           0 :         struct ecommunity *ecom;
    2764             : 
    2765           0 :         ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
    2766           0 :         if (!ecom)
    2767             :                 return NULL;
    2768             : 
    2769           0 :         rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
    2770           0 :         rcs->ecom = ecommunity_intern(ecom);
    2771           0 :         rcs->none = false;
    2772             : 
    2773           0 :         return rcs;
    2774             : }
    2775             : 
    2776             : /* Free function for set community.  Used by _rt and _soo */
    2777           0 : static void route_set_ecommunity_free(void *rule)
    2778             : {
    2779           0 :         struct rmap_ecom_set *rcs = rule;
    2780             : 
    2781           0 :         if (rcs->ecom)
    2782           0 :                 ecommunity_unintern(&rcs->ecom);
    2783             : 
    2784           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
    2785           0 : }
    2786             : 
    2787             : static const struct route_map_rule_cmd route_set_ecommunity_none_cmd = {
    2788             :         "extcommunity",
    2789             :         route_set_ecommunity,
    2790             :         route_set_ecommunity_none_compile,
    2791             :         route_set_ecommunity_free,
    2792             : };
    2793             : 
    2794             : /* Set community rule structure. */
    2795             : static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
    2796             :         "extcommunity rt",
    2797             :         route_set_ecommunity,
    2798             :         route_set_ecommunity_rt_compile,
    2799             :         route_set_ecommunity_free,
    2800             : };
    2801             : 
    2802             : /* `set extcommunity soo COMMUNITY' */
    2803             : 
    2804             : /* Compile function for set community. */
    2805           0 : static void *route_set_ecommunity_soo_compile(const char *arg)
    2806             : {
    2807           0 :         struct rmap_ecom_set *rcs;
    2808           0 :         struct ecommunity *ecom;
    2809             : 
    2810           0 :         ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
    2811           0 :         if (!ecom)
    2812             :                 return NULL;
    2813             : 
    2814           0 :         rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
    2815           0 :         rcs->ecom = ecommunity_intern(ecom);
    2816           0 :         rcs->none = false;
    2817             : 
    2818           0 :         return rcs;
    2819             : }
    2820             : 
    2821             : /* Set community rule structure. */
    2822             : static const struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
    2823             :         "extcommunity soo",
    2824             :         route_set_ecommunity,
    2825             :         route_set_ecommunity_soo_compile,
    2826             :         route_set_ecommunity_free,
    2827             : };
    2828             : 
    2829             : /* `set extcommunity bandwidth' */
    2830             : 
    2831             : struct rmap_ecomm_lb_set {
    2832             :         uint8_t lb_type;
    2833             : #define RMAP_ECOMM_LB_SET_VALUE 1
    2834             : #define RMAP_ECOMM_LB_SET_CUMUL 2
    2835             : #define RMAP_ECOMM_LB_SET_NUM_MPATH 3
    2836             :         bool non_trans;
    2837             :         uint32_t bw;
    2838             : };
    2839             : 
    2840             : static enum route_map_cmd_result_t
    2841           0 : route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
    2842             : {
    2843           0 :         struct rmap_ecomm_lb_set *rels = rule;
    2844           0 :         struct bgp_path_info *path;
    2845           0 :         struct peer *peer;
    2846           0 :         struct ecommunity ecom_lb = {0};
    2847           0 :         struct ecommunity_val lb_eval;
    2848           0 :         uint32_t bw_bytes = 0;
    2849           0 :         uint16_t mpath_count = 0;
    2850           0 :         struct ecommunity *new_ecom;
    2851           0 :         struct ecommunity *old_ecom;
    2852           0 :         as_t as;
    2853             : 
    2854           0 :         path = object;
    2855           0 :         peer = path->peer;
    2856           0 :         if (!peer || !peer->bgp)
    2857             :                 return RMAP_ERROR;
    2858             : 
    2859             :         /* Build link bandwidth extended community */
    2860           0 :         as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
    2861           0 :         if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
    2862           0 :                 bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
    2863           0 :         } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
    2864             :                 /* process this only for the best path. */
    2865           0 :                 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
    2866             :                         return RMAP_OKAY;
    2867             : 
    2868           0 :                 bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
    2869           0 :                 if (!bw_bytes)
    2870             :                         return RMAP_OKAY;
    2871             : 
    2872           0 :         } else if (rels->lb_type == RMAP_ECOMM_LB_SET_NUM_MPATH) {
    2873             : 
    2874             :                 /* process this only for the best path. */
    2875           0 :                 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
    2876             :                         return RMAP_OKAY;
    2877             : 
    2878           0 :                 bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
    2879           0 :                 mpath_count = bgp_path_info_mpath_count(path) + 1;
    2880           0 :                 bw_bytes *= mpath_count;
    2881             :         }
    2882             : 
    2883           0 :         encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
    2884           0 :                           CHECK_FLAG(peer->flags,
    2885             :                                      PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
    2886             : 
    2887             :         /* add to route or merge with existing */
    2888           0 :         old_ecom = bgp_attr_get_ecommunity(path->attr);
    2889           0 :         if (old_ecom) {
    2890           0 :                 new_ecom = ecommunity_dup(old_ecom);
    2891           0 :                 ecommunity_add_val(new_ecom, &lb_eval, true, true);
    2892           0 :                 if (!old_ecom->refcnt)
    2893           0 :                         ecommunity_free(&old_ecom);
    2894             :         } else {
    2895           0 :                 ecom_lb.size = 1;
    2896           0 :                 ecom_lb.unit_size = ECOMMUNITY_SIZE;
    2897           0 :                 ecom_lb.val = (uint8_t *)lb_eval.val;
    2898           0 :                 new_ecom = ecommunity_dup(&ecom_lb);
    2899             :         }
    2900             : 
    2901             :         /* new_ecom will be intern()'d or attr_flush()'d in call stack */
    2902           0 :         bgp_attr_set_ecommunity(path->attr, new_ecom);
    2903             : 
    2904             :         /* Mark that route-map has set link bandwidth; used in attribute
    2905             :          * setting decisions.
    2906             :          */
    2907           0 :         SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET);
    2908             : 
    2909           0 :         return RMAP_OKAY;
    2910             : }
    2911             : 
    2912           0 : static void *route_set_ecommunity_lb_compile(const char *arg)
    2913             : {
    2914           0 :         struct rmap_ecomm_lb_set *rels;
    2915           0 :         uint8_t lb_type;
    2916           0 :         uint32_t bw = 0;
    2917           0 :         char bw_str[40] = {0};
    2918           0 :         char *p, *str;
    2919           0 :         bool non_trans = false;
    2920             : 
    2921           0 :         str = (char *)arg;
    2922           0 :         p = strchr(arg, ' ');
    2923           0 :         if (p) {
    2924           0 :                 int len;
    2925             : 
    2926           0 :                 len = p - arg;
    2927           0 :                 memcpy(bw_str, arg, len);
    2928           0 :                 non_trans = true;
    2929           0 :                 str = bw_str;
    2930             :         }
    2931             : 
    2932           0 :         if (strcmp(str, "cumulative") == 0)
    2933             :                 lb_type = RMAP_ECOMM_LB_SET_CUMUL;
    2934           0 :         else if (strcmp(str, "num-multipaths") == 0)
    2935             :                 lb_type = RMAP_ECOMM_LB_SET_NUM_MPATH;
    2936             :         else {
    2937           0 :                 char *end = NULL;
    2938             : 
    2939           0 :                 bw = strtoul(str, &end, 10);
    2940           0 :                 if (*end != '\0')
    2941           0 :                         return NULL;
    2942           0 :                 lb_type = RMAP_ECOMM_LB_SET_VALUE;
    2943             :         }
    2944             : 
    2945           0 :         rels = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
    2946             :                        sizeof(struct rmap_ecomm_lb_set));
    2947           0 :         rels->lb_type = lb_type;
    2948           0 :         rels->bw = bw;
    2949           0 :         rels->non_trans = non_trans;
    2950             : 
    2951           0 :         return rels;
    2952             : }
    2953             : 
    2954           0 : static void route_set_ecommunity_lb_free(void *rule)
    2955             : {
    2956           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    2957           0 : }
    2958             : 
    2959             : /* Set community rule structure. */
    2960             : struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
    2961             :         "extcommunity bandwidth",
    2962             :         route_set_ecommunity_lb,
    2963             :         route_set_ecommunity_lb_compile,
    2964             :         route_set_ecommunity_lb_free,
    2965             : };
    2966             : 
    2967             : /* `set origin ORIGIN' */
    2968             : 
    2969             : /* For origin set. */
    2970             : static enum route_map_cmd_result_t
    2971           0 : route_set_origin(void *rule, const struct prefix *prefix, void *object)
    2972             : {
    2973           0 :         uint8_t *origin;
    2974           0 :         struct bgp_path_info *path;
    2975             : 
    2976           0 :         origin = rule;
    2977           0 :         path = object;
    2978             : 
    2979           0 :         path->attr->origin = *origin;
    2980             : 
    2981           0 :         return RMAP_OKAY;
    2982             : }
    2983             : 
    2984             : /* Compile function for origin set. */
    2985           0 : static void *route_set_origin_compile(const char *arg)
    2986             : {
    2987           0 :         uint8_t *origin;
    2988             : 
    2989           0 :         origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
    2990             : 
    2991           0 :         if (strcmp(arg, "igp") == 0)
    2992           0 :                 *origin = 0;
    2993           0 :         else if (strcmp(arg, "egp") == 0)
    2994           0 :                 *origin = 1;
    2995             :         else
    2996           0 :                 *origin = 2;
    2997             : 
    2998           0 :         return origin;
    2999             : }
    3000             : 
    3001             : /* Compile function for origin set. */
    3002           0 : static void route_set_origin_free(void *rule)
    3003             : {
    3004           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3005           0 : }
    3006             : 
    3007             : /* Set origin rule structure. */
    3008             : static const struct route_map_rule_cmd route_set_origin_cmd = {
    3009             :         "origin",
    3010             :         route_set_origin,
    3011             :         route_set_origin_compile,
    3012             :         route_set_origin_free,
    3013             : };
    3014             : 
    3015             : /* `set atomic-aggregate' */
    3016             : 
    3017             : /* For atomic aggregate set. */
    3018             : static enum route_map_cmd_result_t
    3019           0 : route_set_atomic_aggregate(void *rule, const struct prefix *pfx, void *object)
    3020             : {
    3021           0 :         struct bgp_path_info *path;
    3022             : 
    3023           0 :         path = object;
    3024           0 :         path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
    3025             : 
    3026           0 :         return RMAP_OKAY;
    3027             : }
    3028             : 
    3029             : /* Compile function for atomic aggregate. */
    3030           0 : static void *route_set_atomic_aggregate_compile(const char *arg)
    3031             : {
    3032           0 :         return (void *)1;
    3033             : }
    3034             : 
    3035             : /* Compile function for atomic aggregate. */
    3036           0 : static void route_set_atomic_aggregate_free(void *rule)
    3037             : {
    3038           0 :         return;
    3039             : }
    3040             : 
    3041             : /* Set atomic aggregate rule structure. */
    3042             : static const struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
    3043             :         "atomic-aggregate",
    3044             :         route_set_atomic_aggregate,
    3045             :         route_set_atomic_aggregate_compile,
    3046             :         route_set_atomic_aggregate_free,
    3047             : };
    3048             : 
    3049             : /* AIGP TLV Metric */
    3050             : static enum route_map_cmd_result_t
    3051           0 : route_set_aigp_metric(void *rule, const struct prefix *pfx, void *object)
    3052             : {
    3053           0 :         const char *aigp_metric = rule;
    3054           0 :         struct bgp_path_info *path = object;
    3055           0 :         uint32_t aigp = 0;
    3056             : 
    3057           0 :         if (strmatch(aigp_metric, "igp-metric")) {
    3058           0 :                 if (!path->nexthop)
    3059             :                         return RMAP_NOMATCH;
    3060             : 
    3061           0 :                 bgp_attr_set_aigp_metric(path->attr, path->nexthop->metric);
    3062             :         } else {
    3063           0 :                 aigp = atoi(aigp_metric);
    3064           0 :                 bgp_attr_set_aigp_metric(path->attr, aigp);
    3065             :         }
    3066             : 
    3067           0 :         path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AIGP);
    3068             : 
    3069           0 :         return RMAP_OKAY;
    3070             : }
    3071             : 
    3072           0 : static void *route_set_aigp_metric_compile(const char *arg)
    3073             : {
    3074           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    3075             : }
    3076             : 
    3077           0 : static void route_set_aigp_metric_free(void *rule)
    3078             : {
    3079           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3080           0 : }
    3081             : 
    3082             : static const struct route_map_rule_cmd route_set_aigp_metric_cmd = {
    3083             :         "aigp-metric",
    3084             :         route_set_aigp_metric,
    3085             :         route_set_aigp_metric_compile,
    3086             :         route_set_aigp_metric_free,
    3087             : };
    3088             : 
    3089             : /* `set aggregator as AS A.B.C.D' */
    3090             : struct aggregator {
    3091             :         as_t as;
    3092             :         struct in_addr address;
    3093             : };
    3094             : 
    3095             : static enum route_map_cmd_result_t
    3096           0 : route_set_aggregator_as(void *rule, const struct prefix *prefix, void *object)
    3097             : {
    3098           0 :         struct bgp_path_info *path;
    3099           0 :         struct aggregator *aggregator;
    3100             : 
    3101           0 :         path = object;
    3102           0 :         aggregator = rule;
    3103             : 
    3104           0 :         path->attr->aggregator_as = aggregator->as;
    3105           0 :         path->attr->aggregator_addr = aggregator->address;
    3106           0 :         path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
    3107             : 
    3108           0 :         return RMAP_OKAY;
    3109             : }
    3110             : 
    3111           0 : static void *route_set_aggregator_as_compile(const char *arg)
    3112             : {
    3113           0 :         struct aggregator *aggregator;
    3114           0 :         char as[10];
    3115           0 :         char address[20];
    3116           0 :         int ret;
    3117             : 
    3118           0 :         aggregator =
    3119           0 :                 XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
    3120           0 :         if (sscanf(arg, "%s %s", as, address) != 2) {
    3121           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
    3122           0 :                 return NULL;
    3123             :         }
    3124             : 
    3125           0 :         aggregator->as = strtoul(as, NULL, 10);
    3126           0 :         ret = inet_aton(address, &aggregator->address);
    3127           0 :         if (ret == 0) {
    3128           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
    3129           0 :                 return NULL;
    3130             :         }
    3131             :         return aggregator;
    3132             : }
    3133             : 
    3134           0 : static void route_set_aggregator_as_free(void *rule)
    3135             : {
    3136           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3137           0 : }
    3138             : 
    3139             : static const struct route_map_rule_cmd route_set_aggregator_as_cmd = {
    3140             :         "aggregator as",
    3141             :         route_set_aggregator_as,
    3142             :         route_set_aggregator_as_compile,
    3143             :         route_set_aggregator_as_free,
    3144             : };
    3145             : 
    3146             : /* Set tag to object. object must be pointer to struct bgp_path_info */
    3147             : static enum route_map_cmd_result_t
    3148           0 : route_set_tag(void *rule, const struct prefix *prefix, void *object)
    3149             : {
    3150           0 :         route_tag_t *tag;
    3151           0 :         struct bgp_path_info *path;
    3152             : 
    3153           0 :         tag = rule;
    3154           0 :         path = object;
    3155             : 
    3156             :         /* Set tag value */
    3157           0 :         path->attr->tag = *tag;
    3158             : 
    3159           0 :         return RMAP_OKAY;
    3160             : }
    3161             : 
    3162             : /* Route map commands for tag set. */
    3163             : static const struct route_map_rule_cmd route_set_tag_cmd = {
    3164             :         "tag",
    3165             :         route_set_tag,
    3166             :         route_map_rule_tag_compile,
    3167             :         route_map_rule_tag_free,
    3168             : };
    3169             : 
    3170             : /* Set label-index to object. object must be pointer to struct bgp_path_info */
    3171             : static enum route_map_cmd_result_t
    3172           0 : route_set_label_index(void *rule, const struct prefix *prefix, void *object)
    3173             : {
    3174           0 :         struct rmap_value *rv;
    3175           0 :         struct bgp_path_info *path;
    3176           0 :         uint32_t label_index;
    3177             : 
    3178             :         /* Fetch routemap's rule information. */
    3179           0 :         rv = rule;
    3180           0 :         path = object;
    3181             : 
    3182             :         /* Set label-index value. */
    3183           0 :         label_index = rv->value;
    3184           0 :         if (label_index) {
    3185           0 :                 path->attr->label_index = label_index;
    3186           0 :                 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
    3187             :         }
    3188             : 
    3189           0 :         return RMAP_OKAY;
    3190             : }
    3191             : 
    3192             : /* Route map commands for label-index set. */
    3193             : static const struct route_map_rule_cmd route_set_label_index_cmd = {
    3194             :         "label-index",
    3195             :         route_set_label_index,
    3196             :         route_value_compile,
    3197             :         route_value_free,
    3198             : };
    3199             : 
    3200             : /* `match ipv6 address IP_ACCESS_LIST' */
    3201             : 
    3202             : static enum route_map_cmd_result_t
    3203           0 : route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
    3204             : {
    3205           0 :         struct access_list *alist;
    3206             : 
    3207           0 :         if (prefix->family == AF_INET6) {
    3208           0 :                 alist = access_list_lookup(AFI_IP6, (char *)rule);
    3209           0 :                 if (alist == NULL)
    3210             :                         return RMAP_NOMATCH;
    3211             : 
    3212           0 :                 return (access_list_apply(alist, prefix) == FILTER_DENY
    3213             :                                 ? RMAP_NOMATCH
    3214           0 :                                 : RMAP_MATCH);
    3215             :         }
    3216             :         return RMAP_NOMATCH;
    3217             : }
    3218             : 
    3219           0 : static void *route_match_ipv6_address_compile(const char *arg)
    3220             : {
    3221           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    3222             : }
    3223             : 
    3224           0 : static void route_match_ipv6_address_free(void *rule)
    3225             : {
    3226           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3227           0 : }
    3228             : 
    3229             : /* Route map commands for ip address matching. */
    3230             : static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
    3231             :         "ipv6 address",
    3232             :         route_match_ipv6_address,
    3233             :         route_match_ipv6_address_compile,
    3234             :         route_match_ipv6_address_free
    3235             : };
    3236             : 
    3237             : /* `match ipv6 next-hop ACCESSLIST6_NAME' */
    3238             : static enum route_map_cmd_result_t
    3239           0 : route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
    3240             : {
    3241           0 :         struct bgp_path_info *path;
    3242           0 :         struct access_list *alist;
    3243           0 :         struct prefix_ipv6 p;
    3244             : 
    3245           0 :         if (prefix->family == AF_INET6) {
    3246           0 :                 path = object;
    3247           0 :                 p.family = AF_INET6;
    3248           0 :                 p.prefix = path->attr->mp_nexthop_global;
    3249           0 :                 p.prefixlen = IPV6_MAX_BITLEN;
    3250             : 
    3251           0 :                 alist = access_list_lookup(AFI_IP6, (char *)rule);
    3252           0 :                 if (!alist)
    3253             :                         return RMAP_NOMATCH;
    3254             : 
    3255           0 :                 if (access_list_apply(alist, &p) == FILTER_PERMIT)
    3256             :                         return RMAP_MATCH;
    3257             : 
    3258           0 :                 if (path->attr->mp_nexthop_len
    3259             :                     == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
    3260           0 :                         p.prefix = path->attr->mp_nexthop_local;
    3261           0 :                         if (access_list_apply(alist, &p) == FILTER_PERMIT)
    3262             :                                 return RMAP_MATCH;
    3263             :                 }
    3264             :         }
    3265             : 
    3266             :         return RMAP_NOMATCH;
    3267             : }
    3268             : 
    3269           0 : static void *route_match_ipv6_next_hop_compile(const char *arg)
    3270             : {
    3271           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    3272             : }
    3273             : 
    3274           0 : static void route_match_ipv6_next_hop_free(void *rule)
    3275             : {
    3276           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3277           0 : }
    3278             : 
    3279             : static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
    3280             :         "ipv6 next-hop",
    3281             :         route_match_ipv6_next_hop,
    3282             :         route_match_ipv6_next_hop_compile,
    3283             :         route_match_ipv6_next_hop_free
    3284             : };
    3285             : 
    3286             : /* `match ipv6 next-hop IP_ADDRESS' */
    3287             : 
    3288             : static enum route_map_cmd_result_t
    3289           0 : route_match_ipv6_next_hop_address(void *rule, const struct prefix *prefix,
    3290             :                                   void *object)
    3291             : {
    3292           0 :         struct in6_addr *addr = rule;
    3293           0 :         struct bgp_path_info *path;
    3294             : 
    3295           0 :         path = object;
    3296             : 
    3297           0 :         if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
    3298             :                 return RMAP_MATCH;
    3299             : 
    3300           0 :         if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
    3301           0 :             && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
    3302           0 :                 return RMAP_MATCH;
    3303             : 
    3304             :         return RMAP_NOMATCH;
    3305             : }
    3306             : 
    3307           0 : static void *route_match_ipv6_next_hop_address_compile(const char *arg)
    3308             : {
    3309           0 :         struct in6_addr *address;
    3310           0 :         int ret;
    3311             : 
    3312           0 :         address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
    3313             : 
    3314           0 :         ret = inet_pton(AF_INET6, arg, address);
    3315           0 :         if (!ret) {
    3316           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
    3317           0 :                 return NULL;
    3318             :         }
    3319             : 
    3320             :         return address;
    3321             : }
    3322             : 
    3323           0 : static void route_match_ipv6_next_hop_address_free(void *rule)
    3324             : {
    3325           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3326           0 : }
    3327             : 
    3328             : static const struct route_map_rule_cmd route_match_ipv6_next_hop_address_cmd = {
    3329             :         "ipv6 next-hop address",
    3330             :         route_match_ipv6_next_hop_address,
    3331             :         route_match_ipv6_next_hop_address_compile,
    3332             :         route_match_ipv6_next_hop_address_free
    3333             : };
    3334             : 
    3335             : /* `match ip next-hop IP_ADDRESS' */
    3336             : 
    3337             : static enum route_map_cmd_result_t
    3338           0 : route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, void *object)
    3339             : {
    3340           0 :         struct in_addr *addr = rule;
    3341           0 :         struct bgp_path_info *path;
    3342             : 
    3343           0 :         path = object;
    3344             : 
    3345           0 :         if (path->attr->nexthop.s_addr == addr->s_addr
    3346           0 :             || (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4
    3347           0 :                 && IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
    3348           0 :                 return RMAP_MATCH;
    3349             : 
    3350             :         return RMAP_NOMATCH;
    3351             : }
    3352             : 
    3353           0 : static void *route_match_ipv4_next_hop_compile(const char *arg)
    3354             : {
    3355           0 :         struct in_addr *address;
    3356           0 :         int ret;
    3357             : 
    3358           0 :         address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
    3359             : 
    3360           0 :         ret = inet_pton(AF_INET, arg, address);
    3361           0 :         if (!ret) {
    3362           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
    3363           0 :                 return NULL;
    3364             :         }
    3365             : 
    3366             :         return address;
    3367             : }
    3368             : 
    3369           0 : static void route_match_ipv4_next_hop_free(void *rule)
    3370             : {
    3371           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3372           0 : }
    3373             : 
    3374             : static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
    3375             :         "ip next-hop address",
    3376             :         route_match_ipv4_next_hop,
    3377             :         route_match_ipv4_next_hop_compile,
    3378             :         route_match_ipv4_next_hop_free
    3379             : };
    3380             : 
    3381             : /* `match ipv6 address prefix-list PREFIX_LIST' */
    3382             : 
    3383             : static enum route_map_cmd_result_t
    3384           0 : route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
    3385             :                                      void *object)
    3386             : {
    3387           0 :         return route_match_address_prefix_list(rule, AFI_IP6, prefix, object);
    3388             : }
    3389             : 
    3390           0 : static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
    3391             : {
    3392           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    3393             : }
    3394             : 
    3395           0 : static void route_match_ipv6_address_prefix_list_free(void *rule)
    3396             : {
    3397           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3398           0 : }
    3399             : 
    3400             : static const struct route_map_rule_cmd
    3401             :                 route_match_ipv6_address_prefix_list_cmd = {
    3402             :         "ipv6 address prefix-list",
    3403             :         route_match_ipv6_address_prefix_list,
    3404             :         route_match_ipv6_address_prefix_list_compile,
    3405             :         route_match_ipv6_address_prefix_list_free
    3406             : };
    3407             : 
    3408             : /* `match ipv6 next-hop type <TYPE>' */
    3409             : 
    3410             : static enum route_map_cmd_result_t
    3411           0 : route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
    3412             :                                void *object)
    3413             : {
    3414           0 :         struct bgp_path_info *path;
    3415           0 :         struct in6_addr *addr = rule;
    3416             : 
    3417           0 :         if (prefix->family == AF_INET6) {
    3418           0 :                 path = (struct bgp_path_info *)object;
    3419           0 :                 if (!path)
    3420             :                         return RMAP_NOMATCH;
    3421             : 
    3422           0 :                 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
    3423           0 :                     && !path->attr->nh_ifindex)
    3424           0 :                         return RMAP_MATCH;
    3425             :         }
    3426             : 
    3427             :         return RMAP_NOMATCH;
    3428             : }
    3429             : 
    3430           0 : static void *route_match_ipv6_next_hop_type_compile(const char *arg)
    3431             : {
    3432           0 :         struct in6_addr *address;
    3433           0 :         int ret;
    3434             : 
    3435           0 :         address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
    3436             : 
    3437           0 :         ret = inet_pton(AF_INET6, "::0", address);
    3438           0 :         if (!ret) {
    3439           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
    3440           0 :                 return NULL;
    3441             :         }
    3442             : 
    3443             :         return address;
    3444             : }
    3445             : 
    3446           0 : static void route_match_ipv6_next_hop_type_free(void *rule)
    3447             : {
    3448           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3449           0 : }
    3450             : 
    3451             : static const struct route_map_rule_cmd
    3452             :                 route_match_ipv6_next_hop_type_cmd = {
    3453             :         "ipv6 next-hop type",
    3454             :         route_match_ipv6_next_hop_type,
    3455             :         route_match_ipv6_next_hop_type_compile,
    3456             :         route_match_ipv6_next_hop_type_free
    3457             : };
    3458             : 
    3459             : /* `set ipv6 nexthop global IP_ADDRESS' */
    3460             : 
    3461             : /* Set nexthop to object.  object must be pointer to struct attr. */
    3462             : static enum route_map_cmd_result_t
    3463           0 : route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, void *object)
    3464             : {
    3465           0 :         struct in6_addr *address;
    3466           0 :         struct bgp_path_info *path;
    3467             : 
    3468             :         /* Fetch routemap's rule information. */
    3469           0 :         address = rule;
    3470           0 :         path = object;
    3471             : 
    3472             :         /* Set next hop value. */
    3473           0 :         path->attr->mp_nexthop_global = *address;
    3474             : 
    3475             :         /* Set nexthop length. */
    3476           0 :         if (path->attr->mp_nexthop_len == 0)
    3477           0 :                 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
    3478             : 
    3479           0 :         SET_FLAG(path->attr->rmap_change_flags,
    3480             :                  BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
    3481             : 
    3482           0 :         return RMAP_OKAY;
    3483             : }
    3484             : 
    3485             : /* Route map `ip next-hop' compile function.  Given string is converted
    3486             :    to struct in_addr structure. */
    3487           0 : static void *route_set_ipv6_nexthop_global_compile(const char *arg)
    3488             : {
    3489           0 :         int ret;
    3490           0 :         struct in6_addr *address;
    3491             : 
    3492           0 :         address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
    3493             : 
    3494           0 :         ret = inet_pton(AF_INET6, arg, address);
    3495             : 
    3496           0 :         if (ret == 0) {
    3497           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
    3498           0 :                 return NULL;
    3499             :         }
    3500             : 
    3501             :         return address;
    3502             : }
    3503             : 
    3504             : /* Free route map's compiled `ip next-hop' value. */
    3505           0 : static void route_set_ipv6_nexthop_global_free(void *rule)
    3506             : {
    3507           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3508           0 : }
    3509             : 
    3510             : /* Route map commands for ip nexthop set. */
    3511             : static const struct route_map_rule_cmd
    3512             :                 route_set_ipv6_nexthop_global_cmd = {
    3513             :         "ipv6 next-hop global",
    3514             :         route_set_ipv6_nexthop_global,
    3515             :         route_set_ipv6_nexthop_global_compile,
    3516             :         route_set_ipv6_nexthop_global_free
    3517             : };
    3518             : 
    3519             : /* Set next-hop preference value. */
    3520             : static enum route_map_cmd_result_t
    3521           0 : route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
    3522             :                                      void *object)
    3523             : {
    3524           0 :         struct bgp_path_info *path;
    3525           0 :         struct peer *peer;
    3526             : 
    3527             :         /* Fetch routemap's rule information. */
    3528           0 :         path = object;
    3529           0 :         peer = path->peer;
    3530             : 
    3531           0 :         if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
    3532             :             || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
    3533             :                 /* Set next hop preference to global */
    3534           0 :                 path->attr->mp_nexthop_prefer_global = true;
    3535           0 :                 SET_FLAG(path->attr->rmap_change_flags,
    3536             :                          BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
    3537             :         } else {
    3538           0 :                 path->attr->mp_nexthop_prefer_global = false;
    3539           0 :                 SET_FLAG(path->attr->rmap_change_flags,
    3540             :                          BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
    3541             :         }
    3542             : 
    3543           0 :         return RMAP_OKAY;
    3544             : }
    3545             : 
    3546           0 : static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
    3547             : {
    3548           0 :         int *rins = NULL;
    3549             : 
    3550           0 :         rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
    3551           0 :         *rins = 1;
    3552             : 
    3553           0 :         return rins;
    3554             : }
    3555             : 
    3556             : /* Free route map's compiled `ip next-hop' value. */
    3557           0 : static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
    3558             : {
    3559           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3560           0 : }
    3561             : 
    3562             : /* Route map commands for ip nexthop set preferred. */
    3563             : static const struct route_map_rule_cmd
    3564             :                 route_set_ipv6_nexthop_prefer_global_cmd = {
    3565             :         "ipv6 next-hop prefer-global",
    3566             :         route_set_ipv6_nexthop_prefer_global,
    3567             :         route_set_ipv6_nexthop_prefer_global_compile,
    3568             :         route_set_ipv6_nexthop_prefer_global_free
    3569             : };
    3570             : 
    3571             : /* `set ipv6 nexthop local IP_ADDRESS' */
    3572             : 
    3573             : /* Set nexthop to object.  object must be pointer to struct attr. */
    3574             : static enum route_map_cmd_result_t
    3575           0 : route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
    3576             : {
    3577           0 :         struct in6_addr *address;
    3578           0 :         struct bgp_path_info *path;
    3579             : 
    3580             :         /* Fetch routemap's rule information. */
    3581           0 :         address = rule;
    3582           0 :         path = object;
    3583             : 
    3584             :         /* Set next hop value. */
    3585           0 :         path->attr->mp_nexthop_local = *address;
    3586             : 
    3587             :         /* Set nexthop length. */
    3588           0 :         if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL &&
    3589             :             path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
    3590           0 :                 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
    3591             : 
    3592           0 :         SET_FLAG(path->attr->rmap_change_flags,
    3593             :                  BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
    3594             : 
    3595           0 :         return RMAP_OKAY;
    3596             : }
    3597             : 
    3598             : /* Route map `ip nexthop' compile function.  Given string is converted
    3599             :    to struct in_addr structure. */
    3600           0 : static void *route_set_ipv6_nexthop_local_compile(const char *arg)
    3601             : {
    3602           0 :         int ret;
    3603           0 :         struct in6_addr *address;
    3604             : 
    3605           0 :         address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
    3606             : 
    3607           0 :         ret = inet_pton(AF_INET6, arg, address);
    3608             : 
    3609           0 :         if (ret == 0) {
    3610           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
    3611           0 :                 return NULL;
    3612             :         }
    3613             : 
    3614             :         return address;
    3615             : }
    3616             : 
    3617             : /* Free route map's compiled `ip nexthop' value. */
    3618           0 : static void route_set_ipv6_nexthop_local_free(void *rule)
    3619             : {
    3620           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3621           0 : }
    3622             : 
    3623             : /* Route map commands for ip nexthop set. */
    3624             : static const struct route_map_rule_cmd
    3625             :                 route_set_ipv6_nexthop_local_cmd = {
    3626             :         "ipv6 next-hop local",
    3627             :         route_set_ipv6_nexthop_local,
    3628             :         route_set_ipv6_nexthop_local_compile,
    3629             :         route_set_ipv6_nexthop_local_free
    3630             : };
    3631             : 
    3632             : /* `set ipv6 nexthop peer-address' */
    3633             : 
    3634             : /* Set nexthop to object.  object must be pointer to struct attr. */
    3635             : static enum route_map_cmd_result_t
    3636           0 : route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
    3637             : {
    3638           0 :         struct in6_addr peer_address;
    3639           0 :         struct bgp_path_info *path;
    3640           0 :         struct peer *peer;
    3641             : 
    3642             :         /* Fetch routemap's rule information. */
    3643           0 :         path = object;
    3644           0 :         peer = path->peer;
    3645             : 
    3646           0 :         if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
    3647             :              || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
    3648           0 :             && peer->su_remote
    3649           0 :             && sockunion_family(peer->su_remote) == AF_INET6) {
    3650           0 :                 peer_address = peer->su_remote->sin6.sin6_addr;
    3651             :                 /* Set next hop value and length in attribute. */
    3652           0 :                 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
    3653           0 :                         path->attr->mp_nexthop_local = peer_address;
    3654           0 :                         if (path->attr->mp_nexthop_len
    3655             :                             != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
    3656           0 :                                 path->attr->mp_nexthop_len =
    3657             :                                         BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
    3658             :                 } else {
    3659           0 :                         path->attr->mp_nexthop_global = peer_address;
    3660           0 :                         if (path->attr->mp_nexthop_len == 0)
    3661           0 :                                 path->attr->mp_nexthop_len =
    3662             :                                         BGP_ATTR_NHLEN_IPV6_GLOBAL;
    3663             :                 }
    3664             : 
    3665           0 :         } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
    3666             :                 /* The next hop value will be set as part of packet
    3667             :                  * rewrite.
    3668             :                  * Set the flags here to indicate that rewrite needs to
    3669             :                  * be done.
    3670             :                  * Also, clear the value - we clear both global and
    3671             :                  * link-local
    3672             :                  * nexthops, whether we send one or both is determined
    3673             :                  * elsewhere.
    3674             :                  */
    3675           0 :                 SET_FLAG(path->attr->rmap_change_flags,
    3676             :                          BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
    3677             :                 /* clear next hop value. */
    3678           0 :                 memset(&(path->attr->mp_nexthop_global), 0,
    3679             :                        sizeof(struct in6_addr));
    3680           0 :                 memset(&(path->attr->mp_nexthop_local), 0,
    3681             :                        sizeof(struct in6_addr));
    3682             :         }
    3683             : 
    3684           0 :         return RMAP_OKAY;
    3685             : }
    3686             : 
    3687             : /* Route map `ip next-hop' compile function.  Given string is converted
    3688             :    to struct in_addr structure. */
    3689           0 : static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
    3690             : {
    3691           0 :         int *rins = NULL;
    3692             : 
    3693           0 :         rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
    3694           0 :         *rins = 1;
    3695             : 
    3696           0 :         return rins;
    3697             : }
    3698             : 
    3699             : /* Free route map's compiled `ip next-hop' value. */
    3700           0 : static void route_set_ipv6_nexthop_peer_free(void *rule)
    3701             : {
    3702           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3703           0 : }
    3704             : 
    3705             : /* Route map commands for ip nexthop set. */
    3706             : static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
    3707             :         "ipv6 next-hop peer-address",
    3708             :         route_set_ipv6_nexthop_peer,
    3709             :         route_set_ipv6_nexthop_peer_compile,
    3710             :         route_set_ipv6_nexthop_peer_free
    3711             : };
    3712             : 
    3713             : /* `set ipv4 vpn next-hop A.B.C.D' */
    3714             : 
    3715             : static enum route_map_cmd_result_t
    3716           0 : route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
    3717             : {
    3718           0 :         struct in_addr *address;
    3719           0 :         struct bgp_path_info *path;
    3720             : 
    3721             :         /* Fetch routemap's rule information. */
    3722           0 :         address = rule;
    3723           0 :         path = object;
    3724             : 
    3725             :         /* Set next hop value. */
    3726           0 :         path->attr->mp_nexthop_global_in = *address;
    3727           0 :         path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
    3728             : 
    3729           0 :         SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_VPNV4_NHOP_CHANGED);
    3730             : 
    3731           0 :         return RMAP_OKAY;
    3732             : }
    3733             : 
    3734           0 : static void *route_set_vpnv4_nexthop_compile(const char *arg)
    3735             : {
    3736           0 :         int ret;
    3737           0 :         struct in_addr *address;
    3738             : 
    3739           0 :         address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
    3740             : 
    3741           0 :         ret = inet_aton(arg, address);
    3742             : 
    3743           0 :         if (ret == 0) {
    3744           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
    3745           0 :                 return NULL;
    3746             :         }
    3747             : 
    3748             :         return address;
    3749             : }
    3750             : 
    3751             : /* `set ipv6 vpn next-hop A.B.C.D' */
    3752             : 
    3753             : static enum route_map_cmd_result_t
    3754           0 : route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
    3755             : {
    3756           0 :         struct in6_addr *address;
    3757           0 :         struct bgp_path_info *path;
    3758             : 
    3759             :         /* Fetch routemap's rule information. */
    3760           0 :         address = rule;
    3761           0 :         path = object;
    3762             : 
    3763             :         /* Set next hop value. */
    3764           0 :         memcpy(&path->attr->mp_nexthop_global, address,
    3765             :                sizeof(struct in6_addr));
    3766           0 :         path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
    3767             : 
    3768           0 :         SET_FLAG(path->attr->rmap_change_flags,
    3769             :                  BATTR_RMAP_VPNV6_GLOBAL_NHOP_CHANGED);
    3770             : 
    3771           0 :         return RMAP_OKAY;
    3772             : }
    3773             : 
    3774           0 : static void *route_set_vpnv6_nexthop_compile(const char *arg)
    3775             : {
    3776           0 :         int ret;
    3777           0 :         struct in6_addr *address;
    3778             : 
    3779           0 :         address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
    3780           0 :         ret = inet_pton(AF_INET6, arg, address);
    3781             : 
    3782           0 :         if (ret == 0) {
    3783           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
    3784           0 :                 return NULL;
    3785             :         }
    3786             : 
    3787             :         return address;
    3788             : }
    3789             : 
    3790           0 : static void route_set_vpn_nexthop_free(void *rule)
    3791             : {
    3792           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3793           0 : }
    3794             : 
    3795             : /* Route map commands for ipv4 next-hop set. */
    3796             : static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
    3797             :         "ipv4 vpn next-hop",
    3798             :         route_set_vpnv4_nexthop,
    3799             :         route_set_vpnv4_nexthop_compile,
    3800             :         route_set_vpn_nexthop_free
    3801             : };
    3802             : 
    3803             : /* Route map commands for ipv6 next-hop set. */
    3804             : static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
    3805             :         "ipv6 vpn next-hop",
    3806             :         route_set_vpnv6_nexthop,
    3807             :         route_set_vpnv6_nexthop_compile,
    3808             :         route_set_vpn_nexthop_free
    3809             : };
    3810             : 
    3811             : /* `set originator-id' */
    3812             : 
    3813             : /* For origin set. */
    3814             : static enum route_map_cmd_result_t
    3815           0 : route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
    3816             : {
    3817           0 :         struct in_addr *address;
    3818           0 :         struct bgp_path_info *path;
    3819             : 
    3820           0 :         address = rule;
    3821           0 :         path = object;
    3822             : 
    3823           0 :         path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
    3824           0 :         path->attr->originator_id = *address;
    3825             : 
    3826           0 :         return RMAP_OKAY;
    3827             : }
    3828             : 
    3829             : /* Compile function for originator-id set. */
    3830           0 : static void *route_set_originator_id_compile(const char *arg)
    3831             : {
    3832           0 :         int ret;
    3833           0 :         struct in_addr *address;
    3834             : 
    3835           0 :         address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
    3836             : 
    3837           0 :         ret = inet_aton(arg, address);
    3838             : 
    3839           0 :         if (ret == 0) {
    3840           0 :                 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
    3841           0 :                 return NULL;
    3842             :         }
    3843             : 
    3844             :         return address;
    3845             : }
    3846             : 
    3847             : /* Compile function for originator_id set. */
    3848           0 : static void route_set_originator_id_free(void *rule)
    3849             : {
    3850           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    3851           0 : }
    3852             : 
    3853             : /* Set originator-id rule structure. */
    3854             : static const struct route_map_rule_cmd route_set_originator_id_cmd = {
    3855             :         "originator-id",
    3856             :         route_set_originator_id,
    3857             :         route_set_originator_id_compile,
    3858             :         route_set_originator_id_free,
    3859             : };
    3860             : 
    3861             : static enum route_map_cmd_result_t
    3862           0 : route_match_rpki_extcommunity(void *rule, const struct prefix *prefix,
    3863             :                               void *object)
    3864             : {
    3865           0 :         struct bgp_path_info *path;
    3866           0 :         struct ecommunity *ecomm;
    3867           0 :         struct ecommunity_val *ecomm_val;
    3868           0 :         enum rpki_states *rpki_status = rule;
    3869           0 :         enum rpki_states ecomm_rpki_status = RPKI_NOT_BEING_USED;
    3870             : 
    3871           0 :         path = object;
    3872             : 
    3873           0 :         ecomm = bgp_attr_get_ecommunity(path->attr);
    3874           0 :         if (!ecomm)
    3875             :                 return RMAP_NOMATCH;
    3876             : 
    3877           0 :         ecomm_val = ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS,
    3878             :                                       ECOMMUNITY_ORIGIN_VALIDATION_STATE);
    3879           0 :         if (!ecomm_val)
    3880             :                 return RMAP_NOMATCH;
    3881             : 
    3882             :         /* The Origin Validation State is encoded in the last octet of
    3883             :          * the extended community.
    3884             :          */
    3885           0 :         switch (ecomm_val->val[7]) {
    3886             :         case ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID:
    3887             :                 ecomm_rpki_status = RPKI_VALID;
    3888             :                 break;
    3889             :         case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND:
    3890             :                 ecomm_rpki_status = RPKI_NOTFOUND;
    3891             :                 break;
    3892             :         case ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID:
    3893             :                 ecomm_rpki_status = RPKI_INVALID;
    3894             :                 break;
    3895             :         case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED:
    3896             :                 break;
    3897             :         }
    3898             : 
    3899           0 :         if (ecomm_rpki_status == *rpki_status)
    3900             :                 return RMAP_MATCH;
    3901             : 
    3902             :         return RMAP_NOMATCH;
    3903             : }
    3904             : 
    3905           0 : static void *route_match_extcommunity_compile(const char *arg)
    3906             : {
    3907           0 :         int *rpki_status;
    3908             : 
    3909           0 :         rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
    3910             : 
    3911           0 :         if (strcmp(arg, "valid") == 0)
    3912           0 :                 *rpki_status = RPKI_VALID;
    3913           0 :         else if (strcmp(arg, "invalid") == 0)
    3914           0 :                 *rpki_status = RPKI_INVALID;
    3915             :         else
    3916           0 :                 *rpki_status = RPKI_NOTFOUND;
    3917             : 
    3918           0 :         return rpki_status;
    3919             : }
    3920             : 
    3921             : static const struct route_map_rule_cmd route_match_rpki_extcommunity_cmd = {
    3922             :         "rpki-extcommunity",
    3923             :         route_match_rpki_extcommunity,
    3924             :         route_match_extcommunity_compile,
    3925             :         route_value_free
    3926             : };
    3927             : 
    3928             : /*
    3929             :  * This is the workhorse routine for processing in/out routemap
    3930             :  * modifications.
    3931             :  */
    3932          21 : static void bgp_route_map_process_peer(const char *rmap_name,
    3933             :                                        struct route_map *map, struct peer *peer,
    3934             :                                        int afi, int safi, int route_update)
    3935             : {
    3936          21 :         struct bgp_filter *filter;
    3937             : 
    3938          21 :         if (!peer || !rmap_name)
    3939             :                 return;
    3940             : 
    3941          21 :         filter = &peer->filter[afi][safi];
    3942             :         /*
    3943             :          * in is for non-route-server clients,
    3944             :          * out is for all peers
    3945             :          */
    3946          21 :         if (filter->map[RMAP_IN].name
    3947           1 :             && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
    3948           1 :                 filter->map[RMAP_IN].map = map;
    3949             : 
    3950           1 :                 if (route_update && peer_established(peer)) {
    3951           1 :                         if (CHECK_FLAG(peer->af_flags[afi][safi],
    3952             :                                        PEER_FLAG_SOFT_RECONFIG)) {
    3953           0 :                                 if (bgp_debug_update(peer, NULL, NULL, 1))
    3954           0 :                                         zlog_debug(
    3955             :                                                 "Processing route_map %s(%s:%s) update on peer %s (inbound, soft-reconfig)",
    3956             :                                                 rmap_name, afi2str(afi),
    3957             :                                                 safi2str(safi), peer->host);
    3958             : 
    3959           0 :                                 bgp_soft_reconfig_in(peer, afi, safi);
    3960           1 :                         } else if (CHECK_FLAG(peer->cap,
    3961             :                                               PEER_CAP_REFRESH_OLD_RCV)
    3962           1 :                                    || CHECK_FLAG(peer->cap,
    3963             :                                                  PEER_CAP_REFRESH_NEW_RCV)) {
    3964           1 :                                 if (bgp_debug_update(peer, NULL, NULL, 1))
    3965           0 :                                         zlog_debug(
    3966             :                                                 "Processing route_map %s(%s:%s) update on peer %s (inbound, route-refresh)",
    3967             :                                                 rmap_name, afi2str(afi),
    3968             :                                                 safi2str(safi), peer->host);
    3969           1 :                                 bgp_route_refresh_send(
    3970             :                                         peer, afi, safi, 0, 0, 0,
    3971             :                                         BGP_ROUTE_REFRESH_NORMAL);
    3972             :                         }
    3973             :                 }
    3974             :         }
    3975             : 
    3976             :         /*
    3977             :          * For outbound, unsuppress and default-originate map change (content or
    3978             :          * map created), merely update the "config" here, the actual route
    3979             :          * announcement happens at the group level.
    3980             :          */
    3981          21 :         if (filter->map[RMAP_OUT].name
    3982           0 :             && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
    3983           0 :                 filter->map[RMAP_OUT].map = map;
    3984             : 
    3985          21 :         if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
    3986           0 :                 filter->usmap.map = map;
    3987             : 
    3988          21 :         if (filter->advmap.aname
    3989           0 :             && (strcmp(rmap_name, filter->advmap.aname) == 0)) {
    3990           0 :                 filter->advmap.amap = map;
    3991             :         }
    3992             : 
    3993          21 :         if (filter->advmap.cname
    3994           0 :             && (strcmp(rmap_name, filter->advmap.cname) == 0)) {
    3995           0 :                 filter->advmap.cmap = map;
    3996             :         }
    3997             : 
    3998          21 :         if (peer->default_rmap[afi][safi].name
    3999           0 :             && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
    4000           0 :                 peer->default_rmap[afi][safi].map = map;
    4001             : 
    4002             :         /* Notify BGP conditional advertisement scanner percess */
    4003          21 :         peer->advmap_config_change[afi][safi] = true;
    4004             : }
    4005             : 
    4006           1 : static void bgp_route_map_update_peer_group(const char *rmap_name,
    4007             :                                             struct route_map *map,
    4008             :                                             struct bgp *bgp)
    4009             : {
    4010           1 :         struct peer_group *group;
    4011           1 :         struct listnode *node, *nnode;
    4012           1 :         struct bgp_filter *filter;
    4013           1 :         int afi, safi;
    4014           1 :         int direct;
    4015             : 
    4016           1 :         if (!bgp)
    4017             :                 return;
    4018             : 
    4019             :         /* All the peers have been updated correctly already. This is
    4020             :          * just updating the placeholder data. No real update required.
    4021             :          */
    4022           2 :         for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
    4023           0 :                 FOREACH_AFI_SAFI (afi, safi) {
    4024           0 :                         filter = &group->conf->filter[afi][safi];
    4025             : 
    4026           0 :                         for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
    4027           0 :                                 if ((filter->map[direct].name)
    4028           0 :                                     && (strcmp(rmap_name,
    4029             :                                                filter->map[direct].name)
    4030             :                                         == 0))
    4031           0 :                                         filter->map[direct].map = map;
    4032             :                         }
    4033             : 
    4034           0 :                         if (filter->usmap.name
    4035           0 :                             && (strcmp(rmap_name, filter->usmap.name) == 0))
    4036           0 :                                 filter->usmap.map = map;
    4037             : 
    4038           0 :                         if (filter->advmap.aname &&
    4039           0 :                             (strcmp(rmap_name, filter->advmap.aname) == 0))
    4040           0 :                                 filter->advmap.amap = map;
    4041             : 
    4042           0 :                         if (filter->advmap.cname &&
    4043           0 :                             (strcmp(rmap_name, filter->advmap.cname) == 0))
    4044           0 :                                 filter->advmap.cmap = map;
    4045             :                 }
    4046             :         }
    4047             : }
    4048             : 
    4049             : /*
    4050             :  * Note that if an extreme number (tens of thousands) of route-maps are in use
    4051             :  * and if bgp has an extreme number of peers, network statements, etc then this
    4052             :  * function can consume a lot of cycles. This is due to this function being
    4053             :  * called for each route-map and within this function we walk the list of peers,
    4054             :  * network statements, etc looking to see if they use this route-map.
    4055             :  */
    4056           1 : static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
    4057             :                                          bool route_update)
    4058             : {
    4059           1 :         int i;
    4060           1 :         bool matched;
    4061           1 :         afi_t afi;
    4062           1 :         safi_t safi;
    4063           1 :         struct peer *peer;
    4064           1 :         struct bgp_dest *bn;
    4065           1 :         struct bgp_static *bgp_static;
    4066           1 :         struct bgp_aggregate *aggregate;
    4067           1 :         struct listnode *node, *nnode;
    4068           1 :         struct route_map *map;
    4069           1 :         char buf[INET6_ADDRSTRLEN];
    4070             : 
    4071           1 :         map = route_map_lookup_by_name(rmap_name);
    4072             : 
    4073           3 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
    4074             : 
    4075             :                 /* Ignore dummy peer-group structure */
    4076           1 :                 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    4077           0 :                         continue;
    4078             : 
    4079          25 :                 FOREACH_AFI_SAFI (afi, safi) {
    4080             :                         /* process in/out/import/export/default-orig
    4081             :                          * route-maps */
    4082          21 :                         bgp_route_map_process_peer(rmap_name, map, peer, afi,
    4083             :                                                    safi, route_update);
    4084             :                 }
    4085             :         }
    4086             : 
    4087             :         /* for outbound/default-orig route-maps, process for groups */
    4088           1 :         update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
    4089             :                                    route_update, 0);
    4090             : 
    4091             :         /* update peer-group config (template) */
    4092           1 :         bgp_route_map_update_peer_group(rmap_name, map, bgp);
    4093             : 
    4094          26 :         FOREACH_AFI_SAFI (afi, safi) {
    4095             :                 /* For table route-map updates. */
    4096          21 :                 if (!bgp_fibupd_safi(safi))
    4097           9 :                         continue;
    4098             : 
    4099          12 :                 if (bgp->table_map[afi][safi].name
    4100           0 :                     && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
    4101             :                         == 0)) {
    4102             : 
    4103             :                         /* bgp->table_map[afi][safi].map  is NULL.
    4104             :                          * i.e Route map creation event.
    4105             :                          * So update applied_counter.
    4106             :                          * If it is not NULL, i.e It may be routemap updation or
    4107             :                          * deletion. so no need to update the counter.
    4108             :                          */
    4109           0 :                         if (!bgp->table_map[afi][safi].map)
    4110           0 :                                 route_map_counter_increment(map);
    4111           0 :                         bgp->table_map[afi][safi].map = map;
    4112             : 
    4113           0 :                         if (BGP_DEBUG(zebra, ZEBRA))
    4114           0 :                                 zlog_debug(
    4115             :                                         "Processing route_map %s(%s:%s) update on table map",
    4116             :                                         rmap_name, afi2str(afi),
    4117             :                                         safi2str(safi));
    4118           0 :                         if (route_update)
    4119           0 :                                 bgp_zebra_announce_table(bgp, afi, safi);
    4120             :                 }
    4121             : 
    4122             :                 /* For network route-map updates. */
    4123          24 :                 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
    4124           0 :                      bn = bgp_route_next(bn)) {
    4125           0 :                         bgp_static = bgp_dest_get_bgp_static_info(bn);
    4126           0 :                         if (!bgp_static)
    4127           0 :                                 continue;
    4128             : 
    4129           0 :                         if (!bgp_static->rmap.name
    4130           0 :                             || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
    4131           0 :                                 continue;
    4132             : 
    4133           0 :                         if (!bgp_static->rmap.map)
    4134           0 :                                 route_map_counter_increment(map);
    4135             : 
    4136           0 :                         bgp_static->rmap.map = map;
    4137             : 
    4138           0 :                         if (route_update && !bgp_static->backdoor) {
    4139           0 :                                 const struct prefix *bn_p =
    4140           0 :                                         bgp_dest_get_prefix(bn);
    4141             : 
    4142           0 :                                 if (bgp_debug_zebra(bn_p))
    4143           0 :                                         zlog_debug(
    4144             :                                                 "Processing route_map %s(%s:%s) update on static route %s",
    4145             :                                                 rmap_name, afi2str(afi),
    4146             :                                                 safi2str(safi),
    4147             :                                                 inet_ntop(bn_p->family,
    4148             :                                                           &bn_p->u.prefix, buf,
    4149             :                                                           sizeof(buf)));
    4150           0 :                                 bgp_static_update(bgp, bn_p, bgp_static, afi,
    4151             :                                                   safi);
    4152             :                         }
    4153             :                 }
    4154             : 
    4155             :                 /* For aggregate-address route-map updates. */
    4156          24 :                 for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
    4157           0 :                      bn = bgp_route_next(bn)) {
    4158           0 :                         aggregate = bgp_dest_get_bgp_aggregate_info(bn);
    4159           0 :                         if (!aggregate)
    4160           0 :                                 continue;
    4161             : 
    4162           0 :                         matched = false;
    4163             : 
    4164             :                         /* Update suppress map pointer. */
    4165           0 :                         if (aggregate->suppress_map_name
    4166           0 :                             && strmatch(aggregate->suppress_map_name,
    4167             :                                         rmap_name)) {
    4168           0 :                                 if (aggregate->rmap.map == NULL)
    4169           0 :                                         route_map_counter_increment(map);
    4170             : 
    4171           0 :                                 aggregate->suppress_map = map;
    4172             : 
    4173           0 :                                 bgp_aggregate_toggle_suppressed(
    4174             :                                         aggregate, bgp, bgp_dest_get_prefix(bn),
    4175             :                                         afi, safi, false);
    4176             : 
    4177           0 :                                 matched = true;
    4178             :                         }
    4179             : 
    4180           0 :                         if (aggregate->rmap.name
    4181           0 :                             && strmatch(rmap_name, aggregate->rmap.name)) {
    4182           0 :                                 if (aggregate->rmap.map == NULL)
    4183           0 :                                         route_map_counter_increment(map);
    4184             : 
    4185           0 :                                 aggregate->rmap.map = map;
    4186             : 
    4187           0 :                                 matched = true;
    4188             :                         }
    4189             : 
    4190           0 :                         if (matched && route_update) {
    4191           0 :                                 const struct prefix *bn_p =
    4192           0 :                                         bgp_dest_get_prefix(bn);
    4193             : 
    4194           0 :                                 if (bgp_debug_zebra(bn_p))
    4195           0 :                                         zlog_debug(
    4196             :                                                 "Processing route_map %s(%s:%s) update on aggregate-address route %s",
    4197             :                                                 rmap_name, afi2str(afi),
    4198             :                                                 safi2str(safi),
    4199             :                                                 inet_ntop(bn_p->family,
    4200             :                                                           &bn_p->u.prefix, buf,
    4201             :                                                           sizeof(buf)));
    4202           0 :                                 bgp_aggregate_route(bgp, bn_p, afi, safi,
    4203             :                                                     aggregate);
    4204             :                         }
    4205             :                 }
    4206             :         }
    4207             : 
    4208             :         /* For redistribute route-map updates. */
    4209           4 :         for (afi = AFI_IP; afi < AFI_MAX; afi++)
    4210          96 :                 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
    4211          93 :                         struct list *red_list;
    4212          93 :                         struct bgp_redist *red;
    4213             : 
    4214          93 :                         red_list = bgp->redist[afi][i];
    4215          93 :                         if (!red_list)
    4216          93 :                                 continue;
    4217             : 
    4218           0 :                         for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
    4219           0 :                                 if (!red->rmap.name
    4220           0 :                                     || (strcmp(rmap_name, red->rmap.name) != 0))
    4221           0 :                                         continue;
    4222             : 
    4223           0 :                                 if (!red->rmap.map)
    4224           0 :                                         route_map_counter_increment(map);
    4225             : 
    4226           0 :                                 red->rmap.map = map;
    4227             : 
    4228           0 :                                 if (!route_update)
    4229           0 :                                         continue;
    4230             : 
    4231           0 :                                 if (BGP_DEBUG(zebra, ZEBRA))
    4232           0 :                                         zlog_debug(
    4233             :                                                 "Processing route_map %s(%s:%s) update on redistributed routes",
    4234             :                                                 rmap_name, afi2str(afi),
    4235             :                                                 safi2str(safi));
    4236             : 
    4237           0 :                                 bgp_redistribute_resend(bgp, afi, i,
    4238           0 :                                                         red->instance);
    4239             :                         }
    4240             :                 }
    4241             : 
    4242             :         /* for type5 command route-maps */
    4243          25 :         FOREACH_AFI_SAFI (afi, safi) {
    4244          21 :                 if (!bgp->adv_cmd_rmap[afi][safi].name
    4245           0 :                     || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
    4246             :                                != 0)
    4247          21 :                         continue;
    4248             : 
    4249             :                 /* Make sure the route-map is populated here if not already done */
    4250           0 :                 bgp->adv_cmd_rmap[afi][safi].map = map;
    4251             : 
    4252           0 :                 if (BGP_DEBUG(zebra, ZEBRA))
    4253           0 :                         zlog_debug(
    4254             :                                 "Processing route_map %s(%s:%s) update on advertise type5 route command",
    4255             :                                 rmap_name, afi2str(afi), safi2str(safi));
    4256             : 
    4257           0 :                 if (route_update && advertise_type5_routes(bgp, afi)) {
    4258           0 :                         bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
    4259           0 :                         bgp_evpn_advertise_type5_routes(bgp, afi, safi);
    4260             :                 }
    4261             :         }
    4262           1 : }
    4263             : 
    4264           1 : static void bgp_route_map_process_update_cb(char *rmap_name)
    4265             : {
    4266           1 :         struct listnode *node, *nnode;
    4267           1 :         struct bgp *bgp;
    4268             : 
    4269           3 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
    4270           1 :                 bgp_route_map_process_update(bgp, rmap_name, true);
    4271             : 
    4272             : #ifdef ENABLE_BGP_VNC
    4273           1 :                 vnc_routemap_update(bgp, __func__);
    4274             : #endif
    4275             :         }
    4276             : 
    4277           1 :         vpn_policy_routemap_event(rmap_name);
    4278           1 : }
    4279             : 
    4280           1 : void bgp_route_map_update_timer(struct thread *thread)
    4281             : {
    4282           1 :         route_map_walk_update_list(bgp_route_map_process_update_cb);
    4283           1 : }
    4284             : 
    4285           8 : static void bgp_route_map_mark_update(const char *rmap_name)
    4286             : {
    4287           8 :         struct listnode *node, *nnode;
    4288           8 :         struct bgp *bgp;
    4289             : 
    4290             :         /* If new update is received before the current timer timed out,
    4291             :          * turn it off and start a new timer.
    4292             :          */
    4293           8 :         THREAD_OFF(bm->t_rmap_update);
    4294             : 
    4295             :         /* rmap_update_timer of 0 means don't do route updates */
    4296           8 :         if (bm->rmap_update_timer) {
    4297           8 :                 thread_add_timer(bm->master, bgp_route_map_update_timer,
    4298             :                                  NULL, bm->rmap_update_timer,
    4299             :                                  &bm->t_rmap_update);
    4300             : 
    4301             :                 /* Signal the groups that a route-map update event has
    4302             :                  * started */
    4303          24 :                 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
    4304           8 :                         update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP,
    4305             :                                                    rmap_name, true, 1);
    4306             :         } else {
    4307           0 :                 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
    4308           0 :                         bgp_route_map_process_update(bgp, rmap_name, false);
    4309             : #ifdef ENABLE_BGP_VNC
    4310           0 :                         vnc_routemap_update(bgp, __func__);
    4311             : #endif
    4312             :                 }
    4313             : 
    4314           0 :                 vpn_policy_routemap_event(rmap_name);
    4315             :         }
    4316           8 : }
    4317             : 
    4318           1 : static void bgp_route_map_add(const char *rmap_name)
    4319             : {
    4320           1 :         if (route_map_mark_updated(rmap_name) == 0)
    4321           1 :                 bgp_route_map_mark_update(rmap_name);
    4322             : 
    4323           1 :         route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
    4324           1 : }
    4325             : 
    4326           0 : static void bgp_route_map_delete(const char *rmap_name)
    4327             : {
    4328           0 :         if (route_map_mark_updated(rmap_name) == 0)
    4329           0 :                 bgp_route_map_mark_update(rmap_name);
    4330             : 
    4331           0 :         route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
    4332           0 : }
    4333             : 
    4334           7 : static void bgp_route_map_event(const char *rmap_name)
    4335             : {
    4336           7 :         if (route_map_mark_updated(rmap_name) == 0)
    4337           7 :                 bgp_route_map_mark_update(rmap_name);
    4338             : 
    4339           7 :         route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
    4340           7 : }
    4341             : 
    4342           0 : DEFUN_YANG (match_mac_address,
    4343             :             match_mac_address_cmd,
    4344             :             "match mac address ACCESSLIST_MAC_NAME",
    4345             :             MATCH_STR
    4346             :             "mac address\n"
    4347             :             "Match address of route\n"
    4348             :             "MAC Access-list name\n")
    4349             : {
    4350           0 :         const char *xpath =
    4351             :                 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
    4352           0 :         char xpath_value[XPATH_MAXLEN];
    4353             : 
    4354           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4355           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4356             :                  "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
    4357           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
    4358             : 
    4359           0 :         return nb_cli_apply_changes(vty, NULL);
    4360             : }
    4361             : 
    4362           0 : DEFUN_YANG (no_match_mac_address,
    4363             :             no_match_mac_address_cmd,
    4364             :             "no match mac address ACCESSLIST_MAC_NAME",
    4365             :             NO_STR
    4366             :             MATCH_STR
    4367             :             "mac\n"
    4368             :             "Match address of route\n"
    4369             :             "MAC acess-list name\n")
    4370             : {
    4371           0 :         const char *xpath =
    4372             :                 "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
    4373             : 
    4374           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4375           0 :         return nb_cli_apply_changes(vty, NULL);
    4376             : }
    4377             : 
    4378             : /*
    4379             :  * Helper to handle the case of the user passing in a number or type string
    4380             :  */
    4381           0 : static const char *parse_evpn_rt_type(const char *num_rt_type)
    4382             : {
    4383           0 :         switch (num_rt_type[0]) {
    4384             :         case '1':
    4385             :                 return "ead";
    4386           0 :         case '2':
    4387           0 :                 return "macip";
    4388           0 :         case '3':
    4389           0 :                 return "multicast";
    4390           0 :         case '4':
    4391           0 :                 return "es";
    4392           0 :         case '5':
    4393           0 :                 return "prefix";
    4394             :         default:
    4395           0 :                 break;
    4396             :         }
    4397             : 
    4398             :         /* Was already full type string */
    4399           0 :         return num_rt_type;
    4400             : }
    4401             : 
    4402           0 : DEFUN_YANG (match_evpn_route_type,
    4403             :             match_evpn_route_type_cmd,
    4404             :             "match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
    4405             :             MATCH_STR
    4406             :             EVPN_HELP_STR
    4407             :             EVPN_TYPE_HELP_STR
    4408             :             EVPN_TYPE_1_HELP_STR
    4409             :             EVPN_TYPE_1_HELP_STR
    4410             :             EVPN_TYPE_2_HELP_STR
    4411             :             EVPN_TYPE_2_HELP_STR
    4412             :             EVPN_TYPE_3_HELP_STR
    4413             :             EVPN_TYPE_3_HELP_STR
    4414             :             EVPN_TYPE_4_HELP_STR
    4415             :             EVPN_TYPE_4_HELP_STR
    4416             :             EVPN_TYPE_5_HELP_STR
    4417             :             EVPN_TYPE_5_HELP_STR)
    4418             : {
    4419           0 :         const char *xpath =
    4420             :                 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
    4421           0 :         char xpath_value[XPATH_MAXLEN];
    4422             : 
    4423           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4424           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4425             :                  "%s/rmap-match-condition/frr-bgp-route-map:evpn-route-type",
    4426             :                  xpath);
    4427           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    4428           0 :                               parse_evpn_rt_type(argv[3]->arg));
    4429             : 
    4430           0 :         return nb_cli_apply_changes(vty, NULL);
    4431             : }
    4432             : 
    4433           0 : DEFUN_YANG (no_match_evpn_route_type,
    4434             :             no_match_evpn_route_type_cmd,
    4435             :             "no match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
    4436             :             NO_STR
    4437             :             MATCH_STR
    4438             :             EVPN_HELP_STR
    4439             :             EVPN_TYPE_HELP_STR
    4440             :             EVPN_TYPE_1_HELP_STR
    4441             :             EVPN_TYPE_1_HELP_STR
    4442             :             EVPN_TYPE_2_HELP_STR
    4443             :             EVPN_TYPE_2_HELP_STR
    4444             :             EVPN_TYPE_3_HELP_STR
    4445             :             EVPN_TYPE_3_HELP_STR
    4446             :             EVPN_TYPE_4_HELP_STR
    4447             :             EVPN_TYPE_4_HELP_STR
    4448             :             EVPN_TYPE_5_HELP_STR
    4449             :             EVPN_TYPE_5_HELP_STR)
    4450             : {
    4451           0 :         const char *xpath =
    4452             :                 "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
    4453             : 
    4454           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4455             : 
    4456           0 :         return nb_cli_apply_changes(vty, NULL);
    4457             : }
    4458             : 
    4459             : 
    4460           0 : DEFUN_YANG (match_evpn_vni,
    4461             :             match_evpn_vni_cmd,
    4462             :             "match evpn vni " CMD_VNI_RANGE,
    4463             :             MATCH_STR
    4464             :             EVPN_HELP_STR
    4465             :             "Match VNI\n"
    4466             :             "VNI ID\n")
    4467             : {
    4468           0 :         const char *xpath =
    4469             :                 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
    4470           0 :         char xpath_value[XPATH_MAXLEN];
    4471             : 
    4472           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4473           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4474             :                  "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
    4475           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
    4476             : 
    4477           0 :         return nb_cli_apply_changes(vty, NULL);
    4478             : }
    4479             : 
    4480           0 : DEFUN_YANG (no_match_evpn_vni,
    4481             :             no_match_evpn_vni_cmd,
    4482             :             "no match evpn vni " CMD_VNI_RANGE,
    4483             :             NO_STR
    4484             :             MATCH_STR
    4485             :             EVPN_HELP_STR
    4486             :             "Match VNI\n"
    4487             :             "VNI ID\n")
    4488             : {
    4489           0 :         const char *xpath =
    4490             :                 "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
    4491           0 :         char xpath_value[XPATH_MAXLEN];
    4492             : 
    4493           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4494           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4495             :                  "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
    4496           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, argv[3]->arg);
    4497             : 
    4498           0 :         return nb_cli_apply_changes(vty, NULL);
    4499             : }
    4500             : 
    4501           0 : DEFUN_YANG (match_evpn_default_route,
    4502             :             match_evpn_default_route_cmd,
    4503             :             "match evpn default-route",
    4504             :             MATCH_STR
    4505             :             EVPN_HELP_STR
    4506             :             "default EVPN type-5 route\n")
    4507             : {
    4508           0 :         const char *xpath =
    4509             :                 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
    4510           0 :         char xpath_value[XPATH_MAXLEN];
    4511             : 
    4512           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4513             : 
    4514           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4515             :                  "%s/rmap-match-condition/frr-bgp-route-map:evpn-default-route",
    4516             :                  xpath);
    4517           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
    4518             : 
    4519           0 :         return nb_cli_apply_changes(vty, NULL);
    4520             : }
    4521             : 
    4522           0 : DEFUN_YANG (no_match_evpn_default_route,
    4523             :             no_match_evpn_default_route_cmd,
    4524             :             "no match evpn default-route",
    4525             :             NO_STR
    4526             :             MATCH_STR
    4527             :             EVPN_HELP_STR
    4528             :             "default EVPN type-5 route\n")
    4529             : {
    4530           0 :         const char *xpath =
    4531             :                 "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
    4532             : 
    4533           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4534             : 
    4535           0 :         return nb_cli_apply_changes(vty, NULL);
    4536             : }
    4537             : 
    4538           0 : DEFUN_YANG (match_evpn_rd,
    4539             :             match_evpn_rd_cmd,
    4540             :             "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
    4541             :             MATCH_STR
    4542             :             EVPN_HELP_STR
    4543             :             "Route Distinguisher\n"
    4544             :             "ASN:XX or A.B.C.D:XX\n")
    4545             : {
    4546           0 :         const char *xpath =
    4547             :                 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
    4548           0 :         char xpath_value[XPATH_MAXLEN];
    4549             : 
    4550           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4551           0 :         snprintf(
    4552             :                 xpath_value, sizeof(xpath_value),
    4553             :                 "%s/rmap-match-condition/frr-bgp-route-map:route-distinguisher",
    4554             :                 xpath);
    4555           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
    4556             : 
    4557           0 :         return nb_cli_apply_changes(vty, NULL);
    4558             : }
    4559             : 
    4560           0 : DEFUN_YANG (no_match_evpn_rd,
    4561             :             no_match_evpn_rd_cmd,
    4562             :             "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
    4563             :             NO_STR
    4564             :             MATCH_STR
    4565             :             EVPN_HELP_STR
    4566             :             "Route Distinguisher\n"
    4567             :             "ASN:XX or A.B.C.D:XX\n")
    4568             : {
    4569           0 :         const char *xpath =
    4570             :                 "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
    4571             : 
    4572           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4573           0 :         return nb_cli_apply_changes(vty, NULL);
    4574             : }
    4575             : 
    4576           0 : DEFUN_YANG (set_evpn_gw_ip_ipv4,
    4577             :             set_evpn_gw_ip_ipv4_cmd,
    4578             :             "set evpn gateway-ip ipv4 A.B.C.D",
    4579             :             SET_STR
    4580             :             EVPN_HELP_STR
    4581             :             "Set gateway IP for prefix advertisement route\n"
    4582             :             "IPv4 address\n"
    4583             :             "Gateway IP address in IPv4 format\n")
    4584             : {
    4585           0 :         int ret;
    4586           0 :         union sockunion su;
    4587           0 :         const char *xpath =
    4588             :                 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
    4589           0 :         char xpath_value[XPATH_MAXLEN];
    4590             : 
    4591           0 :         ret = str2sockunion(argv[4]->arg, &su);
    4592           0 :         if (ret < 0) {
    4593           0 :                 vty_out(vty, "%% Malformed gateway IP\n");
    4594           0 :                 return CMD_WARNING_CONFIG_FAILED;
    4595             :         }
    4596             : 
    4597           0 :         if (su.sin.sin_addr.s_addr == 0 ||
    4598           0 :             !ipv4_unicast_valid(&su.sin.sin_addr)) {
    4599           0 :                 vty_out(vty,
    4600             :                         "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
    4601           0 :                 return CMD_WARNING_CONFIG_FAILED;
    4602             :         }
    4603             : 
    4604           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4605             : 
    4606           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4607             :                  "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
    4608             :                  xpath);
    4609             : 
    4610           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
    4611           0 :         return nb_cli_apply_changes(vty, NULL);
    4612             : }
    4613             : 
    4614           0 : DEFUN_YANG (no_set_evpn_gw_ip_ipv4,
    4615             :             no_set_evpn_gw_ip_ipv4_cmd,
    4616             :             "no set evpn gateway-ip ipv4 A.B.C.D",
    4617             :             NO_STR
    4618             :             SET_STR
    4619             :             EVPN_HELP_STR
    4620             :             "Set gateway IP for prefix advertisement route\n"
    4621             :             "IPv4 address\n"
    4622             :             "Gateway IP address in IPv4 format\n")
    4623             : {
    4624           0 :         int ret;
    4625           0 :         union sockunion su;
    4626           0 :         const char *xpath =
    4627             :                 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
    4628             : 
    4629           0 :         ret = str2sockunion(argv[5]->arg, &su);
    4630           0 :         if (ret < 0) {
    4631           0 :                 vty_out(vty, "%% Malformed gateway IP\n");
    4632           0 :                 return CMD_WARNING_CONFIG_FAILED;
    4633             :         }
    4634             : 
    4635           0 :         if (su.sin.sin_addr.s_addr == 0 ||
    4636           0 :             !ipv4_unicast_valid(&su.sin.sin_addr)) {
    4637           0 :                 vty_out(vty,
    4638             :                         "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
    4639           0 :                 return CMD_WARNING_CONFIG_FAILED;
    4640             :         }
    4641             : 
    4642           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4643             : 
    4644           0 :         return nb_cli_apply_changes(vty, NULL);
    4645             : }
    4646             : 
    4647           0 : DEFUN_YANG (set_evpn_gw_ip_ipv6,
    4648             :             set_evpn_gw_ip_ipv6_cmd,
    4649             :             "set evpn gateway-ip ipv6 X:X::X:X",
    4650             :             SET_STR
    4651             :             EVPN_HELP_STR
    4652             :             "Set gateway IP for prefix advertisement route\n"
    4653             :             "IPv6 address\n"
    4654             :             "Gateway IP address in IPv6 format\n")
    4655             : {
    4656           0 :         int ret;
    4657           0 :         union sockunion su;
    4658           0 :         const char *xpath =
    4659             :                 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
    4660           0 :         char xpath_value[XPATH_MAXLEN];
    4661             : 
    4662           0 :         ret = str2sockunion(argv[4]->arg, &su);
    4663           0 :         if (ret < 0) {
    4664           0 :                 vty_out(vty, "%% Malformed gateway IP\n");
    4665           0 :                 return CMD_WARNING_CONFIG_FAILED;
    4666             :         }
    4667             : 
    4668           0 :         if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
    4669           0 :             || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
    4670           0 :                 vty_out(vty,
    4671             :                         "%% Gateway IP cannot be a linklocal or multicast address\n");
    4672           0 :                 return CMD_WARNING_CONFIG_FAILED;
    4673             :         }
    4674             : 
    4675           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4676             : 
    4677           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4678             :                  "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
    4679             :                  xpath);
    4680             : 
    4681           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
    4682           0 :         return nb_cli_apply_changes(vty, NULL);
    4683             : }
    4684             : 
    4685           0 : DEFUN_YANG (no_set_evpn_gw_ip_ipv6,
    4686             :             no_set_evpn_gw_ip_ipv6_cmd,
    4687             :             "no set evpn gateway-ip ipv6 X:X::X:X",
    4688             :             NO_STR
    4689             :             SET_STR
    4690             :             EVPN_HELP_STR
    4691             :             "Set gateway IP for prefix advertisement route\n"
    4692             :             "IPv4 address\n"
    4693             :             "Gateway IP address in IPv4 format\n")
    4694             : {
    4695           0 :         int ret;
    4696           0 :         union sockunion su;
    4697           0 :         const char *xpath =
    4698             :                 "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
    4699             : 
    4700           0 :         ret = str2sockunion(argv[5]->arg, &su);
    4701           0 :         if (ret < 0) {
    4702           0 :                 vty_out(vty, "%% Malformed gateway IP\n");
    4703           0 :                 return CMD_WARNING_CONFIG_FAILED;
    4704             :         }
    4705             : 
    4706           0 :         if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
    4707           0 :             || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
    4708           0 :                 vty_out(vty,
    4709             :                         "%% Gateway IP cannot be a linklocal or multicast address\n");
    4710           0 :                 return CMD_WARNING_CONFIG_FAILED;
    4711             :         }
    4712             : 
    4713           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4714             : 
    4715           0 :         return nb_cli_apply_changes(vty, NULL);
    4716             : }
    4717             : 
    4718           0 : DEFPY_YANG(match_vrl_source_vrf,
    4719             :       match_vrl_source_vrf_cmd,
    4720             :       "match source-vrf NAME$vrf_name",
    4721             :       MATCH_STR
    4722             :       "source vrf\n"
    4723             :       "The VRF name\n")
    4724             : {
    4725           0 :         const char *xpath =
    4726             :                 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
    4727           0 :         char xpath_value[XPATH_MAXLEN];
    4728             : 
    4729           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4730           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4731             :                  "%s/rmap-match-condition/frr-bgp-route-map:source-vrf", xpath);
    4732           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, vrf_name);
    4733             : 
    4734           0 :         return nb_cli_apply_changes(vty, NULL);
    4735             : }
    4736             : 
    4737           0 : DEFPY_YANG(no_match_vrl_source_vrf,
    4738             :       no_match_vrl_source_vrf_cmd,
    4739             :       "no match source-vrf NAME$vrf_name",
    4740             :       NO_STR MATCH_STR
    4741             :       "source vrf\n"
    4742             :       "The VRF name\n")
    4743             : {
    4744           0 :         const char *xpath =
    4745             :                 "./match-condition[condition='frr-bgp-route-map:source-vrf']";
    4746             : 
    4747           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4748           0 :         return nb_cli_apply_changes(vty, NULL);
    4749             : }
    4750             : 
    4751           0 : DEFPY_YANG (match_peer,
    4752             :        match_peer_cmd,
    4753             :        "match peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
    4754             :        MATCH_STR
    4755             :        "Match peer address\n"
    4756             :        "IP address of peer\n"
    4757             :        "IPv6 address of peer\n"
    4758             :        "Interface name of peer or peer group name\n")
    4759             : {
    4760           0 :         const char *xpath =
    4761             :                 "./match-condition[condition='frr-bgp-route-map:peer']";
    4762           0 :         char xpath_value[XPATH_MAXLEN];
    4763             : 
    4764           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4765             : 
    4766           0 :         if (addrv4_str) {
    4767           0 :                 snprintf(
    4768             :                         xpath_value, sizeof(xpath_value),
    4769             :                         "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
    4770             :                         xpath);
    4771           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    4772             :                                       addrv4_str);
    4773           0 :         } else if (addrv6_str) {
    4774           0 :                 snprintf(
    4775             :                         xpath_value, sizeof(xpath_value),
    4776             :                         "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address",
    4777             :                         xpath);
    4778           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    4779             :                                       addrv6_str);
    4780             :         } else {
    4781           0 :                 snprintf(
    4782             :                         xpath_value, sizeof(xpath_value),
    4783             :                         "%s/rmap-match-condition/frr-bgp-route-map:peer-interface",
    4784             :                         xpath);
    4785           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, intf);
    4786             :         }
    4787             : 
    4788           0 :         return nb_cli_apply_changes(vty, NULL);
    4789             : }
    4790             : 
    4791           0 : DEFUN_YANG (match_peer_local,
    4792             :             match_peer_local_cmd,
    4793             :             "match peer local",
    4794             :             MATCH_STR
    4795             :             "Match peer address\n"
    4796             :             "Static or Redistributed routes\n")
    4797             : {
    4798           0 :         const char *xpath =
    4799             :                 "./match-condition[condition='frr-bgp-route-map:peer']";
    4800           0 :         char xpath_value[XPATH_MAXLEN];
    4801             : 
    4802           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4803             : 
    4804           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4805             :                  "%s/rmap-match-condition/frr-bgp-route-map:peer-local", xpath);
    4806           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
    4807             : 
    4808           0 :         return nb_cli_apply_changes(vty, NULL);
    4809             : }
    4810             : 
    4811           0 : DEFUN_YANG (no_match_peer,
    4812             :             no_match_peer_cmd,
    4813             :             "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
    4814             :             NO_STR
    4815             :             MATCH_STR
    4816             :             "Match peer address\n"
    4817             :             "Static or Redistributed routes\n"
    4818             :             "IP address of peer\n"
    4819             :             "IPv6 address of peer\n"
    4820             :             "Interface name of peer\n")
    4821             : {
    4822           0 :         const char *xpath =
    4823             :                 "./match-condition[condition='frr-bgp-route-map:peer']";
    4824             : 
    4825           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4826             : 
    4827           0 :         return nb_cli_apply_changes(vty, NULL);
    4828             : }
    4829             : 
    4830             : #ifdef HAVE_SCRIPTING
    4831             : DEFUN_YANG (match_script,
    4832             :             match_script_cmd,
    4833             :             "[no] match script WORD",
    4834             :             NO_STR
    4835             :             MATCH_STR
    4836             :             "Execute script to determine match\n"
    4837             :             "The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
    4838             : {
    4839             :         bool no = strmatch(argv[0]->text, "no");
    4840             :         int i = 0;
    4841             :         argv_find(argv, argc, "WORD", &i);
    4842             :         const char *script = argv[i]->arg;
    4843             :         const char *xpath =
    4844             :                 "./match-condition[condition='frr-bgp-route-map:match-script']";
    4845             :         char xpath_value[XPATH_MAXLEN];
    4846             : 
    4847             :         if (no) {
    4848             :                 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4849             :                 snprintf(xpath_value, sizeof(xpath_value),
    4850             :                          "%s/rmap-match-condition/frr-bgp-route-map:script",
    4851             :                          xpath);
    4852             :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
    4853             :                                       script);
    4854             : 
    4855             :                 return nb_cli_apply_changes(vty, NULL);
    4856             :         }
    4857             : 
    4858             :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4859             :         snprintf(xpath_value, sizeof(xpath_value),
    4860             :                         "%s/rmap-match-condition/frr-bgp-route-map:script",
    4861             :                         xpath);
    4862             :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    4863             :                         script);
    4864             : 
    4865             :         return nb_cli_apply_changes(vty, NULL);
    4866             : }
    4867             : #endif /* HAVE_SCRIPTING */
    4868             : 
    4869             : /* match probability */
    4870           0 : DEFUN_YANG (match_probability,
    4871             :             match_probability_cmd,
    4872             :             "match probability (0-100)",
    4873             :             MATCH_STR
    4874             :             "Match portion of routes defined by percentage value\n"
    4875             :             "Percentage of routes\n")
    4876             : {
    4877           0 :         int idx_number = 2;
    4878             : 
    4879           0 :         const char *xpath =
    4880             :                 "./match-condition[condition='frr-bgp-route-map:probability']";
    4881           0 :         char xpath_value[XPATH_MAXLEN];
    4882             : 
    4883           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4884           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4885             :                  "%s/rmap-match-condition/frr-bgp-route-map:probability",
    4886             :                  xpath);
    4887           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    4888           0 :                               argv[idx_number]->arg);
    4889             : 
    4890           0 :         return nb_cli_apply_changes(vty, NULL);
    4891             : }
    4892             : 
    4893             : 
    4894           0 : DEFUN_YANG (no_match_probability,
    4895             :             no_match_probability_cmd,
    4896             :             "no match probability [(1-99)]",
    4897             :             NO_STR
    4898             :             MATCH_STR
    4899             :             "Match portion of routes defined by percentage value\n"
    4900             :             "Percentage of routes\n")
    4901             : {
    4902           0 :         int idx_number = 3;
    4903           0 :         const char *xpath =
    4904             :                 "./match-condition[condition='frr-bgp-route-map:probability']";
    4905           0 :         char xpath_value[XPATH_MAXLEN];
    4906             : 
    4907           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4908             : 
    4909           0 :         if (argc <= idx_number)
    4910           0 :                 return nb_cli_apply_changes(vty, NULL);
    4911             : 
    4912           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4913             :                  "%s/rmap-match-condition/frr-bgp-route-map:probability",
    4914             :                  xpath);
    4915           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
    4916           0 :                               argv[idx_number]->arg);
    4917             : 
    4918           0 :         return nb_cli_apply_changes(vty, NULL);
    4919             : }
    4920             : 
    4921             : 
    4922           0 : DEFPY_YANG (match_ip_route_source,
    4923             :        match_ip_route_source_cmd,
    4924             :        "match ip route-source ACCESSLIST4_NAME",
    4925             :        MATCH_STR
    4926             :        IP_STR
    4927             :        "Match advertising source address of route\n"
    4928             :        "IP Access-list name\n")
    4929             : {
    4930           0 :         const char *xpath =
    4931             :                 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
    4932           0 :         char xpath_value[XPATH_MAXLEN + 32];
    4933           0 :         int idx_acl = 3;
    4934             : 
    4935           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4936           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4937             :                         "%s/rmap-match-condition/frr-bgp-route-map:list-name",
    4938             :                         xpath);
    4939           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    4940           0 :                               argv[idx_acl]->arg);
    4941             : 
    4942           0 :         return nb_cli_apply_changes(vty, NULL);
    4943             : }
    4944             : 
    4945             : 
    4946           0 : DEFUN_YANG (no_match_ip_route_source,
    4947             :             no_match_ip_route_source_cmd,
    4948             :             "no match ip route-source [ACCESSLIST4_NAME]",
    4949             :             NO_STR
    4950             :             MATCH_STR
    4951             :             IP_STR
    4952             :             "Match advertising source address of route\n"
    4953             :             "IP Access-list name\n")
    4954             : {
    4955           0 :         const char *xpath =
    4956             :                 "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
    4957             : 
    4958           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    4959           0 :         return nb_cli_apply_changes(vty, NULL);
    4960             : }
    4961             : 
    4962           0 : DEFUN_YANG (match_ip_route_source_prefix_list,
    4963             :             match_ip_route_source_prefix_list_cmd,
    4964             :             "match ip route-source prefix-list PREFIXLIST_NAME",
    4965             :             MATCH_STR
    4966             :             IP_STR
    4967             :             "Match advertising source address of route\n"
    4968             :             "Match entries of prefix-lists\n"
    4969             :             "IP prefix-list name\n")
    4970             : {
    4971           0 :         int idx_word = 4;
    4972           0 :         const char *xpath =
    4973             :                 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
    4974           0 :         char xpath_value[XPATH_MAXLEN + 32];
    4975             : 
    4976           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    4977           0 :         snprintf(xpath_value, sizeof(xpath_value),
    4978             :                  "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
    4979           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    4980           0 :                               argv[idx_word]->arg);
    4981             : 
    4982           0 :         return nb_cli_apply_changes(vty, NULL);
    4983             : }
    4984             : 
    4985             : 
    4986           0 : DEFUN_YANG (no_match_ip_route_source_prefix_list,
    4987             :             no_match_ip_route_source_prefix_list_cmd,
    4988             :             "no match ip route-source prefix-list [PREFIXLIST_NAME]",
    4989             :             NO_STR
    4990             :             MATCH_STR
    4991             :             IP_STR
    4992             :             "Match advertising source address of route\n"
    4993             :             "Match entries of prefix-lists\n"
    4994             :             "IP prefix-list name\n")
    4995             : {
    4996           0 :         const char *xpath =
    4997             :                 "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
    4998             : 
    4999           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5000           0 :         return nb_cli_apply_changes(vty, NULL);
    5001             : }
    5002             : 
    5003           0 : DEFUN_YANG (match_local_pref,
    5004             :             match_local_pref_cmd,
    5005             :             "match local-preference (0-4294967295)",
    5006             :             MATCH_STR
    5007             :             "Match local-preference of route\n"
    5008             :             "Metric value\n")
    5009             : {
    5010           0 :         int idx_number = 2;
    5011             : 
    5012           0 :         const char *xpath =
    5013             :                 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
    5014           0 :         char xpath_value[XPATH_MAXLEN];
    5015             : 
    5016           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5017           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5018             :                  "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
    5019             :                  xpath);
    5020           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5021           0 :                               argv[idx_number]->arg);
    5022             : 
    5023           0 :         return nb_cli_apply_changes(vty, NULL);
    5024             : }
    5025             : 
    5026             : 
    5027           0 : DEFUN_YANG (no_match_local_pref,
    5028             :             no_match_local_pref_cmd,
    5029             :             "no match local-preference [(0-4294967295)]",
    5030             :             NO_STR
    5031             :             MATCH_STR
    5032             :             "Match local preference of route\n"
    5033             :             "Local preference value\n")
    5034             : {
    5035           0 :         int idx_localpref = 3;
    5036           0 :         const char *xpath =
    5037             :                 "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
    5038           0 :         char xpath_value[XPATH_MAXLEN];
    5039             : 
    5040           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5041             : 
    5042           0 :         if (argc <= idx_localpref)
    5043           0 :                 return nb_cli_apply_changes(vty, NULL);
    5044             : 
    5045           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5046             :                  "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
    5047             :                  xpath);
    5048           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
    5049           0 :                               argv[idx_localpref]->arg);
    5050             : 
    5051           0 :         return nb_cli_apply_changes(vty, NULL);
    5052             : }
    5053             : 
    5054           0 : DEFUN_YANG(match_alias, match_alias_cmd, "match alias ALIAS_NAME",
    5055             :            MATCH_STR
    5056             :            "Match BGP community alias name\n"
    5057             :            "BGP community alias name\n")
    5058             : {
    5059           0 :         const char *alias = argv[2]->arg;
    5060           0 :         struct community_alias ca1;
    5061           0 :         struct community_alias *lookup_alias;
    5062             : 
    5063           0 :         const char *xpath =
    5064             :                 "./match-condition[condition='frr-bgp-route-map:match-alias']";
    5065           0 :         char xpath_value[XPATH_MAXLEN];
    5066             : 
    5067           0 :         memset(&ca1, 0, sizeof(ca1));
    5068           0 :         strlcpy(ca1.alias, alias, sizeof(ca1.alias));
    5069           0 :         lookup_alias = bgp_ca_alias_lookup(&ca1);
    5070           0 :         if (!lookup_alias) {
    5071           0 :                 vty_out(vty, "%% BGP alias name '%s' does not exist\n", alias);
    5072           0 :                 return CMD_WARNING_CONFIG_FAILED;
    5073             :         }
    5074             : 
    5075           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5076           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5077             :                  "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
    5078           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, alias);
    5079             : 
    5080           0 :         return nb_cli_apply_changes(vty, NULL);
    5081             : }
    5082             : 
    5083             : 
    5084           0 : DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
    5085             :            NO_STR MATCH_STR
    5086             :            "Match BGP community alias name\n"
    5087             :            "BGP community alias name\n")
    5088             : {
    5089           0 :         int idx_alias = 3;
    5090           0 :         const char *xpath =
    5091             :                 "./match-condition[condition='frr-bgp-route-map:match-alias']";
    5092           0 :         char xpath_value[XPATH_MAXLEN];
    5093             : 
    5094           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5095             : 
    5096           0 :         if (argc <= idx_alias)
    5097           0 :                 return nb_cli_apply_changes(vty, NULL);
    5098             : 
    5099           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5100             :                  "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
    5101           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
    5102           0 :                               argv[idx_alias]->arg);
    5103             : 
    5104           0 :         return nb_cli_apply_changes(vty, NULL);
    5105             : }
    5106             : 
    5107           0 : DEFPY_YANG (match_community,
    5108             :        match_community_cmd,
    5109             :        "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
    5110             :        MATCH_STR
    5111             :        "Match BGP community list\n"
    5112             :        "Community-list number (standard)\n"
    5113             :        "Community-list number (expanded)\n"
    5114             :        "Community-list name\n"
    5115             :        "Do exact matching of communities\n")
    5116             : {
    5117           0 :         const char *xpath =
    5118             :                 "./match-condition[condition='frr-bgp-route-map:match-community']";
    5119           0 :         char xpath_value[XPATH_MAXLEN];
    5120           0 :         char xpath_match[XPATH_MAXLEN];
    5121           0 :         int idx_comm_list = 2;
    5122             : 
    5123           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5124             : 
    5125           0 :         snprintf(
    5126             :                 xpath_value, sizeof(xpath_value),
    5127             :                 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
    5128             :                 xpath);
    5129           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
    5130             : 
    5131           0 :         if (argc == 4) {
    5132           0 :                 snprintf(
    5133             :                         xpath_match, sizeof(xpath_match),
    5134             :                         "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
    5135             :                         xpath);
    5136           0 :                 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
    5137             :                                 "true");
    5138             :         } else {
    5139           0 :                 snprintf(
    5140             :                         xpath_match, sizeof(xpath_match),
    5141             :                         "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
    5142             :                         xpath);
    5143           0 :                 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
    5144             :                                 "false");
    5145             :         }
    5146             : 
    5147           0 :         return nb_cli_apply_changes(vty, NULL);
    5148             : }
    5149             : 
    5150           0 : DEFUN_YANG (no_match_community,
    5151             :             no_match_community_cmd,
    5152             :             "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
    5153             :             NO_STR
    5154             :             MATCH_STR
    5155             :             "Match BGP community list\n"
    5156             :             "Community-list number (standard)\n"
    5157             :             "Community-list number (expanded)\n"
    5158             :             "Community-list name\n"
    5159             :             "Do exact matching of communities\n")
    5160             : {
    5161           0 :         const char *xpath =
    5162             :                 "./match-condition[condition='frr-bgp-route-map:match-community']";
    5163             : 
    5164           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5165           0 :         return nb_cli_apply_changes(vty, NULL);
    5166             : }
    5167             : 
    5168           0 : DEFPY_YANG (match_lcommunity,
    5169             :             match_lcommunity_cmd,
    5170             :             "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
    5171             :             MATCH_STR
    5172             :             "Match BGP large community list\n"
    5173             :             "Large Community-list number (standard)\n"
    5174             :             "Large Community-list number (expanded)\n"
    5175             :             "Large Community-list name\n"
    5176             :             "Do exact matching of communities\n")
    5177             : {
    5178           0 :         const char *xpath =
    5179             :                 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
    5180           0 :         char xpath_value[XPATH_MAXLEN];
    5181           0 :         char xpath_match[XPATH_MAXLEN];
    5182           0 :         int idx_lcomm_list = 2;
    5183             : 
    5184           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5185             : 
    5186           0 :         snprintf(
    5187             :                 xpath_value, sizeof(xpath_value),
    5188             :                 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
    5189             :                 xpath);
    5190           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
    5191             : 
    5192           0 :         if (argc == 4) {
    5193           0 :                 snprintf(
    5194             :                         xpath_match, sizeof(xpath_match),
    5195             :                         "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
    5196             :                         xpath);
    5197           0 :                 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
    5198             :                                 "true");
    5199             :         } else {
    5200           0 :                 snprintf(
    5201             :                         xpath_match, sizeof(xpath_match),
    5202             :                         "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
    5203             :                         xpath);
    5204           0 :                 nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
    5205             :                                 "false");
    5206             :         }
    5207             : 
    5208           0 :         return nb_cli_apply_changes(vty, NULL);
    5209             : }
    5210             : 
    5211           0 : DEFUN_YANG (no_match_lcommunity,
    5212             :             no_match_lcommunity_cmd,
    5213             :             "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
    5214             :             NO_STR
    5215             :             MATCH_STR
    5216             :             "Match BGP large community list\n"
    5217             :             "Large Community-list number (standard)\n"
    5218             :             "Large Community-list number (expanded)\n"
    5219             :             "Large Community-list name\n"
    5220             :             "Do exact matching of communities\n")
    5221             : {
    5222           0 :         const char *xpath =
    5223             :                 "./match-condition[condition='frr-bgp-route-map:match-large-community']";
    5224             : 
    5225           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5226           0 :         return nb_cli_apply_changes(vty, NULL);
    5227             : }
    5228             : 
    5229           0 : DEFPY_YANG (match_ecommunity,
    5230             :             match_ecommunity_cmd,
    5231             :             "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>",
    5232             :             MATCH_STR
    5233             :             "Match BGP/VPN extended community list\n"
    5234             :             "Extended community-list number (standard)\n"
    5235             :             "Extended community-list number (expanded)\n"
    5236             :             "Extended community-list name\n")
    5237             : {
    5238           0 :         const char *xpath =
    5239             :                 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
    5240           0 :         char xpath_value[XPATH_MAXLEN];
    5241           0 :         int idx_comm_list = 2;
    5242             : 
    5243           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5244             : 
    5245           0 :         snprintf(
    5246             :                 xpath_value, sizeof(xpath_value),
    5247             :                 "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
    5248             :                 xpath);
    5249           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
    5250             : 
    5251           0 :         return nb_cli_apply_changes(vty, NULL);
    5252             : }
    5253             : 
    5254             : 
    5255           0 : DEFUN_YANG (no_match_ecommunity,
    5256             :             no_match_ecommunity_cmd,
    5257             :             "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
    5258             :             NO_STR
    5259             :             MATCH_STR
    5260             :             "Match BGP/VPN extended community list\n"
    5261             :             "Extended community-list number (standard)\n"
    5262             :             "Extended community-list number (expanded)\n"
    5263             :             "Extended community-list name\n")
    5264             : {
    5265           0 :         const char *xpath =
    5266             :                 "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
    5267             : 
    5268           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5269           0 :         return nb_cli_apply_changes(vty, NULL);
    5270             : }
    5271             : 
    5272             : 
    5273           0 : DEFUN_YANG (match_aspath,
    5274             :             match_aspath_cmd,
    5275             :             "match as-path AS_PATH_FILTER_NAME",
    5276             :             MATCH_STR
    5277             :             "Match BGP AS path list\n"
    5278             :             "AS path access-list name\n")
    5279             : {
    5280           0 :         int idx_word = 2;
    5281             : 
    5282           0 :         const char *xpath =
    5283             :                 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
    5284           0 :         char xpath_value[XPATH_MAXLEN];
    5285             : 
    5286           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5287           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5288             :                  "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
    5289           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5290           0 :                               argv[idx_word]->arg);
    5291             : 
    5292           0 :         return nb_cli_apply_changes(vty, NULL);
    5293             : }
    5294             : 
    5295             : 
    5296           0 : DEFUN_YANG (no_match_aspath,
    5297             :             no_match_aspath_cmd,
    5298             :             "no match as-path [AS_PATH_FILTER_NAME]",
    5299             :             NO_STR
    5300             :             MATCH_STR
    5301             :             "Match BGP AS path list\n"
    5302             :             "AS path access-list name\n")
    5303             : {
    5304           0 :         const char *xpath =
    5305             :                 "./match-condition[condition='frr-bgp-route-map:as-path-list']";
    5306             : 
    5307           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5308             : 
    5309           0 :         return nb_cli_apply_changes(vty, NULL);
    5310             : }
    5311             : 
    5312           0 : DEFUN_YANG (match_origin,
    5313             :             match_origin_cmd,
    5314             :             "match origin <egp|igp|incomplete>",
    5315             :             MATCH_STR
    5316             :             "BGP origin code\n"
    5317             :             "remote EGP\n"
    5318             :             "local IGP\n"
    5319             :              "unknown heritage\n")
    5320             : {
    5321           0 :         int idx_origin = 2;
    5322           0 :         const char *origin_type;
    5323           0 :         const char *xpath =
    5324             :                 "./match-condition[condition='frr-bgp-route-map:match-origin']";
    5325           0 :         char xpath_value[XPATH_MAXLEN];
    5326             : 
    5327           0 :         if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
    5328             :                 origin_type = "igp";
    5329           0 :         else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
    5330             :                 origin_type = "egp";
    5331           0 :         else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
    5332             :                 origin_type = "incomplete";
    5333             :         else {
    5334           0 :                 vty_out(vty, "%% Invalid match origin type\n");
    5335           0 :                 return CMD_WARNING_CONFIG_FAILED;
    5336             :         }
    5337             : 
    5338           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5339           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5340             :                  "%s/rmap-match-condition/frr-bgp-route-map:origin", xpath);
    5341           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
    5342             : 
    5343           0 :         return nb_cli_apply_changes(vty, NULL);
    5344             : }
    5345             : 
    5346             : 
    5347           0 : DEFUN_YANG (no_match_origin,
    5348             :             no_match_origin_cmd,
    5349             :             "no match origin [<egp|igp|incomplete>]",
    5350             :             NO_STR
    5351             :             MATCH_STR
    5352             :             "BGP origin code\n"
    5353             :             "remote EGP\n"
    5354             :             "local IGP\n"
    5355             :             "unknown heritage\n")
    5356             : {
    5357           0 :         const char *xpath =
    5358             :                 "./match-condition[condition='frr-bgp-route-map:match-origin']";
    5359           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5360           0 :         return nb_cli_apply_changes(vty, NULL);
    5361             : }
    5362             : 
    5363           0 : DEFUN_YANG (set_table_id,
    5364             :             set_table_id_cmd,
    5365             :             "set table (1-4294967295)",
    5366             :             SET_STR
    5367             :             "export route to non-main kernel table\n"
    5368             :             "Kernel routing table id\n")
    5369             : {
    5370           0 :         int idx_number = 2;
    5371           0 :         const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
    5372           0 :         char xpath_value[XPATH_MAXLEN];
    5373             : 
    5374           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5375           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5376             :                  "%s/rmap-set-action/frr-bgp-route-map:table", xpath);
    5377           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5378           0 :                               argv[idx_number]->arg);
    5379           0 :         return nb_cli_apply_changes(vty, NULL);
    5380             : }
    5381             : 
    5382           0 : DEFUN_YANG (no_set_table_id,
    5383             :             no_set_table_id_cmd,
    5384             :             "no set table",
    5385             :             NO_STR
    5386             :             SET_STR
    5387             :             "export route to non-main kernel table\n")
    5388             : {
    5389           0 :         const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
    5390           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5391           0 :         return nb_cli_apply_changes(vty, NULL);
    5392             : }
    5393             : 
    5394           0 : DEFUN_YANG (set_ip_nexthop_peer,
    5395             :             set_ip_nexthop_peer_cmd,
    5396             :             "[no] set ip next-hop peer-address",
    5397             :             NO_STR
    5398             :             SET_STR
    5399             :             IP_STR
    5400             :             "Next hop address\n"
    5401             :             "Use peer address (for BGP only)\n")
    5402             : {
    5403           0 :         char xpath_value[XPATH_MAXLEN];
    5404           0 :         const char *xpath =
    5405             :                 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
    5406             : 
    5407           0 :         if (strmatch(argv[0]->text, "no"))
    5408           0 :                 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5409             :         else {
    5410           0 :                 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5411           0 :                 snprintf(xpath_value, sizeof(xpath_value),
    5412             :                          "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
    5413             :                          xpath);
    5414           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5415             :                                       "peer-address");
    5416             :         }
    5417           0 :         return nb_cli_apply_changes(vty, NULL);
    5418             : }
    5419             : 
    5420           0 : DEFUN_YANG (set_ip_nexthop_unchanged,
    5421             :             set_ip_nexthop_unchanged_cmd,
    5422             :             "[no] set ip next-hop unchanged",
    5423             :             NO_STR
    5424             :             SET_STR
    5425             :             IP_STR
    5426             :             "Next hop address\n"
    5427             :             "Don't modify existing Next hop address\n")
    5428             : {
    5429           0 :         char xpath_value[XPATH_MAXLEN];
    5430           0 :         const char *xpath =
    5431             :                 "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
    5432             : 
    5433           0 :         if (strmatch(argv[0]->text, "no"))
    5434           0 :                 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5435             :         else {
    5436           0 :                 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5437           0 :                 snprintf(xpath_value, sizeof(xpath_value),
    5438             :                          "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
    5439             :                          xpath);
    5440           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5441             :                                       "unchanged");
    5442             :         }
    5443           0 :         return nb_cli_apply_changes(vty, NULL);
    5444             : }
    5445             : 
    5446           0 : DEFUN_YANG (set_distance,
    5447             :             set_distance_cmd,
    5448             :             "set distance (0-255)",
    5449             :             SET_STR
    5450             :             "BGP Administrative Distance to use\n"
    5451             :             "Distance value\n")
    5452             : {
    5453           0 :         int idx_number = 2;
    5454           0 :         const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
    5455           0 :         char xpath_value[XPATH_MAXLEN];
    5456             : 
    5457           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5458           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5459             :                  "%s/rmap-set-action/frr-bgp-route-map:distance", xpath);
    5460           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5461           0 :                               argv[idx_number]->arg);
    5462           0 :         return nb_cli_apply_changes(vty, NULL);
    5463             : }
    5464             : 
    5465           0 : DEFUN_YANG (no_set_distance,
    5466             :             no_set_distance_cmd,
    5467             :             "no set distance [(0-255)]",
    5468             :             NO_STR SET_STR
    5469             :             "BGP Administrative Distance to use\n"
    5470             :             "Distance value\n")
    5471             : {
    5472           0 :         const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
    5473             : 
    5474           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5475           0 :         return nb_cli_apply_changes(vty, NULL);
    5476             : }
    5477             : 
    5478           0 : DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
    5479             :            "[no] set l3vpn next-hop encapsulation gre",
    5480             :            NO_STR SET_STR
    5481             :            "L3VPN operations\n"
    5482             :            "Next hop Information\n"
    5483             :            "Encapsulation options (for BGP only)\n"
    5484             :            "Accept L3VPN traffic over GRE encapsulation\n")
    5485             : {
    5486           0 :         const char *xpath =
    5487             :                 "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']";
    5488           0 :         const char *xpath_value =
    5489             :                 "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation";
    5490           0 :         enum nb_operation operation;
    5491             : 
    5492           0 :         if (no)
    5493             :                 operation = NB_OP_DESTROY;
    5494             :         else
    5495           0 :                 operation = NB_OP_CREATE;
    5496             : 
    5497           0 :         nb_cli_enqueue_change(vty, xpath, operation, NULL);
    5498           0 :         if (operation == NB_OP_DESTROY)
    5499           0 :                 return nb_cli_apply_changes(vty, NULL);
    5500             : 
    5501           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "gre");
    5502             : 
    5503           0 :         return nb_cli_apply_changes(vty, NULL);
    5504             : }
    5505             : 
    5506           0 : DEFUN_YANG (set_local_pref,
    5507             :             set_local_pref_cmd,
    5508             :             "set local-preference WORD",
    5509             :             SET_STR
    5510             :             "BGP local preference path attribute\n"
    5511             :             "Preference value (0-4294967295)\n")
    5512             : {
    5513           0 :         int idx_number = 2;
    5514           0 :         const char *xpath =
    5515             :                 "./set-action[action='frr-bgp-route-map:set-local-preference']";
    5516           0 :         char xpath_value[XPATH_MAXLEN];
    5517             : 
    5518           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5519           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5520             :                  "%s/rmap-set-action/frr-bgp-route-map:local-pref", xpath);
    5521           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5522           0 :                               argv[idx_number]->arg);
    5523           0 :         return nb_cli_apply_changes(vty, NULL);
    5524             : }
    5525             : 
    5526           0 : DEFUN_YANG (no_set_local_pref,
    5527             :             no_set_local_pref_cmd,
    5528             :             "no set local-preference [WORD]",
    5529             :             NO_STR
    5530             :             SET_STR
    5531             :             "BGP local preference path attribute\n"
    5532             :             "Preference value (0-4294967295)\n")
    5533             : {
    5534           0 :         const char *xpath =
    5535             :                 "./set-action[action='frr-bgp-route-map:set-local-preference']";
    5536             : 
    5537           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5538           0 :         return nb_cli_apply_changes(vty, NULL);
    5539             : }
    5540             : 
    5541           0 : DEFUN_YANG (set_weight,
    5542             :             set_weight_cmd,
    5543             :             "set weight (0-4294967295)",
    5544             :             SET_STR
    5545             :             "BGP weight for routing table\n"
    5546             :             "Weight value\n")
    5547             : {
    5548           0 :         int idx_number = 2;
    5549           0 :         const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
    5550           0 :         char xpath_value[XPATH_MAXLEN];
    5551             : 
    5552           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5553           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5554             :                  "%s/rmap-set-action/frr-bgp-route-map:weight", xpath);
    5555           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5556           0 :                               argv[idx_number]->arg);
    5557           0 :         return nb_cli_apply_changes(vty, NULL);
    5558             : }
    5559             : 
    5560           0 : DEFUN_YANG (no_set_weight,
    5561             :             no_set_weight_cmd,
    5562             :             "no set weight [(0-4294967295)]",
    5563             :             NO_STR
    5564             :             SET_STR
    5565             :             "BGP weight for routing table\n"
    5566             :             "Weight value\n")
    5567             : {
    5568           0 :         const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
    5569             : 
    5570           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5571           0 :         return nb_cli_apply_changes(vty, NULL);
    5572             : }
    5573             : 
    5574           0 : DEFUN_YANG (set_label_index,
    5575             :             set_label_index_cmd,
    5576             :             "set label-index (0-1048560)",
    5577             :             SET_STR
    5578             :             "Label index to associate with the prefix\n"
    5579             :             "Label index value\n")
    5580             : {
    5581           0 :         int idx_number = 2;
    5582           0 :         const char *xpath =
    5583             :                 "./set-action[action='frr-bgp-route-map:label-index']";
    5584           0 :         char xpath_value[XPATH_MAXLEN];
    5585             : 
    5586           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5587           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5588             :                  "%s/rmap-set-action/frr-bgp-route-map:label-index", xpath);
    5589           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5590           0 :                               argv[idx_number]->arg);
    5591           0 :         return nb_cli_apply_changes(vty, NULL);
    5592             : }
    5593             : 
    5594           0 : DEFUN_YANG (no_set_label_index,
    5595             :             no_set_label_index_cmd,
    5596             :             "no set label-index [(0-1048560)]",
    5597             :             NO_STR
    5598             :             SET_STR
    5599             :             "Label index to associate with the prefix\n"
    5600             :             "Label index value\n")
    5601             : {
    5602           0 :         const char *xpath =
    5603             :                 "./set-action[action='frr-bgp-route-map:label-index']";
    5604             : 
    5605           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5606           0 :         return nb_cli_apply_changes(vty, NULL);
    5607             : }
    5608             : 
    5609           0 : DEFUN_YANG (set_aspath_prepend_asn,
    5610             :             set_aspath_prepend_asn_cmd,
    5611             :             "set as-path prepend (1-4294967295)...",
    5612             :             SET_STR
    5613             :             "Transform BGP AS_PATH attribute\n"
    5614             :             "Prepend to the as-path\n"
    5615             :             "AS number\n")
    5616             : {
    5617           0 :         int idx_asn = 3;
    5618           0 :         int ret;
    5619           0 :         char *str;
    5620             : 
    5621           0 :         str = argv_concat(argv, argc, idx_asn);
    5622             : 
    5623           0 :         const char *xpath =
    5624             :                 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
    5625           0 :         char xpath_value[XPATH_MAXLEN];
    5626             : 
    5627           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5628           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5629             :                  "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath);
    5630           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
    5631           0 :         ret = nb_cli_apply_changes(vty, NULL);
    5632           0 :         XFREE(MTYPE_TMP, str);
    5633           0 :         return ret;
    5634             : }
    5635             : 
    5636           0 : DEFUN_YANG (set_aspath_prepend_lastas,
    5637             :             set_aspath_prepend_lastas_cmd,
    5638             :             "set as-path prepend last-as (1-10)",
    5639             :             SET_STR
    5640             :             "Transform BGP AS_PATH attribute\n"
    5641             :             "Prepend to the as-path\n"
    5642             :             "Use the last AS-number in the as-path\n"
    5643             :             "Number of times to insert\n")
    5644             : {
    5645           0 :         int idx_num = 4;
    5646             : 
    5647           0 :         const char *xpath =
    5648             :                 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
    5649           0 :         char xpath_value[XPATH_MAXLEN];
    5650             : 
    5651           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5652           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5653             :                  "%s/rmap-set-action/frr-bgp-route-map:last-as", xpath);
    5654           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5655           0 :                               argv[idx_num]->arg);
    5656           0 :         return nb_cli_apply_changes(vty, NULL);
    5657             : }
    5658             : 
    5659           2 : DEFPY_YANG (set_aspath_replace_asn,
    5660             :             set_aspath_replace_asn_cmd,
    5661             :             "set as-path replace <any|(1-4294967295)>$replace",
    5662             :             SET_STR
    5663             :             "Transform BGP AS_PATH attribute\n"
    5664             :             "Replace AS number to local AS number\n"
    5665             :             "Replace any AS number to local AS number\n"
    5666             :             "Replace a specific AS number to local AS number\n")
    5667             : {
    5668           2 :         const char *xpath =
    5669             :                 "./set-action[action='frr-bgp-route-map:as-path-replace']";
    5670           2 :         char xpath_value[XPATH_MAXLEN];
    5671             : 
    5672           2 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5673           2 :         snprintf(xpath_value, sizeof(xpath_value),
    5674             :                  "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
    5675           2 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace);
    5676           2 :         return nb_cli_apply_changes(vty, NULL);
    5677             : }
    5678             : 
    5679           0 : DEFPY_YANG (no_set_aspath_replace_asn,
    5680             :             no_set_aspath_replace_asn_cmd,
    5681             :             "no set as-path replace [<any|(1-4294967295)>]",
    5682             :             NO_STR
    5683             :             SET_STR
    5684             :             "Transform BGP AS_PATH attribute\n"
    5685             :             "Replace AS number to local AS number\n"
    5686             :             "Replace any AS number to local AS number\n"
    5687             :             "Replace a specific AS number to local AS number\n")
    5688             : {
    5689           0 :         const char *xpath =
    5690             :                 "./set-action[action='frr-bgp-route-map:as-path-replace']";
    5691             : 
    5692           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5693           0 :         return nb_cli_apply_changes(vty, NULL);
    5694             : }
    5695             : 
    5696           0 : DEFUN_YANG (no_set_aspath_prepend,
    5697             :             no_set_aspath_prepend_cmd,
    5698             :             "no set as-path prepend [(1-4294967295)]",
    5699             :             NO_STR
    5700             :             SET_STR
    5701             :             "Transform BGP AS_PATH attribute\n"
    5702             :             "Prepend to the as-path\n"
    5703             :             "AS number\n")
    5704             : {
    5705           0 :         const char *xpath =
    5706             :                 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
    5707             : 
    5708           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5709           0 :         return nb_cli_apply_changes(vty, NULL);
    5710             : }
    5711             : 
    5712           0 : DEFUN_YANG (no_set_aspath_prepend_lastas,
    5713             :             no_set_aspath_prepend_lastas_cmd,
    5714             :             "no set as-path prepend last-as [(1-10)]",
    5715             :             NO_STR
    5716             :             SET_STR
    5717             :             "Transform BGP AS_PATH attribute\n"
    5718             :             "Prepend to the as-path\n"
    5719             :             "Use the peers AS-number\n"
    5720             :             "Number of times to insert\n")
    5721             : {
    5722           0 :         const char *xpath =
    5723             :                 "./set-action[action='frr-bgp-route-map:as-path-prepend']";
    5724             : 
    5725           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5726           0 :         return nb_cli_apply_changes(vty, NULL);
    5727             : }
    5728             : 
    5729           0 : DEFUN_YANG (set_aspath_exclude,
    5730             :             set_aspath_exclude_cmd,
    5731             :             "set as-path exclude (1-4294967295)...",
    5732             :             SET_STR
    5733             :             "Transform BGP AS-path attribute\n"
    5734             :             "Exclude from the as-path\n"
    5735             :             "AS number\n")
    5736             : {
    5737           0 :         int idx_asn = 3;
    5738           0 :         int ret;
    5739           0 :         char *str;
    5740             : 
    5741           0 :         str = argv_concat(argv, argc, idx_asn);
    5742             : 
    5743           0 :         const char *xpath =
    5744             :                 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
    5745           0 :         char xpath_value[XPATH_MAXLEN];
    5746             : 
    5747           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5748           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5749             :                  "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath);
    5750           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
    5751           0 :         ret = nb_cli_apply_changes(vty, NULL);
    5752           0 :         XFREE(MTYPE_TMP, str);
    5753           0 :         return ret;
    5754             : }
    5755             : 
    5756           0 : DEFUN_YANG (no_set_aspath_exclude,
    5757             :             no_set_aspath_exclude_cmd,
    5758             :             "no set as-path exclude (1-4294967295)...",
    5759             :             NO_STR
    5760             :             SET_STR
    5761             :             "Transform BGP AS_PATH attribute\n"
    5762             :             "Exclude from the as-path\n"
    5763             :             "AS number\n")
    5764             : {
    5765           0 :         const char *xpath =
    5766             :                 "./set-action[action='frr-bgp-route-map:as-path-exclude']";
    5767             : 
    5768           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5769           0 :         return nb_cli_apply_changes(vty, NULL);
    5770             : }
    5771             : 
    5772             : ALIAS_YANG (no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
    5773             :             "no set as-path exclude",
    5774             :             NO_STR SET_STR
    5775             :             "Transform BGP AS_PATH attribute\n"
    5776             :             "Exclude from the as-path\n")
    5777             : 
    5778           0 : DEFUN_YANG (set_community,
    5779             :             set_community_cmd,
    5780             :             "set community AA:NN...",
    5781             :             SET_STR
    5782             :             "BGP community attribute\n"
    5783             :             COMMUNITY_VAL_STR)
    5784             : {
    5785           0 :         int idx_aa_nn = 2;
    5786           0 :         int i;
    5787           0 :         int first = 0;
    5788           0 :         int additive = 0;
    5789           0 :         struct buffer *b;
    5790           0 :         struct community *com = NULL;
    5791           0 :         char *str;
    5792           0 :         char *argstr = NULL;
    5793           0 :         int ret;
    5794             : 
    5795           0 :         const char *xpath =
    5796             :                 "./set-action[action='frr-bgp-route-map:set-community']";
    5797           0 :         char xpath_value[XPATH_MAXLEN];
    5798             : 
    5799           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5800           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5801             :                  "%s/rmap-set-action/frr-bgp-route-map:community-string",
    5802             :                  xpath);
    5803             : 
    5804           0 :         b = buffer_new(1024);
    5805             : 
    5806           0 :         for (i = idx_aa_nn; i < argc; i++) {
    5807           0 :                 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
    5808             :                     == 0) {
    5809           0 :                         additive = 1;
    5810           0 :                         continue;
    5811             :                 }
    5812             : 
    5813           0 :                 if (first)
    5814           0 :                         buffer_putc(b, ' ');
    5815             :                 else
    5816             :                         first = 1;
    5817             : 
    5818           0 :                 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
    5819             :                     == 0) {
    5820           0 :                         buffer_putstr(b, "internet");
    5821           0 :                         continue;
    5822             :                 }
    5823           0 :                 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
    5824             :                     == 0) {
    5825           0 :                         buffer_putstr(b, "local-AS");
    5826           0 :                         continue;
    5827             :                 }
    5828           0 :                 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
    5829           0 :                     && strncmp(argv[i]->arg, "no-advertise",
    5830             :                                strlen(argv[i]->arg))
    5831             :                                == 0) {
    5832           0 :                         buffer_putstr(b, "no-advertise");
    5833           0 :                         continue;
    5834             :                 }
    5835           0 :                 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
    5836           0 :                     && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
    5837             :                                == 0) {
    5838           0 :                         buffer_putstr(b, "no-export");
    5839           0 :                         continue;
    5840             :                 }
    5841           0 :                 if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg))
    5842             :                     == 0) {
    5843           0 :                         buffer_putstr(b, "blackhole");
    5844           0 :                         continue;
    5845             :                 }
    5846           0 :                 if (strncmp(argv[i]->arg, "graceful-shutdown",
    5847             :                             strlen(argv[i]->arg))
    5848             :                     == 0) {
    5849           0 :                         buffer_putstr(b, "graceful-shutdown");
    5850           0 :                         continue;
    5851             :                 }
    5852           0 :                 buffer_putstr(b, argv[i]->arg);
    5853             :         }
    5854           0 :         buffer_putc(b, '\0');
    5855             : 
    5856             :         /* Fetch result string then compile it to communities attribute.  */
    5857           0 :         str = buffer_getstr(b);
    5858           0 :         buffer_free(b);
    5859             : 
    5860           0 :         if (str)
    5861           0 :                 com = community_str2com(str);
    5862             : 
    5863             :         /* Can't compile user input into communities attribute.  */
    5864           0 :         if (!com) {
    5865           0 :                 vty_out(vty, "%% Malformed communities attribute '%s'\n", str);
    5866           0 :                 XFREE(MTYPE_TMP, str);
    5867           0 :                 return CMD_WARNING_CONFIG_FAILED;
    5868             :         }
    5869           0 :         XFREE(MTYPE_TMP, str);
    5870             : 
    5871             :         /* Set communites attribute string.  */
    5872           0 :         str = community_str(com, false, false);
    5873             : 
    5874           0 :         if (additive) {
    5875           0 :                 size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
    5876           0 :                 argstr = XCALLOC(MTYPE_TMP, argstr_sz);
    5877           0 :                 strlcpy(argstr, str, argstr_sz);
    5878           0 :                 strlcat(argstr, " additive", argstr_sz);
    5879           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argstr);
    5880             :         } else
    5881           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
    5882             : 
    5883           0 :         ret = nb_cli_apply_changes(vty, NULL);
    5884             : 
    5885           0 :         if (argstr)
    5886           0 :                 XFREE(MTYPE_TMP, argstr);
    5887           0 :         community_free(&com);
    5888             : 
    5889           0 :         return ret;
    5890             : }
    5891             : 
    5892           0 : DEFUN_YANG (set_community_none,
    5893             :             set_community_none_cmd,
    5894             :             "set community none",
    5895             :             SET_STR
    5896             :             "BGP community attribute\n"
    5897             :             "No community attribute\n")
    5898             : {
    5899           0 :         const char *xpath =
    5900             :                 "./set-action[action='frr-bgp-route-map:set-community']";
    5901           0 :         char xpath_value[XPATH_MAXLEN];
    5902             : 
    5903           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5904             : 
    5905           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5906             :                  "%s/rmap-set-action/frr-bgp-route-map:community-none", xpath);
    5907           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
    5908           0 :         return nb_cli_apply_changes(vty, NULL);
    5909             : }
    5910             : 
    5911           0 : DEFUN_YANG (no_set_community,
    5912             :             no_set_community_cmd,
    5913             :             "no set community AA:NN...",
    5914             :             NO_STR
    5915             :             SET_STR
    5916             :             "BGP community attribute\n"
    5917             :             COMMUNITY_VAL_STR)
    5918             : {
    5919           0 :         const char *xpath =
    5920             :                 "./set-action[action='frr-bgp-route-map:set-community']";
    5921             : 
    5922           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5923           0 :         return nb_cli_apply_changes(vty, NULL);
    5924             : }
    5925             : 
    5926             : ALIAS_YANG (no_set_community,
    5927             :             no_set_community_short_cmd,
    5928             :             "no set community",
    5929             :             NO_STR
    5930             :             SET_STR
    5931             :             "BGP community attribute\n")
    5932             : 
    5933           0 : DEFPY_YANG (set_community_delete,
    5934             :        set_community_delete_cmd,
    5935             :        "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete",
    5936             :        SET_STR
    5937             :        "set BGP community list (for deletion)\n"
    5938             :        "Community-list number (standard)\n"
    5939             :        "Community-list number (expanded)\n"
    5940             :        "Community-list name\n"
    5941             :        "Delete matching communities\n")
    5942             : {
    5943           0 :         const char *xpath =
    5944             :                 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
    5945           0 :         char xpath_value[XPATH_MAXLEN];
    5946           0 :         int idx_comm_list = 2;
    5947             : 
    5948           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5949             : 
    5950           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5951             :                  "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
    5952             :                  xpath);
    5953           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    5954           0 :                         argv[idx_comm_list]->arg);
    5955             : 
    5956           0 :         return nb_cli_apply_changes(vty, NULL);
    5957             : 
    5958             : }
    5959             : 
    5960           0 : DEFUN_YANG (no_set_community_delete,
    5961             :             no_set_community_delete_cmd,
    5962             :             "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]",
    5963             :             NO_STR
    5964             :             SET_STR
    5965             :             "set BGP community list (for deletion)\n"
    5966             :             "Community-list number (standard)\n"
    5967             :             "Community-list number (expanded)\n"
    5968             :             "Community-list name\n"
    5969             :             "Delete matching communities\n")
    5970             : {
    5971           0 :         const char *xpath =
    5972             :                 "./set-action[action='frr-bgp-route-map:comm-list-delete']";
    5973             : 
    5974           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    5975           0 :         return nb_cli_apply_changes(vty, NULL);
    5976             : }
    5977             : 
    5978           0 : DEFUN_YANG (set_lcommunity,
    5979             :             set_lcommunity_cmd,
    5980             :             "set large-community AA:BB:CC...",
    5981             :             SET_STR
    5982             :             "BGP large community attribute\n"
    5983             :             "Large Community number in aa:bb:cc format or additive\n")
    5984             : {
    5985           0 :         char *str;
    5986           0 :         int ret;
    5987           0 :         const char *xpath =
    5988             :                 "./set-action[action='frr-bgp-route-map:set-large-community']";
    5989           0 :         char xpath_value[XPATH_MAXLEN];
    5990             : 
    5991           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    5992             : 
    5993           0 :         snprintf(xpath_value, sizeof(xpath_value),
    5994             :                  "%s/rmap-set-action/frr-bgp-route-map:large-community-string",
    5995             :                  xpath);
    5996           0 :         str = argv_concat(argv, argc, 2);
    5997           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
    5998           0 :         ret = nb_cli_apply_changes(vty, NULL);
    5999           0 :         XFREE(MTYPE_TMP, str);
    6000           0 :         return ret;
    6001             : }
    6002             : 
    6003           0 : DEFUN_YANG (set_lcommunity_none,
    6004             :             set_lcommunity_none_cmd,
    6005             :             "set large-community none",
    6006             :             SET_STR
    6007             :             "BGP large community attribute\n"
    6008             :             "No large community attribute\n")
    6009             : {
    6010           0 :         const char *xpath =
    6011             :                 "./set-action[action='frr-bgp-route-map:set-large-community']";
    6012           0 :         char xpath_value[XPATH_MAXLEN];
    6013             : 
    6014           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6015             : 
    6016           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6017             :                  "%s/rmap-set-action/frr-bgp-route-map:large-community-none",
    6018             :                  xpath);
    6019           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
    6020           0 :         return nb_cli_apply_changes(vty, NULL);
    6021             : }
    6022             : 
    6023           0 : DEFUN_YANG (no_set_lcommunity,
    6024             :             no_set_lcommunity_cmd,
    6025             :             "no set large-community none",
    6026             :             NO_STR
    6027             :             SET_STR
    6028             :             "BGP large community attribute\n"
    6029             :             "No community attribute\n")
    6030             : {
    6031           0 :         const char *xpath =
    6032             :                 "./set-action[action='frr-bgp-route-map:set-large-community']";
    6033             : 
    6034           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6035           0 :         return nb_cli_apply_changes(vty, NULL);
    6036             : }
    6037             : 
    6038           0 : DEFUN_YANG (no_set_lcommunity1,
    6039             :             no_set_lcommunity1_cmd,
    6040             :             "no set large-community AA:BB:CC...",
    6041             :             NO_STR
    6042             :             SET_STR
    6043             :             "BGP large community attribute\n"
    6044             :             "Large community in AA:BB:CC... format or additive\n")
    6045             : {
    6046           0 :         const char *xpath =
    6047             :                 "./set-action[action='frr-bgp-route-map:set-large-community']";
    6048             : 
    6049           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6050           0 :         return nb_cli_apply_changes(vty, NULL);
    6051             : }
    6052             : 
    6053             : ALIAS_YANG (no_set_lcommunity1,
    6054             :             no_set_lcommunity1_short_cmd,
    6055             :             "no set large-community",
    6056             :             NO_STR
    6057             :             SET_STR
    6058             :             "BGP large community attribute\n")
    6059             : 
    6060           0 : DEFPY_YANG (set_lcommunity_delete,
    6061             :        set_lcommunity_delete_cmd,
    6062             :        "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete",
    6063             :        SET_STR
    6064             :        "set BGP large community list (for deletion)\n"
    6065             :        "Large Community-list number (standard)\n"
    6066             :        "Large Communitly-list number (expanded)\n"
    6067             :        "Large Community-list name\n"
    6068             :        "Delete matching large communities\n")
    6069             : {
    6070           0 :         const char *xpath =
    6071             :                 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
    6072           0 :         char xpath_value[XPATH_MAXLEN];
    6073           0 :         int idx_lcomm_list = 2;
    6074             : 
    6075           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6076             : 
    6077           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6078             :                         "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
    6079             :                         xpath);
    6080           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    6081           0 :                         argv[idx_lcomm_list]->arg);
    6082             : 
    6083           0 :         return nb_cli_apply_changes(vty, NULL);
    6084             : }
    6085             : 
    6086           0 : DEFUN_YANG (no_set_lcommunity_delete,
    6087             :             no_set_lcommunity_delete_cmd,
    6088             :             "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]",
    6089             :             NO_STR
    6090             :             SET_STR
    6091             :             "set BGP large community list (for deletion)\n"
    6092             :             "Large Community-list number (standard)\n"
    6093             :             "Large Communitly-list number (expanded)\n"
    6094             :             "Large Community-list name\n"
    6095             :             "Delete matching large communities\n")
    6096             : {
    6097           0 :         const char *xpath =
    6098             :                 "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
    6099             : 
    6100           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6101           0 :         return nb_cli_apply_changes(vty, NULL);
    6102             : }
    6103             : 
    6104             : ALIAS_YANG (no_set_lcommunity_delete,
    6105             :             no_set_lcommunity_delete_short_cmd,
    6106             :             "no set large-comm-list",
    6107             :             NO_STR
    6108             :             SET_STR
    6109             :             "set BGP large community list (for deletion)\n")
    6110             : 
    6111           0 : DEFUN_YANG (set_ecommunity_rt,
    6112             :             set_ecommunity_rt_cmd,
    6113             :             "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
    6114             :             SET_STR
    6115             :             "BGP extended community attribute\n"
    6116             :             "Route Target extended community\n"
    6117             :             "VPN extended community\n")
    6118             : {
    6119           0 :         int idx_asn_nn = 3;
    6120           0 :         char *str;
    6121           0 :         int ret;
    6122           0 :         const char *xpath =
    6123             :                 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
    6124           0 :         char xpath_value[XPATH_MAXLEN];
    6125             : 
    6126           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6127             : 
    6128           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6129             :                  "%s/rmap-set-action/frr-bgp-route-map:extcommunity-rt", xpath);
    6130           0 :         str = argv_concat(argv, argc, idx_asn_nn);
    6131           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
    6132           0 :         ret = nb_cli_apply_changes(vty, NULL);
    6133           0 :         XFREE(MTYPE_TMP, str);
    6134           0 :         return ret;
    6135             : }
    6136             : 
    6137           0 : DEFUN_YANG (no_set_ecommunity_rt,
    6138             :             no_set_ecommunity_rt_cmd,
    6139             :             "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
    6140             :             NO_STR
    6141             :             SET_STR
    6142             :             "BGP extended community attribute\n"
    6143             :             "Route Target extended community\n"
    6144             :             "VPN extended community\n")
    6145             : {
    6146           0 :         const char *xpath =
    6147             :                 "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
    6148           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6149           0 :         return nb_cli_apply_changes(vty, NULL);
    6150             : }
    6151             : 
    6152             : ALIAS_YANG (no_set_ecommunity_rt,
    6153             :             no_set_ecommunity_rt_short_cmd,
    6154             :             "no set extcommunity rt",
    6155             :             NO_STR
    6156             :             SET_STR
    6157             :             "BGP extended community attribute\n"
    6158             :             "Route Target extended community\n")
    6159             : 
    6160           0 : DEFUN_YANG (set_ecommunity_soo,
    6161             :             set_ecommunity_soo_cmd,
    6162             :             "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
    6163             :             SET_STR
    6164             :            "BGP extended community attribute\n"
    6165             :            "Site-of-Origin extended community\n"
    6166             :            "VPN extended community\n")
    6167             : {
    6168           0 :         int idx_asn_nn = 3;
    6169           0 :         char *str;
    6170           0 :         int ret;
    6171           0 :         const char *xpath =
    6172             :                 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
    6173           0 :         char xpath_value[XPATH_MAXLEN];
    6174             : 
    6175           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6176             : 
    6177           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6178             :                  "%s/rmap-set-action/frr-bgp-route-map:extcommunity-soo",
    6179             :                  xpath);
    6180           0 :         str = argv_concat(argv, argc, idx_asn_nn);
    6181           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
    6182           0 :         ret = nb_cli_apply_changes(vty, NULL);
    6183           0 :         XFREE(MTYPE_TMP, str);
    6184           0 :         return ret;
    6185             : }
    6186             : 
    6187           0 : DEFUN_YANG (no_set_ecommunity_soo,
    6188             :             no_set_ecommunity_soo_cmd,
    6189             :             "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
    6190             :             NO_STR
    6191             :             SET_STR
    6192             :             "BGP extended community attribute\n"
    6193             :             "Site-of-Origin extended community\n"
    6194             :             "VPN extended community\n")
    6195             : {
    6196           0 :         const char *xpath =
    6197             :                 "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
    6198           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6199           0 :         return nb_cli_apply_changes(vty, NULL);
    6200             : }
    6201             : 
    6202             : ALIAS_YANG (no_set_ecommunity_soo,
    6203             :             no_set_ecommunity_soo_short_cmd,
    6204             :             "no set extcommunity soo",
    6205             :             NO_STR
    6206             :             SET_STR
    6207             :             "GP extended community attribute\n"
    6208             :             "Site-of-Origin extended community\n")
    6209             : 
    6210           0 : DEFUN_YANG(set_ecommunity_none, set_ecommunity_none_cmd,
    6211             :            "set extcommunity none",
    6212             :            SET_STR
    6213             :            "BGP extended community attribute\n"
    6214             :            "No extended community attribute\n")
    6215             : {
    6216           0 :         const char *xpath =
    6217             :                 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
    6218           0 :         char xpath_value[XPATH_MAXLEN];
    6219             : 
    6220           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6221             : 
    6222           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6223             :                  "%s/rmap-set-action/frr-bgp-route-map:extcommunity-none",
    6224             :                  xpath);
    6225           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
    6226           0 :         return nb_cli_apply_changes(vty, NULL);
    6227             : }
    6228             : 
    6229           0 : DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
    6230             :            "no set extcommunity none",
    6231             :            NO_STR SET_STR
    6232             :            "BGP extended community attribute\n"
    6233             :            "No extended community attribute\n")
    6234             : {
    6235           0 :         const char *xpath =
    6236             :                 "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
    6237           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6238           0 :         return nb_cli_apply_changes(vty, NULL);
    6239             : }
    6240             : 
    6241           0 : DEFUN_YANG (set_ecommunity_lb,
    6242             :             set_ecommunity_lb_cmd,
    6243             :             "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
    6244             :             SET_STR
    6245             :             "BGP extended community attribute\n"
    6246             :             "Link bandwidth extended community\n"
    6247             :             "Bandwidth value in Mbps\n"
    6248             :             "Cumulative bandwidth of all multipaths (outbound-only)\n"
    6249             :             "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
    6250             :             "Attribute is set as non-transitive\n")
    6251             : {
    6252           0 :         int idx_lb = 3;
    6253           0 :         int idx_non_transitive = 0;
    6254           0 :         const char *xpath =
    6255             :                 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
    6256           0 :         char xpath_lb_type[XPATH_MAXLEN];
    6257           0 :         char xpath_bandwidth[XPATH_MAXLEN];
    6258           0 :         char xpath_non_transitive[XPATH_MAXLEN];
    6259             : 
    6260           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6261             : 
    6262           0 :         snprintf(xpath_lb_type, sizeof(xpath_lb_type),
    6263             :                  "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type",
    6264             :                  xpath);
    6265           0 :         snprintf(xpath_bandwidth, sizeof(xpath_bandwidth),
    6266             :                  "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth",
    6267             :                  xpath);
    6268           0 :         snprintf(xpath_non_transitive, sizeof(xpath_non_transitive),
    6269             :                  "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific",
    6270             :                  xpath);
    6271             : 
    6272           0 :         if ((strcmp(argv[idx_lb]->arg, "cumulative")) == 0)
    6273           0 :                 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
    6274             :                                       "cumulative-bandwidth");
    6275           0 :         else if ((strcmp(argv[idx_lb]->arg, "num-multipaths")) == 0)
    6276           0 :                 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
    6277             :                                       "computed-bandwidth");
    6278             :         else {
    6279           0 :                 nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
    6280             :                                       "explicit-bandwidth");
    6281           0 :                 nb_cli_enqueue_change(vty, xpath_bandwidth, NB_OP_MODIFY,
    6282           0 :                                       argv[idx_lb]->arg);
    6283             :         }
    6284             : 
    6285           0 :         if (argv_find(argv, argc, "non-transitive", &idx_non_transitive))
    6286           0 :                 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
    6287             :                                       "true");
    6288             :         else
    6289           0 :                 nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
    6290             :                                       "false");
    6291             : 
    6292           0 :         return nb_cli_apply_changes(vty, NULL);
    6293             : }
    6294             : 
    6295           0 : DEFUN_YANG (no_set_ecommunity_lb,
    6296             :             no_set_ecommunity_lb_cmd,
    6297             :             "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
    6298             :             NO_STR
    6299             :             SET_STR
    6300             :             "BGP extended community attribute\n"
    6301             :             "Link bandwidth extended community\n"
    6302             :             "Bandwidth value in Mbps\n"
    6303             :             "Cumulative bandwidth of all multipaths (outbound-only)\n"
    6304             :             "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
    6305             :             "Attribute is set as non-transitive\n")
    6306             : {
    6307           0 :         const char *xpath =
    6308             :                 "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
    6309             : 
    6310           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6311           0 :         return nb_cli_apply_changes(vty, NULL);
    6312             : }
    6313             : 
    6314             : ALIAS_YANG (no_set_ecommunity_lb,
    6315             :             no_set_ecommunity_lb_short_cmd,
    6316             :             "no set extcommunity bandwidth",
    6317             :             NO_STR
    6318             :             SET_STR
    6319             :             "BGP extended community attribute\n"
    6320             :             "Link bandwidth extended community\n")
    6321             : 
    6322           0 : DEFUN_YANG (set_origin,
    6323             :             set_origin_cmd,
    6324             :             "set origin <egp|igp|incomplete>",
    6325             :             SET_STR
    6326             :             "BGP origin code\n"
    6327             :             "remote EGP\n"
    6328             :             "local IGP\n"
    6329             :             "unknown heritage\n")
    6330             : {
    6331           0 :         int idx_origin = 2;
    6332           0 :         const char *origin_type;
    6333           0 :         const char *xpath =
    6334             :                 "./set-action[action='frr-bgp-route-map:set-origin']";
    6335           0 :         char xpath_value[XPATH_MAXLEN];
    6336             : 
    6337           0 :         if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
    6338             :                 origin_type = "igp";
    6339           0 :         else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
    6340             :                 origin_type = "egp";
    6341           0 :         else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
    6342             :                 origin_type = "incomplete";
    6343             :         else {
    6344           0 :                 vty_out(vty, "%% Invalid match origin type\n");
    6345           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6346             :         }
    6347             : 
    6348           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6349           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6350             :                  "%s/rmap-set-action/frr-bgp-route-map:origin", xpath);
    6351           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
    6352             : 
    6353           0 :         return nb_cli_apply_changes(vty, NULL);
    6354             : }
    6355             : 
    6356           0 : DEFUN_YANG (no_set_origin,
    6357             :             no_set_origin_cmd,
    6358             :             "no set origin [<egp|igp|incomplete>]",
    6359             :             NO_STR
    6360             :             SET_STR
    6361             :             "BGP origin code\n"
    6362             :             "remote EGP\n"
    6363             :             "local IGP\n"
    6364             :             "unknown heritage\n")
    6365             : {
    6366           0 :         const char *xpath =
    6367             :                 "./set-action[action='frr-bgp-route-map:set-origin']";
    6368             : 
    6369           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6370           0 :         return nb_cli_apply_changes(vty, NULL);
    6371             : }
    6372             : 
    6373           0 : DEFUN_YANG (set_atomic_aggregate,
    6374             :             set_atomic_aggregate_cmd,
    6375             :             "set atomic-aggregate",
    6376             :             SET_STR
    6377             :             "BGP atomic aggregate attribute\n" )
    6378             : {
    6379           0 :         const char *xpath =
    6380             :                 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
    6381           0 :         char xpath_value[XPATH_MAXLEN];
    6382             : 
    6383           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6384           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6385             :                  "%s/rmap-set-action/frr-bgp-route-map:atomic-aggregate",
    6386             :                  xpath);
    6387           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
    6388             : 
    6389           0 :         return nb_cli_apply_changes(vty, NULL);
    6390             : }
    6391             : 
    6392           0 : DEFUN_YANG (no_set_atomic_aggregate,
    6393             :             no_set_atomic_aggregate_cmd,
    6394             :             "no set atomic-aggregate",
    6395             :             NO_STR
    6396             :             SET_STR
    6397             :             "BGP atomic aggregate attribute\n" )
    6398             : {
    6399           0 :         const char *xpath =
    6400             :                 "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
    6401             : 
    6402           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6403           0 :         return nb_cli_apply_changes(vty, NULL);
    6404             : }
    6405             : 
    6406           0 : DEFPY_YANG (set_aigp_metric,
    6407             :             set_aigp_metric_cmd,
    6408             :             "set aigp-metric <igp-metric|(1-4294967295)>$aigp_metric",
    6409             :             SET_STR
    6410             :             "BGP AIGP attribute (AIGP Metric TLV)\n"
    6411             :             "AIGP Metric value from IGP protocol\n"
    6412             :             "Manual AIGP Metric value\n")
    6413             : {
    6414           0 :         const char *xpath =
    6415             :                 "./set-action[action='frr-bgp-route-map:aigp-metric']";
    6416           0 :         char xpath_value[XPATH_MAXLEN];
    6417             : 
    6418           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6419           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6420             :                  "%s/rmap-set-action/frr-bgp-route-map:aigp-metric", xpath);
    6421           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, aigp_metric);
    6422             : 
    6423           0 :         return nb_cli_apply_changes(vty, NULL);
    6424             : }
    6425             : 
    6426           0 : DEFPY_YANG (no_set_aigp_metric,
    6427             :             no_set_aigp_metric_cmd,
    6428             :             "no set aigp-metric [<igp-metric|(1-4294967295)>]",
    6429             :             NO_STR
    6430             :             SET_STR
    6431             :             "BGP AIGP attribute (AIGP Metric TLV)\n"
    6432             :             "AIGP Metric value from IGP protocol\n"
    6433             :             "Manual AIGP Metric value\n")
    6434             : {
    6435           0 :         const char *xpath =
    6436             :                 "./set-action[action='frr-bgp-route-map:aigp-metric']";
    6437             : 
    6438           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6439           0 :         return nb_cli_apply_changes(vty, NULL);
    6440             : }
    6441             : 
    6442           0 : DEFUN_YANG (set_aggregator_as,
    6443             :             set_aggregator_as_cmd,
    6444             :             "set aggregator as (1-4294967295) A.B.C.D",
    6445             :             SET_STR
    6446             :             "BGP aggregator attribute\n"
    6447             :             "AS number of aggregator\n"
    6448             :             "AS number\n"
    6449             :             "IP address of aggregator\n")
    6450             : {
    6451           0 :         int idx_number = 3;
    6452           0 :         int idx_ipv4 = 4;
    6453           0 :         char xpath_asn[XPATH_MAXLEN];
    6454           0 :         char xpath_addr[XPATH_MAXLEN];
    6455           0 :         const char *xpath =
    6456             :                 "./set-action[action='frr-bgp-route-map:aggregator']";
    6457             : 
    6458           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6459             : 
    6460           0 :         snprintf(
    6461             :                 xpath_asn, sizeof(xpath_asn),
    6462             :                 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn",
    6463             :                 xpath);
    6464           0 :         nb_cli_enqueue_change(vty, xpath_asn, NB_OP_MODIFY,
    6465           0 :                               argv[idx_number]->arg);
    6466             : 
    6467           0 :         snprintf(
    6468             :                 xpath_addr, sizeof(xpath_addr),
    6469             :                 "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address",
    6470             :                 xpath);
    6471           0 :         nb_cli_enqueue_change(vty, xpath_addr, NB_OP_MODIFY,
    6472           0 :                               argv[idx_ipv4]->arg);
    6473             : 
    6474           0 :         return nb_cli_apply_changes(vty, NULL);
    6475             : }
    6476             : 
    6477           0 : DEFUN_YANG (no_set_aggregator_as,
    6478             :             no_set_aggregator_as_cmd,
    6479             :             "no set aggregator as [(1-4294967295) A.B.C.D]",
    6480             :             NO_STR
    6481             :             SET_STR
    6482             :             "BGP aggregator attribute\n"
    6483             :             "AS number of aggregator\n"
    6484             :             "AS number\n"
    6485             :             "IP address of aggregator\n")
    6486             : {
    6487           0 :         const char *xpath =
    6488             :                 "./set-action[action='frr-bgp-route-map:aggregator']";
    6489             : 
    6490           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6491           0 :         return nb_cli_apply_changes(vty, NULL);
    6492             : }
    6493             : 
    6494           0 : DEFUN_YANG (match_ipv6_next_hop,
    6495             :             match_ipv6_next_hop_cmd,
    6496             :             "match ipv6 next-hop ACCESSLIST6_NAME",
    6497             :             MATCH_STR
    6498             :             IPV6_STR
    6499             :             "Match IPv6 next-hop address of route\n"
    6500             :             "IPv6 access-list name\n")
    6501             : {
    6502           0 :         const char *xpath =
    6503             :                 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
    6504           0 :         char xpath_value[XPATH_MAXLEN];
    6505             : 
    6506           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6507           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6508             :                  "%s/rmap-match-condition/list-name", xpath);
    6509           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    6510           0 :                               argv[argc - 1]->arg);
    6511             : 
    6512           0 :         return nb_cli_apply_changes(vty, NULL);
    6513             : }
    6514             : 
    6515           0 : DEFUN_YANG (no_match_ipv6_next_hop,
    6516             :             no_match_ipv6_next_hop_cmd,
    6517             :             "no match ipv6 next-hop [ACCESSLIST6_NAME]",
    6518             :             NO_STR
    6519             :             MATCH_STR
    6520             :             IPV6_STR
    6521             :             "Match IPv6 next-hop address of route\n"
    6522             :             "IPv6 access-list name\n")
    6523             : {
    6524           0 :         const char *xpath =
    6525             :                 "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
    6526             : 
    6527           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6528           0 :         return nb_cli_apply_changes(vty, NULL);
    6529             : }
    6530             : 
    6531           0 : DEFUN_YANG (match_ipv6_next_hop_address,
    6532             :             match_ipv6_next_hop_address_cmd,
    6533             :             "match ipv6 next-hop address X:X::X:X",
    6534             :             MATCH_STR
    6535             :             IPV6_STR
    6536             :             "Match IPv6 next-hop address of route\n"
    6537             :             "IPv6 address\n"
    6538             :             "IPv6 address of next hop\n")
    6539             : {
    6540           0 :         const char *xpath =
    6541             :                 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
    6542           0 :         char xpath_value[XPATH_MAXLEN];
    6543             : 
    6544           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6545           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6546             :                  "%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
    6547             :                  xpath);
    6548           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    6549           0 :                               argv[argc - 1]->arg);
    6550             : 
    6551           0 :         return nb_cli_apply_changes(vty, NULL);
    6552             : }
    6553             : 
    6554           0 : DEFUN_YANG (no_match_ipv6_next_hop_address,
    6555             :             no_match_ipv6_next_hop_address_cmd,
    6556             :             "no match ipv6 next-hop address X:X::X:X",
    6557             :             NO_STR
    6558             :             MATCH_STR
    6559             :             IPV6_STR
    6560             :             "Match IPv6 next-hop address of route\n"
    6561             :             "IPv6 address\n"
    6562             :             "IPv6 address of next hop\n")
    6563             : {
    6564           0 :         const char *xpath =
    6565             :                 "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
    6566             : 
    6567           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6568           0 :         return nb_cli_apply_changes(vty, NULL);
    6569             : }
    6570             : 
    6571             : ALIAS_HIDDEN (match_ipv6_next_hop_address,
    6572             :               match_ipv6_next_hop_old_cmd,
    6573             :               "match ipv6 next-hop X:X::X:X",
    6574             :               MATCH_STR
    6575             :               IPV6_STR
    6576             :               "Match IPv6 next-hop address of route\n"
    6577             :               "IPv6 address of next hop\n")
    6578             : 
    6579             : ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
    6580             :               no_match_ipv6_next_hop_old_cmd,
    6581             :               "no match ipv6 next-hop X:X::X:X",
    6582             :               NO_STR
    6583             :               MATCH_STR
    6584             :               IPV6_STR
    6585             :               "Match IPv6 next-hop address of route\n"
    6586             :               "IPv6 address of next hop\n")
    6587             : 
    6588           0 : DEFUN_YANG (match_ipv6_next_hop_prefix_list,
    6589             :             match_ipv6_next_hop_prefix_list_cmd,
    6590             :             "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
    6591             :             MATCH_STR
    6592             :             IPV6_STR
    6593             :             "Match IPv6 next-hop address of route\n"
    6594             :             "Match entries by prefix-list\n"
    6595             :             "IPv6 prefix-list name\n")
    6596             : {
    6597           0 :         const char *xpath =
    6598             :                 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
    6599           0 :         char xpath_value[XPATH_MAXLEN];
    6600             : 
    6601           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6602           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6603             :                  "%s/rmap-match-condition/list-name", xpath);
    6604           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    6605           0 :                               argv[argc - 1]->arg);
    6606             : 
    6607           0 :         return nb_cli_apply_changes(vty, NULL);
    6608             : }
    6609             : 
    6610           0 : DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
    6611             :             no_match_ipv6_next_hop_prefix_list_cmd,
    6612             :             "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
    6613             :             NO_STR
    6614             :             MATCH_STR
    6615             :             IPV6_STR
    6616             :             "Match IPv6 next-hop address of route\n"
    6617             :             "Match entries by prefix-list\n"
    6618             :             "IPv6 prefix-list name\n")
    6619             : {
    6620           0 :         const char *xpath =
    6621             :                 "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
    6622             : 
    6623           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6624           0 :         return nb_cli_apply_changes(vty, NULL);
    6625             : }
    6626             : 
    6627           0 : DEFPY_YANG (match_ipv4_next_hop,
    6628             :        match_ipv4_next_hop_cmd,
    6629             :        "match ip next-hop address A.B.C.D",
    6630             :        MATCH_STR
    6631             :        IP_STR
    6632             :        "Match IP next-hop address of route\n"
    6633             :        "IP address\n"
    6634             :        "IP address of next-hop\n")
    6635             : {
    6636           0 :         const char *xpath =
    6637             :                 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
    6638           0 :         char xpath_value[XPATH_MAXLEN];
    6639             : 
    6640           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6641           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6642             :                  "%s/rmap-match-condition/frr-bgp-route-map:ipv4-address",
    6643             :                  xpath);
    6644           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
    6645             : 
    6646           0 :         return nb_cli_apply_changes(vty, NULL);
    6647             : }
    6648             : 
    6649           0 : DEFPY_YANG (no_match_ipv4_next_hop,
    6650             :        no_match_ipv4_next_hop_cmd,
    6651             :        "no match ip next-hop address [A.B.C.D]",
    6652             :        NO_STR
    6653             :        MATCH_STR
    6654             :        IP_STR
    6655             :        "Match IP next-hop address of route\n"
    6656             :        "IP address\n"
    6657             :        "IP address of next-hop\n")
    6658             : {
    6659           0 :         const char *xpath =
    6660             :                 "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
    6661             : 
    6662           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6663           0 :         return nb_cli_apply_changes(vty, NULL);
    6664             : }
    6665             : 
    6666           0 : DEFUN_YANG (set_ipv6_nexthop_peer,
    6667             :             set_ipv6_nexthop_peer_cmd,
    6668             :             "set ipv6 next-hop peer-address",
    6669             :             SET_STR
    6670             :             IPV6_STR
    6671             :             "Next hop address\n"
    6672             :             "Use peer address (for BGP only)\n")
    6673             : {
    6674           0 :         const char *xpath =
    6675             :                 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
    6676           0 :         char xpath_value[XPATH_MAXLEN];
    6677             : 
    6678           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6679           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6680             :                  "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
    6681           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
    6682             : 
    6683           0 :         return nb_cli_apply_changes(vty, NULL);
    6684             : }
    6685             : 
    6686           0 : DEFUN_YANG (no_set_ipv6_nexthop_peer,
    6687             :             no_set_ipv6_nexthop_peer_cmd,
    6688             :             "no set ipv6 next-hop peer-address",
    6689             :             NO_STR
    6690             :             SET_STR
    6691             :             IPV6_STR
    6692             :             "IPv6 next-hop address\n"
    6693             :             "Use peer address (for BGP only)\n")
    6694             : {
    6695           0 :         const char *xpath =
    6696             :                 "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
    6697             : 
    6698           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6699           0 :         return nb_cli_apply_changes(vty, NULL);
    6700             : }
    6701             : 
    6702           0 : DEFUN_YANG (set_ipv6_nexthop_prefer_global,
    6703             :             set_ipv6_nexthop_prefer_global_cmd,
    6704             :             "set ipv6 next-hop prefer-global",
    6705             :             SET_STR
    6706             :             IPV6_STR
    6707             :             "IPv6 next-hop address\n"
    6708             :             "Prefer global over link-local if both exist\n")
    6709             : {
    6710           0 :         const char *xpath =
    6711             :                 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
    6712           0 :         char xpath_value[XPATH_MAXLEN];
    6713             : 
    6714           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6715           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6716             :                  "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
    6717           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
    6718             : 
    6719           0 :         return nb_cli_apply_changes(vty, NULL);
    6720             : }
    6721             : 
    6722           0 : DEFUN_YANG (no_set_ipv6_nexthop_prefer_global,
    6723             :             no_set_ipv6_nexthop_prefer_global_cmd,
    6724             :             "no set ipv6 next-hop prefer-global",
    6725             :             NO_STR
    6726             :             SET_STR
    6727             :             IPV6_STR
    6728             :             "IPv6 next-hop address\n"
    6729             :             "Prefer global over link-local if both exist\n")
    6730             : {
    6731           0 :         const char *xpath =
    6732             :                 "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
    6733             : 
    6734           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6735           0 :         return nb_cli_apply_changes(vty, NULL);
    6736             : }
    6737             : 
    6738           0 : DEFUN_YANG (set_ipv6_nexthop_global,
    6739             :             set_ipv6_nexthop_global_cmd,
    6740             :             "set ipv6 next-hop global X:X::X:X",
    6741             :             SET_STR
    6742             :             IPV6_STR
    6743             :             "IPv6 next-hop address\n"
    6744             :             "IPv6 global address\n"
    6745             :             "IPv6 address of next hop\n")
    6746             : {
    6747           0 :         int idx_ipv6 = 4;
    6748           0 :         const char *xpath =
    6749             :                 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
    6750           0 :         char xpath_value[XPATH_MAXLEN];
    6751             : 
    6752           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6753           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6754             :                  "%s/rmap-set-action/frr-bgp-route-map:ipv6-address", xpath);
    6755           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    6756           0 :                               argv[idx_ipv6]->arg);
    6757             : 
    6758           0 :         return nb_cli_apply_changes(vty, NULL);
    6759             : }
    6760             : 
    6761           0 : DEFUN_YANG (no_set_ipv6_nexthop_global,
    6762             :             no_set_ipv6_nexthop_global_cmd,
    6763             :             "no set ipv6 next-hop global X:X::X:X",
    6764             :             NO_STR
    6765             :             SET_STR
    6766             :             IPV6_STR
    6767             :             "IPv6 next-hop address\n"
    6768             :             "IPv6 global address\n"
    6769             :             "IPv6 address of next hop\n")
    6770             : {
    6771           0 :         const char *xpath =
    6772             :                 "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
    6773             : 
    6774           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6775           0 :         return nb_cli_apply_changes(vty, NULL);
    6776             : }
    6777             : 
    6778             : #ifdef KEEP_OLD_VPN_COMMANDS
    6779             : DEFUN_YANG (set_vpn_nexthop,
    6780             :             set_vpn_nexthop_cmd,
    6781             :             "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
    6782             :             SET_STR
    6783             :             "VPNv4 information\n"
    6784             :             "VPN next-hop address\n"
    6785             :             "IP address of next hop\n"
    6786             :             "VPNv6 information\n"
    6787             :             "VPN next-hop address\n"
    6788             :             "IPv6 address of next hop\n")
    6789             : {
    6790             :         int idx_ip = 3;
    6791             :         afi_t afi;
    6792             :         int idx = 0;
    6793             :         char xpath_value[XPATH_MAXLEN];
    6794             : 
    6795             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
    6796             :                 if (afi == AFI_IP) {
    6797             :                         const char *xpath =
    6798             :                                 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
    6799             : 
    6800             :                         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6801             :                         snprintf(
    6802             :                                 xpath_value, sizeof(xpath_value),
    6803             :                                 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
    6804             :                                 xpath);
    6805             :                 } else {
    6806             :                         const char *xpath =
    6807             :                                 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
    6808             : 
    6809             :                         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6810             :                         snprintf(
    6811             :                                 xpath_value, sizeof(xpath_value),
    6812             :                                 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
    6813             :                                 xpath);
    6814             :                 }
    6815             : 
    6816             :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    6817             :                                 argv[idx_ip]->arg);
    6818             : 
    6819             :                 return nb_cli_apply_changes(vty, NULL);
    6820             :         }
    6821             : 
    6822             :         return CMD_SUCCESS;
    6823             : }
    6824             : 
    6825             : DEFUN_YANG (no_set_vpn_nexthop,
    6826             :            no_set_vpn_nexthop_cmd,
    6827             :            "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
    6828             :            NO_STR
    6829             :            SET_STR
    6830             :            "VPNv4 information\n"
    6831             :            "VPN next-hop address\n"
    6832             :            "IP address of next hop\n"
    6833             :            "VPNv6 information\n"
    6834             :            "VPN next-hop address\n"
    6835             :            "IPv6 address of next hop\n")
    6836             : {
    6837             :         afi_t afi;
    6838             :         int idx = 0;
    6839             : 
    6840             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
    6841             :                 if (afi == AFI_IP) {
    6842             :                         const char *xpath =
    6843             :                                 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
    6844             :                         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6845             :                 } else {
    6846             :                         const char *xpath =
    6847             :                                 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
    6848             :                         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6849             :                 }
    6850             :                 return nb_cli_apply_changes(vty, NULL);
    6851             :         }
    6852             :         return CMD_SUCCESS;
    6853             : }
    6854             : #endif /* KEEP_OLD_VPN_COMMANDS */
    6855             : 
    6856           0 : DEFPY_YANG (set_ipx_vpn_nexthop,
    6857             :             set_ipx_vpn_nexthop_cmd,
    6858             :             "set <ipv4|ipv6> vpn next-hop <A.B.C.D$addrv4|X:X::X:X$addrv6>",
    6859             :             SET_STR
    6860             :             "IPv4 information\n"
    6861             :             "IPv6 information\n"
    6862             :             "VPN information\n"
    6863             :             "VPN next-hop address\n"
    6864             :             "IP address of next hop\n"
    6865             :             "IPv6 address of next hop\n")
    6866             : {
    6867           0 :         int idx_ip = 4;
    6868           0 :         afi_t afi;
    6869           0 :         int idx = 0;
    6870           0 :         char xpath_value[XPATH_MAXLEN];
    6871             : 
    6872           0 :         if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
    6873           0 :                 if (afi == AFI_IP) {
    6874           0 :                         if (addrv6_str) {
    6875           0 :                                 vty_out(vty, "%% IPv4 next-hop expected\n");
    6876           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    6877             :                         }
    6878             : 
    6879           0 :                         const char *xpath =
    6880             :                                 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
    6881             : 
    6882           0 :                         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6883           0 :                         snprintf(
    6884             :                                 xpath_value, sizeof(xpath_value),
    6885             :                                 "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
    6886             :                                 xpath);
    6887             :                 } else {
    6888           0 :                         if (addrv4_str) {
    6889           0 :                                 vty_out(vty, "%% IPv6 next-hop expected\n");
    6890           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    6891             :                         }
    6892             : 
    6893           0 :                         const char *xpath =
    6894             :                                 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
    6895             : 
    6896           0 :                         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6897           0 :                         snprintf(
    6898             :                                 xpath_value, sizeof(xpath_value),
    6899             :                                 "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
    6900             :                                 xpath);
    6901             :                 }
    6902           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    6903           0 :                                       argv[idx_ip]->arg);
    6904           0 :                 return nb_cli_apply_changes(vty, NULL);
    6905             :         }
    6906             :         return CMD_SUCCESS;
    6907             : }
    6908             : 
    6909           0 : DEFUN_YANG (no_set_ipx_vpn_nexthop,
    6910             :             no_set_ipx_vpn_nexthop_cmd,
    6911             :             "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
    6912             :             NO_STR
    6913             :             SET_STR
    6914             :             "IPv4 information\n"
    6915             :             "IPv6 information\n"
    6916             :             "VPN information\n"
    6917             :             "VPN next-hop address\n"
    6918             :             "IP address of next hop\n"
    6919             :             "IPv6 address of next hop\n")
    6920             : {
    6921           0 :         afi_t afi;
    6922           0 :         int idx = 0;
    6923             : 
    6924           0 :         if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
    6925           0 :                 if (afi == AFI_IP) {
    6926           0 :                         const char *xpath =
    6927             :                                 "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
    6928           0 :                         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6929             :                 } else {
    6930           0 :                         const char *xpath =
    6931             :                                 "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
    6932           0 :                         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6933             :                 }
    6934           0 :                 return nb_cli_apply_changes(vty, NULL);
    6935             :         }
    6936             :         return CMD_SUCCESS;
    6937             : }
    6938             : 
    6939           0 : DEFUN_YANG (set_originator_id,
    6940             :             set_originator_id_cmd,
    6941             :             "set originator-id A.B.C.D",
    6942             :             SET_STR
    6943             :            "BGP originator ID attribute\n"
    6944             :            "IP address of originator\n")
    6945             : {
    6946           0 :         int idx_ipv4 = 2;
    6947           0 :         const char *xpath =
    6948             :                 "./set-action[action='frr-bgp-route-map:originator-id']";
    6949           0 :         char xpath_value[XPATH_MAXLEN];
    6950             : 
    6951           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6952           0 :         snprintf(xpath_value, sizeof(xpath_value),
    6953             :                  "%s/rmap-set-action/frr-bgp-route-map:originator-id", xpath);
    6954           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    6955           0 :                               argv[idx_ipv4]->arg);
    6956             : 
    6957           0 :         return nb_cli_apply_changes(vty, NULL);
    6958             : }
    6959             : 
    6960           0 : DEFUN_YANG (no_set_originator_id,
    6961             :             no_set_originator_id_cmd,
    6962             :             "no set originator-id [A.B.C.D]",
    6963             :             NO_STR
    6964             :             SET_STR
    6965             :             "BGP originator ID attribute\n"
    6966             :             "IP address of originator\n")
    6967             : {
    6968           0 :         const char *xpath =
    6969             :                 "./set-action[action='frr-bgp-route-map:originator-id']";
    6970             : 
    6971           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
    6972           0 :         return nb_cli_apply_changes(vty, NULL);
    6973             : }
    6974             : 
    6975           0 : DEFPY_YANG (match_rpki_extcommunity,
    6976             :        match_rpki_extcommunity_cmd,
    6977             :        "[no$no] match rpki-extcommunity <valid|invalid|notfound>",
    6978             :        NO_STR
    6979             :        MATCH_STR
    6980             :        "BGP RPKI (Origin Validation State) extended community attribute\n"
    6981             :        "Valid prefix\n"
    6982             :        "Invalid prefix\n"
    6983             :        "Prefix not found\n")
    6984             : {
    6985           0 :         const char *xpath =
    6986             :                 "./match-condition[condition='frr-bgp-route-map:rpki-extcommunity']";
    6987           0 :         char xpath_value[XPATH_MAXLEN];
    6988             : 
    6989           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
    6990             : 
    6991           0 :         if (!no) {
    6992           0 :                 snprintf(
    6993             :                         xpath_value, sizeof(xpath_value),
    6994             :                         "%s/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
    6995             :                         xpath);
    6996           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
    6997           0 :                                       argv[2]->arg);
    6998             :         }
    6999             : 
    7000           0 :         return nb_cli_apply_changes(vty, NULL);
    7001             : }
    7002             : 
    7003             : /* Initialization of route map. */
    7004           3 : void bgp_route_map_init(void)
    7005             : {
    7006           3 :         route_map_init();
    7007             : 
    7008           3 :         route_map_add_hook(bgp_route_map_add);
    7009           3 :         route_map_delete_hook(bgp_route_map_delete);
    7010           3 :         route_map_event_hook(bgp_route_map_event);
    7011             : 
    7012           3 :         route_map_match_interface_hook(generic_match_add);
    7013           3 :         route_map_no_match_interface_hook(generic_match_delete);
    7014             : 
    7015           3 :         route_map_match_ip_address_hook(generic_match_add);
    7016           3 :         route_map_no_match_ip_address_hook(generic_match_delete);
    7017             : 
    7018           3 :         route_map_match_ip_address_prefix_list_hook(generic_match_add);
    7019           3 :         route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
    7020             : 
    7021           3 :         route_map_match_ip_next_hop_hook(generic_match_add);
    7022           3 :         route_map_no_match_ip_next_hop_hook(generic_match_delete);
    7023             : 
    7024           3 :         route_map_match_ipv6_next_hop_hook(generic_match_add);
    7025           3 :         route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
    7026             : 
    7027           3 :         route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
    7028           3 :         route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
    7029             : 
    7030           3 :         route_map_match_ip_next_hop_type_hook(generic_match_add);
    7031           3 :         route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
    7032             : 
    7033           3 :         route_map_match_ipv6_address_hook(generic_match_add);
    7034           3 :         route_map_no_match_ipv6_address_hook(generic_match_delete);
    7035             : 
    7036           3 :         route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
    7037           3 :         route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
    7038             : 
    7039           3 :         route_map_match_ipv6_next_hop_type_hook(generic_match_add);
    7040           3 :         route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
    7041             : 
    7042           3 :         route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
    7043           3 :         route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
    7044             : 
    7045           3 :         route_map_match_metric_hook(generic_match_add);
    7046           3 :         route_map_no_match_metric_hook(generic_match_delete);
    7047             : 
    7048           3 :         route_map_match_tag_hook(generic_match_add);
    7049           3 :         route_map_no_match_tag_hook(generic_match_delete);
    7050             : 
    7051           3 :         route_map_set_srte_color_hook(generic_set_add);
    7052           3 :         route_map_no_set_srte_color_hook(generic_set_delete);
    7053             : 
    7054           3 :         route_map_set_ip_nexthop_hook(generic_set_add);
    7055           3 :         route_map_no_set_ip_nexthop_hook(generic_set_delete);
    7056             : 
    7057           3 :         route_map_set_ipv6_nexthop_local_hook(generic_set_add);
    7058           3 :         route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
    7059             : 
    7060           3 :         route_map_set_metric_hook(generic_set_add);
    7061           3 :         route_map_no_set_metric_hook(generic_set_delete);
    7062             : 
    7063           3 :         route_map_set_tag_hook(generic_set_add);
    7064           3 :         route_map_no_set_tag_hook(generic_set_delete);
    7065             : 
    7066           3 :         route_map_install_match(&route_match_peer_cmd);
    7067           3 :         route_map_install_match(&route_match_alias_cmd);
    7068           3 :         route_map_install_match(&route_match_local_pref_cmd);
    7069             : #ifdef HAVE_SCRIPTING
    7070             :         route_map_install_match(&route_match_script_cmd);
    7071             : #endif
    7072           3 :         route_map_install_match(&route_match_ip_address_cmd);
    7073           3 :         route_map_install_match(&route_match_ip_next_hop_cmd);
    7074           3 :         route_map_install_match(&route_match_ip_route_source_cmd);
    7075           3 :         route_map_install_match(&route_match_ip_address_prefix_list_cmd);
    7076           3 :         route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
    7077           3 :         route_map_install_match(&route_match_ip_next_hop_type_cmd);
    7078           3 :         route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
    7079           3 :         route_map_install_match(&route_match_aspath_cmd);
    7080           3 :         route_map_install_match(&route_match_community_cmd);
    7081           3 :         route_map_install_match(&route_match_lcommunity_cmd);
    7082           3 :         route_map_install_match(&route_match_ecommunity_cmd);
    7083           3 :         route_map_install_match(&route_match_local_pref_cmd);
    7084           3 :         route_map_install_match(&route_match_metric_cmd);
    7085           3 :         route_map_install_match(&route_match_origin_cmd);
    7086           3 :         route_map_install_match(&route_match_probability_cmd);
    7087           3 :         route_map_install_match(&route_match_interface_cmd);
    7088           3 :         route_map_install_match(&route_match_tag_cmd);
    7089           3 :         route_map_install_match(&route_match_mac_address_cmd);
    7090           3 :         route_map_install_match(&route_match_evpn_vni_cmd);
    7091           3 :         route_map_install_match(&route_match_evpn_route_type_cmd);
    7092           3 :         route_map_install_match(&route_match_evpn_rd_cmd);
    7093           3 :         route_map_install_match(&route_match_evpn_default_route_cmd);
    7094           3 :         route_map_install_match(&route_match_vrl_source_vrf_cmd);
    7095             : 
    7096           3 :         route_map_install_set(&route_set_evpn_gateway_ip_ipv4_cmd);
    7097           3 :         route_map_install_set(&route_set_evpn_gateway_ip_ipv6_cmd);
    7098           3 :         route_map_install_set(&route_set_table_id_cmd);
    7099           3 :         route_map_install_set(&route_set_srte_color_cmd);
    7100           3 :         route_map_install_set(&route_set_ip_nexthop_cmd);
    7101           3 :         route_map_install_set(&route_set_local_pref_cmd);
    7102           3 :         route_map_install_set(&route_set_weight_cmd);
    7103           3 :         route_map_install_set(&route_set_label_index_cmd);
    7104           3 :         route_map_install_set(&route_set_metric_cmd);
    7105           3 :         route_map_install_set(&route_set_distance_cmd);
    7106           3 :         route_map_install_set(&route_set_aspath_prepend_cmd);
    7107           3 :         route_map_install_set(&route_set_aspath_exclude_cmd);
    7108           3 :         route_map_install_set(&route_set_aspath_replace_cmd);
    7109           3 :         route_map_install_set(&route_set_origin_cmd);
    7110           3 :         route_map_install_set(&route_set_atomic_aggregate_cmd);
    7111           3 :         route_map_install_set(&route_set_aigp_metric_cmd);
    7112           3 :         route_map_install_set(&route_set_aggregator_as_cmd);
    7113           3 :         route_map_install_set(&route_set_community_cmd);
    7114           3 :         route_map_install_set(&route_set_community_delete_cmd);
    7115           3 :         route_map_install_set(&route_set_lcommunity_cmd);
    7116           3 :         route_map_install_set(&route_set_lcommunity_delete_cmd);
    7117           3 :         route_map_install_set(&route_set_vpnv4_nexthop_cmd);
    7118           3 :         route_map_install_set(&route_set_vpnv6_nexthop_cmd);
    7119           3 :         route_map_install_set(&route_set_originator_id_cmd);
    7120           3 :         route_map_install_set(&route_set_ecommunity_rt_cmd);
    7121           3 :         route_map_install_set(&route_set_ecommunity_soo_cmd);
    7122           3 :         route_map_install_set(&route_set_ecommunity_lb_cmd);
    7123           3 :         route_map_install_set(&route_set_ecommunity_none_cmd);
    7124           3 :         route_map_install_set(&route_set_tag_cmd);
    7125           3 :         route_map_install_set(&route_set_label_index_cmd);
    7126           3 :         route_map_install_set(&route_set_l3vpn_nexthop_encapsulation_cmd);
    7127             : 
    7128           3 :         install_element(RMAP_NODE, &match_peer_cmd);
    7129           3 :         install_element(RMAP_NODE, &match_peer_local_cmd);
    7130           3 :         install_element(RMAP_NODE, &no_match_peer_cmd);
    7131           3 :         install_element(RMAP_NODE, &match_ip_route_source_cmd);
    7132           3 :         install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
    7133           3 :         install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
    7134           3 :         install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
    7135           3 :         install_element(RMAP_NODE, &match_mac_address_cmd);
    7136           3 :         install_element(RMAP_NODE, &no_match_mac_address_cmd);
    7137           3 :         install_element(RMAP_NODE, &match_evpn_vni_cmd);
    7138           3 :         install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
    7139           3 :         install_element(RMAP_NODE, &match_evpn_route_type_cmd);
    7140           3 :         install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
    7141           3 :         install_element(RMAP_NODE, &match_evpn_rd_cmd);
    7142           3 :         install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
    7143           3 :         install_element(RMAP_NODE, &match_evpn_default_route_cmd);
    7144           3 :         install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
    7145           3 :         install_element(RMAP_NODE, &set_evpn_gw_ip_ipv4_cmd);
    7146           3 :         install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv4_cmd);
    7147           3 :         install_element(RMAP_NODE, &set_evpn_gw_ip_ipv6_cmd);
    7148           3 :         install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv6_cmd);
    7149           3 :         install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
    7150           3 :         install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
    7151             : 
    7152           3 :         install_element(RMAP_NODE, &match_aspath_cmd);
    7153           3 :         install_element(RMAP_NODE, &no_match_aspath_cmd);
    7154           3 :         install_element(RMAP_NODE, &match_local_pref_cmd);
    7155           3 :         install_element(RMAP_NODE, &no_match_local_pref_cmd);
    7156           3 :         install_element(RMAP_NODE, &match_alias_cmd);
    7157           3 :         install_element(RMAP_NODE, &no_match_alias_cmd);
    7158           3 :         install_element(RMAP_NODE, &match_community_cmd);
    7159           3 :         install_element(RMAP_NODE, &no_match_community_cmd);
    7160           3 :         install_element(RMAP_NODE, &match_lcommunity_cmd);
    7161           3 :         install_element(RMAP_NODE, &no_match_lcommunity_cmd);
    7162           3 :         install_element(RMAP_NODE, &match_ecommunity_cmd);
    7163           3 :         install_element(RMAP_NODE, &no_match_ecommunity_cmd);
    7164           3 :         install_element(RMAP_NODE, &match_origin_cmd);
    7165           3 :         install_element(RMAP_NODE, &no_match_origin_cmd);
    7166           3 :         install_element(RMAP_NODE, &match_probability_cmd);
    7167           3 :         install_element(RMAP_NODE, &no_match_probability_cmd);
    7168             : 
    7169           3 :         install_element(RMAP_NODE, &no_set_table_id_cmd);
    7170           3 :         install_element(RMAP_NODE, &set_table_id_cmd);
    7171           3 :         install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
    7172           3 :         install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
    7173           3 :         install_element(RMAP_NODE, &set_local_pref_cmd);
    7174           3 :         install_element(RMAP_NODE, &set_distance_cmd);
    7175           3 :         install_element(RMAP_NODE, &no_set_distance_cmd);
    7176           3 :         install_element(RMAP_NODE, &no_set_local_pref_cmd);
    7177           3 :         install_element(RMAP_NODE, &set_weight_cmd);
    7178           3 :         install_element(RMAP_NODE, &set_label_index_cmd);
    7179           3 :         install_element(RMAP_NODE, &no_set_weight_cmd);
    7180           3 :         install_element(RMAP_NODE, &no_set_label_index_cmd);
    7181           3 :         install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
    7182           3 :         install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
    7183           3 :         install_element(RMAP_NODE, &set_aspath_exclude_cmd);
    7184           3 :         install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
    7185           3 :         install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
    7186           3 :         install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
    7187           3 :         install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
    7188           3 :         install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
    7189           3 :         install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
    7190           3 :         install_element(RMAP_NODE, &set_origin_cmd);
    7191           3 :         install_element(RMAP_NODE, &no_set_origin_cmd);
    7192           3 :         install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
    7193           3 :         install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
    7194           3 :         install_element(RMAP_NODE, &set_aigp_metric_cmd);
    7195           3 :         install_element(RMAP_NODE, &no_set_aigp_metric_cmd);
    7196           3 :         install_element(RMAP_NODE, &set_aggregator_as_cmd);
    7197           3 :         install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
    7198           3 :         install_element(RMAP_NODE, &set_community_cmd);
    7199           3 :         install_element(RMAP_NODE, &set_community_none_cmd);
    7200           3 :         install_element(RMAP_NODE, &no_set_community_cmd);
    7201           3 :         install_element(RMAP_NODE, &no_set_community_short_cmd);
    7202           3 :         install_element(RMAP_NODE, &set_community_delete_cmd);
    7203           3 :         install_element(RMAP_NODE, &no_set_community_delete_cmd);
    7204           3 :         install_element(RMAP_NODE, &set_lcommunity_cmd);
    7205           3 :         install_element(RMAP_NODE, &set_lcommunity_none_cmd);
    7206           3 :         install_element(RMAP_NODE, &no_set_lcommunity_cmd);
    7207           3 :         install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
    7208           3 :         install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
    7209           3 :         install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
    7210           3 :         install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
    7211           3 :         install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
    7212           3 :         install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
    7213           3 :         install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
    7214           3 :         install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
    7215           3 :         install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
    7216           3 :         install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
    7217           3 :         install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
    7218           3 :         install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
    7219           3 :         install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
    7220           3 :         install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
    7221           3 :         install_element(RMAP_NODE, &set_ecommunity_none_cmd);
    7222           3 :         install_element(RMAP_NODE, &no_set_ecommunity_none_cmd);
    7223             : #ifdef KEEP_OLD_VPN_COMMANDS
    7224             :         install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
    7225             :         install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
    7226             : #endif /* KEEP_OLD_VPN_COMMANDS */
    7227           3 :         install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
    7228           3 :         install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
    7229           3 :         install_element(RMAP_NODE, &set_originator_id_cmd);
    7230           3 :         install_element(RMAP_NODE, &no_set_originator_id_cmd);
    7231           3 :         install_element(RMAP_NODE, &set_l3vpn_nexthop_encapsulation_cmd);
    7232             : 
    7233           3 :         route_map_install_match(&route_match_ipv6_address_cmd);
    7234           3 :         route_map_install_match(&route_match_ipv6_next_hop_cmd);
    7235           3 :         route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
    7236           3 :         route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
    7237           3 :         route_map_install_match(&route_match_ipv4_next_hop_cmd);
    7238           3 :         route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
    7239           3 :         route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
    7240           3 :         route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
    7241           3 :         route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
    7242           3 :         route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
    7243           3 :         route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
    7244           3 :         route_map_install_match(&route_match_rpki_extcommunity_cmd);
    7245             : 
    7246           3 :         install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
    7247           3 :         install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
    7248           3 :         install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
    7249           3 :         install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
    7250           3 :         install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
    7251           3 :         install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
    7252           3 :         install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
    7253           3 :         install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
    7254           3 :         install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
    7255           3 :         install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
    7256           3 :         install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
    7257           3 :         install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
    7258           3 :         install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
    7259           3 :         install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
    7260           3 :         install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
    7261           3 :         install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
    7262           3 :         install_element(RMAP_NODE, &match_rpki_extcommunity_cmd);
    7263             : #ifdef HAVE_SCRIPTING
    7264             :         install_element(RMAP_NODE, &match_script_cmd);
    7265             : #endif
    7266           3 : }
    7267             : 
    7268           3 : void bgp_route_map_terminate(void)
    7269             : {
    7270             :         /* ToDo: Cleanup all the used memory */
    7271           3 :         route_map_finish();
    7272           3 : }

Generated by: LCOV version v1.16-topotato