2 * Route map function of ospfd.
3 * Copyright (C) 2000 IP Infusion Inc.
5 * Written by Toshiaki Takada.
7 * This file is part of GNU Zebra.
9 * GNU Zebra is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
14 * GNU Zebra is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with GNU Zebra; see the file COPYING. If not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
35 #include "ospfd/ospfd.h"
36 #include "ospfd/ospf_asbr.h"
37 #include "ospfd/ospf_interface.h"
38 #include "ospfd/ospf_lsa.h"
39 #include "ospfd/ospf_route.h"
40 #include "ospfd/ospf_zebra.h"
42 /* Hook function for updating route_map assignment. */
44 ospf_route_map_update (const char *name)
49 /* If OSPF instatnce does not exist, return right now. */
50 ospf = ospf_lookup ();
54 /* Update route-map */
55 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
57 if (ROUTEMAP_NAME (ospf, type)
58 && strcmp (ROUTEMAP_NAME (ospf, type), name) == 0)
60 /* Keep old route-map. */
61 struct route_map *old = ROUTEMAP (ospf, type);
63 /* Update route-map. */
64 ROUTEMAP (ospf, type) =
65 route_map_lookup_by_name (ROUTEMAP_NAME (ospf, type));
67 /* No update for this distribute type. */
68 if (old == NULL && ROUTEMAP (ospf, type) == NULL)
71 ospf_distribute_list_update (ospf, type);
77 ospf_route_map_event (route_map_event_t event, const char *name)
82 /* If OSPF instatnce does not exist, return right now. */
83 ospf = ospf_lookup ();
87 /* Update route-map. */
88 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
90 if (ROUTEMAP_NAME (ospf, type) && ROUTEMAP (ospf, type)
91 && !strcmp (ROUTEMAP_NAME (ospf, type), name))
93 ospf_distribute_list_update (ospf, type);
98 /* Delete rip route map rule. */
100 ospf_route_match_delete (struct vty *vty, struct route_map_index *index,
101 const char *command, const char *arg)
105 ret = route_map_delete_match (index, command, arg);
110 case RMAP_RULE_MISSING:
111 vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
113 case RMAP_COMPILE_ERROR:
114 vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
123 ospf_route_match_add (struct vty *vty, struct route_map_index *index,
124 const char *command, const char *arg)
128 ret = route_map_add_match (index, command, arg);
133 case RMAP_RULE_MISSING:
134 vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
136 case RMAP_COMPILE_ERROR:
137 vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
146 ospf_route_set_add (struct vty *vty, struct route_map_index *index,
147 const char *command, const char *arg)
151 ret = route_map_add_set (index, command, arg);
156 case RMAP_RULE_MISSING:
157 vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
159 case RMAP_COMPILE_ERROR:
160 vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
168 /* Delete rip route map rule. */
170 ospf_route_set_delete (struct vty *vty, struct route_map_index *index,
171 const char *command, const char *arg)
175 ret = route_map_delete_set (index, command, arg);
180 case RMAP_RULE_MISSING:
181 vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
183 case RMAP_COMPILE_ERROR:
184 vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
192 /* `match ip netxthop ' */
193 /* Match function return 1 if match is success else return zero. */
194 static route_map_result_t
195 route_match_ip_nexthop (void *rule, struct prefix *prefix,
196 route_map_object_t type, void *object)
198 struct access_list *alist;
199 struct external_info *ei = object;
200 struct prefix_ipv4 p;
202 if (type == RMAP_OSPF)
205 p.prefix = ei->nexthop;
206 p.prefixlen = IPV4_MAX_BITLEN;
208 alist = access_list_lookup (AFI_IP, (char *) rule);
212 return (access_list_apply (alist, &p) == FILTER_DENY ?
213 RMAP_NOMATCH : RMAP_MATCH);
218 /* Route map `ip next-hop' match statement. `arg' should be
221 route_match_ip_nexthop_compile (const char *arg)
223 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
226 /* Free route map's compiled `ip address' value. */
228 route_match_ip_nexthop_free (void *rule)
230 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
233 /* Route map commands for metric matching. */
234 struct route_map_rule_cmd route_match_ip_nexthop_cmd =
237 route_match_ip_nexthop,
238 route_match_ip_nexthop_compile,
239 route_match_ip_nexthop_free
242 /* `match ip next-hop prefix-list PREFIX_LIST' */
244 static route_map_result_t
245 route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
246 route_map_object_t type, void *object)
248 struct prefix_list *plist;
249 struct external_info *ei = object;
250 struct prefix_ipv4 p;
252 if (type == RMAP_OSPF)
255 p.prefix = ei->nexthop;
256 p.prefixlen = IPV4_MAX_BITLEN;
258 plist = prefix_list_lookup (AFI_IP, (char *) rule);
262 return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
263 RMAP_NOMATCH : RMAP_MATCH);
269 route_match_ip_next_hop_prefix_list_compile (const char *arg)
271 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
275 route_match_ip_next_hop_prefix_list_free (void *rule)
277 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
280 struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
282 "ip next-hop prefix-list",
283 route_match_ip_next_hop_prefix_list,
284 route_match_ip_next_hop_prefix_list_compile,
285 route_match_ip_next_hop_prefix_list_free
288 /* `match ip address IP_ACCESS_LIST' */
289 /* Match function should return 1 if match is success else return
291 static route_map_result_t
292 route_match_ip_address (void *rule, struct prefix *prefix,
293 route_map_object_t type, void *object)
295 struct access_list *alist;
296 /* struct prefix_ipv4 match; */
298 if (type == RMAP_OSPF)
300 alist = access_list_lookup (AFI_IP, (char *) rule);
304 return (access_list_apply (alist, prefix) == FILTER_DENY ?
305 RMAP_NOMATCH : RMAP_MATCH);
310 /* Route map `ip address' match statement. `arg' should be
313 route_match_ip_address_compile (const char *arg)
315 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
318 /* Free route map's compiled `ip address' value. */
320 route_match_ip_address_free (void *rule)
322 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
325 /* Route map commands for ip address matching. */
326 struct route_map_rule_cmd route_match_ip_address_cmd =
329 route_match_ip_address,
330 route_match_ip_address_compile,
331 route_match_ip_address_free
334 /* `match ip address prefix-list PREFIX_LIST' */
335 static route_map_result_t
336 route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
337 route_map_object_t type, void *object)
339 struct prefix_list *plist;
341 if (type == RMAP_OSPF)
343 plist = prefix_list_lookup (AFI_IP, (char *) rule);
347 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
348 RMAP_NOMATCH : RMAP_MATCH);
354 route_match_ip_address_prefix_list_compile (const char *arg)
356 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
360 route_match_ip_address_prefix_list_free (void *rule)
362 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
365 struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
367 "ip address prefix-list",
368 route_match_ip_address_prefix_list,
369 route_match_ip_address_prefix_list_compile,
370 route_match_ip_address_prefix_list_free
373 /* `match interface IFNAME' */
374 /* Match function should return 1 if match is success else return
376 static route_map_result_t
377 route_match_interface (void *rule, struct prefix *prefix,
378 route_map_object_t type, void *object)
380 struct interface *ifp;
381 struct external_info *ei;
383 if (type == RMAP_OSPF)
386 ifp = if_lookup_by_name ((char *)rule);
388 if (ifp == NULL || ifp->ifindex != ei->ifindex)
396 /* Route map `interface' match statement. `arg' should be
399 route_match_interface_compile (const char *arg)
401 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
404 /* Free route map's compiled `interface' value. */
406 route_match_interface_free (void *rule)
408 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
411 /* Route map commands for ip address matching. */
412 struct route_map_rule_cmd route_match_interface_cmd =
415 route_match_interface,
416 route_match_interface_compile,
417 route_match_interface_free
420 /* Match function return 1 if match is success else return zero. */
421 static route_map_result_t
422 route_match_tag (void *rule, struct prefix *prefix,
423 route_map_object_t type, void *object)
426 struct external_info *ei;
428 if (type == RMAP_OSPF)
433 return ((ei->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH);
439 /* Route map commands for tag matching. */
440 static struct route_map_rule_cmd route_match_tag_cmd =
444 route_map_rule_tag_compile,
445 route_map_rule_tag_free,
449 /* `set metric METRIC' */
450 /* Set metric to attribute. */
451 static route_map_result_t
452 route_set_metric (void *rule, struct prefix *prefix,
453 route_map_object_t type, void *object)
456 struct external_info *ei;
458 if (type == RMAP_OSPF)
460 /* Fetch routemap's rule information. */
464 /* Set metric out value. */
465 ei->route_map_set.metric = *metric;
470 /* set metric compilation. */
472 route_set_metric_compile (const char *arg)
477 /* OSPF doesn't support the +/- in
478 set metric <+/-metric> check
479 Ignore the +/- component */
480 if (! all_digit (arg))
482 if ((strncmp (arg, "+", 1) == 0 || strncmp (arg, "-", 1) == 0) &&
485 zlog_warn ("OSPF does not support 'set metric +/-'");
492 metric = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
497 *metric = (u_int32_t)ret;
501 XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
505 /* Free route map's compiled `set metric' value. */
507 route_set_metric_free (void *rule)
509 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
512 /* Set metric rule structure. */
513 struct route_map_rule_cmd route_set_metric_cmd =
517 route_set_metric_compile,
518 route_set_metric_free,
521 /* `set metric-type TYPE' */
522 /* Set metric-type to attribute. */
523 static route_map_result_t
524 route_set_metric_type (void *rule, struct prefix *prefix,
525 route_map_object_t type, void *object)
527 u_int32_t *metric_type;
528 struct external_info *ei;
530 if (type == RMAP_OSPF)
532 /* Fetch routemap's rule information. */
536 /* Set metric out value. */
537 ei->route_map_set.metric_type = *metric_type;
542 /* set metric-type compilation. */
544 route_set_metric_type_compile (const char *arg)
546 u_int32_t *metric_type;
548 metric_type = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
549 if (strcmp (arg, "type-1") == 0)
550 *metric_type = EXTERNAL_METRIC_TYPE_1;
551 else if (strcmp (arg, "type-2") == 0)
552 *metric_type = EXTERNAL_METRIC_TYPE_2;
554 if (*metric_type == EXTERNAL_METRIC_TYPE_1 ||
555 *metric_type == EXTERNAL_METRIC_TYPE_2)
558 XFREE (MTYPE_ROUTE_MAP_COMPILED, metric_type);
562 /* Free route map's compiled `set metric-type' value. */
564 route_set_metric_type_free (void *rule)
566 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
569 /* Set metric rule structure. */
570 struct route_map_rule_cmd route_set_metric_type_cmd =
573 route_set_metric_type,
574 route_set_metric_type_compile,
575 route_set_metric_type_free,
578 static route_map_result_t
579 route_set_tag (void *rule, struct prefix *prefix,
580 route_map_object_t type, void *object)
583 struct external_info *ei;
585 if (type == RMAP_OSPF)
597 /* Route map commands for tag set. */
598 static struct route_map_rule_cmd route_set_tag_cmd =
602 route_map_rule_tag_compile,
603 route_map_rule_tag_free,
606 DEFUN (match_ip_nexthop,
607 match_ip_nexthop_cmd,
608 "match ip next-hop (<1-199>|<1300-2699>|WORD)",
611 "Match next-hop address of route\n"
612 "IP access-list number\n"
613 "IP access-list number (expanded range)\n"
614 "IP access-list name\n")
616 return ospf_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
619 DEFUN (no_match_ip_nexthop,
620 no_match_ip_nexthop_cmd,
621 "no match ip next-hop",
625 "Match next-hop address of route\n")
628 return ospf_route_match_delete (vty, vty->index, "ip next-hop", NULL);
630 return ospf_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
633 ALIAS (no_match_ip_nexthop,
634 no_match_ip_nexthop_val_cmd,
635 "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
639 "Match next-hop address of route\n"
640 "IP access-list number\n"
641 "IP access-list number (expanded range)\n"
642 "IP access-list name\n")
644 DEFUN (match_ip_next_hop_prefix_list,
645 match_ip_next_hop_prefix_list_cmd,
646 "match ip next-hop prefix-list WORD",
649 "Match next-hop address of route\n"
650 "Match entries of prefix-lists\n"
651 "IP prefix-list name\n")
653 return ospf_route_match_add (vty, vty->index, "ip next-hop prefix-list",
657 DEFUN (no_match_ip_next_hop_prefix_list,
658 no_match_ip_next_hop_prefix_list_cmd,
659 "no match ip next-hop prefix-list",
663 "Match next-hop address of route\n"
664 "Match entries of prefix-lists\n")
667 return ospf_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
669 return ospf_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
673 ALIAS (no_match_ip_next_hop_prefix_list,
674 no_match_ip_next_hop_prefix_list_val_cmd,
675 "no match ip next-hop prefix-list WORD",
679 "Match next-hop address of route\n"
680 "Match entries of prefix-lists\n"
681 "IP prefix-list name\n")
683 DEFUN (match_ip_address,
684 match_ip_address_cmd,
685 "match ip address (<1-199>|<1300-2699>|WORD)",
688 "Match address of route\n"
689 "IP access-list number\n"
690 "IP access-list number (expanded range)\n"
691 "IP access-list name\n")
693 return ospf_route_match_add (vty, vty->index, "ip address", argv[0]);
696 DEFUN (no_match_ip_address,
697 no_match_ip_address_cmd,
698 "no match ip address",
702 "Match address of route\n")
705 return ospf_route_match_delete (vty, vty->index, "ip address", NULL);
707 return ospf_route_match_delete (vty, vty->index, "ip address", argv[0]);
710 ALIAS (no_match_ip_address,
711 no_match_ip_address_val_cmd,
712 "no match ip address (<1-199>|<1300-2699>|WORD)",
716 "Match address of route\n"
717 "IP access-list number\n"
718 "IP access-list number (expanded range)\n"
719 "IP access-list name\n")
721 DEFUN (match_ip_address_prefix_list,
722 match_ip_address_prefix_list_cmd,
723 "match ip address prefix-list WORD",
726 "Match address of route\n"
727 "Match entries of prefix-lists\n"
728 "IP prefix-list name\n")
730 return ospf_route_match_add (vty, vty->index, "ip address prefix-list",
734 DEFUN (no_match_ip_address_prefix_list,
735 no_match_ip_address_prefix_list_cmd,
736 "no match ip address prefix-list",
740 "Match address of route\n"
741 "Match entries of prefix-lists\n")
744 return ospf_route_match_delete (vty, vty->index, "ip address prefix-list",
746 return ospf_route_match_delete (vty, vty->index, "ip address prefix-list",
750 ALIAS (no_match_ip_address_prefix_list,
751 no_match_ip_address_prefix_list_val_cmd,
752 "no match ip address prefix-list WORD",
756 "Match address of route\n"
757 "Match entries of prefix-lists\n"
758 "IP prefix-list name\n")
760 DEFUN (match_interface,
762 "match interface WORD",
764 "Match first hop interface of route\n"
767 return ospf_route_match_add (vty, vty->index, "interface", argv[0]);
770 DEFUN (no_match_interface,
771 no_match_interface_cmd,
772 "no match interface",
775 "Match first hop interface of route\n")
778 return ospf_route_match_delete (vty, vty->index, "interface", NULL);
780 return ospf_route_match_delete (vty, vty->index, "interface", argv[0]);
783 ALIAS (no_match_interface,
784 no_match_interface_val_cmd,
785 "no match interface WORD",
788 "Match first hop interface of route\n"
793 "match tag <1-4294967295>",
795 "Match tag of route\n"
798 return ospf_route_match_add (vty, vty->index, "tag", argv[0]);
806 "Match tag of route\n")
809 return ospf_route_match_delete (vty, vty->index, "tag", NULL);
811 return ospf_route_match_delete (vty, vty->index, "tag", argv[0]);
815 no_match_tag_val_cmd,
816 "no match tag <1-4294967295>",
819 "Match tag of route\n"
824 "set metric <0-4294967295>",
826 "Metric value for destination routing protocol\n"
829 return ospf_route_set_add (vty, vty->index, "metric", argv[0]);
832 DEFUN (no_set_metric,
837 "Metric value for destination routing protocol\n")
840 return ospf_route_set_delete (vty, vty->index, "metric", NULL);
842 return ospf_route_set_delete (vty, vty->index, "metric", argv[0]);
845 ALIAS (no_set_metric,
846 no_set_metric_val_cmd,
847 "no set metric <0-4294967295>",
850 "Metric value for destination routing protocol\n"
853 DEFUN (set_metric_type,
855 "set metric-type (type-1|type-2)",
857 "Type of metric for destination routing protocol\n"
858 "OSPF[6] external type 1 metric\n"
859 "OSPF[6] external type 2 metric\n")
861 if (strcmp (argv[0], "1") == 0)
862 return ospf_route_set_add (vty, vty->index, "metric-type", "type-1");
863 if (strcmp (argv[0], "2") == 0)
864 return ospf_route_set_add (vty, vty->index, "metric-type", "type-2");
866 return ospf_route_set_add (vty, vty->index, "metric-type", argv[0]);
869 DEFUN (no_set_metric_type,
870 no_set_metric_type_cmd,
871 "no set metric-type",
874 "Type of metric for destination routing protocol\n")
877 return ospf_route_set_delete (vty, vty->index, "metric-type", NULL);
879 return ospf_route_set_delete (vty, vty->index, "metric-type", argv[0]);
882 ALIAS (no_set_metric_type,
883 no_set_metric_type_val_cmd,
884 "no set metric-type (type-1|type-2)",
887 "Type of metric for destination routing protocol\n"
888 "OSPF[6] external type 1 metric\n"
889 "OSPF[6] external type 2 metric\n")
893 "set tag <1-4294967295>",
895 "Tag value for routing protocol\n"
898 return ospf_route_set_add (vty, vty->index, "tag", argv[0]);
906 "Tag value for routing protocol\n")
909 ospf_route_set_delete(vty, vty->index, "tag", NULL);
911 return ospf_route_set_delete (vty, vty->index, "tag", argv[0]);
916 "no set tag <1-4294967295>",
919 "Tag value for routing protocol\n"
924 ospf_route_map_init (void)
927 route_map_init_vty ();
929 route_map_add_hook (ospf_route_map_update);
930 route_map_delete_hook (ospf_route_map_update);
931 route_map_event_hook (ospf_route_map_event);
933 route_map_install_match (&route_match_ip_nexthop_cmd);
934 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
935 route_map_install_match (&route_match_ip_address_cmd);
936 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
937 route_map_install_match (&route_match_interface_cmd);
938 route_map_install_match (&route_match_tag_cmd);
940 route_map_install_set (&route_set_metric_cmd);
941 route_map_install_set (&route_set_metric_type_cmd);
942 route_map_install_set (&route_set_tag_cmd);
944 install_element (RMAP_NODE, &match_ip_nexthop_cmd);
945 install_element (RMAP_NODE, &no_match_ip_nexthop_cmd);
946 install_element (RMAP_NODE, &no_match_ip_nexthop_val_cmd);
947 install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
948 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
949 install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
950 install_element (RMAP_NODE, &match_ip_address_cmd);
951 install_element (RMAP_NODE, &no_match_ip_address_cmd);
952 install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
953 install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
954 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
955 install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
956 install_element (RMAP_NODE, &match_interface_cmd);
957 install_element (RMAP_NODE, &no_match_interface_cmd);
958 install_element (RMAP_NODE, &no_match_interface_val_cmd);
959 install_element (RMAP_NODE, &match_tag_cmd);
960 install_element (RMAP_NODE, &no_match_tag_cmd);
961 install_element (RMAP_NODE, &no_match_tag_val_cmd);
963 install_element (RMAP_NODE, &set_metric_cmd);
964 install_element (RMAP_NODE, &no_set_metric_cmd);
965 install_element (RMAP_NODE, &no_set_metric_val_cmd);
966 install_element (RMAP_NODE, &set_metric_type_cmd);
967 install_element (RMAP_NODE, &no_set_metric_type_cmd);
968 install_element (RMAP_NODE, &no_set_metric_type_val_cmd);
969 install_element (RMAP_NODE, &set_tag_cmd);
970 install_element (RMAP_NODE, &no_set_tag_cmd);
971 install_element (RMAP_NODE, &no_set_tag_val_cmd);