]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
Merge pull request #6577 from rtrlib/2020-06-12-master-fixes
[mirror_frr.git] / bgpd / bgp_routemap.c
CommitLineData
718e3744 1/* Route map function of bgpd.
896014f4
DL
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 */
718e3744 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"
5dbb0a7b 31#include "frrlua.h"
25f45887 32#ifdef HAVE_LIBPCREPOSIX
d62a17ae 33#include <pcreposix.h>
718e3744 34#else
d62a17ae 35#include <regex.h>
25f45887 36#endif /* HAVE_LIBPCREPOSIX */
718e3744 37#include "buffer.h"
38#include "sockunion.h"
518f0eb1 39#include "hash.h"
3f9c7369 40#include "queue.h"
5d5ba018 41#include "frrstr.h"
5920b3eb 42#include "network.h"
718e3744 43
44#include "bgpd/bgpd.h"
45#include "bgpd/bgp_table.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_aspath.h"
518f0eb1 48#include "bgpd/bgp_packet.h"
718e3744 49#include "bgpd/bgp_route.h"
73ac8160 50#include "bgpd/bgp_zebra.h"
718e3744 51#include "bgpd/bgp_regex.h"
52#include "bgpd/bgp_community.h"
53#include "bgpd/bgp_clist.h"
54#include "bgpd/bgp_filter.h"
55#include "bgpd/bgp_mplsvpn.h"
56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
320da874 58#include "bgpd/bgp_vty.h"
73ac8160 59#include "bgpd/bgp_debug.h"
d37ba549
MK
60#include "bgpd/bgp_evpn.h"
61#include "bgpd/bgp_evpn_private.h"
62982d5a 62#include "bgpd/bgp_evpn_vty.h"
ddb5b488 63#include "bgpd/bgp_mplsvpn.h"
2e59405f
DS
64#include "bgpd/bgp_pbr.h"
65#include "bgpd/bgp_flowspec_util.h"
82b692c0 66#include "bgpd/bgp_encap_types.h"
b1875e65 67#include "bgpd/bgp_mpath.h"
718e3744 68
49e5a4a0 69#ifdef ENABLE_BGP_VNC
d62a17ae 70#include "bgpd/rfapi/bgp_rfapi_cfg.h"
65efcfce 71#endif
518f0eb1 72
1dcc9e5b
CS
73#ifndef VTYSH_EXTRACT_PL
74#include "bgpd/bgp_routemap_clippy.c"
75#endif
76
718e3744 77/* Memo of route-map commands.
78
79o Cisco route-map
80
81 match as-path : Done
82 community : Done
bc413143 83 interface : Done
718e3744 84 ip address : Done
85 ip next-hop : Done
c1643bb7 86 ip route-source : Done
718e3744 87 ip prefix-list : Done
88 ipv6 address : Done
89 ipv6 next-hop : Done
90 ipv6 route-source: (This will not be implemented by bgpd)
91 ipv6 prefix-list : Done
92 length : (This will not be implemented by bgpd)
93 metric : Done
94 route-type : (This will not be implemented by bgpd)
0d9551dc 95 tag : Done
af291c15 96 local-preference : Done
718e3744 97
98 set as-path prepend : Done
99 as-path tag : Not yet
100 automatic-tag : (This will not be implemented by bgpd)
101 community : Done
57d187bc
JS
102 large-community : Done
103 large-comm-list : Done
718e3744 104 comm-list : Not yet
105 dampning : Not yet
106 default : (This will not be implemented by bgpd)
107 interface : (This will not be implemented by bgpd)
108 ip default : (This will not be implemented by bgpd)
109 ip next-hop : Done
110 ip precedence : (This will not be implemented by bgpd)
111 ip tos : (This will not be implemented by bgpd)
112 level : (This will not be implemented by bgpd)
113 local-preference : Done
114 metric : Done
115 metric-type : Not yet
116 origin : Done
0d9551dc 117 tag : Done
718e3744 118 weight : Done
951745bd 119 table : Done
718e3744 120
515e500c 121o Local extensions
718e3744 122
123 set ipv6 next-hop global: Done
161995ea 124 set ipv6 next-hop prefer-global: Done
718e3744 125 set ipv6 next-hop local : Done
841f7a57 126 set as-path exclude : Done
718e3744 127
e52702f2 128*/
6b0655a2 129
d62a17ae 130/* generic value manipulation to be shared in multiple rules */
76759f4f
TT
131
132#define RMAP_VALUE_SET 0
133#define RMAP_VALUE_ADD 1
134#define RMAP_VALUE_SUB 2
135
d62a17ae 136struct rmap_value {
d7c0a89a
QY
137 uint8_t action;
138 uint8_t variable;
139 uint32_t value;
76759f4f
TT
140};
141
d7c0a89a 142static int route_value_match(struct rmap_value *rv, uint32_t value)
d62a17ae 143{
144 if (rv->variable == 0 && value == rv->value)
145 return RMAP_MATCH;
76759f4f 146
d62a17ae 147 return RMAP_NOMATCH;
76759f4f
TT
148}
149
d7c0a89a
QY
150static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
151 struct peer *peer)
76759f4f 152{
d7c0a89a 153 uint32_t value;
baa376fc 154
d62a17ae 155 switch (rv->variable) {
156 case 1:
157 value = peer->rtt;
158 break;
159 default:
160 value = rv->value;
161 break;
162 }
76759f4f 163
d62a17ae 164 switch (rv->action) {
165 case RMAP_VALUE_ADD:
166 if (current > UINT32_MAX - value)
167 return UINT32_MAX;
168 return current + value;
169 case RMAP_VALUE_SUB:
170 if (current <= value)
171 return 0;
172 return current - value;
173 default:
174 return value;
175 }
76759f4f
TT
176}
177
d62a17ae 178static void *route_value_compile(const char *arg)
76759f4f 179{
d7c0a89a 180 uint8_t action = RMAP_VALUE_SET, var = 0;
d62a17ae 181 unsigned long larg = 0;
182 char *endptr = NULL;
183 struct rmap_value *rv;
76759f4f 184
d62a17ae 185 if (arg[0] == '+') {
186 action = RMAP_VALUE_ADD;
187 arg++;
188 } else if (arg[0] == '-') {
189 action = RMAP_VALUE_SUB;
190 arg++;
191 }
76759f4f 192
d62a17ae 193 if (all_digit(arg)) {
194 errno = 0;
195 larg = strtoul(arg, &endptr, 10);
196 if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
197 return NULL;
198 } else {
199 if (strcmp(arg, "rtt") == 0)
200 var = 1;
201 else
202 return NULL;
203 }
76759f4f 204
d62a17ae 205 rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
76759f4f 206
d62a17ae 207 rv->action = action;
208 rv->variable = var;
209 rv->value = larg;
210 return rv;
76759f4f
TT
211}
212
d62a17ae 213static void route_value_free(void *rule)
76759f4f 214{
d62a17ae 215 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
76759f4f
TT
216}
217
d62a17ae 218/* generic as path object to be shared in multiple rules */
374f12f9 219
d62a17ae 220static void *route_aspath_compile(const char *arg)
374f12f9 221{
d62a17ae 222 struct aspath *aspath;
374f12f9 223
d62a17ae 224 aspath = aspath_str2aspath(arg);
225 if (!aspath)
226 return NULL;
227 return aspath;
374f12f9
TT
228}
229
d62a17ae 230static void route_aspath_free(void *rule)
374f12f9 231{
d62a17ae 232 struct aspath *aspath = rule;
233 aspath_free(aspath);
374f12f9
TT
234}
235
8c3433e4
DS
236struct bgp_match_peer_compiled {
237 char *interface;
238 union sockunion su;
239};
240
241/* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
fee0f4c6 242
243/* Compares the peer specified in the 'match peer' clause with the peer
18ee8310 244 received in bgp_path_info->peer. If it is the same, or if the peer structure
fee0f4c6 245 received is a peer_group containing it, returns RMAP_MATCH. */
b68885f9
LK
246static enum route_map_cmd_result_t
247route_match_peer(void *rule, const struct prefix *prefix,
248 route_map_object_t type, void *object)
d62a17ae 249{
8c3433e4 250 struct bgp_match_peer_compiled *pc;
d62a17ae 251 union sockunion *su;
252 union sockunion su_def = {
253 .sin = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY}};
254 struct peer_group *group;
255 struct peer *peer;
256 struct listnode *node, *nnode;
257
258 if (type == RMAP_BGP) {
8c3433e4
DS
259 pc = rule;
260 su = &pc->su;
4b7e6066 261 peer = ((struct bgp_path_info *)object)->peer;
d62a17ae 262
8c3433e4
DS
263 if (pc->interface) {
264 if (!peer->conf_if)
265 return RMAP_NOMATCH;
266
267 if (strcmp(peer->conf_if, pc->interface) == 0)
268 return RMAP_MATCH;
269
270 return RMAP_NOMATCH;
271 }
272
d62a17ae 273 /* If su='0.0.0.0' (command 'match peer local'), and it's a
274 NETWORK,
20894f50
DA
275 REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
276 => return RMAP_MATCH
d62a17ae 277 */
278 if (sockunion_same(su, &su_def)) {
279 int ret;
280 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
281 || CHECK_FLAG(peer->rmap_type,
282 PEER_RMAP_TYPE_REDISTRIBUTE)
20894f50
DA
283 || CHECK_FLAG(peer->rmap_type,
284 PEER_RMAP_TYPE_AGGREGATE)
d62a17ae 285 || CHECK_FLAG(peer->rmap_type,
286 PEER_RMAP_TYPE_DEFAULT))
287 ret = RMAP_MATCH;
288 else
289 ret = RMAP_NOMATCH;
290 return ret;
291 }
292
293 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
294 if (sockunion_same(su, &peer->su))
295 return RMAP_MATCH;
296
297 return RMAP_NOMATCH;
298 } else {
299 group = peer->group;
300 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
301 peer)) {
302 if (sockunion_same(su, &peer->su))
303 return RMAP_MATCH;
304 }
305 return RMAP_NOMATCH;
306 }
307 }
308 return RMAP_NOMATCH;
309}
310
311static void *route_match_peer_compile(const char *arg)
312{
8c3433e4 313 struct bgp_match_peer_compiled *pc;
d62a17ae 314 int ret;
315
a633d869 316 pc = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
8c3433e4 317 sizeof(struct bgp_match_peer_compiled));
d62a17ae 318
8c3433e4 319 ret = str2sockunion(strcmp(arg, "local") ? arg : "0.0.0.0", &pc->su);
d62a17ae 320 if (ret < 0) {
8c3433e4
DS
321 pc->interface = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
322 return pc;
d62a17ae 323 }
324
8c3433e4 325 return pc;
fee0f4c6 326}
327
328/* Free route map's compiled `ip address' value. */
d62a17ae 329static void route_match_peer_free(void *rule)
fee0f4c6 330{
8c3433e4
DS
331 struct bgp_match_peer_compiled *pc = rule;
332
0a22ddfb 333 XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
8c3433e4 334
d62a17ae 335 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
fee0f4c6 336}
337
338/* Route map commands for ip address matching. */
364deb04
DL
339static const struct route_map_rule_cmd route_match_peer_cmd = {
340 "peer",
341 route_match_peer,
342 route_match_peer_compile,
343 route_match_peer_free
344};
fee0f4c6 345
1d7c7ace 346#if defined(HAVE_LUA)
b68885f9
LK
347static enum route_map_cmd_result_t
348route_match_command(void *rule, const struct prefix *prefix,
349 route_map_object_t type, void *object)
1d7c7ace
DS
350{
351 int status = RMAP_NOMATCH;
352 u_int32_t locpref = 0;
353 u_int32_t newlocpref = 0;
354 enum lua_rm_status lrm_status;
40381db7 355 struct bgp_path_info *path = (struct bgp_path_info *)object;
1d7c7ace
DS
356 lua_State *L = lua_initialize("/etc/frr/lua.scr");
357
358 if (L == NULL)
359 return status;
360
361 /*
362 * Setup the prefix information to pass in
363 */
364 lua_setup_prefix_table(L, prefix);
365
366 zlog_debug("Set up prefix table");
367 /*
18ee8310 368 * Setup the bgp_path_info information
1d7c7ace
DS
369 */
370 lua_newtable(L);
40381db7 371 lua_pushinteger(L, path->attr->med);
1d7c7ace 372 lua_setfield(L, -2, "metric");
40381db7 373 lua_pushinteger(L, path->attr->nh_ifindex);
1d7c7ace 374 lua_setfield(L, -2, "ifindex");
40381db7 375 lua_pushstring(L, path->attr->aspath->str);
1d7c7ace 376 lua_setfield(L, -2, "aspath");
40381db7 377 lua_pushinteger(L, path->attr->local_pref);
1d7c7ace 378 lua_setfield(L, -2, "localpref");
40381db7 379 zlog_debug("%s %d", path->attr->aspath->str, path->attr->nh_ifindex);
1d7c7ace
DS
380 lua_setglobal(L, "nexthop");
381
382 zlog_debug("Set up nexthop information");
383 /*
384 * Run the rule
385 */
386 lrm_status = lua_run_rm_rule(L, rule);
387 switch (lrm_status) {
388 case LUA_RM_FAILURE:
389 zlog_debug("RM_FAILURE");
390 break;
391 case LUA_RM_NOMATCH:
392 zlog_debug("RM_NOMATCH");
393 break;
394 case LUA_RM_MATCH_AND_CHANGE:
395 zlog_debug("MATCH AND CHANGE");
396 lua_getglobal(L, "nexthop");
40381db7 397 path->attr->med = get_integer(L, "metric");
1d7c7ace
DS
398 /*
399 * This needs to be abstraced with the set function
400 */
40381db7
DS
401 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
402 locpref = path->attr->local_pref;
1d7c7ace
DS
403 newlocpref = get_integer(L, "localpref");
404 if (newlocpref != locpref) {
40381db7
DS
405 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
406 path->attr->local_pref = newlocpref;
1d7c7ace
DS
407 }
408 status = RMAP_MATCH;
409 break;
410 case LUA_RM_MATCH:
411 zlog_debug("MATCH ONLY");
412 status = RMAP_MATCH;
413 break;
414 }
415 lua_close(L);
416 return status;
417}
418
419static void *route_match_command_compile(const char *arg)
420{
421 char *command;
422
423 command = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
424 return command;
425}
426
427static void
428route_match_command_free(void *rule)
429{
430 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
431}
432
364deb04 433static const struct route_map_rule_cmd route_match_command_cmd = {
1d7c7ace
DS
434 "command",
435 route_match_command,
436 route_match_command_compile,
437 route_match_command_free
438};
439#endif
440
718e3744 441/* `match ip address IP_ACCESS_LIST' */
442
443/* Match function should return 1 if match is success else return
444 zero. */
b68885f9
LK
445static enum route_map_cmd_result_t
446route_match_ip_address(void *rule, const struct prefix *prefix,
447 route_map_object_t type, void *object)
d62a17ae 448{
449 struct access_list *alist;
d62a17ae 450
09cd98eb 451 if (type == RMAP_BGP && prefix->family == AF_INET) {
d62a17ae 452 alist = access_list_lookup(AFI_IP, (char *)rule);
453 if (alist == NULL)
454 return RMAP_NOMATCH;
455
456 return (access_list_apply(alist, prefix) == FILTER_DENY
457 ? RMAP_NOMATCH
458 : RMAP_MATCH);
459 }
718e3744 460 return RMAP_NOMATCH;
718e3744 461}
462
463/* Route map `ip address' match statement. `arg' should be
464 access-list name. */
d62a17ae 465static void *route_match_ip_address_compile(const char *arg)
718e3744 466{
d62a17ae 467 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 468}
469
470/* Free route map's compiled `ip address' value. */
d62a17ae 471static void route_match_ip_address_free(void *rule)
718e3744 472{
d62a17ae 473 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 474}
475
476/* Route map commands for ip address matching. */
364deb04
DL
477static const struct route_map_rule_cmd route_match_ip_address_cmd = {
478 "ip address",
479 route_match_ip_address,
480 route_match_ip_address_compile,
481 route_match_ip_address_free
482};
6b0655a2 483
718e3744 484/* `match ip next-hop IP_ADDRESS' */
485
486/* Match function return 1 if match is success else return zero. */
b68885f9
LK
487static enum route_map_cmd_result_t
488route_match_ip_next_hop(void *rule, const struct prefix *prefix,
489 route_map_object_t type, void *object)
d62a17ae 490{
491 struct access_list *alist;
9b6d8fcf 492 struct bgp_path_info *path;
d62a17ae 493 struct prefix_ipv4 p;
494
09cd98eb 495 if (type == RMAP_BGP && prefix->family == AF_INET) {
9b6d8fcf 496 path = object;
d62a17ae 497 p.family = AF_INET;
9b6d8fcf 498 p.prefix = path->attr->nexthop;
d62a17ae 499 p.prefixlen = IPV4_MAX_BITLEN;
500
501 alist = access_list_lookup(AFI_IP, (char *)rule);
502 if (alist == NULL)
503 return RMAP_NOMATCH;
504
505 return (access_list_apply(alist, &p) == FILTER_DENY
506 ? RMAP_NOMATCH
507 : RMAP_MATCH);
508 }
718e3744 509 return RMAP_NOMATCH;
718e3744 510}
511
512/* Route map `ip next-hop' match statement. `arg' is
513 access-list name. */
d62a17ae 514static void *route_match_ip_next_hop_compile(const char *arg)
718e3744 515{
d62a17ae 516 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 517}
518
519/* Free route map's compiled `ip address' value. */
d62a17ae 520static void route_match_ip_next_hop_free(void *rule)
718e3744 521{
d62a17ae 522 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 523}
524
525/* Route map commands for ip next-hop matching. */
364deb04
DL
526static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
527 "ip next-hop",
528 route_match_ip_next_hop,
529 route_match_ip_next_hop_compile,
530 route_match_ip_next_hop_free
531};
6b0655a2 532
c1643bb7 533/* `match ip route-source ACCESS-LIST' */
534
535/* Match function return 1 if match is success else return zero. */
b68885f9
LK
536static enum route_map_cmd_result_t
537route_match_ip_route_source(void *rule, const struct prefix *pfx,
538 route_map_object_t type, void *object)
d62a17ae 539{
540 struct access_list *alist;
9b6d8fcf 541 struct bgp_path_info *path;
d62a17ae 542 struct peer *peer;
543 struct prefix_ipv4 p;
544
123214ef 545 if (type == RMAP_BGP && pfx->family == AF_INET) {
9b6d8fcf
DS
546 path = object;
547 peer = path->peer;
d62a17ae 548
549 if (!peer || sockunion_family(&peer->su) != AF_INET)
550 return RMAP_NOMATCH;
551
552 p.family = AF_INET;
553 p.prefix = peer->su.sin.sin_addr;
554 p.prefixlen = IPV4_MAX_BITLEN;
555
556 alist = access_list_lookup(AFI_IP, (char *)rule);
557 if (alist == NULL)
558 return RMAP_NOMATCH;
559
560 return (access_list_apply(alist, &p) == FILTER_DENY
561 ? RMAP_NOMATCH
562 : RMAP_MATCH);
563 }
c1643bb7 564 return RMAP_NOMATCH;
c1643bb7 565}
566
567/* Route map `ip route-source' match statement. `arg' is
568 access-list name. */
d62a17ae 569static void *route_match_ip_route_source_compile(const char *arg)
c1643bb7 570{
d62a17ae 571 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
c1643bb7 572}
573
574/* Free route map's compiled `ip address' value. */
d62a17ae 575static void route_match_ip_route_source_free(void *rule)
c1643bb7 576{
d62a17ae 577 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
c1643bb7 578}
579
580/* Route map commands for ip route-source matching. */
364deb04
DL
581static const struct route_map_rule_cmd route_match_ip_route_source_cmd = {
582 "ip route-source",
583 route_match_ip_route_source,
584 route_match_ip_route_source_compile,
585 route_match_ip_route_source_free
586};
6b0655a2 587
b68885f9
LK
588static enum route_map_cmd_result_t
589route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist,
590 const struct prefix *p)
2e59405f
DS
591{
592 int ret;
593 struct bgp_pbr_entry_main api;
594
595 memset(&api, 0, sizeof(api));
596
597 /* extract match from flowspec entries */
598 ret = bgp_flowspec_match_rules_fill(
599 (uint8_t *)p->u.prefix_flowspec.ptr,
600 p->u.prefix_flowspec.prefixlen, &api);
601 if (ret < 0)
602 return RMAP_NOMATCH;
603 if (api.match_bitmask & PREFIX_DST_PRESENT ||
604 api.match_bitmask_iprule & PREFIX_DST_PRESENT) {
605 if (family2afi((&api.dst_prefix)->family) != afi)
606 return RMAP_NOMATCH;
607 return prefix_list_apply(plist, &api.dst_prefix) == PREFIX_DENY
608 ? RMAP_NOMATCH
609 : RMAP_MATCH;
610 } else if (api.match_bitmask & PREFIX_SRC_PRESENT ||
611 api.match_bitmask_iprule & PREFIX_SRC_PRESENT) {
612 if (family2afi((&api.src_prefix)->family) != afi)
613 return RMAP_NOMATCH;
614 return (prefix_list_apply(plist, &api.src_prefix) == PREFIX_DENY
615 ? RMAP_NOMATCH
616 : RMAP_MATCH);
617 }
618 return RMAP_NOMATCH;
619}
718e3744 620
b68885f9 621static enum route_map_cmd_result_t
2e59405f
DS
622route_match_address_prefix_list(void *rule, afi_t afi,
623 const struct prefix *prefix,
624 route_map_object_t type, void *object)
718e3744 625{
d62a17ae 626 struct prefix_list *plist;
718e3744 627
2e59405f
DS
628 if (type != RMAP_BGP)
629 return RMAP_NOMATCH;
e52702f2 630
2e59405f
DS
631 plist = prefix_list_lookup(afi, (char *)rule);
632 if (plist == NULL)
633 return RMAP_NOMATCH;
634
635 if (prefix->family == AF_FLOWSPEC)
636 return route_match_prefix_list_flowspec(afi, plist,
637 prefix);
638 return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
639 : RMAP_MATCH);
640}
641
b68885f9 642static enum route_map_cmd_result_t
2e59405f
DS
643route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
644 route_map_object_t type, void *object)
645{
646 return route_match_address_prefix_list(rule, AFI_IP, prefix, type,
647 object);
718e3744 648}
649
d62a17ae 650static void *route_match_ip_address_prefix_list_compile(const char *arg)
718e3744 651{
d62a17ae 652 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 653}
654
d62a17ae 655static void route_match_ip_address_prefix_list_free(void *rule)
718e3744 656{
d62a17ae 657 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 658}
659
364deb04
DL
660static const struct route_map_rule_cmd
661 route_match_ip_address_prefix_list_cmd = {
662 "ip address prefix-list",
663 route_match_ip_address_prefix_list,
d62a17ae 664 route_match_ip_address_prefix_list_compile,
364deb04
DL
665 route_match_ip_address_prefix_list_free
666};
6b0655a2 667
718e3744 668/* `match ip next-hop prefix-list PREFIX_LIST' */
669
b68885f9 670static enum route_map_cmd_result_t
123214ef 671route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
d62a17ae 672 route_map_object_t type, void *object)
718e3744 673{
d62a17ae 674 struct prefix_list *plist;
9b6d8fcf 675 struct bgp_path_info *path;
d62a17ae 676 struct prefix_ipv4 p;
718e3744 677
09cd98eb 678 if (type == RMAP_BGP && prefix->family == AF_INET) {
9b6d8fcf 679 path = object;
d62a17ae 680 p.family = AF_INET;
9b6d8fcf 681 p.prefix = path->attr->nexthop;
d62a17ae 682 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 683
d62a17ae 684 plist = prefix_list_lookup(AFI_IP, (char *)rule);
685 if (plist == NULL)
686 return RMAP_NOMATCH;
718e3744 687
d62a17ae 688 return (prefix_list_apply(plist, &p) == PREFIX_DENY
689 ? RMAP_NOMATCH
690 : RMAP_MATCH);
691 }
692 return RMAP_NOMATCH;
718e3744 693}
694
d62a17ae 695static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
718e3744 696{
d62a17ae 697 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 698}
699
d62a17ae 700static void route_match_ip_next_hop_prefix_list_free(void *rule)
718e3744 701{
d62a17ae 702 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 703}
704
364deb04
DL
705static const struct route_map_rule_cmd
706 route_match_ip_next_hop_prefix_list_cmd = {
707 "ip next-hop prefix-list",
708 route_match_ip_next_hop_prefix_list,
d62a17ae 709 route_match_ip_next_hop_prefix_list_compile,
364deb04
DL
710 route_match_ip_next_hop_prefix_list_free
711};
6b0655a2 712
61ad901e
DA
713/* `match ip next-hop type <blackhole>' */
714
b68885f9 715static enum route_map_cmd_result_t
61ad901e
DA
716route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
717 route_map_object_t type, void *object)
718{
9b6d8fcf 719 struct bgp_path_info *path;
61ad901e
DA
720
721 if (type == RMAP_BGP && prefix->family == AF_INET) {
9b6d8fcf 722 path = (struct bgp_path_info *)object;
05864da7 723 if (!path)
b68885f9 724 return RMAP_NOMATCH;
61ad901e
DA
725
726 /* If nexthop interface's index can't be resolved and nexthop is
727 set to any address then mark it as type `blackhole`.
728 This logic works for matching kernel/static routes like:
729 `ip route add blackhole 10.0.0.1`. */
9b6d8fcf
DS
730 if (path->attr->nexthop.s_addr == INADDR_ANY
731 && !path->attr->nh_ifindex)
61ad901e
DA
732 return RMAP_MATCH;
733 }
734 return RMAP_NOMATCH;
735}
736
737static void *route_match_ip_next_hop_type_compile(const char *arg)
738{
739 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
740}
741
742static void route_match_ip_next_hop_type_free(void *rule)
743{
744 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
745}
746
364deb04
DL
747static const struct route_map_rule_cmd
748 route_match_ip_next_hop_type_cmd = {
749 "ip next-hop type",
750 route_match_ip_next_hop_type,
61ad901e 751 route_match_ip_next_hop_type_compile,
364deb04
DL
752 route_match_ip_next_hop_type_free
753};
61ad901e 754
c1643bb7 755/* `match ip route-source prefix-list PREFIX_LIST' */
756
b68885f9 757static enum route_map_cmd_result_t
123214ef
MS
758route_match_ip_route_source_prefix_list(void *rule,
759 const struct prefix *prefix,
d62a17ae 760 route_map_object_t type, void *object)
c1643bb7 761{
d62a17ae 762 struct prefix_list *plist;
9b6d8fcf 763 struct bgp_path_info *path;
d62a17ae 764 struct peer *peer;
765 struct prefix_ipv4 p;
c1643bb7 766
09cd98eb 767 if (type == RMAP_BGP && prefix->family == AF_INET) {
9b6d8fcf
DS
768 path = object;
769 peer = path->peer;
c1643bb7 770
d62a17ae 771 if (!peer || sockunion_family(&peer->su) != AF_INET)
772 return RMAP_NOMATCH;
c1643bb7 773
d62a17ae 774 p.family = AF_INET;
775 p.prefix = peer->su.sin.sin_addr;
776 p.prefixlen = IPV4_MAX_BITLEN;
c1643bb7 777
d62a17ae 778 plist = prefix_list_lookup(AFI_IP, (char *)rule);
779 if (plist == NULL)
780 return RMAP_NOMATCH;
c1643bb7 781
d62a17ae 782 return (prefix_list_apply(plist, &p) == PREFIX_DENY
783 ? RMAP_NOMATCH
784 : RMAP_MATCH);
785 }
786 return RMAP_NOMATCH;
c1643bb7 787}
788
d62a17ae 789static void *route_match_ip_route_source_prefix_list_compile(const char *arg)
c1643bb7 790{
d62a17ae 791 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
c1643bb7 792}
793
d62a17ae 794static void route_match_ip_route_source_prefix_list_free(void *rule)
c1643bb7 795{
d62a17ae 796 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
c1643bb7 797}
798
364deb04
DL
799static const struct route_map_rule_cmd
800 route_match_ip_route_source_prefix_list_cmd = {
801 "ip route-source prefix-list",
802 route_match_ip_route_source_prefix_list,
d62a17ae 803 route_match_ip_route_source_prefix_list_compile,
364deb04
DL
804 route_match_ip_route_source_prefix_list_free
805};
6b0655a2 806
6fb219da
MK
807/* `match evpn default-route' */
808
809/* Match function should return 1 if match is success else 0 */
b68885f9
LK
810static enum route_map_cmd_result_t
811route_match_evpn_default_route(void *rule, const struct prefix *p,
812 route_map_object_t type, void *object)
6fb219da
MK
813{
814 if (type == RMAP_BGP && is_evpn_prefix_default(p))
815 return RMAP_MATCH;
816
817 return RMAP_NOMATCH;
818}
819
820/* Route map commands for default-route matching. */
364deb04
DL
821static const struct route_map_rule_cmd
822 route_match_evpn_default_route_cmd = {
823 "evpn default-route",
824 route_match_evpn_default_route,
825 NULL,
826 NULL
827};
6fb219da 828
d37ba549
MK
829/* `match mac address MAC_ACCESS_LIST' */
830
831/* Match function should return 1 if match is success else return
832 zero. */
b68885f9
LK
833static enum route_map_cmd_result_t
834route_match_mac_address(void *rule, const struct prefix *prefix,
835 route_map_object_t type, void *object)
d37ba549
MK
836{
837 struct access_list *alist;
0f6476cc 838 struct prefix p;
d37ba549
MK
839
840 if (type == RMAP_BGP) {
841 alist = access_list_lookup(AFI_L2VPN, (char *)rule);
842 if (alist == NULL)
843 return RMAP_NOMATCH;
844
845 if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE)
846 return RMAP_NOMATCH;
847
0f6476cc
DS
848 p.family = AF_ETHERNET;
849 p.prefixlen = ETH_ALEN * 8;
3714a385 850 p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
0f6476cc 851
a4d82a8a 852 return (access_list_apply(alist, &p) == FILTER_DENY
d37ba549
MK
853 ? RMAP_NOMATCH
854 : RMAP_MATCH);
855 }
856
857 return RMAP_NOMATCH;
858}
859
860/* Route map `mac address' match statement. `arg' should be
861 access-list name. */
862static void *route_match_mac_address_compile(const char *arg)
863{
864 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
865}
866
867/* Free route map's compiled `ip address' value. */
868static void route_match_mac_address_free(void *rule)
869{
870 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
871}
872
873/* Route map commands for mac address matching. */
364deb04
DL
874static const struct route_map_rule_cmd route_match_mac_address_cmd = {
875 "mac address",
876 route_match_mac_address,
877 route_match_mac_address_compile,
878 route_match_mac_address_free
879};
d37ba549 880
82b692c0
LK
881/*
882 * Match function returns:
883 * ...RMAP_MATCH if match is found.
884 * ...RMAP_NOMATCH if match is not found.
885 * ...RMAP_NOOP to ignore this match check.
886 */
b68885f9
LK
887static enum route_map_cmd_result_t
888route_match_vni(void *rule, const struct prefix *prefix,
889 route_map_object_t type, void *object)
16f7ce2b
MK
890{
891 vni_t vni = 0;
82b692c0 892 unsigned int label_cnt = 0;
9b6d8fcf 893 struct bgp_path_info *path = NULL;
82b692c0 894 struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
16f7ce2b
MK
895
896 if (type == RMAP_BGP) {
897 vni = *((vni_t *)rule);
9b6d8fcf 898 path = (struct bgp_path_info *)object;
16f7ce2b 899
82b692c0
LK
900 /*
901 * This rmap filter is valid for vxlan tunnel type only.
902 * For any other tunnel type, return noop to ignore
903 * this check.
904 */
05864da7 905 if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN)
82b692c0
LK
906 return RMAP_NOOP;
907
908 /*
909 * Apply filter to type 1, 2, 5 routes only.
910 * Other route types do not have vni label.
911 */
912 if (evp && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE &&
913 evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE &&
914 evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
915 return RMAP_NOOP;
916
9b6d8fcf 917 if (path->extra == NULL)
80ced710
CS
918 return RMAP_NOMATCH;
919
82b692c0
LK
920 for ( ; label_cnt < BGP_MAX_LABELS &&
921 label_cnt < path->extra->num_labels; label_cnt++) {
922 if (vni == label2vni(&path->extra->label[label_cnt]))
923 return RMAP_MATCH;
924 }
16f7ce2b
MK
925 }
926
927 return RMAP_NOMATCH;
928}
929
930/* Route map `vni' match statement. */
931static void *route_match_vni_compile(const char *arg)
932{
933 vni_t *vni = NULL;
934 char *end = NULL;
935
936 vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
16f7ce2b
MK
937
938 *vni = strtoul(arg, &end, 10);
0af35d90
RW
939 if (*end != '\0') {
940 XFREE(MTYPE_ROUTE_MAP_COMPILED, vni);
16f7ce2b 941 return NULL;
0af35d90 942 }
16f7ce2b
MK
943
944 return vni;
945}
946
947/* Free route map's compiled `vni' value. */
948static void route_match_vni_free(void *rule)
949{
950 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
951}
952
953/* Route map commands for vni matching. */
364deb04
DL
954static const struct route_map_rule_cmd route_match_evpn_vni_cmd = {
955 "evpn vni",
956 route_match_vni,
957 route_match_vni_compile,
958 route_match_vni_free
959};
16f7ce2b 960
33c2ff62
MK
961/* `match evpn route-type' */
962
963/* Match function should return 1 if match is success else return
964 zero. */
b68885f9
LK
965static enum route_map_cmd_result_t
966route_match_evpn_route_type(void *rule, const struct prefix *pfx,
967 route_map_object_t type, void *object)
33c2ff62 968{
d7c0a89a 969 uint8_t route_type = 0;
33c2ff62
MK
970
971 if (type == RMAP_BGP) {
d7c0a89a 972 route_type = *((uint8_t *)rule);
33c2ff62 973
123214ef 974 if (route_type == pfx->u.prefix_evpn.route_type)
33c2ff62
MK
975 return RMAP_MATCH;
976 }
977
978 return RMAP_NOMATCH;
979}
980
981/* Route map `route-type' match statement. */
982static void *route_match_evpn_route_type_compile(const char *arg)
983{
d7c0a89a 984 uint8_t *route_type = NULL;
33c2ff62 985
d7c0a89a 986 route_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
33c2ff62
MK
987
988 if (strncmp(arg, "ma", 2) == 0)
989 *route_type = BGP_EVPN_MAC_IP_ROUTE;
990 else if (strncmp(arg, "mu", 2) == 0)
991 *route_type = BGP_EVPN_IMET_ROUTE;
992 else
993 *route_type = BGP_EVPN_IP_PREFIX_ROUTE;
994
995 return route_type;
996}
997
998/* Free route map's compiled `route-type' value. */
999static void route_match_evpn_route_type_free(void *rule)
1000{
1001 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1002}
1003
1004/* Route map commands for evpn route-type matching. */
364deb04
DL
1005static const struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
1006 "evpn route-type",
1007 route_match_evpn_route_type,
1008 route_match_evpn_route_type_compile,
1009 route_match_evpn_route_type_free
1010};
33c2ff62 1011
196c6b09
LK
1012/* `match rd' */
1013
1014/* Match function should return 1 if match is success else return zero. */
1015static enum route_map_cmd_result_t
1016route_match_rd(void *rule, const struct prefix *prefix,
1017 route_map_object_t type, void *object)
1018{
1019 struct prefix_rd *prd_rule = NULL;
b54892e0 1020 const struct prefix_rd *prd_route = NULL;
196c6b09
LK
1021 struct bgp_path_info *path = NULL;
1022
1023 if (type == RMAP_BGP) {
1024 if (prefix->family != AF_EVPN)
1025 return RMAP_NOMATCH;
1026
1027 prd_rule = (struct prefix_rd *)rule;
1028 path = (struct bgp_path_info *)object;
1029
1030 if (path->net == NULL || path->net->prn == NULL)
1031 return RMAP_NOMATCH;
1032
b54892e0
DS
1033 prd_route =
1034 (struct prefix_rd *)bgp_node_get_prefix(path->net->prn);
196c6b09
LK
1035 if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0)
1036 return RMAP_MATCH;
1037 }
1038
1039 return RMAP_NOMATCH;
1040}
1041
1042/* Route map `rd' match statement. */
1043static void *route_match_rd_compile(const char *arg)
1044{
1045 struct prefix_rd *prd;
1046 int ret;
1047
1048 prd = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct prefix_rd));
1049
1050 ret = str2prefix_rd(arg, prd);
1051 if (!ret) {
1052 XFREE(MTYPE_ROUTE_MAP_COMPILED, prd);
1053 return NULL;
1054 }
1055
1056 return prd;
1057}
1058
1059/* Free route map's compiled `rd' value. */
1060static void route_match_rd_free(void *rule)
1061{
1062 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1063}
1064
1065/* Route map commands for rd matching. */
364deb04
DL
1066static const struct route_map_rule_cmd route_match_evpn_rd_cmd = {
1067 "evpn rd",
1068 route_match_rd,
1069 route_match_rd_compile,
1070 route_match_rd_free
1071};
196c6b09 1072
1dcc9e5b 1073/* Route map commands for VRF route leak with source vrf matching */
b68885f9 1074static enum route_map_cmd_result_t
c3935045
DS
1075route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
1076 route_map_object_t type, void *object)
1dcc9e5b
CS
1077{
1078 struct bgp_path_info *path;
1079 char *vrf_name;
1080
1081 if (type == RMAP_BGP) {
1082 vrf_name = rule;
1083 path = (struct bgp_path_info *)object;
1084
1085 if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
1086 return RMAP_NOMATCH;
1087
1088 if (path->extra == NULL)
1089 return RMAP_NOMATCH;
1090
1091 if (strncmp(vrf_name, vrf_id_to_name(
1092 path->extra->bgp_orig->vrf_id), VRF_NAMSIZ)
1093 == 0)
1094 return RMAP_MATCH;
1095 }
1096
1097 return RMAP_NOMATCH;
1098}
1099
1100static void *route_match_vrl_source_vrf_compile(const char *arg)
1101{
1102 uint8_t *vrf_name = NULL;
1103
1104 vrf_name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1105
1106 return vrf_name;
1107}
1108
1109/* Free route map's compiled `route-type' value. */
1110static void route_match_vrl_source_vrf_free(void *rule)
1111{
1112 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1113}
1114
364deb04
DL
1115static const struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
1116 "source-vrf",
1117 route_match_vrl_source_vrf,
1dcc9e5b 1118 route_match_vrl_source_vrf_compile,
364deb04
DL
1119 route_match_vrl_source_vrf_free
1120};
1dcc9e5b 1121
af291c15
DS
1122/* `match local-preference LOCAL-PREF' */
1123
1124/* Match function return 1 if match is success else return zero. */
b68885f9
LK
1125static enum route_map_cmd_result_t
1126route_match_local_pref(void *rule, const struct prefix *prefix,
1127 route_map_object_t type, void *object)
d62a17ae 1128{
d7c0a89a 1129 uint32_t *local_pref;
9b6d8fcf 1130 struct bgp_path_info *path;
d62a17ae 1131
1132 if (type == RMAP_BGP) {
1133 local_pref = rule;
9b6d8fcf 1134 path = object;
d62a17ae 1135
9b6d8fcf 1136 if (path->attr->local_pref == *local_pref)
d62a17ae 1137 return RMAP_MATCH;
1138 else
1139 return RMAP_NOMATCH;
1140 }
af291c15 1141 return RMAP_NOMATCH;
af291c15
DS
1142}
1143
196c6b09
LK
1144/*
1145 * Route map `match local-preference' match statement.
1146 * `arg' is local-pref value
1147 */
d62a17ae 1148static void *route_match_local_pref_compile(const char *arg)
af291c15 1149{
d7c0a89a 1150 uint32_t *local_pref;
d62a17ae 1151 char *endptr = NULL;
1152 unsigned long tmpval;
af291c15 1153
d62a17ae 1154 /* Locpref value shoud be integer. */
1155 if (!all_digit(arg))
1156 return NULL;
af291c15 1157
d62a17ae 1158 errno = 0;
1159 tmpval = strtoul(arg, &endptr, 10);
1160 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1161 return NULL;
af291c15 1162
d7c0a89a 1163 local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
af291c15 1164
d62a17ae 1165 *local_pref = tmpval;
1166 return local_pref;
af291c15
DS
1167}
1168
1169/* Free route map's compiled `match local-preference' value. */
d62a17ae 1170static void route_match_local_pref_free(void *rule)
af291c15 1171{
d62a17ae 1172 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
af291c15
DS
1173}
1174
1175/* Route map commands for metric matching. */
364deb04
DL
1176static const struct route_map_rule_cmd route_match_local_pref_cmd = {
1177 "local-preference",
1178 route_match_local_pref,
1179 route_match_local_pref_compile,
1180 route_match_local_pref_free
1181};
af291c15 1182
718e3744 1183/* `match metric METRIC' */
1184
1185/* Match function return 1 if match is success else return zero. */
b68885f9
LK
1186static enum route_map_cmd_result_t
1187route_match_metric(void *rule, const struct prefix *prefix,
1188 route_map_object_t type, void *object)
718e3744 1189{
d62a17ae 1190 struct rmap_value *rv;
9b6d8fcf 1191 struct bgp_path_info *path;
718e3744 1192
d62a17ae 1193 if (type == RMAP_BGP) {
1194 rv = rule;
9b6d8fcf
DS
1195 path = object;
1196 return route_value_match(rv, path->attr->med);
d62a17ae 1197 }
1198 return RMAP_NOMATCH;
718e3744 1199}
1200
718e3744 1201/* Route map commands for metric matching. */
364deb04
DL
1202static const struct route_map_rule_cmd route_match_metric_cmd = {
1203 "metric",
1204 route_match_metric,
1205 route_value_compile,
1206 route_value_free,
718e3744 1207};
6b0655a2 1208
718e3744 1209/* `match as-path ASPATH' */
1210
1211/* Match function for as-path match. I assume given object is */
b68885f9
LK
1212static enum route_map_cmd_result_t
1213route_match_aspath(void *rule, const struct prefix *prefix,
1214 route_map_object_t type, void *object)
718e3744 1215{
e52702f2 1216
d62a17ae 1217 struct as_list *as_list;
9b6d8fcf 1218 struct bgp_path_info *path;
718e3744 1219
d62a17ae 1220 if (type == RMAP_BGP) {
1221 as_list = as_list_lookup((char *)rule);
1222 if (as_list == NULL)
1223 return RMAP_NOMATCH;
518f0eb1 1224
9b6d8fcf 1225 path = object;
518f0eb1 1226
d62a17ae 1227 /* Perform match. */
9b6d8fcf 1228 return ((as_list_apply(as_list, path->attr->aspath)
d62a17ae 1229 == AS_FILTER_DENY)
1230 ? RMAP_NOMATCH
1231 : RMAP_MATCH);
1232 }
1233 return RMAP_NOMATCH;
718e3744 1234}
1235
1236/* Compile function for as-path match. */
d62a17ae 1237static void *route_match_aspath_compile(const char *arg)
718e3744 1238{
d62a17ae 1239 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 1240}
1241
1242/* Compile function for as-path match. */
d62a17ae 1243static void route_match_aspath_free(void *rule)
718e3744 1244{
d62a17ae 1245 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 1246}
1247
1248/* Route map commands for aspath matching. */
364deb04
DL
1249static const struct route_map_rule_cmd route_match_aspath_cmd = {
1250 "as-path",
1251 route_match_aspath,
1252 route_match_aspath_compile,
1253 route_match_aspath_free
1254};
6b0655a2 1255
718e3744 1256/* `match community COMMUNIY' */
d62a17ae 1257struct rmap_community {
1258 char *name;
e237b0d2 1259 uint32_t name_hash;
d62a17ae 1260 int exact;
718e3744 1261};
1262
1263/* Match function for community match. */
b68885f9
LK
1264static enum route_map_cmd_result_t
1265route_match_community(void *rule, const struct prefix *prefix,
1266 route_map_object_t type, void *object)
d62a17ae 1267{
1268 struct community_list *list;
9b6d8fcf 1269 struct bgp_path_info *path;
e9a223ac 1270 struct rmap_community *rcom = rule;
d62a17ae 1271
1272 if (type == RMAP_BGP) {
9b6d8fcf 1273 path = object;
d62a17ae 1274 rcom = rule;
1275
1276 list = community_list_lookup(bgp_clist, rcom->name,
e237b0d2 1277 rcom->name_hash,
d62a17ae 1278 COMMUNITY_LIST_MASTER);
1279 if (!list)
1280 return RMAP_NOMATCH;
1281
1282 if (rcom->exact) {
9b6d8fcf
DS
1283 if (community_list_exact_match(path->attr->community,
1284 list))
d62a17ae 1285 return RMAP_MATCH;
1286 } else {
9b6d8fcf 1287 if (community_list_match(path->attr->community, list))
d62a17ae 1288 return RMAP_MATCH;
1289 }
718e3744 1290 }
d62a17ae 1291 return RMAP_NOMATCH;
718e3744 1292}
1293
1294/* Compile function for community match. */
d62a17ae 1295static void *route_match_community_compile(const char *arg)
1296{
1297 struct rmap_community *rcom;
1298 int len;
1299 char *p;
1300
1301 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1302
1303 p = strchr(arg, ' ');
1304 if (p) {
1305 len = p - arg;
1306 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1307 memcpy(rcom->name, arg, len);
1308 rcom->exact = 1;
1309 } else {
1310 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1311 rcom->exact = 0;
1312 }
e237b0d2
DS
1313
1314 rcom->name_hash = bgp_clist_hash_key(rcom->name);
d62a17ae 1315 return rcom;
718e3744 1316}
1317
1318/* Compile function for community match. */
d62a17ae 1319static void route_match_community_free(void *rule)
718e3744 1320{
d62a17ae 1321 struct rmap_community *rcom = rule;
718e3744 1322
d62a17ae 1323 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1324 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 1325}
1326
909f3d56 1327/*
1328 * In routemap processing there is a need to add the
1329 * name as a rule_key in the dependency table. Routemap
1330 * lib is unaware of rule_key when exact-match clause
1331 * is in use. routemap lib uses the compiled output to
1332 * get the rule_key value.
1333 */
1334static void *route_match_get_community_key(void *rule)
1335{
1336 struct rmap_community *rcom;
1337
1338 rcom = rule;
1339 return rcom->name;
1340}
1341
1342
718e3744 1343/* Route map commands for community matching. */
364deb04
DL
1344static const struct route_map_rule_cmd route_match_community_cmd = {
1345 "community",
1346 route_match_community,
1347 route_match_community_compile,
1348 route_match_community_free,
1349 route_match_get_community_key
1350};
6b0655a2 1351
57d187bc 1352/* Match function for lcommunity match. */
b68885f9
LK
1353static enum route_map_cmd_result_t
1354route_match_lcommunity(void *rule, const struct prefix *prefix,
1355 route_map_object_t type, void *object)
d62a17ae 1356{
1357 struct community_list *list;
9b6d8fcf 1358 struct bgp_path_info *path;
e9a223ac 1359 struct rmap_community *rcom = rule;
d62a17ae 1360
1361 if (type == RMAP_BGP) {
9b6d8fcf 1362 path = object;
d62a17ae 1363
1364 list = community_list_lookup(bgp_clist, rcom->name,
e237b0d2 1365 rcom->name_hash,
d62a17ae 1366 LARGE_COMMUNITY_LIST_MASTER);
1367 if (!list)
1368 return RMAP_NOMATCH;
1369
03ff9a14 1370 if (rcom->exact) {
1371 if (lcommunity_list_exact_match(
1372 path->attr->lcommunity,
1373 list))
1374 return RMAP_MATCH;
1375 } else {
1376 if (lcommunity_list_match(
1377 path->attr->lcommunity,
1378 list))
1379 return RMAP_MATCH;
1380 }
d62a17ae 1381 }
1382 return RMAP_NOMATCH;
57d187bc
JS
1383}
1384
1385/* Compile function for community match. */
d62a17ae 1386static void *route_match_lcommunity_compile(const char *arg)
1387{
1388 struct rmap_community *rcom;
1389 int len;
1390 char *p;
1391
1392 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1393
1394 p = strchr(arg, ' ');
1395 if (p) {
1396 len = p - arg;
1397 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1398 memcpy(rcom->name, arg, len);
03ff9a14 1399 rcom->exact = 1;
d62a17ae 1400 } else {
1401 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1402 rcom->exact = 0;
1403 }
e237b0d2
DS
1404
1405 rcom->name_hash = bgp_clist_hash_key(rcom->name);
d62a17ae 1406 return rcom;
57d187bc
JS
1407}
1408
1409/* Compile function for community match. */
d62a17ae 1410static void route_match_lcommunity_free(void *rule)
57d187bc 1411{
d62a17ae 1412 struct rmap_community *rcom = rule;
57d187bc 1413
d62a17ae 1414 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1415 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
1416}
1417
1418/* Route map commands for community matching. */
364deb04
DL
1419static const struct route_map_rule_cmd route_match_lcommunity_cmd = {
1420 "large-community",
1421 route_match_lcommunity,
1422 route_match_lcommunity_compile,
1423 route_match_lcommunity_free,
1424 route_match_get_community_key
1425};
57d187bc
JS
1426
1427
73ffb25b 1428/* Match function for extcommunity match. */
b68885f9
LK
1429static enum route_map_cmd_result_t
1430route_match_ecommunity(void *rule, const struct prefix *prefix,
1431 route_map_object_t type, void *object)
73ffb25b 1432{
d62a17ae 1433 struct community_list *list;
9b6d8fcf 1434 struct bgp_path_info *path;
e9a223ac 1435 struct rmap_community *rcom = rule;
73ffb25b 1436
d62a17ae 1437 if (type == RMAP_BGP) {
9b6d8fcf 1438 path = object;
e52702f2 1439
e9a223ac 1440 list = community_list_lookup(bgp_clist, rcom->name,
e237b0d2 1441 rcom->name_hash,
d62a17ae 1442 EXTCOMMUNITY_LIST_MASTER);
1443 if (!list)
1444 return RMAP_NOMATCH;
73ffb25b 1445
9b6d8fcf 1446 if (ecommunity_list_match(path->attr->ecommunity, list))
d62a17ae 1447 return RMAP_MATCH;
1448 }
1449 return RMAP_NOMATCH;
73ffb25b 1450}
1451
1452/* Compile function for extcommunity match. */
d62a17ae 1453static void *route_match_ecommunity_compile(const char *arg)
73ffb25b 1454{
e9a223ac
DS
1455 struct rmap_community *rcom;
1456
1457 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1458 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
e237b0d2 1459 rcom->name_hash = bgp_clist_hash_key(rcom->name);
e9a223ac
DS
1460
1461 return rcom;
73ffb25b 1462}
1463
1464/* Compile function for extcommunity match. */
d62a17ae 1465static void route_match_ecommunity_free(void *rule)
73ffb25b 1466{
e9a223ac
DS
1467 struct rmap_community *rcom = rule;
1468
1469 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1470 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
73ffb25b 1471}
1472
1473/* Route map commands for community matching. */
364deb04
DL
1474static const struct route_map_rule_cmd route_match_ecommunity_cmd = {
1475 "extcommunity",
1476 route_match_ecommunity,
1477 route_match_ecommunity_compile,
1478 route_match_ecommunity_free
1479};
6b0655a2 1480
718e3744 1481/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1482 and `address-family vpnv4'. */
6b0655a2 1483
718e3744 1484/* `match origin' */
b68885f9
LK
1485static enum route_map_cmd_result_t
1486route_match_origin(void *rule, const struct prefix *prefix,
1487 route_map_object_t type, void *object)
718e3744 1488{
d7c0a89a 1489 uint8_t *origin;
9b6d8fcf 1490 struct bgp_path_info *path;
718e3744 1491
d62a17ae 1492 if (type == RMAP_BGP) {
1493 origin = rule;
9b6d8fcf 1494 path = object;
e52702f2 1495
9b6d8fcf 1496 if (path->attr->origin == *origin)
d62a17ae 1497 return RMAP_MATCH;
1498 }
718e3744 1499
d62a17ae 1500 return RMAP_NOMATCH;
718e3744 1501}
1502
d62a17ae 1503static void *route_match_origin_compile(const char *arg)
718e3744 1504{
d7c0a89a 1505 uint8_t *origin;
718e3744 1506
d7c0a89a 1507 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 1508
d62a17ae 1509 if (strcmp(arg, "igp") == 0)
1510 *origin = 0;
1511 else if (strcmp(arg, "egp") == 0)
1512 *origin = 1;
1513 else
1514 *origin = 2;
718e3744 1515
d62a17ae 1516 return origin;
718e3744 1517}
1518
1519/* Free route map's compiled `ip address' value. */
d62a17ae 1520static void route_match_origin_free(void *rule)
718e3744 1521{
d62a17ae 1522 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 1523}
1524
1525/* Route map commands for origin matching. */
364deb04
DL
1526static const struct route_map_rule_cmd route_match_origin_cmd = {
1527 "origin",
1528 route_match_origin,
1529 route_match_origin_compile,
1530 route_match_origin_free
1531};
1add115a
VT
1532
1533/* match probability { */
1534
b68885f9
LK
1535static enum route_map_cmd_result_t
1536route_match_probability(void *rule, const struct prefix *prefix,
1537 route_map_object_t type, void *object)
d62a17ae 1538{
5920b3eb 1539 long r = frr_weak_random();
d62a17ae 1540
1541 switch (*(long *)rule) {
1542 case 0:
1543 break;
1544 case RAND_MAX:
1545 return RMAP_MATCH;
1546 default:
1547 if (r < *(long *)rule) {
1548 return RMAP_MATCH;
1549 }
1550 }
1add115a 1551
d62a17ae 1552 return RMAP_NOMATCH;
1add115a
VT
1553}
1554
d62a17ae 1555static void *route_match_probability_compile(const char *arg)
1add115a 1556{
d62a17ae 1557 long *lobule;
1558 unsigned perc;
1add115a 1559
d62a17ae 1560 perc = atoi(arg);
1561 lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long));
1add115a 1562
d62a17ae 1563 switch (perc) {
1564 case 0:
1565 *lobule = 0;
1566 break;
1567 case 100:
1568 *lobule = RAND_MAX;
1569 break;
1570 default:
1571 *lobule = RAND_MAX / 100 * perc;
1572 }
1add115a 1573
d62a17ae 1574 return lobule;
1add115a
VT
1575}
1576
d62a17ae 1577static void route_match_probability_free(void *rule)
1add115a 1578{
d62a17ae 1579 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1add115a
VT
1580}
1581
364deb04
DL
1582static const struct route_map_rule_cmd route_match_probability_cmd = {
1583 "probability",
1584 route_match_probability,
1585 route_match_probability_compile,
1586 route_match_probability_free
1587};
1add115a 1588
bc413143
DS
1589/* `match interface IFNAME' */
1590/* Match function should return 1 if match is success else return
1591 zero. */
b68885f9
LK
1592static enum route_map_cmd_result_t
1593route_match_interface(void *rule, const struct prefix *prefix,
1594 route_map_object_t type, void *object)
bc413143 1595{
d62a17ae 1596 struct interface *ifp;
40381db7 1597 struct bgp_path_info *path;
bc413143 1598
d62a17ae 1599 if (type == RMAP_BGP) {
40381db7 1600 path = object;
bc413143 1601
05864da7 1602 if (!path)
d62a17ae 1603 return RMAP_NOMATCH;
bc413143 1604
d62a17ae 1605 ifp = if_lookup_by_name_all_vrf((char *)rule);
bc413143 1606
40381db7 1607 if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
d62a17ae 1608 return RMAP_NOMATCH;
bc413143 1609
d62a17ae 1610 return RMAP_MATCH;
1611 }
1612 return RMAP_NOMATCH;
bc413143
DS
1613}
1614
1615/* Route map `interface' match statement. `arg' should be
1616 interface name. */
d62a17ae 1617static void *route_match_interface_compile(const char *arg)
bc413143 1618{
d62a17ae 1619 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
bc413143
DS
1620}
1621
1622/* Free route map's compiled `interface' value. */
d62a17ae 1623static void route_match_interface_free(void *rule)
bc413143 1624{
d62a17ae 1625 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
bc413143
DS
1626}
1627
1628/* Route map commands for ip address matching. */
364deb04
DL
1629static const struct route_map_rule_cmd route_match_interface_cmd = {
1630 "interface",
1631 route_match_interface,
1632 route_match_interface_compile,
1633 route_match_interface_free
1634};
bc413143 1635
1add115a
VT
1636/* } */
1637
718e3744 1638/* `set ip next-hop IP_ADDRESS' */
1639
0d9551dc 1640/* Match function return 1 if match is success else return zero. */
b68885f9
LK
1641static enum route_map_cmd_result_t
1642route_match_tag(void *rule, const struct prefix *prefix,
1643 route_map_object_t type, void *object)
0d9551dc 1644{
d62a17ae 1645 route_tag_t *tag;
9b6d8fcf 1646 struct bgp_path_info *path;
0d9551dc 1647
d62a17ae 1648 if (type == RMAP_BGP) {
1649 tag = rule;
9b6d8fcf 1650 path = object;
0d9551dc 1651
9b6d8fcf 1652 return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
d62a17ae 1653 }
0d9551dc 1654
d62a17ae 1655 return RMAP_NOMATCH;
0d9551dc
DS
1656}
1657
1658
0d9551dc 1659/* Route map commands for tag matching. */
364deb04
DL
1660static const struct route_map_rule_cmd route_match_tag_cmd = {
1661 "tag",
1662 route_match_tag,
1663 route_map_rule_tag_compile,
d62a17ae 1664 route_map_rule_tag_free,
0d9551dc
DS
1665};
1666
1667
718e3744 1668/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 1669struct rmap_ip_nexthop_set {
1670 struct in_addr *address;
1671 int peer_address;
1672 int unchanged;
ac41b2a2 1673};
1674
b68885f9
LK
1675static enum route_map_cmd_result_t
1676route_set_ip_nexthop(void *rule, const struct prefix *prefix,
1677 route_map_object_t type, void *object)
d62a17ae 1678{
1679 struct rmap_ip_nexthop_set *rins = rule;
9b6d8fcf 1680 struct bgp_path_info *path;
d62a17ae 1681 struct peer *peer;
1682
2b67b6f1
DS
1683 if (type != RMAP_BGP)
1684 return RMAP_OKAY;
1685
77f4dfb9
DS
1686 if (prefix->family == AF_INET6)
1687 return RMAP_OKAY;
1688
2b67b6f1
DS
1689 path = object;
1690 peer = path->peer;
1691
1692 if (rins->unchanged) {
1693 SET_FLAG(path->attr->rmap_change_flags,
1694 BATTR_RMAP_NEXTHOP_UNCHANGED);
1695 } else if (rins->peer_address) {
1696 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
1697 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
1698 && peer->su_remote
1699 && sockunion_family(peer->su_remote) == AF_INET) {
1700 path->attr->nexthop.s_addr =
1701 sockunion2ip(peer->su_remote);
9b6d8fcf 1702 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
2b67b6f1
DS
1703 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
1704 /* The next hop value will be set as part of
1705 * packet rewrite. Set the flags here to indicate
1706 * that rewrite needs to be done.
1707 * Also, clear the value.
1708 */
9b6d8fcf 1709 SET_FLAG(path->attr->rmap_change_flags,
2b67b6f1 1710 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
975a328e 1711 path->attr->nexthop.s_addr = INADDR_ANY;
d62a17ae 1712 }
2b67b6f1
DS
1713 } else {
1714 /* Set next hop value. */
1715 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1716 path->attr->nexthop = *rins->address;
1717 SET_FLAG(path->attr->rmap_change_flags,
1718 BATTR_RMAP_IPV4_NHOP_CHANGED);
1719 /* case for MP-BGP : MPLS VPN */
1720 path->attr->mp_nexthop_global_in = *rins->address;
1721 path->attr->mp_nexthop_len = sizeof(*rins->address);
ac41b2a2 1722 }
718e3744 1723
d62a17ae 1724 return RMAP_OKAY;
718e3744 1725}
1726
1727/* Route map `ip nexthop' compile function. Given string is converted
1728 to struct in_addr structure. */
d62a17ae 1729static void *route_set_ip_nexthop_compile(const char *arg)
1730{
1731 struct rmap_ip_nexthop_set *rins;
1732 struct in_addr *address = NULL;
1733 int peer_address = 0;
1734 int unchanged = 0;
1735 int ret;
1736
1737 if (strcmp(arg, "peer-address") == 0)
1738 peer_address = 1;
1739 else if (strcmp(arg, "unchanged") == 0)
1740 unchanged = 1;
1741 else {
1742 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
1743 sizeof(struct in_addr));
1744 ret = inet_aton(arg, address);
1745
1746 if (ret == 0) {
1747 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
1748 return NULL;
1749 }
ac41b2a2 1750 }
718e3744 1751
d62a17ae 1752 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
1753 sizeof(struct rmap_ip_nexthop_set));
ac41b2a2 1754
d62a17ae 1755 rins->address = address;
1756 rins->peer_address = peer_address;
1757 rins->unchanged = unchanged;
ac41b2a2 1758
d62a17ae 1759 return rins;
718e3744 1760}
1761
1762/* Free route map's compiled `ip nexthop' value. */
d62a17ae 1763static void route_set_ip_nexthop_free(void *rule)
718e3744 1764{
d62a17ae 1765 struct rmap_ip_nexthop_set *rins = rule;
ac41b2a2 1766
0a22ddfb 1767 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
e52702f2 1768
d62a17ae 1769 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
718e3744 1770}
1771
1772/* Route map commands for ip nexthop set. */
364deb04
DL
1773static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
1774 "ip next-hop",
1775 route_set_ip_nexthop,
1776 route_set_ip_nexthop_compile,
1777 route_set_ip_nexthop_free
1778};
6b0655a2 1779
718e3744 1780/* `set local-preference LOCAL_PREF' */
1781
1782/* Set local preference. */
b68885f9
LK
1783static enum route_map_cmd_result_t
1784route_set_local_pref(void *rule, const struct prefix *prefix,
1785 route_map_object_t type, void *object)
d62a17ae 1786{
1787 struct rmap_value *rv;
9b6d8fcf 1788 struct bgp_path_info *path;
d7c0a89a 1789 uint32_t locpref = 0;
d62a17ae 1790
1791 if (type == RMAP_BGP) {
1792 /* Fetch routemap's rule information. */
1793 rv = rule;
9b6d8fcf 1794 path = object;
d62a17ae 1795
1796 /* Set local preference value. */
9b6d8fcf
DS
1797 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
1798 locpref = path->attr->local_pref;
d62a17ae 1799
9b6d8fcf
DS
1800 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1801 path->attr->local_pref =
1802 route_value_adjust(rv, locpref, path->peer);
d62a17ae 1803 }
718e3744 1804
d62a17ae 1805 return RMAP_OKAY;
718e3744 1806}
1807
718e3744 1808/* Set local preference rule structure. */
364deb04
DL
1809static const struct route_map_rule_cmd route_set_local_pref_cmd = {
1810 "local-preference",
1811 route_set_local_pref,
1812 route_value_compile,
d62a17ae 1813 route_value_free,
718e3744 1814};
6b0655a2 1815
718e3744 1816/* `set weight WEIGHT' */
1817
1818/* Set weight. */
b68885f9
LK
1819static enum route_map_cmd_result_t
1820route_set_weight(void *rule, const struct prefix *prefix,
1821 route_map_object_t type, void *object)
718e3744 1822{
d62a17ae 1823 struct rmap_value *rv;
9b6d8fcf 1824 struct bgp_path_info *path;
718e3744 1825
d62a17ae 1826 if (type == RMAP_BGP) {
1827 /* Fetch routemap's rule information. */
1828 rv = rule;
9b6d8fcf 1829 path = object;
e52702f2 1830
d62a17ae 1831 /* Set weight value. */
9b6d8fcf 1832 path->attr->weight = route_value_adjust(rv, 0, path->peer);
d62a17ae 1833 }
718e3744 1834
d62a17ae 1835 return RMAP_OKAY;
718e3744 1836}
1837
718e3744 1838/* Set local preference rule structure. */
364deb04
DL
1839static const struct route_map_rule_cmd route_set_weight_cmd = {
1840 "weight",
1841 route_set_weight,
1842 route_value_compile,
1843 route_value_free,
718e3744 1844};
6b0655a2 1845
7b7d48e5
DS
1846/* `set distance DISTANCE */
1847static enum route_map_cmd_result_t
1848route_set_distance(void *rule, const struct prefix *prefix,
1849 route_map_object_t type, void *object)
1850{
1851 struct bgp_path_info *path = object;
1852 struct rmap_value *rv = rule;
1853
1854 if (type != RMAP_BGP)
1855 return RMAP_OKAY;
1856
1857 path->attr->distance = rv->value;
1858
1859 return RMAP_OKAY;
1860}
1861
1862/* set distance rule structure */
364deb04 1863static const struct route_map_rule_cmd route_set_distance_cmd = {
7b7d48e5
DS
1864 "distance",
1865 route_set_distance,
1866 route_value_compile,
1867 route_value_free,
1868};
1869
718e3744 1870/* `set metric METRIC' */
1871
1872/* Set metric to attribute. */
b68885f9
LK
1873static enum route_map_cmd_result_t
1874route_set_metric(void *rule, const struct prefix *prefix,
1875 route_map_object_t type, void *object)
d62a17ae 1876{
1877 struct rmap_value *rv;
9b6d8fcf 1878 struct bgp_path_info *path;
d7c0a89a 1879 uint32_t med = 0;
d62a17ae 1880
1881 if (type == RMAP_BGP) {
1882 /* Fetch routemap's rule information. */
1883 rv = rule;
9b6d8fcf 1884 path = object;
d62a17ae 1885
9b6d8fcf
DS
1886 if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
1887 med = path->attr->med;
d62a17ae 1888
9b6d8fcf
DS
1889 path->attr->med = route_value_adjust(rv, med, path->peer);
1890 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
d62a17ae 1891 }
1892 return RMAP_OKAY;
718e3744 1893}
1894
718e3744 1895/* Set metric rule structure. */
364deb04
DL
1896static const struct route_map_rule_cmd route_set_metric_cmd = {
1897 "metric",
1898 route_set_metric,
1899 route_value_compile,
1900 route_value_free,
718e3744 1901};
6b0655a2 1902
951745bd
PG
1903/* `set table (1-4294967295)' */
1904
1905static enum route_map_cmd_result_t route_set_table_id(void *rule,
1906 const struct prefix *prefix,
1907 route_map_object_t type,
1908 void *object)
1909{
1910 struct rmap_value *rv;
1911 struct bgp_path_info *path;
1912
1913 if (type == RMAP_BGP) {
1914 /* Fetch routemap's rule information. */
1915 rv = rule;
1916 path = object;
1917
1918 path->attr->rmap_table_id = rv->value;
1919 }
1920 return RMAP_OKAY;
1921}
1922
1923/* Set table_id rule structure. */
364deb04
DL
1924static const struct route_map_rule_cmd route_set_table_id_cmd = {
1925 "table",
1926 route_set_table_id,
1927 route_value_compile,
1928 route_value_free
951745bd
PG
1929};
1930
718e3744 1931/* `set as-path prepend ASPATH' */
1932
1933/* For AS path prepend mechanism. */
b68885f9
LK
1934static enum route_map_cmd_result_t
1935route_set_aspath_prepend(void *rule, const struct prefix *prefix,
1936 route_map_object_t type, void *object)
d62a17ae 1937{
1938 struct aspath *aspath;
1939 struct aspath *new;
9b6d8fcf 1940 struct bgp_path_info *path;
d62a17ae 1941
1942 if (type == RMAP_BGP) {
9b6d8fcf 1943 path = object;
d62a17ae 1944
9b6d8fcf
DS
1945 if (path->attr->aspath->refcnt)
1946 new = aspath_dup(path->attr->aspath);
d62a17ae 1947 else
9b6d8fcf 1948 new = path->attr->aspath;
d62a17ae 1949
1950 if ((uintptr_t)rule > 10) {
1951 aspath = rule;
1952 aspath_prepend(aspath, new);
1953 } else {
1954 as_t as = aspath_leftmost(new);
1955 if (!as)
9b6d8fcf 1956 as = path->peer->as;
d62a17ae 1957 new = aspath_add_seq_n(new, as, (uintptr_t)rule);
1958 }
bc3dd427 1959
9b6d8fcf 1960 path->attr->aspath = new;
d62a17ae 1961 }
718e3744 1962
d62a17ae 1963 return RMAP_OKAY;
718e3744 1964}
1965
d62a17ae 1966static void *route_set_aspath_prepend_compile(const char *arg)
bc3dd427 1967{
d62a17ae 1968 unsigned int num;
bc3dd427 1969
d62a17ae 1970 if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
1971 return (void *)(uintptr_t)num;
bc3dd427 1972
d62a17ae 1973 return route_aspath_compile(arg);
bc3dd427
DW
1974}
1975
d62a17ae 1976static void route_set_aspath_prepend_free(void *rule)
bc3dd427 1977{
d62a17ae 1978 if ((uintptr_t)rule > 10)
1979 route_aspath_free(rule);
bc3dd427
DW
1980}
1981
1982
515e500c 1983/* Set as-path prepend rule structure. */
364deb04
DL
1984static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
1985 "as-path prepend",
1986 route_set_aspath_prepend,
1987 route_set_aspath_prepend_compile,
1988 route_set_aspath_prepend_free,
718e3744 1989};
6b0655a2 1990
841f7a57
DO
1991/* `set as-path exclude ASn' */
1992
1993/* For ASN exclude mechanism.
d62a17ae 1994 * Iterate over ASns requested and filter them from the given AS_PATH one by
1995 * one.
841f7a57
DO
1996 * Make a deep copy of existing AS_PATH, but for the first ASn only.
1997 */
b68885f9
LK
1998static enum route_map_cmd_result_t
1999route_set_aspath_exclude(void *rule, const struct prefix *dummy,
2000 route_map_object_t type, void *object)
d62a17ae 2001{
2002 struct aspath *new_path, *exclude_path;
9b6d8fcf 2003 struct bgp_path_info *path;
d62a17ae 2004
2005 if (type == RMAP_BGP) {
2006 exclude_path = rule;
9b6d8fcf
DS
2007 path = object;
2008 if (path->attr->aspath->refcnt)
2009 new_path = aspath_dup(path->attr->aspath);
d62a17ae 2010 else
9b6d8fcf
DS
2011 new_path = path->attr->aspath;
2012 path->attr->aspath =
d62a17ae 2013 aspath_filter_exclude(new_path, exclude_path);
2014 }
2015 return RMAP_OKAY;
841f7a57
DO
2016}
2017
841f7a57 2018/* Set ASn exlude rule structure. */
364deb04
DL
2019static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
2020 "as-path exclude",
2021 route_set_aspath_exclude,
2022 route_aspath_compile,
d62a17ae 2023 route_aspath_free,
841f7a57 2024};
6b0655a2 2025
718e3744 2026/* `set community COMMUNITY' */
d62a17ae 2027struct rmap_com_set {
2028 struct community *com;
2029 int additive;
2030 int none;
718e3744 2031};
2032
2033/* For community set mechanism. */
b68885f9
LK
2034static enum route_map_cmd_result_t
2035route_set_community(void *rule, const struct prefix *prefix,
2036 route_map_object_t type, void *object)
d62a17ae 2037{
2038 struct rmap_com_set *rcs;
9b6d8fcf 2039 struct bgp_path_info *path;
d62a17ae 2040 struct attr *attr;
2041 struct community *new = NULL;
2042 struct community *old;
2043 struct community *merge;
2044
2045 if (type == RMAP_BGP) {
2046 rcs = rule;
9b6d8fcf
DS
2047 path = object;
2048 attr = path->attr;
d62a17ae 2049 old = attr->community;
2050
2051 /* "none" case. */
2052 if (rcs->none) {
2053 attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
2054 attr->community = NULL;
2055 /* See the longer comment down below. */
2056 if (old && old->refcnt == 0)
3c1f53de 2057 community_free(&old);
d62a17ae 2058 return RMAP_OKAY;
2059 }
718e3744 2060
d62a17ae 2061 /* "additive" case. */
2062 if (rcs->additive && old) {
2063 merge = community_merge(community_dup(old), rcs->com);
2064
d62a17ae 2065 new = community_uniq_sort(merge);
3c1f53de 2066 community_free(&merge);
d62a17ae 2067 } else
2068 new = community_dup(rcs->com);
2069
f24804f4
NK
2070 /* HACK: if the old community is not intern'd,
2071 * we should free it here, or all reference to it may be
2072 * lost.
2073 * Really need to cleanup attribute caching sometime.
2074 */
2075 if (old && old->refcnt == 0)
3c1f53de 2076 community_free(&old);
f24804f4 2077
d62a17ae 2078 /* will be interned by caller if required */
2079 attr->community = new;
2080
2081 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
718e3744 2082 }
718e3744 2083
d62a17ae 2084 return RMAP_OKAY;
718e3744 2085}
2086
2087/* Compile function for set community. */
d62a17ae 2088static void *route_set_community_compile(const char *arg)
2089{
2090 struct rmap_com_set *rcs;
2091 struct community *com = NULL;
2092 char *sp;
2093 int additive = 0;
2094 int none = 0;
2095
2096 if (strcmp(arg, "none") == 0)
2097 none = 1;
2098 else {
2099 sp = strstr(arg, "additive");
2100
2101 if (sp && sp > arg) {
770817b4 2102 /* "additive" keyword is included. */
d62a17ae 2103 additive = 1;
2104 *(sp - 1) = '\0';
2105 }
718e3744 2106
d62a17ae 2107 com = community_str2com(arg);
718e3744 2108
d62a17ae 2109 if (additive)
2110 *(sp - 1) = ' ';
718e3744 2111
d62a17ae 2112 if (!com)
2113 return NULL;
2114 }
e52702f2 2115
d62a17ae 2116 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2117 rcs->com = com;
2118 rcs->additive = additive;
2119 rcs->none = none;
e52702f2 2120
d62a17ae 2121 return rcs;
718e3744 2122}
2123
2124/* Free function for set community. */
d62a17ae 2125static void route_set_community_free(void *rule)
718e3744 2126{
d62a17ae 2127 struct rmap_com_set *rcs = rule;
718e3744 2128
d62a17ae 2129 if (rcs->com)
3c1f53de 2130 community_free(&rcs->com);
d62a17ae 2131 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
718e3744 2132}
2133
2134/* Set community rule structure. */
364deb04
DL
2135static const struct route_map_rule_cmd route_set_community_cmd = {
2136 "community",
2137 route_set_community,
2138 route_set_community_compile,
d62a17ae 2139 route_set_community_free,
718e3744 2140};
6b0655a2 2141
57d187bc 2142/* `set community COMMUNITY' */
d62a17ae 2143struct rmap_lcom_set {
2144 struct lcommunity *lcom;
2145 int additive;
2146 int none;
57d187bc
JS
2147};
2148
2149
2150/* For lcommunity set mechanism. */
b68885f9
LK
2151static enum route_map_cmd_result_t
2152route_set_lcommunity(void *rule, const struct prefix *prefix,
2153 route_map_object_t type, void *object)
d62a17ae 2154{
2155 struct rmap_lcom_set *rcs;
9b6d8fcf 2156 struct bgp_path_info *path;
d62a17ae 2157 struct attr *attr;
2158 struct lcommunity *new = NULL;
2159 struct lcommunity *old;
2160 struct lcommunity *merge;
2161
2162 if (type == RMAP_BGP) {
2163 rcs = rule;
9b6d8fcf
DS
2164 path = object;
2165 attr = path->attr;
d62a17ae 2166 old = attr->lcommunity;
2167
2168 /* "none" case. */
2169 if (rcs->none) {
2170 attr->flag &=
2171 ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
2172 attr->lcommunity = NULL;
2173
2174 /* See the longer comment down below. */
2175 if (old && old->refcnt == 0)
2176 lcommunity_free(&old);
2177 return RMAP_OKAY;
2178 }
57d187bc 2179
d62a17ae 2180 if (rcs->additive && old) {
2181 merge = lcommunity_merge(lcommunity_dup(old),
2182 rcs->lcom);
2183
d62a17ae 2184 new = lcommunity_uniq_sort(merge);
2185 lcommunity_free(&merge);
2186 } else
2187 new = lcommunity_dup(rcs->lcom);
2188
4265a53e
NK
2189 /* HACK: if the old large-community is not intern'd,
2190 * we should free it here, or all reference to it may be
2191 * lost.
2192 * Really need to cleanup attribute caching sometime.
2193 */
2194 if (old && old->refcnt == 0)
2195 lcommunity_free(&old);
2196
d62a17ae 2197 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
2198 attr->lcommunity = new;
2199
2200 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
2201 }
57d187bc 2202
d62a17ae 2203 return RMAP_OKAY;
2204}
57d187bc 2205
d62a17ae 2206/* Compile function for set community. */
2207static void *route_set_lcommunity_compile(const char *arg)
2208{
2209 struct rmap_lcom_set *rcs;
2210 struct lcommunity *lcom = NULL;
2211 char *sp;
2212 int additive = 0;
2213 int none = 0;
2214
2215 if (strcmp(arg, "none") == 0)
2216 none = 1;
2217 else {
2218 sp = strstr(arg, "additive");
2219
2220 if (sp && sp > arg) {
2221 /* "additive" keyworkd is included. */
2222 additive = 1;
2223 *(sp - 1) = '\0';
2224 }
57d187bc 2225
d62a17ae 2226 lcom = lcommunity_str2com(arg);
57d187bc 2227
d62a17ae 2228 if (additive)
2229 *(sp - 1) = ' ';
57d187bc 2230
d62a17ae 2231 if (!lcom)
2232 return NULL;
2233 }
57d187bc 2234
d62a17ae 2235 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2236 rcs->lcom = lcom;
2237 rcs->additive = additive;
2238 rcs->none = none;
57d187bc 2239
d62a17ae 2240 return rcs;
57d187bc
JS
2241}
2242
2243/* Free function for set lcommunity. */
d62a17ae 2244static void route_set_lcommunity_free(void *rule)
57d187bc 2245{
d62a17ae 2246 struct rmap_lcom_set *rcs = rule;
57d187bc 2247
d62a17ae 2248 if (rcs->lcom) {
2249 lcommunity_free(&rcs->lcom);
2250 }
2251 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
57d187bc
JS
2252}
2253
2254/* Set community rule structure. */
364deb04
DL
2255static const struct route_map_rule_cmd route_set_lcommunity_cmd = {
2256 "large-community",
2257 route_set_lcommunity,
2258 route_set_lcommunity_compile,
d62a17ae 2259 route_set_lcommunity_free,
57d187bc
JS
2260};
2261
2262/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
2263
2264/* For large community set mechanism. */
b68885f9
LK
2265static enum route_map_cmd_result_t
2266route_set_lcommunity_delete(void *rule, const struct prefix *pfx,
2267 route_map_object_t type, void *object)
d62a17ae 2268{
2269 struct community_list *list;
2270 struct lcommunity *merge;
2271 struct lcommunity *new;
2272 struct lcommunity *old;
9b6d8fcf 2273 struct bgp_path_info *path;
e9a223ac 2274 struct rmap_community *rcom = rule;
d62a17ae 2275
2276 if (type == RMAP_BGP) {
e9a223ac 2277 if (!rcom)
d62a17ae 2278 return RMAP_OKAY;
2279
9b6d8fcf 2280 path = object;
e9a223ac 2281 list = community_list_lookup(bgp_clist, rcom->name,
e237b0d2 2282 rcom->name_hash,
d62a17ae 2283 LARGE_COMMUNITY_LIST_MASTER);
9b6d8fcf 2284 old = path->attr->lcommunity;
d62a17ae 2285
2286 if (list && old) {
2287 merge = lcommunity_list_match_delete(
2288 lcommunity_dup(old), list);
2289 new = lcommunity_uniq_sort(merge);
2290 lcommunity_free(&merge);
2291
2292 /* HACK: if the old community is not intern'd,
2293 * we should free it here, or all reference to it may be
2294 * lost.
2295 * Really need to cleanup attribute caching sometime.
2296 */
2297 if (old->refcnt == 0)
2298 lcommunity_free(&old);
2299
2300 if (new->size == 0) {
9b6d8fcf
DS
2301 path->attr->lcommunity = NULL;
2302 path->attr->flag &= ~ATTR_FLAG_BIT(
d62a17ae 2303 BGP_ATTR_LARGE_COMMUNITIES);
2304 lcommunity_free(&new);
2305 } else {
9b6d8fcf
DS
2306 path->attr->lcommunity = new;
2307 path->attr->flag |= ATTR_FLAG_BIT(
d62a17ae 2308 BGP_ATTR_LARGE_COMMUNITIES);
2309 }
2310 }
2311 }
2312
2313 return RMAP_OKAY;
57d187bc
JS
2314}
2315
2316/* Compile function for set lcommunity. */
d62a17ae 2317static void *route_set_lcommunity_delete_compile(const char *arg)
57d187bc 2318{
e9a223ac 2319 struct rmap_community *rcom;
caa5af30
DA
2320 char **splits;
2321 int num;
57d187bc 2322
caa5af30 2323 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2324
caa5af30
DA
2325 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2326 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2327 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2328
caa5af30
DA
2329 for (int i = 0; i < num; i++)
2330 XFREE(MTYPE_TMP, splits[i]);
2331 XFREE(MTYPE_TMP, splits);
2332
e9a223ac 2333 return rcom;
57d187bc
JS
2334}
2335
2336/* Free function for set lcommunity. */
d62a17ae 2337static void route_set_lcommunity_delete_free(void *rule)
57d187bc 2338{
e9a223ac
DS
2339 struct rmap_community *rcom = rule;
2340
2341 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2342 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
2343}
2344
2345/* Set lcommunity rule structure. */
364deb04
DL
2346static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
2347 "large-comm-list",
2348 route_set_lcommunity_delete,
2349 route_set_lcommunity_delete_compile,
2350 route_set_lcommunity_delete_free,
57d187bc
JS
2351};
2352
2353
fee6e4e4 2354/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
718e3744 2355
2356/* For community set mechanism. */
b68885f9
LK
2357static enum route_map_cmd_result_t
2358route_set_community_delete(void *rule, const struct prefix *prefix,
2359 route_map_object_t type, void *object)
d62a17ae 2360{
2361 struct community_list *list;
2362 struct community *merge;
2363 struct community *new;
2364 struct community *old;
9b6d8fcf 2365 struct bgp_path_info *path;
e9a223ac 2366 struct rmap_community *rcom = rule;
d62a17ae 2367
2368 if (type == RMAP_BGP) {
e9a223ac 2369 if (!rcom)
d62a17ae 2370 return RMAP_OKAY;
2371
9b6d8fcf 2372 path = object;
e9a223ac 2373 list = community_list_lookup(bgp_clist, rcom->name,
e237b0d2 2374 rcom->name_hash,
d62a17ae 2375 COMMUNITY_LIST_MASTER);
9b6d8fcf 2376 old = path->attr->community;
d62a17ae 2377
2378 if (list && old) {
2379 merge = community_list_match_delete(community_dup(old),
2380 list);
2381 new = community_uniq_sort(merge);
3c1f53de 2382 community_free(&merge);
d62a17ae 2383
2384 /* HACK: if the old community is not intern'd,
2385 * we should free it here, or all reference to it may be
2386 * lost.
2387 * Really need to cleanup attribute caching sometime.
2388 */
2389 if (old->refcnt == 0)
3c1f53de 2390 community_free(&old);
d62a17ae 2391
2392 if (new->size == 0) {
9b6d8fcf
DS
2393 path->attr->community = NULL;
2394 path->attr->flag &=
d62a17ae 2395 ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3c1f53de 2396 community_free(&new);
d62a17ae 2397 } else {
9b6d8fcf
DS
2398 path->attr->community = new;
2399 path->attr->flag |=
d62a17ae 2400 ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
2401 }
2402 }
718e3744 2403 }
718e3744 2404
d62a17ae 2405 return RMAP_OKAY;
718e3744 2406}
2407
2408/* Compile function for set community. */
d62a17ae 2409static void *route_set_community_delete_compile(const char *arg)
718e3744 2410{
e9a223ac 2411 struct rmap_community *rcom;
60762f8f
DA
2412 char **splits;
2413 int num;
718e3744 2414
60762f8f 2415 frrstr_split(arg, " ", &splits, &num);
e9a223ac 2416
60762f8f
DA
2417 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2418 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
e237b0d2 2419 rcom->name_hash = bgp_clist_hash_key(rcom->name);
a5dc3899 2420
60762f8f
DA
2421 for (int i = 0; i < num; i++)
2422 XFREE(MTYPE_TMP, splits[i]);
2423 XFREE(MTYPE_TMP, splits);
2424
e9a223ac 2425 return rcom;
718e3744 2426}
2427
2428/* Free function for set community. */
d62a17ae 2429static void route_set_community_delete_free(void *rule)
718e3744 2430{
e9a223ac
DS
2431 struct rmap_community *rcom = rule;
2432
2433 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2434 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 2435}
2436
2437/* Set community rule structure. */
364deb04
DL
2438static const struct route_map_rule_cmd route_set_community_delete_cmd = {
2439 "comm-list",
2440 route_set_community_delete,
2441 route_set_community_delete_compile,
2442 route_set_community_delete_free,
718e3744 2443};
6b0655a2 2444
718e3744 2445/* `set extcommunity rt COMMUNITY' */
2446
73d78ea0 2447/* For community set mechanism. Used by _rt and _soo. */
b68885f9
LK
2448static enum route_map_cmd_result_t
2449route_set_ecommunity(void *rule, const struct prefix *prefix,
2450 route_map_object_t type, void *object)
d62a17ae 2451{
2452 struct ecommunity *ecom;
2453 struct ecommunity *new_ecom;
2454 struct ecommunity *old_ecom;
9b6d8fcf 2455 struct bgp_path_info *path;
d62a17ae 2456
2457 if (type == RMAP_BGP) {
2458 ecom = rule;
9b6d8fcf 2459 path = object;
d62a17ae 2460
2461 if (!ecom)
2462 return RMAP_OKAY;
2463
2464 /* We assume additive for Extended Community. */
9b6d8fcf 2465 old_ecom = path->attr->ecommunity;
d62a17ae 2466
2467 if (old_ecom) {
2468 new_ecom = ecommunity_merge(ecommunity_dup(old_ecom),
2469 ecom);
2470
2471 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
2472 * bgp_update_receive()
2473 * ->refcnt = 0 => set by a previous route-map
2474 * statement */
2475 if (!old_ecom->refcnt)
2476 ecommunity_free(&old_ecom);
2477 } else
2478 new_ecom = ecommunity_dup(ecom);
2479
2480 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
9b6d8fcf 2481 path->attr->ecommunity = new_ecom;
d62a17ae 2482
9b6d8fcf 2483 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
27bf90a1 2484 }
d62a17ae 2485 return RMAP_OKAY;
718e3744 2486}
2487
2488/* Compile function for set community. */
d62a17ae 2489static void *route_set_ecommunity_rt_compile(const char *arg)
718e3744 2490{
d62a17ae 2491 struct ecommunity *ecom;
718e3744 2492
d62a17ae 2493 ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
2494 if (!ecom)
2495 return NULL;
2496 return ecommunity_intern(ecom);
718e3744 2497}
2498
73d78ea0 2499/* Free function for set community. Used by _rt and _soo */
d62a17ae 2500static void route_set_ecommunity_free(void *rule)
718e3744 2501{
d62a17ae 2502 struct ecommunity *ecom = rule;
2503 ecommunity_unintern(&ecom);
718e3744 2504}
2505
2506/* Set community rule structure. */
364deb04
DL
2507static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
2508 "extcommunity rt",
2509 route_set_ecommunity,
2510 route_set_ecommunity_rt_compile,
2511 route_set_ecommunity_free,
718e3744 2512};
2513
2514/* `set extcommunity soo COMMUNITY' */
2515
718e3744 2516/* Compile function for set community. */
d62a17ae 2517static void *route_set_ecommunity_soo_compile(const char *arg)
718e3744 2518{
d62a17ae 2519 struct ecommunity *ecom;
718e3744 2520
d62a17ae 2521 ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
2522 if (!ecom)
2523 return NULL;
e52702f2 2524
d62a17ae 2525 return ecommunity_intern(ecom);
718e3744 2526}
2527
718e3744 2528/* Set community rule structure. */
364deb04
DL
2529static const struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
2530 "extcommunity soo",
2531 route_set_ecommunity,
2532 route_set_ecommunity_soo_compile,
2533 route_set_ecommunity_free,
718e3744 2534};
6b0655a2 2535
ca9ac3ef 2536/* `set extcommunity bandwidth' */
2537
2538struct rmap_ecomm_lb_set {
2539 uint8_t lb_type;
2540#define RMAP_ECOMM_LB_SET_VALUE 1
2541#define RMAP_ECOMM_LB_SET_CUMUL 2
2542#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
2543 bool non_trans;
2544 uint32_t bw;
2545};
2546
2547static enum route_map_cmd_result_t
2548route_set_ecommunity_lb(void *rule, const struct prefix *prefix,
2549 route_map_object_t type, void *object)
2550{
2551 struct rmap_ecomm_lb_set *rels = rule;
2552 struct bgp_path_info *path;
2553 struct peer *peer;
2554 struct ecommunity ecom_lb = {0};
2555 struct ecommunity_val lb_eval;
2556 uint32_t bw_bytes = 0;
b1875e65 2557 uint16_t mpath_count = 0;
ca9ac3ef 2558 struct ecommunity *new_ecom;
2559 struct ecommunity *old_ecom;
2560 as_t as;
2561
2562 if (type != RMAP_BGP)
2563 return RMAP_OKAY;
2564
2565 path = object;
2566 peer = path->peer;
2567 if (!peer || !peer->bgp)
2568 return RMAP_ERROR;
2569
2570 /* Build link bandwidth extended community */
2571 as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
b1875e65 2572 if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
87b42e3b 2573 bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
b1875e65 2574 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
2575 /* process this only for the best path. */
2576 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2577 return RMAP_OKAY;
2578
2579 bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
2580 if (!bw_bytes)
2581 return RMAP_OKAY;
2582
2583 } else if (rels->lb_type == RMAP_ECOMM_LB_SET_NUM_MPATH) {
2584
2585 /* process this only for the best path. */
2586 if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2587 return RMAP_OKAY;
2588
87b42e3b 2589 bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
b1875e65 2590 mpath_count = bgp_path_info_mpath_count(path) + 1;
2591 bw_bytes *= mpath_count;
2592 }
ca9ac3ef 2593
2594 encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval);
ca9ac3ef 2595
2596 /* add to route or merge with existing */
2597 old_ecom = path->attr->ecommunity;
2598 if (old_ecom) {
f6ca545a 2599 new_ecom = ecommunity_dup(old_ecom);
2600 ecommunity_add_val(new_ecom, &lb_eval, true, true);
ca9ac3ef 2601 if (!old_ecom->refcnt)
2602 ecommunity_free(&old_ecom);
f6ca545a 2603 } else {
2604 ecom_lb.size = 1;
2605 ecom_lb.val = (uint8_t *)lb_eval.val;
ca9ac3ef 2606 new_ecom = ecommunity_dup(&ecom_lb);
f6ca545a 2607 }
ca9ac3ef 2608
2609 /* new_ecom will be intern()'d or attr_flush()'d in call stack */
2610 path->attr->ecommunity = new_ecom;
2611 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
2612
7b651a32 2613 /* Mark that route-map has set link bandwidth; used in attribute
2614 * setting decisions.
2615 */
2616 SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET);
ca9ac3ef 2617
2618 return RMAP_OKAY;
2619}
2620
2621static void *route_set_ecommunity_lb_compile(const char *arg)
2622{
2623 struct rmap_ecomm_lb_set *rels;
2624 uint8_t lb_type;
2625 uint32_t bw = 0;
4c13ffe4 2626 char bw_str[40] = {0};
2627 char *p, *str;
2628 bool non_trans = false;
ca9ac3ef 2629
4c13ffe4 2630 str = (char *)arg;
2631 p = strchr(arg, ' ');
2632 if (p) {
2633 int len;
2634
2635 len = p - arg;
2636 memcpy(bw_str, arg, len);
2637 non_trans = true;
2638 str = bw_str;
2639 }
2640
2641 if (strcmp(str, "cumulative") == 0)
ca9ac3ef 2642 lb_type = RMAP_ECOMM_LB_SET_CUMUL;
4c13ffe4 2643 else if (strcmp(str, "num-multipaths") == 0)
ca9ac3ef 2644 lb_type = RMAP_ECOMM_LB_SET_NUM_MPATH;
2645 else {
2646 char *end = NULL;
2647
4c13ffe4 2648 bw = strtoul(str, &end, 10);
ca9ac3ef 2649 if (*end != '\0')
2650 return NULL;
2651 lb_type = RMAP_ECOMM_LB_SET_VALUE;
2652 }
2653
2654 rels = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2655 sizeof(struct rmap_ecomm_lb_set));
2656 rels->lb_type = lb_type;
2657 rels->bw = bw;
4c13ffe4 2658 rels->non_trans = non_trans;
ca9ac3ef 2659
2660 return rels;
2661}
2662
2663static void route_set_ecommunity_lb_free(void *rule)
2664{
2665 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2666}
2667
2668/* Set community rule structure. */
2669struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
2670 "extcommunity bandwidth",
2671 route_set_ecommunity_lb,
2672 route_set_ecommunity_lb_compile,
2673 route_set_ecommunity_lb_free,
2674};
2675
718e3744 2676/* `set origin ORIGIN' */
2677
2678/* For origin set. */
b68885f9
LK
2679static enum route_map_cmd_result_t
2680route_set_origin(void *rule, const struct prefix *prefix,
2681 route_map_object_t type, void *object)
718e3744 2682{
d7c0a89a 2683 uint8_t *origin;
9b6d8fcf 2684 struct bgp_path_info *path;
718e3744 2685
d62a17ae 2686 if (type == RMAP_BGP) {
2687 origin = rule;
9b6d8fcf 2688 path = object;
e52702f2 2689
9b6d8fcf 2690 path->attr->origin = *origin;
d62a17ae 2691 }
718e3744 2692
d62a17ae 2693 return RMAP_OKAY;
718e3744 2694}
2695
2696/* Compile function for origin set. */
d62a17ae 2697static void *route_set_origin_compile(const char *arg)
718e3744 2698{
d7c0a89a 2699 uint8_t *origin;
718e3744 2700
d7c0a89a 2701 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 2702
d62a17ae 2703 if (strcmp(arg, "igp") == 0)
2704 *origin = 0;
2705 else if (strcmp(arg, "egp") == 0)
2706 *origin = 1;
2707 else
2708 *origin = 2;
718e3744 2709
d62a17ae 2710 return origin;
718e3744 2711}
2712
2713/* Compile function for origin set. */
d62a17ae 2714static void route_set_origin_free(void *rule)
718e3744 2715{
d62a17ae 2716 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2717}
2718
515e500c 2719/* Set origin rule structure. */
364deb04
DL
2720static const struct route_map_rule_cmd route_set_origin_cmd = {
2721 "origin",
2722 route_set_origin,
2723 route_set_origin_compile,
d62a17ae 2724 route_set_origin_free,
718e3744 2725};
6b0655a2 2726
718e3744 2727/* `set atomic-aggregate' */
2728
2729/* For atomic aggregate set. */
b68885f9
LK
2730static enum route_map_cmd_result_t
2731route_set_atomic_aggregate(void *rule, const struct prefix *pfx,
2732 route_map_object_t type, void *object)
718e3744 2733{
9b6d8fcf 2734 struct bgp_path_info *path;
718e3744 2735
d62a17ae 2736 if (type == RMAP_BGP) {
9b6d8fcf
DS
2737 path = object;
2738 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
d62a17ae 2739 }
718e3744 2740
d62a17ae 2741 return RMAP_OKAY;
718e3744 2742}
2743
2744/* Compile function for atomic aggregate. */
d62a17ae 2745static void *route_set_atomic_aggregate_compile(const char *arg)
718e3744 2746{
d62a17ae 2747 return (void *)1;
718e3744 2748}
2749
2750/* Compile function for atomic aggregate. */
d62a17ae 2751static void route_set_atomic_aggregate_free(void *rule)
718e3744 2752{
d62a17ae 2753 return;
718e3744 2754}
2755
2756/* Set atomic aggregate rule structure. */
364deb04
DL
2757static const struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
2758 "atomic-aggregate",
2759 route_set_atomic_aggregate,
2760 route_set_atomic_aggregate_compile,
2761 route_set_atomic_aggregate_free,
718e3744 2762};
6b0655a2 2763
718e3744 2764/* `set aggregator as AS A.B.C.D' */
d62a17ae 2765struct aggregator {
2766 as_t as;
2767 struct in_addr address;
718e3744 2768};
2769
b68885f9
LK
2770static enum route_map_cmd_result_t
2771route_set_aggregator_as(void *rule, const struct prefix *prefix,
2772 route_map_object_t type, void *object)
718e3744 2773{
9b6d8fcf 2774 struct bgp_path_info *path;
d62a17ae 2775 struct aggregator *aggregator;
718e3744 2776
d62a17ae 2777 if (type == RMAP_BGP) {
9b6d8fcf 2778 path = object;
d62a17ae 2779 aggregator = rule;
e52702f2 2780
9b6d8fcf
DS
2781 path->attr->aggregator_as = aggregator->as;
2782 path->attr->aggregator_addr = aggregator->address;
2783 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
d62a17ae 2784 }
718e3744 2785
d62a17ae 2786 return RMAP_OKAY;
718e3744 2787}
2788
d62a17ae 2789static void *route_set_aggregator_as_compile(const char *arg)
718e3744 2790{
d62a17ae 2791 struct aggregator *aggregator;
2792 char as[10];
2793 char address[20];
2794 int ret;
718e3744 2795
d62a17ae 2796 aggregator =
2797 XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
116e176d
DS
2798 if (sscanf(arg, "%s %s", as, address) != 2) {
2799 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2800 return NULL;
2801 }
718e3744 2802
d62a17ae 2803 aggregator->as = strtoul(as, NULL, 10);
2804 ret = inet_aton(address, &aggregator->address);
2805 if (ret == 0) {
2806 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2807 return NULL;
2808 }
2809 return aggregator;
718e3744 2810}
2811
d62a17ae 2812static void route_set_aggregator_as_free(void *rule)
718e3744 2813{
d62a17ae 2814 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2815}
2816
364deb04
DL
2817static const struct route_map_rule_cmd route_set_aggregator_as_cmd = {
2818 "aggregator as",
2819 route_set_aggregator_as,
2820 route_set_aggregator_as_compile,
2821 route_set_aggregator_as_free,
718e3744 2822};
6b0655a2 2823
4b7e6066 2824/* Set tag to object. object must be pointer to struct bgp_path_info */
b68885f9
LK
2825static enum route_map_cmd_result_t
2826route_set_tag(void *rule, const struct prefix *prefix,
2827 route_map_object_t type, void *object)
0d9551dc 2828{
d62a17ae 2829 route_tag_t *tag;
9b6d8fcf 2830 struct bgp_path_info *path;
0d9551dc 2831
d62a17ae 2832 if (type == RMAP_BGP) {
2833 tag = rule;
9b6d8fcf 2834 path = object;
0d9551dc 2835
d62a17ae 2836 /* Set tag value */
9b6d8fcf 2837 path->attr->tag = *tag;
d62a17ae 2838 }
0d9551dc 2839
d62a17ae 2840 return RMAP_OKAY;
0d9551dc
DS
2841}
2842
0d9551dc 2843/* Route map commands for tag set. */
364deb04
DL
2844static const struct route_map_rule_cmd route_set_tag_cmd = {
2845 "tag",
2846 route_set_tag,
2847 route_map_rule_tag_compile,
d62a17ae 2848 route_map_rule_tag_free,
0d9551dc
DS
2849};
2850
4b7e6066 2851/* Set label-index to object. object must be pointer to struct bgp_path_info */
b68885f9
LK
2852static enum route_map_cmd_result_t
2853route_set_label_index(void *rule, const struct prefix *prefix,
2854 route_map_object_t type, void *object)
d62a17ae 2855{
2856 struct rmap_value *rv;
9b6d8fcf 2857 struct bgp_path_info *path;
d7c0a89a 2858 uint32_t label_index;
d62a17ae 2859
2860 if (type == RMAP_BGP) {
2861 /* Fetch routemap's rule information. */
2862 rv = rule;
9b6d8fcf 2863 path = object;
d62a17ae 2864
2865 /* Set label-index value. */
2866 label_index = rv->value;
2867 if (label_index) {
9b6d8fcf
DS
2868 path->attr->label_index = label_index;
2869 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
d62a17ae 2870 }
2871 }
d990e384 2872
d62a17ae 2873 return RMAP_OKAY;
d990e384
DS
2874}
2875
2876/* Route map commands for label-index set. */
364deb04
DL
2877static const struct route_map_rule_cmd route_set_label_index_cmd = {
2878 "label-index",
2879 route_set_label_index,
2880 route_value_compile,
d62a17ae 2881 route_value_free,
d990e384 2882};
0d9551dc 2883
718e3744 2884/* `match ipv6 address IP_ACCESS_LIST' */
2885
b68885f9
LK
2886static enum route_map_cmd_result_t
2887route_match_ipv6_address(void *rule, const struct prefix *prefix,
2888 route_map_object_t type, void *object)
718e3744 2889{
d62a17ae 2890 struct access_list *alist;
718e3744 2891
09cd98eb 2892 if (type == RMAP_BGP && prefix->family == AF_INET6) {
d62a17ae 2893 alist = access_list_lookup(AFI_IP6, (char *)rule);
2894 if (alist == NULL)
2895 return RMAP_NOMATCH;
e52702f2 2896
d62a17ae 2897 return (access_list_apply(alist, prefix) == FILTER_DENY
2898 ? RMAP_NOMATCH
2899 : RMAP_MATCH);
2900 }
2901 return RMAP_NOMATCH;
718e3744 2902}
2903
d62a17ae 2904static void *route_match_ipv6_address_compile(const char *arg)
718e3744 2905{
d62a17ae 2906 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 2907}
2908
d62a17ae 2909static void route_match_ipv6_address_free(void *rule)
718e3744 2910{
d62a17ae 2911 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2912}
2913
2914/* Route map commands for ip address matching. */
364deb04
DL
2915static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
2916 "ipv6 address",
2917 route_match_ipv6_address,
2918 route_match_ipv6_address_compile,
2919 route_match_ipv6_address_free
2920};
6b0655a2 2921
718e3744 2922/* `match ipv6 next-hop IP_ADDRESS' */
2923
b68885f9
LK
2924static enum route_map_cmd_result_t
2925route_match_ipv6_next_hop(void *rule, const struct prefix *prefix,
2926 route_map_object_t type, void *object)
718e3744 2927{
d62a17ae 2928 struct in6_addr *addr = rule;
9b6d8fcf 2929 struct bgp_path_info *path;
718e3744 2930
d62a17ae 2931 if (type == RMAP_BGP) {
9b6d8fcf 2932 path = object;
e52702f2 2933
9b6d8fcf 2934 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
d62a17ae 2935 return RMAP_MATCH;
718e3744 2936
9b6d8fcf 2937 if (path->attr->mp_nexthop_len
d62a17ae 2938 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
9b6d8fcf 2939 && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
d62a17ae 2940 return RMAP_MATCH;
718e3744 2941
d62a17ae 2942 return RMAP_NOMATCH;
2943 }
718e3744 2944
d62a17ae 2945 return RMAP_NOMATCH;
718e3744 2946}
2947
d62a17ae 2948static void *route_match_ipv6_next_hop_compile(const char *arg)
718e3744 2949{
d62a17ae 2950 struct in6_addr *address;
2951 int ret;
718e3744 2952
d62a17ae 2953 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 2954
d62a17ae 2955 ret = inet_pton(AF_INET6, arg, address);
2956 if (!ret) {
2957 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2958 return NULL;
2959 }
718e3744 2960
d62a17ae 2961 return address;
718e3744 2962}
2963
d62a17ae 2964static void route_match_ipv6_next_hop_free(void *rule)
718e3744 2965{
d62a17ae 2966 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2967}
2968
364deb04
DL
2969static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
2970 "ipv6 next-hop",
2971 route_match_ipv6_next_hop,
2972 route_match_ipv6_next_hop_compile,
2973 route_match_ipv6_next_hop_free
2974};
6b0655a2 2975
be7735b3
PG
2976/* `match ip next-hop IP_ADDRESS' */
2977
2978static enum route_map_cmd_result_t
2979route_match_ipv4_next_hop(void *rule, const struct prefix *prefix,
2980 route_map_object_t type, void *object)
2981{
2982 struct in_addr *addr = rule;
2983 struct bgp_path_info *path;
2984
2985 if (type == RMAP_BGP) {
2986 path = object;
2987
2988 if (path->attr->nexthop.s_addr == addr->s_addr ||
2989 (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4 &&
2990 IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
2991 return RMAP_MATCH;
2992
2993 return RMAP_NOMATCH;
2994 }
2995
2996 return RMAP_NOMATCH;
2997}
2998
2999static void *route_match_ipv4_next_hop_compile(const char *arg)
3000{
3001 struct in_addr *address;
3002 int ret;
3003
3004 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3005
3006 ret = inet_pton(AF_INET, arg, address);
3007 if (!ret) {
3008 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3009 return NULL;
3010 }
3011
3012 return address;
3013}
3014
3015static void route_match_ipv4_next_hop_free(void *rule)
3016{
3017 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3018}
3019
3020static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
3021 "ip next-hop address",
3022 route_match_ipv4_next_hop,
3023 route_match_ipv4_next_hop_compile,
3024 route_match_ipv4_next_hop_free
3025};
3026
718e3744 3027/* `match ipv6 address prefix-list PREFIX_LIST' */
3028
b68885f9 3029static enum route_map_cmd_result_t
123214ef 3030route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
d62a17ae 3031 route_map_object_t type, void *object)
718e3744 3032{
2e59405f
DS
3033 return route_match_address_prefix_list(rule, AFI_IP6, prefix, type,
3034 object);
718e3744 3035}
3036
d62a17ae 3037static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
718e3744 3038{
d62a17ae 3039 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 3040}
3041
d62a17ae 3042static void route_match_ipv6_address_prefix_list_free(void *rule)
718e3744 3043{
d62a17ae 3044 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3045}
3046
364deb04
DL
3047static const struct route_map_rule_cmd
3048 route_match_ipv6_address_prefix_list_cmd = {
3049 "ipv6 address prefix-list",
3050 route_match_ipv6_address_prefix_list,
d62a17ae 3051 route_match_ipv6_address_prefix_list_compile,
364deb04
DL
3052 route_match_ipv6_address_prefix_list_free
3053};
6b0655a2 3054
61ad901e
DA
3055/* `match ipv6 next-hop type <TYPE>' */
3056
b68885f9 3057static enum route_map_cmd_result_t
61ad901e 3058route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
b68885f9 3059 route_map_object_t type, void *object)
61ad901e 3060{
9b6d8fcf 3061 struct bgp_path_info *path;
61ad901e
DA
3062 struct in6_addr *addr = rule;
3063
3064 if (type == RMAP_BGP && prefix->family == AF_INET6) {
9b6d8fcf 3065 path = (struct bgp_path_info *)object;
05864da7 3066 if (!path)
b68885f9 3067 return RMAP_NOMATCH;
61ad901e 3068
9b6d8fcf
DS
3069 if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
3070 && !path->attr->nh_ifindex)
61ad901e
DA
3071 return RMAP_MATCH;
3072 }
3073 return RMAP_NOMATCH;
3074}
3075
3076static void *route_match_ipv6_next_hop_type_compile(const char *arg)
3077{
3078 struct in6_addr *address;
3079 int ret;
3080
3081 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3082
3083 ret = inet_pton(AF_INET6, "::0", address);
3084 if (!ret) {
3085 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3086 return NULL;
3087 }
3088
3089 return address;
3090}
3091
3092static void route_match_ipv6_next_hop_type_free(void *rule)
3093{
3094 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3095}
3096
364deb04
DL
3097static const struct route_map_rule_cmd
3098 route_match_ipv6_next_hop_type_cmd = {
3099 "ipv6 next-hop type",
3100 route_match_ipv6_next_hop_type,
61ad901e 3101 route_match_ipv6_next_hop_type_compile,
364deb04
DL
3102 route_match_ipv6_next_hop_type_free
3103};
61ad901e 3104
718e3744 3105/* `set ipv6 nexthop global IP_ADDRESS' */
3106
3107/* Set nexthop to object. ojbect must be pointer to struct attr. */
b68885f9
LK
3108static enum route_map_cmd_result_t
3109route_set_ipv6_nexthop_global(void *rule, const struct prefix *p,
3110 route_map_object_t type, void *object)
718e3744 3111{
d62a17ae 3112 struct in6_addr *address;
9b6d8fcf 3113 struct bgp_path_info *path;
718e3744 3114
d62a17ae 3115 if (type == RMAP_BGP) {
3116 /* Fetch routemap's rule information. */
3117 address = rule;
9b6d8fcf 3118 path = object;
e52702f2 3119
d62a17ae 3120 /* Set next hop value. */
9b6d8fcf 3121 path->attr->mp_nexthop_global = *address;
3f9c7369 3122
d62a17ae 3123 /* Set nexthop length. */
9b6d8fcf
DS
3124 if (path->attr->mp_nexthop_len == 0)
3125 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369 3126
9b6d8fcf 3127 SET_FLAG(path->attr->rmap_change_flags,
d62a17ae 3128 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
3129 }
718e3744 3130
d62a17ae 3131 return RMAP_OKAY;
718e3744 3132}
3133
3134/* Route map `ip next-hop' compile function. Given string is converted
3135 to struct in_addr structure. */
d62a17ae 3136static void *route_set_ipv6_nexthop_global_compile(const char *arg)
718e3744 3137{
d62a17ae 3138 int ret;
3139 struct in6_addr *address;
718e3744 3140
d62a17ae 3141 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3142
d62a17ae 3143 ret = inet_pton(AF_INET6, arg, address);
718e3744 3144
d62a17ae 3145 if (ret == 0) {
3146 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3147 return NULL;
3148 }
718e3744 3149
d62a17ae 3150 return address;
718e3744 3151}
3152
3153/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3154static void route_set_ipv6_nexthop_global_free(void *rule)
718e3744 3155{
d62a17ae 3156 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3157}
3158
3159/* Route map commands for ip nexthop set. */
364deb04
DL
3160static const struct route_map_rule_cmd
3161 route_set_ipv6_nexthop_global_cmd = {
3162 "ipv6 next-hop global",
3163 route_set_ipv6_nexthop_global,
d62a17ae 3164 route_set_ipv6_nexthop_global_compile,
364deb04
DL
3165 route_set_ipv6_nexthop_global_free
3166};
6b0655a2 3167
161995ea 3168/* Set next-hop preference value. */
b68885f9 3169static enum route_map_cmd_result_t
123214ef 3170route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
d62a17ae 3171 route_map_object_t type, void *object)
3172{
9b6d8fcf 3173 struct bgp_path_info *path;
d62a17ae 3174 struct peer *peer;
3175
3176 if (type == RMAP_BGP) {
3177 /* Fetch routemap's rule information. */
9b6d8fcf
DS
3178 path = object;
3179 peer = path->peer;
d62a17ae 3180
c5ca731e 3181 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3182 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
d62a17ae 3183 /* Set next hop preference to global */
2951a7a4 3184 path->attr->mp_nexthop_prefer_global = true;
9b6d8fcf 3185 SET_FLAG(path->attr->rmap_change_flags,
d62a17ae 3186 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3187 } else {
2951a7a4 3188 path->attr->mp_nexthop_prefer_global = false;
9b6d8fcf 3189 SET_FLAG(path->attr->rmap_change_flags,
d62a17ae 3190 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3191 }
161995ea 3192 }
d62a17ae 3193 return RMAP_OKAY;
161995ea
DS
3194}
3195
d62a17ae 3196static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
161995ea 3197{
d62a17ae 3198 int *rins = NULL;
161995ea 3199
d62a17ae 3200 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3201 *rins = 1;
161995ea 3202
d62a17ae 3203 return rins;
161995ea
DS
3204}
3205
3206/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3207static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
161995ea 3208{
d62a17ae 3209 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
161995ea
DS
3210}
3211
3212/* Route map commands for ip nexthop set preferred. */
364deb04
DL
3213static const struct route_map_rule_cmd
3214 route_set_ipv6_nexthop_prefer_global_cmd = {
3215 "ipv6 next-hop prefer-global",
3216 route_set_ipv6_nexthop_prefer_global,
d62a17ae 3217 route_set_ipv6_nexthop_prefer_global_compile,
364deb04
DL
3218 route_set_ipv6_nexthop_prefer_global_free
3219};
161995ea 3220
718e3744 3221/* `set ipv6 nexthop local IP_ADDRESS' */
3222
3223/* Set nexthop to object. ojbect must be pointer to struct attr. */
b68885f9
LK
3224static enum route_map_cmd_result_t
3225route_set_ipv6_nexthop_local(void *rule, const struct prefix *p,
3226 route_map_object_t type, void *object)
d62a17ae 3227{
3228 struct in6_addr *address;
9b6d8fcf 3229 struct bgp_path_info *path;
d62a17ae 3230
3231 if (type == RMAP_BGP) {
3232 /* Fetch routemap's rule information. */
3233 address = rule;
9b6d8fcf 3234 path = object;
d62a17ae 3235
3236 /* Set next hop value. */
9b6d8fcf 3237 path->attr->mp_nexthop_local = *address;
d62a17ae 3238
3239 /* Set nexthop length. */
9b6d8fcf 3240 if (path->attr->mp_nexthop_len
d62a17ae 3241 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 3242 path->attr->mp_nexthop_len =
d62a17ae 3243 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3244
9b6d8fcf 3245 SET_FLAG(path->attr->rmap_change_flags,
d62a17ae 3246 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
3247 }
718e3744 3248
d62a17ae 3249 return RMAP_OKAY;
718e3744 3250}
3251
3252/* Route map `ip nexthop' compile function. Given string is converted
3253 to struct in_addr structure. */
d62a17ae 3254static void *route_set_ipv6_nexthop_local_compile(const char *arg)
718e3744 3255{
d62a17ae 3256 int ret;
3257 struct in6_addr *address;
718e3744 3258
d62a17ae 3259 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 3260
d62a17ae 3261 ret = inet_pton(AF_INET6, arg, address);
718e3744 3262
d62a17ae 3263 if (ret == 0) {
3264 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3265 return NULL;
3266 }
718e3744 3267
d62a17ae 3268 return address;
718e3744 3269}
3270
3271/* Free route map's compiled `ip nexthop' value. */
d62a17ae 3272static void route_set_ipv6_nexthop_local_free(void *rule)
718e3744 3273{
d62a17ae 3274 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3275}
3276
3277/* Route map commands for ip nexthop set. */
364deb04
DL
3278static const struct route_map_rule_cmd
3279 route_set_ipv6_nexthop_local_cmd = {
3280 "ipv6 next-hop local",
3281 route_set_ipv6_nexthop_local,
d62a17ae 3282 route_set_ipv6_nexthop_local_compile,
364deb04
DL
3283 route_set_ipv6_nexthop_local_free
3284};
90916ac2
DS
3285
3286/* `set ipv6 nexthop peer-address' */
3287
3288/* Set nexthop to object. ojbect must be pointer to struct attr. */
b68885f9
LK
3289static enum route_map_cmd_result_t
3290route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx,
3291 route_map_object_t type, void *object)
d62a17ae 3292{
3293 struct in6_addr peer_address;
9b6d8fcf 3294 struct bgp_path_info *path;
d62a17ae 3295 struct peer *peer;
3296
3297 if (type == RMAP_BGP) {
3298 /* Fetch routemap's rule information. */
9b6d8fcf
DS
3299 path = object;
3300 peer = path->peer;
d62a17ae 3301
3302 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3303 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
3304 && peer->su_remote
3305 && sockunion_family(peer->su_remote) == AF_INET6) {
3306 peer_address = peer->su_remote->sin6.sin6_addr;
3307 /* Set next hop value and length in attribute. */
3308 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
9b6d8fcf 3309 path->attr->mp_nexthop_local = peer_address;
0606039c
DA
3310 if (path->attr->mp_nexthop_len
3311 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3312 path->attr->mp_nexthop_len =
3313 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
d62a17ae 3314 } else {
9b6d8fcf
DS
3315 path->attr->mp_nexthop_global = peer_address;
3316 if (path->attr->mp_nexthop_len == 0)
0606039c
DA
3317 path->attr->mp_nexthop_len =
3318 BGP_ATTR_NHLEN_IPV6_GLOBAL;
d62a17ae 3319 }
3320
3321 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
3322 /* The next hop value will be set as part of packet
3323 * rewrite.
3324 * Set the flags here to indicate that rewrite needs to
3325 * be done.
3326 * Also, clear the value - we clear both global and
3327 * link-local
3328 * nexthops, whether we send one or both is determined
3329 * elsewhere.
3330 */
9b6d8fcf 3331 SET_FLAG(path->attr->rmap_change_flags,
d62a17ae 3332 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3333 /* clear next hop value. */
9b6d8fcf 3334 memset(&(path->attr->mp_nexthop_global), 0,
d62a17ae 3335 sizeof(struct in6_addr));
9b6d8fcf 3336 memset(&(path->attr->mp_nexthop_local), 0,
d62a17ae 3337 sizeof(struct in6_addr));
3338 }
90916ac2 3339 }
90916ac2 3340
d62a17ae 3341 return RMAP_OKAY;
90916ac2
DS
3342}
3343
3344/* Route map `ip next-hop' compile function. Given string is converted
3345 to struct in_addr structure. */
d62a17ae 3346static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
90916ac2 3347{
d62a17ae 3348 int *rins = NULL;
90916ac2 3349
d62a17ae 3350 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3351 *rins = 1;
90916ac2 3352
d62a17ae 3353 return rins;
90916ac2
DS
3354}
3355
3356/* Free route map's compiled `ip next-hop' value. */
d62a17ae 3357static void route_set_ipv6_nexthop_peer_free(void *rule)
90916ac2 3358{
d62a17ae 3359 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
90916ac2
DS
3360}
3361
3362/* Route map commands for ip nexthop set. */
364deb04
DL
3363static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
3364 "ipv6 next-hop peer-address",
3365 route_set_ipv6_nexthop_peer,
3366 route_set_ipv6_nexthop_peer_compile,
3367 route_set_ipv6_nexthop_peer_free
3368};
90916ac2 3369
69ba6dd7 3370/* `set ipv4 vpn next-hop A.B.C.D' */
718e3744 3371
b68885f9
LK
3372static enum route_map_cmd_result_t
3373route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix,
3374 route_map_object_t type, void *object)
718e3744 3375{
d62a17ae 3376 struct in_addr *address;
9b6d8fcf 3377 struct bgp_path_info *path;
718e3744 3378
d62a17ae 3379 if (type == RMAP_BGP) {
3380 /* Fetch routemap's rule information. */
3381 address = rule;
9b6d8fcf 3382 path = object;
e52702f2 3383
d62a17ae 3384 /* Set next hop value. */
9b6d8fcf 3385 path->attr->mp_nexthop_global_in = *address;
0606039c 3386 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
d62a17ae 3387 }
718e3744 3388
d62a17ae 3389 return RMAP_OKAY;
718e3744 3390}
3391
d62a17ae 3392static void *route_set_vpnv4_nexthop_compile(const char *arg)
718e3744 3393{
d62a17ae 3394 int ret;
3395 struct in_addr *address;
718e3744 3396
d62a17ae 3397 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3398
d62a17ae 3399 ret = inet_aton(arg, address);
718e3744 3400
d62a17ae 3401 if (ret == 0) {
3402 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3403 return NULL;
3404 }
718e3744 3405
d62a17ae 3406 return address;
718e3744 3407}
3408
69ba6dd7 3409/* `set ipv6 vpn next-hop A.B.C.D' */
d6902373 3410
b68885f9
LK
3411static enum route_map_cmd_result_t
3412route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix,
3413 route_map_object_t type, void *object)
d6902373 3414{
d62a17ae 3415 struct in6_addr *address;
9b6d8fcf 3416 struct bgp_path_info *path;
d6902373 3417
d62a17ae 3418 if (type == RMAP_BGP) {
3419 /* Fetch routemap's rule information. */
3420 address = rule;
9b6d8fcf 3421 path = object;
d6902373 3422
d62a17ae 3423 /* Set next hop value. */
9b6d8fcf 3424 memcpy(&path->attr->mp_nexthop_global, address,
d62a17ae 3425 sizeof(struct in6_addr));
9b6d8fcf 3426 path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
d62a17ae 3427 }
d6902373 3428
d62a17ae 3429 return RMAP_OKAY;
d6902373
PG
3430}
3431
d62a17ae 3432static void *route_set_vpnv6_nexthop_compile(const char *arg)
d6902373 3433{
d62a17ae 3434 int ret;
3435 struct in6_addr *address;
d6902373 3436
d62a17ae 3437 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3438 ret = inet_pton(AF_INET6, arg, address);
d6902373 3439
d62a17ae 3440 if (ret == 0) {
3441 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3442 return NULL;
3443 }
d6902373 3444
d62a17ae 3445 return address;
d6902373
PG
3446}
3447
d62a17ae 3448static void route_set_vpn_nexthop_free(void *rule)
718e3744 3449{
d62a17ae 3450 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3451}
3452
69ba6dd7 3453/* Route map commands for ipv4 next-hop set. */
364deb04
DL
3454static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
3455 "ipv4 vpn next-hop",
3456 route_set_vpnv4_nexthop,
3457 route_set_vpnv4_nexthop_compile,
3458 route_set_vpn_nexthop_free
3459};
d6902373 3460
69ba6dd7 3461/* Route map commands for ipv6 next-hop set. */
364deb04
DL
3462static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
3463 "ipv6 vpn next-hop",
3464 route_set_vpnv6_nexthop,
3465 route_set_vpnv6_nexthop_compile,
3466 route_set_vpn_nexthop_free
3467};
6b0655a2 3468
718e3744 3469/* `set originator-id' */
3470
3471/* For origin set. */
b68885f9
LK
3472static enum route_map_cmd_result_t
3473route_set_originator_id(void *rule, const struct prefix *prefix,
3474 route_map_object_t type, void *object)
718e3744 3475{
d62a17ae 3476 struct in_addr *address;
9b6d8fcf 3477 struct bgp_path_info *path;
718e3744 3478
d62a17ae 3479 if (type == RMAP_BGP) {
3480 address = rule;
9b6d8fcf 3481 path = object;
e52702f2 3482
9b6d8fcf
DS
3483 path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
3484 path->attr->originator_id = *address;
d62a17ae 3485 }
718e3744 3486
d62a17ae 3487 return RMAP_OKAY;
718e3744 3488}
3489
3490/* Compile function for originator-id set. */
d62a17ae 3491static void *route_set_originator_id_compile(const char *arg)
718e3744 3492{
d62a17ae 3493 int ret;
3494 struct in_addr *address;
718e3744 3495
d62a17ae 3496 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 3497
d62a17ae 3498 ret = inet_aton(arg, address);
718e3744 3499
d62a17ae 3500 if (ret == 0) {
3501 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3502 return NULL;
3503 }
718e3744 3504
d62a17ae 3505 return address;
718e3744 3506}
3507
3508/* Compile function for originator_id set. */
d62a17ae 3509static void route_set_originator_id_free(void *rule)
718e3744 3510{
d62a17ae 3511 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 3512}
3513
515e500c 3514/* Set originator-id rule structure. */
364deb04
DL
3515static const struct route_map_rule_cmd route_set_originator_id_cmd = {
3516 "originator-id",
3517 route_set_originator_id,
3518 route_set_originator_id_compile,
3519 route_set_originator_id_free,
718e3744 3520};
6b0655a2 3521
718e3744 3522/* Add bgp route map rule. */
d62a17ae 3523static int bgp_route_match_add(struct vty *vty, const char *command,
3524 const char *arg, route_map_event_t type)
3525{
3526 VTY_DECLVAR_CONTEXT(route_map_index, index);
9ca25fed 3527 int retval = CMD_SUCCESS;
cda7187d 3528 enum rmap_compile_rets ret;
d62a17ae 3529
e2c8d6ce 3530 ret = route_map_add_match(index, command, arg, type);
9ca25fed
DS
3531 switch (ret) {
3532 case RMAP_RULE_MISSING:
3533 vty_out(vty, "%% BGP Can't find rule.\n");
3534 retval = CMD_WARNING_CONFIG_FAILED;
3535 break;
3536 case RMAP_COMPILE_ERROR:
3537 vty_out(vty, "%% BGP Argument is malformed.\n");
3538 retval = CMD_WARNING_CONFIG_FAILED;
3539 break;
3540 case RMAP_COMPILE_SUCCESS:
cda7187d
DS
3541 /*
3542 * Intentionally doing nothing here.
3543 */
3544 break;
718e3744 3545 }
518f0eb1 3546
9ca25fed 3547 return retval;
718e3744 3548}
3549
3550/* Delete bgp route map rule. */
d62a17ae 3551static int bgp_route_match_delete(struct vty *vty, const char *command,
3552 const char *arg, route_map_event_t type)
3553{
3554 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 3555 enum rmap_compile_rets ret;
9ca25fed 3556 int retval = CMD_SUCCESS;
d62a17ae 3557 char *dep_name = NULL;
3558 const char *tmpstr;
3559 char *rmap_name = NULL;
3560
3561 if (type != RMAP_EVENT_MATCH_DELETED) {
3562 /* ignore the mundane, the types without any dependency */
3563 if (arg == NULL) {
3564 if ((tmpstr = route_map_get_match_arg(index, command))
3565 != NULL)
3566 dep_name =
3567 XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
3568 } else {
3569 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
3570 }
3571 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
ffd0c037 3572 }
d62a17ae 3573
909f3d56 3574 ret = route_map_delete_match(index, command, dep_name, type);
9ca25fed
DS
3575 switch (ret) {
3576 case RMAP_RULE_MISSING:
3577 vty_out(vty, "%% BGP Can't find rule.\n");
3578 retval = CMD_WARNING_CONFIG_FAILED;
3579 break;
3580 case RMAP_COMPILE_ERROR:
3581 vty_out(vty, "%% BGP Argument is malformed.\n");
3582 retval = CMD_WARNING_CONFIG_FAILED;
3583 break;
3584 case RMAP_COMPILE_SUCCESS:
cda7187d
DS
3585 /*
3586 * Nothing to do here
3587 */
3588 break;
718e3744 3589 }
518f0eb1 3590
0a22ddfb
QY
3591 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
3592 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
518f0eb1 3593
9ca25fed 3594 return retval;
718e3744 3595}
3596
518f0eb1 3597/*
2a3d5731 3598 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
3599 * modifications.
3600 */
d62a17ae 3601static void bgp_route_map_process_peer(const char *rmap_name,
3602 struct route_map *map, struct peer *peer,
3603 int afi, int safi, int route_update)
3604{
d62a17ae 3605 struct bgp_filter *filter;
3606
3607 if (!peer || !rmap_name)
3608 return;
3609
3610 filter = &peer->filter[afi][safi];
3611 /*
3612 * in is for non-route-server clients,
3613 * out is for all peers
3614 */
db77a501
DS
3615 if (filter->map[RMAP_IN].name
3616 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
3617 filter->map[RMAP_IN].map = map;
d62a17ae 3618
db77a501 3619 if (route_update && peer->status == Established) {
d62a17ae 3620 if (CHECK_FLAG(peer->af_flags[afi][safi],
3621 PEER_FLAG_SOFT_RECONFIG)) {
3622 if (bgp_debug_update(peer, NULL, NULL, 1))
3623 zlog_debug(
db77a501 3624 "Processing route_map %s update on peer %s (inbound, soft-reconfig)",
d62a17ae 3625 rmap_name, peer->host);
3626
3627 bgp_soft_reconfig_in(peer, afi, safi);
3628 } else if (CHECK_FLAG(peer->cap,
3629 PEER_CAP_REFRESH_OLD_RCV)
3630 || CHECK_FLAG(peer->cap,
3631 PEER_CAP_REFRESH_NEW_RCV)) {
3632 if (bgp_debug_update(peer, NULL, NULL, 1))
3633 zlog_debug(
db77a501 3634 "Processing route_map %s update on peer %s (inbound, route-refresh)",
d62a17ae 3635 rmap_name, peer->host);
3636 bgp_route_refresh_send(peer, afi, safi, 0, 0,
3637 0);
3638 }
d62a17ae 3639 }
518f0eb1 3640 }
d62a17ae 3641
3642 /*
3643 * For outbound, unsuppress and default-originate map change (content or
3644 * map created), merely update the "config" here, the actual route
3645 * announcement happens at the group level.
3646 */
3647 if (filter->map[RMAP_OUT].name
3648 && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
3649 filter->map[RMAP_OUT].map = map;
3650
3651 if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
3652 filter->usmap.map = map;
3653
3654 if (peer->default_rmap[afi][safi].name
3655 && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
3656 peer->default_rmap[afi][safi].map = map;
3657}
3658
3659static void bgp_route_map_update_peer_group(const char *rmap_name,
3660 struct route_map *map,
3661 struct bgp *bgp)
3662{
3663 struct peer_group *group;
3664 struct listnode *node, *nnode;
3665 struct bgp_filter *filter;
3666 int afi, safi;
3667 int direct;
3668
3669 if (!bgp)
3670 return;
3671
3672 /* All the peers have been updated correctly already. This is
3673 * just updating the placeholder data. No real update required.
3674 */
05c7a1cc
QY
3675 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
3676 FOREACH_AFI_SAFI (afi, safi) {
3677 filter = &group->conf->filter[afi][safi];
3678
3679 for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
3680 if ((filter->map[direct].name)
3681 && (strcmp(rmap_name,
3682 filter->map[direct].name)
d62a17ae 3683 == 0))
05c7a1cc 3684 filter->map[direct].map = map;
d62a17ae 3685 }
05c7a1cc
QY
3686
3687 if (filter->usmap.name
3688 && (strcmp(rmap_name, filter->usmap.name) == 0))
3689 filter->usmap.map = map;
3690 }
3691 }
518f0eb1
DS
3692}
3693
a6e0d253
DW
3694/*
3695 * Note that if an extreme number (tens of thousands) of route-maps are in use
3696 * and if bgp has an extreme number of peers, network statements, etc then this
3697 * function can consume a lot of cycles. This is due to this function being
3698 * called for each route-map and within this function we walk the list of peers,
3699 * network statements, etc looking to see if they use this route-map.
3700 */
d62a17ae 3701static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
3702 int route_update)
3703{
3704 int i;
3705 afi_t afi;
3706 safi_t safi;
3707 struct peer *peer;
3708 struct bgp_node *bn;
3709 struct bgp_static *bgp_static;
20894f50 3710 struct bgp_aggregate *aggregate;
d62a17ae 3711 struct listnode *node, *nnode;
3712 struct route_map *map;
3713 char buf[INET6_ADDRSTRLEN];
3714
3715 map = route_map_lookup_by_name(rmap_name);
3716
3717 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
3718
3719 /* Ignore dummy peer-group structure */
3720 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
3721 continue;
3722
05c7a1cc
QY
3723 FOREACH_AFI_SAFI (afi, safi) {
3724 /* process in/out/import/export/default-orig
3725 * route-maps */
3726 bgp_route_map_process_peer(rmap_name, map, peer, afi,
3727 safi, route_update);
3728 }
d62a17ae 3729 }
3730
3731 /* for outbound/default-orig route-maps, process for groups */
3732 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
3733 route_update, 0);
3734
3735 /* update peer-group config (template) */
3736 bgp_route_map_update_peer_group(rmap_name, map, bgp);
3737
05c7a1cc
QY
3738 FOREACH_AFI_SAFI (afi, safi) {
3739 /* For table route-map updates. */
3740 if (!bgp_fibupd_safi(safi))
3741 continue;
d62a17ae 3742
05c7a1cc
QY
3743 if (bgp->table_map[afi][safi].name
3744 && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
3745 == 0)) {
b4897fa5 3746
3747 /* bgp->table_map[afi][safi].map is NULL.
3748 * i.e Route map creation event.
3749 * So update applied_counter.
3750 * If it is not NULL, i.e It may be routemap updation or
3751 * deletion. so no need to update the counter.
3752 */
3753 if (!bgp->table_map[afi][safi].map)
3754 route_map_counter_increment(map);
05c7a1cc
QY
3755 bgp->table_map[afi][safi].map = map;
3756
3757 if (BGP_DEBUG(zebra, ZEBRA))
3758 zlog_debug(
3759 "Processing route_map %s update on "
3760 "table map",
3761 rmap_name);
3762 if (route_update)
3763 bgp_zebra_announce_table(bgp, afi, safi);
3764 }
d62a17ae 3765
05c7a1cc
QY
3766 /* For network route-map updates. */
3767 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
96f10e1e 3768 bn = bgp_route_next(bn)) {
5a8ba9fc 3769 bgp_static = bgp_node_get_bgp_static_info(bn);
c9837105
DS
3770 if (!bgp_static)
3771 continue;
3772
3773 if (!bgp_static->rmap.name
3774 || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
3775 continue;
3776
b4897fa5 3777 if (!bgp_static->rmap.map)
3778 route_map_counter_increment(map);
3779
c9837105
DS
3780 bgp_static->rmap.map = map;
3781
3782 if (route_update && !bgp_static->backdoor) {
b54892e0
DS
3783 const struct prefix *bn_p =
3784 bgp_node_get_prefix(bn);
3785
3786 if (bgp_debug_zebra(bn_p))
c9837105
DS
3787 zlog_debug(
3788 "Processing route_map %s update on static route %s",
3789 rmap_name,
b54892e0
DS
3790 inet_ntop(bn_p->family,
3791 &bn_p->u.prefix, buf,
c9837105 3792 INET6_ADDRSTRLEN));
b54892e0 3793 bgp_static_update(bgp, bn_p, bgp_static, afi,
c9837105 3794 safi);
05c7a1cc 3795 }
96f10e1e 3796 }
20894f50
DA
3797
3798 /* For aggregate-address route-map updates. */
3799 for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
3800 bn = bgp_route_next(bn)) {
3801 aggregate = bgp_node_get_bgp_aggregate_info(bn);
3802 if (!aggregate)
3803 continue;
3804
3805 if (!aggregate->rmap.name
3806 || (strcmp(rmap_name, aggregate->rmap.name) != 0))
3807 continue;
3808
3809 if (!aggregate->rmap.map)
3810 route_map_counter_increment(map);
3811
3812 aggregate->rmap.map = map;
3813
3814 if (route_update) {
b54892e0
DS
3815 const struct prefix *bn_p =
3816 bgp_node_get_prefix(bn);
3817
3818 if (bgp_debug_zebra(bn_p))
20894f50
DA
3819 zlog_debug(
3820 "Processing route_map %s update on aggregate-address route %s",
3821 rmap_name,
b54892e0
DS
3822 inet_ntop(bn_p->family,
3823 &bn_p->u.prefix, buf,
20894f50 3824 INET6_ADDRSTRLEN));
b54892e0 3825 bgp_aggregate_route(bgp, bn_p, afi, safi,
20894f50
DA
3826 aggregate);
3827 }
3828 }
05c7a1cc 3829 }
d62a17ae 3830
3831 /* For redistribute route-map updates. */
3832 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3833 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
3834 struct list *red_list;
d62a17ae 3835 struct bgp_redist *red;
3836
3837 red_list = bgp->redist[afi][i];
3838 if (!red_list)
3839 continue;
3840
3841 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
c9837105
DS
3842 if (!red->rmap.name
3843 || (strcmp(rmap_name, red->rmap.name) != 0))
3844 continue;
3845
b4897fa5 3846 if (!red->rmap.map)
3847 route_map_counter_increment(map);
3848
c9837105
DS
3849 red->rmap.map = map;
3850
3851 if (!route_update)
3852 continue;
3853
3854 if (BGP_DEBUG(zebra, ZEBRA))
3855 zlog_debug(
3856 "Processing route_map %s update on redistributed routes",
3857 rmap_name);
3858
3859 bgp_redistribute_resend(bgp, afi, i,
d62a17ae 3860 red->instance);
d62a17ae 3861 }
3862 }
53c84f78
MK
3863
3864 /* for type5 command route-maps */
3865 FOREACH_AFI_SAFI (afi, safi) {
c9837105
DS
3866 if (!bgp->adv_cmd_rmap[afi][safi].name
3867 || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
3868 != 0)
3869 continue;
3870
2686df6a
NS
3871 /* Make sure the route-map is populated here if not already done */
3872 bgp->adv_cmd_rmap[afi][safi].map = map;
3873
c9837105
DS
3874 if (BGP_DEBUG(zebra, ZEBRA))
3875 zlog_debug(
3876 "Processing route_map %s update on advertise type5 route command",
3877 rmap_name);
2686df6a 3878
456a4697 3879 if (route_update && advertise_type5_routes(bgp, afi)) {
2686df6a
NS
3880 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
3881 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
3882 }
53c84f78 3883 }
d62a17ae 3884}
3885
46a69f10 3886static void bgp_route_map_process_update_cb(char *rmap_name)
d62a17ae 3887{
3888 struct listnode *node, *nnode;
3889 struct bgp *bgp;
3890
ddb5b488 3891 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
d62a17ae 3892 bgp_route_map_process_update(bgp, rmap_name, 1);
5fe9f963 3893
49e5a4a0 3894#ifdef ENABLE_BGP_VNC
ddb5b488
PZ
3895 /* zlog_debug("%s: calling vnc_routemap_update", __func__); */
3896 vnc_routemap_update(bgp, __func__);
65efcfce 3897#endif
ddb5b488
PZ
3898 }
3899
3900 vpn_policy_routemap_event(rmap_name);
518f0eb1
DS
3901}
3902
d62a17ae 3903int bgp_route_map_update_timer(struct thread *thread)
518f0eb1 3904{
d62a17ae 3905 bm->t_rmap_update = NULL;
518f0eb1 3906
d62a17ae 3907 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1 3908
95f7965d 3909 return 0;
518f0eb1
DS
3910}
3911
d62a17ae 3912static void bgp_route_map_mark_update(const char *rmap_name)
518f0eb1 3913{
47c8fa1f
NT
3914 struct listnode *node, *nnode;
3915 struct bgp *bgp;
3916
3917 /* If new update is received before the current timer timed out,
3918 * turn it off and start a new timer.
3919 */
3920 if (bm->t_rmap_update != NULL)
3921 THREAD_OFF(bm->t_rmap_update);
3922
3923 /* rmap_update_timer of 0 means don't do route updates */
3924 if (bm->rmap_update_timer) {
3925 thread_add_timer(bm->master, bgp_route_map_update_timer,
3926 NULL, bm->rmap_update_timer,
3927 &bm->t_rmap_update);
3928
3929 /* Signal the groups that a route-map update event has
3930 * started */
3931 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3932 update_group_policy_update(bgp,
3933 BGP_POLICY_ROUTE_MAP,
3934 rmap_name, 1, 1);
3935 } else {
3936 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3937 bgp_route_map_process_update(bgp, rmap_name, 0);
49e5a4a0 3938#ifdef ENABLE_BGP_VNC
47c8fa1f
NT
3939 zlog_debug("%s: calling vnc_routemap_update", __func__);
3940 vnc_routemap_update(bgp, __func__);
65efcfce 3941#endif
d62a17ae 3942 }
718e3744 3943}
6b0655a2 3944
d62a17ae 3945static void bgp_route_map_add(const char *rmap_name)
73ac8160 3946{
7096e938 3947 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3948 bgp_route_map_mark_update(rmap_name);
73ac8160 3949
d62a17ae 3950 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 3951}
518f0eb1 3952
d62a17ae 3953static void bgp_route_map_delete(const char *rmap_name)
73ac8160 3954{
7096e938 3955 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3956 bgp_route_map_mark_update(rmap_name);
73ac8160 3957
d62a17ae 3958 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 3959}
518f0eb1 3960
097b5973 3961static void bgp_route_map_event(const char *rmap_name)
73ac8160 3962{
7096e938 3963 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3964 bgp_route_map_mark_update(rmap_name);
518f0eb1 3965
d62a17ae 3966 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
3967}
3968
d37ba549
MK
3969DEFUN (match_mac_address,
3970 match_mac_address_cmd,
3971 "match mac address WORD",
3972 MATCH_STR
3973 "mac address\n"
3974 "Match address of route\n"
3975 "MAC Access-list name\n")
3976{
3977 return bgp_route_match_add(vty, "mac address", argv[3]->arg,
3978 RMAP_EVENT_FILTER_ADDED);
3979}
3980
3981DEFUN (no_match_mac_address,
3982 no_match_mac_address_cmd,
646050e5 3983 "no match mac address WORD",
d37ba549
MK
3984 NO_STR
3985 MATCH_STR
3986 "mac\n"
646050e5
MK
3987 "Match address of route\n"
3988 "MAC acess-list name\n")
d37ba549 3989{
d37ba549
MK
3990 return bgp_route_match_delete(vty, "mac address", argv[4]->arg,
3991 RMAP_EVENT_FILTER_DELETED);
3992}
73ac8160 3993
33c2ff62
MK
3994DEFUN (match_evpn_route_type,
3995 match_evpn_route_type_cmd,
d4ef18b6 3996 "match evpn route-type <macip | multicast | prefix>",
33c2ff62
MK
3997 MATCH_STR
3998 EVPN_HELP_STR
3999 "Match route-type\n"
4000 "mac-ip route\n"
4001 "IMET route\n"
4002 "prefix route\n")
4003{
4004 return bgp_route_match_add(vty, "evpn route-type", argv[3]->arg,
4005 RMAP_EVENT_MATCH_ADDED);
4006}
4007
4008DEFUN (no_match_evpn_route_type,
4009 no_match_evpn_route_type_cmd,
d4ef18b6 4010 "no match evpn route-type <macip | multicast | prefix>",
33c2ff62
MK
4011 NO_STR
4012 MATCH_STR
4013 EVPN_HELP_STR
4014 "Match route-type\n"
4015 "mac-ip route\n"
4016 "IMET route\n"
4017 "prefix route\n")
4018{
4019 return bgp_route_match_delete(vty, "evpn route-type", argv[4]->arg,
4020 RMAP_EVENT_MATCH_DELETED);
4021}
4022
4023
16f7ce2b
MK
4024DEFUN (match_evpn_vni,
4025 match_evpn_vni_cmd,
093e3f23 4026 "match evpn vni " CMD_VNI_RANGE,
16f7ce2b 4027 MATCH_STR
62982d5a 4028 EVPN_HELP_STR
16f7ce2b
MK
4029 "Match VNI\n"
4030 "VNI ID\n")
4031{
646050e5 4032 return bgp_route_match_add(vty, "evpn vni", argv[3]->arg,
16f7ce2b
MK
4033 RMAP_EVENT_MATCH_ADDED);
4034}
4035
4036DEFUN (no_match_evpn_vni,
4037 no_match_evpn_vni_cmd,
093e3f23 4038 "no match evpn vni " CMD_VNI_RANGE,
16f7ce2b
MK
4039 NO_STR
4040 MATCH_STR
62982d5a 4041 EVPN_HELP_STR
16f7ce2b
MK
4042 "Match VNI\n"
4043 "VNI ID\n")
4044{
646050e5 4045 return bgp_route_match_delete(vty, "evpn vni", argv[4]->arg,
16f7ce2b
MK
4046 RMAP_EVENT_MATCH_DELETED);
4047}
4048
6fb219da
MK
4049DEFUN (match_evpn_default_route,
4050 match_evpn_default_route_cmd,
4051 "match evpn default-route",
4052 MATCH_STR
4053 EVPN_HELP_STR
4054 "default EVPN type-5 route\n")
4055{
4056 return bgp_route_match_add(vty, "evpn default-route", NULL,
4057 RMAP_EVENT_MATCH_ADDED);
4058}
4059
4060DEFUN (no_match_evpn_default_route,
4061 no_match_evpn_default_route_cmd,
4062 "no match evpn default-route",
4063 NO_STR
4064 MATCH_STR
4065 EVPN_HELP_STR
4066 "default EVPN type-5 route\n")
4067{
4068 return bgp_route_match_delete(vty, "evpn default-route", NULL,
4069 RMAP_EVENT_MATCH_DELETED);
4070}
4071
196c6b09
LK
4072DEFUN (match_evpn_rd,
4073 match_evpn_rd_cmd,
4074 "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4075 MATCH_STR
4076 EVPN_HELP_STR
4077 "Route Distinguisher\n"
4078 "ASN:XX or A.B.C.D:XX\n")
4079{
4080 return bgp_route_match_add(vty, "evpn rd", argv[3]->arg,
4081 RMAP_EVENT_MATCH_ADDED);
4082}
4083
4084DEFUN (no_match_evpn_rd,
4085 no_match_evpn_rd_cmd,
4086 "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4087 NO_STR
4088 MATCH_STR
4089 EVPN_HELP_STR
4090 "Route Distinguisher\n"
4091 "ASN:XX or A.B.C.D:XX\n")
4092{
4093 return bgp_route_match_delete(vty, "evpn rd", argv[4]->arg,
4094 RMAP_EVENT_MATCH_DELETED);
4095}
4096
1dcc9e5b
CS
4097DEFPY(match_vrl_source_vrf,
4098 match_vrl_source_vrf_cmd,
4099 "match source-vrf NAME$vrf_name",
4100 MATCH_STR
4101 "source vrf\n"
4102 "The VRF name\n")
4103{
4104 return bgp_route_match_add(vty, "source-vrf", vrf_name,
4105 RMAP_EVENT_MATCH_ADDED);
4106}
4107
4108DEFPY(no_match_vrl_source_vrf,
4109 no_match_vrl_source_vrf_cmd,
4110 "no match source-vrf NAME$vrf_name",
4111 NO_STR
4112 MATCH_STR
4113 "source vrf\n"
4114 "The VRF name\n")
4115{
4116 return bgp_route_match_delete(vty, "source-vrf", vrf_name,
4117 RMAP_EVENT_MATCH_DELETED);
4118}
4119
fee0f4c6 4120DEFUN (match_peer,
4121 match_peer_cmd,
8c3433e4 4122 "match peer <A.B.C.D|X:X::X:X|WORD>",
fee0f4c6 4123 MATCH_STR
4124 "Match peer address\n"
6e13ed4a 4125 "IP address of peer\n"
8c3433e4
DS
4126 "IPv6 address of peer\n"
4127 "Interface name of peer\n")
fee0f4c6 4128{
d62a17ae 4129 int idx_ip = 2;
4130 return bgp_route_match_add(vty, "peer", argv[idx_ip]->arg,
4131 RMAP_EVENT_MATCH_ADDED);
fee0f4c6 4132}
4133
4134DEFUN (match_peer_local,
f412b39a 4135 match_peer_local_cmd,
fee0f4c6 4136 "match peer local",
4137 MATCH_STR
4138 "Match peer address\n"
4139 "Static or Redistributed routes\n")
4140{
d62a17ae 4141 return bgp_route_match_add(vty, "peer", "local",
4142 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 4143}
4144
4145DEFUN (no_match_peer,
4146 no_match_peer_cmd,
8c3433e4 4147 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
fee0f4c6 4148 NO_STR
4149 MATCH_STR
4c9bd275
DW
4150 "Match peer address\n"
4151 "Static or Redistributed routes\n"
4152 "IP address of peer\n"
8c3433e4
DS
4153 "IPv6 address of peer\n"
4154 "Interface name of peer\n")
fee0f4c6 4155{
d62a17ae 4156 int idx_peer = 3;
4c9bd275 4157
d62a17ae 4158 if (argc <= idx_peer)
4159 return bgp_route_match_delete(vty, "peer", NULL,
4160 RMAP_EVENT_MATCH_DELETED);
4161 return bgp_route_match_delete(vty, "peer", argv[idx_peer]->arg,
4162 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 4163}
4164
1d7c7ace
DS
4165#if defined(HAVE_LUA)
4166DEFUN (match_command,
4167 match_command_cmd,
4168 "match command WORD",
4169 MATCH_STR
4170 "Run a command to match\n"
4171 "The command to run\n")
4172{
4173 return bgp_route_match_add(vty, "command", argv[2]->arg,
4174 RMAP_EVENT_FILTER_ADDED);
4175}
4176
4177DEFUN (no_match_command,
4178 no_match_command_cmd,
4179 "no match command WORD",
4180 NO_STR
4181 MATCH_STR
4182 "Run a command to match\n"
4183 "The command to run\n")
4184{
4185 return bgp_route_match_delete(vty, "command", argv[3]->arg,
4186 RMAP_EVENT_FILTER_DELETED);
4187}
4188#endif
fee0f4c6 4189
4c9bd275 4190/* match probability */
1add115a
VT
4191DEFUN (match_probability,
4192 match_probability_cmd,
6147e2c6 4193 "match probability (0-100)",
1add115a
VT
4194 MATCH_STR
4195 "Match portion of routes defined by percentage value\n"
4196 "Percentage of routes\n")
4197{
d62a17ae 4198 int idx_number = 2;
4199 return bgp_route_match_add(vty, "probability", argv[idx_number]->arg,
4200 RMAP_EVENT_MATCH_ADDED);
1add115a
VT
4201}
4202
4c9bd275 4203
1add115a
VT
4204DEFUN (no_match_probability,
4205 no_match_probability_cmd,
4c9bd275 4206 "no match probability [(1-99)]",
1add115a
VT
4207 NO_STR
4208 MATCH_STR
4c9bd275
DW
4209 "Match portion of routes defined by percentage value\n"
4210 "Percentage of routes\n")
1add115a 4211{
d62a17ae 4212 int idx_number = 3;
4213 if (argc <= idx_number)
4214 return bgp_route_match_delete(vty, "probability", NULL,
4215 RMAP_EVENT_MATCH_DELETED);
4216 return bgp_route_match_delete(vty, "probability", argv[idx_number]->arg,
4217 RMAP_EVENT_MATCH_DELETED);
1add115a
VT
4218}
4219
1add115a 4220
f412b39a 4221DEFUN (match_ip_route_source,
c1643bb7 4222 match_ip_route_source_cmd,
6147e2c6 4223 "match ip route-source <(1-199)|(1300-2699)|WORD>",
c1643bb7 4224 MATCH_STR
4225 IP_STR
4226 "Match advertising source address of route\n"
4227 "IP access-list number\n"
4228 "IP access-list number (expanded range)\n"
4229 "IP standard access-list name\n")
4230{
d62a17ae 4231 int idx_acl = 3;
4232 return bgp_route_match_add(vty, "ip route-source", argv[idx_acl]->arg,
4233 RMAP_EVENT_FILTER_ADDED);
c1643bb7 4234}
4235
4c9bd275 4236
c1643bb7 4237DEFUN (no_match_ip_route_source,
4238 no_match_ip_route_source_cmd,
6de69f83 4239 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
c1643bb7 4240 NO_STR
4241 MATCH_STR
4242 IP_STR
4c9bd275
DW
4243 "Match advertising source address of route\n"
4244 "IP access-list number\n"
4245 "IP access-list number (expanded range)\n"
4246 "IP standard access-list name\n")
c1643bb7 4247{
d62a17ae 4248 int idx_number = 4;
4249 if (argc <= idx_number)
4250 return bgp_route_match_delete(vty, "ip route-source", NULL,
4251 RMAP_EVENT_FILTER_DELETED);
4252 return bgp_route_match_delete(vty, "ip route-source",
4253 argv[idx_number]->arg,
4254 RMAP_EVENT_FILTER_DELETED);
c1643bb7 4255}
4256
c1643bb7 4257
f412b39a 4258DEFUN (match_ip_route_source_prefix_list,
c1643bb7 4259 match_ip_route_source_prefix_list_cmd,
4260 "match ip route-source prefix-list WORD",
4261 MATCH_STR
4262 IP_STR
4263 "Match advertising source address of route\n"
4264 "Match entries of prefix-lists\n"
4265 "IP prefix-list name\n")
4266{
d62a17ae 4267 int idx_word = 4;
4268 return bgp_route_match_add(vty, "ip route-source prefix-list",
4269 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
c1643bb7 4270}
4271
4c9bd275 4272
c1643bb7 4273DEFUN (no_match_ip_route_source_prefix_list,
4274 no_match_ip_route_source_prefix_list_cmd,
4c9bd275 4275 "no match ip route-source prefix-list [WORD]",
c1643bb7 4276 NO_STR
4277 MATCH_STR
4278 IP_STR
4279 "Match advertising source address of route\n"
4c9bd275
DW
4280 "Match entries of prefix-lists\n"
4281 "IP prefix-list name\n")
c1643bb7 4282{
d62a17ae 4283 int idx_word = 5;
4284 if (argc <= idx_word)
4285 return bgp_route_match_delete(vty,
4286 "ip route-source prefix-list",
4287 NULL, RMAP_EVENT_PLIST_DELETED);
4288 return bgp_route_match_delete(vty, "ip route-source prefix-list",
4289 argv[idx_word]->arg,
4290 RMAP_EVENT_PLIST_DELETED);
c1643bb7 4291}
4292
c1643bb7 4293
af291c15
DS
4294DEFUN (match_local_pref,
4295 match_local_pref_cmd,
6147e2c6 4296 "match local-preference (0-4294967295)",
af291c15
DS
4297 MATCH_STR
4298 "Match local-preference of route\n"
4299 "Metric value\n")
4300{
d62a17ae 4301 int idx_number = 2;
4302 return bgp_route_match_add(vty, "local-preference",
4303 argv[idx_number]->arg,
4304 RMAP_EVENT_MATCH_ADDED);
af291c15
DS
4305}
4306
4c9bd275 4307
af291c15
DS
4308DEFUN (no_match_local_pref,
4309 no_match_local_pref_cmd,
4c9bd275 4310 "no match local-preference [(0-4294967295)]",
af291c15
DS
4311 NO_STR
4312 MATCH_STR
4c9bd275
DW
4313 "Match local preference of route\n"
4314 "Local preference value\n")
af291c15 4315{
d62a17ae 4316 int idx_localpref = 3;
4317 if (argc <= idx_localpref)
4318 return bgp_route_match_delete(vty, "local-preference", NULL,
4319 RMAP_EVENT_MATCH_DELETED);
4320 return bgp_route_match_delete(vty, "local-preference",
4321 argv[idx_localpref]->arg,
4322 RMAP_EVENT_MATCH_DELETED);
af291c15
DS
4323}
4324
af291c15 4325
f412b39a 4326DEFUN (match_community,
718e3744 4327 match_community_cmd,
0d702986 4328 "match community <(1-99)|(100-500)|WORD> [exact-match]",
718e3744 4329 MATCH_STR
4330 "Match BGP community list\n"
4331 "Community-list number (standard)\n"
4332 "Community-list number (expanded)\n"
4333 "Community-list name\n"
4334 "Do exact matching of communities\n")
4335{
d62a17ae 4336 int idx_comm_list = 2;
4337 int ret;
4338 char *argstr;
718e3744 4339
d62a17ae 4340 if (argc == 4) {
4341 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4342 strlen(argv[idx_comm_list]->arg)
4343 + strlen("exact-match") + 2);
718e3744 4344
d62a17ae 4345 sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
4346 } else
4347 argstr = argv[idx_comm_list]->arg;
718e3744 4348
d62a17ae 4349 ret = bgp_route_match_add(vty, "community", argstr,
4350 RMAP_EVENT_CLIST_ADDED);
718e3744 4351
d62a17ae 4352 if (argstr != argv[idx_comm_list]->arg)
4353 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 4354
d62a17ae 4355 return ret;
718e3744 4356}
4357
4358DEFUN (no_match_community,
4359 no_match_community_cmd,
4c9bd275 4360 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
718e3744 4361 NO_STR
4362 MATCH_STR
4c9bd275
DW
4363 "Match BGP community list\n"
4364 "Community-list number (standard)\n"
4365 "Community-list number (expanded)\n"
4366 "Community-list name\n"
4367 "Do exact matching of communities\n")
718e3744 4368{
d62a17ae 4369 return bgp_route_match_delete(vty, "community", NULL,
4370 RMAP_EVENT_CLIST_DELETED);
718e3744 4371}
4372
57d187bc
JS
4373DEFUN (match_lcommunity,
4374 match_lcommunity_cmd,
03ff9a14 4375 "match large-community <(1-99)|(100-500)|WORD> [exact-match]",
57d187bc
JS
4376 MATCH_STR
4377 "Match BGP large community list\n"
4378 "Large Community-list number (standard)\n"
4379 "Large Community-list number (expanded)\n"
03ff9a14 4380 "Large Community-list name\n"
4381 "Do exact matching of communities\n")
57d187bc 4382{
03ff9a14 4383 int idx_lcomm_list = 2;
4384 int ret;
4385 char *argstr;
4386
4387 if (argc == 4) {
4388 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4389 strlen(argv[idx_lcomm_list]->arg)
4390 + strlen("exact-match") + 2);
4391
4392 sprintf(argstr, "%s exact-match", argv[idx_lcomm_list]->arg);
4393 } else
4394 argstr = argv[idx_lcomm_list]->arg;
4395
4396 ret = bgp_route_match_add(vty, "large-community", argstr,
d62a17ae 4397 RMAP_EVENT_LLIST_ADDED);
03ff9a14 4398 if (argstr != argv[idx_lcomm_list]->arg)
4399 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
4400
4401 return ret;
57d187bc 4402}
718e3744 4403
57d187bc
JS
4404DEFUN (no_match_lcommunity,
4405 no_match_lcommunity_cmd,
03ff9a14 4406 "no match large-community [<(1-99)|(100-500)|WORD> [exact-match]]",
57d187bc
JS
4407 NO_STR
4408 MATCH_STR
4409 "Match BGP large community list\n"
4410 "Large Community-list number (standard)\n"
4411 "Large Community-list number (expanded)\n"
03ff9a14 4412 "Large Community-list name\n"
4413 "Do exact matching of communities\n")
57d187bc 4414{
d62a17ae 4415 return bgp_route_match_delete(vty, "large-community", NULL,
4416 RMAP_EVENT_LLIST_DELETED);
57d187bc 4417}
718e3744 4418
f412b39a 4419DEFUN (match_ecommunity,
73ffb25b 4420 match_ecommunity_cmd,
6147e2c6 4421 "match extcommunity <(1-99)|(100-500)|WORD>",
73ffb25b 4422 MATCH_STR
4423 "Match BGP/VPN extended community list\n"
4424 "Extended community-list number (standard)\n"
4425 "Extended community-list number (expanded)\n"
4426 "Extended community-list name\n")
4427{
d62a17ae 4428 int idx_comm_list = 2;
4429 return bgp_route_match_add(vty, "extcommunity",
4430 argv[idx_comm_list]->arg,
4431 RMAP_EVENT_ECLIST_ADDED);
73ffb25b 4432}
4433
4c9bd275 4434
73ffb25b 4435DEFUN (no_match_ecommunity,
4436 no_match_ecommunity_cmd,
4c9bd275 4437 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
73ffb25b 4438 NO_STR
4439 MATCH_STR
4c9bd275
DW
4440 "Match BGP/VPN extended community list\n"
4441 "Extended community-list number (standard)\n"
4442 "Extended community-list number (expanded)\n"
4443 "Extended community-list name\n")
73ffb25b 4444{
d62a17ae 4445 return bgp_route_match_delete(vty, "extcommunity", NULL,
4446 RMAP_EVENT_ECLIST_DELETED);
73ffb25b 4447}
4448
73ffb25b 4449
718e3744 4450DEFUN (match_aspath,
4451 match_aspath_cmd,
4452 "match as-path WORD",
4453 MATCH_STR
4454 "Match BGP AS path list\n"
4455 "AS path access-list name\n")
4456{
d62a17ae 4457 int idx_word = 2;
4458 return bgp_route_match_add(vty, "as-path", argv[idx_word]->arg,
4459 RMAP_EVENT_ASLIST_ADDED);
718e3744 4460}
4461
4c9bd275 4462
718e3744 4463DEFUN (no_match_aspath,
4464 no_match_aspath_cmd,
4c9bd275 4465 "no match as-path [WORD]",
718e3744 4466 NO_STR
4467 MATCH_STR
4c9bd275
DW
4468 "Match BGP AS path list\n"
4469 "AS path access-list name\n")
718e3744 4470{
d62a17ae 4471 return bgp_route_match_delete(vty, "as-path", NULL,
4472 RMAP_EVENT_ASLIST_DELETED);
718e3744 4473}
4474
718e3744 4475
4476DEFUN (match_origin,
4477 match_origin_cmd,
6147e2c6 4478 "match origin <egp|igp|incomplete>",
718e3744 4479 MATCH_STR
4480 "BGP origin code\n"
4481 "remote EGP\n"
4482 "local IGP\n"
4483 "unknown heritage\n")
4484{
d62a17ae 4485 int idx_origin = 2;
4486 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
4487 return bgp_route_match_add(vty, "origin", "igp",
4488 RMAP_EVENT_MATCH_ADDED);
4489 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
4490 return bgp_route_match_add(vty, "origin", "egp",
4491 RMAP_EVENT_MATCH_ADDED);
4492 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
4493 return bgp_route_match_add(vty, "origin", "incomplete",
4494 RMAP_EVENT_MATCH_ADDED);
718e3744 4495
d62a17ae 4496 vty_out(vty, "%% Invalid match origin type\n");
4497 return CMD_WARNING_CONFIG_FAILED;
718e3744 4498}
4499
4c9bd275 4500
718e3744 4501DEFUN (no_match_origin,
4502 no_match_origin_cmd,
4c9bd275 4503 "no match origin [<egp|igp|incomplete>]",
718e3744 4504 NO_STR
4505 MATCH_STR
4c9bd275
DW
4506 "BGP origin code\n"
4507 "remote EGP\n"
4508 "local IGP\n"
4509 "unknown heritage\n")
718e3744 4510{
d62a17ae 4511 return bgp_route_match_delete(vty, "origin", NULL,
4512 RMAP_EVENT_MATCH_DELETED);
718e3744 4513}
4514
951745bd
PG
4515DEFUN (set_table_id,
4516 set_table_id_cmd,
4517 "set table (1-4294967295)",
4518 SET_STR
4519 "export route to non-main kernel table\n"
4520 "Kernel routing table id\n")
4521{
4522 int idx_id = 2;
4523
4524 VTY_DECLVAR_CONTEXT(route_map_index, index);
4525
4526 return generic_set_add(vty, index, "table", argv[idx_id]->arg);
4527}
4528
4529DEFUN (no_set_table_id,
4530 no_set_table_id_cmd,
4531 "no set table",
4532 NO_STR
4533 SET_STR
4534 "export route to non-main kernel table\n")
4535{
4536 VTY_DECLVAR_CONTEXT(route_map_index, index);
4537
4538 return generic_set_delete(vty, index, "table", NULL);
4539}
4540
af5cd0a5 4541DEFUN (set_ip_nexthop_peer,
4542 set_ip_nexthop_peer_cmd,
89602edb
QY
4543 "[no] set ip next-hop peer-address",
4544 NO_STR
af5cd0a5 4545 SET_STR
4546 IP_STR
4547 "Next hop address\n"
4548 "Use peer address (for BGP only)\n")
4549{
89602edb 4550 int (*func)(struct vty *, struct route_map_index *, const char *,
a4d82a8a
PZ
4551 const char *) = strmatch(argv[0]->text, "no")
4552 ? generic_set_delete
4553 : generic_set_add;
89602edb
QY
4554
4555 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
4556 "peer-address");
af5cd0a5 4557}
4558
316e074d
DS
4559DEFUN (set_ip_nexthop_unchanged,
4560 set_ip_nexthop_unchanged_cmd,
cca30ba8
QY
4561 "[no] set ip next-hop unchanged",
4562 NO_STR
316e074d
DS
4563 SET_STR
4564 IP_STR
4565 "Next hop address\n"
4566 "Don't modify existing Next hop address\n")
4567{
cca30ba8 4568 int (*func)(struct vty *, struct route_map_index *, const char *,
a4d82a8a
PZ
4569 const char *) = strmatch(argv[0]->text, "no")
4570 ? generic_set_delete
4571 : generic_set_add;
cca30ba8
QY
4572
4573 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
4574 "unchanged");
718e3744 4575}
4576
7b7d48e5
DS
4577DEFUN (set_distance,
4578 set_distance_cmd,
4579 "set distance (0-255)",
4580 SET_STR
4581 "BGP Administrative Distance to use\n"
4582 "Distance value\n")
4583{
4584 int idx_number = 2;
4585
4586 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4587 "distance", argv[idx_number]->arg);
4588}
4589
4590DEFUN (no_set_distance,
4591 no_set_distance_cmd,
4592 "no set distance [(0-255)]",
4593 NO_STR SET_STR
4594 "BGP Administrative Distance to use\n"
4595 "Distance value\n")
4596{
4597 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4598 "distance", NULL);
4599}
718e3744 4600
4601DEFUN (set_local_pref,
4602 set_local_pref_cmd,
3684eb43 4603 "set local-preference WORD",
718e3744 4604 SET_STR
4605 "BGP local preference path attribute\n"
3684eb43 4606 "Preference value (0-4294967295)\n")
718e3744 4607{
d62a17ae 4608 int idx_number = 2;
4609 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4610 "local-preference", argv[idx_number]->arg);
718e3744 4611}
4612
4c9bd275 4613
718e3744 4614DEFUN (no_set_local_pref,
4615 no_set_local_pref_cmd,
3684eb43 4616 "no set local-preference [WORD]",
718e3744 4617 NO_STR
4618 SET_STR
4c9bd275 4619 "BGP local preference path attribute\n"
3684eb43 4620 "Preference value (0-4294967295)\n")
718e3744 4621{
d62a17ae 4622 int idx_localpref = 3;
4623 if (argc <= idx_localpref)
4624 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4625 "local-preference", NULL);
4626 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4627 "local-preference", argv[idx_localpref]->arg);
718e3744 4628}
4629
718e3744 4630
4631DEFUN (set_weight,
4632 set_weight_cmd,
6147e2c6 4633 "set weight (0-4294967295)",
718e3744 4634 SET_STR
4635 "BGP weight for routing table\n"
4636 "Weight value\n")
4637{
d62a17ae 4638 int idx_number = 2;
4639 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "weight",
4640 argv[idx_number]->arg);
718e3744 4641}
4642
4c9bd275 4643
718e3744 4644DEFUN (no_set_weight,
4645 no_set_weight_cmd,
4c9bd275 4646 "no set weight [(0-4294967295)]",
718e3744 4647 NO_STR
4648 SET_STR
4c9bd275
DW
4649 "BGP weight for routing table\n"
4650 "Weight value\n")
718e3744 4651{
d62a17ae 4652 int idx_weight = 3;
4653 if (argc <= idx_weight)
4654 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4655 "weight", NULL);
4656 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4657 "weight", argv[idx_weight]->arg);
718e3744 4658}
4659
d990e384
DS
4660DEFUN (set_label_index,
4661 set_label_index_cmd,
8b81993e 4662 "set label-index (0-1048560)",
d990e384
DS
4663 SET_STR
4664 "Label index to associate with the prefix\n"
4665 "Label index value\n")
4666{
d62a17ae 4667 int idx_number = 2;
4668 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4669 "label-index", argv[idx_number]->arg);
d990e384
DS
4670}
4671
4672DEFUN (no_set_label_index,
4673 no_set_label_index_cmd,
8b81993e 4674 "no set label-index [(0-1048560)]",
d990e384
DS
4675 NO_STR
4676 SET_STR
4677 "Label index to associate with the prefix\n"
4678 "Label index value\n")
4679{
d62a17ae 4680 int idx_label_index = 3;
4681 if (argc <= idx_label_index)
4682 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4683 "label-index", NULL);
4684 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4685 "label-index", argv[idx_label_index]->arg);
d990e384 4686}
718e3744 4687
12dcf78e
QY
4688DEFUN (set_aspath_prepend_asn,
4689 set_aspath_prepend_asn_cmd,
4690 "set as-path prepend (1-4294967295)...",
718e3744 4691 SET_STR
841f7a57 4692 "Transform BGP AS_PATH attribute\n"
718e3744 4693 "Prepend to the as-path\n"
12dcf78e 4694 "AS number\n")
718e3744 4695{
d62a17ae 4696 int idx_asn = 3;
4697 int ret;
4698 char *str;
718e3744 4699
d62a17ae 4700 str = argv_concat(argv, argc, idx_asn);
4701 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4702 "as-path prepend", str);
4703 XFREE(MTYPE_TMP, str);
718e3744 4704
d62a17ae 4705 return ret;
718e3744 4706}
4707
12dcf78e
QY
4708DEFUN (set_aspath_prepend_lastas,
4709 set_aspath_prepend_lastas_cmd,
b6ab2929 4710 "set as-path prepend last-as (1-10)",
12dcf78e
QY
4711 SET_STR
4712 "Transform BGP AS_PATH attribute\n"
4713 "Prepend to the as-path\n"
4714 "Use the peer's AS-number\n"
b6ab2929 4715 "Number of times to insert\n")
12dcf78e 4716{
d62a17ae 4717 return set_aspath_prepend_asn(self, vty, argc, argv);
12dcf78e 4718}
bc3dd427 4719
718e3744 4720DEFUN (no_set_aspath_prepend,
4721 no_set_aspath_prepend_cmd,
a4b2b610 4722 "no set as-path prepend [(1-4294967295)]",
718e3744 4723 NO_STR
4724 SET_STR
841f7a57 4725 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
4726 "Prepend to the as-path\n"
4727 "AS number\n")
718e3744 4728{
d62a17ae 4729 int idx_asn = 4;
4730 int ret;
4731 char *str;
a7f93f3e 4732
d62a17ae 4733 str = argv_concat(argv, argc, idx_asn);
4734 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4735 "as-path prepend", str);
4736 XFREE(MTYPE_TMP, str);
4737 return ret;
718e3744 4738}
4739
9131e6e8
DS
4740DEFUN (no_set_aspath_prepend_lastas,
4741 no_set_aspath_prepend_lastas_cmd,
4742 "no set as-path prepend last-as [(1-10)]",
4743 NO_STR
4744 SET_STR
4745 "Transform BGP AS_PATH attribute\n"
4746 "Prepend to the as-path\n"
4747 "Use the peers AS-number\n"
4748 "Number of times to insert\n")
4749{
4750 return no_set_aspath_prepend(self, vty, argc, argv);
4751}
718e3744 4752
841f7a57
DO
4753DEFUN (set_aspath_exclude,
4754 set_aspath_exclude_cmd,
a4b2b610 4755 "set as-path exclude (1-4294967295)...",
841f7a57
DO
4756 SET_STR
4757 "Transform BGP AS-path attribute\n"
4758 "Exclude from the as-path\n"
4759 "AS number\n")
4760{
d62a17ae 4761 int idx_asn = 3;
4762 int ret;
4763 char *str;
841f7a57 4764
d62a17ae 4765 str = argv_concat(argv, argc, idx_asn);
4766 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4767 "as-path exclude", str);
4768 XFREE(MTYPE_TMP, str);
4769 return ret;
841f7a57
DO
4770}
4771
4772DEFUN (no_set_aspath_exclude,
4773 no_set_aspath_exclude_cmd,
a4b2b610 4774 "no set as-path exclude (1-4294967295)...",
841f7a57
DO
4775 NO_STR
4776 SET_STR
4777 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
4778 "Exclude from the as-path\n"
4779 "AS number\n")
841f7a57 4780{
d62a17ae 4781 int idx_asn = 4;
4782 int ret;
4783 char *str;
841f7a57 4784
d62a17ae 4785 str = argv_concat(argv, argc, idx_asn);
4786 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4787 "as-path exclude", str);
4788 XFREE(MTYPE_TMP, str);
4789 return ret;
841f7a57
DO
4790}
4791
499ceb3d
DA
4792ALIAS(no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
4793 "no set as-path exclude",
4794 NO_STR SET_STR
4795 "Transform BGP AS_PATH attribute\n"
4796 "Exclude from the as-path\n")
841f7a57 4797
718e3744 4798DEFUN (set_community,
4799 set_community_cmd,
e961923c 4800 "set community AA:NN...",
718e3744 4801 SET_STR
4802 "BGP community attribute\n"
859d388e 4803 COMMUNITY_VAL_STR)
718e3744 4804{
d62a17ae 4805 int idx_aa_nn = 2;
4806 int i;
4807 int first = 0;
4808 int additive = 0;
4809 struct buffer *b;
4810 struct community *com = NULL;
4811 char *str;
4812 char *argstr;
4813 int ret;
4814
4815 b = buffer_new(1024);
4816
4817 for (i = idx_aa_nn; i < argc; i++) {
4818 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
4819 == 0) {
4820 additive = 1;
4821 continue;
4822 }
4823
4824 if (first)
4825 buffer_putc(b, ' ');
4826 else
4827 first = 1;
4828
4829 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
4830 == 0) {
4831 buffer_putstr(b, "internet");
4832 continue;
4833 }
4834 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
4835 == 0) {
4836 buffer_putstr(b, "local-AS");
4837 continue;
4838 }
4839 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
4840 && strncmp(argv[i]->arg, "no-advertise",
4841 strlen(argv[i]->arg))
4842 == 0) {
4843 buffer_putstr(b, "no-advertise");
4844 continue;
4845 }
4846 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
4847 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
4848 == 0) {
4849 buffer_putstr(b, "no-export");
4850 continue;
4851 }
a4d82a8a
PZ
4852 if (strncmp(argv[i]->arg, "graceful-shutdown",
4853 strlen(argv[i]->arg))
7f323236
DW
4854 == 0) {
4855 buffer_putstr(b, "graceful-shutdown");
4856 continue;
4857 }
d62a17ae 4858 buffer_putstr(b, argv[i]->arg);
4859 }
4860 buffer_putc(b, '\0');
4861
4862 /* Fetch result string then compile it to communities attribute. */
4863 str = buffer_getstr(b);
4864 buffer_free(b);
4865
4866 if (str) {
4867 com = community_str2com(str);
4868 XFREE(MTYPE_TMP, str);
4869 }
4870
4871 /* Can't compile user input into communities attribute. */
4872 if (!com) {
4873 vty_out(vty, "%% Malformed communities attribute\n");
4874 return CMD_WARNING_CONFIG_FAILED;
4875 }
4876
4877 /* Set communites attribute string. */
a69ea8ae 4878 str = community_str(com, false);
d62a17ae 4879
4880 if (additive) {
552d6491
QY
4881 size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
4882 argstr = XCALLOC(MTYPE_TMP, argstr_sz);
4883 strlcpy(argstr, str, argstr_sz);
4884 strlcat(argstr, " additive", argstr_sz);
d62a17ae 4885 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4886 "community", argstr);
4887 XFREE(MTYPE_TMP, argstr);
4888 } else
4889 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4890 "community", str);
4891
3c1f53de 4892 community_free(&com);
d62a17ae 4893
4894 return ret;
718e3744 4895}
4896
4897DEFUN (set_community_none,
4898 set_community_none_cmd,
4899 "set community none",
4900 SET_STR
4901 "BGP community attribute\n"
4902 "No community attribute\n")
4903{
d62a17ae 4904 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4905 "community", "none");
718e3744 4906}
4907
4908DEFUN (no_set_community,
4909 no_set_community_cmd,
a4b2b610 4910 "no set community AA:NN...",
718e3744 4911 NO_STR
4912 SET_STR
d7fa34c1
QY
4913 "BGP community attribute\n"
4914 COMMUNITY_VAL_STR)
718e3744 4915{
d62a17ae 4916 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4917 "community", NULL);
718e3744 4918}
4919
2929de9e
DS
4920ALIAS (no_set_community,
4921 no_set_community_short_cmd,
4922 "no set community",
4923 NO_STR
4924 SET_STR
4925 "BGP community attribute\n")
4926
718e3744 4927
718e3744 4928DEFUN (set_community_delete,
4929 set_community_delete_cmd,
6147e2c6 4930 "set comm-list <(1-99)|(100-500)|WORD> delete",
718e3744 4931 SET_STR
4932 "set BGP community list (for deletion)\n"
4933 "Community-list number (standard)\n"
5e3edbf5 4934 "Community-list number (expanded)\n"
718e3744 4935 "Community-list name\n"
4936 "Delete matching communities\n")
4937{
d62a17ae 4938 int idx_comm_list = 2;
4cae2269 4939 char *args;
718e3744 4940
4cae2269 4941 args = argv_concat(argv, argc, idx_comm_list);
d62a17ae 4942 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
4cae2269
DA
4943 args);
4944 XFREE(MTYPE_TMP, args);
718e3744 4945
d62a17ae 4946 return CMD_SUCCESS;
718e3744 4947}
4948
4949DEFUN (no_set_community_delete,
4950 no_set_community_delete_cmd,
a4b2b610 4951 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
718e3744 4952 NO_STR
4953 SET_STR
d7fa34c1
QY
4954 "set BGP community list (for deletion)\n"
4955 "Community-list number (standard)\n"
4956 "Community-list number (expanded)\n"
4957 "Community-list name\n"
4958 "Delete matching communities\n")
718e3744 4959{
d62a17ae 4960 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4961 "comm-list", NULL);
718e3744 4962}
4963
57d187bc
JS
4964DEFUN (set_lcommunity,
4965 set_lcommunity_cmd,
4966 "set large-community AA:BB:CC...",
4967 SET_STR
4968 "BGP large community attribute\n"
4969 "Large Community number in aa:bb:cc format or additive\n")
4970{
d62a17ae 4971 int ret;
4972 char *str;
57d187bc 4973
d62a17ae 4974 str = argv_concat(argv, argc, 2);
4975 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4976 "large-community", str);
4977 XFREE(MTYPE_TMP, str);
57d187bc 4978
d62a17ae 4979 return ret;
57d187bc
JS
4980}
4981
4982DEFUN (set_lcommunity_none,
4983 set_lcommunity_none_cmd,
4984 "set large-community none",
4985 SET_STR
4986 "BGP large community attribute\n"
4987 "No large community attribute\n")
4988{
d62a17ae 4989 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4990 "large-community", "none");
57d187bc
JS
4991}
4992
4993DEFUN (no_set_lcommunity,
4994 no_set_lcommunity_cmd,
52951b63 4995 "no set large-community none",
57d187bc
JS
4996 NO_STR
4997 SET_STR
4998 "BGP large community attribute\n"
52951b63 4999 "No community attribute\n")
57d187bc 5000{
d62a17ae 5001 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5002 "large-community", NULL);
57d187bc
JS
5003}
5004
52951b63
DS
5005DEFUN (no_set_lcommunity1,
5006 no_set_lcommunity1_cmd,
5007 "no set large-community AA:BB:CC...",
5008 NO_STR
5009 SET_STR
5010 "BGP large community attribute\n"
5011 "Large community in AA:BB:CC... format or additive\n")
5012{
d62a17ae 5013 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5014 "large-community", NULL);
52951b63 5015}
57d187bc 5016
76a20aa9
DS
5017ALIAS (no_set_lcommunity1,
5018 no_set_lcommunity1_short_cmd,
5019 "no set large-community",
5020 NO_STR
5021 SET_STR
5022 "BGP large community attribute\n")
5023
57d187bc
JS
5024DEFUN (set_lcommunity_delete,
5025 set_lcommunity_delete_cmd,
5026 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
5027 SET_STR
5028 "set BGP large community list (for deletion)\n"
5029 "Large Community-list number (standard)\n"
5030 "Large Communitly-list number (expanded)\n"
5031 "Large Community-list name\n"
5032 "Delete matching large communities\n")
5033{
4cae2269
DA
5034 int idx_lcomm_list = 2;
5035 char *args;
5036
5037 args = argv_concat(argv, argc, idx_lcomm_list);
d62a17ae 5038 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4cae2269
DA
5039 "large-comm-list", args);
5040 XFREE(MTYPE_TMP, args);
57d187bc 5041
d62a17ae 5042 return CMD_SUCCESS;
57d187bc
JS
5043}
5044
5045DEFUN (no_set_lcommunity_delete,
5046 no_set_lcommunity_delete_cmd,
db4f7086 5047 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
57d187bc
JS
5048 NO_STR
5049 SET_STR
5050 "set BGP large community list (for deletion)\n"
5051 "Large Community-list number (standard)\n"
5052 "Large Communitly-list number (expanded)\n"
5053 "Large Community-list name\n"
5054 "Delete matching large communities\n")
5055{
d62a17ae 5056 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5057 "large-comm-list", NULL);
57d187bc 5058}
718e3744 5059
76a20aa9
DS
5060ALIAS (no_set_lcommunity_delete,
5061 no_set_lcommunity_delete_short_cmd,
5062 "no set large-comm-list",
5063 NO_STR
5064 SET_STR
5065 "set BGP large community list (for deletion)\n")
5066
718e3744 5067DEFUN (set_ecommunity_rt,
5068 set_ecommunity_rt_cmd,
d114b977 5069 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 5070 SET_STR
5071 "BGP extended community attribute\n"
e6b6a564 5072 "Route Target extended community\n"
718e3744 5073 "VPN extended community\n")
5074{
d62a17ae 5075 int idx_asn_nn = 3;
5076 int ret;
5077 char *str;
718e3744 5078
d62a17ae 5079 str = argv_concat(argv, argc, idx_asn_nn);
5080 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5081 "extcommunity rt", str);
5082 XFREE(MTYPE_TMP, str);
718e3744 5083
d62a17ae 5084 return ret;
718e3744 5085}
5086
5087DEFUN (no_set_ecommunity_rt,
5088 no_set_ecommunity_rt_cmd,
d114b977 5089 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 5090 NO_STR
5091 SET_STR
5092 "BGP extended community attribute\n"
3a2d747c
QY
5093 "Route Target extended community\n"
5094 "VPN extended community\n")
718e3744 5095{
d62a17ae 5096 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5097 "extcommunity rt", NULL);
718e3744 5098}
5099
4db5ee8e
DS
5100ALIAS (no_set_ecommunity_rt,
5101 no_set_ecommunity_rt_short_cmd,
5102 "no set extcommunity rt",
5103 NO_STR
5104 SET_STR
5105 "BGP extended community attribute\n"
5106 "Route Target extended community\n")
718e3744 5107
5108DEFUN (set_ecommunity_soo,
5109 set_ecommunity_soo_cmd,
d114b977 5110 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 5111 SET_STR
5112 "BGP extended community attribute\n"
5113 "Site-of-Origin extended community\n"
5114 "VPN extended community\n")
5115{
d62a17ae 5116 int idx_asn_nn = 3;
5117 int ret;
5118 char *str;
718e3744 5119
d62a17ae 5120 str = argv_concat(argv, argc, idx_asn_nn);
5121 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5122 "extcommunity soo", str);
5123 XFREE(MTYPE_TMP, str);
5124 return ret;
718e3744 5125}
5126
a4b2b610 5127
718e3744 5128DEFUN (no_set_ecommunity_soo,
5129 no_set_ecommunity_soo_cmd,
d114b977 5130 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 5131 NO_STR
5132 SET_STR
5133 "BGP extended community attribute\n"
3a2d747c
QY
5134 "Site-of-Origin extended community\n"
5135 "VPN extended community\n")
718e3744 5136{
d62a17ae 5137 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5138 "extcommunity soo", NULL);
718e3744 5139}
5140
4db5ee8e
DS
5141ALIAS (no_set_ecommunity_soo,
5142 no_set_ecommunity_soo_short_cmd,
5143 "no set extcommunity soo",
5144 NO_STR
5145 SET_STR
5146 "GP extended community attribute\n"
5147 "Site-of-Origin extended community\n")
718e3744 5148
ca9ac3ef 5149DEFUN (set_ecommunity_lb,
5150 set_ecommunity_lb_cmd,
5151 "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
5152 SET_STR
5153 "BGP extended community attribute\n"
5154 "Link bandwidth extended community\n"
5155 "Bandwidth value in Mbps\n"
5156 "Cumulative bandwidth of all multipaths (outbound-only)\n"
5157 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
5158 "Attribute is set as non-transitive\n")
5159{
5160 int idx_lb = 3;
5161 int ret;
5162 char *str;
5163
5164 str = argv_concat(argv, argc, idx_lb);
5165 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5166 "extcommunity bandwidth", str);
5167 XFREE(MTYPE_TMP, str);
5168 return ret;
5169}
5170
5171
5172DEFUN (no_set_ecommunity_lb,
5173 no_set_ecommunity_lb_cmd,
5174 "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
5175 NO_STR
5176 SET_STR
5177 "BGP extended community attribute\n"
5178 "Link bandwidth extended community\n"
5179 "Bandwidth value in Mbps\n"
5180 "Cumulative bandwidth of all multipaths (outbound-only)\n"
5181 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
5182 "Attribute is set as non-transitive\n")
5183{
5184 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5185 "extcommunity bandwidth", NULL);
5186}
5187
5188ALIAS (no_set_ecommunity_lb,
5189 no_set_ecommunity_lb_short_cmd,
5190 "no set extcommunity bandwidth",
5191 NO_STR
5192 SET_STR
5193 "BGP extended community attribute\n"
5194 "Link bandwidth extended community\n")
5195
718e3744 5196DEFUN (set_origin,
5197 set_origin_cmd,
6147e2c6 5198 "set origin <egp|igp|incomplete>",
718e3744 5199 SET_STR
5200 "BGP origin code\n"
5201 "remote EGP\n"
5202 "local IGP\n"
5203 "unknown heritage\n")
5204{
d62a17ae 5205 int idx_origin = 2;
5206 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
5207 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5208 "origin", "igp");
5209 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5210 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5211 "origin", "egp");
5212 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5213 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5214 "origin", "incomplete");
718e3744 5215
d62a17ae 5216 vty_out(vty, "%% Invalid set origin type\n");
5217 return CMD_WARNING_CONFIG_FAILED;
718e3744 5218}
5219
a4b2b610 5220
718e3744 5221DEFUN (no_set_origin,
5222 no_set_origin_cmd,
a4b2b610 5223 "no set origin [<egp|igp|incomplete>]",
718e3744 5224 NO_STR
5225 SET_STR
d7fa34c1
QY
5226 "BGP origin code\n"
5227 "remote EGP\n"
5228 "local IGP\n"
5229 "unknown heritage\n")
718e3744 5230{
d62a17ae 5231 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5232 "origin", NULL);
718e3744 5233}
5234
718e3744 5235
5236DEFUN (set_atomic_aggregate,
5237 set_atomic_aggregate_cmd,
5238 "set atomic-aggregate",
5239 SET_STR
5240 "BGP atomic aggregate attribute\n" )
5241{
d62a17ae 5242 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5243 "atomic-aggregate", NULL);
718e3744 5244}
5245
5246DEFUN (no_set_atomic_aggregate,
5247 no_set_atomic_aggregate_cmd,
5248 "no set atomic-aggregate",
5249 NO_STR
5250 SET_STR
5251 "BGP atomic aggregate attribute\n" )
5252{
d62a17ae 5253 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5254 "atomic-aggregate", NULL);
718e3744 5255}
5256
5257DEFUN (set_aggregator_as,
5258 set_aggregator_as_cmd,
9ccf14f7 5259 "set aggregator as (1-4294967295) A.B.C.D",
718e3744 5260 SET_STR
5261 "BGP aggregator attribute\n"
5262 "AS number of aggregator\n"
5263 "AS number\n"
5264 "IP address of aggregator\n")
5265{
d62a17ae 5266 int idx_number = 3;
5267 int idx_ipv4 = 4;
5268 int ret;
5269 struct in_addr address;
5270 char *argstr;
e52702f2 5271
d62a17ae 5272 ret = inet_aton(argv[idx_ipv4]->arg, &address);
5273 if (ret == 0) {
5274 vty_out(vty, "Aggregator IP address is invalid\n");
5275 return CMD_WARNING_CONFIG_FAILED;
5276 }
718e3744 5277
d62a17ae 5278 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
5279 strlen(argv[idx_number]->arg)
5280 + strlen(argv[idx_ipv4]->arg) + 2);
718e3744 5281
d62a17ae 5282 sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
718e3744 5283
d62a17ae 5284 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5285 "aggregator as", argstr);
718e3744 5286
d62a17ae 5287 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 5288
d62a17ae 5289 return ret;
718e3744 5290}
5291
a4b2b610 5292
718e3744 5293DEFUN (no_set_aggregator_as,
5294 no_set_aggregator_as_cmd,
a4b2b610 5295 "no set aggregator as [(1-4294967295) A.B.C.D]",
718e3744 5296 NO_STR
5297 SET_STR
5298 "BGP aggregator attribute\n"
a4b2b610
DW
5299 "AS number of aggregator\n"
5300 "AS number\n"
5301 "IP address of aggregator\n")
718e3744 5302{
d62a17ae 5303 int idx_asn = 4;
5304 int idx_ip = 5;
5305 int ret;
5306 struct in_addr address;
5307 char *argstr;
718e3744 5308
d62a17ae 5309 if (argc <= idx_asn)
5310 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5311 "aggregator as", NULL);
e52702f2 5312
d62a17ae 5313 ret = inet_aton(argv[idx_ip]->arg, &address);
5314 if (ret == 0) {
5315 vty_out(vty, "Aggregator IP address is invalid\n");
5316 return CMD_WARNING_CONFIG_FAILED;
5317 }
718e3744 5318
d62a17ae 5319 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
5320 strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
5321 + 2);
718e3744 5322
d62a17ae 5323 sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
718e3744 5324
d62a17ae 5325 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5326 "aggregator as", argstr);
718e3744 5327
d62a17ae 5328 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 5329
d62a17ae 5330 return ret;
718e3744 5331}
5332
f412b39a 5333DEFUN (match_ipv6_next_hop,
718e3744 5334 match_ipv6_next_hop_cmd,
5335 "match ipv6 next-hop X:X::X:X",
5336 MATCH_STR
5337 IPV6_STR
5338 "Match IPv6 next-hop address of route\n"
5339 "IPv6 address of next hop\n")
5340{
d62a17ae 5341 int idx_ipv6 = 3;
5342 return bgp_route_match_add(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
5343 RMAP_EVENT_MATCH_ADDED);
718e3744 5344}
5345
5346DEFUN (no_match_ipv6_next_hop,
5347 no_match_ipv6_next_hop_cmd,
5348 "no match ipv6 next-hop X:X::X:X",
5349 NO_STR
5350 MATCH_STR
5351 IPV6_STR
5352 "Match IPv6 next-hop address of route\n"
5353 "IPv6 address of next hop\n")
5354{
d62a17ae 5355 int idx_ipv6 = 4;
5356 return bgp_route_match_delete(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
5357 RMAP_EVENT_MATCH_DELETED);
718e3744 5358}
5359
be7735b3
PG
5360DEFPY (match_ipv4_next_hop,
5361 match_ipv4_next_hop_cmd,
17ac51eb 5362 "match ip next-hop address A.B.C.D",
be7735b3
PG
5363 MATCH_STR
5364 IP_STR
5365 "Match IP next-hop address of route\n"
5366 "IP address\n"
5367 "IP address of next-hop\n")
5368{
5369 int idx_ipv4 = 4;
5370
17ac51eb
DS
5371 return bgp_route_match_add(vty, "ip next-hop address",
5372 argv[idx_ipv4]->arg, RMAP_EVENT_MATCH_ADDED);
5373}
be7735b3 5374
17ac51eb
DS
5375DEFPY (no_match_ipv4_next_hop,
5376 no_match_ipv4_next_hop_cmd,
5377 "no match ip next-hop address [A.B.C.D]",
5378 NO_STR
5379 MATCH_STR
5380 IP_STR
5381 "Match IP next-hop address of route\n"
5382 "IP address\n"
5383 "IP address of next-hop\n")
5384{
5385 return bgp_route_match_delete(vty, "ip next-hop address", NULL,
5386 RMAP_EVENT_MATCH_DELETED);
be7735b3 5387}
718e3744 5388
90916ac2
DS
5389DEFUN (set_ipv6_nexthop_peer,
5390 set_ipv6_nexthop_peer_cmd,
5391 "set ipv6 next-hop peer-address",
5392 SET_STR
5393 IPV6_STR
5394 "Next hop address\n"
5395 "Use peer address (for BGP only)\n")
5396{
d62a17ae 5397 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5398 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
5399}
5400
5401DEFUN (no_set_ipv6_nexthop_peer,
5402 no_set_ipv6_nexthop_peer_cmd,
5403 "no set ipv6 next-hop peer-address",
5404 NO_STR
5405 SET_STR
5406 IPV6_STR
5407 "IPv6 next-hop address\n"
161995ea 5408 "Use peer address (for BGP only)\n")
90916ac2 5409{
d62a17ae 5410 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5411 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
5412}
5413
161995ea
DS
5414DEFUN (set_ipv6_nexthop_prefer_global,
5415 set_ipv6_nexthop_prefer_global_cmd,
5416 "set ipv6 next-hop prefer-global",
5417 SET_STR
5418 IPV6_STR
5419 "IPv6 next-hop address\n"
5420 "Prefer global over link-local if both exist\n")
5421{
d62a17ae 5422 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5423 "ipv6 next-hop prefer-global", NULL);
5424 ;
161995ea
DS
5425}
5426
5427DEFUN (no_set_ipv6_nexthop_prefer_global,
5428 no_set_ipv6_nexthop_prefer_global_cmd,
5429 "no set ipv6 next-hop prefer-global",
5430 NO_STR
5431 SET_STR
5432 IPV6_STR
5433 "IPv6 next-hop address\n"
5434 "Prefer global over link-local if both exist\n")
5435{
d62a17ae 5436 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5437 "ipv6 next-hop prefer-global", NULL);
161995ea
DS
5438}
5439
718e3744 5440DEFUN (set_ipv6_nexthop_global,
5441 set_ipv6_nexthop_global_cmd,
5442 "set ipv6 next-hop global X:X::X:X",
5443 SET_STR
5444 IPV6_STR
5445 "IPv6 next-hop address\n"
5446 "IPv6 global address\n"
5447 "IPv6 address of next hop\n")
5448{
d62a17ae 5449 int idx_ipv6 = 4;
5450 struct in6_addr addr;
5451 int ret;
bf8b3d27 5452
d62a17ae 5453 ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr);
5454 if (!ret) {
5455 vty_out(vty, "%% Malformed nexthop address\n");
5456 return CMD_WARNING_CONFIG_FAILED;
5457 }
5458 if (IN6_IS_ADDR_UNSPECIFIED(&addr) || IN6_IS_ADDR_LOOPBACK(&addr)
5459 || IN6_IS_ADDR_MULTICAST(&addr) || IN6_IS_ADDR_LINKLOCAL(&addr)) {
5460 vty_out(vty, "%% Invalid global nexthop address\n");
5461 return CMD_WARNING_CONFIG_FAILED;
5462 }
bf8b3d27 5463
d62a17ae 5464 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5465 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 5466}
5467
a4b2b610 5468
718e3744 5469DEFUN (no_set_ipv6_nexthop_global,
5470 no_set_ipv6_nexthop_global_cmd,
a4b2b610 5471 "no set ipv6 next-hop global X:X::X:X",
718e3744 5472 NO_STR
5473 SET_STR
5474 IPV6_STR
5475 "IPv6 next-hop address\n"
a4b2b610
DW
5476 "IPv6 global address\n"
5477 "IPv6 address of next hop\n")
718e3744 5478{
d62a17ae 5479 int idx_ipv6 = 5;
5480 if (argc <= idx_ipv6)
5481 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5482 "ipv6 next-hop global", NULL);
5483 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5484 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 5485}
718e3744 5486
d6902373
PG
5487#ifdef KEEP_OLD_VPN_COMMANDS
5488DEFUN (set_vpn_nexthop,
5489 set_vpn_nexthop_cmd,
a13c883e 5490 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 5491 SET_STR
5492 "VPNv4 information\n"
d6902373
PG
5493 "VPN next-hop address\n"
5494 "IP address of next hop\n"
a13c883e
QY
5495 "VPNv6 information\n"
5496 "VPN next-hop address\n"
d6902373 5497 "IPv6 address of next hop\n")
718e3744 5498{
d62a17ae 5499 int idx_ip = 3;
5500 afi_t afi;
5501 int idx = 0;
5502
5503 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
5504 if (afi == AFI_IP)
5505 return generic_set_add(
5506 vty, VTY_GET_CONTEXT(route_map_index),
5507 "ipv4 vpn next-hop", argv[idx_ip]->arg);
5508 else
5509 return generic_set_add(
5510 vty, VTY_GET_CONTEXT(route_map_index),
5511 "ipv6 vpn next-hop", argv[idx_ip]->arg);
5512 }
5513 return CMD_SUCCESS;
d6902373 5514}
a4b2b610 5515
d6902373
PG
5516DEFUN (no_set_vpn_nexthop,
5517 no_set_vpn_nexthop_cmd,
a13c883e 5518 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 5519 NO_STR
5520 SET_STR
a13c883e 5521 "VPNv4 information\n"
d6902373
PG
5522 "VPN next-hop address\n"
5523 "IP address of next hop\n"
a13c883e
QY
5524 "VPNv6 information\n"
5525 "VPN next-hop address\n"
d6902373 5526 "IPv6 address of next hop\n")
718e3744 5527{
d62a17ae 5528 int idx_ip = 4;
5529 char *arg;
5530 afi_t afi;
5531 int idx = 0;
5532
5533 if (argc <= idx_ip)
5534 arg = NULL;
5535 else
5536 arg = argv[idx_ip]->arg;
5537 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
5538 if (afi == AFI_IP)
5539 return generic_set_delete(
5540 vty, VTY_GET_CONTEXT(route_map_index),
5541 "ipv4 vpn next-hop", arg);
5542 else
5543 return generic_set_delete(
5544 vty, VTY_GET_CONTEXT(route_map_index),
5545 "ipv6 vpn next-hop", argv[idx_ip]->arg);
5546 }
5547 return CMD_SUCCESS;
d6902373
PG
5548}
5549#endif /* KEEP_OLD_VPN_COMMANDS */
5550
5551DEFUN (set_ipx_vpn_nexthop,
5552 set_ipx_vpn_nexthop_cmd,
0d702986 5553 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
d6902373
PG
5554 SET_STR
5555 "IPv4 information\n"
5556 "IPv6 information\n"
5557 "VPN information\n"
5558 "VPN next-hop address\n"
5559 "IP address of next hop\n"
5560 "IPv6 address of next hop\n")
5561{
d62a17ae 5562 int idx_ip = 4;
5563 afi_t afi;
5564 int idx = 0;
5565
5566 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
5567 if (afi == AFI_IP)
5568 return generic_set_add(
5569 vty, VTY_GET_CONTEXT(route_map_index),
5570 "ipv4 vpn next-hop", argv[idx_ip]->arg);
5571 else
5572 return generic_set_add(
5573 vty, VTY_GET_CONTEXT(route_map_index),
5574 "ipv6 vpn next-hop", argv[idx_ip]->arg);
5575 }
5576 return CMD_SUCCESS;
718e3744 5577}
5578
d6902373
PG
5579DEFUN (no_set_ipx_vpn_nexthop,
5580 no_set_ipx_vpn_nexthop_cmd,
9fa4d336 5581 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
d6902373
PG
5582 NO_STR
5583 SET_STR
5584 "IPv4 information\n"
5585 "IPv6 information\n"
5586 "VPN information\n"
5587 "VPN next-hop address\n"
5588 "IP address of next hop\n"
5589 "IPv6 address of next hop\n")
5590{
d62a17ae 5591 int idx_ip = 5;
5592 char *arg;
5593 afi_t afi;
5594 int idx = 0;
5595
5596 if (argc <= idx_ip)
5597 arg = NULL;
5598 else
5599 arg = argv[idx_ip]->arg;
5600 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
5601 if (afi == AFI_IP)
5602 return generic_set_delete(
5603 vty, VTY_GET_CONTEXT(route_map_index),
5604 "ipv4 vpn next-hop", arg);
5605 else
5606 return generic_set_delete(
5607 vty, VTY_GET_CONTEXT(route_map_index),
5608 "ipv6 vpn next-hop", arg);
5609 }
5610 return CMD_SUCCESS;
d6902373 5611}
718e3744 5612
5613DEFUN (set_originator_id,
5614 set_originator_id_cmd,
5615 "set originator-id A.B.C.D",
5616 SET_STR
5617 "BGP originator ID attribute\n"
5618 "IP address of originator\n")
5619{
d62a17ae 5620 int idx_ipv4 = 2;
5621 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5622 "originator-id", argv[idx_ipv4]->arg);
718e3744 5623}
5624
4c9bd275 5625
718e3744 5626DEFUN (no_set_originator_id,
5627 no_set_originator_id_cmd,
4c9bd275 5628 "no set originator-id [A.B.C.D]",
718e3744 5629 NO_STR
5630 SET_STR
4c9bd275
DW
5631 "BGP originator ID attribute\n"
5632 "IP address of originator\n")
718e3744 5633{
d62a17ae 5634 int idx = 0;
5635 char *arg =
5636 argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
0d702986 5637
d62a17ae 5638 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5639 "originator-id", arg);
718e3744 5640}
5641
718e3744 5642
718e3744 5643/* Initialization of route map. */
d62a17ae 5644void bgp_route_map_init(void)
5645{
5646 route_map_init();
5647
5648 route_map_add_hook(bgp_route_map_add);
5649 route_map_delete_hook(bgp_route_map_delete);
5650 route_map_event_hook(bgp_route_map_event);
5651
5652 route_map_match_interface_hook(generic_match_add);
5653 route_map_no_match_interface_hook(generic_match_delete);
5654
5655 route_map_match_ip_address_hook(generic_match_add);
5656 route_map_no_match_ip_address_hook(generic_match_delete);
5657
5658 route_map_match_ip_address_prefix_list_hook(generic_match_add);
5659 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
5660
5661 route_map_match_ip_next_hop_hook(generic_match_add);
5662 route_map_no_match_ip_next_hop_hook(generic_match_delete);
5663
5664 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
5665 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
5666
61ad901e
DA
5667 route_map_match_ip_next_hop_type_hook(generic_match_add);
5668 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
5669
d62a17ae 5670 route_map_match_ipv6_address_hook(generic_match_add);
5671 route_map_no_match_ipv6_address_hook(generic_match_delete);
5672
5673 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
5674 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
5675
61ad901e
DA
5676 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
5677 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
5678
d62a17ae 5679 route_map_match_metric_hook(generic_match_add);
5680 route_map_no_match_metric_hook(generic_match_delete);
5681
5682 route_map_match_tag_hook(generic_match_add);
5683 route_map_no_match_tag_hook(generic_match_delete);
5684
5685 route_map_set_ip_nexthop_hook(generic_set_add);
5686 route_map_no_set_ip_nexthop_hook(generic_set_delete);
5687
5688 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
5689 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
5690
5691 route_map_set_metric_hook(generic_set_add);
5692 route_map_no_set_metric_hook(generic_set_delete);
5693
5694 route_map_set_tag_hook(generic_set_add);
5695 route_map_no_set_tag_hook(generic_set_delete);
5696
5697 route_map_install_match(&route_match_peer_cmd);
5698 route_map_install_match(&route_match_local_pref_cmd);
1d7c7ace
DS
5699#if defined(HAVE_LUA)
5700 route_map_install_match(&route_match_command_cmd);
5701#endif
d62a17ae 5702 route_map_install_match(&route_match_ip_address_cmd);
5703 route_map_install_match(&route_match_ip_next_hop_cmd);
5704 route_map_install_match(&route_match_ip_route_source_cmd);
5705 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
5706 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
61ad901e 5707 route_map_install_match(&route_match_ip_next_hop_type_cmd);
d62a17ae 5708 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
5709 route_map_install_match(&route_match_aspath_cmd);
5710 route_map_install_match(&route_match_community_cmd);
5711 route_map_install_match(&route_match_lcommunity_cmd);
5712 route_map_install_match(&route_match_ecommunity_cmd);
5713 route_map_install_match(&route_match_local_pref_cmd);
5714 route_map_install_match(&route_match_metric_cmd);
5715 route_map_install_match(&route_match_origin_cmd);
5716 route_map_install_match(&route_match_probability_cmd);
5717 route_map_install_match(&route_match_interface_cmd);
5718 route_map_install_match(&route_match_tag_cmd);
d37ba549 5719 route_map_install_match(&route_match_mac_address_cmd);
16f7ce2b 5720 route_map_install_match(&route_match_evpn_vni_cmd);
33c2ff62 5721 route_map_install_match(&route_match_evpn_route_type_cmd);
196c6b09 5722 route_map_install_match(&route_match_evpn_rd_cmd);
6fb219da 5723 route_map_install_match(&route_match_evpn_default_route_cmd);
1dcc9e5b 5724 route_map_install_match(&route_match_vrl_source_vrf_cmd);
d62a17ae 5725
951745bd 5726 route_map_install_set(&route_set_table_id_cmd);
d62a17ae 5727 route_map_install_set(&route_set_ip_nexthop_cmd);
5728 route_map_install_set(&route_set_local_pref_cmd);
5729 route_map_install_set(&route_set_weight_cmd);
5730 route_map_install_set(&route_set_label_index_cmd);
5731 route_map_install_set(&route_set_metric_cmd);
7b7d48e5 5732 route_map_install_set(&route_set_distance_cmd);
d62a17ae 5733 route_map_install_set(&route_set_aspath_prepend_cmd);
5734 route_map_install_set(&route_set_aspath_exclude_cmd);
5735 route_map_install_set(&route_set_origin_cmd);
5736 route_map_install_set(&route_set_atomic_aggregate_cmd);
5737 route_map_install_set(&route_set_aggregator_as_cmd);
5738 route_map_install_set(&route_set_community_cmd);
5739 route_map_install_set(&route_set_community_delete_cmd);
5740 route_map_install_set(&route_set_lcommunity_cmd);
5741 route_map_install_set(&route_set_lcommunity_delete_cmd);
5742 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
5743 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
5744 route_map_install_set(&route_set_originator_id_cmd);
5745 route_map_install_set(&route_set_ecommunity_rt_cmd);
5746 route_map_install_set(&route_set_ecommunity_soo_cmd);
ca9ac3ef 5747 route_map_install_set(&route_set_ecommunity_lb_cmd);
d62a17ae 5748 route_map_install_set(&route_set_tag_cmd);
5749 route_map_install_set(&route_set_label_index_cmd);
5750
5751 install_element(RMAP_NODE, &match_peer_cmd);
5752 install_element(RMAP_NODE, &match_peer_local_cmd);
5753 install_element(RMAP_NODE, &no_match_peer_cmd);
5754 install_element(RMAP_NODE, &match_ip_route_source_cmd);
5755 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
5756 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
5757 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
d37ba549
MK
5758 install_element(RMAP_NODE, &match_mac_address_cmd);
5759 install_element(RMAP_NODE, &no_match_mac_address_cmd);
16f7ce2b
MK
5760 install_element(RMAP_NODE, &match_evpn_vni_cmd);
5761 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
33c2ff62
MK
5762 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
5763 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
196c6b09
LK
5764 install_element(RMAP_NODE, &match_evpn_rd_cmd);
5765 install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
6fb219da
MK
5766 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
5767 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
1dcc9e5b
CS
5768 install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
5769 install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
d62a17ae 5770
5771 install_element(RMAP_NODE, &match_aspath_cmd);
5772 install_element(RMAP_NODE, &no_match_aspath_cmd);
5773 install_element(RMAP_NODE, &match_local_pref_cmd);
5774 install_element(RMAP_NODE, &no_match_local_pref_cmd);
5775 install_element(RMAP_NODE, &match_community_cmd);
5776 install_element(RMAP_NODE, &no_match_community_cmd);
5777 install_element(RMAP_NODE, &match_lcommunity_cmd);
5778 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
5779 install_element(RMAP_NODE, &match_ecommunity_cmd);
5780 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
5781 install_element(RMAP_NODE, &match_origin_cmd);
5782 install_element(RMAP_NODE, &no_match_origin_cmd);
5783 install_element(RMAP_NODE, &match_probability_cmd);
5784 install_element(RMAP_NODE, &no_match_probability_cmd);
5785
951745bd
PG
5786 install_element(RMAP_NODE, &no_set_table_id_cmd);
5787 install_element(RMAP_NODE, &set_table_id_cmd);
d62a17ae 5788 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
5789 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
5790 install_element(RMAP_NODE, &set_local_pref_cmd);
7b7d48e5
DS
5791 install_element(RMAP_NODE, &set_distance_cmd);
5792 install_element(RMAP_NODE, &no_set_distance_cmd);
d62a17ae 5793 install_element(RMAP_NODE, &no_set_local_pref_cmd);
5794 install_element(RMAP_NODE, &set_weight_cmd);
5795 install_element(RMAP_NODE, &set_label_index_cmd);
5796 install_element(RMAP_NODE, &no_set_weight_cmd);
5797 install_element(RMAP_NODE, &no_set_label_index_cmd);
5798 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
5799 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
5800 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
5801 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
9131e6e8 5802 install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
d62a17ae 5803 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
499ceb3d 5804 install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
d62a17ae 5805 install_element(RMAP_NODE, &set_origin_cmd);
5806 install_element(RMAP_NODE, &no_set_origin_cmd);
5807 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
5808 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
5809 install_element(RMAP_NODE, &set_aggregator_as_cmd);
5810 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
5811 install_element(RMAP_NODE, &set_community_cmd);
5812 install_element(RMAP_NODE, &set_community_none_cmd);
5813 install_element(RMAP_NODE, &no_set_community_cmd);
2929de9e 5814 install_element(RMAP_NODE, &no_set_community_short_cmd);
d62a17ae 5815 install_element(RMAP_NODE, &set_community_delete_cmd);
5816 install_element(RMAP_NODE, &no_set_community_delete_cmd);
5817 install_element(RMAP_NODE, &set_lcommunity_cmd);
5818 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
5819 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
5820 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
76a20aa9 5821 install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
d62a17ae 5822 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
5823 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
76a20aa9 5824 install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
d62a17ae 5825 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
5826 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4db5ee8e 5827 install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
d62a17ae 5828 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
5829 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
4db5ee8e 5830 install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
ca9ac3ef 5831 install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
5832 install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
5833 install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
d6902373 5834#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 5835 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
5836 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
d6902373 5837#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 5838 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
5839 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
5840 install_element(RMAP_NODE, &set_originator_id_cmd);
5841 install_element(RMAP_NODE, &no_set_originator_id_cmd);
5842
5843 route_map_install_match(&route_match_ipv6_address_cmd);
5844 route_map_install_match(&route_match_ipv6_next_hop_cmd);
be7735b3 5845 route_map_install_match(&route_match_ipv4_next_hop_cmd);
d62a17ae 5846 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
61ad901e 5847 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
d62a17ae 5848 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
5849 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
5850 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
5851 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
5852
5853 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
5854 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
be7735b3 5855 install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
17ac51eb 5856 install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
d62a17ae 5857 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
5858 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
5859 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
5860 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
5861 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
5862 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
1d7c7ace
DS
5863#if defined(HAVE_LUA)
5864 install_element(RMAP_NODE, &match_command_cmd);
5865 install_element(RMAP_NODE, &no_match_command_cmd);
5866#endif
d62a17ae 5867}
5868
5869void bgp_route_map_terminate(void)
5870{
5871 /* ToDo: Cleanup all the used memory */
d62a17ae 5872 route_map_finish();
518f0eb1 5873}