SVN revisions 916-920 from Zebra. ABR support is almost done.
diff --git a/ospf6d/ChangeLog b/ospf6d/ChangeLog
index e9fe119..52f4cef 100644
--- a/ospf6d/ChangeLog
+++ b/ospf6d/ChangeLog
@@ -1,3 +1,25 @@
+2004-08-15  Yasuhiro Ohara  <yasu@sfc.wide.ad.jp>
+
+	* *.c: Area support almost done. (almost ! ;p)
+	* ospf6d.h: version 0.9.7i
+
+2004-08-15  Yasuhiro Ohara  <yasu@sfc.wide.ad.jp>
+
+	* ospf6_message.c: Bug cause BadLSReq is fixed.
+	* ospf6_abr.c: Border Router check.
+	* ospf6d.h: version 0.9.7h
+
+2004-08-14  Yasuhiro Ohara  <yasu@sfc.wide.ad.jp>
+
+	* ospf6_area.[ch], ospf6_abr.[ch]: area range,
+	border-routers, Inter-Area-Router-LSA origination
+	* ospf6d.h: version 0.9.7g
+
+2004-08-12  Yasuhiro Ohara  <yasu@sfc.wide.ad.jp>
+
+	* *.[c,h]: LSA refreshing is changed and cleaned up.
+	* ospf6d.h: version 0.9.7f
+
 2004-08-01  Yasuhiro Ohara  <yasu@sfc.wide.ad.jp>
 
 	* ospf6_abr.[ch]: add files for abr function.
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index 04a55c4..397cef7 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -34,18 +34,42 @@
 #include "ospf6_lsa.h"
 #include "ospf6_route.h"
 #include "ospf6_lsdb.h"
+#include "ospf6_message.h"
+
 #include "ospf6_top.h"
 #include "ospf6_area.h"
 #include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
+
 #include "ospf6_abr.h"
+#include "ospf6_flood.h"
 #include "ospf6d.h"
 
 unsigned char conf_debug_ospf6_abr;
 
+int
+ospf6_is_router_abr (struct ospf6 *o)
+{
+  listnode node;
+  struct ospf6_area *oa;
+  int area_count = 0;
+
+  for (node = listhead (o->area_list); node; nextnode (node))
+    {
+      oa = OSPF6_AREA (getdata (node));
+      if (IS_AREA_ENABLED (oa))
+        area_count++;
+    }
+
+  if (area_count > 1)
+    return 1;
+  return 0;
+}
+
 /* RFC 2328 12.4.3. Summary-LSAs */
 void
-ospf6_abr_originate_prefix_to_area (struct ospf6_route *route,
-                                    struct ospf6_area *area)
+ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
+                                     struct ospf6_area *area)
 {
   struct ospf6_lsa *lsa, *old = NULL;
   struct ospf6_interface *oi;
@@ -55,26 +79,63 @@
   struct ospf6_lsa_header *lsa_header;
   caddr_t p;
   struct ospf6_inter_prefix_lsa *prefix_lsa;
+  struct ospf6_inter_router_lsa *router_lsa;
+  struct ospf6_route_table *summary_table = NULL;
+  u_int16_t type;
 
-  summary = ospf6_route_lookup (&route->prefix, area->summary_table);
+  if (IS_OSPF6_DEBUG_ABR)
+    {
+      char buf[64];
+      if (route->type == OSPF6_DEST_TYPE_ROUTER)
+        {
+          inet_ntop (AF_INET,
+                     &(ospf6_linkstate_prefix_adv_router (&route->prefix)),
+                     buf, sizeof (buf));
+          zlog_info ("Originating summary in area %s for ASBR %s",
+                     area->name, buf);
+        }
+      else
+        {
+          prefix2str (&route->prefix, buf, sizeof (buf));
+          zlog_info ("Originating summary in area %s for %s",
+                     area->name, buf);
+        }
+    }
+
+  if (route->type == OSPF6_DEST_TYPE_ROUTER)
+    summary_table = area->summary_router;
+  else
+    summary_table = area->summary_prefix;
+  summary = ospf6_route_lookup (&route->prefix, summary_table);
   if (summary)
-    old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTER_PREFIX),
+    old = ospf6_lsdb_lookup (summary->path.origin.type,
                              summary->path.origin.id,
                              area->ospf6->router_id, area->lsdb);
 
   /* if this route has just removed, remove corresponding LSA */
   if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
     {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("The route has just removed, purge previous LSA");
+      if (summary)
+        ospf6_route_remove (summary, summary_table);
       if (old)
-        ospf6_lsa_premature_aging (old);
+        ospf6_lsa_purge (old);
       return;
     }
 
-  /* Only destination type network and address range are considered */
-  if (route->type != OSPF6_DEST_TYPE_NETWORK)
+  /* Only destination type network, range or ASBR are considered */
+  if (route->type != OSPF6_DEST_TYPE_NETWORK &&
+      route->type != OSPF6_DEST_TYPE_RANGE &&
+      (route->type != OSPF6_DEST_TYPE_ROUTER ||
+       ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E)))
     {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("Route type is none of network, range nor ASBR, withdraw");
+      if (summary)
+        ospf6_route_remove (summary, summary_table);
       if (old)
-        ospf6_lsa_premature_aging (old);
+        ospf6_lsa_purge (old);
       return;
     }
 
@@ -82,95 +143,203 @@
   if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
       route->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
     {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("Path type is external, withdraw");
+      if (summary)
+        ospf6_route_remove (summary, summary_table);
       if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
-    }
-
-  /* do not generate if the route cost is greater or equal to LSInfinity */
-  if (route->path.cost >= LS_INFINITY)
-    {
-      if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
-    }
-
-  /* if this is an inter-area route */
-  if (route->path.type == OSPF6_PATH_TYPE_INTRA)
-    {
-      /* search for configured address range for the route's area */
-      route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
-      assert (route_area);
-      range = ospf6_route_lookup_bestmatch (&route->prefix,
-                                            route_area->summary_table);
-    }
-
-  /* ranges are ignored when originate backbone routes to transit area.
-     Otherwise, if ranges are configured, the route is suppressed. */
-  if (range && (route->path.area_id != htonl (0) || ! area->transit_capability))
-    {
-      if (old)
-        ospf6_lsa_premature_aging (old);
-      if (range->path.cost < route->path.cost)
-        range->path.cost = route->path.cost;
-      SET_FLAG (range->flag, OSPF6_ROUTE_HAVE_LONGER);
+        ospf6_lsa_purge (old);
       return;
     }
 
   /* do not generate if the path's area is the same as target area */
   if (route->path.area_id == area->area_id)
     {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("The route is in the area itself, ignore");
+      if (summary)
+        ospf6_route_remove (summary, summary_table);
       if (old)
-        ospf6_lsa_premature_aging (old);
+        ospf6_lsa_purge (old);
       return;
     }
 
   /* do not generate if the nexthops belongs to the target area */
   oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex);
-  if (oi && oi->area && oi->area->area_id == area->area_id)
+  if (oi && oi->area && oi->area == area)
     {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("The route's nexthop is in the same area, ignore");
+      if (summary)
+        ospf6_route_remove (summary, summary_table);
       if (old)
-        ospf6_lsa_premature_aging (old);
+        ospf6_lsa_purge (old);
       return;
     }
 
+  /* do not generate if the route cost is greater or equal to LSInfinity */
+  if (route->path.cost >= LS_INFINITY)
+    {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("The cost exceeds LSInfinity, withdraw");
+      if (summary)
+        ospf6_route_remove (summary, summary_table);
+      if (old)
+        ospf6_lsa_purge (old);
+      return;
+    }
+
+  /* if this is a route to ASBR */
+  if (route->type == OSPF6_DEST_TYPE_ROUTER)
+    {
+      /* Only the prefered best path is considered */
+      if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST))
+        {
+          if (IS_OSPF6_DEBUG_ABR)
+            zlog_info ("This is the secondary path to the ASBR, ignore");
+          if (summary)
+            ospf6_route_remove (summary, summary_table);
+          if (old)
+            ospf6_lsa_purge (old);
+          return;
+        }
+
+      /* Do not generate if the area is stub */
+      /* XXX */
+    }
+
+  /* if this is an intra-area route, this may be suppressed by aggregation */
+  if (route->type == OSPF6_DEST_TYPE_NETWORK &&
+      route->path.type == OSPF6_PATH_TYPE_INTRA)
+    {
+      /* search for configured address range for the route's area */
+      route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
+      assert (route_area);
+      range = ospf6_route_lookup_bestmatch (&route->prefix,
+                                            route_area->range_table);
+
+      /* ranges are ignored when originate backbone routes to transit area.
+         Otherwise, if ranges are configured, the route is suppressed. */
+      if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
+          (route->path.area_id != BACKBONE_AREA_ID ||
+           ! IS_AREA_TRANSIT (area)))
+        {
+          if (IS_OSPF6_DEBUG_ABR)
+            {
+              char buf[64];
+              prefix2str (&range->prefix, buf, sizeof (buf));
+              zlog_info ("Suppressed by range %s of area %s",
+                         buf, route_area->name);
+            }
+
+          if (summary)
+            ospf6_route_remove (summary, summary_table);
+          if (old)
+            ospf6_lsa_purge (old);
+          return;
+        }
+    }
+
+  /* If this is a configured address range */
+  if (route->type == OSPF6_DEST_TYPE_RANGE)
+    {
+      /* If DoNotAdvertise is set */
+      if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
+        {
+          if (IS_OSPF6_DEBUG_ABR)
+            zlog_info ("This is the range with DoNotAdvertise set. ignore");
+          if (summary)
+            ospf6_route_remove (summary, summary_table);
+          if (old)
+            ospf6_lsa_purge (old);
+          return;
+        }
+
+      /* Whether the route have active longer prefix */
+      if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
+        {
+          if (IS_OSPF6_DEBUG_ABR)
+            zlog_info ("The range is not active. withdraw");
+          if (summary)
+            ospf6_route_remove (summary, summary_table);
+          if (old)
+            ospf6_lsa_purge (old);
+          return;
+        }
+    }
+
   /* the route is going to be originated. store it in area's summary_table */
   if (summary == NULL)
     {
       summary = ospf6_route_copy (route);
-      summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+      if (route->type == OSPF6_DEST_TYPE_NETWORK ||
+          route->type == OSPF6_DEST_TYPE_RANGE)
+        summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+      else
+        summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER);
       summary->path.origin.adv_router = area->ospf6->router_id;
       summary->path.origin.id =
         ospf6_new_ls_id (summary->path.origin.type,
                          summary->path.origin.adv_router, area->lsdb);
-      ospf6_route_add (summary, area->summary_table);
+      ospf6_route_add (summary, summary_table);
     }
+  else
+    {
+      summary->type = route->type;
+      gettimeofday (&summary->changed, NULL);
+    }
+
+  summary->path.router_bits = route->path.router_bits;
+  summary->path.options[0] = route->path.options[0];
+  summary->path.options[1] = route->path.options[1];
+  summary->path.options[2] = route->path.options[2];
+  summary->path.prefix_options = route->path.prefix_options;
+  summary->path.area_id = area->area_id;
+  summary->path.type = OSPF6_PATH_TYPE_INTER;
+  summary->path.cost = route->path.cost;
+  summary->nexthop[0] = route->nexthop[0];
 
   /* prepare buffer */
   memset (buffer, 0, sizeof (buffer));
   lsa_header = (struct ospf6_lsa_header *) buffer;
-  prefix_lsa = (struct ospf6_inter_prefix_lsa *)
-    ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
-  p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);
 
-  /* Fill Inter-Area-Prefix-LSA */
-  OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
+  if (route->type == OSPF6_DEST_TYPE_ROUTER)
+    {
+      router_lsa = (struct ospf6_inter_router_lsa *)
+        ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+      p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa);
 
-  /* prefixlen */
-  prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
+      /* Fill Inter-Area-Router-LSA */
+      router_lsa->options[0] = route->path.options[0];
+      router_lsa->options[1] = route->path.options[1];
+      router_lsa->options[2] = route->path.options[2];
+      OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost);
+      router_lsa->router_id =
+        ospf6_linkstate_prefix_adv_router (&route->prefix);
+      type = htons (OSPF6_LSTYPE_INTER_ROUTER);
+    }
+  else
+    {
+      prefix_lsa = (struct ospf6_inter_prefix_lsa *)
+        ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+      p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);
 
-  /* PrefixOptions */
-  prefix_lsa->prefix.prefix_options = route->path.prefix_options;
+      /* Fill Inter-Area-Prefix-LSA */
+      OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
+      prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
+      prefix_lsa->prefix.prefix_options = route->path.prefix_options;
 
-  /* set Prefix */
-  memcpy (p, &route->prefix.u.prefix6,
-          OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
-  ospf6_prefix_apply_mask (&prefix_lsa->prefix);
-  p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
+      /* set Prefix */
+      memcpy (p, &route->prefix.u.prefix6,
+              OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
+      ospf6_prefix_apply_mask (&prefix_lsa->prefix);
+      p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
+      type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+    }
 
   /* Fill LSA Header */
   lsa_header->age = 0;
-  lsa_header->type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+  lsa_header->type = type;
   lsa_header->id = summary->path.origin.id;
   lsa_header->adv_router = area->ospf6->router_id;
   lsa_header->seqnum =
@@ -183,23 +352,63 @@
 
   /* create LSA */
   lsa = ospf6_lsa_create (lsa_header);
-  lsa->scope = area;
-  SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* XXX */
+
+  if (IS_OSPF6_DEBUG_ABR)
+    zlog_info ("Originate as %s", lsa->name);
 
   /* Originate */
-  ospf6_lsa_originate (lsa);
+  ospf6_lsa_originate_area (lsa, area);
 }
 
 void
-ospf6_abr_originate_prefix (struct ospf6_route *route, struct ospf6 *o)
+ospf6_abr_range_update (struct ospf6_route *range)
+{
+  u_int32_t cost = 0;
+  struct ospf6_route *ro;
+
+  assert (range->type == OSPF6_DEST_TYPE_RANGE);
+
+  /* update range's cost and active flag */
+  for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table);
+       ro; ro = ospf6_route_match_next (&range->prefix, ro))
+    {
+      if (ro->path.area_id == range->path.area_id &&
+          ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE))
+        cost = MAX (cost, ro->path.cost);
+    }
+
+  if (range->path.cost != cost)
+    {
+      range->path.cost = cost;
+
+      if (range->path.cost)
+        SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
+      else
+        UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
+
+      ospf6_abr_originate_summary (range);
+    }
+}
+
+void
+ospf6_abr_originate_summary (struct ospf6_route *route)
 {
   listnode node;
   struct ospf6_area *oa;
+  struct ospf6_route *range = NULL;
 
-  for (node = listhead (o->area_list); node; nextnode (node))
+  if (route->type == OSPF6_DEST_TYPE_NETWORK)
+    {
+      oa = ospf6_area_lookup (route->path.area_id, ospf6);
+      range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table);
+      if (range)
+        ospf6_abr_range_update (range);
+    }
+
+  for (node = listhead (ospf6->area_list); node; nextnode (node))
     {
       oa = (struct ospf6_area *) getdata (node);
-      ospf6_abr_originate_prefix_to_area (route, oa);
+      ospf6_abr_originate_summary_to_area (route, oa);
     }
 }
 
@@ -211,7 +420,7 @@
   struct ospf6_route_table *table = NULL;
   struct ospf6_route *range, *route, *old = NULL;
   struct ospf6_route *abr_entry;
-  u_char type;
+  u_char type = 0;
   char options[3] = {0, 0, 0};
   u_int8_t prefix_options = 0;
   u_int32_t cost = 0;
@@ -274,18 +483,22 @@
     }
 
   /* (3) if the prefix is equal to an active configured address range */
-  range = ospf6_route_lookup (&prefix, oa->summary_table);
-  if (range && CHECK_FLAG (range->flag, OSPF6_ROUTE_HAVE_LONGER))
+  if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
     {
-      if (old)
-        ospf6_route_remove (old, oa->ospf6->route_table);
-      return;
+      range = ospf6_route_lookup (&prefix, oa->range_table);
+      if (range)
+        {
+          if (old)
+            ospf6_route_remove (old, oa->ospf6->route_table);
+          return;
+        }
     }
 
   /* (4) if the routing table entry for the ABR does not exist */
   ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix);
   abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table);
-  if (abr_entry == NULL)
+  if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
+      ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
     {
       if (old)
         ospf6_route_remove (old, oa->ospf6->route_table);
@@ -318,11 +531,6 @@
   ospf6_route_add (route, table);
 }
 
-int
-dummy (struct ospf6_lsa *lsa)
-{
-}
-
 
 /* Display functions */
 int
@@ -412,15 +620,25 @@
   install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd);
 }
 
+struct ospf6_lsa_handler inter_prefix_handler =
+{
+  OSPF6_LSTYPE_INTER_PREFIX,
+  "Inter-Prefix",
+  ospf6_inter_area_prefix_lsa_show
+};
+
+struct ospf6_lsa_handler inter_router_handler =
+{
+  OSPF6_LSTYPE_INTER_ROUTER,
+  "Inter-Router",
+  ospf6_inter_area_router_lsa_show
+};
+
 void
 ospf6_abr_init ()
 {
-  ospf6_lstype[3].name = "Inter-Area-Prefix-LSA";
-  ospf6_lstype[3].reoriginate = dummy;
-  ospf6_lstype[3].show = ospf6_inter_area_prefix_lsa_show;
-  ospf6_lstype[4].name = "Inter-Area-Router-LSA";
-  ospf6_lstype[4].reoriginate = dummy;
-  ospf6_lstype[4].show = ospf6_inter_area_router_lsa_show;
+  ospf6_install_lsa_handler (&inter_prefix_handler);
+  ospf6_install_lsa_handler (&inter_router_handler);
 }
 
 
diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h
index 1c5c6a3..a12d985 100644
--- a/ospf6d/ospf6_abr.h
+++ b/ospf6d/ospf6_abr.h
@@ -52,9 +52,11 @@
   { (E)->metric &= htonl (0x00000000); \
     (E)->metric |= htonl (0x00ffffff) & htonl (C); }
 
-void ospf6_abr_originate_prefix_to_area (struct ospf6_route *route,
-                                         struct ospf6_area *area);
-void ospf6_abr_originate_prefix (struct ospf6_route *route, struct ospf6 *o);
+int ospf6_is_router_abr (struct ospf6 *o);
+
+void ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
+                                          struct ospf6_area *area);
+void ospf6_abr_originate_summary (struct ospf6_route *route);
 void ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa);
 
 int config_write_ospf6_debug_abr (struct vty *vty);
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 04cbb0a..fc2103c 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -48,29 +48,18 @@
 {
   struct ospf6_area *oa = (struct ospf6_area *) va;
   struct ospf6_area *ob = (struct ospf6_area *) vb;
-  return (ntohl (oa->area_id) - ntohl (ob->area_id));
-}
-
-int
-ospf6_area_is_stub (struct ospf6_area *o6a)
-{
-  if (OSPF6_OPT_ISSET (o6a->options, OSPF6_OPT_E))
-    return 0;
-  return 1;
+  return (ntohl (oa->area_id) < ntohl (ob->area_id) ? -1 : 1);
 }
 
 /* schedule routing table recalculation */
 void
 ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
 {
-  struct ospf6_area *oa;
-
-  oa = (struct ospf6_area *) lsa->scope;
   switch (ntohs (lsa->header->type))
     {
     case OSPF6_LSTYPE_ROUTER:
     case OSPF6_LSTYPE_NETWORK:
-      ospf6_spf_schedule (oa);
+      ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
       break;
 
     case OSPF6_LSTYPE_INTRA_PREFIX:
@@ -83,7 +72,8 @@
 
     default:
       if (IS_OSPF6_DEBUG_LSA (RECV))
-	zlog_info ("Unknown LSA in Area %s's lsdb", oa->name);
+	zlog_info ("Unknown LSA in Area %s's lsdb",
+                   OSPF6_AREA (lsa->lsdb->data)->name);
       break;
     }
 }
