Ethereal-dev: [Ethereal-dev] GMM & SM 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: Tue, 11 Jan 2005 13:58:36 +0100
Hi

This patch fix the following parts:
- partly wrong cause values in the gmm (found by Miklos Szurdi)
- high/low nibble swap of the force to standby field (found by Miklos Szurdi)
- dissect now all elements

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 13003)
+++ epan/dissectors/packet-gsm_a.c	(working copy)
@@ -4,6 +4,12 @@
  * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
  * In association with Telos Technology Inc.
  *
+ * Added the GPRS Mobility Managment Protocol and 
+ * the GPRS Session Managment Protocol
+ *   Copyright 2004, Rene Pilz <rene.pilz [AT] ftw.com>
+ *   In association with Telecommunications Research Center 
+ *   Vienna (ftw.)Betriebs-GmbH within the Project Metawin.
+ *
  * Title		3GPP			Other
  *
  *   Reference [1]
@@ -746,7 +752,6 @@
 static gint ett_gmm_update_type = -1;
 static gint ett_gmm_radio_cap = -1;
 
-static gint ett_sm_pfi = -1;
 static gint ett_sm_tft = -1;
 
 static char a_bigbuf[1024];
@@ -757,6 +762,7 @@
 static dissector_handle_t dtap_handle;
 static dissector_handle_t rp_handle;
 static dissector_table_t sms_dissector_table;	/* SMS TPDU */
+static dissector_table_t gprs_sm_pco_subdissector_table; /* GPRS SM PCO PPP Protocols */
 
 static packet_info *g_pinfo;
 static proto_tree *g_tree;
@@ -7555,6 +7561,33 @@
 /*
  * [7] 10.5.5.12a
  */
