2003-07-12 Paul Jakma <paul@dishone.st>

	* (global): Add/fixup NSSA ABR translation functionality
	* ospfd.h: Adjust the NSSA ROLE defines. Rename STATE to TRANSLATE.
	  Rename the LSA_NSSA_GET define to LSA_OPTIONS_NSSA_GET.
	* ospfd.c: Adjust to match changes to ospfd.h
	* ospf_te.c: Adjust to match change to LSA_NSSA_GET.
	* ospf_lsa.h: slights reformatting.
	  Add new NSSA functions, ospf_translated_nssa_compare() (not
	  currently used), ospf_translated_nssa_refresh() and
	  ospf_translated_nssa_originate().
	* ospf_lsa.c: Implemented aforementioned new functions. Fix up
	  several NSSA hooks to /not/ be called for Type-5s which are
	  translated. Add additional hooks. Set the ROUTER_LSA_NT bit in
	  router-lsa flags if ABR does translation. New function,
	  ospf_lsa_translated_nssa_new() implemented. Dont register
	  translated LSAs for refreshing - instead we implicitly rely on
	  the ASBR refreshing the Type-7, and refresh the translated Type-5
	  at the same time. Some minor reformatting. Extra debug info added.
	  Also, existing debug statements modified to report LSA Id.
	* ospf_flood.c: call ospf_translated_nssa_refresh() when refreshing
	  Type-7. minor reformatting.
	* ospf_dump.c: Dump NSSA LSAs.
	* ospf_asbr.h: slight reformatting. Export
	  ospf_external_route_lookup() (though, not used. probably will
          undo this).
        * ospf_abr.c: Slight reformatting in many places. Update to match
          ospfd.h changes.
          (ospf_abr_translate_nssa): make it work, using the new ospf_lsa
	  translation functions.
	  (Several places): change struct prefix * to struct prefix_ipv4 *.
	  (might as well do the casts at higher levels). Add more debug
	  info.
	  (ospf_abr_announce_stub_defaults): announce default to NSSA areas
	  too.
	  (ospf_abr_announce_nssa_defaults): do nothing. this function
          probably should die. (see ospf_abr_announce_stub_defaults).
	  (ospf_abr_task_timer): run NSSA tasks.
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
index 8991bd7..9228251 100644
--- a/ospfd/ospf_abr.c
+++ b/ospfd/ospf_abr.c
@@ -50,7 +50,6 @@
 #include "ospfd/ospf_ase.h"
 #include "ospfd/ospf_zebra.h"
 #include "ospfd/ospf_dump.h"
-
 
 struct ospf_area_range *
 ospf_area_range_new (struct prefix_ipv4 *p)
@@ -123,8 +122,9 @@
 }
 
 struct ospf_area_range *
