]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
Zebra: Restrict IPv6 RA to valid interfaces
[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
718e3744 3682DEFUN (no_set_ip_nexthop,
3683 no_set_ip_nexthop_cmd,
3684 "no set ip next-hop",
3685 NO_STR
3686 SET_STR
718e3744 3687 "Next hop address\n")
3688{
af5cd0a5 3689 if (argc == 0)
718e3744 3690 return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
3691
3692 return bgp_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
3693}
3694
3695ALIAS (no_set_ip_nexthop,
3696 no_set_ip_nexthop_val_cmd,
af5cd0a5 3697 "no set ip next-hop A.B.C.D",
718e3744 3698 NO_STR
3699 SET_STR
3700 IP_STR
3701 "Next hop address\n"
af5cd0a5 3702 "IP address of next hop\n")
718e3744 3703
47e9b292
DW
3704ALIAS (no_set_ip_nexthop,
3705 no_set_ip_nexthop_peer_cmd,
3706 "no set ip next-hop peer-address",
3707 NO_STR
3708 SET_STR
3709 IP_STR
3710 "Next hop address\n"
3711 "Use peer address (for BGP only)\n")
3712
718e3744 3713DEFUN (set_metric,
3714 set_metric_cmd,
73ffb25b 3715 "set metric <0-4294967295>",
718e3744 3716 SET_STR
3717 "Metric value for destination routing protocol\n"
73ffb25b 3718 "Metric value\n")
718e3744 3719{
3720 return bgp_route_set_add (vty, vty->index, "metric", argv[0]);
3721}
3722
73ffb25b 3723ALIAS (set_metric,
3724 set_metric_addsub_cmd,
3725 "set metric <+/-metric>",
3726 SET_STR
3727 "Metric value for destination routing protocol\n"
033e8612 3728 "Add or subtract metric\n")
73ffb25b 3729
718e3744 3730DEFUN (no_set_metric,
3731 no_set_metric_cmd,
3732 "no set metric",
3733 NO_STR
3734 SET_STR
3735 "Metric value for destination routing protocol\n")
3736{
3737 if (argc == 0)
3738 return bgp_route_set_delete (vty, vty->index, "metric", NULL);
3739
3740 return bgp_route_set_delete (vty, vty->index, "metric", argv[0]);
3741}
3742
3743ALIAS (no_set_metric,
3744 no_set_metric_val_cmd,
3745 "no set metric <0-4294967295>",
3746 NO_STR
3747 SET_STR
3748 "Metric value for destination routing protocol\n"
3749 "Metric value\n")
3750
3751DEFUN (set_local_pref,
3752 set_local_pref_cmd,
3753 "set local-preference <0-4294967295>",
3754 SET_STR
3755 "BGP local preference path attribute\n"
3756 "Preference value\n")
3757{
3758 return bgp_route_set_add (vty, vty->index, "local-preference", argv[0]);
3759}
3760
3761DEFUN (no_set_local_pref,
3762 no_set_local_pref_cmd,
3763 "no set local-preference",
3764 NO_STR
3765 SET_STR
3766 "BGP local preference path attribute\n")
3767{
3768 if (argc == 0)
3769 return bgp_route_set_delete (vty, vty->index, "local-preference", NULL);
3770
3771 return bgp_route_set_delete (vty, vty->index, "local-preference", argv[0]);
3772}
3773
3774ALIAS (no_set_local_pref,
3775 no_set_local_pref_val_cmd,
3776 "no set local-preference <0-4294967295>",
3777 NO_STR
3778 SET_STR
3779 "BGP local preference path attribute\n"
3780 "Preference value\n")
3781
3782DEFUN (set_weight,
3783 set_weight_cmd,
3784 "set weight <0-4294967295>",
3785 SET_STR
3786 "BGP weight for routing table\n"
3787 "Weight value\n")
3788{
3789 return bgp_route_set_add (vty, vty->index, "weight", argv[0]);
3790}
3791
3792DEFUN (no_set_weight,
3793 no_set_weight_cmd,
3794 "no set weight",
3795 NO_STR
3796 SET_STR
3797 "BGP weight for routing table\n")
3798{
3799 if (argc == 0)
3800 return bgp_route_set_delete (vty, vty->index, "weight", NULL);
3801
3802 return bgp_route_set_delete (vty, vty->index, "weight", argv[0]);
3803}
3804
3805ALIAS (no_set_weight,
3806 no_set_weight_val_cmd,
3807 "no set weight <0-4294967295>",
3808 NO_STR
3809 SET_STR
3810 "BGP weight for routing table\n"
3811 "Weight value\n")
3812
3813DEFUN (set_aspath_prepend,
3814 set_aspath_prepend_cmd,
10819ece 3815 "set as-path prepend ." CMD_AS_RANGE,
718e3744 3816 SET_STR
841f7a57 3817 "Transform BGP AS_PATH attribute\n"
718e3744 3818 "Prepend to the as-path\n"
3819 "AS number\n")
3820{
3821 int ret;
3822 char *str;
3823
3824 str = argv_concat (argv, argc, 0);
3825 ret = bgp_route_set_add (vty, vty->index, "as-path prepend", str);
3826 XFREE (MTYPE_TMP, str);
3827
3828 return ret;
3829}
3830
3831DEFUN (no_set_aspath_prepend,
3832 no_set_aspath_prepend_cmd,
3833 "no set as-path prepend",
3834 NO_STR
3835 SET_STR
841f7a57 3836 "Transform BGP AS_PATH attribute\n"
718e3744 3837 "Prepend to the as-path\n")
3838{
a7f93f3e
DO
3839 int ret;
3840 char *str;
3841
3842 if (argc == 0)
3843 return bgp_route_set_delete (vty, vty->index, "as-path prepend", NULL);
3844
3845 str = argv_concat (argv, argc, 0);
3846 ret = bgp_route_set_delete (vty, vty->index, "as-path prepend", str);
3847 XFREE (MTYPE_TMP, str);
3848 return ret;
718e3744 3849}
3850
3851ALIAS (no_set_aspath_prepend,
3852 no_set_aspath_prepend_val_cmd,
10819ece 3853 "no set as-path prepend ." CMD_AS_RANGE,
718e3744 3854 NO_STR
3855 SET_STR
841f7a57 3856 "Transform BGP AS_PATH attribute\n"
718e3744 3857 "Prepend to the as-path\n"
3858 "AS number\n")
3859
841f7a57
DO
3860DEFUN (set_aspath_exclude,
3861 set_aspath_exclude_cmd,
10819ece 3862 "set as-path exclude ." CMD_AS_RANGE,
841f7a57
DO
3863 SET_STR
3864 "Transform BGP AS-path attribute\n"
3865 "Exclude from the as-path\n"
3866 "AS number\n")
3867{
3868 int ret;
3869 char *str;
3870
3871 str = argv_concat (argv, argc, 0);
3872 ret = bgp_route_set_add (vty, vty->index, "as-path exclude", str);
3873 XFREE (MTYPE_TMP, str);
3874 return ret;
3875}
3876
3877DEFUN (no_set_aspath_exclude,
3878 no_set_aspath_exclude_cmd,
3879 "no set as-path exclude",
3880 NO_STR
3881 SET_STR
3882 "Transform BGP AS_PATH attribute\n"
3883 "Exclude from the as-path\n")
3884{
3885 int ret;
3886 char *str;
3887
3888 if (argc == 0)
3889 return bgp_route_set_delete (vty, vty->index, "as-path exclude", NULL);
3890
3891 str = argv_concat (argv, argc, 0);
3892 ret = bgp_route_set_delete (vty, vty->index, "as-path exclude", str);
3893 XFREE (MTYPE_TMP, str);
3894 return ret;
3895}
3896
3897ALIAS (no_set_aspath_exclude,
3898 no_set_aspath_exclude_val_cmd,
10819ece 3899 "no set as-path exclude ." CMD_AS_RANGE,
841f7a57
DO
3900 NO_STR
3901 SET_STR
3902 "Transform BGP AS_PATH attribute\n"
3903 "Exclude from the as-path\n"
3904 "AS number\n")
3905
718e3744 3906DEFUN (set_community,
3907 set_community_cmd,
3908 "set community .AA:NN",
3909 SET_STR
3910 "BGP community attribute\n"
3911 "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
3912{
3913 int i;
3914 int first = 0;
3915 int additive = 0;
3916 struct buffer *b;
3917 struct community *com = NULL;
3918 char *str;
3919 char *argstr;
3920 int ret;
3921
3922 b = buffer_new (1024);
3923
3924 for (i = 0; i < argc; i++)
3925 {
3926 if (strncmp (argv[i], "additive", strlen (argv[i])) == 0)
3927 {
3928 additive = 1;
3929 continue;
3930 }
3931
3932 if (first)
3933 buffer_putc (b, ' ');
3934 else
3935 first = 1;
3936
3937 if (strncmp (argv[i], "internet", strlen (argv[i])) == 0)
3938 {
3939 buffer_putstr (b, "internet");
3940 continue;
3941 }
3942 if (strncmp (argv[i], "local-AS", strlen (argv[i])) == 0)
3943 {
3944 buffer_putstr (b, "local-AS");
3945 continue;
3946 }
3947 if (strncmp (argv[i], "no-a", strlen ("no-a")) == 0
3948 && strncmp (argv[i], "no-advertise", strlen (argv[i])) == 0)
3949 {
3950 buffer_putstr (b, "no-advertise");
3951 continue;
3952 }
3953 if (strncmp (argv[i], "no-e", strlen ("no-e"))== 0
3954 && strncmp (argv[i], "no-export", strlen (argv[i])) == 0)
3955 {
3956 buffer_putstr (b, "no-export");
3957 continue;
3958 }
3959 buffer_putstr (b, argv[i]);
3960 }
3961 buffer_putc (b, '\0');
3962
3963 /* Fetch result string then compile it to communities attribute. */
3964 str = buffer_getstr (b);
3965 buffer_free (b);
3966
3967 if (str)
3968 {
3969 com = community_str2com (str);
3b8b1855 3970 XFREE (MTYPE_TMP, str);
718e3744 3971 }
3972
3973 /* Can't compile user input into communities attribute. */
3974 if (! com)
3975 {
3976 vty_out (vty, "%% Malformed communities attribute%s", VTY_NEWLINE);
3977 return CMD_WARNING;
3978 }
3979
3980 /* Set communites attribute string. */
3981 str = community_str (com);
3982
3983 if (additive)
3984 {
3985 argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
3986 strcpy (argstr, str);
3987 strcpy (argstr + strlen (str), " additive");
3988 ret = bgp_route_set_add (vty, vty->index, "community", argstr);
3989 XFREE (MTYPE_TMP, argstr);
3990 }
3991 else
3992 ret = bgp_route_set_add (vty, vty->index, "community", str);
3993
3994 community_free (com);
3995
3996 return ret;
3997}
3998
3999DEFUN (set_community_none,
4000 set_community_none_cmd,
4001 "set community none",
4002 SET_STR
4003 "BGP community attribute\n"
4004 "No community attribute\n")
4005{
4006 return bgp_route_set_add (vty, vty->index, "community", "none");
4007}
4008
4009DEFUN (no_set_community,
4010 no_set_community_cmd,
4011 "no set community",
4012 NO_STR
4013 SET_STR
4014 "BGP community attribute\n")
4015{
4016 return bgp_route_set_delete (vty, vty->index, "community", NULL);
4017}
4018
4019ALIAS (no_set_community,
4020 no_set_community_val_cmd,
4021 "no set community .AA:NN",
4022 NO_STR
4023 SET_STR
4024 "BGP community attribute\n"
4025 "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
4026
4027ALIAS (no_set_community,
4028 no_set_community_none_cmd,
4029 "no set community none",
4030 NO_STR
4031 SET_STR
4032 "BGP community attribute\n"
4033 "No community attribute\n")
4034
4035DEFUN (set_community_delete,
4036 set_community_delete_cmd,
fee6e4e4 4037 "set comm-list (<1-99>|<100-500>|WORD) delete",
718e3744 4038 SET_STR
4039 "set BGP community list (for deletion)\n"
4040 "Community-list number (standard)\n"
5e3edbf5 4041 "Community-list number (expanded)\n"
718e3744 4042 "Community-list name\n"
4043 "Delete matching communities\n")
4044{
4045 char *str;
4046
4047 str = XCALLOC (MTYPE_TMP, strlen (argv[0]) + strlen (" delete") + 1);
4048 strcpy (str, argv[0]);
4049 strcpy (str + strlen (argv[0]), " delete");
4050
4051 bgp_route_set_add (vty, vty->index, "comm-list", str);
4052
4053 XFREE (MTYPE_TMP, str);
4054 return CMD_SUCCESS;
4055}
4056
4057DEFUN (no_set_community_delete,
4058 no_set_community_delete_cmd,
4059 "no set comm-list",
4060 NO_STR
4061 SET_STR
4062 "set BGP community list (for deletion)\n")
4063{
4064 return bgp_route_set_delete (vty, vty->index, "comm-list", NULL);
4065}
4066
4067ALIAS (no_set_community_delete,
4068 no_set_community_delete_val_cmd,
fee6e4e4 4069 "no set comm-list (<1-99>|<100-500>|WORD) delete",
718e3744 4070 NO_STR
4071 SET_STR
4072 "set BGP community list (for deletion)\n"
4073 "Community-list number (standard)\n"
5e3edbf5 4074 "Community-list number (expanded)\n"
718e3744 4075 "Community-list name\n"
4076 "Delete matching communities\n")
4077
4078DEFUN (set_ecommunity_rt,
4079 set_ecommunity_rt_cmd,
4080 "set extcommunity rt .ASN:nn_or_IP-address:nn",
4081 SET_STR
4082 "BGP extended community attribute\n"
e6b6a564 4083 "Route Target extended community\n"
718e3744 4084 "VPN extended community\n")
4085{
4086 int ret;
4087 char *str;
4088
4089 str = argv_concat (argv, argc, 0);
4090 ret = bgp_route_set_add (vty, vty->index, "extcommunity rt", str);
4091 XFREE (MTYPE_TMP, str);
4092
4093 return ret;
4094}
4095
4096DEFUN (no_set_ecommunity_rt,
4097 no_set_ecommunity_rt_cmd,
4098 "no set extcommunity rt",
4099 NO_STR
4100 SET_STR
4101 "BGP extended community attribute\n"
e6b6a564 4102 "Route Target extended community\n")
718e3744 4103{
4104 return bgp_route_set_delete (vty, vty->index, "extcommunity rt", NULL);
4105}
4106
4107ALIAS (no_set_ecommunity_rt,
4108 no_set_ecommunity_rt_val_cmd,
4109 "no set extcommunity rt .ASN:nn_or_IP-address:nn",
4110 NO_STR
4111 SET_STR
4112 "BGP extended community attribute\n"
e6b6a564 4113 "Route Target extended community\n"
718e3744 4114 "VPN extended community\n")
4115
4116DEFUN (set_ecommunity_soo,
4117 set_ecommunity_soo_cmd,
4118 "set extcommunity soo .ASN:nn_or_IP-address:nn",
4119 SET_STR
4120 "BGP extended community attribute\n"
4121 "Site-of-Origin extended community\n"
4122 "VPN extended community\n")
4123{
4124 int ret;
4125 char *str;
4126
4127 str = argv_concat (argv, argc, 0);
4128 ret = bgp_route_set_add (vty, vty->index, "extcommunity soo", str);
4129 XFREE (MTYPE_TMP, str);
4130 return ret;
4131}
4132
4133DEFUN (no_set_ecommunity_soo,
4134 no_set_ecommunity_soo_cmd,
4135 "no set extcommunity soo",
4136 NO_STR
4137 SET_STR
4138 "BGP extended community attribute\n"
4139 "Site-of-Origin extended community\n")
4140{
4141 return bgp_route_set_delete (vty, vty->index, "extcommunity soo", NULL);
4142}
4143
4144ALIAS (no_set_ecommunity_soo,
4145 no_set_ecommunity_soo_val_cmd,
4146 "no set extcommunity soo .ASN:nn_or_IP-address:nn",
4147 NO_STR
4148 SET_STR
4149 "BGP extended community attribute\n"
4150 "Site-of-Origin extended community\n"
4151 "VPN extended community\n")
4152
4153DEFUN (set_origin,
4154 set_origin_cmd,
4155 "set origin (egp|igp|incomplete)",
4156 SET_STR
4157 "BGP origin code\n"
4158 "remote EGP\n"
4159 "local IGP\n"
4160 "unknown heritage\n")
4161{
4162 if (strncmp (argv[0], "igp", 2) == 0)
4163 return bgp_route_set_add (vty, vty->index, "origin", "igp");
4164 if (strncmp (argv[0], "egp", 1) == 0)
4165 return bgp_route_set_add (vty, vty->index, "origin", "egp");
4166 if (strncmp (argv[0], "incomplete", 2) == 0)
4167 return bgp_route_set_add (vty, vty->index, "origin", "incomplete");
4168
4169 return CMD_WARNING;
4170}
4171
4172DEFUN (no_set_origin,
4173 no_set_origin_cmd,
4174 "no set origin",
4175 NO_STR
4176 SET_STR
4177 "BGP origin code\n")
4178{
4179 return bgp_route_set_delete (vty, vty->index, "origin", NULL);
4180}
4181
4182ALIAS (no_set_origin,
4183 no_set_origin_val_cmd,
4184 "no set origin (egp|igp|incomplete)",
4185 NO_STR
4186 SET_STR
4187 "BGP origin code\n"
4188 "remote EGP\n"
4189 "local IGP\n"
4190 "unknown heritage\n")
4191
4192DEFUN (set_atomic_aggregate,
4193 set_atomic_aggregate_cmd,
4194 "set atomic-aggregate",
4195 SET_STR
4196 "BGP atomic aggregate attribute\n" )
4197{
4198 return bgp_route_set_add (vty, vty->index, "atomic-aggregate", NULL);
4199}
4200
4201DEFUN (no_set_atomic_aggregate,
4202 no_set_atomic_aggregate_cmd,
4203 "no set atomic-aggregate",
4204 NO_STR
4205 SET_STR
4206 "BGP atomic aggregate attribute\n" )
4207{
4208 return bgp_route_set_delete (vty, vty->index, "atomic-aggregate", NULL);
4209}
4210
4211DEFUN (set_aggregator_as,
4212 set_aggregator_as_cmd,
320da874 4213 "set aggregator as " CMD_AS_RANGE " A.B.C.D",
718e3744 4214 SET_STR
4215 "BGP aggregator attribute\n"
4216 "AS number of aggregator\n"
4217 "AS number\n"
4218 "IP address of aggregator\n")
4219{
4220 int ret;
718e3744 4221 struct in_addr address;
718e3744 4222 char *argstr;
fd79ac91 4223
718e3744 4224 ret = inet_aton (argv[1], &address);
4225 if (ret == 0)
4226 {
4227 vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
4228 return CMD_WARNING;
4229 }
4230
4231 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
4232 strlen (argv[0]) + strlen (argv[1]) + 2);
4233
4234 sprintf (argstr, "%s %s", argv[0], argv[1]);
4235
4236 ret = bgp_route_set_add (vty, vty->index, "aggregator as", argstr);
4237
4238 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4239
4240 return ret;
4241}
4242
4243DEFUN (no_set_aggregator_as,
4244 no_set_aggregator_as_cmd,
4245 "no set aggregator as",
4246 NO_STR
4247 SET_STR
4248 "BGP aggregator attribute\n"
4249 "AS number of aggregator\n")
4250{
4251 int ret;
718e3744 4252 struct in_addr address;
718e3744 4253 char *argstr;
4254
4255 if (argv == 0)
4256 return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
4257
718e3744 4258 ret = inet_aton (argv[1], &address);
4259 if (ret == 0)
4260 {
4261 vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
4262 return CMD_WARNING;
4263 }
4264
4265 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
4266 strlen (argv[0]) + strlen (argv[1]) + 2);
4267
4268 sprintf (argstr, "%s %s", argv[0], argv[1]);
4269
4270 ret = bgp_route_set_delete (vty, vty->index, "aggregator as", argstr);
4271
4272 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4273
4274 return ret;
4275}
4276
4277ALIAS (no_set_aggregator_as,
4278 no_set_aggregator_as_val_cmd,
320da874 4279 "no set aggregator as " CMD_AS_RANGE " A.B.C.D",
718e3744 4280 NO_STR
4281 SET_STR
4282 "BGP aggregator attribute\n"
4283 "AS number of aggregator\n"
4284 "AS number\n"
4285 "IP address of aggregator\n")
4286
0d9551dc
DS
4287DEFUN (set_tag,
4288 set_tag_cmd,
4289 "set tag <1-65535>",
4290 SET_STR
4291 "Tag value for routing protocol\n"
4292 "Tag value\n")
4293{
4294 return bgp_route_set_add (vty, vty->index, "tag", argv[0]);
4295}
4296
4297DEFUN (no_set_tag,
4298 no_set_tag_cmd,
4299 "no set tag",
4300 NO_STR
4301 SET_STR
4302 "Tag value for routing protocol\n")
4303{
4304 if (argc == 0)
4305 bgp_route_set_delete(vty, vty->index, "tag", NULL);
4306
4307 return bgp_route_set_delete (vty, vty->index, "tag", argv[0]);
4308}
4309
4310ALIAS (no_set_tag,
4311 no_set_tag_val_cmd,
4312 "no set tag <1-65535>",
4313 NO_STR
4314 SET_STR
4315 "Tag value for routing protocol\n"
4316 "Tag value\n")
4317
6b0655a2 4318
718e3744 4319#ifdef HAVE_IPV6
4320DEFUN (match_ipv6_address,
4321 match_ipv6_address_cmd,
4322 "match ipv6 address WORD",
4323 MATCH_STR
4324 IPV6_STR
4325 "Match IPv6 address of route\n"
4326 "IPv6 access-list name\n")
4327{
518f0eb1
DS
4328 return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0],
4329 RMAP_EVENT_FILTER_ADDED);
718e3744 4330}
4331
4332DEFUN (no_match_ipv6_address,
4333 no_match_ipv6_address_cmd,
4334 "no match ipv6 address WORD",
4335 NO_STR
4336 MATCH_STR
4337 IPV6_STR
4338 "Match IPv6 address of route\n"
4339 "IPv6 access-list name\n")
4340{
518f0eb1
DS
4341 return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0],
4342 RMAP_EVENT_FILTER_DELETED);
718e3744 4343}
4344
4345DEFUN (match_ipv6_next_hop,
4346 match_ipv6_next_hop_cmd,
4347 "match ipv6 next-hop X:X::X:X",
4348 MATCH_STR
4349 IPV6_STR
4350 "Match IPv6 next-hop address of route\n"
4351 "IPv6 address of next hop\n")
4352{
518f0eb1
DS
4353 return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0],
4354 RMAP_EVENT_MATCH_ADDED);
718e3744 4355}
4356
4357DEFUN (no_match_ipv6_next_hop,
4358 no_match_ipv6_next_hop_cmd,
4359 "no match ipv6 next-hop X:X::X:X",
4360 NO_STR
4361 MATCH_STR
4362 IPV6_STR
4363 "Match IPv6 next-hop address of route\n"
4364 "IPv6 address of next hop\n")
4365{
518f0eb1
DS
4366 return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0],
4367 RMAP_EVENT_MATCH_DELETED);
718e3744 4368}
4369
4370DEFUN (match_ipv6_address_prefix_list,
4371 match_ipv6_address_prefix_list_cmd,
4372 "match ipv6 address prefix-list WORD",
4373 MATCH_STR
4374 IPV6_STR
4375 "Match address of route\n"
4376 "Match entries of prefix-lists\n"
4377 "IP prefix-list name\n")
4378{
518f0eb1
DS
4379 return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list",
4380 argv[0], RMAP_EVENT_PLIST_ADDED);
718e3744 4381}
4382
4383DEFUN (no_match_ipv6_address_prefix_list,
4384 no_match_ipv6_address_prefix_list_cmd,
4385 "no match ipv6 address prefix-list WORD",
4386 NO_STR
4387 MATCH_STR
4388 IPV6_STR
4389 "Match address of route\n"
4390 "Match entries of prefix-lists\n"
4391 "IP prefix-list name\n")
4392{
518f0eb1
DS
4393 return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list",
4394 argv[0], RMAP_EVENT_PLIST_DELETED);
718e3744 4395}
4396
90916ac2
DS
4397DEFUN (set_ipv6_nexthop_peer,
4398 set_ipv6_nexthop_peer_cmd,
4399 "set ipv6 next-hop peer-address",
4400 SET_STR
4401 IPV6_STR
4402 "Next hop address\n"
4403 "Use peer address (for BGP only)\n")
4404{
4405 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop peer-address", NULL);
4406}
4407
4408DEFUN (no_set_ipv6_nexthop_peer,
4409 no_set_ipv6_nexthop_peer_cmd,
4410 "no set ipv6 next-hop peer-address",
4411 NO_STR
4412 SET_STR
4413 IPV6_STR
4414 "IPv6 next-hop address\n"
4415 )
4416{
2665d9ae 4417 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4418}
4419
718e3744 4420DEFUN (set_ipv6_nexthop_global,
4421 set_ipv6_nexthop_global_cmd,
4422 "set ipv6 next-hop global X:X::X:X",
4423 SET_STR
4424 IPV6_STR
4425 "IPv6 next-hop address\n"
4426 "IPv6 global address\n"
4427 "IPv6 address of next hop\n")
4428{
bf8b3d27
DS
4429 struct in6_addr addr;
4430 int ret;
4431
4432 ret = inet_pton (AF_INET6, argv[0], &addr);
4433 if (!ret)
4434 {
4435 vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
4436 return CMD_WARNING;
4437 }
4438 if (IN6_IS_ADDR_UNSPECIFIED(&addr) ||
4439 IN6_IS_ADDR_LOOPBACK(&addr) ||
4440 IN6_IS_ADDR_MULTICAST(&addr) ||
4441 IN6_IS_ADDR_LINKLOCAL(&addr))
4442 {
4443 vty_out (vty, "%% Invalid global nexthop address%s", VTY_NEWLINE);
4444 return CMD_WARNING;
4445 }
4446
718e3744 4447 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop global", argv[0]);
4448}
4449
4450DEFUN (no_set_ipv6_nexthop_global,
4451 no_set_ipv6_nexthop_global_cmd,
4452 "no set ipv6 next-hop global",
4453 NO_STR
4454 SET_STR
4455 IPV6_STR
4456 "IPv6 next-hop address\n"
4457 "IPv6 global address\n")
4458{
4459 if (argc == 0)
4460 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
4461
4462 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", argv[0]);
4463}
4464
4465ALIAS (no_set_ipv6_nexthop_global,
4466 no_set_ipv6_nexthop_global_val_cmd,
4467 "no set ipv6 next-hop global X:X::X:X",
4468 NO_STR
4469 SET_STR
4470 IPV6_STR
4471 "IPv6 next-hop address\n"
4472 "IPv6 global address\n"
4473 "IPv6 address of next hop\n")
4474
4475DEFUN (set_ipv6_nexthop_local,
4476 set_ipv6_nexthop_local_cmd,
4477 "set ipv6 next-hop local X:X::X:X",
4478 SET_STR
4479 IPV6_STR
4480 "IPv6 next-hop address\n"
4481 "IPv6 local address\n"
4482 "IPv6 address of next hop\n")
4483{
bf8b3d27
DS
4484 struct in6_addr addr;
4485 int ret;
4486
4487 ret = inet_pton (AF_INET6, argv[0], &addr);
4488 if (!ret)
4489 {
4490 vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
4491 return CMD_WARNING;
4492 }
4493 if (!IN6_IS_ADDR_LINKLOCAL(&addr))
4494 {
4495 vty_out (vty, "%% Invalid link-local nexthop address%s", VTY_NEWLINE);
4496 return CMD_WARNING;
4497 }
4498
718e3744 4499 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
4500}
4501
4502DEFUN (no_set_ipv6_nexthop_local,
4503 no_set_ipv6_nexthop_local_cmd,
4504 "no set ipv6 next-hop local",
4505 NO_STR
4506 SET_STR
4507 IPV6_STR
4508 "IPv6 next-hop address\n"
4509 "IPv6 local address\n")
4510{
4511 if (argc == 0)
4512 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
4513
4514 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
4515}
4516
4517ALIAS (no_set_ipv6_nexthop_local,
4518 no_set_ipv6_nexthop_local_val_cmd,
4519 "no set ipv6 next-hop local X:X::X:X",
4520 NO_STR
4521 SET_STR
4522 IPV6_STR
4523 "IPv6 next-hop address\n"
4524 "IPv6 local address\n"
4525 "IPv6 address of next hop\n")
4526#endif /* HAVE_IPV6 */
4527
4528DEFUN (set_vpnv4_nexthop,
4529 set_vpnv4_nexthop_cmd,
4530 "set vpnv4 next-hop A.B.C.D",
4531 SET_STR
4532 "VPNv4 information\n"
4533 "VPNv4 next-hop address\n"
4534 "IP address of next hop\n")
4535{
4536 return bgp_route_set_add (vty, vty->index, "vpnv4 next-hop", argv[0]);
4537}
4538
4539DEFUN (no_set_vpnv4_nexthop,
4540 no_set_vpnv4_nexthop_cmd,
4541 "no set vpnv4 next-hop",
4542 NO_STR
4543 SET_STR
4544 "VPNv4 information\n"
4545 "VPNv4 next-hop address\n")
4546{
4547 if (argc == 0)
4548 return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
4549
4550 return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", argv[0]);
4551}
4552
4553ALIAS (no_set_vpnv4_nexthop,
4554 no_set_vpnv4_nexthop_val_cmd,
4555 "no set vpnv4 next-hop A.B.C.D",
4556 NO_STR
4557 SET_STR
4558 "VPNv4 information\n"
4559 "VPNv4 next-hop address\n"
4560 "IP address of next hop\n")
4561
4562DEFUN (set_originator_id,
4563 set_originator_id_cmd,
4564 "set originator-id A.B.C.D",
4565 SET_STR
4566 "BGP originator ID attribute\n"
4567 "IP address of originator\n")
4568{
4569 return bgp_route_set_add (vty, vty->index, "originator-id", argv[0]);
4570}
4571
4572DEFUN (no_set_originator_id,
4573 no_set_originator_id_cmd,
4574 "no set originator-id",
4575 NO_STR
4576 SET_STR
4577 "BGP originator ID attribute\n")
4578{
4579 if (argc == 0)
4580 return bgp_route_set_delete (vty, vty->index, "originator-id", NULL);
4581
4582 return bgp_route_set_delete (vty, vty->index, "originator-id", argv[0]);
4583}
4584
4585ALIAS (no_set_originator_id,
4586 no_set_originator_id_val_cmd,
4587 "no set originator-id A.B.C.D",
4588 NO_STR
4589 SET_STR
4590 "BGP originator ID attribute\n"
4591 "IP address of originator\n")
4592
718e3744 4593/* Initialization of route map. */
4594void
94f2b392 4595bgp_route_map_init (void)
718e3744 4596{
4597 route_map_init ();
4598 route_map_init_vty ();
73ac8160
DS
4599 route_map_add_hook (bgp_route_map_add);
4600 route_map_delete_hook (bgp_route_map_delete);
4601 route_map_event_hook (bgp_route_map_event);
718e3744 4602
fee0f4c6 4603 route_map_install_match (&route_match_peer_cmd);
af291c15 4604 route_map_install_match (&route_match_local_pref_cmd);
718e3744 4605 route_map_install_match (&route_match_ip_address_cmd);
4606 route_map_install_match (&route_match_ip_next_hop_cmd);
c1643bb7 4607 route_map_install_match (&route_match_ip_route_source_cmd);
718e3744 4608 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
4609 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
c1643bb7 4610 route_map_install_match (&route_match_ip_route_source_prefix_list_cmd);
718e3744 4611 route_map_install_match (&route_match_aspath_cmd);
4612 route_map_install_match (&route_match_community_cmd);
73ffb25b 4613 route_map_install_match (&route_match_ecommunity_cmd);
af291c15 4614 route_map_install_match (&route_match_local_pref_cmd);
718e3744 4615 route_map_install_match (&route_match_metric_cmd);
4616 route_map_install_match (&route_match_origin_cmd);
1add115a 4617 route_map_install_match (&route_match_probability_cmd);
bc413143 4618 route_map_install_match (&route_match_interface_cmd);
0d9551dc 4619 route_map_install_match (&route_match_tag_cmd);
718e3744 4620
4621 route_map_install_set (&route_set_ip_nexthop_cmd);
4622 route_map_install_set (&route_set_local_pref_cmd);
4623 route_map_install_set (&route_set_weight_cmd);
4624 route_map_install_set (&route_set_metric_cmd);
4625 route_map_install_set (&route_set_aspath_prepend_cmd);
841f7a57 4626 route_map_install_set (&route_set_aspath_exclude_cmd);
718e3744 4627 route_map_install_set (&route_set_origin_cmd);
4628 route_map_install_set (&route_set_atomic_aggregate_cmd);
4629 route_map_install_set (&route_set_aggregator_as_cmd);
4630 route_map_install_set (&route_set_community_cmd);
4631 route_map_install_set (&route_set_community_delete_cmd);
4632 route_map_install_set (&route_set_vpnv4_nexthop_cmd);
4633 route_map_install_set (&route_set_originator_id_cmd);
4634 route_map_install_set (&route_set_ecommunity_rt_cmd);
4635 route_map_install_set (&route_set_ecommunity_soo_cmd);
0d9551dc 4636 route_map_install_set (&route_set_tag_cmd);
718e3744 4637
fee0f4c6 4638 install_element (RMAP_NODE, &match_peer_cmd);
4639 install_element (RMAP_NODE, &match_peer_local_cmd);
4640 install_element (RMAP_NODE, &no_match_peer_cmd);
4641 install_element (RMAP_NODE, &no_match_peer_val_cmd);
4642 install_element (RMAP_NODE, &no_match_peer_local_cmd);
718e3744 4643 install_element (RMAP_NODE, &match_ip_address_cmd);
4644 install_element (RMAP_NODE, &no_match_ip_address_cmd);
4645 install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
4646 install_element (RMAP_NODE, &match_ip_next_hop_cmd);
4647 install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
4648 install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
c1643bb7 4649 install_element (RMAP_NODE, &match_ip_route_source_cmd);
4650 install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
4651 install_element (RMAP_NODE, &no_match_ip_route_source_val_cmd);
718e3744 4652 install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
4653 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
4654 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
4655 install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
4656 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
4657 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
c1643bb7 4658 install_element (RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4659 install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
4660 install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_val_cmd);
718e3744 4661
4662 install_element (RMAP_NODE, &match_aspath_cmd);
4663 install_element (RMAP_NODE, &no_match_aspath_cmd);
4664 install_element (RMAP_NODE, &no_match_aspath_val_cmd);
4665 install_element (RMAP_NODE, &match_metric_cmd);
4666 install_element (RMAP_NODE, &no_match_metric_cmd);
4667 install_element (RMAP_NODE, &no_match_metric_val_cmd);
af291c15
DS
4668 install_element (RMAP_NODE, &match_local_pref_cmd);
4669 install_element (RMAP_NODE, &no_match_local_pref_cmd);
4670 install_element (RMAP_NODE, &no_match_local_pref_val_cmd);
718e3744 4671 install_element (RMAP_NODE, &match_community_cmd);
4672 install_element (RMAP_NODE, &match_community_exact_cmd);
4673 install_element (RMAP_NODE, &no_match_community_cmd);
4674 install_element (RMAP_NODE, &no_match_community_val_cmd);
4675 install_element (RMAP_NODE, &no_match_community_exact_cmd);
73ffb25b 4676 install_element (RMAP_NODE, &match_ecommunity_cmd);
4677 install_element (RMAP_NODE, &no_match_ecommunity_cmd);
4678 install_element (RMAP_NODE, &no_match_ecommunity_val_cmd);
718e3744 4679 install_element (RMAP_NODE, &match_origin_cmd);
4680 install_element (RMAP_NODE, &no_match_origin_cmd);
4681 install_element (RMAP_NODE, &no_match_origin_val_cmd);
1add115a
VT
4682 install_element (RMAP_NODE, &match_probability_cmd);
4683 install_element (RMAP_NODE, &no_match_probability_cmd);
4684 install_element (RMAP_NODE, &no_match_probability_val_cmd);
bc413143
DS
4685 install_element (RMAP_NODE, &match_interface_cmd);
4686 install_element (RMAP_NODE, &no_match_interface_cmd);
4687 install_element (RMAP_NODE, &no_match_interface_val_cmd);
0d9551dc
DS
4688 install_element (RMAP_NODE, &match_tag_cmd);
4689 install_element (RMAP_NODE, &no_match_tag_cmd);
4690 install_element (RMAP_NODE, &no_match_tag_val_cmd);
718e3744 4691
4692 install_element (RMAP_NODE, &set_ip_nexthop_cmd);
af5cd0a5 4693 install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
316e074d 4694 install_element (RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
718e3744 4695 install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
4696 install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
47e9b292 4697 install_element (RMAP_NODE, &no_set_ip_nexthop_peer_cmd);
718e3744 4698 install_element (RMAP_NODE, &set_local_pref_cmd);
4699 install_element (RMAP_NODE, &no_set_local_pref_cmd);
4700 install_element (RMAP_NODE, &no_set_local_pref_val_cmd);
4701 install_element (RMAP_NODE, &set_weight_cmd);
4702 install_element (RMAP_NODE, &no_set_weight_cmd);
4703 install_element (RMAP_NODE, &no_set_weight_val_cmd);
4704 install_element (RMAP_NODE, &set_metric_cmd);
73ffb25b 4705 install_element (RMAP_NODE, &set_metric_addsub_cmd);
718e3744 4706 install_element (RMAP_NODE, &no_set_metric_cmd);
4707 install_element (RMAP_NODE, &no_set_metric_val_cmd);
4708 install_element (RMAP_NODE, &set_aspath_prepend_cmd);
841f7a57 4709 install_element (RMAP_NODE, &set_aspath_exclude_cmd);
718e3744 4710 install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
4711 install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
841f7a57
DO
4712 install_element (RMAP_NODE, &no_set_aspath_exclude_cmd);
4713 install_element (RMAP_NODE, &no_set_aspath_exclude_val_cmd);
718e3744 4714 install_element (RMAP_NODE, &set_origin_cmd);
4715 install_element (RMAP_NODE, &no_set_origin_cmd);
4716 install_element (RMAP_NODE, &no_set_origin_val_cmd);
4717 install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
4718 install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
4719 install_element (RMAP_NODE, &set_aggregator_as_cmd);
4720 install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
4721 install_element (RMAP_NODE, &no_set_aggregator_as_val_cmd);
4722 install_element (RMAP_NODE, &set_community_cmd);
4723 install_element (RMAP_NODE, &set_community_none_cmd);
4724 install_element (RMAP_NODE, &no_set_community_cmd);
4725 install_element (RMAP_NODE, &no_set_community_val_cmd);
4726 install_element (RMAP_NODE, &no_set_community_none_cmd);
4727 install_element (RMAP_NODE, &set_community_delete_cmd);
4728 install_element (RMAP_NODE, &no_set_community_delete_cmd);
4729 install_element (RMAP_NODE, &no_set_community_delete_val_cmd);
4730 install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
4731 install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
4732 install_element (RMAP_NODE, &no_set_ecommunity_rt_val_cmd);
4733 install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
4734 install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
4735 install_element (RMAP_NODE, &no_set_ecommunity_soo_val_cmd);
4736 install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
4737 install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
4738 install_element (RMAP_NODE, &no_set_vpnv4_nexthop_val_cmd);
4739 install_element (RMAP_NODE, &set_originator_id_cmd);
4740 install_element (RMAP_NODE, &no_set_originator_id_cmd);
4741 install_element (RMAP_NODE, &no_set_originator_id_val_cmd);
0d9551dc
DS
4742 install_element (RMAP_NODE, &set_tag_cmd);
4743 install_element (RMAP_NODE, &no_set_tag_cmd);
4744 install_element (RMAP_NODE, &no_set_tag_val_cmd);
718e3744 4745
4746#ifdef HAVE_IPV6
4747 route_map_install_match (&route_match_ipv6_address_cmd);
4748 route_map_install_match (&route_match_ipv6_next_hop_cmd);
4749 route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
4750 route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
4751 route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
90916ac2
DS
4752 route_map_install_set (&route_set_ipv6_nexthop_peer_cmd);
4753
718e3744 4754 install_element (RMAP_NODE, &match_ipv6_address_cmd);
4755 install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
4756 install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
4757 install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
4758 install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
4759 install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
4760 install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
4761 install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
4762 install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_val_cmd);
4763 install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
4764 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
4765 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
90916ac2
DS
4766 install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
4767 install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
718e3744 4768#endif /* HAVE_IPV6 */
4769}
518f0eb1
DS
4770
4771void
4772bgp_route_map_terminate (void)
4773{
4774 /* ToDo: Cleanup all the used memory */
4775
4776 route_map_add_hook (NULL);
4777 route_map_delete_hook (NULL);
4778 route_map_event_hook (NULL);
4779 route_map_finish();
4780
4781}