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