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