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