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