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