4550e111c3fd93a8380a29615b2edeac74cdd45d
[obnox/wireshark/wip.git] / epan / dissectors / packet-bssgp.c
1 /* packet-bssgp.c
2  * Routines for Base Station Subsystem GPRS Protocol dissection
3  * Copyright 2000, Susanne Edlund <susanne.edlund@ericsson.com>
4  *
5  * $Id$
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
12  * is a dissector file; if you just copied this from README.developer,
13  * don't bother with the "Copied from" - you don't even need to put
14  * in a "Copied from" if you copied an existing dissector, especially
15  * if the bulk of the code in the new dissector is your code)
16  * 
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  * 
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  * 
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30  */
31
32 /* 3GPP TS 48.018 V 6.5.0 (2004-07) Release 6 */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <math.h>
42 #include <glib.h>
43 #include <epan/packet.h>
44
45 /*#define BSSGP_DEBUG*/
46 #define BSSGP_LITTLE_ENDIAN FALSE
47 #define BSSGP_TRANSLATION_MAX_LEN 50
48 #define BSSGP_MASK_LEFT_OCTET_HALF 0xf0
49 #define BSSGP_MASK_RIGHT_OCTET_HALF 0x0f
50 #define BSSGP_MOBILE_IDENTITY_TYPE_IMSI 1
51 #define BSSGP_MOBILE_IDENTITY_TYPE_IMEI 2
52 #define BSSGP_MOBILE_IDENTITY_TYPE_IMEISV 3
53 #define BSSGP_MOBILE_IDENTITY_TYPE_TMSI_PTMSI 4
54 #define BSSGP_MOBILE_IDENTITY_TYPE_NO_IDENTITY 0
55 #define BSSGP_SEP ", "
56 #define BSSGP_NOT_DECODED "< Not decoded yet >"
57 #define BSSGP_UNKNOWN -1
58
59 static dissector_handle_t bssgp_handle;
60 static dissector_handle_t llc_handle;
61 static dissector_handle_t rrlp_handle;
62 static dissector_handle_t data_handle;
63
64
65 /* Initialize the protocol and registered fields */
66 static int proto_bssgp = -1;
67 static int hf_bssgp_pdu_type = -1;
68 static int hf_bssgp_ie_type = -1;
69 static int hf_bssgp_mcc = -1;
70 static int hf_bssgp_mnc = -1;
71 static int hf_bssgp_lac = -1;
72 static int hf_bssgp_rac = -1;
73 static int hf_bssgp_ci = -1;
74 static int hf_bssgp_imsi = -1;
75 static int hf_bssgp_imei = -1;
76 static int hf_bssgp_imeisv = -1;
77 static int hf_bssgp_tmsi_ptmsi = -1;
78 static int hf_bssgp_bvci = -1;
79 static int hf_bssgp_nsei = -1;
80 static int hf_bssgp_tlli = -1;
81
82 /* Initialize the subtree pointers */
83 static gint ett_bssgp = -1;
84 static gint ett_bssgp_qos_profile = -1; 
85 static gint ett_bssgp_gprs_timer = -1;
86 static gint ett_bssgp_cell_identifier = -1;
87 static gint ett_bssgp_channel_needed = -1;
88 static gint ett_bssgp_drx_parameters = -1;
89 static gint ett_bssgp_mobile_identity = -1;
90 static gint ett_bssgp_priority = -1;
91 static gint ett_bssgp_lsa_identifier_list = -1;
92 static gint ett_bssgp_lsa_information = -1;
93 static gint ett_bssgp_lsa_information_lsa_identification_and_attributes = -1;
94 static gint ett_bssgp_abqp = -1;
95 static gint ett_bssgp_lcs_qos = -1;
96 static gint ett_bssgp_lcs_client_type = -1;
97 static gint ett_bssgp_requested_gps_assistance_data = -1;
98 static gint ett_bssgp_requested_gps_assistance_data_satellite = -1;
99 static gint ett_bssgp_location_type = -1;
100 static gint ett_bssgp_positioning_data_positioning_method = -1;
101 static gint ett_bssgp_deciphering_keys = -1;
102 static gint ett_bssgp_lcs_cause = -1;
103 static gint ett_bssgp_lcs_capability = -1;
104 static gint ett_bssgp_rrlp_flags = -1;
105 static gint ett_bssgp_ran_information_indications = -1;
106 static gint ett_bssgp_mcc = -1;
107 static gint ett_bssgp_mnc = -1;
108 static gint ett_bssgp_routeing_area = -1;
109 static gint ett_bssgp_location_area = -1;
110 static gint ett_bssgp_rai_ci = -1;
111 static gint ett_bssgp_ran_information_request_container_unit = -1;
112 static gint ett_bssgp_ran_information_container_unit = -1;
113 static gint ett_bssgp_pfc_flow_control_parameters = -1;
114 static gint ett_bssgp_pfc_flow_control_parameters_pfc = -1;
115 static gint ett_bssgp_global_cn_id = -1;
116 static gint ett_bssgp_ms_radio_access_capability = -1;
117 static gint ett_bssgp_msrac_value_part = -1;
118 static gint ett_bssgp_msrac_additional_access_technologies = -1;
119 static gint ett_bssgp_msrac_access_capabilities = -1;
120 static gint ett_bssgp_msrac_a5_bits = -1;
121 static gint ett_bssgp_msrac_multislot_capability = -1;
122 static gint ett_bssgp_feature_bitmap = -1;
123 static gint ett_bssgp_positioning_data = -1;
124
125 /* PDU type coding, v6.5.0, table 11.3.26, p 80 */
126 #define BSSGP_PDU_DL_UNITDATA                  0x00
127 #define BSSGP_PDU_UL_UNITDATA                  0x01
128 #define BSSGP_PDU_RA_CAPABILITY                0x02
129 #define BSSGP_PDU_PTM_UNITDATA                 0x03
130 #define BSSGP_PDU_PAGING_PS                    0x06
131 #define BSSGP_PDU_PAGING_CS                    0x07
132 #define BSSGP_PDU_RA_CAPABILITY_UPDATE         0x08
133 #define BSSGP_PDU_RA_CAPABILITY_UPDATE_ACK     0x09
134 #define BSSGP_PDU_RADIO_STATUS                 0x0a
135 #define BSSGP_PDU_SUSPEND                      0x0b
136 #define BSSGP_PDU_SUSPEND_ACK                  0x0c
137 #define BSSGP_PDU_SUSPEND_NACK                 0x0d
138 #define BSSGP_PDU_RESUME                       0x0e
139 #define BSSGP_PDU_RESUME_ACK                   0x0f
140 #define BSSGP_PDU_RESUME_NACK                  0x10
141 #define BSSGP_PDU_BVC_BLOCK                    0x20
142 #define BSSGP_PDU_BVC_BLOCK_ACK                0x21
143 #define BSSGP_PDU_BVC_RESET                    0x22
144 #define BSSGP_PDU_BVC_RESET_ACK                0x23
145 #define BSSGP_PDU_BVC_UNBLOCK                  0x24
146 #define BSSGP_PDU_BVC_UNBLOCK_ACK              0x25
147 #define BSSGP_PDU_FLOW_CONTROL_BVC             0x26
148 #define BSSGP_PDU_FLOW_CONTROL_BVC_ACK         0x27
149 #define BSSGP_PDU_FLOW_CONTROL_MS              0x28
150 #define BSSGP_PDU_FLOW_CONTROL_MS_ACK          0x29
151 #define BSSGP_PDU_FLUSH_LL                     0x2a
152 #define BSSGP_PDU_FLUSH_LL_ACK                 0x2b
153 #define BSSGP_PDU_LLC_DISCARDED                0x2c
154 #define BSSGP_PDU_FLOW_CONTROL_PFC             0x2d
155 #define BSSGP_PDU_FLOW_CONTROL_PFC_ACK         0x2e
156 #define BSSGP_PDU_SGSN_INVOKE_TRACE            0x40
157 #define BSSGP_PDU_STATUS                       0x41
158 #define BSSGP_PDU_DOWNLOAD_BSS_PFC             0x50
159 #define BSSGP_PDU_CREATE_BSS_PFC               0x51
160 #define BSSGP_PDU_CREATE_BSS_PFC_ACK           0x52
161 #define BSSGP_PDU_CREATE_BSS_PFC_NACK          0x53
162 #define BSSGP_PDU_MODIFY_BSS_PFC               0x54
163 #define BSSGP_PDU_MODIFY_BSS_PFC_ACK           0x55
164 #define BSSGP_PDU_DELETE_BSS_PFC               0x56
165 #define BSSGP_PDU_DELETE_BSS_PFC_ACK           0x57
166 #define BSSGP_PDU_DELETE_BSS_PFC_REQ           0x58
167 #define BSSGP_PDU_PERFORM_LOCATION_REQUEST     0x60
168 #define BSSGP_PDU_PERFORM_LOCATION_RESPONSE    0x61
169 #define BSSGP_PDU_PERFORM_LOCATION_ABORT       0x62
170 #define BSSGP_PDU_POSITION_COMMAND             0x63
171 #define BSSGP_PDU_POSITION_RESPONSE            0x64
172 #define BSSGP_PDU_RAN_INFORMATION              0x70
173 #define BSSGP_PDU_RAN_INFORMATION_REQUEST      0x71
174 #define BSSGP_PDU_RAN_INFORMATION_ACK          0x72
175 #define BSSGP_PDU_RAN_INFORMATION_ERROR        0x73
176
177 static const value_string tab_bssgp_pdu_types[] = {
178   { BSSGP_PDU_DL_UNITDATA,                  "DL-UNITDATA" },
179   { BSSGP_PDU_UL_UNITDATA,                  "UL-UNITDATA" },
180   { BSSGP_PDU_RA_CAPABILITY,                "RA-CAPABILITY" },
181   { BSSGP_PDU_PTM_UNITDATA,                 "PTM-UNITDATA" },
182   { BSSGP_PDU_PAGING_PS,                    "PAGING-PS" },
183   { BSSGP_PDU_PAGING_CS,                    "PAGING-CS" },
184   { BSSGP_PDU_RA_CAPABILITY_UPDATE,         "RA-CAPABILITY-UPDATE" },
185   { BSSGP_PDU_RA_CAPABILITY_UPDATE_ACK,     "RA-CAPABILITY-UPDATE-ACK" },
186   { BSSGP_PDU_RADIO_STATUS,                 "RADIO-STATUS" },
187   { BSSGP_PDU_SUSPEND,                      "SUSPEND" },
188   { BSSGP_PDU_SUSPEND_ACK,                  "SUSPEND-ACK" },
189   { BSSGP_PDU_SUSPEND_NACK,                 "SUSPEND-NACK" },
190   { BSSGP_PDU_RESUME,                       "RESUME" },
191   { BSSGP_PDU_RESUME_ACK,                   "RESUME-ACK" },
192   { BSSGP_PDU_RESUME_NACK,                  "RESUME-NACK" },
193   { BSSGP_PDU_BVC_BLOCK,                    "BVC-BLOCK" },
194   { BSSGP_PDU_BVC_BLOCK_ACK,                "BVC-BLOCK-ACK" },
195   { BSSGP_PDU_BVC_RESET,                    "BVC-RESET" },
196   { BSSGP_PDU_BVC_RESET_ACK,                "BVC-RESET-ACK" },
197   { BSSGP_PDU_BVC_UNBLOCK,                  "UNBLOCK" },
198   { BSSGP_PDU_BVC_UNBLOCK_ACK,              "UNBLOCK-ACK" },
199   { BSSGP_PDU_FLOW_CONTROL_BVC,             "FLOW-CONTROL-BVC" },
200   { BSSGP_PDU_FLOW_CONTROL_BVC_ACK,         "FLOW-CONTROL-BVC-ACK" },
201   { BSSGP_PDU_FLOW_CONTROL_MS,              "FLOW-CONTROL-MS" },
202   { BSSGP_PDU_FLOW_CONTROL_MS_ACK,          "FLOW-CONTROL-MS-ACK" },
203   { BSSGP_PDU_FLUSH_LL,                     "FLUSH-LL" },
204   { BSSGP_PDU_FLUSH_LL_ACK,                 "FLUSH_LL_ACK" },
205   { BSSGP_PDU_LLC_DISCARDED,                "LLC-DISCARDED" },
206   { BSSGP_PDU_FLOW_CONTROL_PFC,             "FLOW-CONTROL-PFC" },
207   { BSSGP_PDU_FLOW_CONTROL_PFC_ACK,         "FLOW-CONTROL-PFC-ACK" },
208   { BSSGP_PDU_SGSN_INVOKE_TRACE,            "SGSN-INVOKE-TRACE" },
209   { BSSGP_PDU_STATUS,                       "STATUS" },
210   { BSSGP_PDU_DOWNLOAD_BSS_PFC,             "DOWNLOAD-BSS-PFC" },
211   { BSSGP_PDU_CREATE_BSS_PFC,               "CREATE-BSS-PFC" },
212   { BSSGP_PDU_CREATE_BSS_PFC_ACK,           "CREATE-BSS-PFC-ACK" },
213   { BSSGP_PDU_CREATE_BSS_PFC_NACK,          "CREATE-BSS-PFC-NACK" },
214   { BSSGP_PDU_MODIFY_BSS_PFC,               "MODIFY-BSS-PFC" },
215   { BSSGP_PDU_MODIFY_BSS_PFC_ACK,           "MODIFY-BSS-PFC-ACK" },
216   { BSSGP_PDU_DELETE_BSS_PFC,               "DELETE-BSS-PFC" },
217   { BSSGP_PDU_DELETE_BSS_PFC_ACK,           "DELETE-BSS-PFC-ACK" },
218   { BSSGP_PDU_DELETE_BSS_PFC_REQ,           "DELETE-BSS-PFC-REQ" },
219   { BSSGP_PDU_PERFORM_LOCATION_REQUEST,     "PERFORM-LOCATION-REQUEST" },
220   { BSSGP_PDU_PERFORM_LOCATION_RESPONSE,    "PERFORM-LOCATION-RESPONSE" },
221   { BSSGP_PDU_PERFORM_LOCATION_ABORT,       "PERFORM-LOCATION-ABORT" },
222   { BSSGP_PDU_POSITION_COMMAND,             "POSITION-COMMAND" },
223   { BSSGP_PDU_POSITION_RESPONSE,            "POSITION-RESPONSE" },
224   { BSSGP_PDU_RAN_INFORMATION,              "RAN-INFORMATION" },
225   { BSSGP_PDU_RAN_INFORMATION_REQUEST,      "RAN-INFORMATION-REQUEST" },
226   { BSSGP_PDU_RAN_INFORMATION_ACK,          "RAN-INFORMATION-ACK" },
227   { BSSGP_PDU_RAN_INFORMATION_ERROR,        "RAN-INFORMATION-ERROR" },
228   { 0,                                NULL },
229 };
230
231 /* Information element coding, v 6.5.0, table 11.3, p 72 */
232 #define BSSGP_IEI_ALIGNMENT_OCTETS                         0x00
233 #define BSSGP_IEI_BMAX_DEFAULT_MS                          0x01              
234 #define BSSGP_IEI_BSS_AREA_INDICATION                      0x02
235 #define BSSGP_IEI_BUCKET_LEAK_RATE                         0x03
236 #define BSSGP_IEI_BVCI                                     0x04
237 #define BSSGP_IEI_BVC_BUCKET_SIZE                          0x05
238 #define BSSGP_IEI_BVC_MEASUREMENT                          0x06
239 #define BSSGP_IEI_CAUSE                                    0x07
240 #define BSSGP_IEI_CELL_IDENTIFIER                          0x08
241 #define BSSGP_IEI_CHANNEL_NEEDED                           0x09
242 #define BSSGP_IEI_DRX_PARAMETERS                           0x0a
243 #define BSSGP_IEI_EMLPP_PRIORITY                           0x0b
244 #define BSSGP_IEI_FLUSH_ACTION                             0x0c
245 #define BSSGP_IEI_IMSI                                     0x0d
246 #define BSSGP_IEI_LLC_PDU                                  0x0e
247 #define BSSGP_IEI_LLC_FRAMES_DISCARDED                     0x0f
248 #define BSSGP_IEI_LOCATION_AREA                            0x10
249 #define BSSGP_IEI_MOBILE_ID                                0x11
250 #define BSSGP_IEI_MS_BUCKET_SIZE                           0x12
251 #define BSSGP_IEI_MS_RADIO_ACCESS_CAPABILITY               0x13
252 #define BSSGP_IEI_OMC_ID                                   0x14
253 #define BSSGP_IEI_PDU_IN_ERROR                             0x15
254 #define BSSGP_IEI_PDU_LIFETIME                             0x16
255 #define BSSGP_IEI_PRIORITY                                 0x17
256 #define BSSGP_IEI_QOS_PROFILE                              0x18
257 #define BSSGP_IEI_RADIO_CAUSE                              0x19
258 #define BSSGP_IEI_RA_CAP_UPD_CAUSE                         0x1a
259 #define BSSGP_IEI_ROUTEING_AREA                            0x1b
260 #define BSSGP_IEI_R_DEFAULT_MS                             0x1c
261 #define BSSGP_IEI_SUSPEND_REFERENCE_NUMBER                 0x1d
262 #define BSSGP_IEI_TAG                                      0x1e
263 #define BSSGP_IEI_TLLI                                     0x1f
264 #define BSSGP_IEI_TMSI                                     0x20
265 #define BSSGP_IEI_TRACE_REFERENCE                          0x21
266 #define BSSGP_IEI_TRACE_TYPE                               0x22
267 #define BSSGP_IEI_TRANSACTION_ID                           0x23
268 #define BSSGP_IEI_TRIGGER_ID                               0x24
269 #define BSSGP_IEI_NUMBER_OF_OCTETS_AFFECTED                0x25
270 #define BSSGP_IEI_LSA_IDENTIFIER_LIST                      0x26
271 #define BSSGP_IEI_LSA_INFORMATION                          0x27
272 #define BSSGP_IEI_PFI                                      0x28
273 #define BSSGP_IEI_GPRS_TIMER                               0x29
274 #define BSSGP_IEI_ABQP                                     0x3a
275 #define BSSGP_IEI_FEATURE_BITMAP                           0x3b
276 #define BSSGP_IEI_BUCKET_FULL_RATIO                        0x3c
277 #define BSSGP_IEI_SERVICE_UTRAN_CCO                        0x3d
278 #define BSSGP_IEI_NSEI                                     0x3e
279 #define BSSGP_IEI_RRLP_APDU                                0x3f
280 #define BSSGP_IEI_LCS_QOS                                  0x40
281 #define BSSGP_IEI_LCS_CLIENT_TYPE                          0x41
282 #define BSSGP_IEI_REQUESTED_GPS_ASSISTANCE_DATA            0x42
283 #define BSSGP_IEI_LOCATION_TYPE                            0x43
284 #define BSSGP_IEI_LOCATION_ESTIMATE                        0x44
285 #define BSSGP_IEI_POSITIONING_DATA                         0x45
286 #define BSSGP_IEI_DECIPHERING_KEYS                         0x46
287 #define BSSGP_IEI_LCS_PRIORITY                             0x47
288 #define BSSGP_IEI_LCS_CAUSE                                0x48
289 #define BSSGP_IEI_LCS_CAPABILITY                           0x49
290 #define BSSGP_IEI_RRLP_FLAGS                               0x4a
291 #define BSSGP_IEI_RIM_APPLICATION_IDENTITY                 0x4b
292 #define BSSGP_IEI_RIM_SEQUENCE_NUMBER                      0x4c
293 #define BSSGP_IEI_RAN_INFORMATION_REQUEST_CONTAINER_UNIT   0x4d
294 #define BSSGP_IEI_RAN_INFORMATION_CONTAINER_UNIT           0x4e
295 #define BSSGP_IEI_RAN_INFORMATION_INDICATIONS              0x4f
296 #define BSSGP_IEI_NUMBER_OF_CONTAINER_UNITS                0x50
297 #define BSSGP_IEI_PFC_FLOW_CONTROL_PARAMETERS              0x52
298 #define BSSGP_IEI_GLOBAL_CN_ID                             0x53
299
300 static const value_string tab_bssgp_ie_types[] = {
301   { BSSGP_IEI_ALIGNMENT_OCTETS,            "Alignment Octets" },
302   { BSSGP_IEI_BMAX_DEFAULT_MS,             "Bmax Default MS" },
303   { BSSGP_IEI_BSS_AREA_INDICATION,         "BSS Area Indication" },
304   { BSSGP_IEI_BUCKET_LEAK_RATE,            "Bucket Leak Rate" },
305   { BSSGP_IEI_BVCI,                        "BVCI" },
306   { BSSGP_IEI_BVC_BUCKET_SIZE,             "BVC Bucket Size" },
307   { BSSGP_IEI_BVC_MEASUREMENT,             "BVC Measurement" },
308   { BSSGP_IEI_CAUSE,                       "Cause" },
309   { BSSGP_IEI_CELL_IDENTIFIER,             "Cell Identifier" },
310   { BSSGP_IEI_CHANNEL_NEEDED,              "Channel Needed" },
311   { BSSGP_IEI_DRX_PARAMETERS,              "DRX Parameters" },
312   { BSSGP_IEI_EMLPP_PRIORITY,              "eMLPP Priority" },
313   { BSSGP_IEI_FLUSH_ACTION,                "Flush Action" },
314   { BSSGP_IEI_IMSI,                        "IMSI" },
315   { BSSGP_IEI_LLC_PDU,                     "LLC PDU" },
316   { BSSGP_IEI_LLC_FRAMES_DISCARDED,        "LLC Frames Discarded" },
317   { BSSGP_IEI_LOCATION_AREA,               "Location Area" },
318   { BSSGP_IEI_MOBILE_ID,                   "Mobile Id" },
319   { BSSGP_IEI_MS_BUCKET_SIZE,              "MS Bucket Size" },
320   { BSSGP_IEI_MS_RADIO_ACCESS_CAPABILITY,  "MS Radio Access Capability" },
321   { BSSGP_IEI_OMC_ID,                      "OMC Id" },
322   { BSSGP_IEI_PDU_IN_ERROR,                "PDU In Error" },
323   { BSSGP_IEI_PDU_LIFETIME,                "PDU Lifetime" },
324   { BSSGP_IEI_PRIORITY,                    "Priority" },
325   { BSSGP_IEI_QOS_PROFILE,                 "QoS Profile" },
326   { BSSGP_IEI_RADIO_CAUSE,                 "Radio Cause" },
327   { BSSGP_IEI_RA_CAP_UPD_CAUSE,            "RA-Cap-UPD-Cause" },
328   { BSSGP_IEI_ROUTEING_AREA,               "Routeing Area" },
329   { BSSGP_IEI_R_DEFAULT_MS,                "R_default_MS" },
330   { BSSGP_IEI_SUSPEND_REFERENCE_NUMBER,    "Suspend Reference Number" },
331   { BSSGP_IEI_TAG,                         "Tag" },
332   { BSSGP_IEI_TLLI,                        "TLLI" },
333   { BSSGP_IEI_TMSI,                        "TMSI" },
334   { BSSGP_IEI_TRACE_REFERENCE,             "Trace Reference" },
335   { BSSGP_IEI_TRACE_TYPE,                  "Trace Type" },
336   { BSSGP_IEI_TRANSACTION_ID,              "Transaction Id" },
337   { BSSGP_IEI_TRIGGER_ID,                  "Trigger Id" },
338   { BSSGP_IEI_NUMBER_OF_OCTETS_AFFECTED,   "Number of Octets Affected" },
339   { BSSGP_IEI_LSA_IDENTIFIER_LIST,         "LSA Identifier List" },
340   { BSSGP_IEI_LSA_INFORMATION,             "LSA Information" },
341   { BSSGP_IEI_PFI,                         "Packet Flow Identiifer" },
342   { BSSGP_IEI_GPRS_TIMER,                  "GPRS Timer" },
343   { BSSGP_IEI_ABQP,                        "ABQP" },
344   { BSSGP_IEI_FEATURE_BITMAP,              "Feature Bitmap" },
345   { BSSGP_IEI_BUCKET_FULL_RATIO,           "Bucket Full Ratio" },
346   { BSSGP_IEI_SERVICE_UTRAN_CCO,           "Service UTRAN CCO" },
347   { BSSGP_IEI_NSEI,                        "NSEI" },
348   { BSSGP_IEI_RRLP_APDU,                   "RRLP APDU" },
349   { BSSGP_IEI_LCS_QOS,                     "LCS QoS" },
350   { BSSGP_IEI_LCS_CLIENT_TYPE,             "LCS Client Type" },
351   { BSSGP_IEI_REQUESTED_GPS_ASSISTANCE_DATA, "Requested GPS Assistance Data" },
352   { BSSGP_IEI_LOCATION_TYPE,               "Location Type" },
353   { BSSGP_IEI_LOCATION_ESTIMATE,           "Location Estimate" },
354   { BSSGP_IEI_POSITIONING_DATA,            "Positioning Data" },
355   { BSSGP_IEI_DECIPHERING_KEYS,            "Deciphering Keys" },
356   { BSSGP_IEI_LCS_PRIORITY,                "LCS Priority" },
357   { BSSGP_IEI_LCS_CAUSE,                   "LCS Cause" },
358   { BSSGP_IEI_LCS_CAPABILITY,              "LCS Capability" },
359   { BSSGP_IEI_RRLP_FLAGS,                  "RRLP Flags" },
360   { BSSGP_IEI_RIM_APPLICATION_IDENTITY,    "RIM Application Identity" },
361   { BSSGP_IEI_RIM_SEQUENCE_NUMBER,         "RIM Sequence Number" },
362   { BSSGP_IEI_RAN_INFORMATION_REQUEST_CONTAINER_UNIT, "RAN INFORMATION REQUEST Container Unit" },
363   { BSSGP_IEI_RAN_INFORMATION_CONTAINER_UNIT, "RAN INFORMATION Container Unit" },
364   { BSSGP_IEI_RAN_INFORMATION_INDICATIONS,  "RAN INFORMATION Indications" },
365   { BSSGP_IEI_NUMBER_OF_CONTAINER_UNITS,    "Number of Container Units" },
366   { BSSGP_IEI_PFC_FLOW_CONTROL_PARAMETERS,  "PFC Flow Control Parameters" },
367   { BSSGP_IEI_GLOBAL_CN_ID,                 "Global CN Id" }, 
368   { 0,                                NULL },
369 };
370
371 /* Presence requirements of Information Elements
372    48.016 v 5.3.0, chapter 8.1.1, p. 35 */
373 #define BSSGP_IE_PRESENCE_M 1   /* Mandatory */
374 #define BSSGP_IE_PRESENCE_O 2   /* Conditional */
375 #define BSSGP_IE_PRESENCE_C 3   /* Optional */
376
377 /* Format options */
378 #define BSSGP_IE_FORMAT_V 1
379 #define BSSGP_IE_FORMAT_TV 2
380 #define BSSGP_IE_FORMAT_TLV 3
381
382 typedef struct {
383   guint8        iei;
384   char         *name;
385   guint8        presence_req;
386   int           format;
387   guint16       value_length; /* in bytes (read from capture)*/
388   guint16       total_length; /* as specified, or 0 if unspecified */
389 } bssgp_ie_t;
390
391 typedef struct {
392   tvbuff_t     *tvb;
393   guint32       offset;
394   packet_info  *pinfo;
395   proto_tree   *bssgp_tree;
396   proto_tree   *parent_tree;
397   gboolean      dl_data;
398   gboolean      ul_data;
399 } build_info_t;
400
401 static guint8
402 get_masked_guint8(guint8 value, guint8 mask) {
403   const guint8 MASK_BIT_1 = 0x01; 
404   guint8 i = 0;
405   
406   while (!((mask >> i) & MASK_BIT_1)) {
407     i++;
408     if (i > 7) return 0; 
409   }
410   return (value & mask) >> i;
411 }
412
413 static guint8
414 tvb_get_masked_guint8(tvbuff_t *tvb, int offset, guint8 mask) {
415   guint8 value = tvb_get_guint8(tvb, offset);
416   return get_masked_guint8(value, mask);
417 }
418
419 static char*
420 get_bit_field_label(guint16 value, guint16 value_mask, guint16 num_bits) {
421 #define MAX_NUM_BITS 16
422   guint16 i, bit_mask;
423   static char label[MAX_NUM_BITS + 1];
424
425   g_assert(num_bits <= MAX_NUM_BITS);
426   for (i = 0; i < num_bits; i++) {
427     bit_mask = (guint16)pow(2, i);
428     if (value_mask & bit_mask) {
429       label[num_bits - 1 - i] = (value & bit_mask) ? '1' : '0';
430     }
431     else {
432       label[num_bits - 1 - i] = '.';
433     }
434   }
435 #undef MAX_NUM_BITS
436   return label;
437 }
438
439 static char*
440 get_bit_field_label8(guint8 value, guint8 value_mask) {
441   char *bits;
442   static char formatted_label[10];
443   bits = get_bit_field_label(value, value_mask, 8);
444   g_snprintf(formatted_label, 10, "%c%c%c%c %c%c%c%c",
445              bits[0], bits[1], bits[2], bits[3],
446              bits[4], bits[5], bits[6], bits[7]);
447   return formatted_label;  
448 }
449
450 static char*
451 get_bit_field_label16(guint16 value, guint16 value_mask) {
452   char *bits;
453   static char formatted_label[18];
454   bits = get_bit_field_label(value, value_mask, 16);
455   g_snprintf(formatted_label, 18, "%c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
456              bits[0], bits[1], bits[2], bits[3],
457              bits[4], bits[5], bits[6], bits[7],
458              bits[8], bits[9], bits[10], bits[11],
459              bits[12], bits[13], bits[14], bits[15]);
460   return formatted_label;  
461 }
462
463 static proto_item *
464 proto_tree_add_bitfield8(proto_tree *tree, tvbuff_t *tvb, int offset, guint8 mask) {
465   /* XXX: Use varargs */
466   guint8 value = tvb_get_guint8(tvb, offset);
467   char *label = get_bit_field_label8(value, mask);
468   proto_item *pi = proto_tree_add_text(tree, tvb, offset, 1, "%s = ",
469                                        label);
470   return pi;
471 }
472
473 #if 0
474 static proto_item *
475 proto_tree_add_bitfield16(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 mask) {
476   /* XXX: Use varargs */
477   guint16 value = tvb_get_ntohs(tvb, offset);
478   char *label = get_bit_field_label16(value, mask);
479   proto_item *pi = proto_tree_add_text(tree, tvb, offset, 2, "%s = ",
480                                        label);
481  return pi;
482 }
483 #endif
484
485 static guint8
486 get_byte_offset(guint64 bo) {
487   return (guint8) bo % 8;
488 }
489
490 static guint32
491 get_start_octet(guint64 bo) {
492   return (guint32) floor((gint64)bo / 8.0);
493 }
494
495 static guint32
496 get_end_octet(guint64 bo, guint32 bl) 
497 {
498   return (guint32) ceil((gint64)(bo + bl) / 8.0);
499 }
500
501 static guint32
502 get_num_octets_spanned(guint64 bo, guint32 bl) 
503 {
504   return get_end_octet(bo, bl) - get_start_octet(bo);
505 }
506
507 static gint16
508 make_mask(guint8 num_bits, guint8 shift_value) {
509   guint16 mask;
510
511   switch (num_bits) {
512   case 0: mask = 0x0000; break;
513   case 1: mask = 0x8000; break;
514   case 2: mask = 0xc000; break;
515   case 3: mask = 0xe000; break;
516   case 4: mask = 0xf000; break;
517   case 5: mask = 0xf800; break;
518   case 6: mask = 0xfc00; break;
519   case 7: mask = 0xfe00; break;
520   case 8: mask = 0xff00; break;
521   default: g_assert_not_reached(); mask = 0; break;
522   }
523   return mask >> shift_value;
524 }
525
526 static guint8
527 tvb_get_bits8(tvbuff_t *tvb, guint64 bo, guint8 num_bits) {
528   /* Returns 0-8 bits from tvb */
529   guint8 shift_value;
530   guint16 mask, data;
531   
532   shift_value = get_byte_offset(bo);
533   mask = make_mask(num_bits, shift_value);
534   data = tvb_get_ntohs(tvb, get_start_octet(bo));
535   return (data & mask) >> (16 - shift_value - num_bits);
536 }
537
538 proto_item *
539 bit_proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, 
540                         guint64 bo, guint8 bl, char *value) {
541   /* XXX: Use varargs */
542   return proto_tree_add_text(tree, tvb, get_start_octet(bo),
543                              get_num_octets_spanned(bo, bl), value);
544 }
545
546 proto_item *
547 bit_proto_tree_add_bit_field8(proto_tree *tree, tvbuff_t *tvb,
548                               guint64 bo, guint8 bl) {
549   /* XXX: Use varargs */
550   guint16 value = tvb_get_ntohs(tvb, get_start_octet(bo));
551   guint16 mask = make_mask(bl, get_byte_offset(bo));
552   char *label = get_bit_field_label16(value, mask);
553   guint8 end_i;
554   int i;
555   proto_item *pi;
556
557   g_assert(bl < 9);
558   
559   if (get_num_octets_spanned(bo, bl) == 1) {
560     end_i = 7;
561   }
562   else {
563     end_i = 16;
564   }
565   pi = bit_proto_tree_add_text(tree, tvb, bo, bl, "");
566
567   for (i = 0; i <=end_i; i++) {
568     proto_item_append_text(pi, "%c", label[i]);
569   }
570   proto_item_append_text(pi, " = ");
571   return pi;
572 }
573
574 static char*
575 translate_abqp_reliability_class(guint8 value, build_info_t *bi) {
576   switch (value) {
577   case 0: 
578     if (bi->ul_data) {
579       return "Subscribed reliability class";
580     }
581     else {
582       return "Reserved";
583     }
584   case 1: 
585     return "Unused (Unacknowledged GTP; Acknowledged LLc and RLC, Protected data)"; 
586   case 2: 
587     return "Unacknowledged GTP; Acknowledged LLc and RLC, Protected data"; 
588   case 3: 
589     return "Unacknowledged GTP and LLC; Acknowledged RLC, Protected data";
590   case 4: 
591     return "Unacknowledged GTP, LLC, and RLC, Protected data";
592   case 5:
593     return "Unacknowledged GTP, LLC, and RLC, Unprotedcted data";
594   case 7: 
595     return "Reserved";
596   default:
597     return "Unacknowledged GTP and LLC; Acknowledged RLC, Protected data"; 
598   };
599 }
600 static char*
601 translate_abqp_delay_class(guint8 value, build_info_t *bi) {
602   switch (value) {
603   case 0: 
604     if (bi->ul_data) {
605       return "Subscribed delay class";
606     }
607     else {
608       return "Reserved";
609     }
610   case 1: return "Delay class 1";
611   case 2: return "Delay class 2";
612   case 3: return "Delay class 3";
613   case 4: return "Delay class 4 (best effort)";
614   case 7: return "Reserved";
615   default:
616     return "Delay class 4 (best effort)";
617   };
618 }
619 static char*
620 translate_abqp_peak_throughput(guint8 value, build_info_t *bi) {
621   switch (value) {
622   case 0:
623     if (bi->ul_data) {
624       return "Subscribed peak throughput";
625     }
626     else {
627       return "Reserved";
628     }
629   case 1: return "Up to 1 000 octets/s";
630   case 2: return "Up to 2 000 octets/s";
631   case 3: return "Up to 4 000 octets/s";
632   case 4: return "Up to 8 000 octets/s";
633   case 5: return "Up to 16 000 octets/s";
634   case 6: return "Up to 32 000 octets/s";
635   case 7: return "Up to 64 000 octets/s";
636   case 8: return "Up to 128 000 octets/s";
637   case 9: return "Up to 256 000 octets/s";
638   case 15: return "Reserved";
639   default:
640     return "Up to 1 000 octets/s";
641   };
642 }
643 static char*
644 translate_abqp_precedence_class(guint8 value, build_info_t *bi) {
645   switch (value) {
646   case 0: 
647     if (bi->ul_data) {
648       return "Subscribed precedence";
649     }
650     else {
651       return "Reserved";
652     }
653   case 1: return "High priority";
654   case 2: return "Normal priority";
655   case 3: return "Low priority";
656   case 7: return "Reserved";
657   default:
658     return "Normal priority";
659   };
660 }
661 static char*
662 translate_abqp_mean_throughput(guint8 value, build_info_t *bi) {
663   switch (value) {
664   case 0:
665     if (bi->ul_data) {
666       return "Subscribed mean throughput";
667     }
668     else {
669       return "Reserved";
670     }
671   case 1: return "100 octets/h";
672   case 2: return "200 octets/h";
673   case 3: return "500 octets/h";
674   case 4: return "1 000 octets/h";
675   case 5: return "2 000 octets/h";
676   case 6: return "5 000 octets/h";
677   case 7: return "10 000 octets/h";
678   case 8: return "20 000 octets/h";
679   case 9: return "50 000 octets/h";
680   case 0x0a: return "100 000 octets/h";
681   case 0x0b: return "200 000 octets/h";
682   case 0x0c: return "500 000 octets/h";
683   case 0x0d: return "1 000 000 octets/h";
684   case 0x0e: return "2 000 000 octets/h";
685   case 0x0f: return "5 000 000 octets/h";
686   case 0x10: return "10 000 000 octets/h";
687   case 0x11: return "20 000 000 octets/h";
688   case 0x12: return "50 000 000 octets/h";
689   case 0x1e: return "Reserved";
690   case 0x1f: return "Best effort";
691   default:
692     return "Best effort";
693   };
694 }
695 static char*
696 translate_abqp_traffic_class(guint8 value, build_info_t *bi) {
697   switch (value) {
698   case 0:
699     if (bi->ul_data) {
700       return "Subscribed traffic class";
701     }
702     else {
703       return "Reserved";
704     }
705   case 1: return "Conversational class";
706   case 2: return "Streaming class";
707   case 3: return "Interactive class";
708   case 4: return "Background class";
709   case 7: return "Reserved";
710   default:
711     if (bi->ul_data) {
712       /* The MS shall consider all other values as reserved */
713       return "Reserved";
714     }
715     else {
716       /* The network shall map all other values not explicitly defined onto one of the values defined in this version of the protocol. The network shall return a negotiated value which is explicitly defined in this version of the protocol */
717       return "Error";
718     }
719
720   };
721 }
722 static char*
723 translate_abqp_delivery_order(guint8 value, build_info_t *bi) {
724   switch (value) {
725   case 0: 
726     if (bi->ul_data) {
727       return "Subscribed delivery order";
728     }
729     else {
730       return "Reserved";
731     }
732   case 1: return "With delivery order ('yes')";
733   case 2: return "Without delivery order ('no')";
734   case 3: return "Reserved";
735   default:
736     return "Error in BSSGP dissector";
737   };
738 }
739 static char*
740 translate_abqp_delivery_of_erroneous_sdu(guint8 value, build_info_t *bi) {
741   switch (value) {
742   case 0:
743     if (bi->ul_data) {
744       return "Subscribed delivery of erroneous SDUs";
745     }
746     else {
747       return "Reserved";
748     }
749   case 1: return "No detect ('-')";
750   case 2: return "Erroneous SDUs are delivered ('yes')";
751   case 3: return "Erroneous SDUs are not delivered ('no')";
752   case 7: return "Reserved";
753   default:
754     if (bi->ul_data) {
755       /* The MS shall consider all other values as reserved */
756       return "Reserved";
757     }
758     else {
759       /* The network shall map all other values not explicitly defined onto one of the values defined in this version of the protocol. The network shall return a negotiated value which is explicitly defined in this version of the protocol */
760       return "Error";
761     }
762   };
763 }
764 static char*
765 translate_abqp_max_sdu_size(guint8 value, build_info_t *bi) {
766   static char result[BSSGP_TRANSLATION_MAX_LEN];
767
768   switch (value) {
769   case 0:
770     if (bi->ul_data) {
771       return "Subscribed maximum SDU size";
772     }
773     else {
774       return "Reserved";
775     }
776   case 0xff:
777     if (bi->ul_data) {
778       return "Reserved";
779     }
780     else {
781       return "Reserved";
782     }
783   case 0x97: return "1502 octets";
784   case 0x98: return "1510 octets";
785   case 0x99: return "1520 octets";
786   }
787   if ((value >= 1) && (value <= 0x96)) {
788     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u octets", value * 10);
789     return result;
790   }
791   if (bi->ul_data) {
792     /* The MS shall consider all other values as reserved */
793     return "Reserved";
794   }
795   else {
796     /* The network shall map all other values not explicitly defined onto one of the values defined in this version of the protocol. The network shall return a negotiated value which is explicitly defined in this version of the protocol */
797     return "Error";
798   }
799 }  
800
801 static char*
802 translate_abqp_max_bit_rate_for_ul(guint8 value, build_info_t *bi) {
803   static char result[BSSGP_TRANSLATION_MAX_LEN];
804
805   if (value == 0) {
806     if (bi->ul_data) {
807       return "Subscribed maximum bit rate for uplink";
808     }
809     else {
810       return "Reserved";
811     }
812   };
813   if ((value >= 1) && (value <= 0x3f)) {
814     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", value);
815     return result;
816   }
817   if ((value >= 0x40) && (value <= 0x7f)) {
818     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", 64 + (value - 0x40) * 8);
819     return result;
820   }
821   if ((value >= 0x80) && (value <= 0xfe)) {
822     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", 576 + (value - 0x80) * 64);
823     return result;
824   }
825   return "0 kbps";
826 }
827
828 static char*
829 translate_abqp_max_bit_rate_for_dl(guint8 value, build_info_t *bi) {
830   return translate_abqp_max_bit_rate_for_ul(value, bi);
831 }
832
833 static char*
834 translate_abqp_residual_ber(guint8 value, build_info_t *bi) {
835   switch (value) {
836   case 0:
837     if (bi->ul_data) {
838       return "Subscribed residual BER";
839     }
840     else {
841       return "Reserved";
842     }
843   case 1: return "5*10^-2";
844   case 2: return "1*10^-2";
845   case 3: return "5*10^-3";
846   case 4: return "4*10^-3";
847   case 5: return "1*10^-3";
848   case 6: return "1*10^-4";
849   case 7: return "1*10^-5";
850   case 8: return "1*10^-6";
851   case 9: return "6*10^-8";
852   case 15: return "Reserved";
853   };
854   if (bi->ul_data) {
855     /* The MS shall consider all other values as reserved */
856     return "Reserved";
857   }
858   else {
859     /* The network shall map all other values not explicitly defined onto one of the values defined in this version of the protocol. The network shall return a negotiated value which is explicitly defined in this version of the protocol */
860     return "Error";
861   }
862 }
863
864 static char*
865 translate_abqp_sdu_error_ratio(guint8 value, build_info_t *bi) {
866   switch (value) {
867   case 0:
868     if (bi->ul_data) {
869       return "Subscribed SDU error ratio";
870     }
871     else {
872       return "Reserved";
873     }
874   case 1: return "1*10^-2";
875   case 2: return "7*10^-3";
876   case 3: return "1*10^-3";
877   case 4: return "1*10^-4";
878   case 5: return "1*10^-5";
879   case 6: return "1*10^-6";
880   case 7: return "1*10^-1";
881   case 15: return "Reserved";
882   };
883   if (bi->ul_data) {
884     /* The MS shall consider all other values as reserved */
885     return "Reserved";
886   }
887   else {
888     /* The network shall map all other values not explicitly defined onto one of the values defined in this version of the protocol. The network shall return a negotiated value which is explicitly defined in this version of the protocol */
889     return "";
890   }
891 }
892
893 static char*
894 translate_abqp_transfer_delay(guint8 value, build_info_t *bi) {
895   static char result[BSSGP_TRANSLATION_MAX_LEN];
896
897   if (value == 0) {
898     if (bi->ul_data) {
899       return "Subscribed transfer delay";
900     }
901     else {
902       return "Reserved";
903     }
904   }
905   if ((value >= 1) && (value <= 0x0f)) {
906     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u ms", value * 10);
907     return result;
908   }
909   if ((value >= 0x10) && (value <= 0x1f)) {
910     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u ms", 200 + (value - 0x10) * 50);
911     return result;
912   }
913   if ((value >= 0x20) && (value <= 0x3e)) {
914     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u ms", 1000 + (value - 0x20) * 100);
915     return result;
916   }
917   return "Reserved";
918 }
919
920 static char*
921 translate_abqp_traffic_handling_priority(guint8 value, build_info_t *bi) {
922   switch (value) {
923   case 0:
924     if (bi->ul_data) {
925       return "Subscribed traffic handling_priority";
926     }
927     else {
928       return "Reserved";
929     }
930   case 1: return "Priority level 1";
931   case 2: return "Priority level 2";
932   case 3: return "Priority level 3";
933   default: return "";
934   }
935 }
936
937 static char*
938 translate_abqp_guaranteed_bit_rate_for_ul(guint8 value, build_info_t *bi) {
939   return translate_abqp_max_bit_rate_for_ul(value, bi);
940 }
941 static char*
942 translate_abqp_guaranteed_bit_rate_for_dl(guint8 value, build_info_t *bi) {
943   return translate_abqp_max_bit_rate_for_ul(value, bi);
944 }
945
946 static char*
947 translate_abqp_source_statistics_descriptor(guint8 value, build_info_t *bi) {
948   if (bi->ul_data) {
949     switch (value) {
950     case 0: return "Unknown";
951     case 1: return "Speech";
952     default: return "Unknown";
953     }
954   }
955   else {
956     return "Spare";
957   }
958 }
959
960 static char*
961 translate_abqp_max_bit_rate_for_dl_extended(guint8 value, build_info_t *bi _U_) {
962   static char result[BSSGP_TRANSLATION_MAX_LEN];
963
964   if (value == 0) {
965     return "Use the value indicated by the Maximum bit rate for downlink";
966   }
967   if ((value >= 1) || (value <= 0x4a)) {
968     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", 8600 + value * 100);
969     return result;
970   }
971   /* The network shall map all other values not explicitly defined onto one of the values defined in this version of the protocol. The network shall return a negotiated value which is explicitly defined in this version of the protocol */
972   return "";
973 }
974
975 static char*
976 translate_abqp_guaranteed_bit_rate_for_dl_extended(guint8 value, build_info_t *bi _U_) {
977   static char result[BSSGP_TRANSLATION_MAX_LEN];
978
979   if (value == 0) {
980     return "Use the value indicated by the Guaranteed bit rate for downlink";
981   }
982   if ((value >= 1) || (value <= 0x4a)) {
983     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", 8600 + value * 100);
984     return result;
985   }
986   /* The network shall map all other values not explicitly defined onto one of the values defined in this version of the protocol. The network shall return a negotiated value which is explicitly defined in this version of the protocol */
987   return "";
988 }
989
990 static char*
991 translate_msrac_access_technology_type(guint8 value) {
992   value_string tab_values[] = {
993     { 0, "GSM P" },
994     { 1, "GSM E" },
995     { 2, "GSM R" },
996     { 3, "GSM 1800" },
997     { 4, "GSM 1900" },
998     { 5, "GSM 450" },
999     { 6, "GSM 480" },
1000     { 7, "GSM 850" },
1001     { 8, "GSM 700" },
1002     { 9, "GSM T 380" },
1003     { 10, "GSM T 410" },
1004     { 11, "GSM T 900" },
1005     { 15, "List of Additional Access Technologies present" },
1006     { 0, NULL },
1007     /* Otherwise "Unknown" */
1008   };
1009   return val_to_str(value, tab_values, "Unknown");
1010 }
1011
1012 static char*
1013 translate_msrac_dtm_gprs_multislot_class(guint8 value) {
1014  value_string tab_values[] = {
1015     { 0, "Unused, interpreted as ""Multislot class 5 supported""" },
1016     { 1, "Multislot class 5 supported" },
1017     { 2, "Multislot class 9 supported" },
1018     { 3, "Multislot class 11 supported" },
1019     { 0, NULL },
1020     /* No other combinations*/
1021   };
1022   return val_to_str(value, tab_values, "");
1023 }
1024
1025 static char*
1026 translate_msrac_extended_dtm_gprs_multislot_class(guint8 value, guint8 dgmsc) {
1027   switch (dgmsc) {
1028   case 0: return "Unused, interpreted as Multislot class 5 supported";
1029   case 1: 
1030     switch (value) {
1031     case 0: return "Multislot class 5 supported";
1032     case 1: return "Multislot class 6 supported";
1033     case 2: 
1034     case 3: 
1035       return "Unused, interpreted as Multislot class 5 supported";
1036     }
1037   case 2: 
1038     switch (value) {
1039     case 0: return "Multislot class 9 supported";
1040     case 1: return "Multislot class 10 supported";
1041     case 2: 
1042     case 3: 
1043       return "Unused, interpreted as Multislot class 5 supported";
1044     }
1045   case 3: 
1046     switch (value) {
1047     case 0: return "Multislot class 11 supported";
1048     case 1:
1049     case 2:
1050     case 3: 
1051       return "Unused, interpreted as Multislot class 5 supported";
1052     }
1053   }
1054   g_assert_not_reached();
1055   return "Error"; /* Dummy */
1056 }
1057
1058 #if 0
1059 static guint8
1060 translate_msrac_high_multislot_capability(guint8 capability, guint8 class) {
1061   switch (capability) {
1062   case 0:
1063     switch (class) {
1064     case 8: 
1065       return 30;
1066     case 10:
1067     case 23:
1068     case 28: 
1069     case 29: 
1070       return 39;
1071     case 11:
1072     case 20:
1073     case 25:
1074       return 32;
1075     case 12:
1076     case 21:
1077     case 22:
1078     case 26:
1079     case 27:
1080       return 33;
1081     default: 
1082       return class;
1083     }
1084   case 1:    
1085     switch (class) {
1086     case 8: 
1087       return 35;
1088     case 10:
1089     case 19:
1090     case 24:
1091       return 36;
1092     case 11:
1093     case 23:
1094     case 28:
1095     case 29:
1096       return 45;
1097     case 12:
1098     case 21:
1099     case 22:
1100     case 26:
1101     case 27:
1102       return 38;
1103     default: 
1104       return class;
1105     }
1106   case 2:
1107     switch (class) {
1108     case 8:
1109       return 40;
1110     case 10:
1111     case 19:
1112     case 24:
1113       return 41;
1114     case 11:
1115     case 20:
1116     case 25:
1117       return 42;
1118     case 12:
1119     case 23:
1120     case 28:
1121     case 29:
1122       return 44;
1123     default:
1124       return class;
1125     }
1126   case 3:
1127     switch (class) {
1128     case 12:
1129     case 21:
1130     case 22:
1131     case 26:
1132     case 27:
1133       return 43;
1134     case 11:
1135     case 20:
1136     case 25:
1137       return 37;
1138     case 10:
1139     case 19:
1140     case 24:
1141       return 31;
1142     case 9:
1143     case 23:
1144     case 28:
1145     case 29:
1146       return 34;
1147     default:
1148       return class;
1149     }
1150   }
1151   g_assert_not_reached();
1152   return 0;
1153 }
1154 #endif
1155
1156 static char*
1157 translate_channel_needed(guint8 value) {
1158   switch (value) {
1159   case 0: return "Any channel";
1160   case 1: return "SDCCH";
1161   case 2: return "TCH/F (Full rate)";
1162   case 3: return "TCH/H or TCH/F (Dual rate)";
1163   }
1164   g_assert_not_reached();
1165   return NULL;
1166 }
1167
1168 static proto_item* 
1169 bssgp_proto_tree_add_ie(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1170   return proto_tree_add_uint_format(bi->bssgp_tree, hf_bssgp_ie_type, 
1171                                   bi->tvb, ie_start_offset, ie->total_length, 
1172                                   ie->iei, ie->name);
1173 }
1174
1175 static void
1176 bssgp_proto_handoff(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset, dissector_handle_t handle) {
1177   tvbuff_t *next_tvb;
1178
1179   next_tvb = tvb_new_subset(bi->tvb, bi->offset, -1, -1);
1180
1181   if (bi->bssgp_tree) {
1182     bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1183   }
1184   if (handle) {
1185     call_dissector(handle, next_tvb, bi->pinfo, bi->parent_tree);    
1186   }
1187   else if (data_handle) {
1188     call_dissector(data_handle, next_tvb, bi->pinfo, bi->parent_tree);
1189   }
1190 }
1191
1192 static void
1193 decode_mobile_identity(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1194 #define MAX_NUM_IMSI_DIGITS 15
1195   const guint8 MASK_ODD_EVEN_INDICATION = 0x08;
1196   const guint8 MASK_TYPE_OF_IDENTITY = 0x07;
1197   const guint8 ODD = 1;
1198   proto_item *ti = NULL, *pi;
1199   proto_tree *tf = NULL;
1200   guint8 data, odd_even, type, num_digits, i;
1201   int hf_id;
1202   guint32 tmsi;
1203   guint8 digits[MAX_NUM_IMSI_DIGITS];
1204   char digits_str[MAX_NUM_IMSI_DIGITS + 1];
1205
1206   value_string tab_type_of_identity[] = {
1207     { BSSGP_MOBILE_IDENTITY_TYPE_IMSI, "IMSI" },
1208     { BSSGP_MOBILE_IDENTITY_TYPE_IMEI, "IMEI" },
1209     { BSSGP_MOBILE_IDENTITY_TYPE_IMEISV, "IMEISV" },
1210     { BSSGP_MOBILE_IDENTITY_TYPE_TMSI_PTMSI, "TMSI//P-TMSI" },
1211     { BSSGP_MOBILE_IDENTITY_TYPE_NO_IDENTITY, "No identity" },
1212     { 0, NULL },
1213     /* Otherwise "Reserved" */
1214   };
1215
1216   if (bi->bssgp_tree) {
1217     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1218     tf = proto_item_add_subtree(ti, ett_bssgp_mobile_identity);
1219   }
1220   data = tvb_get_guint8(bi->tvb, bi->offset);
1221   odd_even = get_masked_guint8(data, MASK_ODD_EVEN_INDICATION);
1222
1223   if (bi->bssgp_tree) {
1224     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
1225                                   MASK_ODD_EVEN_INDICATION);
1226     proto_item_append_text(pi, "Odd/Even Indication: %s number of identity digits%s",
1227                         odd_even == ODD ? "Odd" : "Even",
1228                         odd_even == ODD ? "" : " and also when the TMSI/P_TMSI is used");
1229   }
1230   type = get_masked_guint8(data, MASK_TYPE_OF_IDENTITY);
1231
1232   if (bi->bssgp_tree) {
1233     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
1234                                   MASK_TYPE_OF_IDENTITY);
1235     proto_item_append_text(pi, "Type of Identity: %s",
1236                            val_to_str(type, tab_type_of_identity, 
1237                                       "Reserved"));
1238   }
1239   bi->offset++;
1240   switch (type) {
1241   case BSSGP_MOBILE_IDENTITY_TYPE_IMSI:
1242   case BSSGP_MOBILE_IDENTITY_TYPE_IMEI:
1243   case BSSGP_MOBILE_IDENTITY_TYPE_IMEISV:
1244     num_digits = 1 + (ie->value_length - 1) * 2;
1245     if (odd_even != ODD ) num_digits--;
1246
1247     i = 0;
1248     digits[i] = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1249
1250     i++;
1251     while (TRUE) {
1252       data = tvb_get_guint8(bi->tvb, bi->offset);
1253
1254       digits[i] = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1255       i++;
1256       if (i >= num_digits) break;
1257
1258       digits[i] = get_masked_guint8(data, BSSGP_MASK_RIGHT_OCTET_HALF);
1259       i++;
1260       if (i >= num_digits) break;
1261       bi->offset++;
1262     }
1263     bi->offset++;
1264     
1265     if (bi->bssgp_tree) {
1266       proto_item_append_text(ti, ": ");
1267       for (i = 0; i < num_digits; i++) {
1268         proto_item_append_text(ti, "%u", digits[i]);
1269         g_snprintf(&digits_str[i], 2, "%u", digits[i]);
1270       }
1271       switch (type) {
1272       case BSSGP_MOBILE_IDENTITY_TYPE_IMSI:
1273         hf_id = hf_bssgp_imsi;
1274         break;
1275       case BSSGP_MOBILE_IDENTITY_TYPE_IMEI:
1276         hf_id = hf_bssgp_imei;
1277         break;
1278       case BSSGP_MOBILE_IDENTITY_TYPE_IMEISV:
1279         hf_id = hf_bssgp_imeisv;
1280         break;
1281       default:
1282         g_assert_not_reached();
1283         hf_id = -1;
1284         break;
1285       }
1286           if (tf)
1287                   proto_tree_add_string(tf, hf_id, bi->tvb, 0, num_digits, digits_str);
1288
1289     } 
1290     if (check_col(bi->pinfo->cinfo, COL_INFO)) {
1291       col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP, "%s %s", 
1292                           val_to_str(type, tab_type_of_identity, 
1293                                      "Mobile identity unknown"),
1294                           digits_str);
1295     }
1296     break;
1297   case BSSGP_MOBILE_IDENTITY_TYPE_TMSI_PTMSI:
1298     tmsi = tvb_get_ntohl(bi->tvb, bi->offset);
1299     if (bi->bssgp_tree) {
1300       proto_tree_add_item(tf, hf_bssgp_tmsi_ptmsi, bi->tvb, bi->offset, 4, 
1301                           BSSGP_LITTLE_ENDIAN);
1302       proto_item_append_text(ti, ": %#04x", tmsi);
1303     }
1304     bi->offset += 4;
1305
1306     if (check_col(bi->pinfo->cinfo, COL_INFO)) {
1307       col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP, 
1308                           "TMSI/P-TMSI %0x04x", tmsi);
1309     }
1310     return;
1311   default:
1312     ;    
1313   };
1314 #undef MAX_NUM_IMSI_DIGITS
1315 }
1316
1317 static char*
1318 decode_mcc_mnc(build_info_t *bi, proto_tree *parent_tree) {
1319 #define RES_LEN 15
1320   const guint8 UNUSED_MNC3 = 0x0f;
1321   proto_item *pi_mcc, *pi_mnc;
1322   guint8 mcc1, mcc2, mcc3, mnc1, mnc2, mnc3, data;
1323   guint16 start_offset, mcc, mnc;
1324   static char mcc_mnc[RES_LEN];
1325
1326   start_offset = bi->offset;
1327
1328   pi_mcc = proto_tree_add_text(parent_tree, bi->tvb, bi->offset, 3, "MCC");
1329   pi_mnc = proto_tree_add_text(parent_tree, bi->tvb, bi->offset, 3, "MNC");
1330
1331   data = tvb_get_guint8(bi->tvb, bi->offset);
1332   mcc2 = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1333   mcc1 = get_masked_guint8(data, BSSGP_MASK_RIGHT_OCTET_HALF);
1334   bi->offset++;
1335   
1336   data = tvb_get_guint8(bi->tvb, bi->offset);
1337   mnc3 = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1338   mcc3 = get_masked_guint8(data, BSSGP_MASK_RIGHT_OCTET_HALF);
1339   bi->offset++;
1340
1341   data = tvb_get_guint8(bi->tvb, bi->offset);
1342   mnc2 = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1343   mnc1 = get_masked_guint8(data, BSSGP_MASK_RIGHT_OCTET_HALF);
1344   bi->offset++;
1345
1346   /* XXX: If mxci out of range the ms should transmit the values using full hexademical encoding? */
1347
1348   /* XXX: Interpretation of mcci? */
1349   mcc = 100 * mcc1 + 10 * mcc2 + mcc3;
1350
1351   /* XXX: Interpretation of mnci? */
1352   mnc = 10 * mnc1 + mnc2;
1353  
1354   if (mnc3 != UNUSED_MNC3) {
1355     mnc += 10 * mnc + mnc3;
1356   }
1357
1358   proto_tree_add_uint_hidden(bi->bssgp_tree, hf_bssgp_mcc, 
1359                              bi->tvb, start_offset, 3, mcc);
1360   proto_tree_add_uint_hidden(bi->bssgp_tree, hf_bssgp_mnc, 
1361                              bi->tvb, start_offset, 3, mnc);
1362
1363   proto_item_append_text(pi_mcc, ": %03u", mcc);
1364
1365   if (mnc3 != UNUSED_MNC3) {
1366     /* Three digits mnc */
1367     proto_item_append_text(pi_mnc, ": %03u", mnc);
1368     g_snprintf(mcc_mnc, RES_LEN, "%u-%03u", mcc, mnc);
1369   }
1370   else {
1371     /* Two digits mnc */
1372     proto_item_append_text(pi_mnc, ": %02u", mnc);
1373     g_snprintf(mcc_mnc, RES_LEN, "%u-%02u", mcc, mnc);
1374   }
1375 #undef RES_LEN
1376   return mcc_mnc;
1377 }
1378
1379 static char*
1380 decode_lai(build_info_t *bi, proto_tree *parent_tree) {
1381 #define RES_LEN 15
1382   guint16 lac;
1383   char *mcc_mnc;
1384   static char lai[RES_LEN];
1385   
1386   mcc_mnc = decode_mcc_mnc(bi, parent_tree);
1387
1388   lac = tvb_get_ntohs(bi->tvb, bi->offset);
1389   proto_tree_add_item(parent_tree, hf_bssgp_lac, 
1390                       bi->tvb, bi->offset, 2, BSSGP_LITTLE_ENDIAN);
1391   bi->offset += 2;
1392
1393   g_snprintf(lai, RES_LEN, "%s-%u", mcc_mnc, lac);
1394 #undef RES_LEN
1395   return lai;
1396 }
1397
1398 static char*
1399 decode_rai(build_info_t *bi, proto_tree *parent_tree) {
1400 #define RES_LEN 20
1401   guint8 rac;
1402   static char rai[RES_LEN];
1403   char *lai = decode_lai(bi, parent_tree);  
1404  
1405   rac = tvb_get_guint8(bi->tvb, bi->offset);
1406   proto_tree_add_item(parent_tree, hf_bssgp_rac, bi->tvb, bi->offset, 1, BSSGP_LITTLE_ENDIAN);
1407   bi->offset++;
1408
1409   g_snprintf(rai, RES_LEN, "%s-%u", lai, rac);
1410 #undef RES_LEN
1411   return rai;
1412 }
1413
1414 static char*
1415 decode_rai_ci(build_info_t *bi, proto_tree *parent_tree) {
1416 #define RES_LEN 30
1417   char *rai;
1418   static char rai_ci[RES_LEN];
1419   guint16 ci;
1420
1421   rai = decode_rai(bi, parent_tree);
1422
1423   ci = tvb_get_ntohs(bi->tvb, bi->offset);
1424   proto_tree_add_item(parent_tree, hf_bssgp_ci, 
1425                       bi->tvb, bi->offset, 2, BSSGP_LITTLE_ENDIAN);
1426   bi->offset += 2;
1427
1428   g_snprintf(rai_ci, RES_LEN, "RAI %s, CI %u", rai, ci);
1429 #undef RES_LEN
1430   return rai_ci;
1431 }
1432
1433 static void
1434 bssgp_pi_append_queuing_delay(proto_item *pi, tvbuff_t *tvb, int offset) {
1435   const guint16 INFINITE_DELAY = 0xffff;
1436   guint16 value = tvb_get_ntohs(tvb, offset);
1437   if (value == INFINITE_DELAY) {
1438     proto_item_append_text(pi, ": Infinite delay (%#4x)", value);
1439   }
1440   else {
1441     proto_item_append_text(pi, ": %u centi-seconds delay", value);
1442   }
1443 }
1444
1445 static void 
1446 bssgp_pi_append_bucket_leak_rate(proto_item *pi, tvbuff_t *tvb, int offset) {
1447   guint16 value = tvb_get_ntohs(tvb, offset);
1448   proto_item_append_text(pi, ": %u bytes", value * 100);
1449 }
1450
1451 static void 
1452 bssgp_pi_append_bucket_size(proto_item *pi, tvbuff_t *tvb, int offset) {
1453   guint16 value = tvb_get_ntohs(tvb, offset);
1454   proto_item_append_text(pi, ": %u bytes", value * 100);
1455 }
1456
1457 static void 
1458 bssgp_pi_append_bucket_full_ratio(proto_item *pi, tvbuff_t *tvb, int offset) {
1459   guint8 value = tvb_get_guint8(tvb, offset);
1460   proto_item_append_text(pi, ": %.2f * Bmax ", value / 100.0);
1461 }
1462
1463 static void
1464 bssgp_pi_append_pfi(proto_item *pi, tvbuff_t *tvb, int offset) {
1465   const guint8 MASK_PFI = 0x7f;
1466   guint8 value;
1467
1468   value_string tab_pfi[] = {
1469     { 0, "Best effort" },
1470     { 1, "Signaling" },
1471     { 2, "SMS" },
1472     { 3, "TOMB" },
1473     { 4, "Reserved" },
1474     { 5, "Reserved" },
1475     { 6, "Reserved" },
1476     { 7, "Reserved" },
1477     { 0, NULL },
1478     /* Otherwise "Dynamically assigned */
1479   };
1480   value = tvb_get_masked_guint8(tvb, offset, MASK_PFI);
1481   proto_item_append_text(pi, 
1482                          val_to_str(value, tab_pfi, "Dynamically assigned"));
1483 }
1484
1485 static void 
1486 decode_pfi(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1487   proto_item *ti;
1488   if (bi->bssgp_tree) {
1489     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1490     bssgp_pi_append_pfi(ti, bi->tvb, bi->offset);
1491   }
1492   bi->offset += ie->value_length;
1493 }
1494
1495 static void
1496 decode_queuing_delay(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1497   proto_item *ti;
1498   if (bi->bssgp_tree) {
1499     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1500     bssgp_pi_append_queuing_delay(ti, bi->tvb, bi->offset);
1501   }
1502   bi->offset += ie->value_length;
1503 }
1504
1505 static void 
1506 decode_bucket_size(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1507   proto_item *ti;
1508   if (bi->bssgp_tree) {
1509     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1510     bssgp_pi_append_bucket_size(ti, bi->tvb, bi->offset);
1511   }
1512   bi->offset += ie->value_length;
1513 }
1514
1515 static void 
1516 decode_bucket_leak_rate(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1517   proto_item *ti;
1518   if (bi->bssgp_tree) {
1519     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1520     bssgp_pi_append_bucket_leak_rate(ti, bi->tvb, bi->offset);
1521   }
1522   bi->offset += ie->value_length;
1523 }
1524
1525 static void 
1526 get_value_length(bssgp_ie_t *ie, build_info_t *bi) {
1527   /* length indicator in bit 8, 0 => two bytes, 1 => one byte */
1528   const guint8 MASK_LENGTH_INDICATOR = 0x80;
1529   const guint8 MASK_ONE_BYTE_LENGTH = 0x7f;
1530   guint8 length_len;
1531   guint16 length;
1532   
1533   length = tvb_get_guint8(bi->tvb, bi->offset);
1534   length_len = 1;
1535   
1536   if (length & MASK_LENGTH_INDICATOR) {
1537     length &= MASK_ONE_BYTE_LENGTH;
1538   }
1539   else {
1540     length_len++;
1541     length <<= 8;
1542     length |= tvb_get_guint8(bi->tvb, bi->offset);
1543   }
1544   ie->value_length = length;
1545   ie->total_length += length_len + length;
1546   bi->offset += length_len;
1547 }
1548
1549 static void
1550 decode_simple_ie(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset, 
1551                  char *pre_str, char *post_str, 
1552                  gboolean show_as_dec) {
1553   /* XXX: Allow mask? */
1554   proto_item *ti;
1555   guint32 value;
1556
1557   switch (ie->value_length) {
1558   case 1: value = tvb_get_guint8(bi->tvb, bi->offset); break;
1559   case 2: value = tvb_get_ntohs(bi->tvb, bi->offset); break;
1560   case 3: value = tvb_get_ntoh24(bi->tvb, bi->offset); break;
1561   case 4: value = tvb_get_ntohl(bi->tvb, bi->offset); break;
1562   default: value = 0; break;
1563   }
1564
1565   if (bi->bssgp_tree) {
1566     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1567     
1568     proto_item_append_text(ti, ": ");
1569     
1570     if (pre_str) {
1571       proto_item_append_text(ti, "%s ", pre_str);
1572     }
1573     if (show_as_dec) {
1574       proto_item_append_text(ti, "%u", value);
1575     }
1576     else {
1577       switch (ie->value_length) {
1578       case 1: proto_item_append_text(ti, "%#1x", value); break;
1579       case 2: proto_item_append_text(ti, "%#2x", value); break;
1580       case 3: proto_item_append_text(ti, "%#3x", value); break;
1581       case 4: proto_item_append_text(ti, "%#4x", value); break;
1582       default: ;
1583       }
1584     }
1585     proto_item_append_text(ti, " %s", post_str);
1586   }
1587   bi->offset += ie->value_length;
1588 }
1589
1590 static int 
1591 check_correct_iei(bssgp_ie_t *ie, build_info_t *bi) {
1592   guint8 fetched_iei = tvb_get_guint8(bi->tvb, bi->offset);
1593
1594 #ifdef BSSGP_DEBUG
1595   if (fetched_iei != ie->iei) {
1596   proto_tree_add_text(bi->bssgp_tree, bi->tvb, bi->offset, 1, 
1597                         "Tried IEI %s (%#02x), found IEI %s (%#02x)", 
1598                         val_to_str(ie->iei, tab_bssgp_ie_types, "Unknown"), 
1599                         ie->iei, 
1600                         val_to_str(fetched_iei, tab_bssgp_ie_types, "Unknown"), 
1601                         fetched_iei);
1602   }
1603 #endif
1604   return (fetched_iei == ie->iei);
1605 }
1606
1607 static void 
1608 decode_iei_alignment_octets(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1609   proto_item *ti;
1610   if (bi->bssgp_tree) {
1611     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1612     proto_item_append_text(ti, " (%u bytes)", ie->value_length);
1613   }  
1614   bi->offset += ie->value_length;
1615 }
1616
1617 static void 
1618 decode_iei_bvci(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1619   proto_item *ti;
1620   guint16 bvci;
1621
1622   bvci = tvb_get_ntohs(bi->tvb, bi->offset);
1623
1624   if (bi->bssgp_tree) {
1625     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1626     proto_item_append_text(ti, ": %u", bvci);
1627     proto_tree_add_item_hidden(bi->bssgp_tree, hf_bssgp_bvci, 
1628                                bi->tvb, bi->offset, ie->value_length, 
1629                                BSSGP_LITTLE_ENDIAN);
1630   }
1631   bi->offset += ie->value_length;
1632
1633   if (check_col(bi->pinfo->cinfo, COL_INFO)) {
1634     col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP, 
1635                         "BVCI %u", bvci);
1636   }
1637 }
1638
1639 static void 
1640 decode_iei_cause(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1641   proto_item *ti;
1642   guint8 value;
1643
1644   value_string tab_cause[] = {
1645     { 0x00, "Processor overload" },
1646     { 0x01, "Equipment failure" },
1647     { 0x02, "Transit network service failure" },
1648     { 0x03, "Network service transmission capacity modified from zero kbps to greater than zero kbps" },
1649     { 0x04, "Unknown MS" },
1650     { 0x05, "BVCI unknown" },
1651     { 0x06, "Cell traffic congestion" },
1652     { 0x07, "SGSN congestion" },
1653     { 0x08, "O&M intervention" },
1654     { 0x09, "BVCI blocked" },
1655     { 0x0a, "PFC create failure" },
1656     { 0x0b, "PFC preempted" },
1657     { 0x0c, "ABQP no more supported" },
1658     { 0x20, "Semantically incorrect PDU" },
1659     { 0x21, "Invalid mandatory information" },
1660     { 0x22, "Missing mandatory IE" },
1661     { 0x23, "Missing conditional IE" },
1662     { 0x24, "Unexpected conditional IE" },
1663     { 0x25, "Conditional IE error" },
1664     { 0x26, "PDU not compatible with the protocol state" },
1665     { 0x27, "Protocol error - unspecified" },
1666     { 0x28, "PDU not compatible with the feature set" },
1667     { 0x29, "Requested information not available" },
1668     { 0x2a, "Unknown destination address" },
1669     { 0x2b, "Unknown RIM application identity" },
1670     { 0x2c, "Invalid container unit information" },
1671     { 0x2d, "PFC queing" },
1672     { 0x2e, "PFC created successfully" },
1673     { 0,    NULL },
1674   };
1675
1676   if (bi->bssgp_tree) {
1677     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1678     value = tvb_get_guint8(bi->tvb, bi->offset);
1679     proto_item_append_text(ti, ": %s (%#02x)", 
1680                            val_to_str(value, tab_cause, 
1681                                       "Protocol error - unspecified"),
1682                            value);
1683   }
1684   bi->offset += ie->value_length;
1685 }
1686
1687 static void 
1688 decode_iei_cell_identifier(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1689   proto_item *ti;
1690   proto_tree *tf;
1691   char *rai_ci;
1692
1693   if (bi->bssgp_tree) {
1694     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1695     tf = proto_item_add_subtree(ti, ett_bssgp_cell_identifier);
1696     
1697     rai_ci = decode_rai_ci(bi, tf);
1698     proto_item_append_text(ti, ": %s", rai_ci);
1699   }else{
1700   bi->offset += ie->value_length;
1701   }
1702 }
1703
1704 static void 
1705 decode_iei_channel_needed(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1706   /* XXX: 'If this IE is used for only one MS, the the first CHANNEL field 
1707      is used and the second CHANNEL field is spare.' How know? */
1708   const guint8 MASK_CH1 = 0x03;
1709   const guint8 MASK_CH2 = 0x0c;
1710   proto_item *ti;
1711   guint8 data, ch1, ch2;
1712   
1713   if (bi->bssgp_tree) {
1714     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1715     data = tvb_get_guint8(bi->tvb, bi->offset);
1716     ch1 = get_masked_guint8(data, MASK_CH1);
1717     ch2 = get_masked_guint8(data, MASK_CH2);
1718     proto_item_append_text(ti, ": Ch1: %s (%u), Ch2: %s (%u)", 
1719                            translate_channel_needed(ch1),
1720                            ch1,
1721                            translate_channel_needed(ch2),
1722                            ch2);
1723   }
1724   bi->offset += ie->value_length;
1725 }
1726
1727 static void 
1728 decode_iei_drx_parameters(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1729   const guint8 MASK_CYCLE_LENGTH_COEFFICIENT = 0xf0;
1730   const guint8 MASK_SPLIT_ON_CCCH = 0x08;
1731   const guint8 MASK_NON_DRX_TIMER = 0x07;
1732   proto_item *ti, *pi;
1733   proto_tree *tf;
1734   guint8 data, value;
1735   guint16 cycle_value;
1736
1737   value_string tab_non_drx_timer[] = {
1738     { 0, "No non-DRX mode after transfer state" },
1739     { 1, "Max. 1 sec non-DRX mode after transfer state" },
1740     { 2, "Max. 2 sec non-DRX mode after transfer state" },
1741     { 3, "Max. 4 sec non-DRX mode after transfer state" },
1742     { 4, "Max. 8 sec non-DRX mode after transfer state" },
1743     { 5, "Max. 16 sec non-DRX mode after transfer state" },
1744     { 6, "Max. 32 sec non-DRX mode after transfer state" },
1745     { 7, "Max. 64 sec non-DRX mode after transfer state" },
1746     { 0, NULL},
1747     /* Otherwise "" */
1748   };
1749
1750   value_string tab_cycle_length_coefficient[] = {
1751     { 0, "CN Specific DRX cycle length coefficient not specified by the MS, ie. the system information value 'CN domain specific DRX cycle length' is used" },
1752     { 6, "CN Specific DRX cycle length coefficient 6" },
1753     { 7, "CN Specific DRX cycle length coefficient 7" },
1754     { 8, "CN Specific DRX cycle length coefficient 8" },
1755     { 9, "CN Specific DRX cycle length coefficient 9" },
1756     { 0, NULL },
1757     /* Otherwise "CN Specific DRX cycle length coefficient not specified by the MS" */
1758   };
1759
1760   if (!bi->bssgp_tree) {
1761     bi->offset += ie->value_length;
1762     return;
1763   }
1764   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1765   tf = proto_item_add_subtree(ti, ett_bssgp_drx_parameters);
1766
1767   value = tvb_get_guint8(bi->tvb, bi->offset);
1768   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, 
1769                       "SPLIT PG CYCLE: code %u", value);
1770   if ((value >= 1) && (value <= 64)) {
1771     cycle_value = value;
1772   }
1773   else {
1774     switch (value) {
1775     case 0: cycle_value = 704;
1776     case 65: cycle_value = 71; break;
1777     case 66: cycle_value = 72; break;
1778     case 67: cycle_value = 74; break;
1779     case 68: cycle_value = 75; break;
1780     case 69: cycle_value = 77; break;
1781     case 70: cycle_value = 79; break;
1782     case 71: cycle_value = 80; break;
1783     case 72: cycle_value = 83; break;
1784     case 73: cycle_value = 86; break;
1785     case 74: cycle_value = 88; break;
1786     case 75: cycle_value = 90; break;
1787     case 76: cycle_value = 92; break;
1788     case 77: cycle_value = 96; break;
1789     case 78: cycle_value = 101; break;
1790     case 79: cycle_value = 103; break;
1791     case 80: cycle_value = 107; break;
1792     case 81: cycle_value = 112; break;
1793     case 82: cycle_value = 116; break;
1794     case 83: cycle_value = 118; break;
1795     case 84: cycle_value = 128; break;
1796     case 85: cycle_value = 141; break;
1797     case 86: cycle_value = 144; break;
1798     case 87: cycle_value = 150; break;
1799     case 88: cycle_value = 160; break;
1800     case 89: cycle_value = 171; break;
1801     case 90: cycle_value = 176; break;
1802     case 91: cycle_value = 192; break;
1803     case 92: cycle_value = 214; break;
1804     case 93: cycle_value = 224; break;
1805     case 94: cycle_value = 235; break;
1806     case 95: cycle_value = 256; break;
1807     case 96: cycle_value = 288; break;
1808     case 97: cycle_value = 320; break;
1809     case 98: cycle_value = 352; break;
1810     default:
1811       cycle_value = 1;
1812     }
1813     proto_item_append_text(ti, " => value %u", cycle_value);
1814     if (cycle_value == 704) {
1815       proto_item_append_text(ti, " (equivalent to no DRX)");
1816     }
1817   }
1818   bi->offset++;
1819
1820   data = tvb_get_guint8(bi->tvb, bi->offset);
1821
1822   value = get_masked_guint8(data, MASK_CYCLE_LENGTH_COEFFICIENT);
1823   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
1824                                 MASK_CYCLE_LENGTH_COEFFICIENT);
1825   proto_item_append_text(pi, "CN specific DRX cycle length coefficient: %s (%#02x)",
1826                          val_to_str(value, tab_cycle_length_coefficient,
1827                                     "Not specified by the MS"),
1828                          value);
1829
1830   value = get_masked_guint8(data, MASK_SPLIT_ON_CCCH);
1831   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_SPLIT_ON_CCCH);
1832   proto_item_append_text(pi, "SPLIT on CCCH: Split pg cycle on CCCH is%s supported by the mobile station",
1833                          value == 0 ? " not" : "");
1834   
1835   value = get_masked_guint8(data, MASK_NON_DRX_TIMER);
1836   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_NON_DRX_TIMER);
1837   proto_item_append_text(pi, "Non-DRX Timer: %s (%#x)",
1838                          val_to_str(value, tab_non_drx_timer, ""), value);
1839   bi->offset++;
1840 }
1841
1842 static void 
1843 decode_iei_emlpp_priority(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1844   const guint8 MASK_CALL_PRIORITY = 0x07;
1845   proto_item *ti;
1846   guint8 data, value;
1847
1848   value_string tab_call_priority[] = {
1849     { 0, "No priority applied" },
1850     { 1, "Call priority level 4" },
1851     { 2, "Call priority level 3" },
1852     { 3, "Call priority level 2" },
1853     { 4, "Call priority level 1" },
1854     { 5, "Call priority level 0" },
1855     { 6, "Call priority level B" },
1856     { 7, "Call priority level A" },
1857     { 0, NULL },
1858   };
1859
1860   if (bi->bssgp_tree) {
1861     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1862     data = tvb_get_guint8(bi->tvb, bi->offset);
1863     value = get_masked_guint8(data, MASK_CALL_PRIORITY);
1864     proto_item_append_text(ti, ": %s", 
1865                            val_to_str(value, tab_call_priority, ""));
1866   }
1867   bi->offset += ie->value_length;
1868 }
1869
1870 static void 
1871 decode_iei_flush_action(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1872   proto_item *ti;
1873   guint8 value;
1874
1875   value_string tab_action_value[] = {
1876     { 0x00, "LLC-PDU(s) deleted" },
1877     { 0x01, "LLC-PDU(s) transferred" },
1878     { 0,    NULL },
1879     /* Otherwise "Reserved" */
1880   };
1881
1882   if (bi->bssgp_tree) {
1883     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1884     value = tvb_get_guint8(bi->tvb, bi->offset);
1885     proto_item_append_text(ti, ": %s (%u)",
1886                            val_to_str(value, tab_action_value, "Reserved"),
1887                            value);
1888
1889   }
1890   bi->offset += ie->value_length;
1891 }
1892
1893 static void 
1894 decode_iei_llc_frames_discarded(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1895   decode_simple_ie(ie, bi, ie_start_offset, "", " frames discarded", TRUE);
1896 }
1897
1898 static void 
1899 decode_iei_location_area(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1900   proto_item *ti;
1901   proto_tree *tf;
1902   char *lai;
1903
1904   if (!bi->bssgp_tree) {
1905     bi->offset += ie->value_length;
1906     return;
1907   }
1908   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1909   tf = proto_item_add_subtree(ti, ett_bssgp_location_area);
1910
1911   lai = decode_rai(bi, tf);
1912   proto_item_append_text(ti, ": LAI %s", lai);
1913 }
1914
1915 static void
1916 decode_msrac_additional_access_technologies(proto_tree *tree, tvbuff_t *tvb, 
1917                                             guint64 bo, guint32 length _U_) {
1918   proto_item *pi;
1919   guint8 value;
1920   guint8 bl; /* Bit length */
1921
1922   bl = 4;
1923   value = tvb_get_bits8(tvb, bo, bl);
1924   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
1925   bo += bl;
1926   proto_item_append_text(pi, "Access Technology Type: %s (%#01x)", 
1927                          translate_msrac_access_technology_type(value), 
1928                          value);
1929
1930   bl = 3;
1931   value = tvb_get_bits8(tvb, bo, bl);
1932   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
1933   bo += bl;
1934   proto_item_append_text(pi, "GMSK Power Class: Power class %u", value);
1935
1936   bl = 2;
1937   value = tvb_get_bits8(tvb, bo, bl);
1938   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
1939   bo += bl;
1940   proto_item_append_text(pi, "8PSK Power Class");
1941   if (value == 0) {
1942     proto_item_append_text(pi, ": 8PSK modulation not supported for uplink");
1943   }
1944   else{
1945     proto_item_append_text(pi, ": Power Class E%u", value);
1946   }
1947 }
1948
1949 static gboolean
1950 struct_bits_exist(guint64 start_bo, guint32 struct_length, 
1951                   guint64 bo, guint32 num_bits) {
1952   return (bo + num_bits) <= (start_bo + struct_length);
1953
1954 }
1955
1956 static void 
1957 decode_msrac_access_capabilities(proto_tree *tree, tvbuff_t *tvb,
1958                                  guint64 bo, guint32 struct_length) {
1959   /* Error handling:
1960      - Struct too short: assume features do not exist
1961      - Struct too long: ignore data and jump to next Access Technology */
1962   proto_item *ti, *pi;
1963   proto_tree *tf;
1964   guint8 value, i;
1965   guint8 dgmsc = 0, demsc = 0; /* DTM GPRS/EGPRS Multi Slot Class */
1966   guint8 bl; /* Bit length */
1967   guint64 start_bo = bo;
1968
1969   /* RF Power Capability */
1970   bl = 3;
1971   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
1972   value = tvb_get_bits8(tvb, bo, bl);
1973   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
1974   bo += bl;
1975   proto_item_append_text(pi, "RF Power Capability");
1976   if (value == 0) {
1977     proto_item_append_text(pi, ": The MS does not support any GSM access technology type");
1978   }
1979   else {
1980     proto_item_append_text(pi, ": GMSK Power Class %u", value);
1981   }
1982
1983   /* A5 bits */
1984   bl = 1;
1985   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
1986   value = tvb_get_bits8(tvb, bo, bl);
1987   if (value == 1) {
1988     bo += bl;
1989     bl = 7;
1990     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
1991     value = tvb_get_bits8(tvb, bo, bl);
1992     ti = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
1993     proto_item_append_text(ti, "A5 Bits: %#02x", value); 
1994     tf = proto_item_add_subtree(ti, ett_bssgp_msrac_a5_bits);
1995     for (i = 0; i < bl; i++) {
1996       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo + i, 1);
1997       proto_item_append_text(pi, "Encryption algorithm A5/%u%s available",
1998                              i + 1,
1999                              value & (0x40 >> i) ? "" : " not");
2000     }
2001     bo += bl;
2002   }
2003   else {
2004     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2005     bo += bl;
2006     proto_item_append_text(pi, "A5 bits: Same as in the immediately preceding Access capabilities field within this IE"); 
2007   }
2008
2009   /* ES IND */
2010   bl = 1;
2011   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2012   value = tvb_get_bits8(tvb, bo, bl);
2013   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2014   bo += bl;
2015   proto_item_append_text(pi, "ESD IND: Controlled Early Classmark Sending"" option is%s implemented",
2016                          value == 0 ? " not" : "");
2017
2018   /* PS */
2019   bl = 1;
2020   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2021   value = tvb_get_bits8(tvb, bo, bl);
2022   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2023   bo += bl;
2024   proto_item_append_text(pi, "PS: PS capability%s present",
2025                          value == 0 ? " not" : "");
2026
2027   /* VGCS */
2028   bl = 1;
2029   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2030   value = tvb_get_bits8(tvb, bo, bl);
2031   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2032   bo += bl;
2033   proto_item_append_text(pi, "VBCS:%s VGCS capability %s notifications wanted",
2034                          value == 0 ? " No" : "",
2035                          value == 0 ? "or no" : "and");
2036
2037   /* VBS */
2038   bl = 1;
2039   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2040   value = tvb_get_bits8(tvb, bo, bl);
2041   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2042   bo += bl;
2043   proto_item_append_text(pi, "VBS:%s VBS capability %s notifications wanted",
2044                          value == 0 ? " No" : "",
2045                          value == 0 ? "or no" : "and");
2046
2047   /* Multislot capability */
2048   /* XXX: 'Error: struct too short, assume features do not exist'
2049      No length is given! */
2050   bl = 1;
2051   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2052   value = tvb_get_bits8(tvb, bo, bl);
2053   if (value == 1) {
2054     bo += bl;
2055     bl = 1;
2056     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2057     ti = bit_proto_tree_add_text(tree, tvb, bo, bl, "Multislot capability"); 
2058     /* Temporary length */
2059     bo += bl;
2060     tf = proto_item_add_subtree(ti, ett_bssgp_msrac_multislot_capability);
2061
2062     /* HSCSD Multislot Class */
2063     bl = 1;
2064     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2065     value = tvb_get_bits8(tvb, bo, bl);
2066     bo += bl;
2067     if (value == 1) {
2068       bl = 5;
2069       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2070       value = tvb_get_bits8(tvb, bo, bl);
2071       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2072       bo += bl;
2073       proto_item_append_text(pi, "HSCSD Multislot Class");
2074       if ((value > 0 ) && (value < 19)) {
2075         proto_item_append_text(pi, ": Multislot Class %u", value);
2076       }
2077       else {
2078         proto_item_append_text(pi, ": Reserved");
2079       }
2080     }
2081     
2082     /* GPRS Multislot Class, GPRS Extended Dynamic Allocation Capability */
2083     bl = 1;
2084     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2085     value = tvb_get_bits8(tvb, bo, bl);
2086     bo += bl;
2087     if (value == 1) {
2088       bl = 5;
2089       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2090       value = tvb_get_bits8(tvb, bo, bl);
2091       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2092       bo += bl;
2093       proto_item_append_text(pi, "GPRS Multislot Class: Multislot Class %u", 
2094                              value);
2095
2096       bl = 1;
2097       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2098       value = tvb_get_bits8(tvb, bo, bl);
2099       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2100       bo += bl;
2101       proto_item_append_text(pi, "GPRS Extended Dynamic Allocation Capability: Extended Dynamic Allocation for GPRS is%s implemented",
2102                              value == 0 ? " not" : "");
2103     }
2104
2105     /* SMS Value, SM Value */
2106     bl = 1;
2107     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2108     value = tvb_get_bits8(tvb, bo, bl);
2109     bo += bl;
2110     if (value == 1) {
2111       bl = 4;
2112       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2113       value = tvb_get_bits8(tvb, bo, bl);
2114       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2115       bo += bl;
2116       proto_item_append_text(pi, 
2117                              "SMS_VALUE: %u/4 timeslot (~%u microseconds)", 
2118                              value + 1, (value + 1) * 144);
2119
2120       bl = 4;
2121       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2122       value = tvb_get_bits8(tvb, bo, bl);
2123       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2124       bo += bl;
2125       proto_item_append_text(pi, 
2126                              "SM_VALUE: %u/4 timeslot (~%u microseconds)", 
2127                              value + 1, (value + 1) * 144);
2128     }
2129     /* Additions in release 99 */
2130
2131     /* ECSD Multislot Class */
2132     bl = 1;
2133     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2134     value = tvb_get_bits8(tvb, bo, bl);
2135     bo += bl;
2136     if (value == 1) {
2137       bl = 5;
2138       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2139       value = tvb_get_bits8(tvb, bo, bl);
2140       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2141       bo += bl;
2142       proto_item_append_text(pi, "ECSD Multislot Class");
2143       if ((value > 0 ) && (value < 19)) {
2144         proto_item_append_text(pi, ": Multislot Class %u", value);
2145       }
2146       else {
2147         proto_item_append_text(pi, ": Reserved");
2148       }
2149     }
2150
2151     /* EGPRS Multislot Class, EGPRS Extended Dynamic Allocation Capability */
2152     bl = 1;
2153     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2154     value = tvb_get_bits8(tvb, bo, bl);
2155     bo += bl;
2156     if (value == 1) {
2157       bl = 5;
2158       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2159       value = tvb_get_bits8(tvb, bo, bl);
2160       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2161       bo += bl;
2162       proto_item_append_text(pi, "EGPRS Multislot Class: Multislot Class %u",
2163                              value);
2164
2165       bl = 1;
2166       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2167       value = tvb_get_bits8(tvb, bo, bl);
2168       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2169       bo += bl;
2170       proto_item_append_text(pi, "EGPRS Extended Dynamic Allocation Capability: Extended Dynamic Allocation for EGPRS is%s implemented",
2171                              value == 0 ? " not" : "");
2172     }
2173
2174     /* DTM GPRS Multislot Class */
2175     bl = 1;
2176     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2177     value = tvb_get_bits8(tvb, bo, bl);
2178     bo += bl;
2179     if (value == 1) {
2180       bl = 2;
2181       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2182       dgmsc = tvb_get_bits8(tvb, bo, bl);
2183       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2184       bo += bl;
2185       proto_item_append_text(pi, "DTM GPRS Multislot Class: %s", 
2186                              translate_msrac_dtm_gprs_multislot_class(dgmsc));
2187
2188       /* Single slot DTM */
2189       bl = 1;
2190       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2191       value = tvb_get_bits8(tvb, bo, bl);
2192       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2193       bo += bl;
2194       proto_item_append_text(pi, 
2195                              "Single Slot DTM: Single slot DTM%s supported",
2196                              value == 0 ? " not" : "");
2197       
2198       /* DTM EGPRS Multislot Class */
2199       bl = 1;
2200       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2201       value = tvb_get_bits8(tvb, bo, bl);
2202       bo += bl;
2203       if (value == 1) {
2204         bl = 2;
2205         if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2206         demsc = tvb_get_bits8(tvb, bo, bl);
2207         pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2208         bo += bl;
2209         proto_item_append_text(pi, "DTM EGPRS Multislot Class: %s", 
2210                                translate_msrac_dtm_gprs_multislot_class(demsc));
2211       }
2212     }
2213     proto_item_set_len(ti, get_num_octets_spanned(start_bo, 
2214                                                   (guint32) (bo - start_bo)));
2215   }
2216   else {
2217     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2218     bo += bl;
2219     proto_item_append_text(pi, "Multislot capability: Same as in the immediately preceding Access capabilities field within this IE"); 
2220   }
2221
2222   /* Additions in release 99 */
2223
2224   /* 8PSK Power Capability */
2225   bl = 1;
2226   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2227   value = tvb_get_bits8(tvb, bo, bl);
2228   bo += bl;
2229   if (value == 1) {
2230     bl = 2;
2231     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2232     value = tvb_get_bits8(tvb, bo, bl);
2233     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2234     bo += bl;
2235     proto_item_append_text(pi, "8PSK Power Capability");
2236
2237     if (value == 0) {
2238       proto_item_append_text(pi, ": Reserved");
2239     }
2240     else{
2241       proto_item_append_text(pi, ": Power Class E%u", value);
2242     }
2243     proto_item_append_text(pi, ", 8PSK modulation capability in uplink");
2244   }
2245   
2246   /* COMPACT Interference Measurement Capability */
2247   bl = 1;
2248   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2249   value = tvb_get_bits8(tvb, bo, bl);
2250   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2251   bo += bl;
2252   proto_item_append_text(pi, 
2253                          "COMPACT Interference Measurement Capability: %s",
2254                          value == 0 ? "Not implemented" : "Implemented");
2255
2256   /* Revision level indicator */
2257   bl = 1;
2258   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2259   value = tvb_get_bits8(tvb, bo, bl);
2260   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2261   bo += bl;
2262   proto_item_append_text(pi, "Revision Level Indicator: The ME is Release '%u %s", 
2263                          value == 0 ? 98 : 99,
2264                          value == 0 ? "or older" : "onwards");
2265
2266
2267   /* 3G RAT */
2268   bl = 1;
2269   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2270   value = tvb_get_bits8(tvb, bo, bl);
2271   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2272   bo += bl;
2273   proto_item_append_text(pi, "UMTS FDD Radio Access Technology Capability: UMTS FDD%s supported", 
2274                          value == 0 ? " not" : "");
2275
2276   bl = 1;
2277   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2278   value = tvb_get_bits8(tvb, bo, bl);
2279   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2280   bo += bl;
2281   proto_item_append_text(pi, "UMTS 3.84 Mcps TDD Radio Access Technology Capability: UMTS 3.84 Mcps TDD%s supported", 
2282                          value == 0 ? " not" : "");
2283
2284   bl = 1;
2285   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2286   value = tvb_get_bits8(tvb, bo, bl);
2287   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2288   bo += bl;
2289   proto_item_append_text(pi, "CDMA 2000 Radio Access Technology Capability: CDMA 2000%s supported", 
2290                          value == 0 ? " not" : "");
2291
2292
2293   /* Additions in release 4*/
2294   bl = 1;
2295   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2296   value = tvb_get_bits8(tvb, bo, bl);
2297   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2298   bo += bl;
2299   proto_item_append_text(pi, "UMTS 1.28 Mcps TDD Radio Access Technology Capability: UMTS 1.28 Mcps TDD%s supported", 
2300                          value == 0 ? " not" : "");
2301
2302
2303   /* GERAN Feature Package 1 */
2304   bl = 1;
2305   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2306   value = tvb_get_bits8(tvb, bo, bl);
2307   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2308   bo += bl;
2309   proto_item_append_text(pi, "GERAN Feature Package 1: GERAN Feature Package 1%s supported", 
2310                          value == 0 ? " not" : "");
2311
2312
2313   /* Extended DTM xGPRS Multislot Class */  
2314   bl = 1;
2315   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2316   value = tvb_get_bits8(tvb, bo, bl);
2317   bo += bl;
2318   if (value == 1) {
2319     bl = 2;
2320     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2321     value = tvb_get_bits8(tvb, bo, bl);
2322     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2323     bo += bl;
2324     proto_item_append_text(pi, "Extended DTM GPRS Multi Slot Class: %s", 
2325                            translate_msrac_extended_dtm_gprs_multislot_class(value, dgmsc));
2326
2327     /* XXX: 'This field shall be included only if the MS supports EGPRS DTM'.
2328        How know? */
2329     bl = 2;
2330     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2331     value = tvb_get_bits8(tvb, bo, bl);
2332     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2333     bo += bl;
2334     proto_item_append_text(pi, "Extended DTM EGPRS Multi Slot Class: %s", 
2335                            translate_msrac_extended_dtm_gprs_multislot_class(value, demsc));
2336   }
2337
2338   /* Modulation based multislot class support */
2339   bl = 1;
2340   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2341   value = tvb_get_bits8(tvb, bo, bl);
2342   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2343   bo += bl;
2344   proto_item_append_text(pi, "Modulation based multislot class support: %s supported", 
2345                          value == 0 ? "Not" : "");
2346
2347   /* Additions in release 5 */
2348
2349   /* High multislot capability */
2350   bl = 1;
2351   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2352   value = tvb_get_bits8(tvb, bo, bl);
2353   bo += bl;
2354   if (value == 1) {
2355     bl = 2;
2356     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2357     value = tvb_get_bits8(tvb, bo, bl);
2358     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2359     bo += bl;
2360     proto_item_append_text(pi, "High Multislot Capability: %u", value);
2361     /* XXX: Translate? In that case, which values to compare with?
2362      What if Multislot capability struct was not included? */
2363   }
2364
2365   /* GERAN Iu Mode Capabilities */
2366   /* XXX: Interpretation? Length? */
2367   bl = 1;
2368   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2369   value = tvb_get_bits8(tvb, bo, bl);
2370   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2371   bo += bl;
2372   proto_item_append_text(pi, "GERAN Iu Mode Capabilities: %s",
2373                          value == 0 ? "Not supported" : "Supported");
2374
2375   /* GMSK Multislot Power Profile */
2376   bl = 2;
2377   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2378   value = tvb_get_bits8(tvb, bo, bl);
2379   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2380   bo += bl;
2381   proto_item_append_text(pi, "GMSK Multislot Power Profile: GMSK_MULTI_SLOT_POWER_PROFILE %u",
2382                          value);
2383
2384   /* 8PSK Multislot Power Profile */
2385   /* XXX: 'If the MS does not support 8PSK in the uplink, then it shall
2386      set this field to 00' */
2387   bl = 2;
2388   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2389   value = tvb_get_bits8(tvb, bo, bl);
2390   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2391   bo += bl;
2392   proto_item_append_text(pi, "8PSK Multislot Power Profile: 8PSK_MULTI_SLOT_POWER_PROFILE %u",
2393                          value);
2394
2395   /* Additions in release 6 */
2396
2397   /* Multiple TBF Capability */
2398   bl = 1;
2399   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2400   value = tvb_get_bits8(tvb, bo, bl);
2401   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2402   bo += bl;
2403   proto_item_append_text(pi, "Multiple TBF Capability: Multiple TBF procedures in A/Gb mode%s supported",
2404                          value == 0 ? " not" : "");
2405
2406   /* Downlink Advanced Receiver Performance */
2407   bl = 2;
2408   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2409   value = tvb_get_bits8(tvb, bo, bl);
2410   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2411   bo += bl;
2412   proto_item_append_text(pi, "Donwlink Advanced Receiver Performance: Downlink Advanced Receiver Performance %s supported",
2413                          value == 0 ? "not" : "- phase 1");
2414   
2415
2416   /* Extended RLC_MAC Control Message Segmentation Capability */
2417   bl = 1;
2418   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2419   value = tvb_get_bits8(tvb, bo, bl);
2420   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2421   bo += bl;
2422   proto_item_append_text(pi, "Extended RLC/MAC Control Message Segmentation Capability: Extended RLC/MAC Control Message Segmentation%s supported",
2423                          value == 0 ? " not" : "");
2424 }
2425
2426 static void 
2427 decode_msrac_value_part(proto_tree *tree, tvbuff_t *tvb, guint64 bo) {
2428   /* No need to check bi->bssgp_tree here */
2429   const guint8 ADD_ACC_TECHN = 0x0f;
2430   guint8 att, length, bit, bl;
2431   proto_item *ti, *ti2, *pi;
2432   proto_tree *tf, *tf2;
2433   char *att_name;
2434   guint64 start_bo;
2435   
2436   start_bo = bo;
2437   ti = bit_proto_tree_add_text(tree, tvb, bo, 8,
2438                                "MS RA capability value part");
2439   /* Temporary length of item */
2440   tf = proto_item_add_subtree(ti, ett_bssgp_msrac_value_part);
2441
2442   bl = 4;
2443   att = tvb_get_bits8(tvb, bo, bl);
2444   att_name = translate_msrac_access_technology_type(att);
2445   pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2446   proto_item_append_text(pi, "Access Technology Type: %s (%#01x)", att_name, att);
2447   proto_item_append_text(ti, ": Technology Type %s", att_name);
2448   bo += bl;
2449
2450   bl = 7;
2451   length = tvb_get_bits8(tvb, bo, bl);
2452   pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2453   proto_item_append_text(pi, "Length: %u bits", length);
2454   bo += bl;
2455  
2456   if (att == ADD_ACC_TECHN) {
2457     bo++; /* Always '1' */
2458     ti2 = bit_proto_tree_add_text(tf, tvb, bo, length,
2459                                   "Additional Access Technologies");
2460     tf2 = proto_item_add_subtree(ti2, ett_bssgp_msrac_additional_access_technologies);
2461     proto_item_set_len(ti, get_num_octets_spanned(start_bo, 4 + 7 + length + 1 + 1));
2462     decode_msrac_additional_access_technologies(tf2, tvb, bo, length);
2463   }
2464   else if (att <= 0x0b) { 
2465     ti2 = bit_proto_tree_add_text(tf, tvb, bo, length, "Access Capabilities");
2466     tf2 = proto_item_add_subtree(ti2, ett_bssgp_msrac_access_capabilities);
2467     proto_item_set_len(ti, get_num_octets_spanned(start_bo, 4 + 7 + length + 1));
2468     decode_msrac_access_capabilities(tf2, tvb, bo, length); 
2469   }
2470   /* else unknown Access Technology Type */
2471
2472   bo += length;
2473   bit = tvb_get_bits8(tvb, bo, 1);
2474   bo++;
2475   if (bit == 1) {
2476     decode_msrac_value_part(tree, tvb, bo);
2477   }
2478 }
2479
2480 static void 
2481 decode_iei_ms_radio_access_capability(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2482   proto_item *ti;
2483   proto_tree *tf;
2484   
2485   if (!bi->bssgp_tree) {
2486     bi->offset += ie->value_length;
2487     return;  
2488   }
2489   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2490   tf = proto_item_add_subtree(ti, ett_bssgp_ms_radio_access_capability);
2491   
2492   decode_msrac_value_part(tf, bi->tvb, bi->offset * 8);
2493   bi->offset += ie->value_length;
2494 }
2495
2496 static void 
2497 decode_iei_omc_id(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2498   /* XXX: Translation: where in 3GPP TS 12.20? */
2499   proto_item *ti;
2500
2501   if (bi->bssgp_tree) {
2502     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2503     proto_item_append_text(ti, ": %s", BSSGP_NOT_DECODED);
2504   }
2505   bi->offset += ie->value_length;
2506 }
2507
2508 static void 
2509 decode_iei_pdu_in_error(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2510   proto_item *ti;
2511
2512   if (bi->bssgp_tree) {
2513     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2514     proto_item_append_text(ti, ": Erroneous BSSGP PDU (%u bytes)", 
2515                            ie->value_length);
2516   }
2517   bi->offset += ie->value_length;
2518 }
2519
2520 static void 
2521 decode_iei_priority(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2522   const guint8 MASK_PCI = 0x40;
2523   const guint8 MASK_PRIORITY_LEVEL = 0x3c;
2524   const guint8 MASK_QA = 0x02;
2525   const guint8 MASK_PVI = 0x01;
2526   proto_item *ti, *pi;
2527   proto_tree *tf;
2528   guint8 data, value;
2529
2530   value_string tab_priority_level[] = {
2531     { 0, "Spare" },
2532     { 1, "Priority Level 1 = highest priority" },
2533     { 2, "Priority Level 2 = 2nd highest priority" },
2534     { 3, "Priority Level 3 = 3rd highest priority" },
2535     { 4, "Priority Level 4 = 4th highest priority" },
2536     { 5, "Priority Level 5 = 5th highest priority" },
2537     { 6, "Priority Level 6 = 6th highest priority" },
2538     { 7, "Priority Level 7 = 7th highest priority" },
2539     { 8, "Priority Level 8 = 8th highest priority" },
2540     { 9, "Priority Level 9 = 9th highest priority" },
2541     { 10, "Priority Level 10 = 10th highest priority" },
2542     { 11, "Priority Level 11 = 11th highest priority" },
2543     { 12, "Priority Level 12 = 12th highest priority" },
2544     { 13, "Priority Level 13 = 13th highest priority" },
2545     { 14, "Priority Level 14 = lowest priority" },
2546     { 15, "Priority not used" },
2547     { 0, NULL },
2548   };
2549
2550   if (!bi->bssgp_tree) {
2551     bi->offset += ie->value_length;
2552     return;
2553   }   
2554   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2555   tf = proto_item_add_subtree(ti, ett_bssgp_priority);
2556   
2557   data = tvb_get_guint8(bi->tvb, bi->offset); 
2558   
2559   value = get_masked_guint8(data, MASK_PCI);
2560   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
2561                                 MASK_PCI);
2562   proto_item_append_text(pi, "PCI: This allocation request %s preempt an existing connection",
2563                          value == 0 ? "shall not" : "may");
2564   
2565   value = get_masked_guint8(data, MASK_PRIORITY_LEVEL);
2566   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PRIORITY_LEVEL);
2567   proto_item_append_text(pi, "Priority Level: %s",
2568                          val_to_str(value, tab_priority_level, ""));
2569   
2570   value = get_masked_guint8(data, MASK_QA);
2571   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_QA);
2572   proto_item_append_text(pi, "QA: Queuing%s allowed",
2573                          value == 0 ? " not" : "");
2574   
2575   value = get_masked_guint8(data, MASK_PVI);
2576   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PVI);
2577   proto_item_append_text(pi, "PVI: This connection %s be preempted by another allocation request",
2578                       value == 0 ? "shall not" : "might");
2579   
2580   bi->offset += ie->value_length;
2581 }
2582
2583 static void 
2584 decode_iei_qos_profile(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2585   const guint8 MASK_CR_BIT = 0x20;
2586   const guint8 MASK_T_BIT = 0x10;
2587   const guint8 MASK_A_BIT = 0x08;
2588   const guint8 MASK_PRECEDENCE = 0x07;
2589   proto_item *ti, *pi;
2590   proto_tree *tf;
2591   guint8 data, value;
2592   guint16 peak_bit_rate;
2593
2594   value_string tab_precedence_ul[] = {
2595     { 0,   "High priority" }, 
2596     { 1,   "Normal priority" },
2597     { 2,   "Low priority" },
2598     { 0,   NULL },
2599   };
2600
2601   value_string tab_precedence_dl[] = {
2602     { 0,   "Radio priority 1" }, 
2603     { 1,   "Radio priority 2" },
2604     { 2,   "Radio priority 3" },
2605     { 3,   "Radio priority 4" },
2606     { 4,   "Radio priority unknown" },
2607     { 0,   NULL },
2608   };
2609
2610   if (!bi->bssgp_tree) {
2611     bi->offset += ie->value_length;
2612     return;
2613   }
2614   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2615   tf = proto_item_add_subtree(ti, ett_bssgp_qos_profile);
2616
2617   peak_bit_rate = tvb_get_ntohs(bi->tvb, bi->offset);
2618   pi = proto_tree_add_text(tf, bi->tvb, bi->offset, 1, "Peak bit rate: ");
2619   if (peak_bit_rate == 0) {
2620     proto_item_append_text(pi, "Best effort");
2621   }
2622   else {
2623     proto_item_append_text(pi, "%u bits/s", peak_bit_rate * 100);
2624   }
2625   bi->offset += 2;
2626
2627   data = tvb_get_guint8(bi->tvb, bi->offset);
2628
2629   value = get_masked_guint8(data, MASK_CR_BIT);
2630   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_CR_BIT);
2631   proto_item_append_text(pi, "C/R: The SDU %s command/response frame type",
2632                          value == 0 ? "contains" : "does not contain");
2633
2634   value = get_masked_guint8(data, MASK_T_BIT);
2635   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_T_BIT);
2636   proto_item_append_text(pi, "T: The SDU contains %s",
2637                          value == 0 ? 
2638                          "data" : 
2639                          "signalling (e.g. related to GMM)");
2640
2641   value = get_masked_guint8(data, MASK_A_BIT);
2642   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_A_BIT);
2643   proto_item_append_text(pi, "A: Radio interface uses RLC/MAC %s functionality",
2644                          value == 0 ? "ARQ " : "UNITDATA ");
2645   
2646   value = get_masked_guint8(data, MASK_PRECEDENCE);
2647   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PRECEDENCE);
2648   proto_item_append_text(pi, "Precedence: ");
2649
2650   if (bi->ul_data) {
2651     proto_item_append_text(pi, val_to_str(value, tab_precedence_ul, 
2652                                           "Reserved (Low priority)"));
2653   }
2654   else {
2655     proto_item_append_text(pi, val_to_str(value, tab_precedence_dl,
2656                                           "Reserved (Radio priority 3)"));
2657   }
2658   proto_item_append_text(pi, " (%#x)", value);
2659   bi->offset++;
2660 }
2661
2662 static void 
2663 decode_iei_radio_cause(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2664   proto_item *ti;
2665   guint8 value;
2666
2667   value_string tab_radio_cause[] = {
2668     { 0x00, "Radio contact lost with the MS" },
2669     { 0x01, "Radio link quality insufficient to continue communication" },
2670     { 0x02, "Cell reselection ordered" },
2671     { 0x03, "Cell reselection prepare" },
2672     { 0x04, "Cell reselection failure" },
2673     { 0,    NULL },
2674     /* Otherwise "Reserved (Radio contact lost with the MS)" */
2675   };
2676
2677   if (bi->bssgp_tree) {
2678     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2679     value = tvb_get_guint8(bi->tvb, bi->offset);
2680     proto_item_append_text(ti, ": %s (%#02x)",
2681                            val_to_str(value, tab_radio_cause, "Reserved (Radio contact lost with the MS)"),
2682                            value);
2683   }
2684   bi->offset += ie->value_length;
2685 }
2686
2687 static void 
2688 decode_iei_ra_cap_upd_cause(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2689   proto_item *ti;
2690   guint8 value;
2691
2692   value_string tab_cause[] = {
2693     { 0x00, "OK, RA capability IE present" },
2694     { 0x01, "TLLI unknown in SGSN" },
2695     { 0x02, "No RA capabilities or IMSI available for this MS" },
2696     { 0,    NULL },
2697     /* Otherwise "Reserved (TLLI unknown in SGSN)" */
2698   };
2699
2700   if (bi->bssgp_tree) {
2701     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2702     value = tvb_get_guint8(bi->tvb, bi->offset);
2703     proto_item_append_text(ti, ": %s (%#2x)",
2704                            val_to_str(value, tab_cause, "Reserved (TLLI unknown in SGSN)"),
2705                            value);
2706   }
2707   bi->offset += ie->value_length;
2708 }
2709
2710 static void 
2711 decode_iei_routeing_area(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2712   proto_item *ti;
2713   proto_tree *tf;
2714   char *rai;
2715
2716   if (!bi->bssgp_tree) {
2717     bi->offset += ie->value_length;
2718     return;
2719   }
2720   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2721   tf = proto_item_add_subtree(ti, ett_bssgp_routeing_area);
2722
2723   rai = decode_rai(bi, tf);
2724   proto_item_append_text(ti, ": RAI %s", rai);
2725 }
2726
2727 static void 
2728 decode_iei_tlli(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2729   proto_item *ti;
2730   guint32 tlli;
2731
2732   tlli = tvb_get_ntohl(bi->tvb, bi->offset);
2733
2734   if (bi->bssgp_tree) {
2735     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2736     proto_item_append_text(ti, ": %#04x", tlli);
2737     proto_tree_add_item_hidden(bi->bssgp_tree, hf_bssgp_tlli, 
2738                                bi->tvb, bi->offset, 4, BSSGP_LITTLE_ENDIAN);
2739   }
2740   bi->offset += 4;
2741
2742   if (check_col(bi->pinfo->cinfo, COL_INFO)) {
2743     col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP, 
2744                         "TLLI %#4x", tlli);
2745   }
2746 }
2747
2748 static void 
2749 decode_iei_trigger_id(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2750   /* XXX: value is 20 octets long! How add/show? */
2751   proto_item *ti;
2752   
2753   if (bi->bssgp_tree) {
2754     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2755   }
2756   bi->offset += ie->value_length;
2757 }
2758
2759 static void 
2760 proto_tree_add_lsa_id(build_info_t *bi, proto_tree *tree) {
2761   guint32 data, lsa_id;
2762   proto_item *pi;
2763   
2764   data = tvb_get_ntoh24(bi->tvb, bi->offset);
2765   lsa_id = data >> 1;
2766   
2767   pi = proto_tree_add_text(tree, bi->tvb, bi->offset, 3, 
2768                            "LSA ID: %#03x (%s)", lsa_id,
2769                            data & 1 ? 
2770                            "Universal LSA" : "PLMN significant number");
2771   bi->offset += 3;
2772 }
2773
2774 static void 
2775 decode_iei_lsa_identifier_list(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2776   const guint8 MASK_EP = 0x01;
2777   proto_item *ti, *pi;
2778   proto_tree *tf;
2779   int num_lsa_ids, i;
2780   guint32 value;
2781
2782   if (!bi->bssgp_tree) {
2783     bi->offset += ie->value_length;
2784     return;
2785   }
2786   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2787   tf = proto_item_add_subtree(ti, ett_bssgp_lsa_identifier_list);
2788
2789   value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_EP);
2790   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_EP);
2791   proto_item_append_text(pi, "EP: The escape PLMN is%s broadcast",
2792                          value == 0 ? " not" : "");
2793   bi->offset++;
2794
2795   num_lsa_ids = (ie->value_length - 1) / 3;
2796
2797   for (i = 0; i < num_lsa_ids; i++); {
2798     proto_tree_add_lsa_id(bi, tf);
2799   }
2800 }
2801
2802 static void 
2803 decode_iei_lsa_information(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2804   const guint8 MASK_LSA_ONLY = 0x01;
2805   const guint8 MASK_ACT = 0x20;
2806   const guint8 MASK_PREF = 0x10;
2807   const guint8 MASK_PRIORITY = 0x0f;
2808   proto_item *ti, *ti2, *pi;
2809   proto_tree *tf, *tf2;
2810   int num_lsa_infos, i;
2811   guint8 data, value;
2812
2813   value_string tab_priority[] = {
2814     { 0, "Priority 1 = lowest priority" },
2815     { 1, "Priority 2 = 2nd lowest priority" },
2816     { 2, "Priority 3 = 3rd lowest priority" },
2817     { 3, "Priority 4 = 4th lowest priority" },
2818     { 4, "Priority 5 = 5th lowest priority" },
2819     { 5, "Priority 6 = 6th lowest priority" },
2820     { 6, "Priority 7 = 7th lowest priority" },
2821     { 7, "Priority 8 = 8th lowest priority" },
2822     { 8, "Priority 9 = 9th lowest priority" },
2823     { 9, "Priority 10 = 10th lowest priority" },
2824     { 10, "Priority 11 = 11th lowest priority" },
2825     { 11, "Priority 12 = 12th lowest priority" },
2826     { 12, "Priority 13 = 13th lowest priority" },
2827     { 13, "Priority 14 = 14th lowest priority" },
2828     { 14, "Priority 15 = 15th lowest priority" },
2829     { 15, "Priority 16 = highest priority" },
2830     { 0, NULL },
2831   };
2832
2833   if (!bi->bssgp_tree) {
2834     bi->offset += ie->value_length;
2835     return;
2836   }
2837   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2838   tf = proto_item_add_subtree(ti, ett_bssgp_lsa_information);
2839
2840   value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_LSA_ONLY);
2841   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_LSA_ONLY);
2842   proto_item_append_text(pi, "LSA Only: %s",
2843                          value == 0 ? 
2844                          "The subscriber has only access to the LSAs that are defined by the LSA information element" :
2845                          "Allow an emergency call");
2846   bi->offset++;
2847
2848   num_lsa_infos = (ie->value_length - 1) / 4;
2849
2850   for (i = 0; i < num_lsa_infos; i++); {
2851     ti2 = proto_tree_add_text(tf, bi->tvb, bi->offset, 4, 
2852                               "LSA Identification and attributes %u", i + 1);
2853     tf2 = proto_item_add_subtree(ti2, ett_bssgp_lsa_information_lsa_identification_and_attributes);
2854     
2855     data = tvb_get_guint8(bi->tvb, bi->offset);
2856     
2857     value = get_masked_guint8(data, MASK_ACT);
2858     pi = proto_tree_add_bitfield8(tf2, bi->tvb, bi->offset, MASK_ACT);
2859     proto_item_append_text(pi, "Act: The subscriber %s active mode support in the LSA",
2860                            value == 0 ? "does not have" : "has");
2861         
2862     value = get_masked_guint8(data, MASK_PREF);
2863     pi = proto_tree_add_bitfield8(tf2, bi->tvb, bi->offset, MASK_PREF);
2864     proto_item_append_text(pi, "Pref: The subscriber %s preferential access in the LSA",
2865                            value == 0 ? "does not have" : "has");
2866
2867     value = get_masked_guint8(data, MASK_PRIORITY);
2868     pi = proto_tree_add_bitfield8(tf2, bi->tvb, bi->offset, MASK_PRIORITY);
2869     proto_item_append_text(pi, "Priority: %s",
2870                            val_to_str(value, tab_priority, ""));
2871     bi->offset++;
2872     
2873     proto_tree_add_lsa_id(bi, tf2);
2874   }
2875 }
2876
2877 static void 
2878 decode_iei_gprs_timer(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2879   const guint8 MASK_UNIT_VALUE = 0xe0;
2880   const guint8 MASK_TIMER_VALUE = 0x1f;
2881   proto_item *ti;
2882   guint8 data, value;
2883
2884   value_string tab_unit_value[] = {
2885     { 0, "incremented in multiples of 2 s" },
2886     { 1, "incremented in multiples of 1 minute" },
2887     { 2, "incremented in multiples of decihours" },
2888     { 3, "incremented in multiples of 500 msec" },
2889     { 7, "the timer does not expire" },
2890     { 0, NULL},
2891     /* Otherwise "incremented in multiples of 1 minute" */
2892   };
2893
2894   if (bi->bssgp_tree) {
2895     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2896     data = tvb_get_guint8(bi->tvb, bi->offset);
2897     value = get_masked_guint8(data, MASK_TIMER_VALUE);
2898     proto_item_append_text(ti, ": %u", value);
2899     
2900     value = get_masked_guint8(data, MASK_UNIT_VALUE);
2901     proto_item_append_text(ti, ", %s",
2902                            val_to_str(value, tab_unit_value, 
2903                                       "incremented in multiples of 1 minute"));
2904   }
2905   bi->offset += ie->value_length;
2906 }
2907
2908 static void 
2909 decode_iei_abqp(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2910   const guint8 MASK_DELAY_CLASS = 0x38;
2911   const guint8 MASK_RELIABILITY_CLASS = 0x07;
2912   const guint8 MASK_PEAK_THROUGHPUT = 0xf0;
2913   const guint8 MASK_PRECEDENCE_CLASS = 0x07;
2914   const guint8 MASK_MEAN_THROUGHPUT = 0x1f;
2915   const guint8 MASK_TRAFFIC_CLASS = 0xe0;
2916   const guint8 MASK_DELIVERY_ORDER = 0x18;
2917   const guint8 MASK_DELIVERY_OF_ERRONEOUS_SDU = 0x07;
2918   const guint8 MASK_RESIDUAL_BER = 0xf0;
2919   const guint8 MASK_SDU_ERROR_RATIO = 0x0f;
2920   const guint8 MASK_TRANSFER_DELAY = 0xfc;
2921   const guint8 MASK_TRAFFIC_HANDLING_PRIORITY = 0x03;
2922   const guint8 MASK_SIGNALLING_INDICATION = 0x10;
2923   const guint8 MASK_SOURCE_STATISTICS_DESCRIPTOR = 0x0f;
2924   const guint8 TRAFFIC_CLASS_CONVERSATIONAL = 1;
2925   const guint8 TRAFFIC_CLASS_STREAMING = 2;
2926   const guint8 TRAFFIC_CLASS_INTERACTIVE = 3;
2927   const guint8 TRAFFIC_CLASS_BACKGROUND = 4;
2928   guint8 data, value, traffic_class;
2929   proto_item *ti, *pi;
2930   proto_tree *tf;
2931
2932   if (bi->bssgp_tree) {
2933     bi->offset += ie->value_length;
2934     return;
2935   }
2936   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2937   tf = proto_item_add_subtree(ti, ett_bssgp_abqp);
2938     
2939   data = tvb_get_guint8(bi->tvb, bi->offset);
2940
2941   value = get_masked_guint8(data, MASK_DELAY_CLASS);
2942   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_DELAY_CLASS);
2943   proto_item_append_text(pi, "Delay Class: %s (%#x)",  
2944                          translate_abqp_delay_class(value, bi), value);
2945
2946   value = get_masked_guint8(data, MASK_RELIABILITY_CLASS);
2947   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
2948                                 MASK_RELIABILITY_CLASS);
2949   proto_item_append_text(pi, "Reliability Class: %s (%#x)",
2950                          translate_abqp_reliability_class(value, bi), value);
2951   bi->offset++;
2952   data = tvb_get_guint8(bi->tvb, bi->offset);
2953
2954   value = get_masked_guint8(data, MASK_PEAK_THROUGHPUT);
2955   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
2956                                 MASK_PEAK_THROUGHPUT);
2957   proto_item_append_text(pi, "Peak Throughput: %s (%#x)",
2958                          translate_abqp_peak_throughput(value, bi), value);
2959
2960   value = get_masked_guint8(data, MASK_PRECEDENCE_CLASS);
2961   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
2962                                 MASK_PRECEDENCE_CLASS);
2963   proto_item_append_text(pi, "Precedence Class: %s (%#x)",
2964                          translate_abqp_precedence_class(value, bi), value);
2965   bi->offset++;
2966   data = tvb_get_guint8(bi->tvb, bi->offset);
2967
2968   value = get_masked_guint8(data, MASK_MEAN_THROUGHPUT);
2969   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
2970                                 MASK_MEAN_THROUGHPUT);
2971   proto_item_append_text(pi, "Mean Throughput: %s (%#02x)",
2972                          translate_abqp_mean_throughput(value, bi), value);
2973   bi->offset++;
2974   data = tvb_get_guint8(bi->tvb, bi->offset);
2975
2976   traffic_class = get_masked_guint8(data, MASK_TRAFFIC_CLASS);
2977   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_TRAFFIC_CLASS);
2978   proto_item_append_text(pi, "Traffic Class: %s (%#x)",
2979                          translate_abqp_traffic_class(traffic_class, bi), 
2980                          value);
2981   if ((traffic_class == TRAFFIC_CLASS_INTERACTIVE) || 
2982       (traffic_class == TRAFFIC_CLASS_BACKGROUND)) {
2983     proto_item_append_text(pi, " (ignored)");
2984   }
2985
2986   value = get_masked_guint8(data, MASK_DELIVERY_ORDER);
2987   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_DELIVERY_ORDER);
2988   proto_item_append_text(pi, "Delivery Order: %s (%#x)",
2989                          translate_abqp_delivery_order(value, bi), value);
2990
2991   value = get_masked_guint8(data, MASK_DELIVERY_OF_ERRONEOUS_SDU);
2992   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
2993                                 MASK_DELIVERY_OF_ERRONEOUS_SDU);
2994   proto_item_append_text(pi, "Delivery of Erroneous SDU: %s (%#x)",
2995                          translate_abqp_delivery_of_erroneous_sdu(value, bi),
2996                          value);
2997   bi->offset++;
2998
2999   value = tvb_get_guint8(bi->tvb, bi->offset);
3000   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, 
3001                       "Maximum SDU Size: %s",
3002                       translate_abqp_max_sdu_size(value, bi));
3003   bi->offset++;
3004
3005   value = tvb_get_guint8(bi->tvb, bi->offset);
3006   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, 
3007                       "Maximum bit rate for uplink: %s",
3008                       translate_abqp_max_bit_rate_for_ul(value, bi));
3009   bi->offset++;
3010
3011   value = tvb_get_guint8(bi->tvb, bi->offset);
3012   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, 
3013                       "Maximum bit rate for downlink: %s",
3014                       translate_abqp_max_bit_rate_for_dl(value, bi));
3015   bi->offset++;
3016   data = tvb_get_guint8(bi->tvb, bi->offset);
3017
3018   value = get_masked_guint8(data, MASK_RESIDUAL_BER);
3019   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_RESIDUAL_BER);
3020   proto_item_append_text(pi, "Residual BER: %s (%#x)",
3021                          translate_abqp_residual_ber(value, bi), value);
3022
3023   value = get_masked_guint8(data, MASK_SDU_ERROR_RATIO);
3024   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
3025                                 MASK_SDU_ERROR_RATIO);
3026   proto_item_append_text(pi, "SDU Error Ratio: %s (%#x)",
3027                          translate_abqp_sdu_error_ratio(value, bi), value);
3028   bi->offset++;
3029   data = tvb_get_guint8(bi->tvb, bi->offset);
3030
3031   value = get_masked_guint8(data, MASK_TRANSFER_DELAY);
3032   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_TRANSFER_DELAY);
3033   proto_item_append_text(pi, "Transfer Delay: %s (%#02x)",
3034                          translate_abqp_transfer_delay(value, bi), value);
3035
3036   value = get_masked_guint8(data, MASK_TRAFFIC_HANDLING_PRIORITY);
3037   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
3038                                 MASK_TRAFFIC_HANDLING_PRIORITY);
3039   proto_item_append_text(pi, "Traffic Handling Priority: %s (%#x)",
3040                          translate_abqp_traffic_handling_priority(value, bi),
3041                          value);
3042   if ((traffic_class == TRAFFIC_CLASS_CONVERSATIONAL) ||
3043       (traffic_class == TRAFFIC_CLASS_STREAMING) ||
3044       (traffic_class == TRAFFIC_CLASS_BACKGROUND)) {
3045     proto_item_append_text(pi, " (ignored)");
3046   }
3047   bi->offset++;
3048
3049   value = tvb_get_guint8(bi->tvb, bi->offset);
3050   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, 
3051                       "Guaranteed bit rate for uplink: %s",
3052                       translate_abqp_guaranteed_bit_rate_for_ul(value, bi));
3053   bi->offset++;
3054
3055   value = tvb_get_guint8(bi->tvb, bi->offset);
3056   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, 
3057                       "Guaranteed bit rate for downlink: %s",
3058                       translate_abqp_guaranteed_bit_rate_for_dl(value, bi));
3059   bi->offset++;
3060
3061   data = tvb_get_guint8(bi->tvb, bi->offset);
3062
3063   value = get_masked_guint8(data, MASK_SIGNALLING_INDICATION);
3064   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
3065                                 MASK_SIGNALLING_INDICATION);
3066   proto_item_append_text(pi, "Signalling Indication: %s for signalling traffic",
3067                          value == 0 ? "Not optimized" : "Optimized");
3068   if ((traffic_class == TRAFFIC_CLASS_CONVERSATIONAL) ||
3069       (traffic_class == TRAFFIC_CLASS_STREAMING) ||
3070       (traffic_class == TRAFFIC_CLASS_BACKGROUND)) {
3071     proto_item_append_text(pi, " (ignored)");
3072   }
3073
3074   value = get_masked_guint8(data, MASK_SOURCE_STATISTICS_DESCRIPTOR);
3075   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
3076                                 MASK_SOURCE_STATISTICS_DESCRIPTOR);
3077   proto_item_append_text(pi, "Source Statistics Descriptor: %s (%#x)",
3078                          translate_abqp_source_statistics_descriptor(value, bi),
3079                          value);
3080   if ((traffic_class == TRAFFIC_CLASS_INTERACTIVE) ||
3081       (traffic_class == TRAFFIC_CLASS_BACKGROUND)) {
3082     proto_item_append_text(pi, " (ignored)");
3083   }
3084   bi->offset++;
3085
3086   value = tvb_get_guint8(bi->tvb, bi->offset);
3087   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, 
3088                       "Maximum bit rate for downlink (extended): %s",
3089                       translate_abqp_max_bit_rate_for_dl_extended(value, bi));
3090   bi->offset++;
3091
3092   value = tvb_get_guint8(bi->tvb, bi->offset);
3093   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, 
3094                       "Guaranteed bit rate for downlink (extended): %s",
3095                       translate_abqp_guaranteed_bit_rate_for_dl_extended(value, bi));
3096   bi->offset++;
3097 }
3098
3099 static void 
3100 decode_iei_feature_bitmap(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3101   const guint8 MASK_ENHANCED_RADIO_STATUS = 0x40;
3102   const guint8 MASK_PFC_FC = 0x20;
3103   const guint8 MASK_RIM = 0x10;
3104   const guint8 MASK_LCS = 0x08;
3105   const guint8 MASK_INR = 0x04;
3106   const guint8 MASK_CBL = 0x02;
3107   const guint8 MASK_PFC = 0x01;
3108   proto_item *ti, *pi;
3109   proto_tree *tf;
3110   guint8 data, value;
3111
3112   if (!bi->bssgp_tree) {
3113     bi->offset += ie->value_length;
3114     return;
3115   }
3116   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3117   tf = proto_item_add_subtree(ti, ett_bssgp_feature_bitmap);
3118   
3119   data = tvb_get_guint8(bi->tvb, bi->offset);
3120
3121   value = get_masked_guint8(data, MASK_ENHANCED_RADIO_STATUS);
3122   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, 
3123                                 MASK_ENHANCED_RADIO_STATUS);
3124   proto_item_append_text(pi, "Enhanced Radio Status: Enhanced Radio Status Procedures%s supported",
3125                          value == 0 ? " not" : "");
3126   
3127   value = get_masked_guint8(data, MASK_PFC_FC);
3128   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PFC_FC);
3129   proto_item_append_text(pi, "PFC_FC: PFC Flow Control Procedures%s supported",
3130                          value == 0 ? " not" : "");
3131
3132   value = get_masked_guint8(data, MASK_RIM);
3133   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_RIM);
3134   proto_item_append_text(pi, "RIM: RAN Information Management (RIM) Procedures%s supported",
3135                          value == 0 ? " not" : "");
3136
3137   value = get_masked_guint8(data, MASK_LCS);
3138   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_LCS);
3139   proto_item_append_text(pi, "LCS: LCS Procedures%s supported",
3140                       value == 0 ? " not" : "");
3141
3142   value = get_masked_guint8(data, MASK_INR);
3143   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_INR);
3144   proto_item_append_text(pi, "INR: Inter-NSE re-routeing%s supoprted",
3145                          value == 0 ? " not" : "");
3146   
3147   value = get_masked_guint8(data, MASK_CBL);
3148   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_CBL);
3149   proto_item_append_text(pi, "CBL: Current Bucket Level Procedures%s supported",
3150                          value == 0 ? " not" : "");
3151
3152   value = get_masked_guint8(data, MASK_PFC);
3153   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PFC);
3154   proto_item_append_text(pi, "PFC: Packet Flow Context Procedures%s supported",
3155                          value == 0 ? " not" : ""); 
3156
3157   bi->offset += ie->value_length; 
3158 }
3159
3160 static void 
3161 decode_iei_bucket_full_ratio(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3162   proto_item *ti;
3163   
3164   if (bi->bssgp_tree) {
3165     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3166     bssgp_pi_append_bucket_full_ratio(ti, bi->tvb, bi->offset);
3167   }
3168   bi->offset += ie->value_length;
3169 }
3170
3171 static void 
3172 decode_iei_service_utran_cco(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3173   const guint8 MASK_SERVICE_UTRAN_CCO = 0x07;
3174   proto_item *ti;
3175   guint8 data, value; 
3176
3177   value_string tab_service_utran_cco[] = {
3178     { 0, "Network initiated cell change order procedure to UTRAN should be performed" },
3179     { 1, "Network initiated cell change order procedure to UTRAN should not be performed" },
3180     { 2, "Network initiated cell change order procedure to UTRAN shall not be performed" },
3181     { 0,    NULL },
3182     /* Otherwise "No information available" */
3183   };
3184
3185   if (bi->bssgp_tree) {
3186     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3187     data = tvb_get_guint8(bi->tvb, bi->offset);
3188     value = get_masked_guint8(data, MASK_SERVICE_UTRAN_CCO);
3189     proto_item_append_text(ti, ": %s (%#02x)",
3190                            val_to_str(value, tab_service_utran_cco, 
3191                                       "No information available"),
3192                            value);
3193   }
3194   bi->offset += ie->value_length;
3195 }
3196
3197 static void 
3198 decode_iei_nsei(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3199   proto_item *ti;
3200   guint16 nsei;
3201
3202   nsei = tvb_get_ntohs(bi->tvb, bi->offset);
3203
3204   if (bi->bssgp_tree) {
3205     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3206     proto_item_append_text(ti, ": %u", nsei);
3207     proto_tree_add_item_hidden(bi->bssgp_tree, hf_bssgp_nsei, 
3208                                bi->tvb, bi->offset, 2, BSSGP_LITTLE_ENDIAN);
3209   }
3210   bi->offset += ie->value_length;
3211
3212   if (check_col(bi->pinfo->cinfo, COL_INFO)) {
3213     col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP, 
3214                         "NSEI %u", nsei);
3215   }
3216 }
3217
3218 static void 
3219 decode_iei_lcs_qos(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3220   const guint8 MASK_VERT = 0x01;
3221   const guint8 MASK_XA = 0x80;
3222   const guint8 MASK_ACCURACY = 0x7f;
3223   const guint8 MASK_RT = 0xc0;
3224   proto_item *ti, *pi;
3225   proto_tree *tf;
3226   guint8 data, value, vert;
3227
3228   value_string tab_rt[] = {
3229     { 0, "Response time is not specified" },
3230     { 1, "Low delay" },
3231     { 2, "Delay tolerant" },
3232     { 3, "Reserved" },
3233     { 0, NULL },
3234   };
3235
3236   if (!bi->bssgp_tree) {
3237     bi->offset += ie->value_length;
3238     return;
3239   }
3240   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3241   tf = proto_item_add_subtree(ti, ett_bssgp_lcs_qos);
3242
3243   data = tvb_get_guint8(bi->tvb, bi->offset);
3244   vert = get_masked_guint8(data, MASK_VERT);
3245   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_VERT);
3246   proto_item_append_text(pi, "VERT: Vertical coordinate is%s requested",
3247                          vert == 0 ? " not" : "");
3248   bi->offset++;
3249
3250   data = tvb_get_guint8(bi->tvb, bi->offset);
3251   
3252   value = get_masked_guint8(data, MASK_XA);
3253   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_XA);
3254   proto_item_append_text(pi, "HA: Horizontal Accuracy is%s specified",
3255                          value == 0 ? " not" : "");
3256
3257   if (value == 1) {
3258     value = get_masked_guint8(data, MASK_ACCURACY);
3259     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_ACCURACY);
3260     proto_item_append_text(pi, "Horizontal Accuracy: %.1f m", 
3261                            10 * (pow(1.1, value) - 1));
3262   }
3263   bi->offset++;
3264
3265   data = tvb_get_guint8(bi->tvb, bi->offset);
3266   
3267   if (vert == 1) {
3268     value = get_masked_guint8(data, MASK_XA);
3269     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_XA);
3270     proto_item_append_text(pi, "VA: Vertical Accuracy is%s specified",
3271                            value == 0 ? " not" : "");
3272
3273     value = get_masked_guint8(data, MASK_ACCURACY);
3274     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_ACCURACY);
3275     proto_item_append_text(pi, "Vertical Accuracy: %.1f m", 
3276                            45 * (pow(1.025, value) - 1));
3277   }
3278   bi->offset++;
3279
3280   data = tvb_get_guint8(bi->tvb, bi->offset);
3281   value = get_masked_guint8(data, MASK_RT);
3282   
3283   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_RT);
3284   proto_item_append_text(pi, "RT: %s",
3285                          val_to_str(value, tab_rt, ""));
3286   bi->offset++;
3287 }
3288
3289 static void 
3290 decode_iei_lcs_client_type(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3291   const guint8 MASK_CATEGORY = 0xf0;
3292   const guint8 MASK_SUBTYPE = 0x0f;
3293   proto_item *ti, *pi;
3294   proto_tree *tf;
3295   guint8 data, category, subtype;
3296
3297   value_string tab_category[] = {
3298     { 0, "Value Added Client" },
3299     /* { 1, ??? XXX }, */
3300     { 2, "PLMN Operator" },
3301     { 3, "Emergency Services" },
3302     { 4, "Lawful Intercept Services" },
3303     { 0, NULL },
3304     /* Otherwise "Reserved" */
3305   };
3306
3307   if (!bi->bssgp_tree) {
3308     bi->offset += ie->value_length;
3309     return;
3310   }
3311   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3312   tf = proto_item_add_subtree(ti, ett_bssgp_lcs_client_type);
3313
3314   data = tvb_get_guint8(bi->tvb, bi->offset);
3315   
3316   category = get_masked_guint8(data, MASK_CATEGORY);
3317   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_CATEGORY);
3318   proto_item_append_text(pi, "Category: %s (%#x)",
3319                          val_to_str(category, tab_category, "Reserved"),
3320                          category);
3321
3322   subtype = get_masked_guint8(data, MASK_SUBTYPE);
3323   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_SUBTYPE);
3324   proto_item_append_text(pi, "Subtype: ");
3325
3326   switch (category) {
3327   case 0:
3328     if (subtype == 0) {
3329       proto_item_append_text(pi, "Unspecified"); break;
3330     }
3331     else {
3332       proto_item_append_text(pi, "Reserved"); break;
3333     }
3334     /* case 1: ??? XXX*/
3335   case 2:
3336     switch (subtype) {
3337     case 0: proto_item_append_text(pi, "Unspecified"); break;
3338     case 1: proto_item_append_text(pi, "Broadcast service"); break;
3339     case 2: proto_item_append_text(pi, "O&M"); break;
3340     case 3: proto_item_append_text(pi, "Anonymous statistics"); break;
3341     case 4: proto_item_append_text(pi, "Target MS service support node"); break;
3342     default: proto_item_append_text(pi, "Reserved"); break;
3343     };
3344   case 3:
3345   case 4:
3346     if (subtype == 0) {
3347       proto_item_append_text(pi, "Unspecified"); break;
3348     }
3349     else {
3350       proto_item_append_text(pi, "Reserved"); break;
3351     }
3352   default: /* Not category == 1! */
3353     proto_item_append_text(pi, "Reserved"); break;
3354   };
3355
3356   bi->offset++;
3357 }
3358
3359 static void 
3360 decode_iei_requested_gps_assistance_data(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3361   const guint8 MASK_A = 0x01;
3362   const guint8 MASK_B = 0x02;
3363   const guint8 MASK_C = 0x04;
3364   const guint8 MASK_D = 0x08;
3365   const guint8 MASK_E = 0x10;
3366   const guint8 MASK_F = 0x20;
3367   const guint8 MASK_G = 0x40;
3368   const guint8 MASK_H = 0x80;
3369   const guint8 MASK_I = 0x01;
3370   const guint8 MASK_NSAT = 0xf0;
3371   const guint8 MASK_T_TOE_LIMIT = 0x0f;
3372   const guint8 MASK_SAT_ID =0x3f;
3373   proto_tree *tf, *tf2;
3374   proto_item *ti, *ti2, *pi;
3375   guint8 data, value, d, nsat;
3376   guint16 gps_week;
3377   int i;
3378
3379   if (!bi->bssgp_tree) {
3380     bi->offset += ie->value_length;
3381     return;
3382   }
3383   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3384   tf = proto_item_add_subtree(ti, ett_bssgp_requested_gps_assistance_data);
3385
3386   data = tvb_get_guint8(bi->tvb, bi->offset);
3387
3388   value = get_masked_guint8(data, MASK_A);
3389   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_A);
3390   proto_item_append_text(pi, "A: Almanac is%s srequested",
3391                          value == 0 ? " not" : "");
3392
3393   value = get_masked_guint8(data, MASK_B);
3394   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_B);
3395   proto_item_append_text(pi, "B: UTC Model is%s requested",
3396                          value == 0 ? " not" : "");
3397
3398   value = get_masked_guint8(data, MASK_C);
3399   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_C);
3400   proto_item_append_text(pi, "C: Ionospheric Model is%s requested",
3401                          value == 0 ? " not" : "");
3402
3403   value = get_masked_guint8(data, MASK_D);
3404   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_D);
3405   proto_item_append_text(pi, "D: Navigation Model is%s requested",
3406                          value == 0 ? " not" : "");
3407   d = value;
3408
3409   value = get_masked_guint8(data, MASK_E);
3410   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_E);
3411   proto_item_append_text(pi, "E: DGPS Corrections are%s requested",
3412                          value == 0 ? " not" : "");
3413
3414   value = get_masked_guint8(data, MASK_F);
3415   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_F);
3416   proto_item_append_text(pi, "F: Reference Location is%s requested",
3417                          value == 0 ? " not" : "");
3418
3419   value = get_masked_guint8(data, MASK_G);
3420   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_G);
3421   proto_item_append_text(pi, "G: Reference Time is%s requested",
3422                          value == 0 ? " not" : "");
3423
3424   value = get_masked_guint8(data, MASK_H);
3425   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_H);
3426   proto_item_append_text(pi, "H: Acquisition Asssistance is%s requested",
3427                          value == 0 ? " not" : "");
3428
3429   bi->offset++;
3430
3431   value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_I);
3432   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_I);
3433   proto_item_append_text(pi, "I: Real-Time Integrity is%s requested",
3434                          value == 0 ? " not" : "");
3435   if (d == 0) return;
3436
3437   data = tvb_get_guint8(bi->tvb, bi->offset);
3438   gps_week = (data & 0xc0) << 2;
3439   data = tvb_get_guint8(bi->tvb, bi->offset + 1);
3440   gps_week += data;
3441   proto_tree_add_text(tf, bi->tvb, bi->offset, 2, 
3442                       "GPS Week: %u", gps_week);  
3443   bi->offset += 2;
3444
3445   value = tvb_get_guint8(bi->tvb, bi->offset);
3446   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
3447                       "GPS Toe: %u", value);
3448   bi->offset++;
3449
3450   data = tvb_get_guint8(bi->tvb, bi->offset);
3451   nsat = get_masked_guint8(data, MASK_NSAT);
3452   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_NSAT);
3453   proto_item_append_text(pi, "NSAT: %u", value);
3454
3455   value = get_masked_guint8(data, MASK_T_TOE_LIMIT);
3456   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_T_TOE_LIMIT);
3457   proto_item_append_text(pi, "T-Toe Limit: %u", value);
3458   bi->offset++;
3459
3460   for (i = 0; i < nsat; i++) {
3461     ti2 = proto_tree_add_text(tf, bi->tvb, bi->offset, 2, "Satellite %u", i);
3462     tf2 = proto_item_add_subtree(ti2, ett_bssgp_requested_gps_assistance_data_satellite);
3463
3464     value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_SAT_ID);
3465     pi = proto_tree_add_bitfield8(tf2, bi->tvb, bi->offset, MASK_SAT_ID);
3466     proto_item_append_text(pi, "SatId: %u", value);
3467     proto_item_append_text(ti2, ": Id %u", value);
3468     bi->offset++;
3469
3470     value = tvb_get_guint8(bi->tvb, bi->offset);
3471     proto_tree_add_text(tf2, bi->tvb, bi->offset, 1, 
3472                         "IODE: %u", value);
3473     proto_item_append_text(ti2, ", IODE %u", value);
3474     bi->offset++;
3475   }
3476 }
3477
3478 static void 
3479 decode_iei_location_type(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3480   const guint8 LOCATION_ASSISTANCE = 1;
3481   const guint8 DECIPHERING_KEYS = 2;
3482   proto_item *ti;
3483   proto_tree *tf;
3484   guint8 value;
3485
3486   value_string tab_location_information[] = {
3487     { 0, "Current geographic location" },
3488     { 1, "Location assistance information for the target MS" },
3489     { 2, "Deciphering keys for broadcast assistance data for the target MS" },
3490     { 0, NULL },
3491     /* Otherwise "Reserved" */
3492   };
3493
3494   value_string tab_positioning_method[] = {
3495     { 0, "Reserved" },
3496     { 1, "Mobile Assisted E-OTD" },
3497     { 2, "Mobile Based E-OTD" },
3498     { 3, "Assisted GPS" },
3499     { 0, NULL },
3500     /* Otherwise "Reserved" */
3501   };
3502
3503   if (!bi->bssgp_tree) {
3504     bi->offset += ie->value_length;
3505     return;
3506   }
3507   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3508   tf = proto_item_add_subtree(ti, ett_bssgp_location_type);
3509
3510   value = tvb_get_guint8(bi->tvb, bi->offset);
3511   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, "Location Information: %s",
3512                       val_to_str(value, tab_location_information, 
3513                                  "Reserved"));
3514   bi->offset++;
3515
3516   if ((value == LOCATION_ASSISTANCE) || (value == DECIPHERING_KEYS)) {
3517     value = tvb_get_guint8(bi->tvb, bi->offset);
3518     proto_tree_add_text(tf, bi->tvb, bi->offset, 1, "Positioning Method: %s",
3519                         val_to_str(value, tab_positioning_method, 
3520                                    "Reserved"));
3521     bi->offset++;
3522   }
3523 }
3524
3525 static void 
3526 decode_iei_location_estimate(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3527   /* XXX: Which paragraph in 3GPP TS 23.032?*/
3528   proto_item *ti;
3529
3530   if (bi->bssgp_tree) {
3531     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3532     proto_item_append_text(ti, ": %s", BSSGP_NOT_DECODED);
3533   }
3534   if (ie->value_length != BSSGP_UNKNOWN) {
3535     bi->offset += ie->value_length;
3536   }
3537 }
3538
3539 static void 
3540 decode_iei_positioning_data(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3541   const guint8 MASK_PDD = 0x0f;
3542   const guint8 MASK_METHOD = 0xf8;
3543   const guint8 MASK_USAGE = 0x07;
3544   proto_item *ti, *pi;
3545   proto_tree *tf;
3546   guint8 data, value, i, num_methods;
3547
3548   if (!bi->bssgp_tree) {
3549     bi->offset += ie->value_length;
3550     return;
3551   }  
3552   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3553   tf = proto_item_add_subtree(ti, ett_bssgp_positioning_data);
3554
3555   value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_PDD);
3556   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PDD);
3557   proto_item_append_text(pi, "Positioning Data Discriminator: %s",
3558                       value == 0 ? 
3559                       "Indicate usage of each positioning method that was attempted either successfully or unseccessfully" : 
3560                       "Reserved");
3561   bi->offset++;
3562
3563   num_methods = ie->value_length - 1;
3564   for (i = 0; i < num_methods; i++) {
3565     data = tvb_get_guint8(bi->tvb, bi->offset);
3566
3567     value = get_masked_guint8(data, MASK_METHOD);
3568     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_METHOD);
3569     proto_item_append_text(pi, "Method: ");
3570     
3571     switch (value) {
3572     case 0: proto_item_set_text(pi, "Timing Advance"); break;
3573     case 1: proto_item_set_text(pi, "Reserved"); break;
3574     case 2: proto_item_set_text(pi, "Reserved"); break;
3575     case 3: proto_item_set_text(pi, "Mobile Assisted E-OTD"); break;
3576     case 4: proto_item_set_text(pi, "Mobile Based E-OTD"); break;
3577     case 5: proto_item_set_text(pi, "Mobile Assisted GPS"); break;
3578     case 6: proto_item_set_text(pi, "Mobile Based GPS"); break;
3579     case 7: proto_item_set_text(pi, "Conventional GPS"); break;
3580     case 8: proto_item_set_text(pi, "U-TDOA"); break;
3581     default:
3582       if ((value >= 9) && (value <= 0x0f)) {
3583         proto_item_set_text(pi, "Reserved for GSM");
3584       }
3585       else {
3586         proto_item_set_text(pi, "Reserved for network specific positioning methods");
3587       }
3588     };
3589     proto_item_append_text(pi, " (%#02x)", value); /* Method */
3590     
3591     value = get_masked_guint8(data, MASK_USAGE);
3592
3593     switch (value) {
3594     case 0: proto_item_append_text(pi, " attempted unsuccessfully due to failure or interuption "); break;
3595     case 1: proto_item_append_text(pi, " attempted successfully: results not used to generate location"); break;
3596     case 2: proto_item_append_text(pi, " attempted successfully: results used to verify but not generate location"); break;
3597     case 3: proto_item_append_text(pi, "attempted successfully: results used to generate location"); break;
3598     case 4: proto_item_append_text(pi, "a temmpted successfully: case where MS supports multiple mobile based positioning methods and the actual method or methods used by the MS cannot be determined"); break;
3599     default: ; /* ??? */    
3600     }
3601     proto_item_append_text(pi, " (%#x)", value); /* Usage */
3602     bi->offset++;
3603   }
3604 }
3605
3606 static void 
3607 decode_iei_deciphering_keys(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3608   const guint8 MASK_KEY_FLAG = 0x01;
3609   proto_item *ti, *pi;
3610   proto_tree *tf;
3611   guint8 data, value;
3612
3613   if (!bi->bssgp_tree) {
3614     bi->offset += ie->value_length;
3615     return;
3616   }
3617
3618   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3619   tf = proto_item_add_subtree(ti, ett_bssgp_deciphering_keys);
3620
3621   data = tvb_get_guint8(bi->tvb, bi->offset);
3622   value = get_masked_guint8(data, MASK_KEY_FLAG);
3623   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_KEY_FLAG);
3624   proto_item_append_text(pi, "Ciphering Key Flag: %u", value);
3625   bi->offset++;
3626
3627   proto_tree_add_text(tf, bi->tvb, bi->offset, 7,
3628                       "Current Deciphering Key Value");
3629   bi->offset += 7;
3630
3631   proto_tree_add_text(tf, bi->tvb, bi->offset, 7, 
3632                       "Next Deciphering Key Value");
3633   bi->offset += 7;
3634 }
3635
3636 static void 
3637 decode_iei_lcs_priority(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3638   /* XXX: coding (3GPP TS 29.002 7.6.11.7)? */
3639   proto_item *ti;
3640
3641   if (bi->bssgp_tree) {
3642     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3643     proto_item_append_text(ti, ": %s", BSSGP_NOT_DECODED);
3644   }
3645   bi->offset += ie->value_length;
3646 }
3647
3648 static void 
3649 decode_iei_lcs_cause(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3650   proto_item *ti;
3651   proto_tree *tf;
3652   guint8 value;
3653
3654   value_string tab_cause_value[] = {
3655     { 0, "Unspecified" },
3656     { 1, "System failure" },
3657     { 2, "Protocol error" },
3658     { 3, "Data missing in position request" },
3659     { 4, "Unexpected value in position request" },
3660     { 5, "Position method failure" },
3661     { 6, "Target MS unreacheable" },
3662     { 7, "Location request aborted" },
3663     { 8, "Facility not supported" },
3664     { 9, "Inter-BSC handover ongoing" },
3665     { 10, "Intra-BSC handover ongoing" },
3666     { 11, "Congestion" },
3667     { 12, "Inter NSE cell change" },
3668     { 13, "Routeing area update" },
3669     { 14, "PTMSI reallocation" },
3670     { 15, "Suspension of GPRS services" },
3671     { 0, NULL },
3672     /* Otherwise "Unspecified" */
3673   };
3674
3675   value_string tab_diagnostic_value[] = {
3676     { 0, "Congestion" },
3677     { 1, "Insufficient resources" },
3678     { 2, "Insufficient measurement data" },
3679     { 3, "Inconsistent measurement data" },
3680     { 4, "Location procedure not completed" },
3681     { 5, "Location procedure not supported by target MS" },
3682     { 6, "QoS not attainable" },
3683     { 7, "Position method not available in network" },
3684     { 8, "Position method not available in location area" },
3685     { 0, NULL },
3686     /* Otherwise "Unrecognized => ignored" */
3687   };
3688
3689   if (!bi->bssgp_tree) {
3690     bi->offset += ie->value_length;
3691     return;
3692   }
3693   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3694   value = tvb_get_guint8(bi->tvb, bi->offset);
3695
3696   if (ie->value_length == 1) {
3697     /* Diagnostic value not included */
3698     proto_item_append_text(ti, ": %s (%#02x)",
3699                          val_to_str(value, tab_cause_value, "Unspecified"),
3700                          value);
3701     bi->offset++;
3702     return;
3703   }
3704
3705   tf = proto_item_add_subtree(ti, ett_bssgp_lcs_cause);
3706
3707   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, ": %s (%#02x)",
3708                          val_to_str(value, tab_cause_value, "Unspecified"),
3709                          value);
3710   bi->offset++;
3711   
3712   value = tvb_get_guint8(bi->tvb, bi->offset);
3713   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, ": %s (%#02x)",
3714                          val_to_str(value, tab_diagnostic_value, 
3715                                     "Unrecognized => ignored"),
3716                       value);
3717   bi->offset++;
3718 }
3719
3720 static void 
3721 decode_iei_lcs_capability(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3722   const guint8 MASK_OTD_A = 0x10;
3723   const guint8 MASK_OTD_B = 0x08;
3724   const guint8 MASK_GPS_A = 0x04;
3725   const guint8 MASK_GPS_B = 0x02;
3726   const guint8 MASK_GPS_C = 0x01;
3727   proto_item *ti, *pi;
3728   proto_tree *tf;
3729   guint8 data, value;
3730
3731   if (!bi->bssgp_tree) {
3732     bi->offset += ie->value_length;
3733     return;
3734   }
3735   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3736   tf = proto_item_add_subtree(ti, ett_bssgp_lcs_capability);
3737
3738   data = tvb_get_guint8(bi->tvb, bi->offset);
3739
3740   value = get_masked_guint8(data, MASK_OTD_A);
3741   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_OTD_A);
3742   proto_item_append_text(pi, "OTD-A: MS Assisted E-OTD%s supported",
3743                          value == 0 ? " not" : "");
3744
3745   value = get_masked_guint8(data, MASK_OTD_B);
3746   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_OTD_B);
3747   proto_item_append_text(pi, "OTD-B: MS Based E-OTD%s supported",
3748                          value == 0 ? " not" : "");
3749
3750   value = get_masked_guint8(data, MASK_GPS_A);
3751   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_GPS_A);
3752   proto_item_append_text(pi, "GPS-A: MS Assisted GPS%s supported",
3753                          value == 0 ? " not" : "");
3754
3755   value = get_masked_guint8(data, MASK_GPS_B);
3756   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_GPS_B);
3757   proto_item_append_text(pi, "GPS-B: MS Based GPS%s supported",
3758                          value == 0 ? " not" : "");
3759
3760   value = get_masked_guint8(data, MASK_GPS_C);
3761   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_GPS_C);
3762   proto_item_append_text(pi, "GPS-C: Conventional GPS%s supported",
3763                          value == 0 ? " not" : "");
3764
3765   bi->offset++;
3766 }
3767
3768 static void 
3769 decode_iei_rrlp_flags(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3770   const guint8 MASK_FLAG1 = 0x01;
3771   proto_item *ti;
3772   guint8 value;
3773
3774   if (bi->bssgp_tree) {
3775     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3776     value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_FLAG1);
3777     proto_item_append_text(ti, ": Flag1:%s Position Command (BSS to SGSN) or final response (SGSN to BSS) (%u)",
3778                            value == 0 ? " Not a" : "", value);    
3779   }
3780   bi->offset++;
3781 }
3782
3783 static void 
3784 decode_iei_rim_application_identity(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3785   proto_item *ti;
3786   guint8 value;
3787
3788   if (bi->bssgp_tree) {
3789     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3790     value = tvb_get_guint8(bi->tvb, bi->offset);
3791     switch (value) {
3792     case 0: proto_item_append_text(ti, ": Reserved"); break;
3793     case 1: proto_item_append_text(ti, ": Network Assisted Cell Change (NACC)"); break;
3794     default: proto_item_append_text(ti, ": Reserved");
3795     }
3796   }
3797   bi->offset++;
3798 }
3799
3800 static void 
3801 decode_ran_information_common(build_info_t *bi, proto_tree *parent_tree) {
3802   proto_tree *tf;
3803   proto_item *ti;
3804   char *rai_ci;
3805   guint8 num_rai_cis, i;
3806
3807   ti = proto_tree_add_text(parent_tree, bi->tvb, bi->offset, 8, 
3808                            "RAI + CI for Source Cell");
3809   tf = proto_item_add_subtree(ti, ett_bssgp_rai_ci);
3810
3811   rai_ci = decode_rai_ci(bi, tf);
3812   proto_item_append_text(ti, ": %s", rai_ci);
3813
3814   num_rai_cis = tvb_get_guint8(bi->tvb, bi->offset);
3815   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, 
3816                       "%u ""RAI+CI for Destination Cell"" follow%s", 
3817                       num_rai_cis, (num_rai_cis == 0) ? "" : "s");
3818   bi->offset++;
3819
3820   for (i = 0; i < num_rai_cis; i++) {
3821     ti = proto_tree_add_text(parent_tree, bi->tvb, bi->offset, 8, 
3822                              """RAI + CI for Destination Cell"" (%u)", i + 1);
3823     tf = proto_item_add_subtree(ti, ett_bssgp_rai_ci);
3824     rai_ci = decode_rai_ci(bi, tf);
3825     proto_item_append_text(ti, ": %s", rai_ci);
3826   }
3827 }
3828
3829 static void 
3830 decode_iei_ran_information_request_container_unit(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3831   proto_item *ti;
3832   proto_tree *tf;
3833
3834   if (! bi->bssgp_tree) {
3835     bi->offset += 8;
3836     return;
3837   }
3838   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3839   tf = proto_item_add_subtree(ti, ett_bssgp_ran_information_request_container_unit);
3840  
3841   decode_ran_information_common(bi, tf);
3842 }
3843
3844 static void 
3845 decode_iei_ran_information_container_unit(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3846   const guint8 MASK_NUMBER_OF_SI_PSI = 0xfe;
3847   const guint8 MASK_UNIT_TYPE = 0x01;
3848   const guint8 TYPE_SI = 0;
3849   const guint8 TYPE_PSI = 1;
3850   const guint8 LEN_SI = 23;
3851   const guint8 LEN_PSI = 22;
3852   proto_item *ti, *pi;
3853   proto_tree *tf;
3854   guint8 num_si_psi, type_si_psi, data, i;
3855
3856   if (! bi->bssgp_tree) {
3857     bi->offset += 8;
3858     return;
3859   }
3860   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3861 &nb