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