+#define GET_DATA				/* check if we have enough bits left */ \
+		if ( curr_bits_length < bits_needed ) \
+			continue; \
+		/* check if oct has enougth bits */ \
+		if ( bits_in_oct < bits_needed ) \
+		{ \
+			guint32 tmp_oct; \
+			if ( curr_len == 0 ) \
+			{ \
+				proto_tree_add_text(tf_tree, \
+				tvb, curr_offset, 1, \
+				"Not enough data available"); \
+			} \
+			tmp_oct = tvb_get_guint8(tvb, curr_offset); \
+			oct |= tmp_oct<<(32-8-bits_in_oct); \
+			curr_len--; \
+			curr_offset++; \
+			if ( bits_in_oct != 0 ) \
+				add_ocetets = 1; \
+			else \
+				add_ocetets = 0; \
+			bits_in_oct += 8; \
+		} \
+		else \
+			add_ocetets = 0;
+
+
 static guint8
 de_gmm_ms_radio_acc_cap(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
 {
@@ -7562,21 +7595,1327 @@
     guint	curr_len;
     proto_item  *tf = NULL;
     proto_tree      *tf_tree = NULL;
+    guint32     oct;
+    guchar      bits_in_oct;
+    guchar      bits_needed;
+    guint       bits_length;
+    guint       add_ocetets;	/* octets which are covered by one element -1 */
+    guint       curr_bits_length;
+    guchar	acc_type;
+    gchar       *str;
+    gchar       multi_slot_str[64][230] = {
+    	"Not specified", /* 00 */
+    	"Max Rx-Slot/TDMA:1 Max Tx-Slot/TDMA:1 Max-Sum-Slot/TDMA:2 Tta:3 Ttb:2 Tra:4 Trb:2 Type:1", /* 01 */
+    	"Max Rx-Slot/TDMA:2 Max Tx-Slot/TDMA:1 Max-Sum-Slot/TDMA:3 Tta:3 Ttb:2 Tra:3 Trb:1 Type:1", /* 02 */
+    	"Max Rx-Slot/TDMA:2 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:3 Tta:3 Ttb:2 Tra:3 Trb:1 Type:1", /* 03 */
+    	"Max Rx-Slot/TDMA:3 Max Tx-Slot/TDMA:1 Max-Sum-Slot/TDMA:4 Tta:3 Ttb:1 Tra:3 Trb:1 Type:1", /* 04 */
+    	"Max Rx-Slot/TDMA:2 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:4 Tta:3 Ttb:1 Tra:3 Trb:1 Type:1", /* 05 */
+    	"Max Rx-Slot/TDMA:3 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:4 Tta:3 Ttb:1 Tra:3 Trb:1 Type:1", /* 06 */
+    	"Max Rx-Slot/TDMA:3 Max Tx-Slot/TDMA:3 Max-Sum-Slot/TDMA:4 Tta:3 Ttb:1 Tra:3 Trb:1 Type:1", /* 07 */
+    	"Max Rx-Slot/TDMA:4 Max Tx-Slot/TDMA:1 Max-Sum-Slot/TDMA:5 Tta:3 Ttb:1 Tra:2 Trb:1 Type:1", /* 08 */
+    	"Max Rx-Slot/TDMA:3 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:5 Tta:3 Ttb:1 Tra:2 Trb:1 Type:1", /* 09 */
+    	"Max Rx-Slot/TDMA:4 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:5 Tta:3 Ttb:1 Tra:2 Trb:1 Type:1", /* 10 */
+    	"Max Rx-Slot/TDMA:4 Max Tx-Slot/TDMA:3 Max-Sum-Slot/TDMA:5 Tta:3 Ttb:1 Tra:2 Trb:1 Type:1", /* 11 */
+    	"Max Rx-Slot/TDMA:4 Max Tx-Slot/TDMA:4 Max-Sum-Slot/TDMA:5 Tta:2 Ttb:1 Tra:2 Trb:1 Type:1", /* 12 */
+    	"Max Rx-Slot/TDMA:3 Max Tx-Slot/TDMA:3 Max-Sum-Slot/TDMA:NA Tta:NA Ttb:a) Tra:3 Trb:a) Type:2 (a: 1 with frequency hopping, 0 otherwise)", /* 13 */
+    	"Max Rx-Slot/TDMA:4 Max Tx-Slot/TDMA:4 Max-Sum-Slot/TDMA:NA Tta:NA Ttb:a) Tra:3 Trb:a) Type:2 (a: 1 with frequency hopping, 0 otherwise)", /* 14 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:5 Max-Sum-Slot/TDMA:NA Tta:NA Ttb:a) Tra:3 Trb:a) Type:2 (a: 1 with frequency hopping, 0 otherwise)", /* 15 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:6 Max-Sum-Slot/TDMA:NA Tta:NA Ttb:a) Tra:2 Trb:a) Type:2 (a: 1 with frequency hopping, 0 otherwise)", /* 16 */
+    	"Max Rx-Slot/TDMA:7 Max Tx-Slot/TDMA:7 Max-Sum-Slot/TDMA:NA Tta:NA Ttb:a) Tra:1 Trb:0 Type:2 (a: 1 with frequency hopping, 0 otherwise)", /* 17 */
+    	"Max Rx-Slot/TDMA:8 Max Tx-Slot/TDMA:8 Max-Sum-Slot/TDMA:NA Tta:NA Ttb:0 Tra:0 Trb:0 Type:2", /* 18 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 19 */   	
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:3 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 20 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:4 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 21 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:4 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 22 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:6 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 23 */
+    	"Max Rx-Slot/TDMA:8 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 24 */
+    	"Max Rx-Slot/TDMA:8 Max Tx-Slot/TDMA:3 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 25 */
+    	"Max Rx-Slot/TDMA:8 Max Tx-Slot/TDMA:4 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 26 */
+    	"Max Rx-Slot/TDMA:8 Max Tx-Slot/TDMA:4 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 27 */
+    	"Max Rx-Slot/TDMA:8 Max Tx-Slot/TDMA:6 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 28 */
+    	"Max Rx-Slot/TDMA:8 Max Tx-Slot/TDMA:8 Max-Sum-Slot/TDMA:NA Tta:3 Ttb:b) Tra:2 Trb:c) Type:1 (b: 1 with frequency hopping or change from Rx to Tx, 0 otherwise; c: 1 with frequency hopping or change from Tx to Rx, 0 otherwise", /* 29 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:1 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1 Trb:1 Type:1", /* 30 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1 Trb:1 Type:1", /* 31 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:3 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1 Trb:1 Type:1", /* 32 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:4 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1 Trb:1 Type:1", /* 33 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:5 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1 Trb:1 Type:1", /* 34 */
+       	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:1 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1+to Trb:1 Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 35 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1+to Trb:1 Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 36 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:3 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1+to Trb:1 Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 37 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:4 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1+to Trb:1 Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 38 */
+    	"Max Rx-Slot/TDMA:5 Max Tx-Slot/TDMA:5 Max-Sum-Slot/TDMA:6 Tta:2 Ttb:1 Tra:1+to Trb:1 Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 39 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:1 Max-Sum-Slot/TDMA:7 Tta:1 Ttb:1 Tra:1 Trb:to Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 40 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:2 Max-Sum-Slot/TDMA:7 Tta:1 Ttb:1 Tra:1 Trb:to Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 41 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:3 Max-Sum-Slot/TDMA:7 Tta:1 Ttb:1 Tra:1 Trb:to Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 42 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:4 Max-Sum-Slot/TDMA:7 Tta:1 Ttb:1 Tra:1 Trb:to Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 43 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:5 Max-Sum-Slot/TDMA:7 Tta:1 Ttb:1 Tra:1 Trb:to Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 44 */
+    	"Max Rx-Slot/TDMA:6 Max Tx-Slot/TDMA:6 Max-Sum-Slot/TDMA:7 Tta:1 Ttb:1 Tra:1 Trb:to Type:1 (to: to = 31 symbol periods (this can be provided by a TA offset, i.e. a minimum TA value))", /* 45 */
+    	"Not specified", /* 46 */
+    	"Not specified", /* 47 */
+    	"Not specified", /* 48 */
+    	"Not specified", /* 49 */
+    	"Not specified", /* 50 */
+    	"Not specified", /* 51 */
+    	"Not specified", /* 52 */
+    	"Not specified", /* 53 */
+    	"Not specified", /* 54 */
+    	"Not specified", /* 55 */
+    	"Not specified", /* 56 */
+    	"Not specified", /* 57 */
+    	"Not specified", /* 58 */
+    	"Not specified", /* 59 */
+    	"Not specified", /* 60 */
+    	"Not specified", /* 61 */
+    	"Not specified", /* 62 */
+    	"Not specified", /* 63 */
+	};
+    guint index = 0;
+    guchar dtm_gprs_mslot = 0;
+    guchar dtm_egprs_mslot = 4;
     
     curr_len = len;
     add_string = add_string;
     curr_offset = offset;
 
-    tf = proto_tree_add_text(tree,
-    	tvb, curr_offset, 1,
-    	"Mobile Station Radio Access Capability");
+    bits_in_oct = 0;
+    oct = 0;
 
-    tf_tree = proto_item_add_subtree(tf, ett_gmm_radio_cap );
+    do
+    {
+	/* check for a new round */
+	if (( curr_len*8 + bits_in_oct ) < 11 )
+		break;
+
+	/* now read the first 11 bits */
+    	curr_bits_length = 11;	
+	/*
+	 *
+	 */
+	if ( curr_len != len )
+	{
+		bits_needed = 1;
+		GET_DATA;
+
+		if (( oct>>(32-bits_needed) ) == 1 )
+		{
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+	    		
+	    		if (( curr_len*8 + bits_in_oct ) < 11 )
+	    			break;
+	    		curr_bits_length = 11;
+		}
+		else
+		{
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+	    		break;
+		}
+	}
+
+	index++;
+	tf = proto_tree_add_text(tree,
+    		tvb, curr_offset, 1,
+	    	"MS RA capability %d",index);
+
+	tf_tree = proto_item_add_subtree(tf, ett_gmm_radio_cap );
+
+	/*
+	 * Access Technology
+	 */
+	bits_needed = 4;
+	GET_DATA;
+	
+	acc_type = oct>>(32-bits_needed);
+	switch ( acc_type )
+	{
+	    	case 0x00: str="GSM P"; break;
+    		case 0x01: str="GSM E --note that GSM E covers GSM P"; break;
+   	 	case 0x02: str="GSM R --note that GSM R covers GSM E and GSM P"; break;
+    		case 0x03: str="GSM 1800"; break;
+    		case 0x04: str="GSM 1900"; break;
+    		case 0x05: str="GSM 450"; break;
+    		case 0x06: str="GSM 480"; break;
+    		case 0x07: str="GSM 850"; break;
+    		case 0x08: str="GSM 700"; break;
+    		case 0x0f: str="Indicates the presence of a list of Additional access technologies"; break;
+   	 	default: str="unknown";
+   	 }
+
+	proto_tree_add_text(tf_tree,
+	    	tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+    		"Access Technology Type: (%u) %s",acc_type,str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+	
+	/*
+	 * get bits_length
+	 */
+	bits_needed = 7;
+	GET_DATA;
+	
+	bits_length = curr_bits_length = oct>>(32-bits_needed);
+	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"Length: 0x%02x bits (%u)",bits_length,bits_length);
+    	/* This is already done - length doesn't contain this field
+    	 curr_bits_length -= bits_needed;
+    	*/
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+	if ( acc_type == 0x0f )
+	{
+		/*
+		 * Additional access technologies:
+		 */
+
+		/*
+		 * Access Technology
+		 */
+		bits_needed = 4;
+		GET_DATA;
+	
+		acc_type = oct>>(32-bits_needed);
+		switch ( acc_type )
+		{
+		    	case 0x00: str="GSM P"; break;
+    			case 0x01: str="GSM E --note that GSM E covers GSM P"; break;
+	   	 	case 0x02: str="GSM R --note that GSM R covers GSM E and GSM P"; break;
+    			case 0x03: str="GSM 1800"; break;
+    			case 0x04: str="GSM 1900"; break;
+	    		case 0x05: str="GSM 450"; break;
+    			case 0x06: str="GSM 480"; break;
+    			case 0x07: str="GSM 850"; break;
+	    		case 0x08: str="GSM 700"; break;
+    			case 0x0f: str="Indicates the presence of a list of Additional access technologies"; break;
+   	 		default: str="unknown";
+	   	 }
+
+		proto_tree_add_text(tf_tree,
+	    		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+	    		"Access Technology Type: (%u) %s",acc_type,str);
+    		curr_bits_length -= bits_needed;
+	    	oct <<= bits_needed;
+    		bits_in_oct -= bits_needed;
+
+	    	/*
+    		 * RF Power
+	    	 */
+	    	bits_needed = 3;
+		GET_DATA;
+
+		/* analyse bits */
+		if ( acc_type == 0x04 )	/* GSM 1900 */
+		{
+    			switch ( oct>>(32-bits_needed) )
+	    		{
+    				case 0x01: str="1 W (30 dBm)"; break;
+	    			case 0x02: str="0,25 W (24 dBm)"; break;
+		    		case 0x03: str="2 W (33 dBm)"; break;
+    				default: str="Not specified";
+	    		}
+    		}
+	    	else if ( acc_type == 0x03 )
+    		{
+    			switch ( oct>>(32-bits_needed) )
+	 	   	{
+    				case 0x01: str="1 W (30 dBm)"; break;
+    				case 0x02: str="0,25 W (24 dBm)"; break;
+    				case 0x03: str="4 W (36 dBm)"; break;
+	    			default: str="Not specified";
+    			}
+	    	}
+		else if ( acc_type <= 0x08 )
+	    	{
+    			switch ( oct>>(32-bits_needed) )
+    			{
+    				case 0x02: str="8 W (39 dBm)"; break;
+	    			case 0x03: str="5 W (37 dBm)"; break;
+    				case 0x04: str="2 W (33 dBm)"; break;
+    				case 0x05: str="0,8 W (29 dBm)"; break;
+    				default: str="Not specified";
+	    		}
+    		}
+	    	else
+    			str="Not specified??";
     
-    proto_tree_add_text(tf_tree,
-	tvb, curr_offset, curr_len,
-	"Not Implemented" );
+	    	proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"RF Power Capability, GMSK Power Class: (%u) %s",oct>>(32-bits_needed),str);
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+	    	bits_in_oct -= bits_needed;
+
+	    	/*
+    		 * 8PSK Power Class
+	    	 */
+    		bits_needed = 2;
+		GET_DATA;
+
+		/* analyse bits */
+		switch ( oct>>(32-bits_needed) )
+    		{
+			case 0x00: str="8PSK modulation not supported for uplink"; break;
+			case 0x01: str="Power class E1"; break;
+			case 0x02: str="Power class E2"; break;
+			case 0x03: str="Power class E3"; break;
+			default: str="This should not happen";
+	    	}
     
+    		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"8PSK Power Class: (%u) %s",oct>>(32-bits_needed),str);
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+    		bits_in_oct -= bits_needed;
+
+		/*
+		 * we are too long ... so jump over it
+		 */
+		while ( curr_bits_length > 0 )
+		{
+			if ( curr_bits_length > 8 )
+				bits_needed = 8;
+			else
+				bits_needed = curr_bits_length;
+			GET_DATA;
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+			bits_in_oct -= bits_needed;
+		}
+		
+		/* goto next one */
+		continue;
+	}
+    	/*
+    	 * RF Power
+    	 */
+    	bits_needed = 3;
+	GET_DATA;
+
+	/* analyse bits */
+	if ( acc_type == 0x04 )	/* GSM 1900 */
+	{
+    		switch ( oct>>(32-bits_needed) )
+	    	{
+    			case 0x01: str="1 W (30 dBm)"; break;
+    			case 0x02: str="0,25 W (24 dBm)"; break;
+	    		case 0x03: str="2 W (33 dBm)"; break;
+    			default: str="Not specified";
+    		}
+    	}
+    	else if ( acc_type == 0x03 )
+    	{
+    		switch ( oct>>(32-bits_needed) )
+ 	   	{
+    			case 0x01: str="1 W (30 dBm)"; break;
+    			case 0x02: str="0,25 W (24 dBm)"; break;
+    			case 0x03: str="4 W (36 dBm)"; break;
+    			default: str="Not specified";
+    		}
+    	}
+	else if ( acc_type <= 0x08 )
+    	{
+    		switch ( oct>>(32-bits_needed) )
+    		{
+    			case 0x02: str="8 W (39 dBm)"; break;
+    			case 0x03: str="5 W (37 dBm)"; break;
+    			case 0x04: str="2 W (33 dBm)"; break;
+    			case 0x05: str="0,8 W (29 dBm)"; break;
+    			default: str="Not specified";
+    		}
+    	}
+    	else
+    		str="Not specified??";
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"RF Power Capability, GMSK Power Class: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * A5 Bits?
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+        if ((oct>>(32-bits_needed))==0)
+        {
+	    	proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"A5 Bits: (%u) same values apply for parameters as in the immediately preceding Access capabilities field within this IE",oct>>(32-bits_needed));
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+    	}
+    	else
+    	{
+    		int i;
+
+	    	proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"A5 Bits: (%u) A5 bits follows",oct>>(32-bits_needed));
+
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+    		bits_in_oct -= bits_needed;
+    		
+    		for (i=1; i<= 7 ; i++ )
+    		{
+		    	/*
+		    	 * A5 Bits decoding
+		    	 */
+		    	bits_needed = 1;
+			GET_DATA;
+
+			/* analyse bits */
+			switch ( oct>>(32-bits_needed) )
+		    	{
+				case 0x00: str="encryption algorithm not available"; break;
+				case 0x01: str="encryption algorithm available"; break;
+				default: str="This should not happen";
+		    	}
+    
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"A5/%d: (%u) %s",i,oct>>(32-bits_needed),str);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+    		}
+	}
+    
+    	/*
+    	 * ES IND
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="controlled early Classmark Sending option is not implemented"; break;
+		case 0x01: str="controlled early Classmark Sending option is implemented"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"Controlled early Classmark Sending: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * PS
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="PS capability not present"; break;
+		case 0x01: str="PS capability present"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"Pseudo Synchronisation: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * VGCS
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="no VGCS capability or no notifications wanted"; break;
+		case 0x01: str="VGCS capability and notifications wanted"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"Voice Group Call Service: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * VBS
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="no VBS capability or no notifications wanted"; break;
+		case 0x01: str="VBS capability and notifications wanted"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"Voice Broadcast Service: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * Multislot capability?
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+        if ((oct>>(32-bits_needed))==0)
+        {
+	    	proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"Multislot capability: (%u) same values apply for parameters as in the immediately preceding Access capabilities field within this IE",oct>>(32-bits_needed));
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+    	}
+    	else
+    	{
+	    	proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"Multislot capability: (%u) Multislot capability struct available",oct>>(32-bits_needed));
+
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+
+	    	/*
+    		 * HSCSD multislot class?
+	    	 */
+	    	bits_needed = 1;
+		GET_DATA;
+
+		/* analyse bits */
+        	if ((oct>>(32-bits_needed))==0)
+	        {
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"HSCSD multislot class: (%u) Bits are not available",oct>>(32-bits_needed));
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+	    	}
+    		else
+	    	{
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * HSCSD multislot class
+    			 */
+		    	bits_needed = 5;
+			GET_DATA;
+
+			/* analyse bits */
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"HSCSD multislot class: (%u) %s",oct>>(32-bits_needed),multi_slot_str[oct>>(32-bits_needed)]);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+		}
+
+	    	/*
+    		 * GPRS multislot class?
+	    	 */
+	    	bits_needed = 1;
+		GET_DATA;
+
+		/* analyse bits */
+        	if ((oct>>(32-bits_needed))==0)
+	        {
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"GPRS multislot class: (%u) Bits are not available",oct>>(32-bits_needed));
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+	    	}
+    		else
+	    	{
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * GPRS multislot class
+    			 */
+		    	bits_needed = 5;
+			GET_DATA;
+
+			/* analyse bits */
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"GPRS multislot class: (%u) %s",oct>>(32-bits_needed),multi_slot_str[oct>>(32-bits_needed)]);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * GPRS Extended Dynamic Allocation Capability
+    			 */
+		    	bits_needed = 1;
+			GET_DATA;
+
+			/* analyse bits */
+			switch ( oct>>(32-bits_needed) )
+			{
+				case 0x00: str="Extended Dynamic Allocation Capability for GPRS is not implemented"; break;
+				case 0x01: str="Extended Dynamic Allocation Capability for GPRS is implemented"; break;
+				default: str="This should not happen";
+			}
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"GPRS Extended Dynamic Allocation Capability: (%u) %s",oct>>(32-bits_needed),str);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+		}
+
+		/*
+		 * SMS/SM values
+		 */
+	    	bits_needed = 1;
+		GET_DATA;
+
+		/* analyse bits */
+        	if ((oct>>(32-bits_needed))==0)
+	        {
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"SMS/SM values: (%u) Bits are not available",oct>>(32-bits_needed));
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+	    	}
+    		else
+	    	{
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * Switch-Measure-Switch value
+    			 */
+		    	bits_needed = 4;
+			GET_DATA;
+
+			/* analyse bits */
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"Switch-Measure-Switch value: (%u) %d/4 timeslot (~%d microseconds)",
+				oct>>(32-bits_needed),oct>>(32-bits_needed),(oct>>(32-bits_needed))*144);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * Switch-Measure value
+    			 */
+		    	bits_needed = 4;
+			GET_DATA;
+
+			/* analyse bits */
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"Switch-Measure value: (%u) %d/4 timeslot (~%d microseconds)",
+				oct>>(32-bits_needed),oct>>(32-bits_needed),(oct>>(32-bits_needed))*144);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+		}
+
+	    	/*
+    		 * ECSD multislot class?
+	    	 */
+	    	bits_needed = 1;
+		GET_DATA;
+
+		/* analyse bits */
+        	if ((oct>>(32-bits_needed))==0)
+	        {
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"ECSD multislot class: (%u) Bits are not available",oct>>(32-bits_needed));
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+	    	}
+    		else
+	    	{
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * ECSD multislot class
+    			 */
+		    	bits_needed = 5;
+			GET_DATA;
+
+			/* analyse bits */
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"ECSD multislot class: (%u) %s",oct>>(32-bits_needed),multi_slot_str[oct>>(32-bits_needed)]);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+		}
+
+	    	/*
+    		 * EGPRS multislot class?
+	    	 */
+	    	bits_needed = 1;
+		GET_DATA;
+
+		/* analyse bits */
+        	if ((oct>>(32-bits_needed))==0)
+	        {
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"EGPRS multislot class: (%u) Bits are not available",oct>>(32-bits_needed));
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+	    	}
+    		else
+	    	{
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * EGPRS multislot class
+    			 */
+		    	bits_needed = 5;
+			GET_DATA;
+
+			/* analyse bits */
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"EGPRS multislot class: (%u) %s",oct>>(32-bits_needed),multi_slot_str[oct>>(32-bits_needed)]);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * EGPRS Extended Dynamic Allocation Capability
+    			 */
+		    	bits_needed = 1;
+			GET_DATA;
+
+			/* analyse bits */
+			switch ( oct>>(32-bits_needed) )
+			{
+				case 0x00: str="Extended Dynamic Allocation Capability for EGPRS is not implemented"; break;
+				case 0x01: str="Extended Dynamic Allocation Capability for EGPRS is implemented"; break;
+				default: str="This should not happen";
+			}
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"EGPRS Extended Dynamic Allocation Capability: (%u) %s",oct>>(32-bits_needed),str);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+		}
+
+		/*
+		 * DTM GPRS Multi Slot Class ?
+		*/
+	    	bits_needed = 1;
+		GET_DATA;
+
+		/* analyse bits */
+        	if ((oct>>(32-bits_needed))==0)
+	        {
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"DTM GPRS Multi Slot Class: (%u) Bits are not available",oct>>(32-bits_needed));
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+	    	}
+    		else
+	    	{
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+   	 		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * DTM GPRS Multi Slot Class
+    			 */
+		    	bits_needed = 2;
+			GET_DATA;
+
+			/* analyse bits */
+			dtm_gprs_mslot = oct>>(32-bits_needed);
+
+			switch ( oct>>(32-bits_needed) )
+			{
+				case 0: str="Unused. If received, the network shall interpret this as Multislot class 5"; break;
+				case 1: str="Multislot class 5 supported"; break;
+				case 2: str="Multislot class 9 supported"; break;
+				case 3: str="Multislot class 11 supported"; break;
+				default: str="This should not happen";
+			}
+			
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"DTM GPRS Multi Slot Class: (%u) %s",oct>>(32-bits_needed),str);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+
+		    	/*
+		    	 * Single Slot DTM
+    			 */
+		    	bits_needed = 1;
+			GET_DATA;
+
+			/* analyse bits */
+			switch ( oct>>(32-bits_needed) )
+			{
+				case 0x00: str="Single Slot DTM not supported"; break;
+				case 0x01: str="Single Slot DTM supported"; break;
+				default: str="This should not happen";
+			}
+		    	proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"Single Slot DTM: (%u) %s",oct>>(32-bits_needed),str);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+	    		bits_in_oct -= bits_needed;
+
+			/*
+			 * DTM EGPRS Multi Slot Class ?
+			*/
+		    	bits_needed = 1;
+			GET_DATA;
+
+			/* analyse bits */
+			dtm_egprs_mslot = oct>>(32-bits_needed);
+
+        		if ((oct>>(32-bits_needed))==0)
+	        	{
+		    		proto_tree_add_text(tf_tree,
+					tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+					"DTM EGPRS Multi Slot Class: (%u) Bits are not available",oct>>(32-bits_needed));
+			    	curr_bits_length -= bits_needed;
+    				oct <<= bits_needed;
+   	 			bits_in_oct -= bits_needed;
+	    		}
+	    		else
+		    	{
+			    	curr_bits_length -= bits_needed;
+    				oct <<= bits_needed;
+  	 	 		bits_in_oct -= bits_needed;
+
+			    	/*
+			    	 * DTM EGPRS Multi Slot Class
+	    			 */
+			    	bits_needed = 2;
+				GET_DATA;
+
+				/* analyse bits */
+				switch ( oct>>(32-bits_needed) )
+				{
+					case 0: str="Unused. If received, the network shall interpret this as Multislot class 5"; break;
+					case 1: str="Multislot class 5 supported"; break;
+					case 2: str="Multislot class 9 supported"; break;
+					case 3: str="Multislot class 11 supported"; break;
+					default: str="This should not happen";
+				}
+			
+		    		proto_tree_add_text(tf_tree,
+					tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+					"DTM EGPRS Multi Slot Class: (%u) %s",oct>>(32-bits_needed),str);
+			    	curr_bits_length -= bits_needed;
+    				oct <<= bits_needed;
+	    			bits_in_oct -= bits_needed;
+			}
+		}
+	}
+
+    	/*
+    	 * 8PSK Power Capability?
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+        if ((oct>>(32-bits_needed))==0)
+        {
+	    	proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"8PSK Power Capability: (%u) Bits are not available",oct>>(32-bits_needed));
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+    	}
+    	else
+    	{
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+
+	    	/*
+    		 * 8PSK Power Capability
+	    	 */
+    		bits_needed = 2;
+		GET_DATA;
+
+		/* analyse bits */
+		switch ( oct>>(32-bits_needed) )
+    		{
+			case 0x00: str="Reserved"; break;
+			case 0x01: str="Power class E1"; break;
+			case 0x02: str="Power class E2"; break;
+			case 0x03: str="Power class E3"; break;
+			default: str="This should not happen";
+	    	}
+    
+    		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"8PSK Power Capability: (%u) %s",oct>>(32-bits_needed),str);
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+    		bits_in_oct -= bits_needed;
+	}
+
+    	/*
+    	 * COMPACT Interference Measurement Capability
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="COMPACT Interference Measurement Capability is not implemented"; break;
+		case 0x01: str="COMPACT Interference Measurement Capability is implemented"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"COMPACT Interference Measurement Capability: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * Revision Level Indicator
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="The ME is Release 98 or older"; break;
+		case 0x01: str="The ME is Release 99 onwards"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"Revision Level Indicator: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * UMTS FDD Radio Access Technology Capability
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="UMTS FDD not supported"; break;
+		case 0x01: str="UMTS FDD supported"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"UMTS FDD Radio Access Technology Capability: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * UMTS 3.84 Mcps TDD Radio Access Technology Capability
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="UMTS 3.84 Mcps TDD not supported"; break;
+		case 0x01: str="UMTS 3.84 Mcps TDD supported"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"UMTS 3.84 Mcps TDD Radio Access Technology Capability: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * CDMA 2000 Radio Access Technology Capability
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="CDMA 2000 not supported"; break;
+		case 0x01: str="CDMA 2000 supported"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"CDMA 2000 Radio Access Technology Capability: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * UMTS 1.28 Mcps TDD Radio Access Technology Capability
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="UMTS 1.28 Mcps TDD not supported"; break;
+		case 0x01: str="UMTS 1.28 Mcps TDD supported"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"UMTS 1.28 Mcps TDD Radio Access Technology Capability: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * GERAN Feature Package 1
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="GERAN feature package 1 not supported"; break;
+		case 0x01: str="GERAN feature package 1 supported"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"GERAN Feature Package 1: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * Extended DTM (E)GPRS Multi Slot Class
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+        if ((oct>>(32-bits_needed))==0)
+        {
+	    	proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"Extended DTM (E)GPRS Multi Slot Class: (%u) Bits are not available",oct>>(32-bits_needed));
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+    	}
+    	else
+    	{
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+
+	    	/*
+    		 * Extended DTM GPRS Multi Slot Class
+	    	 */
+    		bits_needed = 2;
+		GET_DATA;
+
+		/* analyse bits */
+		switch ( (oct>>(32-bits_needed))|(dtm_gprs_mslot<<4) )
+    		{
+    			case 0x00: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    			case 0x01: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    			case 0x02: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    			case 0x03: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    			case 0x10: str="Multislot class 5 supported"; break;
+    			case 0x11: str="Multislot class 6 supported"; break;
+    			case 0x12: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    			case 0x13: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    			case 0x20: str="Multislot class 9 supported"; break;
+    			case 0x21: str="Multislot class 10 supported"; break;
+    			case 0x22: str="Unused. If received, it shall be interpreted as Multislot class 9 supported"; break;
+    			case 0x23: str="Unused. If received, it shall be interpreted as Multislot class 9 supported"; break;
+    			case 0x30: str="Multislot class 11 supported"; break;
+    			case 0x31: str="Unused. If received, it shall be interpreted as Multislot class 11 supported"; break;
+    			case 0x32: str="Unused. If received, it shall be interpreted as Multislot class 11 supported"; break;
+    			case 0x33: str="Unused. If received, it shall be interpreted as Multislot class 11 supported"; break;
+    			default: str="This should not happen";
+	    	}
+    
+    		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"Extended DTM GPRS Multi Slot Class: (%u) %s",oct>>(32-bits_needed),str);
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+    		bits_in_oct -= bits_needed;
+
+		if ( dtm_egprs_mslot <= 3 )
+		{
+		    	/*
+    			 * Extended DTM EGPRS Multi Slot Class
+	    		 */
+	    		bits_needed = 2;
+			GET_DATA;
+
+			/* analyse bits */
+			switch ( (oct>>(32-bits_needed))|(dtm_egprs_mslot<<4) )
+    			{
+    				case 0x00: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    				case 0x01: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+   	 			case 0x02: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    				case 0x03: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    				case 0x10: str="Multislot class 5 supported"; break;
+    				case 0x11: str="Multislot class 6 supported"; break;
+    				case 0x12: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    				case 0x13: str="Unused. If received, it shall be interpreted as Multislot class 5 supported"; break;
+    				case 0x20: str="Multislot class 9 supported"; break;
+    				case 0x21: str="Multislot class 10 supported"; break;
+    				case 0x22: str="Unused. If received, it shall be interpreted as Multislot class 9 supported"; break;
+    				case 0x23: str="Unused. If received, it shall be interpreted as Multislot class 9 supported"; break;
+    				case 0x30: str="Multislot class 11 supported"; break;
+    				case 0x31: str="Unused. If received, it shall be interpreted as Multislot class 11 supported"; break;
+   	 			case 0x32: str="Unused. If received, it shall be interpreted as Multislot class 11 supported"; break;
+    				case 0x33: str="Unused. If received, it shall be interpreted as Multislot class 11 supported"; break;
+    				default: str="This should not happen";
+	    		}
+    
+	    		proto_tree_add_text(tf_tree,
+				tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+				"Extended DTM EGPRS Multi Slot Class: (%u) %s",oct>>(32-bits_needed),str);
+		    	curr_bits_length -= bits_needed;
+    			oct <<= bits_needed;
+    			bits_in_oct -= bits_needed;
+		}
+	}
+
+    	/*
+    	 * Modulation based multislot class support
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="Modulation based multislot class not supported"; break;
+		case 0x01: str="Modulation based multislot class supported"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"Modulation based multislot class support: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * High Multislot Capability
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+        if ((oct>>(32-bits_needed))==0)
+        {
+	    	proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"High Multislot Capability: (%u) Bits are not available",oct>>(32-bits_needed));
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+    	}
+    	else
+    	{
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+
+	    	/*
+    		 * High Multislot Capability
+	    	 */
+    		bits_needed = 2;
+		GET_DATA;
+
+		/* analyse bits */
+    		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"High Multislot Capability: 0x%02x (%u) - This field effect all other multislot fields. To understand the value please read TS 24.008 5.6.0 Release 5 Chap 10.5.5.12 Page 406",oct>>(32-bits_needed),oct>>(32-bits_needed));
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+    		bits_in_oct -= bits_needed;
+
+	}
+
+    	/*
+    	 * GERAN Iu Mode Capability
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+	switch ( oct>>(32-bits_needed) )
+    	{
+		case 0x00: str="GERAN Iu mode not supported"; break;
+		case 0x01: str="GERAN Iu mode supported"; break;
+		default: str="This should not happen";
+    	}
+    
+    	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+		"GERAN Iu Mode Capability: (%u) %s",oct>>(32-bits_needed),str);
+    	curr_bits_length -= bits_needed;
+    	oct <<= bits_needed;
+    	bits_in_oct -= bits_needed;
+
+    	/*
+    	 * GMSK/8-PSK Multislot Power Profile
+    	 */
+    	bits_needed = 1;
+	GET_DATA;
+
+	/* analyse bits */
+        if ((oct>>(32-bits_needed))==0)
+        {
+	    	proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"GMSK/8-PSK Multislot Power Profile: (%u) Bits are not available",oct>>(32-bits_needed));
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+    	}
+    	else
+    	{
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+   	 	bits_in_oct -= bits_needed;
+
+	    	/*
+    		 * GMSK Multislot Power Profile
+	    	 */
+    		bits_needed = 2;
+		GET_DATA;
+
+		/* analyse bits */
+		switch ( oct>>(32-bits_needed) )
+		{
+			case 0x00: str="GMSK_MULTISLOT_POWER_PROFILE 0"; break;
+			case 0x01: str="GMSK_MULTISLOT_POWER_PROFILE 1"; break;
+			case 0x02: str="GMSK_MULTISLOT_POWER_PROFILE 2"; break;
+			case 0x03: str="GMSK_MULTISLOT_POWER_PROFILE 3"; break;
+			default: str="This should not happen";
+		}
+		
+    		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"GMSK Multislot Power Profile: (%u) %s",oct>>(32-bits_needed),str);
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+    		bits_in_oct -= bits_needed;
+
+	    	/*
+    		 * 8-PSK Multislot Power Profile
+	    	 */
+    		bits_needed = 2;
+		GET_DATA;
+
+		/* analyse bits */
+		switch ( oct>>(32-bits_needed) )
+		{
+			case 0x00: str="8-PSK_MULTISLOT_POWER_PROFILE 0"; break;
+			case 0x01: str="8-PSK_MULTISLOT_POWER_PROFILE 1"; break;
+			case 0x02: str="8-PSK_MULTISLOT_POWER_PROFILE 2"; break;
+			case 0x03: str="8-PSK_MULTISLOT_POWER_PROFILE 3"; break;
+			default: str="This should not happen";
+		}
+		
+    		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1-add_ocetets, 1+add_ocetets,
+			"8-PSK Multislot Power Profile: (%u) %s",oct>>(32-bits_needed),str);
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+    		bits_in_oct -= bits_needed;
+
+	}
+
+	/*
+	 * we are too long ... so jump over it
+	 */
+	while ( curr_bits_length > 0 )
+	{
+		if ( curr_bits_length > 8 )
+			bits_needed = 8;
+		else
+			bits_needed = curr_bits_length;
+		GET_DATA;
+	    	curr_bits_length -= bits_needed;
+    		oct <<= bits_needed;
+		bits_in_oct -= bits_needed;
+	}	 
+	
+    } while ( 1 );
+    
     curr_offset+= curr_len;	   
 	   	   
     EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
