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