]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospfd/ospf_packet.c
Merge remote-tracking branch 'polymorf/master'
[mirror_frr.git] / ospfd / ospf_packet.c
index 5a1c0916eeb5de04d7dd4fe139345320ee8351e4..be137d911604db244ef120301783daa01ca13dd4 100644 (file)
@@ -32,7 +32,8 @@
 #include "stream.h"
 #include "log.h"
 #include "sockopt.h"
-#include "md5-gnu.h"
+#include "checksum.h"
+#include "md5.h"
 
 #include "ospfd/ospfd.h"
 #include "ospfd/ospf_network.h"
@@ -48,9 +49,6 @@
 #include "ospfd/ospf_flood.h"
 #include "ospfd/ospf_dump.h"
 
-static void ospf_ls_ack_send_list (struct ospf_interface *, struct list *,
-                                  struct in_addr);
-
 /* Packet Type String. */
 const char *ospf_packet_type_str[] =
 {
@@ -62,10 +60,8 @@ const char *ospf_packet_type_str[] =
   "Link State Acknowledgment",
 };
 
-extern int in_cksum (void *ptr, int nbytes);
-
 /* OSPF authentication checking function */
-int
+static int
 ospf_auth_type (struct ospf_interface *oi)
 {
   int auth_type;
@@ -84,13 +80,6 @@ ospf_auth_type (struct ospf_interface *oi)
 
 }
 
-/* forward output pointer. */
-void
-ospf_output_forward (struct stream *s, int size)
-{
-  s->putp += size;
-}
-
 struct ospf_packet *
 ospf_packet_new (size_t size)
 {
@@ -136,6 +125,20 @@ ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
   fifo->count++;
 }
 
+/* Add new packet to head of fifo. */
+static void
+ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op)
+{
+  op->next = fifo->head;
+  
+  if (fifo->tail == NULL)
+    fifo->tail = op;
+  
+  fifo->head = op;
+  
+  fifo->count++;
+}
+
 /* Delete first packet from fifo. */
 struct ospf_packet *
 ospf_fifo_pop (struct ospf_fifo *fifo)
@@ -192,6 +195,17 @@ ospf_fifo_free (struct ospf_fifo *fifo)
 void
 ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
 {
+  if (!oi->obuf)
+    {
+      zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
+              "destination %s) called with NULL obuf, ignoring "
+              "(please report this bug)!\n",
+              IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
+              ospf_packet_type_str[stream_getc_from(op->s, 1)],
+              inet_ntoa (op->dst));
+      return;
+    }
+
   /* Add packet to end of queue. */
   ospf_fifo_push (oi->obuf, op);
 
@@ -199,6 +213,27 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
   /* ospf_fifo_debug (oi->obuf); */
 }
 
+static void
+ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op)
+{
+  if (!oi->obuf)
+    {
+      zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
+              "destination %s) called with NULL obuf, ignoring "
+              "(please report this bug)!\n",
+              IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
+              ospf_packet_type_str[stream_getc_from(op->s, 1)],
+              inet_ntoa (op->dst));
+      return;
+    }
+
+  /* Add packet to head of queue. */
+  ospf_fifo_push_head (oi->obuf, op);
+
+  /* Debug of packet fifo*/
+  /* ospf_fifo_debug (oi->obuf); */
+}
+
 void
 ospf_packet_delete (struct ospf_interface *oi)
 {
@@ -210,30 +245,19 @@ ospf_packet_delete (struct ospf_interface *oi)
     ospf_packet_free (op);
 }
 
-struct stream *
-ospf_stream_copy (struct stream *new, struct stream *s)
-{
-  new->endp = s->endp;
-  new->putp = s->putp;
-  new->getp = s->getp;
-
-  memcpy (new->data, s->data, stream_get_endp (s));
-
-  return new;
-}
-
 struct ospf_packet *
 ospf_packet_dup (struct ospf_packet *op)
 {
   struct ospf_packet *new;
 
   if (stream_get_endp(op->s) != op->length)
-    zlog_warn ("ospf_packet_dup stream %ld ospf_packet %d size mismatch",
-              STREAM_SIZE(op->s), op->length);
+    /* XXX size_t */
+    zlog_warn ("ospf_packet_dup stream %lu ospf_packet %u size mismatch",
+              (u_long)STREAM_SIZE(op->s), op->length);
 
   /* Reserve space for MD5 authentication that may be added later. */
   new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE);
-  ospf_stream_copy (new->s, op->s);
+  stream_copy (new->s, op->s);
 
   new->dst = op->dst;
   new->length = op->length;
@@ -241,28 +265,37 @@ ospf_packet_dup (struct ospf_packet *op)
   return new;
 }
 
-unsigned int
+/* XXX inline */
+static inline unsigned int
+ospf_packet_authspace (struct ospf_interface *oi)
+{
+  int auth = 0;
+
+  if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC)
+    auth = OSPF_AUTH_MD5_SIZE;
+
+  return auth;
+}
+
+static unsigned int
 ospf_packet_max (struct ospf_interface *oi)
 {
   int max;
 
-  if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC)
-    max = oi->ifp->mtu - OSPF_AUTH_MD5_SIZE;
-  else
-    max = oi->ifp->mtu;
-  
+  max = oi->ifp->mtu - ospf_packet_authspace(oi);
+
   max -= (OSPF_HEADER_SIZE + sizeof (struct ip));
 
   return max;
 }
 
 \f
-int
+static int
 ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
                        u_int16_t length)
 {
   unsigned char *ibuf;
-  struct md5_ctx ctx;
+  MD5_CTX ctx;
   unsigned char digest[OSPF_AUTH_MD5_SIZE];
   unsigned char *pdigest;
   struct crypt_key *ck;
@@ -299,10 +332,11 @@ ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
     }
       
   /* Generate a digest for the ospf packet - their digest + our digest. */
-  md5_init_ctx (&ctx);
-  md5_process_bytes (ibuf, length, &ctx);
-  md5_process_bytes (ck->auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
-  md5_finish_ctx (&ctx, digest);
+  memset(&ctx, 0, sizeof(ctx));
+  MD5Init(&ctx);
+  MD5Update(&ctx, ibuf, length);
+  MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);
+  MD5Final(digest, &ctx);
 
   /* compare the two */
   if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
@@ -321,17 +355,16 @@ ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
 /* This function is called from ospf_write(), it will detect the
    authentication scheme and if it is MD5, it will change the sequence
    and update the MD5 digest. */
-int
+static int
 ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
 {
   struct ospf_header *ospfh;
   unsigned char digest[OSPF_AUTH_MD5_SIZE];
-  struct md5_ctx ctx;
+  MD5_CTX ctx;
   void *ibuf;
-  unsigned long oldputp;
   u_int32_t t;
   struct crypt_key *ck;
-  char *auth_key;
+  const u_int8_t *auth_key;
 
   ibuf = STREAM_DATA (op->s);
   ospfh = (struct ospf_header *) ibuf;
@@ -340,43 +373,49 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
     return 0;
 
   /* We do this here so when we dup a packet, we don't have to
-     waste CPU rewriting other headers. */
+     waste CPU rewriting other headers.
+     
+     Note that quagga_time /deliberately/ is not used here */
   t = (time(NULL) & 0xFFFFFFFF);
-  oi->crypt_seqnum = ( t > oi->crypt_seqnum ? t : oi->crypt_seqnum++);
+  if (t > oi->crypt_seqnum)
+    oi->crypt_seqnum = t;
+  else
+    oi->crypt_seqnum++;
+  
   ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum); 
 
   /* Get MD5 Authentication key from auth_key list. */
   if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
-    auth_key = (char *) "";
+    auth_key = (const u_int8_t *) "";
   else
     {
-      ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
-      auth_key = (char *) ck->auth_key;
+      ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
+      auth_key = ck->auth_key;
     }
 
   /* Generate a digest for the entire packet + our secret key. */
-  md5_init_ctx (&ctx);
-  md5_process_bytes (ibuf, ntohs (ospfh->length), &ctx);
-  md5_process_bytes (auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
-  md5_finish_ctx (&ctx, digest);
+  memset(&ctx, 0, sizeof(ctx));
+  MD5Init(&ctx);
+  MD5Update(&ctx, ibuf, ntohs (ospfh->length));
+  MD5Update(&ctx, auth_key, OSPF_AUTH_MD5_SIZE);
+  MD5Final(digest, &ctx);
 
   /* Append md5 digest to the end of the stream. */
-  oldputp = stream_get_putp (op->s);
-  stream_set_putp (op->s, ntohs (ospfh->length));
   stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
-  stream_set_putp (op->s, oldputp);
 
   /* We do *NOT* increment the OSPF header length. */
   op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE;
 
   if (stream_get_endp(op->s) != op->length)
-    zlog_warn("ospf_make_md5_digest: length mismatch stream %ld ospf_packet %d", stream_get_endp(op->s), op->length);
+    /* XXX size_t */
+    zlog_warn("ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u",
+             (u_long)stream_get_endp(op->s), op->length);
 
   return OSPF_AUTH_MD5_SIZE;
 }
 
 \f
-int
+static int
 ospf_ls_req_timer (struct thread *thread)
 {
   struct ospf_neighbor *nbr;
@@ -421,10 +460,8 @@ ospf_ls_upd_timer (struct thread *thread)
       struct list *update;
       struct ospf_lsdb *lsdb;
       int i;
-      struct timeval now;
       int retransmit_interval;
 
-      gettimeofday (&now, NULL);
       retransmit_interval = OSPF_IF_PARAM (nbr->oi, retransmit_interval);
 
       lsdb = &nbr->ls_rxmt;
@@ -447,7 +484,7 @@ ospf_ls_upd_timer (struct thread *thread)
                  fired.  This is a small tweak to what is in the RFC,
                  but it will cut out out a lot of retransmit traffic
                  - MAG */
-               if (tv_cmp (tv_sub (now, lsa->tv_recv), 
+               if (tv_cmp (tv_sub (recent_relative_time (), lsa->tv_recv), 
                            int2tv (retransmit_interval)) >= 0)
                  listnode_add (update, rn->info);
            }
@@ -483,7 +520,7 @@ ospf_ls_ack_timer (struct thread *thread)
 }
 
 #ifdef WANT_OSPF_WRITE_FRAGMENT
-void
+static void
 ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph, 
                   struct msghdr *msg, unsigned int maxdatasize, 
                   unsigned int mtu, int flags, u_char type)
