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