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