2005-05-11 Paul Jakma <paul.jakma@sun.com>

	* (general) Fix memory leaks in opaque AS-scope LSAs, reported and
	  with much debugging done by by scott collins <scollins@agile.tv>.
	  (possible backport candidate?)
	* ospf_lsa.c: (ospf_discard_from_db) dont call
	  ospf_ase_unregister_external_lsa for opaque-lsa's, opaques are
	  never registered with ase in the first place.
	* ospf_packet.c: (general) Disabuse opaque related code of its
          tendency to try gather up things into temporary lists.
          (ospf_ls_upd) remove the temporary lists opaque uses, call
          opaque functions inline, just like all other types.
          (ospf_ls_ack) ditto.
          (ospf_recv_packet) fixup sign warning.
        * ospf_opaque.c: (general) fix the unneeded use of lists, and
          untwist some of the logic.
          (ospf_opaque_self_originated_lsa_received) take a single LSA
          as argument, not a list of them. Remove the list loop. Logic
          otherwise unchanged.
          (ospf_opaque_ls_ack_received) Mostly ditto. But untwist the logic,
          move the actions up into the switch block, remove the goto's and
          sanitise the logic near the end a bit.
        * ospf_opaque.h: Adjust definitions of aforementioned functions
          in ospf_opaque.c to match.
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index 6cc0987..8eca9ee 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -2234,11 +2234,9 @@
 
 void
 ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, 
-                                          struct list *lsas)
+                                          struct ospf_lsa *lsa)
 {
   struct ospf *top;
-  struct listnode *node, *next;
-  struct ospf_lsa *lsa;
   u_char before;
 
   if ((top = oi_to_top (nbr->oi)) == NULL)
@@ -2246,37 +2244,32 @@
 
   before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque);
 
-  for (ALL_LIST_ELEMENTS (lsas, node, next, lsa))
+  /*
+   * Since these LSA entries are not yet installed into corresponding
+   * LSDB, just flush them without calling ospf_ls_maxage() afterward.
+   */
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+  switch (lsa->data->type)
     {
-      listnode_delete (lsas, lsa);
-
-      /*
-       * Since these LSA entries are not yet installed into corresponding
-       * LSDB, just flush them without calling ospf_ls_maxage() afterward.
-       */
-      lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
-      switch (lsa->data->type)
-        {
-        case OSPF_OPAQUE_LINK_LSA:
-          SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
-          ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
-          break;
-        case OSPF_OPAQUE_AREA_LSA:
-          SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
-          ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
-          break;
-        case OSPF_OPAQUE_AS_LSA:
-          SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
-          ospf_flood_through_as (top, NULL/*inbr*/, lsa);
-          break;
-        default:
-          zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
-          goto out;
-        }
-
-      ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
+    case OSPF_OPAQUE_LINK_LSA:
+      SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT);
+      ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
+      break;
+    case OSPF_OPAQUE_AREA_LSA:
+      SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT);
+      ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa);
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT);
+      ospf_flood_through_as (top, NULL/*inbr*/, lsa);
+      break;
+    default:
+      zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type);
+      goto out;
     }
 
+  ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */
+
   if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
     {
       if (IS_DEBUG_OSPF_EVENT)
@@ -2288,78 +2281,63 @@
 }
 
 void
-ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct list *acks)
+ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
 {
   struct ospf *top;
+  int delay;
+  struct ospf_interface *oi;
   struct listnode *node, *nnode;
-  struct ospf_lsa *lsa;
-  char type9_lsa_rcv = 0, type10_lsa_rcv = 0, type11_lsa_rcv = 0;
 
   if ((top = oi_to_top (nbr->oi)) == NULL)
-    goto out;
-
-  for (ALL_LIST_ELEMENTS (acks, node, nnode, lsa))
+    return;
+  
+  if (!IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
+    return;
+  
+  switch (lsa->data->type)
     {
-      switch (lsa->data->type)
-        {
-        case OSPF_OPAQUE_LINK_LSA:
-          type9_lsa_rcv = 1;
-          /* Callback function... */
-          break;
-        case OSPF_OPAQUE_AREA_LSA:
-          type10_lsa_rcv = 1;
-          /* Callback function... */
-          break;
-        case OSPF_OPAQUE_AS_LSA:
-          type11_lsa_rcv = 1;
-          /* Callback function... */
-          break;
-        default:
-          zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
-          goto out;
-        }
+    case OSPF_OPAQUE_LINK_LSA:
+      if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
+        ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
+      /* Callback function... */
+      break;
+    case OSPF_OPAQUE_AREA_LSA:
+      if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
+        ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
+      /* Callback function... */
+      break;
+    case OSPF_OPAQUE_AS_LSA:
+      if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
+        ospf_opaque_type11_lsa_rxmt_nbr_check (top);
+      /* Callback function... */
+      break;
+    default:
+      zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type);
+      return;
     }
-
+  
   if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
     {
-      int delay;
-      struct ospf_interface *oi;
-
-      if (type9_lsa_rcv
-      &&  CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT))
-        ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi);
-
-      if (type10_lsa_rcv
-      &&  CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT))
-        ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area);
-
-      if (type11_lsa_rcv
-      &&  CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT))
-        ospf_opaque_type11_lsa_rxmt_nbr_check (top);
-
-      if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque))
-        goto out; /* Blocking still in progress. */
-
       if (IS_DEBUG_OSPF_EVENT)
         zlog_debug ("Block Opaque-LSA origination: ON -> OFF");
-
-      if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
-        goto out; /* Opaque capability condition must have changed. */
-
-      /* Ok, let's start origination of Opaque-LSAs. */
-      delay = OSPF_MIN_LS_INTERVAL;
-
-      for (ALL_LIST_ELEMENTS (top->oiflist, node, nnode, oi))
-        {
-          if (! ospf_if_is_enable (oi)
-              || ospf_nbr_count_opaque_capable (oi) == 0)
-            continue;
-
-          ospf_opaque_lsa_originate_schedule (oi, &delay);
-        }
+      return; /* Blocking still in progress. */
     }
+  
+  if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE))
+    return; /* Opaque capability condition must have changed. */
 
-out:
+  /* Ok, let's start origination of Opaque-LSAs. */
+  delay = OSPF_MIN_LS_INTERVAL;
+
+  for (ALL_LIST_ELEMENTS (top->oiflist, node, nnode, oi))
+    {
+      if (! ospf_if_is_enable (oi)
+          || ospf_nbr_count_opaque_capable (oi) == 0)
+        continue;
+
+      ospf_opaque_lsa_originate_schedule (oi, &delay);
+    }
+    
   return;
 }