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