CVE-2017-13003 (published 2017-09-14T06:29Z)

The LMP parser in tcpdump before 4.9.2 has a buffer over-read in print-lmp.c:lmp_print().

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-125
cwe_name: Out-of-bounds Read
description: The product reads data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/the-tcpdump-group/tcpdump
commit_details: repo_url: https://github.com/the-tcpdump-group/tcpdump
author: Guy Harris
author_date: 2017-02-19 21:13:25-08:00
msg: CVE-2017-13003/Clean up the LMP dissector.

Do a lot more bounds and length checks.

Add a EXTRACT_8BITS() macro, for completeness, and so as not to confuse
people into thinking that, to fetch a 1-byte value from a packet, they
need to use EXTRACT_16BITS() to fetch a 2-byte value and then use
shifting and masking to extract the desired byte.  Use that rather than
using EXTRACT_16BITS() to fetch a 2-byte value and then shifting and
masking to extract the desired byte.

Don't treat IPv4 addresses and unnumbered interface IDs the same; the
first should be printed as an IPv4 address but the latter should just be
printed as numbers.  Handle IPv6 addresses in more object types while
we're at it.

This fixes a buffer over-read discovered by Forcepoint's security
researchers Otto Airamo & Antti Levomäki.

Add a test using the capture file supplied by the reporter(s).
repository: repo_url: https://github.com/the-tcpdump-group/tcpdump
repo_name: the-tcpdump-group/tcpdump
description: the TCPdump network dissector
repo_language: C
owner: the-tcpdump-group
file_changes: filename: extract.h
change_type: ModificationType.MODIFY
diff: @@ -19,6 +19,13 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/*
+ * For 8-bit values; provided for the sake of completeness.  Byte order
+ * isn't relevant, and alignment isn't an issue.
+ */
+#define EXTRACT_8BITS(p)	(*(p))
+#define EXTRACT_LE_8BITS(p)	(*(p))
+
 /*
  * Inline functions or macros to extract possibly-unaligned big-endian
  * integral values.
@@ -226,7 +233,6 @@ EXTRACT_64BITS(const void *p)
  * Macros to extract possibly-unaligned little-endian integral values.
  * XXX - do loads on little-endian machines that support unaligned loads?
  */
-#define EXTRACT_LE_8BITS(p) (*(p))
 #define EXTRACT_LE_16BITS(p) \
 	((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
 	            ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))

programming_language: C
filename: print-lmp.c
change_type: ModificationType.MODIFY
diff: @@ -11,13 +11,14 @@
  * FOR A PARTICULAR PURPOSE.
  *
  * Original code by Hannes Gredler (hannes@gredler.at)
- * Support for LMP service discovery extensions (defined by UNI 1.0) added
- * by Manu Pathak (mapathak@cisco.com), May 2005
+ * Support for LMP service discovery extensions (defined by OIF UNI 1.0)
+ * added by Manu Pathak (mapathak@cisco.com), May 2005
  */
 
 /* \summary: Link Management Protocol (LMP) printer */
 
 /* specification: RFC 4204 */
+/* OIF UNI 1.0: http://www.oiforum.com/public/documents/OIF-UNI-01.0.pdf */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -353,6 +354,73 @@ static const struct tok lmp_ctype_values[] = {
     { 0, NULL}
 };
 
