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