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