]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_routemap.c
Merge pull request #8128 from qlyoung/docs-cleanup
[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 size_t argstr_len;
4319
4320 if (argc == 4) {
4321 argstr_len = strlen(argv[idx_comm_list]->arg)
4322 + strlen("exact-match") + 2;
4323 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
4324
4325 snprintf(argstr, argstr_len, "%s exact-match",
4326 argv[idx_comm_list]->arg);
4327 } else
4328 argstr = argv[idx_comm_list]->arg;
4329
4330 ret = bgp_route_match_add(vty, "community", argstr,
4331 RMAP_EVENT_CLIST_ADDED);
4332
4333 if (argstr != argv[idx_comm_list]->arg)
4334 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
4335
4336 return ret;
4337 }
4338
4339 DEFUN (no_match_community,
4340 no_match_community_cmd,
4341 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
4342 NO_STR
4343 MATCH_STR
4344 "Match BGP community list\n"
4345 "Community-list number (standard)\n"
4346 "Community-list number (expanded)\n"
4347 "Community-list name\n"
4348 "Do exact matching of communities\n")
4349 {
4350 return bgp_route_match_delete(vty, "community", NULL,
4351 RMAP_EVENT_CLIST_DELETED);
4352 }
4353
4354 DEFUN (match_lcommunity,
4355 match_lcommunity_cmd,
4356 "match large-community <(1-99)|(100-500)|WORD> [exact-match]",
4357 MATCH_STR
4358 "Match BGP large community list\n"
4359 "Large Community-list number (standard)\n"
4360 "Large Community-list number (expanded)\n"
4361 "Large Community-list name\n"
4362 "Do exact matching of communities\n")
4363 {
4364 int idx_lcomm_list = 2;
4365 int ret;
4366 char *argstr;
4367 size_t argstr_len;
4368
4369 if (argc == 4) {
4370 argstr_len = strlen(argv[idx_lcomm_list]->arg)
4371 + strlen("exact-match") + 2;
4372 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
4373
4374 snprintf(argstr, argstr_len, "%s exact-match",
4375 argv[idx_lcomm_list]->arg);
4376 } else
4377 argstr = argv[idx_lcomm_list]->arg;
4378
4379 ret = bgp_route_match_add(vty, "large-community", argstr,
4380 RMAP_EVENT_LLIST_ADDED);
4381 if (argstr != argv[idx_lcomm_list]->arg)
4382 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
4383
4384 return ret;
4385 }
4386
4387 DEFUN (no_match_lcommunity,
4388 no_match_lcommunity_cmd,
4389 "no match large-community [<(1-99)|(100-500)|WORD> [exact-match]]",
4390 NO_STR
4391 MATCH_STR
4392 "Match BGP large community list\n"
4393 "Large Community-list number (standard)\n"
4394 "Large Community-list number (expanded)\n"
4395 "Large Community-list name\n"
4396 "Do exact matching of communities\n")
4397 {
4398 return bgp_route_match_delete(vty, "large-community", NULL,
4399 RMAP_EVENT_LLIST_DELETED);
4400 }
4401
4402 DEFUN (match_ecommunity,
4403 match_ecommunity_cmd,
4404 "match extcommunity <(1-99)|(100-500)|WORD>",
4405 MATCH_STR
4406 "Match BGP/VPN extended community list\n"
4407 "Extended community-list number (standard)\n"
4408 "Extended community-list number (expanded)\n"
4409 "Extended community-list name\n")
4410 {
4411 int idx_comm_list = 2;
4412 return bgp_route_match_add(vty, "extcommunity",
4413 argv[idx_comm_list]->arg,
4414 RMAP_EVENT_ECLIST_ADDED);
4415 }
4416
4417
4418 DEFUN (no_match_ecommunity,
4419 no_match_ecommunity_cmd,
4420 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
4421 NO_STR
4422 MATCH_STR
4423 "Match BGP/VPN extended community list\n"
4424 "Extended community-list number (standard)\n"
4425 "Extended community-list number (expanded)\n"
4426 "Extended community-list name\n")
4427 {
4428 return bgp_route_match_delete(vty, "extcommunity", NULL,
4429 RMAP_EVENT_ECLIST_DELETED);
4430 }
4431
4432
4433 DEFUN (match_aspath,
4434 match_aspath_cmd,
4435 "match as-path WORD",
4436 MATCH_STR
4437 "Match BGP AS path list\n"
4438 "AS path access-list name\n")
4439 {
4440 int idx_word = 2;
4441 return bgp_route_match_add(vty, "as-path", argv[idx_word]->arg,
4442 RMAP_EVENT_ASLIST_ADDED);
4443 }
4444
4445
4446 DEFUN (no_match_aspath,
4447 no_match_aspath_cmd,
4448 "no match as-path [WORD]",
4449 NO_STR
4450 MATCH_STR
4451 "Match BGP AS path list\n"
4452 "AS path access-list name\n")
4453 {
4454 return bgp_route_match_delete(vty, "as-path", NULL,
4455 RMAP_EVENT_ASLIST_DELETED);
4456 }
4457
4458
4459 DEFUN (match_origin,
4460 match_origin_cmd,
4461 "match origin <egp|igp|incomplete>",
4462 MATCH_STR
4463 "BGP origin code\n"
4464 "remote EGP\n"
4465 "local IGP\n"
4466 "unknown heritage\n")
4467 {
4468 int idx_origin = 2;
4469 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
4470 return bgp_route_match_add(vty, "origin", "igp",
4471 RMAP_EVENT_MATCH_ADDED);
4472 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
4473 return bgp_route_match_add(vty, "origin", "egp",
4474 RMAP_EVENT_MATCH_ADDED);
4475 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
4476 return bgp_route_match_add(vty, "origin", "incomplete",
4477 RMAP_EVENT_MATCH_ADDED);
4478
4479 vty_out(vty, "%% Invalid match origin type\n");
4480 return CMD_WARNING_CONFIG_FAILED;
4481 }
4482
4483
4484 DEFUN (no_match_origin,
4485 no_match_origin_cmd,
4486 "no match origin [<egp|igp|incomplete>]",
4487 NO_STR
4488 MATCH_STR
4489 "BGP origin code\n"
4490 "remote EGP\n"
4491 "local IGP\n"
4492 "unknown heritage\n")
4493 {
4494 return bgp_route_match_delete(vty, "origin", NULL,
4495 RMAP_EVENT_MATCH_DELETED);
4496 }
4497
4498 DEFUN (set_table_id,
4499 set_table_id_cmd,
4500 "set table (1-4294967295)",
4501 SET_STR
4502 "export route to non-main kernel table\n"
4503 "Kernel routing table id\n")
4504 {
4505 int idx_id = 2;
4506
4507 VTY_DECLVAR_CONTEXT(route_map_index, index);
4508
4509 return generic_set_add(vty, index, "table", argv[idx_id]->arg);
4510 }
4511
4512 DEFUN (no_set_table_id,
4513 no_set_table_id_cmd,
4514 "no set table",
4515 NO_STR
4516 SET_STR
4517 "export route to non-main kernel table\n")
4518 {
4519 VTY_DECLVAR_CONTEXT(route_map_index, index);
4520
4521 return generic_set_delete(vty, index, "table", NULL);
4522 }
4523
4524 DEFUN (set_ip_nexthop_peer,
4525 set_ip_nexthop_peer_cmd,
4526 "[no] set ip next-hop peer-address",
4527 NO_STR
4528 SET_STR
4529 IP_STR
4530 "Next hop address\n"
4531 "Use peer address (for BGP only)\n")
4532 {
4533 int (*func)(struct vty *, struct route_map_index *, const char *,
4534 const char *) = strmatch(argv[0]->text, "no")
4535 ? generic_set_delete
4536 : generic_set_add;
4537
4538 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
4539 "peer-address");
4540 }
4541
4542 DEFUN (set_ip_nexthop_unchanged,
4543 set_ip_nexthop_unchanged_cmd,
4544 "[no] set ip next-hop unchanged",
4545 NO_STR
4546 SET_STR
4547 IP_STR
4548 "Next hop address\n"
4549 "Don't modify existing Next hop address\n")
4550 {
4551 int (*func)(struct vty *, struct route_map_index *, const char *,
4552 const char *) = strmatch(argv[0]->text, "no")
4553 ? generic_set_delete
4554 : generic_set_add;
4555
4556 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
4557 "unchanged");
4558 }
4559
4560 DEFUN (set_distance,
4561 set_distance_cmd,
4562 "set distance (0-255)",
4563 SET_STR
4564 "BGP Administrative Distance to use\n"
4565 "Distance value\n")
4566 {
4567 int idx_number = 2;
4568
4569 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4570 "distance", argv[idx_number]->arg);
4571 }
4572
4573 DEFUN (no_set_distance,
4574 no_set_distance_cmd,
4575 "no set distance [(0-255)]",
4576 NO_STR SET_STR
4577 "BGP Administrative Distance to use\n"
4578 "Distance value\n")
4579 {
4580 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4581 "distance", NULL);
4582 }
4583
4584 DEFUN (set_local_pref,
4585 set_local_pref_cmd,
4586 "set local-preference WORD",
4587 SET_STR
4588 "BGP local preference path attribute\n"
4589 "Preference value (0-4294967295)\n")
4590 {
4591 int idx_number = 2;
4592 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4593 "local-preference", argv[idx_number]->arg);
4594 }
4595
4596
4597 DEFUN (no_set_local_pref,
4598 no_set_local_pref_cmd,
4599 "no set local-preference [WORD]",
4600 NO_STR
4601 SET_STR
4602 "BGP local preference path attribute\n"
4603 "Preference value (0-4294967295)\n")
4604 {
4605 int idx_localpref = 3;
4606 if (argc <= idx_localpref)
4607 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4608 "local-preference", NULL);
4609 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4610 "local-preference", argv[idx_localpref]->arg);
4611 }
4612
4613
4614 DEFUN (set_weight,
4615 set_weight_cmd,
4616 "set weight (0-4294967295)",
4617 SET_STR
4618 "BGP weight for routing table\n"
4619 "Weight value\n")
4620 {
4621 int idx_number = 2;
4622 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "weight",
4623 argv[idx_number]->arg);
4624 }
4625
4626
4627 DEFUN (no_set_weight,
4628 no_set_weight_cmd,
4629 "no set weight [(0-4294967295)]",
4630 NO_STR
4631 SET_STR
4632 "BGP weight for routing table\n"
4633 "Weight value\n")
4634 {
4635 int idx_weight = 3;
4636 if (argc <= idx_weight)
4637 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4638 "weight", NULL);
4639 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4640 "weight", argv[idx_weight]->arg);
4641 }
4642
4643 DEFUN (set_label_index,
4644 set_label_index_cmd,
4645 "set label-index (0-1048560)",
4646 SET_STR
4647 "Label index to associate with the prefix\n"
4648 "Label index value\n")
4649 {
4650 int idx_number = 2;
4651 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4652 "label-index", argv[idx_number]->arg);
4653 }
4654
4655 DEFUN (no_set_label_index,
4656 no_set_label_index_cmd,
4657 "no set label-index [(0-1048560)]",
4658 NO_STR
4659 SET_STR
4660 "Label index to associate with the prefix\n"
4661 "Label index value\n")
4662 {
4663 int idx_label_index = 3;
4664 if (argc <= idx_label_index)
4665 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4666 "label-index", NULL);
4667 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4668 "label-index", argv[idx_label_index]->arg);
4669 }
4670
4671 DEFUN (set_aspath_prepend_asn,
4672 set_aspath_prepend_asn_cmd,
4673 "set as-path prepend (1-4294967295)...",
4674 SET_STR
4675 "Transform BGP AS_PATH attribute\n"
4676 "Prepend to the as-path\n"
4677 "AS number\n")
4678 {
4679 int idx_asn = 3;
4680 int ret;
4681 char *str;
4682
4683 str = argv_concat(argv, argc, idx_asn);
4684 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4685 "as-path prepend", str);
4686 XFREE(MTYPE_TMP, str);
4687
4688 return ret;
4689 }
4690
4691 DEFUN (set_aspath_prepend_lastas,
4692 set_aspath_prepend_lastas_cmd,
4693 "set as-path prepend last-as (1-10)",
4694 SET_STR
4695 "Transform BGP AS_PATH attribute\n"
4696 "Prepend to the as-path\n"
4697 "Use the peer's AS-number\n"
4698 "Number of times to insert\n")
4699 {
4700 return set_aspath_prepend_asn(self, vty, argc, argv);
4701 }
4702
4703 DEFUN (no_set_aspath_prepend,
4704 no_set_aspath_prepend_cmd,
4705 "no set as-path prepend [(1-4294967295)]",
4706 NO_STR
4707 SET_STR
4708 "Transform BGP AS_PATH attribute\n"
4709 "Prepend to the as-path\n"
4710 "AS number\n")
4711 {
4712 int idx_asn = 4;
4713 int ret;
4714 char *str;
4715
4716 str = argv_concat(argv, argc, idx_asn);
4717 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4718 "as-path prepend", str);
4719 XFREE(MTYPE_TMP, str);
4720 return ret;
4721 }
4722
4723 DEFUN (no_set_aspath_prepend_lastas,
4724 no_set_aspath_prepend_lastas_cmd,
4725 "no set as-path prepend last-as [(1-10)]",
4726 NO_STR
4727 SET_STR
4728 "Transform BGP AS_PATH attribute\n"
4729 "Prepend to the as-path\n"
4730 "Use the peers AS-number\n"
4731 "Number of times to insert\n")
4732 {
4733 return no_set_aspath_prepend(self, vty, argc, argv);
4734 }
4735
4736 DEFUN (set_aspath_exclude,
4737 set_aspath_exclude_cmd,
4738 "set as-path exclude (1-4294967295)...",
4739 SET_STR
4740 "Transform BGP AS-path attribute\n"
4741 "Exclude from the as-path\n"
4742 "AS number\n")
4743 {
4744 int idx_asn = 3;
4745 int ret;
4746 char *str;
4747
4748 str = argv_concat(argv, argc, idx_asn);
4749 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4750 "as-path exclude", str);
4751 XFREE(MTYPE_TMP, str);
4752 return ret;
4753 }
4754
4755 DEFUN (no_set_aspath_exclude,
4756 no_set_aspath_exclude_cmd,
4757 "no set as-path exclude (1-4294967295)...",
4758 NO_STR
4759 SET_STR
4760 "Transform BGP AS_PATH attribute\n"
4761 "Exclude from the as-path\n"
4762 "AS number\n")
4763 {
4764 int idx_asn = 4;
4765 int ret;
4766 char *str;
4767
4768 str = argv_concat(argv, argc, idx_asn);
4769 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4770 "as-path exclude", str);
4771 XFREE(MTYPE_TMP, str);
4772 return ret;
4773 }
4774
4775 ALIAS(no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
4776 "no set as-path exclude",
4777 NO_STR SET_STR
4778 "Transform BGP AS_PATH attribute\n"
4779 "Exclude from the as-path\n")
4780
4781 DEFUN (set_community,
4782 set_community_cmd,
4783 "set community AA:NN...",
4784 SET_STR
4785 "BGP community attribute\n"
4786 COMMUNITY_VAL_STR)
4787 {
4788 int idx_aa_nn = 2;
4789 int i;
4790 int first = 0;
4791 int additive = 0;
4792 struct buffer *b;
4793 struct community *com = NULL;
4794 char *str;
4795 char *argstr;
4796 int ret;
4797
4798 b = buffer_new(1024);
4799
4800 for (i = idx_aa_nn; i < argc; i++) {
4801 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
4802 == 0) {
4803 additive = 1;
4804 continue;
4805 }
4806
4807 if (first)
4808 buffer_putc(b, ' ');
4809 else
4810 first = 1;
4811
4812 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
4813 == 0) {
4814 buffer_putstr(b, "internet");
4815 continue;
4816 }
4817 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
4818 == 0) {
4819 buffer_putstr(b, "local-AS");
4820 continue;
4821 }
4822 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
4823 && strncmp(argv[i]->arg, "no-advertise",
4824 strlen(argv[i]->arg))
4825 == 0) {
4826 buffer_putstr(b, "no-advertise");
4827 continue;
4828 }
4829 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
4830 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
4831 == 0) {
4832 buffer_putstr(b, "no-export");
4833 continue;
4834 }
4835 if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg))
4836 == 0) {
4837 buffer_putstr(b, "blackhole");
4838 continue;
4839 }
4840 if (strncmp(argv[i]->arg, "graceful-shutdown",
4841 strlen(argv[i]->arg))
4842 == 0) {
4843 buffer_putstr(b, "graceful-shutdown");
4844 continue;
4845 }
4846 buffer_putstr(b, argv[i]->arg);
4847 }
4848 buffer_putc(b, '\0');
4849
4850 /* Fetch result string then compile it to communities attribute. */
4851 str = buffer_getstr(b);
4852 buffer_free(b);
4853
4854 if (str) {
4855 com = community_str2com(str);
4856 XFREE(MTYPE_TMP, str);
4857 }
4858
4859 /* Can't compile user input into communities attribute. */
4860 if (!com) {
4861 vty_out(vty, "%% Malformed communities attribute\n");
4862 return CMD_WARNING_CONFIG_FAILED;
4863 }
4864
4865 /* Set communites attribute string. */
4866 str = community_str(com, false);
4867
4868 if (additive) {
4869 size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
4870 argstr = XCALLOC(MTYPE_TMP, argstr_sz);
4871 strlcpy(argstr, str, argstr_sz);
4872 strlcat(argstr, " additive", argstr_sz);
4873 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4874 "community", argstr);
4875 XFREE(MTYPE_TMP, argstr);
4876 } else
4877 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4878 "community", str);
4879
4880 community_free(&com);
4881
4882 return ret;
4883 }
4884
4885 DEFUN (set_community_none,
4886 set_community_none_cmd,
4887 "set community none",
4888 SET_STR
4889 "BGP community attribute\n"
4890 "No community attribute\n")
4891 {
4892 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4893 "community", "none");
4894 }
4895
4896 DEFUN (no_set_community,
4897 no_set_community_cmd,
4898 "no set community AA:NN...",
4899 NO_STR
4900 SET_STR
4901 "BGP community attribute\n"
4902 COMMUNITY_VAL_STR)
4903 {
4904 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4905 "community", NULL);
4906 }
4907
4908 ALIAS (no_set_community,
4909 no_set_community_short_cmd,
4910 "no set community",
4911 NO_STR
4912 SET_STR
4913 "BGP community attribute\n")
4914
4915
4916 DEFUN (set_community_delete,
4917 set_community_delete_cmd,
4918 "set comm-list <(1-99)|(100-500)|WORD> delete",
4919 SET_STR
4920 "set BGP community list (for deletion)\n"
4921 "Community-list number (standard)\n"
4922 "Community-list number (expanded)\n"
4923 "Community-list name\n"
4924 "Delete matching communities\n")
4925 {
4926 int idx_comm_list = 2;
4927 char *args;
4928
4929 args = argv_concat(argv, argc, idx_comm_list);
4930 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
4931 args);
4932 XFREE(MTYPE_TMP, args);
4933
4934 return CMD_SUCCESS;
4935 }
4936
4937 DEFUN (no_set_community_delete,
4938 no_set_community_delete_cmd,
4939 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
4940 NO_STR
4941 SET_STR
4942 "set BGP community list (for deletion)\n"
4943 "Community-list number (standard)\n"
4944 "Community-list number (expanded)\n"
4945 "Community-list name\n"
4946 "Delete matching communities\n")
4947 {
4948 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4949 "comm-list", NULL);
4950 }
4951
4952 DEFUN (set_lcommunity,
4953 set_lcommunity_cmd,
4954 "set large-community AA:BB:CC...",
4955 SET_STR
4956 "BGP large community attribute\n"
4957 "Large Community number in aa:bb:cc format or additive\n")
4958 {
4959 int ret;
4960 char *str;
4961
4962 str = argv_concat(argv, argc, 2);
4963 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4964 "large-community", str);
4965 XFREE(MTYPE_TMP, str);
4966
4967 return ret;
4968 }
4969
4970 DEFUN (set_lcommunity_none,
4971 set_lcommunity_none_cmd,
4972 "set large-community none",
4973 SET_STR
4974 "BGP large community attribute\n"
4975 "No large community attribute\n")
4976 {
4977 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4978 "large-community", "none");
4979 }
4980
4981 DEFUN (no_set_lcommunity,
4982 no_set_lcommunity_cmd,
4983 "no set large-community none",
4984 NO_STR
4985 SET_STR
4986 "BGP large community attribute\n"
4987 "No community attribute\n")
4988 {
4989 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4990 "large-community", NULL);
4991 }
4992
4993 DEFUN (no_set_lcommunity1,
4994 no_set_lcommunity1_cmd,
4995 "no set large-community AA:BB:CC...",
4996 NO_STR
4997 SET_STR
4998 "BGP large community attribute\n"
4999 "Large community in AA:BB:CC... format or additive\n")
5000 {
5001 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5002 "large-community", NULL);
5003 }
5004
5005 ALIAS (no_set_lcommunity1,
5006 no_set_lcommunity1_short_cmd,
5007 "no set large-community",
5008 NO_STR
5009 SET_STR
5010 "BGP large community attribute\n")
5011
5012 DEFUN (set_lcommunity_delete,
5013 set_lcommunity_delete_cmd,
5014 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
5015 SET_STR
5016 "set BGP large community list (for deletion)\n"
5017 "Large Community-list number (standard)\n"
5018 "Large Communitly-list number (expanded)\n"
5019 "Large Community-list name\n"
5020 "Delete matching large communities\n")
5021 {
5022 int idx_lcomm_list = 2;
5023 char *args;
5024
5025 args = argv_concat(argv, argc, idx_lcomm_list);
5026 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5027 "large-comm-list", args);
5028 XFREE(MTYPE_TMP, args);
5029
5030 return CMD_SUCCESS;
5031 }
5032
5033 DEFUN (no_set_lcommunity_delete,
5034 no_set_lcommunity_delete_cmd,
5035 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
5036 NO_STR
5037 SET_STR
5038 "set BGP large community list (for deletion)\n"
5039 "Large Community-list number (standard)\n"
5040 "Large Communitly-list number (expanded)\n"
5041 "Large Community-list name\n"
5042 "Delete matching large communities\n")
5043 {
5044 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5045 "large-comm-list", NULL);
5046 }
5047
5048 ALIAS (no_set_lcommunity_delete,
5049 no_set_lcommunity_delete_short_cmd,
5050 "no set large-comm-list",
5051 NO_STR
5052 SET_STR
5053 "set BGP large community list (for deletion)\n")
5054
5055 DEFUN (set_ecommunity_rt,
5056 set_ecommunity_rt_cmd,
5057 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
5058 SET_STR
5059 "BGP extended community attribute\n"
5060 "Route Target extended community\n"
5061 "VPN extended community\n")
5062 {
5063 int idx_asn_nn = 3;
5064 int ret;
5065 char *str;
5066
5067 str = argv_concat(argv, argc, idx_asn_nn);
5068 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5069 "extcommunity rt", str);
5070 XFREE(MTYPE_TMP, str);
5071
5072 return ret;
5073 }
5074
5075 DEFUN (no_set_ecommunity_rt,
5076 no_set_ecommunity_rt_cmd,
5077 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
5078 NO_STR
5079 SET_STR
5080 "BGP extended community attribute\n"
5081 "Route Target extended community\n"
5082 "VPN extended community\n")
5083 {
5084 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5085 "extcommunity rt", NULL);
5086 }
5087
5088 ALIAS (no_set_ecommunity_rt,
5089 no_set_ecommunity_rt_short_cmd,
5090 "no set extcommunity rt",
5091 NO_STR
5092 SET_STR
5093 "BGP extended community attribute\n"
5094 "Route Target extended community\n")
5095
5096 DEFUN (set_ecommunity_soo,
5097 set_ecommunity_soo_cmd,
5098 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
5099 SET_STR
5100 "BGP extended community attribute\n"
5101 "Site-of-Origin extended community\n"
5102 "VPN extended community\n")
5103 {
5104 int idx_asn_nn = 3;
5105 int ret;
5106 char *str;
5107
5108 str = argv_concat(argv, argc, idx_asn_nn);
5109 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5110 "extcommunity soo", str);
5111 XFREE(MTYPE_TMP, str);
5112 return ret;
5113 }
5114
5115
5116 DEFUN (no_set_ecommunity_soo,
5117 no_set_ecommunity_soo_cmd,
5118 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
5119 NO_STR
5120 SET_STR
5121 "BGP extended community attribute\n"
5122 "Site-of-Origin extended community\n"
5123 "VPN extended community\n")
5124 {
5125 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5126 "extcommunity soo", NULL);
5127 }
5128
5129 ALIAS (no_set_ecommunity_soo,
5130 no_set_ecommunity_soo_short_cmd,
5131 "no set extcommunity soo",
5132 NO_STR
5133 SET_STR
5134 "GP extended community attribute\n"
5135 "Site-of-Origin extended community\n")
5136
5137 DEFUN (set_ecommunity_lb,
5138 set_ecommunity_lb_cmd,
5139 "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
5140 SET_STR
5141 "BGP extended community attribute\n"
5142 "Link bandwidth extended community\n"
5143 "Bandwidth value in Mbps\n"
5144 "Cumulative bandwidth of all multipaths (outbound-only)\n"
5145 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
5146 "Attribute is set as non-transitive\n")
5147 {
5148 int idx_lb = 3;
5149 int ret;
5150 char *str;
5151
5152 str = argv_concat(argv, argc, idx_lb);
5153 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5154 "extcommunity bandwidth", str);
5155 XFREE(MTYPE_TMP, str);
5156 return ret;
5157 }
5158
5159
5160 DEFUN (no_set_ecommunity_lb,
5161 no_set_ecommunity_lb_cmd,
5162 "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
5163 NO_STR
5164 SET_STR
5165 "BGP extended community attribute\n"
5166 "Link bandwidth extended community\n"
5167 "Bandwidth value in Mbps\n"
5168 "Cumulative bandwidth of all multipaths (outbound-only)\n"
5169 "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
5170 "Attribute is set as non-transitive\n")
5171 {
5172 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5173 "extcommunity bandwidth", NULL);
5174 }
5175
5176 ALIAS (no_set_ecommunity_lb,
5177 no_set_ecommunity_lb_short_cmd,
5178 "no set extcommunity bandwidth",
5179 NO_STR
5180 SET_STR
5181 "BGP extended community attribute\n"
5182 "Link bandwidth extended community\n")
5183
5184 DEFUN (set_origin,
5185 set_origin_cmd,
5186 "set origin <egp|igp|incomplete>",
5187 SET_STR
5188 "BGP origin code\n"
5189 "remote EGP\n"
5190 "local IGP\n"
5191 "unknown heritage\n")
5192 {
5193 int idx_origin = 2;
5194 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
5195 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5196 "origin", "igp");
5197 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5198 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5199 "origin", "egp");
5200 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5201 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5202 "origin", "incomplete");
5203
5204 vty_out(vty, "%% Invalid set origin type\n");
5205 return CMD_WARNING_CONFIG_FAILED;
5206 }
5207
5208
5209 DEFUN (no_set_origin,
5210 no_set_origin_cmd,
5211 "no set origin [<egp|igp|incomplete>]",
5212 NO_STR
5213 SET_STR
5214 "BGP origin code\n"
5215 "remote EGP\n"
5216 "local IGP\n"
5217 "unknown heritage\n")
5218 {
5219 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5220 "origin", NULL);
5221 }
5222
5223
5224 DEFUN (set_atomic_aggregate,
5225 set_atomic_aggregate_cmd,
5226 "set atomic-aggregate",
5227 SET_STR
5228 "BGP atomic aggregate attribute\n" )
5229 {
5230 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5231 "atomic-aggregate", NULL);
5232 }
5233
5234 DEFUN (no_set_atomic_aggregate,
5235 no_set_atomic_aggregate_cmd,
5236 "no set atomic-aggregate",
5237 NO_STR
5238 SET_STR
5239 "BGP atomic aggregate attribute\n" )
5240 {
5241 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5242 "atomic-aggregate", NULL);
5243 }
5244
5245 DEFUN (set_aggregator_as,
5246 set_aggregator_as_cmd,
5247 "set aggregator as (1-4294967295) A.B.C.D",
5248 SET_STR
5249 "BGP aggregator attribute\n"
5250 "AS number of aggregator\n"
5251 "AS number\n"
5252 "IP address of aggregator\n")
5253 {
5254 int idx_number = 3;
5255 int idx_ipv4 = 4;
5256 int ret;
5257 struct in_addr address;
5258 char *argstr;
5259 size_t argstr_len;
5260
5261 ret = inet_aton(argv[idx_ipv4]->arg, &address);
5262 if (ret == 0) {
5263 vty_out(vty, "Aggregator IP address is invalid\n");
5264 return CMD_WARNING_CONFIG_FAILED;
5265 }
5266
5267 argstr_len =
5268 strlen(argv[idx_number]->arg) + strlen(argv[idx_ipv4]->arg) + 2;
5269 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
5270
5271 snprintf(argstr, argstr_len, "%s %s", argv[idx_number]->arg,
5272 argv[idx_ipv4]->arg);
5273
5274 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5275 "aggregator as", argstr);
5276
5277 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
5278
5279 return ret;
5280 }
5281
5282
5283 DEFUN (no_set_aggregator_as,
5284 no_set_aggregator_as_cmd,
5285 "no set aggregator as [(1-4294967295) A.B.C.D]",
5286 NO_STR
5287 SET_STR
5288 "BGP aggregator attribute\n"
5289 "AS number of aggregator\n"
5290 "AS number\n"
5291 "IP address of aggregator\n")
5292 {
5293 int idx_asn = 4;
5294 int idx_ip = 5;
5295 int ret;
5296 struct in_addr address;
5297 char *argstr;
5298 size_t argstr_len;
5299
5300 if (argc <= idx_asn)
5301 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5302 "aggregator as", NULL);
5303
5304 ret = inet_aton(argv[idx_ip]->arg, &address);
5305 if (ret == 0) {
5306 vty_out(vty, "Aggregator IP address is invalid\n");
5307 return CMD_WARNING_CONFIG_FAILED;
5308 }
5309
5310 argstr_len = strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg) + 2;
5311 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
5312
5313 snprintf(argstr, argstr_len, "%s %s", argv[idx_asn]->arg,
5314 argv[idx_ip]->arg);
5315
5316 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5317 "aggregator as", argstr);
5318
5319 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
5320
5321 return ret;
5322 }
5323
5324 DEFUN (match_ipv6_next_hop,
5325 match_ipv6_next_hop_cmd,
5326 "match ipv6 next-hop X:X::X:X",
5327 MATCH_STR
5328 IPV6_STR
5329 "Match IPv6 next-hop address of route\n"
5330 "IPv6 address of next hop\n")
5331 {
5332 int idx_ipv6 = 3;
5333 return bgp_route_match_add(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
5334 RMAP_EVENT_MATCH_ADDED);
5335 }
5336
5337 DEFUN (no_match_ipv6_next_hop,
5338 no_match_ipv6_next_hop_cmd,
5339 "no match ipv6 next-hop X:X::X:X",
5340 NO_STR
5341 MATCH_STR
5342 IPV6_STR
5343 "Match IPv6 next-hop address of route\n"
5344 "IPv6 address of next hop\n")
5345 {
5346 int idx_ipv6 = 4;
5347 return bgp_route_match_delete(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
5348 RMAP_EVENT_MATCH_DELETED);
5349 }
5350
5351 DEFPY (match_ipv4_next_hop,
5352 match_ipv4_next_hop_cmd,
5353 "match ip next-hop address A.B.C.D",
5354 MATCH_STR
5355 IP_STR
5356 "Match IP next-hop address of route\n"
5357 "IP address\n"
5358 "IP address of next-hop\n")
5359 {
5360 int idx_ipv4 = 4;
5361
5362 return bgp_route_match_add(vty, "ip next-hop address",
5363 argv[idx_ipv4]->arg, RMAP_EVENT_MATCH_ADDED);
5364 }
5365
5366 DEFPY (no_match_ipv4_next_hop,
5367 no_match_ipv4_next_hop_cmd,
5368 "no match ip next-hop address [A.B.C.D]",
5369 NO_STR
5370 MATCH_STR
5371 IP_STR
5372 "Match IP next-hop address of route\n"
5373 "IP address\n"
5374 "IP address of next-hop\n")
5375 {
5376 return bgp_route_match_delete(vty, "ip next-hop address", NULL,
5377 RMAP_EVENT_MATCH_DELETED);
5378 }
5379
5380 DEFUN (set_ipv6_nexthop_peer,
5381 set_ipv6_nexthop_peer_cmd,
5382 "set ipv6 next-hop peer-address",
5383 SET_STR
5384 IPV6_STR
5385 "Next hop address\n"
5386 "Use peer address (for BGP only)\n")
5387 {
5388 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5389 "ipv6 next-hop peer-address", NULL);
5390 }
5391
5392 DEFUN (no_set_ipv6_nexthop_peer,
5393 no_set_ipv6_nexthop_peer_cmd,
5394 "no set ipv6 next-hop peer-address",
5395 NO_STR
5396 SET_STR
5397 IPV6_STR
5398 "IPv6 next-hop address\n"
5399 "Use peer address (for BGP only)\n")
5400 {
5401 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5402 "ipv6 next-hop peer-address", NULL);
5403 }
5404
5405 DEFUN (set_ipv6_nexthop_prefer_global,
5406 set_ipv6_nexthop_prefer_global_cmd,
5407 "set ipv6 next-hop prefer-global",
5408 SET_STR
5409 IPV6_STR
5410 "IPv6 next-hop address\n"
5411 "Prefer global over link-local if both exist\n")
5412 {
5413 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5414 "ipv6 next-hop prefer-global", NULL);
5415 ;
5416 }
5417
5418 DEFUN (no_set_ipv6_nexthop_prefer_global,
5419 no_set_ipv6_nexthop_prefer_global_cmd,
5420 "no set ipv6 next-hop prefer-global",
5421 NO_STR
5422 SET_STR
5423 IPV6_STR
5424 "IPv6 next-hop address\n"
5425 "Prefer global over link-local if both exist\n")
5426 {
5427 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5428 "ipv6 next-hop prefer-global", NULL);
5429 }
5430
5431 DEFUN (set_ipv6_nexthop_global,
5432 set_ipv6_nexthop_global_cmd,
5433 "set ipv6 next-hop global X:X::X:X",
5434 SET_STR
5435 IPV6_STR
5436 "IPv6 next-hop address\n"
5437 "IPv6 global address\n"
5438 "IPv6 address of next hop\n")
5439 {
5440 int idx_ipv6 = 4;
5441 struct in6_addr addr;
5442 int ret;
5443
5444 ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr);
5445 if (!ret) {
5446 vty_out(vty, "%% Malformed nexthop address\n");
5447 return CMD_WARNING_CONFIG_FAILED;
5448 }
5449 if (IN6_IS_ADDR_UNSPECIFIED(&addr) || IN6_IS_ADDR_LOOPBACK(&addr)
5450 || IN6_IS_ADDR_MULTICAST(&addr) || IN6_IS_ADDR_LINKLOCAL(&addr)) {
5451 vty_out(vty, "%% Invalid global nexthop address\n");
5452 return CMD_WARNING_CONFIG_FAILED;
5453 }
5454
5455 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5456 "ipv6 next-hop global", argv[idx_ipv6]->arg);
5457 }
5458
5459
5460 DEFUN (no_set_ipv6_nexthop_global,
5461 no_set_ipv6_nexthop_global_cmd,
5462 "no set ipv6 next-hop global X:X::X:X",
5463 NO_STR
5464 SET_STR
5465 IPV6_STR
5466 "IPv6 next-hop address\n"
5467 "IPv6 global address\n"
5468 "IPv6 address of next hop\n")
5469 {
5470 int idx_ipv6 = 5;
5471 if (argc <= idx_ipv6)
5472 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5473 "ipv6 next-hop global", NULL);
5474 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5475 "ipv6 next-hop global", argv[idx_ipv6]->arg);
5476 }
5477
5478 #ifdef KEEP_OLD_VPN_COMMANDS
5479 DEFUN (set_vpn_nexthop,
5480 set_vpn_nexthop_cmd,
5481 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
5482 SET_STR
5483 "VPNv4 information\n"
5484 "VPN next-hop address\n"
5485 "IP address of next hop\n"
5486 "VPNv6 information\n"
5487 "VPN next-hop address\n"
5488 "IPv6 address of next hop\n")
5489 {
5490 int idx_ip = 3;
5491 afi_t afi;
5492 int idx = 0;
5493
5494 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
5495 if (afi == AFI_IP)
5496 return generic_set_add(
5497 vty, VTY_GET_CONTEXT(route_map_index),
5498 "ipv4 vpn next-hop", argv[idx_ip]->arg);
5499 else
5500 return generic_set_add(
5501 vty, VTY_GET_CONTEXT(route_map_index),
5502 "ipv6 vpn next-hop", argv[idx_ip]->arg);
5503 }
5504 return CMD_SUCCESS;
5505 }
5506
5507 DEFUN (no_set_vpn_nexthop,
5508 no_set_vpn_nexthop_cmd,
5509 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
5510 NO_STR
5511 SET_STR
5512 "VPNv4 information\n"
5513 "VPN next-hop address\n"
5514 "IP address of next hop\n"
5515 "VPNv6 information\n"
5516 "VPN next-hop address\n"
5517 "IPv6 address of next hop\n")
5518 {
5519 int idx_ip = 4;
5520 char *arg;
5521 afi_t afi;
5522 int idx = 0;
5523
5524 if (argc <= idx_ip)
5525 arg = NULL;
5526 else
5527 arg = argv[idx_ip]->arg;
5528 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
5529 if (afi == AFI_IP)
5530 return generic_set_delete(
5531 vty, VTY_GET_CONTEXT(route_map_index),
5532 "ipv4 vpn next-hop", arg);
5533 else
5534 return generic_set_delete(
5535 vty, VTY_GET_CONTEXT(route_map_index),
5536 "ipv6 vpn next-hop", argv[idx_ip]->arg);
5537 }
5538 return CMD_SUCCESS;
5539 }
5540 #endif /* KEEP_OLD_VPN_COMMANDS */
5541
5542 DEFUN (set_ipx_vpn_nexthop,
5543 set_ipx_vpn_nexthop_cmd,
5544 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
5545 SET_STR
5546 "IPv4 information\n"
5547 "IPv6 information\n"
5548 "VPN information\n"
5549 "VPN next-hop address\n"
5550 "IP address of next hop\n"
5551 "IPv6 address of next hop\n")
5552 {
5553 int idx_ip = 4;
5554 afi_t afi;
5555 int idx = 0;
5556
5557 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
5558 if (afi == AFI_IP)
5559 return generic_set_add(
5560 vty, VTY_GET_CONTEXT(route_map_index),
5561 "ipv4 vpn next-hop", argv[idx_ip]->arg);
5562 else
5563 return generic_set_add(
5564 vty, VTY_GET_CONTEXT(route_map_index),
5565 "ipv6 vpn next-hop", argv[idx_ip]->arg);
5566 }
5567 return CMD_SUCCESS;
5568 }
5569
5570 DEFUN (no_set_ipx_vpn_nexthop,
5571 no_set_ipx_vpn_nexthop_cmd,
5572 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
5573 NO_STR
5574 SET_STR
5575 "IPv4 information\n"
5576 "IPv6 information\n"
5577 "VPN information\n"
5578 "VPN next-hop address\n"
5579 "IP address of next hop\n"
5580 "IPv6 address of next hop\n")
5581 {
5582 int idx_ip = 5;
5583 char *arg;
5584 afi_t afi;
5585 int idx = 0;
5586
5587 if (argc <= idx_ip)
5588 arg = NULL;
5589 else
5590 arg = argv[idx_ip]->arg;
5591 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
5592 if (afi == AFI_IP)
5593 return generic_set_delete(
5594 vty, VTY_GET_CONTEXT(route_map_index),
5595 "ipv4 vpn next-hop", arg);
5596 else
5597 return generic_set_delete(
5598 vty, VTY_GET_CONTEXT(route_map_index),
5599 "ipv6 vpn next-hop", arg);
5600 }
5601 return CMD_SUCCESS;
5602 }
5603
5604 DEFUN (set_originator_id,
5605 set_originator_id_cmd,
5606 "set originator-id A.B.C.D",
5607 SET_STR
5608 "BGP originator ID attribute\n"
5609 "IP address of originator\n")
5610 {
5611 int idx_ipv4 = 2;
5612 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
5613 "originator-id", argv[idx_ipv4]->arg);
5614 }
5615
5616
5617 DEFUN (no_set_originator_id,
5618 no_set_originator_id_cmd,
5619 "no set originator-id [A.B.C.D]",
5620 NO_STR
5621 SET_STR
5622 "BGP originator ID attribute\n"
5623 "IP address of originator\n")
5624 {
5625 int idx = 0;
5626 char *arg =
5627 argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
5628
5629 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
5630 "originator-id", arg);
5631 }
5632
5633
5634 /* Initialization of route map. */
5635 void bgp_route_map_init(void)
5636 {
5637 route_map_init();
5638
5639 route_map_add_hook(bgp_route_map_add);
5640 route_map_delete_hook(bgp_route_map_delete);
5641 route_map_event_hook(bgp_route_map_event);
5642
5643 route_map_match_interface_hook(generic_match_add);
5644 route_map_no_match_interface_hook(generic_match_delete);
5645
5646 route_map_match_ip_address_hook(generic_match_add);
5647 route_map_no_match_ip_address_hook(generic_match_delete);
5648
5649 route_map_match_ip_address_prefix_list_hook(generic_match_add);
5650 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
5651
5652 route_map_match_ip_next_hop_hook(generic_match_add);
5653 route_map_no_match_ip_next_hop_hook(generic_match_delete);
5654
5655 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
5656 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
5657
5658 route_map_match_ip_next_hop_type_hook(generic_match_add);
5659 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
5660
5661 route_map_match_ipv6_address_hook(generic_match_add);
5662 route_map_no_match_ipv6_address_hook(generic_match_delete);
5663
5664 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
5665 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
5666
5667 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
5668 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
5669
5670 route_map_match_metric_hook(generic_match_add);
5671 route_map_no_match_metric_hook(generic_match_delete);
5672
5673 route_map_match_tag_hook(generic_match_add);
5674 route_map_no_match_tag_hook(generic_match_delete);
5675
5676 route_map_set_srte_color_hook(generic_set_add);
5677 route_map_no_set_srte_color_hook(generic_set_delete);
5678
5679 route_map_set_ip_nexthop_hook(generic_set_add);
5680 route_map_no_set_ip_nexthop_hook(generic_set_delete);
5681
5682 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
5683 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
5684
5685 route_map_set_metric_hook(generic_set_add);
5686 route_map_no_set_metric_hook(generic_set_delete);
5687
5688 route_map_set_tag_hook(generic_set_add);
5689 route_map_no_set_tag_hook(generic_set_delete);
5690
5691 route_map_install_match(&route_match_peer_cmd);
5692 route_map_install_match(&route_match_local_pref_cmd);
5693 #ifdef HAVE_SCRIPTING
5694 route_map_install_match(&route_match_script_cmd);
5695 #endif
5696 route_map_install_match(&route_match_ip_address_cmd);
5697 route_map_install_match(&route_match_ip_next_hop_cmd);
5698 route_map_install_match(&route_match_ip_route_source_cmd);
5699 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
5700 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
5701 route_map_install_match(&route_match_ip_next_hop_type_cmd);
5702 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
5703 route_map_install_match(&route_match_aspath_cmd);
5704 route_map_install_match(&route_match_community_cmd);
5705 route_map_install_match(&route_match_lcommunity_cmd);
5706 route_map_install_match(&route_match_ecommunity_cmd);
5707 route_map_install_match(&route_match_local_pref_cmd);
5708 route_map_install_match(&route_match_metric_cmd);
5709 route_map_install_match(&route_match_origin_cmd);
5710 route_map_install_match(&route_match_probability_cmd);
5711 route_map_install_match(&route_match_interface_cmd);
5712 route_map_install_match(&route_match_tag_cmd);
5713 route_map_install_match(&route_match_mac_address_cmd);
5714 route_map_install_match(&route_match_evpn_vni_cmd);
5715 route_map_install_match(&route_match_evpn_route_type_cmd);
5716 route_map_install_match(&route_match_evpn_rd_cmd);
5717 route_map_install_match(&route_match_evpn_default_route_cmd);
5718 route_map_install_match(&route_match_vrl_source_vrf_cmd);
5719
5720 route_map_install_set(&route_set_table_id_cmd);
5721 route_map_install_set(&route_set_srte_color_cmd);
5722 route_map_install_set(&route_set_ip_nexthop_cmd);
5723 route_map_install_set(&route_set_local_pref_cmd);
5724 route_map_install_set(&route_set_weight_cmd);
5725 route_map_install_set(&route_set_label_index_cmd);
5726 route_map_install_set(&route_set_metric_cmd);
5727 route_map_install_set(&route_set_distance_cmd);
5728 route_map_install_set(&route_set_aspath_prepend_cmd);
5729 route_map_install_set(&route_set_aspath_exclude_cmd);
5730 route_map_install_set(&route_set_origin_cmd);
5731 route_map_install_set(&route_set_atomic_aggregate_cmd);
5732 route_map_install_set(&route_set_aggregator_as_cmd);
5733 route_map_install_set(&route_set_community_cmd);
5734 route_map_install_set(&route_set_community_delete_cmd);
5735 route_map_install_set(&route_set_lcommunity_cmd);
5736 route_map_install_set(&route_set_lcommunity_delete_cmd);
5737 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
5738 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
5739 route_map_install_set(&route_set_originator_id_cmd);
5740 route_map_install_set(&route_set_ecommunity_rt_cmd);
5741 route_map_install_set(&route_set_ecommunity_soo_cmd);
5742 route_map_install_set(&route_set_ecommunity_lb_cmd);
5743 route_map_install_set(&route_set_tag_cmd);
5744 route_map_install_set(&route_set_label_index_cmd);
5745
5746 install_element(RMAP_NODE, &match_peer_cmd);
5747 install_element(RMAP_NODE, &match_peer_local_cmd);
5748 install_element(RMAP_NODE, &no_match_peer_cmd);
5749 install_element(RMAP_NODE, &match_ip_route_source_cmd);
5750 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
5751 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
5752 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
5753 install_element(RMAP_NODE, &match_mac_address_cmd);
5754 install_element(RMAP_NODE, &no_match_mac_address_cmd);
5755 install_element(RMAP_NODE, &match_evpn_vni_cmd);
5756 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
5757 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
5758 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
5759 install_element(RMAP_NODE, &match_evpn_rd_cmd);
5760 install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
5761 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
5762 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
5763 install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
5764 install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
5765
5766 install_element(RMAP_NODE, &match_aspath_cmd);
5767 install_element(RMAP_NODE, &no_match_aspath_cmd);
5768 install_element(RMAP_NODE, &match_local_pref_cmd);
5769 install_element(RMAP_NODE, &no_match_local_pref_cmd);
5770 install_element(RMAP_NODE, &match_community_cmd);
5771 install_element(RMAP_NODE, &no_match_community_cmd);
5772 install_element(RMAP_NODE, &match_lcommunity_cmd);
5773 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
5774 install_element(RMAP_NODE, &match_ecommunity_cmd);
5775 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
5776 install_element(RMAP_NODE, &match_origin_cmd);
5777 install_element(RMAP_NODE, &no_match_origin_cmd);
5778 install_element(RMAP_NODE, &match_probability_cmd);
5779 install_element(RMAP_NODE, &no_match_probability_cmd);
5780
5781 install_element(RMAP_NODE, &no_set_table_id_cmd);
5782 install_element(RMAP_NODE, &set_table_id_cmd);
5783 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
5784 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
5785 install_element(RMAP_NODE, &set_local_pref_cmd);
5786 install_element(RMAP_NODE, &set_distance_cmd);
5787 install_element(RMAP_NODE, &no_set_distance_cmd);
5788 install_element(RMAP_NODE, &no_set_local_pref_cmd);
5789 install_element(RMAP_NODE, &set_weight_cmd);
5790 install_element(RMAP_NODE, &set_label_index_cmd);
5791 install_element(RMAP_NODE, &no_set_weight_cmd);
5792 install_element(RMAP_NODE, &no_set_label_index_cmd);
5793 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
5794 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
5795 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
5796 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
5797 install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
5798 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
5799 install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
5800 install_element(RMAP_NODE, &set_origin_cmd);
5801 install_element(RMAP_NODE, &no_set_origin_cmd);
5802 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
5803 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
5804 install_element(RMAP_NODE, &set_aggregator_as_cmd);
5805 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
5806 install_element(RMAP_NODE, &set_community_cmd);
5807 install_element(RMAP_NODE, &set_community_none_cmd);
5808 install_element(RMAP_NODE, &no_set_community_cmd);
5809 install_element(RMAP_NODE, &no_set_community_short_cmd);
5810 install_element(RMAP_NODE, &set_community_delete_cmd);
5811 install_element(RMAP_NODE, &no_set_community_delete_cmd);
5812 install_element(RMAP_NODE, &set_lcommunity_cmd);
5813 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
5814 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
5815 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
5816 install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
5817 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
5818 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
5819 install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
5820 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
5821 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
5822 install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
5823 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
5824 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
5825 install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
5826 install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
5827 install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
5828 install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
5829 #ifdef KEEP_OLD_VPN_COMMANDS
5830 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
5831 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
5832 #endif /* KEEP_OLD_VPN_COMMANDS */
5833 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
5834 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
5835 install_element(RMAP_NODE, &set_originator_id_cmd);
5836 install_element(RMAP_NODE, &no_set_originator_id_cmd);
5837
5838 route_map_install_match(&route_match_ipv6_address_cmd);
5839 route_map_install_match(&route_match_ipv6_next_hop_cmd);
5840 route_map_install_match(&route_match_ipv4_next_hop_cmd);
5841 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
5842 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
5843 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
5844 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
5845 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
5846 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
5847
5848 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
5849 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
5850 install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
5851 install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
5852 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
5853 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
5854 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
5855 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
5856 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
5857 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
5858 #ifdef HAVE_SCRIPTING
5859 install_element(RMAP_NODE, &match_script_cmd);
5860 #endif
5861 }
5862
5863 void bgp_route_map_terminate(void)
5864 {
5865 /* ToDo: Cleanup all the used memory */
5866 route_map_finish();
5867 }