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