-ospf_area_range_lookup_next (struct ospf_area *area, struct in_addr *range_net,
-			     int first)
+ospf_area_range_lookup_next (struct ospf_area *area, 
+                             struct in_addr *range_net,
+                             int first)
 {
   struct route_node *rn;
   struct prefix_ipv4 p;
@@ -375,7 +375,7 @@
       if (IS_ROUTER_LSA_NT (rlsa))
         {
           if (IS_DEBUG_OSPF_NSSA)
-            zlog_info ("ospf_abr_nssa_am_elected: ",
+            zlog_info ("ospf_abr_nssa_am_elected: "
                        "router %s asserts Nt",
                        inet_ntoa (lsa->data->id) );
           return 0;
@@ -426,7 +426,7 @@
           if (IS_DEBUG_OSPF (nssa, NSSA))
           zlog_info ("ospf_abr_nssa_check_status: "
                      "not ABR");
-          area->NSSATranslatorState = OSPF_NSSA_STATE_DISABLED;
+          area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
           continue;
         }
       
@@ -438,7 +438,7 @@
             if (IS_DEBUG_OSPF (nssa, NSSA))
               zlog_info ("ospf_abr_nssa_check_status: "
                          "never translate");
-            area->NSSATranslatorState = OSPF_NSSA_STATE_DISABLED;
+            area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
             continue;
              
           case OSPF_NSSA_ROLE_ALWAYS:
@@ -449,21 +449,21 @@
             if (IS_DEBUG_OSPF (nssa, NSSA))
               zlog_info ("ospf_abr_nssa_check_status: "
                          "translate always");
-            area->NSSATranslatorState = OSPF_NSSA_STATE_ENABLED;
+            area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_ENABLED;
             continue;
       
           case OSPF_NSSA_ROLE_CANDIDATE:
             /* We are a candidate for Translation */
             if (ospf_abr_nssa_am_elected (area) > 0 )
               {
-                area->NSSATranslatorState = OSPF_NSSA_STATE_ENABLED;
+                area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_ENABLED;
                 if (IS_DEBUG_OSPF (nssa, NSSA))
                   zlog_info ("ospf_abr_nssa_check_status: "
                              "elected translator");
                }
             else
                {
-                 area->NSSATranslatorState = OSPF_NSSA_STATE_DISABLED;
+                 area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
                  if (IS_DEBUG_OSPF (nssa, NSSA))
                    zlog_info ("ospf_abr_nssa_check_status: "
                               "not elected");
@@ -619,52 +619,88 @@
 ospf_abr_translate_nssa (struct ospf_area *area, struct ospf_lsa *lsa)
 {
   /* Incoming Type-7 or later aggregated Type-7 
+   *
+   * LSA is skipped if P-bit is off.
+   * LSA is aggregated if within range.
+   *
+   * The Type-7 is translated, Installed/Approved as a Type-5 into
+   * global LSDB, then Flooded through AS
+   *
+   *  Later, any Unapproved Translated Type-5's are flushed/discarded 
+   */
 
-     LSA is skipped if P-bit is off.
-     LSA is aggregated if within range.
-
-     The Type-7 is translated, Installed/Approved as a Type-5 into
-     global LSDB, then Flooded through AS
-
-     Later, any Unapproved Translated Type-5's are flushed/discarded */
-
-  struct ospf_lsa *dup;
+  struct ospf_lsa *old = NULL,
+                  *new = NULL;
+  struct as_external_lsa *ext7;
+  struct prefix_ipv4 p;
 
   if (! CHECK_FLAG (lsa->data->options, OSPF_OPTION_NP))
     {
       if (IS_DEBUG_OSPF_NSSA)
-	zlog_info ("ospf_abr_nssa(): P-bit off, NO Translation");
-      return 0; 
+        zlog_info ("ospf_abr_translate_nssa(): LSA Id %s, P-bit off, NO Translation",
+                   inet_ntoa (lsa->data->id));
+      return 1; 
     }
-
+  
   if (IS_DEBUG_OSPF_NSSA)
-    zlog_info ("ospf_abr_nssa(): TRANSLATING 7 to 5");
+    zlog_info ("ospf_abr_translate_nssa(): LSA Id %s, TRANSLATING 7 to 5",
+               inet_ntoa (lsa->data->id));
 
-  /* No more P-bit. */
-  /* UNSET_FLAG (lsa->data->options, OSPF_OPTION_NP); */
+  ext7 = (struct as_external_lsa *)(lsa->data);
+  p.prefix = lsa->data->id;
+  p.prefixlen = ip_masklen (ext7->mask);
+  
+  if (ext7->e[0].fwd_addr.s_addr == OSPF_DEFAULT_DESTINATION)
+    {
+      if (IS_DEBUG_OSPF_NSSA)
+        zlog_info ("ospf_abr_translate_nssa(): LSA Id %s, "
+                   "Forward address is 0, NO Translation",
+                   inet_ntoa (lsa->data->id));
+      return 1;
+    }
+  
+  /* try find existing AS-External LSA for this prefix */
+
+  old = ospf_external_info_find_lsa (area->ospf, &p);
+
+  if (old)
+    {
+      if (IS_DEBUG_OSPF_NSSA)
+        zlog_info ("ospf_abr_translate_nssa(): " 
+                   "found old translated LSA Id %s, refreshing",
+                   inet_ntoa (old->data->id));
+            
+      /* refresh */
+      new = ospf_translated_nssa_refresh (area->ospf, lsa, old);
+      if (!new)
+        {
+          if (IS_DEBUG_OSPF_NSSA)
+            zlog_info ("ospf_abr_translate_nssa(): "
+              "could not refresh translated LSA Id %s",
+              inet_ntoa (old->data->id));
+        }
+    }
+  else
+    {
+      /* no existing external route for this LSA Id
+       * originate translated LSA 
+       */
+      
+	  if ((new = ospf_translated_nssa_originate (area->ospf, lsa)) 
+	       == NULL)
+	    {
+	      if (IS_DEBUG_OSPF_NSSA)
+	        zlog_info ("ospf_abr_translate_nssa(): Could not translate "
+	                   "Type-7 for %s to Type-5", 
+	                   inet_ntoa (lsa->data->id));
+	        return 1;
+	    }
+    }
 
   /* Area where Aggregate testing will be inserted, just like summary
      advertisements */
   /* ospf_abr_check_nssa_range (p_arg, lsa-> cost, lsa -> area); */
 
-  /* Follow thru here means no aggregation */
-  dup = ospf_lsa_dup (lsa);	/* keep LSDB intact, lock = 1 */
-
-  SET_FLAG (dup->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7  */
-  SET_FLAG (dup->flags, OSPF_LSA_APPROVED); /* So, do not remove it */
-
-  dup->data->type = OSPF_AS_EXTERNAL_LSA;  /* make Type-5 */
-
-  ospf_lsa_checksum (dup->data);
-
-  ospf_lsa_install (area->ospf, NULL, dup);  /* Install this Type-5 into LSDB, Lock = 2. */
-
-  ospf_flood_through_as (area->ospf, NULL, dup); /* flood non-NSSA/STUB areas */
-  
-  /* This translated Type-5 will go to all non-NSSA areas connected to
-     this ABR; The Type-5 could come from any of the NSSA's connected
-     to this ABR.  */
-
   return 0;
 }
 
@@ -686,51 +722,52 @@
   if (IS_DEBUG_OSPF_EVENT)
     zlog_info ("ospf_abr_announce_network_to_area(): Start");
 
-  old = ospf_lsa_lookup_by_prefix (area->lsdb, OSPF_SUMMARY_LSA, p,
-				   area->ospf->router_id);
+  old = ospf_lsa_lookup_by_prefix (area->lsdb, OSPF_SUMMARY_LSA, 
+                                   (struct prefix_ipv4 *) p,
+                                   area->ospf->router_id);
   if (old)
     {
       if (IS_DEBUG_OSPF_EVENT)
-	zlog_info ("ospf_abr_announce_network_to_area(): old summary found");
+        zlog_info ("ospf_abr_announce_network_to_area(): old summary found");
+
       sl = (struct summary_lsa *) old->data;
 
       if (IS_DEBUG_OSPF_EVENT)
-	zlog_info ("ospf_abr_announce_network_to_area(): "
-		   "old metric: %d, new metric: %d",
-		   GET_METRIC (sl->metric), cost);
-    }
-
-  if (old && (GET_METRIC (sl->metric) == cost))
-    {
-      if (IS_DEBUG_OSPF_EVENT)
-	zlog_info ("ospf_abr_announce_network_to_area(): "
-		   "old summary approved"); 
-      SET_FLAG (old->flags, OSPF_LSA_APPROVED);
+        zlog_info ("ospf_abr_announce_network_to_area(): "
+        	   "old metric: %d, new metric: %d",
+               GET_METRIC (sl->metric), cost);
+               
+      if (GET_METRIC (sl->metric) == cost)
+        {
+          /* unchanged. simply reapprove it */
+          if (IS_DEBUG_OSPF_EVENT)
+            zlog_info ("ospf_abr_announce_network_to_area(): "
+                       "old summary approved"); 
+          SET_FLAG (old->flags, OSPF_LSA_APPROVED);
+        }
+      else
+        {
+          /* LSA is changed, refresh it */
+          if (IS_DEBUG_OSPF_EVENT)
+            zlog_info ("ospf_abr_announce_network_to_area(): "
+                       "refreshing summary");
+          set_metric (old, cost);
+          lsa = ospf_summary_lsa_refresh (area->ospf, old);
+          /* This will flood through area. */
+        }
     }
   else
     {
       if (IS_DEBUG_OSPF_EVENT)
-	zlog_info ("ospf_abr_announce_network_to_area(): "
-		   "creating new summary");
-      if (old)
-	{
-
-	  set_metric (old, cost);
-	  lsa = ospf_summary_lsa_refresh (area->ospf, old);
-	  /* This will flood through area. */
-	}
-      else
-	{
-	  lsa = ospf_summary_lsa_originate (p, cost, area);
-	  /* This will flood through area. */
-	}
+        zlog_info ("ospf_abr_announce_network_to_area(): "
+        	   "creating new summary");
+      lsa = ospf_summary_lsa_originate ( (struct prefix_ipv4 *)p, cost, area);
+          /* This will flood through area. */
       
-
       SET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
       if (IS_DEBUG_OSPF_EVENT)
-	zlog_info ("ospf_abr_announce_network_to_area(): "
-		   "flooding new version of summary");
-
+        zlog_info ("ospf_abr_announce_network_to_area(): "
+        	   "flooding new version of summary");
     }
 
   if (IS_DEBUG_OSPF_EVENT)
@@ -757,7 +794,7 @@
 }
 
 int
-ospf_abr_should_accept (struct prefix *p, struct ospf_area *area)
+ospf_abr_should_accept (struct prefix_ipv4 *p, struct ospf_area *area)
 {
   if (IMPORT_NAME (area))
     {
@@ -774,7 +811,7 @@
 
 int
 ospf_abr_plist_in_check (struct ospf_area *area, struct ospf_route *or,
-			 struct prefix *p)
+			 struct prefix_ipv4 *p)
 {
   if (PREFIX_NAME_IN (area))
     {
@@ -790,7 +827,7 @@
 
 int
 ospf_abr_plist_out_check (struct ospf_area *area, struct ospf_route *or,
-			  struct prefix *p)
+			  struct prefix_ipv4 *p)
 {
   if (PREFIX_NAME_OUT (area))
     {
@@ -806,16 +843,14 @@
 
 void
 ospf_abr_announce_network (struct ospf *ospf,
-			   struct route_node *n, struct ospf_route *or)
+			   struct prefix_ipv4 *p, struct ospf_route *or)
 {
   struct ospf_area_range *range;
   struct ospf_area *area, *or_area;
-  struct prefix_ipv4 *p;
   listnode node;
 
   if (IS_DEBUG_OSPF_EVENT)
     zlog_info ("ospf_abr_announce_network(): Start");
-  p = (struct prefix_ipv4 *) &n->p;
 
   or_area = ospf_area_lookup_by_area_id (ospf, or->u.std.area_id); 
   assert (or_area);
@@ -834,7 +869,7 @@
       if (ospf_abr_nexthops_belong_to_area (or, area))
 	continue;
 
-      if (!ospf_abr_should_accept (&n->p, area))
+      if (!ospf_abr_should_accept (p, area))
 	{
 	  if (IS_DEBUG_OSPF_EVENT)
 	    zlog_info ("ospf_abr_announce_network(): "
@@ -843,7 +878,7 @@
 	  continue; 
 	}
 
-      if (!ospf_abr_plist_in_check (area, or, &n->p))
+      if (!ospf_abr_plist_in_check (area, or, p))
 	{
 	  if (IS_DEBUG_OSPF_EVENT)
 	    zlog_info ("ospf_abr_announce_network(): "
@@ -873,23 +908,23 @@
 	}
 
       if (or->path_type == OSPF_PATH_INTRA_AREA)
-	{
-	  if (IS_DEBUG_OSPF_EVENT)
-	    zlog_info ("ospf_abr_announce_network(): "
-		       "this is intra-area route to %s/%d",
-		       inet_ntoa (p->prefix), p->prefixlen);
-	  if ((range = ospf_area_range_match (or_area, p)) &&
-              !ospf_area_is_transit (area))
-	    ospf_abr_update_aggregate (range, or);
-	  else
-	    ospf_abr_announce_network_to_area (p, or->cost, area);
-	}
+        {
+          if (IS_DEBUG_OSPF_EVENT)
+            zlog_info ("ospf_abr_announce_network(): "
+                       "this is intra-area route to %s/%d",
+                       inet_ntoa (p->prefix), p->prefixlen);
+            if ((range = ospf_area_range_match (or_area, p)) 
+                 && !ospf_area_is_transit (area))
+              ospf_abr_update_aggregate (range, or);
+            else
+              ospf_abr_announce_network_to_area (p, or->cost, area);
+        }
     }
 }
 
 int
 ospf_abr_should_announce (struct ospf *ospf,
-			  struct prefix *p, struct ospf_route *or)
+			  struct prefix_ipv4 *p, struct ospf_route *or)
 {
   struct ospf_area *area;
 
@@ -933,17 +968,17 @@
       area = getdata (node);
 
       if (! area->NSSATranslatorState)
-	continue; /* skip if not translator */
+        continue; /* skip if not translator */
       
       if (area->external_routing != OSPF_AREA_NSSA)
-	continue;  /* skip if not Nssa Area */
+        continue;  /* skip if not Nssa Area */
 
       if (IS_DEBUG_OSPF_NSSA)
-	zlog_info ("ospf_abr_process_nssa_translates(): "
-		   "looking at area %s", inet_ntoa (area->area_id));
+        zlog_info ("ospf_abr_process_nssa_translates(): "
+                   "looking at area %s", inet_ntoa (area->area_id));
       
       LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
-	ospf_abr_translate_nssa (area, lsa);
+        ospf_abr_translate_nssa (area, lsa);
     }
  
   if (IS_DEBUG_OSPF_NSSA)
@@ -1004,7 +1039,7 @@
 	}
 
       if (or->path_type == OSPF_PATH_INTRA_AREA &&
-	  !ospf_abr_should_announce (ospf, &rn->p, or))
+	  !ospf_abr_should_announce (ospf, (struct prefix_ipv4 *) &rn->p, or))
 	{
 	  if (IS_DEBUG_OSPF_EVENT)
 	    zlog_info("ospf_abr_process_network_rt(): denied by export-list");
@@ -1012,7 +1047,7 @@
 	}
 
       if (or->path_type == OSPF_PATH_INTRA_AREA &&
-	  !ospf_abr_plist_out_check (area, or, &rn->p))
+	  !ospf_abr_plist_out_check (area, or, (struct prefix_ipv4 *) &rn->p))
 	{
 	  if (IS_DEBUG_OSPF_EVENT)
 	    zlog_info("ospf_abr_process_network_rt(): denied by prefix-list");
@@ -1043,7 +1078,7 @@
 
       if (IS_DEBUG_OSPF_EVENT)
 	zlog_info ("ospf_abr_process_network_rt(): announcing");
-      ospf_abr_announce_network (ospf, rn, or);
+      ospf_abr_announce_network (ospf, &rn->p, or);
     }
 
   if (IS_DEBUG_OSPF_EVENT)
@@ -1136,7 +1171,7 @@
       if (area->external_routing != OSPF_AREA_DEFAULT)
 	{
 	  if (IS_DEBUG_OSPF_EVENT)
-	    zlog_info ("ospf_abr_announce_network(): "
+	    zlog_info ("ospf_abr_announce_rtr(): "
 		       "area %s doesn't support external routing",
 		       inet_ntoa(area->area_id));
           continue;
@@ -1283,7 +1318,13 @@
 
   LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
     if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
-      UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+      {
+        UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+        if (IS_DEBUG_OSPF_NSSA)
+          zlog_info ("ospf_abr_unapprove_translates(): "
+                     "approved unset on link id %s",
+                     inet_ntoa (lsa->data->id));
+      }
 
   if (IS_DEBUG_OSPF_NSSA)
     zlog_info ("ospf_abr_unapprove_translates(): Stop");
@@ -1304,13 +1345,29 @@
   for (node = listhead (ospf->areas); node; nextnode (node))
     {
       area = getdata (node);
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_info ("ospf_abr_unapprove_summaries(): "
+                   "considering area %s",
+                   inet_ntoa (area->area_id)); 
       LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
-	if (ospf_lsa_is_self_originated (ospf, lsa))
-	  UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+      if (ospf_lsa_is_self_originated (ospf, lsa))
+        {
+          if (IS_DEBUG_OSPF_EVENT)
+            zlog_info ("ospf_abr_unapprove_summaries(): "
+                       "approved unset on summary link id %s",
+                       inet_ntoa (lsa->data->id)); 
+          UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+        }
 
       LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
-	if (ospf_lsa_is_self_originated (ospf, lsa))
-	  UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+      if (ospf_lsa_is_self_originated (ospf, lsa))
+        {
+          if (IS_DEBUG_OSPF_EVENT)
+            zlog_info ("ospf_abr_unapprove_summaries(): "
+                       "approved unset on asbr-summary link id %s",
+                       inet_ntoa (lsa->data->id));
+          UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED);
+        }
     }
 
   if (IS_DEBUG_OSPF_EVENT)
@@ -1349,7 +1406,7 @@
   struct ospf_area *area, *ar;
   struct ospf_area_range *range;
   struct route_node *rn;
-  struct prefix_ipv4 p;
+  struct prefix p;
   listnode node, n;
 
   if (IS_DEBUG_OSPF_EVENT)
@@ -1375,18 +1432,18 @@
 	      }
 
 	    p.family = AF_INET;
-	    p.prefix = range->addr;
+	    p.u.prefix4 = range->addr;
 	    p.prefixlen = range->masklen;
 
 	    if (IS_DEBUG_OSPF_EVENT)
 	      zlog_info ("ospf_abr_announce_aggregates():"
 			 " this is range: %s/%d",
-			 inet_ntoa (p.prefix), p.prefixlen);
+			 inet_ntoa (p.u.prefix4), p.prefixlen);
 
 	    if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE))
 	      {
 		p.family = AF_INET;
-		p.prefix = range->subst_addr;
+		p.u.prefix4 = range->subst_addr;
 		p.prefixlen = range->subst_masklen;
 	      }
 
