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