@@ -7625,6 +8964,7 @@
 
     switch ( oct )
     {
+    	/* additional causes can be found in annex g */
     	case 0x02: str="IMSI unknown in HLR"; break;
     	case 0x03: str="Illegal MS"; break;
     	case 0x04: str="IMSI unknown in VLR"; break;
@@ -7645,26 +8985,35 @@
     	case 0x15: str="Synch failure"; break;
     	case 0x16: str="Congestion"; break;
     	case 0x17: str="GSM authentication unacceptable"; break;
-    	case 0x18: str="No PDP context activated"; break;
-    	case 0x19: str="retry upon entry into a new cell"; break;
-    	case 0x1a: str="retry upon entry into a new cell"; break;
-    	case 0x1b: str="retry upon entry into a new cell"; break;
-    	case 0x1c: str="retry upon entry into a new cell"; break;
-    	case 0x1d: str="retry upon entry into a new cell"; break;
-    	case 0x1e: str="retry upon entry into a new cell"; break;
-    	case 0x1f: str="retry upon entry into a new cell"; break;
     	case 0x20: str="Service option not supported"; break;
     	case 0x21: str="Requested service option not subscribed"; break;
     	case 0x22: str="Service option temporarily out of order"; break;
     	case 0x26: str="Call cannot be identified"; break;
-    	case 0x2f: str="Semantically incorrect message"; break;
-    	case 0x30: str="Invalid mandatory information"; break;
-    	case 0x31: str="Message type non-existent or not implemented"; break;
-        case 0x32: str="Message type not compatible with the protocol state"; break;
-        case 0x33: str="Information element non-existent or not implemented"; break;
-        case 0x34: str="Conditional IE error"; break;
-        case 0x35: str="Message not compatible with the protocol state"; break;
-        case 0x36: str="Protocol error, unspecified"; break;
+    	case 0x28: str="No PDP context activated"; break;
+    	case 0x30: str="retry upon entry into a new cell"; break;
+    	case 0x31: str="retry upon entry into a new cell"; break;
+    	case 0x32: str="retry upon entry into a new cell"; break;
+    	case 0x33: str="retry upon entry into a new cell"; break;
+    	case 0x34: str="retry upon entry into a new cell"; break;
+    	case 0x35: str="retry upon entry into a new cell"; break;
+    	case 0x36: str="retry upon entry into a new cell"; break;
+    	case 0x37: str="retry upon entry into a new cell"; break;
+    	case 0x38: str="retry upon entry into a new cell"; break;
+    	case 0x39: str="retry upon entry into a new cell"; break;
+    	case 0x3a: str="retry upon entry into a new cell"; break;
+    	case 0x3b: str="retry upon entry into a new cell"; break;
+    	case 0x3c: str="retry upon entry into a new cell"; break;
+    	case 0x3d: str="retry upon entry into a new cell"; break;
+    	case 0x3e: str="retry upon entry into a new cell"; break;
+    	case 0x3f: str="retry upon entry into a new cell"; break;
+    	case 0x5f: str="Semantically incorrect message"; break;
+    	case 0x60: str="Invalid mandatory information"; break;
+    	case 0x61: str="Message type non-existent or not implemented"; break;
+        case 0x62: str="Message type not compatible with the protocol state"; break;
+        case 0x63: str="Information element non-existent or not implemented"; break;
+        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;
 	default: str="Protocol error, unspecified";
     }
     
