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