Line data Source code
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 : #include "frrscript.h"
33 : #ifdef HAVE_LIBPCRE2_POSIX
34 : #ifndef _FRR_PCRE2_POSIX
35 : #define _FRR_PCRE2_POSIX
36 : #include <pcre2posix.h>
37 : #endif /* _FRR_PCRE2_POSIX */
38 : #elif defined(HAVE_LIBPCREPOSIX)
39 : #include <pcreposix.h>
40 : #else
41 : #include <regex.h>
42 : #endif /* HAVE_LIBPCRE2_POSIX */
43 : #include "buffer.h"
44 : #include "sockunion.h"
45 : #include "hash.h"
46 : #include "queue.h"
47 : #include "frrstr.h"
48 : #include "network.h"
49 : #include "lib/northbound_cli.h"
50 :
51 : #include "bgpd/bgpd.h"
52 : #include "bgpd/bgp_table.h"
53 : #include "bgpd/bgp_attr.h"
54 : #include "bgpd/bgp_aspath.h"
55 : #include "bgpd/bgp_packet.h"
56 : #include "bgpd/bgp_route.h"
57 : #include "bgpd/bgp_zebra.h"
58 : #include "bgpd/bgp_regex.h"
59 : #include "bgpd/bgp_community.h"
60 : #include "bgpd/bgp_community_alias.h"
61 : #include "bgpd/bgp_clist.h"
62 : #include "bgpd/bgp_filter.h"
63 : #include "bgpd/bgp_mplsvpn.h"
64 : #include "bgpd/bgp_ecommunity.h"
65 : #include "bgpd/bgp_lcommunity.h"
66 : #include "bgpd/bgp_vty.h"
67 : #include "bgpd/bgp_debug.h"
68 : #include "bgpd/bgp_evpn.h"
69 : #include "bgpd/bgp_evpn_private.h"
70 : #include "bgpd/bgp_evpn_vty.h"
71 : #include "bgpd/bgp_mplsvpn.h"
72 : #include "bgpd/bgp_pbr.h"
73 : #include "bgpd/bgp_flowspec_util.h"
74 : #include "bgpd/bgp_encap_types.h"
75 : #include "bgpd/bgp_mpath.h"
76 : #include "bgpd/bgp_script.h"
77 :
78 : #ifdef ENABLE_BGP_VNC
79 : #include "bgpd/rfapi/bgp_rfapi_cfg.h"
80 : #endif
81 :
82 : #include "bgpd/bgp_routemap_clippy.c"
83 :
84 : /* Memo of route-map commands.
85 :
86 : o Cisco route-map
87 :
88 : match as-path : Done
89 : community : Done
90 : interface : Done
91 : ip address : Done
92 : ip next-hop : Done
93 : ip route-source : Done
94 : ip prefix-list : Done
95 : ipv6 address : Done
96 : ipv6 next-hop : Done
97 : ipv6 route-source: (This will not be implemented by bgpd)
98 : ipv6 prefix-list : Done
99 : length : (This will not be implemented by bgpd)
100 : metric : Done
101 : route-type : (This will not be implemented by bgpd)
102 : tag : Done
103 : local-preference : Done
104 :
105 : set as-path prepend : Done
106 : as-path tag : Not yet
107 : automatic-tag : (This will not be implemented by bgpd)
108 : community : Done
109 : large-community : Done
110 : large-comm-list : Done
111 : comm-list : Not yet
112 : dampning : Not yet
113 : default : (This will not be implemented by bgpd)
114 : interface : (This will not be implemented by bgpd)
115 : ip default : (This will not be implemented by bgpd)
116 : ip next-hop : Done
117 : ip precedence : (This will not be implemented by bgpd)
118 : ip tos : (This will not be implemented by bgpd)
119 : level : (This will not be implemented by bgpd)
120 : local-preference : Done
121 : metric : Done
122 : metric-type : Not yet
123 : origin : Done
124 : tag : Done
125 : weight : Done
126 : table : Done
127 :
128 : o Local extensions
129 :
130 : set ipv6 next-hop global: Done
131 : set ipv6 next-hop prefer-global: Done
132 : set ipv6 next-hop local : Done
133 : set as-path exclude : Done
134 :
135 : */
136 :
137 : /* generic value manipulation to be shared in multiple rules */
138 :
139 : #define RMAP_VALUE_SET 0
140 : #define RMAP_VALUE_ADD 1
141 : #define RMAP_VALUE_SUB 2
142 :
143 : struct rmap_value {
144 : uint8_t action;
145 : uint8_t variable;
146 : uint32_t value;
147 : };
148 :
149 0 : static int route_value_match(struct rmap_value *rv, uint32_t value)
150 : {
151 0 : if (rv->variable == 0 && value == rv->value)
152 : return RMAP_MATCH;
153 :
154 : return RMAP_NOMATCH;
155 : }
156 :
157 0 : static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
158 : struct peer *peer)
159 : {
160 0 : uint32_t value;
161 :
162 0 : switch (rv->variable) {
163 0 : case 1:
164 0 : value = peer->rtt;
165 0 : break;
166 0 : default:
167 0 : value = rv->value;
168 0 : break;
169 : }
170 :
171 0 : switch (rv->action) {
172 0 : case RMAP_VALUE_ADD:
173 0 : if (current > UINT32_MAX - value)
174 : return UINT32_MAX;
175 0 : return current + value;
176 0 : case RMAP_VALUE_SUB:
177 0 : if (current <= value)
178 : return 0;
179 0 : return current - value;
180 : default:
181 : return value;
182 : }
183 : }
184 :
185 0 : static void *route_value_compile(const char *arg)
186 : {
187 0 : uint8_t action = RMAP_VALUE_SET, var = 0;
188 0 : unsigned long larg = 0;
189 0 : char *endptr = NULL;
190 0 : struct rmap_value *rv;
191 :
192 0 : if (arg[0] == '+') {
193 0 : action = RMAP_VALUE_ADD;
194 0 : arg++;
195 0 : } else if (arg[0] == '-') {
196 0 : action = RMAP_VALUE_SUB;
197 0 : arg++;
198 : }
199 :
200 0 : if (all_digit(arg)) {
201 0 : errno = 0;
202 0 : larg = strtoul(arg, &endptr, 10);
203 0 : if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
204 : return NULL;
205 : } else {
206 0 : if (strcmp(arg, "rtt") == 0)
207 : var = 1;
208 : else
209 : return NULL;
210 : }
211 :
212 0 : rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
213 :
214 0 : rv->action = action;
215 0 : rv->variable = var;
216 0 : rv->value = larg;
217 0 : return rv;
218 : }
219 :
220 0 : static void route_value_free(void *rule)
221 : {
222 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
223 0 : }
224 :
225 : /* generic as path object to be shared in multiple rules */
226 :
227 0 : static void *route_aspath_compile(const char *arg)
228 : {
229 0 : struct aspath *aspath;
230 :
231 0 : aspath = aspath_str2aspath(arg);
232 0 : if (!aspath)
233 : return NULL;
234 : return aspath;
235 : }
236 :
237 0 : static void route_aspath_free(void *rule)
238 : {
239 0 : struct aspath *aspath = rule;
240 0 : aspath_free(aspath);
241 0 : }
242 :
243 : struct bgp_match_peer_compiled {
244 : char *interface;
245 : union sockunion su;
246 : };
247 :
248 : /* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
249 :
250 : /* Compares the peer specified in the 'match peer' clause with the peer
251 : received in bgp_path_info->peer. If it is the same, or if the peer structure
252 : received is a peer_group containing it, returns RMAP_MATCH. */
253 : static enum route_map_cmd_result_t
254 0 : route_match_peer(void *rule, const struct prefix *prefix, void *object)
255 : {
256 0 : struct bgp_match_peer_compiled *pc;
257 0 : union sockunion *su;
258 0 : union sockunion su_def = {
259 : .sin = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY}};
260 0 : struct peer_group *group;
261 0 : struct peer *peer;
262 0 : struct listnode *node, *nnode;
263 :
264 0 : pc = rule;
265 0 : su = &pc->su;
266 0 : peer = ((struct bgp_path_info *)object)->peer;
267 :
268 0 : if (pc->interface) {
269 0 : if (!peer->conf_if || !peer->group)
270 : return RMAP_NOMATCH;
271 :
272 0 : if (peer->conf_if && strcmp(peer->conf_if, pc->interface) == 0)
273 : return RMAP_MATCH;
274 :
275 0 : if (peer->group &&
276 0 : strcmp(peer->group->name, pc->interface) == 0)
277 : return RMAP_MATCH;
278 :
279 : return RMAP_NOMATCH;
280 : }
281 :
282 : /* If su='0.0.0.0' (command 'match peer local'), and it's a
283 : NETWORK,
284 : REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
285 : => return RMAP_MATCH
286 : */
287 0 : if (sockunion_same(su, &su_def)) {
288 0 : int ret;
289 0 : if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
290 : || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE)
291 : || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_AGGREGATE)
292 : || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_DEFAULT))
293 : ret = RMAP_MATCH;
294 : else
295 0 : ret = RMAP_NOMATCH;
296 0 : return ret;
297 : }
298 :
299 0 : if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
300 0 : if (sockunion_same(su, &peer->su))
301 : return RMAP_MATCH;
302 :
303 : return RMAP_NOMATCH;
304 : } else {
305 0 : group = peer->group;
306 0 : for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
307 0 : if (sockunion_same(su, &peer->su))
308 : return RMAP_MATCH;
309 : }
310 : return RMAP_NOMATCH;
311 : }
312 :
313 : return RMAP_NOMATCH;
314 : }
315 :
316 0 : static void *route_match_peer_compile(const char *arg)
317 : {
318 0 : struct bgp_match_peer_compiled *pc;
319 0 : int ret;
320 :
321 0 : pc = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
322 : sizeof(struct bgp_match_peer_compiled));
323 :
324 0 : ret = str2sockunion(strcmp(arg, "local") ? arg : "0.0.0.0", &pc->su);
325 0 : if (ret < 0) {
326 0 : pc->interface = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
327 0 : return pc;
328 : }
329 :
330 : return pc;
331 : }
332 :
333 : /* Free route map's compiled `ip address' value. */
334 0 : static void route_match_peer_free(void *rule)
335 : {
336 0 : struct bgp_match_peer_compiled *pc = rule;
337 :
338 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
339 :
340 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
341 0 : }
342 :
343 : /* Route map commands for ip address matching. */
344 : static const struct route_map_rule_cmd route_match_peer_cmd = {
345 : "peer",
346 : route_match_peer,
347 : route_match_peer_compile,
348 : route_match_peer_free
349 : };
350 :
351 : #ifdef HAVE_SCRIPTING
352 :
353 : enum frrlua_rm_status {
354 : /*
355 : * Script function run failure. This will translate into a deny
356 : */
357 : LUA_RM_FAILURE = 0,
358 : /*
359 : * No Match was found for the route map function
360 : */
361 : LUA_RM_NOMATCH,
362 : /*
363 : * Match was found but no changes were made to the incoming data.
364 : */
365 : LUA_RM_MATCH,
366 : /*
367 : * Match was found and data was modified, so figure out what changed
368 : */
369 : LUA_RM_MATCH_AND_CHANGE,
370 : };
371 :
372 : static enum route_map_cmd_result_t
373 : route_match_script(void *rule, const struct prefix *prefix, void *object)
374 : {
375 : const char *scriptname = rule;
376 : const char *routematch_function = "route_match";
377 : struct bgp_path_info *path = (struct bgp_path_info *)object;
378 :
379 : struct frrscript *fs = frrscript_new(scriptname);
380 :
381 : if (frrscript_load(fs, routematch_function, NULL)) {
382 : zlog_err(
383 : "Issue loading script or function; defaulting to no match");
384 : return RMAP_NOMATCH;
385 : }
386 :
387 : struct attr newattr = *path->attr;
388 :
389 : int result = frrscript_call(
390 : fs, routematch_function, ("prefix", prefix),
391 : ("attributes", &newattr), ("peer", path->peer),
392 : ("RM_FAILURE", LUA_RM_FAILURE), ("RM_NOMATCH", LUA_RM_NOMATCH),
393 : ("RM_MATCH", LUA_RM_MATCH),
394 : ("RM_MATCH_AND_CHANGE", LUA_RM_MATCH_AND_CHANGE));
395 :
396 : if (result) {
397 : zlog_err("Issue running script rule; defaulting to no match");
398 : return RMAP_NOMATCH;
399 : }
400 :
401 : long long *action = frrscript_get_result(fs, routematch_function,
402 : "action", lua_tointegerp);
403 :
404 : int status = RMAP_NOMATCH;
405 :
406 : switch (*action) {
407 : case LUA_RM_FAILURE:
408 : zlog_err(
409 : "Executing route-map match script '%s' failed; defaulting to no match",
410 : scriptname);
411 : status = RMAP_NOMATCH;
412 : break;
413 : case LUA_RM_NOMATCH:
414 : status = RMAP_NOMATCH;
415 : break;
416 : case LUA_RM_MATCH_AND_CHANGE:
417 : status = RMAP_MATCH;
418 : zlog_debug("Updating attribute based on script's values");
419 :
420 : uint32_t locpref = 0;
421 :
422 : path->attr->med = newattr.med;
423 :
424 : if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
425 : locpref = path->attr->local_pref;
426 : if (locpref != newattr.local_pref) {
427 : SET_FLAG(path->attr->flag,
428 : ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF));
429 : path->attr->local_pref = newattr.local_pref;
430 : }
431 : break;
432 : case LUA_RM_MATCH:
433 : status = RMAP_MATCH;
434 : break;
435 : }
436 :
437 : XFREE(MTYPE_SCRIPT_RES, action);
438 :
439 : frrscript_delete(fs);
440 :
441 : return status;
442 : }
443 :
444 : static void *route_match_script_compile(const char *arg)
445 : {
446 : char *scriptname;
447 :
448 : scriptname = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
449 :
450 : return scriptname;
451 : }
452 :
453 : static void route_match_script_free(void *rule)
454 : {
455 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
456 : }
457 :
458 : static const struct route_map_rule_cmd route_match_script_cmd = {
459 : "script",
460 : route_match_script,
461 : route_match_script_compile,
462 : route_match_script_free
463 : };
464 :
465 : #endif /* HAVE_SCRIPTING */
466 :
467 : /* `match ip address IP_ACCESS_LIST' */
468 :
469 : /* Match function should return 1 if match is success else return
470 : zero. */
471 : static enum route_map_cmd_result_t
472 0 : route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
473 : {
474 0 : struct access_list *alist;
475 :
476 0 : if (prefix->family == AF_INET) {
477 0 : alist = access_list_lookup(AFI_IP, (char *)rule);
478 0 : if (alist == NULL)
479 : return RMAP_NOMATCH;
480 :
481 0 : return (access_list_apply(alist, prefix) == FILTER_DENY
482 : ? RMAP_NOMATCH
483 0 : : RMAP_MATCH);
484 : }
485 : return RMAP_NOMATCH;
486 : }
487 :
488 : /* Route map `ip address' match statement. `arg' should be
489 : access-list name. */
490 0 : static void *route_match_ip_address_compile(const char *arg)
491 : {
492 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
493 : }
494 :
495 : /* Free route map's compiled `ip address' value. */
496 0 : static void route_match_ip_address_free(void *rule)
497 : {
498 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
499 0 : }
500 :
501 : /* Route map commands for ip address matching. */
502 : static const struct route_map_rule_cmd route_match_ip_address_cmd = {
503 : "ip address",
504 : route_match_ip_address,
505 : route_match_ip_address_compile,
506 : route_match_ip_address_free
507 : };
508 :
509 : /* `match ip next-hop IP_ADDRESS' */
510 :
511 : /* Match function return 1 if match is success else return zero. */
512 : static enum route_map_cmd_result_t
513 0 : route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
514 : {
515 0 : struct access_list *alist;
516 0 : struct bgp_path_info *path;
517 0 : struct prefix_ipv4 p;
518 :
519 0 : if (prefix->family == AF_INET) {
520 0 : path = object;
521 0 : p.family = AF_INET;
522 0 : p.prefix = path->attr->nexthop;
523 0 : p.prefixlen = IPV4_MAX_BITLEN;
524 :
525 0 : alist = access_list_lookup(AFI_IP, (char *)rule);
526 0 : if (alist == NULL)
527 : return RMAP_NOMATCH;
528 :
529 0 : return (access_list_apply(alist, &p) == FILTER_DENY
530 : ? RMAP_NOMATCH
531 0 : : RMAP_MATCH);
532 : }
533 : return RMAP_NOMATCH;
534 : }
535 :
536 : /* Route map `ip next-hop' match statement. `arg' is
537 : access-list name. */
538 0 : static void *route_match_ip_next_hop_compile(const char *arg)
539 : {
540 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
541 : }
542 :
543 : /* Free route map's compiled `ip address' value. */
544 0 : static void route_match_ip_next_hop_free(void *rule)
545 : {
546 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
547 0 : }
548 :
549 : /* Route map commands for ip next-hop matching. */
550 : static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
551 : "ip next-hop",
552 : route_match_ip_next_hop,
553 : route_match_ip_next_hop_compile,
554 : route_match_ip_next_hop_free
555 : };
556 :
557 : /* `match ip route-source ACCESS-LIST' */
558 :
559 : /* Match function return 1 if match is success else return zero. */
560 : static enum route_map_cmd_result_t
561 0 : route_match_ip_route_source(void *rule, const struct prefix *pfx, void *object)
562 : {
563 0 : struct access_list *alist;
564 0 : struct bgp_path_info *path;
565 0 : struct peer *peer;
566 0 : struct prefix_ipv4 p;
567 :
568 0 : if (pfx->family == AF_INET) {
569 0 : path = object;
570 0 : peer = path->peer;
571 :
572 0 : if (!peer || sockunion_family(&peer->su) != AF_INET)
573 : return RMAP_NOMATCH;
574 :
575 0 : p.family = AF_INET;
576 0 : p.prefix = peer->su.sin.sin_addr;
577 0 : p.prefixlen = IPV4_MAX_BITLEN;
578 :
579 0 : alist = access_list_lookup(AFI_IP, (char *)rule);
580 0 : if (alist == NULL)
581 : return RMAP_NOMATCH;
582 :
583 0 : return (access_list_apply(alist, &p) == FILTER_DENY
584 : ? RMAP_NOMATCH
585 0 : : RMAP_MATCH);
586 : }
587 : return RMAP_NOMATCH;
588 : }
589 :
590 : /* Route map `ip route-source' match statement. `arg' is
591 : access-list name. */
592 0 : static void *route_match_ip_route_source_compile(const char *arg)
593 : {
594 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
595 : }
596 :
597 : /* Free route map's compiled `ip address' value. */
598 0 : static void route_match_ip_route_source_free(void *rule)
599 : {
600 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
601 0 : }
602 :
603 : /* Route map commands for ip route-source matching. */
604 : static const struct route_map_rule_cmd route_match_ip_route_source_cmd = {
605 : "ip route-source",
606 : route_match_ip_route_source,
607 : route_match_ip_route_source_compile,
608 : route_match_ip_route_source_free
609 : };
610 :
611 : static enum route_map_cmd_result_t
612 0 : route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist,
613 : const struct prefix *p)
614 : {
615 0 : int ret;
616 0 : struct bgp_pbr_entry_main api;
617 :
618 0 : memset(&api, 0, sizeof(api));
619 :
620 0 : if (family2afi(p->u.prefix_flowspec.family) != afi)
621 : return RMAP_NOMATCH;
622 :
623 : /* extract match from flowspec entries */
624 0 : ret = bgp_flowspec_match_rules_fill(
625 0 : (uint8_t *)p->u.prefix_flowspec.ptr,
626 0 : p->u.prefix_flowspec.prefixlen, &api,
627 : afi);
628 0 : if (ret < 0)
629 : return RMAP_NOMATCH;
630 0 : if (api.match_bitmask & PREFIX_DST_PRESENT ||
631 0 : api.match_bitmask_iprule & PREFIX_DST_PRESENT) {
632 0 : if (family2afi((&api.dst_prefix)->family) != afi)
633 : return RMAP_NOMATCH;
634 0 : return prefix_list_apply(plist, &api.dst_prefix) == PREFIX_DENY
635 : ? RMAP_NOMATCH
636 0 : : RMAP_MATCH;
637 0 : } else if (api.match_bitmask & PREFIX_SRC_PRESENT ||
638 : api.match_bitmask_iprule & PREFIX_SRC_PRESENT) {
639 0 : if (family2afi((&api.src_prefix)->family) != afi)
640 : return RMAP_NOMATCH;
641 0 : return (prefix_list_apply(plist, &api.src_prefix) == PREFIX_DENY
642 : ? RMAP_NOMATCH
643 0 : : RMAP_MATCH);
644 : }
645 : return RMAP_NOMATCH;
646 : }
647 :
648 : static enum route_map_cmd_result_t
649 0 : route_match_prefix_list_evpn(afi_t afi, struct prefix_list *plist,
650 : const struct prefix *p)
651 : {
652 : /* Convert to match a general plist */
653 0 : struct prefix new;
654 :
655 0 : if (evpn_prefix2prefix(p, &new))
656 : return RMAP_NOMATCH;
657 :
658 0 : return (prefix_list_apply(plist, &new) == PREFIX_DENY ? RMAP_NOMATCH
659 0 : : RMAP_MATCH);
660 : }
661 :
662 : static enum route_map_cmd_result_t
663 0 : route_match_address_prefix_list(void *rule, afi_t afi,
664 : const struct prefix *prefix, void *object)
665 : {
666 0 : struct prefix_list *plist;
667 :
668 0 : plist = prefix_list_lookup(afi, (char *)rule);
669 0 : if (plist == NULL)
670 : return RMAP_NOMATCH;
671 :
672 0 : if (prefix->family == AF_FLOWSPEC)
673 0 : return route_match_prefix_list_flowspec(afi, plist,
674 : prefix);
675 :
676 0 : else if (prefix->family == AF_EVPN)
677 0 : return route_match_prefix_list_evpn(afi, plist, prefix);
678 :
679 0 : return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
680 0 : : RMAP_MATCH);
681 : }
682 :
683 : static enum route_map_cmd_result_t
684 0 : route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
685 : void *object)
686 : {
687 0 : return route_match_address_prefix_list(rule, AFI_IP, prefix, object);
688 : }
689 :
690 0 : static void *route_match_ip_address_prefix_list_compile(const char *arg)
691 : {
692 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
693 : }
694 :
695 0 : static void route_match_ip_address_prefix_list_free(void *rule)
696 : {
697 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
698 0 : }
699 :
700 : static const struct route_map_rule_cmd
701 : route_match_ip_address_prefix_list_cmd = {
702 : "ip address prefix-list",
703 : route_match_ip_address_prefix_list,
704 : route_match_ip_address_prefix_list_compile,
705 : route_match_ip_address_prefix_list_free
706 : };
707 :
708 : /* `match ip next-hop prefix-list PREFIX_LIST' */
709 :
710 : static enum route_map_cmd_result_t
711 0 : route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
712 : void *object)
713 : {
714 0 : struct prefix_list *plist;
715 0 : struct bgp_path_info *path;
716 0 : struct prefix_ipv4 p;
717 :
718 0 : if (prefix->family == AF_INET) {
719 0 : path = object;
720 0 : p.family = AF_INET;
721 0 : p.prefix = path->attr->nexthop;
722 0 : p.prefixlen = IPV4_MAX_BITLEN;
723 :
724 0 : plist = prefix_list_lookup(AFI_IP, (char *)rule);
725 0 : if (plist == NULL)
726 : return RMAP_NOMATCH;
727 :
728 0 : return (prefix_list_apply(plist, &p) == PREFIX_DENY
729 : ? RMAP_NOMATCH
730 0 : : RMAP_MATCH);
731 : }
732 : return RMAP_NOMATCH;
733 : }
734 :
735 0 : static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
736 : {
737 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
738 : }
739 :
740 0 : static void route_match_ip_next_hop_prefix_list_free(void *rule)
741 : {
742 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
743 0 : }
744 :
745 : static const struct route_map_rule_cmd
746 : route_match_ip_next_hop_prefix_list_cmd = {
747 : "ip next-hop prefix-list",
748 : route_match_ip_next_hop_prefix_list,
749 : route_match_ip_next_hop_prefix_list_compile,
750 : route_match_ip_next_hop_prefix_list_free
751 : };
752 :
753 : /* `match ipv6 next-hop prefix-list PREFIXLIST_NAME' */
754 : static enum route_map_cmd_result_t
755 0 : route_match_ipv6_next_hop_prefix_list(void *rule, const struct prefix *prefix,
756 : void *object)
757 : {
758 0 : struct prefix_list *plist;
759 0 : struct bgp_path_info *path;
760 0 : struct prefix_ipv6 p;
761 :
762 0 : if (prefix->family == AF_INET6) {
763 0 : path = object;
764 0 : p.family = AF_INET6;
765 0 : p.prefix = path->attr->mp_nexthop_global;
766 0 : p.prefixlen = IPV6_MAX_BITLEN;
767 :
768 0 : plist = prefix_list_lookup(AFI_IP6, (char *)rule);
769 0 : if (!plist)
770 : return RMAP_NOMATCH;
771 :
772 0 : if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
773 : return RMAP_MATCH;
774 :
775 0 : if (path->attr->mp_nexthop_len
776 : == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
777 0 : p.prefix = path->attr->mp_nexthop_local;
778 0 : if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
779 : return RMAP_MATCH;
780 : }
781 : }
782 :
783 : return RMAP_NOMATCH;
784 : }
785 :
786 0 : static void *route_match_ipv6_next_hop_prefix_list_compile(const char *arg)
787 : {
788 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
789 : }
790 :
791 0 : static void route_match_ipv6_next_hop_prefix_list_free(void *rule)
792 : {
793 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
794 0 : }
795 :
796 : static const struct route_map_rule_cmd
797 : route_match_ipv6_next_hop_prefix_list_cmd = {
798 : "ipv6 next-hop prefix-list",
799 : route_match_ipv6_next_hop_prefix_list,
800 : route_match_ipv6_next_hop_prefix_list_compile,
801 : route_match_ipv6_next_hop_prefix_list_free
802 : };
803 :
804 : /* `match ip next-hop type <blackhole>' */
805 :
806 : static enum route_map_cmd_result_t
807 0 : route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
808 : void *object)
809 : {
810 0 : struct bgp_path_info *path;
811 :
812 0 : if (prefix->family == AF_INET) {
813 0 : path = (struct bgp_path_info *)object;
814 0 : if (!path)
815 : return RMAP_NOMATCH;
816 :
817 : /* If nexthop interface's index can't be resolved and nexthop is
818 : set to any address then mark it as type `blackhole`.
819 : This logic works for matching kernel/static routes like:
820 : `ip route add blackhole 10.0.0.1`. */
821 0 : if (path->attr->nexthop.s_addr == INADDR_ANY
822 0 : && !path->attr->nh_ifindex)
823 0 : return RMAP_MATCH;
824 : }
825 : return RMAP_NOMATCH;
826 : }
827 :
828 0 : static void *route_match_ip_next_hop_type_compile(const char *arg)
829 : {
830 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
831 : }
832 :
833 0 : static void route_match_ip_next_hop_type_free(void *rule)
834 : {
835 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
836 0 : }
837 :
838 : static const struct route_map_rule_cmd
839 : route_match_ip_next_hop_type_cmd = {
840 : "ip next-hop type",
841 : route_match_ip_next_hop_type,
842 : route_match_ip_next_hop_type_compile,
843 : route_match_ip_next_hop_type_free
844 : };
845 :
846 : /* `match ip route-source prefix-list PREFIX_LIST' */
847 :
848 : static enum route_map_cmd_result_t
849 0 : route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix,
850 : void *object)
851 : {
852 0 : struct prefix_list *plist;
853 0 : struct bgp_path_info *path;
854 0 : struct peer *peer;
855 0 : struct prefix_ipv4 p;
856 :
857 0 : if (prefix->family == AF_INET) {
858 0 : path = object;
859 0 : peer = path->peer;
860 :
861 0 : if (!peer || sockunion_family(&peer->su) != AF_INET)
862 : return RMAP_NOMATCH;
863 :
864 0 : p.family = AF_INET;
865 0 : p.prefix = peer->su.sin.sin_addr;
866 0 : p.prefixlen = IPV4_MAX_BITLEN;
867 :
868 0 : plist = prefix_list_lookup(AFI_IP, (char *)rule);
869 0 : if (plist == NULL)
870 : return RMAP_NOMATCH;
871 :
872 0 : return (prefix_list_apply(plist, &p) == PREFIX_DENY
873 : ? RMAP_NOMATCH
874 0 : : RMAP_MATCH);
875 : }
876 : return RMAP_NOMATCH;
877 : }
878 :
879 0 : static void *route_match_ip_route_source_prefix_list_compile(const char *arg)
880 : {
881 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
882 : }
883 :
884 0 : static void route_match_ip_route_source_prefix_list_free(void *rule)
885 : {
886 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
887 0 : }
888 :
889 : static const struct route_map_rule_cmd
890 : route_match_ip_route_source_prefix_list_cmd = {
891 : "ip route-source prefix-list",
892 : route_match_ip_route_source_prefix_list,
893 : route_match_ip_route_source_prefix_list_compile,
894 : route_match_ip_route_source_prefix_list_free
895 : };
896 :
897 : /* `match evpn default-route' */
898 :
899 : /* Match function should return 1 if match is success else 0 */
900 : static enum route_map_cmd_result_t
901 0 : route_match_evpn_default_route(void *rule, const struct prefix *p, void *object)
902 : {
903 0 : if (is_evpn_prefix_default(p))
904 0 : return RMAP_MATCH;
905 :
906 : return RMAP_NOMATCH;
907 : }
908 :
909 : /* Route map commands for default-route matching. */
910 : static const struct route_map_rule_cmd
911 : route_match_evpn_default_route_cmd = {
912 : "evpn default-route",
913 : route_match_evpn_default_route,
914 : NULL,
915 : NULL
916 : };
917 :
918 : /* `match mac address MAC_ACCESS_LIST' */
919 :
920 : /* Match function should return 1 if match is success else return
921 : zero. */
922 : static enum route_map_cmd_result_t
923 0 : route_match_mac_address(void *rule, const struct prefix *prefix, void *object)
924 : {
925 0 : struct access_list *alist;
926 0 : struct prefix p;
927 :
928 0 : alist = access_list_lookup(AFI_L2VPN, (char *)rule);
929 0 : if (alist == NULL)
930 : return RMAP_NOMATCH;
931 :
932 0 : if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE)
933 : return RMAP_NOMATCH;
934 :
935 0 : p.family = AF_ETHERNET;
936 0 : p.prefixlen = ETH_ALEN * 8;
937 0 : p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
938 :
939 0 : return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
940 0 : : RMAP_MATCH);
941 : }
942 :
943 : /* Route map `mac address' match statement. `arg' should be
944 : access-list name. */
945 0 : static void *route_match_mac_address_compile(const char *arg)
946 : {
947 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
948 : }
949 :
950 : /* Free route map's compiled `ip address' value. */
951 0 : static void route_match_mac_address_free(void *rule)
952 : {
953 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
954 0 : }
955 :
956 : /* Route map commands for mac address matching. */
957 : static const struct route_map_rule_cmd route_match_mac_address_cmd = {
958 : "mac address",
959 : route_match_mac_address,
960 : route_match_mac_address_compile,
961 : route_match_mac_address_free
962 : };
963 :
964 : /*
965 : * Match function returns:
966 : * ...RMAP_MATCH if match is found.
967 : * ...RMAP_NOMATCH if match is not found.
968 : * ...RMAP_NOOP to ignore this match check.
969 : */
970 : static enum route_map_cmd_result_t
971 0 : route_match_vni(void *rule, const struct prefix *prefix, void *object)
972 : {
973 0 : vni_t vni = 0;
974 0 : unsigned int label_cnt = 0;
975 0 : struct bgp_path_info *path = NULL;
976 0 : struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
977 :
978 0 : vni = *((vni_t *)rule);
979 0 : path = (struct bgp_path_info *)object;
980 :
981 : /*
982 : * This rmap filter is valid for vxlan tunnel type only.
983 : * For any other tunnel type, return noop to ignore
984 : * this check.
985 : */
986 0 : if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN)
987 : return RMAP_NOOP;
988 :
989 : /*
990 : * Apply filter to type 1, 2, 5 routes only.
991 : * Other route types do not have vni label.
992 : */
993 0 : if (evp
994 0 : && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE
995 : && evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
996 0 : && evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
997 : return RMAP_NOOP;
998 :
999 0 : if (path->extra == NULL)
1000 : return RMAP_NOMATCH;
1001 :
1002 : for (;
1003 0 : label_cnt < BGP_MAX_LABELS && label_cnt < path->extra->num_labels;
1004 0 : label_cnt++) {
1005 0 : if (vni == label2vni(&path->extra->label[label_cnt]))
1006 : return RMAP_MATCH;
1007 : }
1008 :
1009 : return RMAP_NOMATCH;
1010 : }
1011 :
1012 : /* Route map `vni' match statement. */
1013 0 : static void *route_match_vni_compile(const char *arg)
1014 : {
1015 0 : vni_t *vni = NULL;
1016 0 : char *end = NULL;
1017 :
1018 0 : vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
1019 :
1020 0 : *vni = strtoul(arg, &end, 10);
1021 0 : if (*end != '\0') {
1022 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, vni);
1023 0 : return NULL;
1024 : }
1025 :
1026 : return vni;
1027 : }
1028 :
1029 : /* Free route map's compiled `vni' value. */
1030 0 : static void route_match_vni_free(void *rule)
1031 : {
1032 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1033 0 : }
1034 :
1035 : /* Route map commands for vni matching. */
1036 : static const struct route_map_rule_cmd route_match_evpn_vni_cmd = {
1037 : "evpn vni",
1038 : route_match_vni,
1039 : route_match_vni_compile,
1040 : route_match_vni_free
1041 : };
1042 :
1043 : /* `match evpn route-type' */
1044 :
1045 : /* Match function should return 1 if match is success else return
1046 : zero. */
1047 : static enum route_map_cmd_result_t
1048 0 : route_match_evpn_route_type(void *rule, const struct prefix *pfx, void *object)
1049 : {
1050 0 : uint8_t route_type = 0;
1051 :
1052 0 : route_type = *((uint8_t *)rule);
1053 :
1054 0 : if (route_type == pfx->u.prefix_evpn.route_type)
1055 0 : return RMAP_MATCH;
1056 :
1057 : return RMAP_NOMATCH;
1058 : }
1059 :
1060 : /* Route map `route-type' match statement. */
1061 0 : static void *route_match_evpn_route_type_compile(const char *arg)
1062 : {
1063 0 : uint8_t *route_type = NULL;
1064 :
1065 0 : route_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1066 :
1067 0 : if (strncmp(arg, "ea", 2) == 0)
1068 0 : *route_type = BGP_EVPN_AD_ROUTE;
1069 0 : else if (strncmp(arg, "ma", 2) == 0)
1070 0 : *route_type = BGP_EVPN_MAC_IP_ROUTE;
1071 0 : else if (strncmp(arg, "mu", 2) == 0)
1072 0 : *route_type = BGP_EVPN_IMET_ROUTE;
1073 0 : else if (strncmp(arg, "es", 2) == 0)
1074 0 : *route_type = BGP_EVPN_ES_ROUTE;
1075 : else
1076 0 : *route_type = BGP_EVPN_IP_PREFIX_ROUTE;
1077 :
1078 0 : return route_type;
1079 : }
1080 :
1081 : /* Free route map's compiled `route-type' value. */
1082 0 : static void route_match_evpn_route_type_free(void *rule)
1083 : {
1084 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1085 0 : }
1086 :
1087 : /* Route map commands for evpn route-type matching. */
1088 : static const struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
1089 : "evpn route-type",
1090 : route_match_evpn_route_type,
1091 : route_match_evpn_route_type_compile,
1092 : route_match_evpn_route_type_free
1093 : };
1094 :
1095 : /* `match rd' */
1096 :
1097 : /* Match function should return 1 if match is success else return zero. */
1098 : static enum route_map_cmd_result_t
1099 0 : route_match_rd(void *rule, const struct prefix *prefix, void *object)
1100 : {
1101 0 : struct prefix_rd *prd_rule = NULL;
1102 0 : const struct prefix_rd *prd_route = NULL;
1103 0 : struct bgp_path_info *path = NULL;
1104 :
1105 0 : if (prefix->family != AF_EVPN)
1106 : return RMAP_NOMATCH;
1107 :
1108 0 : prd_rule = (struct prefix_rd *)rule;
1109 0 : path = (struct bgp_path_info *)object;
1110 :
1111 0 : if (path->net == NULL || path->net->pdest == NULL)
1112 : return RMAP_NOMATCH;
1113 :
1114 0 : prd_route = (struct prefix_rd *)bgp_dest_get_prefix(path->net->pdest);
1115 0 : if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0)
1116 0 : return RMAP_MATCH;
1117 :
1118 : return RMAP_NOMATCH;
1119 : }
1120 :
1121 : /* Route map `rd' match statement. */
1122 0 : static void *route_match_rd_compile(const char *arg)
1123 : {
1124 0 : struct prefix_rd *prd;
1125 0 : int ret;
1126 :
1127 0 : prd = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct prefix_rd));
1128 :
1129 0 : ret = str2prefix_rd(arg, prd);
1130 0 : if (!ret) {
1131 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, prd);
1132 0 : return NULL;
1133 : }
1134 :
1135 : return prd;
1136 : }
1137 :
1138 : /* Free route map's compiled `rd' value. */
1139 0 : static void route_match_rd_free(void *rule)
1140 : {
1141 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1142 0 : }
1143 :
1144 : /* Route map commands for rd matching. */
1145 : static const struct route_map_rule_cmd route_match_evpn_rd_cmd = {
1146 : "evpn rd",
1147 : route_match_rd,
1148 : route_match_rd_compile,
1149 : route_match_rd_free
1150 : };
1151 :
1152 : static enum route_map_cmd_result_t
1153 0 : route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object)
1154 : {
1155 0 : struct ipaddr *gw_ip = rule;
1156 0 : struct bgp_path_info *path;
1157 0 : struct prefix_evpn *evp;
1158 :
1159 0 : if (prefix->family != AF_EVPN)
1160 : return RMAP_OKAY;
1161 :
1162 0 : evp = (struct prefix_evpn *)prefix;
1163 0 : if (evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)
1164 : return RMAP_OKAY;
1165 :
1166 0 : if ((is_evpn_prefix_ipaddr_v4(evp) && IPADDRSZ(gw_ip) != 4)
1167 0 : || (is_evpn_prefix_ipaddr_v6(evp) && IPADDRSZ(gw_ip) != 16))
1168 : return RMAP_OKAY;
1169 :
1170 0 : path = object;
1171 :
1172 : /* Set gateway-ip value. */
1173 0 : path->attr->evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
1174 0 : memcpy(&path->attr->evpn_overlay.gw_ip, &gw_ip->ip.addr,
1175 0 : IPADDRSZ(gw_ip));
1176 :
1177 0 : return RMAP_OKAY;
1178 : }
1179 :
1180 : /*
1181 : * Route map `evpn gateway-ip' compile function.
1182 : * Given string is converted to struct ipaddr structure
1183 : */
1184 0 : static void *route_set_evpn_gateway_ip_compile(const char *arg)
1185 : {
1186 0 : struct ipaddr *gw_ip = NULL;
1187 0 : int ret;
1188 :
1189 0 : gw_ip = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct ipaddr));
1190 :
1191 0 : ret = str2ipaddr(arg, gw_ip);
1192 0 : if (ret < 0) {
1193 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
1194 0 : return NULL;
1195 : }
1196 : return gw_ip;
1197 : }
1198 :
1199 : /* Free route map's compiled `evpn gateway_ip' value. */
1200 0 : static void route_set_evpn_gateway_ip_free(void *rule)
1201 : {
1202 0 : struct ipaddr *gw_ip = rule;
1203 :
1204 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
1205 0 : }
1206 :
1207 : /* Route map commands for set evpn gateway-ip ipv4. */
1208 : struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv4_cmd = {
1209 : "evpn gateway-ip ipv4", route_set_evpn_gateway_ip,
1210 : route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
1211 :
1212 : /* Route map commands for set evpn gateway-ip ipv6. */
1213 : struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv6_cmd = {
1214 : "evpn gateway-ip ipv6", route_set_evpn_gateway_ip,
1215 : route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
1216 :
1217 : /* Route map commands for VRF route leak with source vrf matching */
1218 : static enum route_map_cmd_result_t
1219 0 : route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
1220 : void *object)
1221 : {
1222 0 : struct bgp_path_info *path;
1223 0 : char *vrf_name;
1224 :
1225 0 : vrf_name = rule;
1226 0 : path = (struct bgp_path_info *)object;
1227 :
1228 0 : if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
1229 : return RMAP_NOMATCH;
1230 :
1231 0 : if (path->extra == NULL || path->extra->bgp_orig == NULL)
1232 : return RMAP_NOMATCH;
1233 :
1234 0 : if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id),
1235 : VRF_NAMSIZ)
1236 : == 0)
1237 : return RMAP_MATCH;
1238 :
1239 : return RMAP_NOMATCH;
1240 : }
1241 :
1242 0 : static void *route_match_vrl_source_vrf_compile(const char *arg)
1243 : {
1244 0 : uint8_t *vrf_name = NULL;
1245 :
1246 0 : vrf_name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1247 :
1248 0 : return vrf_name;
1249 : }
1250 :
1251 : /* Free route map's compiled `route-type' value. */
1252 0 : static void route_match_vrl_source_vrf_free(void *rule)
1253 : {
1254 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1255 0 : }
1256 :
1257 : static const struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
1258 : "source-vrf",
1259 : route_match_vrl_source_vrf,
1260 : route_match_vrl_source_vrf_compile,
1261 : route_match_vrl_source_vrf_free
1262 : };
1263 :
1264 : /* `match alias` */
1265 : static enum route_map_cmd_result_t
1266 0 : route_match_alias(void *rule, const struct prefix *prefix, void *object)
1267 : {
1268 0 : char *alias = rule;
1269 0 : struct bgp_path_info *path = object;
1270 0 : char **communities;
1271 0 : int num;
1272 0 : bool found;
1273 :
1274 0 : if (bgp_attr_get_community(path->attr)) {
1275 0 : found = false;
1276 0 : frrstr_split(bgp_attr_get_community(path->attr)->str, " ",
1277 : &communities, &num);
1278 0 : for (int i = 0; i < num; i++) {
1279 0 : const char *com2alias =
1280 0 : bgp_community2alias(communities[i]);
1281 0 : if (!found && strcmp(alias, com2alias) == 0)
1282 0 : found = true;
1283 0 : XFREE(MTYPE_TMP, communities[i]);
1284 : }
1285 0 : XFREE(MTYPE_TMP, communities);
1286 0 : if (found)
1287 : return RMAP_MATCH;
1288 : }
1289 :
1290 0 : if (bgp_attr_get_lcommunity(path->attr)) {
1291 0 : found = false;
1292 0 : frrstr_split(bgp_attr_get_lcommunity(path->attr)->str, " ",
1293 : &communities, &num);
1294 0 : for (int i = 0; i < num; i++) {
1295 0 : const char *com2alias =
1296 0 : bgp_community2alias(communities[i]);
1297 0 : if (!found && strcmp(alias, com2alias) == 0)
1298 0 : found = true;
1299 0 : XFREE(MTYPE_TMP, communities[i]);
1300 : }
1301 0 : XFREE(MTYPE_TMP, communities);
1302 0 : if (found)
1303 : return RMAP_MATCH;
1304 : }
1305 :
1306 : return RMAP_NOMATCH;
1307 : }
1308 :
1309 0 : static void *route_match_alias_compile(const char *arg)
1310 : {
1311 :
1312 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1313 : }
1314 :
1315 0 : static void route_match_alias_free(void *rule)
1316 : {
1317 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1318 0 : }
1319 :
1320 : static const struct route_map_rule_cmd route_match_alias_cmd = {
1321 : "alias", route_match_alias, route_match_alias_compile,
1322 : route_match_alias_free};
1323 :
1324 : /* `match local-preference LOCAL-PREF' */
1325 :
1326 : /* Match function return 1 if match is success else return zero. */
1327 : static enum route_map_cmd_result_t
1328 0 : route_match_local_pref(void *rule, const struct prefix *prefix, void *object)
1329 : {
1330 0 : uint32_t *local_pref;
1331 0 : struct bgp_path_info *path;
1332 :
1333 0 : local_pref = rule;
1334 0 : path = object;
1335 :
1336 0 : if (path->attr->local_pref == *local_pref)
1337 : return RMAP_MATCH;
1338 : else
1339 0 : return RMAP_NOMATCH;
1340 : }
1341 :
1342 : /*
1343 : * Route map `match local-preference' match statement.
1344 : * `arg' is local-pref value
1345 : */
1346 0 : static void *route_match_local_pref_compile(const char *arg)
1347 : {
1348 0 : uint32_t *local_pref;
1349 0 : char *endptr = NULL;
1350 0 : unsigned long tmpval;
1351 :
1352 : /* Locpref value shoud be integer. */
1353 0 : if (!all_digit(arg))
1354 : return NULL;
1355 :
1356 0 : errno = 0;
1357 0 : tmpval = strtoul(arg, &endptr, 10);
1358 0 : if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1359 : return NULL;
1360 :
1361 0 : local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1362 :
1363 0 : *local_pref = tmpval;
1364 0 : return local_pref;
1365 : }
1366 :
1367 : /* Free route map's compiled `match local-preference' value. */
1368 0 : static void route_match_local_pref_free(void *rule)
1369 : {
1370 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1371 0 : }
1372 :
1373 : /* Route map commands for metric matching. */
1374 : static const struct route_map_rule_cmd route_match_local_pref_cmd = {
1375 : "local-preference",
1376 : route_match_local_pref,
1377 : route_match_local_pref_compile,
1378 : route_match_local_pref_free
1379 : };
1380 :
1381 : /* `match metric METRIC' */
1382 :
1383 : /* Match function return 1 if match is success else return zero. */
1384 : static enum route_map_cmd_result_t
1385 0 : route_match_metric(void *rule, const struct prefix *prefix, void *object)
1386 : {
1387 0 : struct rmap_value *rv;
1388 0 : struct bgp_path_info *path;
1389 :
1390 0 : rv = rule;
1391 0 : path = object;
1392 0 : return route_value_match(rv, path->attr->med);
1393 : }
1394 :
1395 : /* Route map commands for metric matching. */
1396 : static const struct route_map_rule_cmd route_match_metric_cmd = {
1397 : "metric",
1398 : route_match_metric,
1399 : route_value_compile,
1400 : route_value_free,
1401 : };
1402 :
1403 : /* `match as-path ASPATH' */
1404 :
1405 : /* Match function for as-path match. I assume given object is */
1406 : static enum route_map_cmd_result_t
1407 0 : route_match_aspath(void *rule, const struct prefix *prefix, void *object)
1408 : {
1409 :
1410 0 : struct as_list *as_list;
1411 0 : struct bgp_path_info *path;
1412 :
1413 0 : as_list = as_list_lookup((char *)rule);
1414 0 : if (as_list == NULL)
1415 : return RMAP_NOMATCH;
1416 :
1417 0 : path = object;
1418 :
1419 : /* Perform match. */
1420 0 : return ((as_list_apply(as_list, path->attr->aspath) == AS_FILTER_DENY)
1421 : ? RMAP_NOMATCH
1422 0 : : RMAP_MATCH);
1423 : }
1424 :
1425 : /* Compile function for as-path match. */
1426 0 : static void *route_match_aspath_compile(const char *arg)
1427 : {
1428 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1429 : }
1430 :
1431 : /* Compile function for as-path match. */
1432 0 : static void route_match_aspath_free(void *rule)
1433 : {
1434 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1435 0 : }
1436 :
1437 : /* Route map commands for aspath matching. */
1438 : static const struct route_map_rule_cmd route_match_aspath_cmd = {
1439 : "as-path",
1440 : route_match_aspath,
1441 : route_match_aspath_compile,
1442 : route_match_aspath_free
1443 : };
1444 :
1445 : /* `match community COMMUNIY' */
1446 : struct rmap_community {
1447 : char *name;
1448 : uint32_t name_hash;
1449 : int exact;
1450 : };
1451 :
1452 : /* Match function for community match. */
1453 : static enum route_map_cmd_result_t
1454 0 : route_match_community(void *rule, const struct prefix *prefix, void *object)
1455 : {
1456 0 : struct community_list *list;
1457 0 : struct bgp_path_info *path;
1458 0 : struct rmap_community *rcom = rule;
1459 :
1460 0 : path = object;
1461 0 : rcom = rule;
1462 :
1463 0 : list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1464 : COMMUNITY_LIST_MASTER);
1465 0 : if (!list)
1466 : return RMAP_NOMATCH;
1467 :
1468 0 : if (rcom->exact) {
1469 0 : if (community_list_exact_match(
1470 0 : bgp_attr_get_community(path->attr), list))
1471 : return RMAP_MATCH;
1472 : } else {
1473 0 : if (community_list_match(bgp_attr_get_community(path->attr),
1474 : list))
1475 : return RMAP_MATCH;
1476 : }
1477 :
1478 : return RMAP_NOMATCH;
1479 : }
1480 :
1481 : /* Compile function for community match. */
1482 0 : static void *route_match_community_compile(const char *arg)
1483 : {
1484 0 : struct rmap_community *rcom;
1485 0 : int len;
1486 0 : char *p;
1487 :
1488 0 : rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1489 :
1490 0 : p = strchr(arg, ' ');
1491 0 : if (p) {
1492 0 : len = p - arg;
1493 0 : rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1494 0 : memcpy(rcom->name, arg, len);
1495 0 : rcom->exact = 1;
1496 : } else {
1497 0 : rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1498 0 : rcom->exact = 0;
1499 : }
1500 :
1501 0 : rcom->name_hash = bgp_clist_hash_key(rcom->name);
1502 0 : return rcom;
1503 : }
1504 :
1505 : /* Compile function for community match. */
1506 0 : static void route_match_community_free(void *rule)
1507 : {
1508 0 : struct rmap_community *rcom = rule;
1509 :
1510 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1511 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
1512 0 : }
1513 :
1514 : /*
1515 : * In routemap processing there is a need to add the
1516 : * name as a rule_key in the dependency table. Routemap
1517 : * lib is unaware of rule_key when exact-match clause
1518 : * is in use. routemap lib uses the compiled output to
1519 : * get the rule_key value.
1520 : */
1521 0 : static void *route_match_get_community_key(void *rule)
1522 : {
1523 0 : struct rmap_community *rcom;
1524 :
1525 0 : rcom = rule;
1526 0 : return rcom->name;
1527 : }
1528 :
1529 :
1530 : /* Route map commands for community matching. */
1531 : static const struct route_map_rule_cmd route_match_community_cmd = {
1532 : "community",
1533 : route_match_community,
1534 : route_match_community_compile,
1535 : route_match_community_free,
1536 : route_match_get_community_key
1537 : };
1538 :
1539 : /* Match function for lcommunity match. */
1540 : static enum route_map_cmd_result_t
1541 0 : route_match_lcommunity(void *rule, const struct prefix *prefix, void *object)
1542 : {
1543 0 : struct community_list *list;
1544 0 : struct bgp_path_info *path;
1545 0 : struct rmap_community *rcom = rule;
1546 :
1547 0 : path = object;
1548 :
1549 0 : list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1550 : LARGE_COMMUNITY_LIST_MASTER);
1551 0 : if (!list)
1552 : return RMAP_NOMATCH;
1553 :
1554 0 : if (rcom->exact) {
1555 0 : if (lcommunity_list_exact_match(
1556 0 : bgp_attr_get_lcommunity(path->attr), list))
1557 : return RMAP_MATCH;
1558 : } else {
1559 0 : if (lcommunity_list_match(bgp_attr_get_lcommunity(path->attr),
1560 : list))
1561 : return RMAP_MATCH;
1562 : }
1563 :
1564 : return RMAP_NOMATCH;
1565 : }
1566 :
1567 : /* Compile function for community match. */
1568 0 : static void *route_match_lcommunity_compile(const char *arg)
1569 : {
1570 0 : struct rmap_community *rcom;
1571 0 : int len;
1572 0 : char *p;
1573 :
1574 0 : rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1575 :
1576 0 : p = strchr(arg, ' ');
1577 0 : if (p) {
1578 0 : len = p - arg;
1579 0 : rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1580 0 : memcpy(rcom->name, arg, len);
1581 0 : rcom->exact = 1;
1582 : } else {
1583 0 : rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1584 0 : rcom->exact = 0;
1585 : }
1586 :
1587 0 : rcom->name_hash = bgp_clist_hash_key(rcom->name);
1588 0 : return rcom;
1589 : }
1590 :
1591 : /* Compile function for community match. */
1592 0 : static void route_match_lcommunity_free(void *rule)
1593 : {
1594 0 : struct rmap_community *rcom = rule;
1595 :
1596 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1597 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
1598 0 : }
1599 :
1600 : /* Route map commands for community matching. */
1601 : static const struct route_map_rule_cmd route_match_lcommunity_cmd = {
1602 : "large-community",
1603 : route_match_lcommunity,
1604 : route_match_lcommunity_compile,
1605 : route_match_lcommunity_free,
1606 : route_match_get_community_key
1607 : };
1608 :
1609 :
1610 : /* Match function for extcommunity match. */
1611 : static enum route_map_cmd_result_t
1612 0 : route_match_ecommunity(void *rule, const struct prefix *prefix, void *object)
1613 : {
1614 0 : struct community_list *list;
1615 0 : struct bgp_path_info *path;
1616 0 : struct rmap_community *rcom = rule;
1617 :
1618 0 : path = object;
1619 :
1620 0 : list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1621 : EXTCOMMUNITY_LIST_MASTER);
1622 0 : if (!list)
1623 : return RMAP_NOMATCH;
1624 :
1625 0 : if (ecommunity_list_match(bgp_attr_get_ecommunity(path->attr), list))
1626 : return RMAP_MATCH;
1627 :
1628 : return RMAP_NOMATCH;
1629 : }
1630 :
1631 : /* Compile function for extcommunity match. */
1632 0 : static void *route_match_ecommunity_compile(const char *arg)
1633 : {
1634 0 : struct rmap_community *rcom;
1635 :
1636 0 : rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1637 0 : rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1638 0 : rcom->name_hash = bgp_clist_hash_key(rcom->name);
1639 :
1640 0 : return rcom;
1641 : }
1642 :
1643 : /* Compile function for extcommunity match. */
1644 0 : static void route_match_ecommunity_free(void *rule)
1645 : {
1646 0 : struct rmap_community *rcom = rule;
1647 :
1648 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1649 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
1650 0 : }
1651 :
1652 : /* Route map commands for community matching. */
1653 : static const struct route_map_rule_cmd route_match_ecommunity_cmd = {
1654 : "extcommunity",
1655 : route_match_ecommunity,
1656 : route_match_ecommunity_compile,
1657 : route_match_ecommunity_free
1658 : };
1659 :
1660 : /* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1661 : and `address-family vpnv4'. */
1662 :
1663 : /* `match origin' */
1664 : static enum route_map_cmd_result_t
1665 0 : route_match_origin(void *rule, const struct prefix *prefix, void *object)
1666 : {
1667 0 : uint8_t *origin;
1668 0 : struct bgp_path_info *path;
1669 :
1670 0 : origin = rule;
1671 0 : path = object;
1672 :
1673 0 : if (path->attr->origin == *origin)
1674 0 : return RMAP_MATCH;
1675 :
1676 : return RMAP_NOMATCH;
1677 : }
1678 :
1679 0 : static void *route_match_origin_compile(const char *arg)
1680 : {
1681 0 : uint8_t *origin;
1682 :
1683 0 : origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1684 :
1685 0 : if (strcmp(arg, "igp") == 0)
1686 0 : *origin = 0;
1687 0 : else if (strcmp(arg, "egp") == 0)
1688 0 : *origin = 1;
1689 : else
1690 0 : *origin = 2;
1691 :
1692 0 : return origin;
1693 : }
1694 :
1695 : /* Free route map's compiled `ip address' value. */
1696 0 : static void route_match_origin_free(void *rule)
1697 : {
1698 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1699 0 : }
1700 :
1701 : /* Route map commands for origin matching. */
1702 : static const struct route_map_rule_cmd route_match_origin_cmd = {
1703 : "origin",
1704 : route_match_origin,
1705 : route_match_origin_compile,
1706 : route_match_origin_free
1707 : };
1708 :
1709 : /* match probability { */
1710 :
1711 : static enum route_map_cmd_result_t
1712 0 : route_match_probability(void *rule, const struct prefix *prefix, void *object)
1713 : {
1714 0 : long r = frr_weak_random();
1715 :
1716 0 : switch (*(long *)rule) {
1717 : case 0:
1718 : break;
1719 : case RAND_MAX:
1720 : return RMAP_MATCH;
1721 0 : default:
1722 0 : if (r < *(long *)rule) {
1723 : return RMAP_MATCH;
1724 : }
1725 : }
1726 :
1727 : return RMAP_NOMATCH;
1728 : }
1729 :
1730 0 : static void *route_match_probability_compile(const char *arg)
1731 : {
1732 0 : long *lobule;
1733 0 : unsigned perc;
1734 :
1735 0 : perc = atoi(arg);
1736 0 : lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long));
1737 :
1738 0 : switch (perc) {
1739 0 : case 0:
1740 0 : *lobule = 0;
1741 0 : break;
1742 0 : case 100:
1743 0 : *lobule = RAND_MAX;
1744 0 : break;
1745 0 : default:
1746 0 : *lobule = RAND_MAX / 100 * perc;
1747 : }
1748 :
1749 0 : return lobule;
1750 : }
1751 :
1752 0 : static void route_match_probability_free(void *rule)
1753 : {
1754 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1755 0 : }
1756 :
1757 : static const struct route_map_rule_cmd route_match_probability_cmd = {
1758 : "probability",
1759 : route_match_probability,
1760 : route_match_probability_compile,
1761 : route_match_probability_free
1762 : };
1763 :
1764 : /* `match interface IFNAME' */
1765 : /* Match function should return 1 if match is success else return
1766 : zero. */
1767 : static enum route_map_cmd_result_t
1768 0 : route_match_interface(void *rule, const struct prefix *prefix, void *object)
1769 : {
1770 0 : struct interface *ifp;
1771 0 : struct bgp_path_info *path;
1772 :
1773 0 : path = object;
1774 :
1775 0 : if (!path || !path->peer || !path->peer->bgp)
1776 : return RMAP_NOMATCH;
1777 :
1778 0 : ifp = if_lookup_by_name((char *)rule, path->peer->bgp->vrf_id);
1779 :
1780 0 : if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
1781 : return RMAP_NOMATCH;
1782 :
1783 : return RMAP_MATCH;
1784 : }
1785 :
1786 : /* Route map `interface' match statement. `arg' should be
1787 : interface name. */
1788 0 : static void *route_match_interface_compile(const char *arg)
1789 : {
1790 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1791 : }
1792 :
1793 : /* Free route map's compiled `interface' value. */
1794 0 : static void route_match_interface_free(void *rule)
1795 : {
1796 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1797 0 : }
1798 :
1799 : /* Route map commands for ip address matching. */
1800 : static const struct route_map_rule_cmd route_match_interface_cmd = {
1801 : "interface",
1802 : route_match_interface,
1803 : route_match_interface_compile,
1804 : route_match_interface_free
1805 : };
1806 :
1807 : /* } */
1808 :
1809 : /* `set ip next-hop IP_ADDRESS' */
1810 :
1811 : /* Match function return 1 if match is success else return zero. */
1812 : static enum route_map_cmd_result_t
1813 0 : route_match_tag(void *rule, const struct prefix *prefix, void *object)
1814 : {
1815 0 : route_tag_t *tag;
1816 0 : struct bgp_path_info *path;
1817 :
1818 0 : tag = rule;
1819 0 : path = object;
1820 :
1821 0 : return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
1822 : }
1823 :
1824 :
1825 : /* Route map commands for tag matching. */
1826 : static const struct route_map_rule_cmd route_match_tag_cmd = {
1827 : "tag",
1828 : route_match_tag,
1829 : route_map_rule_tag_compile,
1830 : route_map_rule_tag_free,
1831 : };
1832 :
1833 : static enum route_map_cmd_result_t
1834 0 : route_set_srte_color(void *rule, const struct prefix *prefix, void *object)
1835 : {
1836 0 : uint32_t *srte_color = rule;
1837 0 : struct bgp_path_info *path;
1838 :
1839 0 : path = object;
1840 :
1841 0 : path->attr->srte_color = *srte_color;
1842 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
1843 :
1844 0 : return RMAP_OKAY;
1845 : }
1846 :
1847 : /* Route map `sr-te color' compile function */
1848 0 : static void *route_set_srte_color_compile(const char *arg)
1849 : {
1850 0 : uint32_t *color;
1851 :
1852 0 : color = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1853 0 : *color = atoi(arg);
1854 :
1855 0 : return color;
1856 : }
1857 :
1858 : /* Free route map's compiled `sr-te color' value. */
1859 0 : static void route_set_srte_color_free(void *rule)
1860 : {
1861 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1862 0 : }
1863 :
1864 : /* Route map commands for sr-te color set. */
1865 : struct route_map_rule_cmd route_set_srte_color_cmd = {
1866 : "sr-te color", route_set_srte_color, route_set_srte_color_compile,
1867 : route_set_srte_color_free};
1868 :
1869 : /* Set nexthop to object. object must be pointer to struct attr. */
1870 : struct rmap_ip_nexthop_set {
1871 : struct in_addr *address;
1872 : int peer_address;
1873 : int unchanged;
1874 : };
1875 :
1876 : static enum route_map_cmd_result_t
1877 0 : route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
1878 : {
1879 0 : struct rmap_ip_nexthop_set *rins = rule;
1880 0 : struct bgp_path_info *path;
1881 0 : struct peer *peer;
1882 :
1883 0 : if (prefix->family == AF_INET6)
1884 : return RMAP_OKAY;
1885 :
1886 0 : path = object;
1887 0 : peer = path->peer;
1888 :
1889 0 : if (rins->unchanged) {
1890 0 : SET_FLAG(path->attr->rmap_change_flags,
1891 : BATTR_RMAP_NEXTHOP_UNCHANGED);
1892 0 : } else if (rins->peer_address) {
1893 0 : if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
1894 : || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
1895 0 : && peer->su_remote
1896 0 : && sockunion_family(peer->su_remote) == AF_INET) {
1897 0 : path->attr->nexthop.s_addr =
1898 0 : sockunion2ip(peer->su_remote);
1899 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1900 0 : } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
1901 : /* The next hop value will be set as part of
1902 : * packet rewrite. Set the flags here to indicate
1903 : * that rewrite needs to be done.
1904 : * Also, clear the value.
1905 : */
1906 0 : SET_FLAG(path->attr->rmap_change_flags,
1907 : BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
1908 0 : path->attr->nexthop.s_addr = INADDR_ANY;
1909 : }
1910 : } else {
1911 : /* Set next hop value. */
1912 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1913 0 : path->attr->nexthop = *rins->address;
1914 0 : SET_FLAG(path->attr->rmap_change_flags,
1915 : BATTR_RMAP_IPV4_NHOP_CHANGED);
1916 : /* case for MP-BGP : MPLS VPN */
1917 0 : path->attr->mp_nexthop_global_in = *rins->address;
1918 0 : path->attr->mp_nexthop_len = sizeof(*rins->address);
1919 : }
1920 :
1921 : return RMAP_OKAY;
1922 : }
1923 :
1924 : /* Route map `ip nexthop' compile function. Given string is converted
1925 : to struct in_addr structure. */
1926 0 : static void *route_set_ip_nexthop_compile(const char *arg)
1927 : {
1928 0 : struct rmap_ip_nexthop_set *rins;
1929 0 : struct in_addr *address = NULL;
1930 0 : int peer_address = 0;
1931 0 : int unchanged = 0;
1932 0 : int ret;
1933 :
1934 0 : if (strcmp(arg, "peer-address") == 0)
1935 : peer_address = 1;
1936 0 : else if (strcmp(arg, "unchanged") == 0)
1937 : unchanged = 1;
1938 : else {
1939 0 : address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
1940 : sizeof(struct in_addr));
1941 0 : ret = inet_aton(arg, address);
1942 :
1943 0 : if (ret == 0) {
1944 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
1945 0 : return NULL;
1946 : }
1947 : }
1948 :
1949 0 : rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
1950 : sizeof(struct rmap_ip_nexthop_set));
1951 :
1952 0 : rins->address = address;
1953 0 : rins->peer_address = peer_address;
1954 0 : rins->unchanged = unchanged;
1955 :
1956 0 : return rins;
1957 : }
1958 :
1959 : /* Free route map's compiled `ip nexthop' value. */
1960 0 : static void route_set_ip_nexthop_free(void *rule)
1961 : {
1962 0 : struct rmap_ip_nexthop_set *rins = rule;
1963 :
1964 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
1965 :
1966 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
1967 0 : }
1968 :
1969 : /* Route map commands for ip nexthop set. */
1970 : static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
1971 : "ip next-hop",
1972 : route_set_ip_nexthop,
1973 : route_set_ip_nexthop_compile,
1974 : route_set_ip_nexthop_free
1975 : };
1976 :
1977 : /* `set l3vpn next-hop encapsulation l3vpn gre' */
1978 :
1979 : /* Set nexthop to object */
1980 : struct rmap_l3vpn_nexthop_encapsulation_set {
1981 : uint8_t protocol;
1982 : };
1983 :
1984 : static enum route_map_cmd_result_t
1985 0 : route_set_l3vpn_nexthop_encapsulation(void *rule, const struct prefix *prefix,
1986 : void *object)
1987 : {
1988 0 : struct rmap_l3vpn_nexthop_encapsulation_set *rins = rule;
1989 0 : struct bgp_path_info *path;
1990 :
1991 0 : path = object;
1992 :
1993 0 : if (rins->protocol != IPPROTO_GRE)
1994 : return RMAP_OKAY;
1995 :
1996 0 : SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRE);
1997 0 : return RMAP_OKAY;
1998 : }
1999 :
2000 : /* Route map `l3vpn nexthop encapsulation' compile function. */
2001 0 : static void *route_set_l3vpn_nexthop_encapsulation_compile(const char *arg)
2002 : {
2003 0 : struct rmap_l3vpn_nexthop_encapsulation_set *rins;
2004 :
2005 0 : rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2006 : sizeof(struct rmap_l3vpn_nexthop_encapsulation_set));
2007 :
2008 : /* XXX ALL GRE modes are accepted for now: gre or ip6gre */
2009 0 : rins->protocol = IPPROTO_GRE;
2010 :
2011 0 : return rins;
2012 : }
2013 :
2014 : /* Free route map's compiled `ip nexthop' value. */
2015 0 : static void route_set_l3vpn_nexthop_encapsulation_free(void *rule)
2016 : {
2017 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2018 0 : }
2019 :
2020 : /* Route map commands for l3vpn next-hop encapsulation set. */
2021 : static const struct route_map_rule_cmd
2022 : route_set_l3vpn_nexthop_encapsulation_cmd = {
2023 : "l3vpn next-hop encapsulation",
2024 : route_set_l3vpn_nexthop_encapsulation,
2025 : route_set_l3vpn_nexthop_encapsulation_compile,
2026 : route_set_l3vpn_nexthop_encapsulation_free};
2027 :
2028 : /* `set local-preference LOCAL_PREF' */
2029 :
2030 : /* Set local preference. */
2031 : static enum route_map_cmd_result_t
2032 0 : route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
2033 : {
2034 0 : struct rmap_value *rv;
2035 0 : struct bgp_path_info *path;
2036 0 : uint32_t locpref = 0;
2037 :
2038 : /* Fetch routemap's rule information. */
2039 0 : rv = rule;
2040 0 : path = object;
2041 :
2042 : /* Set local preference value. */
2043 0 : if (path->attr->local_pref)
2044 : locpref = path->attr->local_pref;
2045 :
2046 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2047 0 : path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
2048 :
2049 0 : return RMAP_OKAY;
2050 : }
2051 :
2052 : /* Set local preference rule structure. */
2053 : static const struct route_map_rule_cmd route_set_local_pref_cmd = {
2054 : "local-preference",
2055 : route_set_local_pref,
2056 : route_value_compile,
2057 : route_value_free,
2058 : };
2059 :
2060 : /* `set weight WEIGHT' */
2061 :
2062 : /* Set weight. */
2063 : static enum route_map_cmd_result_t
2064 0 : route_set_weight(void *rule, const struct prefix *prefix, void *object)
2065 : {
2066 0 : struct rmap_value *rv;
2067 0 : struct bgp_path_info *path;
2068 :
2069 : /* Fetch routemap's rule information. */
2070 0 : rv = rule;
2071 0 : path = object;
2072 :
2073 : /* Set weight value. */
2074 0 : path->attr->weight = route_value_adjust(rv, 0, path->peer);
2075 :
2076 0 : return RMAP_OKAY;
2077 : }
2078 :
2079 : /* Set local preference rule structure. */
2080 : static const struct route_map_rule_cmd route_set_weight_cmd = {
2081 : "weight",
2082 : route_set_weight,
2083 : route_value_compile,
2084 : route_value_free,
2085 : };
2086 :
2087 : /* `set distance DISTANCE */
2088 : static enum route_map_cmd_result_t
2089 0 : route_set_distance(void *rule, const struct prefix *prefix, void *object)
2090 : {
2091 0 : struct bgp_path_info *path = object;
2092 0 : struct rmap_value *rv = rule;
2093 :
2094 0 : path->attr->distance = rv->value;
2095 :
2096 0 : return RMAP_OKAY;
2097 : }
2098 :
2099 : /* set distance rule structure */
2100 : static const struct route_map_rule_cmd route_set_distance_cmd = {
2101 : "distance",
2102 : route_set_distance,
2103 : route_value_compile,
2104 : route_value_free,
2105 : };
2106 :
2107 : /* `set metric METRIC' */
2108 :
2109 : /* Set metric to attribute. */
2110 : static enum route_map_cmd_result_t
2111 0 : route_set_metric(void *rule, const struct prefix *prefix, void *object)
2112 : {
2113 0 : struct rmap_value *rv;
2114 0 : struct bgp_path_info *path;
2115 0 : uint32_t med = 0;
2116 :
2117 : /* Fetch routemap's rule information. */
2118 0 : rv = rule;
2119 0 : path = object;
2120 :
2121 0 : if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
2122 0 : med = path->attr->med;
2123 :
2124 0 : path->attr->med = route_value_adjust(rv, med, path->peer);
2125 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
2126 :
2127 0 : return RMAP_OKAY;
2128 : }
2129 :
2130 : /* Set metric rule structure. */
2131 : static const struct route_map_rule_cmd route_set_metric_cmd = {
2132 : "metric",
2133 : route_set_metric,
2134 : route_value_compile,
2135 : route_value_free,
2136 : };
2137 :
2138 : /* `set table (1-4294967295)' */
2139 :
2140 : static enum route_map_cmd_result_t
2141 0 : route_set_table_id(void *rule, const struct prefix *prefix,
2142 :
2143 : void *object)
2144 : {
2145 0 : struct rmap_value *rv;
2146 0 : struct bgp_path_info *path;
2147 :
2148 : /* Fetch routemap's rule information. */
2149 0 : rv = rule;
2150 0 : path = object;
2151 :
2152 0 : path->attr->rmap_table_id = rv->value;
2153 :
2154 0 : return RMAP_OKAY;
2155 : }
2156 :
2157 : /* Set table_id rule structure. */
2158 : static const struct route_map_rule_cmd route_set_table_id_cmd = {
2159 : "table",
2160 : route_set_table_id,
2161 : route_value_compile,
2162 : route_value_free
2163 : };
2164 :
2165 : /* `set as-path prepend ASPATH' */
2166 :
2167 : /* For AS path prepend mechanism. */
2168 : static enum route_map_cmd_result_t
2169 0 : route_set_aspath_prepend(void *rule, const struct prefix *prefix, void *object)
2170 : {
2171 0 : struct aspath *aspath;
2172 0 : struct aspath *new;
2173 0 : struct bgp_path_info *path;
2174 :
2175 0 : path = object;
2176 :
2177 0 : if (path->attr->aspath->refcnt)
2178 0 : new = aspath_dup(path->attr->aspath);
2179 : else
2180 : new = path->attr->aspath;
2181 :
2182 0 : if ((uintptr_t)rule > 10) {
2183 0 : aspath = rule;
2184 0 : aspath_prepend(aspath, new);
2185 : } else {
2186 0 : as_t as = aspath_leftmost(new);
2187 0 : if (as)
2188 0 : new = aspath_add_seq_n(new, as, (uintptr_t)rule);
2189 : }
2190 :
2191 0 : path->attr->aspath = new;
2192 :
2193 0 : return RMAP_OKAY;
2194 : }
2195 :
2196 0 : static void *route_set_aspath_prepend_compile(const char *arg)
2197 : {
2198 0 : unsigned int num;
2199 :
2200 0 : if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
2201 0 : return (void *)(uintptr_t)num;
2202 :
2203 0 : return route_aspath_compile(arg);
2204 : }
2205 :
2206 0 : static void route_set_aspath_prepend_free(void *rule)
2207 : {
2208 0 : if ((uintptr_t)rule > 10)
2209 0 : route_aspath_free(rule);
2210 0 : }
2211 :
2212 :
2213 : /* Set as-path prepend rule structure. */
2214 : static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
2215 : "as-path prepend",
2216 : route_set_aspath_prepend,
2217 : route_set_aspath_prepend_compile,
2218 : route_set_aspath_prepend_free,
2219 : };
2220 :
2221 : /* `set as-path exclude ASn' */
2222 :
2223 : /* For ASN exclude mechanism.
2224 : * Iterate over ASns requested and filter them from the given AS_PATH one by
2225 : * one.
2226 : * Make a deep copy of existing AS_PATH, but for the first ASn only.
2227 : */
2228 : static enum route_map_cmd_result_t
2229 0 : route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
2230 : {
2231 0 : struct aspath *new_path, *exclude_path;
2232 0 : struct bgp_path_info *path;
2233 :
2234 0 : exclude_path = rule;
2235 0 : path = object;
2236 0 : if (path->attr->aspath->refcnt)
2237 0 : new_path = aspath_dup(path->attr->aspath);
2238 : else
2239 : new_path = path->attr->aspath;
2240 0 : path->attr->aspath = aspath_filter_exclude(new_path, exclude_path);
2241 :
2242 0 : return RMAP_OKAY;
2243 : }
2244 :
2245 : /* Set ASn exlude rule structure. */
2246 : static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
2247 : "as-path exclude",
2248 : route_set_aspath_exclude,
2249 : route_aspath_compile,
2250 : route_aspath_free,
2251 : };
2252 :
2253 : /* `set as-path replace AS-PATH` */
2254 0 : static void *route_aspath_replace_compile(const char *arg)
2255 : {
2256 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
2257 : }
2258 :
2259 0 : static void route_aspath_replace_free(void *rule)
2260 : {
2261 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2262 0 : }
2263 :
2264 : static enum route_map_cmd_result_t
2265 0 : route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
2266 : {
2267 0 : struct aspath *aspath_new;
2268 0 : const char *replace = rule;
2269 0 : struct bgp_path_info *path = object;
2270 0 : as_t own_asn = path->peer->change_local_as ? path->peer->change_local_as
2271 0 : : path->peer->local_as;
2272 :
2273 0 : if (path->peer->sort != BGP_PEER_EBGP) {
2274 0 : zlog_warn(
2275 : "`set as-path replace` is supported only for EBGP peers");
2276 0 : return RMAP_NOOP;
2277 : }
2278 :
2279 0 : if (path->attr->aspath->refcnt)
2280 0 : aspath_new = aspath_dup(path->attr->aspath);
2281 : else
2282 : aspath_new = path->attr->aspath;
2283 :
2284 0 : if (strmatch(replace, "any")) {
2285 0 : path->attr->aspath =
2286 0 : aspath_replace_all_asn(aspath_new, own_asn);
2287 : } else {
2288 0 : as_t replace_asn = strtoul(replace, NULL, 10);
2289 :
2290 0 : path->attr->aspath = aspath_replace_specific_asn(
2291 : aspath_new, replace_asn, own_asn);
2292 : }
2293 :
2294 0 : aspath_free(aspath_new);
2295 :
2296 0 : return RMAP_OKAY;
2297 : }
2298 :
2299 : static const struct route_map_rule_cmd route_set_aspath_replace_cmd = {
2300 : "as-path replace",
2301 : route_set_aspath_replace,
2302 : route_aspath_replace_compile,
2303 : route_aspath_replace_free,
2304 : };
2305 :
2306 : /* `set community COMMUNITY' */
2307 : struct rmap_com_set {
2308 : struct community *com;
2309 : int additive;
2310 : int none;
2311 : };
2312 :
2313 : /* For community set mechanism. */
2314 : static enum route_map_cmd_result_t
2315 0 : route_set_community(void *rule, const struct prefix *prefix, void *object)
2316 : {
2317 0 : struct rmap_com_set *rcs;
2318 0 : struct bgp_path_info *path;
2319 0 : struct attr *attr;
2320 0 : struct community *new = NULL;
2321 0 : struct community *old;
2322 0 : struct community *merge;
2323 :
2324 0 : rcs = rule;
2325 0 : path = object;
2326 0 : attr = path->attr;
2327 0 : old = bgp_attr_get_community(attr);
2328 :
2329 : /* "none" case. */
2330 0 : if (rcs->none) {
2331 0 : bgp_attr_set_community(attr, NULL);
2332 : /* See the longer comment down below. */
2333 0 : if (old && old->refcnt == 0)
2334 0 : community_free(&old);
2335 0 : return RMAP_OKAY;
2336 : }
2337 :
2338 : /* "additive" case. */
2339 0 : if (rcs->additive && old) {
2340 0 : merge = community_merge(community_dup(old), rcs->com);
2341 :
2342 0 : new = community_uniq_sort(merge);
2343 0 : community_free(&merge);
2344 : } else
2345 0 : new = community_dup(rcs->com);
2346 :
2347 : /* HACK: if the old community is not intern'd,
2348 : * we should free it here, or all reference to it may be
2349 : * lost.
2350 : * Really need to cleanup attribute caching sometime.
2351 : */
2352 0 : if (old && old->refcnt == 0)
2353 0 : community_free(&old);
2354 :
2355 : /* will be interned by caller if required */
2356 0 : bgp_attr_set_community(attr, new);
2357 :
2358 : return RMAP_OKAY;
2359 : }
2360 :
2361 : /* Compile function for set community. */
2362 0 : static void *route_set_community_compile(const char *arg)
2363 : {
2364 0 : struct rmap_com_set *rcs;
2365 0 : struct community *com = NULL;
2366 0 : char *sp;
2367 0 : int additive = 0;
2368 0 : int none = 0;
2369 :
2370 0 : if (strcmp(arg, "none") == 0)
2371 : none = 1;
2372 : else {
2373 0 : sp = strstr(arg, "additive");
2374 :
2375 0 : if (sp && sp > arg) {
2376 : /* "additive" keyword is included. */
2377 0 : additive = 1;
2378 0 : *(sp - 1) = '\0';
2379 : }
2380 :
2381 0 : com = community_str2com(arg);
2382 :
2383 0 : if (additive)
2384 0 : *(sp - 1) = ' ';
2385 :
2386 0 : if (!com)
2387 : return NULL;
2388 : }
2389 :
2390 0 : rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2391 0 : rcs->com = com;
2392 0 : rcs->additive = additive;
2393 0 : rcs->none = none;
2394 :
2395 0 : return rcs;
2396 : }
2397 :
2398 : /* Free function for set community. */
2399 0 : static void route_set_community_free(void *rule)
2400 : {
2401 0 : struct rmap_com_set *rcs = rule;
2402 :
2403 0 : if (rcs->com)
2404 0 : community_free(&rcs->com);
2405 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
2406 0 : }
2407 :
2408 : /* Set community rule structure. */
2409 : static const struct route_map_rule_cmd route_set_community_cmd = {
2410 : "community",
2411 : route_set_community,
2412 : route_set_community_compile,
2413 : route_set_community_free,
2414 : };
2415 :
2416 : /* `set community COMMUNITY' */
2417 : struct rmap_lcom_set {
2418 : struct lcommunity *lcom;
2419 : int additive;
2420 : int none;
2421 : };
2422 :
2423 :
2424 : /* For lcommunity set mechanism. */
2425 : static enum route_map_cmd_result_t
2426 0 : route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
2427 : {
2428 0 : struct rmap_lcom_set *rcs;
2429 0 : struct bgp_path_info *path;
2430 0 : struct attr *attr;
2431 0 : struct lcommunity *new = NULL;
2432 0 : struct lcommunity *old;
2433 0 : struct lcommunity *merge;
2434 :
2435 0 : rcs = rule;
2436 0 : path = object;
2437 0 : attr = path->attr;
2438 0 : old = bgp_attr_get_lcommunity(attr);
2439 :
2440 : /* "none" case. */
2441 0 : if (rcs->none) {
2442 0 : bgp_attr_set_lcommunity(attr, NULL);
2443 :
2444 : /* See the longer comment down below. */
2445 0 : if (old && old->refcnt == 0)
2446 0 : lcommunity_free(&old);
2447 0 : return RMAP_OKAY;
2448 : }
2449 :
2450 0 : if (rcs->additive && old) {
2451 0 : merge = lcommunity_merge(lcommunity_dup(old), rcs->lcom);
2452 :
2453 0 : new = lcommunity_uniq_sort(merge);
2454 0 : lcommunity_free(&merge);
2455 : } else
2456 0 : new = lcommunity_dup(rcs->lcom);
2457 :
2458 : /* HACK: if the old large-community is not intern'd,
2459 : * we should free it here, or all reference to it may be
2460 : * lost.
2461 : * Really need to cleanup attribute caching sometime.
2462 : */
2463 0 : if (old && old->refcnt == 0)
2464 0 : lcommunity_free(&old);
2465 :
2466 : /* will be intern()'d or attr_flush()'d by bgp_update_main() */
2467 0 : bgp_attr_set_lcommunity(attr, new);
2468 :
2469 : return RMAP_OKAY;
2470 : }
2471 :
2472 : /* Compile function for set community. */
2473 0 : static void *route_set_lcommunity_compile(const char *arg)
2474 : {
2475 0 : struct rmap_lcom_set *rcs;
2476 0 : struct lcommunity *lcom = NULL;
2477 0 : char *sp;
2478 0 : int additive = 0;
2479 0 : int none = 0;
2480 :
2481 0 : if (strcmp(arg, "none") == 0)
2482 : none = 1;
2483 : else {
2484 0 : sp = strstr(arg, "additive");
2485 :
2486 0 : if (sp && sp > arg) {
2487 : /* "additive" keyworkd is included. */
2488 0 : additive = 1;
2489 0 : *(sp - 1) = '\0';
2490 : }
2491 :
2492 0 : lcom = lcommunity_str2com(arg);
2493 :
2494 0 : if (additive)
2495 0 : *(sp - 1) = ' ';
2496 :
2497 0 : if (!lcom)
2498 : return NULL;
2499 : }
2500 :
2501 0 : rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2502 0 : rcs->lcom = lcom;
2503 0 : rcs->additive = additive;
2504 0 : rcs->none = none;
2505 :
2506 0 : return rcs;
2507 : }
2508 :
2509 : /* Free function for set lcommunity. */
2510 0 : static void route_set_lcommunity_free(void *rule)
2511 : {
2512 0 : struct rmap_lcom_set *rcs = rule;
2513 :
2514 0 : if (rcs->lcom) {
2515 0 : lcommunity_free(&rcs->lcom);
2516 : }
2517 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
2518 0 : }
2519 :
2520 : /* Set community rule structure. */
2521 : static const struct route_map_rule_cmd route_set_lcommunity_cmd = {
2522 : "large-community",
2523 : route_set_lcommunity,
2524 : route_set_lcommunity_compile,
2525 : route_set_lcommunity_free,
2526 : };
2527 :
2528 : /* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
2529 :
2530 : /* For large community set mechanism. */
2531 : static enum route_map_cmd_result_t
2532 0 : route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object)
2533 : {
2534 0 : struct community_list *list;
2535 0 : struct lcommunity *merge;
2536 0 : struct lcommunity *new;
2537 0 : struct lcommunity *old;
2538 0 : struct bgp_path_info *path;
2539 0 : struct rmap_community *rcom = rule;
2540 :
2541 0 : if (!rcom)
2542 : return RMAP_OKAY;
2543 :
2544 0 : path = object;
2545 0 : list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2546 : LARGE_COMMUNITY_LIST_MASTER);
2547 0 : old = bgp_attr_get_lcommunity(path->attr);
2548 :
2549 0 : if (list && old) {
2550 0 : merge = lcommunity_list_match_delete(lcommunity_dup(old), list);
2551 0 : new = lcommunity_uniq_sort(merge);
2552 0 : lcommunity_free(&merge);
2553 :
2554 : /* HACK: if the old community is not intern'd,
2555 : * we should free it here, or all reference to it may be
2556 : * lost.
2557 : * Really need to cleanup attribute caching sometime.
2558 : */
2559 0 : if (old->refcnt == 0)
2560 0 : lcommunity_free(&old);
2561 :
2562 0 : if (new->size == 0) {
2563 0 : bgp_attr_set_lcommunity(path->attr, NULL);
2564 0 : lcommunity_free(&new);
2565 : } else {
2566 0 : bgp_attr_set_lcommunity(path->attr, new);
2567 : }
2568 : }
2569 :
2570 : return RMAP_OKAY;
2571 : }
2572 :
2573 : /* Compile function for set lcommunity. */
2574 0 : static void *route_set_lcommunity_delete_compile(const char *arg)
2575 : {
2576 0 : struct rmap_community *rcom;
2577 0 : char **splits;
2578 0 : int num;
2579 :
2580 0 : frrstr_split(arg, " ", &splits, &num);
2581 :
2582 0 : rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2583 0 : rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
2584 0 : rcom->name_hash = bgp_clist_hash_key(rcom->name);
2585 :
2586 0 : for (int i = 0; i < num; i++)
2587 0 : XFREE(MTYPE_TMP, splits[i]);
2588 0 : XFREE(MTYPE_TMP, splits);
2589 :
2590 0 : return rcom;
2591 : }
2592 :
2593 : /* Free function for set lcommunity. */
2594 0 : static void route_set_lcommunity_delete_free(void *rule)
2595 : {
2596 0 : struct rmap_community *rcom = rule;
2597 :
2598 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2599 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
2600 0 : }
2601 :
2602 : /* Set lcommunity rule structure. */
2603 : static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
2604 : "large-comm-list",
2605 : route_set_lcommunity_delete,
2606 : route_set_lcommunity_delete_compile,
2607 : route_set_lcommunity_delete_free,
2608 : };
2609 :
2610 :
2611 : /* `set comm-list (<1-99>|<100-500>|WORD) delete' */
2612 :
2613 : /* For community set mechanism. */
2614 : static enum route_map_cmd_result_t
2615 0 : route_set_community_delete(void *rule, const struct prefix *prefix,
2616 : void *object)
2617 : {
2618 0 : struct community_list *list;
2619 0 : struct community *merge;
2620 0 : struct community *new;
2621 0 : struct community *old;
2622 0 : struct bgp_path_info *path;
2623 0 : struct rmap_community *rcom = rule;
2624 :
2625 0 : if (!rcom)
2626 : return RMAP_OKAY;
2627 :
2628 0 : path = object;
2629 0 : list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2630 : COMMUNITY_LIST_MASTER);
2631 0 : old = bgp_attr_get_community(path->attr);
2632 :
2633 0 : if (list && old) {
2634 0 : merge = community_list_match_delete(community_dup(old), list);
2635 0 : new = community_uniq_sort(merge);
2636 0 : community_free(&merge);
2637 :
2638 : /* HACK: if the old community is not intern'd,
2639 : * we should free it here, or all reference to it may be
2640 : * lost.
2641 : * Really need to cleanup attribute caching sometime.
2642 : */
2643 0 : if (old->refcnt == 0)
2644 0 : community_free(&old);
2645 :
2646 0 : if (new->size == 0) {
2647 0 : bgp_attr_set_community(path->attr, NULL);
2648 0 : community_free(&new);
2649 : } else {
2650 0 : bgp_attr_set_community(path->attr, new);
2651 : }
2652 : }
2653 :
2654 : return RMAP_OKAY;
2655 : }
2656 :
2657 : /* Compile function for set community. */
2658 0 : static void *route_set_community_delete_compile(const char *arg)
2659 : {
2660 0 : struct rmap_community *rcom;
2661 0 : char **splits;
2662 0 : int num;
2663 :
2664 0 : frrstr_split(arg, " ", &splits, &num);
2665 :
2666 0 : rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2667 0 : rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
2668 0 : rcom->name_hash = bgp_clist_hash_key(rcom->name);
2669 :
2670 0 : for (int i = 0; i < num; i++)
2671 0 : XFREE(MTYPE_TMP, splits[i]);
2672 0 : XFREE(MTYPE_TMP, splits);
2673 :
2674 0 : return rcom;
2675 : }
2676 :
2677 : /* Free function for set community. */
2678 0 : static void route_set_community_delete_free(void *rule)
2679 : {
2680 0 : struct rmap_community *rcom = rule;
2681 :
2682 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2683 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
2684 0 : }
2685 :
2686 : /* Set community rule structure. */
2687 : static const struct route_map_rule_cmd route_set_community_delete_cmd = {
2688 : "comm-list",
2689 : route_set_community_delete,
2690 : route_set_community_delete_compile,
2691 : route_set_community_delete_free,
2692 : };
2693 :
2694 : /* `set extcommunity rt COMMUNITY' */
2695 :
2696 : struct rmap_ecom_set {
2697 : struct ecommunity *ecom;
2698 : bool none;
2699 : };
2700 :
2701 : /* For community set mechanism. Used by _rt and _soo. */
2702 : static enum route_map_cmd_result_t
2703 0 : route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
2704 : {
2705 0 : struct rmap_ecom_set *rcs;
2706 0 : struct ecommunity *new_ecom;
2707 0 : struct ecommunity *old_ecom;
2708 0 : struct bgp_path_info *path;
2709 0 : struct attr *attr;
2710 :
2711 0 : rcs = rule;
2712 0 : path = object;
2713 0 : attr = path->attr;
2714 :
2715 0 : if (rcs->none) {
2716 0 : bgp_attr_set_ecommunity(attr, NULL);
2717 0 : return RMAP_OKAY;
2718 : }
2719 :
2720 0 : if (!rcs->ecom)
2721 : return RMAP_OKAY;
2722 :
2723 : /* We assume additive for Extended Community. */
2724 0 : old_ecom = bgp_attr_get_ecommunity(path->attr);
2725 :
2726 0 : if (old_ecom) {
2727 0 : new_ecom =
2728 0 : ecommunity_merge(ecommunity_dup(old_ecom), rcs->ecom);
2729 :
2730 : /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
2731 : * bgp_update_receive()
2732 : * ->refcnt = 0 => set by a previous route-map
2733 : * statement */
2734 0 : if (!old_ecom->refcnt)
2735 0 : ecommunity_free(&old_ecom);
2736 : } else
2737 0 : new_ecom = ecommunity_dup(rcs->ecom);
2738 :
2739 : /* will be intern()'d or attr_flush()'d by bgp_update_main() */
2740 0 : bgp_attr_set_ecommunity(path->attr, new_ecom);
2741 :
2742 : return RMAP_OKAY;
2743 : }
2744 :
2745 0 : static void *route_set_ecommunity_none_compile(const char *arg)
2746 : {
2747 0 : struct rmap_ecom_set *rcs;
2748 0 : bool none = false;
2749 :
2750 0 : if (strncmp(arg, "none", 4) == 0)
2751 0 : none = true;
2752 :
2753 0 : rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2754 0 : rcs->ecom = NULL;
2755 0 : rcs->none = none;
2756 :
2757 0 : return rcs;
2758 : }
2759 :
2760 0 : static void *route_set_ecommunity_rt_compile(const char *arg)
2761 : {
2762 0 : struct rmap_ecom_set *rcs;
2763 0 : struct ecommunity *ecom;
2764 :
2765 0 : ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
2766 0 : if (!ecom)
2767 : return NULL;
2768 :
2769 0 : rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2770 0 : rcs->ecom = ecommunity_intern(ecom);
2771 0 : rcs->none = false;
2772 :
2773 0 : return rcs;
2774 : }
2775 :
2776 : /* Free function for set community. Used by _rt and _soo */
2777 0 : static void route_set_ecommunity_free(void *rule)
2778 : {
2779 0 : struct rmap_ecom_set *rcs = rule;
2780 :
2781 0 : if (rcs->ecom)
2782 0 : ecommunity_unintern(&rcs->ecom);
2783 :
2784 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
2785 0 : }
2786 :
2787 : static const struct route_map_rule_cmd route_set_ecommunity_none_cmd = {
2788 : "extcommunity",
2789 : route_set_ecommunity,
2790 : route_set_ecommunity_none_compile,
2791 : route_set_ecommunity_free,
2792 : };
2793 :
2794 : /* Set community rule structure. */
2795 : static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
2796 : "extcommunity rt",
2797 : route_set_ecommunity,
2798 : route_set_ecommunity_rt_compile,
2799 : route_set_ecommunity_free,
2800 : };
2801 :
2802 : /* `set extcommunity soo COMMUNITY' */
2803 :
2804 : /* Compile function for set community. */
2805 0 : static void *route_set_ecommunity_soo_compile(const char *arg)
2806 : {
2807 0 : struct rmap_ecom_set *rcs;
2808 0 : struct ecommunity *ecom;
2809 :
2810 0 : ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
2811 0 : if (!ecom)
2812 : return NULL;
2813 :
2814 0 : rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2815 0 : rcs->ecom = ecommunity_intern(ecom);
2816 0 : rcs->none = false;
2817 :
2818 0 : return rcs;
2819 : }
2820 :
2821 : /* Set community rule structure. */
2822 : static const struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
2823 : "extcommunity soo",
2824 : route_set_ecommunity,
2825 : route_set_ecommunity_soo_compile,
2826 : route_set_ecommunity_free,
2827 : };
2828 :
2829 : /* `set extcommunity bandwidth' */
2830 :
2831 : struct rmap_ecomm_lb_set {
2832 : uint8_t lb_type;
2833 : #define RMAP_ECOMM_LB_SET_VALUE 1
2834 : #define RMAP_ECOMM_LB_SET_CUMUL 2
2835 : #define RMAP_ECOMM_LB_SET_NUM_MPATH 3
2836 : bool non_trans;
2837 : uint32_t bw;
2838 : };
2839 :
2840 : static enum route_map_cmd_result_t
2841 0 : route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
2842 : {
2843 0 : struct rmap_ecomm_lb_set *rels = rule;
2844 0 : struct bgp_path_info *path;
2845 0 : struct peer *peer;
2846 0 : struct ecommunity ecom_lb = {0};
2847 0 : struct ecommunity_val lb_eval;
2848 0 : uint32_t bw_bytes = 0;
2849 0 : uint16_t mpath_count = 0;
2850 0 : struct ecommunity *new_ecom;
2851 0 : struct ecommunity *old_ecom;
2852 0 : as_t as;
2853 :
2854 0 : path = object;
2855 0 : peer = path->peer;
2856 0 : if (!peer || !peer->bgp)
2857 : return RMAP_ERROR;
2858 :
2859 : /* Build link bandwidth extended community */
2860 0 : as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
2861 0 : if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
2862 0 : bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
2863 0 : } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
2864 : /* process this only for the best path. */
2865 0 : if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2866 : return RMAP_OKAY;
2867 :
2868 0 : bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
2869 0 : if (!bw_bytes)
2870 : return RMAP_OKAY;
2871 :
2872 0 : } else if (rels->lb_type == RMAP_ECOMM_LB_SET_NUM_MPATH) {
2873 :
2874 : /* process this only for the best path. */
2875 0 : if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2876 : return RMAP_OKAY;
2877 :
2878 0 : bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
2879 0 : mpath_count = bgp_path_info_mpath_count(path) + 1;
2880 0 : bw_bytes *= mpath_count;
2881 : }
2882 :
2883 0 : encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
2884 0 : CHECK_FLAG(peer->flags,
2885 : PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2886 :
2887 : /* add to route or merge with existing */
2888 0 : old_ecom = bgp_attr_get_ecommunity(path->attr);
2889 0 : if (old_ecom) {
2890 0 : new_ecom = ecommunity_dup(old_ecom);
2891 0 : ecommunity_add_val(new_ecom, &lb_eval, true, true);
2892 0 : if (!old_ecom->refcnt)
2893 0 : ecommunity_free(&old_ecom);
2894 : } else {
2895 0 : ecom_lb.size = 1;
2896 0 : ecom_lb.unit_size = ECOMMUNITY_SIZE;
2897 0 : ecom_lb.val = (uint8_t *)lb_eval.val;
2898 0 : new_ecom = ecommunity_dup(&ecom_lb);
2899 : }
2900 :
2901 : /* new_ecom will be intern()'d or attr_flush()'d in call stack */
2902 0 : bgp_attr_set_ecommunity(path->attr, new_ecom);
2903 :
2904 : /* Mark that route-map has set link bandwidth; used in attribute
2905 : * setting decisions.
2906 : */
2907 0 : SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET);
2908 :
2909 0 : return RMAP_OKAY;
2910 : }
2911 :
2912 0 : static void *route_set_ecommunity_lb_compile(const char *arg)
2913 : {
2914 0 : struct rmap_ecomm_lb_set *rels;
2915 0 : uint8_t lb_type;
2916 0 : uint32_t bw = 0;
2917 0 : char bw_str[40] = {0};
2918 0 : char *p, *str;
2919 0 : bool non_trans = false;
2920 :
2921 0 : str = (char *)arg;
2922 0 : p = strchr(arg, ' ');
2923 0 : if (p) {
2924 0 : int len;
2925 :
2926 0 : len = p - arg;
2927 0 : memcpy(bw_str, arg, len);
2928 0 : non_trans = true;
2929 0 : str = bw_str;
2930 : }
2931 :
2932 0 : if (strcmp(str, "cumulative") == 0)
2933 : lb_type = RMAP_ECOMM_LB_SET_CUMUL;
2934 0 : else if (strcmp(str, "num-multipaths") == 0)
2935 : lb_type = RMAP_ECOMM_LB_SET_NUM_MPATH;
2936 : else {
2937 0 : char *end = NULL;
2938 :
2939 0 : bw = strtoul(str, &end, 10);
2940 0 : if (*end != '\0')
2941 0 : return NULL;
2942 0 : lb_type = RMAP_ECOMM_LB_SET_VALUE;
2943 : }
2944 :
2945 0 : rels = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2946 : sizeof(struct rmap_ecomm_lb_set));
2947 0 : rels->lb_type = lb_type;
2948 0 : rels->bw = bw;
2949 0 : rels->non_trans = non_trans;
2950 :
2951 0 : return rels;
2952 : }
2953 :
2954 0 : static void route_set_ecommunity_lb_free(void *rule)
2955 : {
2956 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2957 0 : }
2958 :
2959 : /* Set community rule structure. */
2960 : struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
2961 : "extcommunity bandwidth",
2962 : route_set_ecommunity_lb,
2963 : route_set_ecommunity_lb_compile,
2964 : route_set_ecommunity_lb_free,
2965 : };
2966 :
2967 : /* `set origin ORIGIN' */
2968 :
2969 : /* For origin set. */
2970 : static enum route_map_cmd_result_t
2971 0 : route_set_origin(void *rule, const struct prefix *prefix, void *object)
2972 : {
2973 0 : uint8_t *origin;
2974 0 : struct bgp_path_info *path;
2975 :
2976 0 : origin = rule;
2977 0 : path = object;
2978 :
2979 0 : path->attr->origin = *origin;
2980 :
2981 0 : return RMAP_OKAY;
2982 : }
2983 :
2984 : /* Compile function for origin set. */
2985 0 : static void *route_set_origin_compile(const char *arg)
2986 : {
2987 0 : uint8_t *origin;
2988 :
2989 0 : origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
2990 :
2991 0 : if (strcmp(arg, "igp") == 0)
2992 0 : *origin = 0;
2993 0 : else if (strcmp(arg, "egp") == 0)
2994 0 : *origin = 1;
2995 : else
2996 0 : *origin = 2;
2997 :
2998 0 : return origin;
2999 : }
3000 :
3001 : /* Compile function for origin set. */
3002 0 : static void route_set_origin_free(void *rule)
3003 : {
3004 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3005 0 : }
3006 :
3007 : /* Set origin rule structure. */
3008 : static const struct route_map_rule_cmd route_set_origin_cmd = {
3009 : "origin",
3010 : route_set_origin,
3011 : route_set_origin_compile,
3012 : route_set_origin_free,
3013 : };
3014 :
3015 : /* `set atomic-aggregate' */
3016 :
3017 : /* For atomic aggregate set. */
3018 : static enum route_map_cmd_result_t
3019 0 : route_set_atomic_aggregate(void *rule, const struct prefix *pfx, void *object)
3020 : {
3021 0 : struct bgp_path_info *path;
3022 :
3023 0 : path = object;
3024 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
3025 :
3026 0 : return RMAP_OKAY;
3027 : }
3028 :
3029 : /* Compile function for atomic aggregate. */
3030 0 : static void *route_set_atomic_aggregate_compile(const char *arg)
3031 : {
3032 0 : return (void *)1;
3033 : }
3034 :
3035 : /* Compile function for atomic aggregate. */
3036 0 : static void route_set_atomic_aggregate_free(void *rule)
3037 : {
3038 0 : return;
3039 : }
3040 :
3041 : /* Set atomic aggregate rule structure. */
3042 : static const struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
3043 : "atomic-aggregate",
3044 : route_set_atomic_aggregate,
3045 : route_set_atomic_aggregate_compile,
3046 : route_set_atomic_aggregate_free,
3047 : };
3048 :
3049 : /* AIGP TLV Metric */
3050 : static enum route_map_cmd_result_t
3051 0 : route_set_aigp_metric(void *rule, const struct prefix *pfx, void *object)
3052 : {
3053 0 : const char *aigp_metric = rule;
3054 0 : struct bgp_path_info *path = object;
3055 0 : uint32_t aigp = 0;
3056 :
3057 0 : if (strmatch(aigp_metric, "igp-metric")) {
3058 0 : if (!path->nexthop)
3059 : return RMAP_NOMATCH;
3060 :
3061 0 : bgp_attr_set_aigp_metric(path->attr, path->nexthop->metric);
3062 : } else {
3063 0 : aigp = atoi(aigp_metric);
3064 0 : bgp_attr_set_aigp_metric(path->attr, aigp);
3065 : }
3066 :
3067 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AIGP);
3068 :
3069 0 : return RMAP_OKAY;
3070 : }
3071 :
3072 0 : static void *route_set_aigp_metric_compile(const char *arg)
3073 : {
3074 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3075 : }
3076 :
3077 0 : static void route_set_aigp_metric_free(void *rule)
3078 : {
3079 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3080 0 : }
3081 :
3082 : static const struct route_map_rule_cmd route_set_aigp_metric_cmd = {
3083 : "aigp-metric",
3084 : route_set_aigp_metric,
3085 : route_set_aigp_metric_compile,
3086 : route_set_aigp_metric_free,
3087 : };
3088 :
3089 : /* `set aggregator as AS A.B.C.D' */
3090 : struct aggregator {
3091 : as_t as;
3092 : struct in_addr address;
3093 : };
3094 :
3095 : static enum route_map_cmd_result_t
3096 0 : route_set_aggregator_as(void *rule, const struct prefix *prefix, void *object)
3097 : {
3098 0 : struct bgp_path_info *path;
3099 0 : struct aggregator *aggregator;
3100 :
3101 0 : path = object;
3102 0 : aggregator = rule;
3103 :
3104 0 : path->attr->aggregator_as = aggregator->as;
3105 0 : path->attr->aggregator_addr = aggregator->address;
3106 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
3107 :
3108 0 : return RMAP_OKAY;
3109 : }
3110 :
3111 0 : static void *route_set_aggregator_as_compile(const char *arg)
3112 : {
3113 0 : struct aggregator *aggregator;
3114 0 : char as[10];
3115 0 : char address[20];
3116 0 : int ret;
3117 :
3118 0 : aggregator =
3119 0 : XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
3120 0 : if (sscanf(arg, "%s %s", as, address) != 2) {
3121 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
3122 0 : return NULL;
3123 : }
3124 :
3125 0 : aggregator->as = strtoul(as, NULL, 10);
3126 0 : ret = inet_aton(address, &aggregator->address);
3127 0 : if (ret == 0) {
3128 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
3129 0 : return NULL;
3130 : }
3131 : return aggregator;
3132 : }
3133 :
3134 0 : static void route_set_aggregator_as_free(void *rule)
3135 : {
3136 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3137 0 : }
3138 :
3139 : static const struct route_map_rule_cmd route_set_aggregator_as_cmd = {
3140 : "aggregator as",
3141 : route_set_aggregator_as,
3142 : route_set_aggregator_as_compile,
3143 : route_set_aggregator_as_free,
3144 : };
3145 :
3146 : /* Set tag to object. object must be pointer to struct bgp_path_info */
3147 : static enum route_map_cmd_result_t
3148 0 : route_set_tag(void *rule, const struct prefix *prefix, void *object)
3149 : {
3150 0 : route_tag_t *tag;
3151 0 : struct bgp_path_info *path;
3152 :
3153 0 : tag = rule;
3154 0 : path = object;
3155 :
3156 : /* Set tag value */
3157 0 : path->attr->tag = *tag;
3158 :
3159 0 : return RMAP_OKAY;
3160 : }
3161 :
3162 : /* Route map commands for tag set. */
3163 : static const struct route_map_rule_cmd route_set_tag_cmd = {
3164 : "tag",
3165 : route_set_tag,
3166 : route_map_rule_tag_compile,
3167 : route_map_rule_tag_free,
3168 : };
3169 :
3170 : /* Set label-index to object. object must be pointer to struct bgp_path_info */
3171 : static enum route_map_cmd_result_t
3172 0 : route_set_label_index(void *rule, const struct prefix *prefix, void *object)
3173 : {
3174 0 : struct rmap_value *rv;
3175 0 : struct bgp_path_info *path;
3176 0 : uint32_t label_index;
3177 :
3178 : /* Fetch routemap's rule information. */
3179 0 : rv = rule;
3180 0 : path = object;
3181 :
3182 : /* Set label-index value. */
3183 0 : label_index = rv->value;
3184 0 : if (label_index) {
3185 0 : path->attr->label_index = label_index;
3186 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
3187 : }
3188 :
3189 0 : return RMAP_OKAY;
3190 : }
3191 :
3192 : /* Route map commands for label-index set. */
3193 : static const struct route_map_rule_cmd route_set_label_index_cmd = {
3194 : "label-index",
3195 : route_set_label_index,
3196 : route_value_compile,
3197 : route_value_free,
3198 : };
3199 :
3200 : /* `match ipv6 address IP_ACCESS_LIST' */
3201 :
3202 : static enum route_map_cmd_result_t
3203 0 : route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
3204 : {
3205 0 : struct access_list *alist;
3206 :
3207 0 : if (prefix->family == AF_INET6) {
3208 0 : alist = access_list_lookup(AFI_IP6, (char *)rule);
3209 0 : if (alist == NULL)
3210 : return RMAP_NOMATCH;
3211 :
3212 0 : return (access_list_apply(alist, prefix) == FILTER_DENY
3213 : ? RMAP_NOMATCH
3214 0 : : RMAP_MATCH);
3215 : }
3216 : return RMAP_NOMATCH;
3217 : }
3218 :
3219 0 : static void *route_match_ipv6_address_compile(const char *arg)
3220 : {
3221 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3222 : }
3223 :
3224 0 : static void route_match_ipv6_address_free(void *rule)
3225 : {
3226 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3227 0 : }
3228 :
3229 : /* Route map commands for ip address matching. */
3230 : static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
3231 : "ipv6 address",
3232 : route_match_ipv6_address,
3233 : route_match_ipv6_address_compile,
3234 : route_match_ipv6_address_free
3235 : };
3236 :
3237 : /* `match ipv6 next-hop ACCESSLIST6_NAME' */
3238 : static enum route_map_cmd_result_t
3239 0 : route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
3240 : {
3241 0 : struct bgp_path_info *path;
3242 0 : struct access_list *alist;
3243 0 : struct prefix_ipv6 p;
3244 :
3245 0 : if (prefix->family == AF_INET6) {
3246 0 : path = object;
3247 0 : p.family = AF_INET6;
3248 0 : p.prefix = path->attr->mp_nexthop_global;
3249 0 : p.prefixlen = IPV6_MAX_BITLEN;
3250 :
3251 0 : alist = access_list_lookup(AFI_IP6, (char *)rule);
3252 0 : if (!alist)
3253 : return RMAP_NOMATCH;
3254 :
3255 0 : if (access_list_apply(alist, &p) == FILTER_PERMIT)
3256 : return RMAP_MATCH;
3257 :
3258 0 : if (path->attr->mp_nexthop_len
3259 : == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3260 0 : p.prefix = path->attr->mp_nexthop_local;
3261 0 : if (access_list_apply(alist, &p) == FILTER_PERMIT)
3262 : return RMAP_MATCH;
3263 : }
3264 : }
3265 :
3266 : return RMAP_NOMATCH;
3267 : }
3268 :
3269 0 : static void *route_match_ipv6_next_hop_compile(const char *arg)
3270 : {
3271 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3272 : }
3273 :
3274 0 : static void route_match_ipv6_next_hop_free(void *rule)
3275 : {
3276 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3277 0 : }
3278 :
3279 : static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
3280 : "ipv6 next-hop",
3281 : route_match_ipv6_next_hop,
3282 : route_match_ipv6_next_hop_compile,
3283 : route_match_ipv6_next_hop_free
3284 : };
3285 :
3286 : /* `match ipv6 next-hop IP_ADDRESS' */
3287 :
3288 : static enum route_map_cmd_result_t
3289 0 : route_match_ipv6_next_hop_address(void *rule, const struct prefix *prefix,
3290 : void *object)
3291 : {
3292 0 : struct in6_addr *addr = rule;
3293 0 : struct bgp_path_info *path;
3294 :
3295 0 : path = object;
3296 :
3297 0 : if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
3298 : return RMAP_MATCH;
3299 :
3300 0 : if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
3301 0 : && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
3302 0 : return RMAP_MATCH;
3303 :
3304 : return RMAP_NOMATCH;
3305 : }
3306 :
3307 0 : static void *route_match_ipv6_next_hop_address_compile(const char *arg)
3308 : {
3309 0 : struct in6_addr *address;
3310 0 : int ret;
3311 :
3312 0 : address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3313 :
3314 0 : ret = inet_pton(AF_INET6, arg, address);
3315 0 : if (!ret) {
3316 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3317 0 : return NULL;
3318 : }
3319 :
3320 : return address;
3321 : }
3322 :
3323 0 : static void route_match_ipv6_next_hop_address_free(void *rule)
3324 : {
3325 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3326 0 : }
3327 :
3328 : static const struct route_map_rule_cmd route_match_ipv6_next_hop_address_cmd = {
3329 : "ipv6 next-hop address",
3330 : route_match_ipv6_next_hop_address,
3331 : route_match_ipv6_next_hop_address_compile,
3332 : route_match_ipv6_next_hop_address_free
3333 : };
3334 :
3335 : /* `match ip next-hop IP_ADDRESS' */
3336 :
3337 : static enum route_map_cmd_result_t
3338 0 : route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, void *object)
3339 : {
3340 0 : struct in_addr *addr = rule;
3341 0 : struct bgp_path_info *path;
3342 :
3343 0 : path = object;
3344 :
3345 0 : if (path->attr->nexthop.s_addr == addr->s_addr
3346 0 : || (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4
3347 0 : && IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
3348 0 : return RMAP_MATCH;
3349 :
3350 : return RMAP_NOMATCH;
3351 : }
3352 :
3353 0 : static void *route_match_ipv4_next_hop_compile(const char *arg)
3354 : {
3355 0 : struct in_addr *address;
3356 0 : int ret;
3357 :
3358 0 : address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3359 :
3360 0 : ret = inet_pton(AF_INET, arg, address);
3361 0 : if (!ret) {
3362 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3363 0 : return NULL;
3364 : }
3365 :
3366 : return address;
3367 : }
3368 :
3369 0 : static void route_match_ipv4_next_hop_free(void *rule)
3370 : {
3371 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3372 0 : }
3373 :
3374 : static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
3375 : "ip next-hop address",
3376 : route_match_ipv4_next_hop,
3377 : route_match_ipv4_next_hop_compile,
3378 : route_match_ipv4_next_hop_free
3379 : };
3380 :
3381 : /* `match ipv6 address prefix-list PREFIX_LIST' */
3382 :
3383 : static enum route_map_cmd_result_t
3384 0 : route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
3385 : void *object)
3386 : {
3387 0 : return route_match_address_prefix_list(rule, AFI_IP6, prefix, object);
3388 : }
3389 :
3390 0 : static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
3391 : {
3392 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3393 : }
3394 :
3395 0 : static void route_match_ipv6_address_prefix_list_free(void *rule)
3396 : {
3397 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3398 0 : }
3399 :
3400 : static const struct route_map_rule_cmd
3401 : route_match_ipv6_address_prefix_list_cmd = {
3402 : "ipv6 address prefix-list",
3403 : route_match_ipv6_address_prefix_list,
3404 : route_match_ipv6_address_prefix_list_compile,
3405 : route_match_ipv6_address_prefix_list_free
3406 : };
3407 :
3408 : /* `match ipv6 next-hop type <TYPE>' */
3409 :
3410 : static enum route_map_cmd_result_t
3411 0 : route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
3412 : void *object)
3413 : {
3414 0 : struct bgp_path_info *path;
3415 0 : struct in6_addr *addr = rule;
3416 :
3417 0 : if (prefix->family == AF_INET6) {
3418 0 : path = (struct bgp_path_info *)object;
3419 0 : if (!path)
3420 : return RMAP_NOMATCH;
3421 :
3422 0 : if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
3423 0 : && !path->attr->nh_ifindex)
3424 0 : return RMAP_MATCH;
3425 : }
3426 :
3427 : return RMAP_NOMATCH;
3428 : }
3429 :
3430 0 : static void *route_match_ipv6_next_hop_type_compile(const char *arg)
3431 : {
3432 0 : struct in6_addr *address;
3433 0 : int ret;
3434 :
3435 0 : address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3436 :
3437 0 : ret = inet_pton(AF_INET6, "::0", address);
3438 0 : if (!ret) {
3439 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3440 0 : return NULL;
3441 : }
3442 :
3443 : return address;
3444 : }
3445 :
3446 0 : static void route_match_ipv6_next_hop_type_free(void *rule)
3447 : {
3448 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3449 0 : }
3450 :
3451 : static const struct route_map_rule_cmd
3452 : route_match_ipv6_next_hop_type_cmd = {
3453 : "ipv6 next-hop type",
3454 : route_match_ipv6_next_hop_type,
3455 : route_match_ipv6_next_hop_type_compile,
3456 : route_match_ipv6_next_hop_type_free
3457 : };
3458 :
3459 : /* `set ipv6 nexthop global IP_ADDRESS' */
3460 :
3461 : /* Set nexthop to object. object must be pointer to struct attr. */
3462 : static enum route_map_cmd_result_t
3463 0 : route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, void *object)
3464 : {
3465 0 : struct in6_addr *address;
3466 0 : struct bgp_path_info *path;
3467 :
3468 : /* Fetch routemap's rule information. */
3469 0 : address = rule;
3470 0 : path = object;
3471 :
3472 : /* Set next hop value. */
3473 0 : path->attr->mp_nexthop_global = *address;
3474 :
3475 : /* Set nexthop length. */
3476 0 : if (path->attr->mp_nexthop_len == 0)
3477 0 : path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3478 :
3479 0 : SET_FLAG(path->attr->rmap_change_flags,
3480 : BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
3481 :
3482 0 : return RMAP_OKAY;
3483 : }
3484 :
3485 : /* Route map `ip next-hop' compile function. Given string is converted
3486 : to struct in_addr structure. */
3487 0 : static void *route_set_ipv6_nexthop_global_compile(const char *arg)
3488 : {
3489 0 : int ret;
3490 0 : struct in6_addr *address;
3491 :
3492 0 : address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3493 :
3494 0 : ret = inet_pton(AF_INET6, arg, address);
3495 :
3496 0 : if (ret == 0) {
3497 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3498 0 : return NULL;
3499 : }
3500 :
3501 : return address;
3502 : }
3503 :
3504 : /* Free route map's compiled `ip next-hop' value. */
3505 0 : static void route_set_ipv6_nexthop_global_free(void *rule)
3506 : {
3507 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3508 0 : }
3509 :
3510 : /* Route map commands for ip nexthop set. */
3511 : static const struct route_map_rule_cmd
3512 : route_set_ipv6_nexthop_global_cmd = {
3513 : "ipv6 next-hop global",
3514 : route_set_ipv6_nexthop_global,
3515 : route_set_ipv6_nexthop_global_compile,
3516 : route_set_ipv6_nexthop_global_free
3517 : };
3518 :
3519 : /* Set next-hop preference value. */
3520 : static enum route_map_cmd_result_t
3521 0 : route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
3522 : void *object)
3523 : {
3524 0 : struct bgp_path_info *path;
3525 0 : struct peer *peer;
3526 :
3527 : /* Fetch routemap's rule information. */
3528 0 : path = object;
3529 0 : peer = path->peer;
3530 :
3531 0 : if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3532 : || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
3533 : /* Set next hop preference to global */
3534 0 : path->attr->mp_nexthop_prefer_global = true;
3535 0 : SET_FLAG(path->attr->rmap_change_flags,
3536 : BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3537 : } else {
3538 0 : path->attr->mp_nexthop_prefer_global = false;
3539 0 : SET_FLAG(path->attr->rmap_change_flags,
3540 : BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3541 : }
3542 :
3543 0 : return RMAP_OKAY;
3544 : }
3545 :
3546 0 : static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
3547 : {
3548 0 : int *rins = NULL;
3549 :
3550 0 : rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3551 0 : *rins = 1;
3552 :
3553 0 : return rins;
3554 : }
3555 :
3556 : /* Free route map's compiled `ip next-hop' value. */
3557 0 : static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
3558 : {
3559 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3560 0 : }
3561 :
3562 : /* Route map commands for ip nexthop set preferred. */
3563 : static const struct route_map_rule_cmd
3564 : route_set_ipv6_nexthop_prefer_global_cmd = {
3565 : "ipv6 next-hop prefer-global",
3566 : route_set_ipv6_nexthop_prefer_global,
3567 : route_set_ipv6_nexthop_prefer_global_compile,
3568 : route_set_ipv6_nexthop_prefer_global_free
3569 : };
3570 :
3571 : /* `set ipv6 nexthop local IP_ADDRESS' */
3572 :
3573 : /* Set nexthop to object. object must be pointer to struct attr. */
3574 : static enum route_map_cmd_result_t
3575 0 : route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
3576 : {
3577 0 : struct in6_addr *address;
3578 0 : struct bgp_path_info *path;
3579 :
3580 : /* Fetch routemap's rule information. */
3581 0 : address = rule;
3582 0 : path = object;
3583 :
3584 : /* Set next hop value. */
3585 0 : path->attr->mp_nexthop_local = *address;
3586 :
3587 : /* Set nexthop length. */
3588 0 : if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL &&
3589 : path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
3590 0 : path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3591 :
3592 0 : SET_FLAG(path->attr->rmap_change_flags,
3593 : BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
3594 :
3595 0 : return RMAP_OKAY;
3596 : }
3597 :
3598 : /* Route map `ip nexthop' compile function. Given string is converted
3599 : to struct in_addr structure. */
3600 0 : static void *route_set_ipv6_nexthop_local_compile(const char *arg)
3601 : {
3602 0 : int ret;
3603 0 : struct in6_addr *address;
3604 :
3605 0 : address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3606 :
3607 0 : ret = inet_pton(AF_INET6, arg, address);
3608 :
3609 0 : if (ret == 0) {
3610 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3611 0 : return NULL;
3612 : }
3613 :
3614 : return address;
3615 : }
3616 :
3617 : /* Free route map's compiled `ip nexthop' value. */
3618 0 : static void route_set_ipv6_nexthop_local_free(void *rule)
3619 : {
3620 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3621 0 : }
3622 :
3623 : /* Route map commands for ip nexthop set. */
3624 : static const struct route_map_rule_cmd
3625 : route_set_ipv6_nexthop_local_cmd = {
3626 : "ipv6 next-hop local",
3627 : route_set_ipv6_nexthop_local,
3628 : route_set_ipv6_nexthop_local_compile,
3629 : route_set_ipv6_nexthop_local_free
3630 : };
3631 :
3632 : /* `set ipv6 nexthop peer-address' */
3633 :
3634 : /* Set nexthop to object. object must be pointer to struct attr. */
3635 : static enum route_map_cmd_result_t
3636 0 : route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
3637 : {
3638 0 : struct in6_addr peer_address;
3639 0 : struct bgp_path_info *path;
3640 0 : struct peer *peer;
3641 :
3642 : /* Fetch routemap's rule information. */
3643 0 : path = object;
3644 0 : peer = path->peer;
3645 :
3646 0 : if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3647 : || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
3648 0 : && peer->su_remote
3649 0 : && sockunion_family(peer->su_remote) == AF_INET6) {
3650 0 : peer_address = peer->su_remote->sin6.sin6_addr;
3651 : /* Set next hop value and length in attribute. */
3652 0 : if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
3653 0 : path->attr->mp_nexthop_local = peer_address;
3654 0 : if (path->attr->mp_nexthop_len
3655 : != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3656 0 : path->attr->mp_nexthop_len =
3657 : BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3658 : } else {
3659 0 : path->attr->mp_nexthop_global = peer_address;
3660 0 : if (path->attr->mp_nexthop_len == 0)
3661 0 : path->attr->mp_nexthop_len =
3662 : BGP_ATTR_NHLEN_IPV6_GLOBAL;
3663 : }
3664 :
3665 0 : } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
3666 : /* The next hop value will be set as part of packet
3667 : * rewrite.
3668 : * Set the flags here to indicate that rewrite needs to
3669 : * be done.
3670 : * Also, clear the value - we clear both global and
3671 : * link-local
3672 : * nexthops, whether we send one or both is determined
3673 : * elsewhere.
3674 : */
3675 0 : SET_FLAG(path->attr->rmap_change_flags,
3676 : BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3677 : /* clear next hop value. */
3678 0 : memset(&(path->attr->mp_nexthop_global), 0,
3679 : sizeof(struct in6_addr));
3680 0 : memset(&(path->attr->mp_nexthop_local), 0,
3681 : sizeof(struct in6_addr));
3682 : }
3683 :
3684 0 : return RMAP_OKAY;
3685 : }
3686 :
3687 : /* Route map `ip next-hop' compile function. Given string is converted
3688 : to struct in_addr structure. */
3689 0 : static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
3690 : {
3691 0 : int *rins = NULL;
3692 :
3693 0 : rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3694 0 : *rins = 1;
3695 :
3696 0 : return rins;
3697 : }
3698 :
3699 : /* Free route map's compiled `ip next-hop' value. */
3700 0 : static void route_set_ipv6_nexthop_peer_free(void *rule)
3701 : {
3702 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3703 0 : }
3704 :
3705 : /* Route map commands for ip nexthop set. */
3706 : static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
3707 : "ipv6 next-hop peer-address",
3708 : route_set_ipv6_nexthop_peer,
3709 : route_set_ipv6_nexthop_peer_compile,
3710 : route_set_ipv6_nexthop_peer_free
3711 : };
3712 :
3713 : /* `set ipv4 vpn next-hop A.B.C.D' */
3714 :
3715 : static enum route_map_cmd_result_t
3716 0 : route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
3717 : {
3718 0 : struct in_addr *address;
3719 0 : struct bgp_path_info *path;
3720 :
3721 : /* Fetch routemap's rule information. */
3722 0 : address = rule;
3723 0 : path = object;
3724 :
3725 : /* Set next hop value. */
3726 0 : path->attr->mp_nexthop_global_in = *address;
3727 0 : path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
3728 :
3729 0 : SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_VPNV4_NHOP_CHANGED);
3730 :
3731 0 : return RMAP_OKAY;
3732 : }
3733 :
3734 0 : static void *route_set_vpnv4_nexthop_compile(const char *arg)
3735 : {
3736 0 : int ret;
3737 0 : struct in_addr *address;
3738 :
3739 0 : address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3740 :
3741 0 : ret = inet_aton(arg, address);
3742 :
3743 0 : if (ret == 0) {
3744 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3745 0 : return NULL;
3746 : }
3747 :
3748 : return address;
3749 : }
3750 :
3751 : /* `set ipv6 vpn next-hop A.B.C.D' */
3752 :
3753 : static enum route_map_cmd_result_t
3754 0 : route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
3755 : {
3756 0 : struct in6_addr *address;
3757 0 : struct bgp_path_info *path;
3758 :
3759 : /* Fetch routemap's rule information. */
3760 0 : address = rule;
3761 0 : path = object;
3762 :
3763 : /* Set next hop value. */
3764 0 : memcpy(&path->attr->mp_nexthop_global, address,
3765 : sizeof(struct in6_addr));
3766 0 : path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
3767 :
3768 0 : SET_FLAG(path->attr->rmap_change_flags,
3769 : BATTR_RMAP_VPNV6_GLOBAL_NHOP_CHANGED);
3770 :
3771 0 : return RMAP_OKAY;
3772 : }
3773 :
3774 0 : static void *route_set_vpnv6_nexthop_compile(const char *arg)
3775 : {
3776 0 : int ret;
3777 0 : struct in6_addr *address;
3778 :
3779 0 : address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3780 0 : ret = inet_pton(AF_INET6, arg, address);
3781 :
3782 0 : if (ret == 0) {
3783 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3784 0 : return NULL;
3785 : }
3786 :
3787 : return address;
3788 : }
3789 :
3790 0 : static void route_set_vpn_nexthop_free(void *rule)
3791 : {
3792 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3793 0 : }
3794 :
3795 : /* Route map commands for ipv4 next-hop set. */
3796 : static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
3797 : "ipv4 vpn next-hop",
3798 : route_set_vpnv4_nexthop,
3799 : route_set_vpnv4_nexthop_compile,
3800 : route_set_vpn_nexthop_free
3801 : };
3802 :
3803 : /* Route map commands for ipv6 next-hop set. */
3804 : static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
3805 : "ipv6 vpn next-hop",
3806 : route_set_vpnv6_nexthop,
3807 : route_set_vpnv6_nexthop_compile,
3808 : route_set_vpn_nexthop_free
3809 : };
3810 :
3811 : /* `set originator-id' */
3812 :
3813 : /* For origin set. */
3814 : static enum route_map_cmd_result_t
3815 0 : route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
3816 : {
3817 0 : struct in_addr *address;
3818 0 : struct bgp_path_info *path;
3819 :
3820 0 : address = rule;
3821 0 : path = object;
3822 :
3823 0 : path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
3824 0 : path->attr->originator_id = *address;
3825 :
3826 0 : return RMAP_OKAY;
3827 : }
3828 :
3829 : /* Compile function for originator-id set. */
3830 0 : static void *route_set_originator_id_compile(const char *arg)
3831 : {
3832 0 : int ret;
3833 0 : struct in_addr *address;
3834 :
3835 0 : address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3836 :
3837 0 : ret = inet_aton(arg, address);
3838 :
3839 0 : if (ret == 0) {
3840 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3841 0 : return NULL;
3842 : }
3843 :
3844 : return address;
3845 : }
3846 :
3847 : /* Compile function for originator_id set. */
3848 0 : static void route_set_originator_id_free(void *rule)
3849 : {
3850 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3851 0 : }
3852 :
3853 : /* Set originator-id rule structure. */
3854 : static const struct route_map_rule_cmd route_set_originator_id_cmd = {
3855 : "originator-id",
3856 : route_set_originator_id,
3857 : route_set_originator_id_compile,
3858 : route_set_originator_id_free,
3859 : };
3860 :
3861 : static enum route_map_cmd_result_t
3862 0 : route_match_rpki_extcommunity(void *rule, const struct prefix *prefix,
3863 : void *object)
3864 : {
3865 0 : struct bgp_path_info *path;
3866 0 : struct ecommunity *ecomm;
3867 0 : struct ecommunity_val *ecomm_val;
3868 0 : enum rpki_states *rpki_status = rule;
3869 0 : enum rpki_states ecomm_rpki_status = RPKI_NOT_BEING_USED;
3870 :
3871 0 : path = object;
3872 :
3873 0 : ecomm = bgp_attr_get_ecommunity(path->attr);
3874 0 : if (!ecomm)
3875 : return RMAP_NOMATCH;
3876 :
3877 0 : ecomm_val = ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS,
3878 : ECOMMUNITY_ORIGIN_VALIDATION_STATE);
3879 0 : if (!ecomm_val)
3880 : return RMAP_NOMATCH;
3881 :
3882 : /* The Origin Validation State is encoded in the last octet of
3883 : * the extended community.
3884 : */
3885 0 : switch (ecomm_val->val[7]) {
3886 : case ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID:
3887 : ecomm_rpki_status = RPKI_VALID;
3888 : break;
3889 : case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND:
3890 : ecomm_rpki_status = RPKI_NOTFOUND;
3891 : break;
3892 : case ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID:
3893 : ecomm_rpki_status = RPKI_INVALID;
3894 : break;
3895 : case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED:
3896 : break;
3897 : }
3898 :
3899 0 : if (ecomm_rpki_status == *rpki_status)
3900 : return RMAP_MATCH;
3901 :
3902 : return RMAP_NOMATCH;
3903 : }
3904 :
3905 0 : static void *route_match_extcommunity_compile(const char *arg)
3906 : {
3907 0 : int *rpki_status;
3908 :
3909 0 : rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3910 :
3911 0 : if (strcmp(arg, "valid") == 0)
3912 0 : *rpki_status = RPKI_VALID;
3913 0 : else if (strcmp(arg, "invalid") == 0)
3914 0 : *rpki_status = RPKI_INVALID;
3915 : else
3916 0 : *rpki_status = RPKI_NOTFOUND;
3917 :
3918 0 : return rpki_status;
3919 : }
3920 :
3921 : static const struct route_map_rule_cmd route_match_rpki_extcommunity_cmd = {
3922 : "rpki-extcommunity",
3923 : route_match_rpki_extcommunity,
3924 : route_match_extcommunity_compile,
3925 : route_value_free
3926 : };
3927 :
3928 : /*
3929 : * This is the workhorse routine for processing in/out routemap
3930 : * modifications.
3931 : */
3932 0 : static void bgp_route_map_process_peer(const char *rmap_name,
3933 : struct route_map *map, struct peer *peer,
3934 : int afi, int safi, int route_update)
3935 : {
3936 0 : struct bgp_filter *filter;
3937 :
3938 0 : if (!peer || !rmap_name)
3939 : return;
3940 :
3941 0 : filter = &peer->filter[afi][safi];
3942 : /*
3943 : * in is for non-route-server clients,
3944 : * out is for all peers
3945 : */
3946 0 : if (filter->map[RMAP_IN].name
3947 0 : && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
3948 0 : filter->map[RMAP_IN].map = map;
3949 :
3950 0 : if (route_update && peer_established(peer)) {
3951 0 : if (CHECK_FLAG(peer->af_flags[afi][safi],
3952 : PEER_FLAG_SOFT_RECONFIG)) {
3953 0 : if (bgp_debug_update(peer, NULL, NULL, 1))
3954 0 : zlog_debug(
3955 : "Processing route_map %s(%s:%s) update on peer %s (inbound, soft-reconfig)",
3956 : rmap_name, afi2str(afi),
3957 : safi2str(safi), peer->host);
3958 :
3959 0 : bgp_soft_reconfig_in(peer, afi, safi);
3960 0 : } else if (CHECK_FLAG(peer->cap,
3961 : PEER_CAP_REFRESH_OLD_RCV)
3962 0 : || CHECK_FLAG(peer->cap,
3963 : PEER_CAP_REFRESH_NEW_RCV)) {
3964 0 : if (bgp_debug_update(peer, NULL, NULL, 1))
3965 0 : zlog_debug(
3966 : "Processing route_map %s(%s:%s) update on peer %s (inbound, route-refresh)",
3967 : rmap_name, afi2str(afi),
3968 : safi2str(safi), peer->host);
3969 0 : bgp_route_refresh_send(
3970 : peer, afi, safi, 0, 0, 0,
3971 : BGP_ROUTE_REFRESH_NORMAL);
3972 : }
3973 : }
3974 : }
3975 :
3976 : /*
3977 : * For outbound, unsuppress and default-originate map change (content or
3978 : * map created), merely update the "config" here, the actual route
3979 : * announcement happens at the group level.
3980 : */
3981 0 : if (filter->map[RMAP_OUT].name
3982 0 : && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
3983 0 : filter->map[RMAP_OUT].map = map;
3984 :
3985 0 : if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
3986 0 : filter->usmap.map = map;
3987 :
3988 0 : if (filter->advmap.aname
3989 0 : && (strcmp(rmap_name, filter->advmap.aname) == 0)) {
3990 0 : filter->advmap.amap = map;
3991 : }
3992 :
3993 0 : if (filter->advmap.cname
3994 0 : && (strcmp(rmap_name, filter->advmap.cname) == 0)) {
3995 0 : filter->advmap.cmap = map;
3996 : }
3997 :
3998 0 : if (peer->default_rmap[afi][safi].name
3999 0 : && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
4000 0 : peer->default_rmap[afi][safi].map = map;
4001 :
4002 : /* Notify BGP conditional advertisement scanner percess */
4003 0 : peer->advmap_config_change[afi][safi] = true;
4004 : }
4005 :
4006 0 : static void bgp_route_map_update_peer_group(const char *rmap_name,
4007 : struct route_map *map,
4008 : struct bgp *bgp)
4009 : {
4010 0 : struct peer_group *group;
4011 0 : struct listnode *node, *nnode;
4012 0 : struct bgp_filter *filter;
4013 0 : int afi, safi;
4014 0 : int direct;
4015 :
4016 0 : if (!bgp)
4017 : return;
4018 :
4019 : /* All the peers have been updated correctly already. This is
4020 : * just updating the placeholder data. No real update required.
4021 : */
4022 0 : for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
4023 0 : FOREACH_AFI_SAFI (afi, safi) {
4024 0 : filter = &group->conf->filter[afi][safi];
4025 :
4026 0 : for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
4027 0 : if ((filter->map[direct].name)
4028 0 : && (strcmp(rmap_name,
4029 : filter->map[direct].name)
4030 : == 0))
4031 0 : filter->map[direct].map = map;
4032 : }
4033 :
4034 0 : if (filter->usmap.name
4035 0 : && (strcmp(rmap_name, filter->usmap.name) == 0))
4036 0 : filter->usmap.map = map;
4037 :
4038 0 : if (filter->advmap.aname &&
4039 0 : (strcmp(rmap_name, filter->advmap.aname) == 0))
4040 0 : filter->advmap.amap = map;
4041 :
4042 0 : if (filter->advmap.cname &&
4043 0 : (strcmp(rmap_name, filter->advmap.cname) == 0))
4044 0 : filter->advmap.cmap = map;
4045 : }
4046 : }
4047 : }
4048 :
4049 : /*
4050 : * Note that if an extreme number (tens of thousands) of route-maps are in use
4051 : * and if bgp has an extreme number of peers, network statements, etc then this
4052 : * function can consume a lot of cycles. This is due to this function being
4053 : * called for each route-map and within this function we walk the list of peers,
4054 : * network statements, etc looking to see if they use this route-map.
4055 : */
4056 0 : static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
4057 : bool route_update)
4058 : {
4059 0 : int i;
4060 0 : bool matched;
4061 0 : afi_t afi;
4062 0 : safi_t safi;
4063 0 : struct peer *peer;
4064 0 : struct bgp_dest *bn;
4065 0 : struct bgp_static *bgp_static;
4066 0 : struct bgp_aggregate *aggregate;
4067 0 : struct listnode *node, *nnode;
4068 0 : struct route_map *map;
4069 0 : char buf[INET6_ADDRSTRLEN];
4070 :
4071 0 : map = route_map_lookup_by_name(rmap_name);
4072 :
4073 0 : for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
4074 :
4075 : /* Ignore dummy peer-group structure */
4076 0 : if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4077 0 : continue;
4078 :
4079 0 : FOREACH_AFI_SAFI (afi, safi) {
4080 : /* process in/out/import/export/default-orig
4081 : * route-maps */
4082 0 : bgp_route_map_process_peer(rmap_name, map, peer, afi,
4083 : safi, route_update);
4084 : }
4085 : }
4086 :
4087 : /* for outbound/default-orig route-maps, process for groups */
4088 0 : update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
4089 : route_update, 0);
4090 :
4091 : /* update peer-group config (template) */
4092 0 : bgp_route_map_update_peer_group(rmap_name, map, bgp);
4093 :
4094 0 : FOREACH_AFI_SAFI (afi, safi) {
4095 : /* For table route-map updates. */
4096 0 : if (!bgp_fibupd_safi(safi))
4097 0 : continue;
4098 :
4099 0 : if (bgp->table_map[afi][safi].name
4100 0 : && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
4101 : == 0)) {
4102 :
4103 : /* bgp->table_map[afi][safi].map is NULL.
4104 : * i.e Route map creation event.
4105 : * So update applied_counter.
4106 : * If it is not NULL, i.e It may be routemap updation or
4107 : * deletion. so no need to update the counter.
4108 : */
4109 0 : if (!bgp->table_map[afi][safi].map)
4110 0 : route_map_counter_increment(map);
4111 0 : bgp->table_map[afi][safi].map = map;
4112 :
4113 0 : if (BGP_DEBUG(zebra, ZEBRA))
4114 0 : zlog_debug(
4115 : "Processing route_map %s(%s:%s) update on table map",
4116 : rmap_name, afi2str(afi),
4117 : safi2str(safi));
4118 0 : if (route_update)
4119 0 : bgp_zebra_announce_table(bgp, afi, safi);
4120 : }
4121 :
4122 : /* For network route-map updates. */
4123 0 : for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
4124 0 : bn = bgp_route_next(bn)) {
4125 0 : bgp_static = bgp_dest_get_bgp_static_info(bn);
4126 0 : if (!bgp_static)
4127 0 : continue;
4128 :
4129 0 : if (!bgp_static->rmap.name
4130 0 : || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
4131 0 : continue;
4132 :
4133 0 : if (!bgp_static->rmap.map)
4134 0 : route_map_counter_increment(map);
4135 :
4136 0 : bgp_static->rmap.map = map;
4137 :
4138 0 : if (route_update && !bgp_static->backdoor) {
4139 0 : const struct prefix *bn_p =
4140 0 : bgp_dest_get_prefix(bn);
4141 :
4142 0 : if (bgp_debug_zebra(bn_p))
4143 0 : zlog_debug(
4144 : "Processing route_map %s(%s:%s) update on static route %s",
4145 : rmap_name, afi2str(afi),
4146 : safi2str(safi),
4147 : inet_ntop(bn_p->family,
4148 : &bn_p->u.prefix, buf,
4149 : sizeof(buf)));
4150 0 : bgp_static_update(bgp, bn_p, bgp_static, afi,
4151 : safi);
4152 : }
4153 : }
4154 :
4155 : /* For aggregate-address route-map updates. */
4156 0 : for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
4157 0 : bn = bgp_route_next(bn)) {
4158 0 : aggregate = bgp_dest_get_bgp_aggregate_info(bn);
4159 0 : if (!aggregate)
4160 0 : continue;
4161 :
4162 0 : matched = false;
4163 :
4164 : /* Update suppress map pointer. */
4165 0 : if (aggregate->suppress_map_name
4166 0 : && strmatch(aggregate->suppress_map_name,
4167 : rmap_name)) {
4168 0 : if (aggregate->rmap.map == NULL)
4169 0 : route_map_counter_increment(map);
4170 :
4171 0 : aggregate->suppress_map = map;
4172 :
4173 0 : bgp_aggregate_toggle_suppressed(
4174 : aggregate, bgp, bgp_dest_get_prefix(bn),
4175 : afi, safi, false);
4176 :
4177 0 : matched = true;
4178 : }
4179 :
4180 0 : if (aggregate->rmap.name
4181 0 : && strmatch(rmap_name, aggregate->rmap.name)) {
4182 0 : if (aggregate->rmap.map == NULL)
4183 0 : route_map_counter_increment(map);
4184 :
4185 0 : aggregate->rmap.map = map;
4186 :
4187 0 : matched = true;
4188 : }
4189 :
4190 0 : if (matched && route_update) {
4191 0 : const struct prefix *bn_p =
4192 0 : bgp_dest_get_prefix(bn);
4193 :
4194 0 : if (bgp_debug_zebra(bn_p))
4195 0 : zlog_debug(
4196 : "Processing route_map %s(%s:%s) update on aggregate-address route %s",
4197 : rmap_name, afi2str(afi),
4198 : safi2str(safi),
4199 : inet_ntop(bn_p->family,
4200 : &bn_p->u.prefix, buf,
4201 : sizeof(buf)));
4202 0 : bgp_aggregate_route(bgp, bn_p, afi, safi,
4203 : aggregate);
4204 : }
4205 : }
4206 : }
4207 :
4208 : /* For redistribute route-map updates. */
4209 0 : for (afi = AFI_IP; afi < AFI_MAX; afi++)
4210 0 : for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
4211 0 : struct list *red_list;
4212 0 : struct bgp_redist *red;
4213 :
4214 0 : red_list = bgp->redist[afi][i];
4215 0 : if (!red_list)
4216 0 : continue;
4217 :
4218 0 : for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
4219 0 : if (!red->rmap.name
4220 0 : || (strcmp(rmap_name, red->rmap.name) != 0))
4221 0 : continue;
4222 :
4223 0 : if (!red->rmap.map)
4224 0 : route_map_counter_increment(map);
4225 :
4226 0 : red->rmap.map = map;
4227 :
4228 0 : if (!route_update)
4229 0 : continue;
4230 :
4231 0 : if (BGP_DEBUG(zebra, ZEBRA))
4232 0 : zlog_debug(
4233 : "Processing route_map %s(%s:%s) update on redistributed routes",
4234 : rmap_name, afi2str(afi),
4235 : safi2str(safi));
4236 :
4237 0 : bgp_redistribute_resend(bgp, afi, i,
4238 0 : red->instance);
4239 : }
4240 : }
4241 :
4242 : /* for type5 command route-maps */
4243 0 : FOREACH_AFI_SAFI (afi, safi) {
4244 0 : if (!bgp->adv_cmd_rmap[afi][safi].name
4245 0 : || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
4246 : != 0)
4247 0 : continue;
4248 :
4249 : /* Make sure the route-map is populated here if not already done */
4250 0 : bgp->adv_cmd_rmap[afi][safi].map = map;
4251 :
4252 0 : if (BGP_DEBUG(zebra, ZEBRA))
4253 0 : zlog_debug(
4254 : "Processing route_map %s(%s:%s) update on advertise type5 route command",
4255 : rmap_name, afi2str(afi), safi2str(safi));
4256 :
4257 0 : if (route_update && advertise_type5_routes(bgp, afi)) {
4258 0 : bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
4259 0 : bgp_evpn_advertise_type5_routes(bgp, afi, safi);
4260 : }
4261 : }
4262 0 : }
4263 :
4264 0 : static void bgp_route_map_process_update_cb(char *rmap_name)
4265 : {
4266 0 : struct listnode *node, *nnode;
4267 0 : struct bgp *bgp;
4268 :
4269 0 : for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
4270 0 : bgp_route_map_process_update(bgp, rmap_name, true);
4271 :
4272 : #ifdef ENABLE_BGP_VNC
4273 0 : vnc_routemap_update(bgp, __func__);
4274 : #endif
4275 : }
4276 :
4277 0 : vpn_policy_routemap_event(rmap_name);
4278 0 : }
4279 :
4280 0 : void bgp_route_map_update_timer(struct thread *thread)
4281 : {
4282 0 : route_map_walk_update_list(bgp_route_map_process_update_cb);
4283 0 : }
4284 :
4285 0 : static void bgp_route_map_mark_update(const char *rmap_name)
4286 : {
4287 0 : struct listnode *node, *nnode;
4288 0 : struct bgp *bgp;
4289 :
4290 : /* If new update is received before the current timer timed out,
4291 : * turn it off and start a new timer.
4292 : */
4293 0 : THREAD_OFF(bm->t_rmap_update);
4294 :
4295 : /* rmap_update_timer of 0 means don't do route updates */
4296 0 : if (bm->rmap_update_timer) {
4297 0 : thread_add_timer(bm->master, bgp_route_map_update_timer,
4298 : NULL, bm->rmap_update_timer,
4299 : &bm->t_rmap_update);
4300 :
4301 : /* Signal the groups that a route-map update event has
4302 : * started */
4303 0 : for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
4304 0 : update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP,
4305 : rmap_name, true, 1);
4306 : } else {
4307 0 : for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
4308 0 : bgp_route_map_process_update(bgp, rmap_name, false);
4309 : #ifdef ENABLE_BGP_VNC
4310 0 : vnc_routemap_update(bgp, __func__);
4311 : #endif
4312 : }
4313 :
4314 0 : vpn_policy_routemap_event(rmap_name);
4315 : }
4316 0 : }
4317 :
4318 0 : static void bgp_route_map_add(const char *rmap_name)
4319 : {
4320 0 : if (route_map_mark_updated(rmap_name) == 0)
4321 0 : bgp_route_map_mark_update(rmap_name);
4322 :
4323 0 : route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
4324 0 : }
4325 :
4326 0 : static void bgp_route_map_delete(const char *rmap_name)
4327 : {
4328 0 : if (route_map_mark_updated(rmap_name) == 0)
4329 0 : bgp_route_map_mark_update(rmap_name);
4330 :
4331 0 : route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
4332 0 : }
4333 :
4334 0 : static void bgp_route_map_event(const char *rmap_name)
4335 : {
4336 0 : if (route_map_mark_updated(rmap_name) == 0)
4337 0 : bgp_route_map_mark_update(rmap_name);
4338 :
4339 0 : route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
4340 0 : }
4341 :
4342 0 : DEFUN_YANG (match_mac_address,
4343 : match_mac_address_cmd,
4344 : "match mac address ACCESSLIST_MAC_NAME",
4345 : MATCH_STR
4346 : "mac address\n"
4347 : "Match address of route\n"
4348 : "MAC Access-list name\n")
4349 : {
4350 0 : const char *xpath =
4351 : "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4352 0 : char xpath_value[XPATH_MAXLEN];
4353 :
4354 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4355 0 : snprintf(xpath_value, sizeof(xpath_value),
4356 : "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4357 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4358 :
4359 0 : return nb_cli_apply_changes(vty, NULL);
4360 : }
4361 :
4362 0 : DEFUN_YANG (no_match_mac_address,
4363 : no_match_mac_address_cmd,
4364 : "no match mac address ACCESSLIST_MAC_NAME",
4365 : NO_STR
4366 : MATCH_STR
4367 : "mac\n"
4368 : "Match address of route\n"
4369 : "MAC acess-list name\n")
4370 : {
4371 0 : const char *xpath =
4372 : "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4373 :
4374 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4375 0 : return nb_cli_apply_changes(vty, NULL);
4376 : }
4377 :
4378 : /*
4379 : * Helper to handle the case of the user passing in a number or type string
4380 : */
4381 0 : static const char *parse_evpn_rt_type(const char *num_rt_type)
4382 : {
4383 0 : switch (num_rt_type[0]) {
4384 : case '1':
4385 : return "ead";
4386 0 : case '2':
4387 0 : return "macip";
4388 0 : case '3':
4389 0 : return "multicast";
4390 0 : case '4':
4391 0 : return "es";
4392 0 : case '5':
4393 0 : return "prefix";
4394 : default:
4395 0 : break;
4396 : }
4397 :
4398 : /* Was already full type string */
4399 0 : return num_rt_type;
4400 : }
4401 :
4402 0 : DEFUN_YANG (match_evpn_route_type,
4403 : match_evpn_route_type_cmd,
4404 : "match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
4405 : MATCH_STR
4406 : EVPN_HELP_STR
4407 : EVPN_TYPE_HELP_STR
4408 : EVPN_TYPE_1_HELP_STR
4409 : EVPN_TYPE_1_HELP_STR
4410 : EVPN_TYPE_2_HELP_STR
4411 : EVPN_TYPE_2_HELP_STR
4412 : EVPN_TYPE_3_HELP_STR
4413 : EVPN_TYPE_3_HELP_STR
4414 : EVPN_TYPE_4_HELP_STR
4415 : EVPN_TYPE_4_HELP_STR
4416 : EVPN_TYPE_5_HELP_STR
4417 : EVPN_TYPE_5_HELP_STR)
4418 : {
4419 0 : const char *xpath =
4420 : "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4421 0 : char xpath_value[XPATH_MAXLEN];
4422 :
4423 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4424 0 : snprintf(xpath_value, sizeof(xpath_value),
4425 : "%s/rmap-match-condition/frr-bgp-route-map:evpn-route-type",
4426 : xpath);
4427 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4428 0 : parse_evpn_rt_type(argv[3]->arg));
4429 :
4430 0 : return nb_cli_apply_changes(vty, NULL);
4431 : }
4432 :
4433 0 : DEFUN_YANG (no_match_evpn_route_type,
4434 : no_match_evpn_route_type_cmd,
4435 : "no match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
4436 : NO_STR
4437 : MATCH_STR
4438 : EVPN_HELP_STR
4439 : EVPN_TYPE_HELP_STR
4440 : EVPN_TYPE_1_HELP_STR
4441 : EVPN_TYPE_1_HELP_STR
4442 : EVPN_TYPE_2_HELP_STR
4443 : EVPN_TYPE_2_HELP_STR
4444 : EVPN_TYPE_3_HELP_STR
4445 : EVPN_TYPE_3_HELP_STR
4446 : EVPN_TYPE_4_HELP_STR
4447 : EVPN_TYPE_4_HELP_STR
4448 : EVPN_TYPE_5_HELP_STR
4449 : EVPN_TYPE_5_HELP_STR)
4450 : {
4451 0 : const char *xpath =
4452 : "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4453 :
4454 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4455 :
4456 0 : return nb_cli_apply_changes(vty, NULL);
4457 : }
4458 :
4459 :
4460 0 : DEFUN_YANG (match_evpn_vni,
4461 : match_evpn_vni_cmd,
4462 : "match evpn vni " CMD_VNI_RANGE,
4463 : MATCH_STR
4464 : EVPN_HELP_STR
4465 : "Match VNI\n"
4466 : "VNI ID\n")
4467 : {
4468 0 : const char *xpath =
4469 : "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4470 0 : char xpath_value[XPATH_MAXLEN];
4471 :
4472 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4473 0 : snprintf(xpath_value, sizeof(xpath_value),
4474 : "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4475 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4476 :
4477 0 : return nb_cli_apply_changes(vty, NULL);
4478 : }
4479 :
4480 0 : DEFUN_YANG (no_match_evpn_vni,
4481 : no_match_evpn_vni_cmd,
4482 : "no match evpn vni " CMD_VNI_RANGE,
4483 : NO_STR
4484 : MATCH_STR
4485 : EVPN_HELP_STR
4486 : "Match VNI\n"
4487 : "VNI ID\n")
4488 : {
4489 0 : const char *xpath =
4490 : "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4491 0 : char xpath_value[XPATH_MAXLEN];
4492 :
4493 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4494 0 : snprintf(xpath_value, sizeof(xpath_value),
4495 : "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4496 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, argv[3]->arg);
4497 :
4498 0 : return nb_cli_apply_changes(vty, NULL);
4499 : }
4500 :
4501 0 : DEFUN_YANG (match_evpn_default_route,
4502 : match_evpn_default_route_cmd,
4503 : "match evpn default-route",
4504 : MATCH_STR
4505 : EVPN_HELP_STR
4506 : "default EVPN type-5 route\n")
4507 : {
4508 0 : const char *xpath =
4509 : "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4510 0 : char xpath_value[XPATH_MAXLEN];
4511 :
4512 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4513 :
4514 0 : snprintf(xpath_value, sizeof(xpath_value),
4515 : "%s/rmap-match-condition/frr-bgp-route-map:evpn-default-route",
4516 : xpath);
4517 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
4518 :
4519 0 : return nb_cli_apply_changes(vty, NULL);
4520 : }
4521 :
4522 0 : DEFUN_YANG (no_match_evpn_default_route,
4523 : no_match_evpn_default_route_cmd,
4524 : "no match evpn default-route",
4525 : NO_STR
4526 : MATCH_STR
4527 : EVPN_HELP_STR
4528 : "default EVPN type-5 route\n")
4529 : {
4530 0 : const char *xpath =
4531 : "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4532 :
4533 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4534 :
4535 0 : return nb_cli_apply_changes(vty, NULL);
4536 : }
4537 :
4538 0 : DEFUN_YANG (match_evpn_rd,
4539 : match_evpn_rd_cmd,
4540 : "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4541 : MATCH_STR
4542 : EVPN_HELP_STR
4543 : "Route Distinguisher\n"
4544 : "ASN:XX or A.B.C.D:XX\n")
4545 : {
4546 0 : const char *xpath =
4547 : "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4548 0 : char xpath_value[XPATH_MAXLEN];
4549 :
4550 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4551 0 : snprintf(
4552 : xpath_value, sizeof(xpath_value),
4553 : "%s/rmap-match-condition/frr-bgp-route-map:route-distinguisher",
4554 : xpath);
4555 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4556 :
4557 0 : return nb_cli_apply_changes(vty, NULL);
4558 : }
4559 :
4560 0 : DEFUN_YANG (no_match_evpn_rd,
4561 : no_match_evpn_rd_cmd,
4562 : "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4563 : NO_STR
4564 : MATCH_STR
4565 : EVPN_HELP_STR
4566 : "Route Distinguisher\n"
4567 : "ASN:XX or A.B.C.D:XX\n")
4568 : {
4569 0 : const char *xpath =
4570 : "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4571 :
4572 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4573 0 : return nb_cli_apply_changes(vty, NULL);
4574 : }
4575 :
4576 0 : DEFUN_YANG (set_evpn_gw_ip_ipv4,
4577 : set_evpn_gw_ip_ipv4_cmd,
4578 : "set evpn gateway-ip ipv4 A.B.C.D",
4579 : SET_STR
4580 : EVPN_HELP_STR
4581 : "Set gateway IP for prefix advertisement route\n"
4582 : "IPv4 address\n"
4583 : "Gateway IP address in IPv4 format\n")
4584 : {
4585 0 : int ret;
4586 0 : union sockunion su;
4587 0 : const char *xpath =
4588 : "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4589 0 : char xpath_value[XPATH_MAXLEN];
4590 :
4591 0 : ret = str2sockunion(argv[4]->arg, &su);
4592 0 : if (ret < 0) {
4593 0 : vty_out(vty, "%% Malformed gateway IP\n");
4594 0 : return CMD_WARNING_CONFIG_FAILED;
4595 : }
4596 :
4597 0 : if (su.sin.sin_addr.s_addr == 0 ||
4598 0 : !ipv4_unicast_valid(&su.sin.sin_addr)) {
4599 0 : vty_out(vty,
4600 : "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4601 0 : return CMD_WARNING_CONFIG_FAILED;
4602 : }
4603 :
4604 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4605 :
4606 0 : snprintf(xpath_value, sizeof(xpath_value),
4607 : "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
4608 : xpath);
4609 :
4610 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4611 0 : return nb_cli_apply_changes(vty, NULL);
4612 : }
4613 :
4614 0 : DEFUN_YANG (no_set_evpn_gw_ip_ipv4,
4615 : no_set_evpn_gw_ip_ipv4_cmd,
4616 : "no set evpn gateway-ip ipv4 A.B.C.D",
4617 : NO_STR
4618 : SET_STR
4619 : EVPN_HELP_STR
4620 : "Set gateway IP for prefix advertisement route\n"
4621 : "IPv4 address\n"
4622 : "Gateway IP address in IPv4 format\n")
4623 : {
4624 0 : int ret;
4625 0 : union sockunion su;
4626 0 : const char *xpath =
4627 : "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4628 :
4629 0 : ret = str2sockunion(argv[5]->arg, &su);
4630 0 : if (ret < 0) {
4631 0 : vty_out(vty, "%% Malformed gateway IP\n");
4632 0 : return CMD_WARNING_CONFIG_FAILED;
4633 : }
4634 :
4635 0 : if (su.sin.sin_addr.s_addr == 0 ||
4636 0 : !ipv4_unicast_valid(&su.sin.sin_addr)) {
4637 0 : vty_out(vty,
4638 : "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4639 0 : return CMD_WARNING_CONFIG_FAILED;
4640 : }
4641 :
4642 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4643 :
4644 0 : return nb_cli_apply_changes(vty, NULL);
4645 : }
4646 :
4647 0 : DEFUN_YANG (set_evpn_gw_ip_ipv6,
4648 : set_evpn_gw_ip_ipv6_cmd,
4649 : "set evpn gateway-ip ipv6 X:X::X:X",
4650 : SET_STR
4651 : EVPN_HELP_STR
4652 : "Set gateway IP for prefix advertisement route\n"
4653 : "IPv6 address\n"
4654 : "Gateway IP address in IPv6 format\n")
4655 : {
4656 0 : int ret;
4657 0 : union sockunion su;
4658 0 : const char *xpath =
4659 : "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4660 0 : char xpath_value[XPATH_MAXLEN];
4661 :
4662 0 : ret = str2sockunion(argv[4]->arg, &su);
4663 0 : if (ret < 0) {
4664 0 : vty_out(vty, "%% Malformed gateway IP\n");
4665 0 : return CMD_WARNING_CONFIG_FAILED;
4666 : }
4667 :
4668 0 : if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4669 0 : || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4670 0 : vty_out(vty,
4671 : "%% Gateway IP cannot be a linklocal or multicast address\n");
4672 0 : return CMD_WARNING_CONFIG_FAILED;
4673 : }
4674 :
4675 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4676 :
4677 0 : snprintf(xpath_value, sizeof(xpath_value),
4678 : "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
4679 : xpath);
4680 :
4681 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4682 0 : return nb_cli_apply_changes(vty, NULL);
4683 : }
4684 :
4685 0 : DEFUN_YANG (no_set_evpn_gw_ip_ipv6,
4686 : no_set_evpn_gw_ip_ipv6_cmd,
4687 : "no set evpn gateway-ip ipv6 X:X::X:X",
4688 : NO_STR
4689 : SET_STR
4690 : EVPN_HELP_STR
4691 : "Set gateway IP for prefix advertisement route\n"
4692 : "IPv4 address\n"
4693 : "Gateway IP address in IPv4 format\n")
4694 : {
4695 0 : int ret;
4696 0 : union sockunion su;
4697 0 : const char *xpath =
4698 : "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4699 :
4700 0 : ret = str2sockunion(argv[5]->arg, &su);
4701 0 : if (ret < 0) {
4702 0 : vty_out(vty, "%% Malformed gateway IP\n");
4703 0 : return CMD_WARNING_CONFIG_FAILED;
4704 : }
4705 :
4706 0 : if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4707 0 : || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4708 0 : vty_out(vty,
4709 : "%% Gateway IP cannot be a linklocal or multicast address\n");
4710 0 : return CMD_WARNING_CONFIG_FAILED;
4711 : }
4712 :
4713 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4714 :
4715 0 : return nb_cli_apply_changes(vty, NULL);
4716 : }
4717 :
4718 0 : DEFPY_YANG(match_vrl_source_vrf,
4719 : match_vrl_source_vrf_cmd,
4720 : "match source-vrf NAME$vrf_name",
4721 : MATCH_STR
4722 : "source vrf\n"
4723 : "The VRF name\n")
4724 : {
4725 0 : const char *xpath =
4726 : "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4727 0 : char xpath_value[XPATH_MAXLEN];
4728 :
4729 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4730 0 : snprintf(xpath_value, sizeof(xpath_value),
4731 : "%s/rmap-match-condition/frr-bgp-route-map:source-vrf", xpath);
4732 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, vrf_name);
4733 :
4734 0 : return nb_cli_apply_changes(vty, NULL);
4735 : }
4736 :
4737 0 : DEFPY_YANG(no_match_vrl_source_vrf,
4738 : no_match_vrl_source_vrf_cmd,
4739 : "no match source-vrf NAME$vrf_name",
4740 : NO_STR MATCH_STR
4741 : "source vrf\n"
4742 : "The VRF name\n")
4743 : {
4744 0 : const char *xpath =
4745 : "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4746 :
4747 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4748 0 : return nb_cli_apply_changes(vty, NULL);
4749 : }
4750 :
4751 0 : DEFPY_YANG (match_peer,
4752 : match_peer_cmd,
4753 : "match peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
4754 : MATCH_STR
4755 : "Match peer address\n"
4756 : "IP address of peer\n"
4757 : "IPv6 address of peer\n"
4758 : "Interface name of peer or peer group name\n")
4759 : {
4760 0 : const char *xpath =
4761 : "./match-condition[condition='frr-bgp-route-map:peer']";
4762 0 : char xpath_value[XPATH_MAXLEN];
4763 :
4764 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4765 :
4766 0 : if (addrv4_str) {
4767 0 : snprintf(
4768 : xpath_value, sizeof(xpath_value),
4769 : "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
4770 : xpath);
4771 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4772 : addrv4_str);
4773 0 : } else if (addrv6_str) {
4774 0 : snprintf(
4775 : xpath_value, sizeof(xpath_value),
4776 : "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address",
4777 : xpath);
4778 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4779 : addrv6_str);
4780 : } else {
4781 0 : snprintf(
4782 : xpath_value, sizeof(xpath_value),
4783 : "%s/rmap-match-condition/frr-bgp-route-map:peer-interface",
4784 : xpath);
4785 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, intf);
4786 : }
4787 :
4788 0 : return nb_cli_apply_changes(vty, NULL);
4789 : }
4790 :
4791 0 : DEFUN_YANG (match_peer_local,
4792 : match_peer_local_cmd,
4793 : "match peer local",
4794 : MATCH_STR
4795 : "Match peer address\n"
4796 : "Static or Redistributed routes\n")
4797 : {
4798 0 : const char *xpath =
4799 : "./match-condition[condition='frr-bgp-route-map:peer']";
4800 0 : char xpath_value[XPATH_MAXLEN];
4801 :
4802 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4803 :
4804 0 : snprintf(xpath_value, sizeof(xpath_value),
4805 : "%s/rmap-match-condition/frr-bgp-route-map:peer-local", xpath);
4806 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
4807 :
4808 0 : return nb_cli_apply_changes(vty, NULL);
4809 : }
4810 :
4811 0 : DEFUN_YANG (no_match_peer,
4812 : no_match_peer_cmd,
4813 : "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
4814 : NO_STR
4815 : MATCH_STR
4816 : "Match peer address\n"
4817 : "Static or Redistributed routes\n"
4818 : "IP address of peer\n"
4819 : "IPv6 address of peer\n"
4820 : "Interface name of peer\n")
4821 : {
4822 0 : const char *xpath =
4823 : "./match-condition[condition='frr-bgp-route-map:peer']";
4824 :
4825 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4826 :
4827 0 : return nb_cli_apply_changes(vty, NULL);
4828 : }
4829 :
4830 : #ifdef HAVE_SCRIPTING
4831 : DEFUN_YANG (match_script,
4832 : match_script_cmd,
4833 : "[no] match script WORD",
4834 : NO_STR
4835 : MATCH_STR
4836 : "Execute script to determine match\n"
4837 : "The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
4838 : {
4839 : bool no = strmatch(argv[0]->text, "no");
4840 : int i = 0;
4841 : argv_find(argv, argc, "WORD", &i);
4842 : const char *script = argv[i]->arg;
4843 : const char *xpath =
4844 : "./match-condition[condition='frr-bgp-route-map:match-script']";
4845 : char xpath_value[XPATH_MAXLEN];
4846 :
4847 : if (no) {
4848 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4849 : snprintf(xpath_value, sizeof(xpath_value),
4850 : "%s/rmap-match-condition/frr-bgp-route-map:script",
4851 : xpath);
4852 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4853 : script);
4854 :
4855 : return nb_cli_apply_changes(vty, NULL);
4856 : }
4857 :
4858 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4859 : snprintf(xpath_value, sizeof(xpath_value),
4860 : "%s/rmap-match-condition/frr-bgp-route-map:script",
4861 : xpath);
4862 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4863 : script);
4864 :
4865 : return nb_cli_apply_changes(vty, NULL);
4866 : }
4867 : #endif /* HAVE_SCRIPTING */
4868 :
4869 : /* match probability */
4870 0 : DEFUN_YANG (match_probability,
4871 : match_probability_cmd,
4872 : "match probability (0-100)",
4873 : MATCH_STR
4874 : "Match portion of routes defined by percentage value\n"
4875 : "Percentage of routes\n")
4876 : {
4877 0 : int idx_number = 2;
4878 :
4879 0 : const char *xpath =
4880 : "./match-condition[condition='frr-bgp-route-map:probability']";
4881 0 : char xpath_value[XPATH_MAXLEN];
4882 :
4883 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4884 0 : snprintf(xpath_value, sizeof(xpath_value),
4885 : "%s/rmap-match-condition/frr-bgp-route-map:probability",
4886 : xpath);
4887 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4888 0 : argv[idx_number]->arg);
4889 :
4890 0 : return nb_cli_apply_changes(vty, NULL);
4891 : }
4892 :
4893 :
4894 0 : DEFUN_YANG (no_match_probability,
4895 : no_match_probability_cmd,
4896 : "no match probability [(1-99)]",
4897 : NO_STR
4898 : MATCH_STR
4899 : "Match portion of routes defined by percentage value\n"
4900 : "Percentage of routes\n")
4901 : {
4902 0 : int idx_number = 3;
4903 0 : const char *xpath =
4904 : "./match-condition[condition='frr-bgp-route-map:probability']";
4905 0 : char xpath_value[XPATH_MAXLEN];
4906 :
4907 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4908 :
4909 0 : if (argc <= idx_number)
4910 0 : return nb_cli_apply_changes(vty, NULL);
4911 :
4912 0 : snprintf(xpath_value, sizeof(xpath_value),
4913 : "%s/rmap-match-condition/frr-bgp-route-map:probability",
4914 : xpath);
4915 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4916 0 : argv[idx_number]->arg);
4917 :
4918 0 : return nb_cli_apply_changes(vty, NULL);
4919 : }
4920 :
4921 :
4922 0 : DEFPY_YANG (match_ip_route_source,
4923 : match_ip_route_source_cmd,
4924 : "match ip route-source ACCESSLIST4_NAME",
4925 : MATCH_STR
4926 : IP_STR
4927 : "Match advertising source address of route\n"
4928 : "IP Access-list name\n")
4929 : {
4930 0 : const char *xpath =
4931 : "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
4932 0 : char xpath_value[XPATH_MAXLEN + 32];
4933 0 : int idx_acl = 3;
4934 :
4935 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4936 0 : snprintf(xpath_value, sizeof(xpath_value),
4937 : "%s/rmap-match-condition/frr-bgp-route-map:list-name",
4938 : xpath);
4939 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4940 0 : argv[idx_acl]->arg);
4941 :
4942 0 : return nb_cli_apply_changes(vty, NULL);
4943 : }
4944 :
4945 :
4946 0 : DEFUN_YANG (no_match_ip_route_source,
4947 : no_match_ip_route_source_cmd,
4948 : "no match ip route-source [ACCESSLIST4_NAME]",
4949 : NO_STR
4950 : MATCH_STR
4951 : IP_STR
4952 : "Match advertising source address of route\n"
4953 : "IP Access-list name\n")
4954 : {
4955 0 : const char *xpath =
4956 : "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
4957 :
4958 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4959 0 : return nb_cli_apply_changes(vty, NULL);
4960 : }
4961 :
4962 0 : DEFUN_YANG (match_ip_route_source_prefix_list,
4963 : match_ip_route_source_prefix_list_cmd,
4964 : "match ip route-source prefix-list PREFIXLIST_NAME",
4965 : MATCH_STR
4966 : IP_STR
4967 : "Match advertising source address of route\n"
4968 : "Match entries of prefix-lists\n"
4969 : "IP prefix-list name\n")
4970 : {
4971 0 : int idx_word = 4;
4972 0 : const char *xpath =
4973 : "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
4974 0 : char xpath_value[XPATH_MAXLEN + 32];
4975 :
4976 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4977 0 : snprintf(xpath_value, sizeof(xpath_value),
4978 : "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4979 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4980 0 : argv[idx_word]->arg);
4981 :
4982 0 : return nb_cli_apply_changes(vty, NULL);
4983 : }
4984 :
4985 :
4986 0 : DEFUN_YANG (no_match_ip_route_source_prefix_list,
4987 : no_match_ip_route_source_prefix_list_cmd,
4988 : "no match ip route-source prefix-list [PREFIXLIST_NAME]",
4989 : NO_STR
4990 : MATCH_STR
4991 : IP_STR
4992 : "Match advertising source address of route\n"
4993 : "Match entries of prefix-lists\n"
4994 : "IP prefix-list name\n")
4995 : {
4996 0 : const char *xpath =
4997 : "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
4998 :
4999 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5000 0 : return nb_cli_apply_changes(vty, NULL);
5001 : }
5002 :
5003 0 : DEFUN_YANG (match_local_pref,
5004 : match_local_pref_cmd,
5005 : "match local-preference (0-4294967295)",
5006 : MATCH_STR
5007 : "Match local-preference of route\n"
5008 : "Metric value\n")
5009 : {
5010 0 : int idx_number = 2;
5011 :
5012 0 : const char *xpath =
5013 : "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5014 0 : char xpath_value[XPATH_MAXLEN];
5015 :
5016 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5017 0 : snprintf(xpath_value, sizeof(xpath_value),
5018 : "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5019 : xpath);
5020 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5021 0 : argv[idx_number]->arg);
5022 :
5023 0 : return nb_cli_apply_changes(vty, NULL);
5024 : }
5025 :
5026 :
5027 0 : DEFUN_YANG (no_match_local_pref,
5028 : no_match_local_pref_cmd,
5029 : "no match local-preference [(0-4294967295)]",
5030 : NO_STR
5031 : MATCH_STR
5032 : "Match local preference of route\n"
5033 : "Local preference value\n")
5034 : {
5035 0 : int idx_localpref = 3;
5036 0 : const char *xpath =
5037 : "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5038 0 : char xpath_value[XPATH_MAXLEN];
5039 :
5040 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5041 :
5042 0 : if (argc <= idx_localpref)
5043 0 : return nb_cli_apply_changes(vty, NULL);
5044 :
5045 0 : snprintf(xpath_value, sizeof(xpath_value),
5046 : "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5047 : xpath);
5048 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5049 0 : argv[idx_localpref]->arg);
5050 :
5051 0 : return nb_cli_apply_changes(vty, NULL);
5052 : }
5053 :
5054 0 : DEFUN_YANG(match_alias, match_alias_cmd, "match alias ALIAS_NAME",
5055 : MATCH_STR
5056 : "Match BGP community alias name\n"
5057 : "BGP community alias name\n")
5058 : {
5059 0 : const char *alias = argv[2]->arg;
5060 0 : struct community_alias ca1;
5061 0 : struct community_alias *lookup_alias;
5062 :
5063 0 : const char *xpath =
5064 : "./match-condition[condition='frr-bgp-route-map:match-alias']";
5065 0 : char xpath_value[XPATH_MAXLEN];
5066 :
5067 0 : memset(&ca1, 0, sizeof(ca1));
5068 0 : strlcpy(ca1.alias, alias, sizeof(ca1.alias));
5069 0 : lookup_alias = bgp_ca_alias_lookup(&ca1);
5070 0 : if (!lookup_alias) {
5071 0 : vty_out(vty, "%% BGP alias name '%s' does not exist\n", alias);
5072 0 : return CMD_WARNING_CONFIG_FAILED;
5073 : }
5074 :
5075 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5076 0 : snprintf(xpath_value, sizeof(xpath_value),
5077 : "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5078 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, alias);
5079 :
5080 0 : return nb_cli_apply_changes(vty, NULL);
5081 : }
5082 :
5083 :
5084 0 : DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
5085 : NO_STR MATCH_STR
5086 : "Match BGP community alias name\n"
5087 : "BGP community alias name\n")
5088 : {
5089 0 : int idx_alias = 3;
5090 0 : const char *xpath =
5091 : "./match-condition[condition='frr-bgp-route-map:match-alias']";
5092 0 : char xpath_value[XPATH_MAXLEN];
5093 :
5094 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5095 :
5096 0 : if (argc <= idx_alias)
5097 0 : return nb_cli_apply_changes(vty, NULL);
5098 :
5099 0 : snprintf(xpath_value, sizeof(xpath_value),
5100 : "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5101 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5102 0 : argv[idx_alias]->arg);
5103 :
5104 0 : return nb_cli_apply_changes(vty, NULL);
5105 : }
5106 :
5107 0 : DEFPY_YANG (match_community,
5108 : match_community_cmd,
5109 : "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
5110 : MATCH_STR
5111 : "Match BGP community list\n"
5112 : "Community-list number (standard)\n"
5113 : "Community-list number (expanded)\n"
5114 : "Community-list name\n"
5115 : "Do exact matching of communities\n")
5116 : {
5117 0 : const char *xpath =
5118 : "./match-condition[condition='frr-bgp-route-map:match-community']";
5119 0 : char xpath_value[XPATH_MAXLEN];
5120 0 : char xpath_match[XPATH_MAXLEN];
5121 0 : int idx_comm_list = 2;
5122 :
5123 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5124 :
5125 0 : snprintf(
5126 : xpath_value, sizeof(xpath_value),
5127 : "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5128 : xpath);
5129 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5130 :
5131 0 : if (argc == 4) {
5132 0 : snprintf(
5133 : xpath_match, sizeof(xpath_match),
5134 : "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5135 : xpath);
5136 0 : nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5137 : "true");
5138 : } else {
5139 0 : snprintf(
5140 : xpath_match, sizeof(xpath_match),
5141 : "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5142 : xpath);
5143 0 : nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5144 : "false");
5145 : }
5146 :
5147 0 : return nb_cli_apply_changes(vty, NULL);
5148 : }
5149 :
5150 0 : DEFUN_YANG (no_match_community,
5151 : no_match_community_cmd,
5152 : "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
5153 : NO_STR
5154 : MATCH_STR
5155 : "Match BGP community list\n"
5156 : "Community-list number (standard)\n"
5157 : "Community-list number (expanded)\n"
5158 : "Community-list name\n"
5159 : "Do exact matching of communities\n")
5160 : {
5161 0 : const char *xpath =
5162 : "./match-condition[condition='frr-bgp-route-map:match-community']";
5163 :
5164 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5165 0 : return nb_cli_apply_changes(vty, NULL);
5166 : }
5167 :
5168 0 : DEFPY_YANG (match_lcommunity,
5169 : match_lcommunity_cmd,
5170 : "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
5171 : MATCH_STR
5172 : "Match BGP large community list\n"
5173 : "Large Community-list number (standard)\n"
5174 : "Large Community-list number (expanded)\n"
5175 : "Large Community-list name\n"
5176 : "Do exact matching of communities\n")
5177 : {
5178 0 : const char *xpath =
5179 : "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5180 0 : char xpath_value[XPATH_MAXLEN];
5181 0 : char xpath_match[XPATH_MAXLEN];
5182 0 : int idx_lcomm_list = 2;
5183 :
5184 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5185 :
5186 0 : snprintf(
5187 : xpath_value, sizeof(xpath_value),
5188 : "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5189 : xpath);
5190 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
5191 :
5192 0 : if (argc == 4) {
5193 0 : snprintf(
5194 : xpath_match, sizeof(xpath_match),
5195 : "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5196 : xpath);
5197 0 : nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5198 : "true");
5199 : } else {
5200 0 : snprintf(
5201 : xpath_match, sizeof(xpath_match),
5202 : "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5203 : xpath);
5204 0 : nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5205 : "false");
5206 : }
5207 :
5208 0 : return nb_cli_apply_changes(vty, NULL);
5209 : }
5210 :
5211 0 : DEFUN_YANG (no_match_lcommunity,
5212 : no_match_lcommunity_cmd,
5213 : "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
5214 : NO_STR
5215 : MATCH_STR
5216 : "Match BGP large community list\n"
5217 : "Large Community-list number (standard)\n"
5218 : "Large Community-list number (expanded)\n"
5219 : "Large Community-list name\n"
5220 : "Do exact matching of communities\n")
5221 : {
5222 0 : const char *xpath =
5223 : "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5224 :
5225 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5226 0 : return nb_cli_apply_changes(vty, NULL);
5227 : }
5228 :
5229 0 : DEFPY_YANG (match_ecommunity,
5230 : match_ecommunity_cmd,
5231 : "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>",
5232 : MATCH_STR
5233 : "Match BGP/VPN extended community list\n"
5234 : "Extended community-list number (standard)\n"
5235 : "Extended community-list number (expanded)\n"
5236 : "Extended community-list name\n")
5237 : {
5238 0 : const char *xpath =
5239 : "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5240 0 : char xpath_value[XPATH_MAXLEN];
5241 0 : int idx_comm_list = 2;
5242 :
5243 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5244 :
5245 0 : snprintf(
5246 : xpath_value, sizeof(xpath_value),
5247 : "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5248 : xpath);
5249 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5250 :
5251 0 : return nb_cli_apply_changes(vty, NULL);
5252 : }
5253 :
5254 :
5255 0 : DEFUN_YANG (no_match_ecommunity,
5256 : no_match_ecommunity_cmd,
5257 : "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
5258 : NO_STR
5259 : MATCH_STR
5260 : "Match BGP/VPN extended community list\n"
5261 : "Extended community-list number (standard)\n"
5262 : "Extended community-list number (expanded)\n"
5263 : "Extended community-list name\n")
5264 : {
5265 0 : const char *xpath =
5266 : "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5267 :
5268 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5269 0 : return nb_cli_apply_changes(vty, NULL);
5270 : }
5271 :
5272 :
5273 0 : DEFUN_YANG (match_aspath,
5274 : match_aspath_cmd,
5275 : "match as-path AS_PATH_FILTER_NAME",
5276 : MATCH_STR
5277 : "Match BGP AS path list\n"
5278 : "AS path access-list name\n")
5279 : {
5280 0 : int idx_word = 2;
5281 :
5282 0 : const char *xpath =
5283 : "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5284 0 : char xpath_value[XPATH_MAXLEN];
5285 :
5286 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5287 0 : snprintf(xpath_value, sizeof(xpath_value),
5288 : "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
5289 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5290 0 : argv[idx_word]->arg);
5291 :
5292 0 : return nb_cli_apply_changes(vty, NULL);
5293 : }
5294 :
5295 :
5296 0 : DEFUN_YANG (no_match_aspath,
5297 : no_match_aspath_cmd,
5298 : "no match as-path [AS_PATH_FILTER_NAME]",
5299 : NO_STR
5300 : MATCH_STR
5301 : "Match BGP AS path list\n"
5302 : "AS path access-list name\n")
5303 : {
5304 0 : const char *xpath =
5305 : "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5306 :
5307 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5308 :
5309 0 : return nb_cli_apply_changes(vty, NULL);
5310 : }
5311 :
5312 0 : DEFUN_YANG (match_origin,
5313 : match_origin_cmd,
5314 : "match origin <egp|igp|incomplete>",
5315 : MATCH_STR
5316 : "BGP origin code\n"
5317 : "remote EGP\n"
5318 : "local IGP\n"
5319 : "unknown heritage\n")
5320 : {
5321 0 : int idx_origin = 2;
5322 0 : const char *origin_type;
5323 0 : const char *xpath =
5324 : "./match-condition[condition='frr-bgp-route-map:match-origin']";
5325 0 : char xpath_value[XPATH_MAXLEN];
5326 :
5327 0 : if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
5328 : origin_type = "igp";
5329 0 : else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5330 : origin_type = "egp";
5331 0 : else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5332 : origin_type = "incomplete";
5333 : else {
5334 0 : vty_out(vty, "%% Invalid match origin type\n");
5335 0 : return CMD_WARNING_CONFIG_FAILED;
5336 : }
5337 :
5338 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5339 0 : snprintf(xpath_value, sizeof(xpath_value),
5340 : "%s/rmap-match-condition/frr-bgp-route-map:origin", xpath);
5341 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
5342 :
5343 0 : return nb_cli_apply_changes(vty, NULL);
5344 : }
5345 :
5346 :
5347 0 : DEFUN_YANG (no_match_origin,
5348 : no_match_origin_cmd,
5349 : "no match origin [<egp|igp|incomplete>]",
5350 : NO_STR
5351 : MATCH_STR
5352 : "BGP origin code\n"
5353 : "remote EGP\n"
5354 : "local IGP\n"
5355 : "unknown heritage\n")
5356 : {
5357 0 : const char *xpath =
5358 : "./match-condition[condition='frr-bgp-route-map:match-origin']";
5359 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5360 0 : return nb_cli_apply_changes(vty, NULL);
5361 : }
5362 :
5363 0 : DEFUN_YANG (set_table_id,
5364 : set_table_id_cmd,
5365 : "set table (1-4294967295)",
5366 : SET_STR
5367 : "export route to non-main kernel table\n"
5368 : "Kernel routing table id\n")
5369 : {
5370 0 : int idx_number = 2;
5371 0 : const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5372 0 : char xpath_value[XPATH_MAXLEN];
5373 :
5374 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5375 0 : snprintf(xpath_value, sizeof(xpath_value),
5376 : "%s/rmap-set-action/frr-bgp-route-map:table", xpath);
5377 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5378 0 : argv[idx_number]->arg);
5379 0 : return nb_cli_apply_changes(vty, NULL);
5380 : }
5381 :
5382 0 : DEFUN_YANG (no_set_table_id,
5383 : no_set_table_id_cmd,
5384 : "no set table",
5385 : NO_STR
5386 : SET_STR
5387 : "export route to non-main kernel table\n")
5388 : {
5389 0 : const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5390 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5391 0 : return nb_cli_apply_changes(vty, NULL);
5392 : }
5393 :
5394 0 : DEFUN_YANG (set_ip_nexthop_peer,
5395 : set_ip_nexthop_peer_cmd,
5396 : "[no] set ip next-hop peer-address",
5397 : NO_STR
5398 : SET_STR
5399 : IP_STR
5400 : "Next hop address\n"
5401 : "Use peer address (for BGP only)\n")
5402 : {
5403 0 : char xpath_value[XPATH_MAXLEN];
5404 0 : const char *xpath =
5405 : "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5406 :
5407 0 : if (strmatch(argv[0]->text, "no"))
5408 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5409 : else {
5410 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5411 0 : snprintf(xpath_value, sizeof(xpath_value),
5412 : "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5413 : xpath);
5414 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5415 : "peer-address");
5416 : }
5417 0 : return nb_cli_apply_changes(vty, NULL);
5418 : }
5419 :
5420 0 : DEFUN_YANG (set_ip_nexthop_unchanged,
5421 : set_ip_nexthop_unchanged_cmd,
5422 : "[no] set ip next-hop unchanged",
5423 : NO_STR
5424 : SET_STR
5425 : IP_STR
5426 : "Next hop address\n"
5427 : "Don't modify existing Next hop address\n")
5428 : {
5429 0 : char xpath_value[XPATH_MAXLEN];
5430 0 : const char *xpath =
5431 : "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5432 :
5433 0 : if (strmatch(argv[0]->text, "no"))
5434 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5435 : else {
5436 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5437 0 : snprintf(xpath_value, sizeof(xpath_value),
5438 : "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5439 : xpath);
5440 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5441 : "unchanged");
5442 : }
5443 0 : return nb_cli_apply_changes(vty, NULL);
5444 : }
5445 :
5446 0 : DEFUN_YANG (set_distance,
5447 : set_distance_cmd,
5448 : "set distance (0-255)",
5449 : SET_STR
5450 : "BGP Administrative Distance to use\n"
5451 : "Distance value\n")
5452 : {
5453 0 : int idx_number = 2;
5454 0 : const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5455 0 : char xpath_value[XPATH_MAXLEN];
5456 :
5457 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5458 0 : snprintf(xpath_value, sizeof(xpath_value),
5459 : "%s/rmap-set-action/frr-bgp-route-map:distance", xpath);
5460 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5461 0 : argv[idx_number]->arg);
5462 0 : return nb_cli_apply_changes(vty, NULL);
5463 : }
5464 :
5465 0 : DEFUN_YANG (no_set_distance,
5466 : no_set_distance_cmd,
5467 : "no set distance [(0-255)]",
5468 : NO_STR SET_STR
5469 : "BGP Administrative Distance to use\n"
5470 : "Distance value\n")
5471 : {
5472 0 : const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5473 :
5474 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5475 0 : return nb_cli_apply_changes(vty, NULL);
5476 : }
5477 :
5478 0 : DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
5479 : "[no] set l3vpn next-hop encapsulation gre",
5480 : NO_STR SET_STR
5481 : "L3VPN operations\n"
5482 : "Next hop Information\n"
5483 : "Encapsulation options (for BGP only)\n"
5484 : "Accept L3VPN traffic over GRE encapsulation\n")
5485 : {
5486 0 : const char *xpath =
5487 : "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']";
5488 0 : const char *xpath_value =
5489 : "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation";
5490 0 : enum nb_operation operation;
5491 :
5492 0 : if (no)
5493 : operation = NB_OP_DESTROY;
5494 : else
5495 0 : operation = NB_OP_CREATE;
5496 :
5497 0 : nb_cli_enqueue_change(vty, xpath, operation, NULL);
5498 0 : if (operation == NB_OP_DESTROY)
5499 0 : return nb_cli_apply_changes(vty, NULL);
5500 :
5501 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "gre");
5502 :
5503 0 : return nb_cli_apply_changes(vty, NULL);
5504 : }
5505 :
5506 0 : DEFUN_YANG (set_local_pref,
5507 : set_local_pref_cmd,
5508 : "set local-preference WORD",
5509 : SET_STR
5510 : "BGP local preference path attribute\n"
5511 : "Preference value (0-4294967295)\n")
5512 : {
5513 0 : int idx_number = 2;
5514 0 : const char *xpath =
5515 : "./set-action[action='frr-bgp-route-map:set-local-preference']";
5516 0 : char xpath_value[XPATH_MAXLEN];
5517 :
5518 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5519 0 : snprintf(xpath_value, sizeof(xpath_value),
5520 : "%s/rmap-set-action/frr-bgp-route-map:local-pref", xpath);
5521 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5522 0 : argv[idx_number]->arg);
5523 0 : return nb_cli_apply_changes(vty, NULL);
5524 : }
5525 :
5526 0 : DEFUN_YANG (no_set_local_pref,
5527 : no_set_local_pref_cmd,
5528 : "no set local-preference [WORD]",
5529 : NO_STR
5530 : SET_STR
5531 : "BGP local preference path attribute\n"
5532 : "Preference value (0-4294967295)\n")
5533 : {
5534 0 : const char *xpath =
5535 : "./set-action[action='frr-bgp-route-map:set-local-preference']";
5536 :
5537 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5538 0 : return nb_cli_apply_changes(vty, NULL);
5539 : }
5540 :
5541 0 : DEFUN_YANG (set_weight,
5542 : set_weight_cmd,
5543 : "set weight (0-4294967295)",
5544 : SET_STR
5545 : "BGP weight for routing table\n"
5546 : "Weight value\n")
5547 : {
5548 0 : int idx_number = 2;
5549 0 : const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5550 0 : char xpath_value[XPATH_MAXLEN];
5551 :
5552 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5553 0 : snprintf(xpath_value, sizeof(xpath_value),
5554 : "%s/rmap-set-action/frr-bgp-route-map:weight", xpath);
5555 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5556 0 : argv[idx_number]->arg);
5557 0 : return nb_cli_apply_changes(vty, NULL);
5558 : }
5559 :
5560 0 : DEFUN_YANG (no_set_weight,
5561 : no_set_weight_cmd,
5562 : "no set weight [(0-4294967295)]",
5563 : NO_STR
5564 : SET_STR
5565 : "BGP weight for routing table\n"
5566 : "Weight value\n")
5567 : {
5568 0 : const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5569 :
5570 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5571 0 : return nb_cli_apply_changes(vty, NULL);
5572 : }
5573 :
5574 0 : DEFUN_YANG (set_label_index,
5575 : set_label_index_cmd,
5576 : "set label-index (0-1048560)",
5577 : SET_STR
5578 : "Label index to associate with the prefix\n"
5579 : "Label index value\n")
5580 : {
5581 0 : int idx_number = 2;
5582 0 : const char *xpath =
5583 : "./set-action[action='frr-bgp-route-map:label-index']";
5584 0 : char xpath_value[XPATH_MAXLEN];
5585 :
5586 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5587 0 : snprintf(xpath_value, sizeof(xpath_value),
5588 : "%s/rmap-set-action/frr-bgp-route-map:label-index", xpath);
5589 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5590 0 : argv[idx_number]->arg);
5591 0 : return nb_cli_apply_changes(vty, NULL);
5592 : }
5593 :
5594 0 : DEFUN_YANG (no_set_label_index,
5595 : no_set_label_index_cmd,
5596 : "no set label-index [(0-1048560)]",
5597 : NO_STR
5598 : SET_STR
5599 : "Label index to associate with the prefix\n"
5600 : "Label index value\n")
5601 : {
5602 0 : const char *xpath =
5603 : "./set-action[action='frr-bgp-route-map:label-index']";
5604 :
5605 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5606 0 : return nb_cli_apply_changes(vty, NULL);
5607 : }
5608 :
5609 0 : DEFUN_YANG (set_aspath_prepend_asn,
5610 : set_aspath_prepend_asn_cmd,
5611 : "set as-path prepend (1-4294967295)...",
5612 : SET_STR
5613 : "Transform BGP AS_PATH attribute\n"
5614 : "Prepend to the as-path\n"
5615 : "AS number\n")
5616 : {
5617 0 : int idx_asn = 3;
5618 0 : int ret;
5619 0 : char *str;
5620 :
5621 0 : str = argv_concat(argv, argc, idx_asn);
5622 :
5623 0 : const char *xpath =
5624 : "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5625 0 : char xpath_value[XPATH_MAXLEN];
5626 :
5627 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5628 0 : snprintf(xpath_value, sizeof(xpath_value),
5629 : "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath);
5630 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5631 0 : ret = nb_cli_apply_changes(vty, NULL);
5632 0 : XFREE(MTYPE_TMP, str);
5633 0 : return ret;
5634 : }
5635 :
5636 0 : DEFUN_YANG (set_aspath_prepend_lastas,
5637 : set_aspath_prepend_lastas_cmd,
5638 : "set as-path prepend last-as (1-10)",
5639 : SET_STR
5640 : "Transform BGP AS_PATH attribute\n"
5641 : "Prepend to the as-path\n"
5642 : "Use the last AS-number in the as-path\n"
5643 : "Number of times to insert\n")
5644 : {
5645 0 : int idx_num = 4;
5646 :
5647 0 : const char *xpath =
5648 : "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5649 0 : char xpath_value[XPATH_MAXLEN];
5650 :
5651 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5652 0 : snprintf(xpath_value, sizeof(xpath_value),
5653 : "%s/rmap-set-action/frr-bgp-route-map:last-as", xpath);
5654 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5655 0 : argv[idx_num]->arg);
5656 0 : return nb_cli_apply_changes(vty, NULL);
5657 : }
5658 :
5659 0 : DEFPY_YANG (set_aspath_replace_asn,
5660 : set_aspath_replace_asn_cmd,
5661 : "set as-path replace <any|(1-4294967295)>$replace",
5662 : SET_STR
5663 : "Transform BGP AS_PATH attribute\n"
5664 : "Replace AS number to local AS number\n"
5665 : "Replace any AS number to local AS number\n"
5666 : "Replace a specific AS number to local AS number\n")
5667 : {
5668 0 : const char *xpath =
5669 : "./set-action[action='frr-bgp-route-map:as-path-replace']";
5670 0 : char xpath_value[XPATH_MAXLEN];
5671 :
5672 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5673 0 : snprintf(xpath_value, sizeof(xpath_value),
5674 : "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
5675 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace);
5676 0 : return nb_cli_apply_changes(vty, NULL);
5677 : }
5678 :
5679 0 : DEFPY_YANG (no_set_aspath_replace_asn,
5680 : no_set_aspath_replace_asn_cmd,
5681 : "no set as-path replace [<any|(1-4294967295)>]",
5682 : NO_STR
5683 : SET_STR
5684 : "Transform BGP AS_PATH attribute\n"
5685 : "Replace AS number to local AS number\n"
5686 : "Replace any AS number to local AS number\n"
5687 : "Replace a specific AS number to local AS number\n")
5688 : {
5689 0 : const char *xpath =
5690 : "./set-action[action='frr-bgp-route-map:as-path-replace']";
5691 :
5692 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5693 0 : return nb_cli_apply_changes(vty, NULL);
5694 : }
5695 :
5696 0 : DEFUN_YANG (no_set_aspath_prepend,
5697 : no_set_aspath_prepend_cmd,
5698 : "no set as-path prepend [(1-4294967295)]",
5699 : NO_STR
5700 : SET_STR
5701 : "Transform BGP AS_PATH attribute\n"
5702 : "Prepend to the as-path\n"
5703 : "AS number\n")
5704 : {
5705 0 : const char *xpath =
5706 : "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5707 :
5708 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5709 0 : return nb_cli_apply_changes(vty, NULL);
5710 : }
5711 :
5712 0 : DEFUN_YANG (no_set_aspath_prepend_lastas,
5713 : no_set_aspath_prepend_lastas_cmd,
5714 : "no set as-path prepend last-as [(1-10)]",
5715 : NO_STR
5716 : SET_STR
5717 : "Transform BGP AS_PATH attribute\n"
5718 : "Prepend to the as-path\n"
5719 : "Use the peers AS-number\n"
5720 : "Number of times to insert\n")
5721 : {
5722 0 : const char *xpath =
5723 : "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5724 :
5725 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5726 0 : return nb_cli_apply_changes(vty, NULL);
5727 : }
5728 :
5729 0 : DEFUN_YANG (set_aspath_exclude,
5730 : set_aspath_exclude_cmd,
5731 : "set as-path exclude (1-4294967295)...",
5732 : SET_STR
5733 : "Transform BGP AS-path attribute\n"
5734 : "Exclude from the as-path\n"
5735 : "AS number\n")
5736 : {
5737 0 : int idx_asn = 3;
5738 0 : int ret;
5739 0 : char *str;
5740 :
5741 0 : str = argv_concat(argv, argc, idx_asn);
5742 :
5743 0 : const char *xpath =
5744 : "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5745 0 : char xpath_value[XPATH_MAXLEN];
5746 :
5747 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5748 0 : snprintf(xpath_value, sizeof(xpath_value),
5749 : "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath);
5750 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5751 0 : ret = nb_cli_apply_changes(vty, NULL);
5752 0 : XFREE(MTYPE_TMP, str);
5753 0 : return ret;
5754 : }
5755 :
5756 0 : DEFUN_YANG (no_set_aspath_exclude,
5757 : no_set_aspath_exclude_cmd,
5758 : "no set as-path exclude (1-4294967295)...",
5759 : NO_STR
5760 : SET_STR
5761 : "Transform BGP AS_PATH attribute\n"
5762 : "Exclude from the as-path\n"
5763 : "AS number\n")
5764 : {
5765 0 : const char *xpath =
5766 : "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5767 :
5768 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5769 0 : return nb_cli_apply_changes(vty, NULL);
5770 : }
5771 :
5772 : ALIAS_YANG (no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
5773 : "no set as-path exclude",
5774 : NO_STR SET_STR
5775 : "Transform BGP AS_PATH attribute\n"
5776 : "Exclude from the as-path\n")
5777 :
5778 0 : DEFUN_YANG (set_community,
5779 : set_community_cmd,
5780 : "set community AA:NN...",
5781 : SET_STR
5782 : "BGP community attribute\n"
5783 : COMMUNITY_VAL_STR)
5784 : {
5785 0 : int idx_aa_nn = 2;
5786 0 : int i;
5787 0 : int first = 0;
5788 0 : int additive = 0;
5789 0 : struct buffer *b;
5790 0 : struct community *com = NULL;
5791 0 : char *str;
5792 0 : char *argstr = NULL;
5793 0 : int ret;
5794 :
5795 0 : const char *xpath =
5796 : "./set-action[action='frr-bgp-route-map:set-community']";
5797 0 : char xpath_value[XPATH_MAXLEN];
5798 :
5799 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5800 0 : snprintf(xpath_value, sizeof(xpath_value),
5801 : "%s/rmap-set-action/frr-bgp-route-map:community-string",
5802 : xpath);
5803 :
5804 0 : b = buffer_new(1024);
5805 :
5806 0 : for (i = idx_aa_nn; i < argc; i++) {
5807 0 : if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
5808 : == 0) {
5809 0 : additive = 1;
5810 0 : continue;
5811 : }
5812 :
5813 0 : if (first)
5814 0 : buffer_putc(b, ' ');
5815 : else
5816 : first = 1;
5817 :
5818 0 : if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
5819 : == 0) {
5820 0 : buffer_putstr(b, "internet");
5821 0 : continue;
5822 : }
5823 0 : if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
5824 : == 0) {
5825 0 : buffer_putstr(b, "local-AS");
5826 0 : continue;
5827 : }
5828 0 : if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
5829 0 : && strncmp(argv[i]->arg, "no-advertise",
5830 : strlen(argv[i]->arg))
5831 : == 0) {
5832 0 : buffer_putstr(b, "no-advertise");
5833 0 : continue;
5834 : }
5835 0 : if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
5836 0 : && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
5837 : == 0) {
5838 0 : buffer_putstr(b, "no-export");
5839 0 : continue;
5840 : }
5841 0 : if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg))
5842 : == 0) {
5843 0 : buffer_putstr(b, "blackhole");
5844 0 : continue;
5845 : }
5846 0 : if (strncmp(argv[i]->arg, "graceful-shutdown",
5847 : strlen(argv[i]->arg))
5848 : == 0) {
5849 0 : buffer_putstr(b, "graceful-shutdown");
5850 0 : continue;
5851 : }
5852 0 : buffer_putstr(b, argv[i]->arg);
5853 : }
5854 0 : buffer_putc(b, '\0');
5855 :
5856 : /* Fetch result string then compile it to communities attribute. */
5857 0 : str = buffer_getstr(b);
5858 0 : buffer_free(b);
5859 :
5860 0 : if (str)
5861 0 : com = community_str2com(str);
5862 :
5863 : /* Can't compile user input into communities attribute. */
5864 0 : if (!com) {
5865 0 : vty_out(vty, "%% Malformed communities attribute '%s'\n", str);
5866 0 : XFREE(MTYPE_TMP, str);
5867 0 : return CMD_WARNING_CONFIG_FAILED;
5868 : }
5869 0 : XFREE(MTYPE_TMP, str);
5870 :
5871 : /* Set communites attribute string. */
5872 0 : str = community_str(com, false, false);
5873 :
5874 0 : if (additive) {
5875 0 : size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
5876 0 : argstr = XCALLOC(MTYPE_TMP, argstr_sz);
5877 0 : strlcpy(argstr, str, argstr_sz);
5878 0 : strlcat(argstr, " additive", argstr_sz);
5879 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argstr);
5880 : } else
5881 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5882 :
5883 0 : ret = nb_cli_apply_changes(vty, NULL);
5884 :
5885 0 : if (argstr)
5886 0 : XFREE(MTYPE_TMP, argstr);
5887 0 : community_free(&com);
5888 :
5889 0 : return ret;
5890 : }
5891 :
5892 0 : DEFUN_YANG (set_community_none,
5893 : set_community_none_cmd,
5894 : "set community none",
5895 : SET_STR
5896 : "BGP community attribute\n"
5897 : "No community attribute\n")
5898 : {
5899 0 : const char *xpath =
5900 : "./set-action[action='frr-bgp-route-map:set-community']";
5901 0 : char xpath_value[XPATH_MAXLEN];
5902 :
5903 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5904 :
5905 0 : snprintf(xpath_value, sizeof(xpath_value),
5906 : "%s/rmap-set-action/frr-bgp-route-map:community-none", xpath);
5907 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
5908 0 : return nb_cli_apply_changes(vty, NULL);
5909 : }
5910 :
5911 0 : DEFUN_YANG (no_set_community,
5912 : no_set_community_cmd,
5913 : "no set community AA:NN...",
5914 : NO_STR
5915 : SET_STR
5916 : "BGP community attribute\n"
5917 : COMMUNITY_VAL_STR)
5918 : {
5919 0 : const char *xpath =
5920 : "./set-action[action='frr-bgp-route-map:set-community']";
5921 :
5922 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5923 0 : return nb_cli_apply_changes(vty, NULL);
5924 : }
5925 :
5926 : ALIAS_YANG (no_set_community,
5927 : no_set_community_short_cmd,
5928 : "no set community",
5929 : NO_STR
5930 : SET_STR
5931 : "BGP community attribute\n")
5932 :
5933 0 : DEFPY_YANG (set_community_delete,
5934 : set_community_delete_cmd,
5935 : "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete",
5936 : SET_STR
5937 : "set BGP community list (for deletion)\n"
5938 : "Community-list number (standard)\n"
5939 : "Community-list number (expanded)\n"
5940 : "Community-list name\n"
5941 : "Delete matching communities\n")
5942 : {
5943 0 : const char *xpath =
5944 : "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5945 0 : char xpath_value[XPATH_MAXLEN];
5946 0 : int idx_comm_list = 2;
5947 :
5948 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5949 :
5950 0 : snprintf(xpath_value, sizeof(xpath_value),
5951 : "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
5952 : xpath);
5953 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5954 0 : argv[idx_comm_list]->arg);
5955 :
5956 0 : return nb_cli_apply_changes(vty, NULL);
5957 :
5958 : }
5959 :
5960 0 : DEFUN_YANG (no_set_community_delete,
5961 : no_set_community_delete_cmd,
5962 : "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]",
5963 : NO_STR
5964 : SET_STR
5965 : "set BGP community list (for deletion)\n"
5966 : "Community-list number (standard)\n"
5967 : "Community-list number (expanded)\n"
5968 : "Community-list name\n"
5969 : "Delete matching communities\n")
5970 : {
5971 0 : const char *xpath =
5972 : "./set-action[action='frr-bgp-route-map:comm-list-delete']";
5973 :
5974 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5975 0 : return nb_cli_apply_changes(vty, NULL);
5976 : }
5977 :
5978 0 : DEFUN_YANG (set_lcommunity,
5979 : set_lcommunity_cmd,
5980 : "set large-community AA:BB:CC...",
5981 : SET_STR
5982 : "BGP large community attribute\n"
5983 : "Large Community number in aa:bb:cc format or additive\n")
5984 : {
5985 0 : char *str;
5986 0 : int ret;
5987 0 : const char *xpath =
5988 : "./set-action[action='frr-bgp-route-map:set-large-community']";
5989 0 : char xpath_value[XPATH_MAXLEN];
5990 :
5991 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5992 :
5993 0 : snprintf(xpath_value, sizeof(xpath_value),
5994 : "%s/rmap-set-action/frr-bgp-route-map:large-community-string",
5995 : xpath);
5996 0 : str = argv_concat(argv, argc, 2);
5997 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5998 0 : ret = nb_cli_apply_changes(vty, NULL);
5999 0 : XFREE(MTYPE_TMP, str);
6000 0 : return ret;
6001 : }
6002 :
6003 0 : DEFUN_YANG (set_lcommunity_none,
6004 : set_lcommunity_none_cmd,
6005 : "set large-community none",
6006 : SET_STR
6007 : "BGP large community attribute\n"
6008 : "No large community attribute\n")
6009 : {
6010 0 : const char *xpath =
6011 : "./set-action[action='frr-bgp-route-map:set-large-community']";
6012 0 : char xpath_value[XPATH_MAXLEN];
6013 :
6014 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6015 :
6016 0 : snprintf(xpath_value, sizeof(xpath_value),
6017 : "%s/rmap-set-action/frr-bgp-route-map:large-community-none",
6018 : xpath);
6019 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6020 0 : return nb_cli_apply_changes(vty, NULL);
6021 : }
6022 :
6023 0 : DEFUN_YANG (no_set_lcommunity,
6024 : no_set_lcommunity_cmd,
6025 : "no set large-community none",
6026 : NO_STR
6027 : SET_STR
6028 : "BGP large community attribute\n"
6029 : "No community attribute\n")
6030 : {
6031 0 : const char *xpath =
6032 : "./set-action[action='frr-bgp-route-map:set-large-community']";
6033 :
6034 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6035 0 : return nb_cli_apply_changes(vty, NULL);
6036 : }
6037 :
6038 0 : DEFUN_YANG (no_set_lcommunity1,
6039 : no_set_lcommunity1_cmd,
6040 : "no set large-community AA:BB:CC...",
6041 : NO_STR
6042 : SET_STR
6043 : "BGP large community attribute\n"
6044 : "Large community in AA:BB:CC... format or additive\n")
6045 : {
6046 0 : const char *xpath =
6047 : "./set-action[action='frr-bgp-route-map:set-large-community']";
6048 :
6049 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6050 0 : return nb_cli_apply_changes(vty, NULL);
6051 : }
6052 :
6053 : ALIAS_YANG (no_set_lcommunity1,
6054 : no_set_lcommunity1_short_cmd,
6055 : "no set large-community",
6056 : NO_STR
6057 : SET_STR
6058 : "BGP large community attribute\n")
6059 :
6060 0 : DEFPY_YANG (set_lcommunity_delete,
6061 : set_lcommunity_delete_cmd,
6062 : "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete",
6063 : SET_STR
6064 : "set BGP large community list (for deletion)\n"
6065 : "Large Community-list number (standard)\n"
6066 : "Large Communitly-list number (expanded)\n"
6067 : "Large Community-list name\n"
6068 : "Delete matching large communities\n")
6069 : {
6070 0 : const char *xpath =
6071 : "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6072 0 : char xpath_value[XPATH_MAXLEN];
6073 0 : int idx_lcomm_list = 2;
6074 :
6075 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6076 :
6077 0 : snprintf(xpath_value, sizeof(xpath_value),
6078 : "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
6079 : xpath);
6080 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6081 0 : argv[idx_lcomm_list]->arg);
6082 :
6083 0 : return nb_cli_apply_changes(vty, NULL);
6084 : }
6085 :
6086 0 : DEFUN_YANG (no_set_lcommunity_delete,
6087 : no_set_lcommunity_delete_cmd,
6088 : "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]",
6089 : NO_STR
6090 : SET_STR
6091 : "set BGP large community list (for deletion)\n"
6092 : "Large Community-list number (standard)\n"
6093 : "Large Communitly-list number (expanded)\n"
6094 : "Large Community-list name\n"
6095 : "Delete matching large communities\n")
6096 : {
6097 0 : const char *xpath =
6098 : "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6099 :
6100 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6101 0 : return nb_cli_apply_changes(vty, NULL);
6102 : }
6103 :
6104 : ALIAS_YANG (no_set_lcommunity_delete,
6105 : no_set_lcommunity_delete_short_cmd,
6106 : "no set large-comm-list",
6107 : NO_STR
6108 : SET_STR
6109 : "set BGP large community list (for deletion)\n")
6110 :
6111 0 : DEFUN_YANG (set_ecommunity_rt,
6112 : set_ecommunity_rt_cmd,
6113 : "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6114 : SET_STR
6115 : "BGP extended community attribute\n"
6116 : "Route Target extended community\n"
6117 : "VPN extended community\n")
6118 : {
6119 0 : int idx_asn_nn = 3;
6120 0 : char *str;
6121 0 : int ret;
6122 0 : const char *xpath =
6123 : "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6124 0 : char xpath_value[XPATH_MAXLEN];
6125 :
6126 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6127 :
6128 0 : snprintf(xpath_value, sizeof(xpath_value),
6129 : "%s/rmap-set-action/frr-bgp-route-map:extcommunity-rt", xpath);
6130 0 : str = argv_concat(argv, argc, idx_asn_nn);
6131 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6132 0 : ret = nb_cli_apply_changes(vty, NULL);
6133 0 : XFREE(MTYPE_TMP, str);
6134 0 : return ret;
6135 : }
6136 :
6137 0 : DEFUN_YANG (no_set_ecommunity_rt,
6138 : no_set_ecommunity_rt_cmd,
6139 : "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6140 : NO_STR
6141 : SET_STR
6142 : "BGP extended community attribute\n"
6143 : "Route Target extended community\n"
6144 : "VPN extended community\n")
6145 : {
6146 0 : const char *xpath =
6147 : "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6148 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6149 0 : return nb_cli_apply_changes(vty, NULL);
6150 : }
6151 :
6152 : ALIAS_YANG (no_set_ecommunity_rt,
6153 : no_set_ecommunity_rt_short_cmd,
6154 : "no set extcommunity rt",
6155 : NO_STR
6156 : SET_STR
6157 : "BGP extended community attribute\n"
6158 : "Route Target extended community\n")
6159 :
6160 0 : DEFUN_YANG (set_ecommunity_soo,
6161 : set_ecommunity_soo_cmd,
6162 : "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6163 : SET_STR
6164 : "BGP extended community attribute\n"
6165 : "Site-of-Origin extended community\n"
6166 : "VPN extended community\n")
6167 : {
6168 0 : int idx_asn_nn = 3;
6169 0 : char *str;
6170 0 : int ret;
6171 0 : const char *xpath =
6172 : "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6173 0 : char xpath_value[XPATH_MAXLEN];
6174 :
6175 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6176 :
6177 0 : snprintf(xpath_value, sizeof(xpath_value),
6178 : "%s/rmap-set-action/frr-bgp-route-map:extcommunity-soo",
6179 : xpath);
6180 0 : str = argv_concat(argv, argc, idx_asn_nn);
6181 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6182 0 : ret = nb_cli_apply_changes(vty, NULL);
6183 0 : XFREE(MTYPE_TMP, str);
6184 0 : return ret;
6185 : }
6186 :
6187 0 : DEFUN_YANG (no_set_ecommunity_soo,
6188 : no_set_ecommunity_soo_cmd,
6189 : "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6190 : NO_STR
6191 : SET_STR
6192 : "BGP extended community attribute\n"
6193 : "Site-of-Origin extended community\n"
6194 : "VPN extended community\n")
6195 : {
6196 0 : const char *xpath =
6197 : "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6198 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6199 0 : return nb_cli_apply_changes(vty, NULL);
6200 : }
6201 :
6202 : ALIAS_YANG (no_set_ecommunity_soo,
6203 : no_set_ecommunity_soo_short_cmd,
6204 : "no set extcommunity soo",
6205 : NO_STR
6206 : SET_STR
6207 : "GP extended community attribute\n"
6208 : "Site-of-Origin extended community\n")
6209 :
6210 0 : DEFUN_YANG(set_ecommunity_none, set_ecommunity_none_cmd,
6211 : "set extcommunity none",
6212 : SET_STR
6213 : "BGP extended community attribute\n"
6214 : "No extended community attribute\n")
6215 : {
6216 0 : const char *xpath =
6217 : "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6218 0 : char xpath_value[XPATH_MAXLEN];
6219 :
6220 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6221 :
6222 0 : snprintf(xpath_value, sizeof(xpath_value),
6223 : "%s/rmap-set-action/frr-bgp-route-map:extcommunity-none",
6224 : xpath);
6225 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6226 0 : return nb_cli_apply_changes(vty, NULL);
6227 : }
6228 :
6229 0 : DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
6230 : "no set extcommunity none",
6231 : NO_STR SET_STR
6232 : "BGP extended community attribute\n"
6233 : "No extended community attribute\n")
6234 : {
6235 0 : const char *xpath =
6236 : "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6237 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6238 0 : return nb_cli_apply_changes(vty, NULL);
6239 : }
6240 :
6241 0 : DEFUN_YANG (set_ecommunity_lb,
6242 : set_ecommunity_lb_cmd,
6243 : "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6244 : SET_STR
6245 : "BGP extended community attribute\n"
6246 : "Link bandwidth extended community\n"
6247 : "Bandwidth value in Mbps\n"
6248 : "Cumulative bandwidth of all multipaths (outbound-only)\n"
6249 : "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6250 : "Attribute is set as non-transitive\n")
6251 : {
6252 0 : int idx_lb = 3;
6253 0 : int idx_non_transitive = 0;
6254 0 : const char *xpath =
6255 : "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6256 0 : char xpath_lb_type[XPATH_MAXLEN];
6257 0 : char xpath_bandwidth[XPATH_MAXLEN];
6258 0 : char xpath_non_transitive[XPATH_MAXLEN];
6259 :
6260 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6261 :
6262 0 : snprintf(xpath_lb_type, sizeof(xpath_lb_type),
6263 : "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type",
6264 : xpath);
6265 0 : snprintf(xpath_bandwidth, sizeof(xpath_bandwidth),
6266 : "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth",
6267 : xpath);
6268 0 : snprintf(xpath_non_transitive, sizeof(xpath_non_transitive),
6269 : "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific",
6270 : xpath);
6271 :
6272 0 : if ((strcmp(argv[idx_lb]->arg, "cumulative")) == 0)
6273 0 : nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6274 : "cumulative-bandwidth");
6275 0 : else if ((strcmp(argv[idx_lb]->arg, "num-multipaths")) == 0)
6276 0 : nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6277 : "computed-bandwidth");
6278 : else {
6279 0 : nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6280 : "explicit-bandwidth");
6281 0 : nb_cli_enqueue_change(vty, xpath_bandwidth, NB_OP_MODIFY,
6282 0 : argv[idx_lb]->arg);
6283 : }
6284 :
6285 0 : if (argv_find(argv, argc, "non-transitive", &idx_non_transitive))
6286 0 : nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6287 : "true");
6288 : else
6289 0 : nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6290 : "false");
6291 :
6292 0 : return nb_cli_apply_changes(vty, NULL);
6293 : }
6294 :
6295 0 : DEFUN_YANG (no_set_ecommunity_lb,
6296 : no_set_ecommunity_lb_cmd,
6297 : "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6298 : NO_STR
6299 : SET_STR
6300 : "BGP extended community attribute\n"
6301 : "Link bandwidth extended community\n"
6302 : "Bandwidth value in Mbps\n"
6303 : "Cumulative bandwidth of all multipaths (outbound-only)\n"
6304 : "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6305 : "Attribute is set as non-transitive\n")
6306 : {
6307 0 : const char *xpath =
6308 : "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6309 :
6310 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6311 0 : return nb_cli_apply_changes(vty, NULL);
6312 : }
6313 :
6314 : ALIAS_YANG (no_set_ecommunity_lb,
6315 : no_set_ecommunity_lb_short_cmd,
6316 : "no set extcommunity bandwidth",
6317 : NO_STR
6318 : SET_STR
6319 : "BGP extended community attribute\n"
6320 : "Link bandwidth extended community\n")
6321 :
6322 0 : DEFUN_YANG (set_origin,
6323 : set_origin_cmd,
6324 : "set origin <egp|igp|incomplete>",
6325 : SET_STR
6326 : "BGP origin code\n"
6327 : "remote EGP\n"
6328 : "local IGP\n"
6329 : "unknown heritage\n")
6330 : {
6331 0 : int idx_origin = 2;
6332 0 : const char *origin_type;
6333 0 : const char *xpath =
6334 : "./set-action[action='frr-bgp-route-map:set-origin']";
6335 0 : char xpath_value[XPATH_MAXLEN];
6336 :
6337 0 : if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
6338 : origin_type = "igp";
6339 0 : else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
6340 : origin_type = "egp";
6341 0 : else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
6342 : origin_type = "incomplete";
6343 : else {
6344 0 : vty_out(vty, "%% Invalid match origin type\n");
6345 0 : return CMD_WARNING_CONFIG_FAILED;
6346 : }
6347 :
6348 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6349 0 : snprintf(xpath_value, sizeof(xpath_value),
6350 : "%s/rmap-set-action/frr-bgp-route-map:origin", xpath);
6351 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
6352 :
6353 0 : return nb_cli_apply_changes(vty, NULL);
6354 : }
6355 :
6356 0 : DEFUN_YANG (no_set_origin,
6357 : no_set_origin_cmd,
6358 : "no set origin [<egp|igp|incomplete>]",
6359 : NO_STR
6360 : SET_STR
6361 : "BGP origin code\n"
6362 : "remote EGP\n"
6363 : "local IGP\n"
6364 : "unknown heritage\n")
6365 : {
6366 0 : const char *xpath =
6367 : "./set-action[action='frr-bgp-route-map:set-origin']";
6368 :
6369 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6370 0 : return nb_cli_apply_changes(vty, NULL);
6371 : }
6372 :
6373 0 : DEFUN_YANG (set_atomic_aggregate,
6374 : set_atomic_aggregate_cmd,
6375 : "set atomic-aggregate",
6376 : SET_STR
6377 : "BGP atomic aggregate attribute\n" )
6378 : {
6379 0 : const char *xpath =
6380 : "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6381 0 : char xpath_value[XPATH_MAXLEN];
6382 :
6383 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6384 0 : snprintf(xpath_value, sizeof(xpath_value),
6385 : "%s/rmap-set-action/frr-bgp-route-map:atomic-aggregate",
6386 : xpath);
6387 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
6388 :
6389 0 : return nb_cli_apply_changes(vty, NULL);
6390 : }
6391 :
6392 0 : DEFUN_YANG (no_set_atomic_aggregate,
6393 : no_set_atomic_aggregate_cmd,
6394 : "no set atomic-aggregate",
6395 : NO_STR
6396 : SET_STR
6397 : "BGP atomic aggregate attribute\n" )
6398 : {
6399 0 : const char *xpath =
6400 : "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6401 :
6402 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6403 0 : return nb_cli_apply_changes(vty, NULL);
6404 : }
6405 :
6406 0 : DEFPY_YANG (set_aigp_metric,
6407 : set_aigp_metric_cmd,
6408 : "set aigp-metric <igp-metric|(1-4294967295)>$aigp_metric",
6409 : SET_STR
6410 : "BGP AIGP attribute (AIGP Metric TLV)\n"
6411 : "AIGP Metric value from IGP protocol\n"
6412 : "Manual AIGP Metric value\n")
6413 : {
6414 0 : const char *xpath =
6415 : "./set-action[action='frr-bgp-route-map:aigp-metric']";
6416 0 : char xpath_value[XPATH_MAXLEN];
6417 :
6418 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6419 0 : snprintf(xpath_value, sizeof(xpath_value),
6420 : "%s/rmap-set-action/frr-bgp-route-map:aigp-metric", xpath);
6421 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, aigp_metric);
6422 :
6423 0 : return nb_cli_apply_changes(vty, NULL);
6424 : }
6425 :
6426 0 : DEFPY_YANG (no_set_aigp_metric,
6427 : no_set_aigp_metric_cmd,
6428 : "no set aigp-metric [<igp-metric|(1-4294967295)>]",
6429 : NO_STR
6430 : SET_STR
6431 : "BGP AIGP attribute (AIGP Metric TLV)\n"
6432 : "AIGP Metric value from IGP protocol\n"
6433 : "Manual AIGP Metric value\n")
6434 : {
6435 0 : const char *xpath =
6436 : "./set-action[action='frr-bgp-route-map:aigp-metric']";
6437 :
6438 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6439 0 : return nb_cli_apply_changes(vty, NULL);
6440 : }
6441 :
6442 0 : DEFUN_YANG (set_aggregator_as,
6443 : set_aggregator_as_cmd,
6444 : "set aggregator as (1-4294967295) A.B.C.D",
6445 : SET_STR
6446 : "BGP aggregator attribute\n"
6447 : "AS number of aggregator\n"
6448 : "AS number\n"
6449 : "IP address of aggregator\n")
6450 : {
6451 0 : int idx_number = 3;
6452 0 : int idx_ipv4 = 4;
6453 0 : char xpath_asn[XPATH_MAXLEN];
6454 0 : char xpath_addr[XPATH_MAXLEN];
6455 0 : const char *xpath =
6456 : "./set-action[action='frr-bgp-route-map:aggregator']";
6457 :
6458 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6459 :
6460 0 : snprintf(
6461 : xpath_asn, sizeof(xpath_asn),
6462 : "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn",
6463 : xpath);
6464 0 : nb_cli_enqueue_change(vty, xpath_asn, NB_OP_MODIFY,
6465 0 : argv[idx_number]->arg);
6466 :
6467 0 : snprintf(
6468 : xpath_addr, sizeof(xpath_addr),
6469 : "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address",
6470 : xpath);
6471 0 : nb_cli_enqueue_change(vty, xpath_addr, NB_OP_MODIFY,
6472 0 : argv[idx_ipv4]->arg);
6473 :
6474 0 : return nb_cli_apply_changes(vty, NULL);
6475 : }
6476 :
6477 0 : DEFUN_YANG (no_set_aggregator_as,
6478 : no_set_aggregator_as_cmd,
6479 : "no set aggregator as [(1-4294967295) A.B.C.D]",
6480 : NO_STR
6481 : SET_STR
6482 : "BGP aggregator attribute\n"
6483 : "AS number of aggregator\n"
6484 : "AS number\n"
6485 : "IP address of aggregator\n")
6486 : {
6487 0 : const char *xpath =
6488 : "./set-action[action='frr-bgp-route-map:aggregator']";
6489 :
6490 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6491 0 : return nb_cli_apply_changes(vty, NULL);
6492 : }
6493 :
6494 0 : DEFUN_YANG (match_ipv6_next_hop,
6495 : match_ipv6_next_hop_cmd,
6496 : "match ipv6 next-hop ACCESSLIST6_NAME",
6497 : MATCH_STR
6498 : IPV6_STR
6499 : "Match IPv6 next-hop address of route\n"
6500 : "IPv6 access-list name\n")
6501 : {
6502 0 : const char *xpath =
6503 : "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6504 0 : char xpath_value[XPATH_MAXLEN];
6505 :
6506 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6507 0 : snprintf(xpath_value, sizeof(xpath_value),
6508 : "%s/rmap-match-condition/list-name", xpath);
6509 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6510 0 : argv[argc - 1]->arg);
6511 :
6512 0 : return nb_cli_apply_changes(vty, NULL);
6513 : }
6514 :
6515 0 : DEFUN_YANG (no_match_ipv6_next_hop,
6516 : no_match_ipv6_next_hop_cmd,
6517 : "no match ipv6 next-hop [ACCESSLIST6_NAME]",
6518 : NO_STR
6519 : MATCH_STR
6520 : IPV6_STR
6521 : "Match IPv6 next-hop address of route\n"
6522 : "IPv6 access-list name\n")
6523 : {
6524 0 : const char *xpath =
6525 : "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6526 :
6527 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6528 0 : return nb_cli_apply_changes(vty, NULL);
6529 : }
6530 :
6531 0 : DEFUN_YANG (match_ipv6_next_hop_address,
6532 : match_ipv6_next_hop_address_cmd,
6533 : "match ipv6 next-hop address X:X::X:X",
6534 : MATCH_STR
6535 : IPV6_STR
6536 : "Match IPv6 next-hop address of route\n"
6537 : "IPv6 address\n"
6538 : "IPv6 address of next hop\n")
6539 : {
6540 0 : const char *xpath =
6541 : "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6542 0 : char xpath_value[XPATH_MAXLEN];
6543 :
6544 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6545 0 : snprintf(xpath_value, sizeof(xpath_value),
6546 : "%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
6547 : xpath);
6548 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6549 0 : argv[argc - 1]->arg);
6550 :
6551 0 : return nb_cli_apply_changes(vty, NULL);
6552 : }
6553 :
6554 0 : DEFUN_YANG (no_match_ipv6_next_hop_address,
6555 : no_match_ipv6_next_hop_address_cmd,
6556 : "no match ipv6 next-hop address X:X::X:X",
6557 : NO_STR
6558 : MATCH_STR
6559 : IPV6_STR
6560 : "Match IPv6 next-hop address of route\n"
6561 : "IPv6 address\n"
6562 : "IPv6 address of next hop\n")
6563 : {
6564 0 : const char *xpath =
6565 : "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6566 :
6567 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6568 0 : return nb_cli_apply_changes(vty, NULL);
6569 : }
6570 :
6571 : ALIAS_HIDDEN (match_ipv6_next_hop_address,
6572 : match_ipv6_next_hop_old_cmd,
6573 : "match ipv6 next-hop X:X::X:X",
6574 : MATCH_STR
6575 : IPV6_STR
6576 : "Match IPv6 next-hop address of route\n"
6577 : "IPv6 address of next hop\n")
6578 :
6579 : ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
6580 : no_match_ipv6_next_hop_old_cmd,
6581 : "no match ipv6 next-hop X:X::X:X",
6582 : NO_STR
6583 : MATCH_STR
6584 : IPV6_STR
6585 : "Match IPv6 next-hop address of route\n"
6586 : "IPv6 address of next hop\n")
6587 :
6588 0 : DEFUN_YANG (match_ipv6_next_hop_prefix_list,
6589 : match_ipv6_next_hop_prefix_list_cmd,
6590 : "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
6591 : MATCH_STR
6592 : IPV6_STR
6593 : "Match IPv6 next-hop address of route\n"
6594 : "Match entries by prefix-list\n"
6595 : "IPv6 prefix-list name\n")
6596 : {
6597 0 : const char *xpath =
6598 : "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6599 0 : char xpath_value[XPATH_MAXLEN];
6600 :
6601 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6602 0 : snprintf(xpath_value, sizeof(xpath_value),
6603 : "%s/rmap-match-condition/list-name", xpath);
6604 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6605 0 : argv[argc - 1]->arg);
6606 :
6607 0 : return nb_cli_apply_changes(vty, NULL);
6608 : }
6609 :
6610 0 : DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
6611 : no_match_ipv6_next_hop_prefix_list_cmd,
6612 : "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
6613 : NO_STR
6614 : MATCH_STR
6615 : IPV6_STR
6616 : "Match IPv6 next-hop address of route\n"
6617 : "Match entries by prefix-list\n"
6618 : "IPv6 prefix-list name\n")
6619 : {
6620 0 : const char *xpath =
6621 : "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6622 :
6623 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6624 0 : return nb_cli_apply_changes(vty, NULL);
6625 : }
6626 :
6627 0 : DEFPY_YANG (match_ipv4_next_hop,
6628 : match_ipv4_next_hop_cmd,
6629 : "match ip next-hop address A.B.C.D",
6630 : MATCH_STR
6631 : IP_STR
6632 : "Match IP next-hop address of route\n"
6633 : "IP address\n"
6634 : "IP address of next-hop\n")
6635 : {
6636 0 : const char *xpath =
6637 : "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6638 0 : char xpath_value[XPATH_MAXLEN];
6639 :
6640 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6641 0 : snprintf(xpath_value, sizeof(xpath_value),
6642 : "%s/rmap-match-condition/frr-bgp-route-map:ipv4-address",
6643 : xpath);
6644 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
6645 :
6646 0 : return nb_cli_apply_changes(vty, NULL);
6647 : }
6648 :
6649 0 : DEFPY_YANG (no_match_ipv4_next_hop,
6650 : no_match_ipv4_next_hop_cmd,
6651 : "no match ip next-hop address [A.B.C.D]",
6652 : NO_STR
6653 : MATCH_STR
6654 : IP_STR
6655 : "Match IP next-hop address of route\n"
6656 : "IP address\n"
6657 : "IP address of next-hop\n")
6658 : {
6659 0 : const char *xpath =
6660 : "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6661 :
6662 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6663 0 : return nb_cli_apply_changes(vty, NULL);
6664 : }
6665 :
6666 0 : DEFUN_YANG (set_ipv6_nexthop_peer,
6667 : set_ipv6_nexthop_peer_cmd,
6668 : "set ipv6 next-hop peer-address",
6669 : SET_STR
6670 : IPV6_STR
6671 : "Next hop address\n"
6672 : "Use peer address (for BGP only)\n")
6673 : {
6674 0 : const char *xpath =
6675 : "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6676 0 : char xpath_value[XPATH_MAXLEN];
6677 :
6678 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6679 0 : snprintf(xpath_value, sizeof(xpath_value),
6680 : "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6681 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6682 :
6683 0 : return nb_cli_apply_changes(vty, NULL);
6684 : }
6685 :
6686 0 : DEFUN_YANG (no_set_ipv6_nexthop_peer,
6687 : no_set_ipv6_nexthop_peer_cmd,
6688 : "no set ipv6 next-hop peer-address",
6689 : NO_STR
6690 : SET_STR
6691 : IPV6_STR
6692 : "IPv6 next-hop address\n"
6693 : "Use peer address (for BGP only)\n")
6694 : {
6695 0 : const char *xpath =
6696 : "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6697 :
6698 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6699 0 : return nb_cli_apply_changes(vty, NULL);
6700 : }
6701 :
6702 0 : DEFUN_YANG (set_ipv6_nexthop_prefer_global,
6703 : set_ipv6_nexthop_prefer_global_cmd,
6704 : "set ipv6 next-hop prefer-global",
6705 : SET_STR
6706 : IPV6_STR
6707 : "IPv6 next-hop address\n"
6708 : "Prefer global over link-local if both exist\n")
6709 : {
6710 0 : const char *xpath =
6711 : "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6712 0 : char xpath_value[XPATH_MAXLEN];
6713 :
6714 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6715 0 : snprintf(xpath_value, sizeof(xpath_value),
6716 : "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6717 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6718 :
6719 0 : return nb_cli_apply_changes(vty, NULL);
6720 : }
6721 :
6722 0 : DEFUN_YANG (no_set_ipv6_nexthop_prefer_global,
6723 : no_set_ipv6_nexthop_prefer_global_cmd,
6724 : "no set ipv6 next-hop prefer-global",
6725 : NO_STR
6726 : SET_STR
6727 : IPV6_STR
6728 : "IPv6 next-hop address\n"
6729 : "Prefer global over link-local if both exist\n")
6730 : {
6731 0 : const char *xpath =
6732 : "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6733 :
6734 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6735 0 : return nb_cli_apply_changes(vty, NULL);
6736 : }
6737 :
6738 0 : DEFUN_YANG (set_ipv6_nexthop_global,
6739 : set_ipv6_nexthop_global_cmd,
6740 : "set ipv6 next-hop global X:X::X:X",
6741 : SET_STR
6742 : IPV6_STR
6743 : "IPv6 next-hop address\n"
6744 : "IPv6 global address\n"
6745 : "IPv6 address of next hop\n")
6746 : {
6747 0 : int idx_ipv6 = 4;
6748 0 : const char *xpath =
6749 : "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6750 0 : char xpath_value[XPATH_MAXLEN];
6751 :
6752 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6753 0 : snprintf(xpath_value, sizeof(xpath_value),
6754 : "%s/rmap-set-action/frr-bgp-route-map:ipv6-address", xpath);
6755 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6756 0 : argv[idx_ipv6]->arg);
6757 :
6758 0 : return nb_cli_apply_changes(vty, NULL);
6759 : }
6760 :
6761 0 : DEFUN_YANG (no_set_ipv6_nexthop_global,
6762 : no_set_ipv6_nexthop_global_cmd,
6763 : "no set ipv6 next-hop global X:X::X:X",
6764 : NO_STR
6765 : SET_STR
6766 : IPV6_STR
6767 : "IPv6 next-hop address\n"
6768 : "IPv6 global address\n"
6769 : "IPv6 address of next hop\n")
6770 : {
6771 0 : const char *xpath =
6772 : "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6773 :
6774 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6775 0 : return nb_cli_apply_changes(vty, NULL);
6776 : }
6777 :
6778 : #ifdef KEEP_OLD_VPN_COMMANDS
6779 : DEFUN_YANG (set_vpn_nexthop,
6780 : set_vpn_nexthop_cmd,
6781 : "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6782 : SET_STR
6783 : "VPNv4 information\n"
6784 : "VPN next-hop address\n"
6785 : "IP address of next hop\n"
6786 : "VPNv6 information\n"
6787 : "VPN next-hop address\n"
6788 : "IPv6 address of next hop\n")
6789 : {
6790 : int idx_ip = 3;
6791 : afi_t afi;
6792 : int idx = 0;
6793 : char xpath_value[XPATH_MAXLEN];
6794 :
6795 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
6796 : if (afi == AFI_IP) {
6797 : const char *xpath =
6798 : "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6799 :
6800 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6801 : snprintf(
6802 : xpath_value, sizeof(xpath_value),
6803 : "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6804 : xpath);
6805 : } else {
6806 : const char *xpath =
6807 : "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6808 :
6809 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6810 : snprintf(
6811 : xpath_value, sizeof(xpath_value),
6812 : "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6813 : xpath);
6814 : }
6815 :
6816 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6817 : argv[idx_ip]->arg);
6818 :
6819 : return nb_cli_apply_changes(vty, NULL);
6820 : }
6821 :
6822 : return CMD_SUCCESS;
6823 : }
6824 :
6825 : DEFUN_YANG (no_set_vpn_nexthop,
6826 : no_set_vpn_nexthop_cmd,
6827 : "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6828 : NO_STR
6829 : SET_STR
6830 : "VPNv4 information\n"
6831 : "VPN next-hop address\n"
6832 : "IP address of next hop\n"
6833 : "VPNv6 information\n"
6834 : "VPN next-hop address\n"
6835 : "IPv6 address of next hop\n")
6836 : {
6837 : afi_t afi;
6838 : int idx = 0;
6839 :
6840 : if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
6841 : if (afi == AFI_IP) {
6842 : const char *xpath =
6843 : "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6844 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6845 : } else {
6846 : const char *xpath =
6847 : "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6848 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6849 : }
6850 : return nb_cli_apply_changes(vty, NULL);
6851 : }
6852 : return CMD_SUCCESS;
6853 : }
6854 : #endif /* KEEP_OLD_VPN_COMMANDS */
6855 :
6856 0 : DEFPY_YANG (set_ipx_vpn_nexthop,
6857 : set_ipx_vpn_nexthop_cmd,
6858 : "set <ipv4|ipv6> vpn next-hop <A.B.C.D$addrv4|X:X::X:X$addrv6>",
6859 : SET_STR
6860 : "IPv4 information\n"
6861 : "IPv6 information\n"
6862 : "VPN information\n"
6863 : "VPN next-hop address\n"
6864 : "IP address of next hop\n"
6865 : "IPv6 address of next hop\n")
6866 : {
6867 0 : int idx_ip = 4;
6868 0 : afi_t afi;
6869 0 : int idx = 0;
6870 0 : char xpath_value[XPATH_MAXLEN];
6871 :
6872 0 : if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
6873 0 : if (afi == AFI_IP) {
6874 0 : if (addrv6_str) {
6875 0 : vty_out(vty, "%% IPv4 next-hop expected\n");
6876 0 : return CMD_WARNING_CONFIG_FAILED;
6877 : }
6878 :
6879 0 : const char *xpath =
6880 : "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6881 :
6882 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6883 0 : snprintf(
6884 : xpath_value, sizeof(xpath_value),
6885 : "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
6886 : xpath);
6887 : } else {
6888 0 : if (addrv4_str) {
6889 0 : vty_out(vty, "%% IPv6 next-hop expected\n");
6890 0 : return CMD_WARNING_CONFIG_FAILED;
6891 : }
6892 :
6893 0 : const char *xpath =
6894 : "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6895 :
6896 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6897 0 : snprintf(
6898 : xpath_value, sizeof(xpath_value),
6899 : "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
6900 : xpath);
6901 : }
6902 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6903 0 : argv[idx_ip]->arg);
6904 0 : return nb_cli_apply_changes(vty, NULL);
6905 : }
6906 : return CMD_SUCCESS;
6907 : }
6908 :
6909 0 : DEFUN_YANG (no_set_ipx_vpn_nexthop,
6910 : no_set_ipx_vpn_nexthop_cmd,
6911 : "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
6912 : NO_STR
6913 : SET_STR
6914 : "IPv4 information\n"
6915 : "IPv6 information\n"
6916 : "VPN information\n"
6917 : "VPN next-hop address\n"
6918 : "IP address of next hop\n"
6919 : "IPv6 address of next hop\n")
6920 : {
6921 0 : afi_t afi;
6922 0 : int idx = 0;
6923 :
6924 0 : if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
6925 0 : if (afi == AFI_IP) {
6926 0 : const char *xpath =
6927 : "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
6928 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6929 : } else {
6930 0 : const char *xpath =
6931 : "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
6932 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6933 : }
6934 0 : return nb_cli_apply_changes(vty, NULL);
6935 : }
6936 : return CMD_SUCCESS;
6937 : }
6938 :
6939 0 : DEFUN_YANG (set_originator_id,
6940 : set_originator_id_cmd,
6941 : "set originator-id A.B.C.D",
6942 : SET_STR
6943 : "BGP originator ID attribute\n"
6944 : "IP address of originator\n")
6945 : {
6946 0 : int idx_ipv4 = 2;
6947 0 : const char *xpath =
6948 : "./set-action[action='frr-bgp-route-map:originator-id']";
6949 0 : char xpath_value[XPATH_MAXLEN];
6950 :
6951 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6952 0 : snprintf(xpath_value, sizeof(xpath_value),
6953 : "%s/rmap-set-action/frr-bgp-route-map:originator-id", xpath);
6954 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6955 0 : argv[idx_ipv4]->arg);
6956 :
6957 0 : return nb_cli_apply_changes(vty, NULL);
6958 : }
6959 :
6960 0 : DEFUN_YANG (no_set_originator_id,
6961 : no_set_originator_id_cmd,
6962 : "no set originator-id [A.B.C.D]",
6963 : NO_STR
6964 : SET_STR
6965 : "BGP originator ID attribute\n"
6966 : "IP address of originator\n")
6967 : {
6968 0 : const char *xpath =
6969 : "./set-action[action='frr-bgp-route-map:originator-id']";
6970 :
6971 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6972 0 : return nb_cli_apply_changes(vty, NULL);
6973 : }
6974 :
6975 0 : DEFPY_YANG (match_rpki_extcommunity,
6976 : match_rpki_extcommunity_cmd,
6977 : "[no$no] match rpki-extcommunity <valid|invalid|notfound>",
6978 : NO_STR
6979 : MATCH_STR
6980 : "BGP RPKI (Origin Validation State) extended community attribute\n"
6981 : "Valid prefix\n"
6982 : "Invalid prefix\n"
6983 : "Prefix not found\n")
6984 : {
6985 0 : const char *xpath =
6986 : "./match-condition[condition='frr-bgp-route-map:rpki-extcommunity']";
6987 0 : char xpath_value[XPATH_MAXLEN];
6988 :
6989 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6990 :
6991 0 : if (!no) {
6992 0 : snprintf(
6993 : xpath_value, sizeof(xpath_value),
6994 : "%s/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
6995 : xpath);
6996 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6997 0 : argv[2]->arg);
6998 : }
6999 :
7000 0 : return nb_cli_apply_changes(vty, NULL);
7001 : }
7002 :
7003 : /* Initialization of route map. */
7004 3 : void bgp_route_map_init(void)
7005 : {
7006 3 : route_map_init();
7007 :
7008 3 : route_map_add_hook(bgp_route_map_add);
7009 3 : route_map_delete_hook(bgp_route_map_delete);
7010 3 : route_map_event_hook(bgp_route_map_event);
7011 :
7012 3 : route_map_match_interface_hook(generic_match_add);
7013 3 : route_map_no_match_interface_hook(generic_match_delete);
7014 :
7015 3 : route_map_match_ip_address_hook(generic_match_add);
7016 3 : route_map_no_match_ip_address_hook(generic_match_delete);
7017 :
7018 3 : route_map_match_ip_address_prefix_list_hook(generic_match_add);
7019 3 : route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
7020 :
7021 3 : route_map_match_ip_next_hop_hook(generic_match_add);
7022 3 : route_map_no_match_ip_next_hop_hook(generic_match_delete);
7023 :
7024 3 : route_map_match_ipv6_next_hop_hook(generic_match_add);
7025 3 : route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
7026 :
7027 3 : route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
7028 3 : route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
7029 :
7030 3 : route_map_match_ip_next_hop_type_hook(generic_match_add);
7031 3 : route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
7032 :
7033 3 : route_map_match_ipv6_address_hook(generic_match_add);
7034 3 : route_map_no_match_ipv6_address_hook(generic_match_delete);
7035 :
7036 3 : route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
7037 3 : route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
7038 :
7039 3 : route_map_match_ipv6_next_hop_type_hook(generic_match_add);
7040 3 : route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
7041 :
7042 3 : route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
7043 3 : route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
7044 :
7045 3 : route_map_match_metric_hook(generic_match_add);
7046 3 : route_map_no_match_metric_hook(generic_match_delete);
7047 :
7048 3 : route_map_match_tag_hook(generic_match_add);
7049 3 : route_map_no_match_tag_hook(generic_match_delete);
7050 :
7051 3 : route_map_set_srte_color_hook(generic_set_add);
7052 3 : route_map_no_set_srte_color_hook(generic_set_delete);
7053 :
7054 3 : route_map_set_ip_nexthop_hook(generic_set_add);
7055 3 : route_map_no_set_ip_nexthop_hook(generic_set_delete);
7056 :
7057 3 : route_map_set_ipv6_nexthop_local_hook(generic_set_add);
7058 3 : route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
7059 :
7060 3 : route_map_set_metric_hook(generic_set_add);
7061 3 : route_map_no_set_metric_hook(generic_set_delete);
7062 :
7063 3 : route_map_set_tag_hook(generic_set_add);
7064 3 : route_map_no_set_tag_hook(generic_set_delete);
7065 :
7066 3 : route_map_install_match(&route_match_peer_cmd);
7067 3 : route_map_install_match(&route_match_alias_cmd);
7068 3 : route_map_install_match(&route_match_local_pref_cmd);
7069 : #ifdef HAVE_SCRIPTING
7070 : route_map_install_match(&route_match_script_cmd);
7071 : #endif
7072 3 : route_map_install_match(&route_match_ip_address_cmd);
7073 3 : route_map_install_match(&route_match_ip_next_hop_cmd);
7074 3 : route_map_install_match(&route_match_ip_route_source_cmd);
7075 3 : route_map_install_match(&route_match_ip_address_prefix_list_cmd);
7076 3 : route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
7077 3 : route_map_install_match(&route_match_ip_next_hop_type_cmd);
7078 3 : route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
7079 3 : route_map_install_match(&route_match_aspath_cmd);
7080 3 : route_map_install_match(&route_match_community_cmd);
7081 3 : route_map_install_match(&route_match_lcommunity_cmd);
7082 3 : route_map_install_match(&route_match_ecommunity_cmd);
7083 3 : route_map_install_match(&route_match_local_pref_cmd);
7084 3 : route_map_install_match(&route_match_metric_cmd);
7085 3 : route_map_install_match(&route_match_origin_cmd);
7086 3 : route_map_install_match(&route_match_probability_cmd);
7087 3 : route_map_install_match(&route_match_interface_cmd);
7088 3 : route_map_install_match(&route_match_tag_cmd);
7089 3 : route_map_install_match(&route_match_mac_address_cmd);
7090 3 : route_map_install_match(&route_match_evpn_vni_cmd);
7091 3 : route_map_install_match(&route_match_evpn_route_type_cmd);
7092 3 : route_map_install_match(&route_match_evpn_rd_cmd);
7093 3 : route_map_install_match(&route_match_evpn_default_route_cmd);
7094 3 : route_map_install_match(&route_match_vrl_source_vrf_cmd);
7095 :
7096 3 : route_map_install_set(&route_set_evpn_gateway_ip_ipv4_cmd);
7097 3 : route_map_install_set(&route_set_evpn_gateway_ip_ipv6_cmd);
7098 3 : route_map_install_set(&route_set_table_id_cmd);
7099 3 : route_map_install_set(&route_set_srte_color_cmd);
7100 3 : route_map_install_set(&route_set_ip_nexthop_cmd);
7101 3 : route_map_install_set(&route_set_local_pref_cmd);
7102 3 : route_map_install_set(&route_set_weight_cmd);
7103 3 : route_map_install_set(&route_set_label_index_cmd);
7104 3 : route_map_install_set(&route_set_metric_cmd);
7105 3 : route_map_install_set(&route_set_distance_cmd);
7106 3 : route_map_install_set(&route_set_aspath_prepend_cmd);
7107 3 : route_map_install_set(&route_set_aspath_exclude_cmd);
7108 3 : route_map_install_set(&route_set_aspath_replace_cmd);
7109 3 : route_map_install_set(&route_set_origin_cmd);
7110 3 : route_map_install_set(&route_set_atomic_aggregate_cmd);
7111 3 : route_map_install_set(&route_set_aigp_metric_cmd);
7112 3 : route_map_install_set(&route_set_aggregator_as_cmd);
7113 3 : route_map_install_set(&route_set_community_cmd);
7114 3 : route_map_install_set(&route_set_community_delete_cmd);
7115 3 : route_map_install_set(&route_set_lcommunity_cmd);
7116 3 : route_map_install_set(&route_set_lcommunity_delete_cmd);
7117 3 : route_map_install_set(&route_set_vpnv4_nexthop_cmd);
7118 3 : route_map_install_set(&route_set_vpnv6_nexthop_cmd);
7119 3 : route_map_install_set(&route_set_originator_id_cmd);
7120 3 : route_map_install_set(&route_set_ecommunity_rt_cmd);
7121 3 : route_map_install_set(&route_set_ecommunity_soo_cmd);
7122 3 : route_map_install_set(&route_set_ecommunity_lb_cmd);
7123 3 : route_map_install_set(&route_set_ecommunity_none_cmd);
7124 3 : route_map_install_set(&route_set_tag_cmd);
7125 3 : route_map_install_set(&route_set_label_index_cmd);
7126 3 : route_map_install_set(&route_set_l3vpn_nexthop_encapsulation_cmd);
7127 :
7128 3 : install_element(RMAP_NODE, &match_peer_cmd);
7129 3 : install_element(RMAP_NODE, &match_peer_local_cmd);
7130 3 : install_element(RMAP_NODE, &no_match_peer_cmd);
7131 3 : install_element(RMAP_NODE, &match_ip_route_source_cmd);
7132 3 : install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
7133 3 : install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
7134 3 : install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
7135 3 : install_element(RMAP_NODE, &match_mac_address_cmd);
7136 3 : install_element(RMAP_NODE, &no_match_mac_address_cmd);
7137 3 : install_element(RMAP_NODE, &match_evpn_vni_cmd);
7138 3 : install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
7139 3 : install_element(RMAP_NODE, &match_evpn_route_type_cmd);
7140 3 : install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
7141 3 : install_element(RMAP_NODE, &match_evpn_rd_cmd);
7142 3 : install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
7143 3 : install_element(RMAP_NODE, &match_evpn_default_route_cmd);
7144 3 : install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
7145 3 : install_element(RMAP_NODE, &set_evpn_gw_ip_ipv4_cmd);
7146 3 : install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv4_cmd);
7147 3 : install_element(RMAP_NODE, &set_evpn_gw_ip_ipv6_cmd);
7148 3 : install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv6_cmd);
7149 3 : install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
7150 3 : install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
7151 :
7152 3 : install_element(RMAP_NODE, &match_aspath_cmd);
7153 3 : install_element(RMAP_NODE, &no_match_aspath_cmd);
7154 3 : install_element(RMAP_NODE, &match_local_pref_cmd);
7155 3 : install_element(RMAP_NODE, &no_match_local_pref_cmd);
7156 3 : install_element(RMAP_NODE, &match_alias_cmd);
7157 3 : install_element(RMAP_NODE, &no_match_alias_cmd);
7158 3 : install_element(RMAP_NODE, &match_community_cmd);
7159 3 : install_element(RMAP_NODE, &no_match_community_cmd);
7160 3 : install_element(RMAP_NODE, &match_lcommunity_cmd);
7161 3 : install_element(RMAP_NODE, &no_match_lcommunity_cmd);
7162 3 : install_element(RMAP_NODE, &match_ecommunity_cmd);
7163 3 : install_element(RMAP_NODE, &no_match_ecommunity_cmd);
7164 3 : install_element(RMAP_NODE, &match_origin_cmd);
7165 3 : install_element(RMAP_NODE, &no_match_origin_cmd);
7166 3 : install_element(RMAP_NODE, &match_probability_cmd);
7167 3 : install_element(RMAP_NODE, &no_match_probability_cmd);
7168 :
7169 3 : install_element(RMAP_NODE, &no_set_table_id_cmd);
7170 3 : install_element(RMAP_NODE, &set_table_id_cmd);
7171 3 : install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
7172 3 : install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
7173 3 : install_element(RMAP_NODE, &set_local_pref_cmd);
7174 3 : install_element(RMAP_NODE, &set_distance_cmd);
7175 3 : install_element(RMAP_NODE, &no_set_distance_cmd);
7176 3 : install_element(RMAP_NODE, &no_set_local_pref_cmd);
7177 3 : install_element(RMAP_NODE, &set_weight_cmd);
7178 3 : install_element(RMAP_NODE, &set_label_index_cmd);
7179 3 : install_element(RMAP_NODE, &no_set_weight_cmd);
7180 3 : install_element(RMAP_NODE, &no_set_label_index_cmd);
7181 3 : install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
7182 3 : install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
7183 3 : install_element(RMAP_NODE, &set_aspath_exclude_cmd);
7184 3 : install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
7185 3 : install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
7186 3 : install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
7187 3 : install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
7188 3 : install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
7189 3 : install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
7190 3 : install_element(RMAP_NODE, &set_origin_cmd);
7191 3 : install_element(RMAP_NODE, &no_set_origin_cmd);
7192 3 : install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
7193 3 : install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
7194 3 : install_element(RMAP_NODE, &set_aigp_metric_cmd);
7195 3 : install_element(RMAP_NODE, &no_set_aigp_metric_cmd);
7196 3 : install_element(RMAP_NODE, &set_aggregator_as_cmd);
7197 3 : install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
7198 3 : install_element(RMAP_NODE, &set_community_cmd);
7199 3 : install_element(RMAP_NODE, &set_community_none_cmd);
7200 3 : install_element(RMAP_NODE, &no_set_community_cmd);
7201 3 : install_element(RMAP_NODE, &no_set_community_short_cmd);
7202 3 : install_element(RMAP_NODE, &set_community_delete_cmd);
7203 3 : install_element(RMAP_NODE, &no_set_community_delete_cmd);
7204 3 : install_element(RMAP_NODE, &set_lcommunity_cmd);
7205 3 : install_element(RMAP_NODE, &set_lcommunity_none_cmd);
7206 3 : install_element(RMAP_NODE, &no_set_lcommunity_cmd);
7207 3 : install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
7208 3 : install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
7209 3 : install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
7210 3 : install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
7211 3 : install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
7212 3 : install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
7213 3 : install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
7214 3 : install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
7215 3 : install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
7216 3 : install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
7217 3 : install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
7218 3 : install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
7219 3 : install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
7220 3 : install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
7221 3 : install_element(RMAP_NODE, &set_ecommunity_none_cmd);
7222 3 : install_element(RMAP_NODE, &no_set_ecommunity_none_cmd);
7223 : #ifdef KEEP_OLD_VPN_COMMANDS
7224 : install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
7225 : install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
7226 : #endif /* KEEP_OLD_VPN_COMMANDS */
7227 3 : install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
7228 3 : install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
7229 3 : install_element(RMAP_NODE, &set_originator_id_cmd);
7230 3 : install_element(RMAP_NODE, &no_set_originator_id_cmd);
7231 3 : install_element(RMAP_NODE, &set_l3vpn_nexthop_encapsulation_cmd);
7232 :
7233 3 : route_map_install_match(&route_match_ipv6_address_cmd);
7234 3 : route_map_install_match(&route_match_ipv6_next_hop_cmd);
7235 3 : route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
7236 3 : route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
7237 3 : route_map_install_match(&route_match_ipv4_next_hop_cmd);
7238 3 : route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
7239 3 : route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
7240 3 : route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
7241 3 : route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
7242 3 : route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
7243 3 : route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
7244 3 : route_map_install_match(&route_match_rpki_extcommunity_cmd);
7245 :
7246 3 : install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
7247 3 : install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
7248 3 : install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
7249 3 : install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
7250 3 : install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
7251 3 : install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
7252 3 : install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
7253 3 : install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
7254 3 : install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
7255 3 : install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
7256 3 : install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
7257 3 : install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
7258 3 : install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
7259 3 : install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
7260 3 : install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
7261 3 : install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
7262 3 : install_element(RMAP_NODE, &match_rpki_extcommunity_cmd);
7263 : #ifdef HAVE_SCRIPTING
7264 : install_element(RMAP_NODE, &match_script_cmd);
7265 : #endif
7266 3 : }
7267 :
7268 3 : void bgp_route_map_terminate(void)
7269 : {
7270 : /* ToDo: Cleanup all the used memory */
7271 3 : route_map_finish();
7272 3 : }
|