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