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