]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
Merge pull request #73 from opensourcerouting/ldpd-json
[mirror_frr.git] / bgpd / bgp_routemap.c
CommitLineData
718e3744 1/* Route map function of bgpd.
2 Copyright (C) 1998, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "filter.h"
82f97584 25#include "vty.h"
718e3744 26#include "routemap.h"
27#include "command.h"
28#include "linklist.h"
29#include "plist.h"
30#include "memory.h"
31#include "log.h"
25f45887
JJ
32#ifdef HAVE_LIBPCREPOSIX
33# include <pcreposix.h>
718e3744 34#else
24f5e2fc 35# include <regex.h>
25f45887 36#endif /* HAVE_LIBPCREPOSIX */
718e3744 37#include "buffer.h"
38#include "sockunion.h"
518f0eb1 39#include "hash.h"
3f9c7369 40#include "queue.h"
718e3744 41
42#include "bgpd/bgpd.h"
43#include "bgpd/bgp_table.h"
44#include "bgpd/bgp_attr.h"
45#include "bgpd/bgp_aspath.h"
518f0eb1 46#include "bgpd/bgp_packet.h"
718e3744 47#include "bgpd/bgp_route.h"
73ac8160 48#include "bgpd/bgp_zebra.h"
718e3744 49#include "bgpd/bgp_regex.h"
50#include "bgpd/bgp_community.h"
51#include "bgpd/bgp_clist.h"
52#include "bgpd/bgp_filter.h"
53#include "bgpd/bgp_mplsvpn.h"
54#include "bgpd/bgp_ecommunity.h"
320da874 55#include "bgpd/bgp_vty.h"
73ac8160 56#include "bgpd/bgp_debug.h"
718e3744 57
65efcfce 58#if ENABLE_BGP_VNC
f8b6f499 59# include "bgpd/rfapi/bgp_rfapi_cfg.h"
65efcfce 60#endif
518f0eb1 61
718e3744 62/* Memo of route-map commands.
63
64o Cisco route-map
65
66 match as-path : Done
67 community : Done
bc413143 68 interface : Done
718e3744 69 ip address : Done
70 ip next-hop : Done
c1643bb7 71 ip route-source : Done
718e3744 72 ip prefix-list : Done
73 ipv6 address : Done
74 ipv6 next-hop : Done
75 ipv6 route-source: (This will not be implemented by bgpd)
76 ipv6 prefix-list : Done
77 length : (This will not be implemented by bgpd)
78 metric : Done
79 route-type : (This will not be implemented by bgpd)
0d9551dc 80 tag : Done
af291c15 81 local-preference : Done
718e3744 82
83 set as-path prepend : Done
84 as-path tag : Not yet
85 automatic-tag : (This will not be implemented by bgpd)
86 community : Done
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
e52702f2 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
e52702f2 332route_match_ip_address (void *rule, struct prefix *prefix,
718e3744 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;
e52702f2 343
718e3744 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
e52702f2 378route_match_ip_next_hop (void *rule, struct prefix *prefix,
718e3744 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
e52702f2 430route_match_ip_route_source (void *rule, struct prefix *prefix,
c1643bb7 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
e52702f2 487route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
718e3744 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;
e52702f2 497
718e3744 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
e52702f2 694route_match_metric (void *rule, struct prefix *prefix,
718e3744 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
e52702f2 722route_match_aspath (void *rule, struct prefix *prefix,
718e3744 723 route_map_object_t type, void *object)
724{
e52702f2 725
718e3744 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. */
e52702f2 758struct route_map_rule_cmd route_match_aspath_cmd =
718e3744 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
e52702f2 775route_match_community (void *rule, struct prefix *prefix,
718e3744 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
e52702f2 782 if (type == RMAP_BGP)
718e3744 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
e52702f2 837 XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name);
718e3744 838 XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom);
839}
840
841/* Route map commands for community matching. */
e52702f2 842struct route_map_rule_cmd route_match_community_cmd =
718e3744 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
e52702f2 852route_match_ecommunity (void *rule, struct prefix *prefix,
73ffb25b 853 route_map_object_t type, void *object)
854{
855 struct community_list *list;
856 struct bgp_info *bgp_info;
857
e52702f2 858 if (type == RMAP_BGP)
73ffb25b 859 {
860 bgp_info = object;
e52702f2 861
fb982c25
PJ
862 if (!bgp_info->attr->extra)
863 return RMAP_NOMATCH;
e52702f2 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. */
e52702f2 891struct route_map_rule_cmd route_match_ecommunity_cmd =
73ffb25b 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
e52702f2 904route_match_origin (void *rule, struct prefix *prefix,
718e3744 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;
e52702f2 914
718e3744 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{
dc9ffce8 1070 route_tag_t *tag;
0d9551dc
DS
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
0d9551dc 1088/* Route map commands for tag matching. */
dc9ffce8 1089static struct route_map_rule_cmd route_match_tag_cmd =
0d9551dc
DS
1090{
1091 "tag",
1092 route_match_tag,
dc9ffce8
CF
1093 route_map_rule_tag_compile,
1094 route_map_rule_tag_free,
0d9551dc
DS
1095};
1096
1097
718e3744 1098/* Set nexthop to object. ojbect must be pointer to struct attr. */
ac41b2a2 1099struct rmap_ip_nexthop_set
1100{
1101 struct in_addr *address;
1102 int peer_address;
316e074d 1103 int unchanged;
ac41b2a2 1104};
1105
94f2b392 1106static route_map_result_t
718e3744 1107route_set_ip_nexthop (void *rule, struct prefix *prefix,
1108 route_map_object_t type, void *object)
1109{
ac41b2a2 1110 struct rmap_ip_nexthop_set *rins = rule;
718e3744 1111 struct bgp_info *bgp_info;
ac41b2a2 1112 struct peer *peer;
718e3744 1113
1114 if (type == RMAP_BGP)
1115 {
718e3744 1116 bgp_info = object;
ac41b2a2 1117 peer = bgp_info->peer;
1118
316e074d
DS
1119 if (rins->unchanged)
1120 {
1121 SET_FLAG(bgp_info->attr->rmap_change_flags,
1122 BATTR_RMAP_NEXTHOP_UNCHANGED);
1123 }
1124 else if (rins->peer_address)
ac41b2a2 1125 {
fee0f4c6 1126 if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
1127 CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
e52702f2 1128 && peer->su_remote
ac41b2a2 1129 && sockunion_family (peer->su_remote) == AF_INET)
1130 {
0c5ed3ed 1131 bgp_info->attr->nexthop.s_addr = sockunion2ip (peer->su_remote);
ac41b2a2 1132 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1133 }
3f9c7369 1134 else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT))
ac41b2a2 1135 {
3f9c7369
DS
1136 /* The next hop value will be set as part of packet rewrite.
1137 * Set the flags here to indicate that rewrite needs to be done.
1138 * Also, clear the value.
1139 */
1140 SET_FLAG(bgp_info->attr->rmap_change_flags,
1141 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3f9c7369 1142 bgp_info->attr->nexthop.s_addr = 0;
ac41b2a2 1143 }
1144 }
1145 else
1146 {
3f9c7369 1147 /* Set next hop value. */
ac41b2a2 1148 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
1149 bgp_info->attr->nexthop = *rins->address;
3f9c7369 1150 SET_FLAG(bgp_info->attr->rmap_change_flags,
3811f1e2 1151 BATTR_RMAP_IPV4_NHOP_CHANGED);
ac41b2a2 1152 }
718e3744 1153 }
1154
1155 return RMAP_OKAY;
1156}
1157
1158/* Route map `ip nexthop' compile function. Given string is converted
1159 to struct in_addr structure. */
94f2b392 1160static void *
fd79ac91 1161route_set_ip_nexthop_compile (const char *arg)
718e3744 1162{
ac41b2a2 1163 struct rmap_ip_nexthop_set *rins;
1164 struct in_addr *address = NULL;
1165 int peer_address = 0;
316e074d 1166 int unchanged = 0;
718e3744 1167 int ret;
718e3744 1168
ac41b2a2 1169 if (strcmp (arg, "peer-address") == 0)
1170 peer_address = 1;
316e074d
DS
1171 else if (strcmp (arg, "unchanged") == 0)
1172 unchanged = 1;
ac41b2a2 1173 else
718e3744 1174 {
ac41b2a2 1175 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
1176 ret = inet_aton (arg, address);
1177
1178 if (ret == 0)
1179 {
1180 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
1181 return NULL;
1182 }
718e3744 1183 }
1184
393deb9b 1185 rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_ip_nexthop_set));
ac41b2a2 1186
1187 rins->address = address;
1188 rins->peer_address = peer_address;
316e074d 1189 rins->unchanged = unchanged;
ac41b2a2 1190
1191 return rins;
718e3744 1192}
1193
1194/* Free route map's compiled `ip nexthop' value. */
94f2b392 1195static void
718e3744 1196route_set_ip_nexthop_free (void *rule)
1197{
ac41b2a2 1198 struct rmap_ip_nexthop_set *rins = rule;
1199
1200 if (rins->address)
1201 XFREE (MTYPE_ROUTE_MAP_COMPILED, rins->address);
e52702f2 1202
ac41b2a2 1203 XFREE (MTYPE_ROUTE_MAP_COMPILED, rins);
718e3744 1204}
1205
1206/* Route map commands for ip nexthop set. */
1207struct route_map_rule_cmd route_set_ip_nexthop_cmd =
1208{
1209 "ip next-hop",
1210 route_set_ip_nexthop,
1211 route_set_ip_nexthop_compile,
1212 route_set_ip_nexthop_free
1213};
6b0655a2 1214
718e3744 1215/* `set local-preference LOCAL_PREF' */
1216
1217/* Set local preference. */
94f2b392 1218static route_map_result_t
718e3744 1219route_set_local_pref (void *rule, struct prefix *prefix,
1220 route_map_object_t type, void *object)
1221{
76759f4f 1222 struct rmap_value *rv;
718e3744 1223 struct bgp_info *bgp_info;
76759f4f 1224 u_int32_t locpref = 0;
718e3744 1225
1226 if (type == RMAP_BGP)
1227 {
1228 /* Fetch routemap's rule information. */
76759f4f 1229 rv = rule;
718e3744 1230 bgp_info = object;
e52702f2
QY
1231
1232 /* Set local preference value. */
76759f4f
TT
1233 if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
1234 locpref = bgp_info->attr->local_pref;
1235
718e3744 1236 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
baa376fc 1237 bgp_info->attr->local_pref = route_value_adjust(rv, locpref, bgp_info->peer);
718e3744 1238 }
1239
1240 return RMAP_OKAY;
1241}
1242
718e3744 1243/* Set local preference rule structure. */
e52702f2 1244struct route_map_rule_cmd route_set_local_pref_cmd =
718e3744 1245{
1246 "local-preference",
1247 route_set_local_pref,
76759f4f
TT
1248 route_value_compile,
1249 route_value_free,
718e3744 1250};
6b0655a2 1251
718e3744 1252/* `set weight WEIGHT' */
1253
1254/* Set weight. */
94f2b392 1255static route_map_result_t
718e3744 1256route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
1257 void *object)
1258{
76759f4f 1259 struct rmap_value *rv;
718e3744 1260 struct bgp_info *bgp_info;
76759f4f 1261 u_int32_t weight;
718e3744 1262
1263 if (type == RMAP_BGP)
1264 {
1265 /* Fetch routemap's rule information. */
76759f4f 1266 rv = rule;
718e3744 1267 bgp_info = object;
e52702f2
QY
1268
1269 /* Set weight value. */
baa376fc 1270 weight = route_value_adjust(rv, 0, bgp_info->peer);
76759f4f
TT
1271 if (weight)
1272 (bgp_attr_extra_get (bgp_info->attr))->weight = weight;
fb982c25
PJ
1273 else if (bgp_info->attr->extra)
1274 bgp_info->attr->extra->weight = 0;
718e3744 1275 }
1276
1277 return RMAP_OKAY;
1278}
1279
718e3744 1280/* Set local preference rule structure. */
e52702f2 1281struct route_map_rule_cmd route_set_weight_cmd =
718e3744 1282{
1283 "weight",
1284 route_set_weight,
76759f4f
TT
1285 route_value_compile,
1286 route_value_free,
718e3744 1287};
6b0655a2 1288
718e3744 1289/* `set metric METRIC' */
1290
1291/* Set metric to attribute. */
94f2b392 1292static route_map_result_t
e52702f2 1293route_set_metric (void *rule, struct prefix *prefix,
718e3744 1294 route_map_object_t type, void *object)
1295{
76759f4f 1296 struct rmap_value *rv;
718e3744 1297 struct bgp_info *bgp_info;
76759f4f 1298 u_int32_t med = 0;
718e3744 1299
1300 if (type == RMAP_BGP)
1301 {
1302 /* Fetch routemap's rule information. */
76759f4f 1303 rv = rule;
718e3744 1304 bgp_info = object;
1305
76759f4f
TT
1306 if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
1307 med = bgp_info->attr->med;
718e3744 1308
baa376fc 1309 bgp_info->attr->med = route_value_adjust(rv, med, bgp_info->peer);
76759f4f 1310 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
718e3744 1311 }
1312 return RMAP_OKAY;
1313}
1314
718e3744 1315/* Set metric rule structure. */
e52702f2 1316struct route_map_rule_cmd route_set_metric_cmd =
718e3744 1317{
1318 "metric",
1319 route_set_metric,
76759f4f
TT
1320 route_value_compile,
1321 route_value_free,
718e3744 1322};
6b0655a2 1323
718e3744 1324/* `set as-path prepend ASPATH' */
1325
1326/* For AS path prepend mechanism. */
94f2b392 1327static route_map_result_t
718e3744 1328route_set_aspath_prepend (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
1329{
1330 struct aspath *aspath;
1331 struct aspath *new;
1332 struct bgp_info *binfo;
1333
1334 if (type == RMAP_BGP)
1335 {
718e3744 1336 binfo = object;
e52702f2 1337
718e3744 1338 if (binfo->attr->aspath->refcnt)
1339 new = aspath_dup (binfo->attr->aspath);
1340 else
1341 new = binfo->attr->aspath;
1342
bc3dd427
DW
1343 if ((uintptr_t)rule > 10)
1344 {
1345 aspath = rule;
1346 aspath_prepend (aspath, new);
1347 }
1348 else
1349 {
1350 as_t as = aspath_leftmost(new);
1351 if (!as) as = binfo->peer->as;
1352 new = aspath_add_seq_n (new, as, (uintptr_t) rule);
1353 }
1354
718e3744 1355 binfo->attr->aspath = new;
1356 }
1357
1358 return RMAP_OKAY;
1359}
1360
bc3dd427
DW
1361static void *
1362route_set_aspath_prepend_compile (const char *arg)
1363{
1364 unsigned int num;
1365
1366 if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num < 10)
1367 return (void*)(uintptr_t)num;
1368
1369 return route_aspath_compile(arg);
1370}
1371
1372static void
1373route_set_aspath_prepend_free (void *rule)
1374{
1375 if ((uintptr_t)rule > 10)
1376 route_aspath_free(rule);
1377}
1378
1379
515e500c 1380/* Set as-path prepend rule structure. */
e52702f2 1381struct route_map_rule_cmd route_set_aspath_prepend_cmd =
718e3744 1382{
1383 "as-path prepend",
1384 route_set_aspath_prepend,
bc3dd427
DW
1385 route_set_aspath_prepend_compile,
1386 route_set_aspath_prepend_free,
718e3744 1387};
6b0655a2 1388
841f7a57
DO
1389/* `set as-path exclude ASn' */
1390
1391/* For ASN exclude mechanism.
1392 * Iterate over ASns requested and filter them from the given AS_PATH one by one.
1393 * Make a deep copy of existing AS_PATH, but for the first ASn only.
1394 */
1395static route_map_result_t
1396route_set_aspath_exclude (void *rule, struct prefix *dummy, route_map_object_t type, void *object)
1397{
1398 struct aspath * new_path, * exclude_path;
1399 struct bgp_info *binfo;
1400
1401 if (type == RMAP_BGP)
1402 {
1403 exclude_path = rule;
1404 binfo = object;
1405 if (binfo->attr->aspath->refcnt)
1406 new_path = aspath_dup (binfo->attr->aspath);
1407 else
1408 new_path = binfo->attr->aspath;
1409 binfo->attr->aspath = aspath_filter_exclude (new_path, exclude_path);
1410 }
1411 return RMAP_OKAY;
1412}
1413
841f7a57 1414/* Set ASn exlude rule structure. */
e52702f2 1415struct route_map_rule_cmd route_set_aspath_exclude_cmd =
841f7a57
DO
1416{
1417 "as-path exclude",
1418 route_set_aspath_exclude,
374f12f9
TT
1419 route_aspath_compile,
1420 route_aspath_free,
841f7a57 1421};
6b0655a2 1422
718e3744 1423/* `set community COMMUNITY' */
1424struct rmap_com_set
1425{
1426 struct community *com;
1427 int additive;
1428 int none;
1429};
1430
1431/* For community set mechanism. */
94f2b392 1432static route_map_result_t
718e3744 1433route_set_community (void *rule, struct prefix *prefix,
1434 route_map_object_t type, void *object)
1435{
1436 struct rmap_com_set *rcs;
1437 struct bgp_info *binfo;
1438 struct attr *attr;
1439 struct community *new = NULL;
1440 struct community *old;
1441 struct community *merge;
e52702f2 1442
718e3744 1443 if (type == RMAP_BGP)
1444 {
1445 rcs = rule;
1446 binfo = object;
1447 attr = binfo->attr;
1448 old = attr->community;
1449
1450 /* "none" case. */
1451 if (rcs->none)
1452 {
1453 attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
1454 attr->community = NULL;
b06b35f0
CF
1455 /* See the longer comment down below. */
1456 if (old && old->refcnt == 0)
1457 community_free(old);
718e3744 1458 return RMAP_OKAY;
1459 }
1460
1461 /* "additive" case. */
1462 if (rcs->additive && old)
1463 {
1464 merge = community_merge (community_dup (old), rcs->com);
e52702f2
QY
1465
1466 /* HACK: if the old community is not intern'd,
aa94ca86
PJ
1467 * we should free it here, or all reference to it may be lost.
1468 * Really need to cleanup attribute caching sometime.
1469 */
1470 if (old->refcnt == 0)
1471 community_free (old);
718e3744 1472 new = community_uniq_sort (merge);
1473 community_free (merge);
1474 }
1475 else
1476 new = community_dup (rcs->com);
e52702f2 1477
aa94ca86 1478 /* will be interned by caller if required */
4a2035fd 1479 attr->community = new;
70601e06 1480
718e3744 1481 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1482 }
1483
1484 return RMAP_OKAY;
1485}
1486
1487/* Compile function for set community. */
94f2b392 1488static void *
fd79ac91 1489route_set_community_compile (const char *arg)
718e3744 1490{
1491 struct rmap_com_set *rcs;
1492 struct community *com = NULL;
1493 char *sp;
1494 int additive = 0;
1495 int none = 0;
e52702f2 1496
718e3744 1497 if (strcmp (arg, "none") == 0)
1498 none = 1;
1499 else
1500 {
1501 sp = strstr (arg, "additive");
1502
1503 if (sp && sp > arg)
1504 {
1505 /* "additive" keyworkd is included. */
1506 additive = 1;
1507 *(sp - 1) = '\0';
1508 }
1509
1510 com = community_str2com (arg);
1511
1512 if (additive)
1513 *(sp - 1) = ' ';
1514
1515 if (! com)
1516 return NULL;
1517 }
e52702f2 1518
393deb9b 1519 rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
4a2035fd 1520 rcs->com = com;
718e3744 1521 rcs->additive = additive;
1522 rcs->none = none;
e52702f2 1523
718e3744 1524 return rcs;
1525}
1526
1527/* Free function for set community. */
94f2b392 1528static void
718e3744 1529route_set_community_free (void *rule)
1530{
1531 struct rmap_com_set *rcs = rule;
1532
1533 if (rcs->com)
1534 community_free (rcs->com);
1535 XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs);
1536}
1537
1538/* Set community rule structure. */
e52702f2 1539struct route_map_rule_cmd route_set_community_cmd =
718e3744 1540{
1541 "community",
1542 route_set_community,
1543 route_set_community_compile,
1544 route_set_community_free,
1545};
6b0655a2 1546
fee6e4e4 1547/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
718e3744 1548
1549/* For community set mechanism. */
94f2b392 1550static route_map_result_t
718e3744 1551route_set_community_delete (void *rule, struct prefix *prefix,
1552 route_map_object_t type, void *object)
1553{
1554 struct community_list *list;
1555 struct community *merge;
1556 struct community *new;
1557 struct community *old;
1558 struct bgp_info *binfo;
1559
1560 if (type == RMAP_BGP)
1561 {
1562 if (! rule)
1563 return RMAP_OKAY;
1564
1565 binfo = object;
fee6e4e4 1566 list = community_list_lookup (bgp_clist, rule, COMMUNITY_LIST_MASTER);
718e3744 1567 old = binfo->attr->community;
1568
1569 if (list && old)
1570 {
1571 merge = community_list_match_delete (community_dup (old), list);
1572 new = community_uniq_sort (merge);
1573 community_free (merge);
1574
604a9b43
ML
1575 /* HACK: if the old community is not intern'd,
1576 * we should free it here, or all reference to it may be lost.
1577 * Really need to cleanup attribute caching sometime.
1578 */
1579 if (old->refcnt == 0)
1580 community_free (old);
1581
718e3744 1582 if (new->size == 0)
1583 {
1584 binfo->attr->community = NULL;
1585 binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1586 community_free (new);
1587 }
1588 else
1589 {
4a2035fd 1590 binfo->attr->community = new;
718e3744 1591 binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
1592 }
1593 }
1594 }
1595
1596 return RMAP_OKAY;
1597}
1598
1599/* Compile function for set community. */
94f2b392 1600static void *
fd79ac91 1601route_set_community_delete_compile (const char *arg)
718e3744 1602{
1603 char *p;
1604 char *str;
1605 int len;
1606
1607 p = strchr (arg, ' ');
1608 if (p)
1609 {
1610 len = p - arg;
1611 str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
1612 memcpy (str, arg, len);
1613 }
1614 else
1615 str = NULL;
1616
1617 return str;
1618}
1619
1620/* Free function for set community. */
94f2b392 1621static void
718e3744 1622route_set_community_delete_free (void *rule)
1623{
1624 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1625}
1626
1627/* Set community rule structure. */
1628struct route_map_rule_cmd route_set_community_delete_cmd =
1629{
1630 "comm-list",
1631 route_set_community_delete,
1632 route_set_community_delete_compile,
1633 route_set_community_delete_free,
1634};
6b0655a2 1635
718e3744 1636/* `set extcommunity rt COMMUNITY' */
1637
73d78ea0 1638/* For community set mechanism. Used by _rt and _soo. */
94f2b392 1639static route_map_result_t
73d78ea0
DL
1640route_set_ecommunity (void *rule, struct prefix *prefix,
1641 route_map_object_t type, void *object)
718e3744 1642{
1643 struct ecommunity *ecom;
1644 struct ecommunity *new_ecom;
1645 struct ecommunity *old_ecom;
1646 struct bgp_info *bgp_info;
1647
1648 if (type == RMAP_BGP)
1649 {
1650 ecom = rule;
1651 bgp_info = object;
e52702f2 1652
718e3744 1653 if (! ecom)
1654 return RMAP_OKAY;
e52702f2 1655
718e3744 1656 /* We assume additive for Extended Community. */
fb982c25 1657 old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
718e3744 1658
1659 if (old_ecom)
27bf90a1
DL
1660 {
1661 new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
1662
1663 /* old_ecom->refcnt = 1 => owned elsewhere, e.g. bgp_update_receive()
1664 * ->refcnt = 0 => set by a previous route-map statement */
1665 if (!old_ecom->refcnt)
1666 ecommunity_free (&old_ecom);
1667 }
718e3744 1668 else
1669 new_ecom = ecommunity_dup (ecom);
1670
27bf90a1
DL
1671 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1672 bgp_info->attr->extra->ecommunity = new_ecom;
70601e06 1673
718e3744 1674 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
1675 }
1676 return RMAP_OKAY;
1677}
1678
1679/* Compile function for set community. */
94f2b392 1680static void *
fd79ac91 1681route_set_ecommunity_rt_compile (const char *arg)
718e3744 1682{
1683 struct ecommunity *ecom;
1684
1685 ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
1686 if (! ecom)
1687 return NULL;
f6f434b2 1688 return ecommunity_intern (ecom);
718e3744 1689}
1690
73d78ea0 1691/* Free function for set community. Used by _rt and _soo */
94f2b392 1692static void
73d78ea0 1693route_set_ecommunity_free (void *rule)
718e3744 1694{
1695 struct ecommunity *ecom = rule;
f6f434b2 1696 ecommunity_unintern (&ecom);
718e3744 1697}
1698
1699/* Set community rule structure. */
e52702f2 1700struct route_map_rule_cmd route_set_ecommunity_rt_cmd =
718e3744 1701{
1702 "extcommunity rt",
73d78ea0 1703 route_set_ecommunity,
718e3744 1704 route_set_ecommunity_rt_compile,
73d78ea0 1705 route_set_ecommunity_free,
718e3744 1706};
1707
1708/* `set extcommunity soo COMMUNITY' */
1709
718e3744 1710/* Compile function for set community. */
94f2b392 1711static void *
fd79ac91 1712route_set_ecommunity_soo_compile (const char *arg)
718e3744 1713{
1714 struct ecommunity *ecom;
1715
1716 ecom = ecommunity_str2com (arg, ECOMMUNITY_SITE_ORIGIN, 0);
1717 if (! ecom)
1718 return NULL;
e52702f2 1719
f6f434b2 1720 return ecommunity_intern (ecom);
718e3744 1721}
1722
718e3744 1723/* Set community rule structure. */
e52702f2 1724struct route_map_rule_cmd route_set_ecommunity_soo_cmd =
718e3744 1725{
1726 "extcommunity soo",
73d78ea0 1727 route_set_ecommunity,
718e3744 1728 route_set_ecommunity_soo_compile,
73d78ea0 1729 route_set_ecommunity_free,
718e3744 1730};
6b0655a2 1731
718e3744 1732/* `set origin ORIGIN' */
1733
1734/* For origin set. */
94f2b392 1735static route_map_result_t
718e3744 1736route_set_origin (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
1737{
1738 u_char *origin;
1739 struct bgp_info *bgp_info;
1740
1741 if (type == RMAP_BGP)
1742 {
1743 origin = rule;
1744 bgp_info = object;
e52702f2 1745
718e3744 1746 bgp_info->attr->origin = *origin;
1747 }
1748
1749 return RMAP_OKAY;
1750}
1751
1752/* Compile function for origin set. */
94f2b392 1753static void *
fd79ac91 1754route_set_origin_compile (const char *arg)
718e3744 1755{
1756 u_char *origin;
1757
1758 origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
1759
1760 if (strcmp (arg, "igp") == 0)
1761 *origin = 0;
1762 else if (strcmp (arg, "egp") == 0)
1763 *origin = 1;
1764 else
1765 *origin = 2;
1766
1767 return origin;
1768}
1769
1770/* Compile function for origin set. */
94f2b392 1771static void
718e3744 1772route_set_origin_free (void *rule)
1773{
1774 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1775}
1776
515e500c 1777/* Set origin rule structure. */
e52702f2 1778struct route_map_rule_cmd route_set_origin_cmd =
718e3744 1779{
1780 "origin",
1781 route_set_origin,
1782 route_set_origin_compile,
1783 route_set_origin_free,
1784};
6b0655a2 1785
718e3744 1786/* `set atomic-aggregate' */
1787
1788/* For atomic aggregate set. */
94f2b392 1789static route_map_result_t
718e3744 1790route_set_atomic_aggregate (void *rule, struct prefix *prefix,
1791 route_map_object_t type, void *object)
1792{
1793 struct bgp_info *bgp_info;
1794
1795 if (type == RMAP_BGP)
1796 {
1797 bgp_info = object;
1798 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
1799 }
1800
1801 return RMAP_OKAY;
1802}
1803
1804/* Compile function for atomic aggregate. */
94f2b392 1805static void *
fd79ac91 1806route_set_atomic_aggregate_compile (const char *arg)
718e3744 1807{
1808 return (void *)1;
1809}
1810
1811/* Compile function for atomic aggregate. */
94f2b392 1812static void
718e3744 1813route_set_atomic_aggregate_free (void *rule)
1814{
1815 return;
1816}
1817
1818/* Set atomic aggregate rule structure. */
e52702f2 1819struct route_map_rule_cmd route_set_atomic_aggregate_cmd =
718e3744 1820{
1821 "atomic-aggregate",
1822 route_set_atomic_aggregate,
1823 route_set_atomic_aggregate_compile,
1824 route_set_atomic_aggregate_free,
1825};
6b0655a2 1826
718e3744 1827/* `set aggregator as AS A.B.C.D' */
1828struct aggregator
1829{
1830 as_t as;
1831 struct in_addr address;
1832};
1833
94f2b392 1834static route_map_result_t
e52702f2 1835route_set_aggregator_as (void *rule, struct prefix *prefix,
718e3744 1836 route_map_object_t type, void *object)
1837{
1838 struct bgp_info *bgp_info;
1839 struct aggregator *aggregator;
fb982c25 1840 struct attr_extra *ae;
718e3744 1841
1842 if (type == RMAP_BGP)
1843 {
1844 bgp_info = object;
1845 aggregator = rule;
fb982c25 1846 ae = bgp_attr_extra_get (bgp_info->attr);
e52702f2 1847
fb982c25
PJ
1848 ae->aggregator_as = aggregator->as;
1849 ae->aggregator_addr = aggregator->address;
718e3744 1850 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
1851 }
1852
1853 return RMAP_OKAY;
1854}
1855
94f2b392 1856static void *
fd79ac91 1857route_set_aggregator_as_compile (const char *arg)
718e3744 1858{
1859 struct aggregator *aggregator;
1860 char as[10];
1861 char address[20];
1862
393deb9b 1863 aggregator = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct aggregator));
718e3744 1864 sscanf (arg, "%s %s", as, address);
1865
1866 aggregator->as = strtoul (as, NULL, 10);
1867 inet_aton (address, &aggregator->address);
1868
1869 return aggregator;
1870}
1871
94f2b392 1872static void
718e3744 1873route_set_aggregator_as_free (void *rule)
1874{
1875 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1876}
1877
e52702f2 1878struct route_map_rule_cmd route_set_aggregator_as_cmd =
718e3744 1879{
1880 "aggregator as",
1881 route_set_aggregator_as,
1882 route_set_aggregator_as_compile,
1883 route_set_aggregator_as_free,
1884};
6b0655a2 1885
0d9551dc
DS
1886/* Set tag to object. object must be pointer to struct bgp_info */
1887static route_map_result_t
1888route_set_tag (void *rule, struct prefix *prefix,
1889 route_map_object_t type, void *object)
1890{
dc9ffce8 1891 route_tag_t *tag;
0d9551dc
DS
1892 struct bgp_info *bgp_info;
1893 struct attr_extra *ae;
1894
1895 if (type == RMAP_BGP)
1896 {
1897 tag = rule;
1898 bgp_info = object;
1899 ae = bgp_attr_extra_get (bgp_info->attr);
1900
1901 /* Set tag value */
1902 ae->tag=*tag;
1903
1904 }
1905
1906 return RMAP_OKAY;
1907}
1908
0d9551dc 1909/* Route map commands for tag set. */
dc9ffce8 1910static struct route_map_rule_cmd route_set_tag_cmd =
0d9551dc
DS
1911{
1912 "tag",
1913 route_set_tag,
dc9ffce8
CF
1914 route_map_rule_tag_compile,
1915 route_map_rule_tag_free,
0d9551dc
DS
1916};
1917
1918
718e3744 1919/* `match ipv6 address IP_ACCESS_LIST' */
1920
94f2b392 1921static route_map_result_t
e52702f2 1922route_match_ipv6_address (void *rule, struct prefix *prefix,
718e3744 1923 route_map_object_t type, void *object)
1924{
1925 struct access_list *alist;
1926
1927 if (type == RMAP_BGP)
1928 {
1929 alist = access_list_lookup (AFI_IP6, (char *) rule);
1930 if (alist == NULL)
1931 return RMAP_NOMATCH;
e52702f2 1932
718e3744 1933 return (access_list_apply (alist, prefix) == FILTER_DENY ?
1934 RMAP_NOMATCH : RMAP_MATCH);
1935 }
1936 return RMAP_NOMATCH;
1937}
1938
94f2b392 1939static void *
fd79ac91 1940route_match_ipv6_address_compile (const char *arg)
718e3744 1941{
1942 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1943}
1944
94f2b392 1945static void
718e3744 1946route_match_ipv6_address_free (void *rule)
1947{
1948 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1949}
1950
1951/* Route map commands for ip address matching. */
1952struct route_map_rule_cmd route_match_ipv6_address_cmd =
1953{
1954 "ipv6 address",
1955 route_match_ipv6_address,
1956 route_match_ipv6_address_compile,
1957 route_match_ipv6_address_free
1958};
6b0655a2 1959
718e3744 1960/* `match ipv6 next-hop IP_ADDRESS' */
1961
94f2b392 1962static route_map_result_t
e52702f2 1963route_match_ipv6_next_hop (void *rule, struct prefix *prefix,
718e3744 1964 route_map_object_t type, void *object)
1965{
1f9a9fff 1966 struct in6_addr *addr = rule;
718e3744 1967 struct bgp_info *bgp_info;
1968
1969 if (type == RMAP_BGP)
1970 {
718e3744 1971 bgp_info = object;
e52702f2 1972
fb982c25
PJ
1973 if (!bgp_info->attr->extra)
1974 return RMAP_NOMATCH;
e52702f2 1975
1f9a9fff 1976 if (IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_global, addr))
718e3744 1977 return RMAP_MATCH;
1978
801a9bcc 1979 if (bgp_info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL &&
fb982c25 1980 IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_local, rule))
718e3744 1981 return RMAP_MATCH;
1982
1983 return RMAP_NOMATCH;
1984 }
1985
1986 return RMAP_NOMATCH;
1987}
1988
94f2b392 1989static void *
fd79ac91 1990route_match_ipv6_next_hop_compile (const char *arg)
718e3744 1991{
1992 struct in6_addr *address;
1993 int ret;
1994
1995 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
1996
1997 ret = inet_pton (AF_INET6, arg, address);
1998 if (!ret)
1999 {
2000 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2001 return NULL;
2002 }
2003
2004 return address;
2005}
2006
94f2b392 2007static void
718e3744 2008route_match_ipv6_next_hop_free (void *rule)
2009{
2010 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2011}
2012
2013struct route_map_rule_cmd route_match_ipv6_next_hop_cmd =
2014{
2015 "ipv6 next-hop",
2016 route_match_ipv6_next_hop,
2017 route_match_ipv6_next_hop_compile,
2018 route_match_ipv6_next_hop_free
2019};
6b0655a2 2020
718e3744 2021/* `match ipv6 address prefix-list PREFIX_LIST' */
2022
94f2b392 2023static route_map_result_t
e52702f2 2024route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix,
718e3744 2025 route_map_object_t type, void *object)
2026{
2027 struct prefix_list *plist;
2028
2029 if (type == RMAP_BGP)
2030 {
2031 plist = prefix_list_lookup (AFI_IP6, (char *) rule);
2032 if (plist == NULL)
2033 return RMAP_NOMATCH;
e52702f2 2034
718e3744 2035 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
2036 RMAP_NOMATCH : RMAP_MATCH);
2037 }
2038 return RMAP_NOMATCH;
2039}
2040
94f2b392 2041static void *
fd79ac91 2042route_match_ipv6_address_prefix_list_compile (const char *arg)
718e3744 2043{
2044 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
2045}
2046
94f2b392 2047static void
718e3744 2048route_match_ipv6_address_prefix_list_free (void *rule)
2049{
2050 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2051}
2052
2053struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
2054{
2055 "ipv6 address prefix-list",
2056 route_match_ipv6_address_prefix_list,
2057 route_match_ipv6_address_prefix_list_compile,
2058 route_match_ipv6_address_prefix_list_free
2059};
6b0655a2 2060
718e3744 2061/* `set ipv6 nexthop global IP_ADDRESS' */
2062
2063/* Set nexthop to object. ojbect must be pointer to struct attr. */
94f2b392 2064static route_map_result_t
e52702f2 2065route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix,
718e3744 2066 route_map_object_t type, void *object)
2067{
2068 struct in6_addr *address;
2069 struct bgp_info *bgp_info;
2070
2071 if (type == RMAP_BGP)
2072 {
2073 /* Fetch routemap's rule information. */
2074 address = rule;
2075 bgp_info = object;
e52702f2
QY
2076
2077 /* Set next hop value. */
fb982c25 2078 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = *address;
3f9c7369 2079
718e3744 2080 /* Set nexthop length. */
fb982c25 2081 if (bgp_info->attr->extra->mp_nexthop_len == 0)
801a9bcc 2082 bgp_info->attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369
DS
2083
2084 SET_FLAG(bgp_info->attr->rmap_change_flags,
3811f1e2 2085 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
718e3744 2086 }
2087
2088 return RMAP_OKAY;
2089}
2090
2091/* Route map `ip next-hop' compile function. Given string is converted
2092 to struct in_addr structure. */
94f2b392 2093static void *
fd79ac91 2094route_set_ipv6_nexthop_global_compile (const char *arg)
718e3744 2095{
2096 int ret;
2097 struct in6_addr *address;
2098
2099 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
2100
2101 ret = inet_pton (AF_INET6, arg, address);
2102
2103 if (ret == 0)
2104 {
2105 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2106 return NULL;
2107 }
2108
2109 return address;
2110}
2111
2112/* Free route map's compiled `ip next-hop' value. */
94f2b392 2113static void
718e3744 2114route_set_ipv6_nexthop_global_free (void *rule)
2115{
2116 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2117}
2118
2119/* Route map commands for ip nexthop set. */
2120struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd =
2121{
2122 "ipv6 next-hop global",
2123 route_set_ipv6_nexthop_global,
2124 route_set_ipv6_nexthop_global_compile,
2125 route_set_ipv6_nexthop_global_free
2126};
6b0655a2 2127
161995ea
DS
2128/* Set next-hop preference value. */
2129static route_map_result_t
2130route_set_ipv6_nexthop_prefer_global (void *rule, struct prefix *prefix,
2131 route_map_object_t type, void *object)
2132{
2133 struct bgp_info *bgp_info;
2134 struct peer *peer;
2135
2136 if (type == RMAP_BGP)
2137 {
2138 /* Fetch routemap's rule information. */
2139 bgp_info = object;
2140 peer = bgp_info->peer;
2141
2142 if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
2143 CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
2144 && peer->su_remote
2145 && sockunion_family (peer->su_remote) == AF_INET6)
2146 {
2147 /* Set next hop preference to global */
2148 bgp_info->attr->extra->mp_nexthop_prefer_global = TRUE;
2149 SET_FLAG(bgp_info->attr->rmap_change_flags,
b2e03f7a 2150 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
161995ea 2151 }
b2e03f7a 2152 else
2153 {
2154 bgp_info->attr->extra->mp_nexthop_prefer_global = FALSE;
2155 SET_FLAG(bgp_info->attr->rmap_change_flags,
2156 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
2157 }
161995ea
DS
2158 }
2159 return RMAP_OKAY;
2160}
2161
2162static void *
2163route_set_ipv6_nexthop_prefer_global_compile (const char *arg)
2164{
2165 int *rins = NULL;
2166
2167 rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int));
2168 *rins = 1;
2169
2170 return rins;
2171}
2172
2173/* Free route map's compiled `ip next-hop' value. */
2174static void
2175route_set_ipv6_nexthop_prefer_global_free (void *rule)
2176{
2177 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2178}
2179
2180/* Route map commands for ip nexthop set preferred. */
2181struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd =
2182{
2183 "ipv6 next-hop prefer-global",
2184 route_set_ipv6_nexthop_prefer_global,
2185 route_set_ipv6_nexthop_prefer_global_compile,
2186 route_set_ipv6_nexthop_prefer_global_free
2187};
2188
718e3744 2189/* `set ipv6 nexthop local IP_ADDRESS' */
2190
2191/* Set nexthop to object. ojbect must be pointer to struct attr. */
94f2b392 2192static route_map_result_t
e52702f2 2193route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
718e3744 2194 route_map_object_t type, void *object)
2195{
2196 struct in6_addr *address;
2197 struct bgp_info *bgp_info;
2198
2199 if (type == RMAP_BGP)
2200 {
2201 /* Fetch routemap's rule information. */
2202 address = rule;
2203 bgp_info = object;
e52702f2
QY
2204
2205 /* Set next hop value. */
fb982c25 2206 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = *address;
e52702f2 2207
718e3744 2208 /* Set nexthop length. */
801a9bcc
DS
2209 if (bgp_info->attr->extra->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
2210 bgp_info->attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3f9c7369
DS
2211
2212 SET_FLAG(bgp_info->attr->rmap_change_flags,
3811f1e2 2213 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
718e3744 2214 }
2215
2216 return RMAP_OKAY;
2217}
2218
2219/* Route map `ip nexthop' compile function. Given string is converted
2220 to struct in_addr structure. */
94f2b392 2221static void *
fd79ac91 2222route_set_ipv6_nexthop_local_compile (const char *arg)
718e3744 2223{
2224 int ret;
2225 struct in6_addr *address;
2226
2227 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
2228
2229 ret = inet_pton (AF_INET6, arg, address);
2230
2231 if (ret == 0)
2232 {
2233 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2234 return NULL;
2235 }
2236
2237 return address;
2238}
2239
2240/* Free route map's compiled `ip nexthop' value. */
94f2b392 2241static void
718e3744 2242route_set_ipv6_nexthop_local_free (void *rule)
2243{
2244 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2245}
2246
2247/* Route map commands for ip nexthop set. */
2248struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
2249{
2250 "ipv6 next-hop local",
2251 route_set_ipv6_nexthop_local,
2252 route_set_ipv6_nexthop_local_compile,
2253 route_set_ipv6_nexthop_local_free
2254};
90916ac2
DS
2255
2256/* `set ipv6 nexthop peer-address' */
2257
2258/* Set nexthop to object. ojbect must be pointer to struct attr. */
2259static route_map_result_t
2260route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix,
2261 route_map_object_t type, void *object)
2262{
90916ac2
DS
2263 struct in6_addr peer_address;
2264 struct bgp_info *bgp_info;
2265 struct peer *peer;
90916ac2
DS
2266
2267 if (type == RMAP_BGP)
2268 {
2269 /* Fetch routemap's rule information. */
90916ac2
DS
2270 bgp_info = object;
2271 peer = bgp_info->peer;
2272
2273 if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
2274 CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
2275 && peer->su_remote
2276 && sockunion_family (peer->su_remote) == AF_INET6)
2277 {
6e71194f 2278 peer_address = peer->su_remote->sin6.sin6_addr;
2665d9ae
DS
2279 /* Set next hop value and length in attribute. */
2280 if (IN6_IS_ADDR_LINKLOCAL(&peer_address))
2281 {
2282 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = peer_address;
2283 if (bgp_info->attr->extra->mp_nexthop_len != 32)
2284 bgp_info->attr->extra->mp_nexthop_len = 32;
2285 }
2286 else
2287 {
2288 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = peer_address;
2289 if (bgp_info->attr->extra->mp_nexthop_len == 0)
2290 bgp_info->attr->extra->mp_nexthop_len = 16;
2291 }
2292
90916ac2 2293 }
3f9c7369 2294 else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT))
90916ac2 2295 {
2665d9ae
DS
2296 /* The next hop value will be set as part of packet rewrite.
2297 * Set the flags here to indicate that rewrite needs to be done.
2298 * Also, clear the value - we clear both global and link-local
2299 * nexthops, whether we send one or both is determined elsewhere.
2300 */
3f9c7369
DS
2301 SET_FLAG(bgp_info->attr->rmap_change_flags,
2302 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3f9c7369
DS
2303 /* clear next hop value. */
2304 memset (&((bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global),
2305 0, sizeof (struct in6_addr));
2665d9ae
DS
2306 memset (&((bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local),
2307 0, sizeof (struct in6_addr));
90916ac2
DS
2308 }
2309 }
2310
2311 return RMAP_OKAY;
2312}
2313
2314/* Route map `ip next-hop' compile function. Given string is converted
2315 to struct in_addr structure. */
2316static void *
2317route_set_ipv6_nexthop_peer_compile (const char *arg)
2318{
90916ac2
DS
2319 int *rins = NULL;
2320
2321 rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int));
2322 *rins = 1;
2323
2324 return rins;
2325}
2326
2327/* Free route map's compiled `ip next-hop' value. */
2328static void
2329route_set_ipv6_nexthop_peer_free (void *rule)
2330{
2331 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2332}
2333
2334/* Route map commands for ip nexthop set. */
2335struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd =
2336{
2337 "ipv6 next-hop peer-address",
2338 route_set_ipv6_nexthop_peer,
2339 route_set_ipv6_nexthop_peer_compile,
2340 route_set_ipv6_nexthop_peer_free
2341};
2342
718e3744 2343/* `set vpnv4 nexthop A.B.C.D' */
2344
94f2b392 2345static route_map_result_t
e52702f2 2346route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
718e3744 2347 route_map_object_t type, void *object)
2348{
2349 struct in_addr *address;
2350 struct bgp_info *bgp_info;
2351
2352 if (type == RMAP_BGP)
2353 {
2354 /* Fetch routemap's rule information. */
2355 address = rule;
2356 bgp_info = object;
e52702f2
QY
2357
2358 /* Set next hop value. */
fb982c25 2359 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address;
93b73dfa 2360 (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = 4;
718e3744 2361 }
2362
2363 return RMAP_OKAY;
2364}
2365
94f2b392 2366static void *
fd79ac91 2367route_set_vpnv4_nexthop_compile (const char *arg)
718e3744 2368{
2369 int ret;
2370 struct in_addr *address;
2371
2372 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
2373
2374 ret = inet_aton (arg, address);
2375
2376 if (ret == 0)
2377 {
2378 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2379 return NULL;
2380 }
2381
2382 return address;
2383}
2384
94f2b392 2385static void
718e3744 2386route_set_vpnv4_nexthop_free (void *rule)
2387{
2388 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2389}
2390
2391/* Route map commands for ip nexthop set. */
2392struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd =
2393{
2394 "vpnv4 next-hop",
2395 route_set_vpnv4_nexthop,
2396 route_set_vpnv4_nexthop_compile,
2397 route_set_vpnv4_nexthop_free
2398};
6b0655a2 2399
718e3744 2400/* `set originator-id' */
2401
2402/* For origin set. */
94f2b392 2403static route_map_result_t
718e3744 2404route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
2405{
2406 struct in_addr *address;
2407 struct bgp_info *bgp_info;
2408
e52702f2 2409 if (type == RMAP_BGP)
718e3744 2410 {
2411 address = rule;
2412 bgp_info = object;
e52702f2 2413
718e3744 2414 bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
fb982c25 2415 (bgp_attr_extra_get (bgp_info->attr))->originator_id = *address;
718e3744 2416 }
2417
2418 return RMAP_OKAY;
2419}
2420
2421/* Compile function for originator-id set. */
94f2b392 2422static void *
fd79ac91 2423route_set_originator_id_compile (const char *arg)
718e3744 2424{
2425 int ret;
2426 struct in_addr *address;
2427
2428 address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
2429
2430 ret = inet_aton (arg, address);
2431
2432 if (ret == 0)
2433 {
2434 XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
2435 return NULL;
2436 }
2437
2438 return address;
2439}
2440
2441/* Compile function for originator_id set. */
94f2b392 2442static void
718e3744 2443route_set_originator_id_free (void *rule)
2444{
2445 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
2446}
2447
515e500c 2448/* Set originator-id rule structure. */
e52702f2 2449struct route_map_rule_cmd route_set_originator_id_cmd =
718e3744 2450{
2451 "originator-id",
2452 route_set_originator_id,
2453 route_set_originator_id_compile,
2454 route_set_originator_id_free,
2455};
6b0655a2 2456
718e3744 2457/* Add bgp route map rule. */
94f2b392 2458static int
cdc2d765 2459bgp_route_match_add (struct vty *vty,
518f0eb1
DS
2460 const char *command, const char *arg,
2461 route_map_event_t type)
718e3744 2462{
cdc2d765 2463 VTY_DECLVAR_CONTEXT(route_map_index, index);
718e3744 2464 int ret;
2465
2466 ret = route_map_add_match (index, command, arg);
2467 if (ret)
2468 {
2469 switch (ret)
2470 {
2471 case RMAP_RULE_MISSING:
5e3edbf5 2472 vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
718e3744 2473 return CMD_WARNING;
718e3744 2474 case RMAP_COMPILE_ERROR:
5e3edbf5 2475 vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
718e3744 2476 return CMD_WARNING;
718e3744 2477 }
2478 }
518f0eb1
DS
2479
2480 if (type != RMAP_EVENT_MATCH_ADDED)
2481 {
2482 route_map_upd8_dependency (type, arg, index->map->name);
2483 }
2484
718e3744 2485 return CMD_SUCCESS;
2486}
2487
2488/* Delete bgp route map rule. */
94f2b392 2489static int
cdc2d765 2490bgp_route_match_delete (struct vty *vty,
518f0eb1
DS
2491 const char *command, const char *arg,
2492 route_map_event_t type)
718e3744 2493{
cdc2d765 2494 VTY_DECLVAR_CONTEXT(route_map_index, index);
718e3744 2495 int ret;
ffd0c037 2496 char *dep_name = NULL;
518f0eb1
DS
2497 const char *tmpstr;
2498 char *rmap_name = NULL;
718e3744 2499
518f0eb1
DS
2500 if (type != RMAP_EVENT_MATCH_DELETED)
2501 {
2502 /* ignore the mundane, the types without any dependency */
2503 if (arg == NULL)
2504 {
2505 if ((tmpstr = route_map_get_match_arg(index, command)) != NULL)
2506 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
2507 }
ffd0c037
DS
2508 else
2509 {
2510 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
2511 }
518f0eb1
DS
2512 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
2513 }
2514
2515 ret = route_map_delete_match (index, command, dep_name);
718e3744 2516 if (ret)
2517 {
2518 switch (ret)
2519 {
2520 case RMAP_RULE_MISSING:
5e3edbf5 2521 vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
518f0eb1 2522 break;
718e3744 2523 case RMAP_COMPILE_ERROR:
5e3edbf5 2524 vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
518f0eb1 2525 break;
718e3744 2526 }
ffd0c037 2527 if (dep_name)
518f0eb1
DS
2528 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
2529 if (rmap_name)
2530 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
2531 return CMD_WARNING;
718e3744 2532 }
518f0eb1
DS
2533
2534 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
2535 route_map_upd8_dependency(type, dep_name, rmap_name);
2536
ffd0c037 2537 if (dep_name)
518f0eb1
DS
2538 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
2539 if (rmap_name)
2540 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
2541
718e3744 2542 return CMD_SUCCESS;
2543}
2544
518f0eb1 2545/*
2a3d5731 2546 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
2547 * modifications.
2548 */
94f2b392 2549static void
a6e0d253
DW
2550bgp_route_map_process_peer (const char *rmap_name, struct route_map *map,
2551 struct peer *peer, int afi, int safi,
2552 int route_update)
718e3744 2553{
518f0eb1
DS
2554
2555 int update;
718e3744 2556 struct bgp_filter *filter;
718e3744 2557
518f0eb1
DS
2558 if (!peer || !rmap_name)
2559 return;
2560
2561 filter = &peer->filter[afi][safi];
2562 /*
2563 * in is for non-route-server clients,
518f0eb1
DS
2564 * out is for all peers
2565 */
2566 if (!CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT))
718e3744 2567 {
518f0eb1
DS
2568 if (filter->map[RMAP_IN].name &&
2569 (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0))
718e3744 2570 {
a6e0d253 2571 filter->map[RMAP_IN].map = map;
518f0eb1 2572
fa5f7ad5 2573 if (route_update && peer->status == Established)
518f0eb1
DS
2574 {
2575 if (CHECK_FLAG (peer->af_flags[afi][safi],
2576 PEER_FLAG_SOFT_RECONFIG))
2577 {
3f9c7369 2578 if (bgp_debug_update(peer, NULL, NULL, 1))
518f0eb1
DS
2579 zlog_debug("Processing route_map %s update on "
2580 "peer %s (inbound, soft-reconfig)",
2581 rmap_name, peer->host);
2582
2583 bgp_soft_reconfig_in (peer, afi, safi);
2584 }
2585 else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2586 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2587 {
2588
3f9c7369 2589 if (bgp_debug_update(peer, NULL, NULL, 1))
518f0eb1
DS
2590 zlog_debug("Processing route_map %s update on "
2591 "peer %s (inbound, route-refresh)",
2592 rmap_name, peer->host);
2593 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2594 }
2595 }
718e3744 2596 }
2597 }
2598
518f0eb1 2599 if (CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT))
718e3744 2600 {
518f0eb1
DS
2601 update = 0;
2602
fa5f7ad5 2603 if (update && route_update && peer->status == Established)
518f0eb1
DS
2604 {
2605 if (CHECK_FLAG (peer->af_flags[afi][safi],
2606 PEER_FLAG_SOFT_RECONFIG))
2607 {
3f9c7369 2608 if (bgp_debug_update(peer, NULL, NULL, 1))
518f0eb1
DS
2609 zlog_debug("Processing route_map %s update on "
2610 "peer %s (import, soft-reconfig)",
2611 rmap_name, peer->host);
2612
2613 bgp_soft_reconfig_in (peer, afi, safi);
2614 }
2615 else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2616 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2617 {
3f9c7369 2618 if (bgp_debug_update(peer, NULL, NULL, 1))
518f0eb1
DS
2619 zlog_debug("Processing route_map %s update on "
2620 "peer %s (import, route-refresh)",
2621 rmap_name, peer->host);
2622 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2623 }
2624 /* DD: Else, what else do we do ? Reset peer ? */
718e3744 2625 }
2626 }
2627
3f9c7369
DS
2628 /*
2629 * For outbound, unsuppress and default-originate map change (content or
2630 * map created), merely update the "config" here, the actual route
2631 * announcement happens at the group level.
2632 */
518f0eb1 2633 if (filter->map[RMAP_OUT].name &&
3f9c7369 2634 (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
a6e0d253 2635 filter->map[RMAP_OUT].map = map;
518f0eb1
DS
2636
2637 if (filter->usmap.name &&
2638 (strcmp(rmap_name, filter->usmap.name) == 0))
a6e0d253 2639 filter->usmap.map = map;
3f9c7369
DS
2640
2641 if (peer->default_rmap[afi][safi].name &&
2642 (strcmp (rmap_name, peer->default_rmap[afi][safi].name) == 0))
a6e0d253 2643 peer->default_rmap[afi][safi].map = map;
518f0eb1 2644}
73ac8160 2645
518f0eb1 2646static void
a6e0d253
DW
2647bgp_route_map_update_peer_group(const char *rmap_name, struct route_map *map,
2648 struct bgp *bgp)
518f0eb1
DS
2649{
2650 struct peer_group *group;
2651 struct listnode *node, *nnode;
2652 struct bgp_filter *filter;
2653 int afi, safi;
2654 int direct;
2655
2656 if (!bgp)
2657 return;
2658
2659 /* All the peers have been updated correctly already. This is
2660 * just updating the placeholder data. No real update required.
2661 */
2662 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
2663 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2664 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2665 {
2666 filter = &group->conf->filter[afi][safi];
2667
2668 for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
2669 {
2670 if ((filter->map[direct].name) &&
2671 (strcmp(rmap_name, filter->map[direct].name) == 0))
a6e0d253 2672 filter->map[direct].map = map;
518f0eb1
DS
2673 }
2674
2675 if (filter->usmap.name &&
2676 (strcmp(rmap_name, filter->usmap.name) == 0))
a6e0d253 2677 filter->usmap.map = map;
518f0eb1
DS
2678 }
2679}
2680
a6e0d253
DW
2681/*
2682 * Note that if an extreme number (tens of thousands) of route-maps are in use
2683 * and if bgp has an extreme number of peers, network statements, etc then this
2684 * function can consume a lot of cycles. This is due to this function being
2685 * called for each route-map and within this function we walk the list of peers,
2686 * network statements, etc looking to see if they use this route-map.
2687 */
5fe9f963 2688static void
2689bgp_route_map_process_update (struct bgp *bgp, const char *rmap_name, int route_update)
518f0eb1
DS
2690{
2691 int i;
2692 afi_t afi;
2693 safi_t safi;
2694 struct peer *peer;
2695 struct bgp_node *bn;
2696 struct bgp_static *bgp_static;
518f0eb1 2697 struct listnode *node, *nnode;
a6e0d253 2698 struct route_map *map;
518f0eb1
DS
2699 char buf[INET6_ADDRSTRLEN];
2700
a6e0d253
DW
2701 map = route_map_lookup_by_name (rmap_name);
2702
518f0eb1 2703 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 2704 {
518f0eb1
DS
2705
2706 /* Ignore dummy peer-group structure */
2707 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
2708 continue;
2709
718e3744 2710 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2711 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
518f0eb1
DS
2712 {
2713 /* Ignore inactive AFI/SAFI */
2714 if (! peer->afc[afi][safi])
2715 continue;
2716
3f9c7369 2717 /* process in/out/import/export/default-orig route-maps */
a6e0d253 2718 bgp_route_map_process_peer(rmap_name, map, peer, afi, safi, route_update);
518f0eb1 2719 }
718e3744 2720 }
2721
3f9c7369
DS
2722 /* for outbound/default-orig route-maps, process for groups */
2723 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
2724 route_update, 0);
2725
2726 /* update peer-group config (template) */
a6e0d253 2727 bgp_route_map_update_peer_group(rmap_name, map, bgp);
518f0eb1 2728
518f0eb1
DS
2729 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2730 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2731 {
a6e0d253 2732 /* For table route-map updates. */
518f0eb1
DS
2733 if (bgp->table_map[afi][safi].name &&
2734 (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0))
2735 {
a6e0d253
DW
2736 bgp->table_map[afi][safi].map = map;
2737
16286195 2738 if (BGP_DEBUG (zebra, ZEBRA))
518f0eb1
DS
2739 zlog_debug("Processing route_map %s update on "
2740 "table map", rmap_name);
2741 if (route_update)
2742 bgp_zebra_announce_table(bgp, afi, safi);
2743 }
518f0eb1 2744
a6e0d253
DW
2745 /* For network route-map updates. */
2746 for (bn = bgp_table_top (bgp->route[afi][safi]); bn; bn = bgp_route_next (bn))
2747 if ((bgp_static = bn->info) != NULL)
2748 {
2749 if (bgp_static->rmap.name &&
2750 (strcmp(rmap_name, bgp_static->rmap.name) == 0))
2751 {
2752 bgp_static->rmap.map = map;
2753
2754 if (route_update)
2755 if (!bgp_static->backdoor)
2756 {
2757 if (bgp_debug_zebra(&bn->p))
2758 zlog_debug("Processing route_map %s update on "
2759 "static route %s", rmap_name,
2760 inet_ntop (bn->p.family, &bn->p.u.prefix,
2761 buf, INET6_ADDRSTRLEN));
2762 bgp_static_update (bgp, &bn->p, bgp_static, afi, safi);
2763 }
2764 }
2765 }
2766 }
518f0eb1 2767
718e3744 2768 /* For redistribute route-map updates. */
518f0eb1
DS
2769 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2770 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2771 {
7c8ff89e
DS
2772 struct list *red_list;
2773 struct listnode *node;
2774 struct bgp_redist *red;
2775
2776 red_list = bgp->redist[afi][i];
2777 if (!red_list)
2778 continue;
2779
2780 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
2781 {
2782 if (red->rmap.name &&
2783 (strcmp(rmap_name, red->rmap.name) == 0))
2784 {
a6e0d253 2785 red->rmap.map = map;
7c8ff89e
DS
2786
2787 if (route_update)
2788 {
3f9c7369 2789 if (BGP_DEBUG (zebra, ZEBRA))
7c8ff89e
DS
2790 zlog_debug("Processing route_map %s update on "
2791 "redistributed routes", rmap_name);
2792
2793 bgp_redistribute_resend (bgp, afi, i, red->instance);
2794 }
2795 }
518f0eb1
DS
2796 }
2797 }
518f0eb1
DS
2798}
2799
2800static int
5fe9f963 2801bgp_route_map_process_update_cb (char *rmap_name)
518f0eb1 2802{
5fe9f963 2803 struct listnode *node, *nnode;
2804 struct bgp *bgp;
2805
2806 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
2807 bgp_route_map_process_update(bgp, rmap_name, 1);
2808
65efcfce
LB
2809#if ENABLE_BGP_VNC
2810 zlog_debug("%s: calling vnc_routemap_update", __func__);
2811 vnc_routemap_update(bgp, __func__);
2812#endif
5fe9f963 2813 return 0;
518f0eb1
DS
2814}
2815
2816int
2817bgp_route_map_update_timer(struct thread *thread)
2818{
5fe9f963 2819 bm->t_rmap_update = NULL;
518f0eb1 2820
5fe9f963 2821 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1 2822
518f0eb1
DS
2823 return (0);
2824}
2825
2826static void
ffd0c037 2827bgp_route_map_mark_update (const char *rmap_name)
518f0eb1 2828{
5fe9f963 2829 if (bm->t_rmap_update == NULL)
718e3744 2830 {
5fe9f963 2831 struct listnode *node, *nnode;
2832 struct bgp *bgp;
3f9c7369 2833
5fe9f963 2834 /* rmap_update_timer of 0 means don't do route updates */
2835 if (bm->rmap_update_timer)
2836 {
2837 bm->t_rmap_update =
2838 thread_add_timer(bm->master, bgp_route_map_update_timer, NULL,
2839 bm->rmap_update_timer);
2840
2841 /* Signal the groups that a route-map update event has started */
2842 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
2843 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name, 1, 1);
2844 }
2845 else
2846 {
2847 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
2848 bgp_route_map_process_update(bgp, rmap_name, 0);
65efcfce
LB
2849 #if ENABLE_BGP_VNC
2850 zlog_debug("%s: calling vnc_routemap_update", __func__);
2851 vnc_routemap_update(bgp, __func__);
2852#endif
5fe9f963 2853 }
718e3744 2854 }
2855}
6b0655a2 2856
73ac8160 2857static void
518f0eb1 2858bgp_route_map_add (const char *rmap_name)
73ac8160 2859{
518f0eb1
DS
2860 if (route_map_mark_updated(rmap_name, 0) == 0)
2861 bgp_route_map_mark_update(rmap_name);
73ac8160 2862
518f0eb1 2863 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 2864}
518f0eb1 2865
73ac8160 2866static void
518f0eb1 2867bgp_route_map_delete (const char *rmap_name)
73ac8160 2868{
518f0eb1
DS
2869 if (route_map_mark_updated(rmap_name, 1) == 0)
2870 bgp_route_map_mark_update(rmap_name);
73ac8160 2871
518f0eb1 2872 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 2873}
518f0eb1 2874
73ac8160 2875static void
518f0eb1 2876bgp_route_map_event (route_map_event_t event, const char *rmap_name)
73ac8160 2877{
518f0eb1
DS
2878 if (route_map_mark_updated(rmap_name, 0) == 0)
2879 bgp_route_map_mark_update(rmap_name);
2880
2881 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
2882}
2883
2884
fee0f4c6 2885DEFUN (match_peer,
2886 match_peer_cmd,
6147e2c6 2887 "match peer <A.B.C.D|X:X::X:X>",
fee0f4c6 2888 MATCH_STR
2889 "Match peer address\n"
6e13ed4a
IR
2890 "IP address of peer\n"
2891 "IPv6 address of peer\n")
fee0f4c6 2892{
c500ae40 2893 int idx_ip = 2;
cdc2d765 2894 return bgp_route_match_add (vty, "peer", argv[idx_ip]->arg,
518f0eb1 2895 RMAP_EVENT_MATCH_ADDED);
fee0f4c6 2896}
2897
2898DEFUN (match_peer_local,
f412b39a 2899 match_peer_local_cmd,
fee0f4c6 2900 "match peer local",
2901 MATCH_STR
2902 "Match peer address\n"
2903 "Static or Redistributed routes\n")
2904{
cdc2d765 2905 return bgp_route_match_add (vty, "peer", "local",
518f0eb1 2906 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 2907}
2908
2909DEFUN (no_match_peer,
2910 no_match_peer_cmd,
4c9bd275 2911 "no match peer [<local|A.B.C.D|X:X::X:X>]",
fee0f4c6 2912 NO_STR
2913 MATCH_STR
4c9bd275
DW
2914 "Match peer address\n"
2915 "Static or Redistributed routes\n"
2916 "IP address of peer\n"
2917 "IPv6 address of peer\n")
fee0f4c6 2918{
4c9bd275
DW
2919 int idx_peer = 3;
2920
2921 if (argc <= idx_peer)
cdc2d765 2922 return bgp_route_match_delete (vty, "peer", NULL,
4c9bd275 2923 RMAP_EVENT_MATCH_DELETED);
cdc2d765 2924 return bgp_route_match_delete (vty, "peer", argv[idx_peer]->arg,
518f0eb1 2925 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 2926}
2927
fee0f4c6 2928
4c9bd275 2929/* match probability */
1add115a
VT
2930DEFUN (match_probability,
2931 match_probability_cmd,
6147e2c6 2932 "match probability (0-100)",
1add115a
VT
2933 MATCH_STR
2934 "Match portion of routes defined by percentage value\n"
2935 "Percentage of routes\n")
2936{
c500ae40 2937 int idx_number = 2;
cdc2d765 2938 return bgp_route_match_add (vty, "probability", argv[idx_number]->arg,
518f0eb1 2939 RMAP_EVENT_MATCH_ADDED);
1add115a
VT
2940}
2941
4c9bd275 2942
1add115a
VT
2943DEFUN (no_match_probability,
2944 no_match_probability_cmd,
4c9bd275 2945 "no match probability [(1-99)]",
1add115a
VT
2946 NO_STR
2947 MATCH_STR
4c9bd275
DW
2948 "Match portion of routes defined by percentage value\n"
2949 "Percentage of routes\n")
1add115a 2950{
4c9bd275
DW
2951 int idx_number = 3;
2952 if (argc <= idx_number)
cdc2d765 2953 return bgp_route_match_delete (vty, "probability", NULL,
4c9bd275 2954 RMAP_EVENT_MATCH_DELETED);
cdc2d765 2955 return bgp_route_match_delete (vty, "probability", argv[idx_number]->arg,
518f0eb1 2956 RMAP_EVENT_MATCH_DELETED);
1add115a
VT
2957}
2958
1add115a 2959
f412b39a 2960DEFUN (match_ip_route_source,
c1643bb7 2961 match_ip_route_source_cmd,
6147e2c6 2962 "match ip route-source <(1-199)|(1300-2699)|WORD>",
c1643bb7 2963 MATCH_STR
2964 IP_STR
2965 "Match advertising source address of route\n"
2966 "IP access-list number\n"
2967 "IP access-list number (expanded range)\n"
2968 "IP standard access-list name\n")
2969{
c500ae40 2970 int idx_acl = 3;
cdc2d765 2971 return bgp_route_match_add (vty, "ip route-source", argv[idx_acl]->arg,
518f0eb1 2972 RMAP_EVENT_FILTER_ADDED);
c1643bb7 2973}
2974
4c9bd275 2975
c1643bb7 2976DEFUN (no_match_ip_route_source,
2977 no_match_ip_route_source_cmd,
6de69f83 2978 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
c1643bb7 2979 NO_STR
2980 MATCH_STR
2981 IP_STR
4c9bd275
DW
2982 "Match advertising source address of route\n"
2983 "IP access-list number\n"
2984 "IP access-list number (expanded range)\n"
2985 "IP standard access-list name\n")
c1643bb7 2986{
4c9bd275
DW
2987 int idx_number = 4;
2988 if (argc <= idx_number)
cdc2d765 2989 return bgp_route_match_delete (vty, "ip route-source",
4c9bd275 2990 NULL, RMAP_EVENT_FILTER_DELETED);
cdc2d765 2991 return bgp_route_match_delete (vty, "ip route-source",
4c9bd275 2992 argv[idx_number]->arg, RMAP_EVENT_FILTER_DELETED);
c1643bb7 2993}
2994
c1643bb7 2995
f412b39a 2996DEFUN (match_ip_route_source_prefix_list,
c1643bb7 2997 match_ip_route_source_prefix_list_cmd,
2998 "match ip route-source prefix-list WORD",
2999 MATCH_STR
3000 IP_STR
3001 "Match advertising source address of route\n"
3002 "Match entries of prefix-lists\n"
3003 "IP prefix-list name\n")
3004{
c500ae40 3005 int idx_word = 4;
cdc2d765 3006 return bgp_route_match_add (vty, "ip route-source prefix-list",
c500ae40 3007 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
c1643bb7 3008}
3009
4c9bd275 3010
c1643bb7 3011DEFUN (no_match_ip_route_source_prefix_list,
3012 no_match_ip_route_source_prefix_list_cmd,
4c9bd275 3013 "no match ip route-source prefix-list [WORD]",
c1643bb7 3014 NO_STR
3015 MATCH_STR
3016 IP_STR
3017 "Match advertising source address of route\n"
4c9bd275
DW
3018 "Match entries of prefix-lists\n"
3019 "IP prefix-list name\n")
c1643bb7 3020{
4c9bd275
DW
3021 int idx_word = 5;
3022 if (argc <= idx_word)
cdc2d765 3023 return bgp_route_match_delete (vty, "ip route-source prefix-list",
4c9bd275 3024 NULL, RMAP_EVENT_PLIST_DELETED);
cdc2d765 3025 return bgp_route_match_delete (vty, "ip route-source prefix-list",
4c9bd275 3026 argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
c1643bb7 3027}
3028
c1643bb7 3029
af291c15
DS
3030DEFUN (match_local_pref,
3031 match_local_pref_cmd,
6147e2c6 3032 "match local-preference (0-4294967295)",
af291c15
DS
3033 MATCH_STR
3034 "Match local-preference of route\n"
3035 "Metric value\n")
3036{
c500ae40 3037 int idx_number = 2;
cdc2d765 3038 return bgp_route_match_add (vty, "local-preference", argv[idx_number]->arg,
518f0eb1 3039 RMAP_EVENT_MATCH_ADDED);
af291c15
DS
3040}
3041
4c9bd275 3042
af291c15
DS
3043DEFUN (no_match_local_pref,
3044 no_match_local_pref_cmd,
4c9bd275 3045 "no match local-preference [(0-4294967295)]",
af291c15
DS
3046 NO_STR
3047 MATCH_STR
4c9bd275
DW
3048 "Match local preference of route\n"
3049 "Local preference value\n")
af291c15 3050{
4c9bd275
DW
3051 int idx_localpref = 3;
3052 if (argc <= idx_localpref)
cdc2d765 3053 return bgp_route_match_delete (vty, "local-preference",
4c9bd275 3054 NULL, RMAP_EVENT_MATCH_DELETED);
cdc2d765 3055 return bgp_route_match_delete (vty, "local-preference",
4c9bd275 3056 argv[idx_localpref]->arg,
518f0eb1 3057 RMAP_EVENT_MATCH_DELETED);
af291c15
DS
3058}
3059
af291c15 3060
f412b39a 3061DEFUN (match_community,
718e3744 3062 match_community_cmd,
6147e2c6 3063 "match community <(1-99)|(100-500)|WORD>",
718e3744 3064 MATCH_STR
3065 "Match BGP community list\n"
3066 "Community-list number (standard)\n"
3067 "Community-list number (expanded)\n"
3068 "Community-list name\n")
3069{
c500ae40 3070 int idx_comm_list = 2;
cdc2d765 3071 return bgp_route_match_add (vty, "community", argv[idx_comm_list]->arg,
518f0eb1 3072 RMAP_EVENT_CLIST_ADDED);
718e3744 3073}
3074
f412b39a 3075DEFUN (match_community_exact,
718e3744 3076 match_community_exact_cmd,
6147e2c6 3077 "match community <(1-99)|(100-500)|WORD> exact-match",
718e3744 3078 MATCH_STR
3079 "Match BGP community list\n"
3080 "Community-list number (standard)\n"
3081 "Community-list number (expanded)\n"
3082 "Community-list name\n"
3083 "Do exact matching of communities\n")
3084{
c500ae40 3085 int idx_comm_list = 2;
718e3744 3086 int ret;
3087 char *argstr;
3088
3089 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
c500ae40 3090 strlen (argv[idx_comm_list]->arg) + strlen ("exact-match") + 2);
718e3744 3091
c500ae40 3092 sprintf (argstr, "%s exact-match", argv[idx_comm_list]->arg);
718e3744 3093
cdc2d765 3094 ret = bgp_route_match_add (vty, "community", argstr,
518f0eb1 3095 RMAP_EVENT_CLIST_ADDED);
718e3744 3096
3097 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
3098
3099 return ret;
3100}
3101
3102DEFUN (no_match_community,
3103 no_match_community_cmd,
4c9bd275 3104 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
718e3744 3105 NO_STR
3106 MATCH_STR
4c9bd275
DW
3107 "Match BGP community list\n"
3108 "Community-list number (standard)\n"
3109 "Community-list number (expanded)\n"
3110 "Community-list name\n"
3111 "Do exact matching of communities\n")
718e3744 3112{
cdc2d765 3113 return bgp_route_match_delete (vty, "community", NULL,
518f0eb1 3114 RMAP_EVENT_CLIST_DELETED);
718e3744 3115}
3116
718e3744 3117
718e3744 3118
f412b39a 3119DEFUN (match_ecommunity,
73ffb25b 3120 match_ecommunity_cmd,
6147e2c6 3121 "match extcommunity <(1-99)|(100-500)|WORD>",
73ffb25b 3122 MATCH_STR
3123 "Match BGP/VPN extended community list\n"
3124 "Extended community-list number (standard)\n"
3125 "Extended community-list number (expanded)\n"
3126 "Extended community-list name\n")
3127{
c500ae40 3128 int idx_comm_list = 2;
cdc2d765 3129 return bgp_route_match_add (vty, "extcommunity", argv[idx_comm_list]->arg,
518f0eb1 3130 RMAP_EVENT_ECLIST_ADDED);
73ffb25b 3131}
3132
4c9bd275 3133
73ffb25b 3134DEFUN (no_match_ecommunity,
3135 no_match_ecommunity_cmd,
4c9bd275 3136 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
73ffb25b 3137 NO_STR
3138 MATCH_STR
4c9bd275
DW
3139 "Match BGP/VPN extended community list\n"
3140 "Extended community-list number (standard)\n"
3141 "Extended community-list number (expanded)\n"
3142 "Extended community-list name\n")
73ffb25b 3143{
cdc2d765 3144 return bgp_route_match_delete (vty, "extcommunity", NULL,
518f0eb1 3145 RMAP_EVENT_ECLIST_DELETED);
73ffb25b 3146}
3147
73ffb25b 3148
718e3744 3149DEFUN (match_aspath,
3150 match_aspath_cmd,
3151 "match as-path WORD",
3152 MATCH_STR
3153 "Match BGP AS path list\n"
3154 "AS path access-list name\n")
3155{
c500ae40 3156 int idx_word = 2;
cdc2d765 3157 return bgp_route_match_add (vty, "as-path", argv[idx_word]->arg,
518f0eb1 3158 RMAP_EVENT_ASLIST_ADDED);
718e3744 3159}
3160
4c9bd275 3161
718e3744 3162DEFUN (no_match_aspath,
3163 no_match_aspath_cmd,
4c9bd275 3164 "no match as-path [WORD]",
718e3744 3165 NO_STR
3166 MATCH_STR
4c9bd275
DW
3167 "Match BGP AS path list\n"
3168 "AS path access-list name\n")
718e3744 3169{
cdc2d765 3170 return bgp_route_match_delete (vty, "as-path", NULL,
518f0eb1 3171 RMAP_EVENT_ASLIST_DELETED);
718e3744 3172}
3173
718e3744 3174
3175DEFUN (match_origin,
3176 match_origin_cmd,
6147e2c6 3177 "match origin <egp|igp|incomplete>",
718e3744 3178 MATCH_STR
3179 "BGP origin code\n"
3180 "remote EGP\n"
3181 "local IGP\n"
3182 "unknown heritage\n")
3183{
c500ae40
DW
3184 int idx_origin = 2;
3185 if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
cdc2d765 3186 return bgp_route_match_add (vty, "origin", "igp",
518f0eb1 3187 RMAP_EVENT_MATCH_ADDED);
c500ae40 3188 if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
cdc2d765 3189 return bgp_route_match_add (vty, "origin", "egp",
518f0eb1 3190 RMAP_EVENT_MATCH_ADDED);
c500ae40 3191 if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
cdc2d765 3192 return bgp_route_match_add (vty, "origin", "incomplete",
518f0eb1 3193 RMAP_EVENT_MATCH_ADDED);
718e3744 3194
3195 return CMD_WARNING;
3196}
3197
4c9bd275 3198
718e3744 3199DEFUN (no_match_origin,
3200 no_match_origin_cmd,
4c9bd275 3201 "no match origin [<egp|igp|incomplete>]",
718e3744 3202 NO_STR
3203 MATCH_STR
4c9bd275
DW
3204 "BGP origin code\n"
3205 "remote EGP\n"
3206 "local IGP\n"
3207 "unknown heritage\n")
718e3744 3208{
cdc2d765 3209 return bgp_route_match_delete (vty, "origin", NULL,
518f0eb1 3210 RMAP_EVENT_MATCH_DELETED);
718e3744 3211}
3212
af5cd0a5 3213DEFUN (set_ip_nexthop_peer,
3214 set_ip_nexthop_peer_cmd,
3215 "set ip next-hop peer-address",
3216 SET_STR
3217 IP_STR
3218 "Next hop address\n"
3219 "Use peer address (for BGP only)\n")
3220{
cdc2d765
DL
3221 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3222 "ip next-hop", "peer-address");
af5cd0a5 3223}
3224
316e074d
DS
3225DEFUN (set_ip_nexthop_unchanged,
3226 set_ip_nexthop_unchanged_cmd,
3227 "set ip next-hop unchanged",
3228 SET_STR
3229 IP_STR
3230 "Next hop address\n"
3231 "Don't modify existing Next hop address\n")
3232{
cdc2d765
DL
3233 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3234 "ip next-hop", "unchanged");
718e3744 3235}
3236
718e3744 3237
3238DEFUN (set_local_pref,
3239 set_local_pref_cmd,
6147e2c6 3240 "set local-preference (0-4294967295)",
718e3744 3241 SET_STR
3242 "BGP local preference path attribute\n"
3243 "Preference value\n")
3244{
c500ae40 3245 int idx_number = 2;
cdc2d765
DL
3246 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3247 "local-preference", argv[idx_number]->arg);
718e3744 3248}
3249
4c9bd275 3250
718e3744 3251DEFUN (no_set_local_pref,
3252 no_set_local_pref_cmd,
4c9bd275 3253 "no set local-preference [(0-4294967295)]",
718e3744 3254 NO_STR
3255 SET_STR
4c9bd275
DW
3256 "BGP local preference path attribute\n"
3257 "Preference value\n")
718e3744 3258{
4c9bd275
DW
3259 int idx_localpref = 3;
3260 if (argc <= idx_localpref)
cdc2d765
DL
3261 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3262 "local-preference", NULL);
3263 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3264 "local-preference", argv[idx_localpref]->arg);
718e3744 3265}
3266
718e3744 3267
3268DEFUN (set_weight,
3269 set_weight_cmd,
6147e2c6 3270 "set weight (0-4294967295)",
718e3744 3271 SET_STR
3272 "BGP weight for routing table\n"
3273 "Weight value\n")
3274{
c500ae40 3275 int idx_number = 2;
cdc2d765
DL
3276 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "weight",
3277 argv[idx_number]->arg);
718e3744 3278}
3279
4c9bd275 3280
718e3744 3281DEFUN (no_set_weight,
3282 no_set_weight_cmd,
4c9bd275 3283 "no set weight [(0-4294967295)]",
718e3744 3284 NO_STR
3285 SET_STR
4c9bd275
DW
3286 "BGP weight for routing table\n"
3287 "Weight value\n")
718e3744 3288{
4c9bd275
DW
3289 int idx_weight = 3;
3290 if (argc <= idx_weight)
cdc2d765
DL
3291 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3292 "weight", NULL);
3293 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "weight",
3294 argv[idx_weight]->arg);
718e3744 3295}
3296
718e3744 3297
12dcf78e
QY
3298DEFUN (set_aspath_prepend_asn,
3299 set_aspath_prepend_asn_cmd,
3300 "set as-path prepend (1-4294967295)...",
718e3744 3301 SET_STR
841f7a57 3302 "Transform BGP AS_PATH attribute\n"
718e3744 3303 "Prepend to the as-path\n"
12dcf78e 3304 "AS number\n")
718e3744 3305{
58749582 3306 int idx_asn = 3;
718e3744 3307 int ret;
3308 char *str;
3309
58749582 3310 str = argv_concat (argv, argc, idx_asn);
cdc2d765
DL
3311 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3312 "as-path prepend", str);
718e3744 3313 XFREE (MTYPE_TMP, str);
3314
3315 return ret;
3316}
3317
12dcf78e
QY
3318DEFUN (set_aspath_prepend_lastas,
3319 set_aspath_prepend_lastas_cmd,
3320 "set as-path prepend last-as (1-10)",
3321 SET_STR
3322 "Transform BGP AS_PATH attribute\n"
3323 "Prepend to the as-path\n"
3324 "Use the peer's AS-number\n"
3325 "Number of times to insert")
3326{
3327 return set_aspath_prepend_asn (self, vty, argc, argv);
3328}
bc3dd427 3329
718e3744 3330DEFUN (no_set_aspath_prepend,
3331 no_set_aspath_prepend_cmd,
a4b2b610 3332 "no set as-path prepend [(1-4294967295)]",
718e3744 3333 NO_STR
3334 SET_STR
841f7a57 3335 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
3336 "Prepend to the as-path\n"
3337 "AS number\n")
718e3744 3338{
58749582 3339 int idx_asn = 4;
a7f93f3e
DO
3340 int ret;
3341 char *str;
3342
58749582 3343 str = argv_concat (argv, argc, idx_asn);
cdc2d765
DL
3344 ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3345 "as-path prepend", str);
a7f93f3e
DO
3346 XFREE (MTYPE_TMP, str);
3347 return ret;
718e3744 3348}
3349
718e3744 3350
841f7a57
DO
3351DEFUN (set_aspath_exclude,
3352 set_aspath_exclude_cmd,
a4b2b610 3353 "set as-path exclude (1-4294967295)...",
841f7a57
DO
3354 SET_STR
3355 "Transform BGP AS-path attribute\n"
3356 "Exclude from the as-path\n"
3357 "AS number\n")
3358{
58749582 3359 int idx_asn = 3;
841f7a57
DO
3360 int ret;
3361 char *str;
3362
58749582 3363 str = argv_concat (argv, argc, idx_asn);
cdc2d765
DL
3364 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3365 "as-path exclude", str);
841f7a57
DO
3366 XFREE (MTYPE_TMP, str);
3367 return ret;
3368}
3369
3370DEFUN (no_set_aspath_exclude,
3371 no_set_aspath_exclude_cmd,
a4b2b610 3372 "no set as-path exclude (1-4294967295)...",
841f7a57
DO
3373 NO_STR
3374 SET_STR
3375 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
3376 "Exclude from the as-path\n"
3377 "AS number\n")
841f7a57 3378{
58749582 3379 int idx_asn = 4;
841f7a57
DO
3380 int ret;
3381 char *str;
3382
58749582 3383 str = argv_concat (argv, argc, idx_asn);
cdc2d765
DL
3384 ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3385 "as-path exclude", str);
841f7a57
DO
3386 XFREE (MTYPE_TMP, str);
3387 return ret;
3388}
3389
841f7a57 3390
718e3744 3391DEFUN (set_community,
3392 set_community_cmd,
e961923c 3393 "set community AA:NN...",
718e3744 3394 SET_STR
3395 "BGP community attribute\n"
859d388e 3396 COMMUNITY_VAL_STR)
718e3744 3397{
58749582 3398 int idx_aa_nn = 2;
718e3744 3399 int i;
3400 int first = 0;
3401 int additive = 0;
3402 struct buffer *b;
3403 struct community *com = NULL;
3404 char *str;
3405 char *argstr;
3406 int ret;
3407
3408 b = buffer_new (1024);
3409
58749582 3410 for (i = idx_aa_nn; i < argc; i++)
718e3744 3411 {
4dcadbef 3412 if (strncmp (argv[i]->arg, "additive", strlen (argv[i]->arg)) == 0)
718e3744 3413 {
3414 additive = 1;
3415 continue;
3416 }
3417
3418 if (first)
3419 buffer_putc (b, ' ');
3420 else
3421 first = 1;
3422
4dcadbef 3423 if (strncmp (argv[i]->arg, "internet", strlen (argv[i]->arg)) == 0)
718e3744 3424 {
3425 buffer_putstr (b, "internet");
3426 continue;
3427 }
4dcadbef 3428 if (strncmp (argv[i]->arg, "local-AS", strlen (argv[i]->arg)) == 0)
718e3744 3429 {
3430 buffer_putstr (b, "local-AS");
3431 continue;
3432 }
4dcadbef
DW
3433 if (strncmp (argv[i]->arg, "no-a", strlen ("no-a")) == 0
3434 && strncmp (argv[i]->arg, "no-advertise", strlen (argv[i]->arg)) == 0)
718e3744 3435 {
3436 buffer_putstr (b, "no-advertise");
3437 continue;
3438 }
4dcadbef
DW
3439 if (strncmp (argv[i]->arg, "no-e", strlen ("no-e"))== 0
3440 && strncmp (argv[i]->arg, "no-export", strlen (argv[i]->arg)) == 0)
718e3744 3441 {
3442 buffer_putstr (b, "no-export");
3443 continue;
3444 }
4dcadbef 3445 buffer_putstr (b, argv[i]->arg);
718e3744 3446 }
3447 buffer_putc (b, '\0');
3448
3449 /* Fetch result string then compile it to communities attribute. */
3450 str = buffer_getstr (b);
3451 buffer_free (b);
3452
3453 if (str)
3454 {
3455 com = community_str2com (str);
3b8b1855 3456 XFREE (MTYPE_TMP, str);
718e3744 3457 }
3458
3459 /* Can't compile user input into communities attribute. */
3460 if (! com)
3461 {
3462 vty_out (vty, "%% Malformed communities attribute%s", VTY_NEWLINE);
3463 return CMD_WARNING;
3464 }
3465
3466 /* Set communites attribute string. */
3467 str = community_str (com);
3468
3469 if (additive)
3470 {
3471 argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
3472 strcpy (argstr, str);
3473 strcpy (argstr + strlen (str), " additive");
cdc2d765
DL
3474 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3475 "community", argstr);
718e3744 3476 XFREE (MTYPE_TMP, argstr);
3477 }
3478 else
cdc2d765
DL
3479 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3480 "community", str);
718e3744 3481
3482 community_free (com);
3483
3484 return ret;
3485}
3486
3487DEFUN (set_community_none,
3488 set_community_none_cmd,
3489 "set community none",
3490 SET_STR
3491 "BGP community attribute\n"
3492 "No community attribute\n")
3493{
cdc2d765
DL
3494 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "community",
3495 "none");
718e3744 3496}
3497
3498DEFUN (no_set_community,
3499 no_set_community_cmd,
a4b2b610 3500 "no set community AA:NN...",
718e3744 3501 NO_STR
3502 SET_STR
d7fa34c1
QY
3503 "BGP community attribute\n"
3504 COMMUNITY_VAL_STR)
718e3744 3505{
cdc2d765
DL
3506 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3507 "community", NULL);
718e3744 3508}
3509
718e3744 3510
718e3744 3511
3512DEFUN (set_community_delete,
3513 set_community_delete_cmd,
6147e2c6 3514 "set comm-list <(1-99)|(100-500)|WORD> delete",
718e3744 3515 SET_STR
3516 "set BGP community list (for deletion)\n"
3517 "Community-list number (standard)\n"
5e3edbf5 3518 "Community-list number (expanded)\n"
718e3744 3519 "Community-list name\n"
3520 "Delete matching communities\n")
3521{
c500ae40 3522 int idx_comm_list = 2;
718e3744 3523 char *str;
3524
c500ae40
DW
3525 str = XCALLOC (MTYPE_TMP, strlen (argv[idx_comm_list]->arg) + strlen (" delete") + 1);
3526 strcpy (str, argv[idx_comm_list]->arg);
3527 strcpy (str + strlen (argv[idx_comm_list]->arg), " delete");
718e3744 3528
cdc2d765 3529 generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "comm-list", str);
718e3744 3530
3531 XFREE (MTYPE_TMP, str);
3532 return CMD_SUCCESS;
3533}
3534
3535DEFUN (no_set_community_delete,
3536 no_set_community_delete_cmd,
a4b2b610 3537 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
718e3744 3538 NO_STR
3539 SET_STR
d7fa34c1
QY
3540 "set BGP community list (for deletion)\n"
3541 "Community-list number (standard)\n"
3542 "Community-list number (expanded)\n"
3543 "Community-list name\n"
3544 "Delete matching communities\n")
718e3744 3545{
cdc2d765
DL
3546 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3547 "comm-list", NULL);
718e3744 3548}
3549
718e3744 3550
3551DEFUN (set_ecommunity_rt,
3552 set_ecommunity_rt_cmd,
a4b2b610 3553 "set extcommunity rt ASN:nn_or_IP-address:nn...",
718e3744 3554 SET_STR
3555 "BGP extended community attribute\n"
e6b6a564 3556 "Route Target extended community\n"
718e3744 3557 "VPN extended community\n")
3558{
58749582 3559 int idx_asn_nn = 3;
718e3744 3560 int ret;
3561 char *str;
3562
58749582 3563 str = argv_concat (argv, argc, idx_asn_nn);
cdc2d765
DL
3564 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3565 "extcommunity rt", str);
718e3744 3566 XFREE (MTYPE_TMP, str);
3567
3568 return ret;
3569}
3570
3571DEFUN (no_set_ecommunity_rt,
3572 no_set_ecommunity_rt_cmd,
a4b2b610 3573 "no set extcommunity rt ASN:nn_or_IP-address:nn...",
718e3744 3574 NO_STR
3575 SET_STR
3576 "BGP extended community attribute\n"
3a2d747c
QY
3577 "Route Target extended community\n"
3578 "VPN extended community\n")
718e3744 3579{
cdc2d765
DL
3580 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3581 "extcommunity rt", NULL);
718e3744 3582}
3583
718e3744 3584
3585DEFUN (set_ecommunity_soo,
3586 set_ecommunity_soo_cmd,
a4b2b610 3587 "set extcommunity soo ASN:nn_or_IP-address:nn...",
718e3744 3588 SET_STR
3589 "BGP extended community attribute\n"
3590 "Site-of-Origin extended community\n"
3591 "VPN extended community\n")
3592{
58749582 3593 int idx_asn_nn = 3;
718e3744 3594 int ret;
3595 char *str;
3596
58749582 3597 str = argv_concat (argv, argc, idx_asn_nn);
cdc2d765
DL
3598 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3599 "extcommunity soo", str);
718e3744 3600 XFREE (MTYPE_TMP, str);
3601 return ret;
3602}
3603
a4b2b610 3604
718e3744 3605DEFUN (no_set_ecommunity_soo,
3606 no_set_ecommunity_soo_cmd,
a4b2b610 3607 "no set extcommunity soo ASN:nn_or_IP-address:nn...",
718e3744 3608 NO_STR
3609 SET_STR
3610 "BGP extended community attribute\n"
3a2d747c
QY
3611 "Site-of-Origin extended community\n"
3612 "VPN extended community\n")
718e3744 3613{
cdc2d765
DL
3614 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3615 "extcommunity soo", NULL);
718e3744 3616}
3617
718e3744 3618
3619DEFUN (set_origin,
3620 set_origin_cmd,
6147e2c6 3621 "set origin <egp|igp|incomplete>",
718e3744 3622 SET_STR
3623 "BGP origin code\n"
3624 "remote EGP\n"
3625 "local IGP\n"
3626 "unknown heritage\n")
3627{
c500ae40
DW
3628 int idx_origin = 2;
3629 if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
cdc2d765
DL
3630 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
3631 "igp");
c500ae40 3632 if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
cdc2d765
DL
3633 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
3634 "egp");
c500ae40 3635 if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
cdc2d765
DL
3636 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
3637 "incomplete");
718e3744 3638
3639 return CMD_WARNING;
3640}
3641
a4b2b610 3642
718e3744 3643DEFUN (no_set_origin,
3644 no_set_origin_cmd,
a4b2b610 3645 "no set origin [<egp|igp|incomplete>]",
718e3744 3646 NO_STR
3647 SET_STR
d7fa34c1
QY
3648 "BGP origin code\n"
3649 "remote EGP\n"
3650 "local IGP\n"
3651 "unknown heritage\n")
718e3744 3652{
cdc2d765
DL
3653 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "origin",
3654 NULL);
718e3744 3655}
3656
718e3744 3657
3658DEFUN (set_atomic_aggregate,
3659 set_atomic_aggregate_cmd,
3660 "set atomic-aggregate",
3661 SET_STR
3662 "BGP atomic aggregate attribute\n" )
3663{
cdc2d765
DL
3664 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3665 "atomic-aggregate", NULL);
718e3744 3666}
3667
3668DEFUN (no_set_atomic_aggregate,
3669 no_set_atomic_aggregate_cmd,
3670 "no set atomic-aggregate",
3671 NO_STR
3672 SET_STR
3673 "BGP atomic aggregate attribute\n" )
3674{
cdc2d765
DL
3675 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3676 "atomic-aggregate", NULL);
718e3744 3677}
3678
3679DEFUN (set_aggregator_as,
3680 set_aggregator_as_cmd,
9ccf14f7 3681 "set aggregator as (1-4294967295) A.B.C.D",
718e3744 3682 SET_STR
3683 "BGP aggregator attribute\n"
3684 "AS number of aggregator\n"
3685 "AS number\n"
3686 "IP address of aggregator\n")
3687{
c500ae40
DW
3688 int idx_number = 3;
3689 int idx_ipv4 = 4;
718e3744 3690 int ret;
718e3744 3691 struct in_addr address;
718e3744 3692 char *argstr;
e52702f2 3693
c500ae40 3694 ret = inet_aton (argv[idx_ipv4]->arg, &address);
718e3744 3695 if (ret == 0)
3696 {
3697 vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
3698 return CMD_WARNING;
3699 }
3700
3701 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
c500ae40 3702 strlen (argv[idx_number]->arg) + strlen (argv[idx_ipv4]->arg) + 2);
718e3744 3703
c500ae40 3704 sprintf (argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
718e3744 3705
cdc2d765
DL
3706 ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3707 "aggregator as", argstr);
718e3744 3708
3709 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
3710
3711 return ret;
3712}
3713
a4b2b610 3714
718e3744 3715DEFUN (no_set_aggregator_as,
3716 no_set_aggregator_as_cmd,
a4b2b610 3717 "no set aggregator as [(1-4294967295) A.B.C.D]",
718e3744 3718 NO_STR
3719 SET_STR
3720 "BGP aggregator attribute\n"
a4b2b610
DW
3721 "AS number of aggregator\n"
3722 "AS number\n"
3723 "IP address of aggregator\n")
718e3744 3724{
a4b2b610
DW
3725 int idx_asn = 4;
3726 int idx_ip = 5;
718e3744 3727 int ret;
718e3744 3728 struct in_addr address;
718e3744 3729 char *argstr;
3730
a4b2b610 3731 if (argc <= idx_asn)
cdc2d765
DL
3732 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3733 "aggregator as", NULL);
e52702f2 3734
a4b2b610 3735 ret = inet_aton (argv[idx_ip]->arg, &address);
718e3744 3736 if (ret == 0)
3737 {
3738 vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
3739 return CMD_WARNING;
3740 }
3741
3742 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
a4b2b610 3743 strlen (argv[idx_asn]->arg) + strlen (argv[idx_ip]->arg) + 2);
718e3744 3744
a4b2b610 3745 sprintf (argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
718e3744 3746
cdc2d765
DL
3747 ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3748 "aggregator as", argstr);
718e3744 3749
3750 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
3751
3752 return ret;
3753}
3754
f412b39a 3755DEFUN (match_ipv6_next_hop,
718e3744 3756 match_ipv6_next_hop_cmd,
3757 "match ipv6 next-hop X:X::X:X",
3758 MATCH_STR
3759 IPV6_STR
3760 "Match IPv6 next-hop address of route\n"
3761 "IPv6 address of next hop\n")
3762{
c500ae40 3763 int idx_ipv6 = 3;
cdc2d765 3764 return bgp_route_match_add (vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
518f0eb1 3765 RMAP_EVENT_MATCH_ADDED);
718e3744 3766}
3767
3768DEFUN (no_match_ipv6_next_hop,
3769 no_match_ipv6_next_hop_cmd,
3770 "no match ipv6 next-hop X:X::X:X",
3771 NO_STR
3772 MATCH_STR
3773 IPV6_STR
3774 "Match IPv6 next-hop address of route\n"
3775 "IPv6 address of next hop\n")
3776{
c500ae40 3777 int idx_ipv6 = 4;
cdc2d765 3778 return bgp_route_match_delete (vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
518f0eb1 3779 RMAP_EVENT_MATCH_DELETED);
718e3744 3780}
3781
718e3744 3782
90916ac2
DS
3783DEFUN (set_ipv6_nexthop_peer,
3784 set_ipv6_nexthop_peer_cmd,
3785 "set ipv6 next-hop peer-address",
3786 SET_STR
3787 IPV6_STR
3788 "Next hop address\n"
3789 "Use peer address (for BGP only)\n")
3790{
cdc2d765
DL
3791 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3792 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
3793}
3794
3795DEFUN (no_set_ipv6_nexthop_peer,
3796 no_set_ipv6_nexthop_peer_cmd,
3797 "no set ipv6 next-hop peer-address",
3798 NO_STR
3799 SET_STR
3800 IPV6_STR
3801 "IPv6 next-hop address\n"
161995ea 3802 "Use peer address (for BGP only)\n")
90916ac2 3803{
cdc2d765
DL
3804 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3805 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
3806}
3807
161995ea
DS
3808DEFUN (set_ipv6_nexthop_prefer_global,
3809 set_ipv6_nexthop_prefer_global_cmd,
3810 "set ipv6 next-hop prefer-global",
3811 SET_STR
3812 IPV6_STR
3813 "IPv6 next-hop address\n"
3814 "Prefer global over link-local if both exist\n")
3815{
cdc2d765
DL
3816 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3817 "ipv6 next-hop prefer-global", NULL);;
161995ea
DS
3818}
3819
3820DEFUN (no_set_ipv6_nexthop_prefer_global,
3821 no_set_ipv6_nexthop_prefer_global_cmd,
3822 "no set ipv6 next-hop prefer-global",
3823 NO_STR
3824 SET_STR
3825 IPV6_STR
3826 "IPv6 next-hop address\n"
3827 "Prefer global over link-local if both exist\n")
3828{
cdc2d765
DL
3829 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3830 "ipv6 next-hop prefer-global", NULL);
161995ea
DS
3831}
3832
718e3744 3833DEFUN (set_ipv6_nexthop_global,
3834 set_ipv6_nexthop_global_cmd,
3835 "set ipv6 next-hop global X:X::X:X",
3836 SET_STR
3837 IPV6_STR
3838 "IPv6 next-hop address\n"
3839 "IPv6 global address\n"
3840 "IPv6 address of next hop\n")
3841{
c500ae40 3842 int idx_ipv6 = 4;
bf8b3d27
DS
3843 struct in6_addr addr;
3844 int ret;
3845
c500ae40 3846 ret = inet_pton (AF_INET6, argv[idx_ipv6]->arg, &addr);
bf8b3d27
DS
3847 if (!ret)
3848 {
3849 vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
3850 return CMD_WARNING;
3851 }
3852 if (IN6_IS_ADDR_UNSPECIFIED(&addr) ||
3853 IN6_IS_ADDR_LOOPBACK(&addr) ||
3854 IN6_IS_ADDR_MULTICAST(&addr) ||
3855 IN6_IS_ADDR_LINKLOCAL(&addr))
3856 {
3857 vty_out (vty, "%% Invalid global nexthop address%s", VTY_NEWLINE);
3858 return CMD_WARNING;
3859 }
3860
cdc2d765
DL
3861 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3862 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 3863}
3864
a4b2b610 3865
718e3744 3866DEFUN (no_set_ipv6_nexthop_global,
3867 no_set_ipv6_nexthop_global_cmd,
a4b2b610 3868 "no set ipv6 next-hop global X:X::X:X",
718e3744 3869 NO_STR
3870 SET_STR
3871 IPV6_STR
3872 "IPv6 next-hop address\n"
a4b2b610
DW
3873 "IPv6 global address\n"
3874 "IPv6 address of next hop\n")
718e3744 3875{
a4b2b610
DW
3876 int idx_ipv6 = 5;
3877 if (argc <= idx_ipv6)
cdc2d765
DL
3878 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3879 "ipv6 next-hop global", NULL);
3880 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3881 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 3882}
718e3744 3883
3884DEFUN (set_vpnv4_nexthop,
3885 set_vpnv4_nexthop_cmd,
3886 "set vpnv4 next-hop A.B.C.D",
3887 SET_STR
3888 "VPNv4 information\n"
3889 "VPNv4 next-hop address\n"
3890 "IP address of next hop\n")
3891{
c500ae40 3892 int idx_ipv4 = 3;
cdc2d765
DL
3893 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3894 "vpnv4 next-hop", argv[idx_ipv4]->arg);
718e3744 3895}
3896
a4b2b610 3897
718e3744 3898DEFUN (no_set_vpnv4_nexthop,
3899 no_set_vpnv4_nexthop_cmd,
a4b2b610 3900 "no set vpnv4 next-hop [A.B.C.D]",
718e3744 3901 NO_STR
3902 SET_STR
3903 "VPNv4 information\n"
a4b2b610
DW
3904 "VPNv4 next-hop address\n"
3905 "IP address of next hop\n")
718e3744 3906{
a4b2b610
DW
3907 int idx_ipv4 = 4;
3908 if (argc <= idx_ipv4)
cdc2d765
DL
3909 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3910 "vpnv4 next-hop", NULL);
3911 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3912 "vpnv4 next-hop", argv[idx_ipv4]->arg);
718e3744 3913}
3914
718e3744 3915
3916DEFUN (set_originator_id,
3917 set_originator_id_cmd,
3918 "set originator-id A.B.C.D",
3919 SET_STR
3920 "BGP originator ID attribute\n"
3921 "IP address of originator\n")
3922{
c500ae40 3923 int idx_ipv4 = 2;
cdc2d765
DL
3924 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
3925 "originator-id", argv[idx_ipv4]->arg);
718e3744 3926}
3927
4c9bd275 3928
718e3744 3929DEFUN (no_set_originator_id,
3930 no_set_originator_id_cmd,
4c9bd275 3931 "no set originator-id [A.B.C.D]",
718e3744 3932 NO_STR
3933 SET_STR
4c9bd275
DW
3934 "BGP originator ID attribute\n"
3935 "IP address of originator\n")
718e3744 3936{
4c9bd275
DW
3937 int idx_id = 3;
3938 if (argc < idx_id)
cdc2d765
DL
3939 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3940 "originator-id", NULL);
3941 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
3942 "originator-id", argv[idx_id]->arg);
718e3744 3943}
3944
718e3744 3945
718e3744 3946/* Initialization of route map. */
3947void
94f2b392 3948bgp_route_map_init (void)
718e3744 3949{
3950 route_map_init ();
b2575bc0 3951
73ac8160
DS
3952 route_map_add_hook (bgp_route_map_add);
3953 route_map_delete_hook (bgp_route_map_delete);
3954 route_map_event_hook (bgp_route_map_event);
718e3744 3955
82f97584
DW
3956 route_map_match_interface_hook (generic_match_add);
3957 route_map_no_match_interface_hook (generic_match_delete);
3958
3959 route_map_match_ip_address_hook (generic_match_add);
3960 route_map_no_match_ip_address_hook (generic_match_delete);
3961
3962 route_map_match_ip_address_prefix_list_hook (generic_match_add);
3963 route_map_no_match_ip_address_prefix_list_hook (generic_match_delete);
3964
3965 route_map_match_ip_next_hop_hook (generic_match_add);
3966 route_map_no_match_ip_next_hop_hook (generic_match_delete);
3967
3968 route_map_match_ip_next_hop_prefix_list_hook (generic_match_add);
3969 route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete);
3970
3971 route_map_match_ipv6_address_hook (generic_match_add);
3972 route_map_no_match_ipv6_address_hook (generic_match_delete);
3973
3974 route_map_match_ipv6_address_prefix_list_hook (generic_match_add);
3975 route_map_no_match_ipv6_address_prefix_list_hook (generic_match_delete);
3976
3977 route_map_match_metric_hook (generic_match_add);
3978 route_map_no_match_metric_hook (generic_match_delete);
3979
3980 route_map_match_tag_hook (generic_match_add);
3981 route_map_no_match_tag_hook (generic_match_delete);
3982
3983 route_map_set_ip_nexthop_hook (generic_set_add);
3984 route_map_no_set_ip_nexthop_hook (generic_set_delete);
3985
3986 route_map_set_ipv6_nexthop_local_hook (generic_set_add);
3987 route_map_no_set_ipv6_nexthop_local_hook (generic_set_delete);
3988
3989 route_map_set_metric_hook (generic_set_add);
3990 route_map_no_set_metric_hook (generic_set_delete);
3991
3992 route_map_set_tag_hook (generic_set_add);
3993 route_map_no_set_tag_hook (generic_set_delete);
3994
fee0f4c6 3995 route_map_install_match (&route_match_peer_cmd);
af291c15 3996 route_map_install_match (&route_match_local_pref_cmd);
718e3744 3997 route_map_install_match (&route_match_ip_address_cmd);
3998 route_map_install_match (&route_match_ip_next_hop_cmd);
c1643bb7 3999 route_map_install_match (&route_match_ip_route_source_cmd);
718e3744 4000 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
4001 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
c1643bb7 4002 route_map_install_match (&route_match_ip_route_source_prefix_list_cmd);
718e3744 4003 route_map_install_match (&route_match_aspath_cmd);
4004 route_map_install_match (&route_match_community_cmd);
73ffb25b 4005 route_map_install_match (&route_match_ecommunity_cmd);
af291c15 4006 route_map_install_match (&route_match_local_pref_cmd);
718e3744 4007 route_map_install_match (&route_match_metric_cmd);
4008 route_map_install_match (&route_match_origin_cmd);
1add115a 4009 route_map_install_match (&route_match_probability_cmd);
bc413143 4010 route_map_install_match (&route_match_interface_cmd);
0d9551dc 4011 route_map_install_match (&route_match_tag_cmd);
718e3744 4012
4013 route_map_install_set (&route_set_ip_nexthop_cmd);
4014 route_map_install_set (&route_set_local_pref_cmd);
4015 route_map_install_set (&route_set_weight_cmd);
4016 route_map_install_set (&route_set_metric_cmd);
4017 route_map_install_set (&route_set_aspath_prepend_cmd);
841f7a57 4018 route_map_install_set (&route_set_aspath_exclude_cmd);
718e3744 4019 route_map_install_set (&route_set_origin_cmd);
4020 route_map_install_set (&route_set_atomic_aggregate_cmd);
4021 route_map_install_set (&route_set_aggregator_as_cmd);
4022 route_map_install_set (&route_set_community_cmd);
4023 route_map_install_set (&route_set_community_delete_cmd);
4024 route_map_install_set (&route_set_vpnv4_nexthop_cmd);
4025 route_map_install_set (&route_set_originator_id_cmd);
4026 route_map_install_set (&route_set_ecommunity_rt_cmd);
4027 route_map_install_set (&route_set_ecommunity_soo_cmd);
0d9551dc 4028 route_map_install_set (&route_set_tag_cmd);
718e3744 4029
fee0f4c6 4030 install_element (RMAP_NODE, &match_peer_cmd);
4031 install_element (RMAP_NODE, &match_peer_local_cmd);
4032 install_element (RMAP_NODE, &no_match_peer_cmd);
c1643bb7 4033 install_element (RMAP_NODE, &match_ip_route_source_cmd);
4034 install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
c1643bb7 4035 install_element (RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4036 install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
718e3744 4037
4038 install_element (RMAP_NODE, &match_aspath_cmd);
4039 install_element (RMAP_NODE, &no_match_aspath_cmd);
af291c15
DS
4040 install_element (RMAP_NODE, &match_local_pref_cmd);
4041 install_element (RMAP_NODE, &no_match_local_pref_cmd);
718e3744 4042 install_element (RMAP_NODE, &match_community_cmd);
4043 install_element (RMAP_NODE, &match_community_exact_cmd);
4044 install_element (RMAP_NODE, &no_match_community_cmd);
73ffb25b 4045 install_element (RMAP_NODE, &match_ecommunity_cmd);
4046 install_element (RMAP_NODE, &no_match_ecommunity_cmd);
718e3744 4047 install_element (RMAP_NODE, &match_origin_cmd);
4048 install_element (RMAP_NODE, &no_match_origin_cmd);
1add115a
VT
4049 install_element (RMAP_NODE, &match_probability_cmd);
4050 install_element (RMAP_NODE, &no_match_probability_cmd);
718e3744 4051
af5cd0a5 4052 install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
316e074d 4053 install_element (RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
718e3744 4054 install_element (RMAP_NODE, &set_local_pref_cmd);
4055 install_element (RMAP_NODE, &no_set_local_pref_cmd);
718e3744 4056 install_element (RMAP_NODE, &set_weight_cmd);
4057 install_element (RMAP_NODE, &no_set_weight_cmd);
12dcf78e
QY
4058 install_element (RMAP_NODE, &set_aspath_prepend_asn_cmd);
4059 install_element (RMAP_NODE, &set_aspath_prepend_lastas_cmd);
841f7a57 4060 install_element (RMAP_NODE, &set_aspath_exclude_cmd);
718e3744 4061 install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
841f7a57 4062 install_element (RMAP_NODE, &no_set_aspath_exclude_cmd);
718e3744 4063 install_element (RMAP_NODE, &set_origin_cmd);
4064 install_element (RMAP_NODE, &no_set_origin_cmd);
718e3744 4065 install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
4066 install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
4067 install_element (RMAP_NODE, &set_aggregator_as_cmd);
4068 install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
718e3744 4069 install_element (RMAP_NODE, &set_community_cmd);
4070 install_element (RMAP_NODE, &set_community_none_cmd);
4071 install_element (RMAP_NODE, &no_set_community_cmd);
718e3744 4072 install_element (RMAP_NODE, &set_community_delete_cmd);
4073 install_element (RMAP_NODE, &no_set_community_delete_cmd);
718e3744 4074 install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
4075 install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
718e3744 4076 install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
4077 install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
718e3744 4078 install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
4079 install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
718e3744 4080 install_element (RMAP_NODE, &set_originator_id_cmd);
4081 install_element (RMAP_NODE, &no_set_originator_id_cmd);
718e3744 4082
718e3744 4083 route_map_install_match (&route_match_ipv6_address_cmd);
4084 route_map_install_match (&route_match_ipv6_next_hop_cmd);
4085 route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
4086 route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
161995ea 4087 route_map_install_set (&route_set_ipv6_nexthop_prefer_global_cmd);
718e3744 4088 route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
90916ac2
DS
4089 route_map_install_set (&route_set_ipv6_nexthop_peer_cmd);
4090
718e3744 4091 install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
4092 install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
718e3744 4093 install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
4094 install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
161995ea
DS
4095 install_element (RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
4096 install_element (RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
90916ac2
DS
4097 install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
4098 install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
718e3744 4099}
518f0eb1
DS
4100
4101void
4102bgp_route_map_terminate (void)
4103{
4104 /* ToDo: Cleanup all the used memory */
4105
4106 route_map_add_hook (NULL);
4107 route_map_delete_hook (NULL);
4108 route_map_event_hook (NULL);
4109 route_map_finish();
4110
4111}