Diff for /embedaddon/quagga/ospfd/ospf_packet.c between versions 1.1 and 1.1.1.5

version 1.1, 2012/02/21 17:26:12 version 1.1.1.5, 2016/11/02 10:09:12
Line 50 Line 50
 #include "ospfd/ospf_dump.h"  #include "ospfd/ospf_dump.h"
   
 /* Packet Type String. */  /* Packet Type String. */
const char *ospf_packet_type_str[] =const struct message ospf_packet_type_str[] =
 {  {
  "unknown",  { OSPF_MSG_HELLO,   "Hello"                     },
  "Hello",  { OSPF_MSG_DB_DESC, "Database Description"      },
  "Database Description",  { OSPF_MSG_LS_REQ,  "Link State Request"        },
  "Link State Request",  { OSPF_MSG_LS_UPD,  "Link State Update"         },
  "Link State Update",  { OSPF_MSG_LS_ACK,  "Link State Acknowledgment" },
  "Link State Acknowledgment", 
 };  };
   const size_t ospf_packet_type_str_max = sizeof (ospf_packet_type_str) /
     sizeof (ospf_packet_type_str[0]);
   
   /* Minimum (besides OSPF_HEADER_SIZE) lengths for OSPF packets of
      particular types, offset is the "type" field of a packet. */
   static const u_int16_t ospf_packet_minlen[] =
   {
     0,
     OSPF_HELLO_MIN_SIZE,
     OSPF_DB_DESC_MIN_SIZE,
     OSPF_LS_REQ_MIN_SIZE,
     OSPF_LS_UPD_MIN_SIZE,
     OSPF_LS_ACK_MIN_SIZE,
   };
   
   /* Minimum (besides OSPF_LSA_HEADER_SIZE) lengths for LSAs of particular
      types, offset is the "LSA type" field. */
   static const u_int16_t ospf_lsa_minlen[] =
   {
     0,
     OSPF_ROUTER_LSA_MIN_SIZE,
     OSPF_NETWORK_LSA_MIN_SIZE,
     OSPF_SUMMARY_LSA_MIN_SIZE,
     OSPF_SUMMARY_LSA_MIN_SIZE,
     OSPF_AS_EXTERNAL_LSA_MIN_SIZE,
     0,
     OSPF_AS_EXTERNAL_LSA_MIN_SIZE,
     0,
     0,
     0,
     0,
   };
   
   /* for ospf_check_auth() */
   static int ospf_check_sum (struct ospf_header *);
   
 /* OSPF authentication checking function */  /* OSPF authentication checking function */
 static int  static int
 ospf_auth_type (struct ospf_interface *oi)  ospf_auth_type (struct ospf_interface *oi)
Line 201  ospf_packet_add (struct ospf_interface *oi, struct osp Line 235  ospf_packet_add (struct ospf_interface *oi, struct osp
                "destination %s) called with NULL obuf, ignoring "                 "destination %s) called with NULL obuf, ignoring "
                "(please report this bug)!\n",                 "(please report this bug)!\n",
                IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),                 IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
               ospf_packet_type_str[stream_getc_from(op->s, 1)],               LOOKUP (ospf_packet_type_str, stream_getc_from(op->s, 1)),
                inet_ntoa (op->dst));                 inet_ntoa (op->dst));
       return;        return;
     }      }
Line 222  ospf_packet_add_top (struct ospf_interface *oi, struct Line 256  ospf_packet_add_top (struct ospf_interface *oi, struct
                "destination %s) called with NULL obuf, ignoring "                 "destination %s) called with NULL obuf, ignoring "
                "(please report this bug)!\n",                 "(please report this bug)!\n",
                IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),                 IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
               ospf_packet_type_str[stream_getc_from(op->s, 1)],               LOOKUP (ospf_packet_type_str, stream_getc_from(op->s, 1)),
                inet_ntoa (op->dst));                 inet_ntoa (op->dst));
       return;        return;
     }      }
Line 266  ospf_packet_dup (struct ospf_packet *op) Line 300  ospf_packet_dup (struct ospf_packet *op)
 }  }
   
 /* XXX inline */  /* XXX inline */
static inline unsigned intstatic unsigned int
 ospf_packet_authspace (struct ospf_interface *oi)  ospf_packet_authspace (struct ospf_interface *oi)
 {  {
   int auth = 0;    int auth = 0;
Line 289  ospf_packet_max (struct ospf_interface *oi) Line 323  ospf_packet_max (struct ospf_interface *oi)
   return max;    return max;
 }  }
   
 static int  static int
ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,ospf_check_md5_digest (struct ospf_interface *oi, struct ospf_header *ospfh)
                       u_int16_t length) 
 {  {
   unsigned char *ibuf;  
   MD5_CTX ctx;    MD5_CTX ctx;
   unsigned char digest[OSPF_AUTH_MD5_SIZE];    unsigned char digest[OSPF_AUTH_MD5_SIZE];
   unsigned char *pdigest;  
   struct crypt_key *ck;    struct crypt_key *ck;
   struct ospf_header *ospfh;  
   struct ospf_neighbor *nbr;    struct ospf_neighbor *nbr;
     u_int16_t length = ntohs (ospfh->length);
       
   
   ibuf = STREAM_PNT (s);  
   ospfh = (struct ospf_header *) ibuf;  
   
   /* Get pointer to the end of the packet. */  
   pdigest = ibuf + length;  
   
   /* Get secret key. */    /* Get secret key. */
   ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),    ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),
                               ospfh->u.crypt.key_id);                                ospfh->u.crypt.key_id);
Line 334  ospf_check_md5_digest (struct ospf_interface *oi, stru Line 358  ospf_check_md5_digest (struct ospf_interface *oi, stru
   /* Generate a digest for the ospf packet - their digest + our digest. */    /* Generate a digest for the ospf packet - their digest + our digest. */
   memset(&ctx, 0, sizeof(ctx));    memset(&ctx, 0, sizeof(ctx));
   MD5Init(&ctx);    MD5Init(&ctx);
  MD5Update(&ctx, ibuf, length);  MD5Update(&ctx, ospfh, length);
   MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);    MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);
   MD5Final(digest, &ctx);    MD5Final(digest, &ctx);
   
   /* compare the two */    /* compare the two */
  if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))  if (memcmp ((caddr_t)ospfh + length, digest, OSPF_AUTH_MD5_SIZE))
     {      {
       zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",        zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",
                  IF_NAME (oi));                   IF_NAME (oi));