@@ -91,14 +81,11 @@
 void
 ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
 {
-  struct ospf6_area *oa;
-
-  oa = (struct ospf6_area *) lsa->scope;
   switch (ntohs (lsa->header->type))
     {
     case OSPF6_LSTYPE_ROUTER:
     case OSPF6_LSTYPE_NETWORK:
-      ospf6_spf_schedule (oa);
+      ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
       break;
 
     case OSPF6_LSTYPE_INTRA_PREFIX:
@@ -111,7 +98,8 @@
 
     default:
       if (IS_OSPF6_DEBUG_LSA (RECV))
-	zlog_info ("Unknown LSA in Area %s's lsdb", oa->name);
+	zlog_info ("Unknown LSA in Area %s's lsdb",
+                   OSPF6_AREA (lsa->lsdb->data)->name);
       break;
     }
 }
@@ -146,17 +134,20 @@
   oa->area_id = area_id;
   oa->if_list = list_new ();
 
-  oa->summary_table = ospf6_route_table_create ();
-
-  oa->lsdb = ospf6_lsdb_create ();
+  oa->lsdb = ospf6_lsdb_create (oa);
   oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
   oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
+  oa->lsdb_self = ospf6_lsdb_create (oa);
 
   oa->spf_table = ospf6_route_table_create ();
   oa->route_table = ospf6_route_table_create ();
   oa->route_table->hook_add = ospf6_area_route_hook_add;
   oa->route_table->hook_remove = ospf6_area_route_hook_remove;
 
+  oa->range_table = ospf6_route_table_create ();
+  oa->summary_prefix = ospf6_route_table_create ();
+  oa->summary_router = ospf6_route_table_create ();
+
   /* set default options */
   OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
   OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
@@ -168,7 +159,7 @@
   /* import athoer area's routes as inter-area routes */
   for (route = ospf6_route_head (o->route_table); route;
        route = ospf6_route_next (route))
-    ospf6_abr_originate_prefix_to_area (route, oa);
+    ospf6_abr_originate_summary_to_area (route, oa);
 
   return oa;
 }
@@ -179,7 +170,9 @@
   listnode n;
   struct ospf6_interface *oi;
 
-  ospf6_route_table_delete (oa->summary_table);
+  ospf6_route_table_delete (oa->range_table);
+  ospf6_route_table_delete (oa->summary_prefix);
+  ospf6_route_table_delete (oa->summary_router);
 
   /* ospf6 interface list */
   for (n = listhead (oa->if_list); n; nextnode (n))
@@ -190,6 +183,8 @@
   list_delete (oa->if_list);
 
   ospf6_lsdb_delete (oa->lsdb);
+  ospf6_lsdb_delete (oa->lsdb_self);
+
   ospf6_route_table_delete (oa->spf_table);
   ospf6_route_table_delete (oa->route_table);
 
@@ -224,13 +219,23 @@
   return (struct ospf6_area *) NULL;
 }
 
+struct ospf6_area *
+ospf6_area_get (u_int32_t area_id, struct ospf6 *o)
+{
+  struct ospf6_area *oa;
+  oa = ospf6_area_lookup (area_id, o);
+  if (oa == NULL)
+    oa = ospf6_area_create (area_id, o);
+  return oa;
+}
+
 void
 ospf6_area_enable (struct ospf6_area *oa)
 {
   listnode i;
   struct ospf6_interface *oi;
 
-  UNSET_FLAG (oa->flag, OSPF6_AREA_DISABLE);
+  SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
 
   for (i = listhead (oa->if_list); i; nextnode (i))
     {
@@ -245,7 +250,7 @@
   listnode i;
   struct ospf6_interface *oi;
 
-  SET_FLAG (oa->flag, OSPF6_AREA_DISABLE);
+  UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
 
   for (i = listhead (oa->if_list); i; nextnode (i))
     {
@@ -291,6 +296,130 @@
     }                                                      \
 }
 
+#define OSPF6_CMD_AREA_GET(str, oa)                        \
+{                                                          \
+  u_int32_t area_id = 0;                                   \
+  if (inet_pton (AF_INET, str, &area_id) != 1)             \
+    {                                                      \
+      vty_out (vty, "Malformed Area-ID: %s%s", str, VNL);  \
+      return CMD_SUCCESS;                                  \
+    }                                                      \
+  oa = ospf6_area_get (area_id, ospf6);                    \
+}
+
+DEFUN (area_range,
+       area_range_cmd,
+       "area A.B.C.D range X:X::X:X/M",
+       "OSPF area parameters\n"
+       OSPF6_AREA_ID_STR
+       "Configured address range\n"
+       "Specify IPv6 prefix\n"
+       )
+{
+  int ret;
+  struct ospf6_area *oa;
+  struct prefix prefix;
+  struct ospf6_route *range;
+
+  OSPF6_CMD_AREA_GET (argv[0], oa);
+  argc--;
+  argv++;
+
+  ret = str2prefix (argv[0], &prefix);
+  if (ret != 1 || prefix.family != AF_INET6)
+    {
+      vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
+      return CMD_SUCCESS;
+    }
+  argc--;
+  argv++;
+
+  range = ospf6_route_lookup (&prefix, oa->range_table);
+  if (range == NULL)
+    {
+      range = ospf6_route_create ();
+      range->type = OSPF6_DEST_TYPE_RANGE;
+      range->prefix = prefix;
+    }
+
+  if (argc)
+    {
+      if (! strcmp (argv[0], "not-advertise"))
+        SET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
+      else if (! strcmp (argv[0], "advertise"))
+        UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
+    }
+
+  ospf6_route_add (range, oa->range_table);
+  return CMD_SUCCESS;
+}
+
+ALIAS (area_range,
+       area_range_advertise_cmd,
+       "area A.B.C.D range X:X::X:X/M (advertise|not-advertise)",
+       "OSPF area parameters\n"
+       OSPF6_AREA_ID_STR
+       "Configured address range\n"
+       "Specify IPv6 prefix\n"
+       );
+
+DEFUN (no_area_range,
+       no_area_range_cmd,
+       "no area A.B.C.D range X:X::X:X/M",
+       "OSPF area parameters\n"
+       OSPF6_AREA_ID_STR
+       "Configured address range\n"
+       "Specify IPv6 prefix\n"
+       )
+{
+  int ret;
+  struct ospf6_area *oa;
+  struct prefix prefix;
+  struct ospf6_route *range;
+
+  OSPF6_CMD_AREA_GET (argv[0], oa);
+  argc--;
+  argv++;
+
+  ret = str2prefix (argv[0], &prefix);
+  if (ret != 1 || prefix.family != AF_INET6)
+    {
+      vty_out (vty, "Malformed argument: %s%s", argv[0], VNL);
+      return CMD_SUCCESS;
+    }
+
+  range = ospf6_route_lookup (&prefix, oa->range_table);
+  if (range == NULL)
+    {
+      vty_out (vty, "Range %s does not exists.%s", argv[0], VNL);
+      return CMD_SUCCESS;
+    }
+
+  ospf6_route_remove (range, oa->range_table);
+  return CMD_SUCCESS;
+}
+
+void
+ospf6_area_config_write (struct vty *vty)
+{
+  listnode node;
+  struct ospf6_area *oa;
+  struct ospf6_route *range;
+  char buf[128];
+
+  for (node = listhead (ospf6->area_list); node; nextnode (node))
+    {
+      oa = OSPF6_AREA (getdata (node));
+
+      for (range = ospf6_route_head (oa->range_table); range;
+           range = ospf6_route_next (range))
+        {
+          prefix2str (&range->prefix, buf, sizeof (buf));
+          vty_out (vty, " area %s range %s%s", oa->name, buf, VNL);
+        }
+    }
+}
+
 DEFUN (show_ipv6_ospf6_area_route_intra,
        show_ipv6_ospf6_area_route_intra_cmd,
        "show ipv6 ospf6 area A.B.C.D route intra-area",
@@ -876,5 +1005,10 @@
   install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_intra_match_detail_cmd);
 
   install_element (ENABLE_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
+
+  install_element (OSPF6_NODE, &area_range_cmd);
+  install_element (OSPF6_NODE, &area_range_advertise_cmd);
+  install_element (OSPF6_NODE, &no_area_range_cmd);
 }
 
+
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index c15960c..734f030 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -41,16 +41,17 @@
   /* OSPF Option */
   u_char options[3];
 
-  /* TransitCapability */
-  int transit_capability;
-
   /* Summary routes to be originated (includes Configured Address Ranges) */
-  struct ospf6_route_table *summary_table;
+  struct ospf6_route_table *range_table;
+  struct ospf6_route_table *summary_prefix;
+  struct ospf6_route_table *summary_router;
 
   /* OSPF interface list */
   list if_list;
 
-  struct ospf6_lsdb        *lsdb;
+  struct ospf6_lsdb *lsdb;
+  struct ospf6_lsdb *lsdb_self;
+
   struct ospf6_route_table *spf_table;
   struct ospf6_route_table *route_table;
 
@@ -62,12 +63,21 @@
   u_int32_t router_lsa_size_limit;
 };
 
-#define OSPF6_AREA_DISABLE 0x01
-#define OSPF6_AREA_STUB    0x02
+#define OSPF6_AREA_ENABLE     0x01
+#define OSPF6_AREA_ACTIVE     0x02
+#define OSPF6_AREA_TRANSIT    0x04 /* TransitCapability */
+#define OSPF6_AREA_STUB       0x08
+
+#define BACKBONE_AREA_ID (htonl (0))
+#define IS_AREA_BACKBONE(oa) ((oa)->area_id == BACKBONE_AREA_ID)
+#define IS_AREA_ENABLED(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ENABLE))
+#define IS_AREA_ACTIVE(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ACTIVE))
+#define IS_AREA_TRANSIT(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_TRANSIT))
+#define IS_AREA_STUB(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_STUB))
 
 /* prototypes */
 int ospf6_area_cmp (void *va, void *vb);
-int ospf6_area_is_stub (struct ospf6_area *o6a);
+
 struct ospf6_area *ospf6_area_create (u_int32_t, struct ospf6 *);
 void ospf6_area_delete (struct ospf6_area *);
 struct ospf6_area *ospf6_area_lookup (u_int32_t, struct ospf6 *);
@@ -76,6 +86,8 @@
 void ospf6_area_disable (struct ospf6_area *);
 
 void ospf6_area_show (struct vty *, struct ospf6_area *);
+
+void ospf6_area_config_write (struct vty *vty);
 void ospf6_area_init ();
 
 #endif /* OSPF_AREA_H */
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 18f7cc2..a8a1ce1 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -37,10 +37,15 @@
 #include "ospf6_lsdb.h"
 #include "ospf6_route.h"
 #include "ospf6_zebra.h"
+#include "ospf6_message.h"
+
 #include "ospf6_top.h"
 #include "ospf6_area.h"
+#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
 #include "ospf6_asbr.h"
 #include "ospf6_intra.h"
+#include "ospf6_flood.h"
 #include "ospf6d.h"
 
 unsigned char conf_debug_ospf6_asbr = 0;
@@ -61,20 +66,19 @@
 
 /* AS External LSA origination */
 void
-ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force)
+ospf6_as_external_lsa_originate (struct ospf6_route *route)
 {
   char buffer[OSPF6_MAX_LSASIZE];
   struct ospf6_lsa_header *lsa_header;
   struct ospf6_lsa *old, *lsa;
 
-  struct ospf6_external_info *info = route->route_option;
   struct ospf6_as_external_lsa *as_external_lsa;
   char buf[64];
   caddr_t p;
 
   /* find previous LSA */
   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
-                           htonl (info->id), ospf6->router_id,
+                           route->path.origin.id, ospf6->router_id,
                            ospf6->lsdb);
 
   if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -99,7 +103,7 @@
     UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
 
   /* forwarding address */
-  if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
+  if (! IN6_IS_ADDR_UNSPECIFIED (&route->nexthop[0].address))
     SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
   else
     UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
@@ -128,7 +132,7 @@
   /* Forwarding address */
   if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
     {
-      memcpy (p, &info->forwarding, sizeof (struct in6_addr));
+      memcpy (p, &route->nexthop[0].address, sizeof (struct in6_addr));
       p += sizeof (struct in6_addr);
     }
 
@@ -141,7 +145,7 @@
   /* Fill LSA Header */
   lsa_header->age = 0;
   lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
-  lsa_header->id = htonl (info->id);
+  lsa_header->id = route->path.origin.id;
   lsa_header->adv_router = ospf6->router_id;
   lsa_header->seqnum =
     ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
@@ -153,37 +157,11 @@
 
   /* create LSA */
   lsa = ospf6_lsa_create (lsa_header);
-  lsa->scope = ospf6;
-  if (force)
-    SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
 
   /* Originate */
-  ospf6_lsa_originate (lsa);
+  ospf6_lsa_originate_process (lsa, ospf6);
 }
 
-int
-ospf6_as_external_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
-  struct prefix prefix_id;
-  struct route_node *node;
-  struct ospf6_route *route;
-
-  /* create/update binding in external_id_table */
-  prefix_id.family = AF_INET;
-  prefix_id.prefixlen = 32;
-  prefix_id.u.prefix4.s_addr = lsa->header->id;
-  node = route_node_get (ospf6->external_id_table, &prefix_id);
-  route = node->info;
-
-  if (route)
-    ospf6_as_external_lsa_originate_sub (route, 1);
-  else
-    ospf6_lsa_premature_aging (lsa);
-
-  return 0;
-}
-
-
 
 void
 ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
@@ -217,7 +195,7 @@
   asbr_id.family = AF_INET;
   asbr_id.prefixlen = 32;
   asbr_id.u.prefix4.s_addr = lsa->header->adv_router;
-  asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->asbr_table);
+  asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
 
   if (asbr_entry == NULL)
     {
@@ -545,7 +523,7 @@
           zlog_info ("Advertise as AS-External Id:%s", ibuf);
         }
 
-      ospf6_as_external_lsa_originate_sub (match, 0);
+      ospf6_as_external_lsa_originate (match);
       return;
     }
 
@@ -593,7 +571,7 @@
       zlog_info ("Advertise as AS-External Id:%s", ibuf);
     }
 
-  ospf6_as_external_lsa_originate_sub (route, 0);
+  ospf6_as_external_lsa_originate (route);
 
   /* Router-Bit (ASBR Flag) may have to be updated */
   for (lnode = listhead (ospf6->area_list); lnode; nextnode (lnode))
@@ -649,7 +627,7 @@
   lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
                            htonl (info->id), ospf6->router_id, ospf6->lsdb);
   if (lsa)
-    ospf6_lsa_premature_aging (lsa);
+    ospf6_lsa_purge (lsa);
 
   /* remove binding in external_id_table */
   prefix_id.family = AF_INET;
@@ -1254,95 +1232,23 @@
   return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_asbr,
-       show_ipv6_ospf6_asbr_cmd,
-       "show ipv6 ospf6 asbr",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Show AS Boundary Router table\n"
-      )
+struct ospf6_lsa_handler as_external_handler =
 {
-  ospf6_lsentry_table_show (vty, argc, argv, ospf6->asbr_table);
-  return CMD_SUCCESS;
-}
-
-ALIAS (show_ipv6_ospf6_asbr,
-       show_ipv6_ospf6_asbr_1_cmd,
-       "show ipv6 ospf6 asbr (A.B.C.D|A.B.C.D/M|detail)",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Show AS Boundary Router table\n"
-       "Specify Router-ID\n"
-       "Display multiple entry by specifying match-prefix of Router-ID\n"
-       "Display Detail\n"
-      );
-
-ALIAS (show_ipv6_ospf6_asbr,
-       show_ipv6_ospf6_asbr_2_cmd,
-       "show ipv6 ospf6 asbr (A.B.C.D|A.B.C.D/M|*) (A.B.C.D|A.B.C.D/M|detail)",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Show AS Boundary Router table\n"
-       "Specify Router-ID\n"
-       "Display multiple entry by specifying match-prefix of Router-ID\n"
-       "Wildcard Router-ID\n"
-       "Specify Link State ID\n"
-       "Display multiple entry by specifying match-prefix of Link State ID\n"
-       "Display Detail\n"
-      );
-
-DEFUN (show_ipv6_ospf6_asbr_3,
-       show_ipv6_ospf6_asbr_3_cmd,
-       "show ipv6 ospf6 asbr (A.B.C.D|*) A.B.C.D/M detail",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Show AS Boundary Router table\n"
-       "Specify Router-ID\n"
-       "Wildcard Router-ID\n"
-       "Display multiple entry by specifying match-prefix of Link State ID\n"
-       "Display Detail\n"
-      )
-{
-  char *sargv[CMD_ARGC_MAX];
-  int i, sargc;
-
-  /* copy argv to sargv and then append "detail" */
-  for (i = 0; i < argc; i++)
-    sargv[i] = argv[i];
-  sargc = argc;
-  sargv[sargc++] = "detail";
-  sargv[sargc] = NULL;
-
-  ospf6_lsentry_table_show (vty, sargc, sargv, ospf6->asbr_table);
-  return CMD_SUCCESS;
-}
-
+  OSPF6_LSTYPE_AS_EXTERNAL,
+  "AS-External",
+  ospf6_as_external_lsa_show
+};
 
 void
 ospf6_asbr_init ()
 {
   ospf6_routemap_init ();
 
-  ospf6_lstype[5].name = "AS-External";
-  ospf6_lstype[5].reoriginate = ospf6_as_external_lsa_reoriginate;
-  ospf6_lstype[5].show = ospf6_as_external_lsa_show;
+  ospf6_install_lsa_handler (&as_external_handler);
 
   install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
   install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
 
-  install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_1_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_2_cmd);
-  install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_3_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_1_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_2_cmd);
-  install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_3_cmd);
-
   install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
   install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
   install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index 6e84a03..aeff15b 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -39,160 +39,169 @@
 #include "ospf6_interface.h"
 #include "ospf6_neighbor.h"
 
-
-void *
-ospf6_get_lsa_scope (u_int16_t type, struct ospf6_neighbor *from)
-{
-  void *scope = NULL;
-
-  if (from == NULL)
-    return NULL;
-
-  switch (OSPF6_LSA_SCOPE (type))
-    {
-      case OSPF6_LSA_SCOPE_AS:
-        scope = (from)->ospf6_if->area->ospf6;
-        break;
-      case OSPF6_LSA_SCOPE_AREA:
-        scope = (from)->ospf6_if->area;
-        break;
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
-        scope = (from)->ospf6_if;
-        break;
-      default:
-        break;
-    }
-
-  return scope;
-}
+#include "ospf6_flood.h"
 
 struct ospf6_lsdb *
-ospf6_get_scoped_lsdb (u_int16_t type, void *scope)
+ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa)
 {
   struct ospf6_lsdb *lsdb = NULL;
-
-  if (scope == NULL)
-    return NULL;
-
-  switch (OSPF6_LSA_SCOPE (type))
+  switch (OSPF6_LSA_SCOPE (lsa->header->type))
     {
-      case OSPF6_LSA_SCOPE_AS:
-        lsdb = ((struct ospf6 *)(scope))->lsdb;
-        break;
-      case OSPF6_LSA_SCOPE_AREA:
-        lsdb = ((struct ospf6_area *)(scope))->lsdb;
-        break;
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
-        lsdb = ((struct ospf6_interface *)(scope))->lsdb;
-        break;
-      default:
-        break;
+    case OSPF6_SCOPE_LINKLOCAL:
+      lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb;
+      break;
+    case OSPF6_SCOPE_AREA:
+      lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb;
+      break;
+    case OSPF6_SCOPE_AS:
+      lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb;
+      break;
+    default:
+      assert (0);
+      break;
     }
-
   return lsdb;
 }
 
