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