Ethereal-dev: [Ethereal-dev] GMM/SM + LLC + BSSGP Patch

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Pilz Rene <rene.pilz@xxxxxx>
Date: Fri, 28 Jan 2005 13:31:43 +0100
Hi

This patch solves several issues in different dissectors.

BSSGP:
   - Does not dissect the LLC-PDU twice

LLC:
- Add CRC calculation to differ between ciphered and non-ciphered packets without taking care about the encryption bit. This solves crashes when the option "ignore ciphere bit" was activated

GMM/SM:
   - Dissect detach_type now correctly ( fixed by Miklos Szurdi )
   - Dissect timer correctly ( fixed by Miklos Szurdi )
   - Update SM causes for Release 6 ( Miklos Szurdi )
   - Update service_type for Release 6 ( Miklos Szurdi )
   - Rearange pco code like Guy Harris has suggested ( Guy Harris )
   - reimplement dissection of IPv4 and IPv6 addresses
   - Fix offset in pdp_addr
   - Fix offset in Traffic Flow Template (tft)

Please apply this patch.

Regards

Rene

--
Dipl-Ing (FH) MSc. C.E Ren� Pilz
ftw. Telekommunications Research Center Vienna http://www.ftw.at
Tech Gate Vienna, Donaucitystra�e 1, A-1220 Wien
Mobile: +43 664 8269871 Office: +43 1 5052830-13  Fax: +43 1 5052830-99

--- epan/dissectors/packet-gsm_a.c	(revision 13182)
+++ epan/dissectors/packet-gsm_a.c	(working copy)
@@ -50,6 +50,12 @@
  *   Stage 3
  *   (3GPP TS 24.008 version 5.9.0 Release 5)
  *
+ *   Reference [8]
+ *   Mobile radio interface Layer 3 specification;
+ *   Core network protocols;
+ *   Stage 3
+ *   (3GPP TS 24.008 version 6.7.0 Release 6)
+ *
  * $Id$
  *
  * Ethereal - Network traffic analyzer
@@ -91,6 +97,8 @@
 #include "packet-gsm_ss.h"
 #include "packet-gsm_a.h"
 
+#include "packet-ppp.h"
+
 /* PROTOTYPES/FORWARDS */
 
 const value_string gsm_a_bssmap_msg_strings[] = {
@@ -6997,10 +7005,10 @@
 
     switch(oct&7)
     {
-    	case 0: str="GPRS detach/re-attach required"; break;
-    	case 1: str="IMSI detach/re-attach not required"; break;
-    	case 2: str="Combined GPRS/IMSI detach/IMSI detach (after VLR failure)"; break;
-    	default: str="Not specified";
+    	case 1: str="GPRS detach/re-attach required"; break;
+    	case 2: str="IMSI detach/re-attach not required"; break;
+    	case 3: str="Combined GPRS/IMSI detach/IMSI detach (after VLR failure)"; break;
+    	default: str="Combined GPRS/IMSI detach/re-attach not required";
     }
 
     switch(oct&8)
@@ -9236,7 +9244,7 @@
 }
 
 /*
- * [7] 10.5.5.20
+ * [8] 10.5.5.20
  */
 static guint8
 de_gmm_service_type(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
@@ -9261,6 +9269,7 @@
     	case 0: str="Signalling"; break;
     	case 1: str="Data"; break;
     	case 2: str="Paging Response"; break;
+    	case 3: str="MBMS Notification Reponse"; break;
     	default: str="reserved";
     }
 
@@ -9424,7 +9433,7 @@
     	case 0: str="sec"; val*=2; break;
     	case 1: str="min"; break;
     	case 2: str="min"; val*=6; break;
-    	case 3:
+    	case 7:
 	    proto_tree_add_text(tree,
 		tvb, curr_offset, 1,
 		"GPRS Timer: timer is deactivated");
@@ -9469,7 +9478,7 @@
     	case 0: str="sec"; val*=2; break;
     	case 1: str="min"; break;
     	case 2: str="min"; val*=6; break;
-    	case 3:
+    	case 7:
 	    proto_tree_add_text(tree,
 		tvb, curr_offset, 1,
 		"GPRS Timer: timer is deactivated");
@@ -9689,6 +9698,7 @@
     guint32	curr_offset;
     guint	curr_len;
     guchar	oct;
+    struct e_in6_addr ipv6_addr;
     
     curr_len = len;
     add_string = add_string;
@@ -9706,7 +9716,8 @@
     	guchar e_len;
     	guint16 prot;
 	tvbuff_t *l3_tvb;
-	static packet_info pco_pinfo;
+	dissector_handle_t handle = NULL;
+	static packet_info p_info;
 	
 	prot = tvb_get_guint8(tvb, curr_offset);
 	prot <<= 8;
@@ -9719,18 +9730,13 @@
     	{
     		case 0x0001:
 		{
-		    guchar *addr;
 	    	    proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Parameter: (%u) P-CSCF Address" , prot );
 	    	    proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
-	            addr = (guchar*)tvb_get_ptr(tvb, curr_offset, 16);
-  
-        	    proto_tree_add_text(tree,
-	    		tvb, curr_offset, 16,
-    			"IPv6: %4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x",
-			(addr[0]<<8)| addr[1], (addr[2]<<8)| addr[3],
-			(addr[4]<<8)| addr[5], (addr[6]<<8)| addr[7],
-			(addr[8]<<8)| addr[9], (addr[10]<<8)| addr[11],
-			(addr[12]<<8)| addr[13], (addr[14]<<8)| addr[15] );				
+
+		    tvb_memcpy(tvb, (guint8 *)&ipv6_addr, curr_offset, 16);
+		    proto_tree_add_text(tree,
+			tvb, curr_offset, 16,
+			"IPv6: %s", ip6_to_str(&ipv6_addr));
 	    	    break;
 	    	}
     		case 0x0002:
@@ -9739,19 +9745,13 @@
 	    	    break;
     		case 0x0003:
     		{
-    		    guchar *addr;
 	    	    proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Parameter: (%u) DNS Server Address" , prot );
 	    	    proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
 
-	            addr = (guchar*)tvb_get_ptr(tvb, curr_offset, 16);
-  
-        	    proto_tree_add_text(tree,
-	    		tvb, curr_offset, 16,
-    			"IPv6: %4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x",
-			(addr[0]<<8)| addr[1], (addr[2]<<8)| addr[3],
-			(addr[4]<<8)| addr[5], (addr[6]<<8)| addr[7],
-			(addr[8]<<8)| addr[9], (addr[10]<<8)| addr[11],
-			(addr[12]<<8)| addr[13], (addr[14]<<8)| addr[15] );				
+		    tvb_memcpy(tvb, (guint8 *)&ipv6_addr, curr_offset, 16);
+		    proto_tree_add_text(tree,
+			tvb, curr_offset, 16,
+			"IPv6: %s", ip6_to_str(&ipv6_addr));
 	    	    break;
 	    	}
     		case 0x0004:
@@ -9760,54 +9760,29 @@
 	    	    oct = tvb_get_guint8(tvb, curr_offset);
 	    	    proto_tree_add_text(tree,tvb, curr_offset, 1, "Reject Code: 0x%02x (%u)", e_len , e_len);
 	    	    break;
-    		case 0xC021:
-	    	    proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Protocol: (%u) LCP" , prot );
-	    	    proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
-		    /*
-		     * dissect the embedded LCP message
-		     */
-		    l3_tvb = tvb_new_subset(tvb, curr_offset, e_len, e_len);
-		    if (!dissector_try_port(gprs_sm_pco_subdissector_table, prot, l3_tvb, &pco_pinfo, tree))
-			call_dissector(data_handle, l3_tvb, &pco_pinfo, tree);
-	    	    break;
-    		case 0xC023:
-	    	    proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Protocol: (%u) PAP" , prot );
-	    	    proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
-		    /*
-		     * dissect the embedded PAP message
-		     */
-		    l3_tvb = tvb_new_subset(tvb, curr_offset, e_len, e_len);
-		    if (!dissector_try_port(gprs_sm_pco_subdissector_table, prot, l3_tvb, &pco_pinfo, tree))
-			call_dissector(data_handle, l3_tvb, &pco_pinfo, tree);
-	    	    break;
-    		case 0xC223:
-	    	    proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Protocol: (%u) CHAP" , prot );
-	    	    proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
-		    /*
-		     * dissect the embedded CHAP message
-		     */
-		    l3_tvb = tvb_new_subset(tvb, curr_offset, e_len, e_len);
-		    if (!dissector_try_port(gprs_sm_pco_subdissector_table, prot, l3_tvb, &pco_pinfo, tree))
-			call_dissector(data_handle, l3_tvb, &pco_pinfo, tree);
-	    	    break;
-    		case 0x8021:
-	    	    proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Protocol: (%u) IPCP" , prot );
-	    	    proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
-		    /*
-		     * dissect the embedded IPCP message
-		     */
-		    l3_tvb = tvb_new_subset(tvb, curr_offset, e_len, e_len);
-		    if (!dissector_try_port(gprs_sm_pco_subdissector_table, prot, l3_tvb, &pco_pinfo, tree))
-			call_dissector(data_handle, l3_tvb, &pco_pinfo, tree);
-	    	    break;
-    		default:
-	    	    proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Protocol/Parameter: (%u) unknwown" , prot );
-	    	    proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
-		    /*
-		     * dissect the embedded DATA message
-		     */
-		    l3_tvb = tvb_new_subset(tvb, curr_offset, e_len, e_len);
-		    call_dissector(data_handle, l3_tvb, &pco_pinfo, tree);
+		default:
+			handle = dissector_get_port_handle ( gprs_sm_pco_subdissector_table , prot );
+			if ( handle != NULL )
+			{
+				proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Protocol: (%u) %s" , 
+					prot , val_to_str(prot, ppp_vals, "Unknown"));
+				proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
+				/*
+				 * dissect the embedded message
+				 */
+				l3_tvb = tvb_new_subset(tvb, curr_offset, e_len, e_len);
+				call_dissector(handle, l3_tvb ,  &p_info  , tree );
+			}
+			else
+			{
+				proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Protocol/Parameter: (%u) unknwown" , prot );
+				proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
+				/*
+				* dissect the embedded DATA message
+				*/
+				l3_tvb = tvb_new_subset(tvb, curr_offset, e_len, e_len);
+				call_dissector(data_handle, l3_tvb, &p_info , tree);
+			}
     	}
 
 	curr_len-= e_len;