Line 359  static int Line 383  static int
 ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)  ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
 {  {
   struct ospf_header *ospfh;    struct ospf_header *ospfh;
  unsigned char digest[OSPF_AUTH_MD5_SIZE];  unsigned char digest[OSPF_AUTH_MD5_SIZE] = {0};
   MD5_CTX ctx;    MD5_CTX ctx;
   void *ibuf;    void *ibuf;
   u_int32_t t;    u_int32_t t;
Line 386  ospf_make_md5_digest (struct ospf_interface *oi, struc Line 410  ospf_make_md5_digest (struct ospf_interface *oi, struc
   
   /* Get MD5 Authentication key from auth_key list. */    /* Get MD5 Authentication key from auth_key list. */
   if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))    if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
    auth_key = (const u_int8_t *) "";    auth_key = (const u_int8_t *) digest;
   else    else
     {      {
       ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));        ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
Line 414  ospf_make_md5_digest (struct ospf_interface *oi, struc Line 438  ospf_make_md5_digest (struct ospf_interface *oi, struc
   return OSPF_AUTH_MD5_SIZE;    return OSPF_AUTH_MD5_SIZE;
 }  }
   
 static int  static int
 ospf_ls_req_timer (struct thread *thread)  ospf_ls_req_timer (struct thread *thread)
 {  {
Line 620  ospf_write (struct thread *thread) Line 644  ospf_write (struct thread *thread)
   struct listnode *node;    struct listnode *node;
 #ifdef WANT_OSPF_WRITE_FRAGMENT  #ifdef WANT_OSPF_WRITE_FRAGMENT
   static u_int16_t ipid = 0;    static u_int16_t ipid = 0;
 #endif /* WANT_OSPF_WRITE_FRAGMENT */  
   u_int16_t maxdatasize;    u_int16_t maxdatasize;
   #endif /* WANT_OSPF_WRITE_FRAGMENT */
 #define OSPF_WRITE_IPHL_SHIFT 2  #define OSPF_WRITE_IPHL_SHIFT 2
       
   ospf->t_write = NULL;    ospf->t_write = NULL;
Line 635  ospf_write (struct thread *thread) Line 659  ospf_write (struct thread *thread)
   /* seed ipid static with low order bits of time */    /* seed ipid static with low order bits of time */
   if (ipid == 0)    if (ipid == 0)
     ipid = (time(NULL) & 0xffff);      ipid = (time(NULL) & 0xffff);
 #endif /* WANT_OSPF_WRITE_FRAGMENT */  
   
   /* convenience - max OSPF data per packet,    /* convenience - max OSPF data per packet,
    * and reliability - not more data, than our     * and reliability - not more data, than our
Line 643  ospf_write (struct thread *thread) Line 666  ospf_write (struct thread *thread)
    */     */
   maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) -    maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) -
     sizeof (struct ip);      sizeof (struct ip);
   #endif /* WANT_OSPF_WRITE_FRAGMENT */
       
   /* Get one packet from queue. */    /* Get one packet from queue. */
   op = ospf_fifo_head (oi->obuf);    op = ospf_fifo_head (oi->obuf);
Line 755  ospf_write (struct thread *thread) Line 779  ospf_write (struct thread *thread)
         }          }
   
       zlog_debug ("%s sent to [%s] via [%s].",        zlog_debug ("%s sent to [%s] via [%s].",
                 ospf_packet_type_str[type], inet_ntoa (op->dst),                 LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst),
                  IF_NAME (oi));                   IF_NAME (oi));
   
       if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))        if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
