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