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