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