Line 765  ospf_write (struct thread *thread) Line 789  ospf_write (struct thread *thread)
   /* Now delete packet from queue. */    /* Now delete packet from queue. */
   ospf_packet_delete (oi);    ospf_packet_delete (oi);
   
     /* Move this interface to the tail of write_q to
            serve everyone in a round robin fashion */
     listnode_move_to_tail (ospf->oi_write_q, node);
   if (ospf_fifo_head (oi->obuf) == NULL)    if (ospf_fifo_head (oi->obuf) == NULL)
     {      {
       oi->on_write_q = 0;        oi->on_write_q = 0;
Line 801  ospf_hello (struct ip *iph, struct ospf_header *ospfh, Line 828  ospf_hello (struct ip *iph, struct ospf_header *ospfh,
         {          {
           zlog_debug ("ospf_header[%s/%s]: selforiginated, "            zlog_debug ("ospf_header[%s/%s]: selforiginated, "
                      "dropping.",                       "dropping.",
                     ospf_packet_type_str[ospfh->type],                     LOOKUP (ospf_packet_type_str, ospfh->type),
                      inet_ntoa (iph->ip_src));                       inet_ntoa (iph->ip_src));
         }          }
       return;        return;
Line 867  ospf_hello (struct ip *iph, struct ospf_header *ospfh, Line 894  ospf_hello (struct ip *iph, struct ospf_header *ospfh,
     }      }
 #endif /* REJECT_IF_TBIT_ON */  #endif /* REJECT_IF_TBIT_ON */
   
 #ifdef HAVE_OPAQUE_LSA  
   if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)    if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)
       && CHECK_FLAG (hello->options, OSPF_OPTION_O))        && CHECK_FLAG (hello->options, OSPF_OPTION_O))
     {      {
Line 883  ospf_hello (struct ip *iph, struct ospf_header *ospfh, Line 909  ospf_hello (struct ip *iph, struct ospf_header *ospfh,
       UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */        UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */
 #endif /* STRICT_OBIT_USAGE_CHECK */  #endif /* STRICT_OBIT_USAGE_CHECK */
     }      }
 #endif /* HAVE_OPAQUE_LSA */  
   
   /* new for NSSA is to ensure that NP is on and E is off */    /* new for NSSA is to ensure that NP is on and E is off */
   
Line 1035  ospf_db_desc_proc (struct stream *s, struct ospf_inter Line 1060  ospf_db_desc_proc (struct stream *s, struct ospf_inter
           return;            return;
         }          }
   
 #ifdef HAVE_OPAQUE_LSA  
       if (IS_OPAQUE_LSA (lsah->type)        if (IS_OPAQUE_LSA (lsah->type)
       &&  ! CHECK_FLAG (nbr->options, OSPF_OPTION_O))        &&  ! CHECK_FLAG (nbr->options, OSPF_OPTION_O))
         {          {
Line 1043  ospf_db_desc_proc (struct stream *s, struct ospf_inter Line 1067  ospf_db_desc_proc (struct stream *s, struct ospf_inter
           OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);            OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
           return;            return;
         }          }
 #endif /* HAVE_OPAQUE_LSA */  
   
       switch (lsah->type)        switch (lsah->type)
         {          {
         case OSPF_AS_EXTERNAL_LSA:          case OSPF_AS_EXTERNAL_LSA:
 #ifdef HAVE_OPAQUE_LSA  
         case OSPF_OPAQUE_AS_LSA:          case OSPF_OPAQUE_AS_LSA:
 #endif /* HAVE_OPAQUE_LSA */  
           /* Check for stub area.  Reject if AS-External from stub but            /* Check for stub area.  Reject if AS-External from stub but
              allow if from NSSA. */               allow if from NSSA. */
           if (oi->area->external_routing == OSPF_AREA_STUB)            if (oi->area->external_routing == OSPF_AREA_STUB)
Line 1221  ospf_db_desc (struct ip *iph, struct ospf_header *ospf Line 1242  ospf_db_desc (struct ip *iph, struct ospf_header *ospf
     }      }
 #endif /* REJECT_IF_TBIT_ON */  #endif /* REJECT_IF_TBIT_ON */
   
 #ifdef HAVE_OPAQUE_LSA  
   if (CHECK_FLAG (dd->options, OSPF_OPTION_O)    if (CHECK_FLAG (dd->options, OSPF_OPTION_O)
       && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))        && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
     {      {
Line 1231  ospf_db_desc (struct ip *iph, struct ospf_header *ospf Line 1251  ospf_db_desc (struct ip *iph, struct ospf_header *ospf
        */         */
       UNSET_FLAG (dd->options, OSPF_OPTION_O);        UNSET_FLAG (dd->options, OSPF_OPTION_O);
     }      }
 #endif /* HAVE_OPAQUE_LSA */  
   
   /* Add event to thread. */    /* Add event to thread. */
   OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);    OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
Line 1296  ospf_db_desc (struct ip *iph, struct ospf_header *ospf Line 1315  ospf_db_desc (struct ip *iph, struct ospf_header *ospf
       /* This is where the real Options are saved */        /* This is where the real Options are saved */
       nbr->options = dd->options;        nbr->options = dd->options;
   
 #ifdef HAVE_OPAQUE_LSA  
       if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))        if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
         {          {
           if (IS_DEBUG_OSPF_EVENT)            if (IS_DEBUG_OSPF_EVENT)
Line 1314  ospf_db_desc (struct ip *iph, struct ospf_header *ospf Line 1332  ospf_db_desc (struct ip *iph, struct ospf_header *ospf
               /* This situation is undesirable, but not a real error. */                /* This situation is undesirable, but not a real error. */
             }              }
         }          }
 #endif /* HAVE_OPAQUE_LSA */  
   
       OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone);        OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone);
   
Line 1566  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc Line 1583  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc
   
       /* Validate the LSA's LS checksum. */        /* Validate the LSA's LS checksum. */
       sum = lsah->checksum;        sum = lsah->checksum;
      if (sum != ospf_lsa_checksum (lsah))      if (! ospf_lsa_checksum_valid (lsah))
         {          {
          zlog_warn ("Link State Update: LSA checksum error %x, %x.",          /* (bug #685) more details in a one-line message make it possible
                     sum, lsah->checksum);           * to identify problem source on the one hand and to have a better
            * chance to compress repeated messages in syslog on the other */
           zlog_warn ("Link State Update: LSA checksum error %x/%x, ID=%s from: nbr %s, router ID %s, adv router %s",
                      sum, lsah->checksum, inet_ntoa (lsah->id),
                      inet_ntoa (nbr->src), inet_ntoa (nbr->router_id),
                      inet_ntoa (lsah->adv_router));
           continue;            continue;
         }          }
   
Line 1587  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc Line 1609  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc
       if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE)        if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE)
         lsah->ls_age = htons (OSPF_LSA_MAXAGE);          lsah->ls_age = htons (OSPF_LSA_MAXAGE);
   
 #ifdef HAVE_OPAQUE_LSA  
       if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))        if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
         {          {
 #ifdef STRICT_OBIT_USAGE_CHECK  #ifdef STRICT_OBIT_USAGE_CHECK
Line 1619  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc Line 1640  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc
           zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));            zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
           continue;            continue;
         }          }
 #endif /* HAVE_OPAQUE_LSA */  
   
       /* Create OSPF LSA instance. */        /* Create OSPF LSA instance. */
       lsa = ospf_lsa_new ();        lsa = ospf_lsa_new ();