@@ -1504,7 +1561,6 @@
 {
   listnode node;
   struct ospf_area *area;
-  struct prefix_ipv4 p;
 
   if (! IS_OSPF_ABR (ospf))
     return;
@@ -1512,10 +1568,6 @@
   if (IS_DEBUG_OSPF_NSSA)
     zlog_info ("ospf_abr_announce_stub_defaults(): Start");
 
-  p.family = AF_INET;
-  p.prefix.s_addr = OSPF_DEFAULT_DESTINATION;
-  p.prefixlen = 0;
-
   for (node = listhead (ospf->areas); node; nextnode (node))
     {
       area = getdata (node);
@@ -1536,7 +1588,7 @@
             zlog_info ("ospf_abr_announce_nssa_defaults(): "
                        "announcing 0.0.0.0/0 to this nssa");
           /* ospf_abr_announce_nssa_asbr_to_as (&p, area->default_cost, area); */
-          ospf_abr_announce_network_to_area (&p, area->default_cost, area);
+          /*ospf_abr_announce_network_to_area (&p, area->default_cost, area);*/
         }
     }
 }
@@ -1563,22 +1615,26 @@
     {
       area = getdata (node);
       if (IS_DEBUG_OSPF_EVENT)
-	zlog_info ("ospf_abr_announce_stub_defaults(): looking at area %s",
-		   inet_ntoa (area->area_id));
+      zlog_info ("ospf_abr_announce_stub_defaults(): looking at area %s",
+                 inet_ntoa (area->area_id));
 
+     if ( (area->external_routing != OSPF_AREA_STUB)
 #ifdef HAVE_NSSA
-      if (area->external_routing != OSPF_AREA_STUB)
-#else /* ! HAVE_NSSA */
-      if (area->external_routing == OSPF_AREA_DEFAULT)
+          && (area->external_routing != OSPF_AREA_NSSA)
 #endif /* HAVE_NSSA */
-	continue;
+        )
+       continue;
 
       if (OSPF_IS_AREA_BACKBONE (area))
-	continue; /* Sanity Check */
+        continue; /* Sanity Check */
+
+      if (area->no_summary)
+        continue;
 
       if (IS_DEBUG_OSPF_EVENT)
-	zlog_info ("ospf_abr_announce_stub_defaults(): "
-		   "announcing 0.0.0.0/0 to this area");
+      zlog_info ("ospf_abr_announce_stub_defaults(): "
+                 "announcing 0.0.0.0/0 to area %s",
+                 inet_ntoa (area->area_id));
       ospf_abr_announce_network_to_area (&p, area->default_cost, area);
     }
 
