]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospfd/ospf_packet.c
[ospfd/zserv] adjust to new format
[mirror_frr.git] / ospfd / ospf_packet.c
index 58369250cf4c8571591bdededf8c913a51ecc451..d6aca719862452271b25eabdcb1d1974f7874cc3 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;
@@ -214,17 +210,6 @@ 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->getp = s->getp;
-
-  memcpy (new->data, s->data, stream_get_endp (s));
-
-  return new;
-}
-
 struct ospf_packet *
 ospf_packet_dup (struct ospf_packet *op)
 {
@@ -236,7 +221,7 @@ ospf_packet_dup (struct ospf_packet *op)
 
   /* 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;
@@ -245,7 +230,7 @@ ospf_packet_dup (struct ospf_packet *op)
 }
 
 /* XXX inline */
-unsigned int
+static inline unsigned int
 ospf_packet_authspace (struct ospf_interface *oi)
 {
   int auth = 0;
@@ -256,7 +241,7 @@ ospf_packet_authspace (struct ospf_interface *oi)
   return auth;
 }
 
-unsigned int
+static unsigned int
 ospf_packet_max (struct ospf_interface *oi)
 {
   int max;
@@ -269,12 +254,12 @@ ospf_packet_max (struct ospf_interface *oi)
 }
 
 \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;
@@ -311,10 +296,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))
@@ -333,16 +319,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;
   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;
@@ -353,23 +339,28 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
   /* We do this here so when we dup a packet, we don't have to
      waste CPU rewriting other headers. */
   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. */
   stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
@@ -384,7 +375,7 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
 }
 
 \f
-int
+static int
 ospf_ls_req_timer (struct thread *thread)
 {
   struct ospf_neighbor *nbr;
@@ -429,10 +420,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;
@@ -455,7 +444,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_time, lsa->tv_recv), 
                            int2tv (retransmit_interval)) >= 0)
                  listnode_add (update, rn->info);
            }
@@ -491,7 +480,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)
@@ -542,12 +531,13 @@ 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,
-                   safe_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))
         {
@@ -574,7 +564,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);
@@ -598,7 +588,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
@@ -698,9 +688,9 @@ ospf_write (struct thread *thread)
   
   if (ret < 0)
     zlog_warn ("*** sendmsg in ospf_write failed to %s, "
-              "id %d, off %d, len %d: %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,
-              safe_strerror (errno));
+              oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
 
   /* Show debug sending packet. */
   if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
@@ -739,7 +729,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)
 {
@@ -769,12 +759,12 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
   /* If incoming interface is passive one, ignore Hello. */
   if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
     char buf[3][INET_ADDRSTRLEN];
-    zlog_warn("Warning: ignoring HELLO from router %s sent to %s; we "
-             "should not receive hellos on 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])));
+    zlog_debug ("ignoring HELLO 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. */
@@ -800,14 +790,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
        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))
     {
@@ -816,6 +798,17 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
       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.",
+                     inet_ntoa (ospfh->router_id));
+          return;
+        }
+    }
+  
   if (IS_DEBUG_OSPF_EVENT)
     zlog_debug ("Packet %s [Hello:RECV]: Options %s",
               inet_ntoa (ospfh->router_id),
@@ -971,7 +964,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)
 {
@@ -1088,7 +1081,7 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
   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? */
@@ -1122,7 +1115,8 @@ 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]: Neighbor %s MTU %u is larger than [%s]'s MTU %u",
                 inet_ntoa (nbr->router_id), ntohs (dd->mtu),
@@ -1210,7 +1204,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
          else
            {
              /* We're Master, ignore the initial DBD from Slave */
-             zlog_warn ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
+             zlog_info ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
                         "ignoring.", inet_ntoa(nbr->router_id));
              break;
            }
@@ -1245,7 +1239,10 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
           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. */
             }
         }
@@ -1261,12 +1258,12 @@ 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): Neighbor %s 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]: Neighbor %s packet duplicated.",
+             zlog_info ("Packet[DD] [Slave]: Neighbor %s packet duplicated.",
                         inet_ntoa (nbr->router_id));
              ospf_db_desc_resend (nbr);
            }
@@ -1289,7 +1286,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
       /* Check initialize bit is set. */
       if (IS_SET_DD_I (dd->flags))
        {
-         zlog_warn ("Packet[DD]: Neighbor %s 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;
@@ -1330,7 +1327,8 @@ 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("Packet[DD]: Neighbor %s duplicated, packet discarded.",
+             zlog_info ("Packet[DD]: Neighbor %s duplicated, "
+                        "packet discarded.",
                        inet_ntoa(nbr->router_id));
              break;
            }
@@ -1368,7 +1366,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)
 {
@@ -1586,30 +1584,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; */
 
@@ -1644,13 +1638,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
@@ -1659,6 +1646,9 @@ 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 */
 
@@ -1669,15 +1659,11 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
        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];
@@ -1745,8 +1731,8 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
          ospf_ls_ack_send (nbr, lsa);
 
          /* Discard LSA. */      
-         zlog_warn("Link State Update[%s]: LS age is equal to MaxAge.",
-                   dump_lsa_key(lsa));
+         zlog_info ("Link State Update[%s]: LS age is equal to MaxAge.",
+                    dump_lsa_key(lsa));
           DISCARD_LSA (lsa, 3);
        }
 
@@ -1783,18 +1769,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_debug ("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
@@ -1804,12 +1795,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;
 
@@ -1863,10 +1854,6 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
           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;
        }
 
@@ -1944,37 +1931,17 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
        }
     }
   