Line 1629  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc Line 1649  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc
       switch (lsah->type)        switch (lsah->type)
         {          {
         case OSPF_AS_EXTERNAL_LSA:          case OSPF_AS_EXTERNAL_LSA:
 #ifdef HAVE_OPAQUE_LSA  
         case OSPF_OPAQUE_AS_LSA:          case OSPF_OPAQUE_AS_LSA:
           lsa->area = NULL;            lsa->area = NULL;
           break;            break;
         case OSPF_OPAQUE_LINK_LSA:          case OSPF_OPAQUE_LINK_LSA:
           lsa->oi = oi; /* Remember incoming interface for flooding control. */            lsa->oi = oi; /* Remember incoming interface for flooding control. */
           /* Fallthrough */            /* Fallthrough */
 #endif /* HAVE_OPAQUE_LSA */  
         default:          default:
           lsa->area = oi->area;            lsa->area = oi->area;
           break;            break;
Line 1647  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc Line 1665  ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struc
   
       if (IS_DEBUG_OSPF_EVENT)        if (IS_DEBUG_OSPF_EVENT)
         zlog_debug("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);                  lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa);
       listnode_add (lsas, lsa);        listnode_add (lsas, lsa);
     }      }
   
Line 1669  ospf_upd_list_clean (struct list *lsas) Line 1687  ospf_upd_list_clean (struct list *lsas)
   
 /* OSPF Link State Update message read -- RFC2328 Section 13. */  /* OSPF Link State Update message read -- RFC2328 Section 13. */
 static void  static void
ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh,
              struct stream *s, struct ospf_interface *oi, u_int16_t size)               struct stream *s, struct ospf_interface *oi, u_int16_t size)
 {  {
   struct ospf_neighbor *nbr;    struct ospf_neighbor *nbr;
Line 1711  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh Line 1729  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh
    */     */
   lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);    lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);
   
 #ifdef HAVE_OPAQUE_LSA  
   /*  
    * If self-originated Opaque-LSAs that have flooded before restart  
    * are contained in the received LSUpd message, corresponding LSReq  
    * messages to be sent may have to be modified.  
    * To eliminate possible race conditions such that flushing and normal  
    * 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) {\  #define DISCARD_LSA(L,N) {\
         if (IS_DEBUG_OSPF_EVENT) \          if (IS_DEBUG_OSPF_EVENT) \
          zlog_debug ("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, (void *)lsa, (int) lsa->data->type); \
         ospf_lsa_discard (L); \          ospf_lsa_discard (L); \
         continue; }          continue; }
   
  /* Process each LSA received in the one packet. */  /* Process each LSA received in the one packet.
    *
    * Numbers in parentheses, e.g. (1), (2), etc., and the corresponding
    * text below are from the steps in RFC 2328, Section 13.
    */
   for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))    for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
     {      {
       struct ospf_lsa *ls_ret, *current;        struct ospf_lsa *ls_ret, *current;
Line 1756  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh Line 1764  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh
   
       listnode_delete (lsas, lsa); /* We don't need it in list anymore */        listnode_delete (lsas, lsa); /* We don't need it in list anymore */
   
      /* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */      /* (1) Validate Checksum - Done above by ospf_ls_upd_list_lsa() */
   
      /* LSA Type  - Done above by ospf_ls_upd_list_lsa() */      /* (2) LSA Type  - Done above by ospf_ls_upd_list_lsa() */
         
      /* Do not take in AS External LSAs if we are a stub or NSSA. */      /* (3) Do not take in AS External LSAs if we are a stub or NSSA. */
   
       /* Do not take in AS NSSA if this neighbor and we are not NSSA */        /* Do not take in AS NSSA if this neighbor and we are not NSSA */
   
Line 1788  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh Line 1796  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh
             DISCARD_LSA (lsa,2);              DISCARD_LSA (lsa,2);
           }            }
   
         /* VU229804: Router-LSA Adv-ID must be equal to LS-ID */
         if (lsa->data->type == OSPF_ROUTER_LSA)
           if (!IPV4_ADDR_SAME(&lsa->data->id, &lsa->data->adv_router))
             {
               char buf1[INET_ADDRSTRLEN];
               char buf2[INET_ADDRSTRLEN];
               char buf3[INET_ADDRSTRLEN];
   
               zlog_err("Incoming Router-LSA from %s with "
                         "Adv-ID[%s] != LS-ID[%s]",
                         inet_ntop (AF_INET, &ospfh->router_id,
                                    buf1, INET_ADDRSTRLEN),
                         inet_ntop (AF_INET, &lsa->data->id,
                                    buf2, INET_ADDRSTRLEN),
                         inet_ntop (AF_INET, &lsa->data->adv_router,
                                    buf3, INET_ADDRSTRLEN));
               zlog_err("OSPF domain compromised by attack or corruption. "
                        "Verify correct operation of -ALL- OSPF routers.");
               DISCARD_LSA (lsa, 0);
             }
   
       /* Find the LSA in the current database. */        /* Find the LSA in the current database. */
   
       current = ospf_lsa_lookup_by_header (oi->area, lsa->data);        current = ospf_lsa_lookup_by_header (oi->area, lsa->data);
   
      /* If the LSA's LS age is equal to MaxAge, and there is currently      /* (4) If the LSA's LS age is equal to MaxAge, and there is currently
          no instance of the LSA in the router's link state database,           no instance of the LSA in the router's link state database,
          and none of router's neighbors are in states Exchange or Loading,           and none of router's neighbors are in states Exchange or Loading,
         then take the following actions. */         then take the following actions: */
   
       if (IS_LSA_MAXAGE (lsa) && !current &&        if (IS_LSA_MAXAGE (lsa) && !current &&
          (ospf_nbr_count (oi, NSM_Exchange) +          ospf_check_nbr_status(oi->ospf))
           ospf_nbr_count (oi, NSM_Loading)) == 0) 
         {          {
          /* Response Link State Acknowledgment. */          /* (4a) Response Link State Acknowledgment. */
           ospf_ls_ack_send (nbr, lsa);            ospf_ls_ack_send (nbr, lsa);
   
          /* Discard LSA. */                    /* (4b) Discard LSA. */
          zlog_info ("Link State Update[%s]: LS age is equal to MaxAge.",          if (IS_DEBUG_OSPF (lsa, LSA))
                     dump_lsa_key(lsa));            {
                zlog_debug ("Link State Update[%s]: LS age is equal to MaxAge.",
                            dump_lsa_key(lsa));
             }
           DISCARD_LSA (lsa, 3);            DISCARD_LSA (lsa, 3);
         }          }
   
 #ifdef HAVE_OPAQUE_LSA  
       if (IS_OPAQUE_LSA (lsa->data->type)        if (IS_OPAQUE_LSA (lsa->data->type)
       &&  IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id))        &&  IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id))
         {          {
Line 1858  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh Line 1888  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh
               continue;                continue;
             }              }
         }          }
 #endif /* HAVE_OPAQUE_LSA */  
   
       /* It might be happen that received LSA is self-originated network LSA, but        /* 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       * router ID is changed. 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         * Link State ID is one of the router's own IP interface addresses but whose
        * Advertising Router is not equal to the router's own Router ID         * Advertising Router is not equal to the router's own Router ID
        * According to RFC 2328 12.4.2 and 13.4 this LSA should be flushed.         * According to RFC 2328 12.4.2 and 13.4 this LSA should be flushed.
Line 1886  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh Line 1915  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh
               ospf_lsa_flush_area(lsa,out_if->area);                ospf_lsa_flush_area(lsa,out_if->area);
               if(IS_DEBUG_OSPF_EVENT)                if(IS_DEBUG_OSPF_EVENT)
                 zlog_debug ("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);                            (void *)lsa, (int) lsa->data->type);
               ospf_lsa_discard (lsa);                ospf_lsa_discard (lsa);
               Flag = 1;                Flag = 1;
             }              }
Line 1900  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh Line 1929  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh
       /* (5) Find the instance of this LSA that is currently contained        /* (5) Find the instance of this LSA that is currently contained
          in the router's link state database.  If there is no           in the router's link state database.  If there is no
          database copy, or the received LSA is more recent than           database copy, or the received LSA is more recent than
         the database copy the following steps must be performed. */         the database copy the following steps must be performed.
          (The sub steps from RFC 2328 section 13 step (5) will be performed in
          ospf_flood() ) */
   
       if (current == NULL ||        if (current == NULL ||
           (ret = ospf_lsa_more_recent (current, lsa)) < 0)            (ret = ospf_lsa_more_recent (current, lsa)) < 0)
Line 1997  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh Line 2028  ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh
               quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);                quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
                               
               if (tv_cmp (tv_sub (now, current->tv_orig),                 if (tv_cmp (tv_sub (now, current->tv_orig), 
                          int2tv (OSPF_MIN_LS_ARRIVAL)) >= 0)                          msec2tv (ospf->min_ls_arrival)) >= 0)
                 /* Trap NSSA type later.*/                  /* Trap NSSA type later.*/
                 ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);                  ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
               DISCARD_LSA (lsa, 8);                DISCARD_LSA (lsa, 8);