+static int
+lmp_print_data_link_subobjs(netdissect_options *ndo, const u_char *obj_tptr,
+                            int total_subobj_len, int offset)
+{
+    int hexdump = FALSE;
+    int subobj_type, subobj_len;
+
+    union { /* int to float conversion buffer */
+        float f;
+        uint32_t i;
+    } bw;
+
+    while (total_subobj_len > 0 && hexdump == FALSE ) {
+	subobj_type = EXTRACT_8BITS(obj_tptr+offset);
+	subobj_len  = EXTRACT_8BITS(obj_tptr+offset+1);
+	ND_PRINT((ndo, "\n\t    Subobject, Type: %s (%u), Length: %u",
+		tok2str(lmp_data_link_subobj,
+			"Unknown",
+			subobj_type),
+			subobj_type,
+			subobj_len));
+	if (subobj_len < 4) {
+	    ND_PRINT((ndo, " (too short)"));
+	    break;
+	}
+	if ((subobj_len % 4) != 0) {
+	    ND_PRINT((ndo, " (not a multiple of 4)"));
+	    break;
+	}
+	if (total_subobj_len < subobj_len) {
+	    ND_PRINT((ndo, " (goes past the end of the object)"));
+	    break;
+	}
+	switch(subobj_type) {
+	case INT_SWITCHING_TYPE_SUBOBJ:
+	    ND_PRINT((ndo, "\n\t      Switching Type: %s (%u)",
+		tok2str(gmpls_switch_cap_values,
+			"Unknown",
+			EXTRACT_8BITS(obj_tptr+offset+2)),
+		EXTRACT_8BITS(obj_tptr+offset+2)));
+	    ND_PRINT((ndo, "\n\t      Encoding Type: %s (%u)",
+		tok2str(gmpls_encoding_values,
+			"Unknown",
+			EXTRACT_8BITS(obj_tptr+offset+3)),
+		EXTRACT_8BITS(obj_tptr+offset+3)));
+	    bw.i = EXTRACT_32BITS(obj_tptr+offset+4);
+	    ND_PRINT((ndo, "\n\t      Min Reservable Bandwidth: %.3f Mbps",
+                bw.f*8/1000000));
+	    bw.i = EXTRACT_32BITS(obj_tptr+offset+8);
+	    ND_PRINT((ndo, "\n\t      Max Reservable Bandwidth: %.3f Mbps",
+                bw.f*8/1000000));
+	    break;
+	case WAVELENGTH_SUBOBJ:
+	    ND_PRINT((ndo, "\n\t      Wavelength: %u",
+		EXTRACT_32BITS(obj_tptr+offset+4)));
+	    break;
+	default:
+	    /* Any Unknown Subobject ==> Exit loop */
+	    hexdump=TRUE;
+	    break;
+	}
+	total_subobj_len-=subobj_len;
+	offset+=subobj_len;
+    }
+    return (hexdump);
+}
+
 void
 lmp_print(netdissect_options *ndo,
           register const u_char *pptr, register u_int len)
@@ -360,10 +428,10 @@ lmp_print(netdissect_options *ndo,
     const struct lmp_common_header *lmp_com_header;
     const struct lmp_object_header *lmp_obj_header;
     const u_char *tptr,*obj_tptr;
-    int tlen,lmp_obj_len,lmp_obj_ctype,obj_tlen;
+    u_int tlen,lmp_obj_len,lmp_obj_ctype,obj_tlen;
     int hexdump;
-    int offset,subobj_type,subobj_len,total_subobj_len;
-    int link_type;
+    u_int offset;
+    u_int link_type;
 
     union { /* int to float conversion buffer */
         float f;
@@ -401,6 +469,14 @@ lmp_print(netdissect_options *ndo,
            tok2str(lmp_msg_type_values, "unknown, type: %u",lmp_com_header->msg_type),
            bittok2str(lmp_header_flag_values,"none",lmp_com_header->flags),
            tlen));
+    if (tlen < sizeof(const struct lmp_common_header)) {
+        ND_PRINT((ndo, " (too short)"));
+        return;
+    }
+    if (tlen > len) {
+        ND_PRINT((ndo, " (too long)"));
+        tlen = len;
+    }
 
     tptr+=sizeof(const struct lmp_common_header);
     tlen-=sizeof(const struct lmp_common_header);
@@ -413,9 +489,6 @@ lmp_print(netdissect_options *ndo,
         lmp_obj_len=EXTRACT_16BITS(lmp_obj_header->length);
         lmp_obj_ctype=(lmp_obj_header->ctype)&0x7f;
 
-        if(lmp_obj_len % 4 || lmp_obj_len < 4)
-            return;
-
         ND_PRINT((ndo, "\n\t  %s Object (%u), Class-Type: %s (%u) Flags: [%snegotiable], length: %u",
                tok2str(lmp_obj_values,
                        "Unknown",
@@ -428,6 +501,15 @@ lmp_print(netdissect_options *ndo,
                (lmp_obj_header->ctype)&0x80 ? "" : "non-",
                lmp_obj_len));
 
+        if (lmp_obj_len < 4) {
+            ND_PRINT((ndo, " (too short)"));
+            return;
+        }
+        if ((lmp_obj_len % 4) != 0) {
+            ND_PRINT((ndo, " (not a multiple of 4)"));
+            return;
+        }
+
         obj_tptr=tptr+sizeof(struct lmp_object_header);
         obj_tlen=lmp_obj_len-sizeof(struct lmp_object_header);
 
@@ -441,6 +523,10 @@ lmp_print(netdissect_options *ndo,
             switch(lmp_obj_ctype) {
             case LMP_CTYPE_LOC:
             case LMP_CTYPE_RMT:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    Control Channel ID: %u (0x%08x)",
                        EXTRACT_32BITS(obj_tptr),
                        EXTRACT_32BITS(obj_tptr)));
@@ -456,18 +542,30 @@ lmp_print(netdissect_options *ndo,
             switch(lmp_obj_ctype) {
             case LMP_CTYPE_IPV4_LOC:
             case LMP_CTYPE_IPV4_RMT:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    IPv4 Link ID: %s (0x%08x)",
                        ipaddr_string(ndo, obj_tptr),
                        EXTRACT_32BITS(obj_tptr)));
                 break;
             case LMP_CTYPE_IPV6_LOC:
             case LMP_CTYPE_IPV6_RMT:
+                if (obj_tlen != 16) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    IPv6 Link ID: %s (0x%08x)",
                        ip6addr_string(ndo, obj_tptr),
                        EXTRACT_32BITS(obj_tptr)));
                 break;
             case LMP_CTYPE_UNMD_LOC:
             case LMP_CTYPE_UNMD_RMT:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    Link ID: %u (0x%08x)",
                        EXTRACT_32BITS(obj_tptr),
                        EXTRACT_32BITS(obj_tptr)));
