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