Line 2060  ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh Line 2091  ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh
   
       lsr = ospf_ls_retransmit_lookup (nbr, lsa);        lsr = ospf_ls_retransmit_lookup (nbr, lsa);
   
      if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)      if (lsr != NULL && ospf_lsa_more_recent (lsr, lsa) == 0)
        {        ospf_ls_retransmit_delete (nbr, lsr);
#ifdef HAVE_OPAQUE_LSA 
          if (IS_OPAQUE_LSA (lsr->data->type)) 
            ospf_opaque_ls_ack_received (nbr, lsr); 
#endif /* HAVE_OPAQUE_LSA */ 
   
           ospf_ls_retransmit_delete (nbr, lsr);  
         }  
   
       lsa->data = NULL;        lsa->data = NULL;
       ospf_lsa_discard (lsa);        ospf_lsa_discard (lsa);
     }      }
   
   return;    return;
 }  }
 static struct stream *  static struct stream *
 ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)  ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
 {  {
   int ret;    int ret;
   struct ip *iph;    struct ip *iph;
   u_int16_t ip_len;    u_int16_t ip_len;
  unsigned int ifindex = 0;  ifindex_t ifindex = 0;
   struct iovec iov;    struct iovec iov;
   /* Header and data both require alignment. */    /* Header and data both require alignment. */
   char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];    char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
Line 2116  ospf_recv_packet (int fd, struct interface **ifp, stru Line 2140  ospf_recv_packet (int fd, struct interface **ifp, stru
       
   ip_len = iph->ip_len;    ip_len = iph->ip_len;
       
#if !defined(GNU_LINUX) && (OpenBSD < 200311)#if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
   /*    /*
    * Kernel network code touches incoming IP header parameters,     * Kernel network code touches incoming IP header parameters,
    * before protocol specific processing.     * before protocol specific processing.
Line 2208  ospf_associate_packet_vl (struct ospf *ospf, struct in Line 2232  ospf_associate_packet_vl (struct ospf *ospf, struct in
   return NULL;    return NULL;
 }  }
   
static inline intstatic int
 ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)  ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
 {  {
   /* Check match the Area ID of the receiving interface. */    /* Check match the Area ID of the receiving interface. */
Line 2241  ospf_check_network_mask (struct ospf_interface *oi, st Line 2265  ospf_check_network_mask (struct ospf_interface *oi, st
  return 0;   return 0;
 }  }
   
   /* Return 1, if the packet is properly authenticated and checksummed,
      0 otherwise. In particular, check that AuType header field is valid and
      matches the locally configured AuType, and that D.5 requirements are met. */
 static int  static int
ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,ospf_check_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
                 struct ospf_header *ospfh) 
 {  {
   int ret = 0;  
   struct crypt_key *ck;    struct crypt_key *ck;
     u_int16_t iface_auth_type;
     u_int16_t pkt_auth_type = ntohs (ospfh->auth_type);
   
  switch (ntohs (ospfh->auth_type))  switch (pkt_auth_type)
   {
   case OSPF_AUTH_NULL: /* RFC2328 D.5.1 */
     if (OSPF_AUTH_NULL != (iface_auth_type = ospf_auth_type (oi)))
     {      {
    case OSPF_AUTH_NULL:      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
      ret = 1;        zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Null",
      break;                   IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type));
    case OSPF_AUTH_SIMPLE:      return 0;
      if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE)) 
        ret = 1; 
      else 
        ret = 0; 
      break; 
    case OSPF_AUTH_CRYPTOGRAPHIC: 
      if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL) 
        { 
          ret = 0; 
          break; 
        } 
       
      /* This is very basic, the digest processing is elsewhere */ 
      if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE &&  
          ospfh->u.crypt.key_id == ck->key_id && 
          ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf)) 
        ret = 1; 
      else 
        ret = 0; 
      break; 
    default: 
      ret = 0; 
      break; 
     }      }
    if (! ospf_check_sum (ospfh))
  return ret;    {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
         zlog_warn ("interface %s: Null auth OK, but checksum error, Router-ID %s",
                    IF_NAME (oi), inet_ntoa (ospfh->router_id));
       return 0;
     }
     return 1;
   case OSPF_AUTH_SIMPLE: /* RFC2328 D.5.2 */
     if (OSPF_AUTH_SIMPLE != (iface_auth_type = ospf_auth_type (oi)))
     {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
         zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Simple",
                    IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type));
       return 0;
     }
     if (memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
     {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
         zlog_warn ("interface %s: Simple auth failed", IF_NAME (oi));
       return 0;
     }
     if (! ospf_check_sum (ospfh))
     {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
         zlog_warn ("interface %s: Simple auth OK, checksum error, Router-ID %s",
                    IF_NAME (oi), inet_ntoa (ospfh->router_id));
       return 0;
     }
     return 1;
   case OSPF_AUTH_CRYPTOGRAPHIC: /* RFC2328 D.5.3 */
     if (OSPF_AUTH_CRYPTOGRAPHIC != (iface_auth_type = ospf_auth_type (oi)))
     {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
         zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Cryptographic",
                    IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type));
       return 0;
     }
     if (ospfh->checksum)
     {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
         zlog_warn ("interface %s: OSPF header checksum is not 0", IF_NAME (oi));
       return 0;
     }
     /* only MD5 crypto method can pass ospf_packet_examin() */
     if
     (
       NULL == (ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) ||
       ospfh->u.crypt.key_id != ck->key_id ||
       /* Condition above uses the last key ID on the list, which is
          different from what ospf_crypt_key_lookup() does. A bug? */
       ! ospf_check_md5_digest (oi, ospfh)
     )
     {
       if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
         zlog_warn ("interface %s: MD5 auth failed", IF_NAME (oi));
       return 0;
     }
     return 1;
   default:
     if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       zlog_warn ("interface %s: invalid packet auth-type (%02x)",
                  IF_NAME (oi), pkt_auth_type);
     return 0;
   }
 }  }
   
 static int  static int
Line 2308  ospf_check_sum (struct ospf_header *ospfh) Line 2378  ospf_check_sum (struct ospf_header *ospfh)
   return 1;    return 1;
 }  }
   
