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