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