/* OSPF Header verification. *//* Verify, that given link/TOS records are properly sized/aligned and match
static int   Router-LSA "# links" and "# TOS" fields as specified in RFC2328 A.4.2. */
ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,static unsigned
                    struct ip *iph, struct ospf_header *ospfh)ospf_router_lsa_links_examin
 (
   struct router_lsa_link * link,
   u_int16_t linkbytes,
   const u_int16_t num_links
 )
 {  {
  /* check version. */  unsigned counted_links = 0, thislinklen;
  if (ospfh->version != OSPF_VERSION)
   while (linkbytes)
   {
     thislinklen = OSPF_ROUTER_LSA_LINK_SIZE + 4 * link->m[0].tos_count;
     if (thislinklen > linkbytes)
     {      {
      zlog_warn ("interface %s: ospf_read version number mismatch.",      if (IS_DEBUG_OSPF_PACKET (0, RECV))
                 IF_NAME (oi));        zlog_debug ("%s: length error in link block #%u", __func__, counted_links);
      return -1;      return MSG_NG;
     }      }
       link = (struct router_lsa_link *)((caddr_t) link + thislinklen);
       linkbytes -= thislinklen;
       counted_links++;
     }
     if (counted_links != num_links)
     {
       if (IS_DEBUG_OSPF_PACKET (0, RECV))
         zlog_debug ("%s: %u link blocks declared, %u present",
                     __func__, num_links, counted_links);
       return MSG_NG;
     }
     return MSG_OK;
   }
   
  /* Valid OSPFv2 packet types are 1 through 5 inclusive. *//* Verify, that the given LSA is properly sized/aligned (including type-specific
  if (ospfh->type < 1 || ospfh->type > 5)   minimum length constraint). */
 static unsigned
 ospf_lsa_examin (struct lsa_header * lsah, const u_int16_t lsalen, const u_char headeronly)
 {
   unsigned ret;
   struct router_lsa * rlsa;
   if
   (
     lsah->type < OSPF_MAX_LSA &&
     ospf_lsa_minlen[lsah->type] &&
     lsalen < OSPF_LSA_HEADER_SIZE + ospf_lsa_minlen[lsah->type]
   )
   {    {
    zlog_warn ("interface %s: invalid packet type %u", IF_NAME (oi), ospfh->type);    if (IS_DEBUG_OSPF_PACKET (0, RECV))
    return -1;      zlog_debug ("%s: undersized (%u B) %s",
                   __func__, lsalen, LOOKUP (ospf_lsa_type_msg, lsah->type));
     return MSG_NG;
   }    }
     switch (lsah->type)
     {
     case OSPF_ROUTER_LSA:
       /* RFC2328 A.4.2, LSA header + 4 bytes followed by N>=1 (12+)-byte link blocks */
       if (headeronly)
       {
         ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
         break;
       }
       rlsa = (struct router_lsa *) lsah;
       ret = ospf_router_lsa_links_examin
       (
         (struct router_lsa_link *) rlsa->link,
         lsalen - OSPF_LSA_HEADER_SIZE - 4, /* skip: basic header, "flags", 0, "# links" */
         ntohs (rlsa->links) /* 16 bits */
       );
       break;
     case OSPF_AS_EXTERNAL_LSA:
       /* RFC2328 A.4.5, LSA header + 4 bytes followed by N>=1 12-bytes long blocks */
     case OSPF_AS_NSSA_LSA:
       /* RFC3101 C, idem */
       ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_AS_EXTERNAL_LSA_MIN_SIZE) % 12 ? MSG_NG : MSG_OK;
       break;
     /* Following LSA types are considered OK length-wise as soon as their minimum
      * length constraint is met and length of the whole LSA is a multiple of 4
      * (basic LSA header size is already a multiple of 4). */
     case OSPF_NETWORK_LSA:
       /* RFC2328 A.4.3, LSA header + 4 bytes followed by N>=1 router-IDs */
     case OSPF_SUMMARY_LSA:
     case OSPF_ASBR_SUMMARY_LSA:
       /* RFC2328 A.4.4, LSA header + 4 bytes followed by N>=1 4-bytes TOS blocks */
     case OSPF_OPAQUE_LINK_LSA:
     case OSPF_OPAQUE_AREA_LSA:
     case OSPF_OPAQUE_AS_LSA:
       /* RFC5250 A.2, "some number of octets (of application-specific
        * data) padded to 32-bit alignment." This is considered equivalent
        * to 4-byte alignment of all other LSA types, see OSPF-ALIGNMENT.txt
        * file for the detailed analysis of this passage. */
       ret = lsalen % 4 ? MSG_NG : MSG_OK;
       break;
     default:
       if (IS_DEBUG_OSPF_PACKET (0, RECV))
         zlog_debug ("%s: unsupported LSA type 0x%02x", __func__, lsah->type);
       return MSG_NG;
     }
     if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV))
       zlog_debug ("%s: alignment error in %s",
                   __func__, LOOKUP (ospf_lsa_type_msg, lsah->type));
     return ret;
   }
   
   /* Verify if the provided input buffer is a valid sequence of LSAs. This
      includes verification of LSA blocks length/alignment and dispatching
      of deeper-level checks. */
   static unsigned
   ospf_lsaseq_examin
   (
     struct lsa_header *lsah, /* start of buffered data */
     size_t length,
     const u_char headeronly,
     /* When declared_num_lsas is not 0, compare it to the real number of LSAs
        and treat the difference as an error. */
     const u_int32_t declared_num_lsas
   )
   {
     u_int32_t counted_lsas = 0;
   
     while (length)
     {
       u_int16_t lsalen;
       if (length < OSPF_LSA_HEADER_SIZE)
       {
         if (IS_DEBUG_OSPF_PACKET (0, RECV))
           zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
                       __func__, length, counted_lsas);
         return MSG_NG;
       }
       /* save on ntohs() calls here and in the LSA validator */
       lsalen = ntohs (lsah->length);
       if (lsalen < OSPF_LSA_HEADER_SIZE)
       {
         if (IS_DEBUG_OSPF_PACKET (0, RECV))
           zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
                       __func__, counted_lsas, lsalen);
         return MSG_NG;
       }
       if (headeronly)
       {
         /* less checks here and in ospf_lsa_examin() */
         if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 1))
         {
           if (IS_DEBUG_OSPF_PACKET (0, RECV))
             zlog_debug ("%s: malformed header-only LSA #%u", __func__, counted_lsas);
           return MSG_NG;
         }
         lsah = (struct lsa_header *) ((caddr_t) lsah + OSPF_LSA_HEADER_SIZE);
         length -= OSPF_LSA_HEADER_SIZE;
       }
       else
       {
         /* make sure the input buffer is deep enough before further checks */
         if (lsalen > length)
         {
           if (IS_DEBUG_OSPF_PACKET (0, RECV))
             zlog_debug ("%s: anomaly in LSA #%u: declared length is %u B, buffered length is %zu B",
                         __func__, counted_lsas, lsalen, length);
           return MSG_NG;
         }
         if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 0))
         {
           if (IS_DEBUG_OSPF_PACKET (0, RECV))
             zlog_debug ("%s: malformed LSA #%u", __func__, counted_lsas);
           return MSG_NG;
         }
         lsah = (struct lsa_header *) ((caddr_t) lsah + lsalen);
         length -= lsalen;
       }
       counted_lsas++;
     }
   
     if (declared_num_lsas && counted_lsas != declared_num_lsas)
     {
       if (IS_DEBUG_OSPF_PACKET (0, RECV))
         zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
                     __func__, declared_num_lsas, counted_lsas);
       return MSG_NG;
     }
     return MSG_OK;
   }
   
   /* Verify a complete OSPF packet for proper sizing/alignment. */
   static unsigned
   ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
   {
     u_int16_t bytesdeclared, bytesauth;
     unsigned ret;
     struct ospf_ls_update * lsupd;
   
     /* Length, 1st approximation. */
     if (bytesonwire < OSPF_HEADER_SIZE)
     {
       if (IS_DEBUG_OSPF_PACKET (0, RECV))
         zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
       return MSG_NG;
     }
     /* Now it is safe to access header fields. Performing length check, allow
      * for possible extra bytes of crypto auth/padding, which are not counted
      * in the OSPF header "length" field. */
     if (oh->version != OSPF_VERSION)
     {
       if (IS_DEBUG_OSPF_PACKET (0, RECV))
         zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
       return MSG_NG;
     }
     bytesdeclared = ntohs (oh->length);
     if (ntohs (oh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
       bytesauth = 0;
     else
     {
       if (oh->u.crypt.auth_data_len != OSPF_AUTH_MD5_SIZE)
       {
         if (IS_DEBUG_OSPF_PACKET (0, RECV))
           zlog_debug ("%s: unsupported crypto auth length (%u B)",
                       __func__, oh->u.crypt.auth_data_len);
         return MSG_NG;
       }
       bytesauth = OSPF_AUTH_MD5_SIZE;
     }
     if (bytesdeclared + bytesauth > bytesonwire)
     {
       if (IS_DEBUG_OSPF_PACKET (0, RECV))
         zlog_debug ("%s: packet length error (%u real, %u+%u declared)",
                     __func__, bytesonwire, bytesdeclared, bytesauth);
       return MSG_NG;
     }
     /* Length, 2nd approximation. The type-specific constraint is checked
        against declared length, not amount of bytes on wire. */
     if
     (
       oh->type >= OSPF_MSG_HELLO &&
       oh->type <= OSPF_MSG_LS_ACK &&
       bytesdeclared < OSPF_HEADER_SIZE + ospf_packet_minlen[oh->type]
     )
     {
       if (IS_DEBUG_OSPF_PACKET (0, RECV))
         zlog_debug ("%s: undersized (%u B) %s packet", __func__,
                     bytesdeclared, LOOKUP (ospf_packet_type_str, oh->type));
       return MSG_NG;
     }
     switch (oh->type)
     {
     case OSPF_MSG_HELLO:
       /* RFC2328 A.3.2, packet header + OSPF_HELLO_MIN_SIZE bytes followed
          by N>=0 router-IDs. */
       ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
       break;
     case OSPF_MSG_DB_DESC:
       /* RFC2328 A.3.3, packet header + OSPF_DB_DESC_MIN_SIZE bytes followed
          by N>=0 header-only LSAs. */
       ret = ospf_lsaseq_examin
       (
         (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE),
         bytesdeclared - OSPF_HEADER_SIZE - OSPF_DB_DESC_MIN_SIZE,
         1, /* header-only LSAs */
         0
       );
       break;
     case OSPF_MSG_LS_REQ:
       /* RFC2328 A.3.4, packet header followed by N>=0 12-bytes request blocks. */
       ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) %
         OSPF_LSA_KEY_SIZE ? MSG_NG : MSG_OK;
       break;
     case OSPF_MSG_LS_UPD:
       /* RFC2328 A.3.5, packet header + OSPF_LS_UPD_MIN_SIZE bytes followed
          by N>=0 full LSAs (with N declared beforehand). */
       lsupd = (struct ospf_ls_update *) ((caddr_t) oh + OSPF_HEADER_SIZE);
       ret = ospf_lsaseq_examin
       (
         (struct lsa_header *) ((caddr_t) lsupd + OSPF_LS_UPD_MIN_SIZE),
         bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE,
         0, /* full LSAs */
         ntohl (lsupd->num_lsas) /* 32 bits */
       );
       break;
     case OSPF_MSG_LS_ACK:
       /* RFC2328 A.3.6, packet header followed by N>=0 header-only LSAs. */
       ret = ospf_lsaseq_examin
       (
         (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_LS_ACK_MIN_SIZE),
         bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE,
         1, /* header-only LSAs */
         0
       );
       break;
     default:
       if (IS_DEBUG_OSPF_PACKET (0, RECV))
         zlog_debug ("%s: invalid packet type 0x%02x", __func__, oh->type);
       return MSG_NG;
     }
     if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV))
       zlog_debug ("%s: malformed %s packet", __func__, LOOKUP (ospf_packet_type_str, oh->type));
     return ret;
   }
   
   /* OSPF Header verification. */
   static int
   ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
                       struct ip *iph, struct ospf_header *ospfh)
   {
   /* Check Area ID. */    /* Check Area ID. */
   if (!ospf_check_area_id (oi, ospfh))    if (!ospf_check_area_id (oi, ospfh))
     {      {
Line 2344  ospf_verify_header (struct stream *ibuf, struct ospf_i Line 2697  ospf_verify_header (struct stream *ibuf, struct ospf_i
       return -1;        return -1;
     }      }
   
  /* Check authentication. */  /* Check authentication. The function handles logging actions, where required. */
  if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))  if (! ospf_check_auth (oi, ospfh))
    {    return -1;
      zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d", 
                 IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type)); 
      return -1; 
    } 
   
   if (! ospf_check_auth (oi, ibuf, ospfh))  
     {  
       zlog_warn ("interface %s: ospf_read authentication failed.",  
                  IF_NAME (oi));  
       return -1;  
     }  
   
   /* if check sum is invalid, packet is discarded. */  
   if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)  
     {  
       if (! ospf_check_sum (ospfh))  
         {  
           zlog_warn ("interface %s: ospf_read packet checksum error %s",  
                      IF_NAME (oi), inet_ntoa (ospfh->router_id));  
           return -1;  
         }  
     }  
   else  
     {  
       if (ospfh->checksum != 0)  
         return -1;  
       if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)  
         {  
           zlog_warn ("interface %s: ospf_read md5 authentication failed.",  
                      IF_NAME (oi));  
           return -1;  
         }  
     }  
   
   return 0;    return 0;
 }  }
   
