Diff for /embedaddon/quagga/ospfd/ospf_packet.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 17:26:12 version 1.1.1.2, 2012/05/29 11:53:41
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 291  ospf_packet_max (struct ospf_interface *oi) Line 325  ospf_packet_max (struct ospf_interface *oi)
   
   
 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 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 801  ospf_hello (struct ip *iph, struct ospf_header *ospfh, Line 825  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 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 */
   #ifdef HAVE_OPAQUE_LSA
     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. */
   #endif
       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 2699  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 2725  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 2763  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 2887  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));

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


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