]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
Merge pull request #2220 from LabNConsulting/working/master/fix-asan
[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_update_timer(struct thread *thread)
1286 {
1287 zebra_t_rmap_update = NULL;
1288
1289 if (IS_ZEBRA_DEBUG_EVENT)
1290 zlog_debug("Event driven route-map update triggered");
1291
1292 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1293 zlog_debug(
1294 "%u: Routemap update-timer fired, scheduling RIB processing",
1295 VRF_DEFAULT);
1296
1297 zebra_import_table_rm_update();
1298 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
1299 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1300 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1301
1302 return (0);
1303 }
1304
1305 static void zebra_route_map_set_delay_timer(uint32_t value)
1306 {
1307 zebra_rmap_update_timer = value;
1308 if (!value && zebra_t_rmap_update) {
1309 /* Event driven route map updates is being disabled */
1310 /* But there's a pending timer. Fire it off now */
1311 thread_cancel(zebra_t_rmap_update);
1312 zebra_route_map_update_timer(zebra_t_rmap_update);
1313 }
1314 }
1315
1316 void zebra_route_map_write_delay_timer(struct vty *vty)
1317 {
1318 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1319 vty_out(vty, "zebra route-map delay-timer %d\n",
1320 zebra_rmap_update_timer);
1321 return;
1322 }
1323
1324 route_map_result_t zebra_route_map_check(int family, int rib_type,
1325 uint8_t instance, struct prefix *p,
1326 struct nexthop *nexthop,
1327 vrf_id_t vrf_id, route_tag_t tag)
1328 {
1329 struct route_map *rmap = NULL;
1330 route_map_result_t ret = RMAP_MATCH;
1331 struct nh_rmap_obj nh_obj;
1332
1333 nh_obj.nexthop = nexthop;
1334 nh_obj.vrf_id = vrf_id;
1335 nh_obj.source_protocol = rib_type;
1336 nh_obj.instance = instance;
1337 nh_obj.metric = 0;
1338 nh_obj.tag = tag;
1339
1340 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1341 rmap = route_map_lookup_by_name(proto_rm[family][rib_type]);
1342 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1343 rmap = route_map_lookup_by_name(
1344 proto_rm[family][ZEBRA_ROUTE_MAX]);
1345 if (rmap) {
1346 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1347 }
1348
1349 return (ret);
1350 }
1351
1352 char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
1353 {
1354 return zebra_import_table_routemap[afi][table];
1355 }
1356
1357 void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
1358 uint32_t table)
1359 {
1360 zebra_import_table_routemap[afi][table] =
1361 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
1362 }
1363
1364 void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
1365 {
1366 XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1367 }
1368
1369 route_map_result_t
1370 zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
1371 struct prefix *p, struct nexthop *nexthop,
1372 vrf_id_t vrf_id, route_tag_t tag,
1373 const char *rmap_name)
1374 {
1375 struct route_map *rmap = NULL;
1376 route_map_result_t ret = RMAP_DENYMATCH;
1377 struct nh_rmap_obj nh_obj;
1378
1379 nh_obj.nexthop = nexthop;
1380 nh_obj.vrf_id = vrf_id;
1381 nh_obj.source_protocol = re_type;
1382 nh_obj.instance = instance;
1383 nh_obj.metric = 0;
1384 nh_obj.tag = tag;
1385
1386 if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1387 rmap = route_map_lookup_by_name(rmap_name);
1388 if (rmap) {
1389 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1390 }
1391
1392 return (ret);
1393 }
1394
1395 route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
1396 struct prefix *p,
1397 struct route_entry *re,
1398 struct nexthop *nexthop)
1399 {
1400 struct route_map *rmap = NULL;
1401 route_map_result_t ret = RMAP_MATCH;
1402 struct nh_rmap_obj nh_obj;
1403
1404 nh_obj.nexthop = nexthop;
1405 nh_obj.vrf_id = nexthop->vrf_id;
1406 nh_obj.source_protocol = re->type;
1407 nh_obj.instance = re->instance;
1408 nh_obj.metric = re->metric;
1409 nh_obj.tag = re->tag;
1410
1411 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1412 rmap = route_map_lookup_by_name(nht_rm[family][client_proto]);
1413 if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX])
1414 rmap = route_map_lookup_by_name(
1415 nht_rm[family][ZEBRA_ROUTE_MAX]);
1416 if (rmap) {
1417 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1418 }
1419
1420 return (ret);
1421 }
1422
1423 static void zebra_route_map_mark_update(const char *rmap_name)
1424 {
1425 /* rmap_update_timer of 0 means don't do route updates */
1426 if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
1427 zebra_t_rmap_update = NULL;
1428 thread_add_timer(zebrad.master, zebra_route_map_update_timer,
1429 NULL, zebra_rmap_update_timer,
1430 &zebra_t_rmap_update);
1431 }
1432 }
1433
1434 static void zebra_route_map_add(const char *rmap_name)
1435 {
1436 zebra_route_map_mark_update(rmap_name);
1437 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1438 }
1439
1440 static void zebra_route_map_delete(const char *rmap_name)
1441 {
1442 zebra_route_map_mark_update(rmap_name);
1443 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1444 }
1445
1446 static void zebra_route_map_event(route_map_event_t event,
1447 const char *rmap_name)
1448 {
1449 zebra_route_map_mark_update(rmap_name);
1450 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1451 }
1452
1453 /* ip protocol configuration write function */
1454 void zebra_routemap_config_write_protocol(struct vty *vty)
1455 {
1456 int i;
1457
1458 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1459 if (proto_rm[AFI_IP][i])
1460 vty_out(vty, "ip protocol %s route-map %s\n",
1461 zebra_route_string(i), proto_rm[AFI_IP][i]);
1462
1463 if (proto_rm[AFI_IP6][i])
1464 vty_out(vty, "ipv6 protocol %s route-map %s\n",
1465 zebra_route_string(i), proto_rm[AFI_IP6][i]);
1466
1467 if (nht_rm[AFI_IP][i])
1468 vty_out(vty, "ip nht %s route-map %s\n",
1469 zebra_route_string(i), nht_rm[AFI_IP][i]);
1470
1471 if (nht_rm[AFI_IP6][i])
1472 vty_out(vty, "ipv6 nht %s route-map %s\n",
1473 zebra_route_string(i), nht_rm[AFI_IP6][i]);
1474 }
1475
1476 if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1477 vty_out(vty, "ip protocol %s route-map %s\n", "any",
1478 proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]);
1479
1480 if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1481 vty_out(vty, "ipv6 protocol %s route-map %s\n", "any",
1482 proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]);
1483
1484 if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1485 vty_out(vty, "ip nht %s route-map %s\n", "any",
1486 nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]);
1487
1488 if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1489 vty_out(vty, "ipv6 nht %s route-map %s\n", "any",
1490 nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]);
1491
1492 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1493 vty_out(vty, "zebra route-map delay-timer %d\n",
1494 zebra_rmap_update_timer);
1495 }
1496
1497 void zebra_route_map_init()
1498 {
1499 install_element(CONFIG_NODE, &ip_protocol_cmd);
1500 install_element(CONFIG_NODE, &no_ip_protocol_cmd);
1501 install_element(VIEW_NODE, &show_ip_protocol_cmd);
1502 install_element(CONFIG_NODE, &ipv6_protocol_cmd);
1503 install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
1504 install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
1505 install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1506 install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1507 install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
1508 install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1509 install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1510 install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1511 install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
1512 install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1513
1514 route_map_init();
1515
1516 route_map_add_hook(zebra_route_map_add);
1517 route_map_delete_hook(zebra_route_map_delete);
1518 route_map_event_hook(zebra_route_map_event);
1519
1520 route_map_match_interface_hook(generic_match_add);
1521 route_map_no_match_interface_hook(generic_match_delete);
1522
1523 route_map_match_ip_address_hook(generic_match_add);
1524 route_map_no_match_ip_address_hook(generic_match_delete);
1525
1526 route_map_match_ip_address_prefix_list_hook(generic_match_add);
1527 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
1528
1529 route_map_match_ip_next_hop_hook(generic_match_add);
1530 route_map_no_match_ip_next_hop_hook(generic_match_delete);
1531
1532 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
1533 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
1534
1535 route_map_match_tag_hook(generic_match_add);
1536 route_map_no_match_tag_hook(generic_match_delete);
1537
1538 route_map_install_match(&route_match_tag_cmd);
1539 route_map_install_match(&route_match_interface_cmd);
1540 route_map_install_match(&route_match_ip_next_hop_cmd);
1541 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
1542 route_map_install_match(&route_match_ip_address_cmd);
1543 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
1544 route_map_install_match(&route_match_ip_address_prefix_len_cmd);
1545 route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
1546 route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
1547 route_map_install_match(&route_match_source_protocol_cmd);
1548 route_map_install_match(&route_match_source_instance_cmd);
1549
1550 /* */
1551 route_map_install_set(&route_set_src_cmd);
1552 /* */
1553 install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
1554 install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
1555 install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
1556 install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
1557 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
1558 install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
1559 install_element(RMAP_NODE, &match_source_protocol_cmd);
1560 install_element(RMAP_NODE, &no_match_source_protocol_cmd);
1561 install_element(RMAP_NODE, &match_source_instance_cmd);
1562 install_element(RMAP_NODE, &no_match_source_instance_cmd);
1563
1564 /* */
1565 install_element(RMAP_NODE, &set_src_cmd);
1566 install_element(RMAP_NODE, &no_set_src_cmd);
1567 }