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