]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_routemap.c
*: Fix duplicate commands from view/enable node consolidation
[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 "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 /* Add zebra route map rule */
60 static int
61 zebra_route_match_add(struct vty *vty,
62 const char *command, const char *arg,
63 route_map_event_t type)
64 {
65 VTY_DECLVAR_CONTEXT (route_map_index, index);
66 int ret;
67
68 ret = route_map_add_match (index, command, arg);
69 if (ret)
70 {
71 switch (ret)
72 {
73 case RMAP_RULE_MISSING:
74 vty_out (vty, "%% Zebra Can't find rule.%s", VTY_NEWLINE);
75 return CMD_WARNING;
76 case RMAP_COMPILE_ERROR:
77 vty_out (vty, "%% Zebra Argument is malformed.%s", VTY_NEWLINE);
78 return CMD_WARNING;
79 }
80 }
81
82 if (type != RMAP_EVENT_MATCH_ADDED)
83 {
84 route_map_upd8_dependency (type, arg, index->map->name);
85 }
86 return CMD_SUCCESS;
87 }
88
89 /* Delete zebra route map rule. */
90 static int
91 zebra_route_match_delete (struct vty *vty,
92 const char *command, const char *arg,
93 route_map_event_t type)
94 {
95 VTY_DECLVAR_CONTEXT (route_map_index, index);
96 int ret;
97 char *dep_name = NULL;
98 const char *tmpstr;
99 char *rmap_name = NULL;
100
101 if (type != RMAP_EVENT_MATCH_DELETED)
102 {
103 /* ignore the mundane, the types without any dependency */
104 if (arg == NULL)
105 {
106 if ((tmpstr = route_map_get_match_arg(index, command)) != NULL)
107 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
108 }
109 else
110 {
111 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
112 }
113 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
114 }
115
116 ret = route_map_delete_match (index, command, arg);
117 if (ret)
118 {
119 switch (ret)
120 {
121 case RMAP_RULE_MISSING:
122 vty_out (vty, "%% Zebra Can't find rule.%s", VTY_NEWLINE);
123 return CMD_WARNING;
124 case RMAP_COMPILE_ERROR:
125 vty_out (vty, "%% Zebra Argument is malformed.%s", VTY_NEWLINE);
126 return CMD_WARNING;
127 }
128 }
129
130 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
131 route_map_upd8_dependency(type, dep_name, rmap_name);
132
133 if (dep_name)
134 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
135 if (rmap_name)
136 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
137
138 return CMD_SUCCESS;
139 }
140
141 /* Add zebra route map rule. */
142 static int
143 zebra_route_set_add (struct vty *vty,
144 const char *command, const char *arg)
145 {
146 VTY_DECLVAR_CONTEXT (route_map_index, index);
147 int ret;
148
149 ret = route_map_add_set (index, command, arg);
150 if (ret)
151 {
152 switch (ret)
153 {
154 case RMAP_RULE_MISSING:
155 vty_out (vty, "%% Zebra Can't find rule.%s", VTY_NEWLINE);
156 return CMD_WARNING;
157 case RMAP_COMPILE_ERROR:
158 vty_out (vty, "%% Zebra Argument is malformed.%s", VTY_NEWLINE);
159 return CMD_WARNING;
160 }
161 }
162 return CMD_SUCCESS;
163 }
164
165 /* Delete zebra route map rule. */
166 static int
167 zebra_route_set_delete (struct vty *vty,
168 const char *command, const char *arg)
169 {
170 VTY_DECLVAR_CONTEXT (route_map_index, index);
171 int ret;
172
173 ret = route_map_delete_set (index, command, arg);
174 if (ret)
175 {
176 switch (ret)
177 {
178 case RMAP_RULE_MISSING:
179 vty_out (vty, "%% Zebra Can't find rule.%s", VTY_NEWLINE);
180 return CMD_WARNING;
181 case RMAP_COMPILE_ERROR:
182 vty_out (vty, "%% Zebra Argument is malformed.%s", VTY_NEWLINE);
183 return CMD_WARNING;
184 }
185 }
186 return CMD_SUCCESS;
187 }
188
189 /* 'match tag TAG'
190 * Match function return 1 if match is success else return 0
191 */
192 static route_map_result_t
193 route_match_tag (void *rule, struct prefix *prefix,
194 route_map_object_t type, void *object)
195 {
196 route_tag_t *tag;
197 struct nh_rmap_obj *nh_data;
198
199 if (type == RMAP_ZEBRA)
200 {
201 tag = rule;
202 nh_data = object;
203
204 if (nh_data->tag == *tag)
205 return RMAP_MATCH;
206 }
207 return RMAP_NOMATCH;
208 }
209
210 /* Route map commands for tag matching */
211 static struct route_map_rule_cmd route_match_tag_cmd =
212 {
213 "tag",
214 route_match_tag,
215 route_map_rule_tag_compile,
216 route_map_rule_tag_free,
217 };
218
219
220 /* `match interface IFNAME' */
221 /* Match function return 1 if match is success else return zero. */
222 static route_map_result_t
223 route_match_interface (void *rule, struct prefix *prefix,
224 route_map_object_t type, void *object)
225 {
226 struct nh_rmap_obj *nh_data;
227 char *ifname = rule;
228 ifindex_t ifindex;
229
230 if (type == RMAP_ZEBRA)
231 {
232 if (strcasecmp(ifname, "any") == 0)
233 return RMAP_MATCH;
234 nh_data = object;
235 if (!nh_data || !nh_data->nexthop)
236 return RMAP_NOMATCH;
237 ifindex = ifname2ifindex_vrf (ifname, nh_data->vrf_id);
238 if (ifindex == 0)
239 return RMAP_NOMATCH;
240 if (nh_data->nexthop->ifindex == ifindex)
241 return RMAP_MATCH;
242 }
243 return RMAP_NOMATCH;
244 }
245
246 /* Route map `match interface' match statement. `arg' is IFNAME value */
247 static void *
248 route_match_interface_compile (const char *arg)
249 {
250 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
251 }
252
253 /* Free route map's compiled `match interface' value. */
254 static void
255 route_match_interface_free (void *rule)
256 {
257 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
258 }
259
260 /* Route map commands for interface matching */
261 struct route_map_rule_cmd route_match_interface_cmd =
262 {
263 "interface",
264 route_match_interface,
265 route_match_interface_compile,
266 route_match_interface_free
267 };
268
269 DEFUN (match_interface,
270 match_interface_cmd,
271 "match interface WORD",
272 MATCH_STR
273 "match first hop interface of route\n"
274 "Interface name\n")
275 {
276 return zebra_route_match_add (vty, "interface", argv[0],
277 RMAP_EVENT_MATCH_ADDED);
278 }
279
280 DEFUN (no_match_interface,
281 no_match_interface_cmd,
282 "no match interface",
283 NO_STR
284 MATCH_STR
285 "Match first hop interface of route\n")
286 {
287 if (argc == 0)
288 return zebra_route_match_delete (vty, "interface", NULL, RMAP_EVENT_MATCH_DELETED);
289
290 return zebra_route_match_delete (vty, "interface", argv[0], RMAP_EVENT_MATCH_DELETED);
291 }
292
293 ALIAS (no_match_interface,
294 no_match_interface_val_cmd,
295 "no match interface WORD",
296 NO_STR
297 MATCH_STR
298 "Match first hop interface of route\n"
299 "Interface name\n")
300
301 DEFUN (match_tag,
302 match_tag_cmd,
303 "match tag <1-4294967295>",
304 MATCH_STR
305 "Match tag of route\n"
306 "Tag value\n")
307 {
308 return zebra_route_match_add (vty, "tag", argv[0],
309 RMAP_EVENT_MATCH_ADDED);
310 }
311
312 DEFUN (no_match_tag,
313 no_match_tag_cmd,
314 "no match tag",
315 NO_STR
316 MATCH_STR
317 "Match tag of route\n")
318 {
319 if (argc == 0)
320 return zebra_route_match_delete (vty, "tag", NULL,
321 RMAP_EVENT_MATCH_DELETED);
322
323 return zebra_route_match_delete (vty, "tag", argv[0],
324 RMAP_EVENT_MATCH_DELETED);
325 }
326
327 ALIAS (no_match_tag,
328 no_match_tag_val_cmd,
329 "no match tag <1-4294967295>",
330 NO_STR
331 MATCH_STR
332 "Match tag of route\n")
333
334 DEFUN (match_ip_next_hop,
335 match_ip_next_hop_cmd,
336 "match ip next-hop (<1-199>|<1300-2699>|WORD)",
337 MATCH_STR
338 IP_STR
339 "Match next-hop address of route\n"
340 "IP access-list number\n"
341 "IP access-list number (expanded range)\n"
342 "IP Access-list name\n")
343 {
344 return zebra_route_match_add (vty, "ip next-hop", argv[0], RMAP_EVENT_FILTER_ADDED);
345 }
346
347 DEFUN (no_match_ip_next_hop,
348 no_match_ip_next_hop_cmd,
349 "no match ip next-hop",
350 NO_STR
351 MATCH_STR
352 IP_STR
353 "Match next-hop address of route\n")
354 {
355 if (argc == 0)
356 return zebra_route_match_delete (vty, "ip next-hop", NULL,
357 RMAP_EVENT_FILTER_DELETED);
358
359 return zebra_route_match_delete (vty, "ip next-hop", argv[0],
360 RMAP_EVENT_FILTER_DELETED);
361 }
362
363 ALIAS (no_match_ip_next_hop,
364 no_match_ip_next_hop_val_cmd,
365 "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
366 NO_STR
367 MATCH_STR
368 IP_STR
369 "Match next-hop address of route\n"
370 "IP access-list number\n"
371 "IP access-list number (expanded range)\n"
372 "IP Access-list name\n")
373
374 DEFUN (match_ip_next_hop_prefix_list,
375 match_ip_next_hop_prefix_list_cmd,
376 "match ip next-hop prefix-list WORD",
377 MATCH_STR
378 IP_STR
379 "Match next-hop address of route\n"
380 "Match entries of prefix-lists\n"
381 "IP prefix-list name\n")
382 {
383 return zebra_route_match_add (vty, "ip next-hop prefix-list",
384 argv[0], RMAP_EVENT_PLIST_ADDED);
385 }
386
387 DEFUN (no_match_ip_next_hop_prefix_list,
388 no_match_ip_next_hop_prefix_list_cmd,
389 "no match ip next-hop prefix-list",
390 NO_STR
391 MATCH_STR
392 IP_STR
393 "Match next-hop address of route\n"
394 "Match entries of prefix-lists\n")
395 {
396 if (argc == 0)
397 return zebra_route_match_delete (vty,
398 "ip next-hop prefix-list", NULL,
399 RMAP_EVENT_PLIST_DELETED);
400
401 return zebra_route_match_delete (vty,
402 "ip next-hop prefix-list", argv[0],
403 RMAP_EVENT_PLIST_DELETED);
404 }
405
406 ALIAS (no_match_ip_next_hop_prefix_list,
407 no_match_ip_next_hop_prefix_list_val_cmd,
408 "no match ip next-hop prefix-list WORD",
409 NO_STR
410 MATCH_STR
411 IP_STR
412 "Match next-hop address of route\n"
413 "Match entries of prefix-lists\n"
414 "IP prefix-list name\n")
415
416 DEFUN (match_ip_address,
417 match_ip_address_cmd,
418 "match ip address (<1-199>|<1300-2699>|WORD)",
419 MATCH_STR
420 IP_STR
421 "Match address of route\n"
422 "IP access-list number\n"
423 "IP access-list number (expanded range)\n"
424 "IP Access-list name\n")
425
426 {
427 return zebra_route_match_add (vty, "ip address", argv[0],
428 RMAP_EVENT_FILTER_ADDED);
429 }
430
431 DEFUN (no_match_ip_address,
432 no_match_ip_address_cmd,
433 "no match ip address",
434 NO_STR
435 MATCH_STR
436 IP_STR
437 "Match address of route\n")
438 {
439 if (argc == 0)
440 return zebra_route_match_delete (vty, "ip address", NULL,
441 RMAP_EVENT_FILTER_DELETED);
442
443 return zebra_route_match_delete (vty, "ip address", argv[0],
444 RMAP_EVENT_FILTER_DELETED);
445 }
446
447 ALIAS (no_match_ip_address,
448 no_match_ip_address_val_cmd,
449 "no match ip address (<1-199>|<1300-2699>|WORD)",
450 NO_STR
451 MATCH_STR
452 IP_STR
453 "Match address of route\n"
454 "IP access-list number\n"
455 "IP access-list number (expanded range)\n"
456 "IP Access-list name\n")
457
458 DEFUN (match_ip_address_prefix_list,
459 match_ip_address_prefix_list_cmd,
460 "match ip address prefix-list WORD",
461 MATCH_STR
462 IP_STR
463 "Match address of route\n"
464 "Match entries of prefix-lists\n"
465 "IP prefix-list name\n")
466 {
467 return zebra_route_match_add (vty, "ip address prefix-list",
468 argv[0], RMAP_EVENT_PLIST_ADDED);
469 }
470
471 DEFUN (no_match_ip_address_prefix_list,
472 no_match_ip_address_prefix_list_cmd,
473 "no match ip address prefix-list",
474 NO_STR
475 MATCH_STR
476 IP_STR
477 "Match address of route\n"
478 "Match entries of prefix-lists\n")
479 {
480 if (argc == 0)
481 return zebra_route_match_delete (vty,
482 "ip address prefix-list", NULL,
483 RMAP_EVENT_PLIST_DELETED);
484
485 return zebra_route_match_delete (vty,
486 "ip address prefix-list", argv[0],
487 RMAP_EVENT_PLIST_DELETED);
488 }
489
490 ALIAS (no_match_ip_address_prefix_list,
491 no_match_ip_address_prefix_list_val_cmd,
492 "no match ip address prefix-list WORD",
493 NO_STR
494 MATCH_STR
495 IP_STR
496 "Match address of route\n"
497 "Match entries of prefix-lists\n"
498 "IP prefix-list name\n")
499
500 DEFUN (match_ip_address_prefix_len,
501 match_ip_address_prefix_len_cmd,
502 "match ip address prefix-len NUMBER",
503 MATCH_STR
504 IP_STR
505 "Match prefix length of ip address\n"
506 "Match prefix length of ip address\n"
507 "Prefix length\n")
508 {
509 return zebra_route_match_add (vty, "ip address prefix-len",
510 argv[0], RMAP_EVENT_MATCH_ADDED);
511 }
512
513 DEFUN (no_match_ip_address_prefix_len,
514 no_match_ip_address_prefix_len_cmd,
515 "no match ip address prefix-len",
516 NO_STR
517 MATCH_STR
518 IP_STR
519 "Match prefixlen of ip address of route\n"
520 "prefix length of ip address\n")
521 {
522 if (argc == 0)
523 return zebra_route_match_delete (vty,
524 "ip address prefix-len", NULL,
525 RMAP_EVENT_MATCH_DELETED);
526
527 return zebra_route_match_delete (vty,
528 "ip address prefix-len", argv[0],
529 RMAP_EVENT_MATCH_DELETED);
530 }
531
532 ALIAS (no_match_ip_address_prefix_len,
533 no_match_ip_address_prefix_len_val_cmd,
534 "no match ip address prefix-len NUMBER",
535 NO_STR
536 MATCH_STR
537 IP_STR
538 "Match prefixlen of ip address of route\n"
539 "prefix length of ip address\n")
540
541 DEFUN (match_ip_nexthop_prefix_len,
542 match_ip_nexthop_prefix_len_cmd,
543 "match ip next-hop prefix-len NUMBER",
544 MATCH_STR
545 IP_STR
546 "Match prefixlen of nexthop ip address\n"
547 "Match prefixlen of given nexthop\n"
548 "Prefix length\n")
549 {
550 return zebra_route_match_add (vty, "ip next-hop prefix-len",
551 argv[0], RMAP_EVENT_MATCH_ADDED);
552 }
553
554 DEFUN (no_match_ip_nexthop_prefix_len,
555 no_match_ip_nexthop_prefix_len_cmd,
556 "no match ip next-hop prefix-len",
557 NO_STR
558 MATCH_STR
559 IP_STR
560 "Match prefixlen of nexthop ip address\n"
561 "Match prefix length of nexthop\n")
562 {
563 if (argc == 0)
564 return zebra_route_match_delete (vty,
565 "ip next-hop prefix-len", NULL,
566 RMAP_EVENT_MATCH_DELETED);
567
568 return zebra_route_match_delete (vty,
569 "ip next-hop prefix-len", argv[0],
570 RMAP_EVENT_MATCH_DELETED);
571 }
572
573 ALIAS (no_match_ip_nexthop_prefix_len,
574 no_match_ip_nexthop_prefix_len_val_cmd,
575 "no match ip next-hop prefix-len NUMBER",
576 MATCH_STR
577 "Match prefixlen of ip address of route\n"
578 "prefix length of ip address\n")
579
580 DEFUN (match_source_protocol,
581 match_source_protocol_cmd,
582 "match source-protocol (bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static)",
583 MATCH_STR
584 "Match protocol via which the route was learnt\n")
585 {
586 int i;
587
588 i = proto_name2num(argv[0]);
589 if (i < 0)
590 {
591 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
592 VTY_NEWLINE);
593 return CMD_WARNING;
594 }
595 return zebra_route_match_add (vty, "source-protocol",
596 argv[0], RMAP_EVENT_MATCH_ADDED);
597 }
598
599 DEFUN (no_match_source_protocol,
600 no_match_source_protocol_cmd,
601 "no match source-protocol (bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static)",
602 NO_STR
603 MATCH_STR
604 "No match protocol via which the route was learnt\n")
605 {
606 int i;
607
608 if (argc >= 1)
609 {
610 i = proto_name2num(argv[0]);
611 if (i < 0)
612 {
613 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
614 VTY_NEWLINE);
615 return CMD_WARNING;
616 }
617 }
618 return zebra_route_match_delete (vty,
619 "source-protocol", argv[0] ? argv[0] : NULL,
620 RMAP_EVENT_MATCH_DELETED);
621 }
622
623 /* set functions */
624
625 DEFUN (set_src,
626 set_src_cmd,
627 "set src (A.B.C.D|X:X::X:X)",
628 SET_STR
629 "src address for route\n"
630 "src address\n")
631 {
632 union g_addr src;
633 struct interface *pif = NULL;
634 int family;
635 struct prefix p;
636 vrf_iter_t iter;
637
638 if (inet_pton(AF_INET, argv[0], &src.ipv4) != 1)
639 {
640 if (inet_pton(AF_INET6, argv[0], &src.ipv6) != 1)
641 {
642 vty_out (vty, "%% not a valid IPv4/v6 address%s", VTY_NEWLINE);
643 return CMD_WARNING;
644 }
645
646 p.family = family = AF_INET6;
647 p.u.prefix6 = src.ipv6;
648 p.prefixlen = IPV6_MAX_BITLEN;
649 }
650 else
651 {
652 p.family = family = AF_INET;
653 p.u.prefix4 = src.ipv4;
654 p.prefixlen = IPV4_MAX_BITLEN;
655 }
656
657 if (!zebra_check_addr(&p))
658 {
659 vty_out (vty, "%% not a valid source IPv4/v6 address%s", VTY_NEWLINE);
660 return CMD_WARNING;
661 }
662
663 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
664 {
665 if (family == AF_INET)
666 pif = if_lookup_exact_address_vrf ((void *)&src.ipv4, AF_INET,
667 vrf_iter2id (iter));
668 else if (family == AF_INET6)
669 pif = if_lookup_exact_address_vrf ((void *)&src.ipv6, AF_INET6,
670 vrf_iter2id (iter));
671
672 if (pif != NULL)
673 break;
674 }
675
676 if (!pif)
677 {
678 vty_out (vty, "%% not a local address%s", VTY_NEWLINE);
679 return CMD_WARNING;
680 }
681 return zebra_route_set_add (vty, "src", argv[0]);
682 }
683
684 DEFUN (no_set_src,
685 no_set_src_cmd,
686 "no set src {A.B.C.D|X:X::X:X}",
687 NO_STR
688 SET_STR
689 "Source address for route\n")
690 {
691 if (argc == 0)
692 return zebra_route_set_delete (vty, "src", NULL);
693
694 return zebra_route_set_delete (vty, "src", argv[0]);
695 }
696
697 DEFUN (zebra_route_map_timer,
698 zebra_route_map_timer_cmd,
699 "zebra route-map delay-timer <0-600>",
700 "Time to wait before route-map updates are processed\n"
701 "0 means event-driven updates are disabled\n")
702 {
703 u_int32_t rmap_delay_timer;
704
705 VTY_GET_INTEGER_RANGE ("delay-timer", rmap_delay_timer, argv[0], 0, 600);
706 zebra_route_map_set_delay_timer(rmap_delay_timer);
707
708 return (CMD_SUCCESS);
709 }
710
711 DEFUN (no_zebra_route_map_timer,
712 no_zebra_route_map_timer_cmd,
713 "no zebra route-map delay-timer",
714 NO_STR
715 "Time to wait before route-map updates are processed\n"
716 "Reset delay-timer to default value, 30 secs\n")
717 {
718 zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
719
720 return (CMD_SUCCESS);
721 }
722
723 ALIAS (no_zebra_route_map_timer,
724 no_zebra_route_map_timer_val_cmd,
725 "no zebra route-map delay-timer <0-600>",
726 NO_STR
727 "Time to wait before route-map updates are processed\n"
728 "Reset delay-timer to default value, 30 secs\n"
729 "0 means event-driven updates are disabled\n")
730
731 DEFUN (ip_protocol,
732 ip_protocol_cmd,
733 "ip protocol " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
734 IP_STR
735 "Filter routing info exchanged between zebra and protocol\n"
736 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
737 "Route map name\n")
738 {
739 int i;
740
741 if (strcasecmp(argv[0], "any") == 0)
742 i = ZEBRA_ROUTE_MAX;
743 else
744 i = proto_name2num(argv[0]);
745 if (i < 0)
746 {
747 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
748 VTY_NEWLINE);
749 return CMD_WARNING;
750 }
751 if (proto_rm[AFI_IP][i])
752 {
753 if (strcmp(proto_rm[AFI_IP][i], argv[1]) == 0)
754 return CMD_SUCCESS;
755
756 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
757 }
758 proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
759
760 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
761 zlog_debug ("%u: IPv4 Routemap config for protocol %s, scheduling RIB processing",
762 VRF_DEFAULT, argv[0]);
763
764 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
765 return CMD_SUCCESS;
766 }
767
768 DEFUN (no_ip_protocol,
769 no_ip_protocol_cmd,
770 "no ip protocol " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA,
771 NO_STR
772 IP_STR
773 "Stop filtering routing info between zebra and protocol\n"
774 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
775 "Protocol from which to stop filtering routes\n")
776 {
777 int i;
778
779 if (strcasecmp(argv[0], "any") == 0)
780 i = ZEBRA_ROUTE_MAX;
781 else
782 i = proto_name2num(argv[0]);
783 if (i < 0)
784 {
785 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
786 VTY_NEWLINE);
787 return CMD_WARNING;
788 }
789 if (!proto_rm[AFI_IP][i])
790 return CMD_SUCCESS;
791
792 if ((argc == 2 && strcmp(argv[1], proto_rm[AFI_IP][i]) == 0) ||
793 (argc < 2))
794 {
795 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
796 proto_rm[AFI_IP][i] = NULL;
797
798 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
799 zlog_debug ("%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing",
800 VRF_DEFAULT, argv[0]);
801 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
802 }
803 return CMD_SUCCESS;
804 }
805
806 ALIAS (no_ip_protocol,
807 no_ip_protocol_val_cmd,
808 "no ip protocol " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
809 NO_STR
810 IP_STR
811 "Stop filtering routing info between zebra and protocol\n"
812 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
813 "route map name")
814
815 DEFUN (show_ip_protocol,
816 show_ip_protocol_cmd,
817 "show ip protocol",
818 SHOW_STR
819 IP_STR
820 "IP protocol filtering status\n")
821 {
822 int i;
823
824 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
825 vty_out(vty, "------------------------%s", VTY_NEWLINE);
826 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
827 {
828 if (proto_rm[AFI_IP][i])
829 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
830 proto_rm[AFI_IP][i],
831 VTY_NEWLINE);
832 else
833 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
834 }
835 if (proto_rm[AFI_IP][i])
836 vty_out (vty, "%-10s : %-10s%s", "any", proto_rm[AFI_IP][i],
837 VTY_NEWLINE);
838 else
839 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
840
841 return CMD_SUCCESS;
842 }
843
844 DEFUN (ipv6_protocol,
845 ipv6_protocol_cmd,
846 "ipv6 protocol " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
847 IP6_STR
848 "Filter IPv6 routing info exchanged between zebra and protocol\n"
849 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
850 "Route map name\n")
851 {
852 int i;
853
854 if (strcasecmp(argv[0], "any") == 0)
855 i = ZEBRA_ROUTE_MAX;
856 else
857 i = proto_name2num(argv[0]);
858 if (i < 0)
859 {
860 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
861 VTY_NEWLINE);
862 return CMD_WARNING;
863 }
864 if (proto_rm[AFI_IP6][i])
865 {
866 if (strcmp(proto_rm[AFI_IP6][i], argv[1]) == 0)
867 return CMD_SUCCESS;
868
869 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
870 }
871 proto_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
872
873 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
874 zlog_debug ("%u: IPv6 Routemap config for protocol %s, scheduling RIB processing",
875 VRF_DEFAULT, argv[0]);
876
877 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
878 return CMD_SUCCESS;
879 }
880
881 DEFUN (no_ipv6_protocol,
882 no_ipv6_protocol_cmd,
883 "no ipv6 protocol " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA,
884 NO_STR
885 IP6_STR
886 "Stop filtering IPv6 routing info between zebra and protocol\n"
887 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
888 "Protocol from which to stop filtering routes\n")
889 {
890 int i;
891
892 if (strcasecmp(argv[0], "any") == 0)
893 i = ZEBRA_ROUTE_MAX;
894 else
895 i = proto_name2num(argv[0]);
896 if (i < 0)
897 {
898 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
899 VTY_NEWLINE);
900 return CMD_WARNING;
901 }
902 if (!proto_rm[AFI_IP6][i])
903 return CMD_SUCCESS;
904
905 if ((argc == 2 && strcmp(argv[1], proto_rm[AFI_IP6][i]) == 0) ||
906 (argc < 2))
907 {
908 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
909 proto_rm[AFI_IP6][i] = NULL;
910
911 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
912 zlog_debug ("%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing",
913 VRF_DEFAULT, argv[0]);
914
915 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
916 }
917 return CMD_SUCCESS;
918 }
919
920 ALIAS (no_ipv6_protocol,
921 no_ipv6_protocol_val_cmd,
922 "no ipv6 protocol " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
923 NO_STR
924 IP6_STR
925 "Stop filtering IPv6 routing info between zebra and protocol\n"
926 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
927 "route map name")
928
929 DEFUN (show_ipv6_protocol,
930 show_ipv6_protocol_cmd,
931 "show ipv6 protocol",
932 SHOW_STR
933 IP6_STR
934 "IPv6 protocol filtering status\n")
935 {
936 int i;
937
938 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
939 vty_out(vty, "------------------------%s", VTY_NEWLINE);
940 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
941 {
942 if (proto_rm[AFI_IP6][i])
943 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
944 proto_rm[AFI_IP6][i],
945 VTY_NEWLINE);
946 else
947 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
948 }
949 if (proto_rm[AFI_IP6][i])
950 vty_out (vty, "%-10s : %-10s%s", "any", proto_rm[AFI_IP6][i],
951 VTY_NEWLINE);
952 else
953 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
954
955 return CMD_SUCCESS;
956 }
957
958 DEFUN (ip_protocol_nht_rmap,
959 ip_protocol_nht_rmap_cmd,
960 "ip nht " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
961 IP_STR
962 "Filter Next Hop tracking route resolution\n"
963 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
964 "Route map name\n")
965 {
966 int i;
967
968 if (strcasecmp(argv[0], "any") == 0)
969 i = ZEBRA_ROUTE_MAX;
970 else
971 i = proto_name2num(argv[0]);
972 if (i < 0)
973 {
974 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
975 VTY_NEWLINE);
976 return CMD_WARNING;
977 }
978 if (nht_rm[AFI_IP][i])
979 {
980 if (strcmp(nht_rm[AFI_IP][i], argv[1]) == 0)
981 return CMD_SUCCESS;
982
983 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
984 }
985
986 nht_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
987 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
988
989 return CMD_SUCCESS;
990 }
991
992 DEFUN (no_ip_protocol_nht_rmap,
993 no_ip_protocol_nht_rmap_cmd,
994 "no ip nht " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA,
995 NO_STR
996 IP_STR
997 "Filter Next Hop tracking route resolution\n"
998 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA)
999 {
1000 int i;
1001
1002 if (strcasecmp(argv[0], "any") == 0)
1003 i = ZEBRA_ROUTE_MAX;
1004 else
1005 i = proto_name2num(argv[0]);
1006 if (i < 0)
1007 {
1008 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
1009 VTY_NEWLINE);
1010 return CMD_WARNING;
1011 }
1012 if (!nht_rm[AFI_IP][i])
1013 return CMD_SUCCESS;
1014
1015 if ((argc == 2 && strcmp(argv[1], nht_rm[AFI_IP][i]) == 0) ||
1016 (argc < 2))
1017 {
1018 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
1019 nht_rm[AFI_IP][i] = NULL;
1020 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1021 }
1022 return CMD_SUCCESS;
1023 }
1024
1025 ALIAS (no_ip_protocol_nht_rmap,
1026 no_ip_protocol_nht_rmap_val_cmd,
1027 "no ip nht " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
1028 IP_STR
1029 "Filter Next Hop tracking route resolution\n"
1030 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
1031 "Route map name\n")
1032
1033 DEFUN (show_ip_protocol_nht,
1034 show_ip_protocol_nht_cmd,
1035 "show ip nht route-map",
1036 SHOW_STR
1037 IP_STR
1038 "IP Next Hop tracking filtering status\n")
1039 {
1040 int i;
1041
1042 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
1043 vty_out(vty, "------------------------%s", VTY_NEWLINE);
1044 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
1045 {
1046 if (nht_rm[AFI_IP][i])
1047 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
1048 nht_rm[AFI_IP][i],
1049 VTY_NEWLINE);
1050 else
1051 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
1052 }
1053 if (nht_rm[AFI_IP][i])
1054 vty_out (vty, "%-10s : %-10s%s", "any", nht_rm[AFI_IP][i],
1055 VTY_NEWLINE);
1056 else
1057 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
1058
1059 return CMD_SUCCESS;
1060 }
1061
1062 DEFUN (ipv6_protocol_nht_rmap,
1063 ipv6_protocol_nht_rmap_cmd,
1064 "ipv6 nht " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
1065 IP6_STR
1066 "Filter Next Hop tracking route resolution\n"
1067 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
1068 "Route map name\n")
1069 {
1070 int i;
1071
1072 if (strcasecmp(argv[0], "any") == 0)
1073 i = ZEBRA_ROUTE_MAX;
1074 else
1075 i = proto_name2num(argv[0]);
1076 if (i < 0)
1077 {
1078 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
1079 VTY_NEWLINE);
1080 return CMD_WARNING;
1081 }
1082 if (nht_rm[AFI_IP6][i])
1083 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
1084 nht_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
1085 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1086
1087 return CMD_SUCCESS;
1088 }
1089
1090 DEFUN (no_ipv6_protocol_nht_rmap,
1091 no_ipv6_protocol_nht_rmap_cmd,
1092 "no ipv6 nht " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA,
1093 NO_STR
1094 IP6_STR
1095 "Filter Next Hop tracking route resolution\n"
1096 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA)
1097 {
1098 int i;
1099
1100 if (strcasecmp(argv[0], "any") == 0)
1101 i = ZEBRA_ROUTE_MAX;
1102 else
1103 i = proto_name2num(argv[0]);
1104 if (i < 0)
1105 {
1106 vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
1107 VTY_NEWLINE);
1108 return CMD_WARNING;
1109 }
1110
1111 if (nht_rm[AFI_IP6][i] && argc == 2 && strcmp(argv[1], nht_rm[AFI_IP6][i]))
1112 {
1113 vty_out (vty, "invalid route-map \"%s\"%s", argv[1], VTY_NEWLINE);
1114 return CMD_WARNING;
1115 }
1116
1117 if (nht_rm[AFI_IP6][i])
1118 {
1119 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
1120 nht_rm[AFI_IP6][i] = NULL;
1121 }
1122
1123 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1124
1125 return CMD_SUCCESS;
1126 }
1127
1128 ALIAS (no_ipv6_protocol_nht_rmap,
1129 no_ipv6_protocol_nht_rmap_val_cmd,
1130 "no ipv6 nht " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
1131 NO_STR
1132 IP6_STR
1133 "Filter Next Hop tracking route resolution\n"
1134 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
1135 "Route map name\n")
1136
1137 DEFUN (show_ipv6_protocol_nht,
1138 show_ipv6_protocol_nht_cmd,
1139 "show ipv6 nht route-map",
1140 SHOW_STR
1141 IP6_STR
1142 "IPv6 protocol Next Hop filtering status\n")
1143 {
1144 int i;
1145
1146 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
1147 vty_out(vty, "------------------------%s", VTY_NEWLINE);
1148 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
1149 {
1150 if (nht_rm[AFI_IP6][i])
1151 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
1152 nht_rm[AFI_IP6][i],
1153 VTY_NEWLINE);
1154 else
1155 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
1156 }
1157 if (nht_rm[AFI_IP][i])
1158 vty_out (vty, "%-10s : %-10s%s", "any", nht_rm[AFI_IP6][i],
1159 VTY_NEWLINE);
1160 else
1161 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
1162
1163 return CMD_SUCCESS;
1164 }
1165
1166 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1167
1168 /* `match ip next-hop IP_ACCESS_LIST' */
1169
1170 /* Match function return 1 if match is success else return zero. */
1171 static route_map_result_t
1172 route_match_ip_next_hop (void *rule, struct prefix *prefix,
1173 route_map_object_t type, void *object)
1174 {
1175 struct access_list *alist;
1176 struct nh_rmap_obj *nh_data;
1177 struct prefix_ipv4 p;
1178
1179 if (type == RMAP_ZEBRA)
1180 {
1181 nh_data = object;
1182 if (!nh_data)
1183 return RMAP_DENYMATCH;
1184
1185 switch (nh_data->nexthop->type) {
1186 case NEXTHOP_TYPE_IFINDEX:
1187 /* Interface routes can't match ip next-hop */
1188 return RMAP_NOMATCH;
1189 case NEXTHOP_TYPE_IPV4_IFINDEX:
1190 case NEXTHOP_TYPE_IPV4:
1191 p.family = AF_INET;
1192 p.prefix = nh_data->nexthop->gate.ipv4;
1193 p.prefixlen = IPV4_MAX_BITLEN;
1194 break;
1195 default:
1196 return RMAP_NOMATCH;
1197 }
1198 alist = access_list_lookup (AFI_IP, (char *) rule);
1199 if (alist == NULL)
1200 return RMAP_NOMATCH;
1201
1202 return (access_list_apply (alist, &p) == FILTER_DENY ?
1203 RMAP_NOMATCH : RMAP_MATCH);
1204 }
1205 return RMAP_NOMATCH;
1206 }
1207
1208 /* Route map `ip next-hop' match statement. `arg' should be
1209 access-list name. */
1210 static void *
1211 route_match_ip_next_hop_compile (const char *arg)
1212 {
1213 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1214 }
1215
1216 /* Free route map's compiled `. */
1217 static void
1218 route_match_ip_next_hop_free (void *rule)
1219 {
1220 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1221 }
1222
1223 /* Route map commands for ip next-hop matching. */
1224 static struct route_map_rule_cmd route_match_ip_next_hop_cmd =
1225 {
1226 "ip next-hop",
1227 route_match_ip_next_hop,
1228 route_match_ip_next_hop_compile,
1229 route_match_ip_next_hop_free
1230 };
1231
1232 /* `match ip next-hop prefix-list PREFIX_LIST' */
1233
1234 static route_map_result_t
1235 route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
1236 route_map_object_t type, void *object)
1237 {
1238 struct prefix_list *plist;
1239 struct nh_rmap_obj *nh_data;
1240 struct prefix_ipv4 p;
1241
1242 if (type == RMAP_ZEBRA)
1243 {
1244 nh_data = (struct nh_rmap_obj *)object;
1245 if (!nh_data)
1246 return RMAP_DENYMATCH;
1247
1248 switch (nh_data->nexthop->type) {
1249 case NEXTHOP_TYPE_IFINDEX:
1250 /* Interface routes can't match ip next-hop */
1251 return RMAP_NOMATCH;
1252 case NEXTHOP_TYPE_IPV4_IFINDEX:
1253 case NEXTHOP_TYPE_IPV4:
1254 p.family = AF_INET;
1255 p.prefix = nh_data->nexthop->gate.ipv4;
1256 p.prefixlen = IPV4_MAX_BITLEN;
1257 break;
1258 default:
1259 return RMAP_NOMATCH;
1260 }
1261 plist = prefix_list_lookup (AFI_IP, (char *) rule);
1262 if (plist == NULL)
1263 return RMAP_NOMATCH;
1264
1265 return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
1266 RMAP_NOMATCH : RMAP_MATCH);
1267 }
1268 return RMAP_NOMATCH;
1269 }
1270
1271 static void *
1272 route_match_ip_next_hop_prefix_list_compile (const char *arg)
1273 {
1274 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1275 }
1276
1277 static void
1278 route_match_ip_next_hop_prefix_list_free (void *rule)
1279 {
1280 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1281 }
1282
1283 static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
1284 {
1285 "ip next-hop prefix-list",
1286 route_match_ip_next_hop_prefix_list,
1287 route_match_ip_next_hop_prefix_list_compile,
1288 route_match_ip_next_hop_prefix_list_free
1289 };
1290
1291 /* `match ip address IP_ACCESS_LIST' */
1292
1293 /* Match function should return 1 if match is success else return
1294 zero. */
1295 static route_map_result_t
1296 route_match_ip_address (void *rule, struct prefix *prefix,
1297 route_map_object_t type, void *object)
1298 {
1299 struct access_list *alist;
1300
1301 if (type == RMAP_ZEBRA)
1302 {
1303 alist = access_list_lookup (AFI_IP, (char *) rule);
1304 if (alist == NULL)
1305 return RMAP_NOMATCH;
1306
1307 return (access_list_apply (alist, prefix) == FILTER_DENY ?
1308 RMAP_NOMATCH : RMAP_MATCH);
1309 }
1310 return RMAP_NOMATCH;
1311 }
1312
1313 /* Route map `ip address' match statement. `arg' should be
1314 access-list name. */
1315 static void *
1316 route_match_ip_address_compile (const char *arg)
1317 {
1318 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1319 }
1320
1321 /* Free route map's compiled `ip address' value. */
1322 static void
1323 route_match_ip_address_free (void *rule)
1324 {
1325 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1326 }
1327
1328 /* Route map commands for ip address matching. */
1329 static struct route_map_rule_cmd route_match_ip_address_cmd =
1330 {
1331 "ip address",
1332 route_match_ip_address,
1333 route_match_ip_address_compile,
1334 route_match_ip_address_free
1335 };
1336
1337 /* `match ip address prefix-list PREFIX_LIST' */
1338
1339 static route_map_result_t
1340 route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
1341 route_map_object_t type, void *object)
1342 {
1343 struct prefix_list *plist;
1344
1345 if (type == RMAP_ZEBRA)
1346 {
1347 plist = prefix_list_lookup (AFI_IP, (char *) rule);
1348 if (plist == NULL)
1349 return RMAP_NOMATCH;
1350
1351 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
1352 RMAP_NOMATCH : RMAP_MATCH);
1353 }
1354 return RMAP_NOMATCH;
1355 }
1356
1357 static void *
1358 route_match_ip_address_prefix_list_compile (const char *arg)
1359 {
1360 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1361 }
1362
1363 static void
1364 route_match_ip_address_prefix_list_free (void *rule)
1365 {
1366 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1367 }
1368
1369 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
1370 {
1371 "ip address prefix-list",
1372 route_match_ip_address_prefix_list,
1373 route_match_ip_address_prefix_list_compile,
1374 route_match_ip_address_prefix_list_free
1375 };
1376
1377
1378 /* `match ip address prefix-len PREFIXLEN' */
1379
1380 static route_map_result_t
1381 route_match_ip_address_prefix_len (void *rule, struct prefix *prefix,
1382 route_map_object_t type, void *object)
1383 {
1384 u_int32_t *prefixlen = (u_int32_t *)rule;
1385
1386 if (type == RMAP_ZEBRA)
1387 {
1388 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1389 }
1390 return RMAP_NOMATCH;
1391 }
1392
1393 static void *
1394 route_match_ip_address_prefix_len_compile (const char *arg)
1395 {
1396 u_int32_t *prefix_len;
1397 char *endptr = NULL;
1398 unsigned long tmpval;
1399
1400 /* prefix len value shoud be integer. */
1401 if (! all_digit (arg))
1402 return NULL;
1403
1404 errno = 0;
1405 tmpval = strtoul (arg, &endptr, 10);
1406 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1407 return NULL;
1408
1409 prefix_len = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
1410
1411 if (!prefix_len)
1412 return prefix_len;
1413
1414 *prefix_len = tmpval;
1415 return prefix_len;
1416 }
1417
1418 static void
1419 route_match_ip_address_prefix_len_free (void *rule)
1420 {
1421 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1422 }
1423
1424 static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd =
1425 {
1426 "ip address prefix-len",
1427 route_match_ip_address_prefix_len,
1428 route_match_ip_address_prefix_len_compile,
1429 route_match_ip_address_prefix_len_free
1430 };
1431
1432
1433 /* `match ip nexthop prefix-len PREFIXLEN' */
1434
1435 static route_map_result_t
1436 route_match_ip_nexthop_prefix_len (void *rule, struct prefix *prefix,
1437 route_map_object_t type, void *object)
1438 {
1439 u_int32_t *prefixlen = (u_int32_t *)rule;
1440 struct nh_rmap_obj *nh_data;
1441 struct prefix_ipv4 p;
1442
1443 if (type == RMAP_ZEBRA)
1444 {
1445 nh_data = (struct nh_rmap_obj *)object;
1446 if (!nh_data || !nh_data->nexthop)
1447 return RMAP_DENYMATCH;
1448
1449 switch (nh_data->nexthop->type) {
1450 case NEXTHOP_TYPE_IFINDEX:
1451 /* Interface routes can't match ip next-hop */
1452 return RMAP_NOMATCH;
1453 case NEXTHOP_TYPE_IPV4_IFINDEX:
1454 case NEXTHOP_TYPE_IPV4:
1455 p.family = AF_INET;
1456 p.prefix = nh_data->nexthop->gate.ipv4;
1457 p.prefixlen = IPV4_MAX_BITLEN;
1458 break;
1459 default:
1460 return RMAP_NOMATCH;
1461 }
1462 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1463 }
1464 return RMAP_NOMATCH;
1465 }
1466
1467 static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd =
1468 {
1469 "ip next-hop prefix-len",
1470 route_match_ip_nexthop_prefix_len,
1471 route_match_ip_address_prefix_len_compile, /* reuse */
1472 route_match_ip_address_prefix_len_free /* reuse */
1473 };
1474
1475 /* `match source-protocol PROTOCOL' */
1476
1477 static route_map_result_t
1478 route_match_source_protocol (void *rule, struct prefix *prefix,
1479 route_map_object_t type, void *object)
1480 {
1481 u_int32_t *rib_type = (u_int32_t *)rule;
1482 struct nh_rmap_obj *nh_data;
1483
1484 if (type == RMAP_ZEBRA)
1485 {
1486 nh_data = (struct nh_rmap_obj *)object;
1487 if (!nh_data)
1488 return RMAP_DENYMATCH;
1489
1490 return ((nh_data->source_protocol == *rib_type)
1491 ? RMAP_MATCH : RMAP_NOMATCH);
1492 }
1493 return RMAP_NOMATCH;
1494 }
1495
1496 static void *
1497 route_match_source_protocol_compile (const char *arg)
1498 {
1499 u_int32_t *rib_type;
1500 int i;
1501
1502 i = proto_name2num(arg);
1503 rib_type = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
1504
1505 *rib_type = i;
1506
1507 return rib_type;
1508 }
1509
1510 static void
1511 route_match_source_protocol_free (void *rule)
1512 {
1513 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1514 }
1515
1516 static struct route_map_rule_cmd route_match_source_protocol_cmd =
1517 {
1518 "source-protocol",
1519 route_match_source_protocol,
1520 route_match_source_protocol_compile,
1521 route_match_source_protocol_free
1522 };
1523
1524 /* `set src A.B.C.D' */
1525
1526 /* Set src. */
1527 static route_map_result_t
1528 route_set_src (void *rule, struct prefix *prefix,
1529 route_map_object_t type, void *object)
1530 {
1531 struct nh_rmap_obj *nh_data;
1532
1533 if (type == RMAP_ZEBRA)
1534 {
1535 nh_data = (struct nh_rmap_obj *)object;
1536 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1537 }
1538 return RMAP_OKAY;
1539 }
1540
1541 /* set src compilation. */
1542 static void *
1543 route_set_src_compile (const char *arg)
1544 {
1545 union g_addr src, *psrc;
1546
1547 if (
1548 #ifdef HAVE_IPV6
1549 (inet_pton(AF_INET6, arg, &src.ipv6) == 1) ||
1550 #endif /* HAVE_IPV6 */
1551 (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1)))
1552 {
1553 psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr));
1554 *psrc = src;
1555 return psrc;
1556 }
1557 return NULL;
1558 }
1559
1560 /* Free route map's compiled `set src' value. */
1561 static void
1562 route_set_src_free (void *rule)
1563 {
1564 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1565 }
1566
1567 /* Set src rule structure. */
1568 static struct route_map_rule_cmd route_set_src_cmd =
1569 {
1570 "src",
1571 route_set_src,
1572 route_set_src_compile,
1573 route_set_src_free,
1574 };
1575
1576 static int
1577 zebra_route_map_update_timer (struct thread *thread)
1578 {
1579 zebra_t_rmap_update = NULL;
1580
1581 if (IS_ZEBRA_DEBUG_EVENT)
1582 zlog_debug("Event driven route-map update triggered");
1583
1584 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1585 zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing",
1586 VRF_DEFAULT);
1587
1588 zebra_import_table_rm_update ();
1589 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
1590 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1591 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1592
1593 return (0);
1594 }
1595
1596 static void
1597 zebra_route_map_set_delay_timer(u_int32_t value)
1598 {
1599 zebra_rmap_update_timer = value;
1600 if (!value && zebra_t_rmap_update)
1601 {
1602 /* Event driven route map updates is being disabled */
1603 /* But there's a pending timer. Fire it off now */
1604 thread_cancel(zebra_t_rmap_update);
1605 zebra_route_map_update_timer(zebra_t_rmap_update);
1606 }
1607 }
1608
1609 void
1610 zebra_route_map_write_delay_timer (struct vty *vty)
1611 {
1612 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1613 vty_out (vty, "zebra route-map delay-timer %d%s", zebra_rmap_update_timer,
1614 VTY_NEWLINE);
1615 return;
1616 }
1617
1618 route_map_result_t
1619 zebra_route_map_check (int family, int rib_type, struct prefix *p,
1620 struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag)
1621 {
1622 struct route_map *rmap = NULL;
1623 route_map_result_t ret = RMAP_MATCH;
1624 struct nh_rmap_obj nh_obj;
1625
1626 nh_obj.nexthop = nexthop;
1627 nh_obj.vrf_id = vrf_id;
1628 nh_obj.source_protocol = rib_type;
1629 nh_obj.metric = 0;
1630 nh_obj.tag = tag;
1631
1632 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1633 rmap = route_map_lookup_by_name (proto_rm[family][rib_type]);
1634 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1635 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1636 if (rmap) {
1637 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1638 }
1639
1640 return (ret);
1641 }
1642
1643 char *
1644 zebra_get_import_table_route_map (afi_t afi, uint32_t table)
1645 {
1646 return zebra_import_table_routemap[afi][table];
1647 }
1648
1649 void
1650 zebra_add_import_table_route_map (afi_t afi, const char *rmap_name, uint32_t table)
1651 {
1652 zebra_import_table_routemap[afi][table] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap_name);
1653 }
1654
1655 void
1656 zebra_del_import_table_route_map (afi_t afi, uint32_t table)
1657 {
1658 XFREE (MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1659 }
1660
1661 route_map_result_t
1662 zebra_import_table_route_map_check (int family, int rib_type, struct prefix *p,
1663 struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag, const char *rmap_name)
1664 {
1665 struct route_map *rmap = NULL;
1666 route_map_result_t ret = RMAP_DENYMATCH;
1667 struct nh_rmap_obj nh_obj;
1668
1669 nh_obj.nexthop = nexthop;
1670 nh_obj.vrf_id = vrf_id;
1671 nh_obj.source_protocol = rib_type;
1672 nh_obj.metric = 0;
1673 nh_obj.tag = tag;
1674
1675 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1676 rmap = route_map_lookup_by_name (rmap_name);
1677 if (rmap) {
1678 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1679 }
1680
1681 return (ret);
1682 }
1683
1684 route_map_result_t
1685 zebra_nht_route_map_check (int family, int client_proto, struct prefix *p,
1686 struct rib * rib, struct nexthop *nexthop)
1687 {
1688 struct route_map *rmap = NULL;
1689 route_map_result_t ret = RMAP_MATCH;
1690 struct nh_rmap_obj nh_obj;
1691
1692 nh_obj.nexthop = nexthop;
1693 nh_obj.vrf_id = rib->vrf_id;
1694 nh_obj.source_protocol = rib->type;
1695 nh_obj.metric = rib->metric;
1696 nh_obj.tag = rib->tag;
1697
1698 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1699 rmap = route_map_lookup_by_name (nht_rm[family][client_proto]);
1700 if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX])
1701 rmap = route_map_lookup_by_name (nht_rm[family][ZEBRA_ROUTE_MAX]);
1702 if (rmap) {
1703 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1704 }
1705
1706 return (ret);
1707 }
1708
1709 static void
1710 zebra_route_map_mark_update (const char *rmap_name)
1711 {
1712 /* rmap_update_timer of 0 means don't do route updates */
1713 if (zebra_rmap_update_timer && !zebra_t_rmap_update)
1714 zebra_t_rmap_update =
1715 thread_add_timer(zebrad.master, zebra_route_map_update_timer, NULL,
1716 zebra_rmap_update_timer);
1717 }
1718
1719 static void
1720 zebra_route_map_add (const char *rmap_name)
1721 {
1722 zebra_route_map_mark_update(rmap_name);
1723 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1724 }
1725
1726 static void
1727 zebra_route_map_delete (const char *rmap_name)
1728 {
1729 zebra_route_map_mark_update(rmap_name);
1730 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1731 }
1732
1733 static void
1734 zebra_route_map_event (route_map_event_t event, const char *rmap_name)
1735 {
1736 zebra_route_map_mark_update(rmap_name);
1737 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1738 }
1739
1740 /* ip protocol configuration write function */
1741 void
1742 zebra_routemap_config_write_protocol (struct vty *vty)
1743 {
1744 int i;
1745
1746 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
1747 {
1748 if (proto_rm[AFI_IP][i])
1749 vty_out (vty, "ip protocol %s route-map %s%s", zebra_route_string(i),
1750 proto_rm[AFI_IP][i], VTY_NEWLINE);
1751
1752 if (proto_rm[AFI_IP6][i])
1753 vty_out (vty, "ipv6 protocol %s route-map %s%s", zebra_route_string(i),
1754 proto_rm[AFI_IP6][i], VTY_NEWLINE);
1755
1756 if (nht_rm[AFI_IP][i])
1757 vty_out (vty, "ip nht %s route-map %s%s", zebra_route_string(i),
1758 nht_rm[AFI_IP][i], VTY_NEWLINE);
1759
1760 if (nht_rm[AFI_IP6][i])
1761 vty_out (vty, "ipv6 nht %s route-map %s%s", zebra_route_string(i),
1762 nht_rm[AFI_IP6][i], VTY_NEWLINE);
1763 }
1764
1765 if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1766 vty_out (vty, "ip protocol %s route-map %s%s", "any",
1767 proto_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1768
1769 if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1770 vty_out (vty, "ipv6 protocol %s route-map %s%s", "any",
1771 proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1772
1773 if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1774 vty_out (vty, "ip nht %s route-map %s%s", "any",
1775 nht_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1776
1777 if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1778 vty_out (vty, "ipv6 nht %s route-map %s%s", "any",
1779 nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1780
1781 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1782 vty_out (vty, "zebra route-map delay-timer %d%s", zebra_rmap_update_timer,
1783 VTY_NEWLINE);
1784 }
1785
1786 void
1787 zebra_route_map_init ()
1788 {
1789 install_element (CONFIG_NODE, &ip_protocol_cmd);
1790 install_element (CONFIG_NODE, &no_ip_protocol_cmd);
1791 install_element (CONFIG_NODE, &no_ip_protocol_val_cmd);
1792 install_element (VIEW_NODE, &show_ip_protocol_cmd);
1793 install_element (CONFIG_NODE, &ipv6_protocol_cmd);
1794 install_element (CONFIG_NODE, &no_ipv6_protocol_cmd);
1795 install_element (CONFIG_NODE, &no_ipv6_protocol_val_cmd);
1796 install_element (VIEW_NODE, &show_ipv6_protocol_cmd);
1797 install_element (CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1798 install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1799 install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_val_cmd);
1800 install_element (VIEW_NODE, &show_ip_protocol_nht_cmd);
1801 install_element (CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1802 install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1803 install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_val_cmd);
1804 install_element (VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1805 install_element (CONFIG_NODE, &zebra_route_map_timer_cmd);
1806 install_element (CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1807 install_element (CONFIG_NODE, &no_zebra_route_map_timer_val_cmd);
1808
1809 route_map_init ();
1810
1811 route_map_add_hook (zebra_route_map_add);
1812 route_map_delete_hook (zebra_route_map_delete);
1813 route_map_event_hook (zebra_route_map_event);
1814
1815 route_map_install_match (&route_match_tag_cmd);
1816 route_map_install_match (&route_match_interface_cmd);
1817 route_map_install_match (&route_match_ip_next_hop_cmd);
1818 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
1819 route_map_install_match (&route_match_ip_address_cmd);
1820 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
1821 route_map_install_match (&route_match_ip_address_prefix_len_cmd);
1822 route_map_install_match (&route_match_ip_nexthop_prefix_len_cmd);
1823 route_map_install_match (&route_match_source_protocol_cmd);
1824 /* */
1825 route_map_install_set (&route_set_src_cmd);
1826 /* */
1827 install_element (RMAP_NODE, &match_tag_cmd);
1828 install_element (RMAP_NODE, &no_match_tag_cmd);
1829 install_element (RMAP_NODE, &no_match_tag_val_cmd);
1830 install_element (RMAP_NODE, &match_interface_cmd);
1831 install_element (RMAP_NODE, &no_match_interface_cmd);
1832 install_element (RMAP_NODE, &no_match_interface_val_cmd);
1833 install_element (RMAP_NODE, &match_ip_next_hop_cmd);
1834 install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
1835 install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
1836 install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
1837 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
1838 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
1839 install_element (RMAP_NODE, &match_ip_address_cmd);
1840 install_element (RMAP_NODE, &no_match_ip_address_cmd);
1841 install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
1842 install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
1843 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
1844 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
1845 install_element (RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
1846 install_element (RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
1847 install_element (RMAP_NODE, &no_match_ip_nexthop_prefix_len_val_cmd);
1848 install_element (RMAP_NODE, &match_ip_address_prefix_len_cmd);
1849 install_element (RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
1850 install_element (RMAP_NODE, &no_match_ip_address_prefix_len_val_cmd);
1851 install_element (RMAP_NODE, &match_source_protocol_cmd);
1852 install_element (RMAP_NODE, &no_match_source_protocol_cmd);
1853 /* */
1854 install_element (RMAP_NODE, &set_src_cmd);
1855 install_element (RMAP_NODE, &no_set_src_cmd);
1856 }