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