@@ -8356,6 +9705,9 @@
     {
     	guchar e_len;
     	guint16 prot;
+	tvbuff_t *l3_tvb;
+	static packet_info pco_pinfo;
+	
 	prot = tvb_get_guint8(tvb, curr_offset);
 	prot <<= 8;
 	prot |= tvb_get_guint8(tvb, curr_offset+1);
@@ -8366,40 +9718,96 @@
     	switch ( prot )
     	{
     		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] );				
 	    	    break;
+	    	}
     		case 0x0002:
 	    	    proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Parameter: (%u) IM CN Subsystem Signaling Flag" , prot );
 	    	    proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
 	    	    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] );				
 	    	    break;
+	    	}
     		case 0x0004:
 	    	    proto_tree_add_text(tree,tvb, curr_offset-3, 2, "Parameter: (%u) Policy Control rejection code" , prot );
 	    	    proto_tree_add_text(tree,tvb, curr_offset-1, 1, "Length: 0x%02x (%u)", e_len , e_len);
+	    	    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);
     	}
 
 	curr_len-= e_len;
@@ -9286,23 +10694,32 @@
 {
     guint32	curr_offset;
     guint	curr_len;
-    proto_item  *tf = NULL;
-    proto_tree      *tf_tree = NULL;
+    guchar	oct;
+    gchar	*str;
     
     curr_len = len;
     add_string = add_string;
     curr_offset = offset;
 
-    tf = proto_tree_add_text(tree,
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    switch ( oct&0x7f )
+    {
+    	case 0x00: str="Best Effort"; break;
+    	case 0x01: str="Signaling"; break;
+    	case 0x02: str="SMS"; break;
+    	case 0x03: str="TOM8"; break;
+    	case 0x04: str="reserved"; break;
+    	case 0x05: str="reserved"; break;
+    	case 0x06: str="reserved"; break;
+    	case 0x07: str="reserved"; break;
+	default: str="dynamically assigned"; break;
+    }
+
+    proto_tree_add_text(tree,
     	tvb, curr_offset, 1,
-    	"Packet Flow Identifier");
+    	"Packet Flow Identifier: (%u) %s",oct&0x7f,str);
 
-    tf_tree = proto_item_add_subtree(tf, ett_sm_pfi );
-    
-    proto_tree_add_text(tf_tree,
-	tvb, curr_offset, curr_len,
-	"Not Implemented" );
-    
     curr_offset+= curr_len;	   
 	   	   
     EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
@@ -9320,21 +10737,315 @@
     guint	curr_len;
     proto_item  *tf = NULL;
     proto_tree      *tf_tree = NULL;
+    guchar	op_code;
+    guchar	pkt_fil_count;
+    guchar      e_bit;
+    gchar	*str;
+    guchar      count;
+    guchar	oct;
     
     curr_len = len;
     add_string = add_string;
     curr_offset = offset;
 
-    tf = proto_tree_add_text(tree,
-    	tvb, curr_offset, 1,
-    	"Traffic Flow Template");
+    /*
+     * parse first byte
+     */
+    oct = tvb_get_guint8(tvb, curr_offset);
+    curr_offset++;
+    curr_len--;
 
-    tf_tree = proto_item_add_subtree(tf, ett_sm_tft );
+    op_code = oct>>5;
+    pkt_fil_count = oct&0x0f;
+    e_bit = (oct>>4)&1;
+
+    switch ( op_code )
+    {
+    	case 0x00: str="Spare"; break;
+    	case 0x01: str="Create new TFT"; break;
+    	case 0x02: str="Delete existing TFT"; break;
+    	case 0x03: str="Add packet filters to existing TFT"; break;
+    	case 0x04: str="Replace packet filters in existing TFT"; break;
+    	case 0x05: str="Delete packet filters from existing TFT"; break;
+    	case 0x06: str="No TFT operation"; break;
+    	case 0x07: str="Reserved"; break;
+    	default: str="dissector bug";
+    }
+    proto_tree_add_text(tree,
+    	tvb, curr_offset-1, 1,
+    	"Operation code: (%u) %s",op_code,str);
+
+    switch ( e_bit )
+    {
+    	case 0x00: str="parameters list is not included"; break;
+    	case 0x01: str="parameters list is included"; break;
+    	default: str="dissector bug";
+    }
+    proto_tree_add_text(tree,
+    	tvb, curr_offset-1, 1,
+    	"E bit: (%u) %s",e_bit,str);
+
+    proto_tree_add_text(tree,
+    	tvb, curr_offset-1, 1,
+    	"Number of packet filters: 0x%02x (%u)",pkt_fil_count,pkt_fil_count);
+
+    count = 0;
+    if ( op_code == 2 )			/* delete TFT contains no packet filters. so we will jump over it */
+	count = pkt_fil_count;
+    while ( count < pkt_fil_count )
+    {
+	tf = proto_tree_add_text(tree,
+    		tvb, curr_offset, 1,
+    		"Packet filter %d",count+1);
+
+    	tf_tree = proto_item_add_subtree(tf, ett_sm_tft );
+
+	if ( op_code == 5 )
+	{
+		if ((curr_offset-offset)<1) { proto_tree_add_text(tf_tree,tvb, curr_offset-1, 1,"Not enough data"); return(curr_offset-offset);}
+		oct = tvb_get_guint8(tvb, curr_offset);
+		curr_offset++;
+		curr_len--;
+
+		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1, 1,
+			"Packet filter identifier: 0x%02x (%u)",oct,oct );		
+	}
+	else
+	{
+		gint pf_length;
+		gint pf_identifier;
+		guchar *pchar;
+		
+		if ((curr_offset-offset)<1) { proto_tree_add_text(tf_tree,tvb, curr_offset-1, 1,"Not enough data"); return(curr_offset-offset);}
+		pf_identifier = tvb_get_guint8(tvb, curr_offset);
+		curr_offset++;
+		curr_len--;
+
+		switch ( pf_identifier )
+		{
+			case 0x10: str="IPv4 source address type"; break;
+			case 0x20: str="IPv6 source address type"; break;
+			case 0x30: str="Protocol identifier/Next header type"; break;
+			case 0x40: str="Single destination port type"; break;
+			case 0x41: str="Destination port range type"; break;
+			case 0x50: str="Single source port type"; break;
+			case 0x51: str="Source port range type"; break;
+			case 0x60: str="Security parameter index type"; break;
+			case 0x70: str="Type of service/Traffic class type"; break;
+			case 0x80: str="Flow label type"; break;
+			default: str="not specified";
+		}
+
+		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1, 1,
+			"Packet filter identifier: (%u) %s",pf_identifier,str );		
+
+		if ((curr_offset-offset)<1) { proto_tree_add_text(tf_tree,tvb, curr_offset-1, 1,"Not enough data"); return(curr_offset-offset);}
+		oct = tvb_get_guint8(tvb, curr_offset);
+		curr_offset++;
+		curr_len--;
+
+		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1, 1,
+			"Packet evaluation precedence: 0x%02x (%u)",oct,oct );		
+
+		if ((curr_offset-offset)<1) { proto_tree_add_text(tf_tree,tvb, curr_offset-1, 1,"Not enough data"); return(curr_offset-offset);}
+		pf_length = tvb_get_guint8(tvb, curr_offset);
+		curr_offset++;
+		curr_len--;
+
+		proto_tree_add_text(tf_tree,
+			tvb, curr_offset-1, 1,
+			"Packet filter length: 0x%02x (%u)",pf_length,pf_length );		
+
+		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] );
+		}
+		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] );				
+		}
+		else if (( pf_identifier == 0x30 ) && ( pf_length == 1 ))
+		{
+			oct = tvb_get_guint8(tvb, curr_offset);
+			
+			proto_tree_add_text(tf_tree,
+				tvb, curr_offset, pf_length ,
+				"Packet filter content: Protocol identifier/Next header %u",
+				oct );
+		}
+		else if (( pf_identifier == 0x40 ) && ( pf_length == 2 ))
+		{
+			pchar = (guchar*)tvb_get_ptr(tvb, offset, pf_length);
+			
+			proto_tree_add_text(tf_tree,
+				tvb, curr_offset, pf_length ,
+				"Packet filter content: Single destination port %u",
+				(pchar[0]<<8)|pchar[1] );
+		}
+		else if (( pf_identifier == 0x50 ) && ( pf_length == 2 ))
+		{
+			pchar = (guchar*)tvb_get_ptr(tvb, offset, pf_length);
+			
+			proto_tree_add_text(tf_tree,
+				tvb, curr_offset, pf_length ,
+				"Packet filter content: Single source port %u",
+				(pchar[0]<<8)|pchar[1] );
+		}
+		else if (( pf_identifier == 0x41 ) && ( 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:  Destination port range %u - %u", 
+				(pchar[0]<<8)|pchar[1] , (pchar[2]<<8)|pchar[3] );
+		}
+		else if (( pf_identifier == 0x51 ) && ( 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:  Source port range %u - %u", 
+				(pchar[0]<<8)|pchar[1] , (pchar[2]<<8)|pchar[3] );
+		}
+		else if (( pf_identifier == 0x70 ) && ( pf_length == 1 ))
+		{
+			oct = tvb_get_guint8(tvb, curr_offset);
+			
+			proto_tree_add_text(tf_tree,
+				tvb, curr_offset, pf_length ,
+				"Packet filter content: Type of service/Traffic class %u",
+				oct );
+		}
+		else if (( pf_identifier == 0x80 ) && ( pf_length == 3 ))
+		{
+			guint32 fl;
+			oct = tvb_get_guint8(tvb, curr_offset);
+			fl = oct;
+			fl <<=8;
+			oct = tvb_get_guint8(tvb, curr_offset+1);
+			fl |= oct;
+			fl <<=8;
+			oct = tvb_get_guint8(tvb, curr_offset+2);
+			fl |= oct;
+			
+			proto_tree_add_text(tf_tree,
+				tvb, curr_offset, pf_length ,
+				"Packet filter content: Flow label type %u",
+				fl );
+		}
+		else if (( pf_identifier == 0x60 ) && ( 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:  Security parameter index 0x%08x", 
+				(pchar[0]<<24)|(pchar[1]<<16)|(pchar[2]<<8)|pchar[3] );
+		}
+		else
+		{
+			proto_tree_add_text(tf_tree,
+				tvb, curr_offset, pf_length ,
+				"Packet filter content" );		
+		}
+		curr_offset+= pf_length;
+	}
+    }
+
+    if ( e_bit == 0 )
+    {
+	proto_tree_add_text(tf_tree,
+		tvb, curr_offset, curr_len ,
+		"Too much data" );		
+	curr_offset+= curr_len;	   
+	   	   
+	EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+	return(curr_offset - offset);
+
+    }
     