@@ -9946,7 +9921,7 @@
 	            tvb, curr_offset+2, 0,
     	            "IPv6: length is wrong");
     	    } else {
-    	        tvb_memcpy(tvb, (guint8 *)&ipv6_addr, offset+2, 16);
+    	        tvb_memcpy(tvb, (guint8 *)&ipv6_addr, curr_offset+2, 16);
                 proto_tree_add_text(tree,
                     tvb, curr_offset+2, len-2,
     	            "IPv6: %s", ip6_to_str(&ipv6_addr));
@@ -10523,7 +10498,7 @@
 }
 
 /*
- * [7] 10.5.6.6
+ * [8] 10.5.6.6
  */
 static guint8
 de_sm_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
@@ -10541,6 +10516,7 @@
     switch ( oct )
     {
     	case 0x08: str="Operator Determined Barring"; break;
+    	case 0x18: str="MBMS bearer capabilities insufficient for the service"; break;
     	case 0x19: str="LLC or SNDCP failure(GSM only)"; break;
     	case 0x1a: str="Insufficient resources"; break;
     	case 0x1b: str="Missing or unknown APN"; break;
@@ -10561,6 +10537,7 @@
     	case 0x2a: str="Syntactical error in the TFT operation"; break;
     	case 0x2b: str="Unknown PDP context"; break;
     	case 0x2e: str="PDP context without TFT already activated"; break;
+    	case 0x2f: str="Multicast group membership time-out"; break;
     	case 0x2c: str="Semantic errors in packet filter(s)"; break;
     	case 0x2d: str="Syntactical errors in packet filter(s)"; break;
     	case 0x51: str="Invalid transaction identifier value"; break;
@@ -10572,6 +10549,7 @@
     	case 0x64: str="Conditional IE error"; break;
     	case 0x65: str="Message not compatible with the protocol state"; break;
     	case 0x6f: str="Protocol error, unspecified"; break;
+    	case 0x70: str="APN restriction value incompatible with active PDP context"; break;
     	default: str="Protocol error, unspecified"; break;
     }
 