@@ -1751,10 +1807,12 @@
     zlog_info("ospf_abr_nssa_task(): send NSSA aggregates");
   ospf_abr_send_nssa_aggregates (ospf);  /*TURNED OFF FOR NOW */
 
-  /* Send any NSSA defaults as Type-5 */
-  if (IS_DEBUG_OSPF_NSSA)
-    zlog_info ("ospf_abr_nssa_task(): announce nssa defaults");
-  ospf_abr_announce_nssa_defaults (ospf);
+  /* Send any NSSA defaults as Type-5 
+   *if (IS_DEBUG_OSPF_NSSA)
+   * zlog_info ("ospf_abr_nssa_task(): announce nssa defaults");
+   *ospf_abr_announce_nssa_defaults (ospf);
+   * havnt a clue what above is supposed to do.
+   */
    
   /* Flush any unapproved previous translates from Global Data Base */
   if (IS_DEBUG_OSPF_NSSA)
@@ -1832,10 +1890,12 @@
     zlog_info ("Running ABR task on timer");
 
   ospf_check_abr_status (ospf);
+#ifdef HAVE_NSSA
+  ospf_abr_nssa_check_status (ospf);
+#endif /* HAVE_NSSA */
 
   ospf_abr_task (ospf);
 #ifdef HAVE_NSSA  
-  ospf_abr_nssa_check_status (ospf);
   ospf_abr_nssa_task (ospf); /* if nssa-abr, then scan Type-7 LSDB */
 #endif /* HAVE_NSSA */
 
diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h
index f368246..3494774 100644
--- a/ospfd/ospf_asbr.h
+++ b/ospfd/ospf_asbr.h
@@ -54,22 +54,27 @@
 
 #define OSPF_ASBR_CHECK_DELAY 30
 
-void ospf_external_route_remove (struct prefix_ipv4 *p);
+void ospf_external_route_remove (struct ospf *, struct prefix_ipv4 *);
 struct external_info *ospf_external_info_new (u_char);
-void ospf_reset_route_map_set_values (struct route_map_set_values *values);
-int ospf_route_map_set_compare (struct route_map_set_values *values1,
-				struct route_map_set_values *values2);
-struct external_info *ospf_external_info_add (u_char, struct prefix_ipv4,
-					      unsigned int, struct in_addr);
+void ospf_reset_route_map_set_values (struct route_map_set_values *);
+int ospf_route_map_set_compare (struct route_map_set_values *,
+				struct route_map_set_values *);
+struct external_info *ospf_external_info_add (u_char, 
+                                              struct prefix_ipv4,
+					      unsigned int, 
+					      struct in_addr);
 void ospf_external_info_delete (u_char, struct prefix_ipv4);
-struct external_info *ospf_external_info_lookup (u_char, struct prefix_ipv4 *);
-
-void ospf_asbr_status_update (u_char);
+struct external_info *ospf_external_info_lookup (u_char, 
+                                                 struct prefix_ipv4 *);
+struct ospf_route *ospf_external_route_lookup (struct ospf *, 
+                                               struct prefix_ipv4 *);
+void ospf_asbr_status_update (struct ospf *, u_char);
 
 void ospf_redistribute_withdraw (u_char);
 void ospf_asbr_check ();
 void ospf_schedule_asbr_check ();
 void ospf_asbr_route_install_lsa (struct ospf_lsa *);
-struct ospf_lsa *ospf_external_info_find_lsa (struct prefix_ipv4 *p);
+struct ospf_lsa *ospf_external_info_find_lsa (struct ospf *,
+					      struct prefix_ipv4 *p);
 
 #endif /* _ZEBRA_OSPF_ASBR_H */
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index f563fb8..fe75a96 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -425,8 +425,7 @@
   int i;
 
   al = (struct as_external_lsa *) STREAM_PNT (s);
