Ospf6d merge from Zebra repository with added privs stuff and merged
zclient changes.
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index f9cc329..b1c1644 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -1,6 +1,5 @@
 /*
- * OSPFv3 Top Level Data Structure
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
  *
  * This file is part of GNU Zebra.
  *
@@ -31,299 +30,419 @@
 #include "thread.h"
 #include "command.h"
 
-#include "ospf6_hook.h"
+#include "ospf6d.h"
 #include "ospf6_proto.h"
-#include "ospf6_prefix.h"
+#include "ospf6_message.h"
 #include "ospf6_lsa.h"
 #include "ospf6_lsdb.h"
-
-#include "ospf6_message.h"
-#include "ospf6_neighbor.h"
-#include "ospf6_interface.h"
-#include "ospf6_area.h"
-#include "ospf6_top.h"
-
 #include "ospf6_route.h"
 #include "ospf6_zebra.h"
 
-#include "ospf6_nsm.h"
-#include "ospf6_asbr.h"
-#include "ospf6_abr.h"
+#include "ospf6_top.h"
+#include "ospf6_area.h"
+#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
 
-#define HEADER_DEPENDENCY
-#include "ospf6d.h"
-#undef HEADER_DEPENDENCY
+#include "ospf6_asbr.h"
 
 /* global ospf6d variable */
 struct ospf6 *ospf6;
 
-static void
-ospf6_top_foreach_area (struct ospf6 *o6, void *arg, int val,
-                        void (*func) (void *, int, void *))
+void
+ospf6_top_lsdb_hook_add (struct ospf6_lsa *lsa)
 {
-  listnode node;
-  struct ospf6_area *o6a;
-
-  for (node = listhead (o6->area_list); node; nextnode (node))
+  switch (ntohs (lsa->header->type))
     {
-      o6a = (struct ospf6_area *) getdata (node);
-      (*func) (arg, val, o6a);
+      case OSPF6_LSTYPE_AS_EXTERNAL:
+        ospf6_asbr_lsa_add (lsa);
+        break;
+
+      default:
+        if (IS_OSPF6_DEBUG_LSA (RECV))
+          zlog_info ("Unknown LSA in AS-scoped lsdb");
+        break;
     }
 }
 
-static void
-ospf6_top_foreach_interface (struct ospf6 *o6, void *arg, int val,
-                             void (*func) (void *, int, void *))
+void
+ospf6_top_lsdb_hook_remove (struct ospf6_lsa *lsa)
 {
-  listnode node;
-  struct ospf6_area *o6a;
-
-  for (node = listhead (o6->area_list); node; nextnode (node))
+  switch (ntohs (lsa->header->type))
     {
-      o6a = (struct ospf6_area *) getdata (node);
-      (*o6a->foreach_if) (o6a, arg, val, func);
+      case OSPF6_LSTYPE_AS_EXTERNAL:
+        ospf6_asbr_lsa_remove (lsa);
+        break;
+
+      default:
+        if (IS_OSPF6_DEBUG_LSA (RECV))
+          zlog_info ("Unknown LSA in AS-scoped lsdb");
+        break;
     }
 }
 
