]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
lib, zebra: Add LIB_ERR_INTERFACE
[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;
3089 struct listnode *node;
3090 struct bgp_redist *red;
3091
3092 red_list = bgp->redist[afi][i];
3093 if (!red_list)
3094 continue;
3095
3096 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
3097 if (red->rmap.name
3098 && (strcmp(rmap_name, red->rmap.name)
3099 == 0)) {
3100 red->rmap.map = map;
3101
3102 if (route_update) {
3103 if (BGP_DEBUG(zebra, ZEBRA))
3104 zlog_debug(
3105 "Processing route_map %s update on "
3106 "redistributed routes",
3107 rmap_name);
3108
3109 bgp_redistribute_resend(
3110 bgp, afi, i,
3111 red->instance);
3112 }
3113 }
3114 }
3115 }
53c84f78
MK
3116
3117 /* for type5 command route-maps */
3118 FOREACH_AFI_SAFI (afi, safi) {
996c9314
LB
3119 if (bgp->adv_cmd_rmap[afi][safi].name
3120 && strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
3121 == 0) {
53c84f78
MK
3122 if (BGP_DEBUG(zebra, ZEBRA))
3123 zlog_debug(
996c9314
LB
3124 "Processing route_map %s update on advertise type5 route command",
3125 rmap_name);
53c84f78
MK
3126 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
3127 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
3128 }
3129 }
d62a17ae 3130}
3131
46a69f10 3132static void bgp_route_map_process_update_cb(char *rmap_name)
d62a17ae 3133{
3134 struct listnode *node, *nnode;
3135 struct bgp *bgp;
3136
ddb5b488 3137 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
d62a17ae 3138 bgp_route_map_process_update(bgp, rmap_name, 1);
5fe9f963 3139
65efcfce 3140#if ENABLE_BGP_VNC
ddb5b488
PZ
3141 /* zlog_debug("%s: calling vnc_routemap_update", __func__); */
3142 vnc_routemap_update(bgp, __func__);
65efcfce 3143#endif
ddb5b488
PZ
3144 }
3145
3146 vpn_policy_routemap_event(rmap_name);
518f0eb1
DS
3147}
3148
d62a17ae 3149int bgp_route_map_update_timer(struct thread *thread)
518f0eb1 3150{
d62a17ae 3151 bm->t_rmap_update = NULL;
518f0eb1 3152
d62a17ae 3153 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1 3154
d62a17ae 3155 return (0);
518f0eb1
DS
3156}
3157
d62a17ae 3158static void bgp_route_map_mark_update(const char *rmap_name)
518f0eb1 3159{
d62a17ae 3160 if (bm->t_rmap_update == NULL) {
3161 struct listnode *node, *nnode;
3162 struct bgp *bgp;
3f9c7369 3163
d62a17ae 3164 /* rmap_update_timer of 0 means don't do route updates */
3165 if (bm->rmap_update_timer) {
3166 bm->t_rmap_update = NULL;
3167 thread_add_timer(bm->master, bgp_route_map_update_timer,
3168 NULL, bm->rmap_update_timer,
3169 &bm->t_rmap_update);
5fe9f963 3170
d62a17ae 3171 /* Signal the groups that a route-map update event has
3172 * started */
3173 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3174 update_group_policy_update(bgp,
3175 BGP_POLICY_ROUTE_MAP,
3176 rmap_name, 1, 1);
3177 } else {
3178 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3179 bgp_route_map_process_update(bgp, rmap_name, 0);
3180#if ENABLE_BGP_VNC
3181 zlog_debug("%s: calling vnc_routemap_update", __func__);
3182 vnc_routemap_update(bgp, __func__);
65efcfce 3183#endif
d62a17ae 3184 }
3185 }
718e3744 3186}
6b0655a2 3187
d62a17ae 3188static void bgp_route_map_add(const char *rmap_name)
73ac8160 3189{
7096e938 3190 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3191 bgp_route_map_mark_update(rmap_name);
73ac8160 3192
d62a17ae 3193 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 3194}
518f0eb1 3195
d62a17ae 3196static void bgp_route_map_delete(const char *rmap_name)
73ac8160 3197{
7096e938 3198 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3199 bgp_route_map_mark_update(rmap_name);
73ac8160 3200
d62a17ae 3201 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 3202}
518f0eb1 3203
d62a17ae 3204static void bgp_route_map_event(route_map_event_t event, const char *rmap_name)
73ac8160 3205{
7096e938 3206 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3207 bgp_route_map_mark_update(rmap_name);
518f0eb1 3208
d62a17ae 3209 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
3210}
3211
d37ba549
MK
3212DEFUN (match_mac_address,
3213 match_mac_address_cmd,
3214 "match mac address WORD",
3215 MATCH_STR
3216 "mac address\n"
3217 "Match address of route\n"
3218 "MAC Access-list name\n")
3219{
3220 return bgp_route_match_add(vty, "mac address", argv[3]->arg,
3221 RMAP_EVENT_FILTER_ADDED);
3222}
3223
3224DEFUN (no_match_mac_address,
3225 no_match_mac_address_cmd,
646050e5 3226 "no match mac address WORD",
d37ba549
MK
3227 NO_STR
3228 MATCH_STR
3229 "mac\n"
646050e5
MK
3230 "Match address of route\n"
3231 "MAC acess-list name\n")
d37ba549 3232{
d37ba549
MK
3233 return bgp_route_match_delete(vty, "mac address", argv[4]->arg,
3234 RMAP_EVENT_FILTER_DELETED);
3235}
73ac8160 3236
33c2ff62
MK
3237DEFUN (match_evpn_route_type,
3238 match_evpn_route_type_cmd,
d4ef18b6 3239 "match evpn route-type <macip | multicast | prefix>",
33c2ff62
MK
3240 MATCH_STR
3241 EVPN_HELP_STR
3242 "Match route-type\n"
3243 "mac-ip route\n"
3244 "IMET route\n"
3245 "prefix route\n")
3246{
3247 return bgp_route_match_add(vty, "evpn route-type", argv[3]->arg,
3248 RMAP_EVENT_MATCH_ADDED);
3249}
3250
3251DEFUN (no_match_evpn_route_type,
3252 no_match_evpn_route_type_cmd,
d4ef18b6 3253 "no match evpn route-type <macip | multicast | prefix>",
33c2ff62
MK
3254 NO_STR
3255 MATCH_STR
3256 EVPN_HELP_STR
3257 "Match route-type\n"
3258 "mac-ip route\n"
3259 "IMET route\n"
3260 "prefix route\n")
3261{
3262 return bgp_route_match_delete(vty, "evpn route-type", argv[4]->arg,
3263 RMAP_EVENT_MATCH_DELETED);
3264}
3265
3266
16f7ce2b
MK
3267DEFUN (match_evpn_vni,
3268 match_evpn_vni_cmd,
3269 "match evpn vni (1-16777215)",
3270 MATCH_STR
62982d5a 3271 EVPN_HELP_STR
16f7ce2b
MK
3272 "Match VNI\n"
3273 "VNI ID\n")
3274{
646050e5 3275 return bgp_route_match_add(vty, "evpn vni", argv[3]->arg,
16f7ce2b
MK
3276 RMAP_EVENT_MATCH_ADDED);
3277}
3278
3279DEFUN (no_match_evpn_vni,
3280 no_match_evpn_vni_cmd,
3281 "no match evpn vni (1-16777215)",
3282 NO_STR
3283 MATCH_STR
62982d5a 3284 EVPN_HELP_STR
16f7ce2b
MK
3285 "Match VNI\n"
3286 "VNI ID\n")
3287{
646050e5 3288 return bgp_route_match_delete(vty, "evpn vni", argv[4]->arg,
16f7ce2b
MK
3289 RMAP_EVENT_MATCH_DELETED);
3290}
3291
6fb219da
MK
3292DEFUN (match_evpn_default_route,
3293 match_evpn_default_route_cmd,
3294 "match evpn default-route",
3295 MATCH_STR
3296 EVPN_HELP_STR
3297 "default EVPN type-5 route\n")
3298{
3299 return bgp_route_match_add(vty, "evpn default-route", NULL,
3300 RMAP_EVENT_MATCH_ADDED);
3301}
3302
3303DEFUN (no_match_evpn_default_route,
3304 no_match_evpn_default_route_cmd,
3305 "no match evpn default-route",
3306 NO_STR
3307 MATCH_STR
3308 EVPN_HELP_STR
3309 "default EVPN type-5 route\n")
3310{
3311 return bgp_route_match_delete(vty, "evpn default-route", NULL,
3312 RMAP_EVENT_MATCH_DELETED);
3313}
3314
fee0f4c6 3315DEFUN (match_peer,
3316 match_peer_cmd,
8c3433e4 3317 "match peer <A.B.C.D|X:X::X:X|WORD>",
fee0f4c6 3318 MATCH_STR
3319 "Match peer address\n"
6e13ed4a 3320 "IP address of peer\n"
8c3433e4
DS
3321 "IPv6 address of peer\n"
3322 "Interface name of peer\n")
fee0f4c6 3323{
d62a17ae 3324 int idx_ip = 2;
3325 return bgp_route_match_add(vty, "peer", argv[idx_ip]->arg,
3326 RMAP_EVENT_MATCH_ADDED);
fee0f4c6 3327}
3328
3329DEFUN (match_peer_local,
f412b39a 3330 match_peer_local_cmd,
fee0f4c6 3331 "match peer local",
3332 MATCH_STR
3333 "Match peer address\n"
3334 "Static or Redistributed routes\n")
3335{
d62a17ae 3336 return bgp_route_match_add(vty, "peer", "local",
3337 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3338}
3339
3340DEFUN (no_match_peer,
3341 no_match_peer_cmd,
8c3433e4 3342 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
fee0f4c6 3343 NO_STR
3344 MATCH_STR
4c9bd275
DW
3345 "Match peer address\n"
3346 "Static or Redistributed routes\n"
3347 "IP address of peer\n"
8c3433e4
DS
3348 "IPv6 address of peer\n"
3349 "Interface name of peer\n")
fee0f4c6 3350{
d62a17ae 3351 int idx_peer = 3;
4c9bd275 3352
d62a17ae 3353 if (argc <= idx_peer)
3354 return bgp_route_match_delete(vty, "peer", NULL,
3355 RMAP_EVENT_MATCH_DELETED);
3356 return bgp_route_match_delete(vty, "peer", argv[idx_peer]->arg,
3357 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3358}
3359
fee0f4c6 3360
4c9bd275 3361/* match probability */
1add115a
VT
3362DEFUN (match_probability,
3363 match_probability_cmd,
6147e2c6 3364 "match probability (0-100)",
1add115a
VT
3365 MATCH_STR
3366 "Match portion of routes defined by percentage value\n"
3367 "Percentage of routes\n")
3368{
d62a17ae 3369 int idx_number = 2;
3370 return bgp_route_match_add(vty, "probability", argv[idx_number]->arg,
3371 RMAP_EVENT_MATCH_ADDED);
1add115a
VT
3372}
3373
4c9bd275 3374
1add115a
VT
3375DEFUN (no_match_probability,
3376 no_match_probability_cmd,
4c9bd275 3377 "no match probability [(1-99)]",
1add115a
VT
3378 NO_STR
3379 MATCH_STR
4c9bd275
DW
3380 "Match portion of routes defined by percentage value\n"
3381 "Percentage of routes\n")
1add115a 3382{
d62a17ae 3383 int idx_number = 3;
3384 if (argc <= idx_number)
3385 return bgp_route_match_delete(vty, "probability", NULL,
3386 RMAP_EVENT_MATCH_DELETED);
3387 return bgp_route_match_delete(vty, "probability", argv[idx_number]->arg,
3388 RMAP_EVENT_MATCH_DELETED);
1add115a
VT
3389}
3390
1add115a 3391
f412b39a 3392DEFUN (match_ip_route_source,
c1643bb7 3393 match_ip_route_source_cmd,
6147e2c6 3394 "match ip route-source <(1-199)|(1300-2699)|WORD>",
c1643bb7 3395 MATCH_STR
3396 IP_STR
3397 "Match advertising source address of route\n"
3398 "IP access-list number\n"
3399 "IP access-list number (expanded range)\n"
3400 "IP standard access-list name\n")
3401{
d62a17ae 3402 int idx_acl = 3;
3403 return bgp_route_match_add(vty, "ip route-source", argv[idx_acl]->arg,
3404 RMAP_EVENT_FILTER_ADDED);
c1643bb7 3405}
3406
4c9bd275 3407
c1643bb7 3408DEFUN (no_match_ip_route_source,
3409 no_match_ip_route_source_cmd,
6de69f83 3410 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
c1643bb7 3411 NO_STR
3412 MATCH_STR
3413 IP_STR
4c9bd275
DW
3414 "Match advertising source address of route\n"
3415 "IP access-list number\n"
3416 "IP access-list number (expanded range)\n"
3417 "IP standard access-list name\n")
c1643bb7 3418{
d62a17ae 3419 int idx_number = 4;
3420 if (argc <= idx_number)
3421 return bgp_route_match_delete(vty, "ip route-source", NULL,
3422 RMAP_EVENT_FILTER_DELETED);
3423 return bgp_route_match_delete(vty, "ip route-source",
3424 argv[idx_number]->arg,
3425 RMAP_EVENT_FILTER_DELETED);
c1643bb7 3426}
3427
c1643bb7 3428
f412b39a 3429DEFUN (match_ip_route_source_prefix_list,
c1643bb7 3430 match_ip_route_source_prefix_list_cmd,
3431 "match ip route-source prefix-list WORD",
3432 MATCH_STR
3433 IP_STR
3434 "Match advertising source address of route\n"
3435 "Match entries of prefix-lists\n"
3436 "IP prefix-list name\n")
3437{
d62a17ae 3438 int idx_word = 4;
3439 return bgp_route_match_add(vty, "ip route-source prefix-list",
3440 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
c1643bb7 3441}
3442
4c9bd275 3443
c1643bb7 3444DEFUN (no_match_ip_route_source_prefix_list,
3445 no_match_ip_route_source_prefix_list_cmd,
4c9bd275 3446 "no match ip route-source prefix-list [WORD]",
c1643bb7 3447 NO_STR
3448 MATCH_STR
3449 IP_STR
3450 "Match advertising source address of route\n"
4c9bd275
DW
3451 "Match entries of prefix-lists\n"
3452 "IP prefix-list name\n")
c1643bb7 3453{
d62a17ae 3454 int idx_word = 5;
3455 if (argc <= idx_word)
3456 return bgp_route_match_delete(vty,
3457 "ip route-source prefix-list",
3458 NULL, RMAP_EVENT_PLIST_DELETED);
3459 return bgp_route_match_delete(vty, "ip route-source prefix-list",
3460 argv[idx_word]->arg,
3461 RMAP_EVENT_PLIST_DELETED);
c1643bb7 3462}
3463
c1643bb7 3464
af291c15
DS
3465DEFUN (match_local_pref,
3466 match_local_pref_cmd,
6147e2c6 3467 "match local-preference (0-4294967295)",
af291c15
DS
3468 MATCH_STR
3469 "Match local-preference of route\n"
3470 "Metric value\n")
3471{
d62a17ae 3472 int idx_number = 2;
3473 return bgp_route_match_add(vty, "local-preference",
3474 argv[idx_number]->arg,
3475 RMAP_EVENT_MATCH_ADDED);
af291c15
DS
3476}
3477
4c9bd275 3478
af291c15
DS
3479DEFUN (no_match_local_pref,
3480 no_match_local_pref_cmd,
4c9bd275 3481 "no match local-preference [(0-4294967295)]",
af291c15
DS
3482 NO_STR
3483 MATCH_STR
4c9bd275
DW
3484 "Match local preference of route\n"
3485 "Local preference value\n")
af291c15 3486{
d62a17ae 3487 int idx_localpref = 3;
3488 if (argc <= idx_localpref)
3489 return bgp_route_match_delete(vty, "local-preference", NULL,
3490 RMAP_EVENT_MATCH_DELETED);
3491 return bgp_route_match_delete(vty, "local-preference",
3492 argv[idx_localpref]->arg,
3493 RMAP_EVENT_MATCH_DELETED);
af291c15
DS
3494}
3495
af291c15 3496
f412b39a 3497DEFUN (match_community,
718e3744 3498 match_community_cmd,
0d702986 3499 "match community <(1-99)|(100-500)|WORD> [exact-match]",
718e3744 3500 MATCH_STR
3501 "Match BGP community list\n"
3502 "Community-list number (standard)\n"
3503 "Community-list number (expanded)\n"
3504 "Community-list name\n"
3505 "Do exact matching of communities\n")
3506{
d62a17ae 3507 int idx_comm_list = 2;
3508 int ret;
3509 char *argstr;
718e3744 3510
d62a17ae 3511 if (argc == 4) {
3512 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
3513 strlen(argv[idx_comm_list]->arg)
3514 + strlen("exact-match") + 2);
718e3744 3515
d62a17ae 3516 sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
3517 } else
3518 argstr = argv[idx_comm_list]->arg;
718e3744 3519
d62a17ae 3520 ret = bgp_route_match_add(vty, "community", argstr,
3521 RMAP_EVENT_CLIST_ADDED);
718e3744 3522
d62a17ae 3523 if (argstr != argv[idx_comm_list]->arg)
3524 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 3525
d62a17ae 3526 return ret;
718e3744 3527}
3528
3529DEFUN (no_match_community,
3530 no_match_community_cmd,
4c9bd275 3531 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
718e3744 3532 NO_STR
3533 MATCH_STR
4c9bd275
DW
3534 "Match BGP community list\n"
3535 "Community-list number (standard)\n"
3536 "Community-list number (expanded)\n"
3537 "Community-list name\n"
3538 "Do exact matching of communities\n")
718e3744 3539{
d62a17ae 3540 return bgp_route_match_delete(vty, "community", NULL,
3541 RMAP_EVENT_CLIST_DELETED);
718e3744 3542}
3543
57d187bc
JS
3544DEFUN (match_lcommunity,
3545 match_lcommunity_cmd,
0d702986 3546 "match large-community <(1-99)|(100-500)|WORD>",
57d187bc
JS
3547 MATCH_STR
3548 "Match BGP large community list\n"
3549 "Large Community-list number (standard)\n"
3550 "Large Community-list number (expanded)\n"
3551 "Large Community-list name\n")
3552{
d62a17ae 3553 return bgp_route_match_add(vty, "large-community", argv[2]->arg,
3554 RMAP_EVENT_LLIST_ADDED);
57d187bc 3555}
718e3744 3556
57d187bc
JS
3557DEFUN (no_match_lcommunity,
3558 no_match_lcommunity_cmd,
52951b63 3559 "no match large-community [<(1-99)|(100-500)|WORD>]",
57d187bc
JS
3560 NO_STR
3561 MATCH_STR
3562 "Match BGP large community list\n"
3563 "Large Community-list number (standard)\n"
3564 "Large Community-list number (expanded)\n"
3565 "Large Community-list name\n")
3566{
d62a17ae 3567 return bgp_route_match_delete(vty, "large-community", NULL,
3568 RMAP_EVENT_LLIST_DELETED);
57d187bc 3569}
718e3744 3570
f412b39a 3571DEFUN (match_ecommunity,
73ffb25b 3572 match_ecommunity_cmd,
6147e2c6 3573 "match extcommunity <(1-99)|(100-500)|WORD>",
73ffb25b 3574 MATCH_STR
3575 "Match BGP/VPN extended community list\n"
3576 "Extended community-list number (standard)\n"
3577 "Extended community-list number (expanded)\n"
3578 "Extended community-list name\n")
3579{
d62a17ae 3580 int idx_comm_list = 2;
3581 return bgp_route_match_add(vty, "extcommunity",
3582 argv[idx_comm_list]->arg,
3583 RMAP_EVENT_ECLIST_ADDED);
73ffb25b 3584}
3585
4c9bd275 3586
73ffb25b 3587DEFUN (no_match_ecommunity,
3588 no_match_ecommunity_cmd,
4c9bd275 3589 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
73ffb25b 3590 NO_STR
3591 MATCH_STR
4c9bd275
DW
3592 "Match BGP/VPN extended community list\n"
3593 "Extended community-list number (standard)\n"
3594 "Extended community-list number (expanded)\n"
3595 "Extended community-list name\n")
73ffb25b 3596{
d62a17ae 3597 return bgp_route_match_delete(vty, "extcommunity", NULL,
3598 RMAP_EVENT_ECLIST_DELETED);
73ffb25b 3599}
3600
73ffb25b 3601
718e3744 3602DEFUN (match_aspath,
3603 match_aspath_cmd,
3604 "match as-path WORD",
3605 MATCH_STR
3606 "Match BGP AS path list\n"
3607 "AS path access-list name\n")
3608{
d62a17ae 3609 int idx_word = 2;
3610 return bgp_route_match_add(vty, "as-path", argv[idx_word]->arg,
3611 RMAP_EVENT_ASLIST_ADDED);
718e3744 3612}
3613
4c9bd275 3614
718e3744 3615DEFUN (no_match_aspath,
3616 no_match_aspath_cmd,
4c9bd275 3617 "no match as-path [WORD]",
718e3744 3618 NO_STR
3619 MATCH_STR
4c9bd275
DW
3620 "Match BGP AS path list\n"
3621 "AS path access-list name\n")
718e3744 3622{
d62a17ae 3623 return bgp_route_match_delete(vty, "as-path", NULL,
3624 RMAP_EVENT_ASLIST_DELETED);
718e3744 3625}
3626
718e3744 3627
3628DEFUN (match_origin,
3629 match_origin_cmd,
6147e2c6 3630 "match origin <egp|igp|incomplete>",
718e3744 3631 MATCH_STR
3632 "BGP origin code\n"
3633 "remote EGP\n"
3634 "local IGP\n"
3635 "unknown heritage\n")
3636{
d62a17ae 3637 int idx_origin = 2;
3638 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
3639 return bgp_route_match_add(vty, "origin", "igp",
3640 RMAP_EVENT_MATCH_ADDED);
3641 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
3642 return bgp_route_match_add(vty, "origin", "egp",
3643 RMAP_EVENT_MATCH_ADDED);
3644 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
3645 return bgp_route_match_add(vty, "origin", "incomplete",
3646 RMAP_EVENT_MATCH_ADDED);
718e3744 3647
d62a17ae 3648 vty_out(vty, "%% Invalid match origin type\n");
3649 return CMD_WARNING_CONFIG_FAILED;
718e3744 3650}
3651
4c9bd275 3652
718e3744 3653DEFUN (no_match_origin,
3654 no_match_origin_cmd,
4c9bd275 3655 "no match origin [<egp|igp|incomplete>]",
718e3744 3656 NO_STR
3657 MATCH_STR
4c9bd275
DW
3658 "BGP origin code\n"
3659 "remote EGP\n"
3660 "local IGP\n"
3661 "unknown heritage\n")
718e3744 3662{
d62a17ae 3663 return bgp_route_match_delete(vty, "origin", NULL,
3664 RMAP_EVENT_MATCH_DELETED);
718e3744 3665}
3666
af5cd0a5 3667DEFUN (set_ip_nexthop_peer,
3668 set_ip_nexthop_peer_cmd,
89602edb
QY
3669 "[no] set ip next-hop peer-address",
3670 NO_STR
af5cd0a5 3671 SET_STR
3672 IP_STR
3673 "Next hop address\n"
3674 "Use peer address (for BGP only)\n")
3675{
89602edb 3676 int (*func)(struct vty *, struct route_map_index *, const char *,
a4d82a8a
PZ
3677 const char *) = strmatch(argv[0]->text, "no")
3678 ? generic_set_delete
3679 : generic_set_add;
89602edb
QY
3680
3681 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
3682 "peer-address");
af5cd0a5 3683}
3684
316e074d
DS
3685DEFUN (set_ip_nexthop_unchanged,
3686 set_ip_nexthop_unchanged_cmd,
cca30ba8
QY
3687 "[no] set ip next-hop unchanged",
3688 NO_STR
316e074d
DS
3689 SET_STR
3690 IP_STR
3691 "Next hop address\n"
3692 "Don't modify existing Next hop address\n")
3693{
cca30ba8 3694 int (*func)(struct vty *, struct route_map_index *, const char *,
a4d82a8a
PZ
3695 const char *) = strmatch(argv[0]->text, "no")
3696 ? generic_set_delete
3697 : generic_set_add;
cca30ba8
QY
3698
3699 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
3700 "unchanged");
718e3744 3701}
3702
718e3744 3703
3704DEFUN (set_local_pref,
3705 set_local_pref_cmd,
6147e2c6 3706 "set local-preference (0-4294967295)",
718e3744 3707 SET_STR
3708 "BGP local preference path attribute\n"
3709 "Preference value\n")
3710{
d62a17ae 3711 int idx_number = 2;
3712 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3713 "local-preference", argv[idx_number]->arg);
718e3744 3714}
3715
4c9bd275 3716
718e3744 3717DEFUN (no_set_local_pref,
3718 no_set_local_pref_cmd,
4c9bd275 3719 "no set local-preference [(0-4294967295)]",
718e3744 3720 NO_STR
3721 SET_STR
4c9bd275
DW
3722 "BGP local preference path attribute\n"
3723 "Preference value\n")
718e3744 3724{
d62a17ae 3725 int idx_localpref = 3;
3726 if (argc <= idx_localpref)
3727 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3728 "local-preference", NULL);
3729 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3730 "local-preference", argv[idx_localpref]->arg);
718e3744 3731}
3732
718e3744 3733
3734DEFUN (set_weight,
3735 set_weight_cmd,
6147e2c6 3736 "set weight (0-4294967295)",
718e3744 3737 SET_STR
3738 "BGP weight for routing table\n"
3739 "Weight value\n")
3740{
d62a17ae 3741 int idx_number = 2;
3742 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "weight",
3743 argv[idx_number]->arg);
718e3744 3744}
3745
4c9bd275 3746
718e3744 3747DEFUN (no_set_weight,
3748 no_set_weight_cmd,
4c9bd275 3749 "no set weight [(0-4294967295)]",
718e3744 3750 NO_STR
3751 SET_STR
4c9bd275
DW
3752 "BGP weight for routing table\n"
3753 "Weight value\n")
718e3744 3754{
d62a17ae 3755 int idx_weight = 3;
3756 if (argc <= idx_weight)
3757 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3758 "weight", NULL);
3759 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3760 "weight", argv[idx_weight]->arg);
718e3744 3761}
3762
d990e384
DS
3763DEFUN (set_label_index,
3764 set_label_index_cmd,
8b81993e 3765 "set label-index (0-1048560)",
d990e384
DS
3766 SET_STR
3767 "Label index to associate with the prefix\n"
3768 "Label index value\n")
3769{
d62a17ae 3770 int idx_number = 2;
3771 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3772 "label-index", argv[idx_number]->arg);
d990e384
DS
3773}
3774
3775DEFUN (no_set_label_index,
3776 no_set_label_index_cmd,
8b81993e 3777 "no set label-index [(0-1048560)]",
d990e384
DS
3778 NO_STR
3779 SET_STR
3780 "Label index to associate with the prefix\n"
3781 "Label index value\n")
3782{
d62a17ae 3783 int idx_label_index = 3;
3784 if (argc <= idx_label_index)
3785 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3786 "label-index", NULL);
3787 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3788 "label-index", argv[idx_label_index]->arg);
d990e384 3789}
718e3744 3790
12dcf78e
QY
3791DEFUN (set_aspath_prepend_asn,
3792 set_aspath_prepend_asn_cmd,
3793 "set as-path prepend (1-4294967295)...",
718e3744 3794 SET_STR
841f7a57 3795 "Transform BGP AS_PATH attribute\n"
718e3744 3796 "Prepend to the as-path\n"
12dcf78e 3797 "AS number\n")
718e3744 3798{
d62a17ae 3799 int idx_asn = 3;
3800 int ret;
3801 char *str;
718e3744 3802
d62a17ae 3803 str = argv_concat(argv, argc, idx_asn);
3804 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3805 "as-path prepend", str);
3806 XFREE(MTYPE_TMP, str);
718e3744 3807
d62a17ae 3808 return ret;
718e3744 3809}
3810
12dcf78e
QY
3811DEFUN (set_aspath_prepend_lastas,
3812 set_aspath_prepend_lastas_cmd,
b6ab2929 3813 "set as-path prepend last-as (1-10)",
12dcf78e
QY
3814 SET_STR
3815 "Transform BGP AS_PATH attribute\n"
3816 "Prepend to the as-path\n"
3817 "Use the peer's AS-number\n"
b6ab2929 3818 "Number of times to insert\n")
12dcf78e 3819{
d62a17ae 3820 return set_aspath_prepend_asn(self, vty, argc, argv);
12dcf78e 3821}
bc3dd427 3822
718e3744 3823DEFUN (no_set_aspath_prepend,
3824 no_set_aspath_prepend_cmd,
a4b2b610 3825 "no set as-path prepend [(1-4294967295)]",
718e3744 3826 NO_STR
3827 SET_STR
841f7a57 3828 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
3829 "Prepend to the as-path\n"
3830 "AS number\n")
718e3744 3831{
d62a17ae 3832 int idx_asn = 4;
3833 int ret;
3834 char *str;
a7f93f3e 3835
d62a17ae 3836 str = argv_concat(argv, argc, idx_asn);
3837 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3838 "as-path prepend", str);
3839 XFREE(MTYPE_TMP, str);
3840 return ret;
718e3744 3841}
3842
718e3744 3843
841f7a57
DO
3844DEFUN (set_aspath_exclude,
3845 set_aspath_exclude_cmd,
a4b2b610 3846 "set as-path exclude (1-4294967295)...",
841f7a57
DO
3847 SET_STR
3848 "Transform BGP AS-path attribute\n"
3849 "Exclude from the as-path\n"
3850 "AS number\n")
3851{
d62a17ae 3852 int idx_asn = 3;
3853 int ret;
3854 char *str;
841f7a57 3855
d62a17ae 3856 str = argv_concat(argv, argc, idx_asn);
3857 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3858 "as-path exclude", str);
3859 XFREE(MTYPE_TMP, str);
3860 return ret;
841f7a57
DO
3861}
3862
3863DEFUN (no_set_aspath_exclude,
3864 no_set_aspath_exclude_cmd,
a4b2b610 3865 "no set as-path exclude (1-4294967295)...",
841f7a57
DO
3866 NO_STR
3867 SET_STR
3868 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
3869 "Exclude from the as-path\n"
3870 "AS number\n")
841f7a57 3871{
d62a17ae 3872 int idx_asn = 4;
3873 int ret;
3874 char *str;
841f7a57 3875
d62a17ae 3876 str = argv_concat(argv, argc, idx_asn);
3877 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3878 "as-path exclude", str);
3879 XFREE(MTYPE_TMP, str);
3880 return ret;
841f7a57
DO
3881}
3882
841f7a57 3883
718e3744 3884DEFUN (set_community,
3885 set_community_cmd,
e961923c 3886 "set community AA:NN...",
718e3744 3887 SET_STR
3888 "BGP community attribute\n"
859d388e 3889 COMMUNITY_VAL_STR)
718e3744 3890{
d62a17ae 3891 int idx_aa_nn = 2;
3892 int i;
3893 int first = 0;
3894 int additive = 0;
3895 struct buffer *b;
3896 struct community *com = NULL;
3897 char *str;
3898 char *argstr;
3899 int ret;
3900
3901 b = buffer_new(1024);
3902
3903 for (i = idx_aa_nn; i < argc; i++) {
3904 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
3905 == 0) {
3906 additive = 1;
3907 continue;
3908 }
3909
3910 if (first)
3911 buffer_putc(b, ' ');
3912 else
3913 first = 1;
3914
3915 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
3916 == 0) {
3917 buffer_putstr(b, "internet");
3918 continue;
3919 }
3920 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
3921 == 0) {
3922 buffer_putstr(b, "local-AS");
3923 continue;
3924 }
3925 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
3926 && strncmp(argv[i]->arg, "no-advertise",
3927 strlen(argv[i]->arg))
3928 == 0) {
3929 buffer_putstr(b, "no-advertise");
3930 continue;
3931 }
3932 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
3933 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
3934 == 0) {
3935 buffer_putstr(b, "no-export");
3936 continue;
3937 }
a4d82a8a
PZ
3938 if (strncmp(argv[i]->arg, "graceful-shutdown",
3939 strlen(argv[i]->arg))
7f323236
DW
3940 == 0) {
3941 buffer_putstr(b, "graceful-shutdown");
3942 continue;
3943 }
d62a17ae 3944 buffer_putstr(b, argv[i]->arg);
3945 }
3946 buffer_putc(b, '\0');
3947
3948 /* Fetch result string then compile it to communities attribute. */
3949 str = buffer_getstr(b);
3950 buffer_free(b);
3951
3952 if (str) {
3953 com = community_str2com(str);
3954 XFREE(MTYPE_TMP, str);
3955 }
3956
3957 /* Can't compile user input into communities attribute. */
3958 if (!com) {
3959 vty_out(vty, "%% Malformed communities attribute\n");
3960 return CMD_WARNING_CONFIG_FAILED;
3961 }
3962
3963 /* Set communites attribute string. */
a69ea8ae 3964 str = community_str(com, false);
d62a17ae 3965
3966 if (additive) {
3967 argstr = XCALLOC(MTYPE_TMP,
3968 strlen(str) + strlen(" additive") + 1);
3969 strcpy(argstr, str);
3970 strcpy(argstr + strlen(str), " additive");
3971 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3972 "community", argstr);
3973 XFREE(MTYPE_TMP, argstr);
3974 } else
3975 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3976 "community", str);
3977
3978 community_free(com);
3979
3980 return ret;
718e3744 3981}
3982
3983DEFUN (set_community_none,
3984 set_community_none_cmd,
3985 "set community none",
3986 SET_STR
3987 "BGP community attribute\n"
3988 "No community attribute\n")
3989{
d62a17ae 3990 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3991 "community", "none");
718e3744 3992}
3993
3994DEFUN (no_set_community,
3995 no_set_community_cmd,
a4b2b610 3996 "no set community AA:NN...",
718e3744 3997 NO_STR
3998 SET_STR
d7fa34c1
QY
3999 "BGP community attribute\n"
4000 COMMUNITY_VAL_STR)
718e3744 4001{
d62a17ae 4002 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4003 "community", NULL);
718e3744 4004}
4005
718e3744 4006
718e3744 4007DEFUN (set_community_delete,
4008 set_community_delete_cmd,
6147e2c6 4009 "set comm-list <(1-99)|(100-500)|WORD> delete",
718e3744 4010 SET_STR
4011 "set BGP community list (for deletion)\n"
4012 "Community-list number (standard)\n"
5e3edbf5 4013 "Community-list number (expanded)\n"
718e3744 4014 "Community-list name\n"
4015 "Delete matching communities\n")
4016{
d62a17ae 4017 int idx_comm_list = 2;
4018 char *str;
718e3744 4019
d62a17ae 4020 str = XCALLOC(MTYPE_TMP,
4021 strlen(argv[idx_comm_list]->arg) + strlen(" delete") + 1);
4022 strcpy(str, argv[idx_comm_list]->arg);
4023 strcpy(str + strlen(argv[idx_comm_list]->arg), " delete");
718e3744 4024
d62a17ae 4025 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
4026 str);
718e3744 4027
d62a17ae 4028 XFREE(MTYPE_TMP, str);
4029 return CMD_SUCCESS;
718e3744 4030}
4031
4032DEFUN (no_set_community_delete,
4033 no_set_community_delete_cmd,
a4b2b610 4034 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
718e3744 4035 NO_STR
4036 SET_STR
d7fa34c1
QY
4037 "set BGP community list (for deletion)\n"
4038 "Community-list number (standard)\n"
4039 "Community-list number (expanded)\n"
4040 "Community-list name\n"
4041 "Delete matching communities\n")
718e3744 4042{
d62a17ae 4043 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4044 "comm-list", NULL);
718e3744 4045}
4046
57d187bc
JS
4047DEFUN (set_lcommunity,
4048 set_lcommunity_cmd,
4049 "set large-community AA:BB:CC...",
4050 SET_STR
4051 "BGP large community attribute\n"
4052 "Large Community number in aa:bb:cc format or additive\n")
4053{
d62a17ae 4054 int ret;
4055 char *str;
57d187bc 4056
d62a17ae 4057 str = argv_concat(argv, argc, 2);
4058 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4059 "large-community", str);
4060 XFREE(MTYPE_TMP, str);
57d187bc 4061
d62a17ae 4062 return ret;
57d187bc
JS
4063}
4064
4065DEFUN (set_lcommunity_none,
4066 set_lcommunity_none_cmd,
4067 "set large-community none",
4068 SET_STR
4069 "BGP large community attribute\n"
4070 "No large community attribute\n")
4071{
d62a17ae 4072 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4073 "large-community", "none");
57d187bc
JS
4074}
4075
4076DEFUN (no_set_lcommunity,
4077 no_set_lcommunity_cmd,
52951b63 4078 "no set large-community none",
57d187bc
JS
4079 NO_STR
4080 SET_STR
4081 "BGP large community attribute\n"
52951b63 4082 "No community attribute\n")
57d187bc 4083{
d62a17ae 4084 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4085 "large-community", NULL);
57d187bc
JS
4086}
4087
52951b63
DS
4088DEFUN (no_set_lcommunity1,
4089 no_set_lcommunity1_cmd,
4090 "no set large-community AA:BB:CC...",
4091 NO_STR
4092 SET_STR
4093 "BGP large community attribute\n"
4094 "Large community in AA:BB:CC... format or additive\n")
4095{
d62a17ae 4096 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4097 "large-community", NULL);
52951b63 4098}
57d187bc
JS
4099
4100DEFUN (set_lcommunity_delete,
4101 set_lcommunity_delete_cmd,
4102 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
4103 SET_STR
4104 "set BGP large community list (for deletion)\n"
4105 "Large Community-list number (standard)\n"
4106 "Large Communitly-list number (expanded)\n"
4107 "Large Community-list name\n"
4108 "Delete matching large communities\n")
4109{
d62a17ae 4110 char *str;
57d187bc 4111
d62a17ae 4112 str = XCALLOC(MTYPE_TMP, strlen(argv[2]->arg) + strlen(" delete") + 1);
4113 strcpy(str, argv[2]->arg);
4114 strcpy(str + strlen(argv[2]->arg), " delete");
57d187bc 4115
d62a17ae 4116 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4117 "large-comm-list", str);
57d187bc 4118
d62a17ae 4119 XFREE(MTYPE_TMP, str);
4120 return CMD_SUCCESS;
57d187bc
JS
4121}
4122
4123DEFUN (no_set_lcommunity_delete,
4124 no_set_lcommunity_delete_cmd,
db4f7086 4125 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
57d187bc
JS
4126 NO_STR
4127 SET_STR
4128 "set BGP large community list (for deletion)\n"
4129 "Large Community-list number (standard)\n"
4130 "Large Communitly-list number (expanded)\n"
4131 "Large Community-list name\n"
4132 "Delete matching large communities\n")
4133{
d62a17ae 4134 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4135 "large-comm-list", NULL);
57d187bc 4136}
718e3744 4137
4138DEFUN (set_ecommunity_rt,
4139 set_ecommunity_rt_cmd,
d114b977 4140 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4141 SET_STR
4142 "BGP extended community attribute\n"
e6b6a564 4143 "Route Target extended community\n"
718e3744 4144 "VPN extended community\n")
4145{
d62a17ae 4146 int idx_asn_nn = 3;
4147 int ret;
4148 char *str;
718e3744 4149
d62a17ae 4150 str = argv_concat(argv, argc, idx_asn_nn);
4151 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4152 "extcommunity rt", str);
4153 XFREE(MTYPE_TMP, str);
718e3744 4154
d62a17ae 4155 return ret;
718e3744 4156}
4157
4158DEFUN (no_set_ecommunity_rt,
4159 no_set_ecommunity_rt_cmd,
d114b977 4160 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4161 NO_STR
4162 SET_STR
4163 "BGP extended community attribute\n"
3a2d747c
QY
4164 "Route Target extended community\n"
4165 "VPN extended community\n")
718e3744 4166{
d62a17ae 4167 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4168 "extcommunity rt", NULL);
718e3744 4169}
4170
718e3744 4171
4172DEFUN (set_ecommunity_soo,
4173 set_ecommunity_soo_cmd,
d114b977 4174 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4175 SET_STR
4176 "BGP extended community attribute\n"
4177 "Site-of-Origin extended community\n"
4178 "VPN extended community\n")
4179{
d62a17ae 4180 int idx_asn_nn = 3;
4181 int ret;
4182 char *str;
718e3744 4183
d62a17ae 4184 str = argv_concat(argv, argc, idx_asn_nn);
4185 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4186 "extcommunity soo", str);
4187 XFREE(MTYPE_TMP, str);
4188 return ret;
718e3744 4189}
4190
a4b2b610 4191
718e3744 4192DEFUN (no_set_ecommunity_soo,
4193 no_set_ecommunity_soo_cmd,
d114b977 4194 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4195 NO_STR
4196 SET_STR
4197 "BGP extended community attribute\n"
3a2d747c
QY
4198 "Site-of-Origin extended community\n"
4199 "VPN extended community\n")
718e3744 4200{
d62a17ae 4201 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4202 "extcommunity soo", NULL);
718e3744 4203}
4204
718e3744 4205
4206DEFUN (set_origin,
4207 set_origin_cmd,
6147e2c6 4208 "set origin <egp|igp|incomplete>",
718e3744 4209 SET_STR
4210 "BGP origin code\n"
4211 "remote EGP\n"
4212 "local IGP\n"
4213 "unknown heritage\n")
4214{
d62a17ae 4215 int idx_origin = 2;
4216 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
4217 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4218 "origin", "igp");
4219 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
4220 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4221 "origin", "egp");
4222 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
4223 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4224 "origin", "incomplete");
718e3744 4225
d62a17ae 4226 vty_out(vty, "%% Invalid set origin type\n");
4227 return CMD_WARNING_CONFIG_FAILED;
718e3744 4228}
4229
a4b2b610 4230
718e3744 4231DEFUN (no_set_origin,
4232 no_set_origin_cmd,
a4b2b610 4233 "no set origin [<egp|igp|incomplete>]",
718e3744 4234 NO_STR
4235 SET_STR
d7fa34c1
QY
4236 "BGP origin code\n"
4237 "remote EGP\n"
4238 "local IGP\n"
4239 "unknown heritage\n")
718e3744 4240{
d62a17ae 4241 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4242 "origin", NULL);
718e3744 4243}
4244
718e3744 4245
4246DEFUN (set_atomic_aggregate,
4247 set_atomic_aggregate_cmd,
4248 "set atomic-aggregate",
4249 SET_STR
4250 "BGP atomic aggregate attribute\n" )
4251{
d62a17ae 4252 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4253 "atomic-aggregate", NULL);
718e3744 4254}
4255
4256DEFUN (no_set_atomic_aggregate,
4257 no_set_atomic_aggregate_cmd,
4258 "no set atomic-aggregate",
4259 NO_STR
4260 SET_STR
4261 "BGP atomic aggregate attribute\n" )
4262{
d62a17ae 4263 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4264 "atomic-aggregate", NULL);
718e3744 4265}
4266
4267DEFUN (set_aggregator_as,
4268 set_aggregator_as_cmd,
9ccf14f7 4269 "set aggregator as (1-4294967295) A.B.C.D",
718e3744 4270 SET_STR
4271 "BGP aggregator attribute\n"
4272 "AS number of aggregator\n"
4273 "AS number\n"
4274 "IP address of aggregator\n")
4275{
d62a17ae 4276 int idx_number = 3;
4277 int idx_ipv4 = 4;
4278 int ret;
4279 struct in_addr address;
4280 char *argstr;
e52702f2 4281
d62a17ae 4282 ret = inet_aton(argv[idx_ipv4]->arg, &address);
4283 if (ret == 0) {
4284 vty_out(vty, "Aggregator IP address is invalid\n");
4285 return CMD_WARNING_CONFIG_FAILED;
4286 }
718e3744 4287
d62a17ae 4288 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4289 strlen(argv[idx_number]->arg)
4290 + strlen(argv[idx_ipv4]->arg) + 2);
718e3744 4291
d62a17ae 4292 sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
718e3744 4293
d62a17ae 4294 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4295 "aggregator as", argstr);
718e3744 4296
d62a17ae 4297 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 4298
d62a17ae 4299 return ret;
718e3744 4300}
4301
a4b2b610 4302
718e3744 4303DEFUN (no_set_aggregator_as,
4304 no_set_aggregator_as_cmd,
a4b2b610 4305 "no set aggregator as [(1-4294967295) A.B.C.D]",
718e3744 4306 NO_STR
4307 SET_STR
4308 "BGP aggregator attribute\n"
a4b2b610
DW
4309 "AS number of aggregator\n"
4310 "AS number\n"
4311 "IP address of aggregator\n")
718e3744 4312{
d62a17ae 4313 int idx_asn = 4;
4314 int idx_ip = 5;
4315 int ret;
4316 struct in_addr address;
4317 char *argstr;
718e3744 4318
d62a17ae 4319 if (argc <= idx_asn)
4320 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4321 "aggregator as", NULL);
e52702f2 4322
d62a17ae 4323 ret = inet_aton(argv[idx_ip]->arg, &address);
4324 if (ret == 0) {
4325 vty_out(vty, "Aggregator IP address is invalid\n");
4326 return CMD_WARNING_CONFIG_FAILED;
4327 }
718e3744 4328
d62a17ae 4329 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4330 strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
4331 + 2);
718e3744 4332
d62a17ae 4333 sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
718e3744 4334
d62a17ae 4335 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4336 "aggregator as", argstr);
718e3744 4337
d62a17ae 4338 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 4339
d62a17ae 4340 return ret;
718e3744 4341}
4342
f412b39a 4343DEFUN (match_ipv6_next_hop,
718e3744 4344 match_ipv6_next_hop_cmd,
4345 "match ipv6 next-hop X:X::X:X",
4346 MATCH_STR
4347 IPV6_STR
4348 "Match IPv6 next-hop address of route\n"
4349 "IPv6 address of next hop\n")
4350{
d62a17ae 4351 int idx_ipv6 = 3;
4352 return bgp_route_match_add(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
4353 RMAP_EVENT_MATCH_ADDED);
718e3744 4354}
4355
4356DEFUN (no_match_ipv6_next_hop,
4357 no_match_ipv6_next_hop_cmd,
4358 "no match ipv6 next-hop X:X::X:X",
4359 NO_STR
4360 MATCH_STR
4361 IPV6_STR
4362 "Match IPv6 next-hop address of route\n"
4363 "IPv6 address of next hop\n")
4364{
d62a17ae 4365 int idx_ipv6 = 4;
4366 return bgp_route_match_delete(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
4367 RMAP_EVENT_MATCH_DELETED);
718e3744 4368}
4369
718e3744 4370
90916ac2
DS
4371DEFUN (set_ipv6_nexthop_peer,
4372 set_ipv6_nexthop_peer_cmd,
4373 "set ipv6 next-hop peer-address",
4374 SET_STR
4375 IPV6_STR
4376 "Next hop address\n"
4377 "Use peer address (for BGP only)\n")
4378{
d62a17ae 4379 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4380 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4381}
4382
4383DEFUN (no_set_ipv6_nexthop_peer,
4384 no_set_ipv6_nexthop_peer_cmd,
4385 "no set ipv6 next-hop peer-address",
4386 NO_STR
4387 SET_STR
4388 IPV6_STR
4389 "IPv6 next-hop address\n"
161995ea 4390 "Use peer address (for BGP only)\n")
90916ac2 4391{
d62a17ae 4392 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4393 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4394}
4395
161995ea
DS
4396DEFUN (set_ipv6_nexthop_prefer_global,
4397 set_ipv6_nexthop_prefer_global_cmd,
4398 "set ipv6 next-hop prefer-global",
4399 SET_STR
4400 IPV6_STR
4401 "IPv6 next-hop address\n"
4402 "Prefer global over link-local if both exist\n")
4403{
d62a17ae 4404 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4405 "ipv6 next-hop prefer-global", NULL);
4406 ;
161995ea
DS
4407}
4408
4409DEFUN (no_set_ipv6_nexthop_prefer_global,
4410 no_set_ipv6_nexthop_prefer_global_cmd,
4411 "no set ipv6 next-hop prefer-global",
4412 NO_STR
4413 SET_STR
4414 IPV6_STR
4415 "IPv6 next-hop address\n"
4416 "Prefer global over link-local if both exist\n")
4417{
d62a17ae 4418 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4419 "ipv6 next-hop prefer-global", NULL);
161995ea
DS
4420}
4421
718e3744 4422DEFUN (set_ipv6_nexthop_global,
4423 set_ipv6_nexthop_global_cmd,
4424 "set ipv6 next-hop global X:X::X:X",
4425 SET_STR
4426 IPV6_STR
4427 "IPv6 next-hop address\n"
4428 "IPv6 global address\n"
4429 "IPv6 address of next hop\n")
4430{
d62a17ae 4431 int idx_ipv6 = 4;
4432 struct in6_addr addr;
4433 int ret;
bf8b3d27 4434
d62a17ae 4435 ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr);
4436 if (!ret) {
4437 vty_out(vty, "%% Malformed nexthop address\n");
4438 return CMD_WARNING_CONFIG_FAILED;
4439 }
4440 if (IN6_IS_ADDR_UNSPECIFIED(&addr) || IN6_IS_ADDR_LOOPBACK(&addr)
4441 || IN6_IS_ADDR_MULTICAST(&addr) || IN6_IS_ADDR_LINKLOCAL(&addr)) {
4442 vty_out(vty, "%% Invalid global nexthop address\n");
4443 return CMD_WARNING_CONFIG_FAILED;
4444 }
bf8b3d27 4445
d62a17ae 4446 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4447 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 4448}
4449
a4b2b610 4450
718e3744 4451DEFUN (no_set_ipv6_nexthop_global,
4452 no_set_ipv6_nexthop_global_cmd,
a4b2b610 4453 "no set ipv6 next-hop global X:X::X:X",
718e3744 4454 NO_STR
4455 SET_STR
4456 IPV6_STR
4457 "IPv6 next-hop address\n"
a4b2b610
DW
4458 "IPv6 global address\n"
4459 "IPv6 address of next hop\n")
718e3744 4460{
d62a17ae 4461 int idx_ipv6 = 5;
4462 if (argc <= idx_ipv6)
4463 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4464 "ipv6 next-hop global", NULL);
4465 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4466 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 4467}
718e3744 4468
d6902373
PG
4469#ifdef KEEP_OLD_VPN_COMMANDS
4470DEFUN (set_vpn_nexthop,
4471 set_vpn_nexthop_cmd,
a13c883e 4472 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 4473 SET_STR
4474 "VPNv4 information\n"
d6902373
PG
4475 "VPN next-hop address\n"
4476 "IP address of next hop\n"
a13c883e
QY
4477 "VPNv6 information\n"
4478 "VPN next-hop address\n"
d6902373 4479 "IPv6 address of next hop\n")
718e3744 4480{
d62a17ae 4481 int idx_ip = 3;
4482 afi_t afi;
4483 int idx = 0;
4484
4485 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
4486 if (afi == AFI_IP)
4487 return generic_set_add(
4488 vty, VTY_GET_CONTEXT(route_map_index),
4489 "ipv4 vpn next-hop", argv[idx_ip]->arg);
4490 else
4491 return generic_set_add(
4492 vty, VTY_GET_CONTEXT(route_map_index),
4493 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4494 }
4495 return CMD_SUCCESS;
d6902373 4496}
a4b2b610 4497
d6902373
PG
4498DEFUN (no_set_vpn_nexthop,
4499 no_set_vpn_nexthop_cmd,
a13c883e 4500 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 4501 NO_STR
4502 SET_STR
a13c883e 4503 "VPNv4 information\n"
d6902373
PG
4504 "VPN next-hop address\n"
4505 "IP address of next hop\n"
a13c883e
QY
4506 "VPNv6 information\n"
4507 "VPN next-hop address\n"
d6902373 4508 "IPv6 address of next hop\n")
718e3744 4509{
d62a17ae 4510 int idx_ip = 4;
4511 char *arg;
4512 afi_t afi;
4513 int idx = 0;
4514
4515 if (argc <= idx_ip)
4516 arg = NULL;
4517 else
4518 arg = argv[idx_ip]->arg;
4519 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
4520 if (afi == AFI_IP)
4521 return generic_set_delete(
4522 vty, VTY_GET_CONTEXT(route_map_index),
4523 "ipv4 vpn next-hop", arg);
4524 else
4525 return generic_set_delete(
4526 vty, VTY_GET_CONTEXT(route_map_index),
4527 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4528 }
4529 return CMD_SUCCESS;
d6902373
PG
4530}
4531#endif /* KEEP_OLD_VPN_COMMANDS */
4532
4533DEFUN (set_ipx_vpn_nexthop,
4534 set_ipx_vpn_nexthop_cmd,
0d702986 4535 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
d6902373
PG
4536 SET_STR
4537 "IPv4 information\n"
4538 "IPv6 information\n"
4539 "VPN information\n"
4540 "VPN next-hop address\n"
4541 "IP address of next hop\n"
4542 "IPv6 address of next hop\n")
4543{
d62a17ae 4544 int idx_ip = 4;
4545 afi_t afi;
4546 int idx = 0;
4547
4548 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
4549 if (afi == AFI_IP)
4550 return generic_set_add(
4551 vty, VTY_GET_CONTEXT(route_map_index),
4552 "ipv4 vpn next-hop", argv[idx_ip]->arg);
4553 else
4554 return generic_set_add(
4555 vty, VTY_GET_CONTEXT(route_map_index),
4556 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4557 }
4558 return CMD_SUCCESS;
718e3744 4559}
4560
d6902373
PG
4561DEFUN (no_set_ipx_vpn_nexthop,
4562 no_set_ipx_vpn_nexthop_cmd,
9fa4d336 4563 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
d6902373
PG
4564 NO_STR
4565 SET_STR
4566 "IPv4 information\n"
4567 "IPv6 information\n"
4568 "VPN information\n"
4569 "VPN next-hop address\n"
4570 "IP address of next hop\n"
4571 "IPv6 address of next hop\n")
4572{
d62a17ae 4573 int idx_ip = 5;
4574 char *arg;
4575 afi_t afi;
4576 int idx = 0;
4577
4578 if (argc <= idx_ip)
4579 arg = NULL;
4580 else
4581 arg = argv[idx_ip]->arg;
4582 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
4583 if (afi == AFI_IP)
4584 return generic_set_delete(
4585 vty, VTY_GET_CONTEXT(route_map_index),
4586 "ipv4 vpn next-hop", arg);
4587 else
4588 return generic_set_delete(
4589 vty, VTY_GET_CONTEXT(route_map_index),
4590 "ipv6 vpn next-hop", arg);
4591 }
4592 return CMD_SUCCESS;
d6902373 4593}
718e3744 4594
4595DEFUN (set_originator_id,
4596 set_originator_id_cmd,
4597 "set originator-id A.B.C.D",
4598 SET_STR
4599 "BGP originator ID attribute\n"
4600 "IP address of originator\n")
4601{
d62a17ae 4602 int idx_ipv4 = 2;
4603 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4604 "originator-id", argv[idx_ipv4]->arg);
718e3744 4605}
4606
4c9bd275 4607
718e3744 4608DEFUN (no_set_originator_id,
4609 no_set_originator_id_cmd,
4c9bd275 4610 "no set originator-id [A.B.C.D]",
718e3744 4611 NO_STR
4612 SET_STR
4c9bd275
DW
4613 "BGP originator ID attribute\n"
4614 "IP address of originator\n")
718e3744 4615{
d62a17ae 4616 int idx = 0;
4617 char *arg =
4618 argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
0d702986 4619
d62a17ae 4620 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4621 "originator-id", arg);
718e3744 4622}
4623
718e3744 4624
718e3744 4625/* Initialization of route map. */
d62a17ae 4626void bgp_route_map_init(void)
4627{
4628 route_map_init();
4629
4630 route_map_add_hook(bgp_route_map_add);
4631 route_map_delete_hook(bgp_route_map_delete);
4632 route_map_event_hook(bgp_route_map_event);
4633
4634 route_map_match_interface_hook(generic_match_add);
4635 route_map_no_match_interface_hook(generic_match_delete);
4636
4637 route_map_match_ip_address_hook(generic_match_add);
4638 route_map_no_match_ip_address_hook(generic_match_delete);
4639
4640 route_map_match_ip_address_prefix_list_hook(generic_match_add);
4641 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
4642
4643 route_map_match_ip_next_hop_hook(generic_match_add);
4644 route_map_no_match_ip_next_hop_hook(generic_match_delete);
4645
4646 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
4647 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
4648
4649 route_map_match_ipv6_address_hook(generic_match_add);
4650 route_map_no_match_ipv6_address_hook(generic_match_delete);
4651
4652 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
4653 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
4654
4655 route_map_match_metric_hook(generic_match_add);
4656 route_map_no_match_metric_hook(generic_match_delete);
4657
4658 route_map_match_tag_hook(generic_match_add);
4659 route_map_no_match_tag_hook(generic_match_delete);
4660
4661 route_map_set_ip_nexthop_hook(generic_set_add);
4662 route_map_no_set_ip_nexthop_hook(generic_set_delete);
4663
4664 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
4665 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
4666
4667 route_map_set_metric_hook(generic_set_add);
4668 route_map_no_set_metric_hook(generic_set_delete);
4669
4670 route_map_set_tag_hook(generic_set_add);
4671 route_map_no_set_tag_hook(generic_set_delete);
4672
4673 route_map_install_match(&route_match_peer_cmd);
4674 route_map_install_match(&route_match_local_pref_cmd);
4675 route_map_install_match(&route_match_ip_address_cmd);
4676 route_map_install_match(&route_match_ip_next_hop_cmd);
4677 route_map_install_match(&route_match_ip_route_source_cmd);
4678 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
4679 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
4680 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
4681 route_map_install_match(&route_match_aspath_cmd);
4682 route_map_install_match(&route_match_community_cmd);
4683 route_map_install_match(&route_match_lcommunity_cmd);
4684 route_map_install_match(&route_match_ecommunity_cmd);
4685 route_map_install_match(&route_match_local_pref_cmd);
4686 route_map_install_match(&route_match_metric_cmd);
4687 route_map_install_match(&route_match_origin_cmd);
4688 route_map_install_match(&route_match_probability_cmd);
4689 route_map_install_match(&route_match_interface_cmd);
4690 route_map_install_match(&route_match_tag_cmd);
d37ba549 4691 route_map_install_match(&route_match_mac_address_cmd);
16f7ce2b 4692 route_map_install_match(&route_match_evpn_vni_cmd);
33c2ff62 4693 route_map_install_match(&route_match_evpn_route_type_cmd);
6fb219da 4694 route_map_install_match(&route_match_evpn_default_route_cmd);
d62a17ae 4695
4696 route_map_install_set(&route_set_ip_nexthop_cmd);
4697 route_map_install_set(&route_set_local_pref_cmd);
4698 route_map_install_set(&route_set_weight_cmd);
4699 route_map_install_set(&route_set_label_index_cmd);
4700 route_map_install_set(&route_set_metric_cmd);
4701 route_map_install_set(&route_set_aspath_prepend_cmd);
4702 route_map_install_set(&route_set_aspath_exclude_cmd);
4703 route_map_install_set(&route_set_origin_cmd);
4704 route_map_install_set(&route_set_atomic_aggregate_cmd);
4705 route_map_install_set(&route_set_aggregator_as_cmd);
4706 route_map_install_set(&route_set_community_cmd);
4707 route_map_install_set(&route_set_community_delete_cmd);
4708 route_map_install_set(&route_set_lcommunity_cmd);
4709 route_map_install_set(&route_set_lcommunity_delete_cmd);
4710 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
4711 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
4712 route_map_install_set(&route_set_originator_id_cmd);
4713 route_map_install_set(&route_set_ecommunity_rt_cmd);
4714 route_map_install_set(&route_set_ecommunity_soo_cmd);
4715 route_map_install_set(&route_set_tag_cmd);
4716 route_map_install_set(&route_set_label_index_cmd);
4717
4718 install_element(RMAP_NODE, &match_peer_cmd);
4719 install_element(RMAP_NODE, &match_peer_local_cmd);
4720 install_element(RMAP_NODE, &no_match_peer_cmd);
4721 install_element(RMAP_NODE, &match_ip_route_source_cmd);
4722 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
4723 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4724 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
d37ba549
MK
4725 install_element(RMAP_NODE, &match_mac_address_cmd);
4726 install_element(RMAP_NODE, &no_match_mac_address_cmd);
16f7ce2b
MK
4727 install_element(RMAP_NODE, &match_evpn_vni_cmd);
4728 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
33c2ff62
MK
4729 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
4730 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
6fb219da
MK
4731 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
4732 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
d62a17ae 4733
4734 install_element(RMAP_NODE, &match_aspath_cmd);
4735 install_element(RMAP_NODE, &no_match_aspath_cmd);
4736 install_element(RMAP_NODE, &match_local_pref_cmd);
4737 install_element(RMAP_NODE, &no_match_local_pref_cmd);
4738 install_element(RMAP_NODE, &match_community_cmd);
4739 install_element(RMAP_NODE, &no_match_community_cmd);
4740 install_element(RMAP_NODE, &match_lcommunity_cmd);
4741 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
4742 install_element(RMAP_NODE, &match_ecommunity_cmd);
4743 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
4744 install_element(RMAP_NODE, &match_origin_cmd);
4745 install_element(RMAP_NODE, &no_match_origin_cmd);
4746 install_element(RMAP_NODE, &match_probability_cmd);
4747 install_element(RMAP_NODE, &no_match_probability_cmd);
4748
4749 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
4750 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
4751 install_element(RMAP_NODE, &set_local_pref_cmd);
4752 install_element(RMAP_NODE, &no_set_local_pref_cmd);
4753 install_element(RMAP_NODE, &set_weight_cmd);
4754 install_element(RMAP_NODE, &set_label_index_cmd);
4755 install_element(RMAP_NODE, &no_set_weight_cmd);
4756 install_element(RMAP_NODE, &no_set_label_index_cmd);
4757 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
4758 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
4759 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
4760 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
4761 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
4762 install_element(RMAP_NODE, &set_origin_cmd);
4763 install_element(RMAP_NODE, &no_set_origin_cmd);
4764 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
4765 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
4766 install_element(RMAP_NODE, &set_aggregator_as_cmd);
4767 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
4768 install_element(RMAP_NODE, &set_community_cmd);
4769 install_element(RMAP_NODE, &set_community_none_cmd);
4770 install_element(RMAP_NODE, &no_set_community_cmd);
4771 install_element(RMAP_NODE, &set_community_delete_cmd);
4772 install_element(RMAP_NODE, &no_set_community_delete_cmd);
4773 install_element(RMAP_NODE, &set_lcommunity_cmd);
4774 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
4775 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
4776 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
4777 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
4778 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
4779 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
4780 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4781 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
4782 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
d6902373 4783#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 4784 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
4785 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
d6902373 4786#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 4787 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
4788 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
4789 install_element(RMAP_NODE, &set_originator_id_cmd);
4790 install_element(RMAP_NODE, &no_set_originator_id_cmd);
4791
4792 route_map_install_match(&route_match_ipv6_address_cmd);
4793 route_map_install_match(&route_match_ipv6_next_hop_cmd);
4794 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
4795 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
4796 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
4797 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
4798 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
4799
4800 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
4801 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
4802 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
4803 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
4804 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
4805 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
4806 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
4807 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
4808}
4809
4810void bgp_route_map_terminate(void)
4811{
4812 /* ToDo: Cleanup all the used memory */
d62a17ae 4813 route_map_finish();
518f0eb1 4814}