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