]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_routemap.c
bgpd: combine special cases for vrf "all"
[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 int idx_ip = 2;
3004 return bgp_route_match_add (vty, vty->index, "peer", argv[idx_ip]->arg,
3005 RMAP_EVENT_MATCH_ADDED);
3006 }
3007
3008 DEFUN (match_peer_local,
3009 match_peer_local_cmd,
3010 "match peer local",
3011 MATCH_STR
3012 "Match peer address\n"
3013 "Static or Redistributed routes\n")
3014 {
3015 return bgp_route_match_add (vty, vty->index, "peer", "local",
3016 RMAP_EVENT_MATCH_DELETED);
3017 }
3018
3019 DEFUN (no_match_peer,
3020 no_match_peer_cmd,
3021 "no match peer [<local|A.B.C.D|X:X::X:X>]",
3022 NO_STR
3023 MATCH_STR
3024 "Match peer address\n"
3025 "Static or Redistributed routes\n"
3026 "IP address of peer\n"
3027 "IPv6 address of peer\n")
3028 {
3029 int idx_peer = 3;
3030
3031 if (argc <= idx_peer)
3032 return bgp_route_match_delete (vty, vty->index, "peer", NULL,
3033 RMAP_EVENT_MATCH_DELETED);
3034 return bgp_route_match_delete (vty, vty->index, "peer", argv[idx_peer]->arg,
3035 RMAP_EVENT_MATCH_DELETED);
3036 }
3037
3038
3039
3040 DEFUN (match_ip_address,
3041 match_ip_address_cmd,
3042 "match ip address <(1-199)|(1300-2699)|WORD>",
3043 MATCH_STR
3044 IP_STR
3045 "Match address of route\n"
3046 "IP access-list number\n"
3047 "IP access-list number (expanded range)\n"
3048 "IP Access-list name\n")
3049 {
3050 int idx_acl = 3;
3051 return bgp_route_match_add (vty, vty->index, "ip address", argv[idx_acl]->arg,
3052 RMAP_EVENT_FILTER_ADDED);
3053 }
3054
3055
3056 DEFUN (no_match_ip_address,
3057 no_match_ip_address_cmd,
3058 "no match ip address [<(1-199)|(1300-2699)|WORD>]",
3059 NO_STR
3060 MATCH_STR
3061 IP_STR
3062 "Match address of route\n"
3063 "IP access-list number\n"
3064 "IP access-list number (expanded range)\n"
3065 "IP Access-list name\n")
3066 {
3067 int idx_word = 4;
3068 if (argc <= idx_word)
3069 return bgp_route_match_delete (vty, vty->index, "ip address", NULL,
3070 RMAP_EVENT_FILTER_DELETED);
3071 return bgp_route_match_delete (vty, vty->index, "ip address", argv[idx_word]->arg,
3072 RMAP_EVENT_FILTER_DELETED);
3073 }
3074
3075
3076 DEFUN (match_ip_next_hop,
3077 match_ip_next_hop_cmd,
3078 "match ip next-hop <(1-199)|(1300-2699)|WORD>",
3079 MATCH_STR
3080 IP_STR
3081 "Match next-hop address of route\n"
3082 "IP access-list number\n"
3083 "IP access-list number (expanded range)\n"
3084 "IP Access-list name\n")
3085 {
3086 int idx_acl = 3;
3087 return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[idx_acl]->arg,
3088 RMAP_EVENT_FILTER_ADDED);
3089 }
3090
3091
3092 DEFUN (no_match_ip_next_hop,
3093 no_match_ip_next_hop_cmd,
3094 "no match ip next-hop [<(1-199)|(1300-2699)|WORD]",
3095 NO_STR
3096 MATCH_STR
3097 IP_STR
3098 "Match next-hop address of route\n"
3099 "IP access-list number\n"
3100 "IP access-list number (expanded range)\n"
3101 "IP Access-list name\n")
3102 {
3103 int idx_word = 4;
3104 if (argc <= idx_word)
3105 return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL,
3106 RMAP_EVENT_FILTER_DELETED);
3107 return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[idx_word]->arg,
3108 RMAP_EVENT_FILTER_DELETED);
3109 }
3110
3111
3112 /* match probability */
3113 DEFUN (match_probability,
3114 match_probability_cmd,
3115 "match probability (0-100)",
3116 MATCH_STR
3117 "Match portion of routes defined by percentage value\n"
3118 "Percentage of routes\n")
3119 {
3120 int idx_number = 2;
3121 return bgp_route_match_add (vty, vty->index, "probability", argv[idx_number]->arg,
3122 RMAP_EVENT_MATCH_ADDED);
3123 }
3124
3125
3126 DEFUN (no_match_probability,
3127 no_match_probability_cmd,
3128 "no match probability [(1-99)]",
3129 NO_STR
3130 MATCH_STR
3131 "Match portion of routes defined by percentage value\n"
3132 "Percentage of routes\n")
3133 {
3134 int idx_number = 3;
3135 if (argc <= idx_number)
3136 return bgp_route_match_delete (vty, vty->index, "probability", NULL,
3137 RMAP_EVENT_MATCH_DELETED);
3138 return bgp_route_match_delete (vty, vty->index, "probability", argv[idx_number]->arg,
3139 RMAP_EVENT_MATCH_DELETED);
3140 }
3141
3142
3143 DEFUN (match_ip_route_source,
3144 match_ip_route_source_cmd,
3145 "match ip route-source <(1-199)|(1300-2699)|WORD>",
3146 MATCH_STR
3147 IP_STR
3148 "Match advertising source address of route\n"
3149 "IP access-list number\n"
3150 "IP access-list number (expanded range)\n"
3151 "IP standard access-list name\n")
3152 {
3153 int idx_acl = 3;
3154 return bgp_route_match_add (vty, vty->index, "ip route-source", argv[idx_acl]->arg,
3155 RMAP_EVENT_FILTER_ADDED);
3156 }
3157
3158
3159 DEFUN (no_match_ip_route_source,
3160 no_match_ip_route_source_cmd,
3161 "no match ip route-source [(1-199)|(1300-2699)|WORD]",
3162 NO_STR
3163 MATCH_STR
3164 IP_STR
3165 "Match advertising source address of route\n"
3166 "IP access-list number\n"
3167 "IP access-list number (expanded range)\n"
3168 "IP standard access-list name\n")
3169 {
3170 int idx_number = 4;
3171 if (argc <= idx_number)
3172 return bgp_route_match_delete (vty, vty->index, "ip route-source",
3173 NULL, RMAP_EVENT_FILTER_DELETED);
3174 return bgp_route_match_delete (vty, vty->index, "ip route-source",
3175 argv[idx_number]->arg, RMAP_EVENT_FILTER_DELETED);
3176 }
3177
3178
3179 DEFUN (match_ip_address_prefix_list,
3180 match_ip_address_prefix_list_cmd,
3181 "match ip address prefix-list WORD",
3182 MATCH_STR
3183 IP_STR
3184 "Match address of route\n"
3185 "Match entries of prefix-lists\n"
3186 "IP prefix-list name\n")
3187 {
3188 int idx_word = 4;
3189 return bgp_route_match_add (vty, vty->index, "ip address prefix-list",
3190 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
3191 }
3192
3193
3194 DEFUN (no_match_ip_address_prefix_list,
3195 no_match_ip_address_prefix_list_cmd,
3196 "no match ip address prefix-list [WORD]",
3197 NO_STR
3198 MATCH_STR
3199 IP_STR
3200 "Match address of route\n"
3201 "Match entries of prefix-lists\n"
3202 "IP prefix-list name\n")
3203 {
3204 int idx_word = 5;
3205 if (argc <= idx_word)
3206 return bgp_route_match_delete (vty, vty->index, "ip address prefix-list",
3207 NULL, RMAP_EVENT_PLIST_DELETED);
3208 return bgp_route_match_delete (vty, vty->index, "ip address prefix-list",
3209 argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
3210 }
3211
3212
3213 DEFUN (match_ip_next_hop_prefix_list,
3214 match_ip_next_hop_prefix_list_cmd,
3215 "match ip next-hop prefix-list WORD",
3216 MATCH_STR
3217 IP_STR
3218 "Match next-hop address of route\n"
3219 "Match entries of prefix-lists\n"
3220 "IP prefix-list name\n")
3221 {
3222 int idx_word = 4;
3223 return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list",
3224 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
3225 }
3226
3227 DEFUN (no_match_ip_next_hop_prefix_list,
3228 no_match_ip_next_hop_prefix_list_cmd,
3229 "no match ip next-hop prefix-list [WORD]",
3230 NO_STR
3231 MATCH_STR
3232 IP_STR
3233 "Match next-hop address of route\n"
3234 "Match entries of prefix-lists\n"
3235 "IP prefix-list name\n")
3236 {
3237 int idx_word = 5;
3238 if (argc <= idx_word)
3239 return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
3240 NULL, RMAP_EVENT_PLIST_DELETED);
3241 return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
3242 argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
3243 }
3244
3245
3246 DEFUN (match_ip_route_source_prefix_list,
3247 match_ip_route_source_prefix_list_cmd,
3248 "match ip route-source prefix-list WORD",
3249 MATCH_STR
3250 IP_STR
3251 "Match advertising source address of route\n"
3252 "Match entries of prefix-lists\n"
3253 "IP prefix-list name\n")
3254 {
3255 int idx_word = 4;
3256 return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list",
3257 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
3258 }
3259
3260
3261 DEFUN (no_match_ip_route_source_prefix_list,
3262 no_match_ip_route_source_prefix_list_cmd,
3263 "no match ip route-source prefix-list [WORD]",
3264 NO_STR
3265 MATCH_STR
3266 IP_STR
3267 "Match advertising source address of route\n"
3268 "Match entries of prefix-lists\n"
3269 "IP prefix-list name\n")
3270 {
3271 int idx_word = 5;
3272 if (argc <= idx_word)
3273 return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list",
3274 NULL, RMAP_EVENT_PLIST_DELETED);
3275 return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list",
3276 argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
3277 }
3278
3279
3280 DEFUN (match_metric,
3281 match_metric_cmd,
3282 "match metric (0-4294967295)",
3283 MATCH_STR
3284 "Match metric of route\n"
3285 "Metric value\n")
3286 {
3287 int idx_number = 2;
3288 return bgp_route_match_add (vty, vty->index, "metric", argv[idx_number]->arg,
3289 RMAP_EVENT_MATCH_ADDED);
3290 }
3291
3292
3293 DEFUN (no_match_metric,
3294 no_match_metric_cmd,
3295 "no match metric [(0-4294967295)]",
3296 NO_STR
3297 MATCH_STR
3298 "Match metric of route\n"
3299 "Metric value\n")
3300 {
3301 int idx_number = 3;
3302 if (argc <= idx_number)
3303 return bgp_route_match_delete (vty, vty->index, "metric",
3304 NULL, RMAP_EVENT_MATCH_DELETED);
3305 return bgp_route_match_delete (vty, vty->index, "metric",
3306 argv[idx_number]->arg,
3307 RMAP_EVENT_MATCH_DELETED);
3308 }
3309
3310
3311 DEFUN (match_local_pref,
3312 match_local_pref_cmd,
3313 "match local-preference (0-4294967295)",
3314 MATCH_STR
3315 "Match local-preference of route\n"
3316 "Metric value\n")
3317 {
3318 int idx_number = 2;
3319 return bgp_route_match_add (vty, vty->index, "local-preference", argv[idx_number]->arg,
3320 RMAP_EVENT_MATCH_ADDED);
3321 }
3322
3323
3324 DEFUN (no_match_local_pref,
3325 no_match_local_pref_cmd,
3326 "no match local-preference [(0-4294967295)]",
3327 NO_STR
3328 MATCH_STR
3329 "Match local preference of route\n"
3330 "Local preference value\n")
3331 {
3332 int idx_localpref = 3;
3333 if (argc <= idx_localpref)
3334 return bgp_route_match_delete (vty, vty->index, "local-preference",
3335 NULL, RMAP_EVENT_MATCH_DELETED);
3336 return bgp_route_match_delete (vty, vty->index, "local-preference",
3337 argv[idx_localpref]->arg,
3338 RMAP_EVENT_MATCH_DELETED);
3339 }
3340
3341
3342 DEFUN (match_community,
3343 match_community_cmd,
3344 "match community <(1-99)|(100-500)|WORD>",
3345 MATCH_STR
3346 "Match BGP community list\n"
3347 "Community-list number (standard)\n"
3348 "Community-list number (expanded)\n"
3349 "Community-list name\n")
3350 {
3351 int idx_comm_list = 2;
3352 return bgp_route_match_add (vty, vty->index, "community", argv[idx_comm_list]->arg,
3353 RMAP_EVENT_CLIST_ADDED);
3354 }
3355
3356 DEFUN (match_community_exact,
3357 match_community_exact_cmd,
3358 "match community <(1-99)|(100-500)|WORD> exact-match",
3359 MATCH_STR
3360 "Match BGP community list\n"
3361 "Community-list number (standard)\n"
3362 "Community-list number (expanded)\n"
3363 "Community-list name\n"
3364 "Do exact matching of communities\n")
3365 {
3366 int idx_comm_list = 2;
3367 int ret;
3368 char *argstr;
3369
3370 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
3371 strlen (argv[idx_comm_list]->arg) + strlen ("exact-match") + 2);
3372
3373 sprintf (argstr, "%s exact-match", argv[idx_comm_list]->arg);
3374
3375 ret = bgp_route_match_add (vty, vty->index, "community", argstr,
3376 RMAP_EVENT_CLIST_ADDED);
3377
3378 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
3379
3380 return ret;
3381 }
3382
3383 DEFUN (no_match_community,
3384 no_match_community_cmd,
3385 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
3386 NO_STR
3387 MATCH_STR
3388 "Match BGP community list\n"
3389 "Community-list number (standard)\n"
3390 "Community-list number (expanded)\n"
3391 "Community-list name\n"
3392 "Do exact matching of communities\n")
3393 {
3394 return bgp_route_match_delete (vty, vty->index, "community", NULL,
3395 RMAP_EVENT_CLIST_DELETED);
3396 }
3397
3398
3399
3400 DEFUN (match_ecommunity,
3401 match_ecommunity_cmd,
3402 "match extcommunity <(1-99)|(100-500)|WORD>",
3403 MATCH_STR
3404 "Match BGP/VPN extended community list\n"
3405 "Extended community-list number (standard)\n"
3406 "Extended community-list number (expanded)\n"
3407 "Extended community-list name\n")
3408 {
3409 int idx_comm_list = 2;
3410 return bgp_route_match_add (vty, vty->index, "extcommunity", argv[idx_comm_list]->arg,
3411 RMAP_EVENT_ECLIST_ADDED);
3412 }
3413
3414
3415 DEFUN (no_match_ecommunity,
3416 no_match_ecommunity_cmd,
3417 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
3418 NO_STR
3419 MATCH_STR
3420 "Match BGP/VPN extended community list\n"
3421 "Extended community-list number (standard)\n"
3422 "Extended community-list number (expanded)\n"
3423 "Extended community-list name\n")
3424 {
3425 return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL,
3426 RMAP_EVENT_ECLIST_DELETED);
3427 }
3428
3429
3430 DEFUN (match_aspath,
3431 match_aspath_cmd,
3432 "match as-path WORD",
3433 MATCH_STR
3434 "Match BGP AS path list\n"
3435 "AS path access-list name\n")
3436 {
3437 int idx_word = 2;
3438 return bgp_route_match_add (vty, vty->index, "as-path", argv[idx_word]->arg,
3439 RMAP_EVENT_ASLIST_ADDED);
3440 }
3441
3442
3443 DEFUN (no_match_aspath,
3444 no_match_aspath_cmd,
3445 "no match as-path [WORD]",
3446 NO_STR
3447 MATCH_STR
3448 "Match BGP AS path list\n"
3449 "AS path access-list name\n")
3450 {
3451 return bgp_route_match_delete (vty, vty->index, "as-path", NULL,
3452 RMAP_EVENT_ASLIST_DELETED);
3453 }
3454
3455
3456 DEFUN (match_origin,
3457 match_origin_cmd,
3458 "match origin <egp|igp|incomplete>",
3459 MATCH_STR
3460 "BGP origin code\n"
3461 "remote EGP\n"
3462 "local IGP\n"
3463 "unknown heritage\n")
3464 {
3465 int idx_origin = 2;
3466 if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
3467 return bgp_route_match_add (vty, vty->index, "origin", "igp",
3468 RMAP_EVENT_MATCH_ADDED);
3469 if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
3470 return bgp_route_match_add (vty, vty->index, "origin", "egp",
3471 RMAP_EVENT_MATCH_ADDED);
3472 if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
3473 return bgp_route_match_add (vty, vty->index, "origin", "incomplete",
3474 RMAP_EVENT_MATCH_ADDED);
3475
3476 return CMD_WARNING;
3477 }
3478
3479
3480 DEFUN (no_match_origin,
3481 no_match_origin_cmd,
3482 "no match origin [<egp|igp|incomplete>]",
3483 NO_STR
3484 MATCH_STR
3485 "BGP origin code\n"
3486 "remote EGP\n"
3487 "local IGP\n"
3488 "unknown heritage\n")
3489 {
3490 return bgp_route_match_delete (vty, vty->index, "origin", NULL,
3491 RMAP_EVENT_MATCH_DELETED);
3492 }
3493
3494
3495 DEFUN (match_interface,
3496 match_interface_cmd,
3497 "match interface WORD",
3498 MATCH_STR
3499 "Match first hop interface of route\n"
3500 "Interface name\n")
3501 {
3502 int idx_word = 2;
3503 return bgp_route_match_add (vty, vty->index, "interface", argv[idx_word]->arg,
3504 RMAP_EVENT_MATCH_ADDED);
3505 }
3506
3507
3508 DEFUN (no_match_interface,
3509 no_match_interface_cmd,
3510 "no match interface [WORD]",
3511 NO_STR
3512 MATCH_STR
3513 "Match first hop interface of route\n"
3514 "Interface name\n")
3515 {
3516 return bgp_route_match_delete (vty, vty->index, "interface", argv[3]->arg,
3517 RMAP_EVENT_MATCH_DELETED);
3518 }
3519
3520
3521 DEFUN (match_tag,
3522 match_tag_cmd,
3523 "match tag (1-65535)",
3524 MATCH_STR
3525 "Match tag of route\n"
3526 "Tag value\n")
3527 {
3528 int idx_number = 2;
3529 return bgp_route_match_add (vty, vty->index, "tag", argv[idx_number]->arg,
3530 RMAP_EVENT_MATCH_ADDED);
3531 }
3532
3533
3534 DEFUN (no_match_tag,
3535 no_match_tag_cmd,
3536 "no match tag [(1-65535)]",
3537 NO_STR
3538 MATCH_STR
3539 "Match tag of route\n"
3540 "Tag value\n")
3541 {
3542 return bgp_route_match_delete (vty, vty->index, "tag", argv[3]->arg,
3543 RMAP_EVENT_MATCH_DELETED);
3544 }
3545
3546
3547 DEFUN (set_ip_nexthop,
3548 set_ip_nexthop_cmd,
3549 "set ip next-hop A.B.C.D",
3550 SET_STR
3551 IP_STR
3552 "Next hop address\n"
3553 "IP address of next hop\n")
3554 {
3555 int idx_ipv4 = 3;
3556 union sockunion su;
3557 int ret;
3558
3559 ret = str2sockunion (argv[idx_ipv4]->arg, &su);
3560 if (ret < 0)
3561 {
3562 vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
3563 return CMD_WARNING;
3564 }
3565 if (su.sin.sin_addr.s_addr == 0 ||
3566 IPV4_CLASS_DE(su.sin.sin_addr.s_addr))
3567 {
3568 vty_out (vty, "%% nexthop address cannot be 0.0.0.0, multicast "
3569 "or reserved%s", VTY_NEWLINE);
3570 return CMD_WARNING;
3571 }
3572
3573 return bgp_route_set_add (vty, vty->index, "ip next-hop", argv[idx_ipv4]->arg);
3574 }
3575
3576 DEFUN (set_ip_nexthop_peer,
3577 set_ip_nexthop_peer_cmd,
3578 "set ip next-hop peer-address",
3579 SET_STR
3580 IP_STR
3581 "Next hop address\n"
3582 "Use peer address (for BGP only)\n")
3583 {
3584 return bgp_route_set_add (vty, vty->index, "ip next-hop", "peer-address");
3585 }
3586
3587 DEFUN (set_ip_nexthop_unchanged,
3588 set_ip_nexthop_unchanged_cmd,
3589 "set ip next-hop unchanged",
3590 SET_STR
3591 IP_STR
3592 "Next hop address\n"
3593 "Don't modify existing Next hop address\n")
3594 {
3595 return bgp_route_set_add (vty, vty->index, "ip next-hop", "unchanged");
3596 }
3597
3598
3599 DEFUN (no_set_ip_nexthop,
3600 no_set_ip_nexthop_cmd,
3601 "no set ip next-hop [<peer-address|A.B.C.D>]",
3602 NO_STR
3603 SET_STR
3604 "Next hop address\n"
3605 "Use peer address (for BGP only)\n"
3606 "IP address of next hop\n")
3607 {
3608 int idx_peer = 4;
3609 if (argc <= idx_peer)
3610 return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
3611 return bgp_route_set_delete (vty, vty->index, "ip next-hop", argv[idx_peer]->arg);
3612 }
3613
3614
3615 DEFUN (set_metric,
3616 set_metric_cmd,
3617 "set metric <(0-4294967295)|rtt|+rtt|-rtt|+metric|-metric>",
3618 SET_STR
3619 "Metric value for destination routing protocol\n"
3620 "Metric value\n"
3621 "Assign round trip time\n"
3622 "Add round trip time\n"
3623 "Subtract round trip time\n"
3624 "Add metric\n"
3625 "Subtract metric\n")
3626 {
3627 int idx_number = 2;
3628 return bgp_route_set_add (vty, vty->index, "metric", argv[idx_number]->arg);
3629 }
3630
3631
3632 DEFUN (no_set_metric,
3633 no_set_metric_cmd,
3634 "no set metric [(0-4294967295)]",
3635 NO_STR
3636 SET_STR
3637 "Metric value for destination routing protocol\n"
3638 "Metric value\n")
3639 {
3640 int idx_number = 3;
3641 if (argc <= idx_number)
3642 return bgp_route_set_delete (vty, vty->index, "metric", NULL);
3643 return bgp_route_set_delete (vty, vty->index, "metric", argv[idx_number]->arg);
3644 }
3645
3646
3647 DEFUN (set_local_pref,
3648 set_local_pref_cmd,
3649 "set local-preference (0-4294967295)",
3650 SET_STR
3651 "BGP local preference path attribute\n"
3652 "Preference value\n")
3653 {
3654 int idx_number = 2;
3655 return bgp_route_set_add (vty, vty->index, "local-preference", argv[idx_number]->arg);
3656 }
3657
3658
3659 DEFUN (no_set_local_pref,
3660 no_set_local_pref_cmd,
3661 "no set local-preference [(0-4294967295)]",
3662 NO_STR
3663 SET_STR
3664 "BGP local preference path attribute\n"
3665 "Preference value\n")
3666 {
3667 int idx_localpref = 3;
3668 if (argc <= idx_localpref)
3669 return bgp_route_set_delete (vty, vty->index, "local-preference", NULL);
3670 return bgp_route_set_delete (vty, vty->index, "local-preference", argv[idx_localpref]->arg);
3671 }
3672
3673
3674 DEFUN (set_weight,
3675 set_weight_cmd,
3676 "set weight (0-4294967295)",
3677 SET_STR
3678 "BGP weight for routing table\n"
3679 "Weight value\n")
3680 {
3681 int idx_number = 2;
3682 return bgp_route_set_add (vty, vty->index, "weight", argv[idx_number]->arg);
3683 }
3684
3685
3686 DEFUN (no_set_weight,
3687 no_set_weight_cmd,
3688 "no set weight [(0-4294967295)]",
3689 NO_STR
3690 SET_STR
3691 "BGP weight for routing table\n"
3692 "Weight value\n")
3693 {
3694 int idx_weight = 3;
3695 if (argc <= idx_weight)
3696 return bgp_route_set_delete (vty, vty->index, "weight", NULL);
3697 return bgp_route_set_delete (vty, vty->index, "weight", argv[idx_weight]->arg);
3698 }
3699
3700
3701 DEFUN (set_aspath_prepend,
3702 set_aspath_prepend_cmd,
3703 "set as-path prepend <(1-4294967295)...|last-as (1-10)>",
3704 SET_STR
3705 "Transform BGP AS_PATH attribute\n"
3706 "Prepend to the as-path\n"
3707 "AS number\n"
3708 "Use the peer's AS-number\n"
3709 "Number of times to insert")
3710 {
3711 int idx_asn = 3;
3712 int ret;
3713 char *str;
3714
3715 str = argv_concat (argv, argc, idx_asn);
3716 ret = bgp_route_set_add (vty, vty->index, "as-path prepend", str);
3717 XFREE (MTYPE_TMP, str);
3718
3719 return ret;
3720 }
3721
3722
3723 DEFUN (no_set_aspath_prepend,
3724 no_set_aspath_prepend_cmd,
3725 "no set as-path prepend [(1-4294967295)]",
3726 NO_STR
3727 SET_STR
3728 "Transform BGP AS_PATH attribute\n"
3729 "Prepend to the as-path\n"
3730 "AS number\n")
3731 {
3732 int idx_asn = 4;
3733 int ret;
3734 char *str;
3735
3736 str = argv_concat (argv, argc, idx_asn);
3737 ret = bgp_route_set_delete (vty, vty->index, "as-path prepend", str);
3738 XFREE (MTYPE_TMP, str);
3739 return ret;
3740 }
3741
3742
3743 DEFUN (set_aspath_exclude,
3744 set_aspath_exclude_cmd,
3745 "set as-path exclude (1-4294967295)...",
3746 SET_STR
3747 "Transform BGP AS-path attribute\n"
3748 "Exclude from the as-path\n"
3749 "AS number\n")
3750 {
3751 int idx_asn = 3;
3752 int ret;
3753 char *str;
3754
3755 str = argv_concat (argv, argc, idx_asn);
3756 ret = bgp_route_set_add (vty, vty->index, "as-path exclude", str);
3757 XFREE (MTYPE_TMP, str);
3758 return ret;
3759 }
3760
3761 DEFUN (no_set_aspath_exclude,
3762 no_set_aspath_exclude_cmd,
3763 "no set as-path exclude (1-4294967295)...",
3764 NO_STR
3765 SET_STR
3766 "Transform BGP AS_PATH attribute\n"
3767 "Exclude from the as-path\n"
3768 "AS number\n")
3769 {
3770 int idx_asn = 4;
3771 int ret;
3772 char *str;
3773
3774 str = argv_concat (argv, argc, idx_asn);
3775 ret = bgp_route_set_delete (vty, vty->index, "as-path exclude", str);
3776 XFREE (MTYPE_TMP, str);
3777 return ret;
3778 }
3779
3780
3781 DEFUN (set_community,
3782 set_community_cmd,
3783 "set community AA:NN...",
3784 SET_STR
3785 "BGP community attribute\n"
3786 COMMUNITY_VAL_STR)
3787 {
3788 int idx_aa_nn = 2;
3789 int i;
3790 int first = 0;
3791 int additive = 0;
3792 struct buffer *b;
3793 struct community *com = NULL;
3794 char *str;
3795 char *argstr;
3796 int ret;
3797
3798 b = buffer_new (1024);
3799
3800 for (i = idx_aa_nn; i < argc; i++)
3801 {
3802 if (strncmp (argv[i]->arg, "additive", strlen (argv[i]->arg)) == 0)
3803 {
3804 additive = 1;
3805 continue;
3806 }
3807
3808 if (first)
3809 buffer_putc (b, ' ');
3810 else
3811 first = 1;
3812
3813 if (strncmp (argv[i]->arg, "internet", strlen (argv[i]->arg)) == 0)
3814 {
3815 buffer_putstr (b, "internet");
3816 continue;
3817 }
3818 if (strncmp (argv[i]->arg, "local-AS", strlen (argv[i]->arg)) == 0)
3819 {
3820 buffer_putstr (b, "local-AS");
3821 continue;
3822 }
3823 if (strncmp (argv[i]->arg, "no-a", strlen ("no-a")) == 0
3824 && strncmp (argv[i]->arg, "no-advertise", strlen (argv[i]->arg)) == 0)
3825 {
3826 buffer_putstr (b, "no-advertise");
3827 continue;
3828 }
3829 if (strncmp (argv[i]->arg, "no-e", strlen ("no-e"))== 0
3830 && strncmp (argv[i]->arg, "no-export", strlen (argv[i]->arg)) == 0)
3831 {
3832 buffer_putstr (b, "no-export");
3833 continue;
3834 }
3835 buffer_putstr (b, argv[i]->arg);
3836 }
3837 buffer_putc (b, '\0');
3838
3839 /* Fetch result string then compile it to communities attribute. */
3840 str = buffer_getstr (b);
3841 buffer_free (b);
3842
3843 if (str)
3844 {
3845 com = community_str2com (str);
3846 XFREE (MTYPE_TMP, str);
3847 }
3848
3849 /* Can't compile user input into communities attribute. */
3850 if (! com)
3851 {
3852 vty_out (vty, "%% Malformed communities attribute%s", VTY_NEWLINE);
3853 return CMD_WARNING;
3854 }
3855
3856 /* Set communites attribute string. */
3857 str = community_str (com);
3858
3859 if (additive)
3860 {
3861 argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
3862 strcpy (argstr, str);
3863 strcpy (argstr + strlen (str), " additive");
3864 ret = bgp_route_set_add (vty, vty->index, "community", argstr);
3865 XFREE (MTYPE_TMP, argstr);
3866 }
3867 else
3868 ret = bgp_route_set_add (vty, vty->index, "community", str);
3869
3870 community_free (com);
3871
3872 return ret;
3873 }
3874
3875 DEFUN (set_community_none,
3876 set_community_none_cmd,
3877 "set community none",
3878 SET_STR
3879 "BGP community attribute\n"
3880 "No community attribute\n")
3881 {
3882 return bgp_route_set_add (vty, vty->index, "community", "none");
3883 }
3884
3885 DEFUN (no_set_community,
3886 no_set_community_cmd,
3887 "no set community AA:NN...",
3888 NO_STR
3889 SET_STR
3890 "BGP community attribute\n")
3891 {
3892 return bgp_route_set_delete (vty, vty->index, "community", NULL);
3893 }
3894
3895
3896
3897 DEFUN (set_community_delete,
3898 set_community_delete_cmd,
3899 "set comm-list <(1-99)|(100-500)|WORD> delete",
3900 SET_STR
3901 "set BGP community list (for deletion)\n"
3902 "Community-list number (standard)\n"
3903 "Community-list number (expanded)\n"
3904 "Community-list name\n"
3905 "Delete matching communities\n")
3906 {
3907 int idx_comm_list = 2;
3908 char *str;
3909
3910 str = XCALLOC (MTYPE_TMP, strlen (argv[idx_comm_list]->arg) + strlen (" delete") + 1);
3911 strcpy (str, argv[idx_comm_list]->arg);
3912 strcpy (str + strlen (argv[idx_comm_list]->arg), " delete");
3913
3914 bgp_route_set_add (vty, vty->index, "comm-list", str);
3915
3916 XFREE (MTYPE_TMP, str);
3917 return CMD_SUCCESS;
3918 }
3919
3920 DEFUN (no_set_community_delete,
3921 no_set_community_delete_cmd,
3922 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
3923 NO_STR
3924 SET_STR
3925 "set BGP community list (for deletion)\n")
3926 {
3927 return bgp_route_set_delete (vty, vty->index, "comm-list", NULL);
3928 }
3929
3930
3931 DEFUN (set_ecommunity_rt,
3932 set_ecommunity_rt_cmd,
3933 "set extcommunity rt ASN:nn_or_IP-address:nn...",
3934 SET_STR
3935 "BGP extended community attribute\n"
3936 "Route Target extended community\n"
3937 "VPN extended community\n")
3938 {
3939 int idx_asn_nn = 3;
3940 int ret;
3941 char *str;
3942
3943 str = argv_concat (argv, argc, idx_asn_nn);
3944 ret = bgp_route_set_add (vty, vty->index, "extcommunity rt", str);
3945 XFREE (MTYPE_TMP, str);
3946
3947 return ret;
3948 }
3949
3950 DEFUN (no_set_ecommunity_rt,
3951 no_set_ecommunity_rt_cmd,
3952 "no set extcommunity rt ASN:nn_or_IP-address:nn...",
3953 NO_STR
3954 SET_STR
3955 "BGP extended community attribute\n"
3956 "Route Target extended community\n")
3957 {
3958 return bgp_route_set_delete (vty, vty->index, "extcommunity rt", NULL);
3959 }
3960
3961
3962 DEFUN (set_ecommunity_soo,
3963 set_ecommunity_soo_cmd,
3964 "set extcommunity soo ASN:nn_or_IP-address:nn...",
3965 SET_STR
3966 "BGP extended community attribute\n"
3967 "Site-of-Origin extended community\n"
3968 "VPN extended community\n")
3969 {
3970 int idx_asn_nn = 3;
3971 int ret;
3972 char *str;
3973
3974 str = argv_concat (argv, argc, idx_asn_nn);
3975 ret = bgp_route_set_add (vty, vty->index, "extcommunity soo", str);
3976 XFREE (MTYPE_TMP, str);
3977 return ret;
3978 }
3979
3980
3981 DEFUN (no_set_ecommunity_soo,
3982 no_set_ecommunity_soo_cmd,
3983 "no set extcommunity soo ASN:nn_or_IP-address:nn...",
3984 NO_STR
3985 SET_STR
3986 "BGP extended community attribute\n"
3987 "Site-of-Origin extended community\n")
3988 {
3989 return bgp_route_set_delete (vty, vty->index, "extcommunity soo", NULL);
3990 }
3991
3992
3993 DEFUN (set_origin,
3994 set_origin_cmd,
3995 "set origin <egp|igp|incomplete>",
3996 SET_STR
3997 "BGP origin code\n"
3998 "remote EGP\n"
3999 "local IGP\n"
4000 "unknown heritage\n")
4001 {
4002 int idx_origin = 2;
4003 if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
4004 return bgp_route_set_add (vty, vty->index, "origin", "igp");
4005 if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
4006 return bgp_route_set_add (vty, vty->index, "origin", "egp");
4007 if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
4008 return bgp_route_set_add (vty, vty->index, "origin", "incomplete");
4009
4010 return CMD_WARNING;
4011 }
4012
4013
4014 DEFUN (no_set_origin,
4015 no_set_origin_cmd,
4016 "no set origin [<egp|igp|incomplete>]",
4017 NO_STR
4018 SET_STR
4019 "BGP origin code\n")
4020 {
4021 return bgp_route_set_delete (vty, vty->index, "origin", NULL);
4022 }
4023
4024
4025 DEFUN (set_atomic_aggregate,
4026 set_atomic_aggregate_cmd,
4027 "set atomic-aggregate",
4028 SET_STR
4029 "BGP atomic aggregate attribute\n" )
4030 {
4031 return bgp_route_set_add (vty, vty->index, "atomic-aggregate", NULL);
4032 }
4033
4034 DEFUN (no_set_atomic_aggregate,
4035 no_set_atomic_aggregate_cmd,
4036 "no set atomic-aggregate",
4037 NO_STR
4038 SET_STR
4039 "BGP atomic aggregate attribute\n" )
4040 {
4041 return bgp_route_set_delete (vty, vty->index, "atomic-aggregate", NULL);
4042 }
4043
4044 DEFUN (set_aggregator_as,
4045 set_aggregator_as_cmd,
4046 "set aggregator as (1-4294967295) A.B.C.D",
4047 SET_STR
4048 "BGP aggregator attribute\n"
4049 "AS number of aggregator\n"
4050 "AS number\n"
4051 "IP address of aggregator\n")
4052 {
4053 int idx_number = 3;
4054 int idx_ipv4 = 4;
4055 int ret;
4056 struct in_addr address;
4057 char *argstr;
4058
4059 ret = inet_aton (argv[idx_ipv4]->arg, &address);
4060 if (ret == 0)
4061 {
4062 vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
4063 return CMD_WARNING;
4064 }
4065
4066 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
4067 strlen (argv[idx_number]->arg) + strlen (argv[idx_ipv4]->arg) + 2);
4068
4069 sprintf (argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
4070
4071 ret = bgp_route_set_add (vty, vty->index, "aggregator as", argstr);
4072
4073 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4074
4075 return ret;
4076 }
4077
4078
4079 DEFUN (no_set_aggregator_as,
4080 no_set_aggregator_as_cmd,
4081 "no set aggregator as [(1-4294967295) A.B.C.D]",
4082 NO_STR
4083 SET_STR
4084 "BGP aggregator attribute\n"
4085 "AS number of aggregator\n"
4086 "AS number\n"
4087 "IP address of aggregator\n")
4088 {
4089 int idx_asn = 4;
4090 int idx_ip = 5;
4091 int ret;
4092 struct in_addr address;
4093 char *argstr;
4094
4095 if (argc <= idx_asn)
4096 return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
4097
4098 ret = inet_aton (argv[idx_ip]->arg, &address);
4099 if (ret == 0)
4100 {
4101 vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
4102 return CMD_WARNING;
4103 }
4104
4105 argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
4106 strlen (argv[idx_asn]->arg) + strlen (argv[idx_ip]->arg) + 2);
4107
4108 sprintf (argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
4109
4110 ret = bgp_route_set_delete (vty, vty->index, "aggregator as", argstr);
4111
4112 XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
4113
4114 return ret;
4115 }
4116
4117
4118 DEFUN (set_tag,
4119 set_tag_cmd,
4120 "set tag (1-65535)",
4121 SET_STR
4122 "Tag value for routing protocol\n"
4123 "Tag value\n")
4124 {
4125 int idx_number = 2;
4126 return bgp_route_set_add (vty, vty->index, "tag", argv[idx_number]->arg);
4127 }
4128
4129
4130 DEFUN (no_set_tag,
4131 no_set_tag_cmd,
4132 "no set tag [(1-65535)]",
4133 NO_STR
4134 SET_STR
4135 "Tag value for routing protocol\n"
4136 "Tag value\n")
4137 {
4138 int idx_number = 3;
4139 if (argc <= idx_number)
4140 return bgp_route_set_delete (vty, vty->index, "tag", NULL);
4141 return bgp_route_set_delete (vty, vty->index, "tag", argv[idx_number]->arg);
4142 }
4143
4144
4145
4146 #ifdef HAVE_IPV6
4147 DEFUN (match_ipv6_address,
4148 match_ipv6_address_cmd,
4149 "match ipv6 address WORD",
4150 MATCH_STR
4151 IPV6_STR
4152 "Match IPv6 address of route\n"
4153 "IPv6 access-list name\n")
4154 {
4155 int idx_word = 3;
4156 return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[idx_word]->arg,
4157 RMAP_EVENT_FILTER_ADDED);
4158 }
4159
4160 DEFUN (no_match_ipv6_address,
4161 no_match_ipv6_address_cmd,
4162 "no match ipv6 address WORD",
4163 NO_STR
4164 MATCH_STR
4165 IPV6_STR
4166 "Match IPv6 address of route\n"
4167 "IPv6 access-list name\n")
4168 {
4169 int idx_word = 4;
4170 return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[idx_word]->arg,
4171 RMAP_EVENT_FILTER_DELETED);
4172 }
4173
4174 DEFUN (match_ipv6_next_hop,
4175 match_ipv6_next_hop_cmd,
4176 "match ipv6 next-hop X:X::X:X",
4177 MATCH_STR
4178 IPV6_STR
4179 "Match IPv6 next-hop address of route\n"
4180 "IPv6 address of next hop\n")
4181 {
4182 int idx_ipv6 = 3;
4183 return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[idx_ipv6]->arg,
4184 RMAP_EVENT_MATCH_ADDED);
4185 }
4186
4187 DEFUN (no_match_ipv6_next_hop,
4188 no_match_ipv6_next_hop_cmd,
4189 "no match ipv6 next-hop X:X::X:X",
4190 NO_STR
4191 MATCH_STR
4192 IPV6_STR
4193 "Match IPv6 next-hop address of route\n"
4194 "IPv6 address of next hop\n")
4195 {
4196 int idx_ipv6 = 4;
4197 return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[idx_ipv6]->arg,
4198 RMAP_EVENT_MATCH_DELETED);
4199 }
4200
4201 DEFUN (match_ipv6_address_prefix_list,
4202 match_ipv6_address_prefix_list_cmd,
4203 "match ipv6 address prefix-list WORD",
4204 MATCH_STR
4205 IPV6_STR
4206 "Match address of route\n"
4207 "Match entries of prefix-lists\n"
4208 "IP prefix-list name\n")
4209 {
4210 int idx_word = 4;
4211 return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list",
4212 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
4213 }
4214
4215 DEFUN (no_match_ipv6_address_prefix_list,
4216 no_match_ipv6_address_prefix_list_cmd,
4217 "no match ipv6 address prefix-list WORD",
4218 NO_STR
4219 MATCH_STR
4220 IPV6_STR
4221 "Match address of route\n"
4222 "Match entries of prefix-lists\n"
4223 "IP prefix-list name\n")
4224 {
4225 int idx_word = 5;
4226 return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list",
4227 argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
4228 }
4229
4230 DEFUN (set_ipv6_nexthop_peer,
4231 set_ipv6_nexthop_peer_cmd,
4232 "set ipv6 next-hop peer-address",
4233 SET_STR
4234 IPV6_STR
4235 "Next hop address\n"
4236 "Use peer address (for BGP only)\n")
4237 {
4238 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop peer-address", NULL);
4239 }
4240
4241 DEFUN (no_set_ipv6_nexthop_peer,
4242 no_set_ipv6_nexthop_peer_cmd,
4243 "no set ipv6 next-hop peer-address",
4244 NO_STR
4245 SET_STR
4246 IPV6_STR
4247 "IPv6 next-hop address\n"
4248 "Use peer address (for BGP only)\n")
4249 {
4250 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop peer-address", NULL);
4251 }
4252
4253 DEFUN (set_ipv6_nexthop_prefer_global,
4254 set_ipv6_nexthop_prefer_global_cmd,
4255 "set ipv6 next-hop prefer-global",
4256 SET_STR
4257 IPV6_STR
4258 "IPv6 next-hop address\n"
4259 "Prefer global over link-local if both exist\n")
4260 {
4261 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop prefer-global", NULL);;
4262 }
4263
4264 DEFUN (no_set_ipv6_nexthop_prefer_global,
4265 no_set_ipv6_nexthop_prefer_global_cmd,
4266 "no set ipv6 next-hop prefer-global",
4267 NO_STR
4268 SET_STR
4269 IPV6_STR
4270 "IPv6 next-hop address\n"
4271 "Prefer global over link-local if both exist\n")
4272 {
4273 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop prefer-global", NULL);
4274 }
4275
4276 DEFUN (set_ipv6_nexthop_global,
4277 set_ipv6_nexthop_global_cmd,
4278 "set ipv6 next-hop global X:X::X:X",
4279 SET_STR
4280 IPV6_STR
4281 "IPv6 next-hop address\n"
4282 "IPv6 global address\n"
4283 "IPv6 address of next hop\n")
4284 {
4285 int idx_ipv6 = 4;
4286 struct in6_addr addr;
4287 int ret;
4288
4289 ret = inet_pton (AF_INET6, argv[idx_ipv6]->arg, &addr);
4290 if (!ret)
4291 {
4292 vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
4293 return CMD_WARNING;
4294 }
4295 if (IN6_IS_ADDR_UNSPECIFIED(&addr) ||
4296 IN6_IS_ADDR_LOOPBACK(&addr) ||
4297 IN6_IS_ADDR_MULTICAST(&addr) ||
4298 IN6_IS_ADDR_LINKLOCAL(&addr))
4299 {
4300 vty_out (vty, "%% Invalid global nexthop address%s", VTY_NEWLINE);
4301 return CMD_WARNING;
4302 }
4303
4304 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop global", argv[idx_ipv6]->arg);
4305 }
4306
4307
4308 DEFUN (no_set_ipv6_nexthop_global,
4309 no_set_ipv6_nexthop_global_cmd,
4310 "no set ipv6 next-hop global X:X::X:X",
4311 NO_STR
4312 SET_STR
4313 IPV6_STR
4314 "IPv6 next-hop address\n"
4315 "IPv6 global address\n"
4316 "IPv6 address of next hop\n")
4317 {
4318 int idx_ipv6 = 5;
4319 if (argc <= idx_ipv6)
4320 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
4321 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", argv[idx_ipv6]->arg);
4322 }
4323
4324
4325 DEFUN (set_ipv6_nexthop_local,
4326 set_ipv6_nexthop_local_cmd,
4327 "set ipv6 next-hop local X:X::X:X",
4328 SET_STR
4329 IPV6_STR
4330 "IPv6 next-hop address\n"
4331 "IPv6 local address\n"
4332 "IPv6 address of next hop\n")
4333 {
4334 int idx_ipv6 = 4;
4335 struct in6_addr addr;
4336 int ret;
4337
4338 ret = inet_pton (AF_INET6, argv[idx_ipv6]->arg, &addr);
4339 if (!ret)
4340 {
4341 vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
4342 return CMD_WARNING;
4343 }
4344 if (!IN6_IS_ADDR_LINKLOCAL(&addr))
4345 {
4346 vty_out (vty, "%% Invalid link-local nexthop address%s", VTY_NEWLINE);
4347 return CMD_WARNING;
4348 }
4349
4350 return bgp_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[idx_ipv6]->arg);
4351 }
4352
4353
4354 DEFUN (no_set_ipv6_nexthop_local,
4355 no_set_ipv6_nexthop_local_cmd,
4356 "no set ipv6 next-hop local [X:X::X:X]",
4357 NO_STR
4358 SET_STR
4359 IPV6_STR
4360 "IPv6 next-hop address\n"
4361 "IPv6 local address\n"
4362 "IPv6 address of next hop\n")
4363 {
4364 int idx_ipv6 = 5;
4365 if (argc <= idx_ipv6)
4366 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
4367 return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[5]->arg);
4368 }
4369
4370 #endif /* HAVE_IPV6 */
4371
4372 DEFUN (set_vpnv4_nexthop,
4373 set_vpnv4_nexthop_cmd,
4374 "set vpnv4 next-hop A.B.C.D",
4375 SET_STR
4376 "VPNv4 information\n"
4377 "VPNv4 next-hop address\n"
4378 "IP address of next hop\n")
4379 {
4380 int idx_ipv4 = 3;
4381 return bgp_route_set_add (vty, vty->index, "vpnv4 next-hop", argv[idx_ipv4]->arg);
4382 }
4383
4384
4385 DEFUN (no_set_vpnv4_nexthop,
4386 no_set_vpnv4_nexthop_cmd,
4387 "no set vpnv4 next-hop [A.B.C.D]",
4388 NO_STR
4389 SET_STR
4390 "VPNv4 information\n"
4391 "VPNv4 next-hop address\n"
4392 "IP address of next hop\n")
4393 {
4394 int idx_ipv4 = 4;
4395 if (argc <= idx_ipv4)
4396 return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
4397 return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", argv[idx_ipv4]->arg);
4398 }
4399
4400
4401 DEFUN (set_originator_id,
4402 set_originator_id_cmd,
4403 "set originator-id A.B.C.D",
4404 SET_STR
4405 "BGP originator ID attribute\n"
4406 "IP address of originator\n")
4407 {
4408 int idx_ipv4 = 2;
4409 return bgp_route_set_add (vty, vty->index, "originator-id", argv[idx_ipv4]->arg);
4410 }
4411
4412
4413 DEFUN (no_set_originator_id,
4414 no_set_originator_id_cmd,
4415 "no set originator-id [A.B.C.D]",
4416 NO_STR
4417 SET_STR
4418 "BGP originator ID attribute\n"
4419 "IP address of originator\n")
4420 {
4421 int idx_id = 3;
4422 if (argc < idx_id)
4423 return bgp_route_set_delete (vty, vty->index, "originator-id", NULL);
4424 return bgp_route_set_delete (vty, vty->index, "originator-id", argv[idx_id]->arg);
4425 }
4426
4427
4428 /* Initialization of route map. */
4429 void
4430 bgp_route_map_init (void)
4431 {
4432 route_map_init ();
4433 route_map_init_vty ();
4434 route_map_add_hook (bgp_route_map_add);
4435 route_map_delete_hook (bgp_route_map_delete);
4436 route_map_event_hook (bgp_route_map_event);
4437
4438 route_map_install_match (&route_match_peer_cmd);
4439 route_map_install_match (&route_match_local_pref_cmd);
4440 route_map_install_match (&route_match_ip_address_cmd);
4441 route_map_install_match (&route_match_ip_next_hop_cmd);
4442 route_map_install_match (&route_match_ip_route_source_cmd);
4443 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
4444 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
4445 route_map_install_match (&route_match_ip_route_source_prefix_list_cmd);
4446 route_map_install_match (&route_match_aspath_cmd);
4447 route_map_install_match (&route_match_community_cmd);
4448 route_map_install_match (&route_match_ecommunity_cmd);
4449 route_map_install_match (&route_match_local_pref_cmd);
4450 route_map_install_match (&route_match_metric_cmd);
4451 route_map_install_match (&route_match_origin_cmd);
4452 route_map_install_match (&route_match_probability_cmd);
4453 route_map_install_match (&route_match_interface_cmd);
4454 route_map_install_match (&route_match_tag_cmd);
4455
4456 route_map_install_set (&route_set_ip_nexthop_cmd);
4457 route_map_install_set (&route_set_local_pref_cmd);
4458 route_map_install_set (&route_set_weight_cmd);
4459 route_map_install_set (&route_set_metric_cmd);
4460 route_map_install_set (&route_set_aspath_prepend_cmd);
4461 route_map_install_set (&route_set_aspath_exclude_cmd);
4462 route_map_install_set (&route_set_origin_cmd);
4463 route_map_install_set (&route_set_atomic_aggregate_cmd);
4464 route_map_install_set (&route_set_aggregator_as_cmd);
4465 route_map_install_set (&route_set_community_cmd);
4466 route_map_install_set (&route_set_community_delete_cmd);
4467 route_map_install_set (&route_set_vpnv4_nexthop_cmd);
4468 route_map_install_set (&route_set_originator_id_cmd);
4469 route_map_install_set (&route_set_ecommunity_rt_cmd);
4470 route_map_install_set (&route_set_ecommunity_soo_cmd);
4471 route_map_install_set (&route_set_tag_cmd);
4472
4473 install_element (RMAP_NODE, &match_peer_cmd);
4474 install_element (RMAP_NODE, &match_peer_local_cmd);
4475 install_element (RMAP_NODE, &no_match_peer_cmd);
4476 install_element (RMAP_NODE, &match_ip_address_cmd);
4477 install_element (RMAP_NODE, &no_match_ip_address_cmd);
4478 install_element (RMAP_NODE, &match_ip_next_hop_cmd);
4479 install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
4480 install_element (RMAP_NODE, &match_ip_route_source_cmd);
4481 install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
4482 install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
4483 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
4484 install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
4485 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
4486 install_element (RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4487 install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
4488
4489 install_element (RMAP_NODE, &match_aspath_cmd);
4490 install_element (RMAP_NODE, &no_match_aspath_cmd);
4491 install_element (RMAP_NODE, &match_metric_cmd);
4492 install_element (RMAP_NODE, &no_match_metric_cmd);
4493 install_element (RMAP_NODE, &match_local_pref_cmd);
4494 install_element (RMAP_NODE, &no_match_local_pref_cmd);
4495 install_element (RMAP_NODE, &match_community_cmd);
4496 install_element (RMAP_NODE, &match_community_exact_cmd);
4497 install_element (RMAP_NODE, &no_match_community_cmd);
4498 install_element (RMAP_NODE, &match_ecommunity_cmd);
4499 install_element (RMAP_NODE, &no_match_ecommunity_cmd);
4500 install_element (RMAP_NODE, &match_origin_cmd);
4501 install_element (RMAP_NODE, &no_match_origin_cmd);
4502 install_element (RMAP_NODE, &match_probability_cmd);
4503 install_element (RMAP_NODE, &no_match_probability_cmd);
4504 install_element (RMAP_NODE, &match_interface_cmd);
4505 install_element (RMAP_NODE, &no_match_interface_cmd);
4506 install_element (RMAP_NODE, &match_tag_cmd);
4507 install_element (RMAP_NODE, &no_match_tag_cmd);
4508
4509 install_element (RMAP_NODE, &set_ip_nexthop_cmd);
4510 install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
4511 install_element (RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
4512 install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
4513 install_element (RMAP_NODE, &set_local_pref_cmd);
4514 install_element (RMAP_NODE, &no_set_local_pref_cmd);
4515 install_element (RMAP_NODE, &set_weight_cmd);
4516 install_element (RMAP_NODE, &no_set_weight_cmd);
4517 install_element (RMAP_NODE, &set_metric_cmd);
4518 install_element (RMAP_NODE, &no_set_metric_cmd);
4519 install_element (RMAP_NODE, &set_aspath_prepend_cmd);
4520 install_element (RMAP_NODE, &set_aspath_exclude_cmd);
4521 install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
4522 install_element (RMAP_NODE, &no_set_aspath_exclude_cmd);
4523 install_element (RMAP_NODE, &set_origin_cmd);
4524 install_element (RMAP_NODE, &no_set_origin_cmd);
4525 install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
4526 install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
4527 install_element (RMAP_NODE, &set_aggregator_as_cmd);
4528 install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
4529 install_element (RMAP_NODE, &set_community_cmd);
4530 install_element (RMAP_NODE, &set_community_none_cmd);
4531 install_element (RMAP_NODE, &no_set_community_cmd);
4532 install_element (RMAP_NODE, &set_community_delete_cmd);
4533 install_element (RMAP_NODE, &no_set_community_delete_cmd);
4534 install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
4535 install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
4536 install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
4537 install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
4538 install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
4539 install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
4540 install_element (RMAP_NODE, &set_originator_id_cmd);
4541 install_element (RMAP_NODE, &no_set_originator_id_cmd);
4542 install_element (RMAP_NODE, &set_tag_cmd);
4543 install_element (RMAP_NODE, &no_set_tag_cmd);
4544
4545 #ifdef HAVE_IPV6
4546 route_map_install_match (&route_match_ipv6_address_cmd);
4547 route_map_install_match (&route_match_ipv6_next_hop_cmd);
4548 route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
4549 route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
4550 route_map_install_set (&route_set_ipv6_nexthop_prefer_global_cmd);
4551 route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
4552 route_map_install_set (&route_set_ipv6_nexthop_peer_cmd);
4553
4554 install_element (RMAP_NODE, &match_ipv6_address_cmd);
4555 install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
4556 install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
4557 install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
4558 install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
4559 install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
4560 install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
4561 install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
4562 install_element (RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
4563 install_element (RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
4564 install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
4565 install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
4566 install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
4567 install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
4568 #endif /* HAVE_IPV6 */
4569 }
4570
4571 void
4572 bgp_route_map_terminate (void)
4573 {
4574 /* ToDo: Cleanup all the used memory */
4575
4576 route_map_add_hook (NULL);
4577 route_map_delete_hook (NULL);
4578 route_map_event_hook (NULL);
4579 route_map_finish();
4580
4581 }