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