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