@@ -480,11 +578,19 @@ lmp_print(netdissect_options *ndo,
         case LMP_OBJ_MESSAGE_ID:
             switch(lmp_obj_ctype) {
             case LMP_CTYPE_1:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    Message ID: %u (0x%08x)",
                        EXTRACT_32BITS(obj_tptr),
                        EXTRACT_32BITS(obj_tptr)));
                 break;
             case LMP_CTYPE_2:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    Message ID Ack: %u (0x%08x)",
                        EXTRACT_32BITS(obj_tptr),
                        EXTRACT_32BITS(obj_tptr)));
@@ -498,6 +604,10 @@ lmp_print(netdissect_options *ndo,
             switch(lmp_obj_ctype) {
             case LMP_CTYPE_LOC:
             case LMP_CTYPE_RMT:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    Node ID: %s (0x%08x)",
                        ipaddr_string(ndo, obj_tptr),
                        EXTRACT_32BITS(obj_tptr)));
@@ -511,6 +621,10 @@ lmp_print(netdissect_options *ndo,
         case LMP_OBJ_CONFIG:
             switch(lmp_obj_ctype) {
             case LMP_CTYPE_HELLO_CONFIG:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    Hello Interval: %u\n\t    Hello Dead Interval: %u",
                        EXTRACT_16BITS(obj_tptr),
                        EXTRACT_16BITS(obj_tptr+2)));
@@ -524,6 +638,10 @@ lmp_print(netdissect_options *ndo,
         case LMP_OBJ_HELLO:
             switch(lmp_obj_ctype) {
 	    case LMP_CTYPE_HELLO:
+                if (obj_tlen != 8) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    Tx Seq: %u, Rx Seq: %u",
                        EXTRACT_32BITS(obj_tptr),
                        EXTRACT_32BITS(obj_tptr+4)));
@@ -535,13 +653,17 @@ lmp_print(netdissect_options *ndo,
             break;
 
         case LMP_OBJ_TE_LINK:
+	    switch(lmp_obj_ctype) {
+	    case LMP_CTYPE_IPV4:
+                if (obj_tlen != 12) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
 		ND_PRINT((ndo, "\n\t    Flags: [%s]",
-		bittok2str(lmp_obj_te_link_flag_values,
+		    bittok2str(lmp_obj_te_link_flag_values,
 			"none",
-			EXTRACT_16BITS(obj_tptr)>>8)));
+			EXTRACT_8BITS(obj_tptr))));
 
