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