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