@@ -534,28 +571,29 @@ ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph,
       
       if (ret < 0)
         zlog_warn ("*** ospf_write_frags: sendmsg failed to %s,"
-                   " id %d, off %d, len %d failed with %s",
-                   inet_ntoa (iph->ip_dst),
-                   iph->ip_id,
-                   iph->ip_off,
-                   iph->ip_len,
-                   strerror (errno));
+                  " id %d, off %d, len %d, mtu %u failed with %s",
+                  inet_ntoa (iph->ip_dst),
+                  iph->ip_id,
+                  iph->ip_off,
+                  iph->ip_len,
+                  mtu,
+                  safe_strerror (errno));
       
       if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
         {
-          zlog_info ("ospf_write_frags: sent id %d, off %d, len %d to %s\n",
+          zlog_debug ("ospf_write_frags: sent id %d, off %d, len %d to %s\n",
                      iph->ip_id, iph->ip_off, iph->ip_len,
                      inet_ntoa (iph->ip_dst));
           if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
             {
-              zlog_info ("-----------------IP Header Dump----------------------");
+              zlog_debug ("-----------------IP Header Dump----------------------");
               ospf_ip_header_dump (iph);
-              zlog_info ("-----------------------------------------------------");
+              zlog_debug ("-----------------------------------------------------");
             }
         }
       
       iph->ip_off += offset;
-      stream_forward (op->s, iovp->iov_len);
+      stream_forward_getp (op->s, iovp->iov_len);
       iovp->iov_base = STREAM_PNT (op->s); 
     }
     
@@ -566,7 +604,7 @@ ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph,
 }
 #endif /* WANT_OSPF_WRITE_FRAGMENT */
 
-int
+static int
 ospf_write (struct thread *thread)
 {
   struct ospf *ospf = THREAD_ARG (thread);
@@ -590,7 +628,7 @@ ospf_write (struct thread *thread)
 
   node = listhead (ospf->oi_write_q);
   assert (node);
-  oi = getdata (node);
+  oi = listgetdata (node);
   assert (oi);
 
 #ifdef WANT_OSPF_WRITE_FRAGMENT
@@ -599,8 +637,12 @@ ospf_write (struct thread *thread)
     ipid = (time(NULL) & 0xffff);
 #endif /* WANT_OSPF_WRITE_FRAGMENT */
 
-  /* convenience - max OSPF data per packet */
-  maxdatasize = oi->ifp->mtu - sizeof (struct ip);
+  /* convenience - max OSPF data per packet,
+   * and reliability - not more data, than our
+   * socket can accept
+   */
+  maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) -
+    sizeof (struct ip);
   
   /* Get one packet from queue. */
   op = ospf_fifo_head (oi->obuf);
@@ -625,9 +667,9 @@ ospf_write (struct thread *thread)
   memset (&sa_dst, 0, sizeof (sa_dst));
   
   sa_dst.sin_family = AF_INET;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
   sa_dst.sin_len = sizeof(sa_dst);
-#endif /* HAVE_SIN_LEN */
+#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
   sa_dst.sin_addr = op->dst;
   sa_dst.sin_port = htons (0);
 
@@ -646,6 +688,13 @@ ospf_write (struct thread *thread)
   iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
   iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
 
+#if defined(__DragonFly__)
+  /*
+   * DragonFly's raw socket expects ip_len/ip_off in network byte order.
+   */
+  iph.ip_len = htons(iph.ip_len);
+#endif
+
 #ifdef WANT_OSPF_WRITE_FRAGMENT
   /* XXX-MT: not thread-safe at all..
    * XXX: this presumes this is only programme sending OSPF packets 
@@ -689,26 +738,28 @@ ospf_write (struct thread *thread)
   sockopt_iphdrincl_swab_systoh (&iph);
   
   if (ret < 0)
-    zlog_warn ("*** sendmsg in ospf_write to %s failed with %s",
-      inet_ntoa (iph.ip_dst), strerror (errno));
+    zlog_warn ("*** sendmsg in ospf_write failed to %s, "
+              "id %d, off %d, len %d, interface %s, mtu %u: %s",
+              inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
+              oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
 
   /* Show debug sending packet. */
   if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
     {
       if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
        {
-         zlog_info ("-----------------------------------------------------");
+         zlog_debug ("-----------------------------------------------------");
          ospf_ip_header_dump (&iph);
          stream_set_getp (op->s, 0);
          ospf_packet_dump (op->s);
        }
 
-      zlog_info ("%s sent to [%s] via [%s].",
+      zlog_debug ("%s sent to [%s] via [%s].",
                 ospf_packet_type_str[type], inet_ntoa (op->dst),
                 IF_NAME (oi));
 
       if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
-       zlog_info ("-----------------------------------------------------");
+       zlog_debug ("-----------------------------------------------------");
     }
 
   /* Now delete packet from queue. */
@@ -729,7 +780,7 @@ ospf_write (struct thread *thread)
 }
 
 /* OSPF Hello message read -- RFC2328 Section 10.5. */
-void
+static void
 ospf_hello (struct ip *iph, struct ospf_header *ospfh,
            struct stream * s, struct ospf_interface *oi, int size)
 {
@@ -748,7 +799,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
     {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
         {
-          zlog_info ("ospf_header[%s/%s]: selforiginated, "
+          zlog_debug ("ospf_header[%s/%s]: selforiginated, "
                      "dropping.",
                      ospf_packet_type_str[ospfh->type],
                      inet_ntoa (iph->ip_src));
@@ -756,13 +807,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
       return;
     }
 
-  /* If incoming interface is passive one, ignore Hello. */
-  if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
-    zlog_info ("Packet %s [HELLO:RECV]: oi is passive",
-               inet_ntoa (ospfh->router_id));
-    return;
-  }
-
   /* get neighbor prefix. */
   p.family = AF_INET;
   p.prefixlen = ip_masklen (hello->network_mask);
@@ -774,29 +818,37 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
       && oi->type != OSPF_IFTYPE_VIRTUALLINK)
     if (oi->address->prefixlen != p.prefixlen)
       {
-       zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch.",
-                  inet_ntoa (ospfh->router_id));
+       zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch on %s (configured prefix length is %d, but hello packet indicates %d).",
+                  inet_ntoa(ospfh->router_id), IF_NAME(oi),
+                  (int)oi->address->prefixlen, (int)p.prefixlen);
        return;
       }
 
-  /* Compare Hello Interval. */
-  if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
-    {
-      zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch.",
-                inet_ntoa (ospfh->router_id));
-      return;
-    }
-
   /* Compare Router Dead Interval. */
   if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval))
     {
-      zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch.",
-                inet_ntoa (ospfh->router_id));
+      zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch "
+                "(expected %u, but received %u).",
+                inet_ntoa(ospfh->router_id),
+                OSPF_IF_PARAM(oi, v_wait), ntohl(hello->dead_interval));
       return;
     }
 
+  /* Compare Hello Interval - ignored if fast-hellos are set. */
+  if (OSPF_IF_PARAM (oi, fast_hello) == 0)
+    {
+      if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
+        {
+          zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch "
+                    "(expected %u, but received %u).",
+                    inet_ntoa(ospfh->router_id),
+                    OSPF_IF_PARAM(oi, v_hello), ntohs(hello->hello_interval));
+          return;
+        }
+    }
+  
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info ("Packet %s [Hello:RECV]: Options %s",
+    zlog_debug ("Packet %s [Hello:RECV]: Options %s",
               inet_ntoa (ospfh->router_id),
               ospf_options_dump (hello->options));
 
@@ -846,7 +898,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
          return;
        }
       if (IS_DEBUG_OSPF_NSSA)
-        zlog_info ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
+        zlog_debug ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
     }
   else    
     /* The setting of the E-bit found in the Hello Packet's Options
@@ -857,8 +909,8 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
     if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) !=
        CHECK_FLAG (hello->options, OSPF_OPTION_E))
       {
-       zlog_warn ("Packet[Hello:RECV]: my options: %x, his options %x",
-                  OPTIONS (oi), hello->options);
+       zlog_warn ("Packet %s [Hello:RECV]: my options: %x, his options %x",
+                  inet_ntoa(ospfh->router_id), OPTIONS (oi), hello->options);
        return;
       }
   
@@ -871,7 +923,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
   old_state = nbr->state;
 
   /* Add event to thread. */
-  OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
 
   /*  RFC2328  Section 9.5.1
       If the router is not eligible to become Designated Router,
@@ -891,7 +943,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
   if (oi->type == OSPF_IFTYPE_NBMA &&
       (old_state == NSM_Down || old_state == NSM_Attempt))
     {
-      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
       nbr->priority = hello->priority;
       nbr->d_router = hello->d_router;
       nbr->bd_router = hello->bd_router;
@@ -901,12 +953,12 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
   if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
                              size - OSPF_HELLO_MIN_SIZE))
     {
-      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
+      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_TwoWayReceived);
       nbr->options |= hello->options;
     }
   else
     {
-      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
       /* Set neighbor information. */
       nbr->priority = hello->priority;
       nbr->d_router = hello->d_router;
@@ -950,7 +1002,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
 }
 
 /* Save DD flags/options/Seqnum received. */