-    proto_tree_add_text(tf_tree,
-	tvb, curr_offset, curr_len,
-	"Not Implemented" );
+    count = 0;
+    while ((curr_offset-offset)>=2)
+    {
+	gint p_length;
+	gint p_identifier;
+	guchar *pchar;
+
+	tf = proto_tree_add_text(tree,
+    		tvb, curr_offset, 1,
+    		"Parameters list %d",count+1);
+
+    	tf_tree = proto_item_add_subtree(tf, ett_sm_tft );
+
+	if ((curr_offset-offset)<1) { proto_tree_add_text(tf_tree,tvb, curr_offset-1, 1,"Not enough data"); return(curr_offset-offset);}
+	p_identifier = tvb_get_guint8(tvb, curr_offset);
+	curr_offset++;
+	curr_len--;
+
+	switch ( p_identifier )
+	{
+		case 0x01: str="Authorization Token";
+		case 0x02: str="Flow Identifier";
+		default: str="not specified";
+	}
+
+	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1, 1,
+		"Parameter identifier: (%u) %s",p_identifier,str );		
+
+	if ((curr_offset-offset)<1) { proto_tree_add_text(tf_tree,tvb, curr_offset-1, 1,"Not enough data"); return(curr_offset-offset);}
+	p_length = tvb_get_guint8(tvb, curr_offset);
+	curr_offset++;
+	curr_len--;
+
+	proto_tree_add_text(tf_tree,
+		tvb, curr_offset-1, 1,
+		"Parameter length: 0x%02x (%u)",p_length,p_length );		
+
+	if (( p_identifier == 0x01 ) && ( p_length == 4 ))
+	{
+		pchar =  (guchar*)tvb_get_ptr(tvb, offset, p_length);
+		
+		proto_tree_add_text(tf_tree,
+			tvb, curr_offset, p_length ,
+			"Parameter content: Media component %u IP Flow %u",
+			(pchar[0]<<8)|pchar[1] , (pchar[2]<<8)|pchar[3] );
+	}
+	else if ( p_identifier == 0x02 )
+	{
+		proto_tree_add_text(tf_tree,
+			tvb, curr_offset, p_length ,
+			"Parameter content: Authentication Token" );		
+	}
+	else
+	{
+		proto_tree_add_text(tf_tree,
+			tvb, curr_offset, p_length ,
+			"Parameter content" );		
+	}
+	curr_offset+= p_length;
     
