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