]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-isoclns.c
Protect code for particular Juniper DLT_ values with #ifdefs, so this
[tcpdump] / print-isoclns.c
index 73ecfb469e0dc1897c662b6dee1fa38ce9389b9c..ac3269c68a8b44327ae185762810c38622be716d 100644 (file)
@@ -26,7 +26,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.131 2005-03-22 08:18:10 hannes Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.133.2.8 2005-05-25 22:06:41 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -201,12 +201,20 @@ static struct tok esis_option_values[] = {
 
 #define CLNP_OPTION_DISCARD_REASON   193
 #define CLNP_OPTION_QOS_MAINTENANCE  195 /* iso8473 */
+#define CLNP_OPTION_SECURITY         197 /* iso8473 */
+#define CLNP_OPTION_SOURCE_ROUTING   200 /* iso8473 */
+#define CLNP_OPTION_ROUTE_RECORDING  203 /* iso8473 */
+#define CLNP_OPTION_PADDING          204 /* iso8473 */
 #define CLNP_OPTION_PRIORITY         205 /* iso8473 */
 
 static struct tok clnp_option_values[] = {
     { CLNP_OPTION_DISCARD_REASON,  "Discard Reason"},
     { CLNP_OPTION_PRIORITY,        "Priority"},
     { CLNP_OPTION_QOS_MAINTENANCE, "QoS Maintenance"},
+    { CLNP_OPTION_SECURITY, "Security"},
+    { CLNP_OPTION_SOURCE_ROUTING, "Source Routing"},
+    { CLNP_OPTION_ROUTE_RECORDING, "Route Recording"},
+    { CLNP_OPTION_PADDING, "Padding"},
     { 0, NULL }
 };
 
@@ -286,6 +294,40 @@ static struct tok *clnp_option_rfd_error_class[] = {
     NULL
 };
 
+#define CLNP_OPTION_OPTION_QOS_MASK 0x3f
+#define CLNP_OPTION_SCOPE_MASK      0xc0
+#define CLNP_OPTION_SCOPE_SA_SPEC   0x40
+#define CLNP_OPTION_SCOPE_DA_SPEC   0x80
+#define CLNP_OPTION_SCOPE_GLOBAL    0xc0
+
+static struct tok clnp_option_scope_values[] = {
+    { CLNP_OPTION_SCOPE_SA_SPEC, "Source Address Specific"},
+    { CLNP_OPTION_SCOPE_DA_SPEC, "Destination Address Specific"},
+    { CLNP_OPTION_SCOPE_GLOBAL, "Globally unique"},
+    { 0, NULL }
+};
+
+static struct tok clnp_option_sr_rr_values[] = {
+    { 0x0, "partial"},
+    { 0x0, "complete"},
+    { 0, NULL }
+};
+
+static struct tok clnp_option_sr_rr_string_values[] = {
+    { CLNP_OPTION_SOURCE_ROUTING, "source routing"},
+    { CLNP_OPTION_ROUTE_RECORDING, "recording of route in progress"},
+    { 0, NULL }
+};
+
+static struct tok clnp_option_qos_global_values[] = {
+    { 0x20, "reserved"},
+    { 0x10, "sequencing vs. delay"},
+    { 0x08, "congested"},
+    { 0x04, "delay vs. cost"},
+    { 0x02, "error vs. delay"},
+    { 0x01, "error vs. cost"},
+    { 0, NULL }
+};
 
 #define ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP           3 /* draft-ietf-isis-traffic-05 */
 #define ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID  4 /* draft-ietf-isis-gmpls-extensions */
@@ -586,7 +628,9 @@ void isoclns_print(const u_int8_t *p, u_int length, u_int caplen)
                break;
 
        case NLPID_NULLNS:
-               (void)printf(", length: %u", length);
+               (void)printf("%slength: %u",
+                            eflag ? "" : ", ",
+                             length);
                break;
 
         case NLPID_Q933:
@@ -594,7 +638,7 @@ void isoclns_print(const u_int8_t *p, u_int length, u_int caplen)
                 break;
 
         case NLPID_IP:
-                ip_print(p+1, length-1);
+               ip_print(gndo, p+1, length-1);
                 break;
 
 #ifdef INET6
@@ -610,7 +654,9 @@ void isoclns_print(const u_int8_t *p, u_int length, u_int caplen)
        default:
                 if (!eflag)
                     printf("OSI NLPID 0x%02x unknown",*p);
-               (void)printf(", length: %u", length);
+               (void)printf("%slength: %u",
+                            eflag ? "" : ", ",
+                             length);
                if (caplen > 1)
                         print_unknown_data(p,"\n\t",caplen);
                break;
@@ -656,7 +702,7 @@ struct clnp_segment_header_t {
 static int clnp_print (const u_int8_t *pptr, u_int length)
 {
        const u_int8_t *optr,*source_address,*dest_address;
-        u_int li,source_address_length,dest_address_length, clnp_pdu_type, clnp_flags;
+        u_int li,tlen,nsap_offset,source_address_length,dest_address_length, clnp_pdu_type, clnp_flags;
        const struct clnp_header_t *clnp_header;
        const struct clnp_segment_header_t *clnp_segment_header;
         u_int8_t rfd_error_major,rfd_error_minor;
@@ -746,8 +792,7 @@ static int clnp_print (const u_int8_t *pptr, u_int length)
             u_int op, opli;
             const u_int8_t *tptr;
             
-            if (snapend - pptr < 2)
-                return (0);
+            TCHECK2(*pptr, 2);
             if (li < 2) {
                 printf(", bad opts/li");
                 return (0);
@@ -755,15 +800,14 @@ static int clnp_print (const u_int8_t *pptr, u_int length)
             op = *pptr++;
             opli = *pptr++;
             li -= 2;
+            TCHECK2(*pptr, opli);
             if (opli > li) {
                 printf(", opt (%d) too long", op);
                 return (0);
             }
             li -= opli;
             tptr = pptr;
-            
-            if (snapend < pptr)
-                return(0);
+            tlen = opli;
             
             printf("\n\t  %s Option #%u, length %u, value: ",
                    tok2str(clnp_option_values,"Unknown",op),
@@ -772,9 +816,61 @@ static int clnp_print (const u_int8_t *pptr, u_int length)
 
             switch (op) {
 
+
+            case CLNP_OPTION_ROUTE_RECORDING: /* those two options share the format */
+            case CLNP_OPTION_SOURCE_ROUTING:  
+                    printf("%s %s",
+                           tok2str(clnp_option_sr_rr_values,"Unknown",*tptr),
+                           tok2str(clnp_option_sr_rr_string_values,"Unknown Option %u",op));
+                    nsap_offset=*(tptr+1);
+                    if (nsap_offset == 0) {
+                            printf(" Bad NSAP offset (0)");
+                            break;
+                    }
+                    nsap_offset-=1; /* offset to nsap list */
+                    if (nsap_offset > tlen) {
+                            printf(" Bad NSAP offset (past end of option)");
+                            break;
+                    }
+                    tptr+=nsap_offset;
+                    tlen-=nsap_offset;
+                    while (tlen > 0) {
+                            source_address_length=*tptr;
+                            if (tlen < source_address_length+1) {
+                                    printf("\n\t    NSAP address goes past end of option");
+                                    break;
+                           }
+                            if (source_address_length > 0) {
+                                    source_address=(tptr+1);
+                                    TCHECK2(*source_address, source_address_length);
+                                    printf("\n\t    NSAP address (length %u): %s",
+                                           source_address_length,
+                                           isonsap_string(source_address, source_address_length));
+                            }
+                            tlen-=source_address_length+1;
+                    }
+                    break;
+
             case CLNP_OPTION_PRIORITY:
-                printf("%u", *tptr);
-                break;
+                    printf("0x%1x", *tptr&0x0f);
+                    break;
+
+            case CLNP_OPTION_QOS_MAINTENANCE:
+                    printf("\n\t    Format Code: %s",
+                           tok2str(clnp_option_scope_values,"Reserved",*tptr&CLNP_OPTION_SCOPE_MASK));
+
+                    if ((*tptr&CLNP_OPTION_SCOPE_MASK) == CLNP_OPTION_SCOPE_GLOBAL)
+                            printf("\n\t    QoS Flags [%s]",
+                                   bittok2str(clnp_option_qos_global_values,
+                                              "none",
+                                              *tptr&CLNP_OPTION_OPTION_QOS_MASK));
+                    break;
+
+            case CLNP_OPTION_SECURITY:
+                    printf("\n\t    Format Code: %s, Security-Level %u",
+                           tok2str(clnp_option_scope_values,"Reserved",*tptr&CLNP_OPTION_SCOPE_MASK),
+                           *(tptr+1));
+                    break;
 
             case CLNP_OPTION_DISCARD_REASON:
                 rfd_error_major = (*tptr&0xf0) >> 4;
@@ -786,6 +882,10 @@ static int clnp_print (const u_int8_t *pptr, u_int length)
                        rfd_error_minor);
                 break;
 
+            case CLNP_OPTION_PADDING:
+                    printf("padding data");
+                break;
+
                 /*
                  * FIXME those are the defined Options that lack a decoder
                  * you are welcome to contribute code ;-)
@@ -804,6 +904,7 @@ static int clnp_print (const u_int8_t *pptr, u_int length)
 
         case    CLNP_PDU_ER: /* fall through */
         case   CLNP_PDU_ERP:
+            TCHECK(*pptr);
             if (*(pptr) == NLPID_CLNP) {
                 printf("\n\t-----original packet-----\n\t");
                 /* FIXME recursion protection */
@@ -817,9 +918,10 @@ static int clnp_print (const u_int8_t *pptr, u_int length)
             
         default:
             /* dump the PDU specific data */
-            printf("\n\t  undecoded non-header data, length %u",length-clnp_header->length_indicator);
-            print_unknown_data(pptr,"\n\t  ",length-(pptr-optr));
-
+            if (length-(pptr-optr) > 0) {
+                printf("\n\t  undecoded non-header data, length %u",length-clnp_header->length_indicator);
+                print_unknown_data(pptr,"\n\t  ",length-(pptr-optr));
+            }
         }
 
         return (1);
@@ -871,6 +973,7 @@ esis_print(const u_int8_t *pptr, u_int length)
        }
 
        esis_header = (const struct esis_header_t *) pptr;
+        TCHECK(*esis_header);
         li = esis_header->length_indicator;
         optr = pptr;
 
@@ -920,7 +1023,8 @@ esis_print(const u_int8_t *pptr, u_int length)
         /* do not attempt to verify the checksum if it is zero */
         if (EXTRACT_16BITS(esis_header->cksum) == 0)
                 printf("(unverified)");
-            else printf("(%s)", osi_cksum(pptr, li) ? "incorrect" : "correct");
+        else
+                printf("(%s)", osi_cksum(pptr, li) ? "incorrect" : "correct");
 
         printf(", holding time: %us, length indicator: %u",EXTRACT_16BITS(esis_header->holdtime),li);
 
@@ -932,25 +1036,72 @@ esis_print(const u_int8_t *pptr, u_int length)
 
        switch (esis_pdu_type) {
        case ESIS_PDU_REDIRECT: {
-               const u_int8_t *dst, *snpa, *tptr;
+               const u_int8_t *dst, *snpa, *neta;
+               u_int dstl, snpal, netal;
 
-               dst = pptr; pptr += *pptr + 1;
-               if (pptr > snapend)
+               TCHECK(*pptr);
+               if (li < 1) {
+                       printf(", bad redirect/li");
+                       return;
+               }
+               dstl = *pptr;
+               pptr++;
+               li--;
+               TCHECK2(*pptr, dstl);
+               if (li < dstl) {
+                       printf(", bad redirect/li");
                        return;
-               printf("\n\t  %s", isonsap_string(dst+1,*dst));
-               snpa = pptr; pptr += *pptr + 1;
-               tptr = pptr;   pptr += *pptr + 1;
-               if (pptr > snapend)
+               }
+               dst = pptr;
+               pptr += dstl;
+                li -= dstl;
+               printf("\n\t  %s", isonsap_string(dst,dstl));
+
+               TCHECK(*pptr);
+               if (li < 1) {
+                       printf(", bad redirect/li");
+                       return;
+               }
+               snpal = *pptr;
+               pptr++;
+               li--;
+               TCHECK2(*pptr, snpal);
+               if (li < snpal) {
+                       printf(", bad redirect/li");
+                       return;
+               }
+               snpa = pptr;
+               pptr += snpal;
+                li -= snpal;
+               TCHECK(*pptr);
+               if (li < 1) {
+                       printf(", bad redirect/li");
+                       return;
+               }
+               netal = *pptr;
+               pptr++;
+               TCHECK2(*pptr, netal);
+               if (li < netal) {
+                       printf(", bad redirect/li");
                        return;
+               }
+               neta = pptr;
+               pptr += netal;
+                li -= netal;
 
-               if (tptr[0] == 0)
-                       printf("\n\t  %s", etheraddr_string(&snpa[1]));
+               if (netal == 0)
+                       printf("\n\t  %s", etheraddr_string(snpa));
                else
-                       printf("\n\t  %s", isonsap_string(tptr+1,*tptr));
+                       printf("\n\t  %s", isonsap_string(neta,netal));
                break;
        }
 
        case ESIS_PDU_ESH:
+            TCHECK(*pptr);
+            if (li < 1) {
+                printf(", bad esh/li");
+                return;
+            }
             source_address_number = *pptr;
             pptr++;
             li--;
@@ -958,23 +1109,47 @@ esis_print(const u_int8_t *pptr, u_int length)
             printf("\n\t  Number of Source Addresses: %u", source_address_number);
            
             while (source_address_number > 0) {
+                TCHECK(*pptr);
+               if (li < 1) {
+                    printf(", bad esh/li");
+                   return;
+               }
                 source_address_length = *pptr;
+                pptr++;
+               li--;
+
+                TCHECK2(*pptr, source_address_length);
+               if (li < source_address_length) {
+                    printf(", bad esh/li");
+                   return;
+               }
                 printf("\n\t  NET (length: %u): %s",
                        source_address_length,
-                       isonsap_string(pptr+1,source_address_length));
-
-                pptr += source_address_length+1;
-                li -= source_address_length+1;
+                       isonsap_string(pptr,source_address_length));
+                pptr += source_address_length;
+                li -= source_address_length;
                 source_address_number--;
             }
 
             break;
 
        case ESIS_PDU_ISH: {
+            TCHECK(*pptr);
+            if (li < 1) {
+                printf(", bad ish/li");
+                return;
+            }
             source_address_length = *pptr;
-            printf("\n\t  NET (length: %u): %s", source_address_length, isonsap_string(pptr+1, source_address_length));
-            pptr += source_address_length+1;
-            li -= source_address_length +1;
+            pptr++;
+            li--;
+            TCHECK2(*pptr, source_address_length);
+            if (li < source_address_length) {
+                printf(", bad ish/li");
+                return;
+            }
+            printf("\n\t  NET (length: %u): %s", source_address_length, isonsap_string(pptr, source_address_length));
+            pptr += source_address_length;
+            li -= source_address_length;
             break;
        }
 
@@ -991,8 +1166,7 @@ esis_print(const u_int8_t *pptr, u_int length)
             u_int op, opli;
             const u_int8_t *tptr;
             
-            if (snapend - pptr < 2)
-                return;
+            TCHECK2(*pptr, 2);
             if (li < 2) {
                 printf(", bad opts/li");
                 return;
@@ -1007,9 +1181,6 @@ esis_print(const u_int8_t *pptr, u_int length)
             li -= opli;
             tptr = pptr;
             
-            if (snapend < pptr)
-                return;
-            
             printf("\n\t  %s Option #%u, length %u, value: ",
                    tok2str(esis_option_values,"Unknown",op),
                    op,
@@ -1018,12 +1189,13 @@ esis_print(const u_int8_t *pptr, u_int length)
             switch (op) {
 
             case ESIS_OPTION_ES_CONF_TIME:
+                TCHECK2(*pptr, 2);
                 printf("%us", EXTRACT_16BITS(tptr));
                 break;
-                
 
             case ESIS_OPTION_PROTOCOLS:
                 while (opli>0) {
+                    TCHECK(*pptr);
                     printf("%s (0x%02x)",
                            tok2str(nlpid_values,
                                    "unknown",
@@ -1055,6 +1227,8 @@ esis_print(const u_int8_t *pptr, u_int length)
                 print_unknown_data(pptr,"\n\t  ",opli);
             pptr += opli;
         }
+trunc:
+       return;
 }   
 
 /* shared routine for printing system, node and lsp-ids */
@@ -1904,6 +2078,9 @@ static int isis_print (const u_int8_t *p, u_int length)
                tlv_type,
                tlv_len);
 
+        if (tlv_len == 0) /* something is malformed */
+            break;
+
         /* now check if we have a decoder otherwise do a hexdump at the end*/
        switch (tlv_type) {
        case ISIS_TLV_AREA_ADDR:
@@ -1934,9 +2111,13 @@ static int isis_print (const u_int8_t *p, u_int length)
            break;
 
         case ISIS_TLV_ISNEIGH_VARLEN:
-            if (!TTEST2(*tptr, 1))
+            if (!TTEST2(*tptr, 1) || tmp < 3) /* min. TLV length */
                goto trunctlv;
-           lan_alen = *tptr++; /* LAN adress length */
+           lan_alen = *tptr++; /* LAN address length */
+           if (lan_alen == 0) {
+                printf("\n\t      LAN address length 0 bytes (invalid)");
+                break;
+            }
             tmp --;
             printf("\n\t      LAN address length %u bytes ",lan_alen);
            while (tmp >= lan_alen) {
@@ -2347,6 +2528,10 @@ static int isis_print (const u_int8_t *p, u_int length)
                 if (!TTEST2(*tptr, 1))
                     goto trunctlv;
                 prefix_len=*tptr++; /* read out prefix length in semioctets*/
+                if (prefix_len < 2) {
+                    printf("\n\t\tAddress: prefix length %u < 2", prefix_len);
+                    break;
+                }
                 tmp--;
                 if (!TTEST2(*tptr, prefix_len/2))
                     goto trunctlv;
@@ -2436,3 +2621,11 @@ osi_cksum(const u_int8_t *tptr, u_int len)
        }
        return (c0 | c1);
 }
+
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */