]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
bgpd, zebra: Use sscanf return value
[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));
116e176d
DS
2085 if (sscanf(arg, "%s %s", as, address) != 2) {
2086 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2087 return NULL;
2088 }
718e3744 2089
d62a17ae 2090 aggregator->as = strtoul(as, NULL, 10);
2091 ret = inet_aton(address, &aggregator->address);
2092 if (ret == 0) {
2093 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2094 return NULL;
2095 }
2096 return aggregator;
718e3744 2097}
2098
d62a17ae 2099static void route_set_aggregator_as_free(void *rule)
718e3744 2100{
d62a17ae 2101 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2102}
2103
d62a17ae 2104struct route_map_rule_cmd route_set_aggregator_as_cmd = {
9d303b37
DL
2105 "aggregator as", route_set_aggregator_as,
2106 route_set_aggregator_as_compile, route_set_aggregator_as_free,
718e3744 2107};
6b0655a2 2108
0d9551dc 2109/* Set tag to object. object must be pointer to struct bgp_info */
d62a17ae 2110static route_map_result_t route_set_tag(void *rule, struct prefix *prefix,
2111 route_map_object_t type, void *object)
0d9551dc 2112{
d62a17ae 2113 route_tag_t *tag;
2114 struct bgp_info *bgp_info;
0d9551dc 2115
d62a17ae 2116 if (type == RMAP_BGP) {
2117 tag = rule;
2118 bgp_info = object;
0d9551dc 2119
d62a17ae 2120 /* Set tag value */
2121 bgp_info->attr->tag = *tag;
2122 }
0d9551dc 2123
d62a17ae 2124 return RMAP_OKAY;
0d9551dc
DS
2125}
2126
0d9551dc 2127/* Route map commands for tag set. */
d62a17ae 2128static struct route_map_rule_cmd route_set_tag_cmd = {
9d303b37 2129 "tag", route_set_tag, route_map_rule_tag_compile,
d62a17ae 2130 route_map_rule_tag_free,
0d9551dc
DS
2131};
2132
d990e384 2133/* Set label-index to object. object must be pointer to struct bgp_info */
d62a17ae 2134static route_map_result_t route_set_label_index(void *rule,
2135 struct prefix *prefix,
2136 route_map_object_t type,
2137 void *object)
2138{
2139 struct rmap_value *rv;
2140 struct bgp_info *bgp_info;
2141 u_int32_t label_index;
2142
2143 if (type == RMAP_BGP) {
2144 /* Fetch routemap's rule information. */
2145 rv = rule;
2146 bgp_info = object;
2147
2148 /* Set label-index value. */
2149 label_index = rv->value;
2150 if (label_index) {
2151 bgp_info->attr->label_index = label_index;
2152 bgp_info->attr->flag |=
2153 ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
2154 }
2155 }
d990e384 2156
d62a17ae 2157 return RMAP_OKAY;
d990e384
DS
2158}
2159
2160/* Route map commands for label-index set. */
d62a17ae 2161static struct route_map_rule_cmd route_set_label_index_cmd = {
9d303b37 2162 "label-index", route_set_label_index, route_value_compile,
d62a17ae 2163 route_value_free,
d990e384 2164};
0d9551dc 2165
718e3744 2166/* `match ipv6 address IP_ACCESS_LIST' */
2167
d62a17ae 2168static route_map_result_t route_match_ipv6_address(void *rule,
2169 struct prefix *prefix,
2170 route_map_object_t type,
2171 void *object)
718e3744 2172{
d62a17ae 2173 struct access_list *alist;
718e3744 2174
d62a17ae 2175 if (type == RMAP_BGP) {
2176 alist = access_list_lookup(AFI_IP6, (char *)rule);
2177 if (alist == NULL)
2178 return RMAP_NOMATCH;
e52702f2 2179
d62a17ae 2180 return (access_list_apply(alist, prefix) == FILTER_DENY
2181 ? RMAP_NOMATCH
2182 : RMAP_MATCH);
2183 }
2184 return RMAP_NOMATCH;
718e3744 2185}
2186
d62a17ae 2187static void *route_match_ipv6_address_compile(const char *arg)
718e3744 2188{
d62a17ae 2189 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 2190}
2191
d62a17ae 2192static void route_match_ipv6_address_free(void *rule)
718e3744 2193{
d62a17ae 2194 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2195}
2196
2197/* Route map commands for ip address matching. */
d62a17ae 2198struct route_map_rule_cmd route_match_ipv6_address_cmd = {
2199 "ipv6 address", route_match_ipv6_address,
2200 route_match_ipv6_address_compile, route_match_ipv6_address_free};
6b0655a2 2201
718e3744 2202/* `match ipv6 next-hop IP_ADDRESS' */
2203
d62a17ae 2204static route_map_result_t route_match_ipv6_next_hop(void *rule,
2205 struct prefix *prefix,
2206 route_map_object_t type,
2207 void *object)
718e3744 2208{
d62a17ae 2209 struct in6_addr *addr = rule;
2210 struct bgp_info *bgp_info;
718e3744 2211
d62a17ae 2212 if (type == RMAP_BGP) {
2213 bgp_info = object;
e52702f2 2214
d62a17ae 2215 if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr))
2216 return RMAP_MATCH;
718e3744 2217
d62a17ae 2218 if (bgp_info->attr->mp_nexthop_len
2219 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
2220 && IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_local, rule))
2221 return RMAP_MATCH;
718e3744 2222
d62a17ae 2223 return RMAP_NOMATCH;
2224 }
718e3744 2225
d62a17ae 2226 return RMAP_NOMATCH;
718e3744 2227}
2228
d62a17ae 2229static void *route_match_ipv6_next_hop_compile(const char *arg)
718e3744 2230{
d62a17ae 2231 struct in6_addr *address;
2232 int ret;
718e3744 2233
d62a17ae 2234 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 2235
d62a17ae 2236 ret = inet_pton(AF_INET6, arg, address);
2237 if (!ret) {
2238 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2239 return NULL;
2240 }
718e3744 2241
d62a17ae 2242 return address;
718e3744 2243}
2244
d62a17ae 2245static void route_match_ipv6_next_hop_free(void *rule)
718e3744 2246{
d62a17ae 2247 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2248}
2249
d62a17ae 2250struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
2251 "ipv6 next-hop", route_match_ipv6_next_hop,
2252 route_match_ipv6_next_hop_compile, route_match_ipv6_next_hop_free};
6b0655a2 2253
718e3744 2254/* `match ipv6 address prefix-list PREFIX_LIST' */
2255
94f2b392 2256static route_map_result_t
d62a17ae 2257route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix,
2258 route_map_object_t type, void *object)
718e3744 2259{
d62a17ae 2260 struct prefix_list *plist;
718e3744 2261
d62a17ae 2262 if (type == RMAP_BGP) {
2263 plist = prefix_list_lookup(AFI_IP6, (char *)rule);
2264 if (plist == NULL)
2265 return RMAP_NOMATCH;
e52702f2 2266
d62a17ae 2267 return (prefix_list_apply(plist, prefix) == PREFIX_DENY
2268 ? RMAP_NOMATCH
2269 : RMAP_MATCH);
2270 }
2271 return RMAP_NOMATCH;
718e3744 2272}
2273
d62a17ae 2274static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
718e3744 2275{
d62a17ae 2276 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 2277}
2278
d62a17ae 2279static void route_match_ipv6_address_prefix_list_free(void *rule)
718e3744 2280{
d62a17ae 2281 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2282}
2283
d62a17ae 2284struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
2285 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
2286 route_match_ipv6_address_prefix_list_compile,
2287 route_match_ipv6_address_prefix_list_free};
6b0655a2 2288
718e3744 2289/* `set ipv6 nexthop global IP_ADDRESS' */
2290
2291/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 2292static route_map_result_t route_set_ipv6_nexthop_global(void *rule,
2293 struct prefix *prefix,
2294 route_map_object_t type,
2295 void *object)
718e3744 2296{
d62a17ae 2297 struct in6_addr *address;
2298 struct bgp_info *bgp_info;
718e3744 2299
d62a17ae 2300 if (type == RMAP_BGP) {
2301 /* Fetch routemap's rule information. */
2302 address = rule;
2303 bgp_info = object;
e52702f2 2304
d62a17ae 2305 /* Set next hop value. */
2306 bgp_info->attr->mp_nexthop_global = *address;
3f9c7369 2307
d62a17ae 2308 /* Set nexthop length. */
2309 if (bgp_info->attr->mp_nexthop_len == 0)
2310 bgp_info->attr->mp_nexthop_len =
2311 BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369 2312
d62a17ae 2313 SET_FLAG(bgp_info->attr->rmap_change_flags,
2314 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
2315 }
718e3744 2316
d62a17ae 2317 return RMAP_OKAY;
718e3744 2318}
2319
2320/* Route map `ip next-hop' compile function. Given string is converted
2321 to struct in_addr structure. */
d62a17ae 2322static void *route_set_ipv6_nexthop_global_compile(const char *arg)
718e3744 2323{
d62a17ae 2324 int ret;
2325 struct in6_addr *address;
718e3744 2326
d62a17ae 2327 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 2328
d62a17ae 2329 ret = inet_pton(AF_INET6, arg, address);
718e3744 2330
d62a17ae 2331 if (ret == 0) {
2332 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2333 return NULL;
2334 }
718e3744 2335
d62a17ae 2336 return address;
718e3744 2337}
2338
2339/* Free route map's compiled `ip next-hop' value. */
d62a17ae 2340static void route_set_ipv6_nexthop_global_free(void *rule)
718e3744 2341{
d62a17ae 2342 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2343}
2344
2345/* Route map commands for ip nexthop set. */
d62a17ae 2346struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = {
2347 "ipv6 next-hop global", route_set_ipv6_nexthop_global,
2348 route_set_ipv6_nexthop_global_compile,
2349 route_set_ipv6_nexthop_global_free};
6b0655a2 2350
161995ea
DS
2351/* Set next-hop preference value. */
2352static route_map_result_t
d62a17ae 2353route_set_ipv6_nexthop_prefer_global(void *rule, struct prefix *prefix,
2354 route_map_object_t type, void *object)
2355{
2356 struct bgp_info *bgp_info;
2357 struct peer *peer;
2358
2359 if (type == RMAP_BGP) {
2360 /* Fetch routemap's rule information. */
2361 bgp_info = object;
2362 peer = bgp_info->peer;
2363
2364 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
2365 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
2366 && peer->su_remote
2367 && sockunion_family(peer->su_remote) == AF_INET6) {
2368 /* Set next hop preference to global */
2369 bgp_info->attr->mp_nexthop_prefer_global = TRUE;
2370 SET_FLAG(bgp_info->attr->rmap_change_flags,
2371 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
2372 } else {
2373 bgp_info->attr->mp_nexthop_prefer_global = FALSE;
2374 SET_FLAG(bgp_info->attr->rmap_change_flags,
2375 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
2376 }
161995ea 2377 }
d62a17ae 2378 return RMAP_OKAY;
161995ea
DS
2379}
2380
d62a17ae 2381static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
161995ea 2382{
d62a17ae 2383 int *rins = NULL;
161995ea 2384
d62a17ae 2385 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
2386 *rins = 1;
161995ea 2387
d62a17ae 2388 return rins;
161995ea
DS
2389}
2390
2391/* Free route map's compiled `ip next-hop' value. */
d62a17ae 2392static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
161995ea 2393{
d62a17ae 2394 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
161995ea
DS
2395}
2396
2397/* Route map commands for ip nexthop set preferred. */
d62a17ae 2398struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = {
2399 "ipv6 next-hop prefer-global", route_set_ipv6_nexthop_prefer_global,
2400 route_set_ipv6_nexthop_prefer_global_compile,
2401 route_set_ipv6_nexthop_prefer_global_free};
161995ea 2402
718e3744 2403/* `set ipv6 nexthop local IP_ADDRESS' */
2404
2405/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 2406static route_map_result_t route_set_ipv6_nexthop_local(void *rule,
2407 struct prefix *prefix,
2408 route_map_object_t type,
2409 void *object)
2410{
2411 struct in6_addr *address;
2412 struct bgp_info *bgp_info;
2413
2414 if (type == RMAP_BGP) {
2415 /* Fetch routemap's rule information. */
2416 address = rule;
2417 bgp_info = object;
2418
2419 /* Set next hop value. */
2420 bgp_info->attr->mp_nexthop_local = *address;
2421
2422 /* Set nexthop length. */
2423 if (bgp_info->attr->mp_nexthop_len
2424 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
2425 bgp_info->attr->mp_nexthop_len =
2426 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2427
2428 SET_FLAG(bgp_info->attr->rmap_change_flags,
2429 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
2430 }
718e3744 2431
d62a17ae 2432 return RMAP_OKAY;
718e3744 2433}
2434
2435/* Route map `ip nexthop' compile function. Given string is converted
2436 to struct in_addr structure. */
d62a17ae 2437static void *route_set_ipv6_nexthop_local_compile(const char *arg)
718e3744 2438{
d62a17ae 2439 int ret;
2440 struct in6_addr *address;
718e3744 2441
d62a17ae 2442 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 2443
d62a17ae 2444 ret = inet_pton(AF_INET6, arg, address);
718e3744 2445
d62a17ae 2446 if (ret == 0) {
2447 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2448 return NULL;
2449 }
718e3744 2450
d62a17ae 2451 return address;
718e3744 2452}
2453
2454/* Free route map's compiled `ip nexthop' value. */
d62a17ae 2455static void route_set_ipv6_nexthop_local_free(void *rule)
718e3744 2456{
d62a17ae 2457 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2458}
2459
2460/* Route map commands for ip nexthop set. */
d62a17ae 2461struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = {
2462 "ipv6 next-hop local", route_set_ipv6_nexthop_local,
2463 route_set_ipv6_nexthop_local_compile,
2464 route_set_ipv6_nexthop_local_free};
90916ac2
DS
2465
2466/* `set ipv6 nexthop peer-address' */
2467
2468/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 2469static route_map_result_t route_set_ipv6_nexthop_peer(void *rule,
2470 struct prefix *prefix,
2471 route_map_object_t type,
2472 void *object)
2473{
2474 struct in6_addr peer_address;
2475 struct bgp_info *bgp_info;
2476 struct peer *peer;
2477
2478 if (type == RMAP_BGP) {
2479 /* Fetch routemap's rule information. */
2480 bgp_info = object;
2481 peer = bgp_info->peer;
2482
2483 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
2484 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
2485 && peer->su_remote
2486 && sockunion_family(peer->su_remote) == AF_INET6) {
2487 peer_address = peer->su_remote->sin6.sin6_addr;
2488 /* Set next hop value and length in attribute. */
2489 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
2490 bgp_info->attr->mp_nexthop_local = peer_address;
2491 if (bgp_info->attr->mp_nexthop_len != 32)
2492 bgp_info->attr->mp_nexthop_len = 32;
2493 } else {
2494 bgp_info->attr->mp_nexthop_global =
2495 peer_address;
2496 if (bgp_info->attr->mp_nexthop_len == 0)
2497 bgp_info->attr->mp_nexthop_len = 16;
2498 }
2499
2500 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
2501 /* The next hop value will be set as part of packet
2502 * rewrite.
2503 * Set the flags here to indicate that rewrite needs to
2504 * be done.
2505 * Also, clear the value - we clear both global and
2506 * link-local
2507 * nexthops, whether we send one or both is determined
2508 * elsewhere.
2509 */
2510 SET_FLAG(bgp_info->attr->rmap_change_flags,
2511 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
2512 /* clear next hop value. */
2513 memset(&(bgp_info->attr->mp_nexthop_global), 0,
2514 sizeof(struct in6_addr));
2515 memset(&(bgp_info->attr->mp_nexthop_local), 0,
2516 sizeof(struct in6_addr));
2517 }
90916ac2 2518 }
90916ac2 2519
d62a17ae 2520 return RMAP_OKAY;
90916ac2
DS
2521}
2522
2523/* Route map `ip next-hop' compile function. Given string is converted
2524 to struct in_addr structure. */
d62a17ae 2525static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
90916ac2 2526{
d62a17ae 2527 int *rins = NULL;
90916ac2 2528
d62a17ae 2529 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
2530 *rins = 1;
90916ac2 2531
d62a17ae 2532 return rins;
90916ac2
DS
2533}
2534
2535/* Free route map's compiled `ip next-hop' value. */
d62a17ae 2536static void route_set_ipv6_nexthop_peer_free(void *rule)
90916ac2 2537{
d62a17ae 2538 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
90916ac2
DS
2539}
2540
2541/* Route map commands for ip nexthop set. */
d62a17ae 2542struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
2543 "ipv6 next-hop peer-address", route_set_ipv6_nexthop_peer,
2544 route_set_ipv6_nexthop_peer_compile, route_set_ipv6_nexthop_peer_free};
90916ac2 2545
69ba6dd7 2546/* `set ipv4 vpn next-hop A.B.C.D' */
718e3744 2547
d62a17ae 2548static route_map_result_t route_set_vpnv4_nexthop(void *rule,
2549 struct prefix *prefix,
2550 route_map_object_t type,
2551 void *object)
718e3744 2552{
d62a17ae 2553 struct in_addr *address;
2554 struct bgp_info *bgp_info;
718e3744 2555
d62a17ae 2556 if (type == RMAP_BGP) {
2557 /* Fetch routemap's rule information. */
2558 address = rule;
2559 bgp_info = object;
e52702f2 2560
d62a17ae 2561 /* Set next hop value. */
2562 bgp_info->attr->mp_nexthop_global_in = *address;
2563 bgp_info->attr->mp_nexthop_len = 4;
2564 }
718e3744 2565
d62a17ae 2566 return RMAP_OKAY;
718e3744 2567}
2568
d62a17ae 2569static void *route_set_vpnv4_nexthop_compile(const char *arg)
718e3744 2570{
d62a17ae 2571 int ret;
2572 struct in_addr *address;
718e3744 2573
d62a17ae 2574 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 2575
d62a17ae 2576 ret = inet_aton(arg, address);
718e3744 2577
d62a17ae 2578 if (ret == 0) {
2579 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2580 return NULL;
2581 }
718e3744 2582
d62a17ae 2583 return address;
718e3744 2584}
2585
69ba6dd7 2586/* `set ipv6 vpn next-hop A.B.C.D' */
d6902373 2587
d62a17ae 2588static route_map_result_t route_set_vpnv6_nexthop(void *rule,
2589 struct prefix *prefix,
2590 route_map_object_t type,
2591 void *object)
d6902373 2592{
d62a17ae 2593 struct in6_addr *address;
2594 struct bgp_info *bgp_info;
d6902373 2595
d62a17ae 2596 if (type == RMAP_BGP) {
2597 /* Fetch routemap's rule information. */
2598 address = rule;
2599 bgp_info = object;
d6902373 2600
d62a17ae 2601 /* Set next hop value. */
2602 memcpy(&bgp_info->attr->mp_nexthop_global, address,
2603 sizeof(struct in6_addr));
2604 bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
2605 }
d6902373 2606
d62a17ae 2607 return RMAP_OKAY;
d6902373
PG
2608}
2609
d62a17ae 2610static void *route_set_vpnv6_nexthop_compile(const char *arg)
d6902373 2611{
d62a17ae 2612 int ret;
2613 struct in6_addr *address;
d6902373 2614
d62a17ae 2615 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
2616 ret = inet_pton(AF_INET6, arg, address);
d6902373 2617
d62a17ae 2618 if (ret == 0) {
2619 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2620 return NULL;
2621 }
d6902373 2622
d62a17ae 2623 return address;
d6902373
PG
2624}
2625
d62a17ae 2626static void route_set_vpn_nexthop_free(void *rule)
718e3744 2627{
d62a17ae 2628 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2629}
2630
69ba6dd7 2631/* Route map commands for ipv4 next-hop set. */
d62a17ae 2632struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
2633 "ipv4 vpn next-hop", route_set_vpnv4_nexthop,
2634 route_set_vpnv4_nexthop_compile, route_set_vpn_nexthop_free};
d6902373 2635
69ba6dd7 2636/* Route map commands for ipv6 next-hop set. */
d62a17ae 2637struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
2638 "ipv6 vpn next-hop", route_set_vpnv6_nexthop,
2639 route_set_vpnv6_nexthop_compile, route_set_vpn_nexthop_free};
6b0655a2 2640
718e3744 2641/* `set originator-id' */
2642
2643/* For origin set. */
d62a17ae 2644static route_map_result_t route_set_originator_id(void *rule,
2645 struct prefix *prefix,
2646 route_map_object_t type,
2647 void *object)
718e3744 2648{
d62a17ae 2649 struct in_addr *address;
2650 struct bgp_info *bgp_info;
718e3744 2651
d62a17ae 2652 if (type == RMAP_BGP) {
2653 address = rule;
2654 bgp_info = object;
e52702f2 2655
d62a17ae 2656 bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
2657 bgp_info->attr->originator_id = *address;
2658 }
718e3744 2659
d62a17ae 2660 return RMAP_OKAY;
718e3744 2661}
2662
2663/* Compile function for originator-id set. */
d62a17ae 2664static void *route_set_originator_id_compile(const char *arg)
718e3744 2665{
d62a17ae 2666 int ret;
2667 struct in_addr *address;
718e3744 2668
d62a17ae 2669 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 2670
d62a17ae 2671 ret = inet_aton(arg, address);
718e3744 2672
d62a17ae 2673 if (ret == 0) {
2674 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2675 return NULL;
2676 }
718e3744 2677
d62a17ae 2678 return address;
718e3744 2679}
2680
2681/* Compile function for originator_id set. */
d62a17ae 2682static void route_set_originator_id_free(void *rule)
718e3744 2683{
d62a17ae 2684 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2685}
2686
515e500c 2687/* Set originator-id rule structure. */
d62a17ae 2688struct route_map_rule_cmd route_set_originator_id_cmd = {
9d303b37
DL
2689 "originator-id", route_set_originator_id,
2690 route_set_originator_id_compile, route_set_originator_id_free,
718e3744 2691};
6b0655a2 2692
718e3744 2693/* Add bgp route map rule. */
d62a17ae 2694static int bgp_route_match_add(struct vty *vty, const char *command,
2695 const char *arg, route_map_event_t type)
2696{
2697 VTY_DECLVAR_CONTEXT(route_map_index, index);
9ca25fed 2698 int retval = CMD_SUCCESS;
d62a17ae 2699 int ret;
2700
2701 ret = route_map_add_match(index, command, arg);
9ca25fed
DS
2702 switch (ret) {
2703 case RMAP_RULE_MISSING:
2704 vty_out(vty, "%% BGP Can't find rule.\n");
2705 retval = CMD_WARNING_CONFIG_FAILED;
2706 break;
2707 case RMAP_COMPILE_ERROR:
2708 vty_out(vty, "%% BGP Argument is malformed.\n");
2709 retval = CMD_WARNING_CONFIG_FAILED;
2710 break;
2711 case RMAP_COMPILE_SUCCESS:
2712 if (type != RMAP_EVENT_MATCH_ADDED) {
2713 route_map_upd8_dependency(type, arg, index->map->name);
d62a17ae 2714 }
9ca25fed 2715 break;
718e3744 2716 }
518f0eb1 2717
9ca25fed 2718 return retval;
718e3744 2719}
2720
2721/* Delete bgp route map rule. */
d62a17ae 2722static int bgp_route_match_delete(struct vty *vty, const char *command,
2723 const char *arg, route_map_event_t type)
2724{
2725 VTY_DECLVAR_CONTEXT(route_map_index, index);
2726 int ret;
9ca25fed 2727 int retval = CMD_SUCCESS;
d62a17ae 2728 char *dep_name = NULL;
2729 const char *tmpstr;
2730 char *rmap_name = NULL;
2731
2732 if (type != RMAP_EVENT_MATCH_DELETED) {
2733 /* ignore the mundane, the types without any dependency */
2734 if (arg == NULL) {
2735 if ((tmpstr = route_map_get_match_arg(index, command))
2736 != NULL)
2737 dep_name =
2738 XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
2739 } else {
2740 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
2741 }
2742 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
ffd0c037 2743 }
d62a17ae 2744
2745 ret = route_map_delete_match(index, command, dep_name);
9ca25fed
DS
2746 switch (ret) {
2747 case RMAP_RULE_MISSING:
2748 vty_out(vty, "%% BGP Can't find rule.\n");
2749 retval = CMD_WARNING_CONFIG_FAILED;
2750 break;
2751 case RMAP_COMPILE_ERROR:
2752 vty_out(vty, "%% BGP Argument is malformed.\n");
2753 retval = CMD_WARNING_CONFIG_FAILED;
2754 break;
2755 case RMAP_COMPILE_SUCCESS:
2756 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
2757 route_map_upd8_dependency(type, dep_name, rmap_name);
2758 break;
718e3744 2759 }
518f0eb1 2760
d62a17ae 2761 if (dep_name)
2762 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
2763 if (rmap_name)
2764 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
518f0eb1 2765
9ca25fed 2766 return retval;
718e3744 2767}
2768
518f0eb1 2769/*
2a3d5731 2770 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
2771 * modifications.
2772 */
d62a17ae 2773static void bgp_route_map_process_peer(const char *rmap_name,
2774 struct route_map *map, struct peer *peer,
2775 int afi, int safi, int route_update)
2776{
2777
2778 int update;
2779 struct bgp_filter *filter;
2780
2781 if (!peer || !rmap_name)
2782 return;
2783
2784 filter = &peer->filter[afi][safi];
2785 /*
2786 * in is for non-route-server clients,
2787 * out is for all peers
2788 */
2789 if (!CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) {
2790 if (filter->map[RMAP_IN].name
2791 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
2792 filter->map[RMAP_IN].map = map;
2793
2794 if (route_update && peer->status == Established) {
2795 if (CHECK_FLAG(peer->af_flags[afi][safi],
2796 PEER_FLAG_SOFT_RECONFIG)) {
2797 if (bgp_debug_update(peer, NULL, NULL,
2798 1))
2799 zlog_debug(
2800 "Processing route_map %s update on "
2801 "peer %s (inbound, soft-reconfig)",
2802 rmap_name, peer->host);
2803
2804 bgp_soft_reconfig_in(peer, afi, safi);
2805 } else if (
2806 CHECK_FLAG(peer->cap,
2807 PEER_CAP_REFRESH_OLD_RCV)
2808 || CHECK_FLAG(
2809 peer->cap,
2810 PEER_CAP_REFRESH_NEW_RCV)) {
2811
2812 if (bgp_debug_update(peer, NULL, NULL,
2813 1))
2814 zlog_debug(
2815 "Processing route_map %s update on "
2816 "peer %s (inbound, route-refresh)",
2817 rmap_name, peer->host);
2818 bgp_route_refresh_send(peer, afi, safi,
2819 0, 0, 0);
2820 }
2821 }
518f0eb1 2822 }
718e3744 2823 }
d62a17ae 2824
2825 if (CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) {
2826 update = 0;
2827
2828 if (update && route_update && peer->status == Established) {
2829 if (CHECK_FLAG(peer->af_flags[afi][safi],
2830 PEER_FLAG_SOFT_RECONFIG)) {
2831 if (bgp_debug_update(peer, NULL, NULL, 1))
2832 zlog_debug(
2833 "Processing route_map %s update on "
2834 "peer %s (import, soft-reconfig)",
2835 rmap_name, peer->host);
2836
2837 bgp_soft_reconfig_in(peer, afi, safi);
2838 } else if (CHECK_FLAG(peer->cap,
2839 PEER_CAP_REFRESH_OLD_RCV)
2840 || CHECK_FLAG(peer->cap,
2841 PEER_CAP_REFRESH_NEW_RCV)) {
2842 if (bgp_debug_update(peer, NULL, NULL, 1))
2843 zlog_debug(
2844 "Processing route_map %s update on "
2845 "peer %s (import, route-refresh)",
2846 rmap_name, peer->host);
2847 bgp_route_refresh_send(peer, afi, safi, 0, 0,
2848 0);
2849 }
2850 /* DD: Else, what else do we do ? Reset peer ? */
2851 }
518f0eb1 2852 }
d62a17ae 2853
2854 /*
2855 * For outbound, unsuppress and default-originate map change (content or
2856 * map created), merely update the "config" here, the actual route
2857 * announcement happens at the group level.
2858 */
2859 if (filter->map[RMAP_OUT].name
2860 && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
2861 filter->map[RMAP_OUT].map = map;
2862
2863 if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
2864 filter->usmap.map = map;
2865
2866 if (peer->default_rmap[afi][safi].name
2867 && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
2868 peer->default_rmap[afi][safi].map = map;
2869}
2870
2871static void bgp_route_map_update_peer_group(const char *rmap_name,
2872 struct route_map *map,
2873 struct bgp *bgp)
2874{
2875 struct peer_group *group;
2876 struct listnode *node, *nnode;
2877 struct bgp_filter *filter;
2878 int afi, safi;
2879 int direct;
2880
2881 if (!bgp)
2882 return;
2883
2884 /* All the peers have been updated correctly already. This is
2885 * just updating the placeholder data. No real update required.
2886 */
05c7a1cc
QY
2887 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
2888 FOREACH_AFI_SAFI (afi, safi) {
2889 filter = &group->conf->filter[afi][safi];
2890
2891 for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
2892 if ((filter->map[direct].name)
2893 && (strcmp(rmap_name,
2894 filter->map[direct].name)
d62a17ae 2895 == 0))
05c7a1cc 2896 filter->map[direct].map = map;
d62a17ae 2897 }
05c7a1cc
QY
2898
2899 if (filter->usmap.name
2900 && (strcmp(rmap_name, filter->usmap.name) == 0))
2901 filter->usmap.map = map;
2902 }
2903 }
518f0eb1
DS
2904}
2905
a6e0d253
DW
2906/*
2907 * Note that if an extreme number (tens of thousands) of route-maps are in use
2908 * and if bgp has an extreme number of peers, network statements, etc then this
2909 * function can consume a lot of cycles. This is due to this function being
2910 * called for each route-map and within this function we walk the list of peers,
2911 * network statements, etc looking to see if they use this route-map.
2912 */
d62a17ae 2913static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
2914 int route_update)
2915{
2916 int i;
2917 afi_t afi;
2918 safi_t safi;
2919 struct peer *peer;
2920 struct bgp_node *bn;
2921 struct bgp_static *bgp_static;
2922 struct listnode *node, *nnode;
2923 struct route_map *map;
2924 char buf[INET6_ADDRSTRLEN];
2925
2926 map = route_map_lookup_by_name(rmap_name);
2927
2928 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
2929
2930 /* Ignore dummy peer-group structure */
2931 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
2932 continue;
2933
05c7a1cc
QY
2934 FOREACH_AFI_SAFI (afi, safi) {
2935 /* process in/out/import/export/default-orig
2936 * route-maps */
2937 bgp_route_map_process_peer(rmap_name, map, peer, afi,
2938 safi, route_update);
2939 }
d62a17ae 2940 }
2941
2942 /* for outbound/default-orig route-maps, process for groups */
2943 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
2944 route_update, 0);
2945
2946 /* update peer-group config (template) */
2947 bgp_route_map_update_peer_group(rmap_name, map, bgp);
2948
05c7a1cc
QY
2949 FOREACH_AFI_SAFI (afi, safi) {
2950 /* For table route-map updates. */
2951 if (!bgp_fibupd_safi(safi))
2952 continue;
d62a17ae 2953
05c7a1cc
QY
2954 if (bgp->table_map[afi][safi].name
2955 && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
2956 == 0)) {
2957 bgp->table_map[afi][safi].map = map;
2958
2959 if (BGP_DEBUG(zebra, ZEBRA))
2960 zlog_debug(
2961 "Processing route_map %s update on "
2962 "table map",
2963 rmap_name);
2964 if (route_update)
2965 bgp_zebra_announce_table(bgp, afi, safi);
2966 }
d62a17ae 2967
05c7a1cc
QY
2968 /* For network route-map updates. */
2969 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
2970 bn = bgp_route_next(bn))
2971 if ((bgp_static = bn->info) != NULL) {
2972 if (bgp_static->rmap.name
2973 && (strcmp(rmap_name, bgp_static->rmap.name)
2974 == 0)) {
2975 bgp_static->rmap.map = map;
2976
2977 if (route_update)
2978 if (!bgp_static->backdoor) {
2979 if (bgp_debug_zebra(
2980 &bn->p))
2981 zlog_debug(
2982 "Processing route_map %s update on "
2983 "static route %s",
2984 rmap_name,
2985 inet_ntop(
2986 bn->p.family,
2987 &bn->p.u.prefix,
2988 buf,
2989 INET6_ADDRSTRLEN));
2990 bgp_static_update(
2991 bgp, &bn->p,
2992 bgp_static, afi,
2993 safi);
2994 }
d62a17ae 2995 }
05c7a1cc
QY
2996 }
2997 }
d62a17ae 2998
2999 /* For redistribute route-map updates. */
3000 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3001 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
3002 struct list *red_list;
3003 struct listnode *node;
3004 struct bgp_redist *red;
3005
3006 red_list = bgp->redist[afi][i];
3007 if (!red_list)
3008 continue;
3009
3010 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
3011 if (red->rmap.name
3012 && (strcmp(rmap_name, red->rmap.name)
3013 == 0)) {
3014 red->rmap.map = map;
3015
3016 if (route_update) {
3017 if (BGP_DEBUG(zebra, ZEBRA))
3018 zlog_debug(
3019 "Processing route_map %s update on "
3020 "redistributed routes",
3021 rmap_name);
3022
3023 bgp_redistribute_resend(
3024 bgp, afi, i,
3025 red->instance);
3026 }
3027 }
3028 }
3029 }
3030}
3031
3032static int bgp_route_map_process_update_cb(char *rmap_name)
3033{
3034 struct listnode *node, *nnode;
3035 struct bgp *bgp;
3036
3037 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3038 bgp_route_map_process_update(bgp, rmap_name, 1);
5fe9f963 3039
65efcfce 3040#if ENABLE_BGP_VNC
d62a17ae 3041 zlog_debug("%s: calling vnc_routemap_update", __func__);
3042 vnc_routemap_update(bgp, __func__);
65efcfce 3043#endif
d62a17ae 3044 return 0;
518f0eb1
DS
3045}
3046
d62a17ae 3047int bgp_route_map_update_timer(struct thread *thread)
518f0eb1 3048{
d62a17ae 3049 bm->t_rmap_update = NULL;
518f0eb1 3050
d62a17ae 3051 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1 3052
d62a17ae 3053 return (0);
518f0eb1
DS
3054}
3055
d62a17ae 3056static void bgp_route_map_mark_update(const char *rmap_name)
518f0eb1 3057{
d62a17ae 3058 if (bm->t_rmap_update == NULL) {
3059 struct listnode *node, *nnode;
3060 struct bgp *bgp;
3f9c7369 3061
d62a17ae 3062 /* rmap_update_timer of 0 means don't do route updates */
3063 if (bm->rmap_update_timer) {
3064 bm->t_rmap_update = NULL;
3065 thread_add_timer(bm->master, bgp_route_map_update_timer,
3066 NULL, bm->rmap_update_timer,
3067 &bm->t_rmap_update);
5fe9f963 3068
d62a17ae 3069 /* Signal the groups that a route-map update event has
3070 * started */
3071 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3072 update_group_policy_update(bgp,
3073 BGP_POLICY_ROUTE_MAP,
3074 rmap_name, 1, 1);
3075 } else {
3076 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3077 bgp_route_map_process_update(bgp, rmap_name, 0);
3078#if ENABLE_BGP_VNC
3079 zlog_debug("%s: calling vnc_routemap_update", __func__);
3080 vnc_routemap_update(bgp, __func__);
65efcfce 3081#endif
d62a17ae 3082 }
3083 }
718e3744 3084}
6b0655a2 3085
d62a17ae 3086static void bgp_route_map_add(const char *rmap_name)
73ac8160 3087{
d62a17ae 3088 if (route_map_mark_updated(rmap_name, 0) == 0)
3089 bgp_route_map_mark_update(rmap_name);
73ac8160 3090
d62a17ae 3091 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 3092}
518f0eb1 3093
d62a17ae 3094static void bgp_route_map_delete(const char *rmap_name)
73ac8160 3095{
d62a17ae 3096 if (route_map_mark_updated(rmap_name, 1) == 0)
3097 bgp_route_map_mark_update(rmap_name);
73ac8160 3098
d62a17ae 3099 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 3100}
518f0eb1 3101
d62a17ae 3102static void bgp_route_map_event(route_map_event_t event, const char *rmap_name)
73ac8160 3103{
d62a17ae 3104 if (route_map_mark_updated(rmap_name, 0) == 0)
3105 bgp_route_map_mark_update(rmap_name);
518f0eb1 3106
d62a17ae 3107 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
3108}
3109
d37ba549
MK
3110DEFUN (match_mac_address,
3111 match_mac_address_cmd,
3112 "match mac address WORD",
3113 MATCH_STR
3114 "mac address\n"
3115 "Match address of route\n"
3116 "MAC Access-list name\n")
3117{
3118 return bgp_route_match_add(vty, "mac address", argv[3]->arg,
3119 RMAP_EVENT_FILTER_ADDED);
3120}
3121
3122DEFUN (no_match_mac_address,
3123 no_match_mac_address_cmd,
646050e5 3124 "no match mac address WORD",
d37ba549
MK
3125 NO_STR
3126 MATCH_STR
3127 "mac\n"
646050e5
MK
3128 "Match address of route\n"
3129 "MAC acess-list name\n")
d37ba549 3130{
d37ba549
MK
3131 return bgp_route_match_delete(vty, "mac address", argv[4]->arg,
3132 RMAP_EVENT_FILTER_DELETED);
3133}
73ac8160 3134
16f7ce2b
MK
3135DEFUN (match_evpn_vni,
3136 match_evpn_vni_cmd,
3137 "match evpn vni (1-16777215)",
3138 MATCH_STR
62982d5a 3139 EVPN_HELP_STR
16f7ce2b
MK
3140 "Match VNI\n"
3141 "VNI ID\n")
3142{
646050e5 3143 return bgp_route_match_add(vty, "evpn vni", argv[3]->arg,
16f7ce2b
MK
3144 RMAP_EVENT_MATCH_ADDED);
3145}
3146
3147DEFUN (no_match_evpn_vni,
3148 no_match_evpn_vni_cmd,
3149 "no match evpn vni (1-16777215)",
3150 NO_STR
3151 MATCH_STR
62982d5a 3152 EVPN_HELP_STR
16f7ce2b
MK
3153 "Match VNI\n"
3154 "VNI ID\n")
3155{
646050e5 3156 return bgp_route_match_delete(vty, "evpn vni", argv[4]->arg,
16f7ce2b
MK
3157 RMAP_EVENT_MATCH_DELETED);
3158}
3159
fee0f4c6 3160DEFUN (match_peer,
3161 match_peer_cmd,
8c3433e4 3162 "match peer <A.B.C.D|X:X::X:X|WORD>",
fee0f4c6 3163 MATCH_STR
3164 "Match peer address\n"
6e13ed4a 3165 "IP address of peer\n"
8c3433e4
DS
3166 "IPv6 address of peer\n"
3167 "Interface name of peer\n")
fee0f4c6 3168{
d62a17ae 3169 int idx_ip = 2;
3170 return bgp_route_match_add(vty, "peer", argv[idx_ip]->arg,
3171 RMAP_EVENT_MATCH_ADDED);
fee0f4c6 3172}
3173
3174DEFUN (match_peer_local,
f412b39a 3175 match_peer_local_cmd,
fee0f4c6 3176 "match peer local",
3177 MATCH_STR
3178 "Match peer address\n"
3179 "Static or Redistributed routes\n")
3180{
d62a17ae 3181 return bgp_route_match_add(vty, "peer", "local",
3182 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3183}
3184
3185DEFUN (no_match_peer,
3186 no_match_peer_cmd,
8c3433e4 3187 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
fee0f4c6 3188 NO_STR
3189 MATCH_STR
4c9bd275
DW
3190 "Match peer address\n"
3191 "Static or Redistributed routes\n"
3192 "IP address of peer\n"
8c3433e4
DS
3193 "IPv6 address of peer\n"
3194 "Interface name of peer\n")
fee0f4c6 3195{
d62a17ae 3196 int idx_peer = 3;
4c9bd275 3197
d62a17ae 3198 if (argc <= idx_peer)
3199 return bgp_route_match_delete(vty, "peer", NULL,
3200 RMAP_EVENT_MATCH_DELETED);
3201 return bgp_route_match_delete(vty, "peer", argv[idx_peer]->arg,
3202 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3203}
3204
fee0f4c6 3205
4c9bd275 3206/* match probability */
1add115a
VT
3207DEFUN (match_probability,
3208 match_probability_cmd,
6147e2c6 3209 "match probability (0-100)",
1add115a
VT
3210 MATCH_STR
3211 "Match portion of routes defined by percentage value\n"
3212 "Percentage of routes\n")
3213{
d62a17ae 3214 int idx_number = 2;
3215 return bgp_route_match_add(vty, "probability", argv[idx_number]->arg,
3216 RMAP_EVENT_MATCH_ADDED);
1add115a
VT
3217}
3218
4c9bd275 3219
1add115a
VT
3220DEFUN (no_match_probability,
3221 no_match_probability_cmd,
4c9bd275 3222 "no match probability [(1-99)]",
1add115a
VT
3223 NO_STR
3224 MATCH_STR
4c9bd275
DW
3225 "Match portion of routes defined by percentage value\n"
3226 "Percentage of routes\n")
1add115a 3227{
d62a17ae 3228 int idx_number = 3;
3229 if (argc <= idx_number)
3230 return bgp_route_match_delete(vty, "probability", NULL,
3231 RMAP_EVENT_MATCH_DELETED);
3232 return bgp_route_match_delete(vty, "probability", argv[idx_number]->arg,
3233 RMAP_EVENT_MATCH_DELETED);
1add115a
VT
3234}
3235
1add115a 3236
f412b39a 3237DEFUN (match_ip_route_source,
c1643bb7 3238 match_ip_route_source_cmd,
6147e2c6 3239 "match ip route-source <(1-199)|(1300-2699)|WORD>",
c1643bb7 3240 MATCH_STR
3241 IP_STR
3242 "Match advertising source address of route\n"
3243 "IP access-list number\n"
3244 "IP access-list number (expanded range)\n"
3245 "IP standard access-list name\n")
3246{
d62a17ae 3247 int idx_acl = 3;
3248 return bgp_route_match_add(vty, "ip route-source", argv[idx_acl]->arg,
3249 RMAP_EVENT_FILTER_ADDED);
c1643bb7 3250}
3251
4c9bd275 3252
c1643bb7 3253DEFUN (no_match_ip_route_source,
3254 no_match_ip_route_source_cmd,
6de69f83 3255 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
c1643bb7 3256 NO_STR
3257 MATCH_STR
3258 IP_STR
4c9bd275
DW
3259 "Match advertising source address of route\n"
3260 "IP access-list number\n"
3261 "IP access-list number (expanded range)\n"
3262 "IP standard access-list name\n")
c1643bb7 3263{
d62a17ae 3264 int idx_number = 4;
3265 if (argc <= idx_number)
3266 return bgp_route_match_delete(vty, "ip route-source", NULL,
3267 RMAP_EVENT_FILTER_DELETED);
3268 return bgp_route_match_delete(vty, "ip route-source",
3269 argv[idx_number]->arg,
3270 RMAP_EVENT_FILTER_DELETED);
c1643bb7 3271}
3272
c1643bb7 3273
f412b39a 3274DEFUN (match_ip_route_source_prefix_list,
c1643bb7 3275 match_ip_route_source_prefix_list_cmd,
3276 "match ip route-source prefix-list WORD",
3277 MATCH_STR
3278 IP_STR
3279 "Match advertising source address of route\n"
3280 "Match entries of prefix-lists\n"
3281 "IP prefix-list name\n")
3282{
d62a17ae 3283 int idx_word = 4;
3284 return bgp_route_match_add(vty, "ip route-source prefix-list",
3285 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
c1643bb7 3286}
3287
4c9bd275 3288
c1643bb7 3289DEFUN (no_match_ip_route_source_prefix_list,
3290 no_match_ip_route_source_prefix_list_cmd,
4c9bd275 3291 "no match ip route-source prefix-list [WORD]",
c1643bb7 3292 NO_STR
3293 MATCH_STR
3294 IP_STR
3295 "Match advertising source address of route\n"
4c9bd275
DW
3296 "Match entries of prefix-lists\n"
3297 "IP prefix-list name\n")
c1643bb7 3298{
d62a17ae 3299 int idx_word = 5;
3300 if (argc <= idx_word)
3301 return bgp_route_match_delete(vty,
3302 "ip route-source prefix-list",
3303 NULL, RMAP_EVENT_PLIST_DELETED);
3304 return bgp_route_match_delete(vty, "ip route-source prefix-list",
3305 argv[idx_word]->arg,
3306 RMAP_EVENT_PLIST_DELETED);
c1643bb7 3307}
3308
c1643bb7 3309
af291c15
DS
3310DEFUN (match_local_pref,
3311 match_local_pref_cmd,
6147e2c6 3312 "match local-preference (0-4294967295)",
af291c15
DS
3313 MATCH_STR
3314 "Match local-preference of route\n"
3315 "Metric value\n")
3316{
d62a17ae 3317 int idx_number = 2;
3318 return bgp_route_match_add(vty, "local-preference",
3319 argv[idx_number]->arg,
3320 RMAP_EVENT_MATCH_ADDED);
af291c15
DS
3321}
3322
4c9bd275 3323
af291c15
DS
3324DEFUN (no_match_local_pref,
3325 no_match_local_pref_cmd,
4c9bd275 3326 "no match local-preference [(0-4294967295)]",
af291c15
DS
3327 NO_STR
3328 MATCH_STR
4c9bd275
DW
3329 "Match local preference of route\n"
3330 "Local preference value\n")
af291c15 3331{
d62a17ae 3332 int idx_localpref = 3;
3333 if (argc <= idx_localpref)
3334 return bgp_route_match_delete(vty, "local-preference", NULL,
3335 RMAP_EVENT_MATCH_DELETED);
3336 return bgp_route_match_delete(vty, "local-preference",
3337 argv[idx_localpref]->arg,
3338 RMAP_EVENT_MATCH_DELETED);
af291c15
DS
3339}
3340
af291c15 3341
f412b39a 3342DEFUN (match_community,
718e3744 3343 match_community_cmd,
0d702986 3344 "match community <(1-99)|(100-500)|WORD> [exact-match]",
718e3744 3345 MATCH_STR
3346 "Match BGP community list\n"
3347 "Community-list number (standard)\n"
3348 "Community-list number (expanded)\n"
3349 "Community-list name\n"
3350 "Do exact matching of communities\n")
3351{
d62a17ae 3352 int idx_comm_list = 2;
3353 int ret;
3354 char *argstr;
718e3744 3355
d62a17ae 3356 if (argc == 4) {
3357 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
3358 strlen(argv[idx_comm_list]->arg)
3359 + strlen("exact-match") + 2);
718e3744 3360
d62a17ae 3361 sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
3362 } else
3363 argstr = argv[idx_comm_list]->arg;
718e3744 3364
d62a17ae 3365 ret = bgp_route_match_add(vty, "community", argstr,
3366 RMAP_EVENT_CLIST_ADDED);
718e3744 3367
d62a17ae 3368 if (argstr != argv[idx_comm_list]->arg)
3369 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 3370
d62a17ae 3371 return ret;
718e3744 3372}
3373
3374DEFUN (no_match_community,
3375 no_match_community_cmd,
4c9bd275 3376 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
718e3744 3377 NO_STR
3378 MATCH_STR
4c9bd275
DW
3379 "Match BGP community list\n"
3380 "Community-list number (standard)\n"
3381 "Community-list number (expanded)\n"
3382 "Community-list name\n"
3383 "Do exact matching of communities\n")
718e3744 3384{
d62a17ae 3385 return bgp_route_match_delete(vty, "community", NULL,
3386 RMAP_EVENT_CLIST_DELETED);
718e3744 3387}
3388
57d187bc
JS
3389DEFUN (match_lcommunity,
3390 match_lcommunity_cmd,
0d702986 3391 "match large-community <(1-99)|(100-500)|WORD>",
57d187bc
JS
3392 MATCH_STR
3393 "Match BGP large community list\n"
3394 "Large Community-list number (standard)\n"
3395 "Large Community-list number (expanded)\n"
3396 "Large Community-list name\n")
3397{
d62a17ae 3398 return bgp_route_match_add(vty, "large-community", argv[2]->arg,
3399 RMAP_EVENT_LLIST_ADDED);
57d187bc 3400}
718e3744 3401
57d187bc
JS
3402DEFUN (no_match_lcommunity,
3403 no_match_lcommunity_cmd,
52951b63 3404 "no match large-community [<(1-99)|(100-500)|WORD>]",
57d187bc
JS
3405 NO_STR
3406 MATCH_STR
3407 "Match BGP large community list\n"
3408 "Large Community-list number (standard)\n"
3409 "Large Community-list number (expanded)\n"
3410 "Large Community-list name\n")
3411{
d62a17ae 3412 return bgp_route_match_delete(vty, "large-community", NULL,
3413 RMAP_EVENT_LLIST_DELETED);
57d187bc 3414}
718e3744 3415
f412b39a 3416DEFUN (match_ecommunity,
73ffb25b 3417 match_ecommunity_cmd,
6147e2c6 3418 "match extcommunity <(1-99)|(100-500)|WORD>",
73ffb25b 3419 MATCH_STR
3420 "Match BGP/VPN extended community list\n"
3421 "Extended community-list number (standard)\n"
3422 "Extended community-list number (expanded)\n"
3423 "Extended community-list name\n")
3424{
d62a17ae 3425 int idx_comm_list = 2;
3426 return bgp_route_match_add(vty, "extcommunity",
3427 argv[idx_comm_list]->arg,
3428 RMAP_EVENT_ECLIST_ADDED);
73ffb25b 3429}
3430
4c9bd275 3431
73ffb25b 3432DEFUN (no_match_ecommunity,
3433 no_match_ecommunity_cmd,
4c9bd275 3434 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
73ffb25b 3435 NO_STR
3436 MATCH_STR
4c9bd275
DW
3437 "Match BGP/VPN extended community list\n"
3438 "Extended community-list number (standard)\n"
3439 "Extended community-list number (expanded)\n"
3440 "Extended community-list name\n")
73ffb25b 3441{
d62a17ae 3442 return bgp_route_match_delete(vty, "extcommunity", NULL,
3443 RMAP_EVENT_ECLIST_DELETED);
73ffb25b 3444}
3445
73ffb25b 3446
718e3744 3447DEFUN (match_aspath,
3448 match_aspath_cmd,
3449 "match as-path WORD",
3450 MATCH_STR
3451 "Match BGP AS path list\n"
3452 "AS path access-list name\n")
3453{
d62a17ae 3454 int idx_word = 2;
3455 return bgp_route_match_add(vty, "as-path", argv[idx_word]->arg,
3456 RMAP_EVENT_ASLIST_ADDED);
718e3744 3457}
3458
4c9bd275 3459
718e3744 3460DEFUN (no_match_aspath,
3461 no_match_aspath_cmd,
4c9bd275 3462 "no match as-path [WORD]",
718e3744 3463 NO_STR
3464 MATCH_STR
4c9bd275
DW
3465 "Match BGP AS path list\n"
3466 "AS path access-list name\n")
718e3744 3467{
d62a17ae 3468 return bgp_route_match_delete(vty, "as-path", NULL,
3469 RMAP_EVENT_ASLIST_DELETED);
718e3744 3470}
3471
718e3744 3472
3473DEFUN (match_origin,
3474 match_origin_cmd,
6147e2c6 3475 "match origin <egp|igp|incomplete>",
718e3744 3476 MATCH_STR
3477 "BGP origin code\n"
3478 "remote EGP\n"
3479 "local IGP\n"
3480 "unknown heritage\n")
3481{
d62a17ae 3482 int idx_origin = 2;
3483 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
3484 return bgp_route_match_add(vty, "origin", "igp",
3485 RMAP_EVENT_MATCH_ADDED);
3486 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
3487 return bgp_route_match_add(vty, "origin", "egp",
3488 RMAP_EVENT_MATCH_ADDED);
3489 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
3490 return bgp_route_match_add(vty, "origin", "incomplete",
3491 RMAP_EVENT_MATCH_ADDED);
718e3744 3492
d62a17ae 3493 vty_out(vty, "%% Invalid match origin type\n");
3494 return CMD_WARNING_CONFIG_FAILED;
718e3744 3495}
3496
4c9bd275 3497
718e3744 3498DEFUN (no_match_origin,
3499 no_match_origin_cmd,
4c9bd275 3500 "no match origin [<egp|igp|incomplete>]",
718e3744 3501 NO_STR
3502 MATCH_STR
4c9bd275
DW
3503 "BGP origin code\n"
3504 "remote EGP\n"
3505 "local IGP\n"
3506 "unknown heritage\n")
718e3744 3507{
d62a17ae 3508 return bgp_route_match_delete(vty, "origin", NULL,
3509 RMAP_EVENT_MATCH_DELETED);
718e3744 3510}
3511
af5cd0a5 3512DEFUN (set_ip_nexthop_peer,
3513 set_ip_nexthop_peer_cmd,
89602edb
QY
3514 "[no] set ip next-hop peer-address",
3515 NO_STR
af5cd0a5 3516 SET_STR
3517 IP_STR
3518 "Next hop address\n"
3519 "Use peer address (for BGP only)\n")
3520{
89602edb
QY
3521 int (*func)(struct vty *, struct route_map_index *, const char *,
3522 const char *) = strmatch(argv[0]->text, "no")
3523 ? generic_set_delete
3524 : generic_set_add;
3525
3526 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
3527 "peer-address");
af5cd0a5 3528}
3529
316e074d
DS
3530DEFUN (set_ip_nexthop_unchanged,
3531 set_ip_nexthop_unchanged_cmd,
cca30ba8
QY
3532 "[no] set ip next-hop unchanged",
3533 NO_STR
316e074d
DS
3534 SET_STR
3535 IP_STR
3536 "Next hop address\n"
3537 "Don't modify existing Next hop address\n")
3538{
cca30ba8
QY
3539 int (*func)(struct vty *, struct route_map_index *, const char *,
3540 const char *) = strmatch(argv[0]->text, "no")
3541 ? generic_set_delete
3542 : generic_set_add;
3543
3544 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
3545 "unchanged");
718e3744 3546}
3547
718e3744 3548
3549DEFUN (set_local_pref,
3550 set_local_pref_cmd,
6147e2c6 3551 "set local-preference (0-4294967295)",
718e3744 3552 SET_STR
3553 "BGP local preference path attribute\n"
3554 "Preference value\n")
3555{
d62a17ae 3556 int idx_number = 2;
3557 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3558 "local-preference", argv[idx_number]->arg);
718e3744 3559}
3560
4c9bd275 3561
718e3744 3562DEFUN (no_set_local_pref,
3563 no_set_local_pref_cmd,
4c9bd275 3564 "no set local-preference [(0-4294967295)]",
718e3744 3565 NO_STR
3566 SET_STR
4c9bd275
DW
3567 "BGP local preference path attribute\n"
3568 "Preference value\n")
718e3744 3569{
d62a17ae 3570 int idx_localpref = 3;
3571 if (argc <= idx_localpref)
3572 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3573 "local-preference", NULL);
3574 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3575 "local-preference", argv[idx_localpref]->arg);
718e3744 3576}
3577
718e3744 3578
3579DEFUN (set_weight,
3580 set_weight_cmd,
6147e2c6 3581 "set weight (0-4294967295)",
718e3744 3582 SET_STR
3583 "BGP weight for routing table\n"
3584 "Weight value\n")
3585{
d62a17ae 3586 int idx_number = 2;
3587 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "weight",
3588 argv[idx_number]->arg);
718e3744 3589}
3590
4c9bd275 3591
718e3744 3592DEFUN (no_set_weight,
3593 no_set_weight_cmd,
4c9bd275 3594 "no set weight [(0-4294967295)]",
718e3744 3595 NO_STR
3596 SET_STR
4c9bd275
DW
3597 "BGP weight for routing table\n"
3598 "Weight value\n")
718e3744 3599{
d62a17ae 3600 int idx_weight = 3;
3601 if (argc <= idx_weight)
3602 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3603 "weight", NULL);
3604 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3605 "weight", argv[idx_weight]->arg);
718e3744 3606}
3607
d990e384
DS
3608DEFUN (set_label_index,
3609 set_label_index_cmd,
8b81993e 3610 "set label-index (0-1048560)",
d990e384
DS
3611 SET_STR
3612 "Label index to associate with the prefix\n"
3613 "Label index value\n")
3614{
d62a17ae 3615 int idx_number = 2;
3616 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3617 "label-index", argv[idx_number]->arg);
d990e384
DS
3618}
3619
3620DEFUN (no_set_label_index,
3621 no_set_label_index_cmd,
8b81993e 3622 "no set label-index [(0-1048560)]",
d990e384
DS
3623 NO_STR
3624 SET_STR
3625 "Label index to associate with the prefix\n"
3626 "Label index value\n")
3627{
d62a17ae 3628 int idx_label_index = 3;
3629 if (argc <= idx_label_index)
3630 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3631 "label-index", NULL);
3632 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3633 "label-index", argv[idx_label_index]->arg);
d990e384 3634}
718e3744 3635
12dcf78e
QY
3636DEFUN (set_aspath_prepend_asn,
3637 set_aspath_prepend_asn_cmd,
3638 "set as-path prepend (1-4294967295)...",
718e3744 3639 SET_STR
841f7a57 3640 "Transform BGP AS_PATH attribute\n"
718e3744 3641 "Prepend to the as-path\n"
12dcf78e 3642 "AS number\n")
718e3744 3643{
d62a17ae 3644 int idx_asn = 3;
3645 int ret;
3646 char *str;
718e3744 3647
d62a17ae 3648 str = argv_concat(argv, argc, idx_asn);
3649 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3650 "as-path prepend", str);
3651 XFREE(MTYPE_TMP, str);
718e3744 3652
d62a17ae 3653 return ret;
718e3744 3654}
3655
12dcf78e
QY
3656DEFUN (set_aspath_prepend_lastas,
3657 set_aspath_prepend_lastas_cmd,
b6ab2929 3658 "set as-path prepend last-as (1-10)",
12dcf78e
QY
3659 SET_STR
3660 "Transform BGP AS_PATH attribute\n"
3661 "Prepend to the as-path\n"
3662 "Use the peer's AS-number\n"
b6ab2929 3663 "Number of times to insert\n")
12dcf78e 3664{
d62a17ae 3665 return set_aspath_prepend_asn(self, vty, argc, argv);
12dcf78e 3666}
bc3dd427 3667
718e3744 3668DEFUN (no_set_aspath_prepend,
3669 no_set_aspath_prepend_cmd,
a4b2b610 3670 "no set as-path prepend [(1-4294967295)]",
718e3744 3671 NO_STR
3672 SET_STR
841f7a57 3673 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
3674 "Prepend to the as-path\n"
3675 "AS number\n")
718e3744 3676{
d62a17ae 3677 int idx_asn = 4;
3678 int ret;
3679 char *str;
a7f93f3e 3680
d62a17ae 3681 str = argv_concat(argv, argc, idx_asn);
3682 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3683 "as-path prepend", str);
3684 XFREE(MTYPE_TMP, str);
3685 return ret;
718e3744 3686}
3687
718e3744 3688
841f7a57
DO
3689DEFUN (set_aspath_exclude,
3690 set_aspath_exclude_cmd,
a4b2b610 3691 "set as-path exclude (1-4294967295)...",
841f7a57
DO
3692 SET_STR
3693 "Transform BGP AS-path attribute\n"
3694 "Exclude from the as-path\n"
3695 "AS number\n")
3696{
d62a17ae 3697 int idx_asn = 3;
3698 int ret;
3699 char *str;
841f7a57 3700
d62a17ae 3701 str = argv_concat(argv, argc, idx_asn);
3702 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3703 "as-path exclude", str);
3704 XFREE(MTYPE_TMP, str);
3705 return ret;
841f7a57
DO
3706}
3707
3708DEFUN (no_set_aspath_exclude,
3709 no_set_aspath_exclude_cmd,
a4b2b610 3710 "no set as-path exclude (1-4294967295)...",
841f7a57
DO
3711 NO_STR
3712 SET_STR
3713 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
3714 "Exclude from the as-path\n"
3715 "AS number\n")
841f7a57 3716{
d62a17ae 3717 int idx_asn = 4;
3718 int ret;
3719 char *str;
841f7a57 3720
d62a17ae 3721 str = argv_concat(argv, argc, idx_asn);
3722 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3723 "as-path exclude", str);
3724 XFREE(MTYPE_TMP, str);
3725 return ret;
841f7a57
DO
3726}
3727
841f7a57 3728
718e3744 3729DEFUN (set_community,
3730 set_community_cmd,
e961923c 3731 "set community AA:NN...",
718e3744 3732 SET_STR
3733 "BGP community attribute\n"
859d388e 3734 COMMUNITY_VAL_STR)
718e3744 3735{
d62a17ae 3736 int idx_aa_nn = 2;
3737 int i;
3738 int first = 0;
3739 int additive = 0;
3740 struct buffer *b;
3741 struct community *com = NULL;
3742 char *str;
3743 char *argstr;
3744 int ret;
3745
3746 b = buffer_new(1024);
3747
3748 for (i = idx_aa_nn; i < argc; i++) {
3749 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
3750 == 0) {
3751 additive = 1;
3752 continue;
3753 }
3754
3755 if (first)
3756 buffer_putc(b, ' ');
3757 else
3758 first = 1;
3759
3760 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
3761 == 0) {
3762 buffer_putstr(b, "internet");
3763 continue;
3764 }
3765 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
3766 == 0) {
3767 buffer_putstr(b, "local-AS");
3768 continue;
3769 }
3770 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
3771 && strncmp(argv[i]->arg, "no-advertise",
3772 strlen(argv[i]->arg))
3773 == 0) {
3774 buffer_putstr(b, "no-advertise");
3775 continue;
3776 }
3777 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
3778 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
3779 == 0) {
3780 buffer_putstr(b, "no-export");
3781 continue;
3782 }
7f323236
DW
3783 if (strncmp(argv[i]->arg, "graceful-shutdown", strlen(argv[i]->arg))
3784 == 0) {
3785 buffer_putstr(b, "graceful-shutdown");
3786 continue;
3787 }
d62a17ae 3788 buffer_putstr(b, argv[i]->arg);
3789 }
3790 buffer_putc(b, '\0');
3791
3792 /* Fetch result string then compile it to communities attribute. */
3793 str = buffer_getstr(b);
3794 buffer_free(b);
3795
3796 if (str) {
3797 com = community_str2com(str);
3798 XFREE(MTYPE_TMP, str);
3799 }
3800
3801 /* Can't compile user input into communities attribute. */
3802 if (!com) {
3803 vty_out(vty, "%% Malformed communities attribute\n");
3804 return CMD_WARNING_CONFIG_FAILED;
3805 }
3806
3807 /* Set communites attribute string. */
a69ea8ae 3808 str = community_str(com, false);
d62a17ae 3809
3810 if (additive) {
3811 argstr = XCALLOC(MTYPE_TMP,
3812 strlen(str) + strlen(" additive") + 1);
3813 strcpy(argstr, str);
3814 strcpy(argstr + strlen(str), " additive");
3815 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3816 "community", argstr);
3817 XFREE(MTYPE_TMP, argstr);
3818 } else
3819 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3820 "community", str);
3821
3822 community_free(com);
3823
3824 return ret;
718e3744 3825}
3826
3827DEFUN (set_community_none,
3828 set_community_none_cmd,
3829 "set community none",
3830 SET_STR
3831 "BGP community attribute\n"
3832 "No community attribute\n")
3833{
d62a17ae 3834 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3835 "community", "none");
718e3744 3836}
3837
3838DEFUN (no_set_community,
3839 no_set_community_cmd,
a4b2b610 3840 "no set community AA:NN...",
718e3744 3841 NO_STR
3842 SET_STR
d7fa34c1
QY
3843 "BGP community attribute\n"
3844 COMMUNITY_VAL_STR)
718e3744 3845{
d62a17ae 3846 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3847 "community", NULL);
718e3744 3848}
3849
718e3744 3850
718e3744 3851DEFUN (set_community_delete,
3852 set_community_delete_cmd,
6147e2c6 3853 "set comm-list <(1-99)|(100-500)|WORD> delete",
718e3744 3854 SET_STR
3855 "set BGP community list (for deletion)\n"
3856 "Community-list number (standard)\n"
5e3edbf5 3857 "Community-list number (expanded)\n"
718e3744 3858 "Community-list name\n"
3859 "Delete matching communities\n")
3860{
d62a17ae 3861 int idx_comm_list = 2;
3862 char *str;
718e3744 3863
d62a17ae 3864 str = XCALLOC(MTYPE_TMP,
3865 strlen(argv[idx_comm_list]->arg) + strlen(" delete") + 1);
3866 strcpy(str, argv[idx_comm_list]->arg);
3867 strcpy(str + strlen(argv[idx_comm_list]->arg), " delete");
718e3744 3868
d62a17ae 3869 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
3870 str);
718e3744 3871
d62a17ae 3872 XFREE(MTYPE_TMP, str);
3873 return CMD_SUCCESS;
718e3744 3874}
3875
3876DEFUN (no_set_community_delete,
3877 no_set_community_delete_cmd,
a4b2b610 3878 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
718e3744 3879 NO_STR
3880 SET_STR
d7fa34c1
QY
3881 "set BGP community list (for deletion)\n"
3882 "Community-list number (standard)\n"
3883 "Community-list number (expanded)\n"
3884 "Community-list name\n"
3885 "Delete matching communities\n")
718e3744 3886{
d62a17ae 3887 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3888 "comm-list", NULL);
718e3744 3889}
3890
57d187bc
JS
3891DEFUN (set_lcommunity,
3892 set_lcommunity_cmd,
3893 "set large-community AA:BB:CC...",
3894 SET_STR
3895 "BGP large community attribute\n"
3896 "Large Community number in aa:bb:cc format or additive\n")
3897{
d62a17ae 3898 int ret;
3899 char *str;
57d187bc 3900
d62a17ae 3901 str = argv_concat(argv, argc, 2);
3902 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3903 "large-community", str);
3904 XFREE(MTYPE_TMP, str);
57d187bc 3905
d62a17ae 3906 return ret;
57d187bc
JS
3907}
3908
3909DEFUN (set_lcommunity_none,
3910 set_lcommunity_none_cmd,
3911 "set large-community none",
3912 SET_STR
3913 "BGP large community attribute\n"
3914 "No large community attribute\n")
3915{
d62a17ae 3916 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3917 "large-community", "none");
57d187bc
JS
3918}
3919
3920DEFUN (no_set_lcommunity,
3921 no_set_lcommunity_cmd,
52951b63 3922 "no set large-community none",
57d187bc
JS
3923 NO_STR
3924 SET_STR
3925 "BGP large community attribute\n"
52951b63 3926 "No community attribute\n")
57d187bc 3927{
d62a17ae 3928 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3929 "large-community", NULL);
57d187bc
JS
3930}
3931
52951b63
DS
3932DEFUN (no_set_lcommunity1,
3933 no_set_lcommunity1_cmd,
3934 "no set large-community AA:BB:CC...",
3935 NO_STR
3936 SET_STR
3937 "BGP large community attribute\n"
3938 "Large community in AA:BB:CC... format or additive\n")
3939{
d62a17ae 3940 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3941 "large-community", NULL);
52951b63 3942}
57d187bc
JS
3943
3944DEFUN (set_lcommunity_delete,
3945 set_lcommunity_delete_cmd,
3946 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
3947 SET_STR
3948 "set BGP large community list (for deletion)\n"
3949 "Large Community-list number (standard)\n"
3950 "Large Communitly-list number (expanded)\n"
3951 "Large Community-list name\n"
3952 "Delete matching large communities\n")
3953{
d62a17ae 3954 char *str;
57d187bc 3955
d62a17ae 3956 str = XCALLOC(MTYPE_TMP, strlen(argv[2]->arg) + strlen(" delete") + 1);
3957 strcpy(str, argv[2]->arg);
3958 strcpy(str + strlen(argv[2]->arg), " delete");
57d187bc 3959
d62a17ae 3960 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3961 "large-comm-list", str);
57d187bc 3962
d62a17ae 3963 XFREE(MTYPE_TMP, str);
3964 return CMD_SUCCESS;
57d187bc
JS
3965}
3966
3967DEFUN (no_set_lcommunity_delete,
3968 no_set_lcommunity_delete_cmd,
db4f7086 3969 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
57d187bc
JS
3970 NO_STR
3971 SET_STR
3972 "set BGP large community list (for deletion)\n"
3973 "Large Community-list number (standard)\n"
3974 "Large Communitly-list number (expanded)\n"
3975 "Large Community-list name\n"
3976 "Delete matching large communities\n")
3977{
d62a17ae 3978 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3979 "large-comm-list", NULL);
57d187bc 3980}
718e3744 3981
3982DEFUN (set_ecommunity_rt,
3983 set_ecommunity_rt_cmd,
d114b977 3984 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 3985 SET_STR
3986 "BGP extended community attribute\n"
e6b6a564 3987 "Route Target extended community\n"
718e3744 3988 "VPN extended community\n")
3989{
d62a17ae 3990 int idx_asn_nn = 3;
3991 int ret;
3992 char *str;
718e3744 3993
d62a17ae 3994 str = argv_concat(argv, argc, idx_asn_nn);
3995 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3996 "extcommunity rt", str);
3997 XFREE(MTYPE_TMP, str);
718e3744 3998
d62a17ae 3999 return ret;
718e3744 4000}
4001
4002DEFUN (no_set_ecommunity_rt,
4003 no_set_ecommunity_rt_cmd,
d114b977 4004 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4005 NO_STR
4006 SET_STR
4007 "BGP extended community attribute\n"
3a2d747c
QY
4008 "Route Target extended community\n"
4009 "VPN extended community\n")
718e3744 4010{
d62a17ae 4011 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4012 "extcommunity rt", NULL);
718e3744 4013}
4014
718e3744 4015
4016DEFUN (set_ecommunity_soo,
4017 set_ecommunity_soo_cmd,
d114b977 4018 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4019 SET_STR
4020 "BGP extended community attribute\n"
4021 "Site-of-Origin extended community\n"
4022 "VPN extended community\n")
4023{
d62a17ae 4024 int idx_asn_nn = 3;
4025 int ret;
4026 char *str;
718e3744 4027
d62a17ae 4028 str = argv_concat(argv, argc, idx_asn_nn);
4029 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4030 "extcommunity soo", str);
4031 XFREE(MTYPE_TMP, str);
4032 return ret;
718e3744 4033}
4034
a4b2b610 4035
718e3744 4036DEFUN (no_set_ecommunity_soo,
4037 no_set_ecommunity_soo_cmd,
d114b977 4038 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4039 NO_STR
4040 SET_STR
4041 "BGP extended community attribute\n"
3a2d747c
QY
4042 "Site-of-Origin extended community\n"
4043 "VPN extended community\n")
718e3744 4044{
d62a17ae 4045 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4046 "extcommunity soo", NULL);
718e3744 4047}
4048
718e3744 4049
4050DEFUN (set_origin,
4051 set_origin_cmd,
6147e2c6 4052 "set origin <egp|igp|incomplete>",
718e3744 4053 SET_STR
4054 "BGP origin code\n"
4055 "remote EGP\n"
4056 "local IGP\n"
4057 "unknown heritage\n")
4058{
d62a17ae 4059 int idx_origin = 2;
4060 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
4061 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4062 "origin", "igp");
4063 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
4064 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4065 "origin", "egp");
4066 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
4067 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4068 "origin", "incomplete");
718e3744 4069
d62a17ae 4070 vty_out(vty, "%% Invalid set origin type\n");
4071 return CMD_WARNING_CONFIG_FAILED;
718e3744 4072}
4073
a4b2b610 4074
718e3744 4075DEFUN (no_set_origin,
4076 no_set_origin_cmd,
a4b2b610 4077 "no set origin [<egp|igp|incomplete>]",
718e3744 4078 NO_STR
4079 SET_STR
d7fa34c1
QY
4080 "BGP origin code\n"
4081 "remote EGP\n"
4082 "local IGP\n"
4083 "unknown heritage\n")
718e3744 4084{
d62a17ae 4085 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4086 "origin", NULL);
718e3744 4087}
4088
718e3744 4089
4090DEFUN (set_atomic_aggregate,
4091 set_atomic_aggregate_cmd,
4092 "set atomic-aggregate",
4093 SET_STR
4094 "BGP atomic aggregate attribute\n" )
4095{
d62a17ae 4096 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4097 "atomic-aggregate", NULL);
718e3744 4098}
4099
4100DEFUN (no_set_atomic_aggregate,
4101 no_set_atomic_aggregate_cmd,
4102 "no set atomic-aggregate",
4103 NO_STR
4104 SET_STR
4105 "BGP atomic aggregate attribute\n" )
4106{
d62a17ae 4107 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4108 "atomic-aggregate", NULL);
718e3744 4109}
4110
4111DEFUN (set_aggregator_as,
4112 set_aggregator_as_cmd,
9ccf14f7 4113 "set aggregator as (1-4294967295) A.B.C.D",
718e3744 4114 SET_STR
4115 "BGP aggregator attribute\n"
4116 "AS number of aggregator\n"
4117 "AS number\n"
4118 "IP address of aggregator\n")
4119{
d62a17ae 4120 int idx_number = 3;
4121 int idx_ipv4 = 4;
4122 int ret;
4123 struct in_addr address;
4124 char *argstr;
e52702f2 4125
d62a17ae 4126 ret = inet_aton(argv[idx_ipv4]->arg, &address);
4127 if (ret == 0) {
4128 vty_out(vty, "Aggregator IP address is invalid\n");
4129 return CMD_WARNING_CONFIG_FAILED;
4130 }
718e3744 4131
d62a17ae 4132 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4133 strlen(argv[idx_number]->arg)
4134 + strlen(argv[idx_ipv4]->arg) + 2);
718e3744 4135
d62a17ae 4136 sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
718e3744 4137
d62a17ae 4138 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4139 "aggregator as", argstr);
718e3744 4140
d62a17ae 4141 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 4142
d62a17ae 4143 return ret;
718e3744 4144}
4145
a4b2b610 4146
718e3744 4147DEFUN (no_set_aggregator_as,
4148 no_set_aggregator_as_cmd,
a4b2b610 4149 "no set aggregator as [(1-4294967295) A.B.C.D]",
718e3744 4150 NO_STR
4151 SET_STR
4152 "BGP aggregator attribute\n"
a4b2b610
DW
4153 "AS number of aggregator\n"
4154 "AS number\n"
4155 "IP address of aggregator\n")
718e3744 4156{
d62a17ae 4157 int idx_asn = 4;
4158 int idx_ip = 5;
4159 int ret;
4160 struct in_addr address;
4161 char *argstr;
718e3744 4162
d62a17ae 4163 if (argc <= idx_asn)
4164 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4165 "aggregator as", NULL);
e52702f2 4166
d62a17ae 4167 ret = inet_aton(argv[idx_ip]->arg, &address);
4168 if (ret == 0) {
4169 vty_out(vty, "Aggregator IP address is invalid\n");
4170 return CMD_WARNING_CONFIG_FAILED;
4171 }
718e3744 4172
d62a17ae 4173 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4174 strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
4175 + 2);
718e3744 4176
d62a17ae 4177 sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
718e3744 4178
d62a17ae 4179 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4180 "aggregator as", argstr);
718e3744 4181
d62a17ae 4182 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 4183
d62a17ae 4184 return ret;
718e3744 4185}
4186
f412b39a 4187DEFUN (match_ipv6_next_hop,
718e3744 4188 match_ipv6_next_hop_cmd,
4189 "match ipv6 next-hop X:X::X:X",
4190 MATCH_STR
4191 IPV6_STR
4192 "Match IPv6 next-hop address of route\n"
4193 "IPv6 address of next hop\n")
4194{
d62a17ae 4195 int idx_ipv6 = 3;
4196 return bgp_route_match_add(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
4197 RMAP_EVENT_MATCH_ADDED);
718e3744 4198}
4199
4200DEFUN (no_match_ipv6_next_hop,
4201 no_match_ipv6_next_hop_cmd,
4202 "no match ipv6 next-hop X:X::X:X",
4203 NO_STR
4204 MATCH_STR
4205 IPV6_STR
4206 "Match IPv6 next-hop address of route\n"
4207 "IPv6 address of next hop\n")
4208{
d62a17ae 4209 int idx_ipv6 = 4;
4210 return bgp_route_match_delete(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
4211 RMAP_EVENT_MATCH_DELETED);
718e3744 4212}
4213
718e3744 4214
90916ac2
DS
4215DEFUN (set_ipv6_nexthop_peer,
4216 set_ipv6_nexthop_peer_cmd,
4217 "set ipv6 next-hop peer-address",
4218 SET_STR
4219 IPV6_STR
4220 "Next hop address\n"
4221 "Use peer address (for BGP only)\n")
4222{
d62a17ae 4223 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4224 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4225}
4226
4227DEFUN (no_set_ipv6_nexthop_peer,
4228 no_set_ipv6_nexthop_peer_cmd,
4229 "no set ipv6 next-hop peer-address",
4230 NO_STR
4231 SET_STR
4232 IPV6_STR
4233 "IPv6 next-hop address\n"
161995ea 4234 "Use peer address (for BGP only)\n")
90916ac2 4235{
d62a17ae 4236 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4237 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4238}
4239
161995ea
DS
4240DEFUN (set_ipv6_nexthop_prefer_global,
4241 set_ipv6_nexthop_prefer_global_cmd,
4242 "set ipv6 next-hop prefer-global",
4243 SET_STR
4244 IPV6_STR
4245 "IPv6 next-hop address\n"
4246 "Prefer global over link-local if both exist\n")
4247{
d62a17ae 4248 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4249 "ipv6 next-hop prefer-global", NULL);
4250 ;
161995ea
DS
4251}
4252
4253DEFUN (no_set_ipv6_nexthop_prefer_global,
4254 no_set_ipv6_nexthop_prefer_global_cmd,
4255 "no set ipv6 next-hop prefer-global",
4256 NO_STR
4257 SET_STR
4258 IPV6_STR
4259 "IPv6 next-hop address\n"
4260 "Prefer global over link-local if both exist\n")
4261{
d62a17ae 4262 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4263 "ipv6 next-hop prefer-global", NULL);
161995ea
DS
4264}
4265
718e3744 4266DEFUN (set_ipv6_nexthop_global,
4267 set_ipv6_nexthop_global_cmd,
4268 "set ipv6 next-hop global X:X::X:X",
4269 SET_STR
4270 IPV6_STR
4271 "IPv6 next-hop address\n"
4272 "IPv6 global address\n"
4273 "IPv6 address of next hop\n")
4274{
d62a17ae 4275 int idx_ipv6 = 4;
4276 struct in6_addr addr;
4277 int ret;
bf8b3d27 4278
d62a17ae 4279 ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr);
4280 if (!ret) {
4281 vty_out(vty, "%% Malformed nexthop address\n");
4282 return CMD_WARNING_CONFIG_FAILED;
4283 }
4284 if (IN6_IS_ADDR_UNSPECIFIED(&addr) || IN6_IS_ADDR_LOOPBACK(&addr)
4285 || IN6_IS_ADDR_MULTICAST(&addr) || IN6_IS_ADDR_LINKLOCAL(&addr)) {
4286 vty_out(vty, "%% Invalid global nexthop address\n");
4287 return CMD_WARNING_CONFIG_FAILED;
4288 }
bf8b3d27 4289
d62a17ae 4290 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4291 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 4292}
4293
a4b2b610 4294
718e3744 4295DEFUN (no_set_ipv6_nexthop_global,
4296 no_set_ipv6_nexthop_global_cmd,
a4b2b610 4297 "no set ipv6 next-hop global X:X::X:X",
718e3744 4298 NO_STR
4299 SET_STR
4300 IPV6_STR
4301 "IPv6 next-hop address\n"
a4b2b610
DW
4302 "IPv6 global address\n"
4303 "IPv6 address of next hop\n")
718e3744 4304{
d62a17ae 4305 int idx_ipv6 = 5;
4306 if (argc <= idx_ipv6)
4307 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4308 "ipv6 next-hop global", NULL);
4309 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4310 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 4311}
718e3744 4312
d6902373
PG
4313#ifdef KEEP_OLD_VPN_COMMANDS
4314DEFUN (set_vpn_nexthop,
4315 set_vpn_nexthop_cmd,
a13c883e 4316 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 4317 SET_STR
4318 "VPNv4 information\n"
d6902373
PG
4319 "VPN next-hop address\n"
4320 "IP address of next hop\n"
a13c883e
QY
4321 "VPNv6 information\n"
4322 "VPN next-hop address\n"
d6902373 4323 "IPv6 address of next hop\n")
718e3744 4324{
d62a17ae 4325 int idx_ip = 3;
4326 afi_t afi;
4327 int idx = 0;
4328
4329 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
4330 if (afi == AFI_IP)
4331 return generic_set_add(
4332 vty, VTY_GET_CONTEXT(route_map_index),
4333 "ipv4 vpn next-hop", argv[idx_ip]->arg);
4334 else
4335 return generic_set_add(
4336 vty, VTY_GET_CONTEXT(route_map_index),
4337 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4338 }
4339 return CMD_SUCCESS;
d6902373 4340}
a4b2b610 4341
d6902373
PG
4342DEFUN (no_set_vpn_nexthop,
4343 no_set_vpn_nexthop_cmd,
a13c883e 4344 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 4345 NO_STR
4346 SET_STR
a13c883e 4347 "VPNv4 information\n"
d6902373
PG
4348 "VPN next-hop address\n"
4349 "IP address of next hop\n"
a13c883e
QY
4350 "VPNv6 information\n"
4351 "VPN next-hop address\n"
d6902373 4352 "IPv6 address of next hop\n")
718e3744 4353{
d62a17ae 4354 int idx_ip = 4;
4355 char *arg;
4356 afi_t afi;
4357 int idx = 0;
4358
4359 if (argc <= idx_ip)
4360 arg = NULL;
4361 else
4362 arg = argv[idx_ip]->arg;
4363 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
4364 if (afi == AFI_IP)
4365 return generic_set_delete(
4366 vty, VTY_GET_CONTEXT(route_map_index),
4367 "ipv4 vpn next-hop", arg);
4368 else
4369 return generic_set_delete(
4370 vty, VTY_GET_CONTEXT(route_map_index),
4371 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4372 }
4373 return CMD_SUCCESS;
d6902373
PG
4374}
4375#endif /* KEEP_OLD_VPN_COMMANDS */
4376
4377DEFUN (set_ipx_vpn_nexthop,
4378 set_ipx_vpn_nexthop_cmd,
0d702986 4379 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
d6902373
PG
4380 SET_STR
4381 "IPv4 information\n"
4382 "IPv6 information\n"
4383 "VPN information\n"
4384 "VPN next-hop address\n"
4385 "IP address of next hop\n"
4386 "IPv6 address of next hop\n")
4387{
d62a17ae 4388 int idx_ip = 4;
4389 afi_t afi;
4390 int idx = 0;
4391
4392 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
4393 if (afi == AFI_IP)
4394 return generic_set_add(
4395 vty, VTY_GET_CONTEXT(route_map_index),
4396 "ipv4 vpn next-hop", argv[idx_ip]->arg);
4397 else
4398 return generic_set_add(
4399 vty, VTY_GET_CONTEXT(route_map_index),
4400 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4401 }
4402 return CMD_SUCCESS;
718e3744 4403}
4404
d6902373
PG
4405DEFUN (no_set_ipx_vpn_nexthop,
4406 no_set_ipx_vpn_nexthop_cmd,
9fa4d336 4407 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
d6902373
PG
4408 NO_STR
4409 SET_STR
4410 "IPv4 information\n"
4411 "IPv6 information\n"
4412 "VPN information\n"
4413 "VPN next-hop address\n"
4414 "IP address of next hop\n"
4415 "IPv6 address of next hop\n")
4416{
d62a17ae 4417 int idx_ip = 5;
4418 char *arg;
4419 afi_t afi;
4420 int idx = 0;
4421
4422 if (argc <= idx_ip)
4423 arg = NULL;
4424 else
4425 arg = argv[idx_ip]->arg;
4426 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
4427 if (afi == AFI_IP)
4428 return generic_set_delete(
4429 vty, VTY_GET_CONTEXT(route_map_index),
4430 "ipv4 vpn next-hop", arg);
4431 else
4432 return generic_set_delete(
4433 vty, VTY_GET_CONTEXT(route_map_index),
4434 "ipv6 vpn next-hop", arg);
4435 }
4436 return CMD_SUCCESS;
d6902373 4437}
718e3744 4438
4439DEFUN (set_originator_id,
4440 set_originator_id_cmd,
4441 "set originator-id A.B.C.D",
4442 SET_STR
4443 "BGP originator ID attribute\n"
4444 "IP address of originator\n")
4445{
d62a17ae 4446 int idx_ipv4 = 2;
4447 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4448 "originator-id", argv[idx_ipv4]->arg);
718e3744 4449}
4450
4c9bd275 4451
718e3744 4452DEFUN (no_set_originator_id,
4453 no_set_originator_id_cmd,
4c9bd275 4454 "no set originator-id [A.B.C.D]",
718e3744 4455 NO_STR
4456 SET_STR
4c9bd275
DW
4457 "BGP originator ID attribute\n"
4458 "IP address of originator\n")
718e3744 4459{
d62a17ae 4460 int idx = 0;
4461 char *arg =
4462 argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
0d702986 4463
d62a17ae 4464 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4465 "originator-id", arg);
718e3744 4466}
4467
718e3744 4468
718e3744 4469/* Initialization of route map. */
d62a17ae 4470void bgp_route_map_init(void)
4471{
4472 route_map_init();
4473
4474 route_map_add_hook(bgp_route_map_add);
4475 route_map_delete_hook(bgp_route_map_delete);
4476 route_map_event_hook(bgp_route_map_event);
4477
4478 route_map_match_interface_hook(generic_match_add);
4479 route_map_no_match_interface_hook(generic_match_delete);
4480
4481 route_map_match_ip_address_hook(generic_match_add);
4482 route_map_no_match_ip_address_hook(generic_match_delete);
4483
4484 route_map_match_ip_address_prefix_list_hook(generic_match_add);
4485 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
4486
4487 route_map_match_ip_next_hop_hook(generic_match_add);
4488 route_map_no_match_ip_next_hop_hook(generic_match_delete);
4489
4490 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
4491 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
4492
4493 route_map_match_ipv6_address_hook(generic_match_add);
4494 route_map_no_match_ipv6_address_hook(generic_match_delete);
4495
4496 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
4497 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
4498
4499 route_map_match_metric_hook(generic_match_add);
4500 route_map_no_match_metric_hook(generic_match_delete);
4501
4502 route_map_match_tag_hook(generic_match_add);
4503 route_map_no_match_tag_hook(generic_match_delete);
4504
4505 route_map_set_ip_nexthop_hook(generic_set_add);
4506 route_map_no_set_ip_nexthop_hook(generic_set_delete);
4507
4508 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
4509 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
4510
4511 route_map_set_metric_hook(generic_set_add);
4512 route_map_no_set_metric_hook(generic_set_delete);
4513
4514 route_map_set_tag_hook(generic_set_add);
4515 route_map_no_set_tag_hook(generic_set_delete);
4516
4517 route_map_install_match(&route_match_peer_cmd);
4518 route_map_install_match(&route_match_local_pref_cmd);
4519 route_map_install_match(&route_match_ip_address_cmd);
4520 route_map_install_match(&route_match_ip_next_hop_cmd);
4521 route_map_install_match(&route_match_ip_route_source_cmd);
4522 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
4523 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
4524 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
4525 route_map_install_match(&route_match_aspath_cmd);
4526 route_map_install_match(&route_match_community_cmd);
4527 route_map_install_match(&route_match_lcommunity_cmd);
4528 route_map_install_match(&route_match_ecommunity_cmd);
4529 route_map_install_match(&route_match_local_pref_cmd);
4530 route_map_install_match(&route_match_metric_cmd);
4531 route_map_install_match(&route_match_origin_cmd);
4532 route_map_install_match(&route_match_probability_cmd);
4533 route_map_install_match(&route_match_interface_cmd);
4534 route_map_install_match(&route_match_tag_cmd);
d37ba549 4535 route_map_install_match(&route_match_mac_address_cmd);
16f7ce2b 4536 route_map_install_match(&route_match_evpn_vni_cmd);
d62a17ae 4537
4538 route_map_install_set(&route_set_ip_nexthop_cmd);
4539 route_map_install_set(&route_set_local_pref_cmd);
4540 route_map_install_set(&route_set_weight_cmd);
4541 route_map_install_set(&route_set_label_index_cmd);
4542 route_map_install_set(&route_set_metric_cmd);
4543 route_map_install_set(&route_set_aspath_prepend_cmd);
4544 route_map_install_set(&route_set_aspath_exclude_cmd);
4545 route_map_install_set(&route_set_origin_cmd);
4546 route_map_install_set(&route_set_atomic_aggregate_cmd);
4547 route_map_install_set(&route_set_aggregator_as_cmd);
4548 route_map_install_set(&route_set_community_cmd);
4549 route_map_install_set(&route_set_community_delete_cmd);
4550 route_map_install_set(&route_set_lcommunity_cmd);
4551 route_map_install_set(&route_set_lcommunity_delete_cmd);
4552 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
4553 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
4554 route_map_install_set(&route_set_originator_id_cmd);
4555 route_map_install_set(&route_set_ecommunity_rt_cmd);
4556 route_map_install_set(&route_set_ecommunity_soo_cmd);
4557 route_map_install_set(&route_set_tag_cmd);
4558 route_map_install_set(&route_set_label_index_cmd);
4559
4560 install_element(RMAP_NODE, &match_peer_cmd);
4561 install_element(RMAP_NODE, &match_peer_local_cmd);
4562 install_element(RMAP_NODE, &no_match_peer_cmd);
4563 install_element(RMAP_NODE, &match_ip_route_source_cmd);
4564 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
4565 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4566 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
d37ba549
MK
4567 install_element(RMAP_NODE, &match_mac_address_cmd);
4568 install_element(RMAP_NODE, &no_match_mac_address_cmd);
16f7ce2b
MK
4569 install_element(RMAP_NODE, &match_evpn_vni_cmd);
4570 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
d62a17ae 4571
4572 install_element(RMAP_NODE, &match_aspath_cmd);
4573 install_element(RMAP_NODE, &no_match_aspath_cmd);
4574 install_element(RMAP_NODE, &match_local_pref_cmd);
4575 install_element(RMAP_NODE, &no_match_local_pref_cmd);
4576 install_element(RMAP_NODE, &match_community_cmd);
4577 install_element(RMAP_NODE, &no_match_community_cmd);
4578 install_element(RMAP_NODE, &match_lcommunity_cmd);
4579 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
4580 install_element(RMAP_NODE, &match_ecommunity_cmd);
4581 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
4582 install_element(RMAP_NODE, &match_origin_cmd);
4583 install_element(RMAP_NODE, &no_match_origin_cmd);
4584 install_element(RMAP_NODE, &match_probability_cmd);
4585 install_element(RMAP_NODE, &no_match_probability_cmd);
4586
4587 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
4588 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
4589 install_element(RMAP_NODE, &set_local_pref_cmd);
4590 install_element(RMAP_NODE, &no_set_local_pref_cmd);
4591 install_element(RMAP_NODE, &set_weight_cmd);
4592 install_element(RMAP_NODE, &set_label_index_cmd);
4593 install_element(RMAP_NODE, &no_set_weight_cmd);
4594 install_element(RMAP_NODE, &no_set_label_index_cmd);
4595 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
4596 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
4597 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
4598 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
4599 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
4600 install_element(RMAP_NODE, &set_origin_cmd);
4601 install_element(RMAP_NODE, &no_set_origin_cmd);
4602 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
4603 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
4604 install_element(RMAP_NODE, &set_aggregator_as_cmd);
4605 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
4606 install_element(RMAP_NODE, &set_community_cmd);
4607 install_element(RMAP_NODE, &set_community_none_cmd);
4608 install_element(RMAP_NODE, &no_set_community_cmd);
4609 install_element(RMAP_NODE, &set_community_delete_cmd);
4610 install_element(RMAP_NODE, &no_set_community_delete_cmd);
4611 install_element(RMAP_NODE, &set_lcommunity_cmd);
4612 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
4613 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
4614 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
4615 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
4616 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
4617 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
4618 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4619 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
4620 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
d6902373 4621#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 4622 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
4623 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
d6902373 4624#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 4625 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
4626 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
4627 install_element(RMAP_NODE, &set_originator_id_cmd);
4628 install_element(RMAP_NODE, &no_set_originator_id_cmd);
4629
4630 route_map_install_match(&route_match_ipv6_address_cmd);
4631 route_map_install_match(&route_match_ipv6_next_hop_cmd);
4632 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
4633 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
4634 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
4635 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
4636 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
4637
4638 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
4639 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
4640 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
4641 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
4642 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
4643 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
4644 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
4645 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
4646}
4647
4648void bgp_route_map_terminate(void)
4649{
4650 /* ToDo: Cleanup all the used memory */
4651
4652 route_map_add_hook(NULL);
4653 route_map_delete_hook(NULL);
4654 route_map_event_hook(NULL);
4655 route_map_finish();
518f0eb1 4656}