-static void
-ospf6_top_foreach_neighbor (struct ospf6 *o6, void *arg, int val,
-                            void (*func) (void *, int, void *))
+struct ospf6 *
+ospf6_create ()
 {
-  listnode node;
-  struct ospf6_area *o6a;
+  struct ospf6 *o;
 
-  for (node = listhead (o6->area_list); node; nextnode (node))
+  o = XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6));
+  memset (o, 0, sizeof (struct ospf6));
+
+  /* initialize */
+  gettimeofday (&o->starttime, (struct timezone *) NULL);
+  o->area_list = list_new ();
+  o->area_list->cmp = ospf6_area_cmp;
+  o->lsdb = ospf6_lsdb_create ();
+  o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
+  o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
+
+  o->route_table = ospf6_route_table_create ();
+  o->route_table->hook_add = ospf6_zebra_route_update_add;
+  o->route_table->hook_remove = ospf6_zebra_route_update_remove;
+
+  o->asbr_table = ospf6_route_table_create ();
+  o->asbr_table->hook_add = ospf6_asbr_lsentry_add;
+  o->asbr_table->hook_remove = ospf6_asbr_lsentry_remove;
+
+  o->external_table = ospf6_route_table_create ();
+  o->external_id_table = route_table_init ();
+
+  return o;
+}
+
+void
+ospf6_delete (struct ospf6 *o)
+{
+  listnode i;
+  struct ospf6_area *oa;
+
+  for (i = listhead (o->area_list); i; nextnode (i))
     {
-      o6a = (struct ospf6_area *) getdata (node);
-      (*o6a->foreach_nei) (o6a, arg, val, func);
+      oa = (struct ospf6_area *) getdata (i);
+      ospf6_area_delete (oa);
+    }
+
+  ospf6_lsdb_delete (o->lsdb);
+
+  ospf6_route_table_delete (o->route_table);
+  ospf6_route_table_delete (o->asbr_table);
+
+  ospf6_route_table_delete (o->external_table);
+  route_table_finish (o->external_id_table);
+
+  XFREE (MTYPE_OSPF6_TOP, o);
+}
+
+void
+ospf6_enable (struct ospf6 *o)
+{
+  listnode i;
+  struct ospf6_area *oa;
+
+  if (CHECK_FLAG (o->flag, OSPF6_DISABLED))
+    {
+      UNSET_FLAG (o->flag, OSPF6_DISABLED);
+      for (i = listhead (o->area_list); i; nextnode (i))
+        {
+          oa = (struct ospf6_area *) getdata (i);
+          ospf6_area_enable (oa);
+        }
     }
 }
 
-static int
-ospf6_top_maxage_remover (struct thread *t)
+void
+ospf6_disable (struct ospf6 *o)
 {
-  int count;
-  struct ospf6 *o6 = (struct ospf6 *) THREAD_ARG (t);
+  listnode i;
+  struct ospf6_area *oa;
 
-  o6->maxage_remover = (struct thread *) NULL;
+  if (! CHECK_FLAG (o->flag, OSPF6_DISABLED))
+    {
+      SET_FLAG (o->flag, OSPF6_DISABLED);
+      for (i = listhead (o->area_list); i; nextnode (i))
+        {
+          oa = (struct ospf6_area *) getdata (i);
+          ospf6_area_disable (oa);
+        }
 
-  count = 0;
-  o6->foreach_nei (o6, &count, NBS_EXCHANGE, ospf6_count_state);
-  o6->foreach_nei (o6, &count, NBS_LOADING, ospf6_count_state);
-  if (count != 0)
-    return 0;
+      ospf6_lsdb_remove_all (o->lsdb);
+      ospf6_route_remove_all (o->route_table);
+      ospf6_route_remove_all (o->asbr_table);
+    }
+}
 
-  ospf6_lsdb_remove_maxage (o6->lsdb);
+int
+ospf6_maxage_remover (struct thread *thread)
+{
+  struct ospf6 *o = (struct ospf6 *) THREAD_ARG (thread);
+  struct ospf6_area *oa;
+  struct ospf6_interface *oi;
+  struct ospf6_neighbor *on;
+  listnode i, j, k;
+
+  o->maxage_remover = (struct thread *) NULL;
+  if (IS_OSPF6_DEBUG_LSA (TIMER))
+    zlog_info ("Maxage Remover");
+
+  for (i = listhead (o->area_list); i; nextnode (i))
+    {
+      oa = (struct ospf6_area *) getdata (i);
+      for (j = listhead (oa->if_list); j; nextnode (j))
+        {
+          oi = (struct ospf6_interface *) getdata (j);
+          for (k = listhead (oi->neighbor_list); k; nextnode (k))
+            {
+              on = (struct ospf6_neighbor *) getdata (k);
+              if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
+                  on->state != OSPF6_NEIGHBOR_LOADING)
+                continue;
+
+              if (IS_OSPF6_DEBUG_LSA (TIMER))
+                zlog_info ("Maxage Remover End: %s exchange or loading",
+                           on->name);
+              return 0;
+            }
+        }
+    }
+
+  for (i = listhead (o->area_list); i; nextnode (i))
+    {
+      oa = (struct ospf6_area *) getdata (i);
+      for (j = listhead (oa->if_list); j; nextnode (j))
+        {
+          oi = (struct ospf6_interface *) getdata (j);
+          OSPF6_LSDB_MAXAGE_REMOVER (oi->lsdb);
+        }
+      OSPF6_LSDB_MAXAGE_REMOVER (oa->lsdb);
+    }
+  OSPF6_LSDB_MAXAGE_REMOVER (o->lsdb);
+
+  if (IS_OSPF6_DEBUG_LSA (TIMER))
+    zlog_info ("Maxage Remover End");
+
   return 0;
 }
 
 void
