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