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