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