]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
5d1cbbe781d5de5b2f5ebbb5ae45000e946ab719
[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);
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 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
709
710 if (!zvrf)
711 return CMD_WARNING;
712
713 if (strcasecmp(proto, "any") == 0)
714 rtype = ZEBRA_ROUTE_MAX;
715 else
716 rtype = proto_name2num(proto);
717 if (rtype < 0) {
718 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
719 return CMD_WARNING_CONFIG_FAILED;
720 }
721
722 ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
723
724 return ret;
725 }
726
727 DEFPY (no_ip_protocol,
728 no_ip_protocol_cmd,
729 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
730 " $proto [route-map ROUTE-MAP$rmap]",
731 NO_STR
732 IP_STR
733 "Stop filtering routing info between zebra and protocol\n"
734 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
735 "Specify route-map\n"
736 "Route map name\n")
737 {
738 int ret, rtype;
739
740 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
741
742 if (!zvrf)
743 return CMD_WARNING;
744
745 if (strcasecmp(proto, "any") == 0)
746 rtype = ZEBRA_ROUTE_MAX;
747 else
748 rtype = proto_name2num(proto);
749 if (rtype < 0) {
750 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
751 return CMD_WARNING_CONFIG_FAILED;
752 }
753
754 ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
755
756 return ret;
757 }
758
759 DEFPY (show_ip_protocol,
760 show_ip_protocol_cmd,
761 "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
762 SHOW_STR
763 IP_STR
764 "IP protocol filtering status\n"
765 VRF_FULL_CMD_HELP_STR)
766 {
767 int ret = show_proto_rm(vty, AFI_IP, vrf_all, vrf_name);
768
769 return ret;
770 }
771
772 DEFPY (ipv6_protocol,
773 ipv6_protocol_cmd,
774 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
775 " $proto route-map ROUTE-MAP$rmap",
776 IP6_STR
777 "Filter IPv6 routing info exchanged between zebra and protocol\n"
778 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
779 "Specify route-map\n"
780 "Route map name\n")
781 {
782 int ret, rtype;
783
784 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
785
786 if (!zvrf)
787 return CMD_WARNING;
788
789 if (strcasecmp(proto, "any") == 0)
790 rtype = ZEBRA_ROUTE_MAX;
791 else
792 rtype = proto_name2num(proto);
793 if (rtype < 0) {
794 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
795 return CMD_WARNING_CONFIG_FAILED;
796 }
797
798 ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
799
800 return ret;
801 }
802
803 DEFPY (no_ipv6_protocol,
804 no_ipv6_protocol_cmd,
805 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
806 " $proto [route-map ROUTE-MAP$rmap]",
807 NO_STR
808 IP6_STR
809 "Stop filtering IPv6 routing info between zebra and protocol\n"
810 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
811 "Specify route-map\n"
812 "Route map name\n")
813 {
814 int ret, rtype;
815
816 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
817
818 if (!zvrf)
819 return CMD_WARNING;
820
821 if (strcasecmp(proto, "any") == 0)
822 rtype = ZEBRA_ROUTE_MAX;
823 else
824 rtype = proto_name2num(proto);
825 if (rtype < 0) {
826 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
827 return CMD_WARNING_CONFIG_FAILED;
828 }
829
830 ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
831
832 return ret;
833 }
834
835 DEFPY (show_ipv6_protocol,
836 show_ipv6_protocol_cmd,
837 "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
838 SHOW_STR
839 IP6_STR
840 "IPv6 protocol filtering status\n"
841 VRF_FULL_CMD_HELP_STR)
842 {
843 int ret = show_proto_rm(vty, AFI_IP6, vrf_all, vrf_name);
844
845 return ret;
846 }
847
848 DEFPY (ip_protocol_nht_rmap,
849 ip_protocol_nht_rmap_cmd,
850 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
851 " $proto route-map ROUTE-MAP$rmap",
852 IP_STR
853 "Filter Next Hop tracking route resolution\n"
854 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
855 "Specify route map\n"
856 "Route map name\n")
857 {
858
859 int ret, rtype;
860
861 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
862
863 if (!zvrf)
864 return CMD_WARNING;
865
866 if (strcasecmp(proto, "any") == 0)
867 rtype = ZEBRA_ROUTE_MAX;
868 else
869 rtype = proto_name2num(proto);
870 if (rtype < 0) {
871 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
872 return CMD_WARNING_CONFIG_FAILED;
873 }
874
875 ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP);
876
877 return ret;
878 }
879
880 DEFPY (no_ip_protocol_nht_rmap,
881 no_ip_protocol_nht_rmap_cmd,
882 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
883 " $proto route-map [ROUTE-MAP$rmap]",
884 NO_STR
885 IP_STR
886 "Filter Next Hop tracking route resolution\n"
887 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
888 "Specify route map\n"
889 "Route map name\n")
890 {
891 int ret, rtype;
892
893 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
894
895 if (!zvrf)
896 return CMD_WARNING;
897
898 if (strcasecmp(proto, "any") == 0)
899 rtype = ZEBRA_ROUTE_MAX;
900 else
901 rtype = proto_name2num(proto);
902 if (rtype < 0) {
903 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
904 return CMD_WARNING_CONFIG_FAILED;
905 }
906
907 ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP);
908
909 return ret;
910 }
911
912 DEFPY (show_ip_protocol_nht,
913 show_ip_protocol_nht_cmd,
914 "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
915 SHOW_STR
916 IP_STR
917 "IP nexthop tracking table\n"
918 "IP Next Hop tracking filtering status\n"
919 VRF_FULL_CMD_HELP_STR)
920 {
921 int ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name);
922
923 return ret;
924 }
925
926 DEFPY (ipv6_protocol_nht_rmap,
927 ipv6_protocol_nht_rmap_cmd,
928 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
929 " $proto route-map ROUTE-MAP$rmap",
930 IP6_STR
931 "Filter Next Hop tracking route resolution\n"
932 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
933 "Specify route map\n"
934 "Route map name\n")
935 {
936 int ret, rtype;
937
938 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
939
940 if (!zvrf)
941 return CMD_WARNING;
942
943 if (strcasecmp(proto, "any") == 0)
944 rtype = ZEBRA_ROUTE_MAX;
945 else
946 rtype = proto_name2num(proto);
947 if (rtype < 0) {
948 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
949 return CMD_WARNING_CONFIG_FAILED;
950 }
951
952 ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP6);
953
954 return ret;
955 }
956
957 DEFPY (no_ipv6_protocol_nht_rmap,
958 no_ipv6_protocol_nht_rmap_cmd,
959 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
960 " $proto [route-map ROUTE-MAP$rmap]",
961 NO_STR
962 IP6_STR
963 "Filter Next Hop tracking route resolution\n"
964 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
965 "Specify route map\n"
966 "Route map name\n")
967 {
968 int ret, rtype;
969
970 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
971
972 if (!zvrf)
973 return CMD_WARNING;
974
975 if (strcasecmp(proto, "any") == 0)
976 rtype = ZEBRA_ROUTE_MAX;
977 else
978 rtype = proto_name2num(proto);
979 if (rtype < 0) {
980 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
981 return CMD_WARNING_CONFIG_FAILED;
982 }
983
984 ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP6);
985
986 return ret;
987 }
988
989 DEFPY (show_ipv6_protocol_nht,
990 show_ipv6_protocol_nht_cmd,
991 "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
992 SHOW_STR
993 IP6_STR
994 "Next Hop filtering status\n"
995 "Route-map\n"
996 VRF_FULL_CMD_HELP_STR)
997 {
998 int ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name);
999
1000 return ret;
1001 }
1002
1003 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1004
1005 /* `match ip next-hop IP_ACCESS_LIST' */
1006
1007 /* Match function return 1 if match is success else return zero. */
1008 static route_map_result_t route_match_ip_next_hop(void *rule,
1009 const struct prefix *prefix,
1010 route_map_object_t type,
1011 void *object)
1012 {
1013 struct access_list *alist;
1014 struct nh_rmap_obj *nh_data;
1015 struct prefix_ipv4 p;
1016
1017 if (type == RMAP_ZEBRA) {
1018 nh_data = object;
1019 if (!nh_data)
1020 return RMAP_DENYMATCH;
1021
1022 switch (nh_data->nexthop->type) {
1023 case NEXTHOP_TYPE_IFINDEX:
1024 /* Interface routes can't match ip next-hop */
1025 return RMAP_NOMATCH;
1026 case NEXTHOP_TYPE_IPV4_IFINDEX:
1027 case NEXTHOP_TYPE_IPV4:
1028 p.family = AF_INET;
1029 p.prefix = nh_data->nexthop->gate.ipv4;
1030 p.prefixlen = IPV4_MAX_BITLEN;
1031 break;
1032 default:
1033 return RMAP_NOMATCH;
1034 }
1035 alist = access_list_lookup(AFI_IP, (char *)rule);
1036 if (alist == NULL)
1037 return RMAP_NOMATCH;
1038
1039 return (access_list_apply(alist, &p) == FILTER_DENY
1040 ? RMAP_NOMATCH
1041 : RMAP_MATCH);
1042 }
1043 return RMAP_NOMATCH;
1044 }
1045
1046 /* Route map `ip next-hop' match statement. `arg' should be
1047 access-list name. */
1048 static void *route_match_ip_next_hop_compile(const char *arg)
1049 {
1050 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1051 }
1052
1053 /* Free route map's compiled `. */
1054 static void route_match_ip_next_hop_free(void *rule)
1055 {
1056 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1057 }
1058
1059 /* Route map commands for ip next-hop matching. */
1060 static struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
1061 "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile,
1062 route_match_ip_next_hop_free};
1063
1064 /* `match ip next-hop prefix-list PREFIX_LIST' */
1065
1066 static route_map_result_t
1067 route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
1068 route_map_object_t type, void *object)
1069 {
1070 struct prefix_list *plist;
1071 struct nh_rmap_obj *nh_data;
1072 struct prefix_ipv4 p;
1073
1074 if (type == RMAP_ZEBRA) {
1075 nh_data = (struct nh_rmap_obj *)object;
1076 if (!nh_data)
1077 return RMAP_DENYMATCH;
1078
1079 switch (nh_data->nexthop->type) {
1080 case NEXTHOP_TYPE_IFINDEX:
1081 /* Interface routes can't match ip next-hop */
1082 return RMAP_NOMATCH;
1083 case NEXTHOP_TYPE_IPV4_IFINDEX:
1084 case NEXTHOP_TYPE_IPV4:
1085 p.family = AF_INET;
1086 p.prefix = nh_data->nexthop->gate.ipv4;
1087 p.prefixlen = IPV4_MAX_BITLEN;
1088 break;
1089 default:
1090 return RMAP_NOMATCH;
1091 }
1092 plist = prefix_list_lookup(AFI_IP, (char *)rule);
1093 if (plist == NULL)
1094 return RMAP_NOMATCH;
1095
1096 return (prefix_list_apply(plist, &p) == PREFIX_DENY
1097 ? RMAP_NOMATCH
1098 : RMAP_MATCH);
1099 }
1100 return RMAP_NOMATCH;
1101 }
1102
1103 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
1104 {
1105 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1106 }
1107
1108 static void route_match_ip_next_hop_prefix_list_free(void *rule)
1109 {
1110 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1111 }
1112
1113 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
1114 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list,
1115 route_match_ip_next_hop_prefix_list_compile,
1116 route_match_ip_next_hop_prefix_list_free};
1117
1118 /* `match ip address IP_ACCESS_LIST' */
1119
1120 /* Match function should return 1 if match is success else return
1121 zero. */
1122 static route_map_result_t route_match_address(afi_t afi, void *rule,
1123 const struct prefix *prefix,
1124 route_map_object_t type,
1125 void *object)
1126 {
1127 struct access_list *alist;
1128
1129 if (type == RMAP_ZEBRA) {
1130 alist = access_list_lookup(afi, (char *)rule);
1131 if (alist == NULL)
1132 return RMAP_NOMATCH;
1133
1134 return (access_list_apply(alist, prefix) == FILTER_DENY
1135 ? RMAP_NOMATCH
1136 : RMAP_MATCH);
1137 }
1138 return RMAP_NOMATCH;
1139 }
1140
1141 static route_map_result_t route_match_ip_address(void *rule,
1142 const struct prefix *prefix,
1143 route_map_object_t type,
1144 void *object)
1145 {
1146 return route_match_address(AFI_IP, rule, prefix, type, object);
1147 }
1148
1149 static route_map_result_t route_match_ipv6_address(void *rule,
1150 const struct prefix *prefix,
1151 route_map_object_t type,
1152 void *object)
1153
1154 {
1155 return route_match_address(AFI_IP6, rule, prefix, type, object);
1156 }
1157
1158 /* Route map `ip address' match statement. `arg' should be
1159 access-list name. */
1160 static void *route_match_address_compile(const char *arg)
1161 {
1162 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1163 }
1164
1165 /* Free route map's compiled `ip address' value. */
1166 static void route_match_address_free(void *rule)
1167 {
1168 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1169 }
1170
1171 /* Route map commands for ip address matching. */
1172 static struct route_map_rule_cmd route_match_ip_address_cmd = {
1173 "ip address", route_match_ip_address, route_match_address_compile,
1174 route_match_address_free};
1175
1176 /* Route map commands for ipv6 address matching. */
1177 static struct route_map_rule_cmd route_match_ipv6_address_cmd = {
1178 "ipv6 address", route_match_ipv6_address, route_match_address_compile,
1179 route_match_address_free};
1180
1181 /* `match ip address prefix-list PREFIX_LIST' */
1182
1183 static route_map_result_t
1184 route_match_address_prefix_list(void *rule, const struct prefix *prefix,
1185 route_map_object_t type, void *object, afi_t afi)
1186 {
1187 struct prefix_list *plist;
1188
1189 if (type == RMAP_ZEBRA) {
1190 plist = prefix_list_lookup(afi, (char *)rule);
1191 if (plist == NULL)
1192 return RMAP_NOMATCH;
1193
1194 return (prefix_list_apply(plist, prefix) == PREFIX_DENY
1195 ? RMAP_NOMATCH
1196 : RMAP_MATCH);
1197 }
1198 return RMAP_NOMATCH;
1199 }
1200
1201 static route_map_result_t
1202 route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
1203 route_map_object_t type, void *object)
1204 {
1205 return (route_match_address_prefix_list(rule, prefix, type, object,
1206 AFI_IP));
1207 }
1208
1209 static void *route_match_address_prefix_list_compile(const char *arg)
1210 {
1211 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1212 }
1213
1214 static void route_match_address_prefix_list_free(void *rule)
1215 {
1216 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1217 }
1218
1219 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
1220 "ip address prefix-list", route_match_ip_address_prefix_list,
1221 route_match_address_prefix_list_compile,
1222 route_match_address_prefix_list_free};
1223
1224 static route_map_result_t
1225 route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1226 route_map_object_t type, void *object)
1227 {
1228 return (route_match_address_prefix_list(rule, prefix, type, object,
1229 AFI_IP6));
1230 }
1231
1232 static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
1233 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
1234 route_match_address_prefix_list_compile,
1235 route_match_address_prefix_list_free};
1236
1237 /* `match ip address prefix-len PREFIXLEN' */
1238
1239 static route_map_result_t
1240 route_match_address_prefix_len(void *rule, const struct prefix *prefix,
1241 route_map_object_t type, void *object)
1242 {
1243 uint32_t *prefixlen = (uint32_t *)rule;
1244
1245 if (type == RMAP_ZEBRA) {
1246 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH
1247 : RMAP_NOMATCH);
1248 }
1249 return RMAP_NOMATCH;
1250 }
1251
1252 static void *route_match_address_prefix_len_compile(const char *arg)
1253 {
1254 uint32_t *prefix_len;
1255 char *endptr = NULL;
1256 unsigned long tmpval;
1257
1258 /* prefix len value shoud be integer. */
1259 if (!all_digit(arg))
1260 return NULL;
1261
1262 errno = 0;
1263 tmpval = strtoul(arg, &endptr, 10);
1264 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1265 return NULL;
1266
1267 prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1268
1269 *prefix_len = tmpval;
1270 return prefix_len;
1271 }
1272
1273 static void route_match_address_prefix_len_free(void *rule)
1274 {
1275 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1276 }
1277
1278 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = {
1279 "ip address prefix-len", route_match_address_prefix_len,
1280 route_match_address_prefix_len_compile,
1281 route_match_address_prefix_len_free};
1282
1283 static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd = {
1284 "ipv6 address prefix-len", route_match_address_prefix_len,
1285 route_match_address_prefix_len_compile,
1286 route_match_address_prefix_len_free};
1287
1288 /* `match ip nexthop prefix-len PREFIXLEN' */
1289
1290 static route_map_result_t
1291 route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
1292 route_map_object_t type, void *object)
1293 {
1294 uint32_t *prefixlen = (uint32_t *)rule;
1295 struct nh_rmap_obj *nh_data;
1296 struct prefix_ipv4 p;
1297
1298 if (type == RMAP_ZEBRA) {
1299 nh_data = (struct nh_rmap_obj *)object;
1300 if (!nh_data || !nh_data->nexthop)
1301 return RMAP_DENYMATCH;
1302
1303 switch (nh_data->nexthop->type) {
1304 case NEXTHOP_TYPE_IFINDEX:
1305 /* Interface routes can't match ip next-hop */
1306 return RMAP_NOMATCH;
1307 case NEXTHOP_TYPE_IPV4_IFINDEX:
1308 case NEXTHOP_TYPE_IPV4:
1309 p.family = AF_INET;
1310 p.prefix = nh_data->nexthop->gate.ipv4;
1311 p.prefixlen = IPV4_MAX_BITLEN;
1312 break;
1313 default:
1314 return RMAP_NOMATCH;
1315 }
1316 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH
1317 : RMAP_NOMATCH);
1318 }
1319 return RMAP_NOMATCH;
1320 }
1321
1322 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = {
1323 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len,
1324 route_match_address_prefix_len_compile, /* reuse */
1325 route_match_address_prefix_len_free /* reuse */
1326 };
1327
1328 /* `match source-protocol PROTOCOL' */
1329
1330 static route_map_result_t route_match_source_protocol(void *rule,
1331 const struct prefix *p,
1332 route_map_object_t type,
1333 void *object)
1334 {
1335 uint32_t *rib_type = (uint32_t *)rule;
1336 struct nh_rmap_obj *nh_data;
1337
1338 if (type == RMAP_ZEBRA) {
1339 nh_data = (struct nh_rmap_obj *)object;
1340 if (!nh_data)
1341 return RMAP_DENYMATCH;
1342
1343 return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
1344 : RMAP_NOMATCH);
1345 }
1346 return RMAP_NOMATCH;
1347 }
1348
1349 static void *route_match_source_protocol_compile(const char *arg)
1350 {
1351 uint32_t *rib_type;
1352 int i;
1353
1354 i = proto_name2num(arg);
1355 rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1356
1357 *rib_type = i;
1358
1359 return rib_type;
1360 }
1361
1362 static void route_match_source_protocol_free(void *rule)
1363 {
1364 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1365 }
1366
1367 static struct route_map_rule_cmd route_match_source_protocol_cmd = {
1368 "source-protocol", route_match_source_protocol,
1369 route_match_source_protocol_compile, route_match_source_protocol_free};
1370
1371 /* `source-instance` */
1372 static route_map_result_t route_match_source_instance(void *rule,
1373 const struct prefix *p,
1374 route_map_object_t type,
1375 void *object)
1376 {
1377 uint8_t *instance = (uint8_t *)rule;
1378 struct nh_rmap_obj *nh_data;
1379
1380 if (type != RMAP_ZEBRA)
1381 return RMAP_NOMATCH;
1382
1383 nh_data = (struct nh_rmap_obj *)object;
1384 if (!nh_data)
1385 return RMAP_DENYMATCH;
1386
1387 return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
1388 }
1389
1390 static void *route_match_source_instance_compile(const char *arg)
1391 {
1392 uint8_t *instance;
1393 int i;
1394
1395 i = atoi(arg);
1396 instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1397
1398 *instance = i;
1399
1400 return instance;
1401 }
1402
1403 static void route_match_source_instance_free(void *rule)
1404 {
1405 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1406 }
1407
1408 static struct route_map_rule_cmd route_match_source_instance_cmd = {
1409 "source-instance", route_match_source_instance,
1410 route_match_source_instance_compile, route_match_source_instance_free};
1411
1412 /* `set src A.B.C.D' */
1413
1414 /* Set src. */
1415 static route_map_result_t route_set_src(void *rule, const struct prefix *prefix,
1416 route_map_object_t type, void *object)
1417 {
1418 struct nh_rmap_obj *nh_data;
1419
1420 if (type == RMAP_ZEBRA) {
1421 nh_data = (struct nh_rmap_obj *)object;
1422 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1423 }
1424 return RMAP_OKAY;
1425 }
1426
1427 /* set src compilation. */
1428 static void *route_set_src_compile(const char *arg)
1429 {
1430 union g_addr src, *psrc;
1431
1432 if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1)
1433 || (inet_pton(AF_INET, arg, &src.ipv4) == 1)) {
1434 psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr));
1435 *psrc = src;
1436 return psrc;
1437 }
1438 return NULL;
1439 }
1440
1441 /* Free route map's compiled `set src' value. */
1442 static void route_set_src_free(void *rule)
1443 {
1444 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1445 }
1446
1447 /* Set src rule structure. */
1448 static struct route_map_rule_cmd route_set_src_cmd = {
1449 "src", route_set_src, route_set_src_compile, route_set_src_free,
1450 };
1451
1452 /* The function checks if the changed routemap specified by parameter rmap
1453 * matches the configured protocol routemaps in proto_rm table. If there is
1454 * a match then rib_update_table() to process the routes.
1455 */
1456 static void zebra_rib_table_rm_update(const char *rmap)
1457 {
1458 int i = 0;
1459 struct route_table *table;
1460 struct vrf *vrf = NULL;
1461 struct zebra_vrf *zvrf = NULL;
1462 char *rmap_name;
1463 char afi_ip = 0;
1464 char afi_ipv6 = 0;
1465 struct route_map *old = NULL;
1466
1467 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1468 zvrf = vrf->info;
1469 if (!zvrf)
1470 continue;
1471 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1472 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP, i);
1473 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1474 if (IS_ZEBRA_DEBUG_EVENT)
1475 zlog_debug(
1476 "%s : AFI_IP rmap %s, route type %s",
1477 __func__, rmap,
1478 zebra_route_string(i));
1479
1480 old = PROTO_RM_MAP(zvrf, AFI_IP, i);
1481
1482 PROTO_RM_MAP(zvrf, AFI_IP, i) =
1483 route_map_lookup_by_name(rmap_name);
1484 /* old is NULL. i.e Route map creation event.
1485 * So update applied_counter.
1486 * If Old is not NULL, i.e It may be routemap
1487 * updation or deletion.
1488 * So no need to update the counter.
1489 */
1490 if (!old)
1491 route_map_counter_increment(
1492 PROTO_RM_MAP(zvrf, AFI_IP, i));
1493 /* There is single rib table for all protocols
1494 */
1495 if (afi_ip == 0) {
1496 table = zvrf->table[AFI_IP]
1497 [SAFI_UNICAST];
1498 if (table) {
1499
1500 afi_ip = 1;
1501 rib_update_table(
1502 table,
1503 RIB_UPDATE_RMAP_CHANGE);
1504 }
1505 }
1506 }
1507 rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i);
1508 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1509 if (IS_ZEBRA_DEBUG_EVENT)
1510 zlog_debug(
1511 "%s : AFI_IP6 rmap %s, route type %s",
1512 __func__, rmap,
1513 zebra_route_string(i));
1514
1515 old = PROTO_RM_MAP(zvrf, AFI_IP6, i);
1516
1517 PROTO_RM_MAP(zvrf, AFI_IP6, i) =
1518 route_map_lookup_by_name(rmap_name);
1519 if (!old)
1520 route_map_counter_increment(
1521 PROTO_RM_MAP(zvrf, AFI_IP6, i));
1522 /* There is single rib table for all protocols
1523 */
1524 if (afi_ipv6 == 0) {
1525 table = zvrf->table[AFI_IP6]
1526 [SAFI_UNICAST];
1527 if (table) {
1528
1529 afi_ipv6 = 1;
1530 rib_update_table(
1531 table,
1532 RIB_UPDATE_RMAP_CHANGE);
1533 }
1534 }
1535 }
1536 }
1537 }
1538 }
1539
1540 /* The function checks if the changed routemap specified by parameter rmap
1541 * matches the configured protocol routemaps in nht_rm table. If there is
1542 * a match then zebra_evaluate_rnh() to process the nexthops.
1543 */
1544 static void zebra_nht_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 = NHT_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 = NHT_RM_MAP(zvrf, AFI_IP, i);
1569
1570 NHT_RM_MAP(zvrf, AFI_IP, i) =
1571 route_map_lookup_by_name(rmap_name);
1572 if (!old)
1573 route_map_counter_increment(
1574 NHT_RM_MAP(zvrf, AFI_IP, i));
1575 /* There is single rib table for all protocols
1576 */
1577 if (afi_ip == 0) {
1578 table = zvrf->table[AFI_IP]
1579 [SAFI_UNICAST];
1580 if (table) {
1581
1582 afi_ip = 1;
1583
1584 zebra_evaluate_rnh(
1585 zvrf, AFI_IP, 1,
1586 RNH_NEXTHOP_TYPE, NULL);
1587 }
1588 }
1589 }
1590
1591 rmap_name = NHT_RM_NAME(zvrf, AFI_IP6, i);
1592 if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1593 if (IS_ZEBRA_DEBUG_EVENT)
1594 zlog_debug(
1595 "%s : AFI_IP6 rmap %s, route type %s",
1596 __func__, rmap,
1597 zebra_route_string(i));
1598
1599 old = NHT_RM_MAP(zvrf, AFI_IP6, i);
1600
1601 NHT_RM_MAP(zvrf, AFI_IP6, i) =
1602 route_map_lookup_by_name(rmap_name);
1603 if (!old)
1604 route_map_counter_increment(
1605 NHT_RM_MAP(zvrf, AFI_IP6, i));
1606 /* There is single rib table for all protocols
1607 */
1608 if (afi_ipv6 == 0) {
1609 table = zvrf->table[AFI_IP6]
1610 [SAFI_UNICAST];
1611 if (table) {
1612
1613 afi_ipv6 = 1;
1614
1615 zebra_evaluate_rnh(
1616 zvrf, AFI_IP, 1,
1617 RNH_NEXTHOP_TYPE, NULL);
1618 }
1619 }
1620 }
1621 }
1622 }
1623 }
1624
1625 static void zebra_route_map_process_update_cb(char *rmap_name)
1626 {
1627 if (IS_ZEBRA_DEBUG_EVENT)
1628 zlog_debug("Event handler for route-map: %s",
1629 rmap_name);
1630 zebra_import_table_rm_update(rmap_name);
1631 zebra_rib_table_rm_update(rmap_name);
1632 zebra_nht_rm_update(rmap_name);
1633 }
1634
1635 static int zebra_route_map_update_timer(struct thread *thread)
1636 {
1637 zebra_t_rmap_update = NULL;
1638
1639 if (IS_ZEBRA_DEBUG_EVENT)
1640 zlog_debug("Event driven route-map update triggered");
1641
1642 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1643 zlog_debug(
1644 "%u: Routemap update-timer fired, scheduling RIB processing",
1645 VRF_DEFAULT);
1646
1647 route_map_walk_update_list(zebra_route_map_process_update_cb);
1648
1649 /*
1650 * This code needs to be updated to be:
1651 * 1) VRF Aware <sigh>
1652 * 2) Route-map aware
1653 */
1654 return (0);
1655 }
1656
1657 static void zebra_route_map_set_delay_timer(uint32_t value)
1658 {
1659 zebra_rmap_update_timer = value;
1660 if (!value && zebra_t_rmap_update) {
1661 /* Event driven route map updates is being disabled */
1662 /* But there's a pending timer. Fire it off now */
1663 thread_cancel(zebra_t_rmap_update);
1664 zebra_route_map_update_timer(zebra_t_rmap_update);
1665 }
1666 }
1667
1668 void zebra_route_map_write_delay_timer(struct vty *vty)
1669 {
1670 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1671 vty_out(vty, "zebra route-map delay-timer %d\n",
1672 zebra_rmap_update_timer);
1673 return;
1674 }
1675
1676 route_map_result_t
1677 zebra_route_map_check(int family, int rib_type, uint8_t instance,
1678 const struct prefix *p, struct nexthop *nexthop,
1679 struct zebra_vrf *zvrf, route_tag_t tag)
1680 {
1681 struct route_map *rmap = NULL;
1682 route_map_result_t ret = RMAP_MATCH;
1683 struct nh_rmap_obj nh_obj;
1684
1685 nh_obj.nexthop = nexthop;
1686 nh_obj.vrf_id = nexthop->vrf_id;
1687 nh_obj.source_protocol = rib_type;
1688 nh_obj.instance = instance;
1689 nh_obj.metric = 0;
1690 nh_obj.tag = tag;
1691
1692 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1693 rmap = PROTO_RM_MAP(zvrf, family, rib_type);
1694 if (!rmap && PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX))
1695 rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
1696 if (rmap) {
1697 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1698 }
1699
1700 return (ret);
1701 }
1702
1703 char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
1704 {
1705 return zebra_import_table_routemap[afi][table];
1706 }
1707
1708 void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
1709 uint32_t table)
1710 {
1711 zebra_import_table_routemap[afi][table] =
1712 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
1713 }
1714
1715 void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
1716 {
1717 XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1718 }
1719
1720 route_map_result_t
1721 zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
1722 const struct prefix *p,
1723 struct nexthop *nexthop,
1724 vrf_id_t vrf_id, route_tag_t tag,
1725 const char *rmap_name)
1726 {
1727 struct route_map *rmap = NULL;
1728 route_map_result_t ret = RMAP_DENYMATCH;
1729 struct nh_rmap_obj nh_obj;
1730
1731 nh_obj.nexthop = nexthop;
1732 nh_obj.vrf_id = vrf_id;
1733 nh_obj.source_protocol = re_type;
1734 nh_obj.instance = instance;
1735 nh_obj.metric = 0;
1736 nh_obj.tag = tag;
1737
1738 if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1739 rmap = route_map_lookup_by_name(rmap_name);
1740 if (rmap) {
1741 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1742 }
1743
1744 return (ret);
1745 }
1746
1747 route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
1748 const struct prefix *p,
1749 struct zebra_vrf *zvrf,
1750 struct route_entry *re,
1751 struct nexthop *nexthop)
1752 {
1753 struct route_map *rmap = NULL;
1754 route_map_result_t ret = RMAP_MATCH;
1755 struct nh_rmap_obj nh_obj;
1756
1757 nh_obj.nexthop = nexthop;
1758 nh_obj.vrf_id = nexthop->vrf_id;
1759 nh_obj.source_protocol = re->type;
1760 nh_obj.instance = re->instance;
1761 nh_obj.metric = re->metric;
1762 nh_obj.tag = re->tag;
1763
1764 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1765 rmap = NHT_RM_MAP(zvrf, afi, client_proto);
1766 if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX))
1767 rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX);
1768 if (rmap)
1769 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1770
1771 return ret;
1772 }
1773
1774 static void zebra_route_map_mark_update(const char *rmap_name)
1775 {
1776 /* rmap_update_timer of 0 means don't do route updates */
1777 if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
1778 zebra_t_rmap_update = NULL;
1779 thread_add_timer(zrouter.master, zebra_route_map_update_timer,
1780 NULL, zebra_rmap_update_timer,
1781 &zebra_t_rmap_update);
1782 }
1783 }
1784
1785 static void zebra_route_map_add(const char *rmap_name)
1786 {
1787 if (route_map_mark_updated(rmap_name) == 0)
1788 zebra_route_map_mark_update(rmap_name);
1789
1790 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1791 }
1792
1793 static void zebra_route_map_delete(const char *rmap_name)
1794 {
1795 if (route_map_mark_updated(rmap_name) == 0)
1796 zebra_route_map_mark_update(rmap_name);
1797
1798 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1799 }
1800
1801 static void zebra_route_map_event(route_map_event_t event,
1802 const char *rmap_name)
1803 {
1804 if (route_map_mark_updated(rmap_name) == 0)
1805 zebra_route_map_mark_update(rmap_name);
1806
1807 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1808 }
1809
1810 /* ip protocol configuration write function */
1811 void zebra_routemap_config_write_protocol(struct vty *vty,
1812 struct zebra_vrf *zvrf)
1813 {
1814 int i;
1815 char space[2];
1816
1817 memset(space, 0, sizeof(space));
1818
1819 if (zvrf_id(zvrf) != VRF_DEFAULT)
1820 sprintf(space, "%s", " ");
1821
1822 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1823 if (PROTO_RM_NAME(zvrf, AFI_IP, i))
1824 vty_out(vty, "%sip protocol %s route-map %s\n", space,
1825 zebra_route_string(i),
1826 PROTO_RM_NAME(zvrf, AFI_IP, i));
1827
1828 if (PROTO_RM_NAME(zvrf, AFI_IP6, i))
1829 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space,
1830 zebra_route_string(i),
1831 PROTO_RM_NAME(zvrf, AFI_IP6, i));
1832
1833 if (NHT_RM_NAME(zvrf, AFI_IP, i))
1834 vty_out(vty, "%sip nht %s route-map %s\n", space,
1835 zebra_route_string(i),
1836 NHT_RM_NAME(zvrf, AFI_IP, i));
1837
1838 if (NHT_RM_NAME(zvrf, AFI_IP6, i))
1839 vty_out(vty, "%sipv6 nht %s route-map %s\n", space,
1840 zebra_route_string(i),
1841 NHT_RM_NAME(zvrf, AFI_IP6, i));
1842 }
1843
1844 if (PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1845 vty_out(vty, "%sip protocol %s route-map %s\n", space, "any",
1846 PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1847
1848 if (PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1849 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, "any",
1850 PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1851
1852 if (NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1853 vty_out(vty, "%sip nht %s route-map %s\n", space, "any",
1854 NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1855
1856 if (NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1857 vty_out(vty, "%sipv6 nht %s route-map %s\n", space, "any",
1858 NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1859
1860 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1861 vty_out(vty, "zebra route-map delay-timer %d\n",
1862 zebra_rmap_update_timer);
1863 }
1864
1865 void zebra_route_map_init(void)
1866 {
1867 install_element(CONFIG_NODE, &ip_protocol_cmd);
1868 install_element(CONFIG_NODE, &no_ip_protocol_cmd);
1869 install_element(VRF_NODE, &ip_protocol_cmd);
1870 install_element(VRF_NODE, &no_ip_protocol_cmd);
1871 install_element(VIEW_NODE, &show_ip_protocol_cmd);
1872 install_element(CONFIG_NODE, &ipv6_protocol_cmd);
1873 install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
1874 install_element(VRF_NODE, &ipv6_protocol_cmd);
1875 install_element(VRF_NODE, &no_ipv6_protocol_cmd);
1876 install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
1877 install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1878 install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1879 install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd);
1880 install_element(VRF_NODE, &no_ip_protocol_nht_rmap_cmd);
1881 install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
1882 install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1883 install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1884 install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd);
1885 install_element(VRF_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1886 install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1887 install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
1888 install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1889
1890 route_map_init();
1891
1892 route_map_add_hook(zebra_route_map_add);
1893 route_map_delete_hook(zebra_route_map_delete);
1894 route_map_event_hook(zebra_route_map_event);
1895
1896 route_map_match_interface_hook(generic_match_add);
1897 route_map_no_match_interface_hook(generic_match_delete);
1898
1899 route_map_match_ip_address_hook(generic_match_add);
1900 route_map_no_match_ip_address_hook(generic_match_delete);
1901
1902 route_map_match_ip_address_prefix_list_hook(generic_match_add);
1903 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
1904
1905 route_map_match_ip_next_hop_hook(generic_match_add);
1906 route_map_no_match_ip_next_hop_hook(generic_match_delete);
1907
1908 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
1909 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
1910
1911 route_map_match_tag_hook(generic_match_add);
1912 route_map_no_match_tag_hook(generic_match_delete);
1913
1914 route_map_match_ipv6_address_hook(generic_match_add);
1915 route_map_no_match_ipv6_address_hook(generic_match_delete);
1916
1917 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
1918 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
1919
1920 route_map_install_match(&route_match_tag_cmd);
1921 route_map_install_match(&route_match_interface_cmd);
1922 route_map_install_match(&route_match_ip_next_hop_cmd);
1923 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
1924 route_map_install_match(&route_match_ip_address_cmd);
1925 route_map_install_match(&route_match_ipv6_address_cmd);
1926 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
1927 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
1928 route_map_install_match(&route_match_ip_address_prefix_len_cmd);
1929 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
1930 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
1931 route_map_install_match(&route_match_source_protocol_cmd);
1932 route_map_install_match(&route_match_source_instance_cmd);
1933
1934 /* */
1935 route_map_install_set(&route_set_src_cmd);
1936 /* */
1937 install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
1938 install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
1939 install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
1940 install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
1941 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
1942 install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
1943 install_element(RMAP_NODE, &match_source_protocol_cmd);
1944 install_element(RMAP_NODE, &no_match_source_protocol_cmd);
1945 install_element(RMAP_NODE, &match_source_instance_cmd);
1946 install_element(RMAP_NODE, &no_match_source_instance_cmd);
1947
1948 /* */
1949 install_element(RMAP_NODE, &set_src_cmd);
1950 install_element(RMAP_NODE, &no_set_src_cmd);
1951 }