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