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