-
-  zlog_info ("  AS-external-LSA");
+  zlog_info ("  %s", ospf_lsa_type_msg[al->header.type].str);
   zlog_info ("    Network Mask %s", inet_ntoa (al->mask));
 
   size = ntohs (al->header.length) - OSPF_LSA_HEADER_SIZE -4;
@@ -563,7 +562,7 @@
 	  break;
 #ifdef HAVE_NSSA
 	case OSPF_AS_NSSA_LSA:
-	  /* XXX */
+	  ospf_as_external_lsa_dump (s, length);
 	  break;
 #endif /* HAVE_NSSA */
 #ifdef HAVE_OPAQUE_LSA
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 1c8cbbf..fc6ab13 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -185,12 +185,18 @@
     case OSPF_AS_EXTERNAL_LSA :
 #ifdef HAVE_NSSA
     case OSPF_AS_NSSA_LSA:
+       if ( (new->data->type == OSPF_AS_EXTERNAL_LSA)
+             && CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT))
+         {
+           ospf_translated_nssa_refresh (ospf, NULL, new);
+           return;
+         }
 #endif /* HAVE_NSSA */
       ei = ospf_external_info_check (new);
       if (ei)
-	ospf_external_lsa_refresh (ospf, new, ei, LSA_REFRESH_FORCE);
+        ospf_external_lsa_refresh (ospf, new, ei, LSA_REFRESH_FORCE);
       else
-	ospf_lsa_flush_as (ospf, new);
+        ospf_lsa_flush_as (ospf, new);
       break;
 #ifdef HAVE_OPAQUE_LSA
     case OSPF_OPAQUE_AREA_LSA:
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 915f0fa..18ab140 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -449,12 +449,13 @@
       SET_FLAG (flags,  ROUTER_LSA_BORDER);
 #ifdef HAVE_NSSA
       /* If Area is NSSA and we are both ABR and unconditional translator, 
-       * set Nt bit 
+       * set Nt bit to inform other routers.
        */
-      SET_FLAG (flags, ROUTER_LSA_NT);
+      if ( (area->external_routing == OSPF_AREA_NSSA)
+           && (area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS))
+        SET_FLAG (flags, ROUTER_LSA_NT);
 #endif /* HAVE_NSSA */
     }
-
   return flags;
 }
 
@@ -742,13 +743,12 @@
 
 #ifdef HAVE_NSSA
   /* Set LSA common header fields. */
-  lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_NSSA_GET (area),
-		  OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
+  lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_OPTIONS_NSSA_GET (area),
 #else /* ! HAVE_NSSA */
   /* Set LSA common header fields. */
   lsa_header_set (s, LSA_OPTIONS_GET (area),
-		  OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
 #endif /* HAVE_NSSA */
+		  OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
 
   /* Set router-LSA body fields. */
   ospf_router_lsa_body_set (s, area);
@@ -1626,10 +1626,17 @@
 ospf_install_flood_nssa (struct ospf *ospf, 
 			 struct ospf_lsa *lsa, struct external_info *ei)
 {
-  struct ospf_lsa *new2;
+  struct ospf_lsa *new;
   struct as_external_lsa *extlsa;
   listnode node;
 
+  /* LSA may be a Type-5 originated via translation of a Type-7 LSA
+   * which originated from an NSSA area. In which case it should not be 
+   * flooded back to NSSA areas.
+   */
+  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
+    return;
+    
   /* NSSA Originate or Refresh (If anyNSSA)
 
   LSA is self-originated. And just installed as Type-5.
@@ -1654,14 +1661,14 @@
         continue;
 
       /* make lsa duplicate, lock=1 */
-      new2 = ospf_lsa_dup (lsa);
-      new2->area = area;
-      new2->data->type = OSPF_AS_NSSA_LSA;
+      new = ospf_lsa_dup (lsa);
+      new->area = area;
+      new->data->type = OSPF_AS_NSSA_LSA;
 
       /* set P-bit if not ABR */
       if (! IS_OSPF_ABR (ospf))
         {
-	  SET_FLAG(new2->data->options, OSPF_OPTION_NP);
+	  SET_FLAG(new->data->options, OSPF_OPTION_NP);
        
 	  /* set non-zero FWD ADDR
        
@@ -1678,8 +1685,8 @@
 	  no type-7 LSA's with the P-bit set should originate from this
 	  router.   */
        
-	  /* kevinm: not updating lsa anymore, just new2 */
-	  extlsa = (struct as_external_lsa *)(new2->data);
+	  /* kevinm: not updating lsa anymore, just new */
+	  extlsa = (struct as_external_lsa *)(new->data);
        
 	  if (extlsa->e[0].fwd_addr.s_addr == 0)
 	    extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area); /* this NSSA area in ifp */
@@ -1688,20 +1695,253 @@
 	  {
 	    if (IS_DEBUG_OSPF_NSSA)
 	      zlog_info ("LSA[Type-7]: Could not build FWD-ADDR");
-	    ospf_lsa_discard(new2);
+	    ospf_lsa_discard(new);
 	    return;
 	  }
 	}
       /* Re-calculate checksum. */
-      ospf_lsa_checksum (new2->data);
+      ospf_lsa_checksum (new->data);
 
       /* install also as Type-7 */
-      ospf_lsa_install (ospf, NULL, new2);   /* Remove Old, Lock New = 2 */
+      ospf_lsa_install (ospf, NULL, new);   /* Remove Old, Lock New = 2 */
 
       /* will send each copy, lock=2+n */
-      ospf_flood_through_as (ospf, NULL, new2); /* all attached NSSA's, no AS/STUBs */
+      ospf_flood_through_as (ospf, NULL, new); /* all attached NSSA's, no AS/STUBs */
     }
 }