-	    switch(lmp_obj_ctype) {
-	    case LMP_CTYPE_IPV4:
 		ND_PRINT((ndo, "\n\t    Local Link-ID: %s (0x%08x)"
 		       "\n\t    Remote Link-ID: %s (0x%08x)",
                        ipaddr_string(ndo, obj_tptr+4),
@@ -551,21 +673,57 @@ lmp_print(netdissect_options *ndo,
 		break;
 
 	    case LMP_CTYPE_IPV6:
+                if (obj_tlen != 36) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
+		ND_PRINT((ndo, "\n\t    Flags: [%s]",
+		    bittok2str(lmp_obj_te_link_flag_values,
+			"none",
+			EXTRACT_8BITS(obj_tptr))));
+
+		ND_PRINT((ndo, "\n\t    Local Link-ID: %s (0x%08x)"
+		       "\n\t    Remote Link-ID: %s (0x%08x)",
+                       ip6addr_string(ndo, obj_tptr+4),
+                       EXTRACT_32BITS(obj_tptr+4),
+                       ip6addr_string(ndo, obj_tptr+20),
+                       EXTRACT_32BITS(obj_tptr+20)));
+                break;
+
 	    case LMP_CTYPE_UNMD:
+                if (obj_tlen != 12) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
+		ND_PRINT((ndo, "\n\t    Flags: [%s]",
+		    bittok2str(lmp_obj_te_link_flag_values,
+			"none",
+			EXTRACT_8BITS(obj_tptr))));
+
+		ND_PRINT((ndo, "\n\t    Local Link-ID: %u (0x%08x)"
+		       "\n\t    Remote Link-ID: %u (0x%08x)",
+                       EXTRACT_32BITS(obj_tptr+4),
+                       EXTRACT_32BITS(obj_tptr+4),
+                       EXTRACT_32BITS(obj_tptr+8),
+                       EXTRACT_32BITS(obj_tptr+8)));
+		break;
+
             default:
                 hexdump=TRUE;
             }
             break;
 
         case LMP_OBJ_DATA_LINK:
-		ND_PRINT((ndo, "\n\t    Flags: [%s]",
-		bittok2str(lmp_obj_data_link_flag_values,
-			"none",
-			EXTRACT_16BITS(obj_tptr)>>8)));
-
 	    switch(lmp_obj_ctype) {
 	    case LMP_CTYPE_IPV4:
-	    case LMP_CTYPE_UNMD:
+                if (obj_tlen < 12) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
+	        ND_PRINT((ndo, "\n\t    Flags: [%s]",
+		    bittok2str(lmp_obj_data_link_flag_values,
+			"none",
+			EXTRACT_8BITS(obj_tptr))));
                 ND_PRINT((ndo, "\n\t    Local Interface ID: %s (0x%08x)"
                        "\n\t    Remote Interface ID: %s (0x%08x)",
                        ipaddr_string(ndo, obj_tptr+4),
@@ -573,51 +731,50 @@ lmp_print(netdissect_options *ndo,
                        ipaddr_string(ndo, obj_tptr+8),
                        EXTRACT_32BITS(obj_tptr+8)));
 
-		total_subobj_len = lmp_obj_len - 16;
-		offset = 12;
-		while (total_subobj_len > 0 && hexdump == FALSE ) {
-			subobj_type = EXTRACT_16BITS(obj_tptr+offset)>>8;
-			subobj_len  = EXTRACT_16BITS(obj_tptr+offset)&0x00FF;
-			ND_PRINT((ndo, "\n\t    Subobject, Type: %s (%u), Length: %u",
-				tok2str(lmp_data_link_subobj,
-					"Unknown",
-					subobj_type),
-					subobj_type,
-					subobj_len));
-			switch(subobj_type) {
-			case INT_SWITCHING_TYPE_SUBOBJ:
-				ND_PRINT((ndo, "\n\t      Switching Type: %s (%u)",
-					tok2str(gmpls_switch_cap_values,
-						"Unknown",
-						EXTRACT_16BITS(obj_tptr+offset+2)>>8),
-					EXTRACT_16BITS(obj_tptr+offset+2)>>8));
-				ND_PRINT((ndo, "\n\t      Encoding Type: %s (%u)",
-					tok2str(gmpls_encoding_values,
-						"Unknown",
-						EXTRACT_16BITS(obj_tptr+offset+2)&0x00FF),
-					EXTRACT_16BITS(obj_tptr+offset+2)&0x00FF));
-				bw.i = EXTRACT_32BITS(obj_tptr+offset+4);
-				ND_PRINT((ndo, "\n\t      Min Reservable Bandwidth: %.3f Mbps",
-                                       bw.f*8/1000000));
-				bw.i = EXTRACT_32BITS(obj_tptr+offset+8);
-				ND_PRINT((ndo, "\n\t      Max Reservable Bandwidth: %.3f Mbps",
-                                       bw.f*8/1000000));
-				break;
-			case WAVELENGTH_SUBOBJ:
-				ND_PRINT((ndo, "\n\t      Wavelength: %u",
-					EXTRACT_32BITS(obj_tptr+offset+4)));
-				break;
-			default:
-				/* Any Unknown Subobject ==> Exit loop */
-				hexdump=TRUE;
-				break;
-			}
-			total_subobj_len-=subobj_len;
-			offset+=subobj_len;
-		}
-
+		if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12))
+		    hexdump=TRUE;
 		break;
+
 	    case LMP_CTYPE_IPV6:
+                if (obj_tlen < 36) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
+	        ND_PRINT((ndo, "\n\t    Flags: [%s]",
+		    bittok2str(lmp_obj_data_link_flag_values,
+			"none",
+			EXTRACT_8BITS(obj_tptr))));
+                ND_PRINT((ndo, "\n\t    Local Interface ID: %s (0x%08x)"
+                       "\n\t    Remote Interface ID: %s (0x%08x)",
+                       ip6addr_string(ndo, obj_tptr+4),
+                       EXTRACT_32BITS(obj_tptr+4),
+                       ip6addr_string(ndo, obj_tptr+20),
+                       EXTRACT_32BITS(obj_tptr+20)));
+
+		if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 36, 36))
+		    hexdump=TRUE;
+		break;
+
+	    case LMP_CTYPE_UNMD:
+                if (obj_tlen < 12) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
+	        ND_PRINT((ndo, "\n\t    Flags: [%s]",
+		    bittok2str(lmp_obj_data_link_flag_values,
+			"none",
+			EXTRACT_8BITS(obj_tptr))));
+                ND_PRINT((ndo, "\n\t    Local Interface ID: %u (0x%08x)"
+                       "\n\t    Remote Interface ID: %u (0x%08x)",
+                       EXTRACT_32BITS(obj_tptr+4),
+                       EXTRACT_32BITS(obj_tptr+4),
+                       EXTRACT_32BITS(obj_tptr+8),
+                       EXTRACT_32BITS(obj_tptr+8)));
+
+		if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12))
+		    hexdump=TRUE;
+		break;
+
             default:
                 hexdump=TRUE;
             }