-void
-ospf6_decrement_onretrans (struct ospf6_lsa *lsa)
+struct ospf6_lsdb *
+ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa)
 {
-  struct ospf6_lsdb *lsdb;
-  struct ospf6_lsa *src;
-
-  lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
-  if (lsdb == NULL)
+  struct ospf6_lsdb *lsdb_self = NULL;
+  switch (OSPF6_LSA_SCOPE (lsa->header->type))
     {
-      zlog_warn ("Decrement onretrans: no such scope: %s", lsa->name);
-      return;
+    case OSPF6_SCOPE_LINKLOCAL:
+      lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self;
+      break;
+    case OSPF6_SCOPE_AREA:
+      lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self;
+      break;
+    case OSPF6_SCOPE_AS:
+      lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self;
+      break;
+    default:
+      assert (0);
+      break;
     }
-
-  src = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
-                           lsa->header->adv_router, lsdb);
-  if (src && src != lsa)
-    src->onretrans--;
-
-  if (src->onretrans < 0)
-    zlog_warn ("internal error: onretrans");
+  return lsdb_self;
 }
 
 void
-ospf6_flood_clear (struct ospf6_lsa *lsa)
+ospf6_lsa_originate (struct ospf6_lsa *lsa)
 {
-  struct ospf6_neighbor *on;
-  struct ospf6_interface *oi, *ospf6_if = NULL;
-  struct ospf6_area *oa, *area = NULL;
-  struct ospf6 *ospf6 = NULL;
-  u_int16_t scope_type;
-  list scoped_interfaces;
-  struct ospf6_lsa *rxmt;
-  listnode i, j;
+  struct ospf6_lsa *old;
+  struct ospf6_lsdb *lsdb_self;
 
-  scoped_interfaces = list_new ();
-  scope_type = OSPF6_LSA_SCOPE (lsa->header->type);
+  /* find previous LSA */
+  old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+                           lsa->header->adv_router, lsa->lsdb);
 
-  if (scope_type == OSPF6_LSA_SCOPE_LINKLOCAL)
+  /* if the new LSA does not differ from previous,
+     suppress this update of the LSA */
+  if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old))
     {
-      ospf6_if = (struct ospf6_interface *) lsa->scope;
-      area = ospf6_if->area;
-      ospf6 = area->ospf6;
-    }
-  else if (scope_type == OSPF6_LSA_SCOPE_AREA)
-    {
-      area = (struct ospf6_area *) lsa->scope;
-      ospf6 = area->ospf6;
-    }
-  else if (scope_type == OSPF6_LSA_SCOPE_AS)
-    {
-      ospf6 = (struct ospf6 *) lsa->scope;
-    }
-  else
-    {
-      zlog_warn ("Can't decide LSA scope, quit ospf6_flood_clear ()");
+      if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+        zlog_info ("Suppress updating LSA: %s", lsa->name);
+      ospf6_lsa_delete (lsa);
       return;
     }
 
-  /* Collect eligible interfaces */
-  for (i = listhead (ospf6->area_list); i; nextnode (i))
+  /* store it in the LSDB for self-originated LSAs */
+  lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
+  ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
+
+  lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
+                                   LS_REFRESH_TIME);
+
+  if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
     {
-      oa = (struct ospf6_area *) getdata (i);
-      if (scope_type != OSPF6_LSA_SCOPE_AS && oa != area)
-        continue;
-
-      for (j = listhead (oa->if_list); j; nextnode (j))
-        {
-          oi = (struct ospf6_interface *) getdata (j);
-          if (scope_type != OSPF6_LSA_SCOPE_AS &&
-              scope_type != OSPF6_LSA_SCOPE_AREA && oi != ospf6_if)
-            continue;
-
-          listnode_add (scoped_interfaces, oi);
-        }
+      zlog_info ("LSA Originate:");
+      ospf6_lsa_header_print (lsa);
     }
 
-  for (i = listhead (scoped_interfaces); i; nextnode (i))
+  if (old)
+    ospf6_flood_clear (old);
+  ospf6_flood (NULL, lsa);
+  ospf6_install_lsa (lsa);
+}
+
+void
+ospf6_lsa_originate_process (struct ospf6_lsa *lsa,
+                             struct ospf6 *process)
+{
+  lsa->lsdb = process->lsdb;
+  ospf6_lsa_originate (lsa);
+}
+
+void
+ospf6_lsa_originate_area (struct ospf6_lsa *lsa,
+                          struct ospf6_area *oa)
+{
+  lsa->lsdb = oa->lsdb;
+  ospf6_lsa_originate (lsa);
+}
+
+void
+ospf6_lsa_originate_interface (struct ospf6_lsa *lsa,
+                               struct ospf6_interface *oi)
+{
+  lsa->lsdb = oi->lsdb;
+  ospf6_lsa_originate (lsa);
+}
+
+void
+ospf6_lsa_purge (struct ospf6_lsa *lsa)
+{
+  struct ospf6_lsa *self;
+  struct ospf6_lsdb *lsdb_self;
+
+  /* remove it from the LSDB for self-originated LSAs */
+  lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
+  self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+                            lsa->header->adv_router, lsdb_self);
+  if (self)
     {
-      oi = (struct ospf6_interface *) getdata (i);
-      for (j = listhead (oi->neighbor_list); j; nextnode (j))
-        {
-          on = (struct ospf6_neighbor *) getdata (j);
-          rxmt = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
-                                    lsa->header->adv_router, on->retrans_list);
-          if (rxmt && ! ospf6_lsa_compare (rxmt, lsa))
-            {
-              if (IS_OSPF6_DEBUG_LSA (DATABASE))
-                zlog_info ("Remove %s from retrans_list of %s",
-                           rxmt->name, on->name);
-              ospf6_decrement_onretrans (rxmt);
-              ospf6_lsdb_remove (rxmt, on->retrans_list);
-            }
-        }
+      THREAD_OFF (self->expire);
+      THREAD_OFF (self->refresh);
+      ospf6_lsdb_remove (self, lsdb_self);
     }
 
-  list_delete (scoped_interfaces);
+  ospf6_lsa_premature_aging (lsa);
+}
+
+
+void
+ospf6_increment_retrans_count (struct ospf6_lsa *lsa)
+{
+  /* The LSA must be the original one (see the description
+     in ospf6_decrement_retrans_count () below) */
+  lsa->retrans_count++;
+}
+
+void
+ospf6_decrement_retrans_count (struct ospf6_lsa *lsa)
+{
+  struct ospf6_lsdb *lsdb;
+  struct ospf6_lsa *orig;
+
+  /* The LSA must be on the retrans-list of a neighbor. It means
+     the "lsa" is a copied one, and we have to decrement the
+     retransmission count of the original one (instead of "lsa"'s).
+     In order to find the original LSA, first we have to find
+     appropriate LSDB that have the original LSA. */
+  lsdb = ospf6_get_scoped_lsdb (lsa);
+
+  /* Find the original LSA of which the retrans_count should be decremented */
+  orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+                           lsa->header->adv_router, lsdb);
+  if (orig)
+    orig->retrans_count--;
+
+  assert (orig->retrans_count >= 0);
 }
 
 /* RFC2328 section 13.2 Installing LSAs in the database */
 void
-ospf6_install_lsa (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
+ospf6_install_lsa (struct ospf6_lsa *lsa)
 {
   struct ospf6_lsa *old;
 
@@ -202,185 +211,299 @@
   /* Remove the old instance from all neighbors' Link state
      retransmission list (RFC2328 13.2 last paragraph) */
   old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
-                           lsa->header->adv_router, lsdb);
+                           lsa->header->adv_router, lsa->lsdb);
   if (old)
     ospf6_flood_clear (old);
 
   /* actually install */
   gettimeofday (&lsa->installed, (struct timezone *) NULL);
-  ospf6_lsdb_add (lsa, lsdb);
+  ospf6_lsdb_add (lsa, lsa->lsdb);
 
   return;
 }
 
+/* RFC2740 section 3.5.2. Sending Link State Update packets */
 /* RFC2328 section 13.3 Next step in the flooding procedure */
 void
-ospf6_flood_lsa (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
+ospf6_flood_interface (struct ospf6_neighbor *from,
+                       struct ospf6_lsa *lsa, struct ospf6_interface *oi)
 {
-  struct ospf6 *scope_as = NULL;
-  struct ospf6_area *oa, *scope_area = NULL;
-  struct ospf6_interface *oi, *scope_linklocal = NULL;
+  listnode node;
   struct ospf6_neighbor *on;
-  list eligible_interfaces;
-  listnode i, j;
-  u_int16_t scope_type;
   struct ospf6_lsa *req;
   int retrans_added = 0;
 
-  scope_type = OSPF6_LSA_SCOPE (lsa->header->type);
-  switch (scope_type)
-    {
-      case OSPF6_LSA_SCOPE_AS:
-        scope_as = (struct ospf6 *) lsa->scope;
-        break;
-      case OSPF6_LSA_SCOPE_AREA:
-        scope_as = ((struct ospf6_area *) lsa->scope)->ospf6;
-        scope_area = (struct ospf6_area *) lsa->scope;
-        break;
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
-        scope_as = ((struct ospf6_interface *) lsa->scope)->area->ospf6;
-        scope_area = ((struct ospf6_interface *) lsa->scope)->area;
-        scope_linklocal = (struct ospf6_interface *) lsa->scope;
-        break;
-      default:
-        if (IS_OSPF6_DEBUG_LSA (SEND))
-          zlog_info ("Can't decide LSA scope");
-        return;
-    }
-
   if (IS_OSPF6_DEBUG_LSA (SEND))
-    zlog_info ("Flood %s", lsa->name);
+    zlog_info ("Flooding on %s: %s", oi->interface->name, lsa->name);
 
-  /* Collect eligible interfaces */
-  eligible_interfaces = list_new ();
-  for (i = listhead (scope_as->area_list); i; nextnode (i))
+  /* (1) For each neighbor */
+  for (node = listhead (oi->neighbor_list); node; nextnode (node))
     {
-      oa = (struct ospf6_area *) getdata (i);
-      if (scope_type != OSPF6_LSA_SCOPE_AS &&
-          oa != scope_area)
-        continue;
+      on = (struct ospf6_neighbor *) getdata (node);
 
-      for (j = listhead (oa->if_list); j; nextnode (j))
+      if (IS_OSPF6_DEBUG_LSA (SEND))
+        zlog_info ("To neighbor %s", on->name);
+
+      /* (a) if neighbor state < Exchange, examin next */
+      if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
         {
-          oi = (struct ospf6_interface *) getdata (j);
-          if (scope_type != OSPF6_LSA_SCOPE_AS &&
-              scope_type != OSPF6_LSA_SCOPE_AREA &&
-              oi != scope_linklocal)
-            continue;
-
-          listnode_add (eligible_interfaces, oi);
+          if (IS_OSPF6_DEBUG_LSA (SEND))
+            zlog_info ("Neighbor state less than ExChange, next neighbor");
+          continue;
         }
-    }
 
-  /* For each eligible interface: */
-  for (i = listhead (eligible_interfaces); i; nextnode (i))
-    {
-      oi = (struct ospf6_interface *) getdata (i);
-
-      /* (1) For each neighbor */
-      for (j = listhead (oi->neighbor_list); j; nextnode (j))
+      /* (b) if neighbor not yet Full, check request-list */
+      if (on->state != OSPF6_NEIGHBOR_FULL)
         {
-          on = (struct ospf6_neighbor *) getdata (j);
+          if (IS_OSPF6_DEBUG_LSA (SEND))
+            zlog_info ("Neighbor not yet Full");
 
-          /* (a) if neighbor state < Exchange, examin next */
-          if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
-            continue;
-
-          /* (b) if neighbor not yet Full, check request-list */
-          if (on->state != OSPF6_NEIGHBOR_FULL)
+          req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+                                   lsa->header->adv_router, on->request_list);
+          if (req == NULL)
             {
-              req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
-                                       lsa->header->adv_router,
-                                       on->request_list);
-              if (req)
+              if (IS_OSPF6_DEBUG_LSA (SEND))
+                zlog_info ("Not on request-list for this neighbor");
+              /* fall through */
+            }
+          else
+            {
+              /* If new LSA less recent, examin next neighbor */
+              if (ospf6_lsa_compare (lsa, req) > 0)
                 {
-                  /* If new LSA less recent, examin next neighbor */
-                  if (ospf6_lsa_compare (lsa, req) > 0)
-                    continue;
+                  if (IS_OSPF6_DEBUG_LSA (SEND))
+                    zlog_info ("Requesting is newer, next neighbor");
+                  continue;
+                }
 
-                  /* If the same instance, delete from request-list and
-                     examin next neighbor */
-                  if (ospf6_lsa_compare (lsa, req) == 0)
-                    {
-                      if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
-                        zlog_info ("Remove %s from request-list of %s: "
-                                   "the same instance", req->name, on->name);
-                      ospf6_lsdb_remove (req, on->request_list);
-                      continue;
-                    }
+              /* If the same instance, delete from request-list and
+                 examin next neighbor */
+              if (ospf6_lsa_compare (lsa, req) == 0)
+                {
+                  if (IS_OSPF6_DEBUG_LSA (SEND))
+                    zlog_info ("Requesting the same, remove it, next neighbor");
+                  ospf6_lsdb_remove (req, on->request_list);
+                  continue;
+                }
 
-                  /* If the new LSA is more recent, delete from
-                     request-list */
-                  if (ospf6_lsa_compare (lsa, req) < 0)
-                    {
-                      if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
-                        zlog_info ("Remove %s from request-list of %s: "
-                                   "newer instance", req->name, on->name);
-                      ospf6_lsdb_remove (req, on->request_list);
-                      /* fall through */
-                    }
+              /* If the new LSA is more recent, delete from request-list */
+              if (ospf6_lsa_compare (lsa, req) < 0)
+                {
+                  if (IS_OSPF6_DEBUG_LSA (SEND))
+                    zlog_info ("Received is newer, remove requesting");
+                  ospf6_lsdb_remove (req, on->request_list);
+                  /* fall through */
                 }
             }
-
-          /* (c) If the new LSA was received from this neighbor,
-             examin next neighbor */
-          if (from == on)
-            continue;
-
-          /* (d) add retrans-list, schedule retransmission */
-          if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
-            zlog_info ("  Add copy of %s to retrans-list of %s",
-                       lsa->name, on->name);
-          lsa->onretrans++;
-          ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
-          if (on->thread_send_lsupdate == NULL)
-            on->thread_send_lsupdate =
-              thread_add_event (master, ospf6_lsupdate_send_neighbor,
-                                on, on->ospf6_if->rxmt_interval);
-          retrans_added++;
         }
 
-      /* (2) examin next interface if not added to retrans-list */
-      if (retrans_added == 0)
-        continue;
-
-      /* (3) If the new LSA was received on this interface,
-         and it was from DR or BDR, examin next interface */
-      if (from && from->ospf6_if == oi &&
-          (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
-        continue;
-
-      /* (4) If the new LSA was received on this interface,
-         and the interface state is BDR, examin next interface */
-      if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
-        continue;
-
-      /* (5) flood the LSA out the interface. */
-      if (if_is_broadcast (oi->interface))
+      /* (c) If the new LSA was received from this neighbor,
+         examin next neighbor */
+      if (from == on)
         {
-          if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE))
-            zlog_info ("  Add copy of %s to lsupdate_list of %s",
-                       lsa->name, oi->interface->name);
-          ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
-          if (oi->thread_send_lsupdate == NULL)
-            oi->thread_send_lsupdate =
-              thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
+          if (IS_OSPF6_DEBUG_LSA (SEND))
+            zlog_info ("Received is from the neighbor, next neighbor");
+          continue;
         }
-      else
-        {
-          for (j = listhead (oi->neighbor_list); j; nextnode (j))
-            {
-              on = (struct ospf6_neighbor *) getdata (j);
-              THREAD_OFF (on->thread_send_lsupdate);
-              on->thread_send_lsupdate =
-                thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
-            }
-        }
+
+      /* (d) add retrans-list, schedule retransmission */
+      if (IS_OSPF6_DEBUG_LSA (SEND))
+        zlog_info ("Add retrans-list of this neighbor");
+      ospf6_increment_retrans_count (lsa);
+      ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
+      if (on->thread_send_lsupdate == NULL)
+        on->thread_send_lsupdate =
+          thread_add_event (master, ospf6_lsupdate_send_neighbor,
+                            on, on->ospf6_if->rxmt_interval);
+      retrans_added++;
     }
 
-  list_delete (eligible_interfaces);
+  /* (2) examin next interface if not added to retrans-list */
+  if (retrans_added == 0)
+    {
+      if (IS_OSPF6_DEBUG_LSA (SEND))
+        zlog_info ("No retransmission scheduled, next interface");
+      return;
+    }
+
+  /* (3) If the new LSA was received on this interface,
+     and it was from DR or BDR, examin next interface */
+  if (from && from->ospf6_if == oi &&
+      (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
+    {
+      if (IS_OSPF6_DEBUG_LSA (SEND))
+        zlog_info ("Received is from the I/F's DR or BDR, next interface");
+      return;
+    }
+
+  /* (4) If the new LSA was received on this interface,
+     and the interface state is BDR, examin next interface */
+  if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
+    {
+      if (IS_OSPF6_DEBUG_LSA (SEND))
+        zlog_info ("Received is from the I/F, itself BDR, next interface");
+      return;
+    }
+
+  /* (5) flood the LSA out the interface. */
+  if (IS_OSPF6_DEBUG_LSA (SEND))
+    zlog_info ("Schedule flooding for the interface");
+  if (if_is_broadcast (oi->interface))
+    {
+      ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
+      if (oi->thread_send_lsupdate == NULL)
+        oi->thread_send_lsupdate =
+          thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
+    }
+  else
+    {
+      /* reschedule retransmissions to all neighbors */
+      for (node = listhead (oi->neighbor_list); node; nextnode (node))
+        {
+          on = (struct ospf6_neighbor *) getdata (node);
+          THREAD_OFF (on->thread_send_lsupdate);
+          on->thread_send_lsupdate =
+            thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
+        }
+    }
 }
 
+void
+ospf6_flood_area (struct ospf6_neighbor *from,
+                  struct ospf6_lsa *lsa, struct ospf6_area *oa)
+{
+  listnode node;
+  struct ospf6_interface *oi;
+
+  for (node = listhead (oa->if_list); node; nextnode (node))
+    {
+      oi = OSPF6_INTERFACE (getdata (node));
+
+      if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
+          oi != OSPF6_INTERFACE (lsa->lsdb->data))
+        continue;
+
+#if 0
+      if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
+          ospf6_is_interface_virtual_link (oi))
+        continue;
+#endif/*0*/
+
+      ospf6_flood_interface (from, lsa, oi);
+    }
+}
+
+void
+ospf6_flood_process (struct ospf6_neighbor *from,
+                     struct ospf6_lsa *lsa, struct ospf6 *process)
+{
+  listnode node;
+  struct ospf6_area *oa;
+
+  for (node = listhead (process->area_list); node; nextnode (node))
+    {
+      oa = OSPF6_AREA (getdata (node));
+
+      if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
+          oa != OSPF6_AREA (lsa->lsdb->data))
+        continue;
+      if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
+          oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
+        continue;
+
+      if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
+          IS_AREA_STUB (oa))
+        continue;
+
+      ospf6_flood_area (from, lsa, oa);
+    }
+}
+
+void
+ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
+{
+  ospf6_flood_process (from, lsa, ospf6);
+}
+
+void
+ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi)
+{
+  listnode node;
+  struct ospf6_neighbor *on;
+  struct ospf6_lsa *rem;
+
+  for (node = listhead (oi->neighbor_list); node; nextnode (node))
+    {
+      on = OSPF6_NEIGHBOR (getdata (node));
+      rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
+                               lsa->header->adv_router, on->retrans_list);
+      if (rem && ! ospf6_lsa_compare (rem, lsa))
+        {
+          if (IS_OSPF6_DEBUG_LSA (DATABASE))
+            zlog_info ("Remove %s from retrans_list of %s",
+                       rem->name, on->name);
+          ospf6_decrement_retrans_count (rem);
+          ospf6_lsdb_remove (rem, on->retrans_list);
+        }
+    }
+}
+
+void
+ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa)
+{
+  listnode node;
+  struct ospf6_interface *oi;
+
+  for (node = listhead (oa->if_list); node; nextnode (node))
+    {
+      oi = OSPF6_INTERFACE (getdata (node));
+
+      if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
+          oi != OSPF6_INTERFACE (lsa->lsdb->data))
+        continue;
+
+#if 0
+      if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
+          ospf6_is_interface_virtual_link (oi))
+        continue;
+#endif/*0*/
+
+      ospf6_flood_clear_interface (lsa, oi);
+    }
+}
+
+void
+ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process)
+{
+  listnode node;
+  struct ospf6_area *oa;
+
+  for (node = listhead (process->area_list); node; nextnode (node))
+    {
+      oa = OSPF6_AREA (getdata (node));
+
+      if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
+          oa != OSPF6_AREA (lsa->lsdb->data))
+        continue;
+      if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
+          oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
+        continue;
+
+      if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
+          IS_AREA_STUB (oa))
+        continue;
+
+      ospf6_flood_clear_area (lsa, oa);
+    }
+}
+
+void
+ospf6_flood_clear (struct ospf6_lsa *lsa)
+{
+  ospf6_flood_clear_process (lsa, ospf6);
+}
+
+
 /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
 static void
 ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
