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