-void
+static void
 ospf_db_desc_save_current (struct ospf_neighbor *nbr,
                           struct ospf_db_desc *dd)
 {
@@ -968,17 +1020,17 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
   struct ospf_lsa *new, *find;
   struct lsa_header *lsah;
 
-  stream_forward (s, OSPF_DB_DESC_MIN_SIZE);
+  stream_forward_getp (s, OSPF_DB_DESC_MIN_SIZE);
   for (size -= OSPF_DB_DESC_MIN_SIZE;
        size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE) 
     {
       lsah = (struct lsa_header *) STREAM_PNT (s);
-      stream_forward (s, OSPF_LSA_HEADER_SIZE);
+      stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
 
       /* Unknown LS type. */
       if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
        {
-         zlog_warn ("Pakcet [DD:RECV]: Unknown LS type %d.", lsah->type);
+         zlog_warn ("Packet [DD:RECV]: Unknown LS type %d.", lsah->type);
          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
          return;
        }
@@ -1020,31 +1072,51 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
 
       /* Lookup received LSA, then add LS request list. */
       find = ospf_lsa_lookup_by_header (oi->area, lsah);
-      if (!find || ospf_lsa_more_recent (find, new) < 0)
-       {
-         ospf_ls_request_add (nbr, new);
-         ospf_lsa_discard (new);
-       }
-      else
-       {
-         /* Received LSA is not recent. */
-         if (IS_DEBUG_OSPF_EVENT)
-           zlog_info ("Packet [DD:RECV]: LSA received Type %d, "
-                      "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
-         ospf_lsa_discard (new);
-         continue;
-       }
+      
+      /* ospf_lsa_more_recent is fine with NULL pointers */
+      switch (ospf_lsa_more_recent (find, new))
+        {
+          case -1:
+            /* Neighbour has a more recent LSA, we must request it */
+            ospf_ls_request_add (nbr, new);
+          case 0:
+            /* If we have a copy of this LSA, it's either less recent
+             * and we're requesting it from neighbour (the case above), or
+             * it's as recent and we both have same copy (this case).
+             *
+             * In neither of these two cases is there any point in
+             * describing our copy of the LSA to the neighbour in a
+             * DB-Summary packet, if we're still intending to do so.
+             *
+             * See: draft-ogier-ospf-dbex-opt-00.txt, describing the
+             * backward compatible optimisation to OSPF DB Exchange /
+             * DB Description process implemented here.
+             */
+            if (find)
+              ospf_lsdb_delete (&nbr->db_sum, find);
+            ospf_lsa_discard (new);
+            break;
+          default:
+            /* We have the more recent copy, nothing specific to do:
+             * - no need to request neighbours stale copy
+             * - must leave DB summary list copy alone
+             */
+            if (IS_DEBUG_OSPF_EVENT)
+              zlog_debug ("Packet [DD:RECV]: LSA received Type %d, "
+                         "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
+            ospf_lsa_discard (new);
+        }
     }
 
   /* Master */
   if (IS_SET_DD_MS (nbr->dd_flags))
     {
       nbr->dd_seqnum++;
-      /* Entire DD packet sent. */
+
+      /* Both sides have no More, then we're done with Exchange */
       if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
        OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
       else
-       /* Send new DD packet. */
        ospf_db_desc_send (nbr);
     }
   /* Slave */
@@ -1052,22 +1124,26 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
     {
       nbr->dd_seqnum = ntohl (dd->dd_seqnum);
 
-      /* When master's more flags is not set. */
-      if (!IS_SET_DD_M (dd->flags) && ospf_db_summary_isempty (nbr))
-       {
-         nbr->dd_flags &= ~(OSPF_DD_FLAG_M);
-         OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
-       }
-
-      /* Send DD pakcet in reply. */
+      /* Send DD packet in reply. 
+       * 
+       * Must be done to acknowledge the Master's DD, regardless of
+       * whether we have more LSAs ourselves to describe.
+       *
+       * This function will clear the 'More' bit, if after this DD
+       * we have no more LSAs to describe to the master..
+       */
       ospf_db_desc_send (nbr);
+      
+      /* Slave can raise ExchangeDone now, if master is also done */
+      if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
+       OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
     }
-
+  
   /* Save received neighbor values from DD. */
   ospf_db_desc_save_current (nbr, dd);
 }
 
-int
+static int
 ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
 {
   /* Is DD duplicated? */
@@ -1080,7 +1156,7 @@ ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
 }
 
 /* OSPF Database Description message read -- RFC2328 Section 10.6. */
-void
+static void
 ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
              struct stream *s, struct ospf_interface *oi, u_int16_t size)
 {
@@ -1101,9 +1177,12 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
     }
 
   /* Check MTU. */
-  if (ntohs (dd->mtu) > oi->ifp->mtu)
+  if ((OSPF_IF_PARAM (oi, mtu_ignore) == 0) && 
+      (ntohs (dd->mtu) > oi->ifp->mtu))
     {
-      zlog_warn ("Packet[DD]: MTU is larger than [%s]'s MTU", IF_NAME (oi));
+      zlog_warn ("Packet[DD]: Neighbor %s MTU %u is larger than [%s]'s MTU %u",
+                inet_ntoa (nbr->router_id), ntohs (dd->mtu),
+                IF_NAME (oi), oi->ifp->mtu);
       return;
     }
 
@@ -1125,7 +1204,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
        && (!CHECK_FLAG (dd->options, OSPF_OPTION_NP)) )
     {
       if (IS_DEBUG_OSPF_EVENT) 
-        zlog_notice ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options",
+        zlog_debug ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options",
                     inet_ntoa (nbr->router_id) );
       SET_FLAG (dd->options, OSPF_OPTION_NP);
     }
@@ -1154,13 +1233,17 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
     }
 #endif /* HAVE_OPAQUE_LSA */
 
+  /* Add event to thread. */
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
   /* Process DD packet by neighbor status. */
   switch (nbr->state)
     {
     case NSM_Down:
     case NSM_Attempt:
     case NSM_TwoWay:
-      zlog_warn ("Packet[DD]: Neighbor state is %s, packet discarded.",
+      zlog_warn ("Packet[DD]: Neighbor %s state is %s, packet discarded.",
+                inet_ntoa(nbr->router_id),
                 LOOKUP (ospf_nsm_state_msg, nbr->state));
       break;
     case NSM_Init:
@@ -1178,14 +1261,18 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
          if (IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) > 0)
            {
              /* We're Slave---obey */
-             zlog_warn ("Packet[DD]: Negotiation done (Slave).");
+             zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Slave).",
+                        inet_ntoa(nbr->router_id));
              nbr->dd_seqnum = ntohl (dd->dd_seqnum);
-             nbr->dd_flags &= ~(OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I); /* Reset I/MS */
+             
+             /* Reset I/MS */
+             UNSET_FLAG (nbr->dd_flags, (OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I));
            }
          else
            {
              /* We're Master, ignore the initial DBD from Slave */
-             zlog_warn ("Packet[DD]: Initial DBD from Slave, ignoring.");
+             zlog_info ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
+                        "ignoring.", inet_ntoa(nbr->router_id));
              break;
            }
        }
@@ -1194,12 +1281,15 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
               ntohl (dd->dd_seqnum) == nbr->dd_seqnum &&
               IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) < 0)
        {
-         zlog_warn ("Packet[DD]: Negotiation done (Master).");
-         nbr->dd_flags &= ~OSPF_DD_FLAG_I;
+         zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Master).",
+                    inet_ntoa(nbr->router_id));
+          /* Reset I, leaving MS */
+          UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_I);
        }
       else
        {
-         zlog_warn ("Packet[DD]: Negotiation fails.");
+         zlog_warn ("Packet[DD]: Neighbor %s Negotiation fails.",
+                    inet_ntoa(nbr->router_id));
          break;
        }
       
@@ -1210,14 +1300,17 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
       if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
         {
           if (IS_DEBUG_OSPF_EVENT)
-            zlog_info ("Neighbor[%s] is %sOpaque-capable.",
+            zlog_debug ("Neighbor[%s] is %sOpaque-capable.",
                       inet_ntoa (nbr->router_id),
                       CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT ");
 
           if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)
           &&  IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
             {
-              zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; Opaque-LSAs cannot be reliably advertised in this network.", inet_ntoa (nbr->router_id));
+              zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; "
+                         "Opaque-LSAs cannot be reliably advertised "
+                         "in this network.",
+                         inet_ntoa (nbr->router_id));
               /* This situation is undesirable, but not a real error. */
             }
         }
@@ -1233,11 +1326,13 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
        {
          if (IS_SET_DD_MS (nbr->dd_flags))
            /* Master: discard duplicated DD packet. */
-           zlog_warn ("Packet[DD] (Master): packet duplicated.");
+           zlog_info ("Packet[DD] (Master): Neighbor %s packet duplicated.",
+                      inet_ntoa (nbr->router_id));
          else
            /* Slave: cause to retransmit the last Database Description. */
            {
-             zlog_warn ("Packet[DD] [Slave]: packet duplicated.");
+             zlog_info ("Packet[DD] [Slave]: Neighbor %s packet duplicated.",
+                        inet_ntoa (nbr->router_id));
              ospf_db_desc_resend (nbr);
            }
          break;
@@ -1247,18 +1342,20 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
       /* Check Master/Slave bit mismatch */
       if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags))
        {
-         zlog_warn ("Packet[DD]: MS-bit mismatch.");
+         zlog_warn ("Packet[DD]: Neighbor %s MS-bit mismatch.",
+                    inet_ntoa(nbr->router_id));
          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
          if (IS_DEBUG_OSPF_EVENT)
-           zlog_info ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
-                      dd->flags, nbr->dd_flags);
+           zlog_debug ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
+                       dd->flags, nbr->dd_flags);
          break;
        }
 
       /* Check initialize bit is set. */
       if (IS_SET_DD_I (dd->flags))
        {
-         zlog_warn ("Packet[DD]: I-bit set.");
+         zlog_info ("Packet[DD]: Neighbor %s I-bit set.",
+                    inet_ntoa(nbr->router_id));
          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
          break;
        }
