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