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