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