@@ -1270,7 +1367,8 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
          /* Save the new options for debugging */
          nbr->options = dd->options;
 #endif /* ORIGINAL_CODING */
-         zlog_warn ("Packet[DD]: options mismatch.");
+         zlog_warn ("Packet[DD]: Neighbor %s options mismatch.",
+                    inet_ntoa(nbr->router_id));
          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
          break;
        }
@@ -1281,7 +1379,8 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
          (!IS_SET_DD_MS (nbr->dd_flags) &&
           ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1))
        {
-         zlog_warn ("Pakcet[DD]: sequence number mismatch.");
+         zlog_warn ("Packet[DD]: Neighbor %s sequence number mismatch.",
+                    inet_ntoa(nbr->router_id));
          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
          break;
        }
@@ -1296,13 +1395,15 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
          if (IS_SET_DD_MS (nbr->dd_flags))
            {
              /* Master should discard duplicate DD packet. */
-             zlog_warn ("Pakcet[DD]: duplicated, packet discarded.");
+             zlog_info ("Packet[DD]: Neighbor %s duplicated, "
+                        "packet discarded.",
+                       inet_ntoa(nbr->router_id));
              break;
            }
          else
            {
              struct timeval t, now;
-             gettimeofday (&now, NULL);
+             quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
              t = tv_sub (now, nbr->last_send_ts);
              if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)
                {
@@ -1324,7 +1425,8 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
       OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
       break;
     default:
-      zlog_warn ("Packet[DD]: NSM illegal status.");
+      zlog_warn ("Packet[DD]: Neighbor %s NSM illegal status %u.",
+                inet_ntoa(nbr->router_id), nbr->state);
       break;
     }
 }
@@ -1332,7 +1434,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
 #define OSPF_LSA_KEY_SIZE       12 /* type(4) + id(4) + ar(4) */
 
 /* OSPF Link State Request Read -- RFC2328 Section 10.7. */
-void
+static void
 ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
             struct stream *s, struct ospf_interface *oi, u_int16_t size)
 {
@@ -1355,12 +1457,17 @@ ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
       return;
     }
 
+  /* Add event to thread. */
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
   /* Neighbor State should be Exchange or later. */
   if (nbr->state != NSM_Exchange &&
       nbr->state != NSM_Loading &&
       nbr->state != NSM_Full)
     {
-      zlog_warn ("Link State Request: Neighbor state is %s, packet discarded.",
+      zlog_warn ("Link State Request received from %s: "
+                "Neighbor state is %s, packet discarded.",
+                inet_ntoa (ospfh->router_id),
                 LOOKUP (ospf_nsm_state_msg, nbr->state));
       return;
     }
@@ -1393,8 +1500,8 @@ ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
          return;
        }
 
-      /* Packet overflows MTU size, send immediatly. */
-      if (length + ntohs (find->data->length) > OSPF_PACKET_MAX (oi))
+      /* Packet overflows MTU size, send immediately. */
+      if (length + ntohs (find->data->length) > ospf_packet_max (oi))
        {
          if (oi->type == OSPF_IFTYPE_NBMA)
            ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
@@ -1446,7 +1553,7 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
   size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */
 
   for (; size >= OSPF_LSA_HEADER_SIZE && count > 0;
-       size -= length, stream_forward (s, length), count--)
+       size -= length, stream_forward_getp (s, length), count--)
     {
       lsah = (struct lsa_header *) STREAM_PNT (s);
       length = ntohs (lsah->length);
@@ -1503,7 +1610,7 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
              && nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) 
             {
               if (IS_DEBUG_OSPF_EVENT)
-                zlog_info ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));
+                zlog_debug ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));
               continue;
             }
         }
@@ -1539,7 +1646,7 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
       memcpy (lsa->data, lsah, length);
 
       if (IS_DEBUG_OSPF_EVENT)
-       zlog_info("LSA[Type%d:%s]: %p new LSA created with Link State Update",
+       zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update",
                  lsa->data->type, inet_ntoa (lsa->data->id), lsa);
       listnode_add (lsas, lsa);
     }
@@ -1548,30 +1655,26 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
 }
 
 /* Cleanup Update list. */
-void
+static void
 ospf_upd_list_clean (struct list *lsas)
 {
-  struct listnode *node;
+  struct listnode *node, *nnode;
   struct ospf_lsa *lsa;
 
-  for (node = listhead (lsas); node; nextnode (node))
-    if ((lsa = getdata (node)) != NULL)
-      ospf_lsa_discard (lsa);
+  for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
+    ospf_lsa_discard (lsa);
 
   list_delete (lsas);
 }
 
 /* OSPF Link State Update message read -- RFC2328 Section 13. */
-void
+static void
 ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
             struct stream *s, struct ospf_interface *oi, u_int16_t size)
 {
   struct ospf_neighbor *nbr;
   struct list *lsas;
-#ifdef HAVE_OPAQUE_LSA
-  struct list *mylsa_acks, *mylsa_upds;
-#endif /* HAVE_OPAQUE_LSA */
-  struct listnode *node, *next;
+  struct listnode *node, *nnode;
   struct ospf_lsa *lsa = NULL;
   /* unsigned long ls_req_found = 0; */
 
@@ -1589,11 +1692,16 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
       return;
     }
 
+  /* Add event to thread. */
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
   /* Check neighbor state. */
   if (nbr->state < NSM_Exchange)
     {
-      zlog_warn ("Link State Update: Neighbor[%s] state is less than Exchange",
-                inet_ntoa (ospfh->router_id));
+      zlog_warn ("Link State Update: "
+                "Neighbor[%s] state %s is less than Exchange",
+                inet_ntoa (ospfh->router_id),
+                LOOKUP(ospf_nsm_state_msg, nbr->state));
       return;
     }
 
@@ -1604,13 +1712,6 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
   lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);
 
 #ifdef HAVE_OPAQUE_LSA
-  /*
-   * Prepare two kinds of lists to clean up unwanted self-originated
-   * Opaque-LSAs from the routing domain as soon as possible.
-   */
-  mylsa_acks = list_new (); /* Let the sender cease retransmission. */
-  mylsa_upds = list_new (); /* Flush target LSAs if necessary. */
-
   /*
    * If self-originated Opaque-LSAs that have flooded before restart
    * are contained in the received LSUpd message, corresponding LSReq
@@ -1619,32 +1720,31 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
    * updating for the same LSA would take place alternately, this trick
    * must be done before entering to the loop below.
    */
+   /* XXX: Why is this Opaque specific? Either our core code is deficient
+    * and this should be fixed generally, or Opaque is inventing strawman
+    * problems */
    ospf_opaque_adjust_lsreq (nbr, lsas);
 #endif /* HAVE_OPAQUE_LSA */
 
 #define DISCARD_LSA(L,N) {\
         if (IS_DEBUG_OSPF_EVENT) \
-          zlog_info ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \
+          zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \
         ospf_lsa_discard (L); \
        continue; }
 
   /* Process each LSA received in the one packet. */
-  for (node = listhead (lsas); node; node = next)
+  for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
     {
       struct ospf_lsa *ls_ret, *current;
       int ret = 1;
 
-      next = node->next;
-
-      lsa = getdata (node);
-
       if (IS_DEBUG_OSPF_NSSA)
        {
          char buf1[INET_ADDRSTRLEN];
          char buf2[INET_ADDRSTRLEN];
          char buf3[INET_ADDRSTRLEN];
 
-         zlog_info("LSA Type-%d from %s, ID: %s, ADV: %s",
+         zlog_debug("LSA Type-%d from %s, ID: %s, ADV: %s",
                  lsa->data->type,
                  inet_ntop (AF_INET, &ospfh->router_id,
                             buf1, INET_ADDRSTRLEN),
@@ -1675,17 +1775,17 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
         /* Reject from STUB or NSSA */
         if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) 
          {
-           DISCARD_LSA (lsa, 1);
            if (IS_DEBUG_OSPF_NSSA)
-             zlog_info("Incoming External LSA Discarded: We are NSSA/STUB Area");
+             zlog_debug("Incoming External LSA Discarded: We are NSSA/STUB Area");
+           DISCARD_LSA (lsa, 1);
          }
 
       if (lsa->data->type == OSPF_AS_NSSA_LSA)
        if (nbr->oi->area->external_routing != OSPF_AREA_NSSA)
          {
-           DISCARD_LSA (lsa,2);
            if (IS_DEBUG_OSPF_NSSA)
-             zlog_info("Incoming NSSA LSA Discarded:  Not NSSA Area");
+             zlog_debug("Incoming NSSA LSA Discarded:  Not NSSA Area");
+           DISCARD_LSA (lsa,2);
          }
 
       /* Find the LSA in the current database. */
@@ -1705,7 +1805,8 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
          ospf_ls_ack_send (nbr, lsa);
 
          /* Discard LSA. */      
-         zlog_warn ("Link State Update: LS age is equal to MaxAge.");
+         zlog_info ("Link State Update[%s]: LS age is equal to MaxAge.",
+                    dump_lsa_key(lsa));
           DISCARD_LSA (lsa, 3);
        }
 
@@ -1742,18 +1843,23 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
            * Otherwise, the LSA instance remains in the routing domain
            * until its age reaches to MaxAge.
            */
+          /* XXX: We should deal with this for *ALL* LSAs, not just opaque */
           if (current == NULL)
             {
               if (IS_DEBUG_OSPF_EVENT)
-                zlog_info ("LSA[%s]: Previously originated Opaque-LSA, not found in the LSDB.", dump_lsa_key (lsa));
+                zlog_debug ("LSA[%s]: Previously originated Opaque-LSA,"
+                            "not found in the LSDB.", dump_lsa_key (lsa));
 
               SET_FLAG (lsa->flags, OSPF_LSA_SELF);
-              listnode_add (mylsa_upds, ospf_lsa_dup  (lsa));
-              listnode_add (mylsa_acks, ospf_lsa_lock (lsa));
+              
+              ospf_opaque_self_originated_lsa_received (nbr, lsa);
+              ospf_ls_ack_send (nbr, lsa);
+              
               continue;
             }
         }
 #endif /* HAVE_OPAQUE_LSA */
+
       /* It might be happen that received LSA is self-originated network LSA, but
        * router ID is cahnged. So, we should check if LSA is a network-LSA whose
        * Link State ID is one of the router's own IP interface addresses but whose
@@ -1763,12 +1869,12 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
 
       if(lsa->data->type == OSPF_NETWORK_LSA)
       {
-        struct listnode *oi_node;
+        struct listnode *oinode, *oinnode;
+        struct ospf_interface *out_if;
         int Flag = 0;
 
-        for(oi_node = listhead(oi->ospf->oiflist); oi_node; oi_node = nextnode(oi_node))
+        for (ALL_LIST_ELEMENTS (oi->ospf->oiflist, oinode, oinnode, out_if))
         {
-          struct ospf_interface *out_if = getdata(oi_node);
           if(out_if == NULL)
             break;
 
@@ -1779,7 +1885,7 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
             {
               ospf_lsa_flush_area(lsa,out_if->area);
               if(IS_DEBUG_OSPF_EVENT)
-                zlog_info ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d",
+                zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d",
                             lsa, (int) lsa->data->type);
               ospf_lsa_discard (lsa);
               Flag = 1;
@@ -1815,16 +1921,13 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
       if (ospf_ls_request_lookup (nbr, lsa))
        {
          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
-         zlog_warn ("LSA instance exists on Link state request list");
+         zlog_warn("LSA[%s] instance exists on Link state request list",
+                   dump_lsa_key(lsa));
 
          /* Clean list of LSAs. */
           ospf_upd_list_clean (lsas);
          /* this lsa is not on lsas list already. */
          ospf_lsa_discard (lsa);
-#ifdef HAVE_OPAQUE_LSA
-          list_delete (mylsa_acks);
-          list_delete (mylsa_upds);
-#endif /* HAVE_OPAQUE_LSA */
          return;
        }
 
