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