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