+
+struct ospf_lsa *
+ospf_lsa_translated_nssa_new (struct ospf *ospf, 
+                             struct ospf_lsa *type7)
+{
+
+  struct ospf_lsa *new;
+  struct as_external_lsa *ext, *extnew;
+  struct external_info ei;
+  
+  ext = (struct as_external_lsa *)(type7->data);
+
+  /* need external_info struct, fill in bare minimum */  
+  ei.p.family = AF_INET;
+  ei.p.prefix = type7->data->id;
+  ei.p.prefixlen = ip_masklen (ext->mask);
+  ei.type = ZEBRA_ROUTE_OSPF;
+  ei.nexthop = ext->header.adv_router;
+  ei.route_map_set.metric = -1;
+  ei.route_map_set.metric_type = -1;
+  ei.tag = 0;
+  
+  if ( (new = ospf_external_lsa_new (ospf, &ei, &type7->data->id)) == NULL)
+  {
+    if (IS_DEBUG_OSPF_NSSA)
+      zlog_info ("ospf_nssa_translate_originate(): Could not originate "
+                 "Translated Type-5 for %s", 
+                 inet_ntoa (ei.p.prefix));
+    return NULL;
+  }
+
+  extnew = (struct as_external_lsa *)(new->data);
+   
+  /* copy over Type-7 data to new */
+  extnew->e[0].tos = ext->e[0].tos;
+  extnew->e[0].route_tag = ext->e[0].route_tag;
+  extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr;
+  new->data->ls_seqnum = type7->data->ls_seqnum;
+
+  /* add translated flag, checksum and lock new lsa */
+  SET_FLAG (new->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7  */   
+  ospf_lsa_checksum (new->data);
+  new = ospf_lsa_lock (new);
+  
+  return new; 
+}
+
+/* compare type-5 to type-7
+ * -1: err, 0: same, 1: different
+ */
+int
+ospf_lsa_translated_nssa_compare (struct ospf_lsa *t7, struct ospf_lsa *t5)
+{
+
+  struct as_external_lsa *e5 = (struct as_external_lsa *)t5, 
+                         *e7 = (struct as_external_lsa *)t7;
+  
+  
+  /* sanity checks */
+  if (! ((t5->data->type == OSPF_AS_EXTERNAL_LSA)
+         && (t7->data->type == OSPF_AS_NSSA_LSA)))
+    return -1;
+
+  if (t5->data->id.s_addr != t7->data->id.s_addr)
+    return -1;
+
+  if (t5->data->ls_seqnum != t7->data->ls_seqnum)
+    return LSA_REFRESH_FORCE;
+
+  if (e5->mask.s_addr != e7->mask.s_addr)
+    return LSA_REFRESH_FORCE;
+    
+  if (e5->e[0].fwd_addr.s_addr != e7->e[0].fwd_addr.s_addr)
+    return LSA_REFRESH_FORCE;
+
+  if (e5->e[0].route_tag != e7->e[0].route_tag)
+    return LSA_REFRESH_FORCE;
+    
+  if (GET_METRIC (e5->e[0].metric) != GET_METRIC (e7->e[0].metric))
+    return LSA_REFRESH_FORCE;
+    
+  return LSA_REFRESH_IF_CHANGED;
+}
+
+/* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
+struct ospf_lsa *
+ospf_translated_nssa_originate (struct ospf *ospf, struct ospf_lsa *type7)
+{
+  struct ospf_lsa *new;
+  struct as_external_lsa *extnew;
+  
+  /* we cant use ospf_external_lsa_originate() as we need to set
+   * the OSPF_LSA_LOCAL_XLT flag, must originate by hand
+   */
+  
+  if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL)
+    {
+      if (IS_DEBUG_OSPF_NSSA)
+      zlog_info ("ospf_translated_nssa_originate(): Could not translate "
+                 "Type-7, Id %s, to Type-5",
+                 inet_ntoa (type7->data->id));
+      return NULL;
+    }
+    
+  extnew = (struct as_external_lsa *)new;
+  
+  if (IS_DEBUG_OSPF_NSSA)
+    {
+      zlog_info ("ospf_translated_nssa_originate(): "
+                 "translated Type 7, installed:");
+      ospf_lsa_header_dump (new->data);
+      zlog_info ("   Network mask: %d",ip_masklen (extnew->mask));
+      zlog_info ("   Forward addr: %s", inet_ntoa (extnew->e[0].fwd_addr));
+    }
+  
+  if ( (new = ospf_lsa_install (ospf, NULL, new)) == NULL)
+    {
+      if (IS_DEBUG_OSPF_NSSA);
+        zlog_warn ("ospf_lsa_translated_nssa_originate(): "
+                   "Could not install LSA "
+                   "id %s", inet_ntoa (type7->data->id));
+      return NULL;
+    }
+    
+  ospf->lsa_originate_count++;
+  ospf_flood_through_as (ospf, NULL, new);
+
+  return new;
+}
+
+/* Refresh Translated from NSSA AS-external-LSA. */
+struct ospf_lsa *
+ospf_translated_nssa_refresh (struct ospf *ospf, struct ospf_lsa *type7, 
+                              struct ospf_lsa *type5)
+{
+  struct ospf_lsa *new = NULL;
+  
+  /* Sanity checks. */
+  assert (type7 || type5);
+  if (type7)
+    assert (type7->data);
+  if (type5)
+    assert (type5->data);
+  assert (ospf->anyNSSA);
+
+  /* get required data according to what has been given */
+  if (type7 && type5 == NULL)
+    {
+      /* find the translated Type-5 for this Type-7 */
+      struct as_external_lsa *ext = (struct as_external_lsa *)(type7->data);
+      struct prefix_ipv4 p = 
+        { 
+          .prefix = type7->data->id,
+          .prefixlen = ip_masklen (ext->mask),
+          .family = AF_INET,
+        };
+
+      type5 = ospf_external_info_find_lsa (ospf, &p);
+    }
+  else if (type5 && type7 == NULL)
+    {
+      /* find the type-7 from which supplied type-5 was translated,
+       * ie find first type-7 with same LSA Id.
+       */
+      listnode ln;
+      struct route_node *rn;
+      struct ospf_lsa *lsa;
+      struct ospf_area *area;
+          
+      LIST_LOOP (ospf->areas, area, ln)
+        {
+          if (area->external_routing != OSPF_AREA_NSSA 
+              && !type7)
+            continue;
+            
+          LSDB_LOOP (NSSA_LSDB(area), rn, lsa)
+            {
+              if (lsa->data->id.s_addr == type5->data->id.s_addr)
+                {
+                  type7 = lsa;
+                  break;
+                }
+            }
+        }
+    }
+
+  /* do we have type7? */
+  if (!type7)
+    {
+      if (IS_DEBUG_OSPF_NSSA)
+        zlog_info ("ospf_translated_nssa_refresh(): no Type-7 found for "
+                   "Type-5 LSA Id %s",
+                   inet_ntoa (type7->data->id));
+      return NULL;
+    }
+
+  /* do we have valid translated type5? */
+  if (type5 == NULL || !CHECK_FLAG (type5->flags, OSPF_LSA_LOCAL_XLT) )
+    {
+      if (IS_DEBUG_OSPF_NSSA)
+        zlog_info ("ospf_translated_nssa_refresh(): No translated Type-5 "
+                   "found for Type-7 with Id %s",
+                   inet_ntoa (type7->data->id));
+      return NULL;
+    }
+
+  /* Delete LSA from neighbor retransmit-list. */
+  ospf_ls_retransmit_delete_nbr_as (ospf, type5);
+  
+  /* create new translated LSA */
+  if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL)
+    {
+      if (IS_DEBUG_OSPF_NSSA)
+        zlog_info ("ospf_translated_nssa_refresh(): Could not translate "
+                   "Type-7 for %s to Type-5",
+                   inet_ntoa (type7->data->id));
+      return NULL;
+    }
+
+  if ( !(new = ospf_lsa_install (ospf, NULL, new)) )
+    {
+      if (IS_DEBUG_OSPF_NSSA)
+        zlog_info ("ospf_translated_nssa_refresh(): Could not install "
+                   "translated LSA, Id %s",
+                   inet_ntoa (new->data->id));
+      return NULL;
+    }
+  
+  /* Flood LSA through area. */
+  ospf_flood_through_as (ospf, NULL, new);
+
+  return new;
+}
 #endif /* HAVE_NSSA */
 
 int
@@ -1781,7 +2021,9 @@
 
 #ifdef HAVE_NSSA
   /* If there is any attached NSSA, do special handling */
-  if (ospf->anyNSSA)
+  if (ospf->anyNSSA &&
+      /* stay away from translated LSAs! */
+      !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT)))
     ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */
 #endif /* HAVE_NSSA */
 