@@ -1891,48 +1994,29 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
            {
              struct timeval now;
              
-             gettimeofday (&now, NULL);
+             quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
              
              if (tv_cmp (tv_sub (now, current->tv_orig), 
-                         int2tv (OSPF_MIN_LS_ARRIVAL)) > 0)
+                         int2tv (OSPF_MIN_LS_ARRIVAL)) >= 0)
                /* Trap NSSA type later.*/
                ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
              DISCARD_LSA (lsa, 8);
            }
        }
     }
-  
-#ifdef HAVE_OPAQUE_LSA
-  /*
-   * Now that previously originated Opaque-LSAs those which not yet
-   * installed into LSDB are captured, take several steps to clear
-   * them completely from the routing domain, before proceeding to
-   * origination for the current target Opaque-LSAs.
-   */
-  while (listcount (mylsa_acks) > 0)
-    ospf_ls_ack_send_list (oi, mylsa_acks, nbr->address.u.prefix4);
-
-  if (listcount (mylsa_upds) > 0)
-    ospf_opaque_self_originated_lsa_received (nbr, mylsa_upds);
-
-  list_delete (mylsa_upds);
-  list_delete (mylsa_acks);
-#endif /* HAVE_OPAQUE_LSA */
+#undef DISCARD_LSA
 
   assert (listcount (lsas) == 0);
   list_delete (lsas);
 }
 
 /* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
-void
+static void
 ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
             struct stream *s, struct ospf_interface *oi, u_int16_t size)
 {
   struct ospf_neighbor *nbr;
-#ifdef HAVE_OPAQUE_LSA
-  struct list *opaque_acks;
-#endif /* HAVE_OPAQUE_LSA */
-
+  
   /* increment statistics. */
   oi->ls_ack_in++;
 
@@ -1944,16 +2028,18 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
       return;
     }
 
+  /* Add event to thread. */
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
   if (nbr->state < NSM_Exchange)
     {
-      zlog_warn ("Link State Acknowledgment: State is less than Exchange.");
+      zlog_warn ("Link State Acknowledgment: "
+                "Neighbor[%s] state %s is less than Exchange",
+                inet_ntoa (ospfh->router_id),
+                LOOKUP(ospf_nsm_state_msg, nbr->state));
       return;
     }
-
-#ifdef HAVE_OPAQUE_LSA
-  opaque_acks = list_new ();
-#endif /* HAVE_OPAQUE_LSA */
-
+  
   while (size >= OSPF_LSA_HEADER_SIZE)
     {
       struct ospf_lsa *lsa, *lsr;
@@ -1963,7 +2049,7 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
 
       /* lsah = (struct lsa_header *) STREAM_PNT (s); */
       size -= OSPF_LSA_HEADER_SIZE;
-      stream_forward (s, OSPF_LSA_HEADER_SIZE);
+      stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
 
       if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)
        {
@@ -1977,9 +2063,8 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
       if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
         {
 #ifdef HAVE_OPAQUE_LSA
-          /* Keep this LSA entry for later reference. */
           if (IS_OPAQUE_LSA (lsr->data->type))
-            listnode_add (opaque_acks, ospf_lsa_dup (lsr));
+            ospf_opaque_ls_ack_received (nbr, lsr);
 #endif /* HAVE_OPAQUE_LSA */
 
           ospf_ls_retransmit_delete (nbr, lsr);
@@ -1989,30 +2074,19 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
       ospf_lsa_discard (lsa);
     }
 
-#ifdef HAVE_OPAQUE_LSA
-  if (listcount (opaque_acks) > 0)
-    ospf_opaque_ls_ack_received (nbr, opaque_acks);
-
-  list_delete (opaque_acks);
   return;
-#endif /* HAVE_OPAQUE_LSA */
 }
 \f
-struct stream *
-ospf_recv_packet (int fd, struct interface **ifp)
+static struct stream *
+ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
 {
   int ret;
-  struct ip iph;
+  struct ip *iph;
   u_int16_t ip_len;
-  struct stream *ibuf;
   unsigned int ifindex = 0;
   struct iovec iov;
-#if defined(CMSG_SPACE)
   /* Header and data both require alignment. */
   char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
-#else
-  char buff [sizeof (struct cmsghdr) + SOPT_SIZE_CMSG_IFINDEX_IPV4()];
-#endif
   struct msghdr msgh;
 
   memset (&msgh, 0, sizeof (struct msghdr));
@@ -2021,17 +2095,26 @@ ospf_recv_packet (int fd, struct interface **ifp)
   msgh.msg_control = (caddr_t) buff;
   msgh.msg_controllen = sizeof (buff);
   
-  ret = recvfrom (fd, (void *)&iph, sizeof (iph), MSG_PEEK, NULL, 0);
-  
-  if (ret != sizeof (iph))
+  ret = stream_recvmsg (ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE+1);
+  if (ret < 0)
     {
-      zlog_warn ("ospf_recv_packet packet smaller than ip header");
+      zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
+      return NULL;
+    }
+  if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */
+    {
+      zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
+               "(ip header size is %u)",
+               ret, (u_int)sizeof(iph));
       return NULL;
     }
   
-  sockopt_iphdrincl_swab_systoh (&iph);
+  /* Note that there should not be alignment problems with this assignment
+     because this is at the beginning of the stream data buffer. */
+  iph = (struct ip *) STREAM_DATA(ibuf);
+  sockopt_iphdrincl_swab_systoh (iph);
   
-  ip_len = iph.ip_len;
+  ip_len = iph->ip_len;
   
 #if !defined(GNU_LINUX) && (OpenBSD < 200311)
   /*
@@ -2048,30 +2131,33 @@ ospf_recv_packet (int fd, struct interface **ifp)
    *
    * For more details, see <netinet/ip_input.c>.
    */
-  ip_len = ip_len + (iph.ip_hl << 2);
+  ip_len = ip_len + (iph->ip_hl << 2);
 #endif
   
-  ibuf = stream_new (ip_len);
-  iov.iov_base = STREAM_DATA (ibuf);
-  iov.iov_len = ip_len;
-  ret = recvmsg (fd, &msgh, 0);
-  
+#if defined(__DragonFly__)
+  /*
+   * in DragonFly's raw socket, ip_len/ip_off are read 
+   * in network byte order.
+   * As OpenBSD < 200311 adjust ip_len to strip IP header size!
+   */
+  ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2);
+#endif
+
   ifindex = getsockopt_ifindex (AF_INET, &msgh);
   
   *ifp = if_lookup_by_index (ifindex);
 
   if (ret != ip_len)
     {
-      zlog_warn ("ospf_recv_packet short read. "
-                "ip_len %d bytes read %d", ip_len, ret);
-      stream_free (ibuf);
+      zlog_warn ("ospf_recv_packet read length mismatch: ip_len is %d, "
+                        "but recvmsg returned %d", ip_len, ret);
       return NULL;
     }
   
   return ibuf;
 }
 
-struct ospf_interface *
+static struct ospf_interface *
 ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp, 
                          struct ip *iph, struct ospf_header *ospfh)
 {
@@ -2093,11 +2179,8 @@ ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
                                               iph->ip_dst)) == NULL)
     return NULL;
 
-  for (node = listhead (ospf->vlinks); node; nextnode (node))
+  for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
     {
-      if ((vl_data = getdata (node)) == NULL)
-       continue;
-      
       vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id);
       if (!vl_area)
        continue;
