Initial revision
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
new file mode 100644
index 0000000..bd33c34
--- /dev/null
+++ b/ospfd/ospf_flood.c
@@ -0,0 +1,1048 @@
+/*
+ * OSPF Flooding -- RFC2328 Section 13.
+ * Copyright (C) 1999, 2000 Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ * 
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "linklist.h"
+#include "prefix.h"
+#include "if.h"
+#include "command.h"
+#include "table.h"
+#include "thread.h"
+#include "memory.h"
+#include "log.h"
+#include "zclient.h"
+
+#include "ospfd/ospfd.h"
+#include "ospfd/ospf_interface.h"
+#include "ospfd/ospf_ism.h"
+#include "ospfd/ospf_asbr.h"
+#include "ospfd/ospf_lsa.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
+#include "ospfd/ospf_spf.h"
+#include "ospfd/ospf_flood.h"
+#include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_abr.h"
+#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_zebra.h"
+#include "ospfd/ospf_dump.h"
+
+extern struct zclient *zclient;
+
+/* Do the LSA acking specified in table 19, Section 13.5, row 2
+ * This get called from ospf_flood_out_interface. Declared inline 
+ * for speed. */
+static void
+ospf_flood_delayed_lsa_ack (struct ospf_neighbor *inbr, struct ospf_lsa *lsa)
+{
+  /* LSA is more recent than database copy, but was not
+     flooded back out receiving interface.  Delayed
+     acknowledgment sent. If interface is in Backup state
+     delayed acknowledgment sent only if advertisement
+     received from Designated Router, otherwise do nothing See
+     RFC 2328 Section 13.5 */
+
+  /* Whether LSA is more recent or not, and whether this is in
+     response to the LSA being sent out recieving interface has been 
+     worked out previously */
+
+  /* Deal with router as BDR */
+  if (inbr->oi->state == ISM_Backup && ! NBR_IS_DR (inbr))
+    return;
+
+  /* Schedule a delayed LSA Ack to be sent */ 
+  listnode_add (inbr->oi->ls_ack, ospf_lsa_lock (lsa));
+}
+
+/* Check LSA is related to external info. */
+struct external_info *
+ospf_external_info_check (struct ospf_lsa *lsa)
+{
+  struct as_external_lsa *al;
+  struct prefix_ipv4 p;
+  struct route_node *rn;
+  int type;
+
+  al = (struct as_external_lsa *) lsa->data;
+
+  p.family = AF_INET;
+  p.prefix = lsa->data->id;
+  p.prefixlen = ip_masklen (al->mask);
+
+  for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
+    {
+      int redist_type = is_prefix_default (&p) ? DEFAULT_ROUTE : type;
+      if (ospf_is_type_redistributed (redist_type))
+	if (EXTERNAL_INFO (type))
+	  {
+	    rn = route_node_lookup (EXTERNAL_INFO (type),
+				    (struct prefix *) &p);
+	    if (rn)
+	      {
+		route_unlock_node (rn);
+		if (rn->info != NULL)
+		  return (struct external_info *) rn->info;
+	      }
+	  }
+    }
+
+  return NULL;
+}
+
+void
+ospf_process_self_originated_lsa (struct ospf_lsa *new, struct ospf_area *area)
+{
+  struct ospf_interface *oi;
+  struct external_info *ei;
+  listnode node;
+  
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("LSA[Type%d:%s]: Process self-originated LSA",
+	       new->data->type, inet_ntoa (new->data->id));
+
+  /* If we're here, we installed a self-originated LSA that we received
+     from a neighbor, i.e. it's more recent.  We must see whether we want
+     to originate it.
+     If yes, we should use this LSA's sequence number and reoriginate
+     a new instance.
+     if not --- we must flush this LSA from the domain. */
+  switch (new->data->type)
+    {
+    case OSPF_ROUTER_LSA:
+      /* Originate a new instance and schedule flooding */
+      /* It shouldn't be necessary, but anyway */
+      ospf_lsa_unlock (area->router_lsa_self);
+      area->router_lsa_self = ospf_lsa_lock (new);
+
+      ospf_router_lsa_timer_add (area);
+      return;
+    case OSPF_NETWORK_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      /* We must find the interface the LSA could belong to.
+	 If the interface is no more a broadcast type or we are no more
+	 the DR, we flush the LSA otherwise -- create the new instance and
+	 schedule flooding. */
+
+      /* Look through all interfaces, not just area, since interface
+	 could be moved from one area to another. */
+      for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+	/* These are sanity check. */
+	if ((oi = getdata (node)) != NULL)
+	  if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &new->data->id))
+	    {
+	      if (oi->area != area ||
+		  oi->type != OSPF_IFTYPE_BROADCAST ||
+		  !IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)))
+		{
+		  ospf_schedule_lsa_flush_area (area, new);
+		  return;
+		}
+	      
+#ifdef HAVE_OPAQUE_LSA
+              if (new->data->type == OSPF_OPAQUE_LINK_LSA)
+                {
+                  ospf_opaque_lsa_refresh (new);
+                  return;
+                }
+#endif /* HAVE_OPAQUE_LSA */
+
+	      ospf_lsa_unlock (oi->network_lsa_self);
+	      oi->network_lsa_self = ospf_lsa_lock (new);
+	      
+	      /* Schedule network-LSA origination. */
+	      ospf_network_lsa_timer_add (oi);
+	      return;
+	    }
+      break;
+    case OSPF_SUMMARY_LSA:
+    case OSPF_ASBR_SUMMARY_LSA:
+      ospf_schedule_abr_task ();
+      break;
+    case OSPF_AS_EXTERNAL_LSA :
+#ifdef HAVE_NSSA
+    case OSPF_AS_NSSA_LSA:
+#endif /* HAVE_NSSA */
+      ei = ospf_external_info_check (new);
+      if (ei)
+	ospf_external_lsa_refresh (new, ei, LSA_REFRESH_FORCE);
+      else
+	ospf_lsa_flush_as (new);
+      break;
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AREA_LSA:
+      ospf_opaque_lsa_refresh (new);
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      ospf_opaque_lsa_refresh (new); /* Reconsideration may needed. *//* XXX */
+      break;
+#endif /* HAVE_OPAQUE_LSA */
+    default:
+      break;
+    }
+}
+
+/* OSPF LSA flooding -- RFC2328 Section 13.(5). */
+
+/* Now Updated for NSSA operation, as follows:
+
+
+	Type-5's have no change.  Blocked to STUB or NSSA.
+
+	Type-7's can be received, and if a DR
+	they will also flood the local NSSA Area as Type-7's
+
+	If a Self-Originated LSA (now an ASBR), 
+	The LSDB will be updated as Type-5's, (for continual re-fresh)
+
+	    If an NSSA-IR it is installed/flooded as Type-7, P-bit on.
+	    if an NSSA-ABR it is installed/flooded as Type-7, P-bit off.
+
+	Later, during the ABR TASK, if the ABR is the Elected NSSA
+	translator, then All Type-7s (with P-bit ON) are Translated to
+	Type-5's and flooded to all non-NSSA/STUB areas.
+
+	During ASE Calculations, 
+	    non-ABRs calculate external routes from Type-7's
+	    ABRs calculate external routes from Type-5's and non-self Type-7s
+*/
+int
+ospf_flood (struct ospf_neighbor *nbr, struct ospf_lsa *current,
+	    struct ospf_lsa *new)
+{
+  struct ospf_interface *oi;
+  struct timeval now;
+  int lsa_ack_flag;
+
+  /* Type-7 LSA's will be flooded throughout their native NSSA area,
+     but will also be flooded as Type-5's into ABR capable links.  */
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("LSA[Flooding]: start, NBR %s (%s), cur(%p), New-LSA[%s]",
+               inet_ntoa (nbr->router_id),
+               LOOKUP (ospf_nsm_state_msg, nbr->state),
+               current,
+               dump_lsa_key (new));
+
+  lsa_ack_flag = 0;
+  oi = nbr->oi;
+
+  /* Get current time. */
+  gettimeofday (&now, NULL);
+
+  /* If there is already a database copy, and if the
+     database copy was received via flooding and installed less
+     than MinLSArrival seconds ago, discard the new LSA
+     (without acknowledging it). */
+  if (current != NULL)		/* -- endo. */
+    {
+      if (IS_LSA_SELF (current)
+      && (ntohs (current->data->ls_age)    == 0
+      &&  ntohl (current->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER))
+        {
+          if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("LSA[Flooding]: Got a self-originated LSA, "
+		       "while local one is initial instance.");
+          ; /* Accept this LSA for quick LSDB resynchronization. */
+        }
+      else if (tv_cmp (tv_sub (now, current->tv_recv),
+	               int2tv (OSPF_MIN_LS_ARRIVAL)) < 0)
+        {
+          if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("LSA[Flooding]: LSA is received recently.");
+          return -1;
+        }
+    }
+
+  /* Flood the new LSA out some subset of the router's interfaces.
+     In some cases (e.g., the state of the receiving interface is
+     DR and the LSA was received from a router other than the
+     Backup DR) the LSA will be flooded back out the receiving
+     interface. */
+  lsa_ack_flag = ospf_flood_through (nbr, new);
+
+#ifdef HAVE_OPAQUE_LSA
+  /* Remove the current database copy from all neighbors' Link state
+     retransmission lists.  AS_EXTERNAL and AS_EXTERNAL_OPAQUE does
+                                        ^^^^^^^^^^^^^^^^^^^^^^^
+     not have area ID.
+     All other (even NSSA's) do have area ID.  */
+#else /* HAVE_OPAQUE_LSA */
+  /* Remove the current database copy from all neighbors' Link state
+     retransmission lists.  Only AS_EXTERNAL does not have area ID.
+     All other (even NSSA's) do have area ID.  */
+#endif /* HAVE_OPAQUE_LSA */
+  if (current)
+    {
+      switch (current->data->type)
+        {
+        case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+        case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+          ospf_ls_retransmit_delete_nbr_all (NULL, current);
+          break;
+        default:
+          ospf_ls_retransmit_delete_nbr_all (nbr->oi->area, current);
+          break;
+        }
+    }
+
+  /* Do some internal house keeping that is needed here */
+  SET_FLAG (new->flags, OSPF_LSA_RECEIVED);
+  ospf_lsa_is_self_originated (new); /* Let it set the flag */
+
+  /* Install the new LSA in the link state database
+     (replacing the current database copy).  This may cause the
+     routing table calculation to be scheduled.  In addition,
+     timestamp the new LSA with the current time.  The flooding
+     procedure cannot overwrite the newly installed LSA until
+     MinLSArrival seconds have elapsed. */  
+
+  new = ospf_lsa_install (nbr->oi, new);
+
+#ifdef HAVE_NSSA 
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("LSA[Flooding]: Type-%d installed", new->data->type);
+
+  /* if  (new->data->type == OSPF_AS_NSSA_LSA )
+     return 0;  */
+#endif /* HAVE_NSSA */
+
+  /* Acknowledge the receipt of the LSA by sending a Link State
+     Acknowledgment packet back out the receiving interface. */
+  if (lsa_ack_flag)
+    ospf_flood_delayed_lsa_ack (nbr, new);     
+
+  /* If this new LSA indicates that it was originated by the
+     receiving router itself, the router must take special action,
+     either updating the LSA or in some cases flushing it from
+     the routing domain. */
+  if (ospf_lsa_is_self_originated (new))
+    ospf_process_self_originated_lsa (new, oi->area);
+  else
+    /* Update statistics value for OSPF-MIB. */
+    ospf_top->rx_lsa_count++;
+
+  return 0;
+}
+
+/* OSPF LSA flooding -- RFC2328 Section 13.3. */
+int
+ospf_flood_through_interface (struct ospf_interface *oi,
+			      struct ospf_neighbor *inbr,
+			      struct ospf_lsa *lsa)
+{
+  struct ospf_neighbor *onbr;
+  struct route_node *rn;
+  int retx_flag;
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_flood_through_interface(): "
+	       "considering int %s, INBR(%s), LSA[%s]",
+	       IF_NAME (oi), inbr ? inet_ntoa (inbr->router_id) : "NULL",
+               dump_lsa_key (lsa));
+
+  if (!ospf_if_is_enable (oi))
+    return 0;
+
+  /* Remember if new LSA is aded to a retransmit list. */
+  retx_flag = 0;
+
+  /* Each of the neighbors attached to this interface are examined,
+     to determine whether they must receive the new LSA.  The following
+     steps are executed for each neighbor: */
+  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+    {
+      struct ospf_lsa *ls_req;
+ 
+      if (rn->info == NULL)
+	continue;
+
+      onbr = rn->info;
+      if (IS_DEBUG_OSPF_EVENT)
+	zlog_info ("ospf_flood_through_interface(): considering nbr %s (%s)",
+		   inet_ntoa (onbr->router_id),
+                   LOOKUP (ospf_nsm_state_msg, onbr->state));
+
+      /* If the neighbor is in a lesser state than Exchange, it
+	 does not participate in flooding, and the next neighbor
+	 should be examined. */
+      if (onbr->state < NSM_Exchange)
+	continue;
+
+      /* If the adjacency is not yet full (neighbor state is
+	 Exchange or Loading), examine the Link state request
+	 list associated with this adjacency.  If there is an
+	 instance of the new LSA on the list, it indicates that
+	 the neighboring router has an instance of the LSA
+	 already.  Compare the new LSA to the neighbor's copy: */
+      if (onbr->state < NSM_Full)
+	{
+	  if (IS_DEBUG_OSPF_EVENT)
+	    zlog_info ("ospf_flood_through_interface(): nbr adj is not Full");
+	  ls_req = ospf_ls_request_lookup (onbr, lsa);
+	  if (ls_req != NULL)
+	    {
+	      int ret;
+
+	      ret = ospf_lsa_more_recent (ls_req, lsa);
+	      /* The new LSA is less recent. */
+	      if (ret > 0)
+		continue;
+	      /* The two copies are the same instance, then delete
+		 the LSA from the Link state request list. */
+	      else if (ret == 0)
+		{
+		  ospf_ls_request_delete (onbr, ls_req);
+		  ospf_check_nbr_loading (onbr);
+		  continue;
+		}
+	      /* The new LSA is more recent.  Delete the LSA
+		 from the Link state request list. */
+	      else
+		{
+		  ospf_ls_request_delete (onbr, ls_req);
+		  ospf_check_nbr_loading (onbr);
+		}
+	    }
+	}
+
+#ifdef HAVE_OPAQUE_LSA
+      if (IS_OPAQUE_LSA (lsa->data->type))
+        {
+          if (! CHECK_FLAG (onbr->options, OSPF_OPTION_O))
+            {
+              if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+                zlog_info ("Skip this neighbor: Not Opaque-capable.");
+              continue;
+            }
+
+          if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (ospf_top->opaque)
+          &&  IS_LSA_SELF (lsa)
+          &&  onbr->state == NSM_Full)
+            {
+              /* Small attempt to reduce unnecessary retransmission. */
+              if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+                zlog_info ("Skip this neighbor: Initial flushing done.");
+              continue;
+            }
+        }
+#endif /* HAVE_OPAQUE_LSA */
+
+      /* If the new LSA was received from this neighbor,
+	 examine the next neighbor. */
+#ifdef ORIGINAL_CODING
+      if (inbr)
+	if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id))
+	  continue;
+#else /* ORIGINAL_CODING */
+      if (inbr)
+        {
+          /*
+           * Triggered by LSUpd message parser "ospf_ls_upd ()".
+           * E.g., all LSAs handling here is received via network.
+           */
+          if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id))
+            {
+              if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+                zlog_info ("Skip this neighbor: inbr == onbr");
+              continue;
+            }
+        }
+      else
+        {
+          /*
+           * Triggered by MaxAge remover, so far.
+           * NULL "inbr" means flooding starts from this node.
+           */
+          if (IPV4_ADDR_SAME (&lsa->data->adv_router, &onbr->router_id))
+            {
+              if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+                zlog_info ("Skip this neighbor: lsah->adv_router == onbr");
+              continue;
+            }
+        }
+#endif /* ORIGINAL_CODING */
+
+      /* Add the new LSA to the Link state retransmission list
+	 for the adjacency. The LSA will be retransmitted
+	 at intervals until an acknowledgment is seen from
+	 the neighbor. */
+      ospf_ls_retransmit_add (onbr, lsa);
+      retx_flag = 1;
+    }
+
+  /* If in the previous step, the LSA was NOT added to any of
+     the Link state retransmission lists, there is no need to
+     flood the LSA out the interface. */
+  if (retx_flag == 0) 
+    {
+      return (inbr && inbr->oi == oi);
+    }
+
+  /* if we've received the lsa on this interface we need to perform
+     additional checking */
+  if (inbr && (inbr->oi == oi))
+    {
+      /* If the new LSA was received on this interface, and it was
+	 received from either the Designated Router or the Backup
+	 Designated Router, chances are that all the neighbors have
+	 received the LSA already. */
+      if (NBR_IS_DR (inbr) || NBR_IS_BDR (inbr))
+	{
+#ifdef HAVE_NSSA
+	  if (IS_DEBUG_OSPF_NSSA)
+	    zlog_info ("ospf_flood_through_interface(): "
+		       "DR/BDR NOT SEND to int %s", IF_NAME (oi));
+#endif /* HAVE_NSSA */
+	  return 1;
+	}
+	  
+      /* If the new LSA was received on this interface, and the
+	 interface state is Backup, examine the next interface.  The
+	 Designated Router will do the flooding on this interface.
+	 However, if the Designated Router fails the router will
+	 end up retransmitting the updates. */
+
+      if (oi->state == ISM_Backup)
+	{
+#ifdef HAVE_NSSA
+	  if (IS_DEBUG_OSPF_NSSA)
+	    zlog_info ("ospf_flood_through_interface(): "
+		       "ISM_Backup NOT SEND to int %s", IF_NAME (oi));
+#endif /* HAVE_NSSA */
+	  return 1;
+	}
+    }
+
+  /* The LSA must be flooded out the interface. Send a Link State
+     Update packet (including the new LSA as contents) out the
+     interface.  The LSA's LS age must be incremented by InfTransDelay
+     (which	must be	> 0) when it is copied into the outgoing Link
+     State Update packet (until the LS age field reaches the maximum
+     value of MaxAge). */
+
+#ifdef HAVE_NSSA
+  if (IS_DEBUG_OSPF_NSSA)
+    zlog_info ("ospf_flood_through_interface(): "
+	       "DR/BDR sending upd to int %s", IF_NAME (oi));
+#else /* ! HAVE_NSSA */
+
+  if (IS_DEBUG_OSPF_EVENT)
+    zlog_info ("ospf_flood_through_interface(): "
+	       "sending upd to int %s", IF_NAME (oi));
+#endif /* HAVE_NSSA */
+
+  /*  RFC2328  Section 13.3
+      On non-broadcast networks, separate	Link State Update
+      packets must be sent, as unicasts, to each adjacent	neighbor
+      (i.e., those in state Exchange or greater).	 The destination
+      IP addresses for these packets are the neighbors' IP
+      addresses.   */
+  if (oi->type == OSPF_IFTYPE_NBMA)
+    {
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+
+      for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+        if ((nbr = rn->info) != NULL)
+	  if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
+	    ospf_ls_upd_send_lsa (nbr, lsa, OSPF_SEND_PACKET_DIRECT);
+    }
+  else
+    ospf_ls_upd_send_lsa (oi->nbr_self, lsa, OSPF_SEND_PACKET_INDIRECT);
+
+  return 0;
+}
+
+int
+ospf_flood_through_area (struct ospf_area * area,struct ospf_neighbor *inbr,
+			 struct ospf_lsa *lsa)
+{
+  listnode node;
+  int lsa_ack_flag = 0;
+
+  /* All other types are specific to a single area (Area A).  The
+     eligible interfaces are all those interfaces attaching to the
+     Area A.  If Area A is the backbone, this includes all the virtual
+     links.  */
+  for (node = listhead (area->oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+
+      if (area->area_id.s_addr != OSPF_AREA_BACKBONE &&
+	  oi->type ==  OSPF_IFTYPE_VIRTUALLINK) 
+	continue;
+
+#ifdef HAVE_OPAQUE_LSA
+      if ((lsa->data->type == OSPF_OPAQUE_LINK_LSA) && (lsa->oi != oi))
+        {
+          /*
+           * Link local scoped Opaque-LSA should only be flooded
+           * for the link on which the LSA has received.
+           */
+          if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+            zlog_info ("Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", lsa->oi, oi);
+          continue;
+        }
+#endif /* HAVE_OPAQUE_LSA */
+
+      if (ospf_flood_through_interface (oi, inbr, lsa))
+	lsa_ack_flag = 1;
+    }
+
+  return (lsa_ack_flag);
+}
+
+int
+ospf_flood_through_as (struct ospf_neighbor *inbr, struct ospf_lsa *lsa)
+{
+  listnode node;
+  int lsa_ack_flag;
+
+  lsa_ack_flag = 0;
+
+  /* The incoming LSA is type 5 or type 7  (AS-EXTERNAL or AS-NSSA )
+
+    Divert the Type-5 LSA's to all non-NSSA/STUB areas
+
+    Divert the Type-7 LSA's to all NSSA areas
+
+     AS-external-LSAs are flooded throughout the entire AS, with the
+     exception of stub areas (see Section 3.6).  The eligible
+     interfaces are all the router's interfaces, excluding virtual
+     links and those interfaces attaching to stub areas.  */
+
+#ifdef HAVE_NSSA
+  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) /* Translated from 7  */
+    if (IS_DEBUG_OSPF_NSSA)
+      zlog_info ("Flood/AS: NSSA TRANSLATED LSA");
+#endif /* HAVE_NSSA */
+
+  for (node = listhead (ospf_top->areas); node; nextnode (node))
+    {
+      int continue_flag = 0;
+      struct ospf_area *area = getdata (node);
+      listnode if_node;
+
+      switch (area->external_routing)
+	{
+	  /* Don't send AS externals into stub areas.  Various types
+             of support for partial stub areas can be implemented
+             here.  NSSA's will receive Type-7's that have areas
+             matching the originl LSA. */
+	case OSPF_AREA_NSSA:	/* Sending Type 5 or 7 into NSSA area */
+#ifdef HAVE_NSSA
+	  /* Type-7, flood NSSA area */
+          if (lsa->data->type == OSPF_AS_NSSA_LSA) 
+	    /* We will send it. */
+	    continue_flag = 0;
+          else
+	    continue_flag = 1;  /* Skip this NSSA area for Type-5's et al */
+          break;
+#endif /* HAVE_NSSA */
+
+	case OSPF_AREA_TYPE_MAX:
+	case OSPF_AREA_STUB:
+	  continue_flag = 1;	/* Skip this area. */
+	  break;
+
+	case OSPF_AREA_DEFAULT:
+	default:
+#ifdef HAVE_NSSA
+	  /* No Type-7 into normal area */
+          if (lsa->data->type == OSPF_AS_NSSA_LSA) 
+	    continue_flag = 1; /* skip Type-7 */
+          else
+#endif /* HAVE_NSSA */
+	    continue_flag = 0;	/* Do this area. */
+	  break;
+	}
+      
+      /* Do continue for above switch.  Saves a big if then mess */
+      if (continue_flag) 
+	continue; /* main for-loop */
+      
+      /* send to every interface in this area */
+
+      for (if_node = listhead (area->oiflist); if_node; nextnode (if_node))
+	{
+	  struct ospf_interface *oi = getdata (if_node);
+
+	  /* Skip virtual links */
+	  if (oi->type !=  OSPF_IFTYPE_VIRTUALLINK)
+	    if (ospf_flood_through_interface (oi, inbr, lsa)) /* lsa */
+	      lsa_ack_flag = 1;
+	}
+    } /* main area for-loop */
+  
+  return (lsa_ack_flag);
+}
+
+int
+ospf_flood_through (struct ospf_neighbor *inbr, struct ospf_lsa *lsa)
+{
+  int lsa_ack_flag = 0;
+  
+  /* Type-7 LSA's for NSSA are flooded throughout the AS here, and
+     upon return are updated in the LSDB for Type-7's.  Later,
+     re-fresh will re-send them (and also, if ABR, packet code will
+     translate to Type-5's)
+  
+     As usual, Type-5 LSA's (if not DISCARDED because we are STUB or
+     NSSA) are flooded throughout the AS, and are updated in the
+     global table.  */
+#ifdef ORIGINAL_CODING
+  switch (lsa->data->type)
+    {
+    case OSPF_ROUTER_LSA:
+    case OSPF_NETWORK_LSA:
+    case OSPF_SUMMARY_LSA:
+    case OSPF_ASBR_SUMMARY_LSA:
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_LINK_LSA: /* ospf_flood_through_interface ? */
+    case OSPF_OPAQUE_AREA_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa);
+      break;
+    case OSPF_AS_EXTERNAL_LSA: /* Type-5 */
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      lsa_ack_flag = ospf_flood_through_as (inbr, lsa);
+      break;
+#ifdef HAVE_NSSA
+      /* Type-7 Only received within NSSA, then flooded */
+    case OSPF_AS_NSSA_LSA:
+      /* Any P-bit was installed with the Type-7. */
+      lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa);
+
+      if (IS_DEBUG_OSPF_NSSA)
+	zlog_info ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7.");
+      break;
+#endif /* HAVE_NSSA */
+    default:
+      break;
+    }
+#else /* ORIGINAL_CODING */
+  /*
+   * At the common sub-sub-function "ospf_flood_through_interface()",
+   * a parameter "inbr" will be used to distinguish the called context
+   * whether the given LSA was received from the neighbor, or the
+   * flooding for the LSA starts from this node (e.g. the LSA was self-
+   * originated, or the LSA is going to be flushed from routing domain).
+   *
+   * So, for consistency reasons, this function "ospf_flood_through()"
+   * should also allow the usage that the given "inbr" parameter to be
+   * NULL. If we do so, corresponding AREA parameter should be referred
+   * by "lsa->area", instead of "inbr->oi->area".
+   */
+  switch (lsa->data->type)
+    {
+    case OSPF_AS_EXTERNAL_LSA: /* Type-5 */
+#ifdef HAVE_OPAQUE_LSA
+    case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+      lsa_ack_flag = ospf_flood_through_as (inbr, lsa);
+      break;
+#ifdef HAVE_NSSA
+      /* Type-7 Only received within NSSA, then flooded */
+    case OSPF_AS_NSSA_LSA:
+      /* Any P-bit was installed with the Type-7. */
+
+      if (IS_DEBUG_OSPF_NSSA)
+	zlog_info ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7.");
+      /* Fallthrough */
+#endif /* HAVE_NSSA */
+    default:
+      lsa_ack_flag = ospf_flood_through_area (lsa->area, inbr, lsa);
+      break;
+    }
+#endif /* ORIGINAL_CODING */
+  
+  return (lsa_ack_flag);
+}
+
+
+
+/* Management functions for neighbor's Link State Request list. */
+void
+ospf_ls_request_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  /*
+   * We cannot make use of the newly introduced callback function
+   * "lsdb->new_lsa_hook" to replace debug output below, just because
+   * it seems no simple and smart way to pass neighbor information to
+   * the common function "ospf_lsdb_add()" -- endo.
+   */
+  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+      zlog_info ("RqstL(%lu)++, NBR(%s), LSA[%s]",
+                  ospf_ls_request_count (nbr),
+                  inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
+
+  ospf_lsdb_add (&nbr->ls_req, lsa);
+}
+
+unsigned long
+ospf_ls_request_count (struct ospf_neighbor *nbr)
+{
+  return ospf_lsdb_count_all (&nbr->ls_req);
+}
+
+int
+ospf_ls_request_isempty (struct ospf_neighbor *nbr)
+{
+  return ospf_lsdb_isempty (&nbr->ls_req);
+}
+
+/* Remove LSA from neighbor's ls-request list. */
+void
+ospf_ls_request_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  if (nbr->ls_req_last == lsa)
+    {
+      ospf_lsa_unlock (nbr->ls_req_last);
+      nbr->ls_req_last = NULL;
+    }
+
+  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))	/* -- endo. */
+      zlog_info ("RqstL(%lu)--, NBR(%s), LSA[%s]",
+                  ospf_ls_request_count (nbr),
+                  inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
+
+  ospf_lsdb_delete (&nbr->ls_req, lsa);
+}
+
+/* Remove all LSA from neighbor's ls-requenst list. */
+void
+ospf_ls_request_delete_all (struct ospf_neighbor *nbr)
+{
+  ospf_lsa_unlock (nbr->ls_req_last);
+  nbr->ls_req_last = NULL;
+  ospf_lsdb_delete_all (&nbr->ls_req);
+}
+
+/* Lookup LSA from neighbor's ls-request list. */
+struct ospf_lsa *
+ospf_ls_request_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  return ospf_lsdb_lookup (&nbr->ls_req, lsa);
+}
+
+struct ospf_lsa *
+ospf_ls_request_new (struct lsa_header *lsah)
+{
+  struct ospf_lsa *new;
+
+  new = ospf_lsa_new ();
+  new->data = ospf_lsa_data_new (OSPF_LSA_HEADER_SIZE);
+  memcpy (new->data, lsah, OSPF_LSA_HEADER_SIZE);
+
+  return new;
+}
+
+
+/* Management functions for neighbor's ls-retransmit list. */
+unsigned long
+ospf_ls_retransmit_count (struct ospf_neighbor *nbr)
+{
+  return ospf_lsdb_count_all (&nbr->ls_rxmt);
+}
+
+unsigned long
+ospf_ls_retransmit_count_self (struct ospf_neighbor *nbr, int lsa_type)
+{
+  return ospf_lsdb_count_self (&nbr->ls_rxmt, lsa_type);
+}
+
+int
+ospf_ls_retransmit_isempty (struct ospf_neighbor *nbr)
+{
+  return ospf_lsdb_isempty (&nbr->ls_rxmt);
+}
+
+/* Add LSA to be retransmitted to neighbor's ls-retransmit list. */
+void
+ospf_ls_retransmit_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  struct ospf_lsa *old;
+
+  old = ospf_ls_retransmit_lookup (nbr, lsa);
+
+  if (ospf_lsa_more_recent (old, lsa) < 0)
+    {
+      if (old)
+	{
+	  old->retransmit_counter--;
+	  ospf_lsdb_delete (&nbr->ls_rxmt, old);
+	}
+      lsa->retransmit_counter++;
+      /*
+       * We cannot make use of the newly introduced callback function
+       * "lsdb->new_lsa_hook" to replace debug output below, just because
+       * it seems no simple and smart way to pass neighbor information to
+       * the common function "ospf_lsdb_add()" -- endo.
+       */
+      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
+	  zlog_info ("RXmtL(%lu)++, NBR(%s), LSA[%s]",
+                     ospf_ls_retransmit_count (nbr),
+		     inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
+      ospf_lsdb_add (&nbr->ls_rxmt, lsa);
+    }
+}
+
+/* Remove LSA from neibghbor's ls-retransmit list. */
+void
+ospf_ls_retransmit_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  if (ospf_ls_retransmit_lookup (nbr, lsa))
+    {
+      lsa->retransmit_counter--;  
+      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))		/* -- endo. */
+	  zlog_info ("RXmtL(%lu)--, NBR(%s), LSA[%s]",
+                     ospf_ls_retransmit_count (nbr),
+		     inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
+      ospf_lsdb_delete (&nbr->ls_rxmt, lsa);
+    }
+}
+
+/* Clear neighbor's ls-retransmit list. */
+void
+ospf_ls_retransmit_clear (struct ospf_neighbor *nbr)
+{
+  struct ospf_lsdb *lsdb;
+  int i;
+
+  lsdb = &nbr->ls_rxmt;
+
+  for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
+    {
+      struct route_table *table = lsdb->type[i].db;
+      struct route_node *rn;
+      struct ospf_lsa *lsa;
+
+      for (rn = route_top (table); rn; rn = route_next (rn))
+	if ((lsa = rn->info) != NULL)
+	  ospf_ls_retransmit_delete (nbr, lsa);
+    }
+
+  ospf_lsa_unlock (nbr->ls_req_last);
+  nbr->ls_req_last = NULL;
+}
+
+/* Lookup LSA from neighbor's ls-retransmit list. */
+struct ospf_lsa *
+ospf_ls_retransmit_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
+{
+  return ospf_lsdb_lookup (&nbr->ls_rxmt, lsa);
+}
+
+/* Remove All neighbor/interface's Link State Retransmit list in area. */
+void
+ospf_ls_retransmit_delete_nbr_all (struct ospf_area *area,
+				   struct ospf_lsa *lsa)
+{
+  listnode node;
+  list oiflist = area ? area->oiflist : ospf_top->oiflist;
+  
+  for (node = listhead (oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+      struct ospf_lsa *lsr;
+      
+      if (ospf_if_is_enable (oi))
+	for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	  /* If LSA find in LS-retransmit list, then remove it. */
+	  if ((nbr = rn->info) != NULL)
+	    {
+	      lsr = ospf_ls_retransmit_lookup (nbr, lsa);
+	     
+	      /* If LSA find in ls-retransmit list, remove it. */
+	      if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
+		ospf_ls_retransmit_delete (nbr, lsr);
+	    }
+    }
+}
+
+/* Add LSA to the current database copy of all neighbors'
+   Link state retransmission lists. */
+void
+ospf_ls_retransmit_add_nbr_all (struct ospf_interface *ospfi,
+				struct ospf_lsa *lsa)
+{
+  listnode node;
+
+  for (node = listhead (ospf_top->oiflist); node; nextnode (node))
+    {
+      struct ospf_interface *oi = getdata (node);
+      struct route_node *rn;
+      struct ospf_neighbor *nbr;
+      struct ospf_lsa *old;
+
+      if (ospf_if_is_enable (oi))
+	if (OSPF_AREA_SAME (&ospfi->area, &oi->area))
+	  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
+	    if ((nbr = rn->info) != NULL)
+	      if (nbr->state == NSM_Full)
+		{
+		  if ((old = ospf_ls_retransmit_lookup (nbr, lsa)))
+		    ospf_ls_retransmit_delete (nbr, old);
+
+		  ospf_ls_retransmit_add (nbr, lsa);
+		}
+    }
+}
+
+
+/* Sets ls_age to MaxAge and floods throu the area. 
+   When we implement ASE routing, there will be anothe function
+   flushing an LSA from the whole domain. */
+void
+ospf_lsa_flush_area (struct ospf_lsa *lsa, struct ospf_area *area)
+{
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+  ospf_flood_through_area (area, NULL, lsa);
+  ospf_lsa_maxage (lsa);
+}
+
+void
+ospf_lsa_flush_as (struct ospf_lsa *lsa)
+{
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+  ospf_flood_through_as (NULL, lsa);
+  ospf_lsa_maxage (lsa);
+}
+
+/* Flush LSA through AS -- used for AS-external-LSAs. */
+void
+ospf_flush_through_as (struct ospf_lsa *lsa)
+{
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+  ospf_flood_through_as (NULL, lsa);
+  ospf_lsa_maxage (lsa);
+}