@@ -396,7 +519,7 @@
   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
     {
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("  BDR, FloodBack, No acknowledgement.");
+        zlog_info ("No acknowledgement (BDR & FloodBack)");
       return;
     }
 
@@ -406,16 +529,11 @@
      otherwide do nothing. */
   if (ismore_recent < 0)
     {
-      if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("  BDR, Not FloodBack, MoreRecent, ");
       if (oi->drouter == from->router_id)
         {
           if (IS_OSPF6_DEBUG_LSA (RECV))
-            zlog_info ("       From DR, Delayed acknowledgement.");
+            zlog_info ("Delayed acknowledgement (BDR & MoreRecent & from DR)");
           /* Delayed acknowledgement */
-          if (IS_OSPF6_DEBUG_LSA (DATABASE))
-            zlog_info ("  Add copy of %s to lsack_list of %s",
-                       lsa->name, oi->interface->name);
           ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
           if (oi->thread_send_lsack == NULL)
             oi->thread_send_lsack =
@@ -424,7 +542,7 @@
       else
         {
           if (IS_OSPF6_DEBUG_LSA (RECV))
-            zlog_info ("       Not From DR, No acknowledgement.");
+            zlog_info ("No acknowledgement (BDR & MoreRecent & ! from DR)");
         }
       return;
     }
@@ -435,16 +553,11 @@
   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
       CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
     {
-      if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("  BDR, Duplicate, ImpliedAck, ");
       if (oi->drouter == from->router_id)
         {
           if (IS_OSPF6_DEBUG_LSA (RECV))
-            zlog_info ("       From DR, Delayed acknowledgement.");
+            zlog_info ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
           /* Delayed acknowledgement */
-          if (IS_OSPF6_DEBUG_LSA (DATABASE))
-            zlog_info ("  Add copy of %s to lsack_list of %s",
-                       lsa->name, oi->interface->name);
           ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
           if (oi->thread_send_lsack == NULL)
             oi->thread_send_lsack =
@@ -453,7 +566,7 @@
       else
         {
           if (IS_OSPF6_DEBUG_LSA (RECV))
-            zlog_info ("       Not From DR, No acknowledgement.");
+            zlog_info ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
         }
       return;
     }
@@ -464,10 +577,7 @@
       ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
     {
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("  BDR, Duplicate, Not ImpliedAck, Direct acknowledgement.");
-      if (IS_OSPF6_DEBUG_LSA (DATABASE))
-        zlog_info ("  Add copy of %s to lsack_list of %s",
-                   lsa->name, from->name);
+        zlog_info ("Direct acknowledgement (BDR & Duplicate)");
       ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
       if (from->thread_send_lsack == NULL)
         from->thread_send_lsack =
@@ -496,7 +606,7 @@
   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
     {
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("  AllOther, FloodBack, No acknowledgement.");
+        zlog_info ("No acknowledgement (AllOther & FloodBack)");
       return;
     }
 
@@ -505,11 +615,8 @@
   if (ismore_recent < 0)
     {
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("  AllOther, Not FloodBack, Delayed acknowledgement.");
+        zlog_info ("Delayed acknowledgement (AllOther & MoreRecent)");
       /* Delayed acknowledgement */
-      if (IS_OSPF6_DEBUG_LSA (DATABASE))
-        zlog_info ("  Add copy of %s to lsack_list of %s",
-                   lsa->name, oi->interface->name);
       ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
       if (oi->thread_send_lsack == NULL)
         oi->thread_send_lsack =
@@ -523,7 +630,7 @@
       CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
     {
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("  AllOther, Duplicate, ImpliedAck, No acknowledgement.");
+        zlog_info ("No acknowledgement (AllOther & Duplicate & ImpliedAck)");
       return;
     }
 
@@ -533,10 +640,7 @@
       ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
     {
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("  AllOther, Duplicate, Not ImpliedAck, Direct acknowledgement.");
-      if (IS_OSPF6_DEBUG_LSA (DATABASE))
-        zlog_info ("  Add copy of %s to lsack_list of %s",
-                   lsa->name, from->name);
+        zlog_info ("Direct acknowledgement (AllOther & Duplicate)");
       ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
       if (from->thread_send_lsack == NULL)
         from->thread_send_lsack =
@@ -571,106 +675,55 @@
    is in states Exchange or Loading
    returns 1 if match this case, else returns 0 */
 static int
-ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa,
-                          struct ospf6_neighbor *from)
+ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
 {
-  struct ospf6_lsdb *lsdb = NULL;
   struct ospf6_neighbor *on;
-  struct ospf6_interface *oi, *ospf6_if = NULL;
-  struct ospf6_area *oa, *area = NULL;
-  struct ospf6 *ospf6 = NULL;
-  u_int16_t scope_type;
-  list scoped_interfaces;
-  listnode i, j;
+  struct ospf6_interface *oi;
+  struct ospf6_area *oa;
+  struct ospf6 *process = NULL;
+  listnode i, j, k;
   int count = 0;
 
   if (! OSPF6_LSA_IS_MAXAGE (lsa))
     return 0;
 
-  lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
-  if (lsdb == NULL)
-    {
-      zlog_info ("Can't decide scoped LSDB");
-      return 0;
-    }
-
   if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
-                         lsa->header->adv_router, lsdb))
+                         lsa->header->adv_router, lsa->lsdb))
     return 0;
 
-  scoped_interfaces = list_new ();
-  scope_type = OSPF6_LSA_SCOPE (lsa->header->type);
-
-  if (scope_type == OSPF6_LSA_SCOPE_LINKLOCAL)
+  process = from->ospf6_if->area->ospf6;
+  for (i = listhead (process->area_list); i; nextnode (i))
     {
-      ospf6_if = (struct ospf6_interface *) lsa->scope;
-      area = ospf6_if->area;
-      ospf6 = area->ospf6;
-    }
-  else if (scope_type == OSPF6_LSA_SCOPE_AREA)
-    {
-      area = (struct ospf6_area *) lsa->scope;
-      ospf6 = area->ospf6;
-    }
-  else if (scope_type == OSPF6_LSA_SCOPE_AS)
-    {
-      ospf6 = (struct ospf6 *) lsa->scope;
-    }
-  else
-    {
-      zlog_info ("Can't decide LSA scope");
-      return 0;
-    }
-
-  /* Collect eligible interfaces */
-  for (i = listhead (ospf6->area_list); i; nextnode (i))
-    {
-      oa = (struct ospf6_area *) getdata (i);
-      if (scope_type != OSPF6_LSA_SCOPE_AS && oa != area)
-        continue;
-
+      oa = OSPF6_AREA (getdata (i));
       for (j = listhead (oa->if_list); j; nextnode (j))
         {
-          oi = (struct ospf6_interface *) getdata (j);
-          if (scope_type != OSPF6_LSA_SCOPE_AS &&
-              scope_type != OSPF6_LSA_SCOPE_AREA && oi != ospf6_if)
-            continue;
-
-          listnode_add (scoped_interfaces, oi);
+          oi = OSPF6_INTERFACE (getdata (j));
+          for (k = listhead (oi->neighbor_list); k; nextnode (k))
+            {
+              on = OSPF6_NEIGHBOR (getdata (k));
+              if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
+                  on->state == OSPF6_NEIGHBOR_LOADING)
+                count++;
+            }
         }
     }
 
-  for (i = listhead (scoped_interfaces); i; nextnode (i))
-    {
-      oi = (struct ospf6_interface *) getdata (i);
-      for (j = listhead (oi->neighbor_list); j; nextnode (j))
-        {
-          on = (struct ospf6_neighbor *) getdata (j);
-          if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
-              on->state == OSPF6_NEIGHBOR_LOADING)
-            count ++;
-        }
-    }
-
-  list_delete (scoped_interfaces);
-
   if (count == 0)
     return 1;
-
   return 0;
 }
 
 /* RFC2328 section 13 The Flooding Procedure */
 void
-ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header,
-                   struct ospf6_neighbor *from)
+ospf6_receive_lsa (struct ospf6_neighbor *from,
+                   struct ospf6_lsa_header *lsa_header)
 {
   struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
   int ismore_recent;
   unsigned short cksum;
-  struct ospf6_lsdb *lsdb = NULL;
 
   ismore_recent = 1;
+  assert (from);
 
   /* make lsa structure for received lsa */
   new = ospf6_lsa_create (lsa_header);
@@ -681,30 +734,45 @@
       ospf6_lsa_header_print (new);
     }
 
-  new->scope = ospf6_get_lsa_scope (new->header->type, from);
-  if (new->scope == NULL)
-    {
-      zlog_warn ("Can't decide LSA scope, ignore");
-      ospf6_lsa_delete (new);
-      return;
-    }
-
   /* (1) LSA Checksum */
   cksum = ntohs (new->header->checksum);
   if (ntohs (ospf6_lsa_checksum (new->header)) != cksum)
     {
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("Wrong LSA Checksum");
+        zlog_info ("Wrong LSA Checksum, discard");
       ospf6_lsa_delete (new);
       return;
     }
 
-  /* (3) Ebit Missmatch: AS-External-LSA */
-  if (ntohs (new->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
-      ospf6_area_is_stub (from->ospf6_if->area))
+  /* (2) Examine the LSA's LS type. 
+     RFC2470 3.5.1. Receiving Link State Update packets  */
+  if (IS_AREA_STUB (from->ospf6_if->area) &&
+      OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS)
     {
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("AS-External-LSA in stub area");
+        zlog_info ("AS-External-LSA (or AS-scope LSA) in stub area, discard");
+      ospf6_lsa_delete (new);
+      return;
+    }
+
+  /* (3) LSA which have reserved scope is discarded
+     RFC2470 3.5.1. Receiving Link State Update packets  */
+  /* Flooding scope check. LSAs with unknown scope are discarded here.
+     Set appropriate LSDB for the LSA */
+  switch (OSPF6_LSA_SCOPE (new->header->type))
+    {
+    case OSPF6_SCOPE_LINKLOCAL:
+      new->lsdb = from->ospf6_if->lsdb;
+      break;
+    case OSPF6_SCOPE_AREA:
+      new->lsdb = from->ospf6_if->area->lsdb;
+      break;
+    case OSPF6_SCOPE_AS:
+      new->lsdb = from->ospf6_if->area->ospf6->lsdb;
+      break;
+    default:
+      if (IS_OSPF6_DEBUG_LSA (RECV))
+        zlog_info ("LSA has reserved scope, discard");
       ospf6_lsa_delete (new);
       return;
     }
@@ -715,41 +783,30 @@
     {
       /* log */
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("Drop MaxAge LSA with Direct acknowledgement.");
+        zlog_info ("Drop MaxAge LSA with direct acknowledgement.");
 
       /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
-      if (IS_OSPF6_DEBUG_LSA (DATABASE))
-        zlog_info ("  Add %s to lsack_list of %s",
-                   new->name, from->name);
-      ospf6_lsdb_add (new, from->lsack_list);
+      ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
       if (from->thread_send_lsack == NULL)
         from->thread_send_lsack =
           thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
 
       /* b) Discard */
-      /* "new" LSA will be discarded just after the LSAck sent */
+      ospf6_lsa_delete (new);
       return;
     }
 
   /* (5) */
   /* lookup the same database copy in lsdb */
-  lsdb = ospf6_get_scoped_lsdb (new->header->type, new->scope);
-  if (lsdb == NULL)
-    {
-      zlog_warn ("Can't decide scoped LSDB, ignore");
-      ospf6_lsa_delete (new);
-      return;
-    }
-
   old = ospf6_lsdb_lookup (new->header->type, new->header->id,
-                           new->header->adv_router, lsdb);
+                           new->header->adv_router, new->lsdb);
   if (old)
     {
       ismore_recent = ospf6_lsa_compare (new, old);
       if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum))
         {
           if (IS_OSPF6_DEBUG_LSA (RECV))
-            zlog_info ("Duplicated LSA");
+            zlog_info ("Received is duplicated LSA");
           SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE);
         }
     }
@@ -769,35 +826,43 @@
           if (res.tv_sec < MIN_LS_ARRIVAL)
             {
               if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (TIMER))
-                zlog_info ("LSA can't be updated within MinLSArrival");
+                zlog_info ("LSA can't be updated within MinLSArrival, discard");
               ospf6_lsa_delete (new);
               return;   /* examin next lsa */
             }
         }
 
+      if (IS_OSPF6_DEBUG_LSA (RECV))
+        zlog_info ("Flood, Install, Possibly acknowledge the received LSA");
+
       /* (b) immediately flood and (c) remove from all retrans-list */
-      ospf6_flood_lsa (new, from);
+      ospf6_flood (from, new);
+
+      /* (c) Remove the current database copy from all neighbors' Link
+             state retransmission lists. */
+      /* XXX, flood_clear ? */
 
       /* (d), installing lsdb, which may cause routing
               table calculation (replacing database copy) */
-      ospf6_install_lsa (new, lsdb);
+      ospf6_install_lsa (new);
 
       /* (e) possibly acknowledge */
       ospf6_acknowledge_lsa (new, ismore_recent, from);
 
-      /* (f) */
-      /* Self Originated LSA, section 13.4 */
-      if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id
-          && (! old || ismore_recent < 0))
+      /* (f) Self Originated LSA, section 13.4 */
+      if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id)
         {
-          /* We have to make a new instance of the LSA
+          /* Self-originated LSA (newer than ours) is received from
+             another router. We have to make a new instance of the LSA
              or have to flush this LSA. */
           if (IS_OSPF6_DEBUG_LSA (RECV))
-            zlog_info ("New instance of the self-originated LSA");
-
-          SET_FLAG (new->flag, OSPF6_LSA_REFRESH);
-          ospf6_lsa_re_originate (new);
+            {
+              zlog_info ("Newer instance of the self-originated LSA");
+              zlog_info ("Schedule reorigination");
+            }
+          new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0);
         }
+
       return;
     }
 
@@ -809,7 +874,10 @@
       assert (old);
 
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("LSA is not newer and on request-list of sending neighbor");
+        {
+          zlog_info ("Received is not newer, on the neighbor's request-list");
+          zlog_info ("BadLSReq, discard the received LSA");
+        }
 
       /* BadLSReq */
       thread_add_event (master, bad_lsreq, from, 0);
@@ -822,7 +890,7 @@
   if (ismore_recent == 0)
     {
       if (IS_OSPF6_DEBUG_LSA (RECV))
-        zlog_info ("The same instance as database copy");
+        zlog_info ("The same instance as database copy (neither recent)");
 
       /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */
       rem = ospf6_lsdb_lookup (new->header->type, new->header->id,
@@ -830,15 +898,18 @@
       if (rem)
         {
           if (IS_OSPF6_DEBUG_LSA (RECV))
-            zlog_info ("Treat as an Implied acknowledgement");
+            {
+              zlog_info ("It is on the neighbor's retrans-list.");
+              zlog_info ("Treat as an Implied acknowledgement");
+            }
           SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK);
-          if (IS_OSPF6_DEBUG_LSA (DATABASE))
-            zlog_info ("Remove %s from retrans_list of %s",
-                       rem->name, from->name);
-          ospf6_decrement_onretrans (rem);
+          ospf6_decrement_retrans_count (rem);
           ospf6_lsdb_remove (rem, from->retrans_list);
         }
 
+      if (IS_OSPF6_DEBUG_LSA (RECV))
+        zlog_info ("Possibly acknowledge and then discard");
+
       /* (b) possibly acknowledge */
       ospf6_acknowledge_lsa (new, ismore_recent, from);
 
@@ -856,7 +927,10 @@
           old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
         {
           if (IS_OSPF6_DEBUG_LSA (RECV))
-            zlog_info ("Database copy is in Seqnumber Wrapping");
+            {
+              zlog_info ("The LSA is in Seqnumber Wrapping");
+              zlog_info ("MaxAge & MaxSeqNum, discard");
+            }
           ospf6_lsa_delete (new);
           return;
         }
@@ -864,13 +938,13 @@
       /* Otherwise, Send database copy of this LSA to this neighbor */
         {
           if (IS_OSPF6_DEBUG_LSA (RECV))
-            zlog_info ("Database is more recent, send back directly");
+            {
+              zlog_info ("Database copy is more recent.");
+              zlog_info ("Send back directly and then discard");
+            }
 
           /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
 
-          if (IS_OSPF6_DEBUG_LSA (DATABASE))
-            zlog_info ("  Add copy of %s to lsupdate_list of %s",
-                       old->name, from->name);
           ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list);
           if (from->thread_send_lsupdate == NULL)
             from->thread_send_lsupdate =
diff --git a/ospf6d/ospf6_flood.h b/ospf6d/ospf6_flood.h
index f639f63..e894e56 100644
--- a/ospf6d/ospf6_flood.h
+++ b/ospf6d/ospf6_flood.h
@@ -23,15 +23,31 @@
 #define OSPF6_FLOOD_H
 
 /* Function Prototypes */
-void *ospf6_get_lsa_scope (u_int16_t type, struct ospf6_neighbor *from);
-struct ospf6_lsdb *ospf6_get_scoped_lsdb (u_int16_t type, void *scope);
+struct ospf6_lsdb *ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa);
+struct ospf6_lsdb *ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa);
 
-void ospf6_decrement_onretrans (struct ospf6_lsa *lsa);
+/* origination & purging */
+void ospf6_lsa_originate (struct ospf6_lsa *lsa);
+void ospf6_lsa_originate_process (struct ospf6_lsa *lsa,
+                                  struct ospf6 *process);
+void ospf6_lsa_originate_area (struct ospf6_lsa *lsa,
+                               struct ospf6_area *oa);
+void ospf6_lsa_originate_interface (struct ospf6_lsa *lsa,
+                                    struct ospf6_interface *oi);
+void ospf6_lsa_purge (struct ospf6_lsa *lsa);
+
+/* access method to retrans_count */
+void ospf6_increment_retrans_count (struct ospf6_lsa *lsa);
+void ospf6_decrement_retrans_count (struct ospf6_lsa *lsa);
+
+/* flooding & clear flooding */
 void ospf6_flood_clear (struct ospf6_lsa *lsa);