@@ -2106,12 +2189,12 @@ ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
          IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id))
        {
          if (IS_DEBUG_OSPF_EVENT)
-           zlog_info ("associating packet with %s",
+           zlog_debug ("associating packet with %s",
                       IF_NAME (vl_data->vl_oi));
          if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP))
            {
              if (IS_DEBUG_OSPF_EVENT)
-               zlog_info ("This VL is not up yet, sorry");
+               zlog_debug ("This VL is not up yet, sorry");
              return NULL;
            }
          
@@ -2120,12 +2203,12 @@ ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
     }
 
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info ("couldn't find any VL to associate the packet with");
+    zlog_debug ("couldn't find any VL to associate the packet with");
   
   return NULL;
 }
 
-int
+static inline int
 ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
 {
   /* Check match the Area ID of the receiving interface. */
@@ -2138,7 +2221,7 @@ ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
 /* Unbound socket will accept any Raw IP packets if proto is matched.
    To prevent it, compare src IP address and i/f address with masking
    i/f network mask. */
-int
+static int
 ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
 {
   struct in_addr mask, me, him;
@@ -2158,7 +2241,7 @@ ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
  return 0;
 }
 
-int
+static int
 ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
                 struct ospf_header *ospfh)
 {
@@ -2177,7 +2260,7 @@ ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
        ret = 0;
       break;
     case OSPF_AUTH_CRYPTOGRAPHIC:
-      if ((ck = getdata (OSPF_IF_PARAM (oi,auth_crypt)->tail)) == NULL)
+      if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL)
        {
          ret = 0;
          break;
@@ -2199,12 +2282,11 @@ ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
   return ret;
 }
 
-int
+static int
 ospf_check_sum (struct ospf_header *ospfh)
 {
   u_int32_t ret;
   u_int16_t sum;
-  int in_cksum (void *ptr, int nbytes);
 
   /* clear auth_data for checksum. */
   memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
@@ -2227,7 +2309,7 @@ ospf_check_sum (struct ospf_header *ospfh)
 }
 
 /* OSPF Header verification. */
-int
+static int
 ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
                    struct ip *iph, struct ospf_header *ospfh)
 {
@@ -2258,8 +2340,8 @@ ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
   /* Check authentication. */
   if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
     {
-      zlog_warn ("interface %s: ospf_read authentication type mismatch.",
-                IF_NAME (oi));
+      zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d",
+                IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type));
       return -1;
     }
 
@@ -2310,30 +2392,28 @@ ospf_read (struct thread *thread)
 
   /* first of all get interface pointer. */
   ospf = THREAD_ARG (thread);
-  ospf->t_read = NULL;
+
+  /* prepare for next packet. */
+  ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
 
   /* read OSPF packet. */
-  ibuf = ospf_recv_packet (ospf->fd, &ifp);
-  if (ibuf == NULL)
+  stream_reset(ospf->ibuf);
+  if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
     return -1;
   
+  /* Note that there should not be alignment problems with this assignment
+     because this is at the beginning of the stream data buffer. */
   iph = (struct ip *) STREAM_DATA (ibuf);
-  sockopt_iphdrincl_swab_systoh (iph);
+  /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */
 
-  /* openbsd lacks IP_RECVIF */
-#if !(defined(IP_PKTINFO) || defined(IP_RECVIF))
   if (ifp == NULL)
+    /* Handle cases where the platform does not support retrieving the ifindex,
+       and also platforms (such as Solaris 8) that claim to support ifindex
+       retrieval but do not. */
     ifp = if_lookup_address (iph->ip_src);
-#endif /* !((defined(IP_PKTINFO) || defined(IP_RECVIF)) */
   
   if (ifp == NULL)
-    {
-      stream_free (ibuf);
-      return 0;
-    }
-  
-  /* prepare for next packet. */
-  ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
+    return 0;
 
   /* IP Header dump. */
     if (IS_DEBUG_OSPF_PACKET(0, RECV))
@@ -2344,21 +2424,46 @@ ospf_read (struct thread *thread)
     {
       if (IS_DEBUG_OSPF_PACKET (0, RECV))
         {
-          zlog_info ("ospf_read[%s]: Dropping self-originated packet",
+          zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
                      inet_ntoa (iph->ip_src));
         }
-      stream_free (ibuf);
       return 0;
     }
 
   /* Adjust size to message length. */
-  stream_forward (ibuf, iph->ip_hl * 4);
+  stream_forward_getp (ibuf, iph->ip_hl * 4);
   
   /* Get ospf packet header. */
   ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
 
   /* associate packet with ospf interface */
-  oi = ospf_if_lookup_recv_if (ospf, iph->ip_src);
+  oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp);
+
+  /* If incoming interface is passive one, ignore it. */
+  if (oi && OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
+    {
+      char buf[3][INET_ADDRSTRLEN];
+
+      if (IS_DEBUG_OSPF_EVENT)
+       zlog_debug ("ignoring packet from router %s sent to %s, "
+                   "received on a passive interface, %s",
+                   inet_ntop(AF_INET, &ospfh->router_id, buf[0], sizeof(buf[0])),
+                   inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
+                   inet_ntop(AF_INET, &oi->address->u.prefix4,
+                             buf[2], sizeof(buf[2])));
+
+      if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
+       {
+         /* Try to fix multicast membership.
+          * Some OS:es may have problems in this area,
+          * make sure it is removed.
+          */
+         OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
+         ospf_if_set_multicast(oi);
+       }
+      return 0;
+  }
+
 
   /* if no local ospf_interface, 
    * or header area is backbone but ospf_interface is not
@@ -2371,22 +2476,39 @@ ospf_read (struct thread *thread)
     {
       if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
         {
-          zlog_warn ("Packet from [%s] received on link %s"
-                     " but no ospf_interface",
-                     inet_ntoa (iph->ip_src), ifp->name);
-          stream_free (ibuf);
+          if (IS_DEBUG_OSPF_EVENT)
+            zlog_debug ("Packet from [%s] received on link %s"
+                        " but no ospf_interface",
+                        inet_ntoa (iph->ip_src), ifp->name);
           return 0;
         }
     }
-    
+
   /* else it must be a local ospf interface, check it was received on 
    * correct link 
    */
   else if (oi->ifp != ifp)
     {
-      zlog_warn ("Packet from [%s] received on wrong link %s",
-                 inet_ntoa (iph->ip_src), ifp->name); 
-      stream_free (ibuf);
+      if (IS_DEBUG_OSPF_EVENT)
+        zlog_warn ("Packet from [%s] received on wrong link %s",
+                   inet_ntoa (iph->ip_src), ifp->name); 
+      return 0;
+    }
+  else if (oi->state == ISM_Down)
+    {
+      char buf[2][INET_ADDRSTRLEN];
+      zlog_warn ("Ignoring packet from %s to %s received on interface that is "
+                "down [%s]; interface flags are %s",
+                inet_ntop(AF_INET, &iph->ip_src, buf[0], sizeof(buf[0])),
+                inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
+                ifp->name, if_flag_dump(ifp->flags));
+      /* Fix multicast memberships? */
+      if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
+        OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
+      else if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS))
+       OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
+      if (oi->multicast_memberships)
+       ospf_if_set_multicast(oi);
       return 0;
     }
 
@@ -2398,10 +2520,12 @@ ospf_read (struct thread *thread)
   if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS)
   && (oi->state != ISM_DR && oi->state != ISM_Backup))
     {
-      zlog_info ("Packet for AllDRouters from [%s] via [%s] (ISM: %s)",
+      zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)",
                  inet_ntoa (iph->ip_src), IF_NAME (oi),
                  LOOKUP (ospf_ism_state_msg, oi->state));
-      stream_free (ibuf);
+      /* Try to fix multicast membership. */
+      SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
+      ospf_if_set_multicast(oi);
       return 0;
     }
 
@@ -2410,18 +2534,18 @@ ospf_read (struct thread *thread)
     {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
         {
-          zlog_info ("-----------------------------------------------------");
+          zlog_debug ("-----------------------------------------------------");
           ospf_packet_dump (ibuf);
         }
 
-      zlog_info ("%s received from [%s] via [%s]",
+      zlog_debug ("%s received from [%s] via [%s]",
                  ospf_packet_type_str[ospfh->type],
                  inet_ntoa (ospfh->router_id), IF_NAME (oi));
-      zlog_info (" src [%s],", inet_ntoa (iph->ip_src));
-      zlog_info (" dst [%s]", inet_ntoa (iph->ip_dst));
+      zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));
+      zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));
 
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
-       zlog_info ("-----------------------------------------------------");
+       zlog_debug ("-----------------------------------------------------");
   }
 
   /* Some header verification. */
@@ -2430,16 +2554,15 @@ ospf_read (struct thread *thread)
     {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
         {
-          zlog_info ("ospf_read[%s/%s]: Header check failed, "
+          zlog_debug ("ospf_read[%s/%s]: Header check failed, "
                      "dropping.",
                      ospf_packet_type_str[ospfh->type],
                      inet_ntoa (iph->ip_src));
         }
-      stream_free (ibuf);
       return ret;
     }
 
-  stream_forward (ibuf, OSPF_HEADER_SIZE);
+  stream_forward_getp (ibuf, OSPF_HEADER_SIZE);
 
   /* Adjust size to message length. */
   length = ntohs (ospfh->length) - OSPF_HEADER_SIZE;
@@ -2469,12 +2592,11 @@ ospf_read (struct thread *thread)
       break;
     }
 
-  stream_free (ibuf);
   return 0;
 }
 
 /* Make OSPF header. */
-void
+static void
 ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
 {
   struct ospf_header *ospfh;
@@ -2492,11 +2614,11 @@ ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
 
   memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
 
-  ospf_output_forward (s, OSPF_HEADER_SIZE);
+  stream_forward_endp (s, OSPF_HEADER_SIZE);
 }
 
 /* Make Authentication Data. */