+    }
+    
     curr_offset+= curr_len;	   
 	   	   
     EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
@@ -13422,7 +15133,7 @@
     curr_offset--;
     curr_len++;
     
-    ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_FORCE_TO_STAND_H );
+    ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_FORCE_TO_STAND );
     
     ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_GPRS_TIMER );
     
@@ -14339,6 +16050,15 @@
 	col_append_str(pinfo->cinfo, COL_INFO, "(RP) ");
     }
 
+    /*
+     * In the interest of speed, if "tree" is NULL, don't do any work
+     * not necessary to generate protocol tree items.
+     */
+    if (!tree)
+    {
+	return;
+    }
+
     offset = 0;
     saved_offset = offset;
 
@@ -14952,7 +16672,7 @@
     };
 
     /* Setup protocol subtree array */
-#define	NUM_INDIVIDUAL_ELEMS	39
+#define	NUM_INDIVIDUAL_ELEMS	38
     static gint *ett[NUM_INDIVIDUAL_ELEMS + NUM_GSM_BSSMAP_MSG +
 			NUM_GSM_DTAP_MSG_MM + NUM_GSM_DTAP_MSG_RR + NUM_GSM_DTAP_MSG_CC +
 			NUM_GSM_DTAP_MSG_GMM + NUM_GSM_DTAP_MSG_SMS +
@@ -15000,8 +16720,7 @@
     ett[35] = &ett_gmm_update_type;
     ett[36] = &ett_gmm_radio_cap;
 
-    ett[37] = &ett_sm_pfi;
-    ett[38] = &ett_sm_tft;
+    ett[37] = &ett_sm_tft;
 
     last_offset = NUM_INDIVIDUAL_ELEMS;
 
@@ -15096,6 +16815,10 @@
 
     proto_register_subtree_array(ett, array_length(ett));
 
+    /* subdissector code */
+    gprs_sm_pco_subdissector_table = register_dissector_table("sm_pco.protocol",
+    	"GPRS SM PCO PPP protocol", FT_UINT16, BASE_HEX);
+
     gsm_a_tap = register_tap("gsm_a");
 }
 
