]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_routemap.c
Merge pull request #3006 from pacovn/static_analysis__shadow_variables1
[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 bgp_redist *red;
3090
3091 red_list = bgp->redist[afi][i];
3092 if (!red_list)
3093 continue;
3094
3095 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
3096 if (red->rmap.name
3097 && (strcmp(rmap_name, red->rmap.name)
3098 == 0)) {
3099 red->rmap.map = map;
3100
3101 if (route_update) {
3102 if (BGP_DEBUG(zebra, ZEBRA))
3103 zlog_debug(
3104 "Processing route_map %s update on "
3105 "redistributed routes",
3106 rmap_name);
3107
3108 bgp_redistribute_resend(
3109 bgp, afi, i,
3110 red->instance);
3111 }
3112 }
3113 }
3114 }
3115
3116 /* for type5 command route-maps */
3117 FOREACH_AFI_SAFI (afi, safi) {
3118 if (bgp->adv_cmd_rmap[afi][safi].name
3119 && strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
3120 == 0) {
3121 if (BGP_DEBUG(zebra, ZEBRA))
3122 zlog_debug(
3123 "Processing route_map %s update on advertise type5 route command",
3124 rmap_name);
3125 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
3126 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
3127 }
3128 }
3129 }
3130
3131 static void bgp_route_map_process_update_cb(char *rmap_name)
3132 {
3133 struct listnode *node, *nnode;
3134 struct bgp *bgp;
3135
3136 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
3137 bgp_route_map_process_update(bgp, rmap_name, 1);
3138
3139 #if ENABLE_BGP_VNC
3140 /* zlog_debug("%s: calling vnc_routemap_update", __func__); */
3141 vnc_routemap_update(bgp, __func__);
3142 #endif
3143 }
3144
3145 vpn_policy_routemap_event(rmap_name);
3146 }
3147
3148 int bgp_route_map_update_timer(struct thread *thread)
3149 {
3150 bm->t_rmap_update = NULL;
3151
3152 route_map_walk_update_list(bgp_route_map_process_update_cb);
3153
3154 return (0);
3155 }
3156
3157 static void bgp_route_map_mark_update(const char *rmap_name)
3158 {
3159 if (bm->t_rmap_update == NULL) {
3160 struct listnode *node, *nnode;
3161 struct bgp *bgp;
3162
3163 /* rmap_update_timer of 0 means don't do route updates */
3164 if (bm->rmap_update_timer) {
3165 bm->t_rmap_update = NULL;
3166 thread_add_timer(bm->master, bgp_route_map_update_timer,
3167 NULL, bm->rmap_update_timer,
3168 &bm->t_rmap_update);
3169
3170 /* Signal the groups that a route-map update event has
3171 * started */
3172 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3173 update_group_policy_update(bgp,
3174 BGP_POLICY_ROUTE_MAP,
3175 rmap_name, 1, 1);
3176 } else {
3177 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3178 bgp_route_map_process_update(bgp, rmap_name, 0);
3179 #if ENABLE_BGP_VNC
3180 zlog_debug("%s: calling vnc_routemap_update", __func__);
3181 vnc_routemap_update(bgp, __func__);
3182 #endif
3183 }
3184 }
3185 }
3186
3187 static void bgp_route_map_add(const char *rmap_name)
3188 {
3189 if (route_map_mark_updated(rmap_name) == 0)
3190 bgp_route_map_mark_update(rmap_name);
3191
3192 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
3193 }
3194
3195 static void bgp_route_map_delete(const char *rmap_name)
3196 {
3197 if (route_map_mark_updated(rmap_name) == 0)
3198 bgp_route_map_mark_update(rmap_name);
3199
3200 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
3201 }
3202
3203 static void bgp_route_map_event(route_map_event_t event, const char *rmap_name)
3204 {
3205 if (route_map_mark_updated(rmap_name) == 0)
3206 bgp_route_map_mark_update(rmap_name);
3207
3208 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
3209 }
3210
3211 DEFUN (match_mac_address,
3212 match_mac_address_cmd,
3213 "match mac address WORD",
3214 MATCH_STR
3215 "mac address\n"
3216 "Match address of route\n"
3217 "MAC Access-list name\n")
3218 {
3219 return bgp_route_match_add(vty, "mac address", argv[3]->arg,
3220 RMAP_EVENT_FILTER_ADDED);
3221 }
3222
3223 DEFUN (no_match_mac_address,
3224 no_match_mac_address_cmd,
3225 "no match mac address WORD",
3226 NO_STR
3227 MATCH_STR
3228 "mac\n"
3229 "Match address of route\n"
3230 "MAC acess-list name\n")
3231 {
3232 return bgp_route_match_delete(vty, "mac address", argv[4]->arg,
3233 RMAP_EVENT_FILTER_DELETED);
3234 }
3235
3236 DEFUN (match_evpn_route_type,
3237 match_evpn_route_type_cmd,
3238 "match evpn route-type <macip | multicast | prefix>",
3239 MATCH_STR
3240 EVPN_HELP_STR
3241 "Match route-type\n"
3242 "mac-ip route\n"
3243 "IMET route\n"
3244 "prefix route\n")
3245 {
3246 return bgp_route_match_add(vty, "evpn route-type", argv[3]->arg,
3247 RMAP_EVENT_MATCH_ADDED);
3248 }
3249
3250 DEFUN (no_match_evpn_route_type,
3251 no_match_evpn_route_type_cmd,
3252 "no match evpn route-type <macip | multicast | prefix>",
3253 NO_STR
3254 MATCH_STR
3255 EVPN_HELP_STR
3256 "Match route-type\n"
3257 "mac-ip route\n"
3258 "IMET route\n"
3259 "prefix route\n")
3260 {
3261 return bgp_route_match_delete(vty, "evpn route-type", argv[4]->arg,
3262 RMAP_EVENT_MATCH_DELETED);
3263 }
3264
3265
3266 DEFUN (match_evpn_vni,
3267 match_evpn_vni_cmd,
3268 "match evpn vni (1-16777215)",
3269 MATCH_STR
3270 EVPN_HELP_STR
3271 "Match VNI\n"
3272 "VNI ID\n")
3273 {
3274 return bgp_route_match_add(vty, "evpn vni", argv[3]->arg,
3275 RMAP_EVENT_MATCH_ADDED);
3276 }
3277
3278 DEFUN (no_match_evpn_vni,
3279 no_match_evpn_vni_cmd,
3280 "no match evpn vni (1-16777215)",
3281 NO_STR
3282 MATCH_STR
3283 EVPN_HELP_STR
3284 "Match VNI\n"
3285 "VNI ID\n")
3286 {
3287 return bgp_route_match_delete(vty, "evpn vni", argv[4]->arg,
3288 RMAP_EVENT_MATCH_DELETED);
3289 }
3290
3291 DEFUN (match_evpn_default_route,
3292 match_evpn_default_route_cmd,
3293 "match evpn default-route",
3294 MATCH_STR
3295 EVPN_HELP_STR
3296 "default EVPN type-5 route\n")
3297 {
3298 return bgp_route_match_add(vty, "evpn default-route", NULL,
3299 RMAP_EVENT_MATCH_ADDED);
3300 }
3301
3302 DEFUN (no_match_evpn_default_route,
3303 no_match_evpn_default_route_cmd,
3304 "no match evpn default-route",
3305 NO_STR
3306 MATCH_STR
3307 EVPN_HELP_STR
3308 "default EVPN type-5 route\n")
3309 {
3310 return bgp_route_match_delete(vty, "evpn default-route", NULL,
3311 RMAP_EVENT_MATCH_DELETED);
3312 }
3313
3314 DEFUN (match_peer,
3315 match_peer_cmd,
3316 "match peer <A.B.C.D|X:X::X:X|WORD>",
3317 MATCH_STR
3318 "Match peer address\n"
3319 "IP address of peer\n"
3320 "IPv6 address of peer\n"
3321 "Interface name of peer\n")
3322 {
3323 int idx_ip = 2;
3324 return bgp_route_match_add(vty, "peer", argv[idx_ip]->arg,
3325 RMAP_EVENT_MATCH_ADDED);
3326 }
3327
3328 DEFUN (match_peer_local,
3329 match_peer_local_cmd,
3330 "match peer local",
3331 MATCH_STR
3332 "Match peer address\n"
3333 "Static or Redistributed routes\n")
3334 {
3335 return bgp_route_match_add(vty, "peer", "local",
3336 RMAP_EVENT_MATCH_DELETED);
3337 }
3338
3339 DEFUN (no_match_peer,
3340 no_match_peer_cmd,
3341 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
3342 NO_STR
3343 MATCH_STR
3344 "Match peer address\n"
3345 "Static or Redistributed routes\n"
3346 "IP address of peer\n"
3347 "IPv6 address of peer\n"
3348 "Interface name of peer\n")
3349 {
3350 int idx_peer = 3;
3351
3352 if (argc <= idx_peer)
3353 return bgp_route_match_delete(vty, "peer", NULL,
3354 RMAP_EVENT_MATCH_DELETED);
3355 return bgp_route_match_delete(vty, "peer", argv[idx_peer]->arg,
3356 RMAP_EVENT_MATCH_DELETED);
3357 }
3358
3359
3360 /* match probability */
3361 DEFUN (match_probability,
3362 match_probability_cmd,
3363 "match probability (0-100)",
3364 MATCH_STR
3365 "Match portion of routes defined by percentage value\n"
3366 "Percentage of routes\n")
3367 {
3368 int idx_number = 2;
3369 return bgp_route_match_add(vty, "probability", argv[idx_number]->arg,
3370 RMAP_EVENT_MATCH_ADDED);
3371 }
3372
3373
3374 DEFUN (no_match_probability,
3375 no_match_probability_cmd,
3376 "no match probability [(1-99)]",
3377 NO_STR
3378 MATCH_STR
3379 "Match portion of routes defined by percentage value\n"
3380 "Percentage of routes\n")
3381 {
3382 int idx_number = 3;
3383 if (argc <= idx_number)
3384 return bgp_route_match_delete(vty, "probability", NULL,
3385 RMAP_EVENT_MATCH_DELETED);
3386 return bgp_route_match_delete(vty, "probability", argv[idx_number]->arg,
3387 RMAP_EVENT_MATCH_DELETED);
3388 }
3389
3390
3391 DEFUN (match_ip_route_source,
3392 match_ip_route_source_cmd,
3393 "match ip route-source <(1-199)|(1300-2699)|WORD>",
3394 MATCH_STR
3395 IP_STR
3396 "Match advertising source address of route\n"
3397 "IP access-list number\n"
3398 "IP access-list number (expanded range)\n"
3399 "IP standard access-list name\n")
3400 {
3401 int idx_acl = 3;
3402 return bgp_route_match_add(vty, "ip route-source", argv[idx_acl]->arg,
3403 RMAP_EVENT_FILTER_ADDED);
3404 }
3405
3406
3407 DEFUN (no_match_ip_route_source,
3408 no_match_ip_route_source_cmd,
3409 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
3410 NO_STR
3411 MATCH_STR
3412 IP_STR
3413 "Match advertising source address of route\n"
3414 "IP access-list number\n"
3415 "IP access-list number (expanded range)\n"
3416 "IP standard access-list name\n")
3417 {
3418 int idx_number = 4;
3419 if (argc <= idx_number)
3420 return bgp_route_match_delete(vty, "ip route-source", NULL,
3421 RMAP_EVENT_FILTER_DELETED);
3422 return bgp_route_match_delete(vty, "ip route-source",
3423 argv[idx_number]->arg,
3424 RMAP_EVENT_FILTER_DELETED);
3425 }
3426
3427
3428 DEFUN (match_ip_route_source_prefix_list,
3429 match_ip_route_source_prefix_list_cmd,
3430 "match ip route-source prefix-list WORD",
3431 MATCH_STR
3432 IP_STR
3433 "Match advertising source address of route\n"
3434 "Match entries of prefix-lists\n"
3435 "IP prefix-list name\n")
3436 {
3437 int idx_word = 4;
3438 return bgp_route_match_add(vty, "ip route-source prefix-list",
3439 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
3440 }
3441
3442
3443 DEFUN (no_match_ip_route_source_prefix_list,
3444 no_match_ip_route_source_prefix_list_cmd,
3445 "no match ip route-source prefix-list [WORD]",
3446 NO_STR
3447 MATCH_STR
3448 IP_STR
3449 "Match advertising source address of route\n"
3450 "Match entries of prefix-lists\n"
3451 "IP prefix-list name\n")
3452 {
3453 int idx_word = 5;
3454 if (argc <= idx_word)
3455 return bgp_route_match_delete(vty,
3456 "ip route-source prefix-list",
3457 NULL, RMAP_EVENT_PLIST_DELETED);
3458 return bgp_route_match_delete(vty, "ip route-source prefix-list",
3459 argv[idx_word]->arg,
3460 RMAP_EVENT_PLIST_DELETED);
3461 }
3462
3463
3464 DEFUN (match_local_pref,
3465 match_local_pref_cmd,
3466 "match local-preference (0-4294967295)",
3467 MATCH_STR
3468 "Match local-preference of route\n"
3469 "Metric value\n")
3470 {
3471 int idx_number = 2;
3472 return bgp_route_match_add(vty, "local-preference",
3473 argv[idx_number]->arg,
3474 RMAP_EVENT_MATCH_ADDED);
3475 }
3476
3477
3478 DEFUN (no_match_local_pref,
3479 no_match_local_pref_cmd,
3480 "no match local-preference [(0-4294967295)]",
3481 NO_STR
3482 MATCH_STR
3483 "Match local preference of route\n"
3484 "Local preference value\n")
3485 {
3486 int idx_localpref = 3;
3487 if (argc <= idx_localpref)
3488 return bgp_route_match_delete(vty, "local-preference", NULL,
3489 RMAP_EVENT_MATCH_DELETED);
3490 return bgp_route_match_delete(vty, "local-preference",
3491 argv[idx_localpref]->arg,
3492 RMAP_EVENT_MATCH_DELETED);
3493 }
3494
3495
3496 DEFUN (match_community,
3497 match_community_cmd,
3498 "match community <(1-99)|(100-500)|WORD> [exact-match]",
3499 MATCH_STR
3500 "Match BGP community list\n"
3501 "Community-list number (standard)\n"
3502 "Community-list number (expanded)\n"
3503 "Community-list name\n"
3504 "Do exact matching of communities\n")
3505 {
3506 int idx_comm_list = 2;
3507 int ret;
3508 char *argstr;
3509
3510 if (argc == 4) {
3511 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
3512 strlen(argv[idx_comm_list]->arg)
3513 + strlen("exact-match") + 2);
3514
3515 sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
3516 } else
3517 argstr = argv[idx_comm_list]->arg;
3518
3519 ret = bgp_route_match_add(vty, "community", argstr,
3520 RMAP_EVENT_CLIST_ADDED);
3521
3522 if (argstr != argv[idx_comm_list]->arg)
3523 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
3524
3525 return ret;
3526 }
3527
3528 DEFUN (no_match_community,
3529 no_match_community_cmd,
3530 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
3531 NO_STR
3532 MATCH_STR
3533 "Match BGP community list\n"
3534 "Community-list number (standard)\n"
3535 "Community-list number (expanded)\n"
3536 "Community-list name\n"
3537 "Do exact matching of communities\n")
3538 {
3539 return bgp_route_match_delete(vty, "community", NULL,
3540 RMAP_EVENT_CLIST_DELETED);
3541 }
3542
3543 DEFUN (match_lcommunity,
3544 match_lcommunity_cmd,
3545 "match large-community <(1-99)|(100-500)|WORD>",
3546 MATCH_STR
3547 "Match BGP large community list\n"
3548 "Large Community-list number (standard)\n"
3549 "Large Community-list number (expanded)\n"
3550 "Large Community-list name\n")
3551 {
3552 return bgp_route_match_add(vty, "large-community", argv[2]->arg,
3553 RMAP_EVENT_LLIST_ADDED);
3554 }
3555
3556 DEFUN (no_match_lcommunity,
3557 no_match_lcommunity_cmd,
3558 "no match large-community [<(1-99)|(100-500)|WORD>]",
3559 NO_STR
3560 MATCH_STR
3561 "Match BGP large community list\n"
3562 "Large Community-list number (standard)\n"
3563 "Large Community-list number (expanded)\n"
3564 "Large Community-list name\n")
3565 {
3566 return bgp_route_match_delete(vty, "large-community", NULL,
3567 RMAP_EVENT_LLIST_DELETED);
3568 }
3569
3570 DEFUN (match_ecommunity,
3571 match_ecommunity_cmd,
3572 "match extcommunity <(1-99)|(100-500)|WORD>",
3573 MATCH_STR
3574 "Match BGP/VPN extended community list\n"
3575 "Extended community-list number (standard)\n"
3576 "Extended community-list number (expanded)\n"
3577 "Extended community-list name\n")
3578 {
3579 int idx_comm_list = 2;
3580 return bgp_route_match_add(vty, "extcommunity",
3581 argv[idx_comm_list]->arg,
3582 RMAP_EVENT_ECLIST_ADDED);
3583 }
3584
3585
3586 DEFUN (no_match_ecommunity,
3587 no_match_ecommunity_cmd,
3588 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
3589 NO_STR
3590 MATCH_STR
3591 "Match BGP/VPN extended community list\n"
3592 "Extended community-list number (standard)\n"
3593 "Extended community-list number (expanded)\n"
3594 "Extended community-list name\n")
3595 {
3596 return bgp_route_match_delete(vty, "extcommunity", NULL,
3597 RMAP_EVENT_ECLIST_DELETED);
3598 }
3599
3600
3601 DEFUN (match_aspath,
3602 match_aspath_cmd,
3603 "match as-path WORD",
3604 MATCH_STR
3605 "Match BGP AS path list\n"
3606 "AS path access-list name\n")
3607 {
3608 int idx_word = 2;
3609 return bgp_route_match_add(vty, "as-path", argv[idx_word]->arg,
3610 RMAP_EVENT_ASLIST_ADDED);
3611 }
3612
3613
3614 DEFUN (no_match_aspath,
3615 no_match_aspath_cmd,
3616 "no match as-path [WORD]",
3617 NO_STR
3618 MATCH_STR
3619 "Match BGP AS path list\n"
3620 "AS path access-list name\n")
3621 {
3622 return bgp_route_match_delete(vty, "as-path", NULL,
3623 RMAP_EVENT_ASLIST_DELETED);
3624 }
3625
3626
3627 DEFUN (match_origin,
3628 match_origin_cmd,
3629 "match origin <egp|igp|incomplete>",
3630 MATCH_STR
3631 "BGP origin code\n"
3632 "remote EGP\n"
3633 "local IGP\n"
3634 "unknown heritage\n")
3635 {
3636 int idx_origin = 2;
3637 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
3638 return bgp_route_match_add(vty, "origin", "igp",
3639 RMAP_EVENT_MATCH_ADDED);
3640 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
3641 return bgp_route_match_add(vty, "origin", "egp",
3642 RMAP_EVENT_MATCH_ADDED);
3643 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
3644 return bgp_route_match_add(vty, "origin", "incomplete",
3645 RMAP_EVENT_MATCH_ADDED);
3646
3647 vty_out(vty, "%% Invalid match origin type\n");
3648 return CMD_WARNING_CONFIG_FAILED;
3649 }
3650
3651
3652 DEFUN (no_match_origin,
3653 no_match_origin_cmd,
3654 "no match origin [<egp|igp|incomplete>]",
3655 NO_STR
3656 MATCH_STR
3657 "BGP origin code\n"
3658 "remote EGP\n"
3659 "local IGP\n"
3660 "unknown heritage\n")
3661 {
3662 return bgp_route_match_delete(vty, "origin", NULL,
3663 RMAP_EVENT_MATCH_DELETED);
3664 }
3665
3666 DEFUN (set_ip_nexthop_peer,
3667 set_ip_nexthop_peer_cmd,
3668 "[no] set ip next-hop peer-address",
3669 NO_STR
3670 SET_STR
3671 IP_STR
3672 "Next hop address\n"
3673 "Use peer address (for BGP only)\n")
3674 {
3675 int (*func)(struct vty *, struct route_map_index *, const char *,
3676 const char *) = strmatch(argv[0]->text, "no")
3677 ? generic_set_delete
3678 : generic_set_add;
3679
3680 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
3681 "peer-address");
3682 }
3683
3684 DEFUN (set_ip_nexthop_unchanged,
3685 set_ip_nexthop_unchanged_cmd,
3686 "[no] set ip next-hop unchanged",
3687 NO_STR
3688 SET_STR
3689 IP_STR
3690 "Next hop address\n"
3691 "Don't modify existing Next hop address\n")
3692 {
3693 int (*func)(struct vty *, struct route_map_index *, const char *,
3694 const char *) = strmatch(argv[0]->text, "no")
3695 ? generic_set_delete
3696 : generic_set_add;
3697
3698 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
3699 "unchanged");
3700 }
3701
3702
3703 DEFUN (set_local_pref,
3704 set_local_pref_cmd,
3705 "set local-preference (0-4294967295)",
3706 SET_STR
3707 "BGP local preference path attribute\n"
3708 "Preference value\n")
3709 {
3710 int idx_number = 2;
3711 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3712 "local-preference", argv[idx_number]->arg);
3713 }
3714
3715
3716 DEFUN (no_set_local_pref,
3717 no_set_local_pref_cmd,
3718 "no set local-preference [(0-4294967295)]",
3719 NO_STR
3720 SET_STR
3721 "BGP local preference path attribute\n"
3722 "Preference value\n")
3723 {
3724 int idx_localpref = 3;
3725 if (argc <= idx_localpref)
3726 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3727 "local-preference", NULL);
3728 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3729 "local-preference", argv[idx_localpref]->arg);
3730 }
3731
3732
3733 DEFUN (set_weight,
3734 set_weight_cmd,
3735 "set weight (0-4294967295)",
3736 SET_STR
3737 "BGP weight for routing table\n"
3738 "Weight value\n")
3739 {
3740 int idx_number = 2;
3741 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "weight",
3742 argv[idx_number]->arg);
3743 }
3744
3745
3746 DEFUN (no_set_weight,
3747 no_set_weight_cmd,
3748 "no set weight [(0-4294967295)]",
3749 NO_STR
3750 SET_STR
3751 "BGP weight for routing table\n"
3752 "Weight value\n")
3753 {
3754 int idx_weight = 3;
3755 if (argc <= idx_weight)
3756 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3757 "weight", NULL);
3758 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3759 "weight", argv[idx_weight]->arg);
3760 }
3761
3762 DEFUN (set_label_index,
3763 set_label_index_cmd,
3764 "set label-index (0-1048560)",
3765 SET_STR
3766 "Label index to associate with the prefix\n"
3767 "Label index value\n")
3768 {
3769 int idx_number = 2;
3770 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3771 "label-index", argv[idx_number]->arg);
3772 }
3773
3774 DEFUN (no_set_label_index,
3775 no_set_label_index_cmd,
3776 "no set label-index [(0-1048560)]",
3777 NO_STR
3778 SET_STR
3779 "Label index to associate with the prefix\n"
3780 "Label index value\n")
3781 {
3782 int idx_label_index = 3;
3783 if (argc <= idx_label_index)
3784 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3785 "label-index", NULL);
3786 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3787 "label-index", argv[idx_label_index]->arg);
3788 }
3789
3790 DEFUN (set_aspath_prepend_asn,
3791 set_aspath_prepend_asn_cmd,
3792 "set as-path prepend (1-4294967295)...",
3793 SET_STR
3794 "Transform BGP AS_PATH attribute\n"
3795 "Prepend to the as-path\n"
3796 "AS number\n")
3797 {
3798 int idx_asn = 3;
3799 int ret;
3800 char *str;
3801
3802 str = argv_concat(argv, argc, idx_asn);
3803 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3804 "as-path prepend", str);
3805 XFREE(MTYPE_TMP, str);
3806
3807 return ret;
3808 }
3809
3810 DEFUN (set_aspath_prepend_lastas,
3811 set_aspath_prepend_lastas_cmd,
3812 "set as-path prepend last-as (1-10)",
3813 SET_STR
3814 "Transform BGP AS_PATH attribute\n"
3815 "Prepend to the as-path\n"
3816 "Use the peer's AS-number\n"
3817 "Number of times to insert\n")
3818 {
3819 return set_aspath_prepend_asn(self, vty, argc, argv);
3820 }
3821
3822 DEFUN (no_set_aspath_prepend,
3823 no_set_aspath_prepend_cmd,
3824 "no set as-path prepend [(1-4294967295)]",
3825 NO_STR
3826 SET_STR
3827 "Transform BGP AS_PATH attribute\n"
3828 "Prepend to the as-path\n"
3829 "AS number\n")
3830 {
3831 int idx_asn = 4;
3832 int ret;
3833 char *str;
3834
3835 str = argv_concat(argv, argc, idx_asn);
3836 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3837 "as-path prepend", str);
3838 XFREE(MTYPE_TMP, str);
3839 return ret;
3840 }
3841
3842
3843 DEFUN (set_aspath_exclude,
3844 set_aspath_exclude_cmd,
3845 "set as-path exclude (1-4294967295)...",
3846 SET_STR
3847 "Transform BGP AS-path attribute\n"
3848 "Exclude from the as-path\n"
3849 "AS number\n")
3850 {
3851 int idx_asn = 3;
3852 int ret;
3853 char *str;
3854
3855 str = argv_concat(argv, argc, idx_asn);
3856 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3857 "as-path exclude", str);
3858 XFREE(MTYPE_TMP, str);
3859 return ret;
3860 }
3861
3862 DEFUN (no_set_aspath_exclude,
3863 no_set_aspath_exclude_cmd,
3864 "no set as-path exclude (1-4294967295)...",
3865 NO_STR
3866 SET_STR
3867 "Transform BGP AS_PATH attribute\n"
3868 "Exclude from the as-path\n"
3869 "AS number\n")
3870 {
3871 int idx_asn = 4;
3872 int ret;
3873 char *str;
3874
3875 str = argv_concat(argv, argc, idx_asn);
3876 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3877 "as-path exclude", str);
3878 XFREE(MTYPE_TMP, str);
3879 return ret;
3880 }
3881
3882
3883 DEFUN (set_community,
3884 set_community_cmd,
3885 "set community AA:NN...",
3886 SET_STR
3887 "BGP community attribute\n"
3888 COMMUNITY_VAL_STR)
3889 {
3890 int idx_aa_nn = 2;
3891 int i;
3892 int first = 0;
3893 int additive = 0;
3894 struct buffer *b;
3895 struct community *com = NULL;
3896 char *str;
3897 char *argstr;
3898 int ret;
3899
3900 b = buffer_new(1024);
3901
3902 for (i = idx_aa_nn; i < argc; i++) {
3903 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
3904 == 0) {
3905 additive = 1;
3906 continue;
3907 }
3908
3909 if (first)
3910 buffer_putc(b, ' ');
3911 else
3912 first = 1;
3913
3914 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
3915 == 0) {
3916 buffer_putstr(b, "internet");
3917 continue;
3918 }
3919 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
3920 == 0) {
3921 buffer_putstr(b, "local-AS");
3922 continue;
3923 }
3924 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
3925 && strncmp(argv[i]->arg, "no-advertise",
3926 strlen(argv[i]->arg))
3927 == 0) {
3928 buffer_putstr(b, "no-advertise");
3929 continue;
3930 }
3931 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
3932 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
3933 == 0) {
3934 buffer_putstr(b, "no-export");
3935 continue;
3936 }
3937 if (strncmp(argv[i]->arg, "graceful-shutdown",
3938 strlen(argv[i]->arg))
3939 == 0) {
3940 buffer_putstr(b, "graceful-shutdown");
3941 continue;
3942 }
3943 buffer_putstr(b, argv[i]->arg);
3944 }
3945 buffer_putc(b, '\0');
3946
3947 /* Fetch result string then compile it to communities attribute. */
3948 str = buffer_getstr(b);
3949 buffer_free(b);
3950
3951 if (str) {
3952 com = community_str2com(str);
3953 XFREE(MTYPE_TMP, str);
3954 }
3955
3956 /* Can't compile user input into communities attribute. */
3957 if (!com) {
3958 vty_out(vty, "%% Malformed communities attribute\n");
3959 return CMD_WARNING_CONFIG_FAILED;
3960 }
3961
3962 /* Set communites attribute string. */
3963 str = community_str(com, false);
3964
3965 if (additive) {
3966 argstr = XCALLOC(MTYPE_TMP,
3967 strlen(str) + strlen(" additive") + 1);
3968 strcpy(argstr, str);
3969 strcpy(argstr + strlen(str), " additive");
3970 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3971 "community", argstr);
3972 XFREE(MTYPE_TMP, argstr);
3973 } else
3974 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3975 "community", str);
3976
3977 community_free(com);
3978
3979 return ret;
3980 }
3981
3982 DEFUN (set_community_none,
3983 set_community_none_cmd,
3984 "set community none",
3985 SET_STR
3986 "BGP community attribute\n"
3987 "No community attribute\n")
3988 {
3989 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3990 "community", "none");
3991 }
3992
3993 DEFUN (no_set_community,
3994 no_set_community_cmd,
3995 "no set community AA:NN...",
3996 NO_STR
3997 SET_STR
3998 "BGP community attribute\n"
3999 COMMUNITY_VAL_STR)
4000 {
4001 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4002 "community", NULL);
4003 }
4004
4005
4006 DEFUN (set_community_delete,
4007 set_community_delete_cmd,
4008 "set comm-list <(1-99)|(100-500)|WORD> delete",
4009 SET_STR
4010 "set BGP community list (for deletion)\n"
4011 "Community-list number (standard)\n"
4012 "Community-list number (expanded)\n"
4013 "Community-list name\n"
4014 "Delete matching communities\n")
4015 {
4016 int idx_comm_list = 2;
4017 char *str;
4018
4019 str = XCALLOC(MTYPE_TMP,
4020 strlen(argv[idx_comm_list]->arg) + strlen(" delete") + 1);
4021 strcpy(str, argv[idx_comm_list]->arg);
4022 strcpy(str + strlen(argv[idx_comm_list]->arg), " delete");
4023
4024 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
4025 str);
4026
4027 XFREE(MTYPE_TMP, str);
4028 return CMD_SUCCESS;
4029 }
4030
4031 DEFUN (no_set_community_delete,
4032 no_set_community_delete_cmd,
4033 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
4034 NO_STR
4035 SET_STR
4036 "set BGP community list (for deletion)\n"
4037 "Community-list number (standard)\n"
4038 "Community-list number (expanded)\n"
4039 "Community-list name\n"
4040 "Delete matching communities\n")
4041 {
4042 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4043 "comm-list", NULL);
4044 }
4045
4046 DEFUN (set_lcommunity,
4047 set_lcommunity_cmd,
4048 "set large-community AA:BB:CC...",
4049 SET_STR
4050 "BGP large community attribute\n"
4051 "Large Community number in aa:bb:cc format or additive\n")
4052 {
4053 int ret;
4054 char *str;
4055
4056 str = argv_concat(argv, argc, 2);
4057 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4058 "large-community", str);
4059 XFREE(MTYPE_TMP, str);
4060
4061 return ret;
4062 }
4063
4064 DEFUN (set_lcommunity_none,
4065 set_lcommunity_none_cmd,
4066 "set large-community none",
4067 SET_STR
4068 "BGP large community attribute\n"
4069 "No large community attribute\n")
4070 {
4071 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4072 "large-community", "none");
4073 }
4074
4075 DEFUN (no_set_lcommunity,
4076 no_set_lcommunity_cmd,
4077 "no set large-community none",
4078 NO_STR
4079 SET_STR
4080 "BGP large community attribute\n"
4081 "No community attribute\n")
4082 {
4083 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4084 "large-community", NULL);
4085 }
4086
4087 DEFUN (no_set_lcommunity1,
4088 no_set_lcommunity1_cmd,
4089 "no set large-community AA:BB:CC...",
4090 NO_STR
4091 SET_STR
4092 "BGP large community attribute\n"
4093 "Large community in AA:BB:CC... format or additive\n")
4094 {
4095 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4096 "large-community", NULL);
4097 }
4098
4099 DEFUN (set_lcommunity_delete,
4100 set_lcommunity_delete_cmd,
4101 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
4102 SET_STR
4103 "set BGP large community list (for deletion)\n"
4104 "Large Community-list number (standard)\n"
4105 "Large Communitly-list number (expanded)\n"
4106 "Large Community-list name\n"
4107 "Delete matching large communities\n")
4108 {
4109 char *str;
4110
4111 str = XCALLOC(MTYPE_TMP, strlen(argv[2]->arg) + strlen(" delete") + 1);
4112 strcpy(str, argv[2]->arg);
4113 strcpy(str + strlen(argv[2]->arg), " delete");
4114
4115 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4116 "large-comm-list", str);
4117
4118 XFREE(MTYPE_TMP, str);
4119 return CMD_SUCCESS;
4120 }
4121
4122 DEFUN (no_set_lcommunity_delete,
4123 no_set_lcommunity_delete_cmd,
4124 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
4125 NO_STR
4126 SET_STR
4127 "set BGP large community list (for deletion)\n"
4128 "Large Community-list number (standard)\n"
4129 "Large Communitly-list number (expanded)\n"
4130 "Large Community-list name\n"
4131 "Delete matching large communities\n")
4132 {
4133 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4134 "large-comm-list", NULL);
4135 }
4136
4137 DEFUN (set_ecommunity_rt,
4138 set_ecommunity_rt_cmd,
4139 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
4140 SET_STR
4141 "BGP extended community attribute\n"
4142 "Route Target extended community\n"
4143 "VPN extended community\n")
4144 {
4145 int idx_asn_nn = 3;
4146 int ret;
4147 char *str;
4148
4149 str = argv_concat(argv, argc, idx_asn_nn);
4150 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4151 "extcommunity rt", str);
4152 XFREE(MTYPE_TMP, str);
4153
4154 return ret;
4155 }
4156
4157 DEFUN (no_set_ecommunity_rt,
4158 no_set_ecommunity_rt_cmd,
4159 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
4160 NO_STR
4161 SET_STR
4162 "BGP extended community attribute\n"
4163 "Route Target extended community\n"
4164 "VPN extended community\n")
4165 {
4166 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4167 "extcommunity rt", NULL);
4168 }
4169
4170
4171 DEFUN (set_ecommunity_soo,
4172 set_ecommunity_soo_cmd,
4173 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
4174 SET_STR
4175 "BGP extended community attribute\n"
4176 "Site-of-Origin extended community\n"
4177 "VPN extended community\n")
4178 {
4179 int idx_asn_nn = 3;
4180 int ret;
4181 char *str;
4182
4183 str = argv_concat(argv, argc, idx_asn_nn);
4184 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4185 "extcommunity soo", str);
4186 XFREE(MTYPE_TMP, str);
4187 return ret;
4188 }
4189
4190
4191 DEFUN (no_set_ecommunity_soo,
4192 no_set_ecommunity_soo_cmd,
4193 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
4194 NO_STR
4195 SET_STR
4196 "BGP extended community attribute\n"
4197 "Site-of-Origin extended community\n"
4198 "VPN extended community\n")
4199 {
4200 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4201 "extcommunity soo", NULL);
4202 }
4203
4204
4205 DEFUN (set_origin,
4206 set_origin_cmd,
4207 "set origin <egp|igp|incomplete>",
4208 SET_STR
4209 "BGP origin code\n"
4210 "remote EGP\n"
4211 "local IGP\n"
4212 "unknown heritage\n")
4213 {
4214 int idx_origin = 2;
4215 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
4216 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4217 "origin", "igp");
4218 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
4219 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4220 "origin", "egp");
4221 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
4222 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4223 "origin", "incomplete");
4224
4225 vty_out(vty, "%% Invalid set origin type\n");
4226 return CMD_WARNING_CONFIG_FAILED;
4227 }
4228
4229
4230 DEFUN (no_set_origin,
4231 no_set_origin_cmd,
4232 "no set origin [<egp|igp|incomplete>]",
4233 NO_STR
4234 SET_STR
4235 "BGP origin code\n"
4236 "remote EGP\n"
4237 "local IGP\n"
4238 "unknown heritage\n")
4239 {
4240 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4241 "origin", NULL);
4242 }
4243
4244
4245 DEFUN (set_atomic_aggregate,
4246 set_atomic_aggregate_cmd,
4247 "set atomic-aggregate",
4248 SET_STR
4249 "BGP atomic aggregate attribute\n" )
4250 {
4251 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4252 "atomic-aggregate", NULL);
4253 }
4254
4255 DEFUN (no_set_atomic_aggregate,
4256 no_set_atomic_aggregate_cmd,
4257 "no set atomic-aggregate",
4258 NO_STR
4259 SET_STR
4260 "BGP atomic aggregate attribute\n" )
4261 {
4262 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4263 "atomic-aggregate", NULL);
4264 }
4265
4266 DEFUN (set_aggregator_as,
4267 set_aggregator_as_cmd,
4268 "set aggregator as (1-4294967295) A.B.C.D",
4269 SET_STR
4270 "BGP aggregator attribute\n"
4271 "AS number of aggregator\n"
4272 "AS number\n"
4273 "IP address of aggregator\n")
4274 {
4275 int idx_number = 3;
4276 int idx_ipv4 = 4;
4277 int ret;
4278 struct in_addr address;
4279 char *argstr;
4280
4281 ret = inet_aton(argv[idx_ipv4]->arg, &address);
4282 if (ret == 0) {
4283 vty_out(vty, "Aggregator IP address is invalid\n");
4284 return CMD_WARNING_CONFIG_FAILED;
4285 }
4286
4287 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4288 strlen(argv[idx_number]->arg)
4289 + strlen(argv[idx_ipv4]->arg) + 2);
4290
4291 sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
4292
4293 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4294 "aggregator as", argstr);
4295
4296 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
4297
4298 return ret;
4299 }
4300
4301
4302 DEFUN (no_set_aggregator_as,
4303 no_set_aggregator_as_cmd,
4304 "no set aggregator as [(1-4294967295) A.B.C.D]",
4305 NO_STR
4306 SET_STR
4307 "BGP aggregator attribute\n"
4308 "AS number of aggregator\n"
4309 "AS number\n"
4310 "IP address of aggregator\n")
4311 {
4312 int idx_asn = 4;
4313 int idx_ip = 5;
4314 int ret;
4315 struct in_addr address;
4316 char *argstr;
4317
4318 if (argc <= idx_asn)
4319 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4320 "aggregator as", NULL);
4321
4322 ret = inet_aton(argv[idx_ip]->arg, &address);
4323 if (ret == 0) {
4324 vty_out(vty, "Aggregator IP address is invalid\n");
4325 return CMD_WARNING_CONFIG_FAILED;
4326 }
4327
4328 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4329 strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
4330 + 2);
4331
4332 sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
4333
4334 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4335 "aggregator as", argstr);
4336
4337 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
4338
4339 return ret;
4340 }
4341
4342 DEFUN (match_ipv6_next_hop,
4343 match_ipv6_next_hop_cmd,
4344 "match ipv6 next-hop X:X::X:X",
4345 MATCH_STR
4346 IPV6_STR
4347 "Match IPv6 next-hop address of route\n"
4348 "IPv6 address of next hop\n")
4349 {
4350 int idx_ipv6 = 3;
4351 return bgp_route_match_add(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
4352 RMAP_EVENT_MATCH_ADDED);
4353 }
4354
4355 DEFUN (no_match_ipv6_next_hop,
4356 no_match_ipv6_next_hop_cmd,
4357 "no match ipv6 next-hop X:X::X:X",
4358 NO_STR
4359 MATCH_STR
4360 IPV6_STR
4361 "Match IPv6 next-hop address of route\n"
4362 "IPv6 address of next hop\n")
4363 {
4364 int idx_ipv6 = 4;
4365 return bgp_route_match_delete(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
4366 RMAP_EVENT_MATCH_DELETED);
4367 }
4368
4369
4370 DEFUN (set_ipv6_nexthop_peer,
4371 set_ipv6_nexthop_peer_cmd,
4372 "set ipv6 next-hop peer-address",
4373 SET_STR
4374 IPV6_STR
4375 "Next hop address\n"
4376 "Use peer address (for BGP only)\n")
4377 {
4378 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4379 "ipv6 next-hop peer-address", NULL);
4380 }
4381
4382 DEFUN (no_set_ipv6_nexthop_peer,
4383 no_set_ipv6_nexthop_peer_cmd,
4384 "no set ipv6 next-hop peer-address",
4385 NO_STR
4386 SET_STR
4387 IPV6_STR
4388 "IPv6 next-hop address\n"
4389 "Use peer address (for BGP only)\n")
4390 {
4391 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4392 "ipv6 next-hop peer-address", NULL);
4393 }
4394
4395 DEFUN (set_ipv6_nexthop_prefer_global,
4396 set_ipv6_nexthop_prefer_global_cmd,
4397 "set ipv6 next-hop prefer-global",
4398 SET_STR
4399 IPV6_STR
4400 "IPv6 next-hop address\n"
4401 "Prefer global over link-local if both exist\n")
4402 {
4403 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4404 "ipv6 next-hop prefer-global", NULL);
4405 ;
4406 }
4407
4408 DEFUN (no_set_ipv6_nexthop_prefer_global,
4409 no_set_ipv6_nexthop_prefer_global_cmd,
4410 "no set ipv6 next-hop prefer-global",
4411 NO_STR
4412 SET_STR
4413 IPV6_STR
4414 "IPv6 next-hop address\n"
4415 "Prefer global over link-local if both exist\n")
4416 {
4417 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4418 "ipv6 next-hop prefer-global", NULL);
4419 }
4420
4421 DEFUN (set_ipv6_nexthop_global,
4422 set_ipv6_nexthop_global_cmd,
4423 "set ipv6 next-hop global X:X::X:X",
4424 SET_STR
4425 IPV6_STR
4426 "IPv6 next-hop address\n"
4427 "IPv6 global address\n"
4428 "IPv6 address of next hop\n")
4429 {
4430 int idx_ipv6 = 4;
4431 struct in6_addr addr;
4432 int ret;
4433
4434 ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr);
4435 if (!ret) {
4436 vty_out(vty, "%% Malformed nexthop address\n");
4437 return CMD_WARNING_CONFIG_FAILED;
4438 }
4439 if (IN6_IS_ADDR_UNSPECIFIED(&addr) || IN6_IS_ADDR_LOOPBACK(&addr)
4440 || IN6_IS_ADDR_MULTICAST(&addr) || IN6_IS_ADDR_LINKLOCAL(&addr)) {
4441 vty_out(vty, "%% Invalid global nexthop address\n");
4442 return CMD_WARNING_CONFIG_FAILED;
4443 }
4444
4445 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4446 "ipv6 next-hop global", argv[idx_ipv6]->arg);
4447 }
4448
4449
4450 DEFUN (no_set_ipv6_nexthop_global,
4451 no_set_ipv6_nexthop_global_cmd,
4452 "no set ipv6 next-hop global X:X::X:X",
4453 NO_STR
4454 SET_STR
4455 IPV6_STR
4456 "IPv6 next-hop address\n"
4457 "IPv6 global address\n"
4458 "IPv6 address of next hop\n")
4459 {
4460 int idx_ipv6 = 5;
4461 if (argc <= idx_ipv6)
4462 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4463 "ipv6 next-hop global", NULL);
4464 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4465 "ipv6 next-hop global", argv[idx_ipv6]->arg);
4466 }
4467
4468 #ifdef KEEP_OLD_VPN_COMMANDS
4469 DEFUN (set_vpn_nexthop,
4470 set_vpn_nexthop_cmd,
4471 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
4472 SET_STR
4473 "VPNv4 information\n"
4474 "VPN next-hop address\n"
4475 "IP address of next hop\n"
4476 "VPNv6 information\n"
4477 "VPN next-hop address\n"
4478 "IPv6 address of next hop\n")
4479 {
4480 int idx_ip = 3;
4481 afi_t afi;
4482 int idx = 0;
4483
4484 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
4485 if (afi == AFI_IP)
4486 return generic_set_add(
4487 vty, VTY_GET_CONTEXT(route_map_index),
4488 "ipv4 vpn next-hop", argv[idx_ip]->arg);
4489 else
4490 return generic_set_add(
4491 vty, VTY_GET_CONTEXT(route_map_index),
4492 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4493 }
4494 return CMD_SUCCESS;
4495 }
4496
4497 DEFUN (no_set_vpn_nexthop,
4498 no_set_vpn_nexthop_cmd,
4499 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
4500 NO_STR
4501 SET_STR
4502 "VPNv4 information\n"
4503 "VPN next-hop address\n"
4504 "IP address of next hop\n"
4505 "VPNv6 information\n"
4506 "VPN next-hop address\n"
4507 "IPv6 address of next hop\n")
4508 {
4509 int idx_ip = 4;
4510 char *arg;
4511 afi_t afi;
4512 int idx = 0;
4513
4514 if (argc <= idx_ip)
4515 arg = NULL;
4516 else
4517 arg = argv[idx_ip]->arg;
4518 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
4519 if (afi == AFI_IP)
4520 return generic_set_delete(
4521 vty, VTY_GET_CONTEXT(route_map_index),
4522 "ipv4 vpn next-hop", arg);
4523 else
4524 return generic_set_delete(
4525 vty, VTY_GET_CONTEXT(route_map_index),
4526 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4527 }
4528 return CMD_SUCCESS;
4529 }
4530 #endif /* KEEP_OLD_VPN_COMMANDS */
4531
4532 DEFUN (set_ipx_vpn_nexthop,
4533 set_ipx_vpn_nexthop_cmd,
4534 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
4535 SET_STR
4536 "IPv4 information\n"
4537 "IPv6 information\n"
4538 "VPN information\n"
4539 "VPN next-hop address\n"
4540 "IP address of next hop\n"
4541 "IPv6 address of next hop\n")
4542 {
4543 int idx_ip = 4;
4544 afi_t afi;
4545 int idx = 0;
4546
4547 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
4548 if (afi == AFI_IP)
4549 return generic_set_add(
4550 vty, VTY_GET_CONTEXT(route_map_index),
4551 "ipv4 vpn next-hop", argv[idx_ip]->arg);
4552 else
4553 return generic_set_add(
4554 vty, VTY_GET_CONTEXT(route_map_index),
4555 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4556 }
4557 return CMD_SUCCESS;
4558 }
4559
4560 DEFUN (no_set_ipx_vpn_nexthop,
4561 no_set_ipx_vpn_nexthop_cmd,
4562 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
4563 NO_STR
4564 SET_STR
4565 "IPv4 information\n"
4566 "IPv6 information\n"
4567 "VPN information\n"
4568 "VPN next-hop address\n"
4569 "IP address of next hop\n"
4570 "IPv6 address of next hop\n")
4571 {
4572 int idx_ip = 5;
4573 char *arg;
4574 afi_t afi;
4575 int idx = 0;
4576
4577 if (argc <= idx_ip)
4578 arg = NULL;
4579 else
4580 arg = argv[idx_ip]->arg;
4581 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
4582 if (afi == AFI_IP)
4583 return generic_set_delete(
4584 vty, VTY_GET_CONTEXT(route_map_index),
4585 "ipv4 vpn next-hop", arg);
4586 else
4587 return generic_set_delete(
4588 vty, VTY_GET_CONTEXT(route_map_index),
4589 "ipv6 vpn next-hop", arg);
4590 }
4591 return CMD_SUCCESS;
4592 }
4593
4594 DEFUN (set_originator_id,
4595 set_originator_id_cmd,
4596 "set originator-id A.B.C.D",
4597 SET_STR
4598 "BGP originator ID attribute\n"
4599 "IP address of originator\n")
4600 {
4601 int idx_ipv4 = 2;
4602 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4603 "originator-id", argv[idx_ipv4]->arg);
4604 }
4605
4606
4607 DEFUN (no_set_originator_id,
4608 no_set_originator_id_cmd,
4609 "no set originator-id [A.B.C.D]",
4610 NO_STR
4611 SET_STR
4612 "BGP originator ID attribute\n"
4613 "IP address of originator\n")
4614 {
4615 int idx = 0;
4616 char *arg =
4617 argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
4618
4619 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4620 "originator-id", arg);
4621 }
4622
4623
4624 /* Initialization of route map. */
4625 void bgp_route_map_init(void)
4626 {
4627 route_map_init();
4628
4629 route_map_add_hook(bgp_route_map_add);
4630 route_map_delete_hook(bgp_route_map_delete);
4631 route_map_event_hook(bgp_route_map_event);
4632
4633 route_map_match_interface_hook(generic_match_add);
4634 route_map_no_match_interface_hook(generic_match_delete);
4635
4636 route_map_match_ip_address_hook(generic_match_add);
4637 route_map_no_match_ip_address_hook(generic_match_delete);
4638
4639 route_map_match_ip_address_prefix_list_hook(generic_match_add);
4640 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
4641
4642 route_map_match_ip_next_hop_hook(generic_match_add);
4643 route_map_no_match_ip_next_hop_hook(generic_match_delete);
4644
4645 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
4646 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
4647
4648 route_map_match_ipv6_address_hook(generic_match_add);
4649 route_map_no_match_ipv6_address_hook(generic_match_delete);
4650
4651 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
4652 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
4653
4654 route_map_match_metric_hook(generic_match_add);
4655 route_map_no_match_metric_hook(generic_match_delete);
4656
4657 route_map_match_tag_hook(generic_match_add);
4658 route_map_no_match_tag_hook(generic_match_delete);
4659
4660 route_map_set_ip_nexthop_hook(generic_set_add);
4661 route_map_no_set_ip_nexthop_hook(generic_set_delete);
4662
4663 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
4664 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
4665
4666 route_map_set_metric_hook(generic_set_add);
4667 route_map_no_set_metric_hook(generic_set_delete);
4668
4669 route_map_set_tag_hook(generic_set_add);
4670 route_map_no_set_tag_hook(generic_set_delete);
4671
4672 route_map_install_match(&route_match_peer_cmd);
4673 route_map_install_match(&route_match_local_pref_cmd);
4674 route_map_install_match(&route_match_ip_address_cmd);
4675 route_map_install_match(&route_match_ip_next_hop_cmd);
4676 route_map_install_match(&route_match_ip_route_source_cmd);
4677 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
4678 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
4679 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
4680 route_map_install_match(&route_match_aspath_cmd);
4681 route_map_install_match(&route_match_community_cmd);
4682 route_map_install_match(&route_match_lcommunity_cmd);
4683 route_map_install_match(&route_match_ecommunity_cmd);
4684 route_map_install_match(&route_match_local_pref_cmd);
4685 route_map_install_match(&route_match_metric_cmd);
4686 route_map_install_match(&route_match_origin_cmd);
4687 route_map_install_match(&route_match_probability_cmd);
4688 route_map_install_match(&route_match_interface_cmd);
4689 route_map_install_match(&route_match_tag_cmd);
4690 route_map_install_match(&route_match_mac_address_cmd);
4691 route_map_install_match(&route_match_evpn_vni_cmd);
4692 route_map_install_match(&route_match_evpn_route_type_cmd);
4693 route_map_install_match(&route_match_evpn_default_route_cmd);
4694
4695 route_map_install_set(&route_set_ip_nexthop_cmd);
4696 route_map_install_set(&route_set_local_pref_cmd);
4697 route_map_install_set(&route_set_weight_cmd);
4698 route_map_install_set(&route_set_label_index_cmd);
4699 route_map_install_set(&route_set_metric_cmd);
4700 route_map_install_set(&route_set_aspath_prepend_cmd);
4701 route_map_install_set(&route_set_aspath_exclude_cmd);
4702 route_map_install_set(&route_set_origin_cmd);
4703 route_map_install_set(&route_set_atomic_aggregate_cmd);
4704 route_map_install_set(&route_set_aggregator_as_cmd);
4705 route_map_install_set(&route_set_community_cmd);
4706 route_map_install_set(&route_set_community_delete_cmd);
4707 route_map_install_set(&route_set_lcommunity_cmd);
4708 route_map_install_set(&route_set_lcommunity_delete_cmd);
4709 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
4710 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
4711 route_map_install_set(&route_set_originator_id_cmd);
4712 route_map_install_set(&route_set_ecommunity_rt_cmd);
4713 route_map_install_set(&route_set_ecommunity_soo_cmd);
4714 route_map_install_set(&route_set_tag_cmd);
4715 route_map_install_set(&route_set_label_index_cmd);
4716
4717 install_element(RMAP_NODE, &match_peer_cmd);
4718 install_element(RMAP_NODE, &match_peer_local_cmd);
4719 install_element(RMAP_NODE, &no_match_peer_cmd);
4720 install_element(RMAP_NODE, &match_ip_route_source_cmd);
4721 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
4722 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4723 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
4724 install_element(RMAP_NODE, &match_mac_address_cmd);
4725 install_element(RMAP_NODE, &no_match_mac_address_cmd);
4726 install_element(RMAP_NODE, &match_evpn_vni_cmd);
4727 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
4728 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
4729 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
4730 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
4731 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
4732
4733 install_element(RMAP_NODE, &match_aspath_cmd);
4734 install_element(RMAP_NODE, &no_match_aspath_cmd);
4735 install_element(RMAP_NODE, &match_local_pref_cmd);
4736 install_element(RMAP_NODE, &no_match_local_pref_cmd);
4737 install_element(RMAP_NODE, &match_community_cmd);
4738 install_element(RMAP_NODE, &no_match_community_cmd);
4739 install_element(RMAP_NODE, &match_lcommunity_cmd);
4740 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
4741 install_element(RMAP_NODE, &match_ecommunity_cmd);
4742 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
4743 install_element(RMAP_NODE, &match_origin_cmd);
4744 install_element(RMAP_NODE, &no_match_origin_cmd);
4745 install_element(RMAP_NODE, &match_probability_cmd);
4746 install_element(RMAP_NODE, &no_match_probability_cmd);
4747
4748 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
4749 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
4750 install_element(RMAP_NODE, &set_local_pref_cmd);
4751 install_element(RMAP_NODE, &no_set_local_pref_cmd);
4752 install_element(RMAP_NODE, &set_weight_cmd);
4753 install_element(RMAP_NODE, &set_label_index_cmd);
4754 install_element(RMAP_NODE, &no_set_weight_cmd);
4755 install_element(RMAP_NODE, &no_set_label_index_cmd);
4756 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
4757 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
4758 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
4759 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
4760 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
4761 install_element(RMAP_NODE, &set_origin_cmd);
4762 install_element(RMAP_NODE, &no_set_origin_cmd);
4763 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
4764 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
4765 install_element(RMAP_NODE, &set_aggregator_as_cmd);
4766 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
4767 install_element(RMAP_NODE, &set_community_cmd);
4768 install_element(RMAP_NODE, &set_community_none_cmd);
4769 install_element(RMAP_NODE, &no_set_community_cmd);
4770 install_element(RMAP_NODE, &set_community_delete_cmd);
4771 install_element(RMAP_NODE, &no_set_community_delete_cmd);
4772 install_element(RMAP_NODE, &set_lcommunity_cmd);
4773 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
4774 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
4775 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
4776 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
4777 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
4778 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
4779 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4780 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
4781 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
4782 #ifdef KEEP_OLD_VPN_COMMANDS
4783 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
4784 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
4785 #endif /* KEEP_OLD_VPN_COMMANDS */
4786 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
4787 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
4788 install_element(RMAP_NODE, &set_originator_id_cmd);
4789 install_element(RMAP_NODE, &no_set_originator_id_cmd);
4790
4791 route_map_install_match(&route_match_ipv6_address_cmd);
4792 route_map_install_match(&route_match_ipv6_next_hop_cmd);
4793 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
4794 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
4795 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
4796 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
4797 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
4798
4799 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
4800 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
4801 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
4802 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
4803 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
4804 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
4805 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
4806 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
4807 }
4808
4809 void bgp_route_map_terminate(void)
4810 {
4811 /* ToDo: Cleanup all the used memory */
4812 route_map_finish();
4813 }