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