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