-void ospf6_flood_lsa (struct ospf6_lsa *lsa, struct ospf6_neighbor *from);
-void ospf6_install_lsa (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
-void ospf6_receive_lsa (struct ospf6_lsa_header *header,
-                        struct ospf6_neighbor *from);
+void ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa);
+
+/* receive & install */
+void ospf6_receive_lsa (struct ospf6_neighbor *from,
+                        struct ospf6_lsa_header *header);
+void ospf6_install_lsa (struct ospf6_lsa *lsa);
 
 #endif /* OSPF6_FLOOD_H */
 
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index ccacc23..56ecacc 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -89,21 +89,18 @@
 void
 ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
 {
-  struct ospf6_interface *oi;
-
-  oi = (struct ospf6_interface *) lsa->scope;
   switch (ntohs (lsa->header->type))
     {
       case OSPF6_LSTYPE_LINK:
-        if (oi->state == OSPF6_INTERFACE_DR)
-          OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
-        ospf6_spf_schedule (oi->area);
+        if (OSPF6_INTERFACE (lsa->lsdb->data)->state == OSPF6_INTERFACE_DR)
+          OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (OSPF6_INTERFACE (lsa->lsdb->data));
+        ospf6_spf_schedule (OSPF6_INTERFACE (lsa->lsdb->data)->area);
         break;
 
       default:
         if (IS_OSPF6_DEBUG_LSA (RECV))
           zlog_info ("Unknown LSA in Interface %s's lsdb",
-                     oi->interface->name);
+                     OSPF6_INTERFACE (lsa->lsdb->data)->interface->name);
         break;
     }
 }
@@ -151,11 +148,12 @@
       oi->ifmtu = iobuflen;
     }
 
-  oi->lsupdate_list = ospf6_lsdb_create ();
-  oi->lsack_list = ospf6_lsdb_create ();
-  oi->lsdb = ospf6_lsdb_create ();
+  oi->lsupdate_list = ospf6_lsdb_create (oi);
+  oi->lsack_list = ospf6_lsdb_create (oi);
+  oi->lsdb = ospf6_lsdb_create (oi);
   oi->lsdb->hook_add = ospf6_interface_lsdb_hook;
   oi->lsdb->hook_remove = ospf6_interface_lsdb_hook;
+  oi->lsdb_self = ospf6_lsdb_create (oi);
 
   oi->route_connected = ospf6_route_table_create ();
 
@@ -188,6 +186,8 @@
   ospf6_lsdb_remove_all (oi->lsack_list);
 
   ospf6_lsdb_delete (oi->lsdb);
+  ospf6_lsdb_delete (oi->lsdb_self);
+
   ospf6_lsdb_delete (oi->lsupdate_list);
   ospf6_lsdb_delete (oi->lsack_list);
 
@@ -428,7 +428,14 @@
     ospf6_join_alldrouters (oi->interface->ifindex);
 
   OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
-  if (prev_state == OSPF6_INTERFACE_DR || next_state == OSPF6_INTERFACE_DR)
+  if (next_state == OSPF6_INTERFACE_DOWN)
+    {
+      OSPF6_NETWORK_LSA_EXECUTE (oi);
+      OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT (oi);
+      OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
+    }
+  else if (prev_state == OSPF6_INTERFACE_DR ||
+           next_state == OSPF6_INTERFACE_DR)
     {
       OSPF6_NETWORK_LSA_SCHEDULE (oi);
       OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index 48b56fc..be3007d 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -84,6 +84,7 @@
 
   /* Linklocal LSA Database: includes Link-LSA */
   struct ospf6_lsdb *lsdb;
+  struct ospf6_lsdb *lsdb_self;
 
   struct ospf6_lsdb *lsupdate_list;
   struct ospf6_lsdb *lsack_list;
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 72e2bde..74a8964 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -43,6 +43,8 @@
 #include "ospf6_neighbor.h"
 #include "ospf6_intra.h"
 #include "ospf6_asbr.h"
+#include "ospf6_abr.h"
+#include "ospf6_flood.h"
 #include "ospf6d.h"
 
 /******************************/
@@ -97,9 +99,11 @@
   return 0;
 }
 
-void
-ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force)
+int
+ospf6_router_lsa_originate (struct thread *thread)
 {
+  struct ospf6_area *oa;
+
   char buffer [OSPF6_MAX_LSASIZE];
   struct ospf6_lsa_header *lsa_header;
   struct ospf6_lsa *lsa;
@@ -114,6 +118,9 @@
   u_int32_t router;
   int count;
 
+  oa = (struct ospf6_area *) THREAD_ARG (thread);
+  oa->thread_router_lsa = NULL;
+
   if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
     zlog_info ("Originate Router-LSA for Area %s", oa->name);
 
@@ -129,7 +136,10 @@
   OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
   OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
 
-  UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
+  if (ospf6_is_router_abr (ospf6))
+    SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
+  else
+    UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
   if (ospf6_asbr_is_asbr (ospf6))
     SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
   else
@@ -171,7 +181,7 @@
             {
               if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
                 zlog_info ("Size limit setting for Router-LSA too short");
-              return;
+              return 0;
             }
 
           /* Fill LSA Header */
@@ -189,12 +199,9 @@
 
           /* create LSA */
           lsa = ospf6_lsa_create (lsa_header);
-          lsa->scope = oa;
-          if (force)
-            SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
 
           /* Originate */
-          ospf6_lsa_originate (lsa);
+          ospf6_lsa_originate_area (lsa, oa);
 
           /* Reset setting for consecutive origination */
           memset ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa),
@@ -277,15 +284,17 @@
 
       /* create LSA */
       lsa = ospf6_lsa_create (lsa_header);
-      lsa->scope = oa;
-      if (force)
-        SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
 
       /* Originate */
-      ospf6_lsa_originate (lsa);
+      ospf6_lsa_originate_area (lsa, oa);
 
       link_state_id ++;
     }
+  else
+    {
+      if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+        zlog_info ("Nothing to describe in Router-LSA, suppress");
+    }
 
   /* Do premature-aging of rest, undesired Router-LSAs */
   type = ntohs (OSPF6_LSTYPE_ROUTER);
@@ -295,36 +304,12 @@
     {
       if (ntohl (lsa->header->id) < link_state_id)
         continue;
-      ospf6_lsa_premature_aging (lsa);
+      ospf6_lsa_purge (lsa);
     }
-}
-
-int
-ospf6_router_lsa_originate (struct thread *thread)
-{
-  struct ospf6_area *oa;
-  int force = 0;
-
-  oa = (struct ospf6_area *) THREAD_ARG (thread);
-  oa->thread_router_lsa = NULL;
-  ospf6_router_lsa_originate_sub (oa, force);
 
   return 0;
 }
 
-int
-ospf6_router_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
-  struct ospf6_area *oa;
-  int force = 1;
-
-  oa = (struct ospf6_area *) lsa->scope;
-  ospf6_router_lsa_originate_sub (oa, force);
-
-  return 0;
-}
-
-
 /*******************************/
 /* RFC2740 3.4.3.2 Network-LSA */
 /*******************************/
@@ -355,9 +340,11 @@
   return 0;
 }
 
-void
-ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force)
+int
+ospf6_network_lsa_originate (struct thread *thread)
 {
+  struct ospf6_interface *oi;
+
   char buffer [OSPF6_MAX_LSASIZE];
   struct ospf6_lsa_header *lsa_header;
 
@@ -370,15 +357,13 @@
   listnode i;
   u_int16_t type;
 
-  /* If self-originated Network-LSA for currently unenabled I/F
-     (but was once enabled, so other routers send it to this router),
-     we can't find oi->area for ospf6_lsdb_lookup (), and so can't
-     do premature aging of the Network-LSA. Just let the LSA flow
-     in network (other routers LSDB) for maximum duration of
-     MaxAge. The contents of this router's Router-LSA will preclude
-     the stale Network-LSA to be involved in routing calculation. */
-  if (oi->area == NULL)
-    return;
+  oi = (struct ospf6_interface *) THREAD_ARG (thread);
+  oi->thread_network_lsa = NULL;
+
+  /* The interface must be enabled until here. A Network-LSA of a
+     disabled interface (but was once enabled) should be flushed
+     by ospf6_lsa_refresh (), and does not come here. */
+  assert (oi->area);
 
   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
                            htonl (oi->interface->ifindex),
@@ -388,8 +373,8 @@
   if (oi->state != OSPF6_INTERFACE_DR)
     {
       if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+        ospf6_lsa_purge (old);
+      return 0;
     }
 
   if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -408,8 +393,8 @@
       if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
         zlog_info ("Interface stub, ignore");
       if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+        ospf6_lsa_purge (old);
+      return 0;
     }
 
   /* prepare buffer */
@@ -466,35 +451,9 @@
 
   /* create LSA */
   lsa = ospf6_lsa_create (lsa_header);
-  lsa->scope = oi->area;
-  if (force)
-    SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
 
   /* Originate */
-  ospf6_lsa_originate (lsa);
-}
-
-int
-ospf6_network_lsa_originate (struct thread *thread)
-{
-  struct ospf6_interface *oi;
-  int force = 0;
-
-  oi = (struct ospf6_interface *) THREAD_ARG (thread);
-  oi->thread_network_lsa = NULL;
-  ospf6_network_lsa_originate_sub (oi, force);
-
-  return 0;
-}
-
-int
-ospf6_network_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
-  struct ospf6_interface *oi;
-  int force = 1;
-
-  oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id));
-  ospf6_network_lsa_originate_sub (oi, force);
+  ospf6_lsa_originate_area (lsa, oi->area);
 
   return 0;
 }
@@ -558,9 +517,11 @@
   return 0;
 }
 
-void
-ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force)
+int
+ospf6_link_lsa_originate (struct thread *thread)
 {
+  struct ospf6_interface *oi;
+
   char buffer[OSPF6_MAX_LSASIZE];
   struct ospf6_lsa_header *lsa_header;
   struct ospf6_lsa *old, *lsa;
@@ -569,8 +530,10 @@
   struct ospf6_route *route;
   struct ospf6_prefix *op;
 
-  if (oi->area == NULL)
-    return;
+  oi = (struct ospf6_interface *) THREAD_ARG (thread);
+  oi->thread_link_lsa = NULL;
+
+  assert (oi->area);
 
   /* find previous LSA */
   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
@@ -580,8 +543,8 @@
   if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
     {
       if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+        ospf6_lsa_purge (old);
+      return 0;
     }
 
   if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -594,8 +557,8 @@
         zlog_info ("No Linklocal address on %s, defer originating",
                    oi->interface->name);
       if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+        ospf6_lsa_purge (old);
+      return 0;
     }
 
   /* prepare buffer */
@@ -641,35 +604,9 @@
 
   /* create LSA */
   lsa = ospf6_lsa_create (lsa_header);
-  lsa->scope = oi;
-  if (force)
-    SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
 
   /* Originate */
-  ospf6_lsa_originate (lsa);
-}
-
-int
-ospf6_link_lsa_originate (struct thread *thread)
-{
-  struct ospf6_interface *oi;
-  int force = 0;
-
-  oi = (struct ospf6_interface *) THREAD_ARG (thread);
-  oi->thread_link_lsa = NULL;
-  ospf6_link_lsa_originate_sub (oi, force);
-
-  return 0;
-}
-
-int
-ospf6_link_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
-  struct ospf6_interface *oi;
-  int force = 1;
-
-  oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id));
-  ospf6_link_lsa_originate_sub (oi, force);
+  ospf6_lsa_originate_interface (lsa, oi);
 
   return 0;
 }
@@ -736,10 +673,11 @@
   return 0;
 }
 
-void
-ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa,
-                                           int force)
+int
+ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
 {
+  struct ospf6_area *oa;
+
   char buffer[OSPF6_MAX_LSASIZE];
   struct ospf6_lsa_header *lsa_header;
   struct ospf6_lsa *old, *lsa;
@@ -755,15 +693,18 @@
   char buf[BUFSIZ];
   struct ospf6_route_table *route_advertise;
 
+  oa = (struct ospf6_area *) THREAD_ARG (thread);
+  oa->thread_intra_prefix_lsa = NULL;
+
   /* find previous LSA */
   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
                            htonl (0), oa->ospf6->router_id, oa->lsdb);
 
-  if (CHECK_FLAG (oa->flag, OSPF6_AREA_DISABLE))
+  if (! IS_AREA_ENABLED (oa))
     {
       if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+        ospf6_lsa_purge (old);
+      return 0;
     }
 
   if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -830,9 +771,9 @@
   if (route_advertise->count == 0)
     {
       if (old)
-        ospf6_lsa_premature_aging (old);
+        ospf6_lsa_purge (old);
       ospf6_route_table_delete (route_advertise);
-      return;
+      return 0;
     }
 
   /* put prefixes to advertise */
@@ -857,7 +798,7 @@
     {
       if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
         zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
-      return;
+      return 0;
     }
 
   intra_prefix_lsa->prefix_num = htons (prefix_num);
@@ -877,18 +818,19 @@
 
   /* create LSA */
   lsa = ospf6_lsa_create (lsa_header);
-  lsa->scope = oa;
-  if (force)
-    SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
 
   /* Originate */
-  ospf6_lsa_originate (lsa);
+  ospf6_lsa_originate_area (lsa, oa);
+
+  return 0;
 }
 
-void
-ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
-                                              int force)
+
+int
+ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
 {
+  struct ospf6_interface *oi;
+
   char buffer[OSPF6_MAX_LSASIZE];
   struct ospf6_lsa_header *lsa_header;
   struct ospf6_lsa *old, *lsa;
@@ -906,8 +848,10 @@
   u_int16_t type;
   char buf[BUFSIZ];
 
-  if (oi->area == NULL)
-    return;
+  oi = (struct ospf6_interface *) THREAD_ARG (thread);
+  oi->thread_intra_prefix_lsa = NULL;
+
+  assert (oi->area);
 
   /* find previous LSA */
   old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
@@ -917,8 +861,8 @@
   if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
     {
       if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+        ospf6_lsa_purge (old);
+      return 0;
     }
 
   if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
@@ -941,8 +885,8 @@
       if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
         zlog_info ("  Interface is not DR");
       if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+        ospf6_lsa_purge (old);
+      return 0;
     }
 
   full_count = 0;
@@ -957,8 +901,8 @@
       if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
         zlog_info ("  Interface is stub");
       if (old)
-        ospf6_lsa_premature_aging (old);
-      return;
+        ospf6_lsa_purge (old);
+      return 0;
     }
 
   /* connected prefix to advertise */
@@ -1053,7 +997,7 @@
     {
       if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
         zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
-      return;
+      return 0;
     }
 
   intra_prefix_lsa->prefix_num = htons (prefix_num);
@@ -1073,69 +1017,9 @@
 
   /* create LSA */
   lsa = ospf6_lsa_create (lsa_header);
-  lsa->scope = oi->area;
-  if (force)
-    SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
 
   /* Originate */
-  ospf6_lsa_originate (lsa);
-}
-
-int
-ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
-{
-  struct ospf6_area *oa;
-  int force = 0;
-
-  oa = (struct ospf6_area *) THREAD_ARG (thread);
-  oa->thread_intra_prefix_lsa = NULL;
-  ospf6_intra_prefix_lsa_originate_stub_sub (oa, force);
-
-  return 0;
-}
-
-int
-ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
-{
-  struct ospf6_interface *oi;
-  int force = 0;
-
-  oi = (struct ospf6_interface *) THREAD_ARG (thread);
-  oi->thread_intra_prefix_lsa = NULL;
-  ospf6_intra_prefix_lsa_originate_transit_sub (oi, force);
-
-  return 0;
-}
-
-int
-ospf6_intra_prefix_lsa_reoriginate (struct ospf6_lsa *lsa)
-{
-  struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
-  u_int16_t type;
-  u_int32_t id;
-  struct ospf6_area *oa;
-  struct ospf6_interface *oi;
-  int force = 1;
-
-  intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
-    ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
-  type = ntohs (intra_prefix_lsa->ref_type);
-  id = ntohl (intra_prefix_lsa->ref_id);
-
-  if (type == OSPF6_LSTYPE_ROUTER && id == 0)
-    {
-      oa = (struct ospf6_area *) lsa->scope;
-      ospf6_intra_prefix_lsa_originate_stub_sub (oa, force);
-    }
-  else if (type == OSPF6_LSTYPE_NETWORK && id != 0)
-    {
-      if (intra_prefix_lsa->ref_id != lsa->header->id)
-        ospf6_lsa_premature_aging (lsa);
-      oi = ospf6_interface_lookup_by_ifindex (id);
-      ospf6_intra_prefix_lsa_originate_transit_sub (oi, force);
-    }
-  else
-    ospf6_lsa_premature_aging (lsa);
+  ospf6_lsa_originate_area (lsa, oi->area);
 
   return 0;
 }
@@ -1155,7 +1039,8 @@
   if (IS_OSPF6_DEBUG_ROUTE (INTRA))
     zlog_info ("%s found", lsa->name);
 
-  oa = (struct ospf6_area *) lsa->scope;
+  oa = OSPF6_AREA (lsa->lsdb->data);
+
   intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
     OSPF6_LSA_HEADER_END (lsa->header);
   if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
@@ -1244,7 +1129,8 @@
   if (IS_OSPF6_DEBUG_ROUTE (INTRA))
     zlog_info ("%s disappearing", lsa->name);
 
-  oa = (struct ospf6_area *) lsa->scope;
+  oa = OSPF6_AREA (lsa->lsdb->data);
+
   intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
     OSPF6_LSA_HEADER_END (lsa->header);
 
@@ -1355,21 +1241,22 @@
 }
 
 void
-ospf6_intra_asbr_calculation (struct ospf6_area *oa)
+ospf6_intra_brouter_calculation (struct ospf6_area *oa)
 {
   struct ospf6_route *lsentry, *copy;
   void (*hook_add) (struct ospf6_route *) = NULL;
   void (*hook_remove) (struct ospf6_route *) = NULL;
 
-  if (IS_OSPF6_DEBUG_ASBR)
-    zlog_info ("Intra-area ASBR calculation for area %s", oa->name);
+  if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+    zlog_info ("Border-router calculation for area %s", oa->name);
 
-  hook_add = oa->ospf6->asbr_table->hook_add;
-  hook_remove = oa->ospf6->asbr_table->hook_remove;
-  oa->ospf6->asbr_table->hook_add = NULL;
-  oa->ospf6->asbr_table->hook_remove = NULL;
+  hook_add = oa->ospf6->brouter_table->hook_add;
+  hook_remove = oa->ospf6->brouter_table->hook_remove;
+  oa->ospf6->brouter_table->hook_add = NULL;
+  oa->ospf6->brouter_table->hook_remove = NULL;
 
-  for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry;
+  /* withdraw the previous router entries for the area */
+  for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry;
        lsentry = ospf6_route_next (lsentry))
     {
       if (lsentry->path.area_id != oa->area_id)
@@ -1384,20 +1271,21 @@
         continue;
       if (ospf6_linkstate_prefix_id (&lsentry->prefix) != htonl (0))
         continue;
-      if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E))
+      if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E) &&
+          ! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_B))
         continue;
 
       copy = ospf6_route_copy (lsentry);
       copy->type = OSPF6_DEST_TYPE_ROUTER;
       copy->prefix.family = AF_INET;
       copy->prefix.prefixlen = 32;
-      ospf6_route_add (copy, oa->ospf6->asbr_table);
+      ospf6_route_add (copy, oa->ospf6->brouter_table);
     }
 
-  oa->ospf6->asbr_table->hook_add = hook_add;
-  oa->ospf6->asbr_table->hook_remove = hook_remove;
+  oa->ospf6->brouter_table->hook_add = hook_add;
+  oa->ospf6->brouter_table->hook_remove = hook_remove;
 