-int
+static int
 ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
 {
   struct crypt_key *ck;
@@ -2520,7 +2642,7 @@ ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
        }
       else
        {
-         ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
+         ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
          ospfh->u.crypt.zero = 0;
          ospfh->u.crypt.key_id = ck->key_id;
          ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
@@ -2536,7 +2658,7 @@ ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
 }
 
 /* Fill rest of OSPF header. */
-void
+static void
 ospf_fill_header (struct ospf_interface *oi,
                  struct stream *s, u_int16_t length)
 {
@@ -2557,7 +2679,7 @@ ospf_fill_header (struct ospf_interface *oi,
   ospf_make_auth (oi, ospfh);
 }
 
-int
+static int
 ospf_make_hello (struct ospf_interface *oi, struct stream *s)
 {
   struct ospf_neighbor *nbr;
@@ -2576,10 +2698,13 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s)
   stream_put_ipv4 (s, mask.s_addr);
 
   /* Set Hello Interval. */
-  stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
+  if (OSPF_IF_PARAM (oi, fast_hello) == 0)
+    stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
+  else
+    stream_putw (s, 0); /* hello-interval of 0 for fast-hellos */
 
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info ("make_hello: options: %x, int: %s",
+    zlog_debug ("make_hello: options: %x, int: %s",
               OPTIONS(oi), IF_NAME (oi));
 
   /* Set Options. */
@@ -2594,7 +2719,7 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s)
   /* Set Designated Router. */
   stream_put_ipv4 (s, DR (oi).s_addr);
 
-  p = s->putp;
+  p = stream_get_endp (s);
 
   /* Set Backup Designated Router. */
   stream_put_ipv4 (s, BDR (oi).s_addr);
@@ -2619,15 +2744,12 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s)
 
   /* Let neighbor generate BackupSeen. */
   if (flag == 1)
-    {
-      stream_set_putp (s, p);
-      stream_put_ipv4 (s, 0);
-    }
+    stream_putl_at (s, p, 0); /* ipv4 address, normally */
 
   return length;
 }
 
-int
+static int
 ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
                   struct stream *s)
 {
@@ -2667,24 +2789,16 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
 #endif /* HAVE_OPAQUE_LSA */
   stream_putc (s, options);
 
-  /* Keep pointer to flags. */
-  pp = stream_get_putp (s);
+  /* DD flags */
+  pp = stream_get_endp (s);
   stream_putc (s, nbr->dd_flags);
 
   /* Set DD Sequence Number. */
   stream_putl (s, nbr->dd_seqnum);
 
+  /* shortcut unneeded walk of (empty) summary LSDBs */
   if (ospf_db_summary_isempty (nbr))
-    {
-      if (nbr->state >= NSM_Exchange)
-       {
-         nbr->dd_flags &= ~OSPF_DD_FLAG_M;
-         /* Set DD flags again */
-         stream_set_putp (s, pp);
-         stream_putc (s, nbr->dd_flags);
-       }
-      return length;
-    }
+    goto empty;
 
   /* Describe LSA Header from Database Summary List. */
   lsdb = &nbr->db_sum;
@@ -2714,12 +2828,12 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
                u_int16_t ls_age;
                
                /* DD packet overflows interface MTU. */
-               if (length + OSPF_LSA_HEADER_SIZE > OSPF_PACKET_MAX (oi))
+               if (length + OSPF_LSA_HEADER_SIZE > ospf_packet_max (oi))
                  break;
                
                /* Keep pointer to LS age. */
                lsah = (struct lsa_header *) (STREAM_DATA (s) +
-                                             stream_get_putp (s));
+                                             stream_get_endp (s));
                
                /* Proceed stream pointer. */
                stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
@@ -2736,10 +2850,25 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
          }
     }
 
+  /* Update 'More' bit */
+  if (ospf_db_summary_isempty (nbr))
+    {
+empty:
+      if (nbr->state >= NSM_Exchange)
+        {
+          UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_M);
+          /* Rewrite DD flags */
+          stream_putc_at (s, pp, nbr->dd_flags);
+        }
+      else
+        {
+          assert (IS_SET_DD_M(nbr->dd_flags));
+        }
+    }
   return length;
 }
 
-int
+static int
 ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
                       unsigned long delta, struct ospf_neighbor *nbr,
                       struct ospf_lsa *lsa)
@@ -2749,26 +2878,26 @@ ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
   oi = nbr->oi;
 
   /* LS Request packet overflows interface MTU. */
-  if (*length + delta > OSPF_PACKET_MAX(oi))
+  if (*length + delta > ospf_packet_max(oi))
     return 0;
 
   stream_putl (s, lsa->data->type);
   stream_put_ipv4 (s, lsa->data->id.s_addr);
   stream_put_ipv4 (s, lsa->data->adv_router.s_addr);
   
-  ospf_lsa_unlock (nbr->ls_req_last);
+  ospf_lsa_unlock (&nbr->ls_req_last);
   nbr->ls_req_last = ospf_lsa_lock (lsa);
   
   *length += 12;
   return 1;
 }
 
-int
+static int
 ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
 {
   struct ospf_lsa *lsa;
   u_int16_t length = OSPF_LS_REQ_MIN_SIZE;
-  unsigned long delta = stream_get_putp(s)+12;
+  unsigned long delta = stream_get_endp(s)+12;
   struct route_table *table;
   struct route_node *rn;
   int i;
@@ -2790,7 +2919,7 @@ ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
   return length;
 }
 
-int
+static int
 ls_age_increment (struct ospf_lsa *lsa, int delay)
 {
   int age;
@@ -2800,21 +2929,26 @@ ls_age_increment (struct ospf_lsa *lsa, int delay)
   return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age);
 }
 
-int
+static int
 ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream *s)
 {
   struct ospf_lsa *lsa;
   struct listnode *node;
-  u_int16_t length = OSPF_LS_UPD_MIN_SIZE;
-  unsigned long delta = stream_get_putp (s);
+  u_int16_t length = 0;
+  unsigned int size_noauth;
+  unsigned long delta = stream_get_endp (s);
   unsigned long pp;
   int count = 0;
 
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info ("ospf_make_ls_upd: Start");
+    zlog_debug ("ospf_make_ls_upd: Start");
+
+  pp = stream_get_endp (s);
+  stream_forward_endp (s, OSPF_LS_UPD_MIN_SIZE);
+  length += OSPF_LS_UPD_MIN_SIZE;
 
-  pp = stream_get_putp (s);
-  ospf_output_forward (s, OSPF_LS_UPD_MIN_SIZE);
+  /* Calculate amount of packet usable for data. */
+  size_noauth = stream_get_size(s) - ospf_packet_authspace(oi);
 
   while ((node = listhead (update)) != NULL)
     {
@@ -2822,18 +2956,18 @@ ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream
       u_int16_t ls_age;
 
       if (IS_DEBUG_OSPF_EVENT)
-        zlog_info ("ospf_make_ls_upd: List Iteration");
+        zlog_debug ("ospf_make_ls_upd: List Iteration");
+
+      lsa = listgetdata (node);
 
-      lsa = getdata (node);
-      assert (lsa);
       assert (lsa->data);
 
       /* Will it fit? */
-      if (length + delta + ntohs (lsa->data->length) > stream_get_size (s))
+      if (length + delta + ntohs (lsa->data->length) > size_noauth)
         break;
 
       /* Keep pointer to LS age. */
-      lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_putp (s));
+      lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_endp (s));
 
       /* Put LSA to Link State Request. */
       stream_put (s, lsa->data, ntohs (lsa->data->length));
@@ -2848,61 +2982,44 @@ ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream
       count++;
 
       list_delete_node (update, node);
-      ospf_lsa_unlock (lsa);
+      ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
     }
 
   /* Now set #LSAs. */
-  stream_set_putp (s, pp);
-  stream_putl (s, count);
-
-  stream_set_putp (s, s->endp);
+  stream_putl_at (s, pp, count);
 
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info ("ospf_make_ls_upd: Stop");
+    zlog_debug ("ospf_make_ls_upd: Stop");
   return length;
 }
 
-int
+static int
 ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
 {
-  struct list *rm_list;
-  struct listnode *node;
+  struct listnode *node, *nnode;
   u_int16_t length = OSPF_LS_ACK_MIN_SIZE;
-  unsigned long delta = stream_get_putp(s) + 24;
+  unsigned long delta = stream_get_endp(s) + 24;
   struct ospf_lsa *lsa;
 
-  rm_list = list_new ();
-  
-  for (node = listhead (ack); node; nextnode (node))
+  for (ALL_LIST_ELEMENTS (ack, node, nnode, lsa))
     {
-      lsa = getdata (node);
       assert (lsa);
       
-      if (length + delta > OSPF_PACKET_MAX (oi))
+      if (length + delta > ospf_packet_max (oi))
        break;
       
       stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
       length += OSPF_LSA_HEADER_SIZE;
       
-      listnode_add (rm_list, lsa);
-    }
-  
-  /* Remove LSA from LS-Ack list. */
-  for (node = listhead (rm_list); node; nextnode (node))
-    {
-      lsa = (struct ospf_lsa *) getdata (node);
-      
       listnode_delete (ack, lsa);
-      ospf_lsa_unlock (lsa);
+      ospf_lsa_unlock (&lsa); /* oi->ls_ack_direct.ls_ack */
     }
   
-  list_delete (rm_list);
-  
   return length;
 }
 