-#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 */
-
   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++;
 
@@ -1994,11 +1961,7 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
                 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;
@@ -2022,9 +1985,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);
@@ -2034,22 +1996,15 @@ 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;
   /* Header and data both require alignment. */
@@ -2062,18 +2017,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");
-      /* XXX: We peeked, and thus perhaps should discard this packet. */
+      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)
   /*
@@ -2090,32 +2053,24 @@ 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
   
-  if ( (ibuf = stream_new (ip_len)) == NULL)
-    return NULL;
-  iov.iov_base = STREAM_DATA (ibuf);
-  iov.iov_len = ip_len;
-  
-  ret = stream_recvmsg (ibuf, fd, &msgh, 0, ip_len);
-  
   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)
 {
@@ -2137,11 +2092,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;
@@ -2169,7 +2121,7 @@ ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
   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. */
@@ -2182,7 +2134,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;
@@ -2202,7 +2154,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)
 {
@@ -2221,7 +2173,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;
@@ -2243,12 +2195,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);
@@ -2271,7 +2222,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)
 {
@@ -2302,8 +2253,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;
     }
 
@@ -2354,15 +2305,19 @@ 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. */
 
   if (ifp == NULL)
     /* Handle cases where the platform does not support retrieving the ifindex,
@@ -2371,13 +2326,7 @@ ospf_read (struct thread *thread)
     ifp = if_lookup_address (iph->ip_src);
   
   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))
@@ -2391,7 +2340,6 @@ ospf_read (struct thread *thread)
           zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
                      inet_ntoa (iph->ip_src));
         }
-      stream_free (ibuf);
       return 0;
     }
 
@@ -2415,10 +2363,9 @@ 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"
+          zlog_debug ("Packet from [%s] received on link %s"
                      " but no ospf_interface",
                      inet_ntoa (iph->ip_src), ifp->name);
-          stream_free (ibuf);
           return 0;
         }
     }
@@ -2430,7 +2377,6 @@ ospf_read (struct thread *thread)
     {
       zlog_warn ("Packet from [%s] received on wrong link %s",
                  inet_ntoa (iph->ip_src), ifp->name); 
-      stream_free (ibuf);
       return 0;
     }
   else if (oi->state == ISM_Down)
@@ -2441,7 +2387,6 @@ ospf_read (struct thread *thread)
                 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));
-      stream_free (ibuf);
       /* Fix multicast memberships? */
       if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
        SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
@@ -2463,7 +2408,6 @@ ospf_read (struct thread *thread)
       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);
@@ -2500,7 +2444,6 @@ ospf_read (struct thread *thread)
                      ospf_packet_type_str[ospfh->type],
                      inet_ntoa (iph->ip_src));
         }
-      stream_free (ibuf);
       return ret;
     }
 
@@ -2534,12 +2477,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;
@@ -2561,7 +2503,7 @@ ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
 }
 
 /* Make Authentication Data. */
-int
+static int
 ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
 {
   struct crypt_key *ck;
@@ -2585,7 +2527,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;
@@ -2601,7 +2543,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)
 {
@@ -2622,7 +2564,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;
@@ -2641,7 +2583,10 @@ 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_debug ("make_hello: options: %x, int: %s",
@@ -2689,7 +2634,7 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s)
   return length;
 }
 
-int
+static int
 ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
                   struct stream *s)
 {
@@ -2800,7 +2745,7 @@ ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
   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)
@@ -2824,7 +2769,7 @@ ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
   return 1;
 }
 
-int
+static int
 ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
 {
   struct ospf_lsa *lsa;
@@ -2851,7 +2796,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;
@@ -2861,7 +2806,7 @@ 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;
@@ -2889,8 +2834,8 @@ ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream
       if (IS_DEBUG_OSPF_EVENT)
         zlog_debug ("ospf_make_ls_upd: List Iteration");
 
-      lsa = getdata (node);
-      assert (lsa);
+      lsa = listgetdata (node);
+
       assert (lsa->data);
 
       /* Will it fit? */
@@ -2924,7 +2869,7 @@ ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream
   return length;
 }
 
-int
+static int
 ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
 {
   struct list *rm_list;
@@ -2935,9 +2880,9 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
 
   rm_list = list_new ();
   
-  for (node = listhead (ack); node; nextnode (node))
+  for (ALL_LIST_ELEMENTS_RO (ack, node, lsa))
     {
-      lsa = getdata (node);
+      lsa = listgetdata (node);
       assert (lsa);
       
       if (length + delta > ospf_packet_max (oi))
@@ -2950,10 +2895,11 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
     }
   
   /* Remove LSA from LS-Ack list. */
-  for (node = listhead (rm_list); node; nextnode (node))
+  /* XXX: this loop should be removed and the list move done in previous
+   * loop
+   */
+  for (ALL_LIST_ELEMENTS_RO (rm_list, node, lsa))
     {
-      lsa = (struct ospf_lsa *) getdata (node);
-      
       listnode_delete (ack, lsa);
       ospf_lsa_unlock (lsa);
     }
@@ -2992,7 +2938,7 @@ ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
   OSPF_ISM_WRITE_ON (oi->ospf);
 }
 
-void
+static void
 ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
 {
   struct ospf_interface *oi;
@@ -3271,9 +3217,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))
@@ -3411,9 +3355,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;
 
@@ -3448,8 +3393,11 @@ 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))
+    {
+      ospf_lsa_lock (lsa);
+      listnode_add (rn->info, lsa);
+    }
 
   if (oi->t_ls_upd_event == NULL)
     oi->t_ls_upd_event =