]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_routemap.c
Merge pull request #43 from pguibert6WIND/frr_6wind_mpbgpgracefulrestart_1
[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;
0032dd59
FL
192 ifindex = ifname2ifindex_vrf (ifname, nh_data->vrf_id);
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)
378 pif = if_lookup_exact_address_vrf ((void *)&src.ipv4, AF_INET,
1a1a7065 379 vrf->vrf_id);
f91386cb
FL
380 else if (family == AF_INET6)
381 pif = if_lookup_exact_address_vrf ((void *)&src.ipv6, AF_INET6,
1a1a7065 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,
9ccf14f7 446 "ip protocol <kernel|connected|static|rip|ospf|isis|bgp|pim|table|any> route-map ROUTE-MAP",
9f0ea7d4
DS
447 IP_STR
448 "Filter routing info exchanged between zebra and protocol\n"
449 QUAGGA_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,
9ccf14f7 485 "no ip protocol <kernel|connected|static|rip|ospf|isis|bgp|pim|table|any> [route-map ROUTE-MAP]",
518f0eb1 486 NO_STR
9f0ea7d4
DS
487 IP_STR
488 "Stop filtering routing info between zebra and protocol\n"
489 QUAGGA_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
9f0ea7d4 524
518f0eb1
DS
525DEFUN (show_ip_protocol,
526 show_ip_protocol_cmd,
527 "show ip protocol",
528 SHOW_STR
529 IP_STR
530 "IP protocol filtering status\n")
531{
532 int i;
533
534 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
535 vty_out(vty, "------------------------%s", VTY_NEWLINE);
536 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
537 {
538 if (proto_rm[AFI_IP][i])
539 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
540 proto_rm[AFI_IP][i],
541 VTY_NEWLINE);
542 else
543 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
544 }
545 if (proto_rm[AFI_IP][i])
546 vty_out (vty, "%-10s : %-10s%s", "any", proto_rm[AFI_IP][i],
547 VTY_NEWLINE);
548 else
549 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
550
551 return CMD_SUCCESS;
552}
553
0aabccc0
DD
554DEFUN (ipv6_protocol,
555 ipv6_protocol_cmd,
9ccf14f7 556 "ipv6 protocol <kernel|connected|static|ripng|ospf6|isis|bgp|table|any> route-map ROUTE-MAP",
0aabccc0
DD
557 IP6_STR
558 "Filter IPv6 routing info exchanged between zebra and protocol\n"
559 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
7757e5e1 560 "Specify route map\n"
0aabccc0
DD
561 "Route map name\n")
562{
7757e5e1
QY
563 char *proto = argv[2]->text;
564 char *rmap = argv[4]->arg;
0aabccc0 565 int i;
0aabccc0 566
7757e5e1 567 if (strcasecmp(proto, "any") == 0)
0aabccc0
DD
568 i = ZEBRA_ROUTE_MAX;
569 else
7757e5e1 570 i = proto_name2num(proto);
0aabccc0
DD
571 if (i < 0)
572 {
7757e5e1 573 vty_out (vty, "invalid protocol name \"%s\"%s", proto, VTY_NEWLINE);
0aabccc0
DD
574 return CMD_WARNING;
575 }
576 if (proto_rm[AFI_IP6][i])
577 {
7757e5e1 578 if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0)
0aabccc0
DD
579 return CMD_SUCCESS;
580
581 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
582 }
7757e5e1 583 proto_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap);
b84c7253 584
41ec9222 585 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1c848137 586 zlog_debug ("%u: IPv6 Routemap config for protocol %s, scheduling RIB processing",
7757e5e1 587 VRF_DEFAULT, proto);
b84c7253 588
1c848137 589 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
0aabccc0
DD
590 return CMD_SUCCESS;
591}
592
593DEFUN (no_ipv6_protocol,
594 no_ipv6_protocol_cmd,
9ccf14f7 595 "no ipv6 protocol <kernel|connected|static|ripng|ospf6|isis|bgp|table|any> [route-map ROUTE-MAP]",
0aabccc0
DD
596 NO_STR
597 IP6_STR
598 "Stop filtering IPv6 routing info between zebra and protocol\n"
599 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
7757e5e1
QY
600 "Specify route map\n"
601 "Route map name\n")
0aabccc0 602{
7757e5e1
QY
603 const char *proto = argv[3]->text;
604 const char *rmap = (argc == 6) ? argv[5]->arg : NULL;
0aabccc0 605 int i;
0aabccc0 606
7757e5e1 607 if (strcasecmp(proto, "any") == 0)
0aabccc0
DD
608 i = ZEBRA_ROUTE_MAX;
609 else
7757e5e1 610 i = proto_name2num(proto);
0aabccc0
DD
611 if (i < 0)
612 {
7757e5e1 613 vty_out (vty, "invalid protocol name \"%s\"%s", proto, VTY_NEWLINE);
0aabccc0
DD
614 return CMD_WARNING;
615 }
616 if (!proto_rm[AFI_IP6][i])
617 return CMD_SUCCESS;
618
7757e5e1 619 if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0)
0aabccc0
DD
620 {
621 XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
622 proto_rm[AFI_IP6][i] = NULL;
b84c7253 623
41ec9222 624 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1c848137 625 zlog_debug ("%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing",
7757e5e1 626 VRF_DEFAULT, proto);
b84c7253 627
1c848137 628 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
0aabccc0
DD
629 }
630 return CMD_SUCCESS;
631}
632
0aabccc0
DD
633
634DEFUN (show_ipv6_protocol,
635 show_ipv6_protocol_cmd,
636 "show ipv6 protocol",
637 SHOW_STR
638 IP6_STR
639 "IPv6 protocol filtering status\n")
640{
641 int i;
642
643 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
644 vty_out(vty, "------------------------%s", VTY_NEWLINE);
645 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
646 {
647 if (proto_rm[AFI_IP6][i])
648 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
649 proto_rm[AFI_IP6][i],
650 VTY_NEWLINE);
651 else
652 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
653 }
654 if (proto_rm[AFI_IP6][i])
655 vty_out (vty, "%-10s : %-10s%s", "any", proto_rm[AFI_IP6][i],
656 VTY_NEWLINE);
657 else
658 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
659
660 return CMD_SUCCESS;
661}
662
9f0ea7d4
DS
663DEFUN (ip_protocol_nht_rmap,
664 ip_protocol_nht_rmap_cmd,
9ccf14f7 665 "ip nht <kernel|connected|static|rip|ospf|isis|bgp|pim|table|any> route-map ROUTE-MAP",
9f0ea7d4
DS
666 IP_STR
667 "Filter Next Hop tracking route resolution\n"
668 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
7757e5e1 669 "Specify route map\n"
9f0ea7d4
DS
670 "Route map name\n")
671{
7757e5e1
QY
672 char *proto = argv[2]->text;
673 char *rmap = argv[4]->arg;
9f0ea7d4
DS
674 int i;
675
7757e5e1 676 if (strcasecmp(proto, "any") == 0)
9f0ea7d4
DS
677 i = ZEBRA_ROUTE_MAX;
678 else
7757e5e1 679 i = proto_name2num(proto);
9f0ea7d4
DS
680 if (i < 0)
681 {
7757e5e1 682 vty_out (vty, "invalid protocol name \"%s\"%s", proto, VTY_NEWLINE);
9f0ea7d4
DS
683 return CMD_WARNING;
684 }
685 if (nht_rm[AFI_IP][i])
686 {
7757e5e1 687 if (strcmp(nht_rm[AFI_IP][i], rmap) == 0)
9f0ea7d4
DS
688 return CMD_SUCCESS;
689
690 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
691 }
692
7757e5e1 693 nht_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap);
078430f6 694 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
9f0ea7d4
DS
695
696 return CMD_SUCCESS;
697}
698
699DEFUN (no_ip_protocol_nht_rmap,
700 no_ip_protocol_nht_rmap_cmd,
9ccf14f7 701 "no ip nht <kernel|connected|static|rip|ospf|isis|bgp|pim|table|any> [route-map ROUTE-MAP]",
9f0ea7d4
DS
702 NO_STR
703 IP_STR
704 "Filter Next Hop tracking route resolution\n"
7757e5e1
QY
705 QUAGGA_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
706 "Specify route map\n"
707 "Route map name\n")
9f0ea7d4 708{
55cb6743 709 int idx = 0;
7757e5e1 710 char *proto = argv[3]->text;
55cb6743
QY
711 char *rmap = argv_find (argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg : NULL;
712
713 int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX : proto_name2num(proto);
9f0ea7d4 714
9f0ea7d4
DS
715 if (i < 0)
716 {
7757e5e1
QY
717 vty_out (vty, "invalid protocol name \"%s\"%s", proto, VTY_NEWLINE);
718 return CMD_WARNING;
9f0ea7d4 719 }
55cb6743 720
9f0ea7d4
DS
721 if (!nht_rm[AFI_IP][i])
722 return CMD_SUCCESS;
723
55cb6743 724 if (!rmap || strcmp(rmap, nht_rm[AFI_IP][i]) == 0)
9f0ea7d4
DS
725 {
726 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]);
727 nht_rm[AFI_IP][i] = NULL;
078430f6 728 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
9f0ea7d4
DS
729 }
730 return CMD_SUCCESS;
731}
732
9f0ea7d4
DS
733
734DEFUN (show_ip_protocol_nht,
735 show_ip_protocol_nht_cmd,
736 "show ip nht route-map",
3a2d747c
QY
737 SHOW_STR
738 IP_STR
739 "IP nexthop tracking table\n"
9f0ea7d4
DS
740 "IP Next Hop tracking filtering status\n")
741{
742 int i;
743
744 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
745 vty_out(vty, "------------------------%s", VTY_NEWLINE);
746 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
747 {
748 if (nht_rm[AFI_IP][i])
749 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
750 nht_rm[AFI_IP][i],
751 VTY_NEWLINE);
752 else
753 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
754 }
755 if (nht_rm[AFI_IP][i])
756 vty_out (vty, "%-10s : %-10s%s", "any", nht_rm[AFI_IP][i],
757 VTY_NEWLINE);
758 else
759 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
760
761 return CMD_SUCCESS;
762}
763
764DEFUN (ipv6_protocol_nht_rmap,
765 ipv6_protocol_nht_rmap_cmd,
9ccf14f7 766 "ipv6 nht <kernel|connected|static|ripng|ospf6|isis|bgp|table|any> route-map ROUTE-MAP",
9f0ea7d4
DS
767 IP6_STR
768 "Filter Next Hop tracking route resolution\n"
769 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
7757e5e1 770 "Specify route map\n"
9f0ea7d4
DS
771 "Route map name\n")
772{
7757e5e1
QY
773 char *proto = argv[2]->text;
774 char *rmap = argv[4]->arg;
9f0ea7d4
DS
775 int i;
776
7757e5e1 777 if (strcasecmp(proto, "any") == 0)
9f0ea7d4
DS
778 i = ZEBRA_ROUTE_MAX;
779 else
7757e5e1 780 i = proto_name2num(proto);
9f0ea7d4
DS
781 if (i < 0)
782 {
7757e5e1 783 vty_out (vty, "invalid protocol name \"%s\"%s", proto, VTY_NEWLINE);
9f0ea7d4
DS
784 return CMD_WARNING;
785 }
786 if (nht_rm[AFI_IP6][i])
787 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
7757e5e1 788 nht_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap);
078430f6 789 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
9f0ea7d4
DS
790
791 return CMD_SUCCESS;
792}
793
794DEFUN (no_ipv6_protocol_nht_rmap,
795 no_ipv6_protocol_nht_rmap_cmd,
9ccf14f7 796 "no ipv6 nht <kernel|connected|static|ripng|ospf6|isis|bgp|table|any> [route-map ROUTE-MAP]",
9f0ea7d4
DS
797 NO_STR
798 IP6_STR
799 "Filter Next Hop tracking route resolution\n"
7757e5e1
QY
800 QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
801 "Specify route map\n"
802 "Route map name\n")
9f0ea7d4 803{
7757e5e1
QY
804 char *proto = argv[3]->text;
805 char *rmap = (argc == 6) ? argv[5]->arg : NULL;
9f0ea7d4
DS
806 int i;
807
7757e5e1 808 if (strcasecmp(proto, "any") == 0)
9f0ea7d4
DS
809 i = ZEBRA_ROUTE_MAX;
810 else
7757e5e1 811 i = proto_name2num(proto);
9f0ea7d4
DS
812 if (i < 0)
813 {
7757e5e1
QY
814 vty_out (vty, "invalid protocol name \"%s\"%s", proto, VTY_NEWLINE);
815 return CMD_WARNING;
9f0ea7d4 816 }
9f0ea7d4 817
7757e5e1 818 if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i]))
813d4307 819 {
7757e5e1 820 vty_out (vty, "invalid route-map \"%s\"%s", rmap, VTY_NEWLINE);
813d4307
DW
821 return CMD_WARNING;
822 }
823
824 if (nht_rm[AFI_IP6][i])
9f0ea7d4
DS
825 {
826 XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]);
827 nht_rm[AFI_IP6][i] = NULL;
9f0ea7d4
DS
828 }
829
813d4307
DW
830 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
831
9f0ea7d4
DS
832 return CMD_SUCCESS;
833}
834
9f0ea7d4
DS
835
836DEFUN (show_ipv6_protocol_nht,
837 show_ipv6_protocol_nht_cmd,
838 "show ipv6 nht route-map",
3a2d747c
QY
839 SHOW_STR
840 IP6_STR
841 "Next Hop filtering status\n"
842 "Route-map\n")
9f0ea7d4
DS
843{
844 int i;
845
846 vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
847 vty_out(vty, "------------------------%s", VTY_NEWLINE);
848 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
849 {
850 if (nht_rm[AFI_IP6][i])
851 vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
852 nht_rm[AFI_IP6][i],
853 VTY_NEWLINE);
854 else
855 vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
856 }
857 if (nht_rm[AFI_IP][i])
858 vty_out (vty, "%-10s : %-10s%s", "any", nht_rm[AFI_IP6][i],
859 VTY_NEWLINE);
860 else
861 vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
862
863 return CMD_SUCCESS;
864}
865
5921ef9a
PJ
866/*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
867
868/* `match ip next-hop IP_ACCESS_LIST' */
869
870/* Match function return 1 if match is success else return zero. */
871static route_map_result_t
872route_match_ip_next_hop (void *rule, struct prefix *prefix,
873 route_map_object_t type, void *object)
874{
875 struct access_list *alist;
9f0ea7d4 876 struct nh_rmap_obj *nh_data;
5921ef9a
PJ
877 struct prefix_ipv4 p;
878
879 if (type == RMAP_ZEBRA)
880 {
9f0ea7d4
DS
881 nh_data = object;
882 if (!nh_data)
883 return RMAP_DENYMATCH;
884
885 switch (nh_data->nexthop->type) {
5921ef9a 886 case NEXTHOP_TYPE_IFINDEX:
fa713d9e
CF
887 /* Interface routes can't match ip next-hop */
888 return RMAP_NOMATCH;
5921ef9a 889 case NEXTHOP_TYPE_IPV4_IFINDEX:
5921ef9a
PJ
890 case NEXTHOP_TYPE_IPV4:
891 p.family = AF_INET;
9f0ea7d4 892 p.prefix = nh_data->nexthop->gate.ipv4;
5921ef9a
PJ
893 p.prefixlen = IPV4_MAX_BITLEN;
894 break;
895 default:
896 return RMAP_NOMATCH;
897 }
898 alist = access_list_lookup (AFI_IP, (char *) rule);
899 if (alist == NULL)
900 return RMAP_NOMATCH;
901
902 return (access_list_apply (alist, &p) == FILTER_DENY ?
903 RMAP_NOMATCH : RMAP_MATCH);
904 }
905 return RMAP_NOMATCH;
906}
907
908/* Route map `ip next-hop' match statement. `arg' should be
909 access-list name. */
910static void *
911route_match_ip_next_hop_compile (const char *arg)
912{
913 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
914}
915
916/* Free route map's compiled `. */
917static void
918route_match_ip_next_hop_free (void *rule)
919{
920 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
921}
922
923/* Route map commands for ip next-hop matching. */
924static struct route_map_rule_cmd route_match_ip_next_hop_cmd =
925{
926 "ip next-hop",
927 route_match_ip_next_hop,
928 route_match_ip_next_hop_compile,
929 route_match_ip_next_hop_free
930};
6b0655a2 931
5921ef9a
PJ
932/* `match ip next-hop prefix-list PREFIX_LIST' */
933
934static route_map_result_t
935route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
936 route_map_object_t type, void *object)
937{
938 struct prefix_list *plist;
9f0ea7d4 939 struct nh_rmap_obj *nh_data;
5921ef9a
PJ
940 struct prefix_ipv4 p;
941
942 if (type == RMAP_ZEBRA)
943 {
9f0ea7d4
DS
944 nh_data = (struct nh_rmap_obj *)object;
945 if (!nh_data)
946 return RMAP_DENYMATCH;
947
948 switch (nh_data->nexthop->type) {
5921ef9a 949 case NEXTHOP_TYPE_IFINDEX:
fa713d9e
CF
950 /* Interface routes can't match ip next-hop */
951 return RMAP_NOMATCH;
5921ef9a 952 case NEXTHOP_TYPE_IPV4_IFINDEX:
5921ef9a
PJ
953 case NEXTHOP_TYPE_IPV4:
954 p.family = AF_INET;
9f0ea7d4 955 p.prefix = nh_data->nexthop->gate.ipv4;
5921ef9a
PJ
956 p.prefixlen = IPV4_MAX_BITLEN;
957 break;
958 default:
959 return RMAP_NOMATCH;
960 }
961 plist = prefix_list_lookup (AFI_IP, (char *) rule);
962 if (plist == NULL)
963 return RMAP_NOMATCH;
964
965 return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
966 RMAP_NOMATCH : RMAP_MATCH);
967 }
968 return RMAP_NOMATCH;
969}
970
971static void *
972route_match_ip_next_hop_prefix_list_compile (const char *arg)
973{
974 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
975}
976
977static void
978route_match_ip_next_hop_prefix_list_free (void *rule)
979{
980 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
981}
982
983static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
984{
985 "ip next-hop prefix-list",
986 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
989};
6b0655a2 990
5921ef9a
PJ
991/* `match ip address IP_ACCESS_LIST' */
992
993/* Match function should return 1 if match is success else return
994 zero. */
995static route_map_result_t
996route_match_ip_address (void *rule, struct prefix *prefix,
997 route_map_object_t type, void *object)
998{
999 struct access_list *alist;
1000
1001 if (type == RMAP_ZEBRA)
1002 {
1003 alist = access_list_lookup (AFI_IP, (char *) rule);
1004 if (alist == NULL)
1005 return RMAP_NOMATCH;
1006
1007 return (access_list_apply (alist, prefix) == FILTER_DENY ?
1008 RMAP_NOMATCH : RMAP_MATCH);
1009 }
1010 return RMAP_NOMATCH;
1011}
1012
1013/* Route map `ip address' match statement. `arg' should be
1014 access-list name. */
1015static void *
1016route_match_ip_address_compile (const char *arg)
1017{
1018 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1019}
1020
1021/* Free route map's compiled `ip address' value. */
1022static void
1023route_match_ip_address_free (void *rule)
1024{
1025 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1026}
1027
1028/* Route map commands for ip address matching. */
1029static struct route_map_rule_cmd route_match_ip_address_cmd =
1030{
1031 "ip address",
1032 route_match_ip_address,
1033 route_match_ip_address_compile,
1034 route_match_ip_address_free
1035};
6b0655a2 1036
5921ef9a
PJ
1037/* `match ip address prefix-list PREFIX_LIST' */
1038
1039static route_map_result_t
1040route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
1041 route_map_object_t type, void *object)
1042{
1043 struct prefix_list *plist;
1044
1045 if (type == RMAP_ZEBRA)
1046 {
1047 plist = prefix_list_lookup (AFI_IP, (char *) rule);
1048 if (plist == NULL)
1049 return RMAP_NOMATCH;
1050
1051 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
1052 RMAP_NOMATCH : RMAP_MATCH);
1053 }
1054 return RMAP_NOMATCH;
1055}
1056
1057static void *
1058route_match_ip_address_prefix_list_compile (const char *arg)
1059{
1060 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
1061}
1062
1063static void
1064route_match_ip_address_prefix_list_free (void *rule)
1065{
1066 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1067}
1068
1069static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
1070{
1071 "ip address prefix-list",
1072 route_match_ip_address_prefix_list,
1073 route_match_ip_address_prefix_list_compile,
1074 route_match_ip_address_prefix_list_free
1075};
1076
6b0655a2 1077
9f0ea7d4
DS
1078/* `match ip address prefix-len PREFIXLEN' */
1079
1080static route_map_result_t
1081route_match_ip_address_prefix_len (void *rule, struct prefix *prefix,
1082 route_map_object_t type, void *object)
1083{
1084 u_int32_t *prefixlen = (u_int32_t *)rule;
1085
1086 if (type == RMAP_ZEBRA)
1087 {
1088 return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1089 }
1090 return RMAP_NOMATCH;
1091}
1092
1093static void *
1094route_match_ip_address_prefix_len_compile (const char *arg)
1095{
1096 u_int32_t *prefix_len;
1097 char *endptr = NULL;
1098 unsigned long tmpval;
1099
1100 /* prefix len value shoud be integer. */
1101 if (! all_digit (arg))
1102 return NULL;
1103
1104 errno = 0;
1105 tmpval = strtoul (arg, &endptr, 10);
1106 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1107 return NULL;
1108
1109 prefix_len = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
1110
1111 if (!prefix_len)
1112 return prefix_len;
1113
1114 *prefix_len = tmpval;
1115 return prefix_len;
1116}
1117
1118static void
1119route_match_ip_address_prefix_len_free (void *rule)
1120{
1121 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1122}
1123
1124static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd =
1125{
1126 "ip address prefix-len",
1127 route_match_ip_address_prefix_len,
1128 route_match_ip_address_prefix_len_compile,
1129 route_match_ip_address_prefix_len_free
1130};
1131
1132
1133/* `match ip nexthop prefix-len PREFIXLEN' */
1134
1135static route_map_result_t
1136route_match_ip_nexthop_prefix_len (void *rule, struct prefix *prefix,
1137 route_map_object_t type, void *object)
1138{
1139 u_int32_t *prefixlen = (u_int32_t *)rule;
1140 struct nh_rmap_obj *nh_data;
1141 struct prefix_ipv4 p;
1142
1143 if (type == RMAP_ZEBRA)
1144 {
1145 nh_data = (struct nh_rmap_obj *)object;
1146 if (!nh_data || !nh_data->nexthop)
1147 return RMAP_DENYMATCH;
1148
1149 switch (nh_data->nexthop->type) {
1150 case NEXTHOP_TYPE_IFINDEX:
9f0ea7d4
DS
1151 /* Interface routes can't match ip next-hop */
1152 return RMAP_NOMATCH;
1153 case NEXTHOP_TYPE_IPV4_IFINDEX:
9f0ea7d4
DS
1154 case NEXTHOP_TYPE_IPV4:
1155 p.family = AF_INET;
1156 p.prefix = nh_data->nexthop->gate.ipv4;
1157 p.prefixlen = IPV4_MAX_BITLEN;
1158 break;
1159 default:
1160 return RMAP_NOMATCH;
1161 }
1162 return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1163 }
1164 return RMAP_NOMATCH;
1165}
1166
1167static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd =
1168{
1169 "ip next-hop prefix-len",
1170 route_match_ip_nexthop_prefix_len,
1171 route_match_ip_address_prefix_len_compile, /* reuse */
1172 route_match_ip_address_prefix_len_free /* reuse */
1173};
1174
1175/* `match source-protocol PROTOCOL' */
1176
1177static route_map_result_t
1178route_match_source_protocol (void *rule, struct prefix *prefix,
1179 route_map_object_t type, void *object)
1180{
1181 u_int32_t *rib_type = (u_int32_t *)rule;
1182 struct nh_rmap_obj *nh_data;
1183
1184 if (type == RMAP_ZEBRA)
1185 {
1186 nh_data = (struct nh_rmap_obj *)object;
1187 if (!nh_data)
1188 return RMAP_DENYMATCH;
1189
1190 return ((nh_data->source_protocol == *rib_type)
1191 ? RMAP_MATCH : RMAP_NOMATCH);
1192 }
1193 return RMAP_NOMATCH;
1194}
1195
1196static void *
1197route_match_source_protocol_compile (const char *arg)
1198{
1199 u_int32_t *rib_type;
1200 int i;
1201
1202 i = proto_name2num(arg);
1203 rib_type = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
1204
1205 *rib_type = i;
1206
1207 return rib_type;
1208}
1209
1210static void
1211route_match_source_protocol_free (void *rule)
1212{
1213 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1214}
1215
1216static struct route_map_rule_cmd route_match_source_protocol_cmd =
1217{
1218 "source-protocol",
1219 route_match_source_protocol,
1220 route_match_source_protocol_compile,
1221 route_match_source_protocol_free
1222};
1223
5921ef9a
PJ
1224/* `set src A.B.C.D' */
1225
1226/* Set src. */
1227static route_map_result_t
1228route_set_src (void *rule, struct prefix *prefix,
1229 route_map_object_t type, void *object)
1230{
9f0ea7d4
DS
1231 struct nh_rmap_obj *nh_data;
1232
5921ef9a
PJ
1233 if (type == RMAP_ZEBRA)
1234 {
9f0ea7d4 1235 nh_data = (struct nh_rmap_obj *)object;
c52ef59f 1236 nh_data->nexthop->rmap_src = *(union g_addr *)rule;
5921ef9a
PJ
1237 }
1238 return RMAP_OKAY;
1239}
1240
1241/* set src compilation. */
1242static void *
1243route_set_src_compile (const char *arg)
1244{
5921ef9a
PJ
1245 union g_addr src, *psrc;
1246
0aabccc0 1247 if (
09303314 1248#ifdef HAVE_IPV6
0aabccc0 1249 (inet_pton(AF_INET6, arg, &src.ipv6) == 1) ||
09303314 1250#endif /* HAVE_IPV6 */
0aabccc0
DD
1251 (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1)))
1252 {
1253 psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr));
1254 *psrc = src;
1255 return psrc;
1256 }
1257 return NULL;
5921ef9a
PJ
1258}
1259
1260/* Free route map's compiled `set src' value. */
1261static void
1262route_set_src_free (void *rule)
1263{
1264 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
1265}
1266
1267/* Set src rule structure. */
1268static struct route_map_rule_cmd route_set_src_cmd =
1269{
1270 "src",
1271 route_set_src,
1272 route_set_src_compile,
1273 route_set_src_free,
1274};
1275
518f0eb1
DS
1276static int
1277zebra_route_map_update_timer (struct thread *thread)
1278{
1279 zebra_t_rmap_update = NULL;
1280
1281 if (IS_ZEBRA_DEBUG_EVENT)
1282 zlog_debug("Event driven route-map update triggered");
1283
41ec9222 1284 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1c848137 1285 zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing",
1286 VRF_DEFAULT);
b84c7253 1287
8902474b 1288 zebra_import_table_rm_update ();
1c848137 1289 rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
078430f6
DS
1290 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1291 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
9f0ea7d4
DS
1292
1293 return (0);
518f0eb1
DS
1294}
1295
9f0ea7d4 1296static void
518f0eb1
DS
1297zebra_route_map_set_delay_timer(u_int32_t value)
1298{
1299 zebra_rmap_update_timer = value;
1300 if (!value && zebra_t_rmap_update)
1301 {
1302 /* Event driven route map updates is being disabled */
1303 /* But there's a pending timer. Fire it off now */
1304 thread_cancel(zebra_t_rmap_update);
1305 zebra_route_map_update_timer(zebra_t_rmap_update);
1306 }
1307}
1308
1309void
1310zebra_route_map_write_delay_timer (struct vty *vty)
1311{
1312 if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER))
1313 vty_out (vty, "zebra route-map delay-timer %d%s", zebra_rmap_update_timer,
1314 VTY_NEWLINE);
1315 return;
1316}
1317
1318route_map_result_t
1319zebra_route_map_check (int family, int rib_type, struct prefix *p,
dc9ffce8 1320 struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag)
518f0eb1
DS
1321{
1322 struct route_map *rmap = NULL;
1323 route_map_result_t ret = RMAP_MATCH;
9f0ea7d4
DS
1324 struct nh_rmap_obj nh_obj;
1325
1326 nh_obj.nexthop = nexthop;
0032dd59 1327 nh_obj.vrf_id = vrf_id;
9f0ea7d4
DS
1328 nh_obj.source_protocol = rib_type;
1329 nh_obj.metric = 0;
ca84c8ef 1330 nh_obj.tag = tag;
518f0eb1
DS
1331
1332 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1333 rmap = route_map_lookup_by_name (proto_rm[family][rib_type]);
1334 if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
1335 rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
1336 if (rmap) {
9f0ea7d4
DS
1337 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1338 }
1339
1340 return (ret);
1341}
1342
8902474b
DS
1343char *
1344zebra_get_import_table_route_map (afi_t afi, uint32_t table)
1345{
1346 return zebra_import_table_routemap[afi][table];
1347}
1348
1349void
1350zebra_add_import_table_route_map (afi_t afi, const char *rmap_name, uint32_t table)
1351{
1352 zebra_import_table_routemap[afi][table] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap_name);
1353}
1354
1355void
1356zebra_del_import_table_route_map (afi_t afi, uint32_t table)
1357{
1358 XFREE (MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1359}
1360
1361route_map_result_t
1362zebra_import_table_route_map_check (int family, int rib_type, struct prefix *p,
dc9ffce8 1363 struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag, const char *rmap_name)
8902474b
DS
1364{
1365 struct route_map *rmap = NULL;
1366 route_map_result_t ret = RMAP_DENYMATCH;
1367 struct nh_rmap_obj nh_obj;
1368
1369 nh_obj.nexthop = nexthop;
1370 nh_obj.vrf_id = vrf_id;
1371 nh_obj.source_protocol = rib_type;
1372 nh_obj.metric = 0;
1373 nh_obj.tag = tag;
1374
1375 if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX)
1376 rmap = route_map_lookup_by_name (rmap_name);
1377 if (rmap) {
1378 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
1379 }
1380
1381 return (ret);
1382}
1383
9f0ea7d4
DS
1384route_map_result_t
1385zebra_nht_route_map_check (int family, int client_proto, struct prefix *p,
1386 struct rib * rib, struct nexthop *nexthop)
1387{
1388 struct route_map *rmap = NULL;
1389 route_map_result_t ret = RMAP_MATCH;
1390 struct nh_rmap_obj nh_obj;
1391
1392 nh_obj.nexthop = nexthop;
0032dd59 1393 nh_obj.vrf_id = rib->vrf_id;
9f0ea7d4
DS
1394 nh_obj.source_protocol = rib->type;
1395 nh_obj.metric = rib->metric;
ca84c8ef 1396 nh_obj.tag = rib->tag;
9f0ea7d4
DS
1397
1398 if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1399 rmap = route_map_lookup_by_name (nht_rm[family][client_proto]);
1400 if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX])
1401 rmap = route_map_lookup_by_name (nht_rm[family][ZEBRA_ROUTE_MAX]);
1402 if (rmap) {
1403 ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
518f0eb1
DS
1404 }
1405
1406 return (ret);
1407}
1408
1409static void
9f0ea7d4 1410zebra_route_map_mark_update (const char *rmap_name)
518f0eb1
DS
1411{
1412 /* rmap_update_timer of 0 means don't do route updates */
1413 if (zebra_rmap_update_timer && !zebra_t_rmap_update)
1414 zebra_t_rmap_update =
1415 thread_add_timer(zebrad.master, zebra_route_map_update_timer, NULL,
1416 zebra_rmap_update_timer);
1417}
1418
1419static void
1420zebra_route_map_add (const char *rmap_name)
1421{
1422 zebra_route_map_mark_update(rmap_name);
1423 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1424}
1425
1426static void
1427zebra_route_map_delete (const char *rmap_name)
1428{
1429 zebra_route_map_mark_update(rmap_name);
1430 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1431}
1432
1433static void
1434zebra_route_map_event (route_map_event_t event, const char *rmap_name)
1435{
1436 zebra_route_map_mark_update(rmap_name);
1437 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1438}
1439
1440/* ip protocol configuration write function */
6baf7bb8
DS
1441void
1442zebra_routemap_config_write_protocol (struct vty *vty)
518f0eb1
DS
1443{
1444 int i;
1445
1446 for (i=0;i<ZEBRA_ROUTE_MAX;i++)
1447 {
1448 if (proto_rm[AFI_IP][i])
1449 vty_out (vty, "ip protocol %s route-map %s%s", zebra_route_string(i),
1450 proto_rm[AFI_IP][i], VTY_NEWLINE);
9f0ea7d4 1451
0aabccc0
DD
1452 if (proto_rm[AFI_IP6][i])
1453 vty_out (vty, "ipv6 protocol %s route-map %s%s", zebra_route_string(i),
1454 proto_rm[AFI_IP6][i], VTY_NEWLINE);
1455
9f0ea7d4
DS
1456 if (nht_rm[AFI_IP][i])
1457 vty_out (vty, "ip nht %s route-map %s%s", zebra_route_string(i),
1458 nht_rm[AFI_IP][i], VTY_NEWLINE);
1459
1460 if (nht_rm[AFI_IP6][i])
1461 vty_out (vty, "ipv6 nht %s route-map %s%s", zebra_route_string(i),
1462 nht_rm[AFI_IP6][i], VTY_NEWLINE);
518f0eb1 1463 }
9f0ea7d4 1464
518f0eb1
DS
1465 if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1466 vty_out (vty, "ip protocol %s route-map %s%s", "any",
1467 proto_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1468
0aabccc0
DD
1469 if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1470 vty_out (vty, "ipv6 protocol %s route-map %s%s", "any",
1471 proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1472
9f0ea7d4
DS
1473 if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX])
1474 vty_out (vty, "ip nht %s route-map %s%s", "any",
1475 nht_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1476
1477 if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
1478 vty_out (vty, "ipv6 nht %s route-map %s%s", "any",
1479 nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
1480
518f0eb1
DS
1481 if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1482 vty_out (vty, "zebra route-map delay-timer %d%s", zebra_rmap_update_timer,
1483 VTY_NEWLINE);
518f0eb1 1484}
518f0eb1 1485
5921ef9a
PJ
1486void
1487zebra_route_map_init ()
1488{
518f0eb1
DS
1489 install_element (CONFIG_NODE, &ip_protocol_cmd);
1490 install_element (CONFIG_NODE, &no_ip_protocol_cmd);
1491 install_element (VIEW_NODE, &show_ip_protocol_cmd);
0aabccc0
DD
1492 install_element (CONFIG_NODE, &ipv6_protocol_cmd);
1493 install_element (CONFIG_NODE, &no_ipv6_protocol_cmd);
0aabccc0 1494 install_element (VIEW_NODE, &show_ipv6_protocol_cmd);
9f0ea7d4
DS
1495 install_element (CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1496 install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
9f0ea7d4 1497 install_element (VIEW_NODE, &show_ip_protocol_nht_cmd);
9f0ea7d4
DS
1498 install_element (CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1499 install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
9f0ea7d4 1500 install_element (VIEW_NODE, &show_ipv6_protocol_nht_cmd);
518f0eb1
DS
1501 install_element (CONFIG_NODE, &zebra_route_map_timer_cmd);
1502 install_element (CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1503
5921ef9a 1504 route_map_init ();
5921ef9a 1505
518f0eb1
DS
1506 route_map_add_hook (zebra_route_map_add);
1507 route_map_delete_hook (zebra_route_map_delete);
1508 route_map_event_hook (zebra_route_map_event);
1509
82f97584
DW
1510 route_map_match_interface_hook (generic_match_add);
1511 route_map_no_match_interface_hook (generic_match_delete);
1512
1513 route_map_match_ip_address_hook (generic_match_add);
1514 route_map_no_match_ip_address_hook (generic_match_delete);
1515
1516 route_map_match_ip_address_prefix_list_hook (generic_match_add);
1517 route_map_no_match_ip_address_prefix_list_hook (generic_match_delete);
1518
1519 route_map_match_ip_next_hop_hook (generic_match_add);
1520 route_map_no_match_ip_next_hop_hook (generic_match_delete);
1521
1522 route_map_match_ip_next_hop_prefix_list_hook (generic_match_add);
1523 route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete);
1524
1525 route_map_match_tag_hook (generic_match_add);
1526 route_map_no_match_tag_hook (generic_match_delete);
1527
ca84c8ef 1528 route_map_install_match (&route_match_tag_cmd);
5921ef9a
PJ
1529 route_map_install_match (&route_match_interface_cmd);
1530 route_map_install_match (&route_match_ip_next_hop_cmd);
1531 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
1532 route_map_install_match (&route_match_ip_address_cmd);
1533 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
9f0ea7d4
DS
1534 route_map_install_match (&route_match_ip_address_prefix_len_cmd);
1535 route_map_install_match (&route_match_ip_nexthop_prefix_len_cmd);
1536 route_map_install_match (&route_match_source_protocol_cmd);
5921ef9a
PJ
1537/* */
1538 route_map_install_set (&route_set_src_cmd);
1539/* */
9f0ea7d4
DS
1540 install_element (RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
1541 install_element (RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
9f0ea7d4
DS
1542 install_element (RMAP_NODE, &match_ip_address_prefix_len_cmd);
1543 install_element (RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
9f0ea7d4
DS
1544 install_element (RMAP_NODE, &match_source_protocol_cmd);
1545 install_element (RMAP_NODE, &no_match_source_protocol_cmd);
1546 /* */
5921ef9a
PJ
1547 install_element (RMAP_NODE, &set_src_cmd);
1548 install_element (RMAP_NODE, &no_set_src_cmd);
1549}