-void
-ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
+static void
+ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr)
 {
   struct ospf_packet *op;
   u_int16_t length = OSPF_HEADER_SIZE;
@@ -2921,16 +3038,18 @@ ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
   /* Set packet length. */
   op->length = length;
 
-  op->dst.s_addr = addr->s_addr;
+  op->dst.s_addr = addr;
 
-  /* Add packet to the interface output queue. */
-  ospf_packet_add (oi, op);
+  /* Add packet to the top of the interface output queue, so that they
+   * can't get delayed by things like long queues of LS Update packets
+   */
+  ospf_packet_add_top (oi, op);
 
   /* Hook thread to write packet. */
   OSPF_ISM_WRITE_ON (oi->ospf);
 }
 
-void
+static void
 ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
 {
   struct ospf_interface *oi;
@@ -2939,7 +3058,7 @@ ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
   assert(oi);
 
   /* If this is passive interface, do not send OSPF Hello. */
-  if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+  if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
     return;
 
   if (oi->type != OSPF_IFTYPE_NBMA)
@@ -2955,7 +3074,7 @@ ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
       && oi->state != ISM_DR && oi->state != ISM_Backup)
     return;
 
-  ospf_hello_send_sub (oi, &nbr_nbma->addr);
+  ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr);
 }
 
 int
@@ -2967,7 +3086,7 @@ ospf_poll_timer (struct thread *thread)
   nbr_nbma->t_poll = NULL;
 
   if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
-    zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (Poll timer expire)",
+    zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Poll timer expire)",
     IF_NAME (nbr_nbma->oi), inet_ntoa (nbr_nbma->addr));
 
   ospf_poll_send (nbr_nbma);
@@ -2991,10 +3110,10 @@ ospf_hello_reply_timer (struct thread *thread)
   assert (nbr->oi);
 
   if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
-    zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (hello-reply timer expire)",
+    zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
          IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
 
-  ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
+  ospf_hello_send_sub (nbr->oi, nbr->address.u.prefix4.s_addr);
 
   return 0;
 }
@@ -3003,27 +3122,10 @@ ospf_hello_reply_timer (struct thread *thread)
 void
 ospf_hello_send (struct ospf_interface *oi)
 {
-  struct ospf_packet *op;
-  u_int16_t length = OSPF_HEADER_SIZE;
-
   /* If this is passive interface, do not send OSPF Hello. */
-  if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+  if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
     return;
 
-  op = ospf_packet_new (oi->ifp->mtu);
-
-  /* Prepare OSPF common header. */
-  ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
-
-  /* Prepare OSPF Hello body. */
-  length += ospf_make_hello (oi, op->s);
-
-  /* Fill OSPF header. */
-  ospf_fill_header (oi, op->s, length);
-
-  /* Set packet length. */
-  op->length = length;
-
   if (oi->type == OSPF_IFTYPE_NBMA)
     {
       struct ospf_neighbor *nbr;
@@ -3053,34 +3155,16 @@ ospf_hello_send (struct ospf_interface *oi)
                if (nbr->priority == 0 && oi->state == ISM_DROther)
                  continue;
                /* if oi->state == Waiting, send hello to all neighbors */
-               {
-                 struct ospf_packet *op_dup;
-
-                 op_dup = ospf_packet_dup(op);
-                 op_dup->dst = nbr->address.u.prefix4;
-
-                 /* Add packet to the interface output queue. */
-                 ospf_packet_add (oi, op_dup);
-
-                 OSPF_ISM_WRITE_ON (oi->ospf);
-               }
-
+               ospf_hello_send_sub (oi, nbr->address.u.prefix4.s_addr);
              }
-      ospf_packet_free (op);
     }
   else
     {
       /* Decide destination address. */
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
-       op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
-      else 
-       op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
-
-      /* Add packet to the interface output queue. */
-      ospf_packet_add (oi, op);
-
-      /* Hook thread to write packet. */
-      OSPF_ISM_WRITE_ON (oi->ospf);
+        ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr);
+      else
+        ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS));
     }
 }
 
@@ -3108,7 +3192,10 @@ ospf_db_desc_send (struct ospf_neighbor *nbr)
   op->length = length;
 
   /* Decide destination address. */
-  op->dst = nbr->address.u.prefix4;
+  if (oi->type == OSPF_IFTYPE_POINTOPOINT) 
+    op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+  else
+    op->dst = nbr->address.u.prefix4;
 
   /* Add packet to the interface output queue. */
   ospf_packet_add (oi, op);
@@ -3120,7 +3207,7 @@ ospf_db_desc_send (struct ospf_neighbor *nbr)
   if (nbr->last_send)
     ospf_packet_free (nbr->last_send);
   nbr->last_send = ospf_packet_dup (op);
-  gettimeofday (&nbr->last_send_ts, NULL);
+  quagga_gettime (QUAGGA_CLK_MONOTONIC, &nbr->last_send_ts);
 }
 
 /* Re-send Database Description. */
@@ -3167,7 +3254,10 @@ ospf_ls_req_send (struct ospf_neighbor *nbr)
   op->length = length;
 
   /* Decide destination address. */
-  op->dst = nbr->address.u.prefix4;
+  if (oi->type == OSPF_IFTYPE_POINTOPOINT) 
+    op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+  else
+    op->dst = nbr->address.u.prefix4;
 
   /* Add packet to the interface output queue. */
   ospf_packet_add (oi, op);
@@ -3209,9 +3299,7 @@ ospf_ls_upd_packet_new (struct list *update, struct ospf_interface *oi)
   size_t size;
   static char warned = 0;
 
-  ln = listhead (update);
-  lsa = getdata (ln);
-  assert (lsa);
+  lsa = listgetdata((ln = listhead (update)));
   assert (lsa->data);
 
   if ((OSPF_LS_UPD_MIN_SIZE + ntohs (lsa->data->length))
@@ -3227,7 +3315,7 @@ ospf_ls_upd_packet_new (struct list *update, struct ospf_interface *oi)
         }
 
       if (IS_DEBUG_OSPF_PACKET (0, SEND))
-        zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s,"
+        zlog_debug ("ospf_ls_upd_packet_new: oversized LSA id:%s,"
                    " %d bytes originated by %s, will be fragmented!",
                    inet_ntoa (lsa->data->id),
                    ntohs (lsa->data->length),
@@ -3254,7 +3342,16 @@ ospf_ls_upd_packet_new (struct list *update, struct ospf_interface *oi)
       return NULL;
     }
 
-  return ospf_packet_new (size);
+  /* IP header is built up separately by ospf_write(). This means, that we must
+   * reduce the "affordable" size just calculated by length of an IP header.
+   * This makes sure, that even if we manage to fill the payload with LSA data
+   * completely, the final packet (our data plus IP header) still fits into
+   * outgoing interface MTU. This correction isn't really meaningful for an
+   * oversized LSA, but for consistency the correction is done for both cases.
+   *
+   * P.S. OSPF_MAX_PACKET_SIZE above already includes IP header size
+   */
+  return ospf_packet_new (size - sizeof (struct ip));
 }
 
 static void
@@ -3265,7 +3362,7 @@ ospf_ls_upd_queue_send (struct ospf_interface *oi, struct list *update,
   u_int16_t length = OSPF_HEADER_SIZE;
 
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
+    zlog_debug ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
   
   op = ospf_ls_upd_packet_new (update, oi);
 
@@ -3284,7 +3381,10 @@ ospf_ls_upd_queue_send (struct ospf_interface *oi, struct list *update,
   op->length = length;
 
   /* Decide destination address. */
-  op->dst.s_addr = addr.s_addr;
+  if (oi->type == OSPF_IFTYPE_POINTOPOINT) 
+    op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+  else
+    op->dst.s_addr = addr.s_addr;
 
   /* Add packet to the interface output queue. */
   ospf_packet_add (oi, op);
@@ -3305,7 +3405,7 @@ ospf_ls_upd_send_queue_event (struct thread *thread)
   oi->t_ls_upd_event = NULL;
 
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info ("ospf_ls_upd_send_queue start");
+    zlog_debug ("ospf_ls_upd_send_queue start");
 
   for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext)
     {
@@ -3332,14 +3432,14 @@ ospf_ls_upd_send_queue_event (struct thread *thread)
   if (again != 0)
     {
       if (IS_DEBUG_OSPF_EVENT)
-        zlog_info ("ospf_ls_upd_send_queue: update lists not cleared,"
+        zlog_debug ("ospf_ls_upd_send_queue: update lists not cleared,"
                    " %d nodes to try again, raising new event", again);
       oi->t_ls_upd_event = 
         thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
     }
 
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_info ("ospf_ls_upd_send_queue stop");
+    zlog_debug ("ospf_ls_upd_send_queue stop");
   
   return 0;
 }
@@ -3348,9 +3448,10 @@ void
 ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
 {
   struct ospf_interface *oi;
+  struct ospf_lsa *lsa;
   struct prefix_ipv4 p;
   struct route_node *rn;
-  struct listnode *n;
+  struct listnode *node;
   
   oi = nbr->oi;
 
@@ -3360,13 +3461,12 @@ ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
   /* Decide destination address. */
   if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
     p.prefix = oi->vl_data->peer_addr;
+  else if (oi->type == OSPF_IFTYPE_POINTOPOINT) 
+     p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
   else if (flag == OSPF_SEND_PACKET_DIRECT)
      p.prefix = nbr->address.u.prefix4;
   else if (oi->state == ISM_DR || oi->state == ISM_Backup)
      p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
-  else if ((oi->type == OSPF_IFTYPE_POINTOPOINT) 
-          && (flag == OSPF_SEND_PACKET_INDIRECT))
-     p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
   else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
      p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
   else
@@ -3385,8 +3485,8 @@ ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
   if (rn->info == NULL)
     rn->info = list_new ();
 
-  for (n = listhead (update); n; nextnode (n))
-    listnode_add (rn->info, ospf_lsa_lock (getdata (n)));
+  for (ALL_LIST_ELEMENTS_RO (update, node, lsa))
+    listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */
 
   if (oi->t_ls_upd_event == NULL)
     oi->t_ls_upd_event =