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