]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
*: ditch vty_outln(), part 1 of 2
[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.\n");
77 return CMD_WARNING;
78 case RMAP_COMPILE_ERROR:
79 vty_out (vty, "%% Zebra Argument is malformed.\n");
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.\n");
125 return CMD_WARNING;
126 case RMAP_COMPILE_ERROR:
127 vty_out (vty, "%% Zebra Argument is malformed.\n");
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_outln (vty, "invalid protocol name \"%s\"", proto);
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\n");
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\n");
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\n");
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 rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
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_outln (vty, "invalid protocol name \"%s\"", proto);
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_outln (vty, "invalid protocol name \"%s\"", proto);
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 \n");
533 vty_out (vty, "------------------------\n");
534 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
535 {
536 if (proto_rm[AFI_IP][i])
537 vty_out (vty, "%-10s : %-10s\n", zebra_route_string(i),
538 proto_rm[AFI_IP][i]);
539 else
540 vty_out (vty, "%-10s : none\n", zebra_route_string(i));
541 }
542 if (proto_rm[AFI_IP][i])
543 vty_out (vty, "%-10s : %-10s\n", "any",proto_rm[AFI_IP][i]);
544 else
545 vty_out (vty, "%-10s : none\n", "any");
546
547 return CMD_SUCCESS;
548 }
549
550 DEFUN (ipv6_protocol,
551 ipv6_protocol_cmd,
552 "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
553 IP6_STR
554 "Filter IPv6 routing info exchanged between zebra and protocol\n"
555 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
556 "Specify route map\n"
557 "Route map name\n")
558 {
559 char *proto = argv[2]->text;
560 char *rmap = argv[4]->arg;
561 int i;
562
563 if (strcasecmp(proto, "any") == 0)
564 i = ZEBRA_ROUTE_MAX;
565 else
566 i = proto_name2num(proto);
567 if (i < 0)
568 {
569 vty_outln (vty, "invalid protocol name \"%s\"", proto);
570 return CMD_WARNING;
571 }
572 if (proto_rm[AFI_IP6][i])
573 {
574 if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0)
575 return CMD_SUCCESS;
576
577 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
578 }
579 proto_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap);
580
581 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
582 zlog_debug ("%u: IPv6 Routemap config for protocol %s, scheduling RIB processing",
583 VRF_DEFAULT, proto);
584
585 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
586 return CMD_SUCCESS;
587 }
588
589 DEFUN (no_ipv6_protocol,
590 no_ipv6_protocol_cmd,
591 "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
592 NO_STR
593 IP6_STR
594 "Stop filtering IPv6 routing info between zebra and protocol\n"
595 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
596 "Specify route map\n"
597 "Route map name\n")
598 {
599 const char *proto = argv[3]->text;
600 const char *rmap = (argc == 6) ? argv[5]->arg : NULL;
601 int i;
602
603 if (strcasecmp(proto, "any") == 0)
604 i = ZEBRA_ROUTE_MAX;
605 else
606 i = proto_name2num(proto);
607 if (i < 0)
608 {
609 vty_outln (vty, "invalid protocol name \"%s\"", proto);
610 return CMD_WARNING;
611 }
612 if (!proto_rm[AFI_IP6][i])
613 return CMD_SUCCESS;
614
615 if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0)
616 {
617 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
618 proto_rm[AFI_IP6][i] = NULL;
619
620 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
621 zlog_debug ("%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing",
622 VRF_DEFAULT, proto);
623
624 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
625 }
626 return CMD_SUCCESS;
627 }
628
629 DEFUN (show_ipv6_protocol,
630 show_ipv6_protocol_cmd,
631 "show ipv6 protocol",
632 SHOW_STR
633 IP6_STR
634 "IPv6 protocol filtering status\n")
635 {
636 int i;
637
638 vty_out (vty, "Protocol : route-map \n");
639 vty_out (vty, "------------------------\n");
640 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
641 {
642 if (proto_rm[AFI_IP6][i])
643 vty_out (vty, "%-10s : %-10s\n", zebra_route_string(i),
644 proto_rm[AFI_IP6][i]);
645 else
646 vty_out (vty, "%-10s : none\n", zebra_route_string(i));
647 }
648 if (proto_rm[AFI_IP6][i])
649 vty_out (vty, "%-10s : %-10s\n", "any",proto_rm[AFI_IP6][i]);
650 else
651 vty_out (vty, "%-10s : none\n", "any");
652
653 return CMD_SUCCESS;
654 }
655
656 DEFUN (ip_protocol_nht_rmap,
657 ip_protocol_nht_rmap_cmd,
658 "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
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 char *proto = argv[2]->text;
666 char *rmap = argv[4]->arg;
667 int i;
668
669 if (strcasecmp(proto, "any") == 0)
670 i = ZEBRA_ROUTE_MAX;
671 else
672 i = proto_name2num(proto);
673 if (i < 0)
674 {
675 vty_outln (vty, "invalid protocol name \"%s\"", proto);
676 return CMD_WARNING;
677 }
678 if (nht_rm[AFI_IP][i])
679 {
680 if (strcmp(nht_rm[AFI_IP][i], rmap) == 0)
681 return CMD_SUCCESS;
682
683 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
684 }
685
686 nht_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap);
687 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
688
689 return CMD_SUCCESS;
690 }
691
692 DEFUN (no_ip_protocol_nht_rmap,
693 no_ip_protocol_nht_rmap_cmd,
694 "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
695 NO_STR
696 IP_STR
697 "Filter Next Hop tracking route resolution\n"
698 FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
699 "Specify route map\n"
700 "Route map name\n")
701 {
702 int idx = 0;
703 char *proto = argv[3]->text;
704 char *rmap = argv_find (argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg : NULL;
705
706 int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX : proto_name2num(proto);
707
708 if (i < 0)
709 {
710 vty_outln (vty, "invalid protocol name \"%s\"", proto);
711 return CMD_WARNING;
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 {
719 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
720 nht_rm[AFI_IP][i] = NULL;
721 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
722 }
723 return CMD_SUCCESS;
724 }
725
726 DEFUN (show_ip_protocol_nht,
727 show_ip_protocol_nht_cmd,
728 "show ip nht route-map",
729 SHOW_STR
730 IP_STR
731 "IP nexthop tracking table\n"
732 "IP Next Hop tracking filtering status\n")
733 {
734 int i;
735
736 vty_out (vty, "Protocol : route-map \n");
737 vty_out (vty, "------------------------\n");
738 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
739 {
740 if (nht_rm[AFI_IP][i])
741 vty_out (vty, "%-10s : %-10s\n", zebra_route_string(i),
742 nht_rm[AFI_IP][i]);
743 else
744 vty_out (vty, "%-10s : none\n", zebra_route_string(i));
745 }
746 if (nht_rm[AFI_IP][i])
747 vty_out (vty, "%-10s : %-10s\n", "any",nht_rm[AFI_IP][i]);
748 else
749 vty_out (vty, "%-10s : none\n", "any");
750
751 return CMD_SUCCESS;
752 }
753
754 DEFUN (ipv6_protocol_nht_rmap,
755 ipv6_protocol_nht_rmap_cmd,
756 "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
757 IP6_STR
758 "Filter Next Hop tracking route resolution\n"
759 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
760 "Specify route map\n"
761 "Route map name\n")
762 {
763 char *proto = argv[2]->text;
764 char *rmap = argv[4]->arg;
765 int i;
766
767 if (strcasecmp(proto, "any") == 0)
768 i = ZEBRA_ROUTE_MAX;
769 else
770 i = proto_name2num(proto);
771 if (i < 0)
772 {
773 vty_outln (vty, "invalid protocol name \"%s\"", proto);
774 return CMD_WARNING;
775 }
776 if (nht_rm[AFI_IP6][i])
777 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
778 nht_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap);
779 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
780
781 return CMD_SUCCESS;
782 }
783
784 DEFUN (no_ipv6_protocol_nht_rmap,
785 no_ipv6_protocol_nht_rmap_cmd,
786 "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]",
787 NO_STR
788 IP6_STR
789 "Filter Next Hop tracking route resolution\n"
790 FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
791 "Specify route map\n"
792 "Route map name\n")
793 {
794 char *proto = argv[3]->text;
795 char *rmap = (argc == 6) ? argv[5]->arg : NULL;
796 int i;
797
798 if (strcasecmp(proto, "any") == 0)
799 i = ZEBRA_ROUTE_MAX;
800 else
801 i = proto_name2num(proto);
802 if (i < 0)
803 {
804 vty_outln (vty, "invalid protocol name \"%s\"", proto);
805 return CMD_WARNING;
806 }
807
808 if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i]))
809 {
810 vty_outln (vty, "invalid route-map \"%s\"", rmap);
811 return CMD_WARNING;
812 }
813
814 if (nht_rm[AFI_IP6][i])
815 {
816 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
817 nht_rm[AFI_IP6][i] = NULL;
818 }
819
820 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
821
822 return CMD_SUCCESS;
823 }
824
825 DEFUN (show_ipv6_protocol_nht,
826 show_ipv6_protocol_nht_cmd,
827 "show ipv6 nht route-map",
828 SHOW_STR
829 IP6_STR
830 "Next Hop filtering status\n"
831 "Route-map\n")
832 {
833 int i;
834
835 vty_out (vty, "Protocol : route-map \n");
836 vty_out (vty, "------------------------\n");
837 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
838 {
839 if (nht_rm[AFI_IP6][i])
840 vty_out (vty, "%-10s : %-10s\n", zebra_route_string(i),
841 nht_rm[AFI_IP6][i]);
842 else
843 vty_out (vty, "%-10s : none\n", zebra_route_string(i));
844 }
845 if (nht_rm[AFI_IP][i])
846 vty_out (vty, "%-10s : %-10s\n", "any",nht_rm[AFI_IP6][i]);
847 else
848 vty_out (vty, "%-10s : none\n", "any");
849
850 return CMD_SUCCESS;
851 }
852
853 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
854
855 /* `match ip next-hop IP_ACCESS_LIST' */
856
857 /* Match function return 1 if match is success else return zero. */
858 static route_map_result_t
859 route_match_ip_next_hop (void *rule, struct prefix *prefix,
860 route_map_object_t type, void *object)
861 {
862 struct access_list *alist;
863 struct nh_rmap_obj *nh_data;
864 struct prefix_ipv4 p;
865
866 if (type == RMAP_ZEBRA)
867 {
868 nh_data = object;
869 if (!nh_data)
870 return RMAP_DENYMATCH;
871
872 switch (nh_data->nexthop->type) {
873 case NEXTHOP_TYPE_IFINDEX:
874 /* Interface routes can't match ip next-hop */
875 return RMAP_NOMATCH;
876 case NEXTHOP_TYPE_IPV4_IFINDEX:
877 case NEXTHOP_TYPE_IPV4:
878 p.family = AF_INET;
879 p.prefix = nh_data->nexthop->gate.ipv4;
880 p.prefixlen = IPV4_MAX_BITLEN;
881 break;
882 default:
883 return RMAP_NOMATCH;
884 }
885 alist = access_list_lookup (AFI_IP, (char *) rule);
886 if (alist == NULL)
887 return RMAP_NOMATCH;
888
889 return (access_list_apply (alist, &p) == FILTER_DENY ?
890 RMAP_NOMATCH : RMAP_MATCH);
891 }
892 return RMAP_NOMATCH;
893 }
894
895 /* Route map `ip next-hop' match statement. `arg' should be
896 access-list name. */
897 static void *
898 route_match_ip_next_hop_compile (const char *arg)
899 {
900 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
901 }
902
903 /* Free route map's compiled `. */
904 static void
905 route_match_ip_next_hop_free (void *rule)
906 {
907 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
908 }
909
910 /* Route map commands for ip next-hop matching. */
911 static struct route_map_rule_cmd route_match_ip_next_hop_cmd =
912 {
913 "ip next-hop",
914 route_match_ip_next_hop,
915 route_match_ip_next_hop_compile,
916 route_match_ip_next_hop_free
917 };
918
919 /* `match ip next-hop prefix-list PREFIX_LIST' */
920
921 static route_map_result_t
922 route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
923 route_map_object_t type, void *object)
924 {
925 struct prefix_list *plist;
926 struct nh_rmap_obj *nh_data;
927 struct prefix_ipv4 p;
928
929 if (type == RMAP_ZEBRA)
930 {
931 nh_data = (struct nh_rmap_obj *)object;
932 if (!nh_data)
933 return RMAP_DENYMATCH;
934
935 switch (nh_data->nexthop->type) {
936 case NEXTHOP_TYPE_IFINDEX:
937 /* Interface routes can't match ip next-hop */
938 return RMAP_NOMATCH;
939 case NEXTHOP_TYPE_IPV4_IFINDEX:
940 case NEXTHOP_TYPE_IPV4:
941 p.family = AF_INET;
942 p.prefix = nh_data->nexthop->gate.ipv4;
943 p.prefixlen = IPV4_MAX_BITLEN;
944 break;
945 default:
946 return RMAP_NOMATCH;
947 }
948 plist = prefix_list_lookup (AFI_IP, (char *) rule);
949 if (plist == NULL)
950 return RMAP_NOMATCH;
951
952 return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
953 RMAP_NOMATCH : RMAP_MATCH);
954 }
955 return RMAP_NOMATCH;
956 }
957
958 static void *
959 route_match_ip_next_hop_prefix_list_compile (const char *arg)
960 {
961 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
962 }
963
964 static void
965 route_match_ip_next_hop_prefix_list_free (void *rule)
966 {
967 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
968 }
969
970 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
971 {
972 "ip next-hop prefix-list",
973 route_match_ip_next_hop_prefix_list,
974 route_match_ip_next_hop_prefix_list_compile,
975 route_match_ip_next_hop_prefix_list_free
976 };
977
978 /* `match ip address IP_ACCESS_LIST' */
979
980 /* Match function should return 1 if match is success else return
981 zero. */
982 static route_map_result_t
983 route_match_ip_address (void *rule, struct prefix *prefix,
984 route_map_object_t type, void *object)
985 {
986 struct access_list *alist;
987
988 if (type == RMAP_ZEBRA)
989 {
990 alist = access_list_lookup (AFI_IP, (char *) rule);
991 if (alist == NULL)
992 return RMAP_NOMATCH;
993
994 return (access_list_apply (alist, prefix) == FILTER_DENY ?
995 RMAP_NOMATCH : RMAP_MATCH);
996 }
997 return RMAP_NOMATCH;
998 }
999
1000 /* Route map `ip address' match statement. `arg' should be
1001 access-list name. */
1002 static void *
1003 route_match_ip_address_compile (const char *arg)
1004 {
1005 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1006 }
1007
1008 /* Free route map's compiled `ip address' value. */
1009 static void
1010 route_match_ip_address_free (void *rule)
1011 {
1012 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1013 }
1014
1015 /* Route map commands for ip address matching. */
1016 static struct route_map_rule_cmd route_match_ip_address_cmd =
1017 {
1018 "ip address",
1019 route_match_ip_address,
1020 route_match_ip_address_compile,
1021 route_match_ip_address_free
1022 };
1023
1024 /* `match ip address prefix-list PREFIX_LIST' */
1025
1026 static route_map_result_t
1027 route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
1028 route_map_object_t type, void *object)
1029 {
1030 struct prefix_list *plist;
1031
1032 if (type == RMAP_ZEBRA)
1033 {
1034 plist = prefix_list_lookup (AFI_IP, (char *) rule);
1035 if (plist == NULL)
1036 return RMAP_NOMATCH;
1037
1038 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
1039 RMAP_NOMATCH : RMAP_MATCH);
1040 }
1041 return RMAP_NOMATCH;
1042 }
1043
1044 static void *
1045 route_match_ip_address_prefix_list_compile (const char *arg)
1046 {
1047 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1048 }
1049
1050 static void
1051 route_match_ip_address_prefix_list_free (void *rule)
1052 {
1053 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1054 }
1055
1056 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
1057 {
1058 "ip address prefix-list",
1059 route_match_ip_address_prefix_list,
1060 route_match_ip_address_prefix_list_compile,
1061 route_match_ip_address_prefix_list_free
1062 };
1063
1064
1065 /* `match ip address prefix-len PREFIXLEN' */
1066
1067 static route_map_result_t
1068 route_match_ip_address_prefix_len (void *rule, struct prefix *prefix,
1069 route_map_object_t type, void *object)
1070 {
1071 u_int32_t *prefixlen = (u_int32_t *)rule;
1072
1073 if (type == RMAP_ZEBRA)
1074 {
1075 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1076 }
1077 return RMAP_NOMATCH;
1078 }
1079
1080 static void *
1081 route_match_ip_address_prefix_len_compile (const char *arg)
1082 {
1083 u_int32_t *prefix_len;
1084 char *endptr = NULL;
1085 unsigned long tmpval;
1086
1087 /* prefix len value shoud be integer. */
1088 if (! all_digit (arg))
1089 return NULL;
1090
1091 errno = 0;
1092 tmpval = strtoul (arg, &endptr, 10);
1093 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1094 return NULL;
1095
1096 prefix_len = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
1097
1098 if (!prefix_len)
1099 return prefix_len;
1100
1101 *prefix_len = tmpval;
1102 return prefix_len;
1103 }
1104
1105 static void
1106 route_match_ip_address_prefix_len_free (void *rule)
1107 {
1108 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1109 }
1110
1111 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd =
1112 {
1113 "ip address prefix-len",
1114 route_match_ip_address_prefix_len,
1115 route_match_ip_address_prefix_len_compile,
1116 route_match_ip_address_prefix_len_free
1117 };
1118
1119
1120 /* `match ip nexthop prefix-len PREFIXLEN' */
1121
1122 static route_map_result_t
1123 route_match_ip_nexthop_prefix_len (void *rule, struct prefix *prefix,
1124 route_map_object_t type, void *object)
1125 {
1126 u_int32_t *prefixlen = (u_int32_t *)rule;
1127 struct nh_rmap_obj *nh_data;
1128 struct prefix_ipv4 p;
1129
1130 if (type == RMAP_ZEBRA)
1131 {
1132 nh_data = (struct nh_rmap_obj *)object;
1133 if (!nh_data || !nh_data->nexthop)
1134 return RMAP_DENYMATCH;
1135
1136 switch (nh_data->nexthop->type) {
1137 case NEXTHOP_TYPE_IFINDEX:
1138 /* Interface routes can't match ip next-hop */
1139 return RMAP_NOMATCH;
1140 case NEXTHOP_TYPE_IPV4_IFINDEX:
1141 case NEXTHOP_TYPE_IPV4:
1142 p.family = AF_INET;
1143 p.prefix = nh_data->nexthop->gate.ipv4;
1144 p.prefixlen = IPV4_MAX_BITLEN;
1145 break;
1146 default:
1147 return RMAP_NOMATCH;
1148 }
1149 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1150 }
1151 return RMAP_NOMATCH;
1152 }
1153
1154 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd =
1155 {
1156 "ip next-hop prefix-len",
1157 route_match_ip_nexthop_prefix_len,
1158 route_match_ip_address_prefix_len_compile, /* reuse */
1159 route_match_ip_address_prefix_len_free /* reuse */
1160 };
1161
1162 /* `match source-protocol PROTOCOL' */
1163
1164 static route_map_result_t
1165 route_match_source_protocol (void *rule, struct prefix *prefix,
1166 route_map_object_t type, void *object)
1167 {
1168 u_int32_t *rib_type = (u_int32_t *)rule;
1169 struct nh_rmap_obj *nh_data;
1170
1171 if (type == RMAP_ZEBRA)
1172 {
1173 nh_data = (struct nh_rmap_obj *)object;
1174 if (!nh_data)
1175 return RMAP_DENYMATCH;
1176
1177 return ((nh_data->source_protocol == *rib_type)
1178 ? RMAP_MATCH : RMAP_NOMATCH);
1179 }
1180 return RMAP_NOMATCH;
1181 }
1182
1183 static void *
1184 route_match_source_protocol_compile (const char *arg)
1185 {
1186 u_int32_t *rib_type;
1187 int i;
1188
1189 i = proto_name2num(arg);
1190 rib_type = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
1191
1192 *rib_type = i;
1193
1194 return rib_type;
1195 }
1196
1197 static void
1198 route_match_source_protocol_free (void *rule)
1199 {
1200 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1201 }
1202
1203 static struct route_map_rule_cmd route_match_source_protocol_cmd =
1204 {
1205 "source-protocol",
1206 route_match_source_protocol,
1207 route_match_source_protocol_compile,
1208 route_match_source_protocol_free
1209 };
1210
1211 /* `set src A.B.C.D' */
1212
1213 /* Set src. */
1214 static route_map_result_t
1215 route_set_src (void *rule, struct prefix *prefix,
1216 route_map_object_t type, void *object)
1217 {
1218 struct nh_rmap_obj *nh_data;
1219
1220 if (type == RMAP_ZEBRA)
1221 {
1222 nh_data = (struct nh_rmap_obj *)object;
1223 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1224 }
1225 return RMAP_OKAY;
1226 }
1227
1228 /* set src compilation. */
1229 static void *
1230 route_set_src_compile (const char *arg)
1231 {
1232 union g_addr src, *psrc;
1233
1234 if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1) ||
1235 (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1)))
1236 {
1237 psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr));
1238 *psrc = src;
1239 return psrc;
1240 }
1241 return NULL;
1242 }
1243
1244 /* Free route map's compiled `set src' value. */
1245 static void
1246 route_set_src_free (void *rule)
1247 {
1248 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1249 }
1250
1251 /* Set src rule structure. */
1252 static struct route_map_rule_cmd route_set_src_cmd =
1253 {
1254 "src",
1255 route_set_src,
1256 route_set_src_compile,
1257 route_set_src_free,
1258 };
1259
1260 static int
1261 zebra_route_map_update_timer (struct thread *thread)
1262 {
1263 zebra_t_rmap_update = NULL;
1264
1265 if (IS_ZEBRA_DEBUG_EVENT)
1266 zlog_debug("Event driven route-map update triggered");
1267
1268 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1269 zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing",
1270 VRF_DEFAULT);
1271
1272 zebra_import_table_rm_update ();
1273 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
1274 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1275 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1276
1277 return (0);
1278 }
1279
1280 static void
1281 zebra_route_map_set_delay_timer(u_int32_t value)
1282 {
1283 zebra_rmap_update_timer = value;
1284 if (!value && zebra_t_rmap_update)
1285 {
1286 /* Event driven route map updates is being disabled */
1287 /* But there's a pending timer. Fire it off now */
1288 thread_cancel(zebra_t_rmap_update);
1289 zebra_route_map_update_timer(zebra_t_rmap_update);
1290 }
1291 }
1292
1293 void
1294 zebra_route_map_write_delay_timer (struct vty *vty)
1295 {
1296 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1297 vty_out (vty, "zebra route-map delay-timer %d\n",
1298 zebra_rmap_update_timer);
1299 return;
1300 }
1301
1302 route_map_result_t
1303 zebra_route_map_check (int family, int rib_type, struct prefix *p,
1304 struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag)
1305 {
1306 struct route_map *rmap = NULL;
1307 route_map_result_t ret = RMAP_MATCH;
1308 struct nh_rmap_obj nh_obj;
1309
1310 nh_obj.nexthop = nexthop;
1311 nh_obj.vrf_id = vrf_id;
1312 nh_obj.source_protocol = rib_type;
1313 nh_obj.metric = 0;
1314 nh_obj.tag = tag;
1315
1316 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1317 rmap = route_map_lookup_by_name (proto_rm[family][rib_type]);
1318 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1319 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1320 if (rmap) {
1321 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1322 }
1323
1324 return (ret);
1325 }
1326
1327 char *
1328 zebra_get_import_table_route_map (afi_t afi, uint32_t table)
1329 {
1330 return zebra_import_table_routemap[afi][table];
1331 }
1332
1333 void
1334 zebra_add_import_table_route_map (afi_t afi, const char *rmap_name, uint32_t table)
1335 {
1336 zebra_import_table_routemap[afi][table] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap_name);
1337 }
1338
1339 void
1340 zebra_del_import_table_route_map (afi_t afi, uint32_t table)
1341 {
1342 XFREE (MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1343 }
1344
1345 route_map_result_t
1346 zebra_import_table_route_map_check (int family, int re_type, struct prefix *p,
1347 struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag, const char *rmap_name)
1348 {
1349 struct route_map *rmap = NULL;
1350 route_map_result_t ret = RMAP_DENYMATCH;
1351 struct nh_rmap_obj nh_obj;
1352
1353 nh_obj.nexthop = nexthop;
1354 nh_obj.vrf_id = vrf_id;
1355 nh_obj.source_protocol = re_type;
1356 nh_obj.metric = 0;
1357 nh_obj.tag = tag;
1358
1359 if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1360 rmap = route_map_lookup_by_name (rmap_name);
1361 if (rmap) {
1362 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1363 }
1364
1365 return (ret);
1366 }
1367
1368 route_map_result_t
1369 zebra_nht_route_map_check (int family, int client_proto, struct prefix *p,
1370 struct route_entry * re, struct nexthop *nexthop)
1371 {
1372 struct route_map *rmap = NULL;
1373 route_map_result_t ret = RMAP_MATCH;
1374 struct nh_rmap_obj nh_obj;
1375
1376 nh_obj.nexthop = nexthop;
1377 nh_obj.vrf_id = re->vrf_id;
1378 nh_obj.source_protocol = re->type;
1379 nh_obj.metric = re->metric;
1380 nh_obj.tag = re->tag;
1381
1382 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1383 rmap = route_map_lookup_by_name (nht_rm[family][client_proto]);
1384 if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX])
1385 rmap = route_map_lookup_by_name (nht_rm[family][ZEBRA_ROUTE_MAX]);
1386 if (rmap) {
1387 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1388 }
1389
1390 return (ret);
1391 }
1392
1393 static void
1394 zebra_route_map_mark_update (const char *rmap_name)
1395 {
1396 /* rmap_update_timer of 0 means don't do route updates */
1397 if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
1398 zebra_t_rmap_update = NULL;
1399 thread_add_timer(zebrad.master, zebra_route_map_update_timer, NULL, zebra_rmap_update_timer,
1400 &zebra_t_rmap_update);
1401 }
1402 }
1403
1404 static void
1405 zebra_route_map_add (const char *rmap_name)
1406 {
1407 zebra_route_map_mark_update(rmap_name);
1408 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1409 }
1410
1411 static void
1412 zebra_route_map_delete (const char *rmap_name)
1413 {
1414 zebra_route_map_mark_update(rmap_name);
1415 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1416 }
1417
1418 static void
1419 zebra_route_map_event (route_map_event_t event, const char *rmap_name)
1420 {
1421 zebra_route_map_mark_update(rmap_name);
1422 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1423 }
1424
1425 /* ip protocol configuration write function */
1426 void
1427 zebra_routemap_config_write_protocol (struct vty *vty)
1428 {
1429 int i;
1430
1431 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
1432 {
1433 if (proto_rm[AFI_IP][i])
1434 vty_out (vty, "ip protocol %s route-map %s\n", zebra_route_string(i),
1435 proto_rm[AFI_IP][i]);
1436
1437 if (proto_rm[AFI_IP6][i])
1438 vty_out (vty, "ipv6 protocol %s route-map %s\n", zebra_route_string(i),
1439 proto_rm[AFI_IP6][i]);
1440
1441 if (nht_rm[AFI_IP][i])
1442 vty_out (vty, "ip nht %s route-map %s\n", zebra_route_string(i),
1443 nht_rm[AFI_IP][i]);
1444
1445 if (nht_rm[AFI_IP6][i])
1446 vty_out (vty, "ipv6 nht %s route-map %s\n", zebra_route_string(i),
1447 nht_rm[AFI_IP6][i]);
1448 }
1449
1450 if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1451 vty_out (vty, "ip protocol %s route-map %s\n", "any",
1452 proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]);
1453
1454 if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1455 vty_out (vty, "ipv6 protocol %s route-map %s\n", "any",
1456 proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]);
1457
1458 if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1459 vty_out (vty, "ip nht %s route-map %s\n", "any",
1460 nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]);
1461
1462 if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1463 vty_out (vty, "ipv6 nht %s route-map %s\n", "any",
1464 nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]);
1465
1466 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1467 vty_out (vty, "zebra route-map delay-timer %d\n",
1468 zebra_rmap_update_timer);
1469 }
1470
1471 void
1472 zebra_route_map_init ()
1473 {
1474 install_element (CONFIG_NODE, &ip_protocol_cmd);
1475 install_element (CONFIG_NODE, &no_ip_protocol_cmd);
1476 install_element (VIEW_NODE, &show_ip_protocol_cmd);
1477 install_element (CONFIG_NODE, &ipv6_protocol_cmd);
1478 install_element (CONFIG_NODE, &no_ipv6_protocol_cmd);
1479 install_element (VIEW_NODE, &show_ipv6_protocol_cmd);
1480 install_element (CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1481 install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1482 install_element (VIEW_NODE, &show_ip_protocol_nht_cmd);
1483 install_element (CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1484 install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1485 install_element (VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1486 install_element (CONFIG_NODE, &zebra_route_map_timer_cmd);
1487 install_element (CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1488
1489 route_map_init ();
1490
1491 route_map_add_hook (zebra_route_map_add);
1492 route_map_delete_hook (zebra_route_map_delete);
1493 route_map_event_hook (zebra_route_map_event);
1494
1495 route_map_match_interface_hook (generic_match_add);
1496 route_map_no_match_interface_hook (generic_match_delete);
1497
1498 route_map_match_ip_address_hook (generic_match_add);
1499 route_map_no_match_ip_address_hook (generic_match_delete);
1500
1501 route_map_match_ip_address_prefix_list_hook (generic_match_add);
1502 route_map_no_match_ip_address_prefix_list_hook (generic_match_delete);
1503
1504 route_map_match_ip_next_hop_hook (generic_match_add);
1505 route_map_no_match_ip_next_hop_hook (generic_match_delete);
1506
1507 route_map_match_ip_next_hop_prefix_list_hook (generic_match_add);
1508 route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete);
1509
1510 route_map_match_tag_hook (generic_match_add);
1511 route_map_no_match_tag_hook (generic_match_delete);
1512
1513 route_map_install_match (&route_match_tag_cmd);
1514 route_map_install_match (&route_match_interface_cmd);
1515 route_map_install_match (&route_match_ip_next_hop_cmd);
1516 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
1517 route_map_install_match (&route_match_ip_address_cmd);
1518 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
1519 route_map_install_match (&route_match_ip_address_prefix_len_cmd);
1520 route_map_install_match (&route_match_ip_nexthop_prefix_len_cmd);
1521 route_map_install_match (&route_match_source_protocol_cmd);
1522 /* */
1523 route_map_install_set (&route_set_src_cmd);
1524 /* */
1525 install_element (RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
1526 install_element (RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
1527 install_element (RMAP_NODE, &match_ip_address_prefix_len_cmd);
1528 install_element (RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
1529 install_element (RMAP_NODE, &match_source_protocol_cmd);
1530 install_element (RMAP_NODE, &no_match_source_protocol_cmd);
1531 /* */
1532 install_element (RMAP_NODE, &set_src_cmd);
1533 install_element (RMAP_NODE, &no_set_src_cmd);
1534 }