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