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