Initial revision
diff --git a/ospf6d/ospf6_routemap.c b/ospf6d/ospf6_routemap.c
new file mode 100644
index 0000000..14df794
--- /dev/null
+++ b/ospf6d/ospf6_routemap.c
@@ -0,0 +1,359 @@
+/*
+ * OSPFv3 Route-Map
+ * Copyright (C) 1999 Yasuhiro Ohara
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the 
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
+ * Boston, MA 02111-1307, USA.  
+ */
+
+#include <zebra.h>
+
+#include "log.h"
+#include "memory.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "command.h"
+#include "vty.h"
+#include "routemap.h"
+#include "table.h"
+#include "plist.h"
+
+#include "ospf6_route.h"
+#include "ospf6_prefix.h"
+#include "ospf6_lsa.h"
+#include "ospf6_asbr.h"
+
+route_map_result_t
+ospf6_routemap_rule_match_address_prefixlist (void *rule,
+                                              struct prefix *prefix,
+                                              route_map_object_t type,
+                                              void *object)
+{
+  struct prefix_list *plist;
+
+  if (type != RMAP_OSPF6)
+    return RMAP_NOMATCH;
+
+  plist = prefix_list_lookup (AFI_IP6, (char *) rule);
+
+  if (plist == NULL)
+    return RMAP_NOMATCH;
+
+  return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
+          RMAP_NOMATCH : RMAP_MATCH);
+}
+
+void *
+ospf6_routemap_rule_match_address_prefixlist_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd
+ospf6_routemap_rule_match_address_prefixlist_cmd =
+{
+  "ipv6 address prefix-list",
+  ospf6_routemap_rule_match_address_prefixlist,
+  ospf6_routemap_rule_match_address_prefixlist_compile,
+  ospf6_routemap_rule_match_address_prefixlist_free,
+};
+
+route_map_result_t
+ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
+                                     route_map_object_t type, void *object)
+{
+  char *metric_type = rule;
+  struct ospf6_external_info *info = object;
+
+  if (type != RMAP_OSPF6)
+    return RMAP_OKAY;
+
+  if (strcmp (metric_type, "type-2") == 0)
+    info->metric_type = 2;
+  else
+    info->metric_type = 1;
+
+  return RMAP_OKAY;
+}
+
+void *
+ospf6_routemap_rule_set_metric_type_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+ospf6_routemap_rule_set_metric_type_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd
+ospf6_routemap_rule_set_metric_type_cmd =
+{
+  "metric-type",
+  ospf6_routemap_rule_set_metric_type,
+  ospf6_routemap_rule_set_metric_type_compile,
+  ospf6_routemap_rule_set_metric_type_free,
+};
+
+route_map_result_t
+ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
+                                route_map_object_t type, void *object)
+{
+  char *metric = rule;
+  struct ospf6_external_info *info = object;
+
+  if (type != RMAP_OSPF6)
+    return RMAP_OKAY;
+
+  info->metric = atoi (metric);
+  return RMAP_OKAY;
+}
+
+void *
+ospf6_routemap_rule_set_metric_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+ospf6_routemap_rule_set_metric_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd
+ospf6_routemap_rule_set_metric_cmd =
+{
+  "metric",
+  ospf6_routemap_rule_set_metric,
+  ospf6_routemap_rule_set_metric_compile,
+  ospf6_routemap_rule_set_metric_free,
+};
+
+route_map_result_t
+ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
+                                    route_map_object_t type, void *object)
+{
+  char *forwarding = rule;
+  struct ospf6_external_info *info = object;
+
+  if (type != RMAP_OSPF6)
+    return RMAP_OKAY;
+
+  if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
+    {
+      memset (&info->forwarding, 0, sizeof (struct in6_addr));
+      return RMAP_ERROR;
+    }
+
+  return RMAP_OKAY;
+}
+
+void *
+ospf6_routemap_rule_set_forwarding_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+ospf6_routemap_rule_set_forwarding_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd
+ospf6_routemap_rule_set_forwarding_cmd =
+{
+  "forwarding-address",
+  ospf6_routemap_rule_set_forwarding,
+  ospf6_routemap_rule_set_forwarding_compile,
+  ospf6_routemap_rule_set_forwarding_free,
+};
+
+int
+route_map_command_status (struct vty *vty, int ret)
+{
+  if (! ret)
+    return CMD_SUCCESS;
+
+  switch (ret)
+    {
+    case RMAP_RULE_MISSING:
+      vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
+      break;
+    case RMAP_COMPILE_ERROR:
+      vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
+      break;
+    default:                          
+      vty_out (vty, "route-map add set failed.%s", VTY_NEWLINE);
+      break;
+    }
+  return CMD_WARNING;
+}
+
+/* add "match address" */
+DEFUN (ospf6_routemap_match_address_prefixlist,
+       ospf6_routemap_match_address_prefixlist_cmd,
+       "match ipv6 address prefix-list WORD",
+       "Match values\n"
+       IPV6_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IPv6 prefix-list name\n")
+{
+  int ret = route_map_add_match ((struct route_map_index *) vty->index,
+                                 "ipv6 address prefix-list", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+/* delete "match address" */
+DEFUN (ospf6_routemap_no_match_address_prefixlist,
+       ospf6_routemap_no_match_address_prefixlist_cmd,
+       "no match ipv6 address prefix-list WORD",
+       NO_STR
+       "Match values\n"
+       IPV6_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IPv6 prefix-list name\n")
+{
+  int ret = route_map_delete_match ((struct route_map_index *) vty->index,
+                                    "ipv6 address prefix-list", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+/* add "set metric-type" */
+DEFUN (ospf6_routemap_set_metric_type,
+       ospf6_routemap_set_metric_type_cmd,
+       "set metric-type (type-1|type-2)",
+       "Set value\n"
+       "Type of metric\n"
+       "OSPF6 external type 1 metric\n"
+       "OSPF6 external type 2 metric\n")
+{
+  int ret = route_map_add_set ((struct route_map_index *) vty->index,
+                               "metric-type", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+/* delete "set metric-type" */
+DEFUN (ospf6_routemap_no_set_metric_type,
+       ospf6_routemap_no_set_metric_type_cmd,
+       "no set metric-type (type-1|type-2)",
+       NO_STR
+       "Set value\n"
+       "Type of metric\n"
+       "OSPF6 external type 1 metric\n"
+       "OSPF6 external type 2 metric\n")
+{
+  int ret = route_map_delete_set ((struct route_map_index *) vty->index,
+                                  "metric-type", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+/* add "set metric" */
+DEFUN (set_metric,
+       set_metric_cmd,
+       "set metric <0-4294967295>",
+       "Set value\n"
+       "Metric value\n"
+       "Metric value\n")
+{
+  int ret = route_map_add_set ((struct route_map_index *) vty->index,
+                               "metric", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+/* delete "set metric" */
+DEFUN (no_set_metric,
+       no_set_metric_cmd,
+       "no set metric <0-4294967295>",
+       NO_STR
+       "Set value\n"
+       "Metric\n"
+       "METRIC value\n")
+{
+  int ret = route_map_delete_set ((struct route_map_index *) vty->index,
+                                  "metric", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+/* add "set forwarding-address" */
+DEFUN (ospf6_routemap_set_forwarding,
+       ospf6_routemap_set_forwarding_cmd,
+       "set forwarding-address X:X::X:X",
+       "Set value\n"
+       "Forwarding Address\n"
+       "IPv6 Address\n")
+{
+  int ret = route_map_add_set ((struct route_map_index *) vty->index,
+                               "forwarding-address", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+/* delete "set forwarding-address" */
+DEFUN (ospf6_routemap_no_set_forwarding,
+       ospf6_routemap_no_set_forwarding_cmd,
+       "no set forwarding-address X:X::X:X",
+       NO_STR
+       "Set value\n"
+       "Forwarding Address\n"
+       "IPv6 Address\n")
+{
+  int ret = route_map_delete_set ((struct route_map_index *) vty->index,
+                                  "forwarding-address", argv[0]);
+  return route_map_command_status (vty, ret);
+}
+
+void
+ospf6_routemap_init ()
+{
+  route_map_init ();
+  route_map_init_vty ();
+  route_map_add_hook (ospf6_asbr_routemap_update);
+  route_map_delete_hook (ospf6_asbr_routemap_update);
+
+  route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
+  route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
+  route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
+  route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
+
+  /* Match address prefix-list */
+  install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
+  install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
+
+  /* ASE Metric Type (e.g. Type-1/Type-2) */
+  install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
+  install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
+
+  /* ASE Metric */
+  install_element (RMAP_NODE, &set_metric_cmd);
+  install_element (RMAP_NODE, &no_set_metric_cmd);
+
+  /* ASE Metric */
+  install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
+  install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
+}
+