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