-ospf6_top_schedule_maxage_remover (void *arg, int val, struct ospf6 *o6)
+ospf6_maxage_remove (struct ospf6 *o)
 {
-  if (o6->maxage_remover != NULL)
-    return;
+  if (o && ! o->maxage_remover)
+    o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0);
+}
 
-  o6->maxage_remover =
-    thread_add_event (master, ospf6_top_maxage_remover, o6, 0);
+/* start ospf6 */
+DEFUN (router_ospf6,
+       router_ospf6_cmd,
+       "router ospf6",
+       ROUTER_STR
+       OSPF6_STR)
+{
+  if (ospf6 == NULL)
+    ospf6 = ospf6_create ();
+  if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
+    ospf6_enable (ospf6);
+
+  /* set current ospf point. */
+  vty->node = OSPF6_NODE;
+  vty->index = ospf6;
+
+  return CMD_SUCCESS;
+}
+
+/* stop ospf6 */
+DEFUN (no_router_ospf6,
+       no_router_ospf6_cmd,
+       "no router ospf6",
+       NO_STR
+       OSPF6_ROUTER_STR)
+{
+  if (ospf6 == NULL || CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
+    vty_out (vty, "OSPFv3 is not running%s", VTY_NEWLINE);
+  else
+    ospf6_disable (ospf6);
+
+  /* return to config node . */
+  vty->node = CONFIG_NODE;
+  vty->index = NULL;
+
+  return CMD_SUCCESS;
+}
+
+/* change Router_ID commands. */
+DEFUN (ospf6_router_id,
+       ospf6_router_id_cmd,
+       "router-id A.B.C.D",
+       "Configure OSPF Router-ID\n"
+       V4NOTATION_STR)
+{
+  int ret;
+  u_int32_t router_id;
+  struct ospf6 *o;
+
+  o = (struct ospf6 *) vty->index;
+
+  ret = inet_pton (AF_INET, argv[0], &router_id);
+  if (ret == 0)
+    {
+      vty_out (vty, "malformed OSPF Router-ID: %s%s", argv[0], VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  o->router_id = router_id;
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf6_interface_area,
+       ospf6_interface_area_cmd,
+       "interface IFNAME area A.B.C.D",
+       "Enable routing on an IPv6 interface\n"
+       IFNAME_STR
+       "Specify the OSPF6 area ID\n"
+       "OSPF6 area ID in IPv4 address notation\n"
+      )
+{
+  struct ospf6 *o;
+  struct ospf6_area *oa;
+  struct ospf6_interface *oi;
+  struct interface *ifp;
+  u_int32_t area_id;
+
+  o = (struct ospf6 *) vty->index;
+
+  /* find/create ospf6 interface */
+  ifp = if_get_by_name (argv[0]);
+  oi = (struct ospf6_interface *) ifp->info;
+  if (oi == NULL)
+    oi = ospf6_interface_create (ifp);
+  if (oi->area)
+    {
+      vty_out (vty, "%s already attached to Area %s%s",
+               oi->interface->name, oi->area->name, VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  /* parse Area-ID */
+  if (inet_pton (AF_INET, argv[1], &area_id) != 1)
+    {
+      vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  /* find/create ospf6 area */
+  oa = ospf6_area_lookup (area_id, o);
+  if (oa == NULL)
+    oa = ospf6_area_create (area_id, o);
+
+  /* attach interface to area */
+  listnode_add (oa->if_list, oi); /* sort ?? */
+  oi->area = oa;
+
+  /* start up */
+  thread_add_event (master, interface_up, oi, 0);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_interface_area,
+       no_ospf6_interface_area_cmd,
+       "no interface IFNAME area A.B.C.D",
+       NO_STR
+       "Disable routing on an IPv6 interface\n"
+       IFNAME_STR
+       "Specify the OSPF6 area ID\n"
+       "OSPF6 area ID in IPv4 address notation\n"
+       )
+{
+  struct ospf6 *o;
+  struct ospf6_interface *oi;
+  struct interface *ifp;
+  u_int32_t area_id;
+
+  o = (struct ospf6 *) vty->index;
+
+  ifp = if_lookup_by_name (argv[0]);
+  if (ifp == NULL)
+    {
+      vty_out (vty, "No such interface %s%s", argv[0], VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  oi = (struct ospf6_interface *) ifp->info;
+  if (oi == NULL)
+    {
+      vty_out (vty, "Interface %s not enabled%s", ifp->name, VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  /* parse Area-ID */
+  if (inet_pton (AF_INET, argv[1], &area_id) != 1)
+    {
+      vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  if (oi->area->area_id != area_id)
+    {
+      vty_out (vty, "Wrong Area-ID: %s is attached to area %s%s",
+               oi->interface->name, oi->area->name, VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  thread_execute (master, interface_down, oi, 0);
+
+  listnode_delete (oi->area->if_list, oi);
+  oi->area = (struct ospf6_area *) NULL;
+
+  return CMD_SUCCESS;
 }
 
 void
-ospf6_show (struct vty *vty)
+ospf6_show (struct vty *vty, struct ospf6 *o)
 {
   listnode n;
-  struct ospf6_area *area;
-  char id_string[32];
-  unsigned long day, hour, min, sec;
+  struct ospf6_area *oa;
+  char router_id[16], duration[32];
   struct timeval now, running;
 
   /* process id, router id */
-  inet_ntop (AF_INET, &ospf6->router_id, id_string, sizeof (id_string));
-  vty_out (vty, " Routing Process (%lu) with ID %s%s",
-           ospf6->process_id, id_string, VTY_NEWLINE);
+  inet_ntop (AF_INET, &o->router_id, router_id, sizeof (router_id));
+  vty_out (vty, " OSPFv3 Routing Process (0) with Router-ID %s%s",
+           router_id, VTY_NEWLINE);
 
   /* running time */
   gettimeofday (&now, (struct timezone *)NULL);
-  ospf6_timeval_sub (&now, &ospf6->starttime, &running);
-  ospf6_timeval_decode (&running, &day, &hour, &min, &sec, NULL, NULL);
-  vty_out (vty, " Running %ld days %ld hours %ld minutes %ld seconds%s",
-           day, hour, min, sec, VTY_NEWLINE);
+  timersub (&now, &o->starttime, &running);
+  timerstring (&running, duration, sizeof (duration));
+  vty_out (vty, " Running %s%s", duration, VTY_NEWLINE);
 
-  vty_out (vty, " Supports only single TOS(TOS0) routes%s", VTY_NEWLINE);
-
-  /* Redistribute config */
-  ospf6_redistribute_show_config (vty);
+  /* Redistribute configuration */
+  /* XXX */
 
   /* LSAs */
   vty_out (vty, " Number of AS scoped LSAs is %u%s",
-           ospf6->lsdb->count, VTY_NEWLINE);
-  vty_out (vty, " Route calculation executed %d times%s",
-           ospf6->stat_route_calculation_execed, VTY_NEWLINE);
-
-  /* Route Statistics */
-#if 0
-  ospf6_route_statistics_show (vty, ospf6->route_table);
-#endif
+           o->lsdb->count, VTY_NEWLINE);
 
   /* Areas */
   vty_out (vty, " Number of areas in this router is %u%s",
-           listcount (ospf6->area_list), VTY_NEWLINE);
-  for (n = listhead (ospf6->area_list); n; nextnode (n))
+           listcount (o->area_list), VTY_NEWLINE);
+  for (n = listhead (o->area_list); n; nextnode (n))
     {
-      area = (struct ospf6_area *) getdata (n);
-      ospf6_area_show (vty, area);
+      oa = (struct ospf6_area *) getdata (n);
+      ospf6_area_show (vty, oa);
     }
 }
 
-void
-ospf6_statistics_show (struct vty *vty, struct ospf6 *o6)
+/* show top level structures */
+DEFUN (show_ipv6_ospf6,
+       show_ipv6_ospf6_cmd,
+       "show ipv6 ospf6",
+       SHOW_STR
+       IP6_STR
+       OSPF6_STR)
 {
-  listnode node;
-  struct ospf6_area *o6a;
-  char running_time[128];
-  struct timeval now, running;
+  OSPF6_CMD_CHECK_RUNNING ();
 
-  gettimeofday (&now, (struct timezone *) NULL);
-  ospf6_timeval_sub (&now, &o6->starttime, &running);
-  ospf6_timeval_string (&running, running_time, sizeof (running_time));
-
-  vty_out (vty, "Statistics of OSPF process %ld%s",
-           o6->process_id, VTY_NEWLINE);
-  vty_out (vty, "  Running: %s%s", running_time, VTY_NEWLINE);
-
-#if 0
-  ospf6_route_statistics_show (vty, o6->route_table);
-#endif
-
-  for (node = listhead (o6->area_list); node; nextnode (node))
-    {
-      o6a = (struct ospf6_area *) getdata (node);
-      ospf6_area_statistics_show (vty, o6a);
-    }
-}
-
-static struct ospf6 *
-ospf6_new ()
-{
-  struct ospf6 *new;
-  new = XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6));
-  if (new)
-    memset (new, 0, sizeof (struct ospf6));
-  return new;
-}
-
-void
-ospf6_free (struct ospf6 *ospf6)
-{
-  XFREE (MTYPE_OSPF6_TOP, ospf6);
-}
-
-void
-ospf6_top_topology_add (struct ospf6_route_req *request)
-{
-  assert (request->route.type == OSPF6_DEST_TYPE_ROUTER);
-  if (CHECK_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))
-    ospf6_asbr_asbr_entry_add (request);
-}
-
-void
-ospf6_top_topology_remove (struct ospf6_route_req *request)
-{
-  assert (request->route.type == OSPF6_DEST_TYPE_ROUTER);
-  if (CHECK_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))
-    ospf6_asbr_asbr_entry_remove (request);
-}
-
-struct ospf6 *
-ospf6_create (unsigned long process_id)
-{
-  struct ospf6 *o6;
-  char namebuf[64];
-
-  o6 = ospf6_new ();
-
-  /* initialize */
-  gettimeofday (&o6->starttime, (struct timezone *)NULL);
-  o6->process_id = process_id;
-  o6->version = OSPF6_VERSION;
-  o6->area_list = list_new ();
-
-  o6->lsdb = ospf6_lsdb_create ();
-
-  o6->foreach_area = ospf6_top_foreach_area;
-  o6->foreach_if = ospf6_top_foreach_interface;
-  o6->foreach_nei = ospf6_top_foreach_neighbor;
-
-  snprintf (namebuf, sizeof (namebuf), "InterTopology table");
-  o6->topology_table = ospf6_route_table_create (namebuf);
-  ospf6_route_hook_register (ospf6_top_topology_add,
-                             ospf6_top_topology_add,
-                             ospf6_top_topology_remove,
-                             o6->topology_table);
-
-#if 0
-  snprintf (namebuf, sizeof (namebuf), "External table");
-  o6->external_table = ospf6_route_table_create (namebuf);
-  ospf6_route_hook_register (ospf6_asbr_external_route_add,
-                             ospf6_asbr_external_route_add,
-                             ospf6_asbr_external_route_remove,
-                             o6->external_table);
-#endif /*0*/
-
-  snprintf (namebuf, sizeof (namebuf), "Top route table");
-  o6->route_table = ospf6_route_table_create (namebuf);
-  ospf6_route_hook_register (ospf6_zebra_route_update_add,
-                             ospf6_zebra_route_update_add,
-                             ospf6_zebra_route_update_remove,
-                             o6->route_table);
-  ospf6_route_hook_register (ospf6_abr_route_add,
-                             ospf6_abr_route_add,
-                             ospf6_abr_route_remove,
-                             o6->route_table);
-
-  return o6;
-}
-
-void
-ospf6_delete (struct ospf6 *ospf6)
-{
-  if (!ospf6)
-    return;
-
-  ospf6_route_remove_all (ospf6->route_table);
-  ospf6_free (ospf6);
-}
-
-struct ospf6 *
-ospf6_start ()
-{
-  if (ospf6)
-    return ospf6;
-
-  ospf6 = ospf6_create (0);
-  return ospf6;
-}
-
-void
-ospf6_stop ()
-{
-  if (!ospf6)
-    return;
-
-  ospf6_delete (ospf6);
-  ospf6 = NULL;
-}
-
-int
-ospf6_is_asbr (struct ospf6 *o6)
-{
-  int i = 0;
-  i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_SYSTEM);
-  i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_CONNECT);
-  i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_STATIC);
-  i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_KERNEL);
-  i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_RIPNG);
-  i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_BGP);
-  return (i);
+  ospf6_show (vty, ospf6);
+  return CMD_SUCCESS;
 }
 
 DEFUN (show_ipv6_ospf6_route,
@@ -332,73 +451,146 @@
        SHOW_STR
        IP6_STR
        OSPF6_STR
-       "Routing table\n"
+       ROUTE_STR
        )
 {
-  OSPF6_CMD_CHECK_RUNNING ();
-  return ospf6_route_table_show (vty, argc, argv, ospf6->route_table);
+  ospf6_route_table_show (vty, argc, argv, ospf6->route_table);
+  return CMD_SUCCESS;
 }
 
 ALIAS (show_ipv6_ospf6_route,
-       show_ipv6_ospf6_route_prefix_cmd,
-       "show ipv6 ospf6 route (X::X|detail)",
+       show_ipv6_ospf6_route_detail_cmd,
+       "show ipv6 ospf6 route (X::X|X::X/M|detail|summary)",
        SHOW_STR
        IP6_STR
        OSPF6_STR
-       "Routing table\n"
-       "match IPv6 prefix\n"
-       )
+       ROUTE_STR
+       "Specify IPv6 address\n"
+       "Specify IPv6 prefix\n"
+       "Detailed information\n"
+       "Summary of route table\n"
+       );
 
