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