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