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