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