Line 2403  ospf_read (struct thread *thread) Line 2723  ospf_read (struct thread *thread)
   /* prepare for next packet. */    /* prepare for next packet. */
   ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);    ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
   
   /* read OSPF packet. */  
   stream_reset(ospf->ibuf);    stream_reset(ospf->ibuf);
   if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))    if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
     return -1;      return -1;
     /* This raw packet is known to be at least as big as its IP header. */
       
   /* Note that there should not be alignment problems with this assignment    /* Note that there should not be alignment problems with this assignment
      because this is at the beginning of the stream data buffer. */       because this is at the beginning of the stream data buffer. */
Line 2441  ospf_read (struct thread *thread) Line 2761  ospf_read (struct thread *thread)
      by ospf_recv_packet() to be correct). */       by ospf_recv_packet() to be correct). */
   stream_forward_getp (ibuf, iph->ip_hl * 4);    stream_forward_getp (ibuf, iph->ip_hl * 4);
   
  /* Make sure the OSPF header is really there. */  ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
  if (stream_get_endp (ibuf) - stream_get_getp (ibuf) < OSPF_HEADER_SIZE)  if (MSG_OK != ospf_packet_examin (ospfh, stream_get_endp (ibuf) - stream_get_getp (ibuf)))
  { 
    zlog_debug ("ospf_read: ignored OSPF packet with undersized (%u bytes) header", 
                stream_get_endp (ibuf) - stream_get_getp (ibuf)); 
     return -1;      return -1;
   }  
   
   /* Now it is safe to access all fields of OSPF packet header. */    /* Now it is safe to access all fields of OSPF packet header. */
   ospfh = (struct ospf_header *) STREAM_PNT (ibuf);  
   
   /* associate packet with ospf interface */    /* associate packet with ospf interface */
   oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp);    oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp);
