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