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