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