-DEFUN (show_ipv6_ospf6_topology,
-       show_ipv6_ospf6_topology_cmd,
-       "show ipv6 ospf6 topology",
+DEFUN (show_ipv6_ospf6_route_match,
+       show_ipv6_ospf6_route_match_cmd,
+       "show ipv6 ospf6 route X::X/M match",
        SHOW_STR
        IP6_STR
        OSPF6_STR
-       "Inter Area topology information\n"
+       ROUTE_STR
+       "Specify IPv6 prefix\n"
+       "Display routes which match the specified route\n"
        )
 {
-  OSPF6_CMD_CHECK_RUNNING ();
-  return ospf6_route_table_show (vty, argc, argv, ospf6->topology_table);
+  char *sargv[CMD_ARGC_MAX];
+  int i, sargc;
+
+  /* copy argv to sargv and then append "match" */
+  for (i = 0; i < argc; i++)
+    sargv[i] = argv[i];
+  sargc = argc;
+  sargv[sargc++] = "match";
+  sargv[sargc] = NULL;
+
+  ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
+  return CMD_SUCCESS;
 }
 
-ALIAS (show_ipv6_ospf6_topology,
-       show_ipv6_ospf6_topology_router_cmd,
-       "show ipv6 ospf6 topology (A.B.C.D|<0-4294967295>|detail)",
+DEFUN (show_ipv6_ospf6_route_match_detail,
+       show_ipv6_ospf6_route_match_detail_cmd,
+       "show ipv6 ospf6 route X::X/M match detail",
        SHOW_STR
        IP6_STR
        OSPF6_STR
-       "Inter Area topology information\n"
-       OSPF6_ROUTER_ID_STR
-       OSPF6_ROUTER_ID_STR
+       ROUTE_STR
+       "Specify IPv6 prefix\n"
+       "Display routes which match the specified route\n"
        "Detailed information\n"
        )
+{
+  char *sargv[CMD_ARGC_MAX];
+  int i, sargc;
 
-ALIAS (show_ipv6_ospf6_topology,
-       show_ipv6_ospf6_topology_router_lsid_cmd,
-       "show ipv6 ospf6 topology (A.B.C.D|<0-4294967295>) (A.B.C.D|<0-4294967295>)",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Inter Area topology information\n"
-       OSPF6_ROUTER_ID_STR
-       OSPF6_ROUTER_ID_STR
-       OSPF6_LS_ID_STR
-       OSPF6_LS_ID_STR
-       )
+  /* copy argv to sargv and then append "match" and "detail" */
+  for (i = 0; i < argc; i++)
+    sargv[i] = argv[i];
+  sargc = argc;
+  sargv[sargc++] = "match";
+  sargv[sargc++] = "detail";
+  sargv[sargc] = NULL;
 
+  ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
+  return CMD_SUCCESS;
+}
+
+
+/* OSPF configuration write function. */
+int
+config_write_ospf6 (struct vty *vty)
+{
+  char router_id[16];
+  listnode j, k;
+  struct ospf6_area *oa;
+  struct ospf6_interface *oi;
+
+  /* OSPFv6 configuration. */
+  if (ospf6 == NULL)
+    return CMD_SUCCESS;
+  if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
+    return CMD_SUCCESS;
+
+  inet_ntop (AF_INET, &ospf6->router_id, router_id, sizeof (router_id));
+  vty_out (vty, "router ospf6%s", VTY_NEWLINE);
+  vty_out (vty, " router-id %s%s", router_id, VTY_NEWLINE);
+
+  ospf6_redistribute_config_write (vty);
+
+  for (j = listhead (ospf6->area_list); j; nextnode (j))
+    {
+      oa = (struct ospf6_area *) getdata (j);
+      for (k = listhead (oa->if_list); k; nextnode (k))
+        {
+          oi = (struct ospf6_interface *) getdata (k);
+          vty_out (vty, " interface %s area %s%s",
+                   oi->interface->name, oa->name, VTY_NEWLINE);
+        }
+    }
+  vty_out (vty, "!%s", VTY_NEWLINE);
+  return 0;
+}
+
+/* OSPF6 node structure. */
+struct cmd_node ospf6_node =
+{
+  OSPF6_NODE,
+  "%s(config-ospf6)# ",
+};
+
+/* Install ospf related commands. */
 void
 ospf6_top_init ()
 {
+  /* Install ospf6 top node. */
+  install_node (&ospf6_node, config_write_ospf6);
+
+  install_element (VIEW_NODE, &show_ipv6_ospf6_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_ospf6_cmd);
+  install_element (CONFIG_NODE, &router_ospf6_cmd);
+
   install_element (VIEW_NODE, &show_ipv6_ospf6_route_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_route_prefix_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_topology_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_topology_router_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_topology_router_lsid_cmd);
+  install_element (VIEW_NODE, &show_ipv6_ospf6_route_detail_cmd);
+  install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
+  install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
   install_element (ENABLE_NODE, &show_ipv6_ospf6_route_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_route_prefix_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_topology_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_topology_router_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_topology_router_lsid_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_ospf6_route_detail_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
+
+  install_default (OSPF6_NODE);
+  install_element (OSPF6_NODE, &ospf6_router_id_cmd);
+  install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
+  install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);
+  install_element (OSPF6_NODE, &no_router_ospf6_cmd);
 }
 
+