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