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