]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
OSPF: remove deprecated commands
[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
952 ifp = if_lookup_by_name ((char *)rule);
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 */
518f0eb1 2807static int
ffd0c037 2808bgp_route_map_process_update (void *arg, 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;
2816 struct bgp *bgp = (struct bgp *)arg;
2817 struct listnode *node, *nnode;
a6e0d253 2818 struct route_map *map;
518f0eb1
DS
2819 char buf[INET6_ADDRSTRLEN];
2820
2821 if (!bgp)
7c8ff89e 2822 return (-1);
518f0eb1 2823
a6e0d253
DW
2824 map = route_map_lookup_by_name (rmap_name);
2825
518f0eb1 2826 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 2827 {
518f0eb1
DS
2828
2829 /* Ignore dummy peer-group structure */
2830 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
2831 continue;
2832
718e3744 2833 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2834 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
518f0eb1
DS
2835 {
2836 /* Ignore inactive AFI/SAFI */
2837 if (! peer->afc[afi][safi])
2838 continue;
2839
3f9c7369 2840 /* process in/out/import/export/default-orig route-maps */
a6e0d253 2841 bgp_route_map_process_peer(rmap_name, map, peer, afi, safi, route_update);
518f0eb1 2842 }
718e3744 2843 }
2844
3f9c7369
DS
2845 /* for outbound/default-orig route-maps, process for groups */
2846 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
2847 route_update, 0);
2848
2849 /* update peer-group config (template) */
a6e0d253 2850 bgp_route_map_update_peer_group(rmap_name, map, bgp);
518f0eb1 2851
518f0eb1
DS
2852 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2853 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2854 {
a6e0d253 2855 /* For table route-map updates. */
518f0eb1
DS
2856 if (bgp->table_map[afi][safi].name &&
2857 (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0))
2858 {
a6e0d253
DW
2859 bgp->table_map[afi][safi].map = map;
2860
16286195 2861 if (BGP_DEBUG (zebra, ZEBRA))
518f0eb1
DS
2862 zlog_debug("Processing route_map %s update on "
2863 "table map", rmap_name);
2864 if (route_update)
2865 bgp_zebra_announce_table(bgp, afi, safi);
2866 }
518f0eb1 2867
a6e0d253
DW
2868 /* For network route-map updates. */
2869 for (bn = bgp_table_top (bgp->route[afi][safi]); bn; bn = bgp_route_next (bn))
2870 if ((bgp_static = bn->info) != NULL)
2871 {
2872 if (bgp_static->rmap.name &&
2873 (strcmp(rmap_name, bgp_static->rmap.name) == 0))
2874 {
2875 bgp_static->rmap.map = map;
2876
2877 if (route_update)
2878 if (!bgp_static->backdoor)
2879 {
2880 if (bgp_debug_zebra(&bn->p))
2881 zlog_debug("Processing route_map %s update on "
2882 "static route %s", rmap_name,
2883 inet_ntop (bn->p.family, &bn->p.u.prefix,
2884 buf, INET6_ADDRSTRLEN));
2885 bgp_static_update (bgp, &bn->p, bgp_static, afi, safi);
2886 }
2887 }
2888 }
2889 }
518f0eb1 2890
718e3744 2891 /* For redistribute route-map updates. */
518f0eb1
DS
2892 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2893 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2894 {
7c8ff89e
DS
2895 struct list *red_list;
2896 struct listnode *node;
2897 struct bgp_redist *red;
2898
2899 red_list = bgp->redist[afi][i];
2900 if (!red_list)
2901 continue;
2902
2903 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
2904 {
2905 if (red->rmap.name &&
2906 (strcmp(rmap_name, red->rmap.name) == 0))
2907 {
a6e0d253 2908 red->rmap.map = map;
7c8ff89e
DS
2909
2910 if (route_update)
2911 {
3f9c7369 2912 if (BGP_DEBUG (zebra, ZEBRA))
7c8ff89e
DS
2913 zlog_debug("Processing route_map %s update on "
2914 "redistributed routes", rmap_name);
2915
2916 bgp_redistribute_resend (bgp, afi, i, red->instance);
2917 }
2918 }
518f0eb1
DS
2919 }
2920 }
2921
2922 return (0);
2923}
2924
2925static int
2926bgp_route_map_process_update_cb (void *arg, char *rmap_name)
2927{
2928 return bgp_route_map_process_update (arg, rmap_name, 1);
2929}
2930
2931int
2932bgp_route_map_update_timer(struct thread *thread)
2933{
2934 struct bgp *bgp = THREAD_ARG(thread);
2935
2936 bgp->t_rmap_update = NULL;
2937
518f0eb1
DS
2938 route_map_walk_update_list((void *)bgp, bgp_route_map_process_update_cb);
2939
518f0eb1
DS
2940 return (0);
2941}
2942
2943static void
ffd0c037 2944bgp_route_map_mark_update (const char *rmap_name)
518f0eb1
DS
2945{
2946 struct listnode *node, *nnode;
2947 struct bgp *bgp;
2948
2949 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
718e3744 2950 {
3f9c7369 2951
518f0eb1 2952 if (bgp->t_rmap_update == NULL)
718e3744 2953 {
518f0eb1
DS
2954 /* rmap_update_timer of 0 means don't do route updates */
2955 if (bgp->rmap_update_timer)
3f9c7369
DS
2956 {
2957 bgp->t_rmap_update =
9229d914 2958 thread_add_timer(bm->master, bgp_route_map_update_timer, bgp,
3f9c7369
DS
2959 bgp->rmap_update_timer);
2960 /* Signal the groups that a route-map update event has started */
2961 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name, 1, 1);
2962 }
518f0eb1
DS
2963 else
2964 bgp_route_map_process_update((void *)bgp, rmap_name, 0);
718e3744 2965 }
2966 }
2967}
6b0655a2 2968
73ac8160 2969static void
518f0eb1 2970bgp_route_map_add (const char *rmap_name)
73ac8160 2971{
518f0eb1
DS
2972 if (route_map_mark_updated(rmap_name, 0) == 0)
2973 bgp_route_map_mark_update(rmap_name);
73ac8160 2974
518f0eb1 2975 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 2976}
518f0eb1 2977
73ac8160 2978static void
518f0eb1 2979bgp_route_map_delete (const char *rmap_name)
73ac8160 2980{
518f0eb1
DS
2981 if (route_map_mark_updated(rmap_name, 1) == 0)
2982 bgp_route_map_mark_update(rmap_name);
73ac8160 2983
518f0eb1 2984 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 2985}
518f0eb1 2986
73ac8160 2987static void
518f0eb1 2988bgp_route_map_event (route_map_event_t event, const char *rmap_name)
73ac8160 2989{
518f0eb1
DS
2990 if (route_map_mark_updated(rmap_name, 0) == 0)
2991 bgp_route_map_mark_update(rmap_name);
2992
2993 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
2994}
2995
2996
fee0f4c6 2997DEFUN (match_peer,
2998 match_peer_cmd,
2999 "match peer (A.B.C.D|X:X::X:X)",
3000 MATCH_STR
3001 "Match peer address\n"
3002 "IPv6 address of peer\n"
3003 "IP address of peer\n")
3004{
518f0eb1
DS
3005 return bgp_route_match_add (vty, vty->index, "peer", argv[0],
3006 RMAP_EVENT_MATCH_ADDED);
fee0f4c6 3007}
3008
3009DEFUN (match_peer_local,
3010 match_peer_local_cmd,
3011 "match peer local",
3012 MATCH_STR
3013 "Match peer address\n"
3014 "Static or Redistributed routes\n")
3015{
518f0eb1
DS
3016 return bgp_route_match_add (vty, vty->index, "peer", "local",
3017 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3018}
3019
3020DEFUN (no_match_peer,
3021 no_match_peer_cmd,
3022 "no match peer",
3023 NO_STR
3024 MATCH_STR
3025 "Match peer address\n")
3026{
3027 if (argc == 0)
518f0eb1
DS
3028 return bgp_route_match_delete (vty, vty->index, "peer", NULL,
3029 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3030
518f0eb1
DS
3031 return bgp_route_match_delete (vty, vty->index, "peer", argv[0],
3032 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3033}
3034
3035ALIAS (no_match_peer,
3036 no_match_peer_val_cmd,
3037 "no match peer (A.B.C.D|X:X::X:X)",
3038 NO_STR
3039 MATCH_STR
3040 "Match peer address\n"
3041 "IPv6 address of peer\n"
3042 "IP address of peer\n")
3043
3044ALIAS (no_match_peer,
3045 no_match_peer_local_cmd,
3046 "no match peer local",
3047 NO_STR
3048 MATCH_STR
3049 "Match peer address\n"
3050 "Static or Redistributed routes\n")
3051
718e3744 3052DEFUN (match_ip_address,
3053 match_ip_address_cmd,
3054 "match ip address (<1-199>|<1300-2699>|WORD)",
3055 MATCH_STR
3056 IP_STR
3057 "Match address of route\n"
3058 "IP access-list number\n"
3059 "IP access-list number (expanded range)\n"
3060 "IP Access-list name\n")
3061{
518f0eb1
DS
3062 return bgp_route_match_add (vty, vty->index, "ip address", argv[0],
3063 RMAP_EVENT_FILTER_ADDED);
718e3744 3064}
3065
3066DEFUN (no_match_ip_address,
3067 no_match_ip_address_cmd,
3068 "no match ip address",
3069 NO_STR
3070 MATCH_STR
3071 IP_STR
3072 "Match address of route\n")
3073{
3074 if (argc == 0)
518f0eb1
DS
3075 return bgp_route_match_delete (vty, vty->index, "ip address", NULL,
3076 RMAP_EVENT_FILTER_DELETED);
718e3744 3077
518f0eb1
DS
3078 return bgp_route_match_delete (vty, vty->index, "ip address", argv[0],
3079 RMAP_EVENT_FILTER_DELETED);
718e3744 3080}
3081
3082ALIAS (no_match_ip_address,
3083 no_match_ip_address_val_cmd,
3084 "no match ip address (<1-199>|<1300-2699>|WORD)",
3085 NO_STR
3086 MATCH_STR
3087 IP_STR
3088 "Match address of route\n"
3089 "IP access-list number\n"
3090 "IP access-list number (expanded range)\n"
3091 "IP Access-list name\n")
3092
3093DEFUN (match_ip_next_hop,
3094 match_ip_next_hop_cmd,
3095 "match ip next-hop (<1-199>|<1300-2699>|WORD)",
3096 MATCH_STR
3097 IP_STR
3098 "Match next-hop address of route\n"
3099 "IP access-list number\n"
3100 "IP access-list number (expanded range)\n"
3101 "IP Access-list name\n")
3102{
518f0eb1
DS
3103 return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0],
3104 RMAP_EVENT_FILTER_ADDED);
718e3744 3105}
3106
3107DEFUN (no_match_ip_next_hop,
3108 no_match_ip_next_hop_cmd,
3109 "no match ip next-hop",
3110 NO_STR
3111 MATCH_STR
3112 IP_STR
3113 "Match next-hop address of route\n")
3114{
3115 if (argc == 0)
518f0eb1
DS
3116 return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL,
3117 RMAP_EVENT_FILTER_DELETED);
718e3744 3118
518f0eb1
DS
3119 return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0],
3120 RMAP_EVENT_FILTER_DELETED);
718e3744 3121}
3122
3123ALIAS (no_match_ip_next_hop,
3124 no_match_ip_next_hop_val_cmd,
3125 "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
3126 NO_STR
3127 MATCH_STR
3128 IP_STR
3129 "Match next-hop address of route\n"
3130 "IP access-list number\n"
3131 "IP access-list number (expanded range)\n"
3132 "IP Access-list name\n")
3133
1add115a
VT
3134/* match probability { */
3135
3136DEFUN (match_probability,
3137 match_probability_cmd,
3138 "match probability <0-100>",
3139 MATCH_STR
3140 "Match portion of routes defined by percentage value\n"
3141 "Percentage of routes\n")
3142{
518f0eb1
DS
3143 return bgp_route_match_add (vty, vty->index, "probability", argv[0],
3144 RMAP_EVENT_MATCH_ADDED);
1add115a
VT
3145}
3146
3147DEFUN (no_match_probability,
3148 no_match_probability_cmd,
3149 "no match probability",
3150 NO_STR
3151 MATCH_STR
3152 "Match portion of routes defined by percentage value\n")
3153{
518f0eb1
DS
3154 return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL,
3155 RMAP_EVENT_MATCH_DELETED);
1add115a
VT
3156}
3157
3158ALIAS (no_match_probability,
3159 no_match_probability_val_cmd,
3160 "no match probability <1-99>",
3161 NO_STR
3162 MATCH_STR
3163 "Match portion of routes defined by percentage value\n"
3164 "Percentage of routes\n")
3165
3166/* } */
3167
c1643bb7 3168DEFUN (match_ip_route_source,
3169 match_ip_route_source_cmd,
3170 "match ip route-source (<1-199>|<1300-2699>|WORD)",
3171 MATCH_STR
3172 IP_STR
3173 "Match advertising source address of route\n"
3174 "IP access-list number\n"
3175 "IP access-list number (expanded range)\n"
3176 "IP standard access-list name\n")
3177{
518f0eb1
DS
3178 return bgp_route_match_add (vty, vty->index, "ip route-source", argv[0],
3179 RMAP_EVENT_FILTER_ADDED);
c1643bb7 3180}
3181
3182DEFUN (no_match_ip_route_source,
3183 no_match_ip_route_source_cmd,
3184 "no match ip route-source",
3185 NO_STR
3186 MATCH_STR
3187 IP_STR
3188 "Match advertising source address of route\n")
3189{
3190 if (argc == 0)
518f0eb1
DS
3191 return bgp_route_match_delete (vty, vty->index, "ip route-source", NULL,
3192 RMAP_EVENT_FILTER_DELETED);
c1643bb7 3193
518f0eb1
DS
3194 return bgp_route_match_delete (vty, vty->index, "ip route-source",
3195 argv[0], RMAP_EVENT_FILTER_DELETED);
c1643bb7 3196}
3197
3198ALIAS (no_match_ip_route_source,
3199 no_match_ip_route_source_val_cmd,
3200 "no match ip route-source (<1-199>|<1300-2699>|WORD)",
3201 NO_STR
3202 MATCH_STR
3203 IP_STR
3204 "Match advertising source address of route\n"
3205 "IP access-list number\n"
3206 "IP access-list number (expanded range)\n"
30a2231a 3207 "IP standard access-list name\n")
c1643bb7 3208
718e3744 3209DEFUN (match_ip_address_prefix_list,
3210 match_ip_address_prefix_list_cmd,
3211 "match ip address prefix-list WORD",
3212 MATCH_STR
3213 IP_STR
3214 "Match address of route\n"
3215 "Match entries of prefix-lists\n"
3216 "IP prefix-list name\n")
3217{
518f0eb1
DS
3218 return bgp_route_match_add (vty, vty->index, "ip address prefix-list",
3219 argv[0], RMAP_EVENT_PLIST_ADDED);
718e3744 3220}
3221
3222DEFUN (no_match_ip_address_prefix_list,
3223 no_match_ip_address_prefix_list_cmd,
3224 "no match ip address prefix-list",
3225 NO_STR
3226 MATCH_STR
3227 IP_STR
3228 "Match address of route\n"
3229 "Match entries of prefix-lists\n")
3230{
518f0eb1
DS
3231 return bgp_route_match_delete (vty, vty->index, "ip address prefix-list",
3232 argc == 0 ? NULL : argv[0],
3233 RMAP_EVENT_PLIST_DELETED);
718e3744 3234}
3235
3236ALIAS (no_match_ip_address_prefix_list,
3237 no_match_ip_address_prefix_list_val_cmd,
3238 "no match ip address prefix-list WORD",
3239 NO_STR
3240 MATCH_STR
3241 IP_STR
3242 "Match address of route\n"
3243 "Match entries of prefix-lists\n"
3244 "IP prefix-list name\n")
3245
3246DEFUN (match_ip_next_hop_prefix_list,
3247 match_ip_next_hop_prefix_list_cmd,
3248 "match ip next-hop prefix-list WORD",
3249 MATCH_STR
3250 IP_STR
3251 "Match next-hop address of route\n"
3252 "Match entries of prefix-lists\n"
3253 "IP prefix-list name\n")
3254{
518f0eb1
DS
3255 return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list",
3256 argv[0], RMAP_EVENT_PLIST_ADDED);
718e3744 3257}
3258
3259DEFUN (no_match_ip_next_hop_prefix_list,
3260 no_match_ip_next_hop_prefix_list_cmd,
3261 "no match ip next-hop prefix-list",
3262 NO_STR
3263 MATCH_STR
3264 IP_STR
3265 "Match next-hop address of route\n"
3266 "Match entries of prefix-lists\n")
3267{
518f0eb1
DS
3268 return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
3269 argc == 0 ? NULL : argv[0],
3270 RMAP_EVENT_PLIST_DELETED);
718e3744 3271}
3272
3273ALIAS (no_match_ip_next_hop_prefix_list,
3274 no_match_ip_next_hop_prefix_list_val_cmd,
3275 "no match ip next-hop prefix-list WORD",
3276 NO_STR
3277 MATCH_STR
3278 IP_STR
3279 "Match next-hop address of route\n"
3280 "Match entries of prefix-lists\n"
3281 "IP prefix-list name\n")
3282
c1643bb7 3283DEFUN (match_ip_route_source_prefix_list,
3284 match_ip_route_source_prefix_list_cmd,
3285 "match ip route-source prefix-list WORD",
3286 MATCH_STR
3287 IP_STR
3288 "Match advertising source address of route\n"
3289 "Match entries of prefix-lists\n"
3290 "IP prefix-list name\n")
3291{
518f0eb1
DS
3292 return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list",
3293 argv[0], RMAP_EVENT_PLIST_ADDED);
c1643bb7 3294}
3295
3296DEFUN (no_match_ip_route_source_prefix_list,
3297 no_match_ip_route_source_prefix_list_cmd,
3298 "no match ip route-source prefix-list",
3299 NO_STR
3300 MATCH_STR
3301 IP_STR
3302 "Match advertising source address of route\n"
3303 "Match entries of prefix-lists\n")
3304{
518f0eb1
DS
3305 return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list",
3306 argc == 0 ? NULL : argv[0],
3307 RMAP_EVENT_PLIST_DELETED);
c1643bb7 3308}
3309
3310ALIAS (no_match_ip_route_source_prefix_list,
3311 no_match_ip_route_source_prefix_list_val_cmd,
3312 "no match ip route-source prefix-list WORD",
3313 NO_STR
3314 MATCH_STR
3315 IP_STR
3316 "Match advertising source address of route\n"
3317 "Match entries of prefix-lists\n"
30a2231a 3318 "IP prefix-list name\n")
c1643bb7 3319
718e3744 3320DEFUN (match_metric,
3321 match_metric_cmd,
3322 "match metric <0-4294967295>",
3323 MATCH_STR
3324 "Match metric of route\n"
3325 "Metric value\n")
3326{
518f0eb1
DS
3327 return bgp_route_match_add (vty, vty->index, "metric", argv[0],
3328 RMAP_EVENT_MATCH_ADDED);
718e3744 3329}
3330
3331DEFUN (no_match_metric,
3332 no_match_metric_cmd,
3333 "no match metric",
3334 NO_STR
3335 MATCH_STR
3336 "Match metric of route\n")
3337{
518f0eb1
DS
3338 return bgp_route_match_delete (vty, vty->index, "metric",
3339 argc == 0 ? NULL : argv[0],
3340 RMAP_EVENT_MATCH_DELETED);
718e3744 3341}
3342
3343ALIAS (no_match_metric,
3344 no_match_metric_val_cmd,
3345 "no match metric <0-4294967295>",
3346 NO_STR
3347 MATCH_STR
3348 "Match metric of route\n"
3349 "Metric value\n")
3350
af291c15
DS
3351DEFUN (match_local_pref,
3352 match_local_pref_cmd,
3353 "match local-preference <0-4294967295>",
3354 MATCH_STR
3355 "Match local-preference of route\n"
3356 "Metric value\n")
3357{
518f0eb1
DS
3358 return bgp_route_match_add (vty, vty->index, "local-preference", argv[0],
3359 RMAP_EVENT_MATCH_ADDED);
af291c15
DS
3360}
3361
3362DEFUN (no_match_local_pref,
3363 no_match_local_pref_cmd,
3364 "no match local-preference",
3365 NO_STR
3366 MATCH_STR
3367 "Match local preference of route\n")
3368{
518f0eb1
DS
3369 return bgp_route_match_delete (vty, vty->index, "local-preference",
3370 argc == 0 ? NULL : argv[0],
3371 RMAP_EVENT_MATCH_DELETED);
af291c15 3372
518f0eb1
DS
3373 return bgp_route_match_delete (vty, vty->index, "local-preference", argv[0],
3374 RMAP_EVENT_MATCH_DELETED);
af291c15
DS
3375}
3376
3377ALIAS (no_match_local_pref,
3378 no_match_local_pref_val_cmd,
3379 "no match local-preference <0-4294967295>",
3380 NO_STR
3381 MATCH_STR
3382 "Match local preference of route\n"
3383 "Local preference value\n")
3384
718e3744 3385DEFUN (match_community,
3386 match_community_cmd,
fee6e4e4 3387 "match community (<1-99>|<100-500>|WORD)",
718e3744 3388 MATCH_STR
3389 "Match BGP community list\n"
3390 "Community-list number (standard)\n"
3391 "Community-list number (expanded)\n"
3392 "Community-list name\n")
3393{
518f0eb1
DS
3394 return bgp_route_match_add (vty, vty->index, "community", argv[0],
3395 RMAP_EVENT_CLIST_ADDED);
718e3744 3396}
3397
3398DEFUN (match_community_exact,
3399 match_community_exact_cmd,
fee6e4e4 3400 "match community (<1-99>|<100-500>|WORD) exact-match",
718e3744 3401 MATCH_STR
3402 "Match BGP community list\n"
3403 "Community-list number (standard)\n"
3404 "Community-list number (expanded)\n"
3405 "Community-list name\n"
3406 "Do exact matching of communities\n")
3407{
3408 int ret;
3409 char *argstr;
3410
3411 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
3412 strlen (argv[0]) + strlen ("exact-match") + 2);
3413
3414 sprintf (argstr, "%s exact-match", argv[0]);
3415
518f0eb1
DS
3416 ret = bgp_route_match_add (vty, vty->index, "community", argstr,
3417 RMAP_EVENT_CLIST_ADDED);
718e3744 3418
3419 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
3420
3421 return ret;
3422}
3423
3424DEFUN (no_match_community,
3425 no_match_community_cmd,
3426 "no match community",
3427 NO_STR
3428 MATCH_STR
3429 "Match BGP community list\n")
3430{
518f0eb1
DS
3431 return bgp_route_match_delete (vty, vty->index, "community", NULL,
3432 RMAP_EVENT_CLIST_DELETED);
718e3744 3433}
3434
3435ALIAS (no_match_community,
3436 no_match_community_val_cmd,
fee6e4e4 3437 "no match community (<1-99>|<100-500>|WORD)",
718e3744 3438 NO_STR
3439 MATCH_STR
3440 "Match BGP community list\n"
3441 "Community-list number (standard)\n"
3442 "Community-list number (expanded)\n"
3443 "Community-list name\n")
3444
3445ALIAS (no_match_community,
3446 no_match_community_exact_cmd,
fee6e4e4 3447 "no match community (<1-99>|<100-500>|WORD) exact-match",
718e3744 3448 NO_STR
3449 MATCH_STR
3450 "Match BGP community list\n"
3451 "Community-list number (standard)\n"
3452 "Community-list number (expanded)\n"
3453 "Community-list name\n"
3454 "Do exact matching of communities\n")
3455
73ffb25b 3456DEFUN (match_ecommunity,
3457 match_ecommunity_cmd,
fee6e4e4 3458 "match extcommunity (<1-99>|<100-500>|WORD)",
73ffb25b 3459 MATCH_STR
3460 "Match BGP/VPN extended community list\n"
3461 "Extended community-list number (standard)\n"
3462 "Extended community-list number (expanded)\n"
3463 "Extended community-list name\n")
3464{
518f0eb1
DS
3465 return bgp_route_match_add (vty, vty->index, "extcommunity", argv[0],
3466 RMAP_EVENT_ECLIST_ADDED);
73ffb25b 3467}
3468
3469DEFUN (no_match_ecommunity,
3470 no_match_ecommunity_cmd,
3471 "no match extcommunity",
3472 NO_STR
3473 MATCH_STR
3474 "Match BGP/VPN extended community list\n")
3475{
518f0eb1
DS
3476 return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL,
3477 RMAP_EVENT_ECLIST_DELETED);
73ffb25b 3478}
3479
3480ALIAS (no_match_ecommunity,
3481 no_match_ecommunity_val_cmd,
fee6e4e4 3482 "no match extcommunity (<1-99>|<100-500>|WORD)",
73ffb25b 3483 NO_STR
3484 MATCH_STR
3485 "Match BGP/VPN extended community list\n"
3486 "Extended community-list number (standard)\n"
3487 "Extended community-list number (expanded)\n"
3488 "Extended community-list name\n")
3489
718e3744 3490DEFUN (match_aspath,
3491 match_aspath_cmd,
3492 "match as-path WORD",
3493 MATCH_STR
3494 "Match BGP AS path list\n"
3495 "AS path access-list name\n")
3496{
518f0eb1
DS
3497 return bgp_route_match_add (vty, vty->index, "as-path", argv[0],
3498 RMAP_EVENT_ASLIST_ADDED);
718e3744 3499}
3500
3501DEFUN (no_match_aspath,
3502 no_match_aspath_cmd,
3503 "no match as-path",
3504 NO_STR
3505 MATCH_STR
3506 "Match BGP AS path list\n")
3507{
518f0eb1
DS
3508 return bgp_route_match_delete (vty, vty->index, "as-path", NULL,
3509 RMAP_EVENT_ASLIST_DELETED);
718e3744 3510}
3511
3512ALIAS (no_match_aspath,
3513 no_match_aspath_val_cmd,
3514 "no match as-path WORD",
3515 NO_STR
3516 MATCH_STR
3517 "Match BGP AS path list\n"
3518 "AS path access-list name\n")
3519
3520DEFUN (match_origin,
3521 match_origin_cmd,
3522 "match origin (egp|igp|incomplete)",
3523 MATCH_STR
3524 "BGP origin code\n"
3525 "remote EGP\n"
3526 "local IGP\n"
3527 "unknown heritage\n")
3528{
3529 if (strncmp (argv[0], "igp", 2) == 0)
518f0eb1
DS
3530 return bgp_route_match_add (vty, vty->index, "origin", "igp",
3531 RMAP_EVENT_MATCH_ADDED);
718e3744 3532 if (strncmp (argv[0], "egp", 1) == 0)
518f0eb1
DS
3533 return bgp_route_match_add (vty, vty->index, "origin", "egp",
3534 RMAP_EVENT_MATCH_ADDED);
718e3744 3535 if (strncmp (argv[0], "incomplete", 2) == 0)
518f0eb1
DS
3536 return bgp_route_match_add (vty, vty->index, "origin", "incomplete",
3537 RMAP_EVENT_MATCH_ADDED);
718e3744 3538
3539 return CMD_WARNING;
3540}
3541
3542DEFUN (no_match_origin,
3543 no_match_origin_cmd,
3544 "no match origin",
3545 NO_STR
3546 MATCH_STR
3547 "BGP origin code\n")
3548{
518f0eb1
DS
3549 return bgp_route_match_delete (vty, vty->index, "origin", NULL,
3550 RMAP_EVENT_MATCH_DELETED);
718e3744 3551}
3552
3553ALIAS (no_match_origin,
3554 no_match_origin_val_cmd,
3555 "no match origin (egp|igp|incomplete)",
3556 NO_STR
3557 MATCH_STR
3558 "BGP origin code\n"
3559 "remote EGP\n"
3560 "local IGP\n"
3561 "unknown heritage\n")
3562
bc413143
DS
3563DEFUN (match_interface,
3564 match_interface_cmd,
3565 "match interface WORD",
3566 MATCH_STR
3567 "Match first hop interface of route\n"
3568 "Interface name\n")
3569{
3570 return bgp_route_match_add (vty, vty->index, "interface", argv[0],
3571 RMAP_EVENT_MATCH_ADDED);
3572}
3573
3574DEFUN (no_match_interface,
3575 no_match_interface_cmd,
3576 "no match interface",
3577 NO_STR
3578 MATCH_STR
3579 "Match first hop interface of route\n")
3580{
3581 if (argc == 0)
3582 return bgp_route_match_delete (vty, vty->index, "interface", NULL,
3583 RMAP_EVENT_MATCH_DELETED);
3584
3585 return bgp_route_match_delete (vty, vty->index, "interface", argv[0],
3586 RMAP_EVENT_MATCH_DELETED);
3587}
3588
3589ALIAS (no_match_interface,
3590 no_match_interface_val_cmd,
3591 "no match interface WORD",
3592 NO_STR
3593 MATCH_STR
3594 "Match first hop interface of route\n"
3595 "Interface name\n")
3596
0d9551dc
DS
3597DEFUN (match_tag,
3598 match_tag_cmd,
3599 "match tag <1-65535>",
3600 MATCH_STR
3601 "Match tag of route\n"
3602 "Tag value\n")
3603{
3604 return bgp_route_match_add (vty, vty->index, "tag", argv[0],
3605 RMAP_EVENT_MATCH_ADDED);
3606}
3607
3608DEFUN (no_match_tag,
3609 no_match_tag_cmd,
3610 "no match tag",
3611 NO_STR
3612 MATCH_STR
3613 "Match tag of route\n")
3614{
3615 if (argc == 0)
3616 return bgp_route_match_delete (vty, vty->index, "tag", NULL,
3617 RMAP_EVENT_MATCH_DELETED);
3618
3619 return bgp_route_match_delete (vty, vty->index, "tag", argv[0],
3620 RMAP_EVENT_MATCH_DELETED);
3621}
3622
3623ALIAS (no_match_tag,
3624 no_match_tag_val_cmd,
3625 "no match tag <1-65535>",
3626 NO_STR
3627 MATCH_STR
3628 "Match tag of route\n"
3629 "Tag value\n")
3630
3631
718e3744 3632DEFUN (set_ip_nexthop,
3633 set_ip_nexthop_cmd,
af5cd0a5 3634 "set ip next-hop A.B.C.D",
718e3744 3635 SET_STR
3636 IP_STR
3637 "Next hop address\n"
af5cd0a5 3638 "IP address of next hop\n")
718e3744 3639{
3640 union sockunion su;
3641 int ret;
3642
3643 ret = str2sockunion (argv[0], &su);
3644 if (ret < 0)
3645 {
bf8b3d27
DS
3646 vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
3647 return CMD_WARNING;
3648 }
3649 if (su.sin.sin_addr.s_addr == 0 ||
3650 IPV4_CLASS_DE(su.sin.sin_addr.s_addr))
3651 {
3652 vty_out (vty, "%% nexthop address cannot be 0.0.0.0, multicast "
3653 "or reserved%s", VTY_NEWLINE);
718e3744 3654 return CMD_WARNING;
3655 }
3656
3657 return bgp_route_set_add (vty, vty->index, "ip next-hop", argv[0]);
3658}
3659
af5cd0a5 3660DEFUN (set_ip_nexthop_peer,
3661 set_ip_nexthop_peer_cmd,
3662 "set ip next-hop peer-address",
3663 SET_STR
3664 IP_STR
3665 "Next hop address\n"
3666 "Use peer address (for BGP only)\n")
3667{
3668 return bgp_route_set_add (vty, vty->index, "ip next-hop", "peer-address");
3669}
3670
316e074d
DS
3671DEFUN (set_ip_nexthop_unchanged,
3672 set_ip_nexthop_unchanged_cmd,
3673 "set ip next-hop unchanged",
3674 SET_STR
3675 IP_STR
3676 "Next hop address\n"
3677 "Don't modify existing Next hop address\n")
3678{
3679 return bgp_route_set_add (vty, vty->index, "ip next-hop", "unchanged");
3680}
3681
94f2b392 3682DEFUN_DEPRECATED (no_set_ip_nexthop_peer,
af5cd0a5 3683 no_set_ip_nexthop_peer_cmd,
3684 "no set ip next-hop peer-address",
3685 NO_STR
3686 SET_STR
3687 IP_STR
3688 "Next hop address\n"
3689 "Use peer address (for BGP only)\n")
3690{
3691 return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
3692}
3693
3694
718e3744 3695DEFUN (no_set_ip_nexthop,
3696 no_set_ip_nexthop_cmd,
3697 "no set ip next-hop",
3698 NO_STR
3699 SET_STR
718e3744 3700 "Next hop address\n")
3701{
af5cd0a5 3702 if (argc == 0)
718e3744 3703 return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
3704
3705 return bgp_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
3706}
3707
3708ALIAS (no_set_ip_nexthop,
3709 no_set_ip_nexthop_val_cmd,
af5cd0a5 3710 "no set ip next-hop A.B.C.D",
718e3744 3711 NO_STR
3712 SET_STR
3713 IP_STR
3714 "Next hop address\n"
af5cd0a5 3715 "IP address of next hop\n")
718e3744 3716
3717DEFUN (set_metric,
3718 set_metric_cmd,
73ffb25b 3719 "set metric <0-4294967295>",
718e3744 3720 SET_STR
3721 "Metric value for destination routing protocol\n"
73ffb25b 3722 "Metric value\n")
718e3744 3723{
3724 return bgp_route_set_add (vty, vty->index, "metric", argv[0]);
3725}
3726
73ffb25b 3727ALIAS (set_metric,
3728 set_metric_addsub_cmd,
3729 "set metric <+/-metric>",
3730 SET_STR
3731 "Metric value for destination routing protocol\n"
033e8612 3732 "Add or subtract metric\n")
73ffb25b 3733
718e3744 3734DEFUN (no_set_metric,
3735 no_set_metric_cmd,
3736 "no set metric",
3737 NO_STR
3738 SET_STR
3739 "Metric value for destination routing protocol\n")
3740{
3741 if (argc == 0)
3742 return bgp_route_set_delete (vty, vty->index, "metric", NULL);
3743
3744 return bgp_route_set_delete (vty, vty->index, "metric", argv[0]);
3745}
3746
3747ALIAS (no_set_metric,
3748 no_set_metric_val_cmd,
3749 "no set metric <0-4294967295>",
3750 NO_STR
3751 SET_STR
3752 "Metric value for destination routing protocol\n"
3753 "Metric value\n")
3754
3755DEFUN (set_local_pref,
3756 set_local_pref_cmd,
3757 "set local-preference <0-4294967295>",
3758 SET_STR
3759 "BGP local preference path attribute\n"
3760 "Preference value\n")
3761{
3762 return bgp_route_set_add (vty, vty->index, "local-preference", argv[0]);
3763}
3764
3765DEFUN (no_set_local_pref,
3766 no_set_local_pref_cmd,
3767 "no set local-preference",
3768 NO_STR
3769 SET_STR
3770 "BGP local preference path attribute\n")
3771{
3772 if (argc == 0)
3773 return bgp_route_set_delete (vty, vty->index, "local-preference", NULL);
3774
3775 return bgp_route_set_delete (vty, vty->index, "local-preference", argv[0]);
3776}
3777
3778ALIAS (no_set_local_pref,
3779 no_set_local_pref_val_cmd,
3780 "no set local-preference <0-4294967295>",
3781 NO_STR
3782 SET_STR
3783 "BGP local preference path attribute\n"
3784 "Preference value\n")
3785
3786DEFUN (set_weight,
3787 set_weight_cmd,
3788 "set weight <0-4294967295>",
3789 SET_STR
3790 "BGP weight for routing table\n"
3791 "Weight value\n")
3792{
3793 return bgp_route_set_add (vty, vty->index, "weight", argv[0]);
3794}
3795
3796DEFUN (no_set_weight,
3797 no_set_weight_cmd,
3798 "no set weight",
3799 NO_STR
3800 SET_STR
3801 "BGP weight for routing table\n")
3802{
3803 if (argc == 0)
3804 return bgp_route_set_delete (vty, vty->index, "weight", NULL);
3805
3806 return bgp_route_set_delete (vty, vty->index, "weight", argv[0]);
3807}
3808
3809ALIAS (no_set_weight,
3810 no_set_weight_val_cmd,
3811 "no set weight <0-4294967295>",
3812 NO_STR
3813 SET_STR
3814 "BGP weight for routing table\n"
3815 "Weight value\n")
3816
3817DEFUN (set_aspath_prepend,
3818 set_aspath_prepend_cmd,
10819ece 3819 "set as-path prepend ." CMD_AS_RANGE,
718e3744 3820 SET_STR
841f7a57 3821 "Transform BGP AS_PATH attribute\n"
718e3744 3822 "Prepend to the as-path\n"
3823 "AS number\n")
3824{
3825 int ret;
3826 char *str;
3827
3828 str = argv_concat (argv, argc, 0);
3829 ret = bgp_route_set_add (vty, vty->index, "as-path prepend", str);
3830 XFREE (MTYPE_TMP, str);
3831
3832 return ret;
3833}
3834
3835DEFUN (no_set_aspath_prepend,
3836 no_set_aspath_prepend_cmd,
3837 "no set as-path prepend",
3838 NO_STR
3839 SET_STR
841f7a57 3840 "Transform BGP AS_PATH attribute\n"
718e3744 3841 "Prepend to the as-path\n")
3842{
a7f93f3e
DO
3843 int ret;
3844 char *str;
3845
3846 if (argc == 0)
3847 return bgp_route_set_delete (vty, vty->index, "as-path prepend", NULL);
3848
3849 str = argv_concat (argv, argc, 0);
3850 ret = bgp_route_set_delete (vty, vty->index, "as-path prepend", str);
3851 XFREE (MTYPE_TMP, str);
3852 return ret;
718e3744 3853}
3854
3855ALIAS (no_set_aspath_prepend,
3856 no_set_aspath_prepend_val_cmd,
10819ece 3857 "no set as-path prepend ." CMD_AS_RANGE,
718e3744 3858 NO_STR
3859 SET_STR
841f7a57 3860 "Transform BGP AS_PATH attribute\n"
718e3744 3861 "Prepend to the as-path\n"
3862 "AS number\n")
3863
841f7a57
DO
3864DEFUN (set_aspath_exclude,
3865 set_aspath_exclude_cmd,
10819ece 3866 "set as-path exclude ." CMD_AS_RANGE,
841f7a57
DO
3867 SET_STR
3868 "Transform BGP AS-path attribute\n"
3869 "Exclude from the as-path\n"
3870 "AS number\n")
3871{
3872 int ret;
3873 char *str;
3874
3875 str = argv_concat (argv, argc, 0);
3876 ret = bgp_route_set_add (vty, vty->index, "as-path exclude", str);
3877 XFREE (MTYPE_TMP, str);
3878 return ret;
3879}
3880
3881DEFUN (no_set_aspath_exclude,
3882 no_set_aspath_exclude_cmd,
3883 "no set as-path exclude",
3884 NO_STR
3885 SET_STR
3886 "Transform BGP AS_PATH attribute\n"
3887 "Exclude from the as-path\n")
3888{
3889 int ret;
3890 char *str;
3891
3892 if (argc == 0)
3893 return bgp_route_set_delete (vty, vty->index, "as-path exclude", NULL);
3894
3895 str = argv_concat (argv, argc, 0);
3896 ret = bgp_route_set_delete (vty, vty->index, "as-path exclude", str);
3897 XFREE (MTYPE_TMP, str);
3898 return ret;
3899}
3900
3901ALIAS (no_set_aspath_exclude,
3902 no_set_aspath_exclude_val_cmd,
10819ece 3903 "no set as-path exclude ." CMD_AS_RANGE,
841f7a57
DO
3904 NO_STR
3905 SET_STR
3906 "Transform BGP AS_PATH attribute\n"
3907 "Exclude from the as-path\n"
3908 "AS number\n")
3909
718e3744 3910DEFUN (set_community,
3911 set_community_cmd,
3912 "set community .AA:NN",
3913 SET_STR
3914 "BGP community attribute\n"
3915 "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
3916{
3917 int i;
3918 int first = 0;
3919 int additive = 0;
3920 struct buffer *b;
3921 struct community *com = NULL;
3922 char *str;
3923 char *argstr;
3924 int ret;
3925
3926 b = buffer_new (1024);
3927
3928 for (i = 0; i < argc; i++)
3929 {
3930 if (strncmp (argv[i], "additive", strlen (argv[i])) == 0)
3931 {
3932 additive = 1;
3933 continue;
3934 }
3935
3936 if (first)
3937 buffer_putc (b, ' ');
3938 else
3939 first = 1;
3940
3941 if (strncmp (argv[i], "internet", strlen (argv[i])) == 0)
3942 {
3943 buffer_putstr (b, "internet");
3944 continue;
3945 }
3946 if (strncmp (argv[i], "local-AS", strlen (argv[i])) == 0)
3947 {
3948 buffer_putstr (b, "local-AS");
3949 continue;
3950 }
3951 if (strncmp (argv[i], "no-a", strlen ("no-a")) == 0
3952 && strncmp (argv[i], "no-advertise", strlen (argv[i])) == 0)
3953 {
3954 buffer_putstr (b, "no-advertise");
3955 continue;
3956 }
3957 if (strncmp (argv[i], "no-e", strlen ("no-e"))== 0
3958 && strncmp (argv[i], "no-export", strlen (argv[i])) == 0)
3959 {
3960 buffer_putstr (b, "no-export");
3961 continue;
3962 }
3963 buffer_putstr (b, argv[i]);
3964 }
3965 buffer_putc (b, '\0');
3966
3967 /* Fetch result string then compile it to communities attribute. */
3968 str = buffer_getstr (b);
3969 buffer_free (b);
3970
3971 if (str)
3972 {
3973 com = community_str2com (str);
3b8b1855 3974 XFREE (MTYPE_TMP, str);
718e3744 3975 }
3976
3977 /* Can't compile user input into communities attribute. */
3978 if (! com)
3979 {
3980 vty_out (vty, "%% Malformed communities attribute%s", VTY_NEWLINE);
3981 return CMD_WARNING;
3982 }
3983
3984 /* Set communites attribute string. */
3985 str = community_str (com);
3986
3987 if (additive)
3988 {
3989 argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
3990 strcpy (argstr, str);
3991 strcpy (argstr + strlen (str), " additive");
3992 ret = bgp_route_set_add (vty, vty->index, "community", argstr);
3993 XFREE (MTYPE_TMP, argstr);
3994 }
3995 else
3996 ret = bgp_route_set_add (vty, vty->index, "community", str);
3997
3998 community_free (com);
3999
4000 return ret;
4001}
4002
4003DEFUN (set_community_none,
4004 set_community_none_cmd,
4005 "set community none",
4006 SET_STR
4007 "BGP community attribute\n"
4008 "No community attribute\n")
4009{
4010 return bgp_route_set_add (vty, vty->index, "community", "none");
4011}
4012
4013DEFUN (no_set_community,
4014 no_set_community_cmd,
4015 "no set community",
4016 NO_STR
4017 SET_STR
4018 "BGP community attribute\n")
4019{
4020 return bgp_route_set_delete (vty, vty->index, "community", NULL);
4021}
4022
4023ALIAS (no_set_community,
4024 no_set_community_val_cmd,
4025 "no set community .AA:NN",
4026 NO_STR
4027 SET_STR
4028 "BGP community attribute\n"
4029 "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
4030
4031ALIAS (no_set_community,
4032 no_set_community_none_cmd,
4033 "no set community none",
4034 NO_STR
4035 SET_STR
4036 "BGP community attribute\n"
4037 "No community attribute\n")
4038
4039DEFUN (set_community_delete,
4040 set_community_delete_cmd,
fee6e4e4 4041 "set comm-list (<1-99>|<100-500>|WORD) delete",
718e3744 4042 SET_STR
4043 "set BGP community list (for deletion)\n"
4044 "Community-list number (standard)\n"
5e3edbf5 4045 "Community-list number (expanded)\n"
718e3744 4046 "Community-list name\n"
4047 "Delete matching communities\n")
4048{
4049 char *str;
4050
4051 str = XCALLOC (MTYPE_TMP, strlen (argv[0]) + strlen (" delete") + 1);
4052 strcpy (str, argv[0]);
4053 strcpy (str + strlen (argv[0]), " delete");
4054
4055 bgp_route_set_add (vty, vty->index, "comm-list", str);
4056
4057 XFREE (MTYPE_TMP, str);
4058 return CMD_SUCCESS;
4059}
4060
4061DEFUN (no_set_community_delete,
4062 no_set_community_delete_cmd,
4063 "no set comm-list",
4064 NO_STR
4065 SET_STR
4066 "set BGP community list (for deletion)\n")
4067{
4068 return bgp_route_set_delete (vty, vty->index, "comm-list", NULL);
4069}
4070
4071ALIAS (no_set_community_delete,
4072 no_set_community_delete_val_cmd,
fee6e4e4 4073 "no set comm-list (<1-99>|<100-500>|WORD) delete",
718e3744 4074 NO_STR
4075 SET_STR
4076 "set BGP community list (for deletion)\n"
4077 "Community-list number (standard)\n"
5e3edbf5 4078 "Community-list number (expanded)\n"
718e3744 4079 "Community-list name\n"
4080 "Delete matching communities\n")
4081
4082DEFUN (set_ecommunity_rt,
4083 set_ecommunity_rt_cmd,
4084 "set extcommunity rt .ASN:nn_or_IP-address:nn",
4085 SET_STR
4086 "BGP extended community attribute\n"
e6b6a564 4087 "Route Target extended community\n"
718e3744 4088 "VPN extended community\n")
4089{
4090 int ret;
4091 char *str;
4092
4093 str = argv_concat (argv, argc, 0);
4094 ret = bgp_route_set_add (vty, vty->index, "extcommunity rt", str);
4095 XFREE (MTYPE_TMP, str);
4096
4097 return ret;
4098}
4099
4100DEFUN (no_set_ecommunity_rt,
4101 no_set_ecommunity_rt_cmd,
4102 "no set extcommunity rt",
4103 NO_STR
4104 SET_STR
4105 "BGP extended community attribute\n"
e6b6a564 4106 "Route Target extended community\n")
718e3744 4107{
4108 return bgp_route_set_delete (vty, vty->index, "extcommunity rt", NULL);
4109}
4110
4111ALIAS (no_set_ecommunity_rt,
4112 no_set_ecommunity_rt_val_cmd,
4113 "no set extcommunity rt .ASN:nn_or_IP-address:nn",
4114 NO_STR
4115 SET_STR
4116 "BGP extended community attribute\n"
e6b6a564 4117 "Route Target extended community\n"
718e3744 4118 "VPN extended community\n")
4119
4120DEFUN (set_ecommunity_soo,
4121 set_ecommunity_soo_cmd,
4122 "set extcommunity soo .ASN:nn_or_IP-address:nn",
4123 SET_STR
4124 "BGP extended community attribute\n"
4125 "Site-of-Origin extended community\n"
4126 "VPN extended community\n")
4127{
4128 int ret;
4129 char *str;
4130
4131 str = argv_concat (argv, argc, 0);
4132 ret = bgp_route_set_add (vty, vty->index, "extcommunity soo", str);
4133 XFREE (MTYPE_TMP, str);
4134 return ret;
4135}
4136
4137DEFUN (no_set_ecommunity_soo,
4138 no_set_ecommunity_soo_cmd,
4139 "no set extcommunity soo",
4140 NO_STR
4141 SET_STR
4142 "BGP extended community attribute\n"
4143 "Site-of-Origin extended community\n")
4144{
4145 return bgp_route_set_delete (vty, vty->index, "extcommunity soo", NULL);
4146}
4147
4148ALIAS (no_set_ecommunity_soo,
4149 no_set_ecommunity_soo_val_cmd,
4150 "no set extcommunity soo .ASN:nn_or_IP-address:nn",
4151 NO_STR
4152 SET_STR
4153 "BGP extended community attribute\n"
4154 "Site-of-Origin extended community\n"
4155 "VPN extended community\n")
4156
4157DEFUN (set_origin,
4158 set_origin_cmd,
4159 "set origin (egp|igp|incomplete)",
4160 SET_STR
4161 "BGP origin code\n"
4162 "remote EGP\n"
4163 "local IGP\n"
4164 "unknown heritage\n")
4165{
4166 if (strncmp (argv[0], "igp", 2) == 0)
4167 return bgp_route_set_add (vty, vty->index, "origin", "igp");
4168 if (strncmp (argv[0], "egp", 1) == 0)
4169 return bgp_route_set_add (vty, vty->index, "origin", "egp");
4170 if (strncmp (argv[0], "incomplete", 2) == 0)
4171 return bgp_route_set_add (vty, vty->index, "origin", "incomplete");
4172
4173 return CMD_WARNING;
4174}
4175
4176DEFUN (no_set_origin,
4177 no_set_origin_cmd,
4178 "no set origin",
4179 NO_STR
4180 SET_STR
4181 "BGP origin code\n")
4182{
4183 return bgp_route_set_delete (vty, vty->index, "origin", NULL);
4184}
4185
4186ALIAS (no_set_origin,
4187 no_set_origin_val_cmd,
4188 "no set origin (egp|igp|incomplete)",
4189 NO_STR
4190 SET_STR
4191 "BGP origin code\n"
4192 "remote EGP\n"
4193 "local IGP\n"
4194 "unknown heritage\n")
4195
4196DEFUN (set_atomic_aggregate,
4197 set_atomic_aggregate_cmd,
4198 "set atomic-aggregate",
4199 SET_STR
4200 "BGP atomic aggregate attribute\n" )
4201{
4202 return bgp_route_set_add (vty, vty->index, "atomic-aggregate", NULL);
4203}
4204
4205DEFUN (no_set_atomic_aggregate,
4206 no_set_atomic_aggregate_cmd,
4207 "no set atomic-aggregate",
4208 NO_STR
4209 SET_STR
4210 "BGP atomic aggregate attribute\n" )
4211{
4212 return bgp_route_set_delete (vty, vty->index, "atomic-aggregate", NULL);
4213}
4214
4215DEFUN (set_aggregator_as,
4216 set_aggregator_as_cmd,
320da874 4217 "set aggregator as " CMD_AS_RANGE " A.B.C.D",
718e3744 4218 SET_STR
4219 "BGP aggregator attribute\n"
4220 "AS number of aggregator\n"
4221 "AS number\n"
4222 "IP address of aggregator\n")
4223{
4224 int ret;
718e3744 4225 struct in_addr address;
718e3744 4226 char *argstr;
fd79ac91 4227
718e3744 4228 ret = inet_aton (argv[1], &address);
4229 if (ret == 0)
4230 {
4231 vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
4232 return CMD_WARNING;
4233 }
4234
4235 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
4236 strlen (argv[0]) + strlen (argv[1]) + 2);
4237
4238 sprintf (argstr, "%s %s", argv[0], argv[1]);
4239
4240 ret = bgp_route_set_add (vty, vty->index, "aggregator as", argstr);
4241
4242 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4243
4244 return ret;
4245}
4246
4247DEFUN (no_set_aggregator_as,
4248 no_set_aggregator_as_cmd,
4249 "no set aggregator as",
4250 NO_STR
4251 SET_STR
4252 "BGP aggregator attribute\n"
4253 "AS number of aggregator\n")
4254{
4255 int ret;
718e3744 4256 struct in_addr address;
718e3744 4257 char *argstr;
4258
4259 if (argv == 0)
4260 return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
4261
718e3744 4262 ret = inet_aton (argv[1], &address);
4263 if (ret == 0)
4264 {
4265 vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
4266 return CMD_WARNING;
4267 }
4268
4269 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
4270 strlen (argv[0]) + strlen (argv[1]) + 2);
4271
4272 sprintf (argstr, "%s %s", argv[0], argv[1]);
4273
4274 ret = bgp_route_set_delete (vty, vty->index, "aggregator as", argstr);
4275
4276 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4277
4278 return ret;
4279}
4280
4281ALIAS (no_set_aggregator_as,
4282 no_set_aggregator_as_val_cmd,
320da874 4283 "no set aggregator as " CMD_AS_RANGE " A.B.C.D",
718e3744 4284 NO_STR
4285 SET_STR
4286 "BGP aggregator attribute\n"
4287 "AS number of aggregator\n"
4288 "AS number\n"
4289 "IP address of aggregator\n")
4290
0d9551dc
DS
4291DEFUN (set_tag,
4292 set_tag_cmd,
4293 "set tag <1-65535>",
4294 SET_STR
4295 "Tag value for routing protocol\n"
4296 "Tag value\n")
4297{
4298 return bgp_route_set_add (vty, vty->index, "tag", argv[0]);
4299}
4300
4301DEFUN (no_set_tag,
4302 no_set_tag_cmd,
4303 "no set tag",
4304 NO_STR
4305 SET_STR
4306 "Tag value for routing protocol\n")
4307{
4308 if (argc == 0)
4309 bgp_route_set_delete(vty, vty->index, "tag", NULL);
4310
4311 return bgp_route_set_delete (vty, vty->index, "tag", argv[0]);
4312}
4313
4314ALIAS (no_set_tag,
4315 no_set_tag_val_cmd,
4316 "no set tag <1-65535>",
4317 NO_STR
4318 SET_STR
4319 "Tag value for routing protocol\n"
4320 "Tag value\n")
4321
6b0655a2 4322
718e3744 4323#ifdef HAVE_IPV6
4324DEFUN (match_ipv6_address,
4325 match_ipv6_address_cmd,
4326 "match ipv6 address WORD",
4327 MATCH_STR
4328 IPV6_STR
4329 "Match IPv6 address of route\n"
4330 "IPv6 access-list name\n")
4331{
518f0eb1
DS
4332 return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0],
4333 RMAP_EVENT_FILTER_ADDED);
718e3744 4334}
4335
4336DEFUN (no_match_ipv6_address,
4337 no_match_ipv6_address_cmd,
4338 "no match ipv6 address WORD",
4339 NO_STR
4340 MATCH_STR
4341 IPV6_STR
4342 "Match IPv6 address of route\n"
4343 "IPv6 access-list name\n")
4344{
518f0eb1
DS
4345 return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0],
4346 RMAP_EVENT_FILTER_DELETED);
718e3744 4347}
4348
4349DEFUN (match_ipv6_next_hop,
4350 match_ipv6_next_hop_cmd,
4351 "match ipv6 next-hop X:X::X:X",
4352 MATCH_STR
4353 IPV6_STR
4354 "Match IPv6 next-hop address of route\n"
4355 "IPv6 address of next hop\n")
4356{
518f0eb1
DS
4357 return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0],
4358 RMAP_EVENT_MATCH_ADDED);
718e3744 4359}
4360
4361DEFUN (no_match_ipv6_next_hop,
4362 no_match_ipv6_next_hop_cmd,
4363 "no match ipv6 next-hop X:X::X:X",
4364 NO_STR
4365 MATCH_STR
4366 IPV6_STR
4367 "Match IPv6 next-hop address of route\n"
4368 "IPv6 address of next hop\n")
4369{
518f0eb1
DS
4370 return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0],
4371 RMAP_EVENT_MATCH_DELETED);
718e3744 4372}
4373
4374DEFUN (match_ipv6_address_prefix_list,
4375 match_ipv6_address_prefix_list_cmd,
4376 "match ipv6 address prefix-list WORD",
4377 MATCH_STR
4378 IPV6_STR
4379 "Match address of route\n"
4380 "Match entries of prefix-lists\n"
4381 "IP prefix-list name\n")
4382{
518f0eb1
DS
4383 return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list",
4384 argv[0], RMAP_EVENT_PLIST_ADDED);
718e3744 4385}
4386
4387DEFUN (no_match_ipv6_address_prefix_list,
4388 no_match_ipv6_address_prefix_list_cmd,
4389 "no match ipv6 address prefix-list WORD",
4390 NO_STR
4391 MATCH_STR
4392 IPV6_STR
4393 "Match address of route\n"
4394 "Match entries of prefix-lists\n"
4395 "IP prefix-list name\n")
4396{
518f0eb1
DS
4397 return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list",
4398 argv[0], RMAP_EVENT_PLIST_DELETED);
718e3744 4399}
4400
90916ac2
DS
4401DEFUN (set_ipv6_nexthop_peer,
4402 set_ipv6_nexthop_peer_cmd,
4403 "set ipv6 next-hop peer-address",
4404 SET_STR
4405 IPV6_STR
4406 "Next hop address\n"
4407 "Use peer address (for BGP only)\n")
4408{
4409 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop peer-address", NULL);
4410}
4411
4412DEFUN (no_set_ipv6_nexthop_peer,
4413 no_set_ipv6_nexthop_peer_cmd,
4414 "no set ipv6 next-hop peer-address",
4415 NO_STR
4416 SET_STR
4417 IPV6_STR
4418 "IPv6 next-hop address\n"
4419 )
4420{
2665d9ae 4421 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4422}
4423
718e3744 4424DEFUN (set_ipv6_nexthop_global,
4425 set_ipv6_nexthop_global_cmd,
4426 "set ipv6 next-hop global X:X::X:X",
4427 SET_STR
4428 IPV6_STR
4429 "IPv6 next-hop address\n"
4430 "IPv6 global address\n"
4431 "IPv6 address of next hop\n")
4432{
bf8b3d27
DS
4433 struct in6_addr addr;
4434 int ret;
4435
4436 ret = inet_pton (AF_INET6, argv[0], &addr);
4437 if (!ret)
4438 {
4439 vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
4440 return CMD_WARNING;
4441 }
4442 if (IN6_IS_ADDR_UNSPECIFIED(&addr) ||
4443 IN6_IS_ADDR_LOOPBACK(&addr) ||
4444 IN6_IS_ADDR_MULTICAST(&addr) ||
4445 IN6_IS_ADDR_LINKLOCAL(&addr))
4446 {
4447 vty_out (vty, "%% Invalid global nexthop address%s", VTY_NEWLINE);
4448 return CMD_WARNING;
4449 }
4450
718e3744 4451 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop global", argv[0]);
4452}
4453
4454DEFUN (no_set_ipv6_nexthop_global,
4455 no_set_ipv6_nexthop_global_cmd,
4456 "no set ipv6 next-hop global",
4457 NO_STR
4458 SET_STR
4459 IPV6_STR
4460 "IPv6 next-hop address\n"
4461 "IPv6 global address\n")
4462{
4463 if (argc == 0)
4464 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
4465
4466 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", argv[0]);
4467}
4468
4469ALIAS (no_set_ipv6_nexthop_global,
4470 no_set_ipv6_nexthop_global_val_cmd,
4471 "no set ipv6 next-hop global X:X::X:X",
4472 NO_STR
4473 SET_STR
4474 IPV6_STR
4475 "IPv6 next-hop address\n"
4476 "IPv6 global address\n"
4477 "IPv6 address of next hop\n")
4478
4479DEFUN (set_ipv6_nexthop_local,
4480 set_ipv6_nexthop_local_cmd,
4481 "set ipv6 next-hop local X:X::X:X",
4482 SET_STR
4483 IPV6_STR
4484 "IPv6 next-hop address\n"
4485 "IPv6 local address\n"
4486 "IPv6 address of next hop\n")
4487{
bf8b3d27
DS
4488 struct in6_addr addr;
4489 int ret;
4490
4491 ret = inet_pton (AF_INET6, argv[0], &addr);
4492 if (!ret)
4493 {
4494 vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
4495 return CMD_WARNING;
4496 }
4497 if (!IN6_IS_ADDR_LINKLOCAL(&addr))
4498 {
4499 vty_out (vty, "%% Invalid link-local nexthop address%s", VTY_NEWLINE);
4500 return CMD_WARNING;
4501 }
4502
718e3744 4503 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
4504}
4505
4506DEFUN (no_set_ipv6_nexthop_local,
4507 no_set_ipv6_nexthop_local_cmd,
4508 "no set ipv6 next-hop local",
4509 NO_STR
4510 SET_STR
4511 IPV6_STR
4512 "IPv6 next-hop address\n"
4513 "IPv6 local address\n")
4514{
4515 if (argc == 0)
4516 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
4517
4518 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
4519}
4520
4521ALIAS (no_set_ipv6_nexthop_local,
4522 no_set_ipv6_nexthop_local_val_cmd,
4523 "no set ipv6 next-hop local X:X::X:X",
4524 NO_STR
4525 SET_STR
4526 IPV6_STR
4527 "IPv6 next-hop address\n"
4528 "IPv6 local address\n"
4529 "IPv6 address of next hop\n")
4530#endif /* HAVE_IPV6 */
4531
4532DEFUN (set_vpnv4_nexthop,
4533 set_vpnv4_nexthop_cmd,
4534 "set vpnv4 next-hop A.B.C.D",
4535 SET_STR
4536 "VPNv4 information\n"
4537 "VPNv4 next-hop address\n"
4538 "IP address of next hop\n")
4539{
4540 return bgp_route_set_add (vty, vty->index, "vpnv4 next-hop", argv[0]);
4541}
4542
4543DEFUN (no_set_vpnv4_nexthop,
4544 no_set_vpnv4_nexthop_cmd,
4545 "no set vpnv4 next-hop",
4546 NO_STR
4547 SET_STR
4548 "VPNv4 information\n"
4549 "VPNv4 next-hop address\n")
4550{
4551 if (argc == 0)
4552 return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
4553
4554 return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", argv[0]);
4555}
4556
4557ALIAS (no_set_vpnv4_nexthop,
4558 no_set_vpnv4_nexthop_val_cmd,
4559 "no set vpnv4 next-hop A.B.C.D",
4560 NO_STR
4561 SET_STR
4562 "VPNv4 information\n"
4563 "VPNv4 next-hop address\n"
4564 "IP address of next hop\n")
4565
4566DEFUN (set_originator_id,
4567 set_originator_id_cmd,
4568 "set originator-id A.B.C.D",
4569 SET_STR
4570 "BGP originator ID attribute\n"
4571 "IP address of originator\n")
4572{
4573 return bgp_route_set_add (vty, vty->index, "originator-id", argv[0]);
4574}
4575
4576DEFUN (no_set_originator_id,
4577 no_set_originator_id_cmd,
4578 "no set originator-id",
4579 NO_STR
4580 SET_STR
4581 "BGP originator ID attribute\n")
4582{
4583 if (argc == 0)
4584 return bgp_route_set_delete (vty, vty->index, "originator-id", NULL);
4585
4586 return bgp_route_set_delete (vty, vty->index, "originator-id", argv[0]);
4587}
4588
4589ALIAS (no_set_originator_id,
4590 no_set_originator_id_val_cmd,
4591 "no set originator-id A.B.C.D",
4592 NO_STR
4593 SET_STR
4594 "BGP originator ID attribute\n"
4595 "IP address of originator\n")
4596
c8f3fe30 4597DEFUN_DEPRECATED (set_pathlimit_ttl,
41367172
PJ
4598 set_pathlimit_ttl_cmd,
4599 "set pathlimit ttl <1-255>",
4600 SET_STR
4601 "BGP AS-Pathlimit attribute\n"
4602 "Set AS-Path Hop-count TTL\n")
4603{
c8f3fe30 4604 return CMD_SUCCESS;
41367172
PJ
4605}
4606
c8f3fe30 4607DEFUN_DEPRECATED (no_set_pathlimit_ttl,
41367172
PJ
4608 no_set_pathlimit_ttl_cmd,
4609 "no set pathlimit ttl",
4610 NO_STR
4611 SET_STR
4612 "BGP AS-Pathlimit attribute\n"
4613 "Set AS-Path Hop-count TTL\n")
4614{
c8f3fe30 4615 return CMD_SUCCESS;
41367172
PJ
4616}
4617
4618ALIAS (no_set_pathlimit_ttl,
4619 no_set_pathlimit_ttl_val_cmd,
4620 "no set pathlimit ttl <1-255>",
4621 NO_STR
4622 MATCH_STR
4623 "BGP AS-Pathlimit attribute\n"
4624 "Set AS-Path Hop-count TTL\n")
4625
c8f3fe30 4626DEFUN_DEPRECATED (match_pathlimit_as,
41367172
PJ
4627 match_pathlimit_as_cmd,
4628 "match pathlimit as <1-65535>",
4629 MATCH_STR
4630 "BGP AS-Pathlimit attribute\n"
4631 "Match Pathlimit AS number\n")
4632{
c8f3fe30 4633 return CMD_SUCCESS;
41367172
PJ
4634}
4635
c8f3fe30 4636DEFUN_DEPRECATED (no_match_pathlimit_as,
41367172
PJ
4637 no_match_pathlimit_as_cmd,
4638 "no match pathlimit as",
4639 NO_STR
4640 MATCH_STR
4641 "BGP AS-Pathlimit attribute\n"
4642 "Match Pathlimit AS number\n")
4643{
c8f3fe30 4644 return CMD_SUCCESS;
41367172
PJ
4645}
4646
4647ALIAS (no_match_pathlimit_as,
4648 no_match_pathlimit_as_val_cmd,
4649 "no match pathlimit as <1-65535>",
4650 NO_STR
4651 MATCH_STR
4652 "BGP AS-Pathlimit attribute\n"
4653 "Match Pathlimit ASN\n")
4654
6b0655a2 4655
718e3744 4656/* Initialization of route map. */
4657void
94f2b392 4658bgp_route_map_init (void)
718e3744 4659{
4660 route_map_init ();
4661 route_map_init_vty ();
73ac8160
DS
4662 route_map_add_hook (bgp_route_map_add);
4663 route_map_delete_hook (bgp_route_map_delete);
4664 route_map_event_hook (bgp_route_map_event);
718e3744 4665
fee0f4c6 4666 route_map_install_match (&route_match_peer_cmd);
af291c15 4667 route_map_install_match (&route_match_local_pref_cmd);
718e3744 4668 route_map_install_match (&route_match_ip_address_cmd);
4669 route_map_install_match (&route_match_ip_next_hop_cmd);
c1643bb7 4670 route_map_install_match (&route_match_ip_route_source_cmd);
718e3744 4671 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
4672 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
c1643bb7 4673 route_map_install_match (&route_match_ip_route_source_prefix_list_cmd);
718e3744 4674 route_map_install_match (&route_match_aspath_cmd);
4675 route_map_install_match (&route_match_community_cmd);
73ffb25b 4676 route_map_install_match (&route_match_ecommunity_cmd);
af291c15 4677 route_map_install_match (&route_match_local_pref_cmd);
718e3744 4678 route_map_install_match (&route_match_metric_cmd);
4679 route_map_install_match (&route_match_origin_cmd);
1add115a 4680 route_map_install_match (&route_match_probability_cmd);
bc413143 4681 route_map_install_match (&route_match_interface_cmd);
0d9551dc 4682 route_map_install_match (&route_match_tag_cmd);
718e3744 4683
4684 route_map_install_set (&route_set_ip_nexthop_cmd);
4685 route_map_install_set (&route_set_local_pref_cmd);
4686 route_map_install_set (&route_set_weight_cmd);
4687 route_map_install_set (&route_set_metric_cmd);
4688 route_map_install_set (&route_set_aspath_prepend_cmd);
841f7a57 4689 route_map_install_set (&route_set_aspath_exclude_cmd);
718e3744 4690 route_map_install_set (&route_set_origin_cmd);
4691 route_map_install_set (&route_set_atomic_aggregate_cmd);
4692 route_map_install_set (&route_set_aggregator_as_cmd);
4693 route_map_install_set (&route_set_community_cmd);
4694 route_map_install_set (&route_set_community_delete_cmd);
4695 route_map_install_set (&route_set_vpnv4_nexthop_cmd);
4696 route_map_install_set (&route_set_originator_id_cmd);
4697 route_map_install_set (&route_set_ecommunity_rt_cmd);
4698 route_map_install_set (&route_set_ecommunity_soo_cmd);
0d9551dc 4699 route_map_install_set (&route_set_tag_cmd);
718e3744 4700
fee0f4c6 4701 install_element (RMAP_NODE, &match_peer_cmd);
4702 install_element (RMAP_NODE, &match_peer_local_cmd);
4703 install_element (RMAP_NODE, &no_match_peer_cmd);
4704 install_element (RMAP_NODE, &no_match_peer_val_cmd);
4705 install_element (RMAP_NODE, &no_match_peer_local_cmd);
718e3744 4706 install_element (RMAP_NODE, &match_ip_address_cmd);
4707 install_element (RMAP_NODE, &no_match_ip_address_cmd);
4708 install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
4709 install_element (RMAP_NODE, &match_ip_next_hop_cmd);
4710 install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
4711 install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
c1643bb7 4712 install_element (RMAP_NODE, &match_ip_route_source_cmd);
4713 install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
4714 install_element (RMAP_NODE, &no_match_ip_route_source_val_cmd);
718e3744 4715 install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
4716 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
4717 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
4718 install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
4719 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
4720 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
c1643bb7 4721 install_element (RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4722 install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
4723 install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_val_cmd);
718e3744 4724
4725 install_element (RMAP_NODE, &match_aspath_cmd);
4726 install_element (RMAP_NODE, &no_match_aspath_cmd);
4727 install_element (RMAP_NODE, &no_match_aspath_val_cmd);
4728 install_element (RMAP_NODE, &match_metric_cmd);
4729 install_element (RMAP_NODE, &no_match_metric_cmd);
4730 install_element (RMAP_NODE, &no_match_metric_val_cmd);
af291c15
DS
4731 install_element (RMAP_NODE, &match_local_pref_cmd);
4732 install_element (RMAP_NODE, &no_match_local_pref_cmd);
4733 install_element (RMAP_NODE, &no_match_local_pref_val_cmd);
718e3744 4734 install_element (RMAP_NODE, &match_community_cmd);
4735 install_element (RMAP_NODE, &match_community_exact_cmd);
4736 install_element (RMAP_NODE, &no_match_community_cmd);
4737 install_element (RMAP_NODE, &no_match_community_val_cmd);
4738 install_element (RMAP_NODE, &no_match_community_exact_cmd);
73ffb25b 4739 install_element (RMAP_NODE, &match_ecommunity_cmd);
4740 install_element (RMAP_NODE, &no_match_ecommunity_cmd);
4741 install_element (RMAP_NODE, &no_match_ecommunity_val_cmd);
718e3744 4742 install_element (RMAP_NODE, &match_origin_cmd);
4743 install_element (RMAP_NODE, &no_match_origin_cmd);
4744 install_element (RMAP_NODE, &no_match_origin_val_cmd);
1add115a
VT
4745 install_element (RMAP_NODE, &match_probability_cmd);
4746 install_element (RMAP_NODE, &no_match_probability_cmd);
4747 install_element (RMAP_NODE, &no_match_probability_val_cmd);
bc413143
DS
4748 install_element (RMAP_NODE, &match_interface_cmd);
4749 install_element (RMAP_NODE, &no_match_interface_cmd);
4750 install_element (RMAP_NODE, &no_match_interface_val_cmd);
0d9551dc
DS
4751 install_element (RMAP_NODE, &match_tag_cmd);
4752 install_element (RMAP_NODE, &no_match_tag_cmd);
4753 install_element (RMAP_NODE, &no_match_tag_val_cmd);
718e3744 4754
4755 install_element (RMAP_NODE, &set_ip_nexthop_cmd);
af5cd0a5 4756 install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
316e074d 4757 install_element (RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
718e3744 4758 install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
4759 install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
4760 install_element (RMAP_NODE, &set_local_pref_cmd);
4761 install_element (RMAP_NODE, &no_set_local_pref_cmd);
4762 install_element (RMAP_NODE, &no_set_local_pref_val_cmd);
4763 install_element (RMAP_NODE, &set_weight_cmd);
4764 install_element (RMAP_NODE, &no_set_weight_cmd);
4765 install_element (RMAP_NODE, &no_set_weight_val_cmd);
4766 install_element (RMAP_NODE, &set_metric_cmd);
73ffb25b 4767 install_element (RMAP_NODE, &set_metric_addsub_cmd);
718e3744 4768 install_element (RMAP_NODE, &no_set_metric_cmd);
4769 install_element (RMAP_NODE, &no_set_metric_val_cmd);
4770 install_element (RMAP_NODE, &set_aspath_prepend_cmd);
841f7a57 4771 install_element (RMAP_NODE, &set_aspath_exclude_cmd);
718e3744 4772 install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
4773 install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
841f7a57
DO
4774 install_element (RMAP_NODE, &no_set_aspath_exclude_cmd);
4775 install_element (RMAP_NODE, &no_set_aspath_exclude_val_cmd);
718e3744 4776 install_element (RMAP_NODE, &set_origin_cmd);
4777 install_element (RMAP_NODE, &no_set_origin_cmd);
4778 install_element (RMAP_NODE, &no_set_origin_val_cmd);
4779 install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
4780 install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
4781 install_element (RMAP_NODE, &set_aggregator_as_cmd);
4782 install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
4783 install_element (RMAP_NODE, &no_set_aggregator_as_val_cmd);
4784 install_element (RMAP_NODE, &set_community_cmd);
4785 install_element (RMAP_NODE, &set_community_none_cmd);
4786 install_element (RMAP_NODE, &no_set_community_cmd);
4787 install_element (RMAP_NODE, &no_set_community_val_cmd);
4788 install_element (RMAP_NODE, &no_set_community_none_cmd);
4789 install_element (RMAP_NODE, &set_community_delete_cmd);
4790 install_element (RMAP_NODE, &no_set_community_delete_cmd);
4791 install_element (RMAP_NODE, &no_set_community_delete_val_cmd);
4792 install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
4793 install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
4794 install_element (RMAP_NODE, &no_set_ecommunity_rt_val_cmd);
4795 install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
4796 install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
4797 install_element (RMAP_NODE, &no_set_ecommunity_soo_val_cmd);
4798 install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
4799 install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
4800 install_element (RMAP_NODE, &no_set_vpnv4_nexthop_val_cmd);
4801 install_element (RMAP_NODE, &set_originator_id_cmd);
4802 install_element (RMAP_NODE, &no_set_originator_id_cmd);
4803 install_element (RMAP_NODE, &no_set_originator_id_val_cmd);
0d9551dc
DS
4804 install_element (RMAP_NODE, &set_tag_cmd);
4805 install_element (RMAP_NODE, &no_set_tag_cmd);
4806 install_element (RMAP_NODE, &no_set_tag_val_cmd);
718e3744 4807
4808#ifdef HAVE_IPV6
4809 route_map_install_match (&route_match_ipv6_address_cmd);
4810 route_map_install_match (&route_match_ipv6_next_hop_cmd);
4811 route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
4812 route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
4813 route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
90916ac2
DS
4814 route_map_install_set (&route_set_ipv6_nexthop_peer_cmd);
4815
718e3744 4816 install_element (RMAP_NODE, &match_ipv6_address_cmd);
4817 install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
4818 install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
4819 install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
4820 install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
4821 install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
4822 install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
4823 install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
4824 install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_val_cmd);
4825 install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
4826 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
4827 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
90916ac2
DS
4828 install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
4829 install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
718e3744 4830#endif /* HAVE_IPV6 */
41367172 4831
c8f3fe30
PJ
4832 /* AS-Pathlimit: functionality removed, commands kept for
4833 * compatibility.
4834 */
41367172
PJ
4835 install_element (RMAP_NODE, &set_pathlimit_ttl_cmd);
4836 install_element (RMAP_NODE, &no_set_pathlimit_ttl_cmd);
4837 install_element (RMAP_NODE, &no_set_pathlimit_ttl_val_cmd);
4838 install_element (RMAP_NODE, &match_pathlimit_as_cmd);
4839 install_element (RMAP_NODE, &no_match_pathlimit_as_cmd);
4840 install_element (RMAP_NODE, &no_match_pathlimit_as_val_cmd);
718e3744 4841}
518f0eb1
DS
4842
4843void
4844bgp_route_map_terminate (void)
4845{
4846 /* ToDo: Cleanup all the used memory */
4847
4848 route_map_add_hook (NULL);
4849 route_map_delete_hook (NULL);
4850 route_map_event_hook (NULL);
4851 route_map_finish();
4852
4853}