-  for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry;
+  for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry;
        lsentry = ospf6_route_next (lsentry))
     {
       if (lsentry->path.area_id != oa->area_id)
@@ -1411,7 +1299,7 @@
         }
 
       if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE))
-        ospf6_route_remove (lsentry, oa->ospf6->asbr_table);
+        ospf6_route_remove (lsentry, oa->ospf6->brouter_table);
       else if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD) ||
                CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_CHANGE))
         {
@@ -1422,27 +1310,45 @@
       lsentry->flag = 0;
     }
 
-  if (IS_OSPF6_DEBUG_ASBR)
-    zlog_info ("Intra-area ASBR calculation for area %s: Done", oa->name);
+  if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+    zlog_info ("Border-router calculation for area %s: Done", oa->name);
 }
 
+struct ospf6_lsa_handler router_handler =
+{
+  OSPF6_LSTYPE_ROUTER,
+  "Router",
+  ospf6_router_lsa_show
+};
+
+struct ospf6_lsa_handler network_handler =
+{
+  OSPF6_LSTYPE_NETWORK,
+  "Network",
+  ospf6_network_lsa_show
+};
+
+struct ospf6_lsa_handler link_handler =
+{
+  OSPF6_LSTYPE_LINK,
+  "Link",
+  ospf6_link_lsa_show
+};
+
+struct ospf6_lsa_handler intra_prefix_handler =
+{
+  OSPF6_LSTYPE_INTRA_PREFIX,
+  "Intra-Prefix",
+  ospf6_intra_prefix_lsa_show
+};
+
 void
 ospf6_intra_init ()
 {
-  ospf6_lstype[1].name = "Router";
-  ospf6_lstype[2].name = "Network";
-  ospf6_lstype[8].name = "Link";
-  ospf6_lstype[9].name = "Intra-Prefix";
-
-  ospf6_lstype[1].reoriginate = ospf6_router_lsa_reoriginate;
-  ospf6_lstype[2].reoriginate = ospf6_network_lsa_reoriginate;
-  ospf6_lstype[8].reoriginate = ospf6_link_lsa_reoriginate;
-  ospf6_lstype[9].reoriginate = ospf6_intra_prefix_lsa_reoriginate;
-
-  ospf6_lstype[1].show = ospf6_router_lsa_show;
-  ospf6_lstype[2].show = ospf6_network_lsa_show;
-  ospf6_lstype[8].show = ospf6_link_lsa_show;
-  ospf6_lstype[9].show = ospf6_intra_prefix_lsa_show;
+  ospf6_install_lsa_handler (&router_handler);
+  ospf6_install_lsa_handler (&network_handler);
+  ospf6_install_lsa_handler (&link_handler);
+  ospf6_install_lsa_handler (&intra_prefix_handler);
 }
 
 
diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h
index 28780b4..db92f7e 100644
--- a/ospf6d/ospf6_intra.h
+++ b/ospf6d/ospf6_intra.h
@@ -128,6 +128,18 @@
                           oi, 0); \
   } while (0)
 
+#define OSPF6_NETWORK_LSA_EXECUTE(oi) \
+  do { \
+    THREAD_OFF ((oi)->thread_network_lsa); \
+    thread_execute (master, ospf6_network_lsa_originate, oi, 0); \
+  } while (0)
+#define OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi) \
+  do { \
+    THREAD_OFF ((oi)->thread_intra_prefix_lsa); \
+    thread_execute (master, ospf6_intra_prefix_lsa_originate_transit, oi, 0); \
+  } while (0)
+
+
 /* Function Prototypes */
 char *ospf6_router_lsdesc_lookup (u_char type, u_int32_t interface_id,
                             u_int32_t neighbor_interface_id,
@@ -145,7 +157,7 @@
 void ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa);
 
 void ospf6_intra_route_calculation (struct ospf6_area *oa);
-void ospf6_intra_asbr_calculation (struct ospf6_area *oa);
+void ospf6_intra_brouter_calculation (struct ospf6_area *oa);
 
 void ospf6_intra_init ();
 
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index 56ed318..c031a2d 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -43,7 +43,7 @@
 
 unsigned char conf_debug_ospf6_lsa = 0;
 
-struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE];
+struct ospf6_lsa_handler *ospf6_lsa_handler[OSPF6_LSTYPE_SIZE];
 
 char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE] =
   {"Unknown", "Router", "Network", "Inter-Prefix", "Inter-Router",
@@ -53,10 +53,10 @@
 ospf6_lstype_name (u_int16_t type)
 {
   static char buf[8];
-  int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK;
+  int index = OSPF6_LSTYPE_INDEX (type);
 
-  if (index < OSPF6_LSTYPE_SIZE && ospf6_lstype_str[index])
-    return ospf6_lstype_str[index];
+  if (ospf6_lsa_handler[index])
+    return ospf6_lsa_handler[index]->name;
 
   snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
   return buf;
@@ -125,8 +125,7 @@
   lsa->birth.tv_usec = now.tv_usec;
   if (ntohs (lsa->header->age) != MAXAGE)
     lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
-                                    MAXAGE + lsa->birth.tv_sec
-                                    - now.tv_sec);
+                                    MAXAGE + lsa->birth.tv_sec - now.tv_sec);
   else
     lsa->expire = NULL;
   return;
@@ -272,37 +271,6 @@
 }
 
 void
-ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
-{
-  char adv_router[64], id[64];
-  int index;
-
-  assert (lsa && lsa->header);
-
-  inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
-  inet_ntop (AF_INET, &lsa->header->adv_router,
-             adv_router, sizeof (adv_router));
-
-  vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
-           OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
-  vty_out (vty, "Link State ID: %s%s", id, VNL);
-  vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
-  vty_out (vty, "LS Sequence Number: %#010lx%s",
-           (u_long) ntohl (lsa->header->seqnum), VNL);
-  vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
-           ntohs (lsa->header->checksum),
-           ntohs (lsa->header->length), VNL);
-
-  index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
-  if (ospf6_lstype[index].show)
-    (*ospf6_lstype[index].show) (vty, lsa);
-  else
-    vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL);
-
-  vty_out (vty, "%s", VNL);
-}
-
-void
 ospf6_lsa_show_summary_header (struct vty *vty)
 {
   vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
@@ -360,6 +328,7 @@
     }
 
   vty_out (vty, "%s%s", VNL, VNL);
+  return;
 }
 
 void
@@ -386,10 +355,44 @@
   vty_out (vty, "    Prev: %p This: %p Next: %p%s",
            lsa->prev, lsa, lsa->next, VNL);
   vty_out (vty, "%s", VNL);
+  return;
+}
+
+void
+ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+{
+  char adv_router[64], id[64];
+  int index;
+
+  assert (lsa && lsa->header);
+
+  inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
+  inet_ntop (AF_INET, &lsa->header->adv_router,
+             adv_router, sizeof (adv_router));
+
+  vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
+           OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
+  vty_out (vty, "Link State ID: %s%s", id, VNL);
+  vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
+  vty_out (vty, "LS Sequence Number: %#010lx%s",
+           (u_long) ntohl (lsa->header->seqnum), VNL);
+  vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
+           ntohs (lsa->header->checksum),
+           ntohs (lsa->header->length), VNL);
+
+  index = OSPF6_LSTYPE_INDEX (lsa->header->type);
+  if (ospf6_lsa_handler[index]->show)
+    (*ospf6_lsa_handler[index]->show) (vty, lsa);
+  else
+    {
+      ospf6_lsa_show_dump (vty, lsa);
+      vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL);
+    }
+
+  vty_out (vty, "%s", VNL);
 }
 
 /* OSPFv3 LSA creation/deletion function */
-
 struct ospf6_lsa *
 ospf6_lsa_create (struct ospf6_lsa_header *header)
 {
@@ -414,7 +417,6 @@
   memset (lsa, 0, sizeof (struct ospf6_lsa));
 
   lsa->header = (struct ospf6_lsa_header *) new_header;
-  lsa->headeronly = 0; /* this is not header only */
 
   /* dump string */
   ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
@@ -449,7 +451,7 @@
   memset (lsa, 0, sizeof (struct ospf6_lsa));
 
   lsa->header = (struct ospf6_lsa_header *) new_header;
-  lsa->headeronly = 1; /* this is header only */
+  SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY);
 
   /* dump string */
   ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
@@ -475,8 +477,8 @@
 
   if (IS_OSPF6_DEBUG_LSA (MEMORY))
     zlog_info ("Delete LSA %s Memory: %s (%p/%p)",
-               (lsa->headeronly ? "(Header-only) " : ""),
-               lsa->name, lsa, lsa->header);
+               (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY) ?
+                "(Header-only) " : ""), lsa->name, lsa, lsa->header);
 
   /* do free */
   XFREE (MTYPE_OSPF6_LSA, lsa->header);
@@ -492,7 +494,7 @@
     zlog_info ("Create LSA Copy from %s", lsa->name);
 
   ospf6_lsa_age_current (lsa);
-  if (lsa->headeronly)
+  if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
     copy = ospf6_lsa_create_headeronly (lsa->header);
   else
     copy = ospf6_lsa_create (lsa->header);
@@ -500,7 +502,7 @@
 
   copy->installed = lsa->installed;
   copy->originated = lsa->originated;
-  copy->scope = lsa->scope;
+  copy->lsdb = lsa->lsdb;
 
   return copy;
 }
@@ -527,77 +529,12 @@
   ospf6_lsa_delete (lsa);
 }
 
-void
-ospf6_lsa_originate (struct ospf6_lsa *lsa)
-{
-  struct ospf6_lsa *old;
-  struct ospf6_lsdb *lsdb = NULL;
-
-  /* find previous LSA */
-  lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
-  if (lsdb == NULL)
-    {
-      zlog_warn ("Can't decide scoped LSDB");
-      ospf6_lsa_delete (lsa);
-      return;
-    }
-
-  old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
-                           lsa->header->adv_router, lsdb);
-  if (old)
-    {
-      /* If this origination is neither different instance nor refresh,
-         suppress this origination */
-      if (! CHECK_FLAG (old->flag, OSPF6_LSA_REFRESH) &&
-          ! OSPF6_LSA_IS_DIFFER (lsa, old))
-        {
-          if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
-            zlog_info ("Suppress updating LSA: %s", lsa->name);
-          ospf6_lsa_delete (lsa);
-          return;
-        }
-    }
-
-  lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
-                                   LS_REFRESH_TIME);
-
-  if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
-    {
-      zlog_info ("LSA Originate:");
-      ospf6_lsa_header_print (lsa);
-    }
-
-  if (old)
-    ospf6_flood_clear (old);
-  ospf6_flood_lsa (lsa, NULL);
-  ospf6_install_lsa (lsa, lsdb);
-}
-
-void
-ospf6_lsa_re_originate (struct ospf6_lsa *lsa)
-{
-  u_int16_t index;
-
-  if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
-    {
-      zlog_info ("LSA Reoriginate:");
-      ospf6_lsa_header_print (lsa);
-    }
-
-  index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
-  if (ospf6_lstype[index].reoriginate)
-    (*ospf6_lstype[index].reoriginate) (lsa);
-  else
-    ospf6_lsa_premature_aging (lsa);
-}
-
 
 /* ospf6 lsa expiry */
 int
 ospf6_lsa_expire (struct thread *thread)
 {
   struct ospf6_lsa *lsa;
-  struct ospf6_lsdb *lsdb = NULL;
 
   lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
 
@@ -613,22 +550,16 @@
       ospf6_lsa_header_print (lsa);
     }
 
-  if (lsa->headeronly)
+  if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
     return 0;    /* dbexchange will do something ... */
 
   /* reflood lsa */
-  ospf6_flood_lsa (lsa, NULL);
+  ospf6_flood (NULL, lsa);
 
   /* reinstall lsa */
-  lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
-  if (lsdb == NULL)
-    {
-      zlog_warn ("Can't decide scoped LSDB: %s", lsa->name);
-      return 0;
-    }
   if (IS_OSPF6_DEBUG_LSA (DATABASE))
     zlog_info ("Reinstall MaxAge %s", lsa->name);
-  ospf6_lsdb_add (lsa, lsdb);
+  ospf6_lsdb_add (lsa, lsa->lsdb);
 
   /* schedule maxage remover */
   ospf6_maxage_remove (ospf6);
@@ -636,29 +567,52 @@
   return 0;
 }
 
-/* Below will become dummy thread.
-   refresh function must be set individually per each LSAs */
 int
 ospf6_lsa_refresh (struct thread *thread)
 {
-  struct ospf6_lsa *lsa;
+  struct ospf6_lsa *old, *self, *new;
+  struct ospf6_lsdb *lsdb_self;
 
   assert (thread);
-  lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
-  assert (lsa && lsa->header);
+  old = (struct ospf6_lsa *) THREAD_ARG (thread);
+  assert (old && old->header);
 
-  lsa->refresh = (struct thread *) NULL;
+  old->refresh = (struct thread *) NULL;
 
-  /* this will be used later to decide really originate or not */
-  SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
+  lsdb_self = ospf6_get_scoped_lsdb_self (old);
+  self = ospf6_lsdb_lookup (old->header->type, old->header->id,
+                            old->header->adv_router, lsdb_self);
+  if (self == NULL)
+    {
+      ospf6_lsa_premature_aging (old);
+      return 0;
+    }
+
+  /* Reset age, increment LS sequence number. */
+  self->header->age = htons (0);
+  self->header->seqnum =
+    ospf6_new_ls_seqnum (self->header->type, self->header->id,
+                         self->header->adv_router, old->lsdb);
+  ospf6_lsa_checksum (self->header);
+
+  new = ospf6_lsa_create (self->header);
+  new->lsdb = old->lsdb;
+  new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
+                                   LS_REFRESH_TIME);
+
+  /* store it in the LSDB for self-originated LSAs */
+  ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
 
   if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
     {
       zlog_info ("LSA Refresh:");
-      ospf6_lsa_header_print (lsa);
+      ospf6_lsa_header_print (new);
     }
 
-  ospf6_lsa_re_originate (lsa);
+  ospf6_flood_clear (old);
+  ospf6_flood (NULL, new);
+  ospf6_install_lsa (new);
+
   return 0;
 }
 
@@ -708,14 +662,7 @@
 }
 
 int
-ospf6_unknown_reoriginate (struct ospf6_lsa *lsa)
-{
-  ospf6_lsa_premature_aging (lsa);
-  return 0;
-}
-
-int
-ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa)
+ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
 {
   u_char *start, *end, *current;
   char byte[4];
@@ -740,13 +687,25 @@
 }
 
 void
+ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler)
+{
+  /* might need to adjust dynamic array length ... */
+  int index = OSPF6_LSTYPE_INDEX (htons (handler->type));
+  ospf6_lsa_handler[index] = handler;
+}
+
+struct ospf6_lsa_handler unknown_handler =
+{
+  OSPF6_LSTYPE_UNKNOWN,
+  "Unknown",
+  ospf6_unknown_lsa_show
+};
+
+void
 ospf6_lsa_init ()
 {
-  memset (ospf6_lstype, 0, sizeof (ospf6_lstype));
-
-  ospf6_lstype[0].name = "Unknown";
-  ospf6_lstype[0].reoriginate = ospf6_unknown_reoriginate;
-  ospf6_lstype[0].show = ospf6_unknown_show;
+  memset (ospf6_lsa_handler, 0, sizeof (ospf6_lsa_handler));
+  ospf6_install_lsa_handler (&unknown_handler);
 }
 
 
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index dd750e8..54921e1 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -62,11 +62,12 @@
 #define OSPF6_LSTYPE_FCODE_MASK       0x1fff
 
 /* LSA scope */
-#define OSPF6_LSA_SCOPE_LINKLOCAL  0x0000
-#define OSPF6_LSA_SCOPE_AREA       0x2000
-#define OSPF6_LSA_SCOPE_AS         0x4000
-#define OSPF6_LSA_SCOPE_RESERVED   0x6000
+#define OSPF6_SCOPE_LINKLOCAL  0x0000
+#define OSPF6_SCOPE_AREA       0x2000
+#define OSPF6_SCOPE_AS         0x4000
+#define OSPF6_SCOPE_RESERVED   0x6000
 
+/* XXX U-bit handling should be treated here */
 #define OSPF6_LSA_SCOPE(type) \
   (ntohs (type) & OSPF6_LSTYPE_SCOPE_MASK)
 
@@ -103,55 +104,46 @@
 
 struct ospf6_lsa
 {
-  char                 name[64];   /* dump string */
+  char              name[64];   /* dump string */
 
-  struct ospf6_lsa    *prev;
-  struct ospf6_lsa    *next;
+  struct ospf6_lsa *prev;
+  struct ospf6_lsa *next;
 
-  unsigned char        lock;       /* reference counter */
-  unsigned char        flag;       /* special meaning (e.g. floodback) */
+  unsigned char     lock;           /* reference counter */
+  unsigned char     flag;           /* special meaning (e.g. floodback) */
 
-  struct timeval       birth;      /* tv_sec when LS age 0 */
-  struct timeval       installed;  /* used by MinLSArrival check */
-  struct timeval       originated; /* used by MinLSInterval check */
+  struct timeval    birth;          /* tv_sec when LS age 0 */
+  struct timeval    installed;      /* used by MinLSArrival check */
+  struct timeval    originated;     /* used by MinLSInterval check */
 
-  struct thread       *expire;
-  struct thread       *refresh;    /* For self-originated LSA */
+  struct thread    *expire;
+  struct thread    *refresh;        /* For self-originated LSA */
 
-  void                *scope;      /* pointer to scope data structure */
-  int                  headeronly; /* indicate this is LS header only */
-  int                  onretrans;
+  int               retrans_count;
+
+struct ospf6_lsdb;
+  struct ospf6_lsdb *lsdb;
 
   /* lsa instance */
   struct ospf6_lsa_header *header;
 };
 
-#define OSPF6_LSA_FLOODBACK  0x01
-#define OSPF6_LSA_DUPLICATE  0x02
-#define OSPF6_LSA_IMPLIEDACK 0x04
-#define OSPF6_LSA_REFRESH    0x08
+#define OSPF6_LSA_HEADERONLY 0x01
+#define OSPF6_LSA_FLOODBACK  0x02
+#define OSPF6_LSA_DUPLICATE  0x04
+#define OSPF6_LSA_IMPLIEDACK 0x08
 
-struct ospf6_lstype
+struct ospf6_lsa_handler
 {
+  u_int16_t type; /* network byte order */
   char *name;
-  int (*reoriginate) (struct ospf6_lsa *);
   int (*show) (struct vty *, struct ospf6_lsa *);
 };
 
-extern struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE];
 #define OSPF6_LSTYPE_INDEX(type) \
-  (((type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \
-   ((type) & OSPF6_LSTYPE_FCODE_MASK) : OSPF6_LSTYPE_UNKNOWN)
-
-#if 0
-extern char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE];
-#define OSPF6_LSTYPE_NAME(type) \
   ((ntohs (type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \
-   ospf6_lstype_str[ntohs (type) & OSPF6_LSTYPE_FCODE_MASK] :     \
-   ospf6_lstype_str[OSPF6_LSTYPE_UNKNOWN])
-#else /*0*/
+   (ntohs (type) & OSPF6_LSTYPE_FCODE_MASK) : OSPF6_LSTYPE_UNKNOWN)
 #define OSPF6_LSTYPE_NAME(type) (ospf6_lstype_name (type))
-#endif /*0*/
 
 /* Macro for LSA Origination */
 /* void (CONTINUE_IF_...) (struct prefix *addr); */
@@ -219,11 +211,11 @@
 char *ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size);
 void ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header);
 void ospf6_lsa_header_print (struct ospf6_lsa *lsa);
