]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
zebra: Add initial framework to keep track of changed route-maps
[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
35 #include "zebra/zserv.h"
36 #include "zebra/redistribute.h"
37 #include "zebra/debug.h"
38 #include "zebra/zebra_rnh.h"
39 #include "zebra/zebra_routemap.h"
40
41 static uint32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
42 static struct thread *zebra_t_rmap_update = NULL;
43 char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */
44 /* NH Tracking route map */
45 char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */
46 char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
47
48 struct nh_rmap_obj {
49 struct nexthop *nexthop;
50 vrf_id_t vrf_id;
51 uint32_t source_protocol;
52 uint8_t instance;
53 int metric;
54 route_tag_t tag;
55 };
56
57 static void zebra_route_map_set_delay_timer(uint32_t value);
58
59
60 /* Add zebra route map rule */
61 static int zebra_route_match_add(struct vty *vty, const char *command,
62 const char *arg, route_map_event_t type)
63 {
64 VTY_DECLVAR_CONTEXT(route_map_index, index);
65 int ret;
66 int retval = CMD_SUCCESS;
67
68 ret = route_map_add_match(index, command, arg);
69 switch (ret) {
70 case RMAP_RULE_MISSING:
71 vty_out(vty, "%% Zebra Can't find rule.\n");
72 retval = CMD_WARNING_CONFIG_FAILED;
73 break;
74 case RMAP_COMPILE_ERROR:
75 vty_out(vty, "%% Zebra Argument is malformed.\n");
76 retval = CMD_WARNING_CONFIG_FAILED;
77 break;
78 case RMAP_COMPILE_SUCCESS:
79 if (type != RMAP_EVENT_MATCH_ADDED) {
80 route_map_upd8_dependency(type, arg, index->map->name);
81 }
82 break;
83 }
84
85 return retval;
86 }
87
88 /* Delete zebra route map rule. */
89 static int zebra_route_match_delete(struct vty *vty, const char *command,
90 const char *arg, route_map_event_t type)
91 {
92 VTY_DECLVAR_CONTEXT(route_map_index, index);
93 int ret;
94 int retval = CMD_SUCCESS;
95 char *dep_name = NULL;
96 const char *tmpstr;
97 char *rmap_name = NULL;
98
99 if (type != RMAP_EVENT_MATCH_DELETED) {
100 /* ignore the mundane, the types without any dependency */
101 if (arg == NULL) {
102 if ((tmpstr = route_map_get_match_arg(index, command))
103 != NULL)
104 dep_name =
105 XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
106 } else {
107 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
108 }
109 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
110 }
111
112 ret = route_map_delete_match(index, command, arg);
113 switch (ret) {
114 case RMAP_RULE_MISSING:
115 vty_out(vty, "%% Zebra Can't find rule.\n");
116 retval = CMD_WARNING_CONFIG_FAILED;
117 break;
118 case RMAP_COMPILE_ERROR:
119 vty_out(vty, "%% Zebra Argument is malformed.\n");
120 retval = CMD_WARNING_CONFIG_FAILED;
121 break;
122 case RMAP_COMPILE_SUCCESS:
123 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
124 route_map_upd8_dependency(type, dep_name, rmap_name);
125 break;
126 }
127
128 if (dep_name)
129 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
130 if (rmap_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, struct prefix *prefix,
140 route_map_object_t type, void *object)
141 {
142 route_tag_t *tag;
143 struct nh_rmap_obj *nh_data;
144
145 if (type == RMAP_ZEBRA) {
146 tag = rule;
147 nh_data = object;
148
149 if (nh_data->tag == *tag)
150 return RMAP_MATCH;
151 }
152 return RMAP_NOMATCH;
153 }
154
155 /* Route map commands for tag matching */
156 static struct route_map_rule_cmd route_match_tag_cmd = {
157 "tag", route_match_tag, route_map_rule_tag_compile,
158 route_map_rule_tag_free,
159 };
160
161
162 /* `match interface IFNAME' */
163 /* Match function return 1 if match is success else return zero. */
164 static route_map_result_t route_match_interface(void *rule,
165 struct prefix *prefix,
166 route_map_object_t type,
167 void *object)
168 {
169 struct nh_rmap_obj *nh_data;
170 char *ifname = rule;
171 ifindex_t ifindex;
172
173 if (type == RMAP_ZEBRA) {
174 if (strcasecmp(ifname, "any") == 0)
175 return RMAP_MATCH;
176 nh_data = object;
177 if (!nh_data || !nh_data->nexthop)
178 return RMAP_NOMATCH;
179 ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
180 if (ifindex == 0)
181 return RMAP_NOMATCH;
182 if (nh_data->nexthop->ifindex == ifindex)
183 return RMAP_MATCH;
184 }
185 return RMAP_NOMATCH;
186 }
187
188 /* Route map `match interface' match statement. `arg' is IFNAME value */
189 static void *route_match_interface_compile(const char *arg)
190 {
191 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
192 }
193
194 /* Free route map's compiled `match interface' value. */
195 static void route_match_interface_free(void *rule)
196 {
197 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
198 }
199
200 /* Route map commands for interface matching */
201 struct route_map_rule_cmd route_match_interface_cmd = {
202 "interface", route_match_interface, route_match_interface_compile,
203 route_match_interface_free};
204
205 DEFUN (match_ip_address_prefix_len,
206 match_ip_address_prefix_len_cmd,
207 "match ip address prefix-len (0-32)",
208 MATCH_STR
209 IP_STR
210 "Match prefix length of ip address\n"
211 "Match prefix length of ip address\n"
212 "Prefix length\n")
213 {
214 return zebra_route_match_add(vty, "ip address prefix-len", argv[4]->arg,
215 RMAP_EVENT_MATCH_ADDED);
216 }
217
218 DEFUN (no_match_ip_address_prefix_len,
219 no_match_ip_address_prefix_len_cmd,
220 "no match ip address prefix-len [(0-32)]",
221 NO_STR
222 MATCH_STR
223 IP_STR
224 "Match prefix length of ip address\n"
225 "Match prefix length of ip address\n"
226 "Prefix length\n")
227 {
228 char *plen = (argc == 6) ? argv[5]->arg : NULL;
229 return zebra_route_match_delete(vty, "ip address prefix-len", plen,
230 RMAP_EVENT_MATCH_DELETED);
231 }
232
233 DEFUN (match_ipv6_address_prefix_len,
234 match_ipv6_address_prefix_len_cmd,
235 "match ipv6 address prefix-len (0-128)",
236 MATCH_STR
237 IPV6_STR
238 "Match prefix length of ipv6 address\n"
239 "Match prefix length of ipv6 address\n"
240 "Prefix length\n")
241 {
242 return zebra_route_match_add(vty, "ipv6 address prefix-len",
243 argv[4]->arg, RMAP_EVENT_MATCH_ADDED);
244 }
245
246 DEFUN (no_match_ipv6_address_prefix_len,
247 no_match_ipv6_address_prefix_len_cmd,
248 "no match ipv6 address prefix-len [(0-128)]",
249 NO_STR
250 MATCH_STR
251 IPV6_STR
252 "Match prefix length of ip address\n"
253 "Match prefix length of ip address\n"
254 "Prefix length\n")
255 {
256 char *plen = (argc == 6) ? argv[5]->arg : NULL;
257 return zebra_route_match_delete(vty, "ipv6 address prefix-len", plen,
258 RMAP_EVENT_MATCH_DELETED);
259 }
260
261 DEFUN (match_ip_nexthop_prefix_len,
262 match_ip_nexthop_prefix_len_cmd,
263 "match ip next-hop prefix-len (0-32)",
264 MATCH_STR
265 IP_STR
266 "Match prefixlen of nexthop ip address\n"
267 "Match prefixlen of given nexthop\n"
268 "Prefix length\n")
269 {
270 return zebra_route_match_add(vty, "ip next-hop prefix-len",
271 argv[4]->arg, RMAP_EVENT_MATCH_ADDED);
272 }
273
274 DEFUN (no_match_ip_nexthop_prefix_len,
275 no_match_ip_nexthop_prefix_len_cmd,
276 "no match ip next-hop prefix-len [(0-32)]",
277 NO_STR
278 MATCH_STR
279 IP_STR
280 "Match prefixlen of nexthop ip address\n"
281 "Match prefix length of nexthop\n"
282 "Prefix length\n")
283 {
284 char *plen = (argc == 6) ? argv[5]->arg : NULL;
285 return zebra_route_match_delete(vty, "ip next-hop prefix-len", plen,
286 RMAP_EVENT_MATCH_DELETED);
287 }
288
289 DEFUN (match_source_protocol,
290 match_source_protocol_cmd,
291 "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>",
292 MATCH_STR
293 "Match protocol via which the route was learnt\n"
294 "BGP protocol\n"
295 "OSPF protocol\n"
296 "RIP protocol\n"
297 "RIPNG protocol\n"
298 "ISIS protocol\n"
299 "OSPF6 protocol\n"
300 "PIM protocol\n"
301 "NHRP protocol\n"
302 "EIGRP protocol\n"
303 "BABEL protocol\n"
304 "Routes from directly connected peer\n"
305 "Routes from system configuration\n"
306 "Routes from kernel\n"
307 "Statically configured routes\n"
308 "SHARP process\n")
309 {
310 char *proto = argv[2]->text;
311 int i;
312
313 i = proto_name2num(proto);
314 if (i < 0) {
315 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
316 return CMD_WARNING_CONFIG_FAILED;
317 }
318 return zebra_route_match_add(vty, "source-protocol", proto,
319 RMAP_EVENT_MATCH_ADDED);
320 }
321
322 DEFUN (no_match_source_protocol,
323 no_match_source_protocol_cmd,
324 "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>]",
325 NO_STR
326 MATCH_STR
327 "No match protocol via which the route was learnt\n"
328 "BGP protocol\n"
329 "OSPF protocol\n"
330 "RIP protocol\n"
331 "RIPNG protocol\n"
332 "ISIS protocol\n"
333 "OSPF6 protocol\n"
334 "PIM protocol\n"
335 "NHRP protocol\n"
336 "EIGRP protocol\n"
337 "BABEL protocol\n"
338 "Routes from directly connected peer\n"
339 "Routes from system configuration\n"
340 "Routes from kernel\n"
341 "Statically configured routes\n"
342 "SHARP process\n")
343 {
344 char *proto = (argc == 4) ? argv[3]->text : NULL;
345 return zebra_route_match_delete(vty, "source-protocol", proto,
346 RMAP_EVENT_MATCH_DELETED);
347 }
348
349 DEFUN (match_source_instance,
350 match_source_instance_cmd,
351 "match source-instance (0-255)",
352 MATCH_STR
353 "Match the protocol's instance number\n"
354 "The instance number\n")
355 {
356 char *instance = argv[2]->arg;
357
358 return zebra_route_match_add(vty, "source-instance", instance,
359 RMAP_EVENT_MATCH_ADDED);
360 }
361
362 DEFUN (no_match_source_instance,
363 no_match_source_instance_cmd,
364 "no match source-instance [(0-255)]",
365 NO_STR MATCH_STR
366 "Match the protocol's instance number\n"
367 "The instance number\n")
368 {
369 char *instance = (argc == 4) ? argv[3]->arg : NULL;
370
371 return zebra_route_match_delete(vty, "source-instance", instance,
372 RMAP_EVENT_MATCH_ADDED);
373 }
374
375 /* set functions */
376
377 DEFUN (set_src,
378 set_src_cmd,
379 "set src <A.B.C.D|X:X::X:X>",
380 SET_STR
381 "src address for route\n"
382 "IPv4 src address\n"
383 "IPv6 src address\n")
384 {
385 int idx_ip = 2;
386 union g_addr src;
387 struct interface *pif = NULL;
388 int family;
389 struct prefix p;
390 struct vrf *vrf;
391
392 if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) {
393 if (inet_pton(AF_INET6, argv[idx_ip]->arg, &src.ipv6) != 1) {
394 vty_out(vty, "%% not a valid IPv4/v6 address\n");
395 return CMD_WARNING_CONFIG_FAILED;
396 }
397
398 p.family = family = AF_INET6;
399 p.u.prefix6 = src.ipv6;
400 p.prefixlen = IPV6_MAX_BITLEN;
401 } else {
402 p.family = family = AF_INET;
403 p.u.prefix4 = src.ipv4;
404 p.prefixlen = IPV4_MAX_BITLEN;
405 }
406
407 if (!zebra_check_addr(&p)) {
408 vty_out(vty, "%% not a valid source IPv4/v6 address\n");
409 return CMD_WARNING_CONFIG_FAILED;
410 }
411
412 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
413 if (family == AF_INET)
414 pif = if_lookup_exact_address((void *)&src.ipv4,
415 AF_INET, vrf->vrf_id);
416 else if (family == AF_INET6)
417 pif = if_lookup_exact_address((void *)&src.ipv6,
418 AF_INET6, vrf->vrf_id);
419
420 if (pif != NULL)
421 break;
422 }
423
424 if (!pif) {
425 vty_out(vty, "%% not a local address\n");
426 return CMD_WARNING_CONFIG_FAILED;
427 }
428
429 VTY_DECLVAR_CONTEXT(route_map_index, index);
430 return generic_set_add(vty, index, "src", argv[idx_ip]->arg);
431 }
432
433 DEFUN (no_set_src,
434 no_set_src_cmd,
435 "no set src [<A.B.C.D|X:X::X:X>]",
436 NO_STR
437 SET_STR
438 "Source address for route\n"
439 "IPv4 address\n"
440 "IPv6 address\n")
441 {
442 char *ip = (argc == 4) ? argv[3]->arg : NULL;
443 VTY_DECLVAR_CONTEXT(route_map_index, index);
444 return generic_set_delete(vty, index, "src", ip);
445 }
446
447 DEFUN (zebra_route_map_timer,
448 zebra_route_map_timer_cmd,
449 "zebra route-map delay-timer (0-600)",
450 ZEBRA_STR
451 "Set route-map parameters\n"
452 "Time to wait before route-map updates are processed\n"
453 "0 means event-driven updates are disabled\n")
454 {
455 int idx_number = 3;
456 uint32_t rmap_delay_timer;
457
458 rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
459 zebra_route_map_set_delay_timer(rmap_delay_timer);
460
461 return (CMD_SUCCESS);
462 }
463
464 DEFUN (no_zebra_route_map_timer,
465 no_zebra_route_map_timer_cmd,
466 "no zebra route-map delay-timer [(0-600)]",
467 NO_STR
468 ZEBRA_STR
469 "Set route-map parameters\n"
470 "Reset delay-timer to default value, 30 secs\n"
471 "0 means event-driven updates are disabled\n")
472 {
473 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
474
475 return (CMD_SUCCESS);
476 }
477
478
479 DEFUN (ip_protocol,
480 ip_protocol_cmd,
481 "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
482 IP_STR
483 "Filter routing info exchanged between zebra and protocol\n"
484 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
485 "Specify route-map\n"
486 "Route map name\n")
487 {
488 char *proto = argv[2]->text;
489 char *rmap = argv[4]->arg;
490 int i;
491
492 if (strcasecmp(proto, "any") == 0)
493 i = ZEBRA_ROUTE_MAX;
494 else
495 i = proto_name2num(proto);
496 if (i < 0) {
497 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
498 return CMD_WARNING_CONFIG_FAILED;
499 }
500 if (proto_rm[AFI_IP][i]) {
501 if (strcmp(proto_rm[AFI_IP][i], rmap) == 0)
502 return CMD_SUCCESS;
503
504 XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
505 }
506 proto_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
507
508 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
509 zlog_debug(
510 "%u: IPv4 Routemap config for protocol %s, scheduling RIB processing",
511 VRF_DEFAULT, proto);
512
513 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
514 return CMD_SUCCESS;
515 }
516
517 DEFUN (no_ip_protocol,
518 no_ip_protocol_cmd,
519 "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
520 NO_STR
521 IP_STR
522 "Stop filtering routing info between zebra and protocol\n"
523 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
524 "Specify route map\n"
525 "Route map name\n")
526 {
527 char *proto = argv[3]->text;
528 char *rmap = (argc == 6) ? argv[5]->arg : NULL;
529 int i;
530
531 if (strcasecmp(proto, "any") == 0)
532 i = ZEBRA_ROUTE_MAX;
533 else
534 i = proto_name2num(proto);
535
536 if (i < 0) {
537 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
538 return CMD_WARNING_CONFIG_FAILED;
539 }
540
541 if (!proto_rm[AFI_IP][i])
542 return CMD_SUCCESS;
543
544 if (!rmap || strcmp(rmap, proto_rm[AFI_IP][i]) == 0) {
545 XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
546 proto_rm[AFI_IP][i] = NULL;
547
548 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
549 zlog_debug(
550 "%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing",
551 VRF_DEFAULT, proto);
552 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
553 }
554 return CMD_SUCCESS;
555 }
556
557 DEFUN (show_ip_protocol,
558 show_ip_protocol_cmd,
559 "show ip protocol",
560 SHOW_STR
561 IP_STR
562 "IP protocol filtering status\n")
563 {
564 int i;
565
566 vty_out(vty, "Protocol : route-map \n");
567 vty_out(vty, "------------------------\n");
568 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
569 if (proto_rm[AFI_IP][i])
570 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
571 proto_rm[AFI_IP][i]);
572 else
573 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
574 }
575 if (proto_rm[AFI_IP][i])
576 vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP][i]);
577 else
578 vty_out(vty, "%-10s : none\n", "any");
579
580 return CMD_SUCCESS;
581 }
582
583 DEFUN (ipv6_protocol,
584 ipv6_protocol_cmd,
585 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
586 IP6_STR
587 "Filter IPv6 routing info exchanged between zebra and protocol\n"
588 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
589 "Specify route map\n"
590 "Route map name\n")
591 {
592 char *proto = argv[2]->text;
593 char *rmap = argv[4]->arg;
594 int i;
595
596 if (strcasecmp(proto, "any") == 0)
597 i = ZEBRA_ROUTE_MAX;
598 else
599 i = proto_name2num(proto);
600 if (i < 0) {
601 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
602 return CMD_WARNING_CONFIG_FAILED;
603 }
604 if (proto_rm[AFI_IP6][i]) {
605 if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0)
606 return CMD_SUCCESS;
607
608 XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
609 }
610 proto_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
611
612 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
613 zlog_debug(
614 "%u: IPv6 Routemap config for protocol %s, scheduling RIB processing",
615 VRF_DEFAULT, proto);
616
617 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
618 return CMD_SUCCESS;
619 }
620
621 DEFUN (no_ipv6_protocol,
622 no_ipv6_protocol_cmd,
623 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
624 NO_STR
625 IP6_STR
626 "Stop filtering IPv6 routing info between zebra and protocol\n"
627 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
628 "Specify route map\n"
629 "Route map name\n")
630 {
631 const char *proto = argv[3]->text;
632 const char *rmap = (argc == 6) ? argv[5]->arg : NULL;
633 int i;
634
635 if (strcasecmp(proto, "any") == 0)
636 i = ZEBRA_ROUTE_MAX;
637 else
638 i = proto_name2num(proto);
639 if (i < 0) {
640 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
641 return CMD_WARNING_CONFIG_FAILED;
642 }
643 if (!proto_rm[AFI_IP6][i])
644 return CMD_SUCCESS;
645
646 if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0) {
647 XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
648 proto_rm[AFI_IP6][i] = NULL;
649
650 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
651 zlog_debug(
652 "%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing",
653 VRF_DEFAULT, proto);
654
655 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
656 }
657 return CMD_SUCCESS;
658 }
659
660 DEFUN (show_ipv6_protocol,
661 show_ipv6_protocol_cmd,
662 "show ipv6 protocol",
663 SHOW_STR
664 IP6_STR
665 "IPv6 protocol filtering status\n")
666 {
667 int i;
668
669 vty_out(vty, "Protocol : route-map \n");
670 vty_out(vty, "------------------------\n");
671 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
672 if (proto_rm[AFI_IP6][i])
673 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
674 proto_rm[AFI_IP6][i]);
675 else
676 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
677 }
678 if (proto_rm[AFI_IP6][i])
679 vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP6][i]);
680 else
681 vty_out(vty, "%-10s : none\n", "any");
682
683 return CMD_SUCCESS;
684 }
685
686 DEFUN (ip_protocol_nht_rmap,
687 ip_protocol_nht_rmap_cmd,
688 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
689 IP_STR
690 "Filter Next Hop tracking route resolution\n"
691 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
692 "Specify route map\n"
693 "Route map name\n")
694 {
695 char *proto = argv[2]->text;
696 char *rmap = argv[4]->arg;
697 int i;
698
699 if (strcasecmp(proto, "any") == 0)
700 i = ZEBRA_ROUTE_MAX;
701 else
702 i = proto_name2num(proto);
703 if (i < 0) {
704 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
705 return CMD_WARNING_CONFIG_FAILED;
706 }
707 if (nht_rm[AFI_IP][i]) {
708 if (strcmp(nht_rm[AFI_IP][i], rmap) == 0)
709 return CMD_SUCCESS;
710
711 XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
712 }
713
714 nht_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
715 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
716
717 return CMD_SUCCESS;
718 }
719
720 DEFUN (no_ip_protocol_nht_rmap,
721 no_ip_protocol_nht_rmap_cmd,
722 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
723 NO_STR
724 IP_STR
725 "Filter Next Hop tracking route resolution\n"
726 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
727 "Specify route map\n"
728 "Route map name\n")
729 {
730 int idx = 0;
731 char *proto = argv[3]->text;
732 char *rmap = argv_find(argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg
733 : NULL;
734
735 int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX
736 : proto_name2num(proto);
737
738 if (i < 0) {
739 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
740 return CMD_WARNING_CONFIG_FAILED;
741 }
742
743 if (!nht_rm[AFI_IP][i])
744 return CMD_SUCCESS;
745
746 if (!rmap || strcmp(rmap, nht_rm[AFI_IP][i]) == 0) {
747 XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
748 nht_rm[AFI_IP][i] = NULL;
749 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
750 }
751 return CMD_SUCCESS;
752 }
753
754 DEFUN (show_ip_protocol_nht,
755 show_ip_protocol_nht_cmd,
756 "show ip nht route-map",
757 SHOW_STR
758 IP_STR
759 "IP nexthop tracking table\n"
760 "IP Next Hop tracking filtering status\n")
761 {
762 int i;
763
764 vty_out(vty, "Protocol : route-map \n");
765 vty_out(vty, "------------------------\n");
766 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
767 if (nht_rm[AFI_IP][i])
768 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
769 nht_rm[AFI_IP][i]);
770 else
771 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
772 }
773 if (nht_rm[AFI_IP][i])
774 vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP][i]);
775 else
776 vty_out(vty, "%-10s : none\n", "any");
777
778 return CMD_SUCCESS;
779 }
780
781 DEFUN (ipv6_protocol_nht_rmap,
782 ipv6_protocol_nht_rmap_cmd,
783 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
784 IP6_STR
785 "Filter Next Hop tracking route resolution\n"
786 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
787 "Specify route map\n"
788 "Route map name\n")
789 {
790 char *proto = argv[2]->text;
791 char *rmap = argv[4]->arg;
792 int i;
793
794 if (strcasecmp(proto, "any") == 0)
795 i = ZEBRA_ROUTE_MAX;
796 else
797 i = proto_name2num(proto);
798 if (i < 0) {
799 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
800 return CMD_WARNING_CONFIG_FAILED;
801 }
802 if (nht_rm[AFI_IP6][i])
803 XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
804 nht_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
805 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
806
807 return CMD_SUCCESS;
808 }
809
810 DEFUN (no_ipv6_protocol_nht_rmap,
811 no_ipv6_protocol_nht_rmap_cmd,
812 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
813 NO_STR
814 IP6_STR
815 "Filter Next Hop tracking route resolution\n"
816 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
817 "Specify route map\n"
818 "Route map name\n")
819 {
820 char *proto = argv[3]->text;
821 char *rmap = (argc == 6) ? argv[5]->arg : NULL;
822 int i;
823
824 if (strcasecmp(proto, "any") == 0)
825 i = ZEBRA_ROUTE_MAX;
826 else
827 i = proto_name2num(proto);
828 if (i < 0) {
829 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
830 return CMD_WARNING_CONFIG_FAILED;
831 }
832
833 if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i])) {
834 vty_out(vty, "invalid route-map \"%s\"\n", rmap);
835 return CMD_WARNING_CONFIG_FAILED;
836 }
837
838 if (nht_rm[AFI_IP6][i]) {
839 XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
840 nht_rm[AFI_IP6][i] = NULL;
841 }
842
843 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
844
845 return CMD_SUCCESS;
846 }
847
848 DEFUN (show_ipv6_protocol_nht,
849 show_ipv6_protocol_nht_cmd,
850 "show ipv6 nht route-map",
851 SHOW_STR
852 IP6_STR
853 "Next Hop filtering status\n"
854 "Route-map\n")
855 {
856 int i;
857
858 vty_out(vty, "Protocol : route-map \n");
859 vty_out(vty, "------------------------\n");
860 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
861 if (nht_rm[AFI_IP6][i])
862 vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i),
863 nht_rm[AFI_IP6][i]);
864 else
865 vty_out(vty, "%-10s : none\n", zebra_route_string(i));
866 }
867 if (nht_rm[AFI_IP][i])
868 vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP6][i]);
869 else
870 vty_out(vty, "%-10s : none\n", "any");
871
872 return CMD_SUCCESS;
873 }
874
875 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
876
877 /* `match ip next-hop IP_ACCESS_LIST' */
878
879 /* Match function return 1 if match is success else return zero. */
880 static route_map_result_t route_match_ip_next_hop(void *rule,
881 struct prefix *prefix,
882 route_map_object_t type,
883 void *object)
884 {
885 struct access_list *alist;
886 struct nh_rmap_obj *nh_data;
887 struct prefix_ipv4 p;
888
889 if (type == RMAP_ZEBRA) {
890 nh_data = object;
891 if (!nh_data)
892 return RMAP_DENYMATCH;
893
894 switch (nh_data->nexthop->type) {
895 case NEXTHOP_TYPE_IFINDEX:
896 /* Interface routes can't match ip next-hop */
897 return RMAP_NOMATCH;
898 case NEXTHOP_TYPE_IPV4_IFINDEX:
899 case NEXTHOP_TYPE_IPV4:
900 p.family = AF_INET;
901 p.prefix = nh_data->nexthop->gate.ipv4;
902 p.prefixlen = IPV4_MAX_BITLEN;
903 break;
904 default:
905 return RMAP_NOMATCH;
906 }
907 alist = access_list_lookup(AFI_IP, (char *)rule);
908 if (alist == NULL)
909 return RMAP_NOMATCH;
910
911 return (access_list_apply(alist, &p) == FILTER_DENY
912 ? RMAP_NOMATCH
913 : RMAP_MATCH);
914 }
915 return RMAP_NOMATCH;
916 }
917
918 /* Route map `ip next-hop' match statement. `arg' should be
919 access-list name. */
920 static void *route_match_ip_next_hop_compile(const char *arg)
921 {
922 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
923 }
924
925 /* Free route map's compiled `. */
926 static void route_match_ip_next_hop_free(void *rule)
927 {
928 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
929 }
930
931 /* Route map commands for ip next-hop matching. */
932 static struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
933 "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile,
934 route_match_ip_next_hop_free};
935
936 /* `match ip next-hop prefix-list PREFIX_LIST' */
937
938 static route_map_result_t
939 route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix,
940 route_map_object_t type, void *object)
941 {
942 struct prefix_list *plist;
943 struct nh_rmap_obj *nh_data;
944 struct prefix_ipv4 p;
945
946 if (type == RMAP_ZEBRA) {
947 nh_data = (struct nh_rmap_obj *)object;
948 if (!nh_data)
949 return RMAP_DENYMATCH;
950
951 switch (nh_data->nexthop->type) {
952 case NEXTHOP_TYPE_IFINDEX:
953 /* Interface routes can't match ip next-hop */
954 return RMAP_NOMATCH;
955 case NEXTHOP_TYPE_IPV4_IFINDEX:
956 case NEXTHOP_TYPE_IPV4:
957 p.family = AF_INET;
958 p.prefix = nh_data->nexthop->gate.ipv4;
959 p.prefixlen = IPV4_MAX_BITLEN;
960 break;
961 default:
962 return RMAP_NOMATCH;
963 }
964 plist = prefix_list_lookup(AFI_IP, (char *)rule);
965 if (plist == NULL)
966 return RMAP_NOMATCH;
967
968 return (prefix_list_apply(plist, &p) == PREFIX_DENY
969 ? RMAP_NOMATCH
970 : RMAP_MATCH);
971 }
972 return RMAP_NOMATCH;
973 }
974
975 static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
976 {
977 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
978 }
979
980 static void route_match_ip_next_hop_prefix_list_free(void *rule)
981 {
982 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
983 }
984
985 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
986 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list,
987 route_match_ip_next_hop_prefix_list_compile,
988 route_match_ip_next_hop_prefix_list_free};
989
990 /* `match ip address IP_ACCESS_LIST' */
991
992 /* Match function should return 1 if match is success else return
993 zero. */
994 static route_map_result_t route_match_ip_address(void *rule,
995 struct prefix *prefix,
996 route_map_object_t type,
997 void *object)
998 {
999 struct access_list *alist;
1000
1001 if (type == RMAP_ZEBRA) {
1002 alist = access_list_lookup(AFI_IP, (char *)rule);
1003 if (alist == NULL)
1004 return RMAP_NOMATCH;
1005
1006 return (access_list_apply(alist, prefix) == FILTER_DENY
1007 ? RMAP_NOMATCH
1008 : RMAP_MATCH);
1009 }
1010 return RMAP_NOMATCH;
1011 }
1012
1013 /* Route map `ip address' match statement. `arg' should be
1014 access-list name. */
1015 static void *route_match_ip_address_compile(const char *arg)
1016 {
1017 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1018 }
1019
1020 /* Free route map's compiled `ip address' value. */
1021 static void route_match_ip_address_free(void *rule)
1022 {
1023 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1024 }
1025
1026 /* Route map commands for ip address matching. */
1027 static struct route_map_rule_cmd route_match_ip_address_cmd = {
1028 "ip address", route_match_ip_address, route_match_ip_address_compile,
1029 route_match_ip_address_free};
1030
1031 /* `match ip address prefix-list PREFIX_LIST' */
1032
1033 static route_map_result_t
1034 route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
1035 route_map_object_t type, void *object)
1036 {
1037 struct prefix_list *plist;
1038
1039 if (type == RMAP_ZEBRA) {
1040 plist = prefix_list_lookup(AFI_IP, (char *)rule);
1041 if (plist == NULL)
1042 return RMAP_NOMATCH;
1043
1044 return (prefix_list_apply(plist, prefix) == PREFIX_DENY
1045 ? RMAP_NOMATCH
1046 : RMAP_MATCH);
1047 }
1048 return RMAP_NOMATCH;
1049 }
1050
1051 static void *route_match_ip_address_prefix_list_compile(const char *arg)
1052 {
1053 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1054 }
1055
1056 static void route_match_ip_address_prefix_list_free(void *rule)
1057 {
1058 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1059 }
1060
1061 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
1062 "ip address prefix-list", route_match_ip_address_prefix_list,
1063 route_match_ip_address_prefix_list_compile,
1064 route_match_ip_address_prefix_list_free};
1065
1066
1067 /* `match ip address prefix-len PREFIXLEN' */
1068
1069 static route_map_result_t
1070 route_match_address_prefix_len(void *rule, struct prefix *prefix,
1071 route_map_object_t type, void *object)
1072 {
1073 uint32_t *prefixlen = (uint32_t *)rule;
1074
1075 if (type == RMAP_ZEBRA) {
1076 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH
1077 : RMAP_NOMATCH);
1078 }
1079 return RMAP_NOMATCH;
1080 }
1081
1082 static void *route_match_address_prefix_len_compile(const char *arg)
1083 {
1084 uint32_t *prefix_len;
1085 char *endptr = NULL;
1086 unsigned long tmpval;
1087
1088 /* prefix len value shoud be integer. */
1089 if (!all_digit(arg))
1090 return NULL;
1091
1092 errno = 0;
1093 tmpval = strtoul(arg, &endptr, 10);
1094 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1095 return NULL;
1096
1097 prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1098
1099 if (!prefix_len)
1100 return prefix_len;
1101
1102 *prefix_len = tmpval;
1103 return prefix_len;
1104 }
1105
1106 static void route_match_address_prefix_len_free(void *rule)
1107 {
1108 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1109 }
1110
1111 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = {
1112 "ip address prefix-len", route_match_address_prefix_len,
1113 route_match_address_prefix_len_compile,
1114 route_match_address_prefix_len_free};
1115
1116 static struct route_map_rule_cmd route_match_ipv6_address_prefix_len_cmd = {
1117 "ipv6 address prefix-len", route_match_address_prefix_len,
1118 route_match_address_prefix_len_compile,
1119 route_match_address_prefix_len_free};
1120
1121 /* `match ip nexthop prefix-len PREFIXLEN' */
1122
1123 static route_map_result_t
1124 route_match_ip_nexthop_prefix_len(void *rule, struct prefix *prefix,
1125 route_map_object_t type, void *object)
1126 {
1127 uint32_t *prefixlen = (uint32_t *)rule;
1128 struct nh_rmap_obj *nh_data;
1129 struct prefix_ipv4 p;
1130
1131 if (type == RMAP_ZEBRA) {
1132 nh_data = (struct nh_rmap_obj *)object;
1133 if (!nh_data || !nh_data->nexthop)
1134 return RMAP_DENYMATCH;
1135
1136 switch (nh_data->nexthop->type) {
1137 case NEXTHOP_TYPE_IFINDEX:
1138 /* Interface routes can't match ip next-hop */
1139 return RMAP_NOMATCH;
1140 case NEXTHOP_TYPE_IPV4_IFINDEX:
1141 case NEXTHOP_TYPE_IPV4:
1142 p.family = AF_INET;
1143 p.prefix = nh_data->nexthop->gate.ipv4;
1144 p.prefixlen = IPV4_MAX_BITLEN;
1145 break;
1146 default:
1147 return RMAP_NOMATCH;
1148 }
1149 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH
1150 : RMAP_NOMATCH);
1151 }
1152 return RMAP_NOMATCH;
1153 }
1154
1155 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = {
1156 "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len,
1157 route_match_address_prefix_len_compile, /* reuse */
1158 route_match_address_prefix_len_free /* reuse */
1159 };
1160
1161 /* `match source-protocol PROTOCOL' */
1162
1163 static route_map_result_t route_match_source_protocol(void *rule,
1164 struct prefix *prefix,
1165 route_map_object_t type,
1166 void *object)
1167 {
1168 uint32_t *rib_type = (uint32_t *)rule;
1169 struct nh_rmap_obj *nh_data;
1170
1171 if (type == RMAP_ZEBRA) {
1172 nh_data = (struct nh_rmap_obj *)object;
1173 if (!nh_data)
1174 return RMAP_DENYMATCH;
1175
1176 return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
1177 : RMAP_NOMATCH);
1178 }
1179 return RMAP_NOMATCH;
1180 }
1181
1182 static void *route_match_source_protocol_compile(const char *arg)
1183 {
1184 uint32_t *rib_type;
1185 int i;
1186
1187 i = proto_name2num(arg);
1188 rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1189
1190 *rib_type = i;
1191
1192 return rib_type;
1193 }
1194
1195 static void route_match_source_protocol_free(void *rule)
1196 {
1197 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1198 }
1199
1200 static struct route_map_rule_cmd route_match_source_protocol_cmd = {
1201 "source-protocol", route_match_source_protocol,
1202 route_match_source_protocol_compile, route_match_source_protocol_free};
1203
1204 /* `source-instance` */
1205 static route_map_result_t route_match_source_instance(void *rule,
1206 struct prefix *prefix,
1207 route_map_object_t type,
1208 void *object)
1209 {
1210 uint8_t *instance = (uint8_t *)rule;
1211 struct nh_rmap_obj *nh_data;
1212
1213 if (type != RMAP_ZEBRA)
1214 return RMAP_NOMATCH;
1215
1216 nh_data = (struct nh_rmap_obj *)object;
1217 if (!nh_data)
1218 return RMAP_DENYMATCH;
1219
1220 return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
1221 }
1222
1223 static void *route_match_source_instance_compile(const char *arg)
1224 {
1225 uint8_t *instance;
1226 int i;
1227
1228 i = atoi(arg);
1229 instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1230
1231 *instance = i;
1232
1233 return instance;
1234 }
1235
1236 static void route_match_source_instance_free(void *rule)
1237 {
1238 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1239 }
1240
1241 static struct route_map_rule_cmd route_match_source_instance_cmd = {
1242 "source-instance", route_match_source_instance,
1243 route_match_source_instance_compile, route_match_source_instance_free};
1244
1245 /* `set src A.B.C.D' */
1246
1247 /* Set src. */
1248 static route_map_result_t route_set_src(void *rule, struct prefix *prefix,
1249 route_map_object_t type, void *object)
1250 {
1251 struct nh_rmap_obj *nh_data;
1252
1253 if (type == RMAP_ZEBRA) {
1254 nh_data = (struct nh_rmap_obj *)object;
1255 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1256 }
1257 return RMAP_OKAY;
1258 }
1259
1260 /* set src compilation. */
1261 static void *route_set_src_compile(const char *arg)
1262 {
1263 union g_addr src, *psrc;
1264
1265 if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1)
1266 || (inet_pton(AF_INET, arg, &src.ipv4) == 1)) {
1267 psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr));
1268 *psrc = src;
1269 return psrc;
1270 }
1271 return NULL;
1272 }
1273
1274 /* Free route map's compiled `set src' value. */
1275 static void route_set_src_free(void *rule)
1276 {
1277 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1278 }
1279
1280 /* Set src rule structure. */
1281 static struct route_map_rule_cmd route_set_src_cmd = {
1282 "src", route_set_src, route_set_src_compile, route_set_src_free,
1283 };
1284
1285 static int zebra_route_map_process_update_cb(char *rmap_name)
1286 {
1287 if (IS_ZEBRA_DEBUG_EVENT)
1288 zlog_debug("Event handler for route-map: %s",
1289 rmap_name);
1290
1291 return 0;
1292 }
1293
1294 static int zebra_route_map_update_timer(struct thread *thread)
1295 {
1296 zebra_t_rmap_update = NULL;
1297
1298 if (IS_ZEBRA_DEBUG_EVENT)
1299 zlog_debug("Event driven route-map update triggered");
1300
1301 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1302 zlog_debug(
1303 "%u: Routemap update-timer fired, scheduling RIB processing",
1304 VRF_DEFAULT);
1305
1306 route_map_walk_update_list(zebra_route_map_process_update_cb);
1307
1308 /*
1309 * This code needs to be updated to be:
1310 * 1) VRF Aware <sigh>
1311 * 2) Route-map aware
1312 */
1313 zebra_import_table_rm_update();
1314 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
1315 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1316 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1317
1318 return (0);
1319 }
1320
1321 static void zebra_route_map_set_delay_timer(uint32_t value)
1322 {
1323 zebra_rmap_update_timer = value;
1324 if (!value && zebra_t_rmap_update) {
1325 /* Event driven route map updates is being disabled */
1326 /* But there's a pending timer. Fire it off now */
1327 thread_cancel(zebra_t_rmap_update);
1328 zebra_route_map_update_timer(zebra_t_rmap_update);
1329 }
1330 }
1331
1332 void zebra_route_map_write_delay_timer(struct vty *vty)
1333 {
1334 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1335 vty_out(vty, "zebra route-map delay-timer %d\n",
1336 zebra_rmap_update_timer);
1337 return;
1338 }
1339
1340 route_map_result_t zebra_route_map_check(int family, int rib_type,
1341 uint8_t instance, struct prefix *p,
1342 struct nexthop *nexthop,
1343 vrf_id_t vrf_id, route_tag_t tag)
1344 {
1345 struct route_map *rmap = NULL;
1346 route_map_result_t ret = RMAP_MATCH;
1347 struct nh_rmap_obj nh_obj;
1348
1349 nh_obj.nexthop = nexthop;
1350 nh_obj.vrf_id = vrf_id;
1351 nh_obj.source_protocol = rib_type;
1352 nh_obj.instance = instance;
1353 nh_obj.metric = 0;
1354 nh_obj.tag = tag;
1355
1356 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1357 rmap = route_map_lookup_by_name(proto_rm[family][rib_type]);
1358 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1359 rmap = route_map_lookup_by_name(
1360 proto_rm[family][ZEBRA_ROUTE_MAX]);
1361 if (rmap) {
1362 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1363 }
1364
1365 return (ret);
1366 }
1367
1368 char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
1369 {
1370 return zebra_import_table_routemap[afi][table];
1371 }
1372
1373 void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
1374 uint32_t table)
1375 {
1376 zebra_import_table_routemap[afi][table] =
1377 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
1378 }
1379
1380 void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
1381 {
1382 XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1383 }
1384
1385 route_map_result_t
1386 zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
1387 struct prefix *p, struct nexthop *nexthop,
1388 vrf_id_t vrf_id, route_tag_t tag,
1389 const char *rmap_name)
1390 {
1391 struct route_map *rmap = NULL;
1392 route_map_result_t ret = RMAP_DENYMATCH;
1393 struct nh_rmap_obj nh_obj;
1394
1395 nh_obj.nexthop = nexthop;
1396 nh_obj.vrf_id = vrf_id;
1397 nh_obj.source_protocol = re_type;
1398 nh_obj.instance = instance;
1399 nh_obj.metric = 0;
1400 nh_obj.tag = tag;
1401
1402 if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1403 rmap = route_map_lookup_by_name(rmap_name);
1404 if (rmap) {
1405 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1406 }
1407
1408 return (ret);
1409 }
1410
1411 route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
1412 struct prefix *p,
1413 struct route_entry *re,
1414 struct nexthop *nexthop)
1415 {
1416 struct route_map *rmap = NULL;
1417 route_map_result_t ret = RMAP_MATCH;
1418 struct nh_rmap_obj nh_obj;
1419
1420 nh_obj.nexthop = nexthop;
1421 nh_obj.vrf_id = nexthop->vrf_id;
1422 nh_obj.source_protocol = re->type;
1423 nh_obj.instance = re->instance;
1424 nh_obj.metric = re->metric;
1425 nh_obj.tag = re->tag;
1426
1427 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1428 rmap = route_map_lookup_by_name(nht_rm[family][client_proto]);
1429 if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX])
1430 rmap = route_map_lookup_by_name(
1431 nht_rm[family][ZEBRA_ROUTE_MAX]);
1432 if (rmap) {
1433 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1434 }
1435
1436 return (ret);
1437 }
1438
1439 static void zebra_route_map_mark_update(const char *rmap_name)
1440 {
1441 /* rmap_update_timer of 0 means don't do route updates */
1442 if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
1443 zebra_t_rmap_update = NULL;
1444 thread_add_timer(zebrad.master, zebra_route_map_update_timer,
1445 NULL, zebra_rmap_update_timer,
1446 &zebra_t_rmap_update);
1447 }
1448 }
1449
1450 static void zebra_route_map_add(const char *rmap_name)
1451 {
1452 if (route_map_mark_updated(rmap_name) == 0)
1453 zebra_route_map_mark_update(rmap_name);
1454
1455 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1456 }
1457
1458 static void zebra_route_map_delete(const char *rmap_name)
1459 {
1460 if (route_map_mark_updated(rmap_name) == 0)
1461 zebra_route_map_mark_update(rmap_name);
1462
1463 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1464 }
1465
1466 static void zebra_route_map_event(route_map_event_t event,
1467 const char *rmap_name)
1468 {
1469 if (route_map_mark_updated(rmap_name) == 0)
1470 zebra_route_map_mark_update(rmap_name);
1471
1472 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1473 }
1474
1475 /* ip protocol configuration write function */
1476 void zebra_routemap_config_write_protocol(struct vty *vty)
1477 {
1478 int i;
1479
1480 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1481 if (proto_rm[AFI_IP][i])
1482 vty_out(vty, "ip protocol %s route-map %s\n",
1483 zebra_route_string(i), proto_rm[AFI_IP][i]);
1484
1485 if (proto_rm[AFI_IP6][i])
1486 vty_out(vty, "ipv6 protocol %s route-map %s\n",
1487 zebra_route_string(i), proto_rm[AFI_IP6][i]);
1488
1489 if (nht_rm[AFI_IP][i])
1490 vty_out(vty, "ip nht %s route-map %s\n",
1491 zebra_route_string(i), nht_rm[AFI_IP][i]);
1492
1493 if (nht_rm[AFI_IP6][i])
1494 vty_out(vty, "ipv6 nht %s route-map %s\n",
1495 zebra_route_string(i), nht_rm[AFI_IP6][i]);
1496 }
1497
1498 if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1499 vty_out(vty, "ip protocol %s route-map %s\n", "any",
1500 proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]);
1501
1502 if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1503 vty_out(vty, "ipv6 protocol %s route-map %s\n", "any",
1504 proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]);
1505
1506 if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1507 vty_out(vty, "ip nht %s route-map %s\n", "any",
1508 nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]);
1509
1510 if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1511 vty_out(vty, "ipv6 nht %s route-map %s\n", "any",
1512 nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]);
1513
1514 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1515 vty_out(vty, "zebra route-map delay-timer %d\n",
1516 zebra_rmap_update_timer);
1517 }
1518
1519 void zebra_route_map_init()
1520 {
1521 install_element(CONFIG_NODE, &ip_protocol_cmd);
1522 install_element(CONFIG_NODE, &no_ip_protocol_cmd);
1523 install_element(VIEW_NODE, &show_ip_protocol_cmd);
1524 install_element(CONFIG_NODE, &ipv6_protocol_cmd);
1525 install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
1526 install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
1527 install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1528 install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1529 install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
1530 install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1531 install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1532 install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1533 install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
1534 install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1535
1536 route_map_init();
1537
1538 route_map_add_hook(zebra_route_map_add);
1539 route_map_delete_hook(zebra_route_map_delete);
1540 route_map_event_hook(zebra_route_map_event);
1541
1542 route_map_match_interface_hook(generic_match_add);
1543 route_map_no_match_interface_hook(generic_match_delete);
1544
1545 route_map_match_ip_address_hook(generic_match_add);
1546 route_map_no_match_ip_address_hook(generic_match_delete);
1547
1548 route_map_match_ip_address_prefix_list_hook(generic_match_add);
1549 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
1550
1551 route_map_match_ip_next_hop_hook(generic_match_add);
1552 route_map_no_match_ip_next_hop_hook(generic_match_delete);
1553
1554 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
1555 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
1556
1557 route_map_match_tag_hook(generic_match_add);
1558 route_map_no_match_tag_hook(generic_match_delete);
1559
1560 route_map_install_match(&route_match_tag_cmd);
1561 route_map_install_match(&route_match_interface_cmd);
1562 route_map_install_match(&route_match_ip_next_hop_cmd);
1563 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
1564 route_map_install_match(&route_match_ip_address_cmd);
1565 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
1566 route_map_install_match(&route_match_ip_address_prefix_len_cmd);
1567 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
1568 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
1569 route_map_install_match(&route_match_source_protocol_cmd);
1570 route_map_install_match(&route_match_source_instance_cmd);
1571
1572 /* */
1573 route_map_install_set(&route_set_src_cmd);
1574 /* */
1575 install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
1576 install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
1577 install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
1578 install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
1579 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
1580 install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
1581 install_element(RMAP_NODE, &match_source_protocol_cmd);
1582 install_element(RMAP_NODE, &no_match_source_protocol_cmd);
1583 install_element(RMAP_NODE, &match_source_instance_cmd);
1584 install_element(RMAP_NODE, &no_match_source_instance_cmd);
1585
1586 /* */
1587 install_element(RMAP_NODE, &set_src_cmd);
1588 install_element(RMAP_NODE, &no_set_src_cmd);
1589 }