@@ -10861,24 +10839,19 @@
 
 		if (( pf_identifier == 0x10 ) && ( pf_length == 4 ))
 		{
-			pchar = (guchar*)tvb_get_ptr(tvb, offset, pf_length);
-			
-			proto_tree_add_text(tf_tree,
-				tvb, curr_offset, pf_length ,
-				"Packet filter content: IPv4 %u.%u.%u.%u", 
-				pchar[0], pchar[1], pchar[2], pchar[3] );
+	                proto_tree_add_text(tree,
+    		            tvb, curr_offset, pf_length,
+    	        	    "Packet filter content: IPv4 %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
 		}
 		else if (( pf_identifier == 0x20 ) && ( pf_length == 16 ))
 		{
-			pchar = (guchar*)tvb_get_ptr(tvb, offset, pf_length);
-			
-			proto_tree_add_text(tf_tree,
-				tvb, curr_offset, pf_length ,
-				"Packet filter content: IPv6 %4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x",
-				(pchar[0]<<8)| pchar[1], (pchar[2]<<8)| pchar[3],
-				(pchar[4]<<8)| pchar[5], (pchar[6]<<8)| pchar[7],
-				(pchar[8]<<8)| pchar[9], (pchar[10]<<8)| pchar[11],
-				(pchar[12]<<8)| pchar[13], (pchar[14]<<8)| pchar[15] );				
+			struct e_in6_addr ipv6_addr;
+
+			tvb_memcpy(tvb, (guint8 *)&ipv6_addr, curr_offset, 16);
+			proto_tree_add_text(tree,
+				tvb, curr_offset+2, len-2,
+				"Packet filter content: IPv6 %s", ip6_to_str(&ipv6_addr));
+
 		}
 		else if (( pf_identifier == 0x30 ) && ( pf_length == 1 ))
 		{
@@ -10891,7 +10864,7 @@
 		}
 		else if (( pf_identifier == 0x40 ) && ( pf_length == 2 ))
 		{
-			pchar = (guchar*)tvb_get_ptr(tvb, offset, pf_length);
+			pchar = (guchar*)tvb_get_ptr(tvb, curr_offset, pf_length);
 			
 			proto_tree_add_text(tf_tree,
 				tvb, curr_offset, pf_length ,
@@ -10900,7 +10873,7 @@
 		}
 		else if (( pf_identifier == 0x50 ) && ( pf_length == 2 ))
 		{
-			pchar = (guchar*)tvb_get_ptr(tvb, offset, pf_length);
+			pchar = (guchar*)tvb_get_ptr(tvb, curr_offset, pf_length);
 			
 			proto_tree_add_text(tf_tree,
 				tvb, curr_offset, pf_length ,
@@ -10909,7 +10882,7 @@
 		}
 		else if (( pf_identifier == 0x41 ) && ( pf_length == 4 ))
 		{
-			pchar =  (guchar*)tvb_get_ptr(tvb, offset, pf_length);
+			pchar =  (guchar*)tvb_get_ptr(tvb, curr_offset, pf_length);
 			
 			proto_tree_add_text(tf_tree,
 				tvb, curr_offset, pf_length ,
@@ -10918,7 +10891,7 @@
 		}
 		else if (( pf_identifier == 0x51 ) && ( pf_length == 4 ))
 		{
-			pchar = (guchar*)tvb_get_ptr(tvb, offset, pf_length);
+			pchar = (guchar*)tvb_get_ptr(tvb, curr_offset, pf_length);
 			
 			proto_tree_add_text(tf_tree,
 				tvb, curr_offset, pf_length ,
@@ -10953,7 +10926,7 @@
 		}
 		else if (( pf_identifier == 0x60 ) && ( pf_length == 4 ))
 		{
-			pchar =  (guchar*)tvb_get_ptr(tvb, offset, pf_length);
+			pchar =  (guchar*)tvb_get_ptr(tvb, curr_offset, pf_length);
 			
 			proto_tree_add_text(tf_tree,
 				tvb, curr_offset, pf_length ,
@@ -11023,7 +10996,7 @@
 
 	if (( p_identifier == 0x01 ) && ( p_length == 4 ))
 	{
-		pchar =  (guchar*)tvb_get_ptr(tvb, offset, p_length);
+		pchar =  (guchar*)tvb_get_ptr(tvb, curr_offset, p_length);
 		
 		proto_tree_add_text(tf_tree,
 			tvb, curr_offset, p_length ,
--- epan/dissectors/packet-gprs-llc.c	(revision 13182)
+++ epan/dissectors/packet-gprs-llc.c	(working copy)
@@ -171,6 +171,53 @@
 	{ 0x3,"SACK" },
 	{ 0, NULL },
 };
+
+/* CRC24 table - FCS */
+guint32 tbl_crc24[256] = {
+	0x00000000, 0x00d6a776, 0x00f64557, 0x0020e221, 0x00b78115, 0x00612663, 0x0041c442, 0x00976334, 
+	0x00340991, 0x00e2aee7, 0x00c24cc6, 0x0014ebb0, 0x00838884, 0x00552ff2, 0x0075cdd3, 0x00a36aa5, 
+	0x00681322, 0x00beb454, 0x009e5675, 0x0048f103, 0x00df9237, 0x00093541, 0x0029d760, 0x00ff7016, 
+	0x005c1ab3, 0x008abdc5, 0x00aa5fe4, 0x007cf892, 0x00eb9ba6, 0x003d3cd0, 0x001ddef1, 0x00cb7987, 
+	0x00d02644, 0x00068132, 0x00266313, 0x00f0c465, 0x0067a751, 0x00b10027, 0x0091e206, 0x00474570, 
+	0x00e42fd5, 0x003288a3, 0x00126a82, 0x00c4cdf4, 0x0053aec0, 0x008509b6, 0x00a5eb97, 0x00734ce1, 
+	0x00b83566, 0x006e9210, 0x004e7031, 0x0098d747, 0x000fb473, 0x00d91305, 0x00f9f124, 0x002f5652, 
+	0x008c3cf7, 0x005a9b81, 0x007a79a0, 0x00acded6, 0x003bbde2, 0x00ed1a94, 0x00cdf8b5, 0x001b5fc3, 
+	0x00fb4733, 0x002de045, 0x000d0264, 0x00dba512, 0x004cc626, 0x009a6150, 0x00ba8371, 0x006c2407, 
+	0x00cf4ea2, 0x0019e9d4, 0x00390bf5, 0x00efac83, 0x0078cfb7, 0x00ae68c1, 0x008e8ae0, 0x00582d96, 
+	0x00935411, 0x0045f367, 0x00651146, 0x00b3b630, 0x0024d504, 0x00f27272, 0x00d29053, 0x00043725, 
+	0x00a75d80, 0x0071faf6, 0x005118d7, 0x0087bfa1, 0x0010dc95, 0x00c67be3, 0x00e699c2, 0x00303eb4, 
+	0x002b6177, 0x00fdc601, 0x00dd2420, 0x000b8356, 0x009ce062, 0x004a4714, 0x006aa535, 0x00bc0243, 
+	0x001f68e6, 0x00c9cf90, 0x00e92db1, 0x003f8ac7, 0x00a8e9f3, 0x007e4e85, 0x005eaca4, 0x00880bd2, 
+	0x00437255, 0x0095d523, 0x00b53702, 0x00639074, 0x00f4f340, 0x00225436, 0x0002b617, 0x00d41161, 
+	0x00777bc4, 0x00a1dcb2, 0x00813e93, 0x005799e5, 0x00c0fad1, 0x00165da7, 0x0036bf86, 0x00e018f0, 
+	0x00ad85dd, 0x007b22ab, 0x005bc08a, 0x008d67fc, 0x001a04c8, 0x00cca3be, 0x00ec419f, 0x003ae6e9, 
+	0x00998c4c, 0x004f2b3a, 0x006fc91b, 0x00b96e6d, 0x002e0d59, 0x00f8aa2f, 0x00d8480e, 0x000eef78, 
+	0x00c596ff, 0x00133189, 0x0033d3a8, 0x00e574de, 0x007217ea, 0x00a4b09c, 0x008452bd, 0x0052f5cb, 
+	0x00f19f6e, 0x00273818, 0x0007da39, 0x00d17d4f, 0x00461e7b, 0x0090b90d, 0x00b05b2c, 0x0066fc5a, 
+	0x007da399, 0x00ab04ef, 0x008be6ce, 0x005d41b8, 0x00ca228c, 0x001c85fa, 0x003c67db, 0x00eac0ad, 
+	0x0049aa08, 0x009f0d7e, 0x00bfef5f, 0x00694829, 0x00fe2b1d, 0x00288c6b, 0x00086e4a, 0x00dec93c, 
+	0x0015b0bb, 0x00c317cd, 0x00e3f5ec, 0x0035529a, 0x00a231ae, 0x007496d8, 0x005474f9, 0x0082d38f, 
+	0x0021b92a, 0x00f71e5c, 0x00d7fc7d, 0x00015b0b, 0x0096383f, 0x00409f49, 0x00607d68, 0x00b6da1e, 
+	0x0056c2ee, 0x00806598, 0x00a087b9, 0x007620cf, 0x00e143fb, 0x0037e48d, 0x001706ac, 0x00c1a1da, 
+	0x0062cb7f, 0x00b46c09, 0x00948e28, 0x0042295e, 0x00d54a6a, 0x0003ed1c, 0x00230f3d, 0x00f5a84b, 
+	0x003ed1cc, 0x00e876ba, 0x00c8949b, 0x001e33ed, 0x008950d9, 0x005ff7af, 0x007f158e, 0x00a9b2f8, 
+	0x000ad85d, 0x00dc7f2b, 0x00fc9d0a, 0x002a3a7c, 0x00bd5948, 0x006bfe3e, 0x004b1c1f, 0x009dbb69, 
+	0x0086e4aa, 0x005043dc, 0x0070a1fd, 0x00a6068b, 0x003165bf, 0x00e7c2c9, 0x00c720e8, 0x0011879e, 
+	0x00b2ed3b, 0x00644a4d, 0x0044a86c, 0x00920f1a, 0x00056c2e, 0x00d3cb58, 0x00f32979, 0x00258e0f, 
+	0x00eef788, 0x003850fe, 0x0018b2df, 0x00ce15a9, 0x0059769d, 0x008fd1eb, 0x00af33ca, 0x007994bc, 
+	0x00dafe19, 0x000c596f, 0x002cbb4e, 0x00fa1c38, 0x006d7f0c, 0x00bbd87a, 0x009b3a5b, 0x004d9d2d
+};
+
+#define GOOD_CRC24	0x0c91b6
+#define INIT_CRC24	0xffffff
+
+guint32 crc_calc(guint32 fcs, guchar *cp, int len)
+{
+	while (len--)
+		fcs = (fcs >> 8) ^ tbl_crc24[(fcs ^ *cp++) & 0xff];
+	return fcs;
+}
+
 /* Code to actually dissect the packets */
 static void
 dissect_llcgprs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
@@ -180,6 +227,8 @@
  proto_item *ti, *addres_field_item, *ctrl_field_item, *ui_ti;
  proto_tree *llcgprs_tree=NULL , *ad_f_tree =NULL, *ctrl_f_tree=NULL, *ui_tree=NULL;
  tvbuff_t *next_tvb;
+ guint32 fcs , fcs_calc;
+ guchar *data;
 /* Make entries in Protocol column and Info column on summary display */
 	if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
 		col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-LLC");
@@ -196,7 +245,15 @@
 	if (check_col(pinfo->cinfo, COL_INFO)) 
 		col_add_fstr(pinfo->cinfo, COL_INFO, "SAPI: %s", match_strval(sapi,sapi_abrv));
 	
-	  		  
+	  
+	data = (guchar*)tvb_get_ptr(tvb, 0, crc_start+3 );
+	fcs_calc = crc_calc ( INIT_CRC24 , data , crc_start );
+	fcs_calc = ~fcs_calc;
+
+	if ( memcmp ( &fcs_calc , data+crc_start , 3 ) == 0 )
+		fcs = GOOD_CRC24;
+	else
+		fcs = ~GOOD_CRC24;
         
 /* In the interest of speed, if "tree" is NULL, don't do any work not
    necessary to generate protocol tree items. */
@@ -207,7 +264,11 @@
 		llcgprs_tree = proto_item_add_subtree(ti, ett_llcgprs);
 
 /* add an item to the subtree, see section 1.6 for more information */
-		proto_tree_add_text( llcgprs_tree, tvb, crc_start,3, "CRC of LLC layer" );
+		if ( fcs == GOOD_CRC24 )
+			proto_tree_add_text ( llcgprs_tree , tvb , crc_start , 3 , "FCS: 0x%06x (correct)" , fcs_calc&0xffffff );
+		else
+			proto_tree_add_text ( llcgprs_tree , tvb , crc_start , 3 , "FCS: 0x%02x%02x%02x  (incorrect, should be 0x%06x)",
+				data[crc_start] , data[crc_start+1], data[crc_start+2],  fcs_calc & 0xffffff );
 		addres_field_item = proto_tree_add_uint_format(llcgprs_tree,hf_llcgprs_sapi,
 		     tvb, 0,1, sapi, "Address field  SAPI: %s", match_strval(sapi,sapi_abrv));
 		ad_f_tree = proto_item_add_subtree(addres_field_item, ett_llcgprs_adf);
@@ -216,6 +277,8 @@
                 proto_tree_add_uint(ad_f_tree, hf_llcgprs_sapib, tvb, 0, 1, addr_fld );
 	}	
 
+			  
+
 	ctrl_fld_fb = tvb_get_guint8(tvb,offset);
 	if ( ctrl_fld_fb < 0xc0 ){
 		frame_format = ( ctrl_fld_fb < 0x80)? I_FORMAT : S_FORMAT;
@@ -267,12 +330,13 @@
 				proto_tree_add_boolean( ctrl_f_tree, hf_llcgprs_PM_bit, tvb, offset-2,2,ctrl_fld_ui_s);
 		     	  }
 
+			  
  		   	  next_tvb = tvb_new_subset(tvb, offset,crc_start-3, -1 );
-		   	  if (ignore_cipher_bit || !(epm & 0x2)){
+		   	  if ((ignore_cipher_bit && (fcs == GOOD_CRC24)) || !(epm & 0x2)){
 			  	/*
 			  	 * Either we're ignoring the cipher bit
 			  	 * (because the bit is set but the
-			  	 * data is unciphered), or the cipher
+			  	 * data is unciphered), or the cipher 
 			  	 * bit isn't set (indicating that the
 			  	 * data is unciphered).  Try dissecting
 			  	 * it with a subdissector.
@@ -383,9 +447,9 @@
 	register_dissector( "llcgprs", dissect_llcgprs, proto_llcgprs);
 	
 	llcgprs_module = prefs_register_protocol ( proto_llcgprs, NULL );
-	prefs_register_bool_preference ( llcgprs_module, "ignore_cipher_bit",
-	    "Ignore cipher bit", 
-	    "Whether to ignore the cipher bit (because it might be set on unciphered data)",
+	prefs_register_bool_preference ( llcgprs_module, "autodetect_cipher_bit",
+	    "autodetect cipher bit", 
+	    "Whether to autodetect the cipher bit (because it might be set on unciphered data)",
 	    &ignore_cipher_bit );
 }
 
--- epan/dissectors/packet-bssgp.c	(revision 13182)
+++ epan/dissectors/packet-bssgp.c	(working copy)
@@ -1177,12 +1177,11 @@
   tvbuff_t *next_tvb;
 
   next_tvb = tvb_new_subset(bi->tvb, bi->offset, -1, -1);
-  call_dissector(handle, next_tvb, bi->pinfo, bi->parent_tree);
 
   if (bi->bssgp_tree) {
     bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
   }
-  if (!handle) {
+  if (handle) {
     call_dissector(handle, next_tvb, bi->pinfo, bi->parent_tree);    
   }
   else if (data_handle) {