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