Line 2571  ospf_read (struct thread *thread) Line 2885  ospf_read (struct thread *thread)
         }          }
   
       zlog_debug ("%s received from [%s] via [%s]",        zlog_debug ("%s received from [%s] via [%s]",
                 ospf_packet_type_str[ospfh->type],                 LOOKUP (ospf_packet_type_str, ospfh->type),
                  inet_ntoa (ospfh->router_id), IF_NAME (oi));                   inet_ntoa (ospfh->router_id), IF_NAME (oi));
       zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));        zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));
       zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));        zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));
Line 2598  ospf_read (struct thread *thread) Line 2912  ospf_read (struct thread *thread)
       ospf_ls_req (iph, ospfh, ibuf, oi, length);        ospf_ls_req (iph, ospfh, ibuf, oi, length);
       break;        break;
     case OSPF_MSG_LS_UPD:      case OSPF_MSG_LS_UPD:
      ospf_ls_upd (iph, ospfh, ibuf, oi, length);      ospf_ls_upd (ospf, iph, ospfh, ibuf, oi, length);
       break;        break;
     case OSPF_MSG_LS_ACK:      case OSPF_MSG_LS_ACK:
       ospf_ls_ack (iph, ospfh, ibuf, oi, length);        ospf_ls_ack (iph, ospfh, ibuf, oi, length);
Line 2786  ospf_make_db_desc (struct ospf_interface *oi, struct o Line 3100  ospf_make_db_desc (struct ospf_interface *oi, struct o
   
   /* Set Options. */    /* Set Options. */
   options = OPTIONS (oi);    options = OPTIONS (oi);
 #ifdef HAVE_OPAQUE_LSA  
   if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))    if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
    {    SET_FLAG (options, OSPF_OPTION_O);
      if (IS_SET_DD_I (nbr->dd_flags) 
      ||  CHECK_FLAG (nbr->options, OSPF_OPTION_O)) 
        /* 
         * Set O-bit in the outgoing DD packet for capablity negotiation, 
         * if one of following case is applicable.  
         * 
         * 1) WaitTimer expiration event triggered the neighbor state to 
         *    change to Exstart, but no (valid) DD packet has received 
         *    from the neighbor yet. 
         * 
         * 2) At least one DD packet with O-bit on has received from the 
         *    neighbor. 
         */ 
        SET_FLAG (options, OSPF_OPTION_O); 
    } 
#endif /* HAVE_OPAQUE_LSA */ 
   stream_putc (s, options);    stream_putc (s, options);
   
   /* DD flags */    /* DD flags */
Line 2829  ospf_make_db_desc (struct ospf_interface *oi, struct o Line 3126  ospf_make_db_desc (struct ospf_interface *oi, struct o
       for (rn = route_top (table); rn; rn = route_next (rn))        for (rn = route_top (table); rn; rn = route_next (rn))
         if ((lsa = rn->info) != NULL)          if ((lsa = rn->info) != NULL)
           {            {
 #ifdef HAVE_OPAQUE_LSA  
             if (IS_OPAQUE_LSA (lsa->data->type)              if (IS_OPAQUE_LSA (lsa->data->type)
             && (! CHECK_FLAG (options, OSPF_OPTION_O)))              && (! CHECK_FLAG (options, OSPF_OPTION_O)))
               {                {
Line 2838  ospf_make_db_desc (struct ospf_interface *oi, struct o Line 3134  ospf_make_db_desc (struct ospf_interface *oi, struct o
                 ospf_lsdb_delete (lsdb, lsa);                  ospf_lsdb_delete (lsdb, lsa);
                 continue;                  continue;
               }                }
 #endif /* HAVE_OPAQUE_LSA */  
   
             if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))              if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
               {                {
Line 2974  ospf_make_ls_upd (struct ospf_interface *oi, struct li Line 3269  ospf_make_ls_upd (struct ospf_interface *oi, struct li
       u_int16_t ls_age;        u_int16_t ls_age;
   
       if (IS_DEBUG_OSPF_EVENT)        if (IS_DEBUG_OSPF_EVENT)
        zlog_debug ("ospf_make_ls_upd: List Iteration");        zlog_debug ("ospf_make_ls_upd: List Iteration %d", count);
   
       lsa = listgetdata (node);        lsa = listgetdata (node);
   
Line 3380  ospf_ls_upd_queue_send (struct ospf_interface *oi, str Line 3675  ospf_ls_upd_queue_send (struct ospf_interface *oi, str
   u_int16_t length = OSPF_HEADER_SIZE;    u_int16_t length = OSPF_HEADER_SIZE;
   
   if (IS_DEBUG_OSPF_EVENT)    if (IS_DEBUG_OSPF_EVENT)
    zlog_debug ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));    zlog_debug ("listcount = %d, [%s]dst %s", listcount (update), IF_NAME(oi),
                             inet_ntoa(addr));
       
   op = ospf_ls_upd_packet_new (update, oi);    op = ospf_ls_upd_packet_new (update, oi);
   
Line 3502  ospf_ls_upd_send (struct ospf_neighbor *nbr, struct li Line 3798  ospf_ls_upd_send (struct ospf_neighbor *nbr, struct li
   
   if (rn->info == NULL)    if (rn->info == NULL)
     rn->info = list_new ();      rn->info = list_new ();
     else
       route_unlock_node (rn);
   
   for (ALL_LIST_ELEMENTS_RO (update, node, lsa))    for (ALL_LIST_ELEMENTS_RO (update, node, lsa))
     listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */      listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */

Removed from v.1.1  
changed lines
  Added in v.1.1.1.5


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>