@@ -15111,7 +16834,6 @@
     dissector_add("bssap.pdu_type",  BSSAP_PDU_TYPE_BSSMAP, bssmap_handle);
     dissector_add("bssap.pdu_type",  BSSAP_PDU_TYPE_DTAP, dtap_handle);
     dissector_add("ranap.nas_pdu",  BSSAP_PDU_TYPE_DTAP, dtap_handle);
-    dissector_add("llcgprs.sapi", 1, dtap_handle);
-
+    dissector_add("llcgprs.sapi", 1 , dtap_handle);
     data_handle = find_dissector("data");
 }
--- epan/dissectors/packet-ppp.c	(revision 13003)
+++ epan/dissectors/packet-ppp.c	(working copy)
@@ -3773,6 +3773,12 @@
    * table.
    */
   dissector_add("ethertype", PPP_LCP, lcp_handle);
+
+  /*
+   * for GSM-A / MobileL3 / GPRS SM / PCO
+   */
+  dissector_add("sm_pco.protocol", PPP_LCP, lcp_handle);
+
 }
 
 void
@@ -3803,6 +3809,12 @@
    * registering with the "ethertype" dissector table.
    */
   dissector_add("ethertype", PPP_IPCP, ipcp_handle);
+
+  /*
+   * for GSM-A / MobileL3 / GPRS SM / PCO
+   */
+  dissector_add("sm_pco.protocol", PPP_IPCP, ipcp_handle);
+
 }
 
 void
@@ -4016,6 +4028,11 @@
    * registering with the "ethertype" dissector table.
    */
   dissector_add("ethertype", PPP_PAP, pap_handle);
+
+  /*
+   * for GSM-A / MobileL3 / GPRS SM / PCO
+   */
+  dissector_add("sm_pco.protocol", PPP_PAP, pap_handle);
 }
 
 void
@@ -4047,6 +4064,11 @@
    * registering with the "ethertype" dissector table.
    */
   dissector_add("ethertype", PPP_CHAP, chap_handle);
+  
+  /*
+   * for GSM-A / MobileL3 / GPRS SM / PCO
+   */
+  dissector_add("sm_pco.protocol", PPP_CHAP, chap_handle);
 }
 
 void