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