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