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