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