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