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