-void ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa);
 void ospf6_lsa_show_summary_header (struct vty *vty);
 void ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa);
 void ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa);
 void ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa);
+void ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa);
 
 struct ospf6_lsa *ospf6_lsa_create (struct ospf6_lsa_header *header);
 struct ospf6_lsa *ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header);
@@ -233,8 +225,6 @@
 void ospf6_lsa_lock (struct ospf6_lsa *);
 void ospf6_lsa_unlock (struct ospf6_lsa *);
 
-void ospf6_lsa_originate (struct ospf6_lsa *);
-void ospf6_lsa_re_originate (struct ospf6_lsa *lsa);
 int ospf6_lsa_expire (struct thread *);
 int ospf6_lsa_refresh (struct thread *);
 
@@ -242,6 +232,7 @@
 int ospf6_lsa_prohibited_duration (u_int16_t type, u_int32_t id,
                                    u_int32_t adv_router, void *scope);
 
+void ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler);
 void ospf6_lsa_init ();
 
 int config_write_ospf6_debug_lsa (struct vty *vty);
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index 5c132ca..9b37406 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -34,7 +34,7 @@
 #include "ospf6d.h"
 
 struct ospf6_lsdb *
-ospf6_lsdb_create ()
+ospf6_lsdb_create (void *data)
 {
   struct ospf6_lsdb *lsdb;
 
@@ -46,6 +46,7 @@
     }
   memset (lsdb, 0, sizeof (struct ospf6_lsdb));
 
+  lsdb->data = data;
   lsdb->table = route_table_init ();
   return lsdb;
 }
@@ -228,6 +229,7 @@
 
   ospf6_lsa_unlock (lsa);
   route_unlock_node (node);
+
   ospf6_lsdb_count_assert (lsdb);
 }
 
@@ -475,7 +477,7 @@
       if (ntohl (lsa->header->id) < id)
         continue;
       if (ntohl (lsa->header->id) > id)
-        return ((u_int32_t) htonl (id));
+        break;
       id++;
     }
 
diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h
index 71d996e..a10f001 100644
--- a/ospf6d/ospf6_lsdb.h
+++ b/ospf6d/ospf6_lsdb.h
@@ -27,6 +27,7 @@
 
 struct ospf6_lsdb
 {
+  void *data; /* data structure that holds this lsdb */
   struct route_table *table;
   u_int32_t count;
   void (*hook_add) (struct ospf6_lsa *);
@@ -40,7 +41,7 @@
       {                                                                  \
         if (! OSPF6_LSA_IS_MAXAGE (lsa))                                 \
           continue;                                                      \
-        if (lsa->onretrans != 0)                                         \
+        if (lsa->retrans_count != 0)                                         \
           continue;                                                      \
         if (IS_OSPF6_DEBUG_LSA (TIMER))                                  \
           zlog_info (" remove maxage %s", lsa->name);                    \
@@ -49,7 +50,7 @@
   } while (0)
 
 /* Function Prototypes */
-struct ospf6_lsdb *ospf6_lsdb_create ();
+struct ospf6_lsdb *ospf6_lsdb_create (void *data);
 void ospf6_lsdb_delete (struct ospf6_lsdb *lsdb);
 
 struct ospf6_lsa *ospf6_lsdb_lookup (u_int16_t type, u_int32_t id,
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 91ecdf4..7e022da 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -245,7 +245,7 @@
   /* Area-ID check */
   if (oh->area_id != oi->area->area_id)
     {
-      if (oh->area_id == 0)
+      if (oh->area_id == BACKBONE_AREA_ID)
         {
           if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
             zlog_info ("Message may be via Virtual Link: not supported");
@@ -519,21 +519,34 @@
       struct ospf6_lsdb *lsdb = NULL;
 
       his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
-      his->scope = ospf6_get_lsa_scope (his->header->type, on);
-      lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
-      if (lsdb == NULL)
+
+      if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+        zlog_info ("%s", his->name);
+
+      switch (OSPF6_LSA_SCOPE (his->header->type))
         {
-          zlog_warn ("Can't decide scoped LSDB");
+        case OSPF6_SCOPE_LINKLOCAL:
+          lsdb = on->ospf6_if->lsdb;
+          break;
+        case OSPF6_SCOPE_AREA:
+          lsdb = on->ospf6_if->area->lsdb;
+          break;
+        case OSPF6_SCOPE_AS:
+          lsdb = on->ospf6_if->area->ospf6->lsdb;
+          break;
+        case OSPF6_SCOPE_RESERVED:
+          if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+            zlog_info ("Ignoring LSA of reserved scope");
           ospf6_lsa_delete (his);
-          thread_add_event (master, seqnumber_mismatch, on, 0);
-          return;
+          continue;
+          break;
         }
 
       if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
-          ospf6_area_is_stub (on->ospf6_if->area))
+          IS_AREA_STUB (on->ospf6_if->area))
         {
           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
-            zlog_info ("E-bit mismatch with LSA Headers");
+            zlog_info ("SeqNumMismatch (E-bit mismatch), discard");
           ospf6_lsa_delete (his);
           thread_add_event (master, seqnumber_mismatch, on, 0);
           return;
@@ -541,14 +554,24 @@
 
       mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
                                 his->header->adv_router, lsdb);
-      if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
+      if (mine == NULL)
         {
-          if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
-            zlog_info ("Add %s's request-list: %s", on->name, his->name);
+          if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+            zlog_info ("Add request (No database copy)", his->name);
+          ospf6_lsdb_add (his, on->request_list);
+        }
+      else if (ospf6_lsa_compare (his, mine) < 0)
+        {
+          if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+            zlog_info ("Add request (Received MoreRecent)", his->name);
           ospf6_lsdb_add (his, on->request_list);
         }
       else
-        ospf6_lsa_delete (his);
+        {
+          if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+            zlog_info ("Discard (Existing MoreRecent)", his->name);
+          ospf6_lsa_delete (his);
+        }
     }
 
   if (p != OSPF6_MESSAGE_END (oh))
@@ -721,18 +744,28 @@
       struct ospf6_lsdb *lsdb = NULL;
 
       his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
-      his->scope = ospf6_get_lsa_scope (his->header->type, on);
-      lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
-      if (lsdb == NULL)
+
+      switch (OSPF6_LSA_SCOPE (his->header->type))
         {
-          zlog_warn ("Can't decide scoped LSDB");
+        case OSPF6_SCOPE_LINKLOCAL:
+          lsdb = on->ospf6_if->lsdb;
+          break;
+        case OSPF6_SCOPE_AREA:
+          lsdb = on->ospf6_if->area->lsdb;
+          break;
+        case OSPF6_SCOPE_AS:
+          lsdb = on->ospf6_if->area->ospf6->lsdb;
+          break;
+        case OSPF6_SCOPE_RESERVED:
+          if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+            zlog_info ("Ignoring LSA of reserved scope");
           ospf6_lsa_delete (his);
-          thread_add_event (master, seqnumber_mismatch, on, 0);
-          return;
+          continue;
+          break;
         }
 
-      if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
-          ospf6_area_is_stub (on->ospf6_if->area))
+      if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
+          IS_AREA_STUB (on->ospf6_if->area))
         {
           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
             zlog_info ("E-bit mismatch with LSA Headers");
@@ -745,8 +778,8 @@
                                 his->header->adv_router, lsdb);
       if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
         {
-          if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
-            zlog_info ("Add %s to request-list of %s", his->name, on->name);
+          if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+            zlog_info ("Add request-list: %s", his->name);
           ospf6_lsdb_add (his, on->request_list);
         }
       else
@@ -838,7 +871,6 @@
   struct ospf6_neighbor *on;
   char *p;
   struct ospf6_lsreq_entry *e;
-  void *scope = NULL;
   struct ospf6_lsdb *lsdb = NULL;
   struct ospf6_lsa *lsa;
 
@@ -875,8 +907,24 @@
        p += sizeof (struct ospf6_lsreq_entry))
     {
       e = (struct ospf6_lsreq_entry *) p;
-      scope = ospf6_get_lsa_scope (e->type, on);
-      lsdb = ospf6_get_scoped_lsdb (e->type, scope);
+
+      switch (OSPF6_LSA_SCOPE (e->type))
+        {
+        case OSPF6_SCOPE_LINKLOCAL:
+          lsdb = on->ospf6_if->lsdb;
+          break;
+        case OSPF6_SCOPE_AREA:
+          lsdb = on->ospf6_if->area->lsdb;
+          break;
+        case OSPF6_SCOPE_AS:
+          lsdb = on->ospf6_if->area->ospf6->lsdb;
+          break;
+        default:
+          if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+            zlog_info ("Ignoring LSA of reserved scope");
+          continue;
+          break;
+        }
 
       /* Find database copy */
       lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
@@ -895,9 +943,6 @@
           return;
         }
 
-      if (IS_OSPF6_DEBUG_LSA (DATABASE))
-        zlog_info ("Add copy of %s to lsupdate_list of %s",
-                   lsa->name, on->name);
       ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
     }
 
@@ -969,7 +1014,7 @@
           break;
         }
 
-      ospf6_receive_lsa ((struct ospf6_lsa_header *) p, on);
+      ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
       num--;
     }
 
@@ -1041,11 +1086,27 @@
        p += sizeof (struct ospf6_lsa_header))
     {
       his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
-      his->scope = ospf6_get_lsa_scope (his->header->type, on);
-      lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
 
-      if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
-          IS_OSPF6_DEBUG_LSA (SEND))
+      switch (OSPF6_LSA_SCOPE (his->header->type))
+        {
+        case OSPF6_SCOPE_LINKLOCAL:
+          lsdb = on->ospf6_if->lsdb;
+          break;
+        case OSPF6_SCOPE_AREA:
+          lsdb = on->ospf6_if->area->lsdb;
+          break;
+        case OSPF6_SCOPE_AS:
+          lsdb = on->ospf6_if->area->ospf6->lsdb;
+          break;
+        case OSPF6_SCOPE_RESERVED:
+          if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+            zlog_info ("Ignoring LSA of reserved scope");
+          ospf6_lsa_delete (his);
+          continue;
+          break;
+        }
+
+      if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
         zlog_info ("%s acknowledged by %s", his->name, on->name);
 
       /* Find database copy */
@@ -1080,18 +1141,14 @@
           continue;
         }
 
-      if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
-          IS_OSPF6_DEBUG_LSA (SEND))
+      if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
         zlog_info ("Acknowledged, remove from %s's retrans-list",
                    on->name);
 
       if (OSPF6_LSA_IS_MAXAGE (mine))
         ospf6_maxage_remove (on->ospf6_if->area->ospf6);
 
-      if (IS_OSPF6_DEBUG_LSA (DATABASE))
-        zlog_info ("remove %s from retrans_list of %s",
-                   mine->name, on->name);
-      ospf6_decrement_onretrans (mine);
+      ospf6_decrement_retrans_count (mine);
       ospf6_lsdb_remove (mine, on->retrans_list);
       ospf6_lsa_delete (his);
     }
@@ -1473,8 +1530,6 @@
   unsigned int size = 0;
 
   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
-  if (IS_OSPF6_DEBUG_LSA (DATABASE))
-    zlog_info ("Remove entire dbdesc_list of %s: sending newone", on->name);
   ospf6_lsdb_remove_all (on->dbdesc_list);
 
   /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
@@ -1489,9 +1544,6 @@
           break;
         }
 
-      if (IS_OSPF6_DEBUG_LSA (DATABASE))
-        zlog_info ("Move %s from summary_list to dbdesc_list of %s",
-                   lsa->name, on->name);
       ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
       ospf6_lsdb_remove (lsa, on->summary_list);
       size += sizeof (struct ospf6_lsa_header);
@@ -1587,21 +1639,25 @@
   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
   on->thread_send_lsupdate = (struct thread *) NULL;
 
+  if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+    zlog_info ("LSUpdate to neighbor %s", on->name);
+
   if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
     {
       if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
-        zlog_info ("Quit to send LSUpdate to neighbor %s state %s",
-                   on->name, ospf6_neighbor_state_str[on->state]);
+        zlog_info ("Quit to send (neighbor state %s)",
+                   ospf6_neighbor_state_str[on->state]);
       return 0;
     }
 
   /* if we have nothing to send, return */
   if (on->lsupdate_list->count == 0 &&
       on->retrans_list->count == 0)
-    return 0;
-
-  if (IS_OSPF6_DEBUG_LSA (SEND))
-    zlog_info ("LSA Send to %s", on->name);
+    {
+      if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+        zlog_info ("Quit to send (nothing to send)");
+      return 0;
+    }
 
   memset (sendbuf, 0, iobuflen);
   oh = (struct ospf6_header *) sendbuf;
@@ -1623,9 +1679,6 @@
           break;
         }
 
-      if (IS_OSPF6_DEBUG_LSA (SEND))
-        ospf6_lsa_header_print (lsa);
-
       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
       p += OSPF6_LSA_SIZE (lsa->header);
@@ -1645,9 +1698,6 @@
           break;
         }
 
-      if (IS_OSPF6_DEBUG_LSA (SEND))
-        ospf6_lsa_header_print (lsa);
-
       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
       p += OSPF6_LSA_SIZE (lsa->header);
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index a4823d2..e7818ab 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -51,7 +51,7 @@
 {
   struct ospf6_neighbor *ona = (struct ospf6_neighbor *) va;
   struct ospf6_neighbor *onb = (struct ospf6_neighbor *) vb;
-  return (ntohl (ona->router_id) - ntohl (onb->router_id));
+  return (ntohl (ona->router_id) < ntohl (onb->router_id) ? -1 : 1);
 }
 
 struct ospf6_neighbor *
@@ -94,14 +94,14 @@
   gettimeofday (&on->last_changed, (struct timezone *) NULL);
   on->router_id = router_id;
 
-  on->summary_list = ospf6_lsdb_create ();
-  on->request_list = ospf6_lsdb_create ();
-  on->retrans_list = ospf6_lsdb_create ();
+  on->summary_list = ospf6_lsdb_create (on);
+  on->request_list = ospf6_lsdb_create (on);
+  on->retrans_list = ospf6_lsdb_create (on);
 
-  on->dbdesc_list = ospf6_lsdb_create ();
-  on->lsreq_list = ospf6_lsdb_create ();
-  on->lsupdate_list = ospf6_lsdb_create ();
-  on->lsack_list = ospf6_lsdb_create ();
+  on->dbdesc_list = ospf6_lsdb_create (on);
+  on->lsreq_list = ospf6_lsdb_create (on);
+  on->lsupdate_list = ospf6_lsdb_create (on);
+  on->lsack_list = ospf6_lsdb_create (on);
 
   listnode_add_sort (oi->neighbor_list, on);
   return on;
@@ -117,7 +117,7 @@
   for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     {
-      ospf6_decrement_onretrans (lsa);
+      ospf6_decrement_retrans_count (lsa);
       ospf6_lsdb_remove (lsa, on->retrans_list);
     }
 
@@ -286,7 +286,7 @@
   for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     {
-      ospf6_decrement_onretrans (lsa);
+      ospf6_decrement_retrans_count (lsa);
       ospf6_lsdb_remove (lsa, on->retrans_list);
     }
 
@@ -300,7 +300,7 @@
                     "summary_list"), on->name);
       if (OSPF6_LSA_IS_MAXAGE (lsa))
         {
-          lsa->onretrans++;
+          ospf6_increment_retrans_count (lsa);
           ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
         }
       else
@@ -317,7 +317,7 @@
                     "summary_list"), on->name);
       if (OSPF6_LSA_IS_MAXAGE (lsa))
         {
-          lsa->onretrans++;
+          ospf6_increment_retrans_count (lsa);
           ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
         }
       else
@@ -334,7 +334,7 @@
                     "summary_list"), on->name);
       if (OSPF6_LSA_IS_MAXAGE (lsa))
         {
-          lsa->onretrans++;
+          ospf6_increment_retrans_count (lsa);
           ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
         }
       else
@@ -431,7 +431,7 @@
       for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
            lsa = ospf6_lsdb_next (lsa))
         {
-          ospf6_decrement_onretrans (lsa);
+          ospf6_decrement_retrans_count (lsa);
           ospf6_lsdb_remove (lsa, on->retrans_list);
         }
     }
@@ -464,7 +464,7 @@
   for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     {
-      ospf6_decrement_onretrans (lsa);
+      ospf6_decrement_retrans_count (lsa);
       ospf6_lsdb_remove (lsa, on->retrans_list);
     }
 
@@ -500,7 +500,7 @@
   for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     {
-      ospf6_decrement_onretrans (lsa);
+      ospf6_decrement_retrans_count (lsa);
       ospf6_lsdb_remove (lsa, on->retrans_list);
     }
 
@@ -534,7 +534,7 @@
   for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     {
-      ospf6_decrement_onretrans (lsa);
+      ospf6_decrement_retrans_count (lsa);
       ospf6_lsdb_remove (lsa, on->retrans_list);
     }
 
diff --git a/ospf6d/ospf6_proto.c b/ospf6d/ospf6_proto.c
index 7ee7e0a..5b47cf8 100644
--- a/ospf6d/ospf6_proto.c
+++ b/ospf6d/ospf6_proto.c
@@ -36,12 +36,15 @@
   offset = op->prefix_length % 8;
   mask = 0xff << (8 - offset);
 
-  if (index >= 16)
+  if (index > 16)
     {
-      zlog_warn ("Apply mask to ospf6_prefix failed");
+      zlog_warn ("Prefix length too long: %d", op->prefix_length);
       return;
     }
 
+  if (index == 16)
+    return;
+
   pnt[index] &= mask;
   index ++;
 
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 9e64ea0..1202a3a 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -1069,6 +1069,32 @@
   return CMD_SUCCESS;
 }
 
+void
+ospf6_brouter_show_header (struct vty *vty)
+{
+  vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
+           "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
+}
+
+void
+ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
+{
+  u_int32_t adv_router;
+  char adv[16], rbits[16], options[16], area[16];
+
+  adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
+  inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
+  ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
+  ospf6_options_printbuf (route->path.options, options, sizeof (options));
+  inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
+
+  /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
+           "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
+  vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
+           adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
+           area, VNL);
+}
+
 DEFUN (debug_ospf6_route,
        debug_ospf6_route_cmd,
        "debug ospf6 route (table|intra-area|inter-area)",
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index f58a801..333b2ce 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -90,6 +90,7 @@
 
   /* Path-type */
   u_char type;
+  u_char subtype; /* only used for redistribute i.e ZEBRA_ROUTE_XXX */
 
   /* Cost */
   u_int8_t metric_type;
@@ -97,12 +98,13 @@
   u_int32_t cost_e2;
 };
 
-#define OSPF6_PATH_TYPE_NONE       0
-#define OSPF6_PATH_TYPE_INTRA      1
-#define OSPF6_PATH_TYPE_INTER      2
-#define OSPF6_PATH_TYPE_EXTERNAL1  3
-#define OSPF6_PATH_TYPE_EXTERNAL2  4
-#define OSPF6_PATH_TYPE_MAX        5
+#define OSPF6_PATH_TYPE_NONE         0
+#define OSPF6_PATH_TYPE_INTRA        1
+#define OSPF6_PATH_TYPE_INTER        2
+#define OSPF6_PATH_TYPE_EXTERNAL1    3
+#define OSPF6_PATH_TYPE_EXTERNAL2    4
+#define OSPF6_PATH_TYPE_REDISTRIBUTE 5
+#define OSPF6_PATH_TYPE_MAX          6
 
 #include "prefix.h"
 #include "table.h"
@@ -147,13 +149,15 @@
 #define OSPF6_DEST_TYPE_NETWORK    2
 #define OSPF6_DEST_TYPE_DISCARD    3
 #define OSPF6_DEST_TYPE_LINKSTATE  4
