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