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