-#define OSPF6_DEST_TYPE_MAX        5
+#define OSPF6_DEST_TYPE_RANGE      5
+#define OSPF6_DEST_TYPE_MAX        6
 
-#define OSPF6_ROUTE_CHANGE      0x01
-#define OSPF6_ROUTE_ADD         0x02
-#define OSPF6_ROUTE_REMOVE      0x04
-#define OSPF6_ROUTE_BEST        0x08
-#define OSPF6_ROUTE_HAVE_LONGER 0x10
+#define OSPF6_ROUTE_CHANGE           0x01
+#define OSPF6_ROUTE_ADD              0x02
+#define OSPF6_ROUTE_REMOVE           0x04
+#define OSPF6_ROUTE_BEST             0x08
+#define OSPF6_ROUTE_ACTIVE_SUMMARY   0x08
+#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x10
 
 struct ospf6_route_table
 {
@@ -252,11 +256,18 @@
 void ospf6_route_table_delete (struct ospf6_route_table *);
 void ospf6_route_dump (struct ospf6_route_table *table);
 
+
+void ospf6_route_show (struct vty *vty, struct ospf6_route *route);
+void ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route);
+
 int ospf6_route_table_show (struct vty *, int, char **,
                             struct ospf6_route_table *);
 int ospf6_lsentry_table_show (struct vty *, int, char **,
                               struct ospf6_route_table *);
 
+void ospf6_brouter_show_header (struct vty *vty);
+void ospf6_brouter_show (struct vty *vty, struct ospf6_route *route);
+
 int config_write_ospf6_debug_route (struct vty *vty);
 void install_element_ospf6_debug_route ();
 void ospf6_route_init ();
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index 285d4bb..d3c0f81 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -342,8 +342,11 @@
 
   /* There should be no case where candidate being installed (variable
      "v") is closer than the one in the SPF tree (variable "route").
-     In the case something's gone wrong with the behavior of
+     In the case something has gone wrong with the behavior of
      Priority-Queue. */
+
+  /* the case where the route exists already is handled and returned
+     up to here. */
   assert (route == NULL);
 
   route = ospf6_route_create ();
@@ -387,6 +390,8 @@
     }
 }
 
+/* RFC2328 16.1.  Calculating the shortest-path tree for an area */
+/* RFC2740 3.8.1.  Calculating the shortest path tree for an area */
 void
 ospf6_spf_calculation (u_int32_t router_id,
                        struct ospf6_route_table *result_table,
@@ -415,7 +420,7 @@
   root->area = oa;
   root->cost = 0;
   root->hops = 0;
-  root->nexthop[0].ifindex = 0; /* should have been loopbak I/F ... */
+  root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */
   inet_pton (AF_INET6, "::1", &root->nexthop[0].address);
 
   /* Actually insert root to the candidate-list as the only candidate */
@@ -427,7 +432,7 @@
       /* get closest candidate from priority queue */
       v = pqueue_dequeue (candidate_list);
 
-      /* install may result in merging and rejecting of the vertex */
+      /* installing may result in merging or rejecting of the vertex */
       if (ospf6_spf_install (v, result_table) < 0)
         continue;
 
@@ -507,7 +512,7 @@
     }
 
   ospf6_intra_route_calculation (oa);
-  ospf6_intra_asbr_calculation (oa);
+  ospf6_intra_brouter_calculation (oa);
 
   return 0;
 }
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 4a33d47..865a116 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -42,8 +42,10 @@
 #include "ospf6_interface.h"
 #include "ospf6_neighbor.h"
 
+#include "ospf6_flood.h"
 #include "ospf6_asbr.h"
 #include "ospf6_abr.h"
+#include "ospf6_intra.h"
 #include "ospf6d.h"
 
 /* global ospf6d variable */
@@ -84,17 +86,31 @@
 void
 ospf6_top_route_hook_add (struct ospf6_route *route)
 {
-  ospf6_abr_originate_prefix (route, ospf6);
+  ospf6_abr_originate_summary (route);
   ospf6_zebra_route_update_add (route);
 }
 
 void
 ospf6_top_route_hook_remove (struct ospf6_route *route)
 {
-  ospf6_abr_originate_prefix (route, ospf6);
+  ospf6_abr_originate_summary (route);
   ospf6_zebra_route_update_remove (route);
 }
 
+void
+ospf6_top_brouter_hook_add (struct ospf6_route *route)
+{
+  ospf6_abr_originate_summary (route);
+  ospf6_asbr_lsentry_add (route);
+}
+
+void
+ospf6_top_brouter_hook_remove (struct ospf6_route *route)
+{
+  ospf6_abr_originate_summary (route);
+  ospf6_asbr_lsentry_remove (route);
+}
+
 struct ospf6 *
 ospf6_create ()
 {
@@ -107,7 +123,8 @@
   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 = ospf6_lsdb_create (o);
+  o->lsdb_self = ospf6_lsdb_create (o);
   o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
   o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
 
@@ -115,11 +132,9 @@
   o->route_table->hook_add = ospf6_top_route_hook_add;
   o->route_table->hook_remove = ospf6_top_route_hook_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->brouter_table = ospf6_route_table_create ();
+  o->brouter_table->hook_add = ospf6_top_brouter_hook_add;
+  o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove;
 
   o->external_table = ospf6_route_table_create ();
   o->external_id_table = route_table_init ();
@@ -140,9 +155,9 @@
     }
 
   ospf6_lsdb_delete (o->lsdb);
+  ospf6_lsdb_delete (o->lsdb_self);
 
   ospf6_route_table_delete (o->route_table);
-  ospf6_route_table_delete (o->asbr_table);
   ospf6_route_table_delete (o->brouter_table);
 
   ospf6_route_table_delete (o->external_table);
@@ -185,7 +200,7 @@
 
       ospf6_lsdb_remove_all (o->lsdb);
       ospf6_route_remove_all (o->route_table);
-      ospf6_route_remove_all (o->asbr_table);
+      ospf6_route_remove_all (o->brouter_table);
     }
 }
 
@@ -320,10 +335,12 @@
       )
 {
   struct ospf6 *o;
-  struct ospf6_area *oa;
+  struct ospf6_area *oa, *area;
   struct ospf6_interface *oi;
   struct interface *ifp;
   u_int32_t area_id;
+  listnode node;
+  struct ospf6_route *ro;
 
   o = (struct ospf6 *) vty->index;
 
@@ -355,8 +372,31 @@
   listnode_add (oa->if_list, oi); /* sort ?? */
   oi->area = oa;
 
+  SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
+
   /* start up */
   thread_add_event (master, interface_up, oi, 0);
+
+  /* ABR stuff, redistribute inter-area LSAs and
+     re-originate Router-LSA (B-bit may have been changed) */
+  for (node = listhead (o->area_list); node; nextnode (node))
+    {
+      area = OSPF6_AREA (getdata (node));
+      OSPF6_ROUTER_LSA_SCHEDULE (area);
+
+      for (ro = ospf6_route_head (area->range_table); ro;
+           ro = ospf6_route_next (ro))
+        ospf6_abr_originate_summary_to_area (ro, oa);
+    }
+
+  for (ro = ospf6_route_head (o->brouter_table); ro;
+       ro = ospf6_route_next (ro))
+    ospf6_abr_originate_summary_to_area (ro, oa);
+
+  for (ro = ospf6_route_head (o->route_table); ro;
+       ro = ospf6_route_next (ro))
+    ospf6_abr_originate_summary_to_area (ro, oa);
+
   return CMD_SUCCESS;
 }
 
@@ -372,8 +412,12 @@
 {
   struct ospf6 *o;
   struct ospf6_interface *oi;
+  struct ospf6_area *oa, *area;
   struct interface *ifp;
   u_int32_t area_id;
+  listnode node;
+  struct ospf6_route *ro;
+  struct ospf6_lsa *old;
 
   o = (struct ospf6 *) vty->index;
 
@@ -407,9 +451,45 @@
 
   thread_execute (master, interface_down, oi, 0);
 
+  oa = oi->area;
   listnode_delete (oi->area->if_list, oi);
   oi->area = (struct ospf6_area *) NULL;
 
+  /* Withdraw inter-area routes from this area, if necessary */
+  if (oa->if_list->count == 0)
+    {
+      UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
+
+      for (ro = ospf6_route_head (oa->summary_prefix); ro;
+           ro = ospf6_route_next (ro))
+        {
+          old = ospf6_lsdb_lookup (ro->path.origin.type,
+                                   ro->path.origin.id,
+                                   oa->ospf6->router_id, oa->lsdb);
+          if (old)
+            ospf6_lsa_purge (old);
+          ospf6_route_remove (ro, oa->summary_prefix);
+        }
+      for (ro = ospf6_route_head (oa->summary_router); ro;
+           ro = ospf6_route_next (ro))
+        {
+          old = ospf6_lsdb_lookup (ro->path.origin.type,
+                                   ro->path.origin.id,
+                                   oa->ospf6->router_id, oa->lsdb);
+          if (old)
+            ospf6_lsa_purge (old);
+          ospf6_route_remove (ro, oa->summary_router);
+        }
+    }
+
+  /* Schedule Refreshment of Router-LSA for each area
+     (ABR status may change) */
+  for (node = listhead (o->area_list); node; nextnode (node))
+    {
+      area = OSPF6_AREA (getdata (node));
+      OSPF6_ROUTER_LSA_SCHEDULE (area);
+    }
+
   return CMD_SUCCESS;
 }
 
@@ -562,6 +642,7 @@
   vty_out (vty, " router-id %s%s", router_id, VNL);
 
   ospf6_redistribute_config_write (vty);
+  ospf6_area_config_write (vty);
 
   for (j = listhead (ospf6->area_list); j; nextnode (j))
     {
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index f48b7f6..d831d94 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -38,9 +38,9 @@
 
   /* AS scope link state database */
   struct ospf6_lsdb *lsdb;
+  struct ospf6_lsdb *lsdb_self;
 
   struct ospf6_route_table *route_table;
-  struct ospf6_route_table *asbr_table;
   struct ospf6_route_table *brouter_table;
 
   struct ospf6_route_table *external_table;
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index 4eba8a4..6cc0764 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -140,7 +140,8 @@
   return prev;
 }
 
-
+
+/* show database functions */
 DEFUN (show_version_ospf6,
        show_version_ospf6_cmd,
        "show version ospf6",
@@ -186,7 +187,7 @@
 static int
 parse_show_level (int argc, char **argv)
 {
-  int level;
+  int level = 0;
   if (argc)
     {
       if (! strncmp (argv[0], "de", 2))
@@ -204,7 +205,7 @@
 static u_int16_t
 parse_type_spec (int argc, char **argv)
 {
-  u_int16_t type;
+  u_int16_t type = 0;
   assert (argc);
   if (! strcmp (argv[0], "router"))
     type = htons (OSPF6_LSTYPE_ROUTER);
@@ -316,7 +317,7 @@
 
   switch (OSPF6_LSA_SCOPE (type))
     {
-      case OSPF6_LSA_SCOPE_AREA:
+      case OSPF6_SCOPE_AREA:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -325,7 +326,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
+      case OSPF6_SCOPE_LINKLOCAL:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -339,7 +340,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_AS:
+      case OSPF6_SCOPE_AS:
         vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
         ospf6_lsdb_show (vty, level, &type, NULL, NULL, o->lsdb);
         break;
@@ -623,7 +624,7 @@
 
   switch (OSPF6_LSA_SCOPE (type))
     {
-      case OSPF6_LSA_SCOPE_AREA:
+      case OSPF6_SCOPE_AREA:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -632,7 +633,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
+      case OSPF6_SCOPE_LINKLOCAL:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -646,7 +647,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_AS:
+      case OSPF6_SCOPE_AS:
         vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
         ospf6_lsdb_show (vty, level, &type, &id, NULL, o->lsdb);
         break;
@@ -782,7 +783,7 @@
 
   switch (OSPF6_LSA_SCOPE (type))
     {
-      case OSPF6_LSA_SCOPE_AREA:
+      case OSPF6_SCOPE_AREA:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -791,7 +792,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
+      case OSPF6_SCOPE_LINKLOCAL:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -805,7 +806,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_AS:
+      case OSPF6_SCOPE_AS:
         vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
         ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, o->lsdb);
         break;
@@ -918,7 +919,7 @@
   if ((inet_pton (AF_INET, argv[0], &id)) != 1)
     {
       vty_out (vty, "Link state ID is not parsable: %s%s",
-               argv[1], VNL);
+               argv[0], VNL);
       return CMD_SUCCESS;
     }
 
@@ -1014,7 +1015,7 @@
   if ((inet_pton (AF_INET, argv[0], &id)) != 1)
     {
       vty_out (vty, "Link state ID is not parsable: %s%s",
-               argv[1], VNL);
+               argv[0], VNL);
       return CMD_SUCCESS;
     }
 
@@ -1125,7 +1126,7 @@
 
   switch (OSPF6_LSA_SCOPE (type))
     {
-      case OSPF6_LSA_SCOPE_AREA:
+      case OSPF6_SCOPE_AREA:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1134,7 +1135,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
+      case OSPF6_SCOPE_LINKLOCAL:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1148,7 +1149,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_AS:
+      case OSPF6_SCOPE_AS:
         vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
         ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb);
         break;
@@ -1250,7 +1251,7 @@
 
   switch (OSPF6_LSA_SCOPE (type))
     {
-      case OSPF6_LSA_SCOPE_AREA:
+      case OSPF6_SCOPE_AREA:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1259,7 +1260,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
+      case OSPF6_SCOPE_LINKLOCAL:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1273,7 +1274,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_AS:
+      case OSPF6_SCOPE_AS:
         vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
         ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb);
         break;
@@ -1416,7 +1417,7 @@
 
   switch (OSPF6_LSA_SCOPE (type))
     {
-      case OSPF6_LSA_SCOPE_AREA:
+      case OSPF6_SCOPE_AREA:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1425,7 +1426,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
+      case OSPF6_SCOPE_LINKLOCAL:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1439,7 +1440,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_AS:
+      case OSPF6_SCOPE_AS:
         vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
         ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, o->lsdb);
         break;
@@ -1517,7 +1518,7 @@
   argc--;
   argv++;
 
-  if ((inet_pton (AF_INET, argv[1], &id)) != 1)
+  if ((inet_pton (AF_INET, argv[0], &id)) != 1)
     {
       vty_out (vty, "Link State ID is not parsable: %s%s",
                argv[0], VNL);
@@ -1532,7 +1533,7 @@
 
   switch (OSPF6_LSA_SCOPE (type))
     {
-      case OSPF6_LSA_SCOPE_AREA:
+      case OSPF6_SCOPE_AREA:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1541,7 +1542,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
+      case OSPF6_SCOPE_LINKLOCAL:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1555,7 +1556,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_AS:
+      case OSPF6_SCOPE_AS:
         vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
         ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb);
         break;
@@ -1633,7 +1634,7 @@
   argc--;
   argv++;
 
-  if ((inet_pton (AF_INET, argv[1], &id)) != 1)
+  if ((inet_pton (AF_INET, argv[0], &id)) != 1)
     {
       vty_out (vty, "Link State ID is not parsable: %s%s",
                argv[0], VNL);
@@ -1648,7 +1649,7 @@
 
   switch (OSPF6_LSA_SCOPE (type))
     {
-      case OSPF6_LSA_SCOPE_AREA:
+      case OSPF6_SCOPE_AREA:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1657,7 +1658,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_LINKLOCAL:
+      case OSPF6_SCOPE_LINKLOCAL:
         for (i = listhead (o->area_list); i; nextnode (i))
           {
             oa = (struct ospf6_area *) getdata (i);
@@ -1671,7 +1672,7 @@
           }
         break;
 
-      case OSPF6_LSA_SCOPE_AS:
+      case OSPF6_SCOPE_AS:
         vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL);
         ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb);
         break;
@@ -1712,6 +1713,68 @@
        "Display LSA's internal information\n"
       );
 
+
+DEFUN (show_ipv6_ospf6_border_routers,
+       show_ipv6_ospf6_border_routers_cmd,
+       "show ipv6 ospf6 border-routers",
+       SHOW_STR
+       IP6_STR
+       OSPF6_STR
+       "Display routing table for ABR and ASBR\n"
+      )
+{
+  u_int32_t adv_router;
+  void (*showfunc) (struct vty *, struct ospf6_route *);
+  struct ospf6_route *ro;
+  struct prefix prefix;
+
+  OSPF6_CMD_CHECK_RUNNING ();
+
+  if (argc && ! strcmp ("detail", argv[0]))
+    {
+      showfunc = ospf6_route_show_detail;
+      argc--;
+      argv++;
+    }
+  else
+    showfunc = ospf6_brouter_show;
+
+  if (argc)
+    {
+      if ((inet_pton (AF_INET, argv[0], &adv_router)) != 1)
+        {
+          vty_out (vty, "Router ID is not parsable: %s%s", argv[0], VNL);
+          return CMD_SUCCESS;
+        }
+
+      ospf6_linkstate_prefix (adv_router, 0, &prefix);
+      ro = ospf6_route_lookup (&prefix, ospf6->brouter_table);
+      ospf6_route_show_detail (vty, ro);
+      return CMD_SUCCESS;
+    }
+
+  if (showfunc == ospf6_brouter_show)
+    ospf6_brouter_show_header (vty);
+
+  for (ro = ospf6_route_head (ospf6->brouter_table); ro;
+       ro = ospf6_route_next (ro))
+    (*showfunc) (vty, ro);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_border_routers,
+       show_ipv6_ospf6_border_routers_detail_cmd,
+       "show ipv6 ospf6 border-routers (A.B.C.D|detail)",
+       SHOW_STR
+       IP6_STR
+       OSPF6_STR
+       "Display routing table for ABR and ASBR\n"
+       "Specify Router-ID\n"
+       "Display Detail\n"
+      );
+
+
 /* Install ospf related commands. */
 void
 ospf6_init ()
@@ -1726,10 +1789,16 @@
   install_element_ospf6_debug_spf ();
   install_element_ospf6_debug_route ();
   install_element_ospf6_debug_asbr ();
+  install_element_ospf6_debug_abr ();
 
   install_element (VIEW_NODE, &show_version_ospf6_cmd);
   install_element (ENABLE_NODE, &show_version_ospf6_cmd);
 
+  install_element (VIEW_NODE, &show_ipv6_ospf6_border_routers_cmd);
+  install_element (VIEW_NODE, &show_ipv6_ospf6_border_routers_detail_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_ospf6_border_routers_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_ospf6_border_routers_detail_cmd);
+
 #define INSTALL(n,c) \
   install_element (n ## _NODE, &show_ipv6_ospf6_ ## c);
 
diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h
index c738df6..3274242 100644
--- a/ospf6d/ospf6d.h
+++ b/ospf6d/ospf6d.h
@@ -22,7 +22,7 @@
 #ifndef OSPF6D_H
 #define OSPF6D_H
 
-#define OSPF6_DAEMON_VERSION    "0.9.7e"
+#define OSPF6_DAEMON_VERSION    "0.9.7i"
 
 /* global variables */
 extern int errno;
@@ -50,6 +50,12 @@
 #endif /* IPV6_DROP_MEMBERSHIP */
 #endif /* ! IPV6_LEAVE_GROUP */
 
+/* cast macro */
+#define OSPF6_PROCESS(x) ((struct ospf6 *) (x))
+#define OSPF6_AREA(x) ((struct ospf6_area *) (x))
+#define OSPF6_INTERFACE(x) ((struct ospf6_interface *) (x))
+#define OSPF6_NEIGHBOR(x) ((struct ospf6_neighbor *) (x))
+
 /* operation on timeval structure */
 #ifndef timerclear
 #define timerclear(a) (a)->tv_sec = (tvp)->tv_usec = 0