@@ -1933,10 +2175,11 @@
       return;
     }
 #ifdef HAVE_NSSA
-  /* If LSA is selforiginated and there is NSSA area, flush
-   * Type-7 LSA's at first. */
-
-  if (IS_LSA_SELF(lsa) && (ospf->anyNSSA))
+  /* If LSA is selforiginated, not a translated LSA, and there is 
+   * NSSA area, flush Type-7 LSA's at first. 
+   */
+  if (IS_LSA_SELF(lsa) && (ospf->anyNSSA)
+      && !(CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)))
     ospf_nssa_lsa_flush (ospf, p);
 #endif /* HAVE_NSSA */
 
@@ -2035,13 +2278,22 @@
   /* Check the AS-external-LSA should be originated. */
   if (!ospf_redistribute_check (ospf, ei, &changed))
     {
+      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+        zlog_warn ("LSA[Type%d:%s]: Could not be refreshed, "
+                   "redist check fail", 
+                   lsa->data->type, inet_ntoa (lsa->data->id));
       ospf_external_lsa_flush (ospf, ei->type, &ei->p,
 			       ei->ifindex, ei->nexthop);
       return;
     }
 
   if (!changed && !force)
-    return;
+    {
+      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+        zlog_info ("LSA[Type%d:%s]: Not refreshed, not changed/forced",
+                   lsa->data->type, inet_ntoa (lsa->data->id));
+      return;
+    }
 
   /* Delete LSA from neighbor retransmit-list. */
   ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
@@ -2074,18 +2326,22 @@
 
 #ifdef HAVE_NSSA
   /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */
-  if (ospf->anyNSSA)
+  if (ospf->anyNSSA && !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT)))
     ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood per new rules */
 #endif /* HAVE_NSSA */
 
-  /* Register slef-originated LSA to refresh queue. */
-  ospf_refresher_register_lsa (ospf, new);
+  /* Register self-originated LSA to refresh queue. 
+   * Translated LSAs should not be registered, but refreshed upon 
+   * refresh of the Type-7
+   */
+  if ( !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT) )
+    ospf_refresher_register_lsa (ospf, new);
 
   /* Debug logging. */
   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
     {
       zlog_info ("LSA[Type%d:%s]: AS-external-LSA refresh",
-		 new->data->type, inet_ntoa (new->data->id));
+                 new->data->type, inet_ntoa (new->data->id));
       ospf_lsa_header_dump (new->data);
     }
 
@@ -2115,15 +2371,15 @@
       /* Set router-LSA refresh timer. */
       OSPF_TIMER_OFF (area->t_router_lsa_self);
       OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
-			  ospf_router_lsa_timer, OSPF_LS_REFRESH_TIME);
+                          ospf_router_lsa_timer, OSPF_LS_REFRESH_TIME);
       
       /* Set self-originated router-LSA. */
       ospf_lsa_unlock (area->router_lsa_self);
       area->router_lsa_self = ospf_lsa_lock (new);
 
       if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
-	zlog_info("LSA[Type%d]: ID %s is self-originated",
-		  new->data->type, inet_ntoa (new->data->id));
+        zlog_info("LSA[Type%d]: ID %s is self-originated",
+                  new->data->type, inet_ntoa (new->data->id));
     }
 
   return new;
@@ -2245,18 +2501,31 @@
       */
 
       if (!IS_LSA_SELF (new))
-	ospf_ase_incremental_update (ospf, new);
+        ospf_ase_incremental_update (ospf, new);
     }
 
 #ifdef HAVE_NSSA
-  /* There is no point to register selforiginate Type-7 LSA for
-   * refreshing. We rely on refreshing Type-5 LSA's */
-  if (IS_LSA_SELF (new) && (new->data->type == OSPF_AS_NSSA_LSA))
-    return new;
+  if (new->data->type == OSPF_AS_NSSA_LSA)
+    {
+      /* There is no point to register selforiginate Type-7 LSA for
+       * refreshing. We rely on refreshing Type-5 LSA's 
+       */
+      if (IS_LSA_SELF (new))
+        return new;
+      else
+        {
+          /* Try refresh type-5 translated LSA for this LSA, if one exists.
+           * New translations will be taken care of by the abr_task.
+           */ 
+          ospf_translated_nssa_refresh (ospf, new, NULL);
+        }
+    }
 #endif /* HAVE_NSSA */
 
-  /* Register self-originated LSA to refresh queue. */
-  if (IS_LSA_SELF (new))
+  /* Register self-originated LSA to refresh queue. 
+   * Leave Translated LSAs alone
+   */
+  if (IS_LSA_SELF (new) && !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT ) )
     ospf_refresher_register_lsa (ospf, new);
 
   return new;
@@ -2408,10 +2677,11 @@
       new = ospf_opaque_lsa_install (lsa, rt_recalc);
       break;
 #endif /* HAVE_OPAQUE_LSA */
-    default: /* NSSA, or type-6,8,9....nothing special */
 #ifdef HAVE_NSSA
+    case OSPF_AS_NSSA_LSA:
       new = ospf_external_lsa_install (ospf, lsa, rt_recalc);
 #endif /* HAVE_NSSA */
+    default: /* type-6,8,9....nothing special */
       break;
     }
 
@@ -2813,6 +3083,7 @@
       return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
       break;
     case OSPF_AS_EXTERNAL_LSA:
+    case OSPF_AS_NSSA_LSA:
 #ifdef HAVE_OPAQUE_LSA
     case OSPF_OPAQUE_LINK_LSA:
     case OSPF_OPAQUE_AREA_LSA:
@@ -3287,11 +3558,18 @@
       ospf_summary_asbr_lsa_refresh (ospf, lsa);
       break;
     case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_NSSA
+      /* Translated from NSSA Type-5s are refreshed when 
+       * from refresh of Type-7 - do not refresh these directly.
+       */
+      if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
+        break;
+#endif /* HAVE_NSSA */
       ei = ospf_external_info_check (lsa);
       if (ei)
-	ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
+        ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
       else
-	ospf_lsa_flush_as (ospf, lsa);
+        ospf_lsa_flush_as (ospf, lsa);
       break;
 #ifdef HAVE_OPAQUE_LSA
     case OSPF_OPAQUE_LINK_LSA:
@@ -3335,14 +3613,16 @@
 	% (OSPF_LSA_REFRESHER_SLOTS);
 
       if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
-	zlog_info ("LSA[Refresh]: lsa with age %d added to index %d",
-		   LS_AGE (lsa), index);
+	zlog_info ("LSA[Refresh]: lsa %s with age %d added to index %d",
+		   inet_ntoa (lsa->data->id), LS_AGE (lsa), index);
       if (!ospf->lsa_refresh_queue.qs[index])
 	ospf->lsa_refresh_queue.qs[index] = list_new ();
       listnode_add (ospf->lsa_refresh_queue.qs[index], ospf_lsa_lock (lsa));
       lsa->refresh_list = index;
       if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
