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