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