]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-ospf.c
Avoiding conditional directives that break statements
[tcpdump] / print-ospf.c
index b64438fa676f98fa0cb6cad4b147a85d81347943..6d8abf48e35f6d72960eb0897dc54df01b8775d7 100644 (file)
  * OSPF support contributed by Jeffrey Honig ([email protected])
  */
 
-#define NETDISSECT_REWORKED
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <tcpdump-stdinc.h>
+#include <netdissect-stdinc.h>
 
-#include "interface.h"
+#include "netdissect.h"
 #include "addrtoname.h"
 #include "extract.h"
 #include "gmpls.h"
@@ -36,6 +35,7 @@
 #include "ospf.h"
 
 static const char tstr[] = " [|ospf2]";
+static const char istr[] = " (invalid)";
 
 static const struct tok ospf_option_values[] = {
         { OSPF_OPTION_T,       "MultiTopology" }, /* draft-ietf-ospf-mt-09 */
@@ -181,8 +181,8 @@ static const struct tok ospf_lls_eo_options[] = {
 
 int
 ospf_print_grace_lsa(netdissect_options *ndo,
-                     const uint8_t *tptr, u_int ls_length) {
-
+                     const uint8_t *tptr, u_int ls_length)
+{
     u_int tlv_type, tlv_length;
 
 
@@ -264,8 +264,8 @@ trunc:
 
 int
 ospf_print_te_lsa(netdissect_options *ndo,
-                  const uint8_t *tptr, u_int ls_length) {
-
+                  const uint8_t *tptr, u_int ls_length)
+{
     u_int tlv_type, tlv_length, subtlv_type, subtlv_length;
     u_int priority_level, te_class, count_srlg;
     union { /* int to float conversion buffer for several subTLVs */
@@ -314,6 +314,10 @@ ospf_print_te_lsa(netdissect_options *ndo,
                 tptr+=4;
                 tlv_length-=4;
 
+               /* Infinite loop protection */
+               if (subtlv_type == 0 || subtlv_length == 0)
+                   goto invalid;
+
                 ND_PRINT((ndo, "\n\t      %s subTLV (%u), length: %u",
                        tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
                        subtlv_type,
@@ -322,10 +326,18 @@ ospf_print_te_lsa(netdissect_options *ndo,
                 ND_TCHECK2(*tptr, subtlv_length);
                 switch(subtlv_type) {
                 case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
+                   if (subtlv_length != 4) {
+                       ND_PRINT((ndo, " != 4"));
+                       goto invalid;
+                   }
                     ND_PRINT((ndo, ", 0x%08x", EXTRACT_32BITS(tptr)));
                     break;
                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID:
                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID:
+                   if (subtlv_length != 4 && subtlv_length != 8) {
+                       ND_PRINT((ndo, " != 4 && != 8"));
+                       goto invalid;
+                   }
                     ND_PRINT((ndo, ", %s (0x%08x)",
                            ipaddr_string(ndo, tptr),
                            EXTRACT_32BITS(tptr)));
@@ -336,14 +348,26 @@ ospf_print_te_lsa(netdissect_options *ndo,
                     break;
                 case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP:
                 case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP:
+                   if (subtlv_length != 4) {
+                       ND_PRINT((ndo, " != 4"));
+                       goto invalid;
+                   }
                     ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr)));
                     break;
                 case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW:
                 case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW:
+                   if (subtlv_length != 4) {
+                       ND_PRINT((ndo, " != 4"));
+                       goto invalid;
+                   }
                     bw.i = EXTRACT_32BITS(tptr);
                     ND_PRINT((ndo, ", %.3f Mbps", bw.f * 8 / 1000000));
                     break;
                 case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
+                   if (subtlv_length != 32) {
+                       ND_PRINT((ndo, " != 32"));
+                       goto invalid;
+                   }
                     for (te_class = 0; te_class < 8; te_class++) {
                         bw.i = EXTRACT_32BITS(tptr+te_class*4);
                         ND_PRINT((ndo, "\n\t\tTE-Class %u: %.3f Mbps",
@@ -352,9 +376,22 @@ ospf_print_te_lsa(netdissect_options *ndo,
                     }
                     break;
                 case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
+                   if (subtlv_length < 4) {
+                       ND_PRINT((ndo, " < 4"));
+                       goto invalid;
+                   }
+                   /* BC Model Id (1 octet) + Reserved (3 octets) */
                     ND_PRINT((ndo, "\n\t\tBandwidth Constraints Model ID: %s (%u)",
                            tok2str(diffserv_te_bc_values, "unknown", *tptr),
                            *tptr));
+                   if (subtlv_length % 4 != 0) {
+                       ND_PRINT((ndo, "\n\t\tlength %u != N x 4", subtlv_length));
+                       goto invalid;
+                   }
+                   if (subtlv_length > 36) {
+                       ND_PRINT((ndo, "\n\t\tlength %u > 36", subtlv_length));
+                       goto invalid;
+                   }
                     /* decode BCs until the subTLV ends */
                     for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) {
                         bw.i = EXTRACT_32BITS(tptr+4+te_class*4);
@@ -364,14 +401,27 @@ ospf_print_te_lsa(netdissect_options *ndo,
                     }
                     break;
                 case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC:
+                   if (subtlv_length != 4) {
+                       ND_PRINT((ndo, " != 4"));
+                       goto invalid;
+                   }
                     ND_PRINT((ndo, ", Metric %u", EXTRACT_32BITS(tptr)));
                     break;
                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE:
-                    ND_PRINT((ndo, ", %s, Priority %u",
-                           bittok2str(gmpls_link_prot_values, "none", *tptr),
-                           *(tptr + 1)));
+                   /* Protection Cap (1 octet) + Reserved ((3 octets) */
+                   if (subtlv_length != 4) {
+                       ND_PRINT((ndo, " != 4"));
+                       goto invalid;
+                   }
+                    ND_PRINT((ndo, ", %s",
+                             bittok2str(gmpls_link_prot_values, "none", *tptr)));
                     break;
                 case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR:
+                   if (subtlv_length < 36) {
+                       ND_PRINT((ndo, " < 36"));
+                       goto invalid;
+                   }
+                   /* Switching Cap (1 octet) + Encoding (1) +  Reserved (2) */
                     ND_PRINT((ndo, "\n\t\tInterface Switching Capability: %s",
                            tok2str(gmpls_switch_cap_values, "Unknown", *(tptr))));
                     ND_PRINT((ndo, "\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:",
@@ -384,12 +434,20 @@ ospf_print_te_lsa(netdissect_options *ndo,
                     }
                     break;
                 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE:
+                   if (subtlv_length != 1) {
+                       ND_PRINT((ndo, " != 1"));
+                       goto invalid;
+                   }
                     ND_PRINT((ndo, ", %s (%u)",
                            tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr),
                            *tptr));
                     break;
 
                 case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP:
+                   if (subtlv_length % 4 != 0) {
+                       ND_PRINT((ndo, " != N x 4"));
+                       goto invalid;
+                   }
                     count_srlg = subtlv_length / 4;
                     if (count_srlg != 0)
                         ND_PRINT((ndo, "\n\t\t  Shared risk group: "));
@@ -445,6 +503,9 @@ ospf_print_te_lsa(netdissect_options *ndo,
     return 0;
 trunc:
     return -1;
+invalid:
+    ND_PRINT((ndo, "%s", istr));
+    return -1;
 }
 
 static int
@@ -559,11 +620,11 @@ ospf_print_lsa(netdissect_options *ndo,
        register int ls_length;
        const uint8_t *tptr;
 
-       tptr = (uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
+       tptr = (const uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
         ls_length = ospf_print_lshdr(ndo, &lsap->ls_hdr);
         if (ls_length == -1)
                 return(NULL);
-       ls_end = (uint8_t *)lsap + ls_length;
+       ls_end = (const uint8_t *)lsap + ls_length;
        ls_length -= sizeof(struct lsa_hdr);
 
        switch (lsap->ls_hdr.ls_type) {
@@ -613,7 +674,7 @@ ospf_print_lsa(netdissect_options *ndo,
 
                        ospf_print_tos_metrics(ndo, &rlp->un_tos);
 
-                       rlp = (struct rlalink *)((u_char *)(rlp + 1) +
+                       rlp = (const struct rlalink *)((const u_char *)(rlp + 1) +
                            ((rlp->un_tos.link.link_tos_count) * sizeof(union un_tos)));
                }
                break;
@@ -623,7 +684,7 @@ ospf_print_lsa(netdissect_options *ndo,
                ND_PRINT((ndo, "\n\t    Mask %s\n\t    Connected Routers:",
                    ipaddr_string(ndo, &lsap->lsa_un.un_nla.nla_mask)));
                ap = lsap->lsa_un.un_nla.nla_router;
-               while ((u_char *)ap < ls_end) {
+               while ((const u_char *)ap < ls_end) {
                        ND_TCHECK(*ap);
                        ND_PRINT((ndo, "\n\t      %s", ipaddr_string(ndo, ap)));
                        ++ap;
@@ -636,7 +697,7 @@ ospf_print_lsa(netdissect_options *ndo,
                    ipaddr_string(ndo, &lsap->lsa_un.un_sla.sla_mask)));
                ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
                lp = lsap->lsa_un.un_sla.sla_tosmetric;
-               while ((u_char *)lp < ls_end) {
+               while ((const u_char *)lp < ls_end) {
                        register uint32_t ul;
 
                        ND_TCHECK(*lp);
@@ -653,7 +714,7 @@ ospf_print_lsa(netdissect_options *ndo,
        case LS_TYPE_SUM_ABR:
                ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
                lp = lsap->lsa_un.un_sla.sla_tosmetric;
-               while ((u_char *)lp < ls_end) {
+               while ((const u_char *)lp < ls_end) {
                        register uint32_t ul;
 
                        ND_TCHECK(*lp);
@@ -675,7 +736,7 @@ ospf_print_lsa(netdissect_options *ndo,
 
                ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
                almp = lsap->lsa_un.un_asla.asla_metric;
-               while ((u_char *)almp < ls_end) {
+               while ((const u_char *)almp < ls_end) {
                        register uint32_t ul;
 
                        ND_TCHECK(almp->asla_tosmetric);
@@ -705,7 +766,7 @@ ospf_print_lsa(netdissect_options *ndo,
        case LS_TYPE_GROUP:
                /* Multicast extensions as of 23 July 1991 */
                mcp = lsap->lsa_un.un_mcla;
-               while ((u_char *)mcp < ls_end) {
+               while ((const u_char *)mcp < ls_end) {
                        ND_TCHECK(mcp->mcla_vid);
                        switch (EXTRACT_32BITS(&mcp->mcla_vtype)) {
 
@@ -734,7 +795,7 @@ ospf_print_lsa(netdissect_options *ndo,
 
            switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) {
             case LS_OPAQUE_TYPE_RI:
-               tptr = (uint8_t *)(&lsap->lsa_un.un_ri_tlv.type);
+               tptr = (const uint8_t *)(&lsap->lsa_un.un_ri_tlv.type);
 
                while (ls_length != 0) {
                     ND_TCHECK2(*tptr, 4);
@@ -782,14 +843,14 @@ ospf_print_lsa(netdissect_options *ndo,
                 break;
 
             case LS_OPAQUE_TYPE_GRACE:
-                if (ospf_print_grace_lsa(ndo, (uint8_t *)(&lsap->lsa_un.un_grace_tlv.type),
+                if (ospf_print_grace_lsa(ndo, (const uint8_t *)(&lsap->lsa_un.un_grace_tlv.type),
                                          ls_length) == -1) {
                     return(ls_end);
                 }
                 break;
 
            case LS_OPAQUE_TYPE_TE:
-                if (ospf_print_te_lsa(ndo, (uint8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type),
+                if (ospf_print_te_lsa(ndo, (const uint8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type),
                                       ls_length) == -1) {
                     return(ls_end);
                 }
@@ -797,7 +858,7 @@ ospf_print_lsa(netdissect_options *ndo,
 
             default:
                 if (ndo->ndo_vflag <= 1) {
-                    if (!print_unknown_data(ndo, (uint8_t *)lsap->lsa_un.un_unknown,
+                    if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
                                            "\n\t    ", ls_length))
                         return(ls_end);
                 }
@@ -807,7 +868,7 @@ ospf_print_lsa(netdissect_options *ndo,
 
         /* do we want to see an additionally hexdump ? */
         if (ndo->ndo_vflag> 1)
-            if (!print_unknown_data(ndo, (uint8_t *)lsap->lsa_un.un_unknown,
+            if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
                                    "\n\t    ", ls_length)) {
                 return(ls_end);
             }
@@ -845,8 +906,8 @@ ospf_decode_lls(netdissect_options *ndo,
 
     /* dig deeper if LLS data is available; see RFC4813 */
     length2 = EXTRACT_16BITS(&op->ospf_len);
-    dptr = (u_char *)op + length2;
-    dataend = (u_char *)op + length;
+    dptr = (const u_char *)op + length2;
+    dataend = (const u_char *)op + length;
 
     if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) {
         dptr = dptr + op->ospf_authdata[3];
@@ -950,9 +1011,9 @@ ospf_decode_v2(netdissect_options *ndo,
                                  ipaddr_string(ndo, &op->ospf_hello.hello_bdr)));
 
                ap = op->ospf_hello.hello_neighbor;
-               if ((u_char *)ap < dataend)
+               if ((const u_char *)ap < dataend)
                        ND_PRINT((ndo, "\n\t  Neighbor List:"));
-               while ((u_char *)ap < dataend) {
+               while ((const u_char *)ap < dataend) {
                        ND_TCHECK(*ap);
                        ND_PRINT((ndo, "\n\t    %s", ipaddr_string(ndo, ap)));
                        ++ap;
@@ -975,14 +1036,14 @@ ospf_decode_v2(netdissect_options *ndo,
 
                /* Print all the LS adv's */
                lshp = op->ospf_db.db_lshdr;
-               while (((u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) {
+               while (((const u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) {
                        ++lshp;
                }
                break;
 
        case OSPF_TYPE_LS_REQ:
                 lsrp = op->ospf_lsr;
-                while ((u_char *)lsrp < dataend) {
+                while ((const u_char *)lsrp < dataend) {
                     ND_TCHECK(*lsrp);
 
                     ND_PRINT((ndo, "\n\t  Advertising Router: %s, %s LSA (%u)",
@@ -1047,7 +1108,7 @@ ospf_print(netdissect_options *ndo,
        register const u_char *dataend;
        register const char *cp;
 
-       op = (struct ospfhdr *)bp;
+       op = (const struct ospfhdr *)bp;
 
        /* XXX Before we do anything else, strip off the MD5 trailer */
        ND_TCHECK(op->ospf_authtype);