-	zlog_info ("LSA[Refresh]: ospf_refresher_register_lsa(): setting refresh_list on lsa %p (slod %d)", lsa, index);
+        zlog_info ("LSA[Refresh:%s]: ospf_refresher_register_lsa(): "
+                   "setting refresh_list on lsa %p (slod %d)", 
+                   inet_ntoa (lsa->data->id), lsa, index);
     }
 }
 
@@ -3392,7 +3672,8 @@
        i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS)
     {
       if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
-	zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh index %d", i);
+	zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): "
+	           "refresh index %d", i);
 
       refresh_list = ospf->lsa_refresh_queue.qs [i];
       
@@ -3407,7 +3688,9 @@
 	      next = node->next;
 	      
 	      if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
-		zlog_info ("LSA[Refresh]: ospf_lsa_refresh_walker(): refresh lsa %p (slot %d)", lsa, i);
+		zlog_info ("LSA[Refresh:%s]: ospf_lsa_refresh_walker(): "
+		           "refresh lsa %p (slot %d)", 
+		           inet_ntoa (lsa->data->id), lsa, i);
 	      
 	      list_delete_node (refresh_list, node);
 	      ospf_lsa_unlock (lsa);
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 54c88d4..c5541c8 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -277,7 +277,9 @@
 int ospf_external_lsa_originate_timer (struct thread *);
 struct ospf_lsa *ospf_lsa_lookup (struct ospf_area *, u_int32_t,
 				  struct in_addr, struct in_addr);
-struct ospf_lsa *ospf_lsa_lookup_by_id (struct ospf_area *,u_int32_t, struct in_addr);
+struct ospf_lsa *ospf_lsa_lookup_by_id (struct ospf_area *,
+                                        u_int32_t, 
+                                        struct in_addr);
 struct ospf_lsa *ospf_lsa_lookup_by_header (struct ospf_area *,
 					    struct lsa_header *);
 int ospf_lsa_more_recent (struct ospf_lsa *, struct ospf_lsa *);
@@ -319,10 +321,10 @@
 
 #ifdef HAVE_NSSA
 struct in_addr ospf_get_nssa_ip (struct ospf_area *);
-#endif /* HAVE NSSA */
-
-#ifdef HAVE_NSSA
-struct in_addr ospf_get_nssa_ip (struct ospf_area *);
+int ospf_translated_nssa_compare (struct ospf_lsa *, struct ospf_lsa *);
+struct ospf_lsa *ospf_translated_nssa_refresh (struct ospf *, struct ospf_lsa *,
+                                   struct ospf_lsa *);
+struct ospf_lsa *ospf_translated_nssa_originate (struct ospf *, struct ospf_lsa *);
 #endif
 
 #endif /* _ZEBRA_OSPF_LSA_H */
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index aedac32..0d455ec 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -414,8 +414,8 @@
     {
     case OSPF_IFTYPE_POINTOPOINT:
       /* Take the router ID of the neighbor. */
-      if (((nbr = ospf_nbr_lookup_ptop (oi->nbrs, oi->area->top->router_id)))
-      &&  (nbr->state == NSM_Full))
+      if ((nbr = ospf_nbr_lookup_ptop (oi))
+	  && nbr->state == NSM_Full)
         {
           lp->link_id.value = nbr->router_id;
           done = 1;
@@ -429,7 +429,7 @@
 
       if (nbr->state == NSM_Full
       || (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
-      &&  ospf_nbr_count (oi->nbrs, NSM_Full) > 0))
+      &&  ospf_nbr_count (oi, NSM_Full) > 0))
         {
           lp->link_id.value = DR (oi);
           done = 1;
@@ -628,7 +628,7 @@
       zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi));
       goto out;
     }
-  if (oi->area == NULL || oi->area->top == NULL)
+  if (oi->area == NULL || oi->area->ospf == NULL)
     {
       zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
 IF_NAME (oi));
@@ -879,7 +879,7 @@
 
   options  = LSA_OPTIONS_GET (area);
 #ifdef HAVE_NSSA
-  options |= LSA_NSSA_GET (area);
+  options |= LSA_OPTIONS_NSSA_GET (area);
 #endif /* HAVE_NSSA */
   options |= OSPF_OPTION_O; /* Don't forget this :-) */
 
@@ -891,7 +891,7 @@
     zlog_info ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type, inet_ntoa (lsa_id));
 
   /* Set opaque-LSA header fields. */
-  lsa_header_set (s, options, lsa_type, lsa_id);
+  lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id);
 
   /* Set opaque-LSA body fields. */
   ospf_mpls_te_lsa_body_set (s, lp);
@@ -939,7 +939,7 @@
     }
 
   /* Install this LSA into LSDB. */
-  if (ospf_lsa_install (NULL/*oi*/, new) == NULL)
+  if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
     {
       zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
       ospf_lsa_free (new);
@@ -950,7 +950,7 @@
   lp->flags |= LPFLG_LSA_ENGAGED;
 
   /* Update new LSA origination count. */
-  area->top->lsa_originate_count++;
+  area->ospf->lsa_originate_count++;
 
   /* Flood new LSA through area. */
   ospf_flood_through_area (area, NULL/*nbr*/, new);
@@ -1059,7 +1059,7 @@
 
   /* Install this LSA into LSDB. */
   /* Given "lsa" will be freed in the next function. */
-  if (ospf_lsa_install (NULL/*oi*/, new) == NULL)
+  if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
     {
       zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
       ospf_lsa_free (new);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index cec8903..4418c77 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -1122,7 +1122,7 @@
   /* set NSSA area defaults */
   area->no_summary = 0;
   area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE;
-  area->NSSATranslatorState = OSPF_NSSA_STATE_DISABLED;
+  area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED;
   area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT;
 
   return 1;
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index ca9d9a9..23a83ff 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -344,11 +344,11 @@
 
   u_char NSSATranslatorRole;          /* NSSA configured role */
 #define OSPF_NSSA_ROLE_NEVER     0
-#define OSPF_NSSA_ROLE_ALWAYS    1
-#define OSPF_NSSA_ROLE_CANDIDATE 2
+#define OSPF_NSSA_ROLE_CANDIDATE 1
+#define OSPF_NSSA_ROLE_ALWAYS    2
   u_char NSSATranslatorState;              /* NSSA operational role */
-#define OSPF_NSSA_STATE_DISABLED 0
-#define OSPF_NSSA_STATE_ENABLED  2
+#define OSPF_NSSA_TRANSLATE_DISABLED 0
+#define OSPF_NSSA_TRANSLATE_ENABLED  1
   int NSSATranslatorStabilityInterval;
   
   u_char transit;			/* TransitCapability. */
@@ -474,9 +474,8 @@
 #define LSA_OPTIONS_GET(area) \
         (((area)->external_routing == OSPF_AREA_DEFAULT) ? OSPF_OPTION_E : 0)
 #ifdef HAVE_NSSA
-#define LSA_NSSA_GET(area) \
-        (((area)->external_routing == OSPF_AREA_NSSA) ? \
-          (area)->NSSATranslatorState : 0)
+#define LSA_OPTIONS_NSSA_GET(area) \
+        (((area)->external_routing == OSPF_AREA_NSSA)  ? OSPF_OPTION_NP : 0)
 #endif /* HAVE_NSSA */
 
 #define OSPF_TIMER_ON(T,F,V)                                                  \