@@ -626,6 +783,10 @@ lmp_print(netdissect_options *ndo,
         case LMP_OBJ_VERIFY_BEGIN:
 	    switch(lmp_obj_ctype) {
             case LMP_CTYPE_1:
+                if (obj_tlen != 20) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
 		ND_PRINT((ndo, "\n\t    Flags: %s",
 		bittok2str(lmp_obj_begin_verify_flag_values,
 			"none",
@@ -654,6 +815,10 @@ lmp_print(netdissect_options *ndo,
         case LMP_OBJ_VERIFY_BEGIN_ACK:
 	    switch(lmp_obj_ctype) {
             case LMP_CTYPE_1:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    Verify Dead Interval: %u"
                        "\n\t    Verify Transport Response: %u",
                        EXTRACT_16BITS(obj_tptr),
@@ -668,6 +833,10 @@ lmp_print(netdissect_options *ndo,
 	case LMP_OBJ_VERIFY_ID:
 	    switch(lmp_obj_ctype) {
             case LMP_CTYPE_1:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
                 ND_PRINT((ndo, "\n\t    Verify ID: %u",
                        EXTRACT_32BITS(obj_tptr)));
                 break;
@@ -680,19 +849,20 @@ lmp_print(netdissect_options *ndo,
 	case LMP_OBJ_CHANNEL_STATUS:
             switch(lmp_obj_ctype) {
 	    case LMP_CTYPE_IPV4:
-	    case LMP_CTYPE_UNMD:
 		offset = 0;
 		/* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */
-		while (offset < (lmp_obj_len-(int)sizeof(struct lmp_object_header)) ) {
+		while (offset+8 <= obj_tlen) {
 			ND_PRINT((ndo, "\n\t    Interface ID: %s (0x%08x)",
 			ipaddr_string(ndo, obj_tptr+offset),
 			EXTRACT_32BITS(obj_tptr+offset)));
 
-			ND_PRINT((ndo, "\n\t\t    Active: %s (%u)", 		(EXTRACT_32BITS(obj_tptr+offset+4)>>31) ?
+			ND_PRINT((ndo, "\n\t\t    Active: %s (%u)",
+				(EXTRACT_32BITS(obj_tptr+offset+4)>>31) ?
 						"Allocated" : "Non-allocated",
 				(EXTRACT_32BITS(obj_tptr+offset+4)>>31)));
 
-			ND_PRINT((ndo, "\n\t\t    Direction: %s (%u)", (EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1 ?
+			ND_PRINT((ndo, "\n\t\t    Direction: %s (%u)",
+				(EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1 ?
 						"Transmit" : "Receive",
 				(EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1));
 
@@ -704,7 +874,61 @@ lmp_print(netdissect_options *ndo,
 			offset+=8;
 		}
                 break;
+
 	    case LMP_CTYPE_IPV6:
+		offset = 0;
+		/* Decode pairs: <Interface_ID (16 bytes), Channel_status (4 bytes)> */
+		while (offset+20 <= obj_tlen) {
+			ND_PRINT((ndo, "\n\t    Interface ID: %s (0x%08x)",
+			ip6addr_string(ndo, obj_tptr+offset),
+			EXTRACT_32BITS(obj_tptr+offset)));
+
+			ND_PRINT((ndo, "\n\t\t    Active: %s (%u)",
+				(EXTRACT_32BITS(obj_tptr+offset+16)>>31) ?
+						"Allocated" : "Non-allocated",
+				(EXTRACT_32BITS(obj_tptr+offset+16)>>31)));
+
+			ND_PRINT((ndo, "\n\t\t    Direction: %s (%u)",
+				(EXTRACT_32BITS(obj_tptr+offset+16)>>30)&0x1 ?
+						"Transmit" : "Receive",
+				(EXTRACT_32BITS(obj_tptr+offset+16)>>30)&0x1));
+
+			ND_PRINT((ndo, "\n\t\t    Channel Status: %s (%u)",
+					tok2str(lmp_obj_channel_status_values,
+					"Unknown",
+					EXTRACT_32BITS(obj_tptr+offset+16)&0x3FFFFFF),
+			EXTRACT_32BITS(obj_tptr+offset+16)&0x3FFFFFF));
+			offset+=20;
+		}
+                break;
+
+	    case LMP_CTYPE_UNMD:
+		offset = 0;
+		/* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */
+		while (offset+8 <= obj_tlen) {
+			ND_PRINT((ndo, "\n\t    Interface ID: %u (0x%08x)",
+			EXTRACT_32BITS(obj_tptr+offset),
+			EXTRACT_32BITS(obj_tptr+offset)));
+
+			ND_PRINT((ndo, "\n\t\t    Active: %s (%u)",
+				(EXTRACT_32BITS(obj_tptr+offset+4)>>31) ?
+						"Allocated" : "Non-allocated",
+				(EXTRACT_32BITS(obj_tptr+offset+4)>>31)));
+
+			ND_PRINT((ndo, "\n\t\t    Direction: %s (%u)",
+				(EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1 ?
+						"Transmit" : "Receive",
+				(EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1));
+
+			ND_PRINT((ndo, "\n\t\t    Channel Status: %s (%u)",
+					tok2str(lmp_obj_channel_status_values,
+					"Unknown",
+					EXTRACT_32BITS(obj_tptr+offset+4)&0x3FFFFFF),
+			EXTRACT_32BITS(obj_tptr+offset+4)&0x3FFFFFF));
+			offset+=8;
+		}
+                break;
+
             default:
                 hexdump=TRUE;
             }
@@ -713,16 +937,35 @@ lmp_print(netdissect_options *ndo,
 	case LMP_OBJ_CHANNEL_STATUS_REQ:
             switch(lmp_obj_ctype) {
 	    case LMP_CTYPE_IPV4:
-	    case LMP_CTYPE_UNMD:
 		offset = 0;
-		while (offset < (lmp_obj_len-(int)sizeof(struct lmp_object_header)) ) {
+		while (offset+4 <= obj_tlen) {
 			ND_PRINT((ndo, "\n\t    Interface ID: %s (0x%08x)",
 			ipaddr_string(ndo, obj_tptr+offset),
 			EXTRACT_32BITS(obj_tptr+offset)));
 			offset+=4;
 		}
                 break;
+
 	    case LMP_CTYPE_IPV6:
+		offset = 0;
+		while (offset+16 <= obj_tlen) {
+			ND_PRINT((ndo, "\n\t    Interface ID: %s (0x%08x)",
+			ip6addr_string(ndo, obj_tptr+offset),
+			EXTRACT_32BITS(obj_tptr+offset)));
+			offset+=16;
+		}
+                break;
+
+	    case LMP_CTYPE_UNMD:
+		offset = 0;
+		while (offset+4 <= obj_tlen) {
+			ND_PRINT((ndo, "\n\t    Interface ID: %u (0x%08x)",
+			EXTRACT_32BITS(obj_tptr+offset),
+			EXTRACT_32BITS(obj_tptr+offset)));
+			offset+=4;
+		}
+                break;
+
 	    default:
                 hexdump=TRUE;
             }
@@ -731,6 +974,10 @@ lmp_print(netdissect_options *ndo,
         case LMP_OBJ_ERROR_CODE:
 	    switch(lmp_obj_ctype) {
             case LMP_CTYPE_BEGIN_VERIFY_ERROR:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
 		ND_PRINT((ndo, "\n\t    Error Code: %s",
 		bittok2str(lmp_obj_begin_verify_error_values,
 			"none",
@@ -738,6 +985,10 @@ lmp_print(netdissect_options *ndo,
                 break;
 
             case LMP_CTYPE_LINK_SUMMARY_ERROR:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
 		ND_PRINT((ndo, "\n\t    Error Code: %s",
 		bittok2str(lmp_obj_link_summary_error_values,
 			"none",
@@ -751,51 +1002,60 @@ lmp_print(netdissect_options *ndo,
 	case LMP_OBJ_SERVICE_CONFIG:
 	    switch (lmp_obj_ctype) {
 	    case LMP_CTYPE_SERVICE_CONFIG_SP:
-
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
 		ND_PRINT((ndo, "\n\t Flags: %s",
 		       bittok2str(lmp_obj_service_config_sp_flag_values,
 				  "none",
-				  EXTRACT_16BITS(obj_tptr)>>8)));
+				  EXTRACT_8BITS(obj_tptr))));
 
 		ND_PRINT((ndo, "\n\t  UNI Version: %u",
-		       EXTRACT_16BITS(obj_tptr) & 0x00FF));
+		       EXTRACT_8BITS(obj_tptr+1)));
 
 		break;
 
             case LMP_CTYPE_SERVICE_CONFIG_CPSA:
+                if (obj_tlen != 16) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
 
-		link_type = EXTRACT_16BITS(obj_tptr)>>8;
+		link_type = EXTRACT_8BITS(obj_tptr);
 
 		ND_PRINT((ndo, "\n\t Link Type: %s (%u)",
 		       tok2str(lmp_sd_service_config_cpsa_link_type_values,
 			       "Unknown", link_type),
 		       link_type));
 
-		if (link_type == LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH) {
+		switch (link_type) {
+		case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH:
 		    ND_PRINT((ndo, "\n\t Signal Type: %s (%u)",
 			   tok2str(lmp_sd_service_config_cpsa_signal_type_sdh_values,
 				   "Unknown",
-				   EXTRACT_16BITS(obj_tptr) & 0x00FF),
-			   EXTRACT_16BITS(obj_tptr) & 0x00FF));
-		}
+				   EXTRACT_8BITS(obj_tptr+1)),
+			   EXTRACT_8BITS(obj_tptr+1)));
+		    break;
 
-		if (link_type == LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET) {
+		case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET:
 		    ND_PRINT((ndo, "\n\t Signal Type: %s (%u)",
 			   tok2str(lmp_sd_service_config_cpsa_signal_type_sonet_values,
 				   "Unknown",
-				   EXTRACT_16BITS(obj_tptr) & 0x00FF),
-			   EXTRACT_16BITS(obj_tptr) & 0x00FF));
+				   EXTRACT_8BITS(obj_tptr+1)),
+			   EXTRACT_8BITS(obj_tptr+1)));
+		    break;
 		}
 
 		ND_PRINT((ndo, "\n\t Transparency: %s",
 		       bittok2str(lmp_obj_service_config_cpsa_tp_flag_values,
 				  "none",
-				  EXTRACT_16BITS(obj_tptr+2)>>8)));
+				  EXTRACT_8BITS(obj_tptr+2))));
 
 		ND_PRINT((ndo, "\n\t Contiguous Concatenation Types: %s",
 		       bittok2str(lmp_obj_service_config_cpsa_cct_flag_values,
 				  "none",
-				  EXTRACT_16BITS(obj_tptr+2)>>8 & 0x00FF)));
+				  EXTRACT_8BITS(obj_tptr+3))));
 
 		ND_PRINT((ndo, "\n\t Minimum NCC: %u",
 		       EXTRACT_16BITS(obj_tptr+4)));
@@ -816,6 +1076,10 @@ lmp_print(netdissect_options *ndo,
 		break;
 
 	    case LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM:
+                if (obj_tlen != 8) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
 
 		ND_PRINT((ndo, "\n\t Transparency Flags: %s",
 		       bittok2str(
@@ -827,17 +1091,21 @@ lmp_print(netdissect_options *ndo,
 		       bittok2str(
 			   lmp_obj_service_config_nsa_tcm_flag_values,
 			   "none",
-			   EXTRACT_16BITS(obj_tptr+6) & 0x00FF)));
+			   EXTRACT_8BITS(obj_tptr+7))));
 
 		break;
 
 	    case LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY:
+                if (obj_tlen != 4) {
+                    ND_PRINT((ndo, " (not correct for object)"));
+                    break;
+                }
 
 		ND_PRINT((ndo, "\n\t Diversity: Flags: %s",
 		       bittok2str(
 			   lmp_obj_service_config_nsa_network_diversity_flag_values,
 			   "none",
-			   EXTRACT_16BITS(obj_tptr+2) & 0x00FF)));
+			   EXTRACT_8BITS(obj_tptr+3))));
 		break;
 
 	    default:

programming_language: C
filename: TESTLIST
change_type: ModificationType.MODIFY
diff: @@ -492,6 +492,7 @@ pimv2-oobr-4		pimv2-oobr-4.pcap		pimv2-oobr-4.out		-vvv -e
 802_15_4-oobr-2		802_15_4-oobr-2.pcap		802_15_4-oobr-2.out	-vvv -e
 802_15_4-data		802_15_4-data.pcap		802_15_4-data.out	-vvv -e
 802_15_4_beacon		802_15_4_beacon.pcap		802_15_4_beacon.out	-vvv -e
+lmpv1_busyloop		lmpv1_busyloop.pcap		lmpv1_busyloop.out	-vvv -e
 
 # RTP tests
 # fuzzed pcap

programming_language: Shell
filename: lmpv1_busyloop.out
change_type: ModificationType.ADD
diff: @@ -0,0 +1,42 @@
+00:80:ad:91:d8:6f > 00:0b:64:00:10:72, ethertype IPv4 (0x0800), length 725: (tos 0x0, ttl 128, id 35978, offset 0, flags [none], proto UDP (17), length 711)
+    168.152.32.1.701 > 168.152.32.39.701: [udp sum ok] 
+	LMPv1, msg-type: Config, Flags: [Control Channel Down], length: 257
+	  Data Link Object (12), Class-Type: IPv4 (1) Flags: [non-negotiable], length: 516
+	    Flags: [Allocated for user traffic]
+	    Local Interface ID: 0.0.2.0 (0x00000200)
+	    Remote Interface ID: 2.0.2.0 (0x02000200)
+	    Subobject, Type: Wavelength (2), Length: 0 (too short)
+	    0x0000:  0253 e10b 0000 0200 0200 0200 0200 0200
+	    0x0010:  0200 0200 0200 0200 0200 0200 0200 0200
+	    0x0020:  0200 0200 0200 0200 0200 0200 0200 0200
+	    0x0030:  0200 0200 0200 0200 0200 0200 0200 0200
+	    0x0040:  0200 0280 6d00 0200 0200 0200 0200 0200
+	    0x0050:  0200 0200 0200 0200 0200 0200 0200 0200
+	    0x0060:  0200 0200 0200 0200 0200 0200 0200 0200
+	    0x0070:  0200 0200 0200 0200 0200 0200 0200 8202
+	    0x0080:  0002 0002 0002 0002 0002 0002 0002 0002
+	    0x0090:  0002 0002 0002 0002 0002 0002 0002 0002
+	    0x00a0:  0002 0002 0002 0002 0002 0002 0002 0002
+	    0x00b0:  2002 0002 0002 0002 0002 0002 0002 0002
+	    0x00c0:  0000 0200 0200 0002 0002 0000 0200 0200
+	    0x00d0:  0002 0002 0000 0200 0200 0002 0002 0000
+	    0x00e0:  0200 0200 0002 0002 0000 0200 0200 0002
+	    0x00f0:  0002 0000 0200 0200 0002 0002 0000 0200
+	    0x0100:  0200 0002 0002 0000 0200 0200 0002 0002
+	    0x0110:  0000 0200 0200 0002 0002 0000 0200 0200
+	    0x0120:  0002 0002 0000 0200 0200 0002 0002 0000
+	    0x0130:  0200 0200 0002 0002 0000 0200 0200 0002
+	    0x0140:  0002 0000 0200 0200 0002 0002 0000 0200
+	    0x0150:  0200 0002 0002 0000 0200 0200 0002 0002
+	    0x0160:  0000 0200 0200 0002 0002 0000 0200 0200
+	    0x0170:  0002 0002 0000 0200 0200 0002 0002 0000
+	    0x0180:  0200 0200 0002 0002 0000 0200 0200 0002
+	    0x0190:  0002 0000 0200 0200 0002 0002 0000 0200
+	    0x01a0:  0200 0002 0002 0000 0200 0200 0002 0002
+	    0x01b0:  0000 0200 0200 0002 0002 0000 0200 0200
+	    0x01c0:  0002 0002 0000 0200 0200 0002 0002 0000
+	    0x01d0:  0200 0200 0002 0002 0000 0200 0200 0002
+	    0x01e0:  0002 0000 0200 0200 0002 0002 0000 0200
+	    0x01f0:  0200 0002 0002 0000 0200 0200 0002 0002
+	  Unknown Object (0), Class-Type: Unknown (0) Flags: [non-negotiable], length: 512
+		 packet exceeded snapshot

programming_language: Batchfile