]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
2f7d50541ed2d3546f8d7232ab802ac65f85b700
[mirror_frr.git] / zebra / zebra_routemap.c
1 /* zebra routemap.
2 * Copyright (C) 2006 IBM Corporation
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 "memory.h"
24 #include "zebra_memory.h"
25 #include "prefix.h"
26 #include "rib.h"
27 #include "vty.h"
28 #include "routemap.h"
29 #include "command.h"
30 #include "filter.h"
31 #include "plist.h"
32 #include "nexthop.h"
33 #include "vrf.h"
34 #include "frrstr.h"
35
36 #include "zebra/zebra_router.h"
37 #include "zebra/redistribute.h"
38 #include "zebra/debug.h"
39 #include "zebra/zebra_rnh.h"
40 #include "zebra/zebra_routemap.h"
41
42 #ifndef VTYSH_EXTRACT_PL
43 #include "zebra/zebra_routemap_clippy.c"
44 #endif
45
46 static uint32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
47 static struct thread *zebra_t_rmap_update = NULL;
48 char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
49
50 struct nh_rmap_obj {
51 struct nexthop *nexthop;
52 vrf_id_t vrf_id;
53 uint32_t source_protocol;
54 uint8_t instance;
55 int metric;
56 route_tag_t tag;
57 };
58
59 static void zebra_route_map_set_delay_timer(uint32_t value);
60
61
62 /* Add zebra route map rule */
63 static int zebra_route_match_add(struct vty *vty, const char *command,
64 const char *arg, route_map_event_t type)
65 {
66 VTY_DECLVAR_CONTEXT(route_map_index, index);
67 int ret;
68 int retval = CMD_SUCCESS;
69
70 ret = route_map_add_match(index, command, arg, type);
71 switch (ret) {
72 case RMAP_RULE_MISSING:
73 vty_out(vty, "%% Zebra Can't find rule.\n");
74 retval = CMD_WARNING_CONFIG_FAILED;
75 break;
76 case RMAP_COMPILE_ERROR:
77 vty_out(vty, "%% Zebra Argument is malformed.\n");
78 retval = CMD_WARNING_CONFIG_FAILED;
79 break;
80 case RMAP_COMPILE_SUCCESS:
81 if (type != RMAP_EVENT_MATCH_ADDED) {
82 route_map_upd8_dependency(type, arg, index->map->name);
83 }
84 break;
85 }
86
87 return retval;
88 }
89
90 /* Delete zebra route map rule. */
91 static int zebra_route_match_delete(struct vty *vty, const char *command,
92 const char *arg, route_map_event_t type)
93 {
94 VTY_DECLVAR_CONTEXT(route_map_index, index);
95 int ret;
96 int retval = CMD_SUCCESS;
97 char *dep_name = NULL;
98 const char *tmpstr;
99 char *rmap_name = NULL;
100
101 if (type != RMAP_EVENT_MATCH_DELETED) {
102 /* ignore the mundane, the types without any dependency */
103 if (arg == NULL) {
104 if ((tmpstr = route_map_get_match_arg(index, command))
105 != NULL)
106 dep_name =
107 XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
108 } else {
109 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
110 }
111 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
112 }
113
114 ret = route_map_delete_match(index, command, arg);
115 switch (ret) {
116 case RMAP_RULE_MISSING:
117 vty_out(vty, "%% Zebra Can't find rule.\n");
118 retval = CMD_WARNING_CONFIG_FAILED;
119 break;
120 case RMAP_COMPILE_ERROR:
121 vty_out(vty, "%% Zebra Argument is malformed.\n");
122 retval = CMD_WARNING_CONFIG_FAILED;
123 break;
124 case RMAP_COMPILE_SUCCESS:
125 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
126 route_map_upd8_dependency(type, dep_name, rmap_name);
127 break;
128 }
129
130 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
131 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
132
133 return retval;
134 }
135
136 /* 'match tag TAG'
137 * Match function return 1 if match is success else return 0
138 */
139 static route_map_result_t route_match_tag(void *rule,
140 const struct prefix *prefix,
141 route_map_object_t type, void *object)
142 {
143 route_tag_t *tag;
144 struct nh_rmap_obj *nh_data;
145
146 if (type == RMAP_ZEBRA) {
147 tag = rule;
148 nh_data = object;
149
150 if (nh_data->tag == *tag)
151 return RMAP_MATCH;
152 }
153 return RMAP_NOMATCH;
154 }
155
156 /* Route map commands for tag matching */
157 static struct route_map_rule_cmd route_match_tag_cmd = {
158 "tag", route_match_tag, route_map_rule_tag_compile,
159 route_map_rule_tag_free,
160 };
161
162
163 /* `match interface IFNAME' */
164 /* Match function return 1 if match is success else return zero. */
165 static route_map_result_t route_match_interface(void *rule,
166 const struct prefix *prefix,
167 route_map_object_t type,
168 void *object)
169 {
170 struct nh_rmap_obj *nh_data;
171 char *ifname = rule;
172 ifindex_t ifindex;
173
174 if (type == RMAP_ZEBRA) {
175 if (strcasecmp(ifname, "any") == 0)
176 return RMAP_MATCH;
177 nh_data = object;
178 if (!nh_data || !nh_data->nexthop)
179 return RMAP_NOMATCH;
180 ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
181 if (ifindex == 0)
182 return RMAP_NOMATCH;
183 if (nh_data->nexthop->ifindex == ifindex)
184 return RMAP_MATCH;
185 }
186 return RMAP_NOMATCH;
187 }
188
189 /* Route map `match interface' match statement. `arg' is IFNAME value */
190 static void *route_match_interface_compile(const char *arg)
191 {
192 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
193 }
194
195 /* Free route map's compiled `match interface' value. */
196 static void route_match_interface_free(void *rule)
197 {
198 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
199 }
200
201 static void show_vrf_proto_rm(struct vty *vty, struct zebra_vrf *zvrf,
202 int af_type)
203 {
204 int i;
205
206 vty_out(vty, "Protocol : route-map\n");
207 vty_out(vty, "------------------------\n");
208
209 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
210 if (PROTO_RM_NAME(zvrf, af_type, i))
211 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
212 PROTO_RM_NAME(zvrf, af_type, i));
213 else
214 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
215 }
216
217 if (PROTO_RM_NAME(zvrf, af_type, i))
218 vty_out(vty, "%-10s : %-10s\n", "any",
219 PROTO_RM_NAME(zvrf, af_type, i));
220 else
221 vty_out(vty, "%-10s : none\n", "any");
222 }
223
224 static void show_vrf_nht_rm(struct vty *vty, struct zebra_vrf *zvrf,
225 int af_type)
226 {
227 int i;
228
229 vty_out(vty, "Protocol : route-map\n");
230 vty_out(vty, "------------------------\n");
231
232 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
233 if (NHT_RM_NAME(zvrf, af_type, i))
234 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
235 NHT_RM_NAME(zvrf, af_type, i));
236 else
237 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
238 }
239
240 if (NHT_RM_NAME(zvrf, af_type, i))
241 vty_out(vty, "%-10s : %-10s\n", "any",
242 NHT_RM_NAME(zvrf, af_type, i));
243 else
244 vty_out(vty, "%-10s : none\n", "any");
245 }
246
247 static int show_proto_rm(struct vty *vty, int af_type, const char *vrf_all,
248 const char *vrf_name)
249 {
250 struct zebra_vrf *zvrf;
251
252 if (vrf_all) {
253 struct vrf *vrf;
254
255 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
256 zvrf = (struct zebra_vrf *)vrf->info;
257 if (zvrf == NULL)
258 continue;
259 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
260 show_vrf_proto_rm(vty, zvrf, af_type);
261 }
262 } else {
263 vrf_id_t vrf_id = VRF_DEFAULT;
264
265 if (vrf_name)
266 VRF_GET_ID(vrf_id, vrf_name, false);
267
268 zvrf = zebra_vrf_lookup_by_id(vrf_id);
269 if (!zvrf)
270 return CMD_SUCCESS;
271
272 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
273 show_vrf_proto_rm(vty, zvrf, af_type);
274 }
275
276 return CMD_SUCCESS;
277 }
278
279 static int show_nht_rm(struct vty *vty, int af_type, const char *vrf_all,
280 const char *vrf_name)
281 {
282 struct zebra_vrf *zvrf;
283
284 if (vrf_all) {
285 struct vrf *vrf;
286
287 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
288 zvrf = (struct zebra_vrf *)vrf->info;
289 if (zvrf == NULL)
290 continue;
291
292 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
293 show_vrf_nht_rm(vty, zvrf, af_type);
294 }
295 } else {
296 vrf_id_t vrf_id = VRF_DEFAULT;
297
298 if (vrf_name)
299 VRF_GET_ID(vrf_id, vrf_name, false);
300
301 zvrf = zebra_vrf_lookup_by_id(vrf_id);
302 if (!zvrf)
303 return CMD_SUCCESS;
304
305 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
306 show_vrf_nht_rm(vty, zvrf, af_type);
307 }
308
309 return CMD_SUCCESS;
310 }
311
312 /* Route map commands for interface matching */
313 struct route_map_rule_cmd route_match_interface_cmd = {
314 "interface", route_match_interface, route_match_interface_compile,
315 route_match_interface_free};
316
317 static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap,
318 int rtype, afi_t afi, safi_t safi)
319 {
320 struct route_table *table;
321
322 if (PROTO_RM_NAME(zvrf, afi, rtype)) {
323 if (strcmp(PROTO_RM_NAME(zvrf, afi, rtype), rmap) == 0)
324 return CMD_SUCCESS;
325
326 XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
327 }
328 route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
329 PROTO_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
330 PROTO_RM_MAP(zvrf, afi, rtype) =
331 route_map_lookup_by_name(PROTO_RM_NAME(zvrf, afi, rtype));
332 route_map_counter_increment(PROTO_RM_MAP(zvrf, afi, rtype));
333
334 if (PROTO_RM_MAP(zvrf, afi, rtype)) {
335
336 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
337 zlog_debug(
338 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
339 zvrf->vrf->vrf_id, rtype);
340 /* Process routes of interested address-families. */
341 table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
342 if (table)
343 rib_update_table(table, RIB_UPDATE_RMAP_CHANGE);
344 }
345
346 return CMD_SUCCESS;
347 }
348
349 static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap,
350 int rtype, afi_t afi, safi_t safi)
351 {
352 struct route_table *table;
353
354 if (!PROTO_RM_NAME(zvrf, afi, rtype))
355 return CMD_SUCCESS;
356
357 if (!rmap || strcmp(rmap, PROTO_RM_NAME(zvrf, afi, rtype)) == 0) {
358
359 route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
360 if (PROTO_RM_MAP(zvrf, afi, rtype)) {
361 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
362 zlog_debug(
363 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
364 zvrf->vrf->vrf_id, rtype);
365 PROTO_RM_MAP(zvrf, afi, rtype) = NULL;
366
367 /* Process routes of interested address-families. */
368 table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
369 if (table)
370 rib_update_table(table, RIB_UPDATE_RMAP_CHANGE);
371 }
372 XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
373 }
374 return CMD_SUCCESS;
375 }
376
377 static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
378 int afi)
379 {
380
381 if (NHT_RM_NAME(zvrf, afi, rtype)) {
382 if (strcmp(NHT_RM_NAME(zvrf, afi, rtype), rmap) == 0)
383 return CMD_SUCCESS;
384
385 XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
386 }
387 route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
388 NHT_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
389 NHT_RM_MAP(zvrf, afi, rtype) =
390 route_map_lookup_by_name(NHT_RM_NAME(zvrf, afi, rtype));
391 route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype));
392
393 if (NHT_RM_MAP(zvrf, afi, rtype))
394 zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL);
395
396 return CMD_SUCCESS;
397 }
398
399 static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
400 int afi)
401 {
402
403 if (!NHT_RM_NAME(zvrf, afi, rtype))
404 return CMD_SUCCESS;
405
406 if (!rmap || strcmp(rmap, NHT_RM_NAME(zvrf, afi, rtype)) == 0) {
407 route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
408 if (NHT_RM_MAP(zvrf, afi, rtype)) {
409 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
410 zlog_debug(
411 "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
412 zvrf->vrf->vrf_id, rtype);
413 NHT_RM_MAP(zvrf, afi, rtype) = NULL;
414
415 zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE,
416 NULL);
417 }
418 XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
419 }
420 return CMD_SUCCESS;
421 }
422
423 DEFUN (match_ip_address_prefix_len,
424 match_ip_address_prefix_len_cmd,
425 "match ip address prefix-len (0-32)",
426 MATCH_STR
427 IP_STR
428 "Match prefix length of ip address\n"
429 "Match prefix length of ip address\n"
430 "Prefix length\n")
431 {
432 return zebra_route_match_add(vty, "ip address prefix-len", argv[4]->arg,
433 RMAP_EVENT_MATCH_ADDED);
434 }
435
436 DEFUN (no_match_ip_address_prefix_len,
437 no_match_ip_address_prefix_len_cmd,
438 "no match ip address prefix-len [(0-32)]",
439 NO_STR
440 MATCH_STR
441 IP_STR
442 "Match prefix length of ip address\n"
443 "Match prefix length of ip address\n"
444 "Prefix length\n")
445 {
446 char *plen = (argc == 6) ? argv[5]->arg : NULL;
447 return zebra_route_match_delete(vty, "ip address prefix-len", plen,
448 RMAP_EVENT_MATCH_DELETED);
449 }
450
451 DEFUN (match_ipv6_address_prefix_len,
452 match_ipv6_address_prefix_len_cmd,
453 "match ipv6 address prefix-len (0-128)",
454 MATCH_STR
455 IPV6_STR
456 "Match prefix length of ipv6 address\n"
457 "Match prefix length of ipv6 address\n"
458 "Prefix length\n")
459 {
460 return zebra_route_match_add(vty, "ipv6 address prefix-len",
461 argv[4]->arg, RMAP_EVENT_MATCH_ADDED);
462 }
463
464 DEFUN (no_match_ipv6_address_prefix_len,
465 no_match_ipv6_address_prefix_len_cmd,
466 "no match ipv6 address prefix-len [(0-128)]",
467 NO_STR
468 MATCH_STR
469 IPV6_STR
470 "Match prefix length of ip address\n"
471 "Match prefix length of ip address\n"
472 "Prefix length\n")
473 {
474 char *plen = (argc == 6) ? argv[5]->arg : NULL;
475 return zebra_route_match_delete(vty, "ipv6 address prefix-len", plen,
476 RMAP_EVENT_MATCH_DELETED);
477 }
478
479 DEFUN (match_ip_nexthop_prefix_len,
480 match_ip_nexthop_prefix_len_cmd,
481 "match ip next-hop prefix-len (0-32)",
482 MATCH_STR
483 IP_STR
484 "Match prefixlen of nexthop ip address\n"
485 "Match prefixlen of given nexthop\n"
486 "Prefix length\n")
487 {
488 return zebra_route_match_add(vty, "ip next-hop prefix-len",
489 argv[4]->arg, RMAP_EVENT_MATCH_ADDED);
490 }
491
492 DEFUN (no_match_ip_nexthop_prefix_len,
493 no_match_ip_nexthop_prefix_len_cmd,
494 "no match ip next-hop prefix-len [(0-32)]",
495 NO_STR
496 MATCH_STR
497 IP_STR
498 "Match prefixlen of nexthop ip address\n"
499 "Match prefix length of nexthop\n"
500 "Prefix length\n")
501 {
502 char *plen = (argc == 6) ? argv[5]->arg : NULL;
503 return zebra_route_match_delete(vty, "ip next-hop prefix-len", plen,
504 RMAP_EVENT_MATCH_DELETED);
505 }
506
507 DEFUN (match_source_protocol,
508 match_source_protocol_cmd,
509 "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>",
510 MATCH_STR
511 "Match protocol via which the route was learnt\n"
512 "BGP protocol\n"
513 "OSPF protocol\n"
514 "RIP protocol\n"
515 "RIPNG protocol\n"
516 "ISIS protocol\n"
517 "OSPF6 protocol\n"
518 "PIM protocol\n"
519 "NHRP protocol\n"
520 "EIGRP protocol\n"
521 "BABEL protocol\n"
522 "Routes from directly connected peer\n"
523 "Routes from system configuration\n"
524 "Routes from kernel\n"
525 "Statically configured routes\n"
526 "SHARP process\n")
527 {
528 char *proto = argv[2]->text;
529 int i;
530
531 i = proto_name2num(proto);
532 if (i < 0) {
533 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
534 return CMD_WARNING_CONFIG_FAILED;
535 }
536 return zebra_route_match_add(vty, "source-protocol", proto,
537 RMAP_EVENT_MATCH_ADDED);
538 }
539
540 DEFUN (no_match_source_protocol,
541 no_match_source_protocol_cmd,
542 "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>]",
543 NO_STR
544 MATCH_STR
545 "No match protocol via which the route was learnt\n"
546 "BGP protocol\n"
547 "OSPF protocol\n"
548 "RIP protocol\n"
549 "RIPNG protocol\n"
550 "ISIS protocol\n"
551 "OSPF6 protocol\n"
552 "PIM protocol\n"
553 "NHRP protocol\n"
554 "EIGRP protocol\n"
555 "BABEL protocol\n"
556 "Routes from directly connected peer\n"
557 "Routes from system configuration\n"
558 "Routes from kernel\n"
559 "Statically configured routes\n"
560 "SHARP process\n")
561 {
562 char *proto = (argc == 4) ? argv[3]->text : NULL;
563 return zebra_route_match_delete(vty, "source-protocol", proto,
564 RMAP_EVENT_MATCH_DELETED);
565 }
566
567 DEFUN (match_source_instance,
568 match_source_instance_cmd,
569 "match source-instance (0-255)",
570 MATCH_STR
571 "Match the protocol's instance number\n"
572 "The instance number\n")
573 {
574 char *instance = argv[2]->arg;
575
576 return zebra_route_match_add(vty, "source-instance", instance,
577 RMAP_EVENT_MATCH_ADDED);
578 }
579
580 DEFUN (no_match_source_instance,
581 no_match_source_instance_cmd,
582 "no match source-instance [(0-255)]",
583 NO_STR MATCH_STR
584 "Match the protocol's instance number\n"
585 "The instance number\n")
586 {
587 char *instance = (argc == 4) ? argv[3]->arg : NULL;
588
589 return zebra_route_match_delete(vty, "source-instance", instance,
590 RMAP_EVENT_MATCH_ADDED);
591 }
592
593 /* set functions */
594
595 DEFUN (set_src,
596 set_src_cmd,
597 "set src <A.B.C.D|X:X::X:X>",
598 SET_STR
599 "src address for route\n"
600 "IPv4 src address\n"
601 "IPv6 src address\n")
602 {
603 int idx_ip = 2;
604 union g_addr src;
605 struct interface *pif = NULL;
606 int family;
607 struct prefix p;
608 struct vrf *vrf;
609
610 if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) {
611 if (inet_pton(AF_INET6, argv[idx_ip]->arg, &src.ipv6) != 1) {
612 vty_out(vty, "%% not a valid IPv4/v6 address\n");
613 return CMD_WARNING_CONFIG_FAILED;
614 }
615
616 p.family = family = AF_INET6;
617 p.u.prefix6 = src.ipv6;
618 p.prefixlen = IPV6_MAX_BITLEN;
619 } else {
620 p.family = family = AF_INET;
621 p.u.prefix4 = src.ipv4;
622 p.prefixlen = IPV4_MAX_BITLEN;
623 }
624
625 if (!zebra_check_addr(&p)) {
626 vty_out(vty, "%% not a valid source IPv4/v6 address\n");
627 return CMD_WARNING_CONFIG_FAILED;
628 }
629
630 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
631 if (family == AF_INET)
632 pif = if_lookup_exact_address((void *)&src.ipv4,
633 AF_INET, vrf->vrf_id);
634 else if (family == AF_INET6)
635 pif = if_lookup_exact_address((void *)&src.ipv6,
636 AF_INET6, vrf->vrf_id);
637
638 if (pif != NULL)
639 break;
640 }
641
642 if (!pif) {
643 vty_out(vty, "%% not a local address\n");
644 return CMD_WARNING_CONFIG_FAILED;
645 }
646
647 VTY_DECLVAR_CONTEXT(route_map_index, index);
648 return generic_set_add(vty, index, "src", argv[idx_ip]->arg);
649 }
650
651 DEFUN (no_set_src,
652 no_set_src_cmd,
653 "no set src [<A.B.C.D|X:X::X:X>]",
654 NO_STR
655 SET_STR
656 "Source address for route\n"
657 "IPv4 address\n"
658 "IPv6 address\n")
659 {
660 char *ip = (argc == 4) ? argv[3]->arg : NULL;
661 VTY_DECLVAR_CONTEXT(route_map_index, index);
662 return generic_set_delete(vty, index, "src", ip);
663 }
664
665 DEFUN (zebra_route_map_timer,
666 zebra_route_map_timer_cmd,
667 "zebra route-map delay-timer (0-600)",
668 ZEBRA_STR
669 "Set route-map parameters\n"
670 "Time to wait before route-map updates are processed\n"
671 "0 means event-driven updates are disabled\n")
672 {
673 int idx_number = 3;
674 uint32_t rmap_delay_timer;
675
676 rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
677 zebra_route_map_set_delay_timer(rmap_delay_timer);
678
679 return (CMD_SUCCESS);
680 }
681
682 DEFUN (no_zebra_route_map_timer,
683 no_zebra_route_map_timer_cmd,
684 "no zebra route-map delay-timer [(0-600)]",
685 NO_STR
686 ZEBRA_STR
687 "Set route-map parameters\n"
688 "Reset delay-timer to default value, 30 secs\n"
689 "0 means event-driven updates are disabled\n")
690 {
691 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
692
693 return (CMD_SUCCESS);
694 }
695
696 DEFPY (ip_protocol,
697 ip_protocol_cmd,
698 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
699 " $proto route-map ROUTE-MAP$rmap",
700 IP_STR
701 "Filter routing info exchanged between zebra and protocol\n"
702 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
703 "Specify route-map\n"
704 "Route map name\n")
705 {
706 int ret, rtype;
707
708 assert(proto);
709 assert(rmap);
710
711 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
712
713 if (!zvrf)
714 return CMD_WARNING;
715
716 if (strcasecmp(proto, "any") == 0)
717 rtype = ZEBRA_ROUTE_MAX;
718 else
719 rtype = proto_name2num(proto);
720 if (rtype < 0) {
721 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
722 return CMD_WARNING_CONFIG_FAILED;
723 }
724
725 ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
726
727 return ret;
728 }
729
730 DEFPY (no_ip_protocol,
731 no_ip_protocol_cmd,
732 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
733 " $proto [route-map ROUTE-MAP$rmap]",
734 NO_STR
735 IP_STR
736 "Stop filtering routing info between zebra and protocol\n"
737 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
738 "Specify route-map\n"
739 "Route map name\n")
740 {
741 int ret, rtype;
742
743 assert(proto);
744
745 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
746
747 if (!zvrf)
748 return CMD_WARNING;
749
750 if (strcasecmp(proto, "any") == 0)
751 rtype = ZEBRA_ROUTE_MAX;
752 else
753 rtype = proto_name2num(proto);
754 if (rtype < 0) {
755 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
756 return CMD_WARNING_CONFIG_FAILED;
757 }
758
759 ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
760
761 return ret;
762 }
763
764 DEFPY (show_ip_protocol,
765 show_ip_protocol_cmd,
766 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
767 SHOW_STR
768 IP_STR
769 "IP protocol filtering status\n"
770 VRF_FULL_CMD_HELP_STR)
771 {
772 int ret = show_proto_rm(vty, AFI_IP, vrf_all, vrf_name);
773
774 return ret;
775 }
776
777 DEFPY (ipv6_protocol,
778 ipv6_protocol_cmd,
779 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
780 " $proto route-map ROUTE-MAP$rmap",
781 IP6_STR
782 "Filter IPv6 routing info exchanged between zebra and protocol\n"
783 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
784 "Specify route-map\n"
785 "Route map name\n")
786 {
787 int ret, rtype;
788
789 assert(rmap);
790 assert(proto);
791
792 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
793
794 if (!zvrf)
795 return CMD_WARNING;
796
797 if (strcasecmp(proto, "any") == 0)
798 rtype = ZEBRA_ROUTE_MAX;
799 else
800 rtype = proto_name2num(proto);
801 if (rtype < 0) {
802 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
803 return CMD_WARNING_CONFIG_FAILED;
804 }
805
806 ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
807
808 return ret;
809 }
810
811 DEFPY (no_ipv6_protocol,
812 no_ipv6_protocol_cmd,
813 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
814 " $proto [route-map ROUTE-MAP$rmap]",
815 NO_STR
816 IP6_STR
817 "Stop filtering IPv6 routing info between zebra and protocol\n"
818 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
819 "Specify route-map\n"
820 "Route map name\n")
821 {
822 int ret, rtype;
823
824 assert(proto);
825
826 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
827
828 if (!zvrf)
829 return CMD_WARNING;
830
831 if (strcasecmp(proto, "any") == 0)
832 rtype = ZEBRA_ROUTE_MAX;
833 else
834 rtype = proto_name2num(proto);
835 if (rtype < 0) {
836 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
837 return CMD_WARNING_CONFIG_FAILED;
838 }
839
840 ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
841
842 return ret;
843 }
844
845 DEFPY (show_ipv6_protocol,
846 show_ipv6_protocol_cmd,
847 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
848 SHOW_STR
849 IP6_STR
850 "IPv6 protocol filtering status\n"
851 VRF_FULL_CMD_HELP_STR)
852 {
853 int ret = show_proto_rm(vty, AFI_IP6, vrf_all, vrf_name);
854
855 return ret;
856 }
857
858 DEFPY (ip_protocol_nht_rmap,
859 ip_protocol_nht_rmap_cmd,
860 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
861 " $proto route-map ROUTE-MAP$rmap",
862 IP_STR
863 "Filter Next Hop tracking route resolution\n"
864 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
865 "Specify route map\n"
866 "Route map name\n")
867 {
868
869 int ret, rtype;
870
871 assert(proto);
872 assert(rmap);
873
874 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
875
876 if (!zvrf)
877 return CMD_WARNING;
878
879 if (strcasecmp(proto, "any") == 0)
880 rtype = ZEBRA_ROUTE_MAX;
881 else
882 rtype = proto_name2num(proto);
883 if (rtype < 0) {
884 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
885 return CMD_WARNING_CONFIG_FAILED;
886 }
887
888 ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP);
889
890 return ret;
891 }
892
893 DEFPY (no_ip_protocol_nht_rmap,
894 no_ip_protocol_nht_rmap_cmd,
895 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
896 " $proto route-map [ROUTE-MAP$rmap]",
897 NO_STR
898 IP_STR
899 "Filter Next Hop tracking route resolution\n"
900 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
901 "Specify route map\n"
902 "Route map name\n")
903 {
904 int ret, rtype;
905
906 assert(proto);
907
908 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
909
910 if (!zvrf)
911 return CMD_WARNING;
912
913 if (strcasecmp(proto, "any") == 0)
914 rtype = ZEBRA_ROUTE_MAX;
915 else
916 rtype = proto_name2num(proto);
917 if (rtype < 0) {
918 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
919 return CMD_WARNING_CONFIG_FAILED;
920 }
921
922 ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP);
923
924 return ret;
925 }
926
927 DEFPY (show_ip_protocol_nht,
928 show_ip_protocol_nht_cmd,
929 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
930 SHOW_STR
931 IP_STR
932 "IP nexthop tracking table\n"
933 "IP Next Hop tracking filtering status\n"
934 VRF_FULL_CMD_HELP_STR)
935 {
936 int ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name);
937
938 return ret;
939 }
940
941 DEFPY (ipv6_protocol_nht_rmap,
942 ipv6_protocol_nht_rmap_cmd,
943 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
944 " $proto route-map ROUTE-MAP$rmap",
945 IP6_STR
946 "Filter Next Hop tracking route resolution\n"
947 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
948 "Specify route map\n"
949 "Route map name\n")
950 {
951 int ret, rtype;
952
953 assert(rmap);
954 assert(proto);
955
956 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
957
958 if (!zvrf)
959 return CMD_WARNING;
960
961 if (strcasecmp(proto, "any") == 0)
962 rtype = ZEBRA_ROUTE_MAX;
963 else
964 rtype = proto_name2num(proto);
965 if (rtype < 0) {
966 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
967 return CMD_WARNING_CONFIG_FAILED;
968 }
969
970 ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP6);
971
972 return ret;
973 }
974
975 DEFPY (no_ipv6_protocol_nht_rmap,
976 no_ipv6_protocol_nht_rmap_cmd,
977 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
978 " $proto [route-map ROUTE-MAP$rmap]",
979 NO_STR
980 IP6_STR
981 "Filter Next Hop tracking route resolution\n"
982 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
983 "Specify route map\n"
984 "Route map name\n")
985 {
986 int ret, rtype;
987
988 assert(proto);
989
990 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
991
992 if (!zvrf)
993 return CMD_WARNING;
994
995 if (strcasecmp(proto, "any") == 0)
996 rtype = ZEBRA_ROUTE_MAX;
997 else
998 rtype = proto_name2num(proto);
999 if (rtype < 0) {
1000 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
1001 return CMD_WARNING_CONFIG_FAILED;
1002 }
1003
1004 ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP6);
1005
1006 return ret;
1007 }
1008
1009 DEFPY (show_ipv6_protocol_nht,
1010 show_ipv6_protocol_nht_cmd,
1011 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
1012 SHOW_STR
1013 IP6_STR
1014 "Next Hop filtering status\n"
1015 "Route-map\n"
1016 VRF_FULL_CMD_HELP_STR)
1017 {
1018 int ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name);
1019
1020 return ret;
1021 }
1022
1023 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1024
1025 /* `match ip next-hop IP_ACCESS_LIST' */
1026
1027 /* Match function return 1 if match is success else return zero. */
1028 static route_map_result_t route_match_ip_next_hop(void *rule,
1029 const struct prefix *prefix,
1030 route_map_object_t type,
1031 void *object)
1032 {
1033 struct access_list *alist;
1034 struct nh_rmap_obj *nh_data;
1035 struct prefix_ipv4 p;
1036
1037 if (type == RMAP_ZEBRA) {
1038 nh_data = object;
1039 if (!nh_data)
1040 return RMAP_DENYMATCH;
1041
1042 switch (nh_data->nexthop->type) {
1043 case NEXTHOP_TYPE_IFINDEX:
1044 /* Interface routes can't match ip next-hop */
1045 return RMAP_NOMATCH;
1046 case NEXTHOP_TYPE_IPV4_IFINDEX:
1047 case NEXTHOP_TYPE_IPV4:
1048 p.family = AF_INET;
1049 p.prefix = nh_data->nexthop->gate.ipv4;
1050 p.prefixlen = IPV4_MAX_BITLEN;
1051 break;
1052 default:
1053 return RMAP_NOMATCH;
1054 }
1055 alist = access_list_lookup(AFI_IP, (char *)rule);
1056 if (alist == NULL)
1057 return RMAP_NOMATCH;
1058
1059 return (access_list_apply(alist, &p) == FILTER_DENY
1060 ? RMAP_NOMATCH
1061 : RMAP_MATCH);
1062 }
1063 return RMAP_NOMATCH;
1064 }
1065
1066 /* Route map `ip next-hop' match statement. `arg' should be
1067 access-list name. */
1068 static void *route_match_ip_next_hop_compile(const char *arg)
1069 {
1070 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1071 }
1072
1073 /* Free route map's compiled `. */
1074 static void route_match_ip_next_hop_free(void *rule)
1075 {
1076 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1077 }
1078
1079 /* Route map commands for ip next-hop matching. */
1080 static struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
1081 "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile,
1082 route_match_ip_next_hop_free};
1083
1084 /* `match ip next-hop prefix-list PREFIX_LIST' */
1085
1086 static route_map_result_t
1087 route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
1088 route_map_object_t type, void *object)
1089 {
1090 struct prefix_list *plist;
1091 struct nh_rmap_obj *nh_data;
1092 struct prefix_ipv4 p;
1093
1094 if (type == RMAP_ZEBRA) {
1095 nh_data = (struct nh_rmap_obj *)object;
1096 if (!nh_data)
1097 return RMAP_DENYMATCH;
1098
1099 switch (nh_data->nexthop->type) {
1100 case NEXTHOP_TYPE_IFINDEX:
1101 /* Interface routes can't match ip next-hop */
1102 return RMAP_NOMATCH;
1103 case NEXTHOP_TYPE_IPV4_IFINDEX:
1104 case NEXTHOP_TYPE_IPV4:
1105 p.family = AF_INET;
1106 p.prefix = nh_data->nexthop->gate.ipv4;
1107 p.prefixlen = IPV4_MAX_BITLEN;
1108 break;
1109 default:
1110 return RMAP_NOMATCH;
1111 }
1112 plist = prefix_list_lookup(AFI_IP, (char *)rule);
1113 if (plist == NULL)
1114 return RMAP_NOMATCH;
1115
1116 return (prefix_list_apply(plist, &p) == PREFIX_DENY
1117 ? RMAP_NOMATCH
1118 : RMAP_MATCH);
1119 }
1120 return RMAP_NOMATCH;
1121 }
1122
1123 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
1124 {
1125 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1126 }
1127
1128 static void route_match_ip_next_hop_prefix_list_free(void *rule)
1129 {
1130 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1131 }
1132
1133 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
1134 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list,
1135 route_match_ip_next_hop_prefix_list_compile,
1136 route_match_ip_next_hop_prefix_list_free};
1137
1138 /* `match ip address IP_ACCESS_LIST' */
1139
1140 /* Match function should return 1 if match is success else return
1141 zero. */
1142 static route_map_result_t route_match_address(afi_t afi, void *rule,
1143 const struct prefix *prefix,
1144 route_map_object_t type,
1145 void *object)
1146 {
1147 struct access_list *alist;
1148
1149 if (type == RMAP_ZEBRA) {
1150 alist = access_list_lookup(afi, (char *)rule);
1151 if (alist == NULL)
1152 return RMAP_NOMATCH;
1153
1154 return (access_list_apply(alist, prefix) == FILTER_DENY
1155 ? RMAP_NOMATCH
1156 : RMAP_MATCH);
1157 }
1158 return RMAP_NOMATCH;
1159 }
1160
1161 static route_map_result_t route_match_ip_address(void *rule,
1162 const struct prefix *prefix,
1163 route_map_object_t type,
1164 void *object)
1165 {
1166 return route_match_address(AFI_IP, rule, prefix, type, object);
1167 }
1168
1169 static route_map_result_t route_match_ipv6_address(void *rule,
1170 const struct prefix *prefix,
1171 route_map_object_t type,
1172 void *object)
1173
1174 {
1175 return route_match_address(AFI_IP6, rule, prefix, type, object);
1176 }
1177
1178 /* Route map `ip address' match statement. `arg' should be
1179 access-list name. */
1180 static void *route_match_address_compile(const char *arg)
1181 {
1182 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1183 }
1184
1185 /* Free route map's compiled `ip address' value. */
1186 static void route_match_address_free(void *rule)
1187 {
1188 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1189 }
1190
1191 /* Route map commands for ip address matching. */
1192 static struct route_map_rule_cmd route_match_ip_address_cmd = {
1193 "ip address", route_match_ip_address, route_match_address_compile,
1194 route_match_address_free};
1195
1196 /* Route map commands for ipv6 address matching. */
1197 static struct route_map_rule_cmd route_match_ipv6_address_cmd = {
1198 "ipv6 address", route_match_ipv6_address, route_match_address_compile,
1199 route_match_address_free};
1200
1201 /* `match ip address prefix-list PREFIX_LIST' */
1202
1203 static route_map_result_t
1204 route_match_address_prefix_list(void *rule, const struct prefix *prefix,
1205 route_map_object_t type, void *object, afi_t afi)
1206 {
1207 struct prefix_list *plist;
1208
1209 if (type == RMAP_ZEBRA) {
1210 plist = prefix_list_lookup(afi, (char *)rule);
1211 if (plist == NULL)
1212 return RMAP_NOMATCH;
1213
1214 return (prefix_list_apply(plist, prefix) == PREFIX_DENY
1215 ? RMAP_NOMATCH
1216 : RMAP_MATCH);
1217 }
1218 return RMAP_NOMATCH;
1219 }
1220
1221 static route_map_result_t
1222 route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
1223 route_map_object_t type, void *object)
1224 {
1225 return (route_match_address_prefix_list(rule, prefix, type, object,
1226 AFI_IP));
1227 }
1228
1229 static void *route_match_address_prefix_list_compile(const char *arg)
1230 {
1231 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1232 }
1233
1234 static void route_match_address_prefix_list_free(void *rule)
1235 {
1236 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1237 }
1238
1239 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
1240 "ip address prefix-list", route_match_ip_address_prefix_list,
1241 route_match_address_prefix_list_compile,
1242 route_match_address_prefix_list_free};
1243
1244 static route_map_result_t
1245 route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1246 route_map_object_t type, void *object)
1247 {
1248 return (route_match_address_prefix_list(rule, prefix, type, object,
1249 AFI_IP6));
1250 }
1251
1252 static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
1253 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
1254 route_match_address_prefix_list_compile,
1255 route_match_address_prefix_list_free};
1256
1257 /* `match ipv6 next-hop type <TYPE>' */
1258
1259 static route_map_result_t
1260 route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
1261 route_map_object_t type, void *object)
1262 {
1263 struct nh_rmap_obj *nh_data;
1264
1265 if (type == RMAP_ZEBRA && prefix->family == AF_INET6) {
1266 nh_data = (struct nh_rmap_obj *)object;
1267 if (!nh_data)
1268 return RMAP_DENYMATCH;
1269
1270 if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
1271 return RMAP_MATCH;
1272 }
1273 return RMAP_NOMATCH;
1274 }
1275
1276 static void *route_match_ipv6_next_hop_type_compile(const char *arg)
1277 {
1278 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1279 }
1280
1281 static void route_match_ipv6_next_hop_type_free(void *rule)
1282 {
1283 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1284 }
1285
1286 struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = {
1287 "ipv6 next-hop type", route_match_ipv6_next_hop_type,
1288 route_match_ipv6_next_hop_type_compile,
1289 route_match_ipv6_next_hop_type_free};
1290
1291 /* `match ip address prefix-len PREFIXLEN' */
1292
1293 static route_map_result_t
1294 route_match_address_prefix_len(void *rule, const struct prefix *prefix,
1295 route_map_object_t type, void *object)
1296 {
1297 uint32_t *prefixlen = (uint32_t *)rule;
1298
1299 if (type == RMAP_ZEBRA) {
1300 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH
1301 : RMAP_NOMATCH);
1302 }
1303 return RMAP_NOMATCH;
1304 }
1305
1306 static void *route_match_address_prefix_len_compile(const char *arg)
1307 {
1308 uint32_t *prefix_len;
1309 char *endptr = NULL;
1310 unsigned long tmpval;
1311
1312 /* prefix len value shoud be integer. */
1313 if (!all_digit(arg))
1314 return NULL;
1315
1316 errno = 0;
1317 tmpval = strtoul(arg, &endptr, 10);
1318 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1319 return NULL;
1320
1321 prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1322
1323 *prefix_len = tmpval;
1324 return prefix_len;
1325 }
1326
1327 static void route_match_address_prefix_len_free(void *rule)
1328 {
1329 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1330 }
1331
1332 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = {
1333 "ip address prefix-len", route_match_address_prefix_len,
1334 route_match_address_prefix_len_compile,
1335 route_match_address_prefix_len_free};
1336
1337 static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd = {
1338 "ipv6 address prefix-len", route_match_address_prefix_len,
1339 route_match_address_prefix_len_compile,
1340 route_match_address_prefix_len_free};
1341
1342 /* `match ip nexthop prefix-len PREFIXLEN' */
1343
1344 static route_map_result_t
1345 route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
1346 route_map_object_t type, void *object)
1347 {
1348 uint32_t *prefixlen = (uint32_t *)rule;
1349 struct nh_rmap_obj *nh_data;
1350 struct prefix_ipv4 p;
1351
1352 if (type == RMAP_ZEBRA) {
1353 nh_data = (struct nh_rmap_obj *)object;
1354 if (!nh_data || !nh_data->nexthop)
1355 return RMAP_DENYMATCH;
1356
1357 switch (nh_data->nexthop->type) {
1358 case NEXTHOP_TYPE_IFINDEX:
1359 /* Interface routes can't match ip next-hop */
1360 return RMAP_NOMATCH;
1361 case NEXTHOP_TYPE_IPV4_IFINDEX:
1362 case NEXTHOP_TYPE_IPV4:
1363 p.family = AF_INET;
1364 p.prefix = nh_data->nexthop->gate.ipv4;
1365 p.prefixlen = IPV4_MAX_BITLEN;
1366 break;
1367 default:
1368 return RMAP_NOMATCH;
1369 }
1370 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH
1371 : RMAP_NOMATCH);
1372 }
1373 return RMAP_NOMATCH;
1374 }
1375
1376 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = {
1377 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len,
1378 route_match_address_prefix_len_compile, /* reuse */
1379 route_match_address_prefix_len_free /* reuse */
1380 };
1381
1382 /* `match ip next-hop type <blackhole>' */
1383
1384 static route_map_result_t
1385 route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
1386 route_map_object_t type, void *object)
1387 {
1388 struct nh_rmap_obj *nh_data;
1389
1390 if (type == RMAP_ZEBRA && prefix->family == AF_INET) {
1391 nh_data = (struct nh_rmap_obj *)object;
1392 if (!nh_data)
1393 return RMAP_DENYMATCH;
1394
1395 if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
1396 return RMAP_MATCH;
1397 }
1398 return RMAP_NOMATCH;
1399 }
1400
1401 static void *route_match_ip_next_hop_type_compile(const char *arg)
1402 {
1403 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1404 }
1405
1406 static void route_match_ip_next_hop_type_free(void *rule)
1407 {
1408 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1409 }
1410
1411 static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
1412 "ip next-hop type", route_match_ip_next_hop_type,
1413 route_match_ip_next_hop_type_compile,
1414 route_match_ip_next_hop_type_free};
1415
1416 /* `match source-protocol PROTOCOL' */
1417
1418 static route_map_result_t route_match_source_protocol(void *rule,
1419 const struct prefix *p,
1420 route_map_object_t type,
1421 void *object)
1422 {
1423 uint32_t *rib_type = (uint32_t *)rule;
1424 struct nh_rmap_obj *nh_data;
1425
1426 if (type == RMAP_ZEBRA) {
1427 nh_data = (struct nh_rmap_obj *)object;
1428 if (!nh_data)
1429 return RMAP_DENYMATCH;
1430
1431 return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
1432 : RMAP_NOMATCH);
1433 }
1434 return RMAP_NOMATCH;
1435 }
1436
1437 static void *route_match_source_protocol_compile(const char *arg)
1438 {
1439 uint32_t *rib_type;
1440 int i;
1441
1442 i = proto_name2num(arg);
1443 rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1444
1445 *rib_type = i;
1446
1447 return rib_type;
1448 }
1449
1450 static void route_match_source_protocol_free(void *rule)
1451 {
1452 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1453 }
1454
1455 static struct route_map_rule_cmd route_match_source_protocol_cmd = {
1456 "source-protocol", route_match_source_protocol,
1457 route_match_source_protocol_compile, route_match_source_protocol_free};
1458
1459 /* `source-instance` */
1460 static route_map_result_t route_match_source_instance(void *rule,
1461 const struct prefix *p,
1462 route_map_object_t type,
1463 void *object)
1464 {
1465 uint8_t *instance = (uint8_t *)rule;
1466 struct nh_rmap_obj *nh_data;
1467
1468 if (type != RMAP_ZEBRA)
1469 return RMAP_NOMATCH;
1470
1471 nh_data = (struct nh_rmap_obj *)object;
1472 if (!nh_data)
1473 return RMAP_DENYMATCH;
1474
1475 return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
1476 }
1477
1478 static void *route_match_source_instance_compile(const char *arg)
1479 {
1480 uint8_t *instance;
1481 int i;
1482
1483 i = atoi(arg);
1484 instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1485
1486 *instance = i;
1487
1488 return instance;
1489 }
1490
1491 static void route_match_source_instance_free(void *rule)
1492 {
1493 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1494 }
1495
1496 static struct route_map_rule_cmd route_match_source_instance_cmd = {
1497 "source-instance", route_match_source_instance,
1498 route_match_source_instance_compile, route_match_source_instance_free};
1499
1500 /* `set src A.B.C.D' */
1501
1502 /* Set src. */
1503 static route_map_result_t route_set_src(void *rule, const struct prefix *prefix,
1504 route_map_object_t type, void *object)
1505 {
1506 struct nh_rmap_obj *nh_data;
1507
1508 if (type == RMAP_ZEBRA) {
1509 nh_data = (struct nh_rmap_obj *)object;
1510 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1511 }
1512 return RMAP_OKAY;
1513 }
1514
1515 /* set src compilation. */
1516 static void *route_set_src_compile(const char *arg)
1517 {
1518 union g_addr src, *psrc;
1519
1520 if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1)
1521 || (inet_pton(AF_INET, arg, &src.ipv4) == 1)) {
1522 psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr));
1523 *psrc = src;
1524 return psrc;
1525 }
1526 return NULL;
1527 }
1528
1529 /* Free route map's compiled `set src' value. */
1530 static void route_set_src_free(void *rule)
1531 {
1532 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1533 }
1534
1535 /* Set src rule structure. */
1536 static struct route_map_rule_cmd route_set_src_cmd = {
1537 "src", route_set_src, route_set_src_compile, route_set_src_free,
1538 };
1539
1540 /* The function checks if the changed routemap specified by parameter rmap
1541 * matches the configured protocol routemaps in proto_rm table. If there is
1542 * a match then rib_update_table() to process the routes.
1543 */
1544 static void zebra_rib_table_rm_update(const char *rmap)
1545 {
1546 int i = 0;
1547 struct route_table *table;
1548 struct vrf *vrf = NULL;
1549 struct zebra_vrf *zvrf = NULL;
1550 char *rmap_name;
1551 char afi_ip = 0;
1552 char afi_ipv6 = 0;
1553 struct route_map *old = NULL;
1554
1555 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1556 zvrf = vrf->info;
1557 if (!zvrf)
1558 continue;
1559 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1560 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP, i);
1561 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1562 if (IS_ZEBRA_DEBUG_EVENT)
1563 zlog_debug(
1564 "%s : AFI_IP rmap %s, route type %s",
1565 __func__, rmap,
1566 zebra_route_string(i));
1567
1568 old = PROTO_RM_MAP(zvrf, AFI_IP, i);
1569
1570 PROTO_RM_MAP(zvrf, AFI_IP, i) =
1571 route_map_lookup_by_name(rmap_name);
1572 /* old is NULL. i.e Route map creation event.
1573 * So update applied_counter.
1574 * If Old is not NULL, i.e It may be routemap
1575 * updation or deletion.
1576 * So no need to update the counter.
1577 */
1578 if (!old)
1579 route_map_counter_increment(
1580 PROTO_RM_MAP(zvrf, AFI_IP, i));
1581 /* There is single rib table for all protocols
1582 */
1583 if (afi_ip == 0) {
1584 table = zvrf->table[AFI_IP]
1585 [SAFI_UNICAST];
1586 if (table) {
1587
1588 afi_ip = 1;
1589 rib_update_table(
1590 table,
1591 RIB_UPDATE_RMAP_CHANGE);
1592 }
1593 }
1594 }
1595 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i);
1596 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1597 if (IS_ZEBRA_DEBUG_EVENT)
1598 zlog_debug(
1599 "%s : AFI_IP6 rmap %s, route type %s",
1600 __func__, rmap,
1601 zebra_route_string(i));
1602
1603 old = PROTO_RM_MAP(zvrf, AFI_IP6, i);
1604
1605 PROTO_RM_MAP(zvrf, AFI_IP6, i) =
1606 route_map_lookup_by_name(rmap_name);
1607 if (!old)
1608 route_map_counter_increment(
1609 PROTO_RM_MAP(zvrf, AFI_IP6, i));
1610 /* There is single rib table for all protocols
1611 */
1612 if (afi_ipv6 == 0) {
1613 table = zvrf->table[AFI_IP6]
1614 [SAFI_UNICAST];
1615 if (table) {
1616
1617 afi_ipv6 = 1;
1618 rib_update_table(
1619 table,
1620 RIB_UPDATE_RMAP_CHANGE);
1621 }
1622 }
1623 }
1624 }
1625 }
1626 }
1627
1628 /* The function checks if the changed routemap specified by parameter rmap
1629 * matches the configured protocol routemaps in nht_rm table. If there is
1630 * a match then zebra_evaluate_rnh() to process the nexthops.
1631 */
1632 static void zebra_nht_rm_update(const char *rmap)
1633 {
1634 int i = 0;
1635 struct route_table *table;
1636 struct vrf *vrf = NULL;
1637 struct zebra_vrf *zvrf = NULL;
1638 char *rmap_name;
1639 char afi_ip = 0;
1640 char afi_ipv6 = 0;
1641 struct route_map *old = NULL;
1642
1643 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1644 zvrf = vrf->info;
1645 if (!zvrf)
1646 continue;
1647 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1648 rmap_name = NHT_RM_NAME(zvrf, AFI_IP, i);
1649 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1650 if (IS_ZEBRA_DEBUG_EVENT)
1651 zlog_debug(
1652 "%s : AFI_IP rmap %s, route type %s",
1653 __func__, rmap,
1654 zebra_route_string(i));
1655
1656 old = NHT_RM_MAP(zvrf, AFI_IP, i);
1657
1658 NHT_RM_MAP(zvrf, AFI_IP, i) =
1659 route_map_lookup_by_name(rmap_name);
1660 if (!old)
1661 route_map_counter_increment(
1662 NHT_RM_MAP(zvrf, AFI_IP, i));
1663 /* There is single rib table for all protocols
1664 */
1665 if (afi_ip == 0) {
1666 table = zvrf->table[AFI_IP]
1667 [SAFI_UNICAST];
1668 if (table) {
1669
1670 afi_ip = 1;
1671
1672 zebra_evaluate_rnh(
1673 zvrf, AFI_IP, 1,
1674 RNH_NEXTHOP_TYPE, NULL);
1675 }
1676 }
1677 }
1678
1679 rmap_name = NHT_RM_NAME(zvrf, AFI_IP6, i);
1680 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1681 if (IS_ZEBRA_DEBUG_EVENT)
1682 zlog_debug(
1683 "%s : AFI_IP6 rmap %s, route type %s",
1684 __func__, rmap,
1685 zebra_route_string(i));
1686
1687 old = NHT_RM_MAP(zvrf, AFI_IP6, i);
1688
1689 NHT_RM_MAP(zvrf, AFI_IP6, i) =
1690 route_map_lookup_by_name(rmap_name);
1691 if (!old)
1692 route_map_counter_increment(
1693 NHT_RM_MAP(zvrf, AFI_IP6, i));
1694 /* There is single rib table for all protocols
1695 */
1696 if (afi_ipv6 == 0) {
1697 table = zvrf->table[AFI_IP6]
1698 [SAFI_UNICAST];
1699 if (table) {
1700
1701 afi_ipv6 = 1;
1702
1703 zebra_evaluate_rnh(
1704 zvrf, AFI_IP, 1,
1705 RNH_NEXTHOP_TYPE, NULL);
1706 }
1707 }
1708 }
1709 }
1710 }
1711 }
1712
1713 static void zebra_route_map_process_update_cb(char *rmap_name)
1714 {
1715 if (IS_ZEBRA_DEBUG_EVENT)
1716 zlog_debug("Event handler for route-map: %s",
1717 rmap_name);
1718 zebra_import_table_rm_update(rmap_name);
1719 zebra_rib_table_rm_update(rmap_name);
1720 zebra_nht_rm_update(rmap_name);
1721 }
1722
1723 static int zebra_route_map_update_timer(struct thread *thread)
1724 {
1725 zebra_t_rmap_update = NULL;
1726
1727 if (IS_ZEBRA_DEBUG_EVENT)
1728 zlog_debug("Event driven route-map update triggered");
1729
1730 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1731 zlog_debug(
1732 "%u: Routemap update-timer fired, scheduling RIB processing",
1733 VRF_DEFAULT);
1734
1735 route_map_walk_update_list(zebra_route_map_process_update_cb);
1736
1737 /*
1738 * This code needs to be updated to be:
1739 * 1) VRF Aware <sigh>
1740 * 2) Route-map aware
1741 */
1742 return (0);
1743 }
1744
1745 static void zebra_route_map_set_delay_timer(uint32_t value)
1746 {
1747 zebra_rmap_update_timer = value;
1748 if (!value && zebra_t_rmap_update) {
1749 /* Event driven route map updates is being disabled */
1750 /* But there's a pending timer. Fire it off now */
1751 thread_cancel(zebra_t_rmap_update);
1752 zebra_route_map_update_timer(zebra_t_rmap_update);
1753 }
1754 }
1755
1756 void zebra_route_map_write_delay_timer(struct vty *vty)
1757 {
1758 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1759 vty_out(vty, "zebra route-map delay-timer %d\n",
1760 zebra_rmap_update_timer);
1761 return;
1762 }
1763
1764 route_map_result_t
1765 zebra_route_map_check(int family, int rib_type, uint8_t instance,
1766 const struct prefix *p, struct nexthop *nexthop,
1767 struct zebra_vrf *zvrf, route_tag_t tag)
1768 {
1769 struct route_map *rmap = NULL;
1770 route_map_result_t ret = RMAP_MATCH;
1771 struct nh_rmap_obj nh_obj;
1772
1773 nh_obj.nexthop = nexthop;
1774 nh_obj.vrf_id = nexthop->vrf_id;
1775 nh_obj.source_protocol = rib_type;
1776 nh_obj.instance = instance;
1777 nh_obj.metric = 0;
1778 nh_obj.tag = tag;
1779
1780 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1781 rmap = PROTO_RM_MAP(zvrf, family, rib_type);
1782 if (!rmap && PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX))
1783 rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
1784 if (rmap) {
1785 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1786 }
1787
1788 return (ret);
1789 }
1790
1791 char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
1792 {
1793 return zebra_import_table_routemap[afi][table];
1794 }
1795
1796 void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
1797 uint32_t table)
1798 {
1799 zebra_import_table_routemap[afi][table] =
1800 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
1801 }
1802
1803 void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
1804 {
1805 XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1806 }
1807
1808 route_map_result_t
1809 zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
1810 const struct prefix *p,
1811 struct nexthop *nexthop,
1812 vrf_id_t vrf_id, route_tag_t tag,
1813 const char *rmap_name)
1814 {
1815 struct route_map *rmap = NULL;
1816 route_map_result_t ret = RMAP_DENYMATCH;
1817 struct nh_rmap_obj nh_obj;
1818
1819 nh_obj.nexthop = nexthop;
1820 nh_obj.vrf_id = vrf_id;
1821 nh_obj.source_protocol = re_type;
1822 nh_obj.instance = instance;
1823 nh_obj.metric = 0;
1824 nh_obj.tag = tag;
1825
1826 if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1827 rmap = route_map_lookup_by_name(rmap_name);
1828 if (rmap) {
1829 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1830 }
1831
1832 return (ret);
1833 }
1834
1835 route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
1836 const struct prefix *p,
1837 struct zebra_vrf *zvrf,
1838 struct route_entry *re,
1839 struct nexthop *nexthop)
1840 {
1841 struct route_map *rmap = NULL;
1842 route_map_result_t ret = RMAP_MATCH;
1843 struct nh_rmap_obj nh_obj;
1844
1845 nh_obj.nexthop = nexthop;
1846 nh_obj.vrf_id = nexthop->vrf_id;
1847 nh_obj.source_protocol = re->type;
1848 nh_obj.instance = re->instance;
1849 nh_obj.metric = re->metric;
1850 nh_obj.tag = re->tag;
1851
1852 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1853 rmap = NHT_RM_MAP(zvrf, afi, client_proto);
1854 if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX))
1855 rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX);
1856 if (rmap)
1857 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1858
1859 return ret;
1860 }
1861
1862 static void zebra_route_map_mark_update(const char *rmap_name)
1863 {
1864 /* rmap_update_timer of 0 means don't do route updates */
1865 if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
1866 zebra_t_rmap_update = NULL;
1867 thread_add_timer(zrouter.master, zebra_route_map_update_timer,
1868 NULL, zebra_rmap_update_timer,
1869 &zebra_t_rmap_update);
1870 }
1871 }
1872
1873 static void zebra_route_map_add(const char *rmap_name)
1874 {
1875 if (route_map_mark_updated(rmap_name) == 0)
1876 zebra_route_map_mark_update(rmap_name);
1877
1878 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1879 }
1880
1881 static void zebra_route_map_delete(const char *rmap_name)
1882 {
1883 if (route_map_mark_updated(rmap_name) == 0)
1884 zebra_route_map_mark_update(rmap_name);
1885
1886 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1887 }
1888
1889 static void zebra_route_map_event(const char *rmap_name)
1890 {
1891 if (route_map_mark_updated(rmap_name) == 0)
1892 zebra_route_map_mark_update(rmap_name);
1893
1894 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1895 }
1896
1897 /* ip protocol configuration write function */
1898 void zebra_routemap_config_write_protocol(struct vty *vty,
1899 struct zebra_vrf *zvrf)
1900 {
1901 int i;
1902 char space[2];
1903
1904 memset(space, 0, sizeof(space));
1905
1906 if (zvrf_id(zvrf) != VRF_DEFAULT)
1907 sprintf(space, "%s", " ");
1908
1909 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1910 if (PROTO_RM_NAME(zvrf, AFI_IP, i))
1911 vty_out(vty, "%sip protocol %s route-map %s\n", space,
1912 zebra_route_string(i),
1913 PROTO_RM_NAME(zvrf, AFI_IP, i));
1914
1915 if (PROTO_RM_NAME(zvrf, AFI_IP6, i))
1916 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space,
1917 zebra_route_string(i),
1918 PROTO_RM_NAME(zvrf, AFI_IP6, i));
1919
1920 if (NHT_RM_NAME(zvrf, AFI_IP, i))
1921 vty_out(vty, "%sip nht %s route-map %s\n", space,
1922 zebra_route_string(i),
1923 NHT_RM_NAME(zvrf, AFI_IP, i));
1924
1925 if (NHT_RM_NAME(zvrf, AFI_IP6, i))
1926 vty_out(vty, "%sipv6 nht %s route-map %s\n", space,
1927 zebra_route_string(i),
1928 NHT_RM_NAME(zvrf, AFI_IP6, i));
1929 }
1930
1931 if (PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1932 vty_out(vty, "%sip protocol %s route-map %s\n", space, "any",
1933 PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1934
1935 if (PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1936 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, "any",
1937 PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1938
1939 if (NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1940 vty_out(vty, "%sip nht %s route-map %s\n", space, "any",
1941 NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1942
1943 if (NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1944 vty_out(vty, "%sipv6 nht %s route-map %s\n", space, "any",
1945 NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1946
1947 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1948 vty_out(vty, "zebra route-map delay-timer %d\n",
1949 zebra_rmap_update_timer);
1950 }
1951
1952 void zebra_route_map_init(void)
1953 {
1954 install_element(CONFIG_NODE, &ip_protocol_cmd);
1955 install_element(CONFIG_NODE, &no_ip_protocol_cmd);
1956 install_element(VRF_NODE, &ip_protocol_cmd);
1957 install_element(VRF_NODE, &no_ip_protocol_cmd);
1958 install_element(VIEW_NODE, &show_ip_protocol_cmd);
1959 install_element(CONFIG_NODE, &ipv6_protocol_cmd);
1960 install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
1961 install_element(VRF_NODE, &ipv6_protocol_cmd);
1962 install_element(VRF_NODE, &no_ipv6_protocol_cmd);
1963 install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
1964 install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1965 install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1966 install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd);
1967 install_element(VRF_NODE, &no_ip_protocol_nht_rmap_cmd);
1968 install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
1969 install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1970 install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1971 install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd);
1972 install_element(VRF_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1973 install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1974 install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
1975 install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1976
1977 route_map_init();
1978
1979 route_map_add_hook(zebra_route_map_add);
1980 route_map_delete_hook(zebra_route_map_delete);
1981 route_map_event_hook(zebra_route_map_event);
1982
1983 route_map_match_interface_hook(generic_match_add);
1984 route_map_no_match_interface_hook(generic_match_delete);
1985
1986 route_map_match_ip_address_hook(generic_match_add);
1987 route_map_no_match_ip_address_hook(generic_match_delete);
1988
1989 route_map_match_ip_address_prefix_list_hook(generic_match_add);
1990 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
1991
1992 route_map_match_ip_next_hop_hook(generic_match_add);
1993 route_map_no_match_ip_next_hop_hook(generic_match_delete);
1994
1995 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
1996 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
1997
1998 route_map_match_ip_next_hop_type_hook(generic_match_add);
1999 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
2000
2001 route_map_match_tag_hook(generic_match_add);
2002 route_map_no_match_tag_hook(generic_match_delete);
2003
2004 route_map_match_ipv6_address_hook(generic_match_add);
2005 route_map_no_match_ipv6_address_hook(generic_match_delete);
2006
2007 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
2008 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
2009
2010 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
2011 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
2012
2013 route_map_install_match(&route_match_tag_cmd);
2014 route_map_install_match(&route_match_interface_cmd);
2015 route_map_install_match(&route_match_ip_next_hop_cmd);
2016 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
2017 route_map_install_match(&route_match_ip_address_cmd);
2018 route_map_install_match(&route_match_ipv6_address_cmd);
2019 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
2020 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
2021 route_map_install_match(&route_match_ip_address_prefix_len_cmd);
2022 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
2023 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
2024 route_map_install_match(&route_match_ip_next_hop_type_cmd);
2025 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
2026 route_map_install_match(&route_match_source_protocol_cmd);
2027 route_map_install_match(&route_match_source_instance_cmd);
2028
2029 /* */
2030 route_map_install_set(&route_set_src_cmd);
2031 /* */
2032 install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
2033 install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
2034 install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
2035 install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
2036 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
2037 install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
2038 install_element(RMAP_NODE, &match_source_protocol_cmd);
2039 install_element(RMAP_NODE, &no_match_source_protocol_cmd);
2040 install_element(RMAP_NODE, &match_source_instance_cmd);
2041 install_element(RMAP_NODE, &no_match_source_instance_cmd);
2042
2043 /* */
2044 install_element(RMAP_NODE, &set_src_cmd);
2045 install_element(RMAP_NODE, &no_set_src_cmd);
2046 }