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