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