]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
Merge branch 'evpn-prep'
[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];
e6fda497 2154 int ret;
718e3744 2155
393deb9b 2156 aggregator = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct aggregator));
718e3744 2157 sscanf (arg, "%s %s", as, address);
2158
2159 aggregator->as = strtoul (as, NULL, 10);
e6fda497
DS
2160 ret = inet_aton (address, &aggregator->address);
2161 if (ret == 0)
2162 {
2163 XFREE (MTYPE_ROUTE_MAP_COMPILED, aggregator);
2164 return NULL;
2165 }
718e3744 2166 return aggregator;
2167}
2168
94f2b392 2169static void
718e3744 2170route_set_aggregator_as_free (void *rule)
2171{
2172 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2173}
2174
e52702f2 2175struct route_map_rule_cmd route_set_aggregator_as_cmd =
718e3744 2176{
2177 "aggregator as",
2178 route_set_aggregator_as,
2179 route_set_aggregator_as_compile,
2180 route_set_aggregator_as_free,
2181};
6b0655a2 2182
0d9551dc
DS
2183/* Set tag to object. object must be pointer to struct bgp_info */
2184static route_map_result_t
2185route_set_tag (void *rule, struct prefix *prefix,
2186 route_map_object_t type, void *object)
2187{
dc9ffce8 2188 route_tag_t *tag;
0d9551dc
DS
2189 struct bgp_info *bgp_info;
2190 struct attr_extra *ae;
2191
2192 if (type == RMAP_BGP)
2193 {
2194 tag = rule;
2195 bgp_info = object;
2196 ae = bgp_attr_extra_get (bgp_info->attr);
2197
2198 /* Set tag value */
2199 ae->tag=*tag;
2200
2201 }
2202
2203 return RMAP_OKAY;
2204}
2205
0d9551dc 2206/* Route map commands for tag set. */
dc9ffce8 2207static struct route_map_rule_cmd route_set_tag_cmd =
0d9551dc
DS
2208{
2209 "tag",
2210 route_set_tag,
dc9ffce8
CF
2211 route_map_rule_tag_compile,
2212 route_map_rule_tag_free,
0d9551dc
DS
2213};
2214
d990e384
DS
2215/* Set label-index to object. object must be pointer to struct bgp_info */
2216static route_map_result_t
2217route_set_label_index (void *rule, struct prefix *prefix,
2218 route_map_object_t type, void *object)
2219{
2220 struct rmap_value *rv;
2221 struct bgp_info *bgp_info;
2222 u_int32_t label_index;
2223
2224 if (type == RMAP_BGP)
2225 {
2226 /* Fetch routemap's rule information. */
2227 rv = rule;
2228 bgp_info = object;
2229
2230 /* Set label-index value. */
2231 label_index = rv->value;
2232 if (label_index)
2233 {
2234 (bgp_attr_extra_get (bgp_info->attr))->label_index = label_index;
2235 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID);
2236 }
2237 }
2238
2239 return RMAP_OKAY;
2240}
2241
2242/* Route map commands for label-index set. */
2243static struct route_map_rule_cmd route_set_label_index_cmd =
2244{
2245 "label-index",
2246 route_set_label_index,
2247 route_value_compile,
2248 route_value_free,
2249};
0d9551dc 2250
718e3744 2251/* `match ipv6 address IP_ACCESS_LIST' */
2252
94f2b392 2253static route_map_result_t
e52702f2 2254route_match_ipv6_address (void *rule, struct prefix *prefix,
718e3744 2255 route_map_object_t type, void *object)
2256{
2257 struct access_list *alist;
2258
2259 if (type == RMAP_BGP)
2260 {
2261 alist = access_list_lookup (AFI_IP6, (char *) rule);
2262 if (alist == NULL)
2263 return RMAP_NOMATCH;
e52702f2 2264
718e3744 2265 return (access_list_apply (alist, prefix) == FILTER_DENY ?
2266 RMAP_NOMATCH : RMAP_MATCH);
2267 }
2268 return RMAP_NOMATCH;
2269}
2270
94f2b392 2271static void *
fd79ac91 2272route_match_ipv6_address_compile (const char *arg)
718e3744 2273{
2274 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
2275}
2276
94f2b392 2277static void
718e3744 2278route_match_ipv6_address_free (void *rule)
2279{
2280 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2281}
2282
2283/* Route map commands for ip address matching. */
2284struct route_map_rule_cmd route_match_ipv6_address_cmd =
2285{
2286 "ipv6 address",
2287 route_match_ipv6_address,
2288 route_match_ipv6_address_compile,
2289 route_match_ipv6_address_free
2290};
6b0655a2 2291
718e3744 2292/* `match ipv6 next-hop IP_ADDRESS' */
2293
94f2b392 2294static route_map_result_t
e52702f2 2295route_match_ipv6_next_hop (void *rule, struct prefix *prefix,
718e3744 2296 route_map_object_t type, void *object)
2297{
1f9a9fff 2298 struct in6_addr *addr = rule;
718e3744 2299 struct bgp_info *bgp_info;
2300
2301 if (type == RMAP_BGP)
2302 {
718e3744 2303 bgp_info = object;
e52702f2 2304
fb982c25
PJ
2305 if (!bgp_info->attr->extra)
2306 return RMAP_NOMATCH;
e52702f2 2307
1f9a9fff 2308 if (IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_global, addr))
718e3744 2309 return RMAP_MATCH;
2310
801a9bcc 2311 if (bgp_info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL &&
fb982c25 2312 IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_local, rule))
718e3744 2313 return RMAP_MATCH;
2314
2315 return RMAP_NOMATCH;
2316 }
2317
2318 return RMAP_NOMATCH;
2319}
2320
94f2b392 2321static void *
fd79ac91 2322route_match_ipv6_next_hop_compile (const char *arg)
718e3744 2323{
2324 struct in6_addr *address;
2325 int ret;
2326
2327 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
2328
2329 ret = inet_pton (AF_INET6, arg, address);
2330 if (!ret)
2331 {
2332 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2333 return NULL;
2334 }
2335
2336 return address;
2337}
2338
94f2b392 2339static void
718e3744 2340route_match_ipv6_next_hop_free (void *rule)
2341{
2342 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2343}
2344
2345struct route_map_rule_cmd route_match_ipv6_next_hop_cmd =
2346{
2347 "ipv6 next-hop",
2348 route_match_ipv6_next_hop,
2349 route_match_ipv6_next_hop_compile,
2350 route_match_ipv6_next_hop_free
2351};
6b0655a2 2352
718e3744 2353/* `match ipv6 address prefix-list PREFIX_LIST' */
2354
94f2b392 2355static route_map_result_t
e52702f2 2356route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix,
718e3744 2357 route_map_object_t type, void *object)
2358{
2359 struct prefix_list *plist;
2360
2361 if (type == RMAP_BGP)
2362 {
2363 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
2364 if (plist == NULL)
2365 return RMAP_NOMATCH;
e52702f2 2366
718e3744 2367 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
2368 RMAP_NOMATCH : RMAP_MATCH);
2369 }
2370 return RMAP_NOMATCH;
2371}
2372
94f2b392 2373static void *
fd79ac91 2374route_match_ipv6_address_prefix_list_compile (const char *arg)
718e3744 2375{
2376 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
2377}
2378
94f2b392 2379static void
718e3744 2380route_match_ipv6_address_prefix_list_free (void *rule)
2381{
2382 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2383}
2384
2385struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
2386{
2387 "ipv6 address prefix-list",
2388 route_match_ipv6_address_prefix_list,
2389 route_match_ipv6_address_prefix_list_compile,
2390 route_match_ipv6_address_prefix_list_free
2391};
6b0655a2 2392
718e3744 2393/* `set ipv6 nexthop global IP_ADDRESS' */
2394
2395/* Set nexthop to object. ojbect must be pointer to struct attr. */
94f2b392 2396static route_map_result_t
e52702f2 2397route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix,
718e3744 2398 route_map_object_t type, void *object)
2399{
2400 struct in6_addr *address;
2401 struct bgp_info *bgp_info;
2402
2403 if (type == RMAP_BGP)
2404 {
2405 /* Fetch routemap's rule information. */
2406 address = rule;
2407 bgp_info = object;
e52702f2
QY
2408
2409 /* Set next hop value. */
fb982c25 2410 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = *address;
3f9c7369 2411
718e3744 2412 /* Set nexthop length. */
fb982c25 2413 if (bgp_info->attr->extra->mp_nexthop_len == 0)
801a9bcc 2414 bgp_info->attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369
DS
2415
2416 SET_FLAG(bgp_info->attr->rmap_change_flags,
3811f1e2 2417 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
718e3744 2418 }
2419
2420 return RMAP_OKAY;
2421}
2422
2423/* Route map `ip next-hop' compile function. Given string is converted
2424 to struct in_addr structure. */
94f2b392 2425static void *
fd79ac91 2426route_set_ipv6_nexthop_global_compile (const char *arg)
718e3744 2427{
2428 int ret;
2429 struct in6_addr *address;
2430
2431 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
2432
2433 ret = inet_pton (AF_INET6, arg, address);
2434
2435 if (ret == 0)
2436 {
2437 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2438 return NULL;
2439 }
2440
2441 return address;
2442}
2443
2444/* Free route map's compiled `ip next-hop' value. */
94f2b392 2445static void
718e3744 2446route_set_ipv6_nexthop_global_free (void *rule)
2447{
2448 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2449}
2450
2451/* Route map commands for ip nexthop set. */
2452struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd =
2453{
2454 "ipv6 next-hop global",
2455 route_set_ipv6_nexthop_global,
2456 route_set_ipv6_nexthop_global_compile,
2457 route_set_ipv6_nexthop_global_free
2458};
6b0655a2 2459
161995ea
DS
2460/* Set next-hop preference value. */
2461static route_map_result_t
2462route_set_ipv6_nexthop_prefer_global (void *rule, struct prefix *prefix,
2463 route_map_object_t type, void *object)
2464{
2465 struct bgp_info *bgp_info;
2466 struct peer *peer;
2467
2468 if (type == RMAP_BGP)
2469 {
2470 /* Fetch routemap's rule information. */
2471 bgp_info = object;
2472 peer = bgp_info->peer;
2473
2474 if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
2475 CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
2476 && peer->su_remote
2477 && sockunion_family (peer->su_remote) == AF_INET6)
2478 {
2479 /* Set next hop preference to global */
2480 bgp_info->attr->extra->mp_nexthop_prefer_global = TRUE;
2481 SET_FLAG(bgp_info->attr->rmap_change_flags,
b2e03f7a 2482 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
161995ea 2483 }
b2e03f7a 2484 else
2485 {
2486 bgp_info->attr->extra->mp_nexthop_prefer_global = FALSE;
2487 SET_FLAG(bgp_info->attr->rmap_change_flags,
2488 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
2489 }
161995ea
DS
2490 }
2491 return RMAP_OKAY;
2492}
2493
2494static void *
2495route_set_ipv6_nexthop_prefer_global_compile (const char *arg)
2496{
2497 int *rins = NULL;
2498
2499 rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int));
2500 *rins = 1;
2501
2502 return rins;
2503}
2504
2505/* Free route map's compiled `ip next-hop' value. */
2506static void
2507route_set_ipv6_nexthop_prefer_global_free (void *rule)
2508{
2509 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2510}
2511
2512/* Route map commands for ip nexthop set preferred. */
2513struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd =
2514{
2515 "ipv6 next-hop prefer-global",
2516 route_set_ipv6_nexthop_prefer_global,
2517 route_set_ipv6_nexthop_prefer_global_compile,
2518 route_set_ipv6_nexthop_prefer_global_free
2519};
2520
718e3744 2521/* `set ipv6 nexthop local IP_ADDRESS' */
2522
2523/* Set nexthop to object. ojbect must be pointer to struct attr. */
94f2b392 2524static route_map_result_t
e52702f2 2525route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
718e3744 2526 route_map_object_t type, void *object)
2527{
2528 struct in6_addr *address;
2529 struct bgp_info *bgp_info;
2530
2531 if (type == RMAP_BGP)
2532 {
2533 /* Fetch routemap's rule information. */
2534 address = rule;
2535 bgp_info = object;
e52702f2
QY
2536
2537 /* Set next hop value. */
fb982c25 2538 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = *address;
e52702f2 2539
718e3744 2540 /* Set nexthop length. */
801a9bcc
DS
2541 if (bgp_info->attr->extra->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
2542 bgp_info->attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3f9c7369
DS
2543
2544 SET_FLAG(bgp_info->attr->rmap_change_flags,
3811f1e2 2545 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
718e3744 2546 }
2547
2548 return RMAP_OKAY;
2549}
2550
2551/* Route map `ip nexthop' compile function. Given string is converted
2552 to struct in_addr structure. */
94f2b392 2553static void *
fd79ac91 2554route_set_ipv6_nexthop_local_compile (const char *arg)
718e3744 2555{
2556 int ret;
2557 struct in6_addr *address;
2558
2559 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
2560
2561 ret = inet_pton (AF_INET6, arg, address);
2562
2563 if (ret == 0)
2564 {
2565 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2566 return NULL;
2567 }
2568
2569 return address;
2570}
2571
2572/* Free route map's compiled `ip nexthop' value. */
94f2b392 2573static void
718e3744 2574route_set_ipv6_nexthop_local_free (void *rule)
2575{
2576 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2577}
2578
2579/* Route map commands for ip nexthop set. */
2580struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
2581{
2582 "ipv6 next-hop local",
2583 route_set_ipv6_nexthop_local,
2584 route_set_ipv6_nexthop_local_compile,
2585 route_set_ipv6_nexthop_local_free
2586};
90916ac2
DS
2587
2588/* `set ipv6 nexthop peer-address' */
2589
2590/* Set nexthop to object. ojbect must be pointer to struct attr. */
2591static route_map_result_t
2592route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix,
2593 route_map_object_t type, void *object)
2594{
90916ac2
DS
2595 struct in6_addr peer_address;
2596 struct bgp_info *bgp_info;
2597 struct peer *peer;
90916ac2
DS
2598
2599 if (type == RMAP_BGP)
2600 {
2601 /* Fetch routemap's rule information. */
90916ac2
DS
2602 bgp_info = object;
2603 peer = bgp_info->peer;
2604
2605 if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
2606 CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
2607 && peer->su_remote
2608 && sockunion_family (peer->su_remote) == AF_INET6)
2609 {
6e71194f 2610 peer_address = peer->su_remote->sin6.sin6_addr;
2665d9ae
DS
2611 /* Set next hop value and length in attribute. */
2612 if (IN6_IS_ADDR_LINKLOCAL(&peer_address))
2613 {
2614 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = peer_address;
2615 if (bgp_info->attr->extra->mp_nexthop_len != 32)
2616 bgp_info->attr->extra->mp_nexthop_len = 32;
2617 }
2618 else
2619 {
2620 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = peer_address;
2621 if (bgp_info->attr->extra->mp_nexthop_len == 0)
2622 bgp_info->attr->extra->mp_nexthop_len = 16;
2623 }
2624
90916ac2 2625 }
3f9c7369 2626 else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT))
90916ac2 2627 {
2665d9ae
DS
2628 /* The next hop value will be set as part of packet rewrite.
2629 * Set the flags here to indicate that rewrite needs to be done.
2630 * Also, clear the value - we clear both global and link-local
2631 * nexthops, whether we send one or both is determined elsewhere.
2632 */
3f9c7369
DS
2633 SET_FLAG(bgp_info->attr->rmap_change_flags,
2634 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3f9c7369
DS
2635 /* clear next hop value. */
2636 memset (&((bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global),
2637 0, sizeof (struct in6_addr));
2665d9ae
DS
2638 memset (&((bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local),
2639 0, sizeof (struct in6_addr));
90916ac2
DS
2640 }
2641 }
2642
2643 return RMAP_OKAY;
2644}
2645
2646/* Route map `ip next-hop' compile function. Given string is converted
2647 to struct in_addr structure. */
2648static void *
2649route_set_ipv6_nexthop_peer_compile (const char *arg)
2650{
90916ac2
DS
2651 int *rins = NULL;
2652
2653 rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int));
2654 *rins = 1;
2655
2656 return rins;
2657}
2658
2659/* Free route map's compiled `ip next-hop' value. */
2660static void
2661route_set_ipv6_nexthop_peer_free (void *rule)
2662{
2663 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2664}
2665
2666/* Route map commands for ip nexthop set. */
2667struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd =
2668{
2669 "ipv6 next-hop peer-address",
2670 route_set_ipv6_nexthop_peer,
2671 route_set_ipv6_nexthop_peer_compile,
2672 route_set_ipv6_nexthop_peer_free
2673};
2674
d6902373 2675/* `set ip vpn nexthop A.B.C.D' */
718e3744 2676
94f2b392 2677static route_map_result_t
e52702f2 2678route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
718e3744 2679 route_map_object_t type, void *object)
2680{
2681 struct in_addr *address;
2682 struct bgp_info *bgp_info;
2683
2684 if (type == RMAP_BGP)
2685 {
2686 /* Fetch routemap's rule information. */
2687 address = rule;
2688 bgp_info = object;
e52702f2
QY
2689
2690 /* Set next hop value. */
fb982c25 2691 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address;
93b73dfa 2692 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = 4;
718e3744 2693 }
2694
2695 return RMAP_OKAY;
2696}
2697
94f2b392 2698static void *
fd79ac91 2699route_set_vpnv4_nexthop_compile (const char *arg)
718e3744 2700{
2701 int ret;
2702 struct in_addr *address;
2703
2704 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
2705
2706 ret = inet_aton (arg, address);
2707
2708 if (ret == 0)
2709 {
2710 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2711 return NULL;
2712 }
2713
2714 return address;
2715}
2716
d6902373
PG
2717/* `set ipv6 vpn nexthop A.B.C.D' */
2718
2719static route_map_result_t
2720route_set_vpnv6_nexthop (void *rule, struct prefix *prefix,
2721 route_map_object_t type, void *object)
2722{
2723 struct in6_addr *address;
2724 struct bgp_info *bgp_info;
2725
2726 if (type == RMAP_BGP)
2727 {
2728 /* Fetch routemap's rule information. */
2729 address = rule;
2730 bgp_info = object;
2731
2732 /* Set next hop value. */
2733 memcpy (&(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global, address, sizeof(struct in6_addr));
2734 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
2735 }
2736
2737 return RMAP_OKAY;
2738}
2739
2740static void *
2741route_set_vpnv6_nexthop_compile (const char *arg)
2742{
2743 int ret;
2744 struct in6_addr *address;
2745
2746 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
2747 ret = inet_pton (AF_INET6, arg, address);
2748
2749 if (ret == 0)
2750 {
2751 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2752 return NULL;
2753 }
2754
2755 return address;
2756}
2757
94f2b392 2758static void
d6902373 2759route_set_vpn_nexthop_free (void *rule)
718e3744 2760{
2761 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2762}
2763
2764/* Route map commands for ip nexthop set. */
2765struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd =
2766{
d6902373 2767 "ip vpn next-hop",
718e3744 2768 route_set_vpnv4_nexthop,
2769 route_set_vpnv4_nexthop_compile,
d6902373
PG
2770 route_set_vpn_nexthop_free
2771};
2772
2773/* Route map commands for ip nexthop set. */
2774struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd =
2775{
2776 "ipv6 vpn next-hop",
2777 route_set_vpnv6_nexthop,
2778 route_set_vpnv6_nexthop_compile,
2779 route_set_vpn_nexthop_free
718e3744 2780};
6b0655a2 2781
718e3744 2782/* `set originator-id' */
2783
2784/* For origin set. */
94f2b392 2785static route_map_result_t
718e3744 2786route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
2787{
2788 struct in_addr *address;
2789 struct bgp_info *bgp_info;
2790
e52702f2 2791 if (type == RMAP_BGP)
718e3744 2792 {
2793 address = rule;
2794 bgp_info = object;
e52702f2 2795
718e3744 2796 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
fb982c25 2797 (bgp_attr_extra_get (bgp_info->attr))->originator_id = *address;
718e3744 2798 }
2799
2800 return RMAP_OKAY;
2801}
2802
2803/* Compile function for originator-id set. */
94f2b392 2804static void *
fd79ac91 2805route_set_originator_id_compile (const char *arg)
718e3744 2806{
2807 int ret;
2808 struct in_addr *address;
2809
2810 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
2811
2812 ret = inet_aton (arg, address);
2813
2814 if (ret == 0)
2815 {
2816 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2817 return NULL;
2818 }
2819
2820 return address;
2821}
2822
2823/* Compile function for originator_id set. */
94f2b392 2824static void
718e3744 2825route_set_originator_id_free (void *rule)
2826{
2827 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2828}
2829
515e500c 2830/* Set originator-id rule structure. */
e52702f2 2831struct route_map_rule_cmd route_set_originator_id_cmd =
718e3744 2832{
2833 "originator-id",
2834 route_set_originator_id,
2835 route_set_originator_id_compile,
2836 route_set_originator_id_free,
2837};
6b0655a2 2838
718e3744 2839/* Add bgp route map rule. */
94f2b392 2840static int
cdc2d765 2841bgp_route_match_add (struct vty *vty,
518f0eb1
DS
2842 const char *command, const char *arg,
2843 route_map_event_t type)
718e3744 2844{
cdc2d765 2845 VTY_DECLVAR_CONTEXT(route_map_index, index);
718e3744 2846 int ret;
2847
2848 ret = route_map_add_match (index, command, arg);
2849 if (ret)
2850 {
2851 switch (ret)
2852 {
2853 case RMAP_RULE_MISSING:
96ade3ed 2854 vty_outln (vty, "%% BGP Can't find rule.");
718e3744 2855 return CMD_WARNING;
718e3744 2856 case RMAP_COMPILE_ERROR:
96ade3ed 2857 vty_outln (vty, "%% BGP Argument is malformed.");
718e3744 2858 return CMD_WARNING;
718e3744 2859 }
2860 }
518f0eb1
DS
2861
2862 if (type != RMAP_EVENT_MATCH_ADDED)
2863 {
2864 route_map_upd8_dependency (type, arg, index->map->name);
2865 }
2866
718e3744 2867 return CMD_SUCCESS;
2868}
2869
2870/* Delete bgp route map rule. */
94f2b392 2871static int
cdc2d765 2872bgp_route_match_delete (struct vty *vty,
518f0eb1
DS
2873 const char *command, const char *arg,
2874 route_map_event_t type)
718e3744 2875{
cdc2d765 2876 VTY_DECLVAR_CONTEXT(route_map_index, index);
718e3744 2877 int ret;
ffd0c037 2878 char *dep_name = NULL;
518f0eb1
DS
2879 const char *tmpstr;
2880 char *rmap_name = NULL;
718e3744 2881
518f0eb1
DS
2882 if (type != RMAP_EVENT_MATCH_DELETED)
2883 {
2884 /* ignore the mundane, the types without any dependency */
2885 if (arg == NULL)
2886 {
2887 if ((tmpstr = route_map_get_match_arg(index, command)) != NULL)
2888 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
2889 }
ffd0c037
DS
2890 else
2891 {
2892 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
2893 }
518f0eb1
DS
2894 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
2895 }
2896
2897 ret = route_map_delete_match (index, command, dep_name);
718e3744 2898 if (ret)
2899 {
2900 switch (ret)
2901 {
2902 case RMAP_RULE_MISSING:
96ade3ed 2903 vty_outln (vty, "%% BGP Can't find rule.");
518f0eb1 2904 break;
718e3744 2905 case RMAP_COMPILE_ERROR:
96ade3ed 2906 vty_outln (vty, "%% BGP Argument is malformed.");
518f0eb1 2907 break;
718e3744 2908 }
ffd0c037 2909 if (dep_name)
518f0eb1
DS
2910 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
2911 if (rmap_name)
2912 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
2913 return CMD_WARNING;
718e3744 2914 }
518f0eb1
DS
2915
2916 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
2917 route_map_upd8_dependency(type, dep_name, rmap_name);
2918
ffd0c037 2919 if (dep_name)
518f0eb1
DS
2920 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
2921 if (rmap_name)
2922 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
2923
718e3744 2924 return CMD_SUCCESS;
2925}
2926
518f0eb1 2927/*
2a3d5731 2928 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
2929 * modifications.
2930 */
94f2b392 2931static void
a6e0d253
DW
2932bgp_route_map_process_peer (const char *rmap_name, struct route_map *map,
2933 struct peer *peer, int afi, int safi,
2934 int route_update)
718e3744 2935{
518f0eb1
DS
2936
2937 int update;
718e3744 2938 struct bgp_filter *filter;
718e3744 2939
518f0eb1
DS
2940 if (!peer || !rmap_name)
2941 return;
2942
2943 filter = &peer->filter[afi][safi];
2944 /*
2945 * in is for non-route-server clients,
518f0eb1
DS
2946 * out is for all peers
2947 */
2948 if (!CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT))
718e3744 2949 {
518f0eb1
DS
2950 if (filter->map[RMAP_IN].name &&
2951 (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0))
718e3744 2952 {
a6e0d253 2953 filter->map[RMAP_IN].map = map;
518f0eb1 2954
fa5f7ad5 2955 if (route_update && peer->status == Established)
518f0eb1
DS
2956 {
2957 if (CHECK_FLAG (peer->af_flags[afi][safi],
2958 PEER_FLAG_SOFT_RECONFIG))
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 (inbound, soft-reconfig)",
2963 rmap_name, peer->host);
2964
2965 bgp_soft_reconfig_in (peer, afi, safi);
2966 }
2967 else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2968 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2969 {
2970
3f9c7369 2971 if (bgp_debug_update(peer, NULL, NULL, 1))
518f0eb1
DS
2972 zlog_debug("Processing route_map %s update on "
2973 "peer %s (inbound, route-refresh)",
2974 rmap_name, peer->host);
2975 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2976 }
2977 }
718e3744 2978 }
2979 }
2980
518f0eb1 2981 if (CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT))
718e3744 2982 {
518f0eb1
DS
2983 update = 0;
2984
fa5f7ad5 2985 if (update && route_update && peer->status == Established)
518f0eb1
DS
2986 {
2987 if (CHECK_FLAG (peer->af_flags[afi][safi],
2988 PEER_FLAG_SOFT_RECONFIG))
2989 {
3f9c7369 2990 if (bgp_debug_update(peer, NULL, NULL, 1))
518f0eb1
DS
2991 zlog_debug("Processing route_map %s update on "
2992 "peer %s (import, soft-reconfig)",
2993 rmap_name, peer->host);
2994
2995 bgp_soft_reconfig_in (peer, afi, safi);
2996 }
2997 else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2998 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2999 {
3f9c7369 3000 if (bgp_debug_update(peer, NULL, NULL, 1))
518f0eb1
DS
3001 zlog_debug("Processing route_map %s update on "
3002 "peer %s (import, route-refresh)",
3003 rmap_name, peer->host);
3004 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
3005 }
3006 /* DD: Else, what else do we do ? Reset peer ? */
718e3744 3007 }
3008 }
3009
3f9c7369
DS
3010 /*
3011 * For outbound, unsuppress and default-originate map change (content or
3012 * map created), merely update the "config" here, the actual route
3013 * announcement happens at the group level.
3014 */
518f0eb1 3015 if (filter->map[RMAP_OUT].name &&
3f9c7369 3016 (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
a6e0d253 3017 filter->map[RMAP_OUT].map = map;
518f0eb1
DS
3018
3019 if (filter->usmap.name &&
3020 (strcmp(rmap_name, filter->usmap.name) == 0))
a6e0d253 3021 filter->usmap.map = map;
3f9c7369
DS
3022
3023 if (peer->default_rmap[afi][safi].name &&
3024 (strcmp (rmap_name, peer->default_rmap[afi][safi].name) == 0))
a6e0d253 3025 peer->default_rmap[afi][safi].map = map;
518f0eb1 3026}
73ac8160 3027
518f0eb1 3028static void
a6e0d253
DW
3029bgp_route_map_update_peer_group(const char *rmap_name, struct route_map *map,
3030 struct bgp *bgp)
518f0eb1
DS
3031{
3032 struct peer_group *group;
3033 struct listnode *node, *nnode;
3034 struct bgp_filter *filter;
3035 int afi, safi;
3036 int direct;
3037
3038 if (!bgp)
3039 return;
3040
3041 /* All the peers have been updated correctly already. This is
3042 * just updating the placeholder data. No real update required.
3043 */
3044 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3045 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3046 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3047 {
3048 filter = &group->conf->filter[afi][safi];
3049
3050 for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
3051 {
3052 if ((filter->map[direct].name) &&
3053 (strcmp(rmap_name, filter->map[direct].name) == 0))
a6e0d253 3054 filter->map[direct].map = map;
518f0eb1
DS
3055 }
3056
3057 if (filter->usmap.name &&
3058 (strcmp(rmap_name, filter->usmap.name) == 0))
a6e0d253 3059 filter->usmap.map = map;
518f0eb1
DS
3060 }
3061}
3062
a6e0d253
DW
3063/*
3064 * Note that if an extreme number (tens of thousands) of route-maps are in use
3065 * and if bgp has an extreme number of peers, network statements, etc then this
3066 * function can consume a lot of cycles. This is due to this function being
3067 * called for each route-map and within this function we walk the list of peers,
3068 * network statements, etc looking to see if they use this route-map.
3069 */
5fe9f963 3070static void
3071bgp_route_map_process_update (struct bgp *bgp, const char *rmap_name, int route_update)
518f0eb1
DS
3072{
3073 int i;
3074 afi_t afi;
3075 safi_t safi;
3076 struct peer *peer;
3077 struct bgp_node *bn;
3078 struct bgp_static *bgp_static;
518f0eb1 3079 struct listnode *node, *nnode;
a6e0d253 3080 struct route_map *map;
518f0eb1
DS
3081 char buf[INET6_ADDRSTRLEN];
3082
a6e0d253
DW
3083 map = route_map_lookup_by_name (rmap_name);
3084
518f0eb1 3085 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 3086 {
518f0eb1
DS
3087
3088 /* Ignore dummy peer-group structure */
3089 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
3090 continue;
3091
718e3744 3092 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3093 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
518f0eb1
DS
3094 {
3095 /* Ignore inactive AFI/SAFI */
3096 if (! peer->afc[afi][safi])
3097 continue;
3098
3f9c7369 3099 /* process in/out/import/export/default-orig route-maps */
a6e0d253 3100 bgp_route_map_process_peer(rmap_name, map, peer, afi, safi, route_update);
518f0eb1 3101 }
718e3744 3102 }
3103
3f9c7369
DS
3104 /* for outbound/default-orig route-maps, process for groups */
3105 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
3106 route_update, 0);
3107
3108 /* update peer-group config (template) */
a6e0d253 3109 bgp_route_map_update_peer_group(rmap_name, map, bgp);
518f0eb1 3110
518f0eb1
DS
3111 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3112 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3113 {
a6e0d253 3114 /* For table route-map updates. */
518f0eb1
DS
3115 if (bgp->table_map[afi][safi].name &&
3116 (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0))
3117 {
a6e0d253
DW
3118 bgp->table_map[afi][safi].map = map;
3119
16286195 3120 if (BGP_DEBUG (zebra, ZEBRA))
518f0eb1
DS
3121 zlog_debug("Processing route_map %s update on "
3122 "table map", rmap_name);
3123 if (route_update)
3124 bgp_zebra_announce_table(bgp, afi, safi);
3125 }
518f0eb1 3126
a6e0d253
DW
3127 /* For network route-map updates. */
3128 for (bn = bgp_table_top (bgp->route[afi][safi]); bn; bn = bgp_route_next (bn))
3129 if ((bgp_static = bn->info) != NULL)
3130 {
3131 if (bgp_static->rmap.name &&
3132 (strcmp(rmap_name, bgp_static->rmap.name) == 0))
3133 {
3134 bgp_static->rmap.map = map;
3135
3136 if (route_update)
3137 if (!bgp_static->backdoor)
3138 {
3139 if (bgp_debug_zebra(&bn->p))
3140 zlog_debug("Processing route_map %s update on "
3141 "static route %s", rmap_name,
3142 inet_ntop (bn->p.family, &bn->p.u.prefix,
3143 buf, INET6_ADDRSTRLEN));
3144 bgp_static_update (bgp, &bn->p, bgp_static, afi, safi);
3145 }
3146 }
3147 }
3148 }
518f0eb1 3149
718e3744 3150 /* For redistribute route-map updates. */
518f0eb1
DS
3151 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3152 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3153 {
7c8ff89e
DS
3154 struct list *red_list;
3155 struct listnode *node;
3156 struct bgp_redist *red;
3157
3158 red_list = bgp->redist[afi][i];
3159 if (!red_list)
3160 continue;
3161
3162 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
3163 {
3164 if (red->rmap.name &&
3165 (strcmp(rmap_name, red->rmap.name) == 0))
3166 {
a6e0d253 3167 red->rmap.map = map;
7c8ff89e
DS
3168
3169 if (route_update)
3170 {
3f9c7369 3171 if (BGP_DEBUG (zebra, ZEBRA))
7c8ff89e
DS
3172 zlog_debug("Processing route_map %s update on "
3173 "redistributed routes", rmap_name);
3174
3175 bgp_redistribute_resend (bgp, afi, i, red->instance);
3176 }
3177 }
518f0eb1
DS
3178 }
3179 }
518f0eb1
DS
3180}
3181
3182static int
5fe9f963 3183bgp_route_map_process_update_cb (char *rmap_name)
518f0eb1 3184{
5fe9f963 3185 struct listnode *node, *nnode;
3186 struct bgp *bgp;
3187
3188 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
3189 bgp_route_map_process_update(bgp, rmap_name, 1);
3190
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 return 0;
518f0eb1
DS
3196}
3197
3198int
3199bgp_route_map_update_timer(struct thread *thread)
3200{
5fe9f963 3201 bm->t_rmap_update = NULL;
518f0eb1 3202
5fe9f963 3203 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1 3204
518f0eb1
DS
3205 return (0);
3206}
3207
3208static void
ffd0c037 3209bgp_route_map_mark_update (const char *rmap_name)
518f0eb1 3210{
5fe9f963 3211 if (bm->t_rmap_update == NULL)
718e3744 3212 {
5fe9f963 3213 struct listnode *node, *nnode;
3214 struct bgp *bgp;
3f9c7369 3215
5fe9f963 3216 /* rmap_update_timer of 0 means don't do route updates */
3217 if (bm->rmap_update_timer)
3218 {
66e78ae6
QY
3219 bm->t_rmap_update = NULL;
3220 thread_add_timer(bm->master, bgp_route_map_update_timer, NULL, bm->rmap_update_timer,
3221 &bm->t_rmap_update);
5fe9f963 3222
3223 /* Signal the groups that a route-map update event has started */
3224 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
3225 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name, 1, 1);
3226 }
3227 else
3228 {
3229 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
3230 bgp_route_map_process_update(bgp, rmap_name, 0);
65efcfce
LB
3231 #if ENABLE_BGP_VNC
3232 zlog_debug("%s: calling vnc_routemap_update", __func__);
3233 vnc_routemap_update(bgp, __func__);
3234#endif
5fe9f963 3235 }
718e3744 3236 }
3237}
6b0655a2 3238
73ac8160 3239static void
518f0eb1 3240bgp_route_map_add (const char *rmap_name)
73ac8160 3241{
518f0eb1
DS
3242 if (route_map_mark_updated(rmap_name, 0) == 0)
3243 bgp_route_map_mark_update(rmap_name);
73ac8160 3244
518f0eb1 3245 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 3246}
518f0eb1 3247
73ac8160 3248static void
518f0eb1 3249bgp_route_map_delete (const char *rmap_name)
73ac8160 3250{
518f0eb1
DS
3251 if (route_map_mark_updated(rmap_name, 1) == 0)
3252 bgp_route_map_mark_update(rmap_name);
73ac8160 3253
518f0eb1 3254 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 3255}
518f0eb1 3256
73ac8160 3257static void
518f0eb1 3258bgp_route_map_event (route_map_event_t event, const char *rmap_name)
73ac8160 3259{
518f0eb1
DS
3260 if (route_map_mark_updated(rmap_name, 0) == 0)
3261 bgp_route_map_mark_update(rmap_name);
3262
3263 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
3264}
3265
3266
fee0f4c6 3267DEFUN (match_peer,
3268 match_peer_cmd,
6147e2c6 3269 "match peer <A.B.C.D|X:X::X:X>",
fee0f4c6 3270 MATCH_STR
3271 "Match peer address\n"
6e13ed4a
IR
3272 "IP address of peer\n"
3273 "IPv6 address of peer\n")
fee0f4c6 3274{
c500ae40 3275 int idx_ip = 2;
cdc2d765 3276 return bgp_route_match_add (vty, "peer", argv[idx_ip]->arg,
518f0eb1 3277 RMAP_EVENT_MATCH_ADDED);
fee0f4c6 3278}
3279
3280DEFUN (match_peer_local,
f412b39a 3281 match_peer_local_cmd,
fee0f4c6 3282 "match peer local",
3283 MATCH_STR
3284 "Match peer address\n"
3285 "Static or Redistributed routes\n")
3286{
cdc2d765 3287 return bgp_route_match_add (vty, "peer", "local",
518f0eb1 3288 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3289}
3290
3291DEFUN (no_match_peer,
3292 no_match_peer_cmd,
4c9bd275 3293 "no match peer [<local|A.B.C.D|X:X::X:X>]",
fee0f4c6 3294 NO_STR
3295 MATCH_STR
4c9bd275
DW
3296 "Match peer address\n"
3297 "Static or Redistributed routes\n"
3298 "IP address of peer\n"
3299 "IPv6 address of peer\n")
fee0f4c6 3300{
4c9bd275
DW
3301 int idx_peer = 3;
3302
3303 if (argc <= idx_peer)
cdc2d765 3304 return bgp_route_match_delete (vty, "peer", NULL,
4c9bd275 3305 RMAP_EVENT_MATCH_DELETED);
cdc2d765 3306 return bgp_route_match_delete (vty, "peer", argv[idx_peer]->arg,
518f0eb1 3307 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3308}
3309
fee0f4c6 3310
4c9bd275 3311/* match probability */
1add115a
VT
3312DEFUN (match_probability,
3313 match_probability_cmd,
6147e2c6 3314 "match probability (0-100)",
1add115a
VT
3315 MATCH_STR
3316 "Match portion of routes defined by percentage value\n"
3317 "Percentage of routes\n")
3318{
c500ae40 3319 int idx_number = 2;
cdc2d765 3320 return bgp_route_match_add (vty, "probability", argv[idx_number]->arg,
518f0eb1 3321 RMAP_EVENT_MATCH_ADDED);
1add115a
VT
3322}
3323
4c9bd275 3324
1add115a
VT
3325DEFUN (no_match_probability,
3326 no_match_probability_cmd,
4c9bd275 3327 "no match probability [(1-99)]",
1add115a
VT
3328 NO_STR
3329 MATCH_STR
4c9bd275
DW
3330 "Match portion of routes defined by percentage value\n"
3331 "Percentage of routes\n")
1add115a 3332{
4c9bd275
DW
3333 int idx_number = 3;
3334 if (argc <= idx_number)
cdc2d765 3335 return bgp_route_match_delete (vty, "probability", NULL,
4c9bd275 3336 RMAP_EVENT_MATCH_DELETED);
cdc2d765 3337 return bgp_route_match_delete (vty, "probability", argv[idx_number]->arg,
518f0eb1 3338 RMAP_EVENT_MATCH_DELETED);
1add115a
VT
3339}
3340
1add115a 3341
f412b39a 3342DEFUN (match_ip_route_source,
c1643bb7 3343 match_ip_route_source_cmd,
6147e2c6 3344 "match ip route-source <(1-199)|(1300-2699)|WORD>",
c1643bb7 3345 MATCH_STR
3346 IP_STR
3347 "Match advertising source address of route\n"
3348 "IP access-list number\n"
3349 "IP access-list number (expanded range)\n"
3350 "IP standard access-list name\n")
3351{
c500ae40 3352 int idx_acl = 3;
cdc2d765 3353 return bgp_route_match_add (vty, "ip route-source", argv[idx_acl]->arg,
518f0eb1 3354 RMAP_EVENT_FILTER_ADDED);
c1643bb7 3355}
3356
4c9bd275 3357
c1643bb7 3358DEFUN (no_match_ip_route_source,
3359 no_match_ip_route_source_cmd,
6de69f83 3360 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
c1643bb7 3361 NO_STR
3362 MATCH_STR
3363 IP_STR
4c9bd275
DW
3364 "Match advertising source address of route\n"
3365 "IP access-list number\n"
3366 "IP access-list number (expanded range)\n"
3367 "IP standard access-list name\n")
c1643bb7 3368{
4c9bd275
DW
3369 int idx_number = 4;
3370 if (argc <= idx_number)
cdc2d765 3371 return bgp_route_match_delete (vty, "ip route-source",
4c9bd275 3372 NULL, RMAP_EVENT_FILTER_DELETED);
cdc2d765 3373 return bgp_route_match_delete (vty, "ip route-source",
4c9bd275 3374 argv[idx_number]->arg, RMAP_EVENT_FILTER_DELETED);
c1643bb7 3375}
3376
c1643bb7 3377
f412b39a 3378DEFUN (match_ip_route_source_prefix_list,
c1643bb7 3379 match_ip_route_source_prefix_list_cmd,
3380 "match ip route-source prefix-list WORD",
3381 MATCH_STR
3382 IP_STR
3383 "Match advertising source address of route\n"
3384 "Match entries of prefix-lists\n"
3385 "IP prefix-list name\n")
3386{
c500ae40 3387 int idx_word = 4;
cdc2d765 3388 return bgp_route_match_add (vty, "ip route-source prefix-list",
c500ae40 3389 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
c1643bb7 3390}
3391
4c9bd275 3392
c1643bb7 3393DEFUN (no_match_ip_route_source_prefix_list,
3394 no_match_ip_route_source_prefix_list_cmd,
4c9bd275 3395 "no match ip route-source prefix-list [WORD]",
c1643bb7 3396 NO_STR
3397 MATCH_STR
3398 IP_STR
3399 "Match advertising source address of route\n"
4c9bd275
DW
3400 "Match entries of prefix-lists\n"
3401 "IP prefix-list name\n")
c1643bb7 3402{
4c9bd275
DW
3403 int idx_word = 5;
3404 if (argc <= idx_word)
cdc2d765 3405 return bgp_route_match_delete (vty, "ip route-source prefix-list",
4c9bd275 3406 NULL, RMAP_EVENT_PLIST_DELETED);
cdc2d765 3407 return bgp_route_match_delete (vty, "ip route-source prefix-list",
4c9bd275 3408 argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
c1643bb7 3409}
3410
c1643bb7 3411
af291c15
DS
3412DEFUN (match_local_pref,
3413 match_local_pref_cmd,
6147e2c6 3414 "match local-preference (0-4294967295)",
af291c15
DS
3415 MATCH_STR
3416 "Match local-preference of route\n"
3417 "Metric value\n")
3418{
c500ae40 3419 int idx_number = 2;
cdc2d765 3420 return bgp_route_match_add (vty, "local-preference", argv[idx_number]->arg,
518f0eb1 3421 RMAP_EVENT_MATCH_ADDED);
af291c15
DS
3422}
3423
4c9bd275 3424
af291c15
DS
3425DEFUN (no_match_local_pref,
3426 no_match_local_pref_cmd,
4c9bd275 3427 "no match local-preference [(0-4294967295)]",
af291c15
DS
3428 NO_STR
3429 MATCH_STR
4c9bd275
DW
3430 "Match local preference of route\n"
3431 "Local preference value\n")
af291c15 3432{
4c9bd275
DW
3433 int idx_localpref = 3;
3434 if (argc <= idx_localpref)
cdc2d765 3435 return bgp_route_match_delete (vty, "local-preference",
4c9bd275 3436 NULL, RMAP_EVENT_MATCH_DELETED);
cdc2d765 3437 return bgp_route_match_delete (vty, "local-preference",
4c9bd275 3438 argv[idx_localpref]->arg,
518f0eb1 3439 RMAP_EVENT_MATCH_DELETED);
af291c15
DS
3440}
3441
af291c15 3442
f412b39a 3443DEFUN (match_community,
718e3744 3444 match_community_cmd,
0d702986 3445 "match community <(1-99)|(100-500)|WORD> [exact-match]",
718e3744 3446 MATCH_STR
3447 "Match BGP community list\n"
3448 "Community-list number (standard)\n"
3449 "Community-list number (expanded)\n"
3450 "Community-list name\n"
3451 "Do exact matching of communities\n")
3452{
c500ae40 3453 int idx_comm_list = 2;
718e3744 3454 int ret;
3455 char *argstr;
3456
0d702986
QY
3457 if (argc == 4)
3458 {
3459 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
3460 strlen (argv[idx_comm_list]->arg) +
3461 strlen ("exact-match") + 2);
718e3744 3462
0d702986
QY
3463 sprintf (argstr, "%s exact-match", argv[idx_comm_list]->arg);
3464 }
3465 else
3466 argstr = argv[idx_comm_list]->arg;
718e3744 3467
cdc2d765 3468 ret = bgp_route_match_add (vty, "community", argstr,
518f0eb1 3469 RMAP_EVENT_CLIST_ADDED);
718e3744 3470
0d702986
QY
3471 if (argstr != argv[idx_comm_list]->arg)
3472 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 3473
3474 return ret;
3475}
3476
3477DEFUN (no_match_community,
3478 no_match_community_cmd,
4c9bd275 3479 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
718e3744 3480 NO_STR
3481 MATCH_STR
4c9bd275
DW
3482 "Match BGP community list\n"
3483 "Community-list number (standard)\n"
3484 "Community-list number (expanded)\n"
3485 "Community-list name\n"
3486 "Do exact matching of communities\n")
718e3744 3487{
cdc2d765 3488 return bgp_route_match_delete (vty, "community", NULL,
518f0eb1 3489 RMAP_EVENT_CLIST_DELETED);
718e3744 3490}
3491
57d187bc
JS
3492DEFUN (match_lcommunity,
3493 match_lcommunity_cmd,
0d702986 3494 "match large-community <(1-99)|(100-500)|WORD>",
57d187bc
JS
3495 MATCH_STR
3496 "Match BGP large community list\n"
3497 "Large Community-list number (standard)\n"
3498 "Large Community-list number (expanded)\n"
3499 "Large Community-list name\n")
3500{
3501 return bgp_route_match_add (vty, "large-community", argv[2]->arg,
2acb4ac2 3502 RMAP_EVENT_LLIST_ADDED);
57d187bc 3503}
718e3744 3504
57d187bc
JS
3505DEFUN (no_match_lcommunity,
3506 no_match_lcommunity_cmd,
52951b63 3507 "no match large-community [<(1-99)|(100-500)|WORD>]",
57d187bc
JS
3508 NO_STR
3509 MATCH_STR
3510 "Match BGP large community list\n"
3511 "Large Community-list number (standard)\n"
3512 "Large Community-list number (expanded)\n"
3513 "Large Community-list name\n")
3514{
3515 return bgp_route_match_delete (vty, "large-community", NULL,
2acb4ac2 3516 RMAP_EVENT_LLIST_DELETED);
57d187bc 3517}
718e3744 3518
f412b39a 3519DEFUN (match_ecommunity,
73ffb25b 3520 match_ecommunity_cmd,
6147e2c6 3521 "match extcommunity <(1-99)|(100-500)|WORD>",
73ffb25b 3522 MATCH_STR
3523 "Match BGP/VPN extended community list\n"
3524 "Extended community-list number (standard)\n"
3525 "Extended community-list number (expanded)\n"
3526 "Extended community-list name\n")
3527{
c500ae40 3528 int idx_comm_list = 2;
cdc2d765 3529 return bgp_route_match_add (vty, "extcommunity", argv[idx_comm_list]->arg,
518f0eb1 3530 RMAP_EVENT_ECLIST_ADDED);
73ffb25b 3531}
3532
4c9bd275 3533
73ffb25b 3534DEFUN (no_match_ecommunity,
3535 no_match_ecommunity_cmd,
4c9bd275 3536 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
73ffb25b 3537 NO_STR
3538 MATCH_STR
4c9bd275
DW
3539 "Match BGP/VPN extended community list\n"
3540 "Extended community-list number (standard)\n"
3541 "Extended community-list number (expanded)\n"
3542 "Extended community-list name\n")
73ffb25b 3543{
cdc2d765 3544 return bgp_route_match_delete (vty, "extcommunity", NULL,
518f0eb1 3545 RMAP_EVENT_ECLIST_DELETED);
73ffb25b 3546}
3547
73ffb25b 3548
718e3744 3549DEFUN (match_aspath,
3550 match_aspath_cmd,
3551 "match as-path WORD",
3552 MATCH_STR
3553 "Match BGP AS path list\n"
3554 "AS path access-list name\n")
3555{
c500ae40 3556 int idx_word = 2;
cdc2d765 3557 return bgp_route_match_add (vty, "as-path", argv[idx_word]->arg,
518f0eb1 3558 RMAP_EVENT_ASLIST_ADDED);
718e3744 3559}
3560
4c9bd275 3561
718e3744 3562DEFUN (no_match_aspath,
3563 no_match_aspath_cmd,
4c9bd275 3564 "no match as-path [WORD]",
718e3744 3565 NO_STR
3566 MATCH_STR
4c9bd275
DW
3567 "Match BGP AS path list\n"
3568 "AS path access-list name\n")
718e3744 3569{
cdc2d765 3570 return bgp_route_match_delete (vty, "as-path", NULL,
518f0eb1 3571 RMAP_EVENT_ASLIST_DELETED);
718e3744 3572}
3573
718e3744 3574
3575DEFUN (match_origin,
3576 match_origin_cmd,
6147e2c6 3577 "match origin <egp|igp|incomplete>",
718e3744 3578 MATCH_STR
3579 "BGP origin code\n"
3580 "remote EGP\n"
3581 "local IGP\n"
3582 "unknown heritage\n")
3583{
c500ae40
DW
3584 int idx_origin = 2;
3585 if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
cdc2d765 3586 return bgp_route_match_add (vty, "origin", "igp",
518f0eb1 3587 RMAP_EVENT_MATCH_ADDED);
c500ae40 3588 if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
cdc2d765 3589 return bgp_route_match_add (vty, "origin", "egp",
518f0eb1 3590 RMAP_EVENT_MATCH_ADDED);
c500ae40 3591 if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
cdc2d765 3592 return bgp_route_match_add (vty, "origin", "incomplete",
518f0eb1 3593 RMAP_EVENT_MATCH_ADDED);
718e3744 3594
3595 return CMD_WARNING;
3596}
3597
4c9bd275 3598
718e3744 3599DEFUN (no_match_origin,
3600 no_match_origin_cmd,
4c9bd275 3601 "no match origin [<egp|igp|incomplete>]",
718e3744 3602 NO_STR
3603 MATCH_STR
4c9bd275
DW
3604 "BGP origin code\n"
3605 "remote EGP\n"
3606 "local IGP\n"
3607 "unknown heritage\n")
718e3744 3608{
cdc2d765 3609 return bgp_route_match_delete (vty, "origin", NULL,
518f0eb1 3610 RMAP_EVENT_MATCH_DELETED);
718e3744 3611}
3612
af5cd0a5 3613DEFUN (set_ip_nexthop_peer,
3614 set_ip_nexthop_peer_cmd,
3615 "set ip next-hop peer-address",
3616 SET_STR
3617 IP_STR
3618 "Next hop address\n"
3619 "Use peer address (for BGP only)\n")
3620{
cdc2d765
DL
3621 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3622 "ip next-hop", "peer-address");
af5cd0a5 3623}
3624
316e074d
DS
3625DEFUN (set_ip_nexthop_unchanged,
3626 set_ip_nexthop_unchanged_cmd,
3627 "set ip next-hop unchanged",
3628 SET_STR
3629 IP_STR
3630 "Next hop address\n"
3631 "Don't modify existing Next hop address\n")
3632{
cdc2d765
DL
3633 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3634 "ip next-hop", "unchanged");
718e3744 3635}
3636
718e3744 3637
3638DEFUN (set_local_pref,
3639 set_local_pref_cmd,
6147e2c6 3640 "set local-preference (0-4294967295)",
718e3744 3641 SET_STR
3642 "BGP local preference path attribute\n"
3643 "Preference value\n")
3644{
c500ae40 3645 int idx_number = 2;
cdc2d765
DL
3646 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3647 "local-preference", argv[idx_number]->arg);
718e3744 3648}
3649
4c9bd275 3650
718e3744 3651DEFUN (no_set_local_pref,
3652 no_set_local_pref_cmd,
4c9bd275 3653 "no set local-preference [(0-4294967295)]",
718e3744 3654 NO_STR
3655 SET_STR
4c9bd275
DW
3656 "BGP local preference path attribute\n"
3657 "Preference value\n")
718e3744 3658{
4c9bd275
DW
3659 int idx_localpref = 3;
3660 if (argc <= idx_localpref)
cdc2d765
DL
3661 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3662 "local-preference", NULL);
3663 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3664 "local-preference", argv[idx_localpref]->arg);
718e3744 3665}
3666
718e3744 3667
3668DEFUN (set_weight,
3669 set_weight_cmd,
6147e2c6 3670 "set weight (0-4294967295)",
718e3744 3671 SET_STR
3672 "BGP weight for routing table\n"
3673 "Weight value\n")
3674{
c500ae40 3675 int idx_number = 2;
cdc2d765
DL
3676 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "weight",
3677 argv[idx_number]->arg);
718e3744 3678}
3679
4c9bd275 3680
718e3744 3681DEFUN (no_set_weight,
3682 no_set_weight_cmd,
4c9bd275 3683 "no set weight [(0-4294967295)]",
718e3744 3684 NO_STR
3685 SET_STR
4c9bd275
DW
3686 "BGP weight for routing table\n"
3687 "Weight value\n")
718e3744 3688{
4c9bd275
DW
3689 int idx_weight = 3;
3690 if (argc <= idx_weight)
cdc2d765
DL
3691 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3692 "weight", NULL);
3693 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "weight",
3694 argv[idx_weight]->arg);
718e3744 3695}
3696
d990e384
DS
3697DEFUN (set_label_index,
3698 set_label_index_cmd,
8b81993e 3699 "set label-index (0-1048560)",
d990e384
DS
3700 SET_STR
3701 "Label index to associate with the prefix\n"
3702 "Label index value\n")
3703{
3704 int idx_number = 2;
3705 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "label-index",
3706 argv[idx_number]->arg);
3707}
3708
3709DEFUN (no_set_label_index,
3710 no_set_label_index_cmd,
8b81993e 3711 "no set label-index [(0-1048560)]",
d990e384
DS
3712 NO_STR
3713 SET_STR
3714 "Label index to associate with the prefix\n"
3715 "Label index value\n")
3716{
3717 int idx_label_index = 3;
3718 if (argc <= idx_label_index)
3719 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3720 "label-index", NULL);
3721 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "label-index",
3722 argv[idx_label_index]->arg);
3723}
718e3744 3724
12dcf78e
QY
3725DEFUN (set_aspath_prepend_asn,
3726 set_aspath_prepend_asn_cmd,
3727 "set as-path prepend (1-4294967295)...",
718e3744 3728 SET_STR
841f7a57 3729 "Transform BGP AS_PATH attribute\n"
718e3744 3730 "Prepend to the as-path\n"
12dcf78e 3731 "AS number\n")
718e3744 3732{
58749582 3733 int idx_asn = 3;
718e3744 3734 int ret;
3735 char *str;
3736
58749582 3737 str = argv_concat (argv, argc, idx_asn);
cdc2d765
DL
3738 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3739 "as-path prepend", str);
718e3744 3740 XFREE (MTYPE_TMP, str);
3741
3742 return ret;
3743}
3744
12dcf78e
QY
3745DEFUN (set_aspath_prepend_lastas,
3746 set_aspath_prepend_lastas_cmd,
b6ab2929 3747 "set as-path prepend last-as (1-10)",
12dcf78e
QY
3748 SET_STR
3749 "Transform BGP AS_PATH attribute\n"
3750 "Prepend to the as-path\n"
3751 "Use the peer's AS-number\n"
b6ab2929 3752 "Number of times to insert\n")
12dcf78e
QY
3753{
3754 return set_aspath_prepend_asn (self, vty, argc, argv);
3755}
bc3dd427 3756
718e3744 3757DEFUN (no_set_aspath_prepend,
3758 no_set_aspath_prepend_cmd,
a4b2b610 3759 "no set as-path prepend [(1-4294967295)]",
718e3744 3760 NO_STR
3761 SET_STR
841f7a57 3762 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
3763 "Prepend to the as-path\n"
3764 "AS number\n")
718e3744 3765{
58749582 3766 int idx_asn = 4;
a7f93f3e
DO
3767 int ret;
3768 char *str;
3769
58749582 3770 str = argv_concat (argv, argc, idx_asn);
cdc2d765
DL
3771 ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3772 "as-path prepend", str);
a7f93f3e
DO
3773 XFREE (MTYPE_TMP, str);
3774 return ret;
718e3744 3775}
3776
718e3744 3777
841f7a57
DO
3778DEFUN (set_aspath_exclude,
3779 set_aspath_exclude_cmd,
a4b2b610 3780 "set as-path exclude (1-4294967295)...",
841f7a57
DO
3781 SET_STR
3782 "Transform BGP AS-path attribute\n"
3783 "Exclude from the as-path\n"
3784 "AS number\n")
3785{
58749582 3786 int idx_asn = 3;
841f7a57
DO
3787 int ret;
3788 char *str;
3789
58749582 3790 str = argv_concat (argv, argc, idx_asn);
cdc2d765
DL
3791 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3792 "as-path exclude", str);
841f7a57
DO
3793 XFREE (MTYPE_TMP, str);
3794 return ret;
3795}
3796
3797DEFUN (no_set_aspath_exclude,
3798 no_set_aspath_exclude_cmd,
a4b2b610 3799 "no set as-path exclude (1-4294967295)...",
841f7a57
DO
3800 NO_STR
3801 SET_STR
3802 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
3803 "Exclude from the as-path\n"
3804 "AS number\n")
841f7a57 3805{
58749582 3806 int idx_asn = 4;
841f7a57
DO
3807 int ret;
3808 char *str;
3809
58749582 3810 str = argv_concat (argv, argc, idx_asn);
cdc2d765
DL
3811 ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3812 "as-path exclude", str);
841f7a57
DO
3813 XFREE (MTYPE_TMP, str);
3814 return ret;
3815}
3816
841f7a57 3817
718e3744 3818DEFUN (set_community,
3819 set_community_cmd,
e961923c 3820 "set community AA:NN...",
718e3744 3821 SET_STR
3822 "BGP community attribute\n"
859d388e 3823 COMMUNITY_VAL_STR)
718e3744 3824{
58749582 3825 int idx_aa_nn = 2;
718e3744 3826 int i;
3827 int first = 0;
3828 int additive = 0;
3829 struct buffer *b;
3830 struct community *com = NULL;
3831 char *str;
3832 char *argstr;
3833 int ret;
3834
3835 b = buffer_new (1024);
3836
58749582 3837 for (i = idx_aa_nn; i < argc; i++)
718e3744 3838 {
4dcadbef 3839 if (strncmp (argv[i]->arg, "additive", strlen (argv[i]->arg)) == 0)
718e3744 3840 {
3841 additive = 1;
3842 continue;
3843 }
3844
3845 if (first)
3846 buffer_putc (b, ' ');
3847 else
3848 first = 1;
3849
4dcadbef 3850 if (strncmp (argv[i]->arg, "internet", strlen (argv[i]->arg)) == 0)
718e3744 3851 {
3852 buffer_putstr (b, "internet");
3853 continue;
3854 }
4dcadbef 3855 if (strncmp (argv[i]->arg, "local-AS", strlen (argv[i]->arg)) == 0)
718e3744 3856 {
3857 buffer_putstr (b, "local-AS");
3858 continue;
3859 }
4dcadbef
DW
3860 if (strncmp (argv[i]->arg, "no-a", strlen ("no-a")) == 0
3861 && strncmp (argv[i]->arg, "no-advertise", strlen (argv[i]->arg)) == 0)
718e3744 3862 {
3863 buffer_putstr (b, "no-advertise");
3864 continue;
3865 }
4dcadbef
DW
3866 if (strncmp (argv[i]->arg, "no-e", strlen ("no-e"))== 0
3867 && strncmp (argv[i]->arg, "no-export", strlen (argv[i]->arg)) == 0)
718e3744 3868 {
3869 buffer_putstr (b, "no-export");
3870 continue;
3871 }
4dcadbef 3872 buffer_putstr (b, argv[i]->arg);
718e3744 3873 }
3874 buffer_putc (b, '\0');
3875
3876 /* Fetch result string then compile it to communities attribute. */
3877 str = buffer_getstr (b);
3878 buffer_free (b);
3879
3880 if (str)
3881 {
3882 com = community_str2com (str);
3b8b1855 3883 XFREE (MTYPE_TMP, str);
718e3744 3884 }
3885
3886 /* Can't compile user input into communities attribute. */
3887 if (! com)
3888 {
96ade3ed 3889 vty_outln (vty, "%% Malformed communities attribute");
718e3744 3890 return CMD_WARNING;
3891 }
3892
3893 /* Set communites attribute string. */
3894 str = community_str (com);
3895
3896 if (additive)
3897 {
3898 argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
3899 strcpy (argstr, str);
3900 strcpy (argstr + strlen (str), " additive");
cdc2d765
DL
3901 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3902 "community", argstr);
718e3744 3903 XFREE (MTYPE_TMP, argstr);
3904 }
3905 else
cdc2d765
DL
3906 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3907 "community", str);
718e3744 3908
3909 community_free (com);
3910
3911 return ret;
3912}
3913
3914DEFUN (set_community_none,
3915 set_community_none_cmd,
3916 "set community none",
3917 SET_STR
3918 "BGP community attribute\n"
3919 "No community attribute\n")
3920{
cdc2d765
DL
3921 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "community",
3922 "none");
718e3744 3923}
3924
3925DEFUN (no_set_community,
3926 no_set_community_cmd,
a4b2b610 3927 "no set community AA:NN...",
718e3744 3928 NO_STR
3929 SET_STR
d7fa34c1
QY
3930 "BGP community attribute\n"
3931 COMMUNITY_VAL_STR)
718e3744 3932{
cdc2d765
DL
3933 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3934 "community", NULL);
718e3744 3935}
3936
718e3744 3937
718e3744 3938
3939DEFUN (set_community_delete,
3940 set_community_delete_cmd,
6147e2c6 3941 "set comm-list <(1-99)|(100-500)|WORD> delete",
718e3744 3942 SET_STR
3943 "set BGP community list (for deletion)\n"
3944 "Community-list number (standard)\n"
5e3edbf5 3945 "Community-list number (expanded)\n"
718e3744 3946 "Community-list name\n"
3947 "Delete matching communities\n")
3948{
c500ae40 3949 int idx_comm_list = 2;
718e3744 3950 char *str;
3951
c500ae40
DW
3952 str = XCALLOC (MTYPE_TMP, strlen (argv[idx_comm_list]->arg) + strlen (" delete") + 1);
3953 strcpy (str, argv[idx_comm_list]->arg);
3954 strcpy (str + strlen (argv[idx_comm_list]->arg), " delete");
718e3744 3955
cdc2d765 3956 generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "comm-list", str);
718e3744 3957
3958 XFREE (MTYPE_TMP, str);
3959 return CMD_SUCCESS;
3960}
3961
3962DEFUN (no_set_community_delete,
3963 no_set_community_delete_cmd,
a4b2b610 3964 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
718e3744 3965 NO_STR
3966 SET_STR
d7fa34c1
QY
3967 "set BGP community list (for deletion)\n"
3968 "Community-list number (standard)\n"
3969 "Community-list number (expanded)\n"
3970 "Community-list name\n"
3971 "Delete matching communities\n")
718e3744 3972{
cdc2d765
DL
3973 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3974 "comm-list", NULL);
718e3744 3975}
3976
57d187bc
JS
3977DEFUN (set_lcommunity,
3978 set_lcommunity_cmd,
3979 "set large-community AA:BB:CC...",
3980 SET_STR
3981 "BGP large community attribute\n"
3982 "Large Community number in aa:bb:cc format or additive\n")
3983{
3984 int ret;
3985 char *str;
3986
3987 str = argv_concat (argv, argc, 2);
3988 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "large-community", str);
3989 XFREE (MTYPE_TMP, str);
3990
3991 return ret;
3992}
3993
3994DEFUN (set_lcommunity_none,
3995 set_lcommunity_none_cmd,
3996 "set large-community none",
3997 SET_STR
3998 "BGP large community attribute\n"
3999 "No large community attribute\n")
4000{
4001 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
2acb4ac2 4002 "large-community", "none");
57d187bc
JS
4003}
4004
4005DEFUN (no_set_lcommunity,
4006 no_set_lcommunity_cmd,
52951b63 4007 "no set large-community none",
57d187bc
JS
4008 NO_STR
4009 SET_STR
4010 "BGP large community attribute\n"
52951b63 4011 "No community attribute\n")
57d187bc
JS
4012{
4013 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
2acb4ac2 4014 "large-community", NULL);
57d187bc
JS
4015}
4016
52951b63
DS
4017DEFUN (no_set_lcommunity1,
4018 no_set_lcommunity1_cmd,
4019 "no set large-community AA:BB:CC...",
4020 NO_STR
4021 SET_STR
4022 "BGP large community attribute\n"
4023 "Large community in AA:BB:CC... format or additive\n")
4024{
4025 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
2acb4ac2 4026 "large-community", NULL);
52951b63 4027}
57d187bc
JS
4028
4029DEFUN (set_lcommunity_delete,
4030 set_lcommunity_delete_cmd,
4031 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
4032 SET_STR
4033 "set BGP large community list (for deletion)\n"
4034 "Large Community-list number (standard)\n"
4035 "Large Communitly-list number (expanded)\n"
4036 "Large Community-list name\n"
4037 "Delete matching large communities\n")
4038{
4039 char *str;
4040
4041 str = XCALLOC (MTYPE_TMP, strlen (argv[2]->arg) + strlen (" delete") + 1);
4042 strcpy (str, argv[2]->arg);
4043 strcpy (str + strlen (argv[2]->arg), " delete");
4044
4045 generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
2acb4ac2 4046 "large-comm-list", str);
57d187bc
JS
4047
4048 XFREE (MTYPE_TMP, str);
4049 return CMD_SUCCESS;
4050}
4051
4052DEFUN (no_set_lcommunity_delete,
4053 no_set_lcommunity_delete_cmd,
db4f7086 4054 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
57d187bc
JS
4055 NO_STR
4056 SET_STR
4057 "set BGP large community list (for deletion)\n"
4058 "Large Community-list number (standard)\n"
4059 "Large Communitly-list number (expanded)\n"
4060 "Large Community-list name\n"
4061 "Delete matching large communities\n")
4062{
4063 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
2acb4ac2 4064 "large-comm-list", NULL);
57d187bc 4065}
718e3744 4066
4067DEFUN (set_ecommunity_rt,
4068 set_ecommunity_rt_cmd,
a4b2b610 4069 "set extcommunity rt ASN:nn_or_IP-address:nn...",
718e3744 4070 SET_STR
4071 "BGP extended community attribute\n"
e6b6a564 4072 "Route Target extended community\n"
718e3744 4073 "VPN extended community\n")
4074{
58749582 4075 int idx_asn_nn = 3;
718e3744 4076 int ret;
4077 char *str;
4078
58749582 4079 str = argv_concat (argv, argc, idx_asn_nn);
cdc2d765
DL
4080 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4081 "extcommunity rt", str);
718e3744 4082 XFREE (MTYPE_TMP, str);
4083
4084 return ret;
4085}
4086
4087DEFUN (no_set_ecommunity_rt,
4088 no_set_ecommunity_rt_cmd,
a4b2b610 4089 "no set extcommunity rt ASN:nn_or_IP-address:nn...",
718e3744 4090 NO_STR
4091 SET_STR
4092 "BGP extended community attribute\n"
3a2d747c
QY
4093 "Route Target extended community\n"
4094 "VPN extended community\n")
718e3744 4095{
cdc2d765
DL
4096 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4097 "extcommunity rt", NULL);
718e3744 4098}
4099
718e3744 4100
4101DEFUN (set_ecommunity_soo,
4102 set_ecommunity_soo_cmd,
a4b2b610 4103 "set extcommunity soo ASN:nn_or_IP-address:nn...",
718e3744 4104 SET_STR
4105 "BGP extended community attribute\n"
4106 "Site-of-Origin extended community\n"
4107 "VPN extended community\n")
4108{
58749582 4109 int idx_asn_nn = 3;
718e3744 4110 int ret;
4111 char *str;
4112
58749582 4113 str = argv_concat (argv, argc, idx_asn_nn);
cdc2d765
DL
4114 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4115 "extcommunity soo", str);
718e3744 4116 XFREE (MTYPE_TMP, str);
4117 return ret;
4118}
4119
a4b2b610 4120
718e3744 4121DEFUN (no_set_ecommunity_soo,
4122 no_set_ecommunity_soo_cmd,
a4b2b610 4123 "no set extcommunity soo ASN:nn_or_IP-address:nn...",
718e3744 4124 NO_STR
4125 SET_STR
4126 "BGP extended community attribute\n"
3a2d747c
QY
4127 "Site-of-Origin extended community\n"
4128 "VPN extended community\n")
718e3744 4129{
cdc2d765
DL
4130 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4131 "extcommunity soo", NULL);
718e3744 4132}
4133
718e3744 4134
4135DEFUN (set_origin,
4136 set_origin_cmd,
6147e2c6 4137 "set origin <egp|igp|incomplete>",
718e3744 4138 SET_STR
4139 "BGP origin code\n"
4140 "remote EGP\n"
4141 "local IGP\n"
4142 "unknown heritage\n")
4143{
c500ae40
DW
4144 int idx_origin = 2;
4145 if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
cdc2d765
DL
4146 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
4147 "igp");
c500ae40 4148 if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
cdc2d765
DL
4149 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
4150 "egp");
c500ae40 4151 if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
cdc2d765
DL
4152 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
4153 "incomplete");
718e3744 4154
4155 return CMD_WARNING;
4156}
4157
a4b2b610 4158
718e3744 4159DEFUN (no_set_origin,
4160 no_set_origin_cmd,
a4b2b610 4161 "no set origin [<egp|igp|incomplete>]",
718e3744 4162 NO_STR
4163 SET_STR
d7fa34c1
QY
4164 "BGP origin code\n"
4165 "remote EGP\n"
4166 "local IGP\n"
4167 "unknown heritage\n")
718e3744 4168{
cdc2d765
DL
4169 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "origin",
4170 NULL);
718e3744 4171}
4172
718e3744 4173
4174DEFUN (set_atomic_aggregate,
4175 set_atomic_aggregate_cmd,
4176 "set atomic-aggregate",
4177 SET_STR
4178 "BGP atomic aggregate attribute\n" )
4179{
cdc2d765
DL
4180 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4181 "atomic-aggregate", NULL);
718e3744 4182}
4183
4184DEFUN (no_set_atomic_aggregate,
4185 no_set_atomic_aggregate_cmd,
4186 "no set atomic-aggregate",
4187 NO_STR
4188 SET_STR
4189 "BGP atomic aggregate attribute\n" )
4190{
cdc2d765
DL
4191 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4192 "atomic-aggregate", NULL);
718e3744 4193}
4194
4195DEFUN (set_aggregator_as,
4196 set_aggregator_as_cmd,
9ccf14f7 4197 "set aggregator as (1-4294967295) A.B.C.D",
718e3744 4198 SET_STR
4199 "BGP aggregator attribute\n"
4200 "AS number of aggregator\n"
4201 "AS number\n"
4202 "IP address of aggregator\n")
4203{
c500ae40
DW
4204 int idx_number = 3;
4205 int idx_ipv4 = 4;
718e3744 4206 int ret;
718e3744 4207 struct in_addr address;
718e3744 4208 char *argstr;
e52702f2 4209
c500ae40 4210 ret = inet_aton (argv[idx_ipv4]->arg, &address);
718e3744 4211 if (ret == 0)
4212 {
96ade3ed 4213 vty_outln (vty, "Aggregator IP address is invalid");
718e3744 4214 return CMD_WARNING;
4215 }
4216
4217 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
c500ae40 4218 strlen (argv[idx_number]->arg) + strlen (argv[idx_ipv4]->arg) + 2);
718e3744 4219
c500ae40 4220 sprintf (argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
718e3744 4221
cdc2d765
DL
4222 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4223 "aggregator as", argstr);
718e3744 4224
4225 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4226
4227 return ret;
4228}
4229
a4b2b610 4230
718e3744 4231DEFUN (no_set_aggregator_as,
4232 no_set_aggregator_as_cmd,
a4b2b610 4233 "no set aggregator as [(1-4294967295) A.B.C.D]",
718e3744 4234 NO_STR
4235 SET_STR
4236 "BGP aggregator attribute\n"
a4b2b610
DW
4237 "AS number of aggregator\n"
4238 "AS number\n"
4239 "IP address of aggregator\n")
718e3744 4240{
a4b2b610
DW
4241 int idx_asn = 4;
4242 int idx_ip = 5;
718e3744 4243 int ret;
718e3744 4244 struct in_addr address;
718e3744 4245 char *argstr;
4246
a4b2b610 4247 if (argc <= idx_asn)
cdc2d765
DL
4248 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4249 "aggregator as", NULL);
e52702f2 4250
a4b2b610 4251 ret = inet_aton (argv[idx_ip]->arg, &address);
718e3744 4252 if (ret == 0)
4253 {
96ade3ed 4254 vty_outln (vty, "Aggregator IP address is invalid");
718e3744 4255 return CMD_WARNING;
4256 }
4257
4258 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
a4b2b610 4259 strlen (argv[idx_asn]->arg) + strlen (argv[idx_ip]->arg) + 2);
718e3744 4260
a4b2b610 4261 sprintf (argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
718e3744 4262
cdc2d765
DL
4263 ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4264 "aggregator as", argstr);
718e3744 4265
4266 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4267
4268 return ret;
4269}
4270
f412b39a 4271DEFUN (match_ipv6_next_hop,
718e3744 4272 match_ipv6_next_hop_cmd,
4273 "match ipv6 next-hop X:X::X:X",
4274 MATCH_STR
4275 IPV6_STR
4276 "Match IPv6 next-hop address of route\n"
4277 "IPv6 address of next hop\n")
4278{
c500ae40 4279 int idx_ipv6 = 3;
cdc2d765 4280 return bgp_route_match_add (vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
518f0eb1 4281 RMAP_EVENT_MATCH_ADDED);
718e3744 4282}
4283
4284DEFUN (no_match_ipv6_next_hop,
4285 no_match_ipv6_next_hop_cmd,
4286 "no match ipv6 next-hop X:X::X:X",
4287 NO_STR
4288 MATCH_STR
4289 IPV6_STR
4290 "Match IPv6 next-hop address of route\n"
4291 "IPv6 address of next hop\n")
4292{
c500ae40 4293 int idx_ipv6 = 4;
cdc2d765 4294 return bgp_route_match_delete (vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
518f0eb1 4295 RMAP_EVENT_MATCH_DELETED);
718e3744 4296}
4297
718e3744 4298
90916ac2
DS
4299DEFUN (set_ipv6_nexthop_peer,
4300 set_ipv6_nexthop_peer_cmd,
4301 "set ipv6 next-hop peer-address",
4302 SET_STR
4303 IPV6_STR
4304 "Next hop address\n"
4305 "Use peer address (for BGP only)\n")
4306{
cdc2d765
DL
4307 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4308 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4309}
4310
4311DEFUN (no_set_ipv6_nexthop_peer,
4312 no_set_ipv6_nexthop_peer_cmd,
4313 "no set ipv6 next-hop peer-address",
4314 NO_STR
4315 SET_STR
4316 IPV6_STR
4317 "IPv6 next-hop address\n"
161995ea 4318 "Use peer address (for BGP only)\n")
90916ac2 4319{
cdc2d765
DL
4320 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4321 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4322}
4323
161995ea
DS
4324DEFUN (set_ipv6_nexthop_prefer_global,
4325 set_ipv6_nexthop_prefer_global_cmd,
4326 "set ipv6 next-hop prefer-global",
4327 SET_STR
4328 IPV6_STR
4329 "IPv6 next-hop address\n"
4330 "Prefer global over link-local if both exist\n")
4331{
cdc2d765
DL
4332 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4333 "ipv6 next-hop prefer-global", NULL);;
161995ea
DS
4334}
4335
4336DEFUN (no_set_ipv6_nexthop_prefer_global,
4337 no_set_ipv6_nexthop_prefer_global_cmd,
4338 "no set ipv6 next-hop prefer-global",
4339 NO_STR
4340 SET_STR
4341 IPV6_STR
4342 "IPv6 next-hop address\n"
4343 "Prefer global over link-local if both exist\n")
4344{
cdc2d765
DL
4345 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4346 "ipv6 next-hop prefer-global", NULL);
161995ea
DS
4347}
4348
718e3744 4349DEFUN (set_ipv6_nexthop_global,
4350 set_ipv6_nexthop_global_cmd,
4351 "set ipv6 next-hop global X:X::X:X",
4352 SET_STR
4353 IPV6_STR
4354 "IPv6 next-hop address\n"
4355 "IPv6 global address\n"
4356 "IPv6 address of next hop\n")
4357{
c500ae40 4358 int idx_ipv6 = 4;
bf8b3d27
DS
4359 struct in6_addr addr;
4360 int ret;
4361
c500ae40 4362 ret = inet_pton (AF_INET6, argv[idx_ipv6]->arg, &addr);
bf8b3d27
DS
4363 if (!ret)
4364 {
96ade3ed 4365 vty_outln (vty, "%% Malformed nexthop address");
bf8b3d27
DS
4366 return CMD_WARNING;
4367 }
4368 if (IN6_IS_ADDR_UNSPECIFIED(&addr) ||
4369 IN6_IS_ADDR_LOOPBACK(&addr) ||
4370 IN6_IS_ADDR_MULTICAST(&addr) ||
4371 IN6_IS_ADDR_LINKLOCAL(&addr))
4372 {
96ade3ed 4373 vty_outln (vty, "%% Invalid global nexthop address");
bf8b3d27
DS
4374 return CMD_WARNING;
4375 }
4376
cdc2d765
DL
4377 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4378 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 4379}
4380
a4b2b610 4381
718e3744 4382DEFUN (no_set_ipv6_nexthop_global,
4383 no_set_ipv6_nexthop_global_cmd,
a4b2b610 4384 "no set ipv6 next-hop global X:X::X:X",
718e3744 4385 NO_STR
4386 SET_STR
4387 IPV6_STR
4388 "IPv6 next-hop address\n"
a4b2b610
DW
4389 "IPv6 global address\n"
4390 "IPv6 address of next hop\n")
718e3744 4391{
a4b2b610
DW
4392 int idx_ipv6 = 5;
4393 if (argc <= idx_ipv6)
cdc2d765
DL
4394 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4395 "ipv6 next-hop global", NULL);
4396 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4397 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 4398}
718e3744 4399
d6902373
PG
4400#ifdef KEEP_OLD_VPN_COMMANDS
4401DEFUN (set_vpn_nexthop,
4402 set_vpn_nexthop_cmd,
313605cb 4403 "set <vpnv4|vpnv6> next-hop <A.B.C.D|X:X::X:X>",
718e3744 4404 SET_STR
4405 "VPNv4 information\n"
d6902373
PG
4406 "VPNv6 information\n"
4407 "VPN next-hop address\n"
4408 "IP address of next hop\n"
4409 "IPv6 address of next hop\n")
718e3744 4410{
d6902373
PG
4411 int idx_ip = 3;
4412 afi_t afi;
4413 int idx = 0;
718e3744 4414
d6902373
PG
4415 if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
4416 {
4417 if (afi == AFI_IP)
4418 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4419 "ip vpn next-hop", argv[idx_ip]->arg);
4420 else
4421 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4422 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4423 }
4424 return CMD_SUCCESS;
4425}
a4b2b610 4426
d6902373
PG
4427DEFUN (no_set_vpn_nexthop,
4428 no_set_vpn_nexthop_cmd,
313605cb 4429 "no set vpn next-hop <A.B.C.D|X:X::X:X>",
718e3744 4430 NO_STR
4431 SET_STR
d6902373
PG
4432 "VPN information\n"
4433 "VPN next-hop address\n"
4434 "IP address of next hop\n"
4435 "IPv6 address of next hop\n")
718e3744 4436{
d6902373
PG
4437 int idx_ip = 4;
4438 char *arg;
4439 afi_t afi;
4440 int idx = 0;
4441
4442 if (argc <= idx_ip)
4443 arg = NULL;
4444 else
4445 arg = argv[idx_ip]->arg;
4446 if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
4447 {
4448 if (afi == AFI_IP)
4449 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4450 "ip vpn next-hop", arg);
4451 else
4452 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4453 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4454 }
4455 return CMD_SUCCESS;
4456}
4457#endif /* KEEP_OLD_VPN_COMMANDS */
4458
4459DEFUN (set_ipx_vpn_nexthop,
4460 set_ipx_vpn_nexthop_cmd,
0d702986 4461 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
d6902373
PG
4462 SET_STR
4463 "IPv4 information\n"
4464 "IPv6 information\n"
4465 "VPN information\n"
4466 "VPN next-hop address\n"
4467 "IP address of next hop\n"
4468 "IPv6 address of next hop\n")
4469{
4470 int idx_ip = 4;
4471 afi_t afi;
4472 int idx = 0;
4473
4474 if (argv_find_and_parse_afi (argv, argc, &idx, &afi))
4475 {
4476 if (afi == AFI_IP)
4477 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4478 "ip vpn next-hop", argv[idx_ip]->arg);
4479 else
4480 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4481 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4482 }
4483 return CMD_SUCCESS;
718e3744 4484}
4485
d6902373
PG
4486DEFUN (no_set_ipx_vpn_nexthop,
4487 no_set_ipx_vpn_nexthop_cmd,
9fa4d336 4488 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
d6902373
PG
4489 NO_STR
4490 SET_STR
4491 "IPv4 information\n"
4492 "IPv6 information\n"
4493 "VPN information\n"
4494 "VPN next-hop address\n"
4495 "IP address of next hop\n"
4496 "IPv6 address of next hop\n")
4497{
4498 int idx_ip = 5;
4499 char *arg;
4500 afi_t afi;
4501 int idx = 0;
4502
4503 if (argc <= idx_ip)
4504 arg = NULL;
4505 else
4506 arg = argv[idx_ip]->arg;
4507 if (argv_find_and_parse_afi (argv, argc, &idx, &afi))
4508 {
4509 if (afi == AFI_IP)
4510 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
4511 "ip vpn next-hop", arg);
4512 else
4513 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
313605cb 4514 "ipv6 vpn next-hop", arg);
d6902373
PG
4515 }
4516 return CMD_SUCCESS;
4517}
718e3744 4518
4519DEFUN (set_originator_id,
4520 set_originator_id_cmd,
4521 "set originator-id A.B.C.D",
4522 SET_STR
4523 "BGP originator ID attribute\n"
4524 "IP address of originator\n")
4525{
c500ae40 4526 int idx_ipv4 = 2;
cdc2d765
DL
4527 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
4528 "originator-id", argv[idx_ipv4]->arg);
718e3744 4529}
4530
4c9bd275 4531
718e3744 4532DEFUN (no_set_originator_id,
4533 no_set_originator_id_cmd,
4c9bd275 4534 "no set originator-id [A.B.C.D]",
718e3744 4535 NO_STR
4536 SET_STR
4c9bd275
DW
4537 "BGP originator ID attribute\n"
4538 "IP address of originator\n")
718e3744 4539{
0d702986
QY
4540 int idx = 0;
4541 char *arg = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
4542
cdc2d765 4543 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
0d702986 4544 "originator-id", arg);
718e3744 4545}
4546
718e3744 4547
718e3744 4548/* Initialization of route map. */
4549void
94f2b392 4550bgp_route_map_init (void)
718e3744 4551{
4552 route_map_init ();
b2575bc0 4553
73ac8160
DS
4554 route_map_add_hook (bgp_route_map_add);
4555 route_map_delete_hook (bgp_route_map_delete);
4556 route_map_event_hook (bgp_route_map_event);
718e3744 4557
82f97584
DW
4558 route_map_match_interface_hook (generic_match_add);
4559 route_map_no_match_interface_hook (generic_match_delete);
4560
4561 route_map_match_ip_address_hook (generic_match_add);
4562 route_map_no_match_ip_address_hook (generic_match_delete);
4563
4564 route_map_match_ip_address_prefix_list_hook (generic_match_add);
4565 route_map_no_match_ip_address_prefix_list_hook (generic_match_delete);
4566
4567 route_map_match_ip_next_hop_hook (generic_match_add);
4568 route_map_no_match_ip_next_hop_hook (generic_match_delete);
4569
4570 route_map_match_ip_next_hop_prefix_list_hook (generic_match_add);
4571 route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete);
4572
4573 route_map_match_ipv6_address_hook (generic_match_add);
4574 route_map_no_match_ipv6_address_hook (generic_match_delete);
4575
4576 route_map_match_ipv6_address_prefix_list_hook (generic_match_add);
4577 route_map_no_match_ipv6_address_prefix_list_hook (generic_match_delete);
4578
4579 route_map_match_metric_hook (generic_match_add);
4580 route_map_no_match_metric_hook (generic_match_delete);
4581
4582 route_map_match_tag_hook (generic_match_add);
4583 route_map_no_match_tag_hook (generic_match_delete);
4584
4585 route_map_set_ip_nexthop_hook (generic_set_add);
4586 route_map_no_set_ip_nexthop_hook (generic_set_delete);
4587
4588 route_map_set_ipv6_nexthop_local_hook (generic_set_add);
4589 route_map_no_set_ipv6_nexthop_local_hook (generic_set_delete);
4590
4591 route_map_set_metric_hook (generic_set_add);
4592 route_map_no_set_metric_hook (generic_set_delete);
4593
4594 route_map_set_tag_hook (generic_set_add);
4595 route_map_no_set_tag_hook (generic_set_delete);
4596
fee0f4c6 4597 route_map_install_match (&route_match_peer_cmd);
af291c15 4598 route_map_install_match (&route_match_local_pref_cmd);
718e3744 4599 route_map_install_match (&route_match_ip_address_cmd);
4600 route_map_install_match (&route_match_ip_next_hop_cmd);
c1643bb7 4601 route_map_install_match (&route_match_ip_route_source_cmd);
718e3744 4602 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
4603 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
c1643bb7 4604 route_map_install_match (&route_match_ip_route_source_prefix_list_cmd);
718e3744 4605 route_map_install_match (&route_match_aspath_cmd);
4606 route_map_install_match (&route_match_community_cmd);
57d187bc 4607 route_map_install_match (&route_match_lcommunity_cmd);
73ffb25b 4608 route_map_install_match (&route_match_ecommunity_cmd);
af291c15 4609 route_map_install_match (&route_match_local_pref_cmd);
718e3744 4610 route_map_install_match (&route_match_metric_cmd);
4611 route_map_install_match (&route_match_origin_cmd);
1add115a 4612 route_map_install_match (&route_match_probability_cmd);
bc413143 4613 route_map_install_match (&route_match_interface_cmd);
0d9551dc 4614 route_map_install_match (&route_match_tag_cmd);
718e3744 4615
4616 route_map_install_set (&route_set_ip_nexthop_cmd);
4617 route_map_install_set (&route_set_local_pref_cmd);
4618 route_map_install_set (&route_set_weight_cmd);
d990e384 4619 route_map_install_set (&route_set_label_index_cmd);
718e3744 4620 route_map_install_set (&route_set_metric_cmd);
4621 route_map_install_set (&route_set_aspath_prepend_cmd);
841f7a57 4622 route_map_install_set (&route_set_aspath_exclude_cmd);
718e3744 4623 route_map_install_set (&route_set_origin_cmd);
4624 route_map_install_set (&route_set_atomic_aggregate_cmd);
4625 route_map_install_set (&route_set_aggregator_as_cmd);
4626 route_map_install_set (&route_set_community_cmd);
4627 route_map_install_set (&route_set_community_delete_cmd);
57d187bc
JS
4628 route_map_install_set (&route_set_lcommunity_cmd);
4629 route_map_install_set (&route_set_lcommunity_delete_cmd);
718e3744 4630 route_map_install_set (&route_set_vpnv4_nexthop_cmd);
d6902373 4631 route_map_install_set (&route_set_vpnv6_nexthop_cmd);
718e3744 4632 route_map_install_set (&route_set_originator_id_cmd);
4633 route_map_install_set (&route_set_ecommunity_rt_cmd);
4634 route_map_install_set (&route_set_ecommunity_soo_cmd);
0d9551dc 4635 route_map_install_set (&route_set_tag_cmd);
d990e384 4636 route_map_install_set (&route_set_label_index_cmd);
718e3744 4637
fee0f4c6 4638 install_element (RMAP_NODE, &match_peer_cmd);
4639 install_element (RMAP_NODE, &match_peer_local_cmd);
4640 install_element (RMAP_NODE, &no_match_peer_cmd);
c1643bb7 4641 install_element (RMAP_NODE, &match_ip_route_source_cmd);
4642 install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
c1643bb7 4643 install_element (RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4644 install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
718e3744 4645
4646 install_element (RMAP_NODE, &match_aspath_cmd);
4647 install_element (RMAP_NODE, &no_match_aspath_cmd);
af291c15
DS
4648 install_element (RMAP_NODE, &match_local_pref_cmd);
4649 install_element (RMAP_NODE, &no_match_local_pref_cmd);
718e3744 4650 install_element (RMAP_NODE, &match_community_cmd);
718e3744 4651 install_element (RMAP_NODE, &no_match_community_cmd);
57d187bc
JS
4652 install_element (RMAP_NODE, &match_lcommunity_cmd);
4653 install_element (RMAP_NODE, &no_match_lcommunity_cmd);
73ffb25b 4654 install_element (RMAP_NODE, &match_ecommunity_cmd);
4655 install_element (RMAP_NODE, &no_match_ecommunity_cmd);
718e3744 4656 install_element (RMAP_NODE, &match_origin_cmd);
4657 install_element (RMAP_NODE, &no_match_origin_cmd);
1add115a
VT
4658 install_element (RMAP_NODE, &match_probability_cmd);
4659 install_element (RMAP_NODE, &no_match_probability_cmd);
718e3744 4660
af5cd0a5 4661 install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
316e074d 4662 install_element (RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
718e3744 4663 install_element (RMAP_NODE, &set_local_pref_cmd);
4664 install_element (RMAP_NODE, &no_set_local_pref_cmd);
718e3744 4665 install_element (RMAP_NODE, &set_weight_cmd);
d990e384 4666 install_element (RMAP_NODE, &set_label_index_cmd);
718e3744 4667 install_element (RMAP_NODE, &no_set_weight_cmd);
d990e384 4668 install_element (RMAP_NODE, &no_set_label_index_cmd);
12dcf78e
QY
4669 install_element (RMAP_NODE, &set_aspath_prepend_asn_cmd);
4670 install_element (RMAP_NODE, &set_aspath_prepend_lastas_cmd);
841f7a57 4671 install_element (RMAP_NODE, &set_aspath_exclude_cmd);
718e3744 4672 install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
841f7a57 4673 install_element (RMAP_NODE, &no_set_aspath_exclude_cmd);
718e3744 4674 install_element (RMAP_NODE, &set_origin_cmd);
4675 install_element (RMAP_NODE, &no_set_origin_cmd);
718e3744 4676 install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
4677 install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
4678 install_element (RMAP_NODE, &set_aggregator_as_cmd);
4679 install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
718e3744 4680 install_element (RMAP_NODE, &set_community_cmd);
4681 install_element (RMAP_NODE, &set_community_none_cmd);
4682 install_element (RMAP_NODE, &no_set_community_cmd);
718e3744 4683 install_element (RMAP_NODE, &set_community_delete_cmd);
4684 install_element (RMAP_NODE, &no_set_community_delete_cmd);
57d187bc
JS
4685 install_element (RMAP_NODE, &set_lcommunity_cmd);
4686 install_element (RMAP_NODE, &set_lcommunity_none_cmd);
4687 install_element (RMAP_NODE, &no_set_lcommunity_cmd);
52951b63 4688 install_element (RMAP_NODE, &no_set_lcommunity1_cmd);
57d187bc
JS
4689 install_element (RMAP_NODE, &set_lcommunity_delete_cmd);
4690 install_element (RMAP_NODE, &no_set_lcommunity_delete_cmd);
718e3744 4691 install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
4692 install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
718e3744 4693 install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
4694 install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
d6902373
PG
4695#ifdef KEEP_OLD_VPN_COMMANDS
4696 install_element (RMAP_NODE, &set_vpn_nexthop_cmd);
4697 install_element (RMAP_NODE, &no_set_vpn_nexthop_cmd);
4698#endif /* KEEP_OLD_VPN_COMMANDS */
4699 install_element (RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
4700 install_element (RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
718e3744 4701 install_element (RMAP_NODE, &set_originator_id_cmd);
4702 install_element (RMAP_NODE, &no_set_originator_id_cmd);
718e3744 4703
718e3744 4704 route_map_install_match (&route_match_ipv6_address_cmd);
4705 route_map_install_match (&route_match_ipv6_next_hop_cmd);
4706 route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
4707 route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
161995ea 4708 route_map_install_set (&route_set_ipv6_nexthop_prefer_global_cmd);
718e3744 4709 route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
90916ac2
DS
4710 route_map_install_set (&route_set_ipv6_nexthop_peer_cmd);
4711
718e3744 4712 install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
4713 install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
718e3744 4714 install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
4715 install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
161995ea
DS
4716 install_element (RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
4717 install_element (RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
90916ac2
DS
4718 install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
4719 install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
718e3744 4720}
518f0eb1
DS
4721
4722void
4723bgp_route_map_terminate (void)
4724{
4725 /* ToDo: Cleanup all the used memory */
4726
4727 route_map_add_hook (NULL);
4728 route_map_delete_hook (NULL);
4729 route_map_event_hook (NULL);
4730 route_map_finish();
4731
4732}