From Kovarththanan Rajaratnam via bug 3548:
[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  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26 /* 3GPP TS 48.018 V 6.5.0 (2004-07) Release 6 */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36 #include <glib.h>
37 #include <epan/packet.h>
38 #include <prefs.h>
39
40 #include "packet-bssgp.h"
41 #include "packet-e212.h"
42 #include "packet-gsm_a_common.h"
43
44 /* #define BSSGP_DEBUG */
45 #define BSSGP_LITTLE_ENDIAN FALSE
46 #define BSSGP_TRANSLATION_MAX_LEN 50
47 #define BSSGP_MASK_LEFT_OCTET_HALF 0xf0
48 #define BSSGP_MASK_RIGHT_OCTET_HALF 0x0f
49 #define BSSGP_MOBILE_IDENTITY_TYPE_IMSI 1
50 #define BSSGP_MOBILE_IDENTITY_TYPE_IMEI 2
51 #define BSSGP_MOBILE_IDENTITY_TYPE_IMEISV 3
52 #define BSSGP_MOBILE_IDENTITY_TYPE_TMSI_PTMSI 4
53 #define BSSGP_MOBILE_IDENTITY_TYPE_NO_IDENTITY 0
54 #define BSSGP_SEP ", "
55 #define BSSGP_NOT_DECODED "< Not decoded yet >"
56 #define BSSGP_UNKNOWN (-1)
57 static int bssgp_decode_nri = 0;
58 static guint bssgp_nri_length = 4;
59
60 static dissector_handle_t llc_handle;
61 static dissector_handle_t rrlp_handle;
62 static dissector_handle_t data_handle;
63
64 module_t *bssgp_module;
65
66 /* Initialize the protocol and registered fields */
67 static int hf_bssgp_iei_nacc_cause = -1;
68 static int proto_bssgp = -1;
69 static int hf_bssgp_pdu_type = -1;
70 static int hf_bssgp_ie_type = -1;
71 static int hf_bssgp_mcc = -1;
72 static int hf_bssgp_mnc = -1;
73 static int hf_bssgp_lac = -1;
74 static int hf_bssgp_rac = -1;
75 static int hf_bssgp_ci = -1;
76 static int hf_bssgp_ra_discriminator = -1;
77 static int hf_bssgp_appid = -1;
78 static int hf_bssgp_rcid = -1;
79 static int hf_bssgp_rrc_si_msg_type = -1;
80 static int hf_ran_inf_req_pdu_type_ext = -1;
81 static int hf_ran_inf_pdu_type_ext = -1;
82 static int hf_bssgp_nri = -1;
83 static int hf_bssgp_imsi = -1;
84 static int hf_bssgp_imei = -1;
85 static int hf_bssgp_imeisv = -1;
86 static int hf_bssgp_tmsi_ptmsi = -1;
87 static int hf_bssgp_bvci = -1;
88 static int hf_bssgp_nsei = -1;
89 static int hf_bssgp_tlli = -1;
90
91 /* Initialize the subtree pointers */
92 static gint ett_bssgp = -1;
93 static gint ett_bssgp_qos_profile = -1;
94 static gint ett_bssgp_gprs_timer = -1;
95 static gint ett_bssgp_cell_identifier = -1;
96 static gint ett_bssgp_channel_needed = -1;
97 static gint ett_bssgp_drx_parameters = -1;
98 static gint ett_bssgp_mobile_identity = -1;
99 static gint ett_bssgp_priority = -1;
100 static gint ett_bssgp_lsa_identifier_list = -1;
101 static gint ett_bssgp_lsa_information = -1;
102 static gint ett_bssgp_lsa_information_lsa_identification_and_attributes = -1;
103 static gint ett_bssgp_abqp = -1;
104 static gint ett_bssgp_lcs_qos = -1;
105 static gint ett_bssgp_lcs_client_type = -1;
106 static gint ett_bssgp_requested_gps_assistance_data = -1;
107 static gint ett_bssgp_requested_gps_assistance_data_satellite = -1;
108 static gint ett_bssgp_location_type = -1;
109 static gint ett_bssgp_positioning_data_positioning_method = -1;
110 static gint ett_bssgp_deciphering_keys = -1;
111 static gint ett_bssgp_lcs_cause = -1;
112 static gint ett_bssgp_lcs_capability = -1;
113 static gint ett_bssgp_rrlp_flags = -1;
114 static gint ett_bssgp_rim_pdu_indications = -1;
115 static gint ett_bssgp_mcc = -1;
116 static gint ett_bssgp_mnc = -1;
117 static gint ett_bssgp_routing_area = -1;
118 static gint ett_bssgp_location_area = -1;
119 static gint ett_bssgp_rai_ci = -1;
120 static gint ett_bssgp_rim_routing_information =-1;
121 static gint ett_bssgp_ran_information_request_application_container = -1;
122 static gint ett_bssgp_ran_information_request_container_unit = -1;
123 static gint ett_bssgp_ran_information_container_unit = -1;
124 static gint ett_bssgp_pfc_flow_control_parameters = -1;
125 static gint ett_bssgp_pfc_flow_control_parameters_pfc = -1;
126 static gint ett_bssgp_global_cn_id = -1;
127 static gint ett_bssgp_ms_radio_access_capability = -1;
128 static gint ett_bssgp_msrac_value_part = -1;
129 static gint ett_bssgp_msrac_additional_access_technologies = -1;
130 static gint ett_bssgp_msrac_access_capabilities = -1;
131 static gint ett_bssgp_msrac_a5_bits = -1;
132 static gint ett_bssgp_msrac_multislot_capability = -1;
133 static gint ett_bssgp_feature_bitmap = -1;
134 static gint ett_bssgp_positioning_data = -1;
135 static gint ett_bssgp_tlli = -1;
136 static gint ett_bssgp_tmsi_ptmsi = -1;
137
138 /* PDU type coding, v6.5.0, table 11.3.26, p 80 */
139 #define BSSGP_PDU_DL_UNITDATA                  0x00
140 #define BSSGP_PDU_UL_UNITDATA                  0x01
141 #define BSSGP_PDU_RA_CAPABILITY                0x02
142 #define BSSGP_PDU_PTM_UNITDATA                 0x03
143 #define BSSGP_PDU_PAGING_PS                    0x06
144 #define BSSGP_PDU_PAGING_CS                    0x07
145 #define BSSGP_PDU_RA_CAPABILITY_UPDATE         0x08
146 #define BSSGP_PDU_RA_CAPABILITY_UPDATE_ACK     0x09
147 #define BSSGP_PDU_RADIO_STATUS                 0x0a
148 #define BSSGP_PDU_SUSPEND                      0x0b
149 #define BSSGP_PDU_SUSPEND_ACK                  0x0c
150 #define BSSGP_PDU_SUSPEND_NACK                 0x0d
151 #define BSSGP_PDU_RESUME                       0x0e
152 #define BSSGP_PDU_RESUME_ACK                   0x0f
153 #define BSSGP_PDU_RESUME_NACK                  0x10
154 #define BSSGP_PDU_BVC_BLOCK                    0x20
155 #define BSSGP_PDU_BVC_BLOCK_ACK                0x21
156 #define BSSGP_PDU_BVC_RESET                    0x22
157 #define BSSGP_PDU_BVC_RESET_ACK                0x23
158 #define BSSGP_PDU_BVC_UNBLOCK                  0x24
159 #define BSSGP_PDU_BVC_UNBLOCK_ACK              0x25
160 #define BSSGP_PDU_FLOW_CONTROL_BVC             0x26
161 #define BSSGP_PDU_FLOW_CONTROL_BVC_ACK         0x27
162 #define BSSGP_PDU_FLOW_CONTROL_MS              0x28
163 #define BSSGP_PDU_FLOW_CONTROL_MS_ACK          0x29
164 #define BSSGP_PDU_FLUSH_LL                     0x2a
165 #define BSSGP_PDU_FLUSH_LL_ACK                 0x2b
166 #define BSSGP_PDU_LLC_DISCARDED                0x2c
167 #define BSSGP_PDU_FLOW_CONTROL_PFC             0x2d
168 #define BSSGP_PDU_FLOW_CONTROL_PFC_ACK         0x2e
169 #define BSSGP_PDU_SGSN_INVOKE_TRACE            0x40
170 #define BSSGP_PDU_STATUS                       0x41
171 #define BSSGP_PDU_DOWNLOAD_BSS_PFC             0x50
172 #define BSSGP_PDU_CREATE_BSS_PFC               0x51
173 #define BSSGP_PDU_CREATE_BSS_PFC_ACK           0x52
174 #define BSSGP_PDU_CREATE_BSS_PFC_NACK          0x53
175 #define BSSGP_PDU_MODIFY_BSS_PFC               0x54
176 #define BSSGP_PDU_MODIFY_BSS_PFC_ACK           0x55
177 #define BSSGP_PDU_DELETE_BSS_PFC               0x56
178 #define BSSGP_PDU_DELETE_BSS_PFC_ACK           0x57
179 #define BSSGP_PDU_DELETE_BSS_PFC_REQ           0x58
180 #define BSSGP_PDU_PERFORM_LOCATION_REQUEST     0x60
181 #define BSSGP_PDU_PERFORM_LOCATION_RESPONSE    0x61
182 #define BSSGP_PDU_PERFORM_LOCATION_ABORT       0x62
183 #define BSSGP_PDU_POSITION_COMMAND             0x63
184 #define BSSGP_PDU_POSITION_RESPONSE            0x64
185 #define BSSGP_PDU_RAN_INFORMATION              0x70
186 #define BSSGP_PDU_RAN_INFORMATION_REQUEST      0x71
187 #define BSSGP_PDU_RAN_INFORMATION_ACK          0x72
188 #define BSSGP_PDU_RAN_INFORMATION_ERROR        0x73
189 #define BSSGP_PDU_RAN_APPLICATION_ERROR        0x74
190
191 static const value_string tab_bssgp_pdu_types[] = {
192   { BSSGP_PDU_DL_UNITDATA,                  "DL-UNITDATA" },
193   { BSSGP_PDU_UL_UNITDATA,                  "UL-UNITDATA" },
194   { BSSGP_PDU_RA_CAPABILITY,                "RA-CAPABILITY" },
195   { BSSGP_PDU_PTM_UNITDATA,                 "PTM-UNITDATA" },
196   { BSSGP_PDU_PAGING_PS,                    "PAGING-PS" },
197   { BSSGP_PDU_PAGING_CS,                    "PAGING-CS" },
198   { BSSGP_PDU_RA_CAPABILITY_UPDATE,         "RA-CAPABILITY-UPDATE" },
199   { BSSGP_PDU_RA_CAPABILITY_UPDATE_ACK,     "RA-CAPABILITY-UPDATE-ACK" },
200   { BSSGP_PDU_RADIO_STATUS,                 "RADIO-STATUS" },
201   { BSSGP_PDU_SUSPEND,                      "SUSPEND" },
202   { BSSGP_PDU_SUSPEND_ACK,                  "SUSPEND-ACK" },
203   { BSSGP_PDU_SUSPEND_NACK,                 "SUSPEND-NACK" },
204   { BSSGP_PDU_RESUME,                       "RESUME" },
205   { BSSGP_PDU_RESUME_ACK,                   "RESUME-ACK" },
206   { BSSGP_PDU_RESUME_NACK,                  "RESUME-NACK" },
207   { BSSGP_PDU_BVC_BLOCK,                    "BVC-BLOCK" },
208   { BSSGP_PDU_BVC_BLOCK_ACK,                "BVC-BLOCK-ACK" },
209   { BSSGP_PDU_BVC_RESET,                    "BVC-RESET" },
210   { BSSGP_PDU_BVC_RESET_ACK,                "BVC-RESET-ACK" },
211   { BSSGP_PDU_BVC_UNBLOCK,                  "UNBLOCK" },
212   { BSSGP_PDU_BVC_UNBLOCK_ACK,              "UNBLOCK-ACK" },
213   { BSSGP_PDU_FLOW_CONTROL_BVC,             "FLOW-CONTROL-BVC" },
214   { BSSGP_PDU_FLOW_CONTROL_BVC_ACK,         "FLOW-CONTROL-BVC-ACK" },
215   { BSSGP_PDU_FLOW_CONTROL_MS,              "FLOW-CONTROL-MS" },
216   { BSSGP_PDU_FLOW_CONTROL_MS_ACK,          "FLOW-CONTROL-MS-ACK" },
217   { BSSGP_PDU_FLUSH_LL,                     "FLUSH-LL" },
218   { BSSGP_PDU_FLUSH_LL_ACK,                 "FLUSH_LL_ACK" },
219   { BSSGP_PDU_LLC_DISCARDED,                "LLC-DISCARDED" },
220   { BSSGP_PDU_FLOW_CONTROL_PFC,             "FLOW-CONTROL-PFC" },
221   { BSSGP_PDU_FLOW_CONTROL_PFC_ACK,         "FLOW-CONTROL-PFC-ACK" },
222   { BSSGP_PDU_SGSN_INVOKE_TRACE,            "SGSN-INVOKE-TRACE" },
223   { BSSGP_PDU_STATUS,                       "STATUS" },
224   { BSSGP_PDU_DOWNLOAD_BSS_PFC,             "DOWNLOAD-BSS-PFC" },
225   { BSSGP_PDU_CREATE_BSS_PFC,               "CREATE-BSS-PFC" },
226   { BSSGP_PDU_CREATE_BSS_PFC_ACK,           "CREATE-BSS-PFC-ACK" },
227   { BSSGP_PDU_CREATE_BSS_PFC_NACK,          "CREATE-BSS-PFC-NACK" },
228   { BSSGP_PDU_MODIFY_BSS_PFC,               "MODIFY-BSS-PFC" },
229   { BSSGP_PDU_MODIFY_BSS_PFC_ACK,           "MODIFY-BSS-PFC-ACK" },
230   { BSSGP_PDU_DELETE_BSS_PFC,               "DELETE-BSS-PFC" },
231   { BSSGP_PDU_DELETE_BSS_PFC_ACK,           "DELETE-BSS-PFC-ACK" },
232   { BSSGP_PDU_DELETE_BSS_PFC_REQ,           "DELETE-BSS-PFC-REQ" },
233   { BSSGP_PDU_PERFORM_LOCATION_REQUEST,     "PERFORM-LOCATION-REQUEST" },
234   { BSSGP_PDU_PERFORM_LOCATION_RESPONSE,    "PERFORM-LOCATION-RESPONSE" },
235   { BSSGP_PDU_PERFORM_LOCATION_ABORT,       "PERFORM-LOCATION-ABORT" },
236   { BSSGP_PDU_POSITION_COMMAND,             "POSITION-COMMAND" },
237   { BSSGP_PDU_POSITION_RESPONSE,            "POSITION-RESPONSE" },
238   { BSSGP_PDU_RAN_INFORMATION,              "RAN-INFORMATION" },
239   { BSSGP_PDU_RAN_INFORMATION_REQUEST,      "RAN-INFORMATION-REQUEST" },
240   { BSSGP_PDU_RAN_INFORMATION_ACK,          "RAN-INFORMATION-ACK" },
241   { BSSGP_PDU_RAN_INFORMATION_ERROR,        "RAN-INFORMATION-ERROR" },
242   { 0,                                NULL },
243 };
244
245 /* Information element coding, v 6.5.0, table 11.3, p 72 */
246 #define BSSGP_IEI_ALIGNMENT_OCTETS                         0x00
247 #define BSSGP_IEI_BMAX_DEFAULT_MS                          0x01
248 #define BSSGP_IEI_BSS_AREA_INDICATION                      0x02
249 #define BSSGP_IEI_BUCKET_LEAK_RATE                         0x03
250 #define BSSGP_IEI_BVCI                                     0x04
251 #define BSSGP_IEI_BVC_BUCKET_SIZE                          0x05
252 #define BSSGP_IEI_BVC_MEASUREMENT                          0x06
253 #define BSSGP_IEI_CAUSE                                    0x07
254 #define BSSGP_IEI_CELL_IDENTIFIER                          0x08
255 #define BSSGP_IEI_CHANNEL_NEEDED                           0x09
256 #define BSSGP_IEI_DRX_PARAMETERS                           0x0a
257 #define BSSGP_IEI_EMLPP_PRIORITY                           0x0b
258 #define BSSGP_IEI_FLUSH_ACTION                             0x0c
259 #define BSSGP_IEI_IMSI                                     0x0d
260 #define BSSGP_IEI_LLC_PDU                                  0x0e
261 #define BSSGP_IEI_LLC_FRAMES_DISCARDED                     0x0f
262 #define BSSGP_IEI_LOCATION_AREA                            0x10
263 #define BSSGP_IEI_MOBILE_ID                                0x11
264 #define BSSGP_IEI_MS_BUCKET_SIZE                           0x12
265 #define BSSGP_IEI_MS_RADIO_ACCESS_CAPABILITY               0x13
266 #define BSSGP_IEI_OMC_ID                                   0x14
267 #define BSSGP_IEI_PDU_IN_ERROR                             0x15
268 #define BSSGP_IEI_PDU_LIFETIME                             0x16
269 #define BSSGP_IEI_PRIORITY                                 0x17
270 #define BSSGP_IEI_QOS_PROFILE                              0x18
271 #define BSSGP_IEI_RADIO_CAUSE                              0x19
272 #define BSSGP_IEI_RA_CAP_UPD_CAUSE                         0x1a
273 #define BSSGP_IEI_ROUTING_AREA                             0x1b
274 #define BSSGP_IEI_R_DEFAULT_MS                             0x1c
275 #define BSSGP_IEI_SUSPEND_REFERENCE_NUMBER                 0x1d
276 #define BSSGP_IEI_TAG                                      0x1e
277 #define BSSGP_IEI_TLLI                                     0x1f
278 #define BSSGP_IEI_TMSI                                     0x20
279 #define BSSGP_IEI_TRACE_REFERENCE                          0x21
280 #define BSSGP_IEI_TRACE_TYPE                               0x22
281 #define BSSGP_IEI_TRANSACTION_ID                           0x23
282 #define BSSGP_IEI_TRIGGER_ID                               0x24
283 #define BSSGP_IEI_NUMBER_OF_OCTETS_AFFECTED                0x25
284 #define BSSGP_IEI_LSA_IDENTIFIER_LIST                      0x26
285 #define BSSGP_IEI_LSA_INFORMATION                          0x27
286 #define BSSGP_IEI_PFI                                      0x28
287 #define BSSGP_IEI_GPRS_TIMER                               0x29
288 #define BSSGP_IEI_ABQP                                     0x3a
289 #define BSSGP_IEI_FEATURE_BITMAP                           0x3b
290 #define BSSGP_IEI_BUCKET_FULL_RATIO                        0x3c
291 #define BSSGP_IEI_SERVICE_UTRAN_CCO                        0x3d
292 #define BSSGP_IEI_NSEI                                     0x3e
293 #define BSSGP_IEI_RRLP_APDU                                0x3f
294 #define BSSGP_IEI_LCS_QOS                                  0x40
295 #define BSSGP_IEI_LCS_CLIENT_TYPE                          0x41
296 #define BSSGP_IEI_REQUESTED_GPS_ASSISTANCE_DATA            0x42
297 #define BSSGP_IEI_LOCATION_TYPE                            0x43
298 #define BSSGP_IEI_LOCATION_ESTIMATE                        0x44
299 #define BSSGP_IEI_POSITIONING_DATA                         0x45
300 #define BSSGP_IEI_DECIPHERING_KEYS                         0x46
301 #define BSSGP_IEI_LCS_PRIORITY                             0x47
302 #define BSSGP_IEI_LCS_CAUSE                                0x48
303 #define BSSGP_IEI_LCS_CAPABILITY                           0x49
304 #define BSSGP_IEI_RRLP_FLAGS                               0x4a
305 #define BSSGP_IEI_RIM_APPLICATION_IDENTITY                 0x4b
306 #define BSSGP_IEI_RIM_SEQUENCE_NUMBER                      0x4c
307 #define BSSGP_IEI_RAN_INFORMATION_REQUEST_APPLICATION_CONTAINER        0x4d
308 #define BSSGP_IEI_RAN_INFORMATION_APPLICATION_CONTAINER                0x4e
309 #define BSSGP_IEI_RIM_PDU_INDICATIONS                                      0x4f
310 #define BSSGP_IEI_NUMBER_OF_CONTAINER_UNITS                0x50
311 #define BSSGP_IEI_PFC_FLOW_CONTROL_PARAMETERS              0x52
312 #define BSSGP_IEI_GLOBAL_CN_ID                             0x53
313 #define BSSGP_IEI_RIM_ROUTING_INFORMATION                                  0x54
314 #define BSSGP_IEI_RIM_PROTOCOL_VERSION                                     0x55
315 #define BSSGP_IEI_APPLICATION_ERROR_CONTAINER                      0x56
316
317 #define BSSGP_IEI_RAN_INFORMATION_REQUEST_CONTAINER_UNIT   0x57
318 #define BSSGP_IEI_RAN_INFORMATION_CONTAINER_UNIT           0x58
319
320 #define BSSGP_IEI_RAN_INFORMATION_APPLICATION_ERROR_CONTAINER_UNIT            0x59
321 #define BSSGP_IEI_RAN_INFORMATION_ACK_RIM_CONTAINER        0x5a
322 #define BSSGP_IEI_RAN_INFORMATION_ERROR_RIM_CONTAINER      0x5b
323
324 static const value_string tab_nacc_cause[]={
325   { 0x00,                       "Other unspecified error" },
326   { 0x01,                       "Syntax error in the Application Container" },
327   { 0x02,                       "Reporting Cell Identifier does not match with the Destination Cell Identifier or with the Source Cell Identifier" },
328   { 0x03,                       "SI/PSI type error" },
329   { 0x04,                       "Inconsistent length of a SI/PSI message" },
330   { 0x05,                       "Inconsistent set of messages" },
331   { 0,                          NULL },
332
333 };
334 static const value_string tab_bssgp_ie_types[] = {
335   { BSSGP_IEI_ALIGNMENT_OCTETS,            "Alignment Octets" },
336   { BSSGP_IEI_BMAX_DEFAULT_MS,             "Bmax Default MS" },
337   { BSSGP_IEI_BSS_AREA_INDICATION,         "BSS Area Indication" },
338   { BSSGP_IEI_BUCKET_LEAK_RATE,            "Bucket Leak Rate" },
339   { BSSGP_IEI_BVCI,                        "BVCI" },
340   { BSSGP_IEI_BVC_BUCKET_SIZE,             "BVC Bucket Size" },
341   { BSSGP_IEI_BVC_MEASUREMENT,             "BVC Measurement" },
342   { BSSGP_IEI_CAUSE,                       "Cause" },
343   { BSSGP_IEI_CELL_IDENTIFIER,             "Cell Identifier" },
344   { BSSGP_IEI_CHANNEL_NEEDED,              "Channel Needed" },
345   { BSSGP_IEI_DRX_PARAMETERS,              "DRX Parameters" },
346   { BSSGP_IEI_EMLPP_PRIORITY,              "eMLPP Priority" },
347   { BSSGP_IEI_FLUSH_ACTION,                "Flush Action" },
348   { BSSGP_IEI_IMSI,                        "IMSI" },
349   { BSSGP_IEI_LLC_PDU,                     "LLC PDU" },
350   { BSSGP_IEI_LLC_FRAMES_DISCARDED,        "LLC Frames Discarded" },
351   { BSSGP_IEI_LOCATION_AREA,               "Location Area" },
352   { BSSGP_IEI_MOBILE_ID,                   "Mobile Id" },
353   { BSSGP_IEI_MS_BUCKET_SIZE,              "MS Bucket Size" },
354   { BSSGP_IEI_MS_RADIO_ACCESS_CAPABILITY,  "MS Radio Access Capability" },
355   { BSSGP_IEI_OMC_ID,                      "OMC Id" },
356   { BSSGP_IEI_PDU_IN_ERROR,                "PDU In Error" },
357   { BSSGP_IEI_PDU_LIFETIME,                "PDU Lifetime" },
358   { BSSGP_IEI_PRIORITY,                    "Priority" },
359   { BSSGP_IEI_QOS_PROFILE,                 "QoS Profile" },
360   { BSSGP_IEI_RADIO_CAUSE,                 "Radio Cause" },
361   { BSSGP_IEI_RA_CAP_UPD_CAUSE,            "RA-Cap-UPD-Cause" },
362   { BSSGP_IEI_ROUTING_AREA,                "Routing Area" },
363   { BSSGP_IEI_R_DEFAULT_MS,                "R_default_MS" },
364   { BSSGP_IEI_SUSPEND_REFERENCE_NUMBER,    "Suspend Reference Number" },
365   { BSSGP_IEI_TAG,                         "Tag" },
366   { BSSGP_IEI_TLLI,                        "TLLI" },
367   { BSSGP_IEI_TMSI,                        "TMSI" },
368   { BSSGP_IEI_TRACE_REFERENCE,             "Trace Reference" },
369   { BSSGP_IEI_TRACE_TYPE,                  "Trace Type" },
370   { BSSGP_IEI_TRANSACTION_ID,              "Transaction Id" },
371   { BSSGP_IEI_TRIGGER_ID,                  "Trigger Id" },
372   { BSSGP_IEI_NUMBER_OF_OCTETS_AFFECTED,   "Number of Octets Affected" },
373   { BSSGP_IEI_LSA_IDENTIFIER_LIST,         "LSA Identifier List" },
374   { BSSGP_IEI_LSA_INFORMATION,             "LSA Information" },
375   { BSSGP_IEI_PFI,                         "Packet Flow Identifier: " },
376   { BSSGP_IEI_GPRS_TIMER,                  "GPRS Timer" },
377   { BSSGP_IEI_ABQP,                        "ABQP" },
378   { BSSGP_IEI_FEATURE_BITMAP,              "Feature Bitmap" },
379   { BSSGP_IEI_BUCKET_FULL_RATIO,           "Bucket Full Ratio" },
380   { BSSGP_IEI_SERVICE_UTRAN_CCO,           "Service UTRAN CCO" },
381   { BSSGP_IEI_NSEI,                        "NSEI" },
382   { BSSGP_IEI_RRLP_APDU,                   "RRLP APDU" },
383   { BSSGP_IEI_LCS_QOS,                     "LCS QoS" },
384   { BSSGP_IEI_LCS_CLIENT_TYPE,             "LCS Client Type" },
385   { BSSGP_IEI_REQUESTED_GPS_ASSISTANCE_DATA, "Requested GPS Assistance Data" },
386   { BSSGP_IEI_LOCATION_TYPE,               "Location Type" },
387   { BSSGP_IEI_LOCATION_ESTIMATE,           "Location Estimate" },
388   { BSSGP_IEI_POSITIONING_DATA,            "Positioning Data" },
389   { BSSGP_IEI_DECIPHERING_KEYS,            "Deciphering Keys" },
390   { BSSGP_IEI_LCS_PRIORITY,                "LCS Priority" },
391   { BSSGP_IEI_LCS_CAUSE,                   "LCS Cause" },
392   { BSSGP_IEI_LCS_CAPABILITY,              "LCS Capability" },
393   { BSSGP_IEI_RRLP_FLAGS,                                                               "RRLP Flags" },
394   { BSSGP_IEI_RIM_APPLICATION_IDENTITY,                                 "RIM Application Identity" },
395   { BSSGP_IEI_RAN_INFORMATION_APPLICATION_CONTAINER,    "RAN INFORMATION Application Container" },
396   { BSSGP_IEI_RIM_SEQUENCE_NUMBER,                                              "RIM Sequence Number" },
397   { BSSGP_IEI_RAN_INFORMATION_REQUEST_CONTAINER_UNIT,   "RAN INFORMATION REQUEST RIM Container" },
398   { BSSGP_IEI_RAN_INFORMATION_CONTAINER_UNIT,                   "RAN INFORMATION RIM Container" },
399   { BSSGP_IEI_RIM_PDU_INDICATIONS,                                              "RIM PDU Indications" },
400   { BSSGP_IEI_RIM_PROTOCOL_VERSION,                                             "RIM Protocol Version Number" },
401   { BSSGP_IEI_NUMBER_OF_CONTAINER_UNITS,                                "Number of Container Units" },
402   { BSSGP_IEI_PFC_FLOW_CONTROL_PARAMETERS,                              "PFC Flow Control Parameters" },
403   { BSSGP_IEI_GLOBAL_CN_ID,                                                             "Global CN Id" },
404   { 0,                                NULL },
405 };
406
407 /* Presence requirements of Information Elements
408    48.016 v 5.3.0, chapter 8.1.1, p. 35 */
409 #define BSSGP_IE_PRESENCE_M 1   /* Mandatory */
410 #define BSSGP_IE_PRESENCE_O 2   /* Conditional */
411 #define BSSGP_IE_PRESENCE_C 3   /* Optional */
412
413 /* Format options */
414 #define BSSGP_IE_FORMAT_V 1
415 #define BSSGP_IE_FORMAT_TV 2
416 #define BSSGP_IE_FORMAT_TLV 3
417
418
419 static guint8
420 get_masked_guint8(guint8 value, guint8 mask) {
421   const guint8 MASK_BIT_1 = 0x01;
422   guint8 i = 0;
423
424   while (!((mask >> i) & MASK_BIT_1)) {
425     i++;
426     if (i > 7) return 0;
427   }
428   return (value & mask) >> i;
429 }
430
431 #if 0
432 static guint16
433 get_masked_guint16(guint16 value, guint16 mask) {
434   const guint16 MASK_BIT_1 = 0x01;
435   guint8 i = 0;
436
437   while (!((mask >> i) & MASK_BIT_1)) {
438     i++;
439     if (i > 15) return 0;
440   }
441   return (value & mask) >> i;
442 }
443 #endif
444
445 static gint32
446 make_mask32(guint8 num_bits, guint8 shift_value) {
447   const guint32 LEFT_MOST_1 = 0x80000000;
448   int i;
449   guint32 mask = LEFT_MOST_1;
450
451   for (i = 0; i < (num_bits - 1); i++) {
452     mask = (mask >> 1) | LEFT_MOST_1;
453   }
454   return mask >> shift_value;
455 }
456
457 static guint32
458 get_masked_guint32(guint32 value, guint32 mask) {
459   const guint16 MASK_BIT_1 = 0x01;
460   guint8 i = 0;
461
462   while (!((mask >> i) & MASK_BIT_1)) {
463     i++;
464     if (i > 31) return 0;
465   }
466   return (value & mask) >> i;
467 }
468
469 static guint8
470 tvb_get_masked_guint8(tvbuff_t *tvb, int offset, guint8 mask) {
471   guint8 value = tvb_get_guint8(tvb, offset);
472   return get_masked_guint8(value, mask);
473 }
474
475 static char*
476 get_bit_field_label(guint16 value, guint16 value_mask, guint16 num_bits) {
477 #define MAX_NUM_BITS 16
478   guint16 i, bit_mask;
479   static char label[MAX_NUM_BITS + 1];
480
481   DISSECTOR_ASSERT(num_bits <= MAX_NUM_BITS);
482   for (i = 0; i < num_bits; i++) {
483     bit_mask = 1 << i;
484     if (value_mask & bit_mask) {
485       label[num_bits - 1 - i] = (value & bit_mask) ? '1' : '0';
486     }
487     else {
488       label[num_bits - 1 - i] = '.';
489     }
490   }
491 #undef MAX_NUM_BITS
492   return label;
493 }
494
495 static char*
496 get_bit_field_label8(guint8 value, guint8 value_mask) {
497   char *bits;
498   static char formatted_label[10];
499   bits = get_bit_field_label(value, value_mask, 8);
500   g_snprintf(formatted_label, 10, "%c%c%c%c %c%c%c%c",
501              bits[0], bits[1], bits[2], bits[3],
502              bits[4], bits[5], bits[6], bits[7]);
503   return formatted_label;
504 }
505
506 static char*
507 get_bit_field_label16(guint16 value, guint16 value_mask) {
508   char *bits;
509   static char formatted_label[18];
510   bits = get_bit_field_label(value, value_mask, 16);
511   g_snprintf(formatted_label, 18, "%c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
512              bits[0], bits[1], bits[2], bits[3],
513              bits[4], bits[5], bits[6], bits[7],
514              bits[8], bits[9], bits[10], bits[11],
515              bits[12], bits[13], bits[14], bits[15]);
516   return formatted_label;
517 }
518
519 static proto_item *
520 proto_tree_add_bitfield8(proto_tree *tree, tvbuff_t *tvb, int offset, guint8 mask) {
521   /* XXX: Use varargs */
522   guint8 value = tvb_get_guint8(tvb, offset);
523   char *label = get_bit_field_label8(value, mask);
524   proto_item *pi = proto_tree_add_text(tree, tvb, offset, 1, "%s = ",
525                                        label);
526   return pi;
527 }
528
529 #if 0
530 static proto_item *
531 proto_tree_add_bitfield16(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 mask) {
532   /* XXX: Use varargs */
533   guint16 value = tvb_get_ntohs(tvb, offset);
534   char *label = get_bit_field_label16(value, mask);
535   proto_item *pi = proto_tree_add_text(tree, tvb, offset, 2, "%s = ",
536                                        label);
537   return pi;
538 }
539 #endif
540
541 static guint8
542 get_byte_offset(guint64 bo) {
543   return (guint8) bo % 8;
544 }
545
546 static guint32
547 get_start_octet(guint64 bo) {
548   return (guint32) floor((gint64)bo / 8.0);
549 }
550
551 static guint32
552 get_end_octet(guint64 bo, guint32 bl)
553 {
554   return (guint32) ceil((gint64)(bo + bl) / 8.0);
555 }
556
557 static guint32
558 get_num_octets_spanned(guint64 bo, guint32 bl)
559 {
560   return get_end_octet(bo, bl) - get_start_octet(bo);
561 }
562
563 static gint16
564 make_mask(guint8 num_bits, guint8 shift_value) {
565   guint16 mask;
566
567   switch (num_bits) {
568   case 0: mask = 0x0000; break;
569   case 1: mask = 0x8000; break;
570   case 2: mask = 0xc000; break;
571   case 3: mask = 0xe000; break;
572   case 4: mask = 0xf000; break;
573   case 5: mask = 0xf800; break;
574   case 6: mask = 0xfc00; break;
575   case 7: mask = 0xfe00; break;
576   case 8: mask = 0xff00; break;
577   default: DISSECTOR_ASSERT_NOT_REACHED(); mask = 0; break;
578   }
579   return mask >> shift_value;
580 }
581
582 static guint8
583 bssgp_tvb_get_bits8(tvbuff_t *tvb, guint64 bo, guint8 num_bits) {
584   /* Returns 0-8 bits from tvb */
585   guint8 shift_value;
586   guint16 mask, data;
587
588   shift_value = get_byte_offset(bo);
589   mask = make_mask(num_bits, shift_value);
590   if (( mask & 0xff ) == 0 ) data = tvb_get_guint8(tvb, get_start_octet(bo)) << 8;
591   else data = tvb_get_ntohs(tvb, get_start_octet(bo));
592   return (data & mask) >> (16 - shift_value - num_bits);
593 }
594
595 static proto_item *
596 bit_proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb,
597                         guint64 bo, guint8 bl, const char *value) {
598   /* XXX: Use varargs */
599   return proto_tree_add_text(tree, tvb, get_start_octet(bo),
600                              get_num_octets_spanned(bo, bl), "%s", value);
601 }
602
603 static proto_item *
604 bit_proto_tree_add_bit_field8(proto_tree *tree, tvbuff_t *tvb,
605                               guint64 bo, guint8 bl) {
606   /* XXX: Use varargs */
607   guint16 mask = make_mask(bl, get_byte_offset(bo));
608   guint16 value;
609   guint8 end_i;
610   int i;
611   proto_item *pi;
612   char *label;
613   if (( mask & 0xff ) == 0 ) value = tvb_get_guint8 ( tvb , get_start_octet(bo)) << 8;
614   else value = tvb_get_ntohs(tvb, get_start_octet(bo));
615   label = get_bit_field_label16(value, mask);
616
617   DISSECTOR_ASSERT(bl < 9);
618
619   if (get_num_octets_spanned(bo, bl) == 1) {
620     end_i = 7;
621   }
622   else {
623     end_i = 16;
624   }
625   pi = bit_proto_tree_add_text(tree, tvb, bo, bl, "");
626
627   for (i = 0; i <=end_i; i++) {
628     proto_item_append_text(pi, "%c", label[i]);
629   }
630   proto_item_append_text(pi, " = ");
631   return pi;
632 }
633
634 static const char*
635 translate_abqp_reliability_class(guint8 value, build_info_t *bi) {
636   switch (value) {
637   case 0:
638     if (bi->ul_data) {
639       return "Subscribed reliability class";
640     }
641     else {
642       return "Reserved";
643     }
644   case 1:
645     return "Unused (Unacknowledged GTP; Acknowledged LLc and RLC, Protected data)";
646   case 2:
647     return "Unacknowledged GTP; Acknowledged LLc and RLC, Protected data";
648   case 3:
649     return "Unacknowledged GTP and LLC; Acknowledged RLC, Protected data";
650   case 4:
651     return "Unacknowledged GTP, LLC, and RLC, Protected data";
652   case 5:
653     return "Unacknowledged GTP, LLC, and RLC, Unprotedcted data";
654   case 7:
655     return "Reserved";
656   default:
657     return "Unacknowledged GTP and LLC; Acknowledged RLC, Protected data";
658   }
659 }
660 static const char*
661 translate_abqp_delay_class(guint8 value, build_info_t *bi) {
662   switch (value) {
663   case 0:
664     if (bi->ul_data) {
665       return "Subscribed delay class";
666     }
667     else {
668       return "Reserved";
669     }
670   case 1: return "Delay class 1";
671   case 2: return "Delay class 2";
672   case 3: return "Delay class 3";
673   case 4: return "Delay class 4 (best effort)";
674   case 7: return "Reserved";
675   default:
676     return "Delay class 4 (best effort)";
677   }
678 }
679 static const char*
680 translate_abqp_peak_throughput(guint8 value, build_info_t *bi) {
681   switch (value) {
682   case 0:
683     if (bi->ul_data) {
684       return "Subscribed peak throughput";
685     }
686     else {
687       return "Reserved";
688     }
689   case 1: return "Up to 1 000 octets/s";
690   case 2: return "Up to 2 000 octets/s";
691   case 3: return "Up to 4 000 octets/s";
692   case 4: return "Up to 8 000 octets/s";
693   case 5: return "Up to 16 000 octets/s";
694   case 6: return "Up to 32 000 octets/s";
695   case 7: return "Up to 64 000 octets/s";
696   case 8: return "Up to 128 000 octets/s";
697   case 9: return "Up to 256 000 octets/s";
698   case 15: return "Reserved";
699   default:
700     return "Up to 1 000 octets/s";
701   }
702 }
703 static const char*
704 translate_abqp_precedence_class(guint8 value, build_info_t *bi) {
705   switch (value) {
706   case 0:
707     if (bi->ul_data) {
708       return "Subscribed precedence";
709     }
710     else {
711       return "Reserved";
712     }
713   case 1: return "High priority";
714   case 2: return "Normal priority";
715   case 3: return "Low priority";
716   case 7: return "Reserved";
717   default:
718     return "Normal priority";
719   }
720 }
721 static const char*
722 translate_abqp_mean_throughput(guint8 value, build_info_t *bi) {
723   switch (value) {
724   case 0:
725     if (bi->ul_data) {
726       return "Subscribed mean throughput";
727     }
728     else {
729       return "Reserved";
730     }
731   case 1: return "100 octets/h";
732   case 2: return "200 octets/h";
733   case 3: return "500 octets/h";
734   case 4: return "1 000 octets/h";
735   case 5: return "2 000 octets/h";
736   case 6: return "5 000 octets/h";
737   case 7: return "10 000 octets/h";
738   case 8: return "20 000 octets/h";
739   case 9: return "50 000 octets/h";
740   case 0x0a: return "100 000 octets/h";
741   case 0x0b: return "200 000 octets/h";
742   case 0x0c: return "500 000 octets/h";
743   case 0x0d: return "1 000 000 octets/h";
744   case 0x0e: return "2 000 000 octets/h";
745   case 0x0f: return "5 000 000 octets/h";
746   case 0x10: return "10 000 000 octets/h";
747   case 0x11: return "20 000 000 octets/h";
748   case 0x12: return "50 000 000 octets/h";
749   case 0x1e: return "Reserved";
750   case 0x1f: return "Best effort";
751   default:
752     return "Best effort";
753   }
754 }
755 static const char*
756 translate_abqp_traffic_class(guint8 value, build_info_t *bi) {
757   switch (value) {
758   case 0:
759     if (bi->ul_data) {
760       return "Subscribed traffic class";
761     }
762     else {
763       return "Reserved";
764     }
765   case 1: return "Conversational class";
766   case 2: return "Streaming class";
767   case 3: return "Interactive class";
768   case 4: return "Background class";
769   case 7: return "Reserved";
770   default:
771     if (bi->ul_data) {
772       /* The MS shall consider all other values as reserved */
773       return "Reserved";
774     }
775     else {
776       /* 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 */
777       return "Error";
778     }
779   }
780 }
781 static const char*
782 translate_abqp_delivery_order(guint8 value, build_info_t *bi) {
783   switch (value) {
784   case 0:
785     if (bi->ul_data) {
786       return "Subscribed delivery order";
787     }
788     else {
789       return "Reserved";
790     }
791   case 1: return "With delivery order ('yes')";
792   case 2: return "Without delivery order ('no')";
793   case 3: return "Reserved";
794   default:
795     return "Error in BSSGP dissector";
796   }
797 }
798 static const char*
799 translate_abqp_delivery_of_erroneous_sdu(guint8 value, build_info_t *bi) {
800   switch (value) {
801   case 0:
802     if (bi->ul_data) {
803       return "Subscribed delivery of erroneous SDUs";
804     }
805     else {
806       return "Reserved";
807     }
808   case 1: return "No detect ('-')";
809   case 2: return "Erroneous SDUs are delivered ('yes')";
810   case 3: return "Erroneous SDUs are not delivered ('no')";
811   case 7: return "Reserved";
812   default:
813     if (bi->ul_data) {
814       /* The MS shall consider all other values as reserved */
815       return "Reserved";
816     }
817     else {
818       /* 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 */
819       return "Error";
820     }
821   }
822 }
823 static const char*
824 translate_abqp_max_sdu_size(guint8 value, build_info_t *bi) {
825   static char result[BSSGP_TRANSLATION_MAX_LEN];
826
827   switch (value) {
828   case 0:
829     if (bi->ul_data) {
830       return "Subscribed maximum SDU size";
831     }
832     else {
833       return "Reserved";
834     }
835   case 0xff:
836     if (bi->ul_data) {
837       return "Reserved";
838     }
839     else {
840       return "Reserved";
841     }
842   case 0x97: return "1502 octets";
843   case 0x98: return "1510 octets";
844   case 0x99: return "1520 octets";
845   }
846   if ((value >= 1) && (value <= 0x96)) {
847     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u octets", value * 10);
848     return result;
849   }
850   if (bi->ul_data) {
851     /* The MS shall consider all other values as reserved */
852     return "Reserved";
853   }
854   else {
855     /* 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 */
856     return "Error";
857   }
858 }
859
860 static const char*
861 translate_abqp_max_bit_rate_for_ul(guint8 value, build_info_t *bi) {
862   static char result[BSSGP_TRANSLATION_MAX_LEN];
863
864   if (value == 0) {
865     if (bi->ul_data) {
866       return "Subscribed maximum bit rate for uplink";
867     }
868     else {
869       return "Reserved";
870     }
871   }
872   if ((value >= 1) && (value <= 0x3f)) {
873     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", value);
874     return result;
875   }
876   if ((value >= 0x40) && (value <= 0x7f)) {
877     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", 64 + (value - 0x40) * 8);
878     return result;
879   }
880   if ((value >= 0x80) && (value <= 0xfe)) {
881     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", 576 + (value - 0x80) * 64);
882     return result;
883   }
884   return "0 kbps";
885 }
886
887 static const char*
888 translate_abqp_max_bit_rate_for_dl(guint8 value, build_info_t *bi) {
889   return translate_abqp_max_bit_rate_for_ul(value, bi);
890 }
891
892 static const char*
893 translate_abqp_residual_ber(guint8 value, build_info_t *bi) {
894   switch (value) {
895   case 0:
896     if (bi->ul_data) {
897       return "Subscribed residual BER";
898     }
899     else {
900       return "Reserved";
901     }
902   case 1: return "5*10^-2";
903   case 2: return "1*10^-2";
904   case 3: return "5*10^-3";
905   case 4: return "4*10^-3";
906   case 5: return "1*10^-3";
907   case 6: return "1*10^-4";
908   case 7: return "1*10^-5";
909   case 8: return "1*10^-6";
910   case 9: return "6*10^-8";
911   case 15: return "Reserved";
912   }
913   if (bi->ul_data) {
914     /* The MS shall consider all other values as reserved */
915     return "Reserved";
916   }
917   else {
918     /* 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 */
919     return "Error";
920   }
921 }
922
923 static const char*
924 translate_abqp_sdu_error_ratio(guint8 value, build_info_t *bi) {
925   switch (value) {
926   case 0:
927     if (bi->ul_data) {
928       return "Subscribed SDU error ratio";
929     }
930     else {
931       return "Reserved";
932     }
933   case 1: return "1*10^-2";
934   case 2: return "7*10^-3";
935   case 3: return "1*10^-3";
936   case 4: return "1*10^-4";
937   case 5: return "1*10^-5";
938   case 6: return "1*10^-6";
939   case 7: return "1*10^-1";
940   case 15: return "Reserved";
941   }
942   if (bi->ul_data) {
943     /* The MS shall consider all other values as reserved */
944     return "Reserved";
945   }
946   else {
947     /* 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 */
948     return "";
949   }
950 }
951
952 static const char*
953 translate_abqp_transfer_delay(guint8 value, build_info_t *bi) {
954   static char result[BSSGP_TRANSLATION_MAX_LEN];
955
956   if (value == 0) {
957     if (bi->ul_data) {
958       return "Subscribed transfer delay";
959     }
960     else {
961       return "Reserved";
962     }
963   }
964   if ((value >= 1) && (value <= 0x0f)) {
965     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u ms", value * 10);
966     return result;
967   }
968   if ((value >= 0x10) && (value <= 0x1f)) {
969     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u ms", 200 + (value - 0x10) * 50);
970     return result;
971   }
972   if ((value >= 0x20) && (value <= 0x3e)) {
973     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u ms", 1000 + (value - 0x20) * 100);
974     return result;
975   }
976   return "Reserved";
977 }
978
979 static const char*
980 translate_abqp_traffic_handling_priority(guint8 value, build_info_t *bi) {
981   switch (value) {
982   case 0:
983     if (bi->ul_data) {
984       return "Subscribed traffic handling_priority";
985     }
986     else {
987       return "Reserved";
988     }
989   case 1: return "Priority level 1";
990   case 2: return "Priority level 2";
991   case 3: return "Priority level 3";
992   default: return "";
993   }
994 }
995
996 static const char*
997 translate_abqp_guaranteed_bit_rate_for_ul(guint8 value, build_info_t *bi) {
998   return translate_abqp_max_bit_rate_for_ul(value, bi);
999 }
1000 static const char*
1001 translate_abqp_guaranteed_bit_rate_for_dl(guint8 value, build_info_t *bi) {
1002   return translate_abqp_max_bit_rate_for_ul(value, bi);
1003 }
1004
1005 static const char*
1006 translate_abqp_source_statistics_descriptor(guint8 value, build_info_t *bi) {
1007   if (bi->ul_data) {
1008     switch (value) {
1009     case 0: return "Unknown";
1010     case 1: return "Speech";
1011     default: return "Unknown";
1012     }
1013   }
1014   else {
1015     return "Spare";
1016   }
1017 }
1018
1019 static const char*
1020 translate_abqp_max_bit_rate_for_dl_extended(guint8 value, build_info_t *bi _U_) {
1021   static char result[BSSGP_TRANSLATION_MAX_LEN];
1022
1023   if (value == 0) {
1024     return "Use the value indicated by the Maximum bit rate for downlink";
1025   }
1026   if ((value >= 1) && (value <= 0x4a)) {
1027     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", 8600 + value * 100);
1028     return result;
1029   }
1030   /* 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 */
1031   return "";
1032 }
1033
1034 static const char*
1035 translate_abqp_guaranteed_bit_rate_for_dl_extended(guint8 value, build_info_t *bi _U_) {
1036   static char result[BSSGP_TRANSLATION_MAX_LEN];
1037
1038   if (value == 0) {
1039     return "Use the value indicated by the Guaranteed bit rate for downlink";
1040   }
1041   if ((value >= 1) && (value <= 0x4a)) {
1042     g_snprintf(result, BSSGP_TRANSLATION_MAX_LEN, "%u kbps", 8600 + value * 100);
1043     return result;
1044   }
1045   /* 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 */
1046   return "";
1047 }
1048
1049 static const char*
1050 translate_msrac_access_technology_type(guint8 value) {
1051   static const value_string tab_values[] = {
1052     { 0, "GSM P" },
1053     { 1, "GSM E" },
1054     { 2, "GSM R" },
1055     { 3, "GSM 1800" },
1056     { 4, "GSM 1900" },
1057     { 5, "GSM 450" },
1058     { 6, "GSM 480" },
1059     { 7, "GSM 850" },
1060     { 8, "GSM 700" },
1061     { 9, "GSM T 380" },
1062     { 10, "GSM T 410" },
1063     { 11, "GSM T 900" },
1064     { 15, "List of Additional Access Technologies present" },
1065     { 0, NULL },
1066     /* Otherwise "Unknown" */
1067   };
1068   return val_to_str(value, tab_values, "Unknown");
1069 }
1070
1071 static const char*
1072 translate_msrac_dtm_gprs_multislot_class(guint8 value) {
1073   static const value_string tab_values[] = {
1074     { 0, "Unused, interpreted as \"Multislot class 5 supported\"" },
1075     { 1, "Multislot class 5 supported" },
1076     { 2, "Multislot class 9 supported" },
1077     { 3, "Multislot class 11 supported" },
1078     { 0, NULL },
1079     /* No other combinations*/
1080   };
1081   return val_to_str(value, tab_values, "");
1082 }
1083
1084 static const char*
1085 translate_msrac_extended_dtm_gprs_multislot_class(guint8 value, guint8 dgmsc) {
1086   switch (dgmsc) {
1087   case 0: return "Unused, interpreted as Multislot class 5 supported";
1088   case 1:
1089     switch (value) {
1090     case 0: return "Multislot class 5 supported";
1091     case 1: return "Multislot class 6 supported";
1092     case 2:
1093     case 3:
1094       return "Unused, interpreted as Multislot class 5 supported";
1095     }
1096   case 2:
1097     switch (value) {
1098     case 0: return "Multislot class 9 supported";
1099     case 1: return "Multislot class 10 supported";
1100     case 2:
1101     case 3:
1102       return "Unused, interpreted as Multislot class 5 supported";
1103     }
1104   case 3:
1105     switch (value) {
1106     case 0: return "Multislot class 11 supported";
1107     case 1:
1108     case 2:
1109     case 3:
1110       return "Unused, interpreted as Multislot class 5 supported";
1111     }
1112   }
1113   DISSECTOR_ASSERT_NOT_REACHED();
1114   return "Error"; /* Dummy */
1115 }
1116
1117 #if 0
1118 static guint8
1119 translate_msrac_high_multislot_capability(guint8 capability, guint8 class) {
1120   switch (capability) {
1121   case 0:
1122     switch (class) {
1123     case 8:
1124       return 30;
1125     case 10:
1126     case 23:
1127     case 28:
1128     case 29:
1129       return 39;
1130     case 11:
1131     case 20:
1132     case 25:
1133       return 32;
1134     case 12:
1135     case 21:
1136     case 22:
1137     case 26:
1138     case 27:
1139       return 33;
1140     default:
1141       return class;
1142     }
1143   case 1:
1144     switch (class) {
1145     case 8:
1146       return 35;
1147     case 10:
1148     case 19:
1149     case 24:
1150       return 36;
1151     case 11:
1152     case 23:
1153     case 28:
1154     case 29:
1155       return 45;
1156     case 12:
1157     case 21:
1158     case 22:
1159     case 26:
1160     case 27:
1161       return 38;
1162     default:
1163       return class;
1164     }
1165   case 2:
1166     switch (class) {
1167     case 8:
1168       return 40;
1169     case 10:
1170     case 19:
1171     case 24:
1172       return 41;
1173     case 11:
1174     case 20:
1175     case 25:
1176       return 42;
1177     case 12:
1178     case 23:
1179     case 28:
1180     case 29:
1181       return 44;
1182     default:
1183       return class;
1184     }
1185   case 3:
1186     switch (class) {
1187     case 12:
1188     case 21:
1189     case 22:
1190     case 26:
1191     case 27:
1192       return 43;
1193     case 11:
1194     case 20:
1195     case 25:
1196       return 37;
1197     case 10:
1198     case 19:
1199     case 24:
1200       return 31;
1201     case 9:
1202     case 23:
1203     case 28:
1204     case 29:
1205       return 34;
1206     default:
1207       return class;
1208     }
1209   }
1210   DISSECTOR_ASSERT_NOT_REACHED();
1211   return 0;
1212 }
1213 #endif
1214
1215 static const char*
1216 translate_channel_needed(guint8 value) {
1217   switch (value) {
1218   case 0: return "Any channel";
1219   case 1: return "SDCCH";
1220   case 2: return "TCH/F (Full rate)";
1221   case 3: return "TCH/H or TCH/F (Dual rate)";
1222   }
1223   DISSECTOR_ASSERT_NOT_REACHED();
1224   return NULL;
1225 }
1226
1227 static proto_item*
1228 bssgp_proto_tree_add_ie(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1229   const char *iename;
1230
1231   iename = ie->name;
1232   if (iename == NULL)
1233     iename = val_to_str(ie->iei, tab_bssgp_ie_types, "Unknown");
1234   return proto_tree_add_uint_format(bi->bssgp_tree, hf_bssgp_ie_type,
1235                                   bi->tvb, ie_start_offset, ie->total_length,
1236                                   ie->iei, "%s", iename);
1237 }
1238
1239 static void
1240 bssgp_proto_handoff(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset, dissector_handle_t handle) {
1241   tvbuff_t *next_tvb=NULL;
1242
1243   if(ie->value_length > 0)
1244     next_tvb = tvb_new_subset(bi->tvb, bi->offset, -1, -1);
1245
1246   if (bi->bssgp_tree) {
1247     bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1248   }
1249   if(next_tvb){
1250     if (handle) {
1251       call_dissector(handle, next_tvb, bi->pinfo, bi->parent_tree);
1252     }
1253     else if (data_handle) {
1254       call_dissector(data_handle, next_tvb, bi->pinfo, bi->parent_tree);
1255     }
1256   }
1257 }
1258
1259 static void
1260 decode_nri(proto_tree *tf, build_info_t *bi, guint32 tmsi_tlli) {
1261   proto_item *hidden_item;
1262   const guint32 LOCAL_TLLI_MASK = 0xc0000000;
1263   const guint32 FOREIGN_TLLI_MASK = 0x80000000;
1264   guint16 nri;
1265
1266   if (bssgp_decode_nri && (bssgp_nri_length != 0) &&
1267       (((tmsi_tlli & LOCAL_TLLI_MASK) == LOCAL_TLLI_MASK) ||
1268        ((tmsi_tlli & FOREIGN_TLLI_MASK) == FOREIGN_TLLI_MASK))) {
1269     nri = get_masked_guint32(tmsi_tlli, make_mask32( (guint8) bssgp_nri_length, 8));
1270     if (tf) {
1271       hidden_item = proto_tree_add_uint(tf, hf_bssgp_nri, bi->tvb, bi->offset, 4, nri);
1272       PROTO_ITEM_SET_HIDDEN(hidden_item);
1273     }
1274     if (check_col(bi->pinfo->cinfo, COL_INFO)) {
1275       col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP, "NRI %u", nri);
1276     }
1277   }
1278 }
1279
1280 static void
1281 decode_mobile_identity(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1282 #define MAX_NUM_IMSI_DIGITS 15
1283   const guint8 MASK_ODD_EVEN_INDICATION = 0x08;
1284   const guint8 MASK_TYPE_OF_IDENTITY = 0x07;
1285   const guint8 ODD = 1;
1286   proto_item *ti = NULL, *pi;
1287   proto_tree *tf = NULL;
1288   guint8 data, odd_even, type, num_digits, i;
1289   int hf_id;
1290   guint32 tmsi;
1291   guint8 digits[MAX_NUM_IMSI_DIGITS];
1292   char digits_str[MAX_NUM_IMSI_DIGITS + 1];
1293
1294   static const value_string tab_type_of_identity[] = {
1295     { BSSGP_MOBILE_IDENTITY_TYPE_IMSI, "IMSI" },
1296     { BSSGP_MOBILE_IDENTITY_TYPE_IMEI, "IMEI" },
1297     { BSSGP_MOBILE_IDENTITY_TYPE_IMEISV, "IMEISV" },
1298     { BSSGP_MOBILE_IDENTITY_TYPE_TMSI_PTMSI, "TMSI//P-TMSI" },
1299     { BSSGP_MOBILE_IDENTITY_TYPE_NO_IDENTITY, "No identity" },
1300     { 0, NULL },
1301     /* Otherwise "Reserved" */
1302   };
1303
1304   digits_str[0] = '\0'; /* conceivably num_digits below could be zero */
1305
1306   if (bi->bssgp_tree) {
1307     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1308     tf = proto_item_add_subtree(ti, ett_bssgp_mobile_identity);
1309   }
1310   data = tvb_get_guint8(bi->tvb, bi->offset);
1311   odd_even = get_masked_guint8(data, MASK_ODD_EVEN_INDICATION);
1312
1313   if (bi->bssgp_tree) {
1314     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
1315                                   MASK_ODD_EVEN_INDICATION);
1316     proto_item_append_text(pi, "Odd/Even Indication: %s number of identity digits%s",
1317                         odd_even == ODD ? "Odd" : "Even",
1318                         odd_even == ODD ? "" : " and also when the TMSI/P_TMSI is used");
1319   }
1320   type = get_masked_guint8(data, MASK_TYPE_OF_IDENTITY);
1321
1322   if (bi->bssgp_tree) {
1323     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
1324                                   MASK_TYPE_OF_IDENTITY);
1325     proto_item_append_text(pi, "Type of Identity: %s",
1326                            val_to_str(type, tab_type_of_identity,
1327                                       "Reserved"));
1328   }
1329   bi->offset++;
1330   switch (type) {
1331   case BSSGP_MOBILE_IDENTITY_TYPE_IMSI:
1332   case BSSGP_MOBILE_IDENTITY_TYPE_IMEI:
1333   case BSSGP_MOBILE_IDENTITY_TYPE_IMEISV:
1334     num_digits = 1 + (ie->value_length - 1) * 2;
1335     if (odd_even != ODD ) num_digits--;
1336     if (num_digits > MAX_NUM_IMSI_DIGITS) THROW(ReportedBoundsError);
1337
1338     i = 0;
1339     digits[i] = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1340
1341     i++;
1342     while (TRUE) {
1343       data = tvb_get_guint8(bi->tvb, bi->offset);
1344
1345       digits[i] = get_masked_guint8(data, BSSGP_MASK_RIGHT_OCTET_HALF);
1346       i++;
1347       if (i >= num_digits) break;
1348
1349       digits[i] = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1350       i++;
1351       if (i >= num_digits) break;
1352       bi->offset++;
1353     }
1354     bi->offset++;
1355
1356     if (bi->bssgp_tree) {
1357       proto_item_append_text(ti, ": ");
1358       for (i = 0; i < num_digits; i++) {
1359         proto_item_append_text(ti, "%u", digits[i]);
1360         g_snprintf(&digits_str[i], 2, "%u", digits[i]);
1361       }
1362       switch (type) {
1363       case BSSGP_MOBILE_IDENTITY_TYPE_IMSI:
1364         hf_id = hf_bssgp_imsi;
1365         break;
1366       case BSSGP_MOBILE_IDENTITY_TYPE_IMEI:
1367         hf_id = hf_bssgp_imei;
1368         break;
1369       case BSSGP_MOBILE_IDENTITY_TYPE_IMEISV:
1370         hf_id = hf_bssgp_imeisv;
1371         break;
1372       default:
1373         DISSECTOR_ASSERT_NOT_REACHED();
1374         hf_id = -1;
1375         break;
1376       }
1377       if (tf)
1378         proto_tree_add_string(tf, hf_id, bi->tvb, ie_start_offset + 2, ((num_digits/2)+1), digits_str);
1379
1380     }
1381     if (check_col(bi->pinfo->cinfo, COL_INFO)) {
1382       col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP, "%s %s",
1383                           val_to_str(type, tab_type_of_identity,
1384                                      "Mobile identity unknown"),
1385                           digits_str);
1386     }
1387     break;
1388   case BSSGP_MOBILE_IDENTITY_TYPE_TMSI_PTMSI:
1389     tmsi = tvb_get_ntohl(bi->tvb, bi->offset);
1390     if (check_col(bi->pinfo->cinfo, COL_INFO)) {
1391       col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP,
1392                           "TMSI/P-TMSI %0x04x", tmsi);
1393     }
1394     if (bi->bssgp_tree) {
1395       proto_tree_add_item(tf, hf_bssgp_tmsi_ptmsi, bi->tvb, bi->offset, 4,
1396                           BSSGP_LITTLE_ENDIAN);
1397       proto_item_append_text(ti, ": %#04x", tmsi);
1398     }
1399     decode_nri(tf, bi, tmsi);
1400     bi->offset += 4;
1401     break;
1402   default:
1403     ;
1404   }
1405 #undef MAX_NUM_IMSI_DIGITS
1406 }
1407
1408 static char*
1409 decode_mcc_mnc(build_info_t *bi, proto_tree *parent_tree) {
1410 #define RES_LEN 15
1411   const guint8 UNUSED_MNC3 = 0x0f;
1412   guint8 mcc1, mcc2, mcc3, mnc1, mnc2, mnc3, data;
1413   guint16 start_offset, mcc, mnc;
1414   static char mcc_mnc[RES_LEN];
1415
1416   start_offset = bi->offset;
1417
1418
1419   data = tvb_get_guint8(bi->tvb, bi->offset);
1420   mcc2 = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1421   mcc1 = get_masked_guint8(data, BSSGP_MASK_RIGHT_OCTET_HALF);
1422   bi->offset++;
1423
1424   data = tvb_get_guint8(bi->tvb, bi->offset);
1425   mnc3 = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1426   mcc3 = get_masked_guint8(data, BSSGP_MASK_RIGHT_OCTET_HALF);
1427   bi->offset++;
1428
1429   data = tvb_get_guint8(bi->tvb, bi->offset);
1430   mnc2 = get_masked_guint8(data, BSSGP_MASK_LEFT_OCTET_HALF);
1431   mnc1 = get_masked_guint8(data, BSSGP_MASK_RIGHT_OCTET_HALF);
1432   bi->offset++;
1433
1434   /* XXX: If mxci out of range the ms should transmit the values using full hexademical encoding? */
1435
1436   /* XXX: Interpretation of mcci? */
1437   mcc = 100 * mcc1 + 10 * mcc2 + mcc3;
1438
1439   /* XXX: Interpretation of mnci? */
1440   mnc = 10 * mnc1 + mnc2;
1441
1442   if (mnc3 != UNUSED_MNC3) {
1443     mnc += 10 * mnc + mnc3;
1444   }
1445
1446   proto_tree_add_uint(parent_tree, hf_bssgp_mcc,
1447                              bi->tvb, start_offset, 3, mcc);
1448   proto_tree_add_uint(parent_tree, hf_bssgp_mnc,
1449                              bi->tvb, start_offset, 3, mnc);
1450
1451   if (mnc3 != UNUSED_MNC3) {
1452     /* Three digits mnc */
1453     g_snprintf(mcc_mnc, RES_LEN, "%u-%03u", mcc, mnc);
1454   }
1455   else {
1456     /* Two digits mnc */
1457     g_snprintf(mcc_mnc, RES_LEN, "%u-%02u", mcc, mnc);
1458   }
1459 #undef RES_LEN
1460   return mcc_mnc;
1461 }
1462
1463 static char*
1464 decode_lai(build_info_t *bi, proto_tree *parent_tree) {
1465 #define RES_LEN 15
1466   guint16 lac;
1467   char *mcc_mnc;
1468   static char lai[RES_LEN];
1469
1470   mcc_mnc = decode_mcc_mnc(bi, parent_tree);
1471
1472   lac = tvb_get_ntohs(bi->tvb, bi->offset);
1473   proto_tree_add_item(parent_tree, hf_bssgp_lac,
1474                       bi->tvb, bi->offset, 2, BSSGP_LITTLE_ENDIAN);
1475   bi->offset += 2;
1476
1477   g_snprintf(lai, RES_LEN, "%s-%u", mcc_mnc, lac);
1478 #undef RES_LEN
1479   return lai;
1480 }
1481
1482 static char*
1483 decode_rai(build_info_t *bi, proto_tree *parent_tree) {
1484 #define RES_LEN 20
1485   guint8 rac;
1486   static char rai[RES_LEN];
1487   char *lai = decode_lai(bi, parent_tree);
1488
1489   rac = tvb_get_guint8(bi->tvb, bi->offset);
1490   proto_tree_add_item(parent_tree, hf_bssgp_rac, bi->tvb, bi->offset, 1, BSSGP_LITTLE_ENDIAN);
1491   bi->offset++;
1492
1493   g_snprintf(rai, RES_LEN, "%s-%u", lai, rac);
1494 #undef RES_LEN
1495   return rai;
1496 }
1497
1498 static char*
1499 decode_rai_ci(build_info_t *bi, proto_tree *parent_tree) {
1500 #define RES_LEN 30
1501   char *rai;
1502   static char rai_ci[RES_LEN];
1503   guint16 ci;
1504
1505   rai = decode_rai(bi, parent_tree);
1506
1507   ci = tvb_get_ntohs(bi->tvb, bi->offset);
1508   proto_tree_add_item(parent_tree, hf_bssgp_ci,
1509                       bi->tvb, bi->offset, 2, BSSGP_LITTLE_ENDIAN);
1510   bi->offset += 2;
1511   g_snprintf(rai_ci, RES_LEN, "RAI %s, CI %u", rai, ci);
1512 #undef RES_LEN
1513   return rai_ci;
1514 }
1515
1516 static void
1517 bssgp_pi_append_queuing_delay(proto_item *pi, tvbuff_t *tvb, int offset) {
1518   const guint16 INFINITE_DELAY = 0xffff;
1519   guint16 value = tvb_get_ntohs(tvb, offset);
1520   if (value == INFINITE_DELAY) {
1521     proto_item_append_text(pi, ": Infinite delay (%#4x)", value);
1522   }
1523   else {
1524     proto_item_append_text(pi, ": %u centi-seconds delay", value);
1525   }
1526 }
1527
1528 static void
1529 bssgp_pi_append_bucket_leak_rate(proto_item *pi, tvbuff_t *tvb, int offset) {
1530   guint16 value = tvb_get_ntohs(tvb, offset);
1531   proto_item_append_text(pi, ": %u bits", value * 100);
1532 }
1533
1534 static void
1535 bssgp_pi_append_bucket_size(proto_item *pi, tvbuff_t *tvb, int offset) {
1536   guint16 value = tvb_get_ntohs(tvb, offset);
1537   proto_item_append_text(pi, ": %u bytes", value * 100);
1538 }
1539
1540 static void
1541 bssgp_pi_append_bucket_full_ratio(proto_item *pi, tvbuff_t *tvb, int offset) {
1542   guint8 value = tvb_get_guint8(tvb, offset);
1543   proto_item_append_text(pi, ": %.2f * Bmax ", value / 100.0);
1544 }
1545
1546 static void
1547 bssgp_pi_append_pfi(proto_item *pi, tvbuff_t *tvb, int offset) {
1548   const guint8 MASK_PFI = 0x7f;
1549   guint8 value;
1550
1551   static const value_string tab_pfi[] = {
1552     { 0, "Best effort" },
1553     { 1, "Signaling" },
1554     { 2, "SMS" },
1555     { 3, "TOMB" },
1556     { 4, "Reserved" },
1557     { 5, "Reserved" },
1558     { 6, "Reserved" },
1559     { 7, "Reserved" },
1560     { 0, NULL },
1561     /* Otherwise "Dynamically assigned (PFI: <value>)" */
1562   };
1563   value = tvb_get_masked_guint8(tvb, offset, MASK_PFI);
1564   proto_item_append_text(pi,
1565                   "%s", val_to_str(value, tab_pfi, "Dynamically assigned (PFI: %d)"));
1566 }
1567
1568 static void
1569 decode_pfi(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1570   proto_item *ti;
1571   if (bi->bssgp_tree) {
1572     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1573     bssgp_pi_append_pfi(ti, bi->tvb, bi->offset);
1574   }
1575   bi->offset += ie->value_length;
1576 }
1577
1578 static void
1579 decode_queuing_delay(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1580   proto_item *ti;
1581   if (bi->bssgp_tree) {
1582     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1583     bssgp_pi_append_queuing_delay(ti, bi->tvb, bi->offset);
1584   }
1585   bi->offset += ie->value_length;
1586 }
1587
1588 static void
1589 decode_bucket_size(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1590   proto_item *ti;
1591   if (bi->bssgp_tree) {
1592     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1593     bssgp_pi_append_bucket_size(ti, bi->tvb, bi->offset);
1594   }
1595   bi->offset += ie->value_length;
1596 }
1597
1598 static void
1599 decode_bucket_leak_rate(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1600   proto_item *ti;
1601   if (bi->bssgp_tree) {
1602     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1603     bssgp_pi_append_bucket_leak_rate(ti, bi->tvb, bi->offset);
1604   }
1605   bi->offset += ie->value_length;
1606 }
1607
1608 static void
1609 get_value_length(bssgp_ie_t *ie, build_info_t *bi) {
1610   /* length indicator in bit 8, 0 => two bytes, 1 => one byte */
1611   const guint8 MASK_LENGTH_INDICATOR = 0x80;
1612   const guint8 MASK_ONE_BYTE_LENGTH = 0x7f;
1613   guint8 length_len;
1614   guint16 length;
1615
1616   length = tvb_get_guint8(bi->tvb, bi->offset);
1617   length_len = 1;
1618
1619   if (length & MASK_LENGTH_INDICATOR) {
1620     length &= MASK_ONE_BYTE_LENGTH;
1621   }
1622   else {
1623     length_len++;
1624     length <<= 8;
1625     length |= tvb_get_guint8(bi->tvb, bi->offset+1);
1626   }
1627   ie->value_length = length;
1628   ie->total_length += length_len + length;
1629   bi->offset += length_len;
1630 }
1631
1632 static void
1633 decode_simple_ie(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset,
1634                  const char *pre_str, const char *post_str,
1635                  gboolean show_as_dec) {
1636   /* XXX: Allow mask? */
1637   proto_item *ti;
1638   guint32 value;
1639
1640   switch (ie->value_length) {
1641   case 1: value = tvb_get_guint8(bi->tvb, bi->offset); break;
1642   case 2: value = tvb_get_ntohs(bi->tvb, bi->offset); break;
1643   case 3: value = tvb_get_ntoh24(bi->tvb, bi->offset); break;
1644   case 4: value = tvb_get_ntohl(bi->tvb, bi->offset); break;
1645   default: value = 0; break;
1646   }
1647
1648   if (bi->bssgp_tree) {
1649     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1650
1651     proto_item_append_text(ti, ": ");
1652
1653     if (pre_str) {
1654       proto_item_append_text(ti, "%s ", pre_str);
1655     }
1656     if (show_as_dec) {
1657       proto_item_append_text(ti, "%u", value);
1658     }
1659     else {
1660       switch (ie->value_length) {
1661       case 1: proto_item_append_text(ti, "%#1x", value); break;
1662       case 2: proto_item_append_text(ti, "%#2x", value); break;
1663       case 3: proto_item_append_text(ti, "%#3x", value); break;
1664       case 4: proto_item_append_text(ti, "%#4x", value); break;
1665       default: ;
1666       }
1667     }
1668     proto_item_append_text(ti, " %s", post_str);
1669   }
1670   bi->offset += ie->value_length;
1671 }
1672
1673 static int
1674 check_correct_iei(bssgp_ie_t *ie, build_info_t *bi) {
1675   guint8 fetched_iei = tvb_get_guint8(bi->tvb, bi->offset);
1676
1677 #ifdef BSSGP_DEBUG
1678   if (fetched_iei != ie->iei) {
1679     proto_tree_add_text(bi->bssgp_tree, bi->tvb, bi->offset, 1,
1680                         "Tried IEI %s (%#02x), found IEI %s (%#02x)",
1681                         val_to_str(ie->iei, tab_bssgp_ie_types, "Unknown"),
1682                         ie->iei,
1683                         val_to_str(fetched_iei, tab_bssgp_ie_types, "Unknown"),
1684                         fetched_iei);
1685   }
1686 #endif
1687   return (fetched_iei == ie->iei);
1688 }
1689
1690 static void
1691 decode_iei_alignment_octets(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1692   proto_item *ti;
1693   if (bi->bssgp_tree) {
1694     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1695     proto_item_append_text(ti, " (%u bytes)", ie->value_length);
1696   }
1697   bi->offset += ie->value_length;
1698 }
1699
1700 static void
1701 decode_iei_bvci(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1702   proto_item *ti, *hidden_item;
1703   guint16 bvci;
1704
1705   bvci = tvb_get_ntohs(bi->tvb, bi->offset);
1706
1707   if (bi->bssgp_tree) {
1708     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1709     proto_item_append_text(ti, ": %u", bvci);
1710     hidden_item = proto_tree_add_item(bi->bssgp_tree, hf_bssgp_bvci,
1711                                bi->tvb, bi->offset, ie->value_length,
1712                                BSSGP_LITTLE_ENDIAN);
1713     PROTO_ITEM_SET_HIDDEN(hidden_item);
1714   }
1715   bi->offset += ie->value_length;
1716
1717   if (check_col(bi->pinfo->cinfo, COL_INFO)) {
1718     col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP,
1719                         "BVCI %u", bvci);
1720   }
1721 }
1722
1723 const value_string tab_cause[] = {
1724   { 0x00, "Processor overload" },
1725   { 0x01, "Equipment failure" },
1726   { 0x02, "Transit network service failure" },
1727   { 0x03, "Network service transmission capacity modified from zero kbps to greater than zero kbps" },
1728   { 0x04, "Unknown MS" },
1729   { 0x05, "BVCI unknown" },
1730   { 0x06, "Cell traffic congestion" },
1731   { 0x07, "SGSN congestion" },
1732   { 0x08, "O&M intervention" },
1733   { 0x09, "BVCI blocked" },
1734   { 0x0a, "PFC create failure" },
1735   { 0x0b, "PFC preempted" },
1736   { 0x0c, "ABQP no more supported" },
1737   { 0x20, "Semantically incorrect PDU" },
1738   { 0x21, "Invalid mandatory information" },
1739   { 0x22, "Missing mandatory IE" },
1740   { 0x23, "Missing conditional IE" },
1741   { 0x24, "Unexpected conditional IE" },
1742   { 0x25, "Conditional IE error" },
1743   { 0x26, "PDU not compatible with the protocol state" },
1744   { 0x27, "Protocol error - unspecified" },
1745   { 0x28, "PDU not compatible with the feature set" },
1746   { 0x29, "Requested information not available" },
1747   { 0x2a, "Unknown destination address" },
1748   { 0x2b, "Unknown RIM application identity" },
1749   { 0x2c, "Invalid container unit information" },
1750   { 0x2d, "PFC queuing" },
1751   { 0x2e, "PFC created successfully" },
1752   { 0,    NULL },
1753 };
1754
1755 static void
1756 decode_iei_cause(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1757   proto_item *ti;
1758   guint8 value;
1759
1760
1761   if (bi->bssgp_tree) {
1762     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1763     value = tvb_get_guint8(bi->tvb, bi->offset);
1764     proto_item_append_text(ti, ": %s (%#02x)",
1765                            val_to_str(value, tab_cause,
1766                                       "Protocol error - unspecified"),
1767                            value);
1768   }
1769   bi->offset += ie->value_length;
1770 }
1771
1772 /*
1773  * 11.3.9 Cell Identifier 3GPP TS 48.018 version 6.7.0 Release 6
1774  */
1775 static void
1776 decode_iei_cell_identifier(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1777   proto_item *ti;
1778   proto_tree *tf;
1779   char *rai_ci;
1780
1781   if (bi->bssgp_tree) {
1782     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1783     tf = proto_item_add_subtree(ti, ett_bssgp_cell_identifier);
1784
1785     rai_ci = decode_rai_ci(bi, tf);
1786     proto_item_append_text(ti, ": %s", rai_ci);
1787
1788   } else {
1789     bi->offset += ie->value_length;
1790   }
1791
1792 }
1793
1794 /*
1795  * 11.3.10 Channel needed
1796  */
1797 static void
1798 decode_iei_channel_needed(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1799   /* XXX: 'If this IE is used for only one MS, the the first CHANNEL field
1800      is used and the second CHANNEL field is spare.' How know? */
1801   const guint8 MASK_CH1 = 0x03;
1802   const guint8 MASK_CH2 = 0x0c;
1803   proto_item *ti;
1804   guint8 data, ch1, ch2;
1805
1806   if (bi->bssgp_tree) {
1807     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1808     data = tvb_get_guint8(bi->tvb, bi->offset);
1809     ch1 = get_masked_guint8(data, MASK_CH1);
1810     ch2 = get_masked_guint8(data, MASK_CH2);
1811     proto_item_append_text(ti, ": Ch1: %s (%u), Ch2: %s (%u)",
1812                            translate_channel_needed(ch1),
1813                            ch1,
1814                            translate_channel_needed(ch2),
1815                            ch2);
1816   }
1817   bi->offset += ie->value_length;
1818 }
1819 /*
1820  * 11.3.11 DRX Parameters
1821  */
1822 static void
1823 decode_iei_drx_parameters(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1824   const guint8 MASK_CYCLE_LENGTH_COEFFICIENT = 0xf0;
1825   const guint8 MASK_SPLIT_ON_CCCH = 0x08;
1826   const guint8 MASK_NON_DRX_TIMER = 0x07;
1827   proto_item *ti, *pi;
1828   proto_tree *tf;
1829   guint8 data, value;
1830   guint16 cycle_value;
1831
1832   static const value_string tab_non_drx_timer[] = {
1833     { 0, "No non-DRX mode after transfer state" },
1834     { 1, "Max. 1 sec non-DRX mode after transfer state" },
1835     { 2, "Max. 2 sec non-DRX mode after transfer state" },
1836     { 3, "Max. 4 sec non-DRX mode after transfer state" },
1837     { 4, "Max. 8 sec non-DRX mode after transfer state" },
1838     { 5, "Max. 16 sec non-DRX mode after transfer state" },
1839     { 6, "Max. 32 sec non-DRX mode after transfer state" },
1840     { 7, "Max. 64 sec non-DRX mode after transfer state" },
1841     { 0, NULL},
1842     /* Otherwise "" */
1843   };
1844
1845   static const value_string tab_cycle_length_coefficient[] = {
1846     { 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" },
1847     { 6, "CN Specific DRX cycle length coefficient 6" },
1848     { 7, "CN Specific DRX cycle length coefficient 7" },
1849     { 8, "CN Specific DRX cycle length coefficient 8" },
1850     { 9, "CN Specific DRX cycle length coefficient 9" },
1851     { 0, NULL },
1852     /* Otherwise "CN Specific DRX cycle length coefficient not specified by the MS" */
1853   };
1854
1855   if (!bi->bssgp_tree) {
1856     bi->offset += ie->value_length;
1857     return;
1858   }
1859   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1860   tf = proto_item_add_subtree(ti, ett_bssgp_drx_parameters);
1861
1862   value = tvb_get_guint8(bi->tvb, bi->offset);
1863   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
1864                       "SPLIT PG CYCLE: code %u", value);
1865   if ((value >= 1) && (value <= 64)) {
1866     cycle_value = value;
1867   }
1868   else {
1869     switch (value) {
1870     case 0: cycle_value = 704; break;
1871     case 65: cycle_value = 71; break;
1872     case 66: cycle_value = 72; break;
1873     case 67: cycle_value = 74; break;
1874     case 68: cycle_value = 75; break;
1875     case 69: cycle_value = 77; break;
1876     case 70: cycle_value = 79; break;
1877     case 71: cycle_value = 80; break;
1878     case 72: cycle_value = 83; break;
1879     case 73: cycle_value = 86; break;
1880     case 74: cycle_value = 88; break;
1881     case 75: cycle_value = 90; break;
1882     case 76: cycle_value = 92; break;
1883     case 77: cycle_value = 96; break;
1884     case 78: cycle_value = 101; break;
1885     case 79: cycle_value = 103; break;
1886     case 80: cycle_value = 107; break;
1887     case 81: cycle_value = 112; break;
1888     case 82: cycle_value = 116; break;
1889     case 83: cycle_value = 118; break;
1890     case 84: cycle_value = 128; break;
1891     case 85: cycle_value = 141; break;
1892     case 86: cycle_value = 144; break;
1893     case 87: cycle_value = 150; break;
1894     case 88: cycle_value = 160; break;
1895     case 89: cycle_value = 171; break;
1896     case 90: cycle_value = 176; break;
1897     case 91: cycle_value = 192; break;
1898     case 92: cycle_value = 214; break;
1899     case 93: cycle_value = 224; break;
1900     case 94: cycle_value = 235; break;
1901     case 95: cycle_value = 256; break;
1902     case 96: cycle_value = 288; break;
1903     case 97: cycle_value = 320; break;
1904     case 98: cycle_value = 352; break;
1905     default:
1906       cycle_value = 1;
1907     }
1908     proto_item_append_text(ti, " => value %u", cycle_value);
1909     if (cycle_value == 704) {
1910       proto_item_append_text(ti, " (equivalent to no DRX)");
1911     }
1912   }
1913   bi->offset++;
1914
1915   data = tvb_get_guint8(bi->tvb, bi->offset);
1916
1917   value = get_masked_guint8(data, MASK_CYCLE_LENGTH_COEFFICIENT);
1918   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
1919                                 MASK_CYCLE_LENGTH_COEFFICIENT);
1920   proto_item_append_text(pi, "CN specific DRX cycle length coefficient: %s (%#02x)",
1921                          val_to_str(value, tab_cycle_length_coefficient,
1922                                     "Not specified by the MS"),
1923                          value);
1924
1925   value = get_masked_guint8(data, MASK_SPLIT_ON_CCCH);
1926   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_SPLIT_ON_CCCH);
1927   proto_item_append_text(pi, "SPLIT on CCCH: Split pg cycle on CCCH is%s supported by the mobile station",
1928                          value == 0 ? " not" : "");
1929
1930   value = get_masked_guint8(data, MASK_NON_DRX_TIMER);
1931   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_NON_DRX_TIMER);
1932   proto_item_append_text(pi, "Non-DRX Timer: %s (%#x)",
1933                          val_to_str(value, tab_non_drx_timer, ""), value);
1934   bi->offset++;
1935 }
1936
1937 /*
1938  * 11.3.12 eMLPP-Priority
1939  */
1940
1941 static void
1942 decode_iei_emlpp_priority(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1943   const guint8 MASK_CALL_PRIORITY = 0x07;
1944   proto_item *ti;
1945   guint8 data, value;
1946
1947   static const value_string tab_call_priority[] = {
1948     { 0, "No priority applied" },
1949     { 1, "Call priority level 4" },
1950     { 2, "Call priority level 3" },
1951     { 3, "Call priority level 2" },
1952     { 4, "Call priority level 1" },
1953     { 5, "Call priority level 0" },
1954     { 6, "Call priority level B" },
1955     { 7, "Call priority level A" },
1956     { 0, NULL },
1957   };
1958
1959   if (bi->bssgp_tree) {
1960     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1961     data = tvb_get_guint8(bi->tvb, bi->offset);
1962     value = get_masked_guint8(data, MASK_CALL_PRIORITY);
1963     proto_item_append_text(ti, ": %s",
1964                            val_to_str(value, tab_call_priority, ""));
1965   }
1966   bi->offset += ie->value_length;
1967 }
1968 /*
1969  * 11.3.13 Flush Action
1970  */
1971
1972 static void
1973 decode_iei_flush_action(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
1974   proto_item *ti;
1975   guint8 value;
1976
1977   static const value_string tab_action_value[] = {
1978     { 0x00, "LLC-PDU(s) deleted" },
1979     { 0x01, "LLC-PDU(s) transferred" },
1980     { 0,    NULL },
1981     /* Otherwise "Reserved" */
1982   };
1983
1984   if (bi->bssgp_tree) {
1985     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
1986     value = tvb_get_guint8(bi->tvb, bi->offset);
1987     proto_item_append_text(ti, ": %s (%u)",
1988                            val_to_str(value, tab_action_value, "Reserved"),
1989                            value);
1990
1991   }
1992   bi->offset += ie->value_length;
1993 }
1994 /*
1995  * 11.3.16 LLC Frames Discarded
1996  */
1997
1998 static void
1999 decode_iei_llc_frames_discarded(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2000   decode_simple_ie(ie, bi, ie_start_offset, "", " frames discarded", TRUE);
2001 }
2002 /*
2003  * 11.3.17 Location Area
2004  */
2005 static void
2006 decode_iei_location_area(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2007   proto_item *ti;
2008   proto_tree *tf;
2009   char *lai;
2010
2011   if (!bi->bssgp_tree) {
2012     bi->offset += ie->value_length;
2013     return;
2014   }
2015   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2016   tf = proto_item_add_subtree(ti, ett_bssgp_location_area);
2017
2018   lai = decode_rai(bi, tf);
2019   proto_item_append_text(ti, ": LAI %s", lai);
2020 }
2021
2022 static void
2023 decode_msrac_additional_access_technologies(proto_tree *tree, tvbuff_t *tvb,
2024                                             guint64 bo, guint32 length _U_) {
2025   proto_item *pi;
2026   guint8 value;
2027   guint8 bl; /* Bit length */
2028
2029   bl = 4;
2030   value = bssgp_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, "Access Technology Type: %s (%#01x)",
2034                          translate_msrac_access_technology_type(value),
2035                          value);
2036
2037   bl = 3;
2038   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2039   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2040   bo += bl;
2041   proto_item_append_text(pi, "GMSK Power Class: Power class %u", value);
2042
2043   bl = 2;
2044   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2045   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2046   bo += bl;
2047   proto_item_append_text(pi, "8PSK Power Class");
2048   if (value == 0) {
2049     proto_item_append_text(pi, ": 8PSK modulation not supported for uplink");
2050   }
2051   else{
2052     proto_item_append_text(pi, ": Power Class E%u", value);
2053   }
2054 }
2055
2056 static gboolean
2057 struct_bits_exist(guint64 start_bo, guint32 struct_length,
2058                   guint64 bo, guint32 num_bits) {
2059   return (bo + num_bits) <= (start_bo + struct_length);
2060
2061 }
2062
2063 static void
2064 decode_msrac_access_capabilities(proto_tree *tree, tvbuff_t *tvb,
2065                                  guint64 bo, guint32 struct_length) {
2066   /* Error handling:
2067      - Struct too short: assume features do not exist
2068      - Struct too long: ignore data and jump to next Access Technology */
2069   proto_item *ti, *pi;
2070   proto_tree *tf;
2071   guint8 value, i;
2072   guint8 dgmsc = 0, demsc = 0; /* DTM GPRS/EGPRS Multi Slot Class */
2073   guint8 bl; /* Bit length */
2074   guint64 start_bo = bo;
2075
2076   /* RF Power Capability */
2077   bl = 3;
2078   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2079   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2080   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2081   bo += bl;
2082   proto_item_append_text(pi, "RF Power Capability");
2083   if (value == 0) {
2084     proto_item_append_text(pi, ": The MS does not support any GSM access technology type");
2085   }
2086   else {
2087     proto_item_append_text(pi, ": GMSK Power Class %u", value);
2088   }
2089
2090   /* A5 bits */
2091   bl = 1;
2092   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2093   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2094   if (value == 1) {
2095     bo += bl;
2096     bl = 7;
2097     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2098     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2099     ti = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2100     proto_item_append_text(ti, "A5 Bits: %#02x", value);
2101     tf = proto_item_add_subtree(ti, ett_bssgp_msrac_a5_bits);
2102     for (i = 0; i < bl; i++) {
2103       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo + i, 1);
2104       proto_item_append_text(pi, "Encryption algorithm A5/%u%s available",
2105                              i + 1,
2106                              value & (0x40 >> i) ? "" : " not");
2107     }
2108     bo += bl;
2109   }
2110   else {
2111     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2112     bo += bl;
2113     proto_item_append_text(pi, "A5 bits: Same as in the immediately preceding Access capabilities field within this IE");
2114   }
2115
2116   /* ES IND */
2117   bl = 1;
2118   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2119   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2120   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2121   bo += bl;
2122   proto_item_append_text(pi, "ESD IND: Controlled Early Classmark Sending"" option is%s implemented",
2123                          value == 0 ? " not" : "");
2124
2125   /* PS */
2126   bl = 1;
2127   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2128   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2129   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2130   bo += bl;
2131   proto_item_append_text(pi, "PS: PS capability%s present",
2132                          value == 0 ? " not" : "");
2133
2134   /* VGCS */
2135   bl = 1;
2136   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2137   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2138   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2139   bo += bl;
2140   proto_item_append_text(pi, "VBCS:%s VGCS capability %s notifications wanted",
2141                          value == 0 ? " No" : "",
2142                          value == 0 ? "or no" : "and");
2143
2144   /* VBS */
2145   bl = 1;
2146   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2147   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2148   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2149   bo += bl;
2150   proto_item_append_text(pi, "VBS:%s VBS capability %s notifications wanted",
2151                          value == 0 ? " No" : "",
2152                          value == 0 ? "or no" : "and");
2153
2154   /* Multislot capability */
2155   /* XXX: 'Error: struct too short, assume features do not exist'
2156      No length is given! */
2157   bl = 1;
2158   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2159   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2160   if (value == 1) {
2161     bo += bl;
2162     ti = bit_proto_tree_add_text(tree, tvb, bo, bl, "Multislot capability");
2163     tf = proto_item_add_subtree(ti, ett_bssgp_msrac_multislot_capability);
2164
2165     /* HSCSD Multislot Class */
2166     bl = 1;
2167     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2168     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2169     bo += bl;
2170     if (value == 1) {
2171       bl = 5;
2172       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2173       value = bssgp_tvb_get_bits8(tvb, bo, bl);
2174       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2175       bo += bl;
2176       proto_item_append_text(pi, "HSCSD Multislot Class");
2177       if ((value > 0 ) && (value < 19)) {
2178         proto_item_append_text(pi, ": Multislot Class %u", value);
2179       }
2180       else {
2181         proto_item_append_text(pi, ": Reserved");
2182       }
2183     }
2184     else
2185     {
2186       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo-1, bl);
2187       proto_item_append_text(pi, "HSCSD Multislot Class - Bits are not available" );
2188     }
2189
2190     /* GPRS Multislot Class, GPRS Extended Dynamic Allocation Capability */
2191     bl = 1;
2192     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2193     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2194     bo += bl;
2195     if (value == 1) {
2196       bl = 5;
2197       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2198       value = bssgp_tvb_get_bits8(tvb, bo, bl);
2199       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2200       bo += bl;
2201       proto_item_append_text(pi, "GPRS Multislot Class: Multislot Class %u",
2202                              value);
2203
2204       bl = 1;
2205       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2206       value = bssgp_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, "GPRS Extended Dynamic Allocation Capability: Extended Dynamic Allocation for GPRS is%s implemented",
2210                              value == 0 ? " not" : "");
2211     }
2212     else
2213     {
2214       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo-1, bl);
2215       proto_item_append_text(pi, "GPRS Multislot Class: Multislot Class - Bits are not available" );
2216     }
2217
2218     /* SMS Value, SM Value */
2219     bl = 1;
2220     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2221     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2222     bo += bl;
2223     if (value == 1) {
2224       bl = 4;
2225       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2226       value = bssgp_tvb_get_bits8(tvb, bo, bl);
2227       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2228       bo += bl;
2229       proto_item_append_text(pi,
2230                              "SMS_VALUE: %u/4 timeslot (~%u microseconds)",
2231                              value + 1, (value + 1) * 144);
2232
2233       bl = 4;
2234       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2235       value = bssgp_tvb_get_bits8(tvb, bo, bl);
2236       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2237       bo += bl;
2238       proto_item_append_text(pi,
2239                              "SM_VALUE: %u/4 timeslot (~%u microseconds)",
2240                              value + 1, (value + 1) * 144);
2241     }
2242     else
2243     {
2244       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo-1, bl);
2245       proto_item_append_text(pi, "SMS Value, SM Value - Bits are not available" );
2246     }
2247
2248     /* Additions in release 99 */
2249
2250     /* ECSD Multislot Class */
2251     bl = 1;
2252     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2253     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2254     bo += bl;
2255     if (value == 1) {
2256       bl = 5;
2257       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2258       value = bssgp_tvb_get_bits8(tvb, bo, bl);
2259       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2260       bo += bl;
2261       proto_item_append_text(pi, "ECSD Multislot Class");
2262       if ((value > 0 ) && (value < 19)) {
2263         proto_item_append_text(pi, ": Multislot Class %u", value);
2264       }
2265       else {
2266         proto_item_append_text(pi, ": Reserved");
2267       }
2268     }
2269     else
2270     {
2271       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo-1, bl);
2272       proto_item_append_text(pi, "ECSD Multislot Class - Bits are not available" );
2273     }
2274
2275     /* EGPRS Multislot Class, EGPRS Extended Dynamic Allocation Capability */
2276     bl = 1;
2277     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2278     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2279     bo += bl;
2280     if (value == 1) {
2281       bl = 5;
2282       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2283       value = bssgp_tvb_get_bits8(tvb, bo, bl);
2284       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2285       bo += bl;
2286       proto_item_append_text(pi, "EGPRS Multislot Class: Multislot Class %u",
2287                              value);
2288
2289       bl = 1;
2290       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2291       value = bssgp_tvb_get_bits8(tvb, bo, bl);
2292       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2293       bo += bl;
2294       proto_item_append_text(pi, "EGPRS Extended Dynamic Allocation Capability: Extended Dynamic Allocation for EGPRS is%s implemented",
2295                              value == 0 ? " not" : "");
2296     }
2297     else
2298     {
2299       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo-1, bl);
2300       proto_item_append_text(pi, "EGPRS Multislot Class: Multislot Class - Bits are not available");
2301     }
2302
2303     /* DTM GPRS Multislot Class */
2304     bl = 1;
2305     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2306     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2307     bo += bl;
2308     if (value == 1) {
2309       bl = 2;
2310       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2311       dgmsc = bssgp_tvb_get_bits8(tvb, bo, bl);
2312       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2313       bo += bl;
2314       proto_item_append_text(pi, "DTM GPRS Multislot Class: %s",
2315                              translate_msrac_dtm_gprs_multislot_class(dgmsc));
2316
2317       /* Single slot DTM */
2318       bl = 1;
2319       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2320       value = bssgp_tvb_get_bits8(tvb, bo, bl);
2321       pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2322       bo += bl;
2323       proto_item_append_text(pi,
2324                              "Single Slot DTM: Single slot DTM%s supported",
2325                              value == 0 ? " not" : "");
2326
2327       /* DTM EGPRS Multislot Class */
2328       bl = 1;
2329       if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2330       value = bssgp_tvb_get_bits8(tvb, bo, bl);
2331       bo += bl;
2332       if (value == 1) {
2333         bl = 2;
2334         if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2335         demsc = bssgp_tvb_get_bits8(tvb, bo, bl);
2336         pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2337         bo += bl;
2338         proto_item_append_text(pi, "DTM EGPRS Multislot Class: %s",
2339                                translate_msrac_dtm_gprs_multislot_class(demsc));
2340       }
2341     }
2342     proto_item_set_len(ti, get_num_octets_spanned(start_bo,
2343                                                   (guint32) (bo - start_bo)));
2344   }
2345   else {
2346     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2347     bo += bl;
2348     proto_item_append_text(pi, "Multislot capability: Same as in the immediately preceding Access capabilities field within this IE");
2349   }
2350
2351   /* Additions in release 99 */
2352
2353   /* 8PSK Power Capability */
2354   bl = 1;
2355   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2356   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2357   bo += bl;
2358   if (value == 1) {
2359     bl = 2;
2360     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2361     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2362     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2363     bo += bl;
2364     proto_item_append_text(pi, "8PSK Power Capability");
2365
2366     if (value == 0) {
2367       proto_item_append_text(pi, ": Reserved");
2368     }
2369     else{
2370       proto_item_append_text(pi, ": Power Class E%u", value);
2371     }
2372     proto_item_append_text(pi, ", 8PSK modulation capability in uplink");
2373   }
2374
2375   /* COMPACT Interference Measurement Capability */
2376   bl = 1;
2377   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2378   value = bssgp_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,
2382                          "COMPACT Interference Measurement Capability: %s",
2383                          value == 0 ? "Not implemented" : "Implemented");
2384
2385   /* Revision level indicator */
2386   bl = 1;
2387   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2388   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2389   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2390   bo += bl;
2391   proto_item_append_text(pi, "Revision Level Indicator: The ME is Release '%u %s",
2392                          value == 0 ? 98 : 99,
2393                          value == 0 ? "or older" : "onwards");
2394
2395
2396   /* 3G RAT */
2397   bl = 1;
2398   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2399   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2400   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2401   bo += bl;
2402   proto_item_append_text(pi, "UMTS FDD Radio Access Technology Capability: UMTS FDD%s supported",
2403                          value == 0 ? " not" : "");
2404
2405   bl = 1;
2406   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2407   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2408   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2409   bo += bl;
2410   proto_item_append_text(pi, "UMTS 3.84 Mcps TDD Radio Access Technology Capability: UMTS 3.84 Mcps TDD%s supported",
2411                          value == 0 ? " not" : "");
2412
2413   bl = 1;
2414   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2415   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2416   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2417   bo += bl;
2418   proto_item_append_text(pi, "CDMA 2000 Radio Access Technology Capability: CDMA 2000%s supported",
2419                          value == 0 ? " not" : "");
2420
2421
2422   /* Additions in release 4*/
2423   bl = 1;
2424   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2425   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2426   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2427   bo += bl;
2428   proto_item_append_text(pi, "UMTS 1.28 Mcps TDD Radio Access Technology Capability: UMTS 1.28 Mcps TDD%s supported",
2429                          value == 0 ? " not" : "");
2430
2431
2432   /* GERAN Feature Package 1 */
2433   bl = 1;
2434   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2435   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2436   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2437   bo += bl;
2438   proto_item_append_text(pi, "GERAN Feature Package 1: GERAN Feature Package 1%s supported",
2439                          value == 0 ? " not" : "");
2440
2441
2442   /* Extended DTM xGPRS Multislot Class */
2443   bl = 1;
2444   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2445   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2446   bo += bl;
2447   if (value == 1) {
2448     bl = 2;
2449     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2450     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2451     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2452     bo += bl;
2453     proto_item_append_text(pi, "Extended DTM GPRS Multi Slot Class: %s",
2454                            translate_msrac_extended_dtm_gprs_multislot_class(value, dgmsc));
2455
2456     /* XXX: 'This field shall be included only if the MS supports EGPRS DTM'.
2457        How know? */
2458     bl = 2;
2459     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2460     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2461     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2462     bo += bl;
2463     proto_item_append_text(pi, "Extended DTM EGPRS Multi Slot Class: %s",
2464                            translate_msrac_extended_dtm_gprs_multislot_class(value, demsc));
2465   }
2466
2467   /* Modulation based multislot class support */
2468   bl = 1;
2469   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2470   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2471   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2472   bo += bl;
2473   proto_item_append_text(pi, "Modulation based multislot class support: %s supported",
2474                          value == 0 ? "Not" : "");
2475
2476   /* Additions in release 5 */
2477
2478   /* High multislot capability */
2479   bl = 1;
2480   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2481   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2482   bo += bl;
2483   if (value == 1) {
2484     bl = 2;
2485     if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2486     value = bssgp_tvb_get_bits8(tvb, bo, bl);
2487     pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2488     bo += bl;
2489     proto_item_append_text(pi, "High Multislot Capability: %u", value);
2490     /* XXX: Translate? In that case, which values to compare with?
2491        What if Multislot capability struct was not included? */
2492   }
2493
2494   /* GERAN Iu Mode Capabilities */
2495   /* XXX: Interpretation? Length? */
2496   bl = 1;
2497   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2498   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2499   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2500   bo += bl;
2501   proto_item_append_text(pi, "GERAN Iu Mode Capabilities: %s",
2502                          value == 0 ? "Not supported" : "Supported");
2503
2504   /* GMSK Multislot Power Profile */
2505   bl = 2;
2506   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2507   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2508   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2509   bo += bl;
2510   proto_item_append_text(pi, "GMSK Multislot Power Profile: GMSK_MULTI_SLOT_POWER_PROFILE %u",
2511                          value);
2512
2513   /* 8PSK Multislot Power Profile */
2514   /* XXX: 'If the MS does not support 8PSK in the uplink, then it shall
2515      set this field to 00' */
2516   bl = 2;
2517   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2518   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2519   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2520   bo += bl;
2521   proto_item_append_text(pi, "8PSK Multislot Power Profile: 8PSK_MULTI_SLOT_POWER_PROFILE %u",
2522                          value);
2523
2524   /* Additions in release 6 */
2525
2526   /* Multiple TBF Capability */
2527   bl = 1;
2528   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2529   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2530   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2531   bo += bl;
2532   proto_item_append_text(pi, "Multiple TBF Capability: Multiple TBF procedures in A/Gb mode%s supported",
2533                          value == 0 ? " not" : "");
2534
2535   /* Downlink Advanced Receiver Performance */
2536   bl = 2;
2537   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2538   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2539   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2540   bo += bl;
2541   proto_item_append_text(pi, "Downlink Advanced Receiver Performance: Downlink Advanced Receiver Performance %s supported",
2542                          value == 0 ? "not" : "- phase 1");
2543
2544
2545   /* Extended RLC_MAC Control Message Segmentation Capability */
2546   bl = 1;
2547   if (!struct_bits_exist(start_bo, struct_length, bo, bl)) return;
2548   value = bssgp_tvb_get_bits8(tvb, bo, bl);
2549   pi = bit_proto_tree_add_bit_field8(tree, tvb, bo, bl);
2550   bo += bl;
2551   proto_item_append_text(pi, "Extended RLC/MAC Control Message Segmentation Capability: Extended RLC/MAC Control Message Segmentation%s supported",
2552                          value == 0 ? " not" : "");
2553 }
2554
2555 static void
2556 decode_msrac_value_part(proto_tree *tree, tvbuff_t *tvb, guint64 bo) {
2557   /* No need to check bi->bssgp_tree here */
2558   const guint8 ADD_ACC_TECHN = 0x0f;
2559   guint8 att, length, bit, bl;
2560   proto_item *ti, *ti2, *pi;
2561   proto_tree *tf, *tf2;
2562   const char *att_name;
2563   guint64 start_bo;
2564
2565   start_bo = bo;
2566   ti = bit_proto_tree_add_text(tree, tvb, bo, 8,
2567                                "MS RA capability value part");
2568   /* Temporary length of item */
2569   tf = proto_item_add_subtree(ti, ett_bssgp_msrac_value_part);
2570
2571   bl = 4;
2572   att = bssgp_tvb_get_bits8(tvb, bo, bl);
2573   att_name = translate_msrac_access_technology_type(att);
2574   pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2575   proto_item_append_text(pi, "Access Technology Type: %s (%#01x)", att_name, att);
2576   proto_item_append_text(ti, ": Technology Type %s", att_name);
2577   bo += bl;
2578
2579   bl = 7;
2580   length = bssgp_tvb_get_bits8(tvb, bo, bl);
2581   pi = bit_proto_tree_add_bit_field8(tf, tvb, bo, bl);
2582   proto_item_append_text(pi, "Length: %u bits", length);
2583   bo += bl;
2584
2585   if (att == ADD_ACC_TECHN) {
2586     bo++; /* Always '1' */
2587     ti2 = bit_proto_tree_add_text(tf, tvb, bo, length,
2588                                   "Additional Access Technologies");
2589     tf2 = proto_item_add_subtree(ti2, ett_bssgp_msrac_additional_access_technologies);
2590     proto_item_set_len(ti, get_num_octets_spanned(start_bo, 4 + 7 + length + 1 + 1));
2591     decode_msrac_additional_access_technologies(tf2, tvb, bo, length);
2592   }
2593   else if (att <= 0x0b) {
2594     ti2 = bit_proto_tree_add_text(tf, tvb, bo, length, "Access Capabilities");
2595     tf2 = proto_item_add_subtree(ti2, ett_bssgp_msrac_access_capabilities);
2596     proto_item_set_len(ti, get_num_octets_spanned(start_bo, 4 + 7 + length + 1));
2597     decode_msrac_access_capabilities(tf2, tvb, bo, length);
2598   }
2599   /* else unknown Access Technology Type */
2600
2601   bo += length;
2602   bit = bssgp_tvb_get_bits8(tvb, bo, 1);
2603   bo++;
2604   if (bit == 1) {
2605     decode_msrac_value_part(tree, tvb, bo);
2606   }
2607 }
2608 /*
2609  * 11.3.22 MS Radio Access Capability
2610  */
2611 static void
2612 decode_iei_ms_radio_access_capability(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2613   proto_item *ti;
2614   proto_tree *tf;
2615
2616   if (!bi->bssgp_tree) {
2617     bi->offset += ie->value_length;
2618     return;
2619   }
2620   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2621   tf = proto_item_add_subtree(ti, ett_bssgp_ms_radio_access_capability);
2622   /* Rest of element coded as the value part defined in
2623    * 3GPP TS 24.008, not including 3GPP TS 24.008 IEI and
2624    * 3GPP TS 24.008 octet length indicator.
2625    * 10.5.5.12a MS Radio Access capability
2626    */
2627   decode_msrac_value_part(tf, bi->tvb, bi->offset * 8);
2628   bi->offset += ie->value_length;
2629 }
2630 /*
2631  * 11.3.23 OMC Id
2632  */
2633 static void
2634 decode_iei_omc_id(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2635   /* XXX: Translation: where in 3GPP TS 12.20? */
2636   proto_item *ti;
2637
2638   if (bi->bssgp_tree) {
2639     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2640     proto_item_append_text(ti, ": %s", BSSGP_NOT_DECODED);
2641   }
2642   bi->offset += ie->value_length;
2643 }
2644 /*
2645  * 11.3.24 PDU In Error
2646  */
2647 static void
2648 decode_iei_pdu_in_error(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2649   proto_item *ti;
2650
2651   if (bi->bssgp_tree) {
2652     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2653     proto_item_append_text(ti, ": Erroneous BSSGP PDU (%u bytes)",
2654                            ie->value_length);
2655   }
2656   bi->offset += ie->value_length;
2657 }
2658
2659 static void
2660 decode_iei_priority(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2661   const guint8 MASK_PCI = 0x40;
2662   const guint8 MASK_PRIORITY_LEVEL = 0x3c;
2663   const guint8 MASK_QA = 0x02;
2664   const guint8 MASK_PVI = 0x01;
2665   proto_item *ti, *pi;
2666   proto_tree *tf;
2667   guint8 data, value;
2668
2669   static const value_string tab_priority_level[] = {
2670     { 0, "Spare" },
2671     { 1, "Priority Level 1 = highest priority" },
2672     { 2, "Priority Level 2 = 2nd highest priority" },
2673     { 3, "Priority Level 3 = 3rd highest priority" },
2674     { 4, "Priority Level 4 = 4th highest priority" },
2675     { 5, "Priority Level 5 = 5th highest priority" },
2676     { 6, "Priority Level 6 = 6th highest priority" },
2677     { 7, "Priority Level 7 = 7th highest priority" },
2678     { 8, "Priority Level 8 = 8th highest priority" },
2679     { 9, "Priority Level 9 = 9th highest priority" },
2680     { 10, "Priority Level 10 = 10th highest priority" },
2681     { 11, "Priority Level 11 = 11th highest priority" },
2682     { 12, "Priority Level 12 = 12th highest priority" },
2683     { 13, "Priority Level 13 = 13th highest priority" },
2684     { 14, "Priority Level 14 = lowest priority" },
2685     { 15, "Priority not used" },
2686     { 0, NULL },
2687   };
2688
2689   if (!bi->bssgp_tree) {
2690     bi->offset += ie->value_length;
2691     return;
2692   }
2693   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2694   tf = proto_item_add_subtree(ti, ett_bssgp_priority);
2695
2696   data = tvb_get_guint8(bi->tvb, bi->offset);
2697
2698   value = get_masked_guint8(data, MASK_PCI);
2699   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
2700                                 MASK_PCI);
2701   proto_item_append_text(pi, "PCI: This allocation request %s preempt an existing connection",
2702                          value == 0 ? "shall not" : "may");
2703
2704   value = get_masked_guint8(data, MASK_PRIORITY_LEVEL);
2705   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PRIORITY_LEVEL);
2706   proto_item_append_text(pi, "Priority Level: %s",
2707                          val_to_str(value, tab_priority_level, ""));
2708
2709   value = get_masked_guint8(data, MASK_QA);
2710   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_QA);
2711   proto_item_append_text(pi, "QA: Queuing%s allowed",
2712                          value == 0 ? " not" : "");
2713
2714   value = get_masked_guint8(data, MASK_PVI);
2715   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PVI);
2716   proto_item_append_text(pi, "PVI: This connection %s be preempted by another allocation request",
2717                          value == 0 ? "shall not" : "might");
2718
2719   bi->offset += ie->value_length;
2720 }
2721 /*
2722  * 11.3.28 QoS Profile
2723  */
2724 static void
2725 decode_iei_qos_profile(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2726   const guint8 MASK_CR_BIT = 0x20;
2727   const guint8 MASK_T_BIT = 0x10;
2728   const guint8 MASK_A_BIT = 0x08;
2729   const guint8 MASK_PRECEDENCE = 0x07;
2730   proto_item *ti, *pi;
2731   proto_tree *tf;
2732   guint8 data, value;
2733   guint16 peak_bit_rate;
2734
2735   static const value_string tab_precedence_ul[] = {
2736     { 0,   "High priority" },
2737     { 1,   "Normal priority" },
2738     { 2,   "Low priority" },
2739     { 0,   NULL },
2740   };
2741
2742   static const value_string tab_precedence_dl[] = {
2743     { 0,   "Radio priority 1" },
2744     { 1,   "Radio priority 2" },
2745     { 2,   "Radio priority 3" },
2746     { 3,   "Radio priority 4" },
2747     { 4,   "Radio priority unknown" },
2748     { 0,   NULL },
2749   };
2750
2751   if (!bi->bssgp_tree) {
2752     bi->offset += ie->value_length;
2753     return;
2754   }
2755   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2756   tf = proto_item_add_subtree(ti, ett_bssgp_qos_profile);
2757
2758   peak_bit_rate = tvb_get_ntohs(bi->tvb, bi->offset);
2759   pi = proto_tree_add_text(tf, bi->tvb, bi->offset, 1, "Peak bit rate: ");
2760   if (peak_bit_rate == 0) {
2761     proto_item_append_text(pi, "Best effort");
2762   }
2763   else {
2764     proto_item_append_text(pi, "%u bits/s", peak_bit_rate * 100);
2765   }
2766   bi->offset += 2;
2767
2768   data = tvb_get_guint8(bi->tvb, bi->offset);
2769
2770   value = get_masked_guint8(data, MASK_CR_BIT);
2771   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_CR_BIT);
2772   proto_item_append_text(pi, "C/R: The SDU %s command/response frame type",
2773                          value == 0 ? "contains" : "does not contain");
2774
2775   value = get_masked_guint8(data, MASK_T_BIT);
2776   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_T_BIT);
2777   proto_item_append_text(pi, "T: The SDU contains %s",
2778                          value == 0 ? "signalling (e.g. related to GMM)" : "data");
2779
2780   value = get_masked_guint8(data, MASK_A_BIT);
2781   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_A_BIT);
2782   proto_item_append_text(pi, "A: Radio interface uses RLC/MAC %s functionality",
2783                          value == 0 ? "ARQ " : "UNITDATA ");
2784
2785   value = get_masked_guint8(data, MASK_PRECEDENCE);
2786   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PRECEDENCE);
2787   proto_item_append_text(pi, "Precedence: ");
2788
2789   if (bi->ul_data) {
2790     proto_item_append_text(pi, "%s", val_to_str(value, tab_precedence_ul,
2791                                           "Reserved (Low priority)"));
2792   }
2793   else {
2794     proto_item_append_text(pi, "%s", val_to_str(value, tab_precedence_dl,
2795                                           "Reserved (Radio priority 3)"));
2796   }
2797   proto_item_append_text(pi, " (%#x)", value);
2798   bi->offset++;
2799 }
2800 /*
2801  * 11.3.29 Radio Cause
2802  */
2803 static void
2804 decode_iei_radio_cause(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2805   proto_item *ti;
2806   guint8 value;
2807
2808   static const value_string tab_radio_cause[] = {
2809     { 0x00, "Radio contact lost with the MS" },
2810     { 0x01, "Radio link quality insufficient to continue communication" },
2811     { 0x02, "Cell reselection ordered" },
2812     { 0x03, "Cell reselection prepare" },
2813     { 0x04, "Cell reselection failure" },
2814     { 0,    NULL },
2815     /* Otherwise "Reserved (Radio contact lost with the MS)" */
2816   };
2817
2818   if (bi->bssgp_tree) {
2819     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2820     value = tvb_get_guint8(bi->tvb, bi->offset);
2821     proto_item_append_text(ti, ": %s (%#02x)",
2822                            val_to_str(value, tab_radio_cause, "Reserved (Radio contact lost with the MS)"),
2823                            value);
2824   }
2825   bi->offset += ie->value_length;
2826 }
2827
2828 static void
2829 decode_iei_ra_cap_upd_cause(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2830   proto_item *ti;
2831   guint8 value;
2832
2833   static const value_string tab_cause_value[] = {
2834     { 0x00, "OK, RA capability IE present" },
2835     { 0x01, "TLLI unknown in SGSN" },
2836     { 0x02, "No RA capabilities or IMSI available for this MS" },
2837     { 0,    NULL },
2838     /* Otherwise "Reserved (TLLI unknown in SGSN)" */
2839   };
2840
2841   if (bi->bssgp_tree) {
2842     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2843     value = tvb_get_guint8(bi->tvb, bi->offset);
2844     proto_item_append_text(ti, ": %s (%#2x)",
2845                            val_to_str(value, tab_cause_value, "Reserved (TLLI unknown in SGSN)"),
2846                            value);
2847   }
2848   bi->offset += ie->value_length;
2849 }
2850
2851 static void
2852 decode_iei_routing_area(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2853   proto_item *ti;
2854   proto_tree *tf;
2855   char *rai;
2856
2857   if (!bi->bssgp_tree) {
2858     bi->offset += ie->value_length;
2859     return;
2860   }
2861   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2862   tf = proto_item_add_subtree(ti, ett_bssgp_routing_area);
2863
2864   rai = decode_rai(bi, tf);
2865   proto_item_append_text(ti, ": RAI %s", rai);
2866 }
2867
2868 static void
2869 decode_iei_tlli(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2870   proto_item *ti;
2871   proto_tree *tf;
2872
2873   guint32 tlli;
2874   tlli = tvb_get_ntohl(bi->tvb, bi->offset);
2875
2876   if (bi->bssgp_tree) {
2877     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2878     proto_item_append_text(ti, ": %#04x", tlli);
2879     /* By Stefan Boman LN/Ericsson 2006-07-14 --
2880          * Commented the following four lines. Preventing redundant data
2881          */
2882         /*
2883         ti = bssgp_proto_tree_add_ie(ie, bi, bi->offset);
2884         */
2885         /* If we want to keep the posibillity to filter on ie:s without a Tag and the ie "content"
2886          * this is how it has to be done.
2887          */
2888     tf = proto_item_add_subtree(ti, ett_bssgp_tlli);
2889
2890     proto_tree_add_item(tf, hf_bssgp_tlli,
2891                                bi->tvb, bi->offset, 4, BSSGP_LITTLE_ENDIAN);
2892
2893   }
2894   bi->offset += 4;
2895
2896   if (check_col(bi->pinfo->cinfo, COL_INFO)) {
2897     col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP,
2898                         "TLLI %#4x", tlli);
2899   }
2900
2901   if (check_col(bi->pinfo->cinfo, COL_BSSGP_TLLI)) {
2902     col_add_fstr(bi->pinfo->cinfo, COL_BSSGP_TLLI, "%#04x", tlli);
2903   }
2904
2905   decode_nri(bi->bssgp_tree, bi, tlli);
2906 }
2907
2908 static void
2909 decode_iei_tmsi(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2910   proto_item *ti;
2911   proto_tree *tf;
2912   guint32 tmsi;
2913
2914   tmsi = tvb_get_ntohl(bi->tvb, bi->offset);
2915
2916   if (bi->bssgp_tree) {
2917     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2918     proto_item_append_text(ti, ": %#04x", tmsi);
2919
2920     ti = bssgp_proto_tree_add_ie(ie, bi, bi->offset);
2921     tf = proto_item_add_subtree(ti, ett_bssgp_tmsi_ptmsi);
2922
2923     proto_tree_add_item(tf, hf_bssgp_tmsi_ptmsi,
2924                                bi->tvb, bi->offset, 4, BSSGP_LITTLE_ENDIAN);
2925   }
2926   bi->offset += 4;
2927
2928   if (check_col(bi->pinfo->cinfo, COL_INFO)) {
2929     col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP,
2930                         "(P)TMSI %#4x", tmsi);
2931   }
2932   decode_nri(bi->bssgp_tree, bi, tmsi);
2933 }
2934
2935 static void
2936 decode_iei_trigger_id(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2937   /* XXX: value is 20 octets long! How add/show? */
2938   proto_item *ti;
2939
2940   if (bi->bssgp_tree) {
2941     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2942   }
2943   bi->offset += ie->value_length;
2944 }
2945
2946 static void
2947 proto_tree_add_lsa_id(build_info_t *bi, proto_tree *tree) {
2948   guint32 data, lsa_id;
2949   proto_item *pi;
2950
2951   data = tvb_get_ntoh24(bi->tvb, bi->offset);
2952   lsa_id = data >> 1;
2953
2954   pi = proto_tree_add_text(tree, bi->tvb, bi->offset, 3,
2955                            "LSA ID: %#03x (%s)", lsa_id,
2956                            data & 1 ?
2957                            "Universal LSA" : "PLMN significant number");
2958   bi->offset += 3;
2959 }
2960
2961 static void
2962 decode_iei_lsa_identifier_list(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2963   const guint8 MASK_EP = 0x01;
2964   proto_item *ti, *pi;
2965   proto_tree *tf;
2966   int num_lsa_ids, i;
2967   guint32 value;
2968
2969   if (!bi->bssgp_tree) {
2970     bi->offset += ie->value_length;
2971     return;
2972   }
2973   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
2974   tf = proto_item_add_subtree(ti, ett_bssgp_lsa_identifier_list);
2975
2976   value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_EP);
2977   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_EP);
2978   proto_item_append_text(pi, "EP: The escape PLMN is%s broadcast",
2979                          value == 0 ? " not" : "");
2980   bi->offset++;
2981
2982   num_lsa_ids = (ie->value_length - 1) / 3;
2983
2984   for (i = 0; i < num_lsa_ids; i++) {
2985     proto_tree_add_lsa_id(bi, tf);
2986   }
2987 }
2988
2989 static void
2990 decode_iei_lsa_information(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
2991   const guint8 MASK_LSA_ONLY = 0x01;
2992   const guint8 MASK_ACT = 0x20;
2993   const guint8 MASK_PREF = 0x10;
2994   const guint8 MASK_PRIORITY = 0x0f;
2995   proto_item *ti, *ti2, *pi;
2996   proto_tree *tf, *tf2;
2997   int num_lsa_infos, i;
2998   guint8 data, value;
2999
3000   static const value_string tab_priority[] = {
3001     { 0, "Priority 1 = lowest priority" },
3002     { 1, "Priority 2 = 2nd lowest priority" },
3003     { 2, "Priority 3 = 3rd lowest priority" },
3004     { 3, "Priority 4 = 4th lowest priority" },
3005     { 4, "Priority 5 = 5th lowest priority" },
3006     { 5, "Priority 6 = 6th lowest priority" },
3007     { 6, "Priority 7 = 7th lowest priority" },
3008     { 7, "Priority 8 = 8th lowest priority" },
3009     { 8, "Priority 9 = 9th lowest priority" },
3010     { 9, "Priority 10 = 10th lowest priority" },
3011     { 10, "Priority 11 = 11th lowest priority" },
3012     { 11, "Priority 12 = 12th lowest priority" },
3013     { 12, "Priority 13 = 13th lowest priority" },
3014     { 13, "Priority 14 = 14th lowest priority" },
3015     { 14, "Priority 15 = 15th lowest priority" },
3016     { 15, "Priority 16 = highest priority" },
3017     { 0, NULL },
3018   };
3019
3020   if (!bi->bssgp_tree) {
3021     bi->offset += ie->value_length;
3022     return;
3023   }
3024   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3025   tf = proto_item_add_subtree(ti, ett_bssgp_lsa_information);
3026
3027   value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_LSA_ONLY);
3028   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_LSA_ONLY);
3029   proto_item_append_text(pi, "LSA Only: %s",
3030                          value == 0 ?
3031                          "The subscriber has only access to the LSAs that are defined by the LSA information element" :
3032                          "Allow an emergency call");
3033   bi->offset++;
3034
3035   num_lsa_infos = (ie->value_length - 1) / 4;
3036
3037   for (i = 0; i < num_lsa_infos; i++) {
3038     ti2 = proto_tree_add_text(tf, bi->tvb, bi->offset, 4,
3039                               "LSA Identification and attributes %u", i + 1);
3040     tf2 = proto_item_add_subtree(ti2, ett_bssgp_lsa_information_lsa_identification_and_attributes);
3041
3042     data = tvb_get_guint8(bi->tvb, bi->offset);
3043
3044     value = get_masked_guint8(data, MASK_ACT);
3045     pi = proto_tree_add_bitfield8(tf2, bi->tvb, bi->offset, MASK_ACT);
3046     proto_item_append_text(pi, "Act: The subscriber %s active mode support in the LSA",
3047                            value == 0 ? "does not have" : "has");
3048
3049     value = get_masked_guint8(data, MASK_PREF);
3050     pi = proto_tree_add_bitfield8(tf2, bi->tvb, bi->offset, MASK_PREF);
3051     proto_item_append_text(pi, "Pref: The subscriber %s preferential access in the LSA",
3052                            value == 0 ? "does not have" : "has");
3053
3054     value = get_masked_guint8(data, MASK_PRIORITY);
3055     pi = proto_tree_add_bitfield8(tf2, bi->tvb, bi->offset, MASK_PRIORITY);
3056     proto_item_append_text(pi, "Priority: %s",
3057                            val_to_str(value, tab_priority, ""));
3058     bi->offset++;
3059
3060     proto_tree_add_lsa_id(bi, tf2);
3061   }
3062 }
3063
3064 static void
3065 decode_iei_gprs_timer(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3066   const guint8 MASK_UNIT_VALUE = 0xe0;
3067   const guint8 MASK_TIMER_VALUE = 0x1f;
3068   proto_item *ti;
3069   guint8 data, value;
3070
3071   static const value_string tab_unit_value[] = {
3072     { 0, "incremented in multiples of 2 s" },
3073     { 1, "incremented in multiples of 1 minute" },
3074     { 2, "incremented in multiples of decihours" },
3075     { 3, "incremented in multiples of 500 msec" },
3076     { 7, "the timer does not expire" },
3077     { 0, NULL},
3078     /* Otherwise "incremented in multiples of 1 minute" */
3079   };
3080
3081   if (bi->bssgp_tree) {
3082     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3083     data = tvb_get_guint8(bi->tvb, bi->offset);
3084     value = get_masked_guint8(data, MASK_TIMER_VALUE);
3085     proto_item_append_text(ti, ": %u", value);
3086
3087     value = get_masked_guint8(data, MASK_UNIT_VALUE);
3088     proto_item_append_text(ti, ", %s",
3089                            val_to_str(value, tab_unit_value,
3090                                       "incremented in multiples of 1 minute"));
3091   }
3092   bi->offset += ie->value_length;
3093 }
3094
3095 static void
3096 decode_iei_abqp(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3097   const guint8 MASK_DELAY_CLASS = 0x38;
3098   const guint8 MASK_RELIABILITY_CLASS = 0x07;
3099   const guint8 MASK_PEAK_THROUGHPUT = 0xf0;
3100   const guint8 MASK_PRECEDENCE_CLASS = 0x07;
3101   const guint8 MASK_MEAN_THROUGHPUT = 0x1f;
3102   const guint8 MASK_TRAFFIC_CLASS = 0xe0;
3103   const guint8 MASK_DELIVERY_ORDER = 0x18;
3104   const guint8 MASK_DELIVERY_OF_ERRONEOUS_SDU = 0x07;
3105   const guint8 MASK_RESIDUAL_BER = 0xf0;
3106   const guint8 MASK_SDU_ERROR_RATIO = 0x0f;
3107   const guint8 MASK_TRANSFER_DELAY = 0xfc;
3108   const guint8 MASK_TRAFFIC_HANDLING_PRIORITY = 0x03;
3109   const guint8 MASK_SIGNALLING_INDICATION = 0x10;
3110   const guint8 MASK_SOURCE_STATISTICS_DESCRIPTOR = 0x0f;
3111   const guint8 TRAFFIC_CLASS_CONVERSATIONAL = 1;
3112   const guint8 TRAFFIC_CLASS_STREAMING = 2;
3113   const guint8 TRAFFIC_CLASS_INTERACTIVE = 3;
3114   const guint8 TRAFFIC_CLASS_BACKGROUND = 4;
3115   guint8 data, value, traffic_class;
3116   proto_item *ti, *pi;
3117   proto_tree *tf;
3118
3119   if (!bi->bssgp_tree) {
3120     bi->offset += ie->value_length;
3121     return;
3122   }
3123   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3124   tf = proto_item_add_subtree(ti, ett_bssgp_abqp);
3125
3126   data = tvb_get_guint8(bi->tvb, bi->offset);
3127
3128   value = get_masked_guint8(data, MASK_DELAY_CLASS);
3129   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_DELAY_CLASS);
3130   proto_item_append_text(pi, "Delay Class: %s (%#x)",
3131                          translate_abqp_delay_class(value, bi), value);
3132
3133   value = get_masked_guint8(data, MASK_RELIABILITY_CLASS);
3134   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3135                                 MASK_RELIABILITY_CLASS);
3136   proto_item_append_text(pi, "Reliability Class: %s (%#x)",
3137                          translate_abqp_reliability_class(value, bi), value);
3138   bi->offset++;
3139   /* Octet 4 */
3140   data = tvb_get_guint8(bi->tvb, bi->offset);
3141
3142   value = get_masked_guint8(data, MASK_PEAK_THROUGHPUT);
3143   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3144                                 MASK_PEAK_THROUGHPUT);
3145   proto_item_append_text(pi, "Peak Throughput: %s (%#x)",
3146                          translate_abqp_peak_throughput(value, bi), value);
3147
3148   value = get_masked_guint8(data, MASK_PRECEDENCE_CLASS);
3149   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3150                                 MASK_PRECEDENCE_CLASS);
3151   proto_item_append_text(pi, "Precedence Class: %s (%#x)",
3152                          translate_abqp_precedence_class(value, bi), value);
3153   bi->offset++;
3154   /* Octet 5 */
3155   data = tvb_get_guint8(bi->tvb, bi->offset);
3156
3157   value = get_masked_guint8(data, MASK_MEAN_THROUGHPUT);
3158   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3159                                 MASK_MEAN_THROUGHPUT);
3160   proto_item_append_text(pi, "Mean Throughput: %s (%#02x)",
3161                          translate_abqp_mean_throughput(value, bi), value);
3162   /*
3163    * A QoS IE received without octets 6-16, without octets 14-16, or without octets 15-16 shall be accepted by the
3164    * receiving entity.
3165    */
3166   bi->offset++;
3167   if (ie->value_length == 3)
3168     return;
3169   /* Octet 6 */
3170   data = tvb_get_guint8(bi->tvb, bi->offset);
3171
3172   traffic_class = get_masked_guint8(data, MASK_TRAFFIC_CLASS);
3173   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_TRAFFIC_CLASS);
3174   proto_item_append_text(pi, "Traffic Class: %s (%#x)",
3175                          translate_abqp_traffic_class(traffic_class, bi),
3176                          value);
3177   if ((traffic_class == TRAFFIC_CLASS_INTERACTIVE) ||
3178       (traffic_class == TRAFFIC_CLASS_BACKGROUND)) {
3179     proto_item_append_text(pi, " (ignored)");
3180   }
3181
3182   value = get_masked_guint8(data, MASK_DELIVERY_ORDER);
3183   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_DELIVERY_ORDER);
3184   proto_item_append_text(pi, "Delivery Order: %s (%#x)",
3185                          translate_abqp_delivery_order(value, bi), value);
3186
3187   value = get_masked_guint8(data, MASK_DELIVERY_OF_ERRONEOUS_SDU);
3188   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3189                                 MASK_DELIVERY_OF_ERRONEOUS_SDU);
3190   proto_item_append_text(pi, "Delivery of Erroneous SDU: %s (%#x)",
3191                          translate_abqp_delivery_of_erroneous_sdu(value, bi),
3192                          value);
3193   bi->offset++;
3194   /* Octet 7 */
3195
3196   value = tvb_get_guint8(bi->tvb, bi->offset);
3197   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
3198                       "Maximum SDU Size: %s",
3199                       translate_abqp_max_sdu_size(value, bi));
3200   /* Octet 8 */
3201   bi->offset++;
3202
3203   value = tvb_get_guint8(bi->tvb, bi->offset);
3204   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
3205                       "Maximum bit rate for uplink: %s",
3206                       translate_abqp_max_bit_rate_for_ul(value, bi));
3207   /* Octet 9 */
3208   bi->offset++;
3209
3210   value = tvb_get_guint8(bi->tvb, bi->offset);
3211   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
3212                       "Maximum bit rate for downlink: %s",
3213                       translate_abqp_max_bit_rate_for_dl(value, bi));
3214   /* Octet 10 */
3215   bi->offset++;
3216   data = tvb_get_guint8(bi->tvb, bi->offset);
3217
3218   value = get_masked_guint8(data, MASK_RESIDUAL_BER);
3219   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_RESIDUAL_BER);
3220   proto_item_append_text(pi, "Residual BER: %s (%#x)",
3221                          translate_abqp_residual_ber(value, bi), value);
3222
3223   value = get_masked_guint8(data, MASK_SDU_ERROR_RATIO);
3224   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3225                                 MASK_SDU_ERROR_RATIO);
3226   proto_item_append_text(pi, "SDU Error Ratio: %s (%#x)",
3227                          translate_abqp_sdu_error_ratio(value, bi), value);
3228   /* Octet 11 */
3229   bi->offset++;
3230   data = tvb_get_guint8(bi->tvb, bi->offset);
3231
3232   value = get_masked_guint8(data, MASK_TRANSFER_DELAY);
3233   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_TRANSFER_DELAY);
3234   proto_item_append_text(pi, "Transfer Delay: %s (%#02x)",
3235                          translate_abqp_transfer_delay(value, bi), value);
3236
3237   value = get_masked_guint8(data, MASK_TRAFFIC_HANDLING_PRIORITY);
3238   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3239                                 MASK_TRAFFIC_HANDLING_PRIORITY);
3240   proto_item_append_text(pi, "Traffic Handling Priority: %s (%#x)",
3241                          translate_abqp_traffic_handling_priority(value, bi),
3242                          value);
3243   if ((traffic_class == TRAFFIC_CLASS_CONVERSATIONAL) ||
3244       (traffic_class == TRAFFIC_CLASS_STREAMING) ||
3245       (traffic_class == TRAFFIC_CLASS_BACKGROUND)) {
3246     proto_item_append_text(pi, " (ignored)");
3247   }
3248   /* Octet 12 */
3249   bi->offset++;
3250
3251   value = tvb_get_guint8(bi->tvb, bi->offset);
3252   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
3253                       "Guaranteed bit rate for uplink: %s",
3254                       translate_abqp_guaranteed_bit_rate_for_ul(value, bi));
3255   /* Octet 13 */
3256   bi->offset++;
3257
3258   value = tvb_get_guint8(bi->tvb, bi->offset);
3259   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
3260                       "Guaranteed bit rate for downlink: %s",
3261                       translate_abqp_guaranteed_bit_rate_for_dl(value, bi));
3262   /*
3263    * A QoS IE received without octets 6-16, without octets 14-16, or without octets 15-16 shall be accepted by the
3264    * receiving entity.
3265    */
3266   /* Octet 14 */
3267   bi->offset++;
3268   if (ie->value_length == 11)
3269     return;
3270
3271   data = tvb_get_guint8(bi->tvb, bi->offset);
3272
3273   value = get_masked_guint8(data, MASK_SIGNALLING_INDICATION);
3274   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3275                                 MASK_SIGNALLING_INDICATION);
3276   proto_item_append_text(pi, "Signalling Indication: %s for signalling traffic",
3277                          value == 0 ? "Not optimized" : "Optimized");
3278   if ((traffic_class == TRAFFIC_CLASS_CONVERSATIONAL) ||
3279       (traffic_class == TRAFFIC_CLASS_STREAMING) ||
3280       (traffic_class == TRAFFIC_CLASS_BACKGROUND)) {
3281     proto_item_append_text(pi, " (ignored)");
3282   }
3283
3284   value = get_masked_guint8(data, MASK_SOURCE_STATISTICS_DESCRIPTOR);
3285   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3286                                 MASK_SOURCE_STATISTICS_DESCRIPTOR);
3287   proto_item_append_text(pi, "Source Statistics Descriptor: %s (%#x)",
3288                          translate_abqp_source_statistics_descriptor(value, bi),
3289                          value);
3290   if ((traffic_class == TRAFFIC_CLASS_INTERACTIVE) ||
3291       (traffic_class == TRAFFIC_CLASS_BACKGROUND)) {
3292     proto_item_append_text(pi, " (ignored)");
3293   }
3294   /*
3295    * A QoS IE received without octets 6-16, without octets 14-16, or without octets 15-16 shall be accepted by the
3296    * receiving entity.
3297    */
3298   /* Octet 15 */
3299   bi->offset++;
3300   if (ie->value_length == 12)
3301     return;
3302
3303   value = tvb_get_guint8(bi->tvb, bi->offset);
3304   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
3305                       "Maximum bit rate for downlink (extended): %s",
3306                       translate_abqp_max_bit_rate_for_dl_extended(value, bi));
3307   /* Octet 16 */
3308   bi->offset++;
3309
3310   value = tvb_get_guint8(bi->tvb, bi->offset);
3311   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
3312                       "Guaranteed bit rate for downlink (extended): %s",
3313                       translate_abqp_guaranteed_bit_rate_for_dl_extended(value, bi));
3314   bi->offset++;
3315 }
3316
3317 static void
3318 decode_iei_feature_bitmap(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3319   const guint8 MASK_ENHANCED_RADIO_STATUS = 0x40;
3320   const guint8 MASK_PFC_FC = 0x20;
3321   const guint8 MASK_RIM = 0x10;
3322   const guint8 MASK_LCS = 0x08;
3323   const guint8 MASK_INR = 0x04;
3324   const guint8 MASK_CBL = 0x02;
3325   const guint8 MASK_PFC = 0x01;
3326   proto_item *ti, *pi;
3327   proto_tree *tf;
3328   guint8 data, value;
3329
3330   if (!bi->bssgp_tree) {
3331     bi->offset += ie->value_length;
3332     return;
3333   }
3334   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3335   tf = proto_item_add_subtree(ti, ett_bssgp_feature_bitmap);
3336
3337   data = tvb_get_guint8(bi->tvb, bi->offset);
3338
3339   value = get_masked_guint8(data, MASK_ENHANCED_RADIO_STATUS);
3340   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
3341                                 MASK_ENHANCED_RADIO_STATUS);
3342   proto_item_append_text(pi, "Enhanced Radio Status: Enhanced Radio Status Procedures%s supported",
3343                          value == 0 ? " not" : "");
3344
3345   value = get_masked_guint8(data, MASK_PFC_FC);
3346   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PFC_FC);
3347   proto_item_append_text(pi, "PFC_FC: PFC Flow Control Procedures%s supported",
3348                          value == 0 ? " not" : "");
3349
3350   value = get_masked_guint8(data, MASK_RIM);
3351   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_RIM);
3352   proto_item_append_text(pi, "RIM: RAN Information Management (RIM) Procedures%s supported",
3353                          value == 0 ? " not" : "");
3354
3355   value = get_masked_guint8(data, MASK_LCS);
3356   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_LCS);
3357   proto_item_append_text(pi, "LCS: LCS Procedures%s supported",
3358                          value == 0 ? " not" : "");
3359
3360   value = get_masked_guint8(data, MASK_INR);
3361   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_INR);
3362   proto_item_append_text(pi, "INR: Inter-NSE re-routing%s supported",
3363                          value == 0 ? " not" : "");
3364
3365   value = get_masked_guint8(data, MASK_CBL);
3366   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_CBL);
3367   proto_item_append_text(pi, "CBL: Current Bucket Level Procedures%s supported",
3368                          value == 0 ? " not" : "");
3369
3370   value = get_masked_guint8(data, MASK_PFC);
3371   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PFC);
3372   proto_item_append_text(pi, "PFC: Packet Flow Context Procedures%s supported",
3373                          value == 0 ? " not" : "");
3374
3375   bi->offset += ie->value_length;
3376 }
3377
3378 static void
3379 decode_iei_bucket_full_ratio(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3380   proto_item *ti;
3381
3382   if (bi->bssgp_tree) {
3383     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3384     bssgp_pi_append_bucket_full_ratio(ti, bi->tvb, bi->offset);
3385   }
3386   bi->offset += ie->value_length;
3387 }
3388
3389 static void
3390 decode_iei_service_utran_cco(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3391   const guint8 MASK_SERVICE_UTRAN_CCO = 0x07;
3392   proto_item *ti;
3393   guint8 data, value;
3394
3395   static const value_string tab_service_utran_cco[] = {
3396     { 0, "Network initiated cell change order procedure to UTRAN should be performed" },
3397     { 1, "Network initiated cell change order procedure to UTRAN should not be performed" },
3398     { 2, "Network initiated cell change order procedure to UTRAN shall not be performed" },
3399     { 0,    NULL },
3400     /* Otherwise "No information available" */
3401   };
3402
3403   if (bi->bssgp_tree) {
3404     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3405     data = tvb_get_guint8(bi->tvb, bi->offset);
3406     value = get_masked_guint8(data, MASK_SERVICE_UTRAN_CCO);
3407     proto_item_append_text(ti, ": %s (%#02x)",
3408                            val_to_str(value, tab_service_utran_cco,
3409                                       "No information available"),
3410                            value);
3411   }
3412   bi->offset += ie->value_length;
3413 }
3414
3415 static void
3416 decode_iei_nsei(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3417   proto_item *ti, *hidden_item;
3418   guint16 nsei;
3419
3420   nsei = tvb_get_ntohs(bi->tvb, bi->offset);
3421
3422   if (bi->bssgp_tree) {
3423     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3424     proto_item_append_text(ti, ": %u", nsei);
3425     hidden_item = proto_tree_add_item(bi->bssgp_tree, hf_bssgp_nsei,
3426                                       bi->tvb, bi->offset, 2, BSSGP_LITTLE_ENDIAN);
3427     PROTO_ITEM_SET_HIDDEN(hidden_item);
3428   }
3429   bi->offset += ie->value_length;
3430
3431   if (check_col(bi->pinfo->cinfo, COL_INFO)) {
3432     col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, BSSGP_SEP,
3433                         "NSEI %u", nsei);
3434   }
3435 }
3436
3437 static void
3438 decode_iei_lcs_qos(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3439   const guint8 MASK_VERT = 0x01;
3440   const guint8 MASK_XA = 0x80;
3441   const guint8 MASK_ACCURACY = 0x7f;
3442   const guint8 MASK_RT = 0xc0;
3443   proto_item *ti, *pi;
3444   proto_tree *tf;
3445   guint8 data, value, vert;
3446
3447   static const value_string tab_rt[] = {
3448     { 0, "Response time is not specified" },
3449     { 1, "Low delay" },
3450     { 2, "Delay tolerant" },
3451     { 3, "Reserved" },
3452     { 0, NULL },
3453   };
3454
3455   if (!bi->bssgp_tree) {
3456     bi->offset += ie->value_length;
3457     return;
3458   }
3459   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3460   tf = proto_item_add_subtree(ti, ett_bssgp_lcs_qos);
3461
3462   data = tvb_get_guint8(bi->tvb, bi->offset);
3463   vert = get_masked_guint8(data, MASK_VERT);
3464   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_VERT);
3465   proto_item_append_text(pi, "VERT: Vertical coordinate is%s requested",
3466                          vert == 0 ? " not" : "");
3467   bi->offset++;
3468
3469   data = tvb_get_guint8(bi->tvb, bi->offset);
3470
3471   value = get_masked_guint8(data, MASK_XA);
3472   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_XA);
3473   proto_item_append_text(pi, "HA: Horizontal Accuracy is%s specified",
3474                          value == 0 ? " not" : "");
3475
3476   if (value == 1) {
3477     value = get_masked_guint8(data, MASK_ACCURACY);
3478     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_ACCURACY);
3479     proto_item_append_text(pi, "Horizontal Accuracy: %.1f m",
3480                            10 * (pow(1.1, (double)value) - 1));
3481   }
3482   bi->offset++;
3483
3484   data = tvb_get_guint8(bi->tvb, bi->offset);
3485
3486   if (vert == 1) {
3487     value = get_masked_guint8(data, MASK_XA);
3488     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_XA);
3489     proto_item_append_text(pi, "VA: Vertical Accuracy is%s specified",
3490                            value == 0 ? " not" : "");
3491
3492     value = get_masked_guint8(data, MASK_ACCURACY);
3493     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_ACCURACY);
3494     proto_item_append_text(pi, "Vertical Accuracy: %.1f m",
3495                            45 * (pow(1.025, (double)value) - 1));
3496   }
3497   bi->offset++;
3498
3499   data = tvb_get_guint8(bi->tvb, bi->offset);
3500   value = get_masked_guint8(data, MASK_RT);
3501
3502   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_RT);
3503   proto_item_append_text(pi, "RT: %s",
3504                          val_to_str(value, tab_rt, ""));
3505   bi->offset++;
3506 }
3507
3508 static void
3509 decode_iei_lcs_client_type(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3510   const guint8 MASK_CATEGORY = 0xf0;
3511   const guint8 MASK_SUBTYPE = 0x0f;
3512   proto_item *ti, *pi;
3513   proto_tree *tf;
3514   guint8 data, category, subtype;
3515
3516   static const value_string tab_category[] = {
3517     { 0, "Value Added Client" },
3518     /* { 1, ??? XXX }, */
3519     { 2, "PLMN Operator" },
3520     { 3, "Emergency Services" },
3521     { 4, "Lawful Intercept Services" },
3522     { 0, NULL },
3523     /* Otherwise "Reserved" */
3524   };
3525
3526   if (!bi->bssgp_tree) {
3527     bi->offset += ie->value_length;
3528     return;
3529   }
3530   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3531   tf = proto_item_add_subtree(ti, ett_bssgp_lcs_client_type);
3532
3533   data = tvb_get_guint8(bi->tvb, bi->offset);
3534
3535   category = get_masked_guint8(data, MASK_CATEGORY);
3536   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_CATEGORY);
3537   proto_item_append_text(pi, "Category: %s (%#x)",
3538                          val_to_str(category, tab_category, "Reserved"),
3539                          category);
3540
3541   subtype = get_masked_guint8(data, MASK_SUBTYPE);
3542   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_SUBTYPE);
3543   proto_item_append_text(pi, "Subtype: ");
3544
3545   switch (category) {
3546   case 0:
3547     if (subtype == 0) {
3548       proto_item_append_text(pi, "Unspecified"); break;
3549     }
3550     else {
3551       proto_item_append_text(pi, "Reserved"); break;
3552     }
3553     /* case 1: ??? XXX*/
3554   case 2:
3555     switch (subtype) {
3556     case 0: proto_item_append_text(pi, "Unspecified"); break;
3557     case 1: proto_item_append_text(pi, "Broadcast service"); break;
3558     case 2: proto_item_append_text(pi, "O&M"); break;
3559     case 3: proto_item_append_text(pi, "Anonymous statistics"); break;
3560     case 4: proto_item_append_text(pi, "Target MS service support node"); break;
3561     default: proto_item_append_text(pi, "Reserved"); break;
3562     }
3563     break;
3564   case 3:
3565   case 4:
3566     if (subtype == 0) {
3567       proto_item_append_text(pi, "Unspecified"); break;
3568     }
3569     else {
3570       proto_item_append_text(pi, "Reserved"); break;
3571     }
3572   default: /* Not category == 1! */
3573     proto_item_append_text(pi, "Reserved"); break;
3574   }
3575
3576   bi->offset++;
3577 }
3578
3579 static void
3580 decode_iei_requested_gps_assistance_data(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3581   const guint8 MASK_A = 0x01;
3582   const guint8 MASK_B = 0x02;
3583   const guint8 MASK_C = 0x04;
3584   const guint8 MASK_D = 0x08;
3585   const guint8 MASK_E = 0x10;
3586   const guint8 MASK_F = 0x20;
3587   const guint8 MASK_G = 0x40;
3588   const guint8 MASK_H = 0x80;
3589   const guint8 MASK_I = 0x01;
3590   const guint8 MASK_NSAT = 0xf0;
3591   const guint8 MASK_T_TOE_LIMIT = 0x0f;
3592   const guint8 MASK_SAT_ID =0x3f;
3593   proto_tree *tf, *tf2;
3594   proto_item *ti, *ti2, *pi;
3595   guint8 data, value, d, nsat;
3596   guint16 gps_week;
3597   int i;
3598
3599   if (!bi->bssgp_tree) {
3600     bi->offset += ie->value_length;
3601     return;
3602   }
3603   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3604   tf = proto_item_add_subtree(ti, ett_bssgp_requested_gps_assistance_data);
3605
3606   data = tvb_get_guint8(bi->tvb, bi->offset);
3607
3608   value = get_masked_guint8(data, MASK_A);
3609   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_A);
3610   proto_item_append_text(pi, "A: Almanac is%s srequested",
3611                          value == 0 ? " not" : "");
3612
3613   value = get_masked_guint8(data, MASK_B);
3614   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_B);
3615   proto_item_append_text(pi, "B: UTC Model is%s requested",
3616                          value == 0 ? " not" : "");
3617
3618   value = get_masked_guint8(data, MASK_C);
3619   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_C);
3620   proto_item_append_text(pi, "C: Ionospheric Model is%s requested",
3621                          value == 0 ? " not" : "");
3622
3623   value = get_masked_guint8(data, MASK_D);
3624   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_D);
3625   proto_item_append_text(pi, "D: Navigation Model is%s requested",
3626                          value == 0 ? " not" : "");
3627   d = value;
3628
3629   value = get_masked_guint8(data, MASK_E);
3630   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_E);
3631   proto_item_append_text(pi, "E: DGPS Corrections are%s requested",
3632                          value == 0 ? " not" : "");
3633
3634   value = get_masked_guint8(data, MASK_F);
3635   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_F);
3636   proto_item_append_text(pi, "F: Reference Location is%s requested",
3637                          value == 0 ? " not" : "");
3638
3639   value = get_masked_guint8(data, MASK_G);
3640   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_G);
3641   proto_item_append_text(pi, "G: Reference Time is%s requested",
3642                          value == 0 ? " not" : "");
3643
3644   value = get_masked_guint8(data, MASK_H);
3645   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_H);
3646   proto_item_append_text(pi, "H: Acquisition Assistance is%s requested",
3647                          value == 0 ? " not" : "");
3648
3649   bi->offset++;
3650
3651   value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_I);
3652   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_I);
3653   proto_item_append_text(pi, "I: Real-Time Integrity is%s requested",
3654                          value == 0 ? " not" : "");
3655   if (d == 0) return;
3656
3657   data = tvb_get_guint8(bi->tvb, bi->offset);
3658   gps_week = (data & 0xc0) << 2;
3659   data = tvb_get_guint8(bi->tvb, bi->offset + 1);
3660   gps_week += data;
3661   proto_tree_add_text(tf, bi->tvb, bi->offset, 2,
3662                       "GPS Week: %u", gps_week);
3663   bi->offset += 2;
3664
3665   value = tvb_get_guint8(bi->tvb, bi->offset);
3666   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
3667                       "GPS Toe: %u", value);
3668   bi->offset++;
3669
3670   data = tvb_get_guint8(bi->tvb, bi->offset);
3671   nsat = get_masked_guint8(data, MASK_NSAT);
3672   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_NSAT);
3673   proto_item_append_text(pi, "NSAT: %u", value);
3674
3675   value = get_masked_guint8(data, MASK_T_TOE_LIMIT);
3676   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_T_TOE_LIMIT);
3677   proto_item_append_text(pi, "T-Toe Limit: %u", value);
3678   bi->offset++;
3679
3680   for (i = 0; i < nsat; i++) {
3681     ti2 = proto_tree_add_text(tf, bi->tvb, bi->offset, 2, "Satellite %u", i);
3682     tf2 = proto_item_add_subtree(ti2, ett_bssgp_requested_gps_assistance_data_satellite);
3683
3684     value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_SAT_ID);
3685     pi = proto_tree_add_bitfield8(tf2, bi->tvb, bi->offset, MASK_SAT_ID);
3686     proto_item_append_text(pi, "SatId: %u", value);
3687     proto_item_append_text(ti2, ": Id %u", value);
3688     bi->offset++;
3689
3690     value = tvb_get_guint8(bi->tvb, bi->offset);
3691     proto_tree_add_text(tf2, bi->tvb, bi->offset, 1,
3692                         "IODE: %u", value);
3693     proto_item_append_text(ti2, ", IODE %u", value);
3694     bi->offset++;
3695   }
3696 }
3697
3698 static void
3699 decode_iei_location_type(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3700   const guint8 LOCATION_ASSISTANCE = 1;
3701   const guint8 DECIPHERING_KEYS = 2;
3702   proto_item *ti;
3703   proto_tree *tf;
3704   guint8 value;
3705
3706   static const value_string tab_location_information[] = {
3707     { 0, "Current geographic location" },
3708     { 1, "Location assistance information for the target MS" },
3709     { 2, "Deciphering keys for broadcast assistance data for the target MS" },
3710     { 0, NULL },
3711     /* Otherwise "Reserved" */
3712   };
3713
3714   static const value_string tab_positioning_method[] = {
3715     { 0, "Reserved" },
3716     { 1, "Mobile Assisted E-OTD" },
3717     { 2, "Mobile Based E-OTD" },
3718     { 3, "Assisted GPS" },
3719     { 0, NULL },
3720     /* Otherwise "Reserved" */
3721   };
3722
3723   if (!bi->bssgp_tree) {
3724     bi->offset += ie->value_length;
3725     return;
3726   }
3727   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3728   tf = proto_item_add_subtree(ti, ett_bssgp_location_type);
3729
3730   value = tvb_get_guint8(bi->tvb, bi->offset);
3731   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, "Location Information: %s",
3732                       val_to_str(value, tab_location_information,
3733                                  "Reserved"));
3734   bi->offset++;
3735
3736   if ((value == LOCATION_ASSISTANCE) || (value == DECIPHERING_KEYS)) {
3737     value = tvb_get_guint8(bi->tvb, bi->offset);
3738     proto_tree_add_text(tf, bi->tvb, bi->offset, 1, "Positioning Method: %s",
3739                         val_to_str(value, tab_positioning_method,
3740                                    "Reserved"));
3741     bi->offset++;
3742   }
3743 }
3744
3745 static void
3746 decode_iei_location_estimate(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3747   /* XXX: Which paragraph in 3GPP TS 23.032?*/
3748   proto_item *ti;
3749
3750   if (bi->bssgp_tree) {
3751     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3752     proto_item_append_text(ti, ": %s", BSSGP_NOT_DECODED);
3753   }
3754   if (ie->value_length != BSSGP_UNKNOWN) {
3755     bi->offset += ie->value_length;
3756   }
3757 }
3758
3759 static void
3760 decode_iei_positioning_data(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3761   const guint8 MASK_PDD = 0x0f;
3762   const guint8 MASK_METHOD = 0xf8;
3763   const guint8 MASK_USAGE = 0x07;
3764   proto_item *ti, *pi;
3765   proto_tree *tf;
3766   guint8 data, value, i, num_methods;
3767
3768   if (!bi->bssgp_tree) {
3769     bi->offset += ie->value_length;
3770     return;
3771   }
3772   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3773   tf = proto_item_add_subtree(ti, ett_bssgp_positioning_data);
3774
3775   value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_PDD);
3776   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_PDD);
3777   proto_item_append_text(pi, "Positioning Data Discriminator: %s",
3778                          value == 0 ?
3779                          "Indicate usage of each positioning method that was attempted either successfully or unsuccessfully" :
3780                          "Reserved");
3781   bi->offset++;
3782
3783   num_methods = ie->value_length - 1;
3784   for (i = 0; i < num_methods; i++) {
3785     data = tvb_get_guint8(bi->tvb, bi->offset);
3786
3787     value = get_masked_guint8(data, MASK_METHOD);
3788     pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_METHOD);
3789     proto_item_append_text(pi, "Method: ");
3790
3791     switch (value) {
3792     case 0: proto_item_set_text(pi, "Timing Advance"); break;
3793     case 1: proto_item_set_text(pi, "Reserved"); break;
3794     case 2: proto_item_set_text(pi, "Reserved"); break;
3795     case 3: proto_item_set_text(pi, "Mobile Assisted E-OTD"); break;
3796     case 4: proto_item_set_text(pi, "Mobile Based E-OTD"); break;
3797     case 5: proto_item_set_text(pi, "Mobile Assisted GPS"); break;
3798     case 6: proto_item_set_text(pi, "Mobile Based GPS"); break;
3799     case 7: proto_item_set_text(pi, "Conventional GPS"); break;
3800     case 8: proto_item_set_text(pi, "U-TDOA"); break;
3801     default:
3802       if ((value >= 9) && (value <= 0x0f)) {
3803         proto_item_set_text(pi, "Reserved for GSM");
3804       }
3805       else {
3806         proto_item_set_text(pi, "Reserved for network specific positioning methods");
3807       }
3808     }
3809     proto_item_append_text(pi, " (%#02x)", value); /* Method */
3810
3811     value = get_masked_guint8(data, MASK_USAGE);
3812
3813     switch (value) {
3814     case 0: proto_item_append_text(pi, " attempted unsuccessfully due to failure or interruption "); break;
3815     case 1: proto_item_append_text(pi, " attempted successfully: results not used to generate location"); break;
3816     case 2: proto_item_append_text(pi, " attempted successfully: results used to verify but not generate location"); break;
3817     case 3: proto_item_append_text(pi, " attempted successfully: results used to generate location"); break;
3818     case 4: proto_item_append_text(pi, " attempted successfully: case where MS supports multiple mobile based"
3819                                        " positioning methods and the actual method or methods used by the MS cannot be determined"); break;
3820     default: ; /* ??? */
3821     }
3822     proto_item_append_text(pi, " (%#x)", value); /* Usage */
3823     bi->offset++;
3824   }
3825 }
3826
3827 static void
3828 decode_iei_deciphering_keys(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3829   const guint8 MASK_KEY_FLAG = 0x01;
3830   proto_item *ti, *pi;
3831   proto_tree *tf;
3832   guint8 data, value;
3833
3834   if (!bi->bssgp_tree) {
3835     bi->offset += ie->value_length;
3836     return;
3837   }
3838
3839   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3840   tf = proto_item_add_subtree(ti, ett_bssgp_deciphering_keys);
3841
3842   data = tvb_get_guint8(bi->tvb, bi->offset);
3843   value = get_masked_guint8(data, MASK_KEY_FLAG);
3844   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_KEY_FLAG);
3845   proto_item_append_text(pi, "Ciphering Key Flag: %u", value);
3846   bi->offset++;
3847
3848   proto_tree_add_text(tf, bi->tvb, bi->offset, 7,
3849                       "Current Deciphering Key Value");
3850   bi->offset += 7;
3851
3852   proto_tree_add_text(tf, bi->tvb, bi->offset, 7,
3853                       "Next Deciphering Key Value");
3854   bi->offset += 7;
3855 }
3856
3857 static void
3858 decode_iei_lcs_priority(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3859   /* XXX: coding (3GPP TS 29.002 7.6.11.7)? */
3860   proto_item *ti;
3861
3862   if (bi->bssgp_tree) {
3863     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3864     proto_item_append_text(ti, ": %s", BSSGP_NOT_DECODED);
3865   }
3866   bi->offset += ie->value_length;
3867 }
3868
3869 static void
3870 decode_iei_lcs_cause(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3871   proto_item *ti;
3872   proto_tree *tf;
3873   guint8 value;
3874
3875   static const value_string tab_cause_value[] = {
3876     { 0, "Unspecified" },
3877     { 1, "System failure" },
3878     { 2, "Protocol error" },
3879     { 3, "Data missing in position request" },
3880     { 4, "Unexpected value in position request" },
3881     { 5, "Position method failure" },
3882     { 6, "Target MS unreachable" },
3883     { 7, "Location request aborted" },
3884     { 8, "Facility not supported" },
3885     { 9, "Inter-BSC handover ongoing" },
3886     { 10, "Intra-BSC handover ongoing" },
3887     { 11, "Congestion" },
3888     { 12, "Inter NSE cell change" },
3889     { 13, "Routing area update" },
3890     { 14, "PTMSI reallocation" },
3891     { 15, "Suspension of GPRS services" },
3892     { 0, NULL },
3893     /* Otherwise "Unspecified" */
3894   };
3895
3896   static const value_string tab_diagnostic_value[] = {
3897     { 0, "Congestion" },
3898     { 1, "Insufficient resources" },
3899     { 2, "Insufficient measurement data" },
3900     { 3, "Inconsistent measurement data" },
3901     { 4, "Location procedure not completed" },
3902     { 5, "Location procedure not supported by target MS" },
3903     { 6, "QoS not attainable" },
3904     { 7, "Position method not available in network" },
3905     { 8, "Position method not available in location area" },
3906     { 0, NULL },
3907     /* Otherwise "Unrecognized => ignored" */
3908   };
3909
3910   if (!bi->bssgp_tree) {
3911     bi->offset += ie->value_length;
3912     return;
3913   }
3914   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3915   value = tvb_get_guint8(bi->tvb, bi->offset);
3916
3917   if (ie->value_length == 1) {
3918     /* Diagnostic value not included */
3919     proto_item_append_text(ti, ": %s (%#02x)",
3920                            val_to_str(value, tab_cause_value, "Unspecified"),
3921                            value);
3922     bi->offset++;
3923     return;
3924   }
3925
3926   tf = proto_item_add_subtree(ti, ett_bssgp_lcs_cause);
3927
3928   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, ": %s (%#02x)",
3929                       val_to_str(value, tab_cause_value, "Unspecified"),
3930                       value);
3931   bi->offset++;
3932
3933   value = tvb_get_guint8(bi->tvb, bi->offset);
3934   proto_tree_add_text(tf, bi->tvb, bi->offset, 1, ": %s (%#02x)",
3935                       val_to_str(value, tab_diagnostic_value,
3936                                  "Unrecognized => ignored"),
3937                       value);
3938   bi->offset++;
3939 }
3940
3941 static void
3942 decode_iei_lcs_capability(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3943   const guint8 MASK_OTD_A = 0x10;
3944   const guint8 MASK_OTD_B = 0x08;
3945   const guint8 MASK_GPS_A = 0x04;
3946   const guint8 MASK_GPS_B = 0x02;
3947   const guint8 MASK_GPS_C = 0x01;
3948   proto_item *ti, *pi;
3949   proto_tree *tf;
3950   guint8 data, value;
3951
3952   if (!bi->bssgp_tree) {
3953     bi->offset += ie->value_length;
3954     return;
3955   }
3956   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3957   tf = proto_item_add_subtree(ti, ett_bssgp_lcs_capability);
3958
3959   data = tvb_get_guint8(bi->tvb, bi->offset);
3960
3961   value = get_masked_guint8(data, MASK_OTD_A);
3962   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_OTD_A);
3963   proto_item_append_text(pi, "OTD-A: MS Assisted E-OTD%s supported",
3964                          value == 0 ? " not" : "");
3965
3966   value = get_masked_guint8(data, MASK_OTD_B);
3967   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_OTD_B);
3968   proto_item_append_text(pi, "OTD-B: MS Based E-OTD%s supported",
3969                          value == 0 ? " not" : "");
3970
3971   value = get_masked_guint8(data, MASK_GPS_A);
3972   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_GPS_A);
3973   proto_item_append_text(pi, "GPS-A: MS Assisted GPS%s supported",
3974                          value == 0 ? " not" : "");
3975
3976   value = get_masked_guint8(data, MASK_GPS_B);
3977   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_GPS_B);
3978   proto_item_append_text(pi, "GPS-B: MS Based GPS%s supported",
3979                          value == 0 ? " not" : "");
3980
3981   value = get_masked_guint8(data, MASK_GPS_C);
3982   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_GPS_C);
3983   proto_item_append_text(pi, "GPS-C: Conventional GPS%s supported",
3984                          value == 0 ? " not" : "");
3985
3986   bi->offset++;
3987 }
3988
3989 static void
3990 decode_iei_rrlp_flags(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
3991   const guint8 MASK_FLAG1 = 0x01;
3992   proto_item *ti;
3993   guint8 value;
3994
3995   if (bi->bssgp_tree) {
3996     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
3997     value = tvb_get_masked_guint8(bi->tvb, bi->offset, MASK_FLAG1);
3998     proto_item_append_text(ti, ": Flag1:%s Position Command (BSS to SGSN) or final response (SGSN to BSS) (%u)",
3999                            value == 0 ? " Not a" : "", value);
4000   }
4001   bi->offset++;
4002 }
4003
4004 static void /* [7] 11.3.61 RIM Application Identity */
4005 decode_iei_rim_application_identity(bssgp_ie_t *ie _U_, build_info_t *bi, int ie_start_offset _U_) {
4006   proto_item *ti;
4007   guint8 appid;
4008
4009   if (!bi->bssgp_tree) {
4010     bi->offset += 8;
4011     return;
4012   }
4013
4014   ti = proto_tree_add_item(bi->bssgp_tree, hf_bssgp_appid,
4015                            bi->tvb, bi->offset, 1, FALSE);
4016
4017   appid = tvb_get_guint8(bi->tvb, bi->offset);
4018   switch (appid) {
4019   case 0: proto_item_append_text(ti, " - Reserved"); break;
4020   case 1: proto_item_append_text(ti, " - Network Assisted Cell Change (NACC)"); break;
4021   case 0x10: proto_item_append_text(ti, " - System Information 3 (SI3)"); break;
4022   case 0x11: proto_item_append_text(ti, " - MBMS data channel"); break;
4023   default: proto_item_append_text(ti, " - Reserved");
4024   }
4025   bi->offset++;
4026
4027 }
4028
4029 #if 0
4030 static void
4031 decode_ran_information_common(build_info_t *bi, proto_tree *parent_tree) {
4032   proto_tree *tf;
4033   proto_item *ti;
4034   char *rai_ci;
4035   guint8 num_rai_cis, i;
4036
4037   ti = proto_tree_add_text(parent_tree, bi->tvb, bi->offset, 8,
4038                            "RAI + CI for Source Cell");
4039   tf = proto_item_add_subtree(ti, ett_bssgp_rai_ci);
4040
4041   rai_ci = decode_rai_ci(bi, tf);
4042   proto_item_append_text(ti, ": %s", rai_ci);
4043
4044   num_rai_cis = tvb_get_guint8(bi->tvb, bi->offset);
4045   proto_tree_add_text(tf, bi->tvb, bi->offset, 1,
4046                       "%u ""RAI+CI for Destination Cell"" follow%s",
4047                       num_rai_cis, (num_rai_cis == 0) ? "" : "s");
4048   bi->offset++;
4049
4050   for (i = 0; i < num_rai_cis; i++) {
4051     ti = proto_tree_add_text(parent_tree, bi->tvb, bi->offset, 8,
4052                              """RAI + CI for Destination Cell"" (%u)", i + 1);
4053     tf = proto_item_add_subtree(ti, ett_bssgp_rai_ci);
4054     rai_ci = decode_rai_ci(bi, tf);
4055     proto_item_append_text(ti, ": %s", rai_ci);
4056   }
4057 }
4058 #endif
4059
4060 /*
4061  * 11.3.77 RIM Routing Information
4062  */
4063 static const value_string ra_discriminator_vals[] = {
4064   { 0, "A Cell Identifier is used to identify a GERAN cell" },
4065   { 1, "A Global RNC-ID is used to identify a UTRAN RNC" },
4066   { 0, NULL },
4067 };
4068
4069 static void
4070 decode_iei_rim_routing_information(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
4071   proto_item *ti;
4072   proto_tree *tf;
4073   guint8 data;
4074
4075   if (bi->bssgp_tree) {
4076     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
4077     tf = proto_item_add_subtree(ti, ett_bssgp_rim_routing_information);
4078
4079     proto_tree_add_item(tf, hf_bssgp_ra_discriminator,
4080                         bi->tvb, bi->offset, 1, FALSE);
4081
4082     data = tvb_get_guint8(bi->tvb, bi->offset);
4083
4084     bi->offset += 1;
4085
4086     decode_rai(bi, tf);
4087
4088     proto_tree_add_item(tf, hf_bssgp_ci,
4089                       bi->tvb, bi->offset, 2, BSSGP_LITTLE_ENDIAN);
4090     bi->offset += 2;
4091
4092   } else {
4093     bi->offset += ie->value_length;
4094   }
4095
4096 }
4097
4098 static void  /* [7] 11.62a.1 */
4099 decode_iei_ran_container_unit(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
4100   proto_item *ti;
4101   proto_tree *tf;
4102
4103   if (!bi->bssgp_tree) {
4104     bi->offset += 8;
4105     return;
4106   }
4107
4108   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
4109   tf = proto_item_add_subtree(ti, ett_bssgp_ran_information_request_container_unit);
4110 }
4111
4112 static void
4113 decode_iei_application_error(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
4114   proto_item *ti;
4115   proto_tree *tf;
4116
4117   if (bi->bssgp_tree) {
4118     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
4119     tf = proto_item_add_subtree(ti, ett_bssgp_ran_information_container_unit);
4120
4121     proto_tree_add_item(tf, hf_bssgp_iei_nacc_cause, bi->tvb, bi->offset, 1, FALSE);
4122     proto_tree_add_text(tf, bi->tvb, bi->offset, tvb_length(bi->tvb) - bi->offset , "Erroneous Application Container including IEI and LI");
4123
4124   } else {
4125     bi->offset += ie->value_length;
4126   }
4127 }
4128
4129 /*
4130  * 11.3.63.1.1 RAN-INFORMATION-REQUEST Application Container for the NACC Application
4131  */
4132 static void
4133 decode_iei_ran_information_request_application_container(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
4134   proto_item *ti;
4135   proto_tree *tf;
4136   char *rai_ci;
4137
4138   if (bi->bssgp_tree) {
4139     ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
4140     tf = proto_item_add_subtree(ti, ett_bssgp_ran_information_container_unit);
4141
4142     /*
4143      * Octet 3-10 Reporting Cell Identifier:
4144      * This field is encoded as the Cell Identifier defined in sub-clause 11.3.9
4145      */
4146     rai_ci = decode_rai_ci(bi, tf);
4147     proto_item_append_text(ti, ": %s", rai_ci);
4148
4149   } else {
4150     bi->offset += ie->value_length;
4151   }
4152 }
4153 static void
4154 decode_iei_ran_information_application_container(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
4155   const guint8 MASK_NUMBER_OF_SI_PSI = 0xfe;
4156   const guint8 MASK_UNIT_TYPE = 0x01;
4157   const guint8 TYPE_SI = 0;
4158   const guint8 TYPE_PSI = 1;
4159   const guint8 LEN_SI = 21;
4160   const guint8 LEN_PSI = 22;
4161   proto_item *ti, *pi;
4162   proto_tree *tf;
4163   guint8 num_si_psi, type_si_psi, data, i;
4164
4165   if (! bi->bssgp_tree) {
4166     bi->offset += 8;
4167     return;
4168   }
4169   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
4170   tf = proto_item_add_subtree(ti, ett_bssgp_ran_information_container_unit);
4171
4172   /* don't work, ran_information_common read number of rai's but it is only one.
4173      decode_ran_information_common(bi, tf); */
4174   decode_rai_ci(bi,tf);
4175
4176   data = tvb_get_guint8(bi->tvb, bi->offset);
4177   num_si_psi = get_masked_guint8(data, MASK_NUMBER_OF_SI_PSI);
4178   type_si_psi = get_masked_guint8(data, MASK_UNIT_TYPE);
4179
4180   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset,
4181                                 MASK_NUMBER_OF_SI_PSI);
4182   proto_item_append_text(pi, "Number of SI/PSI: %u ""SI/PSI"" follow%s",
4183                          num_si_psi,
4184                          num_si_psi < 2 ? "s" : "");
4185
4186   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_UNIT_TYPE);
4187   proto_item_append_text(pi, "Type: %s messages as specified for %s follow",
4188                          type_si_psi == TYPE_SI ? "SI" : "PSI",
4189                          type_si_psi == TYPE_SI ? "BCCH" : "PBCCH");
4190
4191   bi->offset++;
4192
4193   for (i = 0; i < num_si_psi; i++) {
4194     if (type_si_psi == TYPE_SI) {
4195       proto_tree_add_text(tf, bi->tvb, bi->offset, LEN_SI,
4196                           " SI (%u), %u octets", i + 1, LEN_SI);
4197       /* XXX: Not decoded yet; which section in 3GPP TS 44.018? */
4198       proto_tree_add_item(tf, hf_bssgp_rrc_si_msg_type, bi->tvb, bi->offset, 1, FALSE);
4199       /* TODO:
4200        * Add decoding in packet-gsm_a.c ? Needs a new exported function "gsm_a_decode_rr_message?)
4201        *
4202        */
4203       bi->offset += LEN_SI;
4204     }
4205     else if (type_si_psi == TYPE_PSI) {
4206       proto_tree_add_text(tf, bi->tvb, bi->offset, LEN_PSI,
4207                           " PSI (%u), %u octets", i + 1, LEN_PSI);
4208       /* XXX: Not decoded yet; which section in 3GPP TS 44.060?
4209
4210           System information messages: Reference
4211           Packet System Information Type 1 11.2.18
4212           Packet System Information Type 2 11.2.19
4213           Packet System Information Type 3 11.2.20
4214           Packet System Information Type 3 bis 11.2.21
4215           Packet System Information Type 3 ter 11.2.21a
4216           Packet System Information Type 3 quater 11.2.21b
4217           Packet System Information Type 5 11.2.23
4218           Packet System Information Type 6 11.2.23a
4219           Packet System Information Type 7 11.2.23b
4220           Packet System Information Type 8 11.2.24
4221           Packet System Information Type 13 11.2.25
4222           Packet System Information Type 14 11.2.25a
4223           Packet System Information Type 15 11.2.25b
4224           Packet System Information Type 16 11.2.25c
4225       */
4226       bi->offset += LEN_PSI;
4227     }
4228   }
4229 }
4230 static const value_string ran_inf_req_pdu_type_ext_vals[] = {
4231   { 0,"RAN-INFORMATION-REQUEST/Stop PDU" },
4232   { 1,"RAN-INFORMATION-REQUEST/Single Report PDU" },
4233   { 2,"RAN-INFORMATION-REQUEST/Multiple Report PDU" },
4234   { 3,"Reserved" },
4235   { 4,"Reserved" },
4236   { 5,"Reserved" },
4237   { 6,"Reserved" },
4238   { 7,"Reserved" },
4239   { 0, NULL },
4240 };
4241
4242 static const value_string ran_inf_pdu_type_ext_vals[] = {
4243   { 0,"RAN-INFORMATION/Stop PDU" },
4244   { 1,"RAN-INFORMATION/Single Report PDU" },
4245   { 2,"RAN-INFORMATION/Initial Multiple Report PDU" },
4246   { 3,"RAN-INFORMATION/Multiple Report PDU" },
4247   { 4,"RAN-INFORMATION/End PDU" },
4248   { 5,"Reserved" },
4249   { 6,"Reserved" },
4250   { 7,"Reserved" },
4251   { 0, NULL },
4252 };
4253 /* 11.3.65 RIM PDU Indications 3GPP TS 48.018 version 6.7.0 Release 6 */
4254 static void
4255 decode_iei_rim_pdu_indications(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
4256   /**  const guint8 MASK_EXT = 0x0E; **/
4257   const guint8 MASK_ACK = 0x01;
4258   proto_item *ti, *pi;
4259   proto_tree *tf;
4260   guint8 data, value;
4261
4262   if (!bi->bssgp_tree) {
4263     bi->offset += ie->value_length;
4264     return;
4265   }
4266   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
4267   tf = proto_item_add_subtree(ti, ett_bssgp_rim_pdu_indications);
4268
4269   data = tvb_get_guint8(bi->tvb, bi->offset);
4270
4271   if (bi->pdutype == BSSGP_IEI_RAN_INFORMATION_CONTAINER_UNIT) {
4272     proto_tree_add_item(tf, hf_ran_inf_pdu_type_ext, bi->tvb, bi->offset, 1, FALSE);
4273   }else{
4274     proto_tree_add_item(tf, hf_ran_inf_req_pdu_type_ext, bi->tvb, bi->offset, 1, FALSE);
4275   }
4276
4277   value = get_masked_guint8(data, MASK_ACK);
4278   pi = proto_tree_add_bitfield8(tf, bi->tvb, bi->offset, MASK_ACK);
4279   proto_item_append_text(pi, "ACK: %sACK requested",
4280                          value == 0 ? "No " : "");
4281   bi->offset++;
4282 }
4283
4284 static void
4285 decode_iei_number_of_container_units(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
4286   proto_item *ti;
4287   guint8 value;
4288
4289   if (!bi->bssgp_tree) {
4290     bi->offset += ie->value_length;
4291     return;
4292   }
4293   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
4294   value = tvb_get_guint8(bi->tvb, bi->offset);
4295   proto_item_append_text(ti, ": %u Container Unit%s follow%s",
4296                          value + 1,
4297                          value == 0 ? "" : "s",
4298                          value > 0 ? "s" : "");
4299   bi->offset++;
4300 }
4301
4302 static void
4303 decode_iei_pfc_flow_control_parameters(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
4304   proto_tree *tf, *tf2;
4305   proto_item *ti, *ti2, *pi;
4306   guint8 num_pfc, i, pfc_len;
4307   gboolean b_pfc_included;
4308
4309   if (!bi->bssgp_tree) {
4310     bi->offset += ie->value_length;
4311     return;
4312   }
4313   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
4314   tf = proto_item_add_subtree(ti, ett_bssgp_pfc_flow_control_parameters);
4315
4316   num_pfc = tvb_get_guint8(bi->tvb, bi->offset);
4317   pi = proto_tree_add_text(bi->bssgp_tree, bi->tvb, bi->offset, 1,
4318                            "Number of PFCs: ");
4319
4320   if (num_pfc < 12) {
4321     proto_item_append_text(pi, "%u", num_pfc);
4322   }
4323   else {
4324     proto_item_append_text(pi, "Reserved");
4325     return;
4326   }
4327   bi->offset++;
4328   if (num_pfc == 0) return;
4329
4330   pfc_len = (ie->value_length - 1) / num_pfc;
4331   b_pfc_included = (pfc_len == 6);
4332
4333   for (i = 0; i < num_pfc; i++) {
4334     ti2 = proto_tree_add_text(tf, bi->tvb, bi->offset, pfc_len,
4335                               "PFC (%u)", i + 1);
4336     tf2 = proto_item_add_subtree(ti2, ett_bssgp_pfc_flow_control_parameters_pfc);
4337
4338     pi = proto_tree_add_text(tf2, bi->tvb, bi->offset, 1, "PFI");
4339     bssgp_pi_append_pfi(pi, bi->tvb, bi->offset);
4340     bi->offset++;
4341
4342     pi = proto_tree_add_text(tf2, bi->tvb, bi->offset, 2, "BMax_PFC");
4343     bssgp_pi_append_bucket_size(pi, bi->tvb, bi->offset);
4344     bi->offset += 2;
4345
4346     pi = proto_tree_add_text(tf2, bi->tvb, bi->offset, 2, "R_PFC");
4347     bssgp_pi_append_bucket_leak_rate(pi, bi->tvb, bi->offset);
4348     bi->offset += 2;
4349
4350     if (b_pfc_included) {
4351       pi = proto_tree_add_text(tf2, bi->tvb, bi->offset, 1, "B_PFC");
4352       bssgp_pi_append_bucket_full_ratio(pi, bi->tvb, bi->offset);
4353       bi->offset++;
4354     }
4355   }
4356 }
4357
4358 static void
4359 decode_iei_global_cn_id(bssgp_ie_t *ie, build_info_t *bi, int ie_start_offset) {
4360   proto_tree *ti;
4361   proto_tree *tf;
4362   guint16 value;
4363   char *mcc_mnc;
4364
4365   if (!bi->bssgp_tree) {
4366     bi->offset += ie->value_length;
4367     return;
4368   }
4369   ti = bssgp_proto_tree_add_ie(ie, bi, ie_start_offset);
4370   tf = proto_item_add_subtree(ti, ett_bssgp_global_cn_id);
4371
4372   mcc_mnc = decode_mcc_mnc(bi, tf);
4373   proto_item_append_text(ti, ": PLMN-Id %s", mcc_mnc);
4374
4375   value = tvb_get_ntohs(bi->tvb, bi->offset);
4376   proto_tree_add_text(tf, bi->tvb, bi->offset, 2,
4377                       "CN-ID: %u", value);
4378   proto_item_append_text(ti, ", CN-Id %u", value);
4379   bi->offset += 2;
4380 }
4381
4382 static void
4383 decode_ie(bssgp_ie_t *ie, build_info_t *bi) {
4384   int org_offset = bi->offset;
4385
4386   if (tvb_length_remaining(bi->tvb, bi->offset) < 1) {
4387     /* TODO This code does not work well with omitted Optional elements
4388        proto_tree_add_none_format(bi->bssgp_tree, NULL, bi->tvb, 0, -1, "[tvb_length_remaining] length remaining: %d", tvb_length_remaining(bi->tvb, bi->offset));
4389     */
4390     return;
4391   }
4392   switch (ie->format) {
4393   case BSSGP_IE_FORMAT_TLV:
4394     if (!check_correct_iei(ie, bi)) {
4395 #ifdef BSSGP_DEBUG
4396       /* TODO This code does not work well with omitted Optional elements */
4397       proto_tree_add_none_format(bi->bssgp_tree, NULL, bi->tvb, 0, -1, "[BSSGP_IE_FORMAT_TLV] format: %d", ie->format);
4398 #endif
4399       return;
4400     }
4401     bi->offset++; /* Account for type */
4402     ie->total_length = 1;
4403     get_value_length(ie, bi);
4404     break;
4405   case BSSGP_IE_FORMAT_TV:
4406     if (!check_correct_iei(ie, bi)) {
4407 #ifdef BSSGP_DEBUG
4408       /* TODO This code does not work well with omitted Optional elements */
4409       proto_tree_add_none_format(bi->bssgp_tree, NULL, bi->tvb, 0, -1, "[BSSGP_IE_FORMAT_TV] format: %d", ie->format);
4410 #endif
4411       return;
4412     }
4413     bi->offset++; /* Account for type */
4414     ie->value_length = ie->total_length - 1;
4415     break;
4416   case BSSGP_IE_FORMAT_V:
4417     ie->value_length = ie->total_length;
4418     break;
4419   default:
4420     ;
4421   }
4422
4423   switch (ie->iei) {
4424   case BSSGP_IEI_ALIGNMENT_OCTETS:
4425     decode_iei_alignment_octets(ie, bi, org_offset);
4426     break;
4427   case BSSGP_IEI_BMAX_DEFAULT_MS:
4428     decode_bucket_size(ie, bi, org_offset);
4429     break;
4430   case BSSGP_IEI_BSS_AREA_INDICATION:
4431     /* XXX: 'The recipient shall ignore the value of this octet'??? */
4432     decode_simple_ie(ie, bi, org_offset, "BSS Indicator", "", TRUE);
4433     break;
4434   case BSSGP_IEI_BUCKET_LEAK_RATE:
4435     decode_bucket_leak_rate(ie, bi, org_offset);
4436     break;
4437   case BSSGP_IEI_BVCI:
4438     decode_iei_bvci(ie, bi, org_offset);
4439     break;
4440   case BSSGP_IEI_BVC_BUCKET_SIZE:
4441     decode_bucket_size(ie, bi, org_offset);
4442     break;
4443   case BSSGP_IEI_BVC_MEASUREMENT:
4444     decode_queuing_delay(ie, bi, org_offset);
4445     break;
4446   case BSSGP_IEI_CAUSE:
4447     decode_iei_cause(ie, bi, org_offset);
4448     break;
4449   case BSSGP_IEI_CELL_IDENTIFIER:
4450     decode_iei_cell_identifier(ie, bi, org_offset);
4451     break;
4452   case BSSGP_IEI_CHANNEL_NEEDED:
4453     decode_iei_channel_needed(ie, bi, org_offset);
4454     break;
4455   case BSSGP_IEI_DRX_PARAMETERS:
4456     decode_iei_drx_parameters(ie, bi, org_offset);
4457     break;
4458   case BSSGP_IEI_EMLPP_PRIORITY:
4459     decode_iei_emlpp_priority(ie, bi, org_offset);
4460     break;
4461   case BSSGP_IEI_FLUSH_ACTION:
4462     decode_iei_flush_action(ie, bi, org_offset);
4463     break;
4464   case BSSGP_IEI_IMSI:
4465     decode_mobile_identity(ie, bi, org_offset);
4466     break;
4467   case BSSGP_IEI_LLC_PDU:
4468     bssgp_proto_handoff(ie, bi, org_offset, llc_handle);
4469     break;
4470   case BSSGP_IEI_LLC_FRAMES_DISCARDED:
4471     decode_iei_llc_frames_discarded(ie, bi, org_offset);
4472     break;
4473   case BSSGP_IEI_LOCATION_AREA:
4474     decode_iei_location_area(ie, bi, org_offset);
4475     break;
4476   case BSSGP_IEI_MOBILE_ID:
4477     decode_mobile_identity(ie, bi, org_offset);
4478     break;
4479   case BSSGP_IEI_MS_BUCKET_SIZE:
4480     decode_bucket_size(ie, bi, org_offset);
4481     break;
4482   case BSSGP_IEI_MS_RADIO_ACCESS_CAPABILITY:
4483     decode_iei_ms_radio_access_capability(ie, bi, org_offset);
4484     break;
4485   case BSSGP_IEI_OMC_ID:
4486     decode_iei_omc_id(ie, bi, org_offset);
4487     break;
4488   case BSSGP_IEI_PDU_IN_ERROR:
4489     decode_iei_pdu_in_error(ie, bi, org_offset);
4490     break;
4491   case BSSGP_IEI_PDU_LIFETIME:
4492     decode_queuing_delay(ie, bi, org_offset);
4493     break;
4494   case BSSGP_IEI_PRIORITY:
4495     decode_iei_priority(ie, bi, org_offset);
4496     break;
4497   case BSSGP_IEI_QOS_PROFILE:
4498     decode_iei_qos_profile(ie, bi, org_offset);
4499     break;
4500   case BSSGP_IEI_RADIO_CAUSE:
4501     decode_iei_radio_cause(ie, bi, org_offset);
4502     break;
4503   case BSSGP_IEI_RA_CAP_UPD_CAUSE:
4504     decode_iei_ra_cap_upd_cause(ie, bi, org_offset);
4505     break;
4506   case BSSGP_IEI_ROUTING_AREA:
4507     decode_iei_routing_area(ie, bi, org_offset);
4508     break;
4509   case BSSGP_IEI_R_DEFAULT_MS:
4510     decode_bucket_leak_rate(ie, bi, org_offset);
4511     break;
4512   case BSSGP_IEI_SUSPEND_REFERENCE_NUMBER:
4513     decode_simple_ie(ie, bi, org_offset, "", "", TRUE);
4514     break;
4515   case BSSGP_IEI_TAG:
4516     decode_simple_ie(ie, bi, org_offset, "", "", TRUE);
4517     break;
4518   case BSSGP_IEI_TLLI:
4519     decode_iei_tlli(ie, bi, org_offset);
4520     break;
4521   case BSSGP_IEI_TMSI:
4522     decode_iei_tmsi(ie, bi, org_offset);
4523     break;
4524   case BSSGP_IEI_TRACE_REFERENCE:
4525     decode_simple_ie(ie, bi, org_offset, "", "", TRUE);
4526     break;
4527   case BSSGP_IEI_TRACE_TYPE:
4528     /* XXX: Coding unknown (Specification withdrawn) 3GPP TS 32.008 */
4529     decode_simple_ie(ie, bi, org_offset, "", "", TRUE);
4530     break;
4531   case BSSGP_IEI_TRANSACTION_ID:
4532     decode_simple_ie(ie, bi, org_offset, "", "", TRUE);
4533     break;
4534   case BSSGP_IEI_TRIGGER_ID:
4535     decode_iei_trigger_id(ie, bi, org_offset);
4536     break;
4537   case BSSGP_IEI_NUMBER_OF_OCTETS_AFFECTED:
4538     decode_simple_ie(ie, bi, org_offset, "", "", TRUE);
4539     break;
4540   case BSSGP_IEI_LSA_IDENTIFIER_LIST:
4541     decode_iei_lsa_identifier_list(ie, bi, org_offset);
4542     break;
4543   case BSSGP_IEI_LSA_INFORMATION:
4544     decode_iei_lsa_information(ie, bi, org_offset);
4545     break;
4546   case BSSGP_IEI_PFI:
4547     decode_pfi(ie, bi, org_offset);
4548     break;
4549   case BSSGP_IEI_GPRS_TIMER:
4550     decode_iei_gprs_timer(ie, bi, org_offset);
4551     break;
4552   case BSSGP_IEI_ABQP:
4553     decode_iei_abqp(ie, bi, org_offset);
4554     break;
4555   case BSSGP_IEI_FEATURE_BITMAP:
4556     decode_iei_feature_bitmap(ie, bi, org_offset);
4557     break;
4558   case BSSGP_IEI_BUCKET_FULL_RATIO:
4559     decode_iei_bucket_full_ratio(ie, bi, org_offset);
4560     break;
4561   case BSSGP_IEI_SERVICE_UTRAN_CCO:
4562     decode_iei_service_utran_cco(ie, bi, org_offset);
4563     break;
4564   case BSSGP_IEI_NSEI:
4565     decode_iei_nsei(ie, bi, org_offset);
4566     break;
4567   case BSSGP_IEI_RRLP_APDU:
4568     bssgp_proto_handoff(ie, bi, org_offset, rrlp_handle);
4569     break;
4570   case BSSGP_IEI_LCS_QOS:
4571     decode_iei_lcs_qos(ie, bi, org_offset);
4572     break;
4573   case BSSGP_IEI_LCS_CLIENT_TYPE:
4574     decode_iei_lcs_client_type(ie, bi, org_offset);
4575     break;
4576   case BSSGP_IEI_REQUESTED_GPS_ASSISTANCE_DATA:
4577     decode_iei_requested_gps_assistance_data(ie, bi, org_offset);
4578     break;
4579   case BSSGP_IEI_LOCATION_TYPE:
4580     decode_iei_location_type(ie, bi, org_offset);
4581     break;
4582   case BSSGP_IEI_LOCATION_ESTIMATE:
4583     decode_iei_location_estimate(ie, bi, org_offset);
4584     break;
4585   case BSSGP_IEI_POSITIONING_DATA:
4586     decode_iei_positioning_data(ie, bi, org_offset);
4587     break;
4588   case BSSGP_IEI_DECIPHERING_KEYS:
4589     decode_iei_deciphering_keys(ie, bi, org_offset);
4590     break;
4591   case BSSGP_IEI_LCS_PRIORITY:
4592     decode_iei_lcs_priority(ie, bi, org_offset);
4593     break;
4594   case BSSGP_IEI_LCS_CAUSE:
4595     decode_iei_lcs_cause(ie, bi, org_offset);
4596     break;
4597   case BSSGP_IEI_LCS_CAPABILITY:
4598     decode_iei_lcs_capability(ie, bi, org_offset);
4599     break;
4600   case BSSGP_IEI_RRLP_FLAGS:
4601     decode_iei_rrlp_flags(ie, bi, org_offset);
4602     break;
4603   case BSSGP_IEI_RIM_ROUTING_INFORMATION:
4604     decode_iei_rim_routing_information(ie, bi, org_offset);
4605     break;
4606   case BSSGP_IEI_RIM_APPLICATION_IDENTITY:
4607     decode_iei_rim_application_identity(ie, bi, org_offset);
4608     break;
4609   case BSSGP_IEI_RIM_SEQUENCE_NUMBER:
4610     decode_simple_ie(ie, bi, org_offset, "", "", TRUE);
4611     break;
4612   case BSSGP_IEI_RIM_PROTOCOL_VERSION:
4613     decode_simple_ie(ie, bi, org_offset, "", "", TRUE);
4614     break;
4615
4616   case BSSGP_IEI_RAN_INFORMATION_REQUEST_APPLICATION_CONTAINER:
4617     decode_iei_ran_information_request_application_container(ie, bi, org_offset);
4618     break;
4619   case BSSGP_IEI_RAN_INFORMATION_APPLICATION_CONTAINER:
4620     decode_iei_ran_information_application_container(ie, bi, org_offset);
4621     break;
4622
4623   case BSSGP_IEI_RAN_INFORMATION_REQUEST_CONTAINER_UNIT:
4624     decode_iei_ran_container_unit(ie, bi, org_offset);
4625     break;
4626   case BSSGP_IEI_RAN_INFORMATION_CONTAINER_UNIT:
4627     decode_iei_ran_container_unit(ie, bi, org_offset);
4628     break;
4629   case  BSSGP_IEI_RAN_INFORMATION_APPLICATION_ERROR_CONTAINER_UNIT:
4630     decode_iei_ran_container_unit(ie, bi, org_offset);
4631     break;
4632   case BSSGP_IEI_RAN_INFORMATION_ACK_RIM_CONTAINER:
4633     decode_iei_ran_container_unit(ie, bi, org_offset);
4634     break;
4635   case BSSGP_IEI_RAN_INFORMATION_ERROR_RIM_CONTAINER:
4636     decode_iei_ran_container_unit(ie, bi, org_offset);
4637     break;
4638
4639   case BSSGP_IEI_APPLICATION_ERROR_CONTAINER:
4640     decode_iei_application_error(ie, bi, org_offset);
4641     break;
4642
4643
4644   case BSSGP_IEI_RIM_PDU_INDICATIONS:
4645     decode_iei_rim_pdu_indications(ie, bi, org_offset);
4646     break;
4647   case BSSGP_IEI_NUMBER_OF_CONTAINER_UNITS:
4648     decode_iei_number_of_container_units(ie, bi, org_offset);
4649     break;
4650   case BSSGP_IEI_PFC_FLOW_CONTROL_PARAMETERS:
4651     decode_iei_pfc_flow_control_parameters(ie, bi, org_offset);
4652     break;
4653   case BSSGP_IEI_GLOBAL_CN_ID:
4654     decode_iei_global_cn_id(ie, bi, org_offset);
4655     break;
4656   default:
4657     ;
4658   }
4659 }
4660
4661 static void
4662 decode_pdu_general(bssgp_ie_t *ies, int num_ies, build_info_t *bi) {
4663   int i;
4664   for (i = 0; i < num_ies; i++) {
4665     decode_ie(&ies[i], bi);
4666   }
4667 }
4668
4669 static void
4670 decode_pdu_dl_unitdata(build_info_t *bi) {
4671   bssgp_ie_t ies[] = {
4672     { BSSGP_IEI_TLLI, "TLLI (current)",
4673       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_V, BSSGP_UNKNOWN, 4 },
4674
4675     { BSSGP_IEI_QOS_PROFILE, NULL,
4676       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_V, BSSGP_UNKNOWN, 3 },
4677
4678     { BSSGP_IEI_PDU_LIFETIME, NULL,
4679       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4},
4680
4681     { BSSGP_IEI_MS_RADIO_ACCESS_CAPABILITY, NULL,
4682       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN},
4683
4684     { BSSGP_IEI_PRIORITY, NULL,
4685       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3},
4686
4687     { BSSGP_IEI_DRX_PARAMETERS, NULL,
4688       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4},
4689
4690     { BSSGP_IEI_IMSI, NULL,
4691       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN},
4692
4693     { BSSGP_IEI_TLLI, "TLLI (old)",
4694       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6},
4695
4696     { BSSGP_IEI_PFI, NULL,
4697       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3},
4698
4699     { BSSGP_IEI_LSA_INFORMATION, NULL,
4700       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN},
4701
4702     { BSSGP_IEI_SERVICE_UTRAN_CCO, NULL,
4703       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3},
4704
4705     { BSSGP_IEI_ALIGNMENT_OCTETS, NULL,
4706       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN},
4707
4708     { BSSGP_IEI_LLC_PDU, NULL,
4709       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN},
4710   };
4711   bi->dl_data = TRUE;
4712   bi->ul_data = FALSE;
4713
4714   decode_pdu_general(ies, 13, bi);
4715 }
4716
4717 static void
4718 decode_pdu_ul_unitdata(build_info_t *bi) {
4719   bssgp_ie_t ies[] = {
4720     { BSSGP_IEI_TLLI, NULL,
4721       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_V, BSSGP_UNKNOWN, 4 },
4722
4723     { BSSGP_IEI_QOS_PROFILE, NULL,
4724       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_V, BSSGP_UNKNOWN, 3 },
4725
4726     { BSSGP_IEI_CELL_IDENTIFIER, NULL,
4727       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
4728
4729     { BSSGP_IEI_PFI, NULL,
4730       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4731
4732     { BSSGP_IEI_LSA_IDENTIFIER_LIST, NULL,
4733       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
4734
4735     { BSSGP_IEI_ALIGNMENT_OCTETS, NULL,
4736       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
4737
4738     { BSSGP_IEI_LLC_PDU, NULL,
4739       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
4740   };
4741   bi->dl_data = FALSE;
4742   bi->ul_data = TRUE;
4743
4744   decode_pdu_general(ies, 7, bi);
4745 }
4746
4747 static void
4748 decode_pdu_ra_capability(build_info_t *bi) {
4749   bssgp_ie_t ies[] = {
4750     { BSSGP_IEI_TLLI, NULL,
4751       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4752
4753     { BSSGP_IEI_MS_RADIO_ACCESS_CAPABILITY, NULL,
4754       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN},
4755   };
4756   bi->dl_data = TRUE;
4757   bi->ul_data = FALSE;
4758
4759   decode_pdu_general(ies, 2, bi);
4760 }
4761
4762 static void
4763 decode_pdu_ptm_unitdata(build_info_t *bi) {
4764   proto_tree_add_text(bi->bssgp_tree, bi->tvb, bi->offset, -1,
4765                       "This shall be developed in GPRS phase 2");
4766 }
4767
4768 static void
4769 decode_pdu_paging_ps(build_info_t *bi) {
4770   bssgp_ie_t ies[] = {
4771     { BSSGP_IEI_IMSI, NULL,
4772       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
4773
4774     { BSSGP_IEI_DRX_PARAMETERS, NULL,
4775       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
4776
4777     { BSSGP_IEI_BVCI, NULL,
4778       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
4779
4780     { BSSGP_IEI_LOCATION_AREA, NULL,
4781       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 7 },
4782
4783     { BSSGP_IEI_ROUTING_AREA, NULL,
4784       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 8 },
4785
4786     { BSSGP_IEI_BSS_AREA_INDICATION, NULL,
4787       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4788
4789     { BSSGP_IEI_PFI, NULL,
4790       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4791
4792     { BSSGP_IEI_ABQP, NULL,
4793       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
4794
4795     { BSSGP_IEI_QOS_PROFILE, NULL,
4796       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 5 },
4797
4798     { BSSGP_IEI_TMSI, "P-TMSI",
4799       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4800   };
4801   bi->dl_data = TRUE;
4802   bi->ul_data = FALSE;
4803
4804   decode_pdu_general(ies, 10, bi);
4805 }
4806
4807 static void
4808 decode_pdu_paging_cs(build_info_t *bi) {
4809   bssgp_ie_t ies[] = {
4810     { BSSGP_IEI_IMSI, NULL,
4811       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
4812
4813     { BSSGP_IEI_DRX_PARAMETERS, NULL,
4814       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
4815
4816     { BSSGP_IEI_BVCI, NULL,
4817       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
4818
4819     { BSSGP_IEI_LOCATION_AREA, NULL,
4820       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 7 },
4821
4822     { BSSGP_IEI_ROUTING_AREA, NULL,
4823       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 8 },
4824
4825     { BSSGP_IEI_BSS_AREA_INDICATION, NULL,
4826       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4827
4828     { BSSGP_IEI_TLLI, NULL,
4829       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4830
4831     { BSSGP_IEI_CHANNEL_NEEDED, NULL,
4832       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4833
4834     { BSSGP_IEI_EMLPP_PRIORITY, NULL,
4835       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4836
4837     { BSSGP_IEI_TMSI, NULL,
4838       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4839
4840     { BSSGP_IEI_GLOBAL_CN_ID, NULL,
4841       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 7 },
4842   };
4843   bi->dl_data = TRUE;
4844   bi->ul_data = FALSE;
4845
4846   decode_pdu_general(ies, 11, bi);
4847 }
4848
4849 static void
4850 decode_pdu_ra_capability_update(build_info_t *bi) {
4851   bssgp_ie_t ies[] = {
4852     { BSSGP_IEI_TLLI, NULL,
4853       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4854
4855     { BSSGP_IEI_TAG, NULL,
4856       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4857   };
4858   bi->dl_data = FALSE;
4859   bi->ul_data = TRUE;
4860
4861   decode_pdu_general(ies, 2, bi);
4862 }
4863
4864 static void
4865 decode_pdu_ra_capability_update_ack(build_info_t *bi) {
4866   bssgp_ie_t ies[] = {
4867     { BSSGP_IEI_TLLI, NULL,
4868       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4869
4870     { BSSGP_IEI_TAG, NULL,
4871       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4872
4873     { BSSGP_IEI_IMSI, NULL,
4874       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
4875
4876     { BSSGP_IEI_RA_CAP_UPD_CAUSE, NULL,
4877       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4878
4879     { BSSGP_IEI_MS_RADIO_ACCESS_CAPABILITY, NULL,
4880       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN},
4881   };
4882   bi->dl_data = TRUE;
4883   bi->ul_data = FALSE;
4884
4885   decode_pdu_general(ies, 5, bi);
4886 }
4887
4888 static void
4889 decode_pdu_radio_status(build_info_t *bi) {
4890   bssgp_ie_t ies[] = {
4891     { BSSGP_IEI_TLLI, NULL,
4892       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4893
4894     { BSSGP_IEI_TMSI, NULL,
4895       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4896
4897     { BSSGP_IEI_IMSI, NULL,
4898       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
4899
4900     { BSSGP_IEI_RADIO_CAUSE, NULL,
4901       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4902   };
4903   bi->dl_data = FALSE;
4904   bi->ul_data = TRUE;
4905
4906   decode_pdu_general(ies, 4, bi);
4907 }
4908
4909 static void
4910 decode_pdu_suspend(build_info_t *bi) {
4911   bssgp_ie_t ies[] = {
4912     { BSSGP_IEI_TLLI, NULL,
4913       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4914
4915     { BSSGP_IEI_ROUTING_AREA, NULL,
4916       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 8 },
4917   };
4918   bi->dl_data = FALSE;
4919   bi->ul_data = TRUE;
4920
4921   decode_pdu_general(ies, 2, bi);
4922 }
4923
4924 static void
4925 decode_pdu_suspend_ack(build_info_t *bi) {
4926   bssgp_ie_t ies[] = {
4927     { BSSGP_IEI_TLLI, NULL,
4928       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4929
4930     { BSSGP_IEI_ROUTING_AREA, NULL,
4931       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 8 },
4932
4933     { BSSGP_IEI_SUSPEND_REFERENCE_NUMBER, NULL,
4934       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4935   };
4936   bi->dl_data = TRUE;
4937   bi->ul_data = FALSE;
4938
4939   decode_pdu_general(ies, 3, bi);
4940 }
4941
4942 static void
4943 decode_pdu_suspend_nack(build_info_t *bi) {
4944   bssgp_ie_t ies[] = {
4945     { BSSGP_IEI_TLLI, NULL,
4946       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4947
4948     { BSSGP_IEI_ROUTING_AREA, NULL,
4949       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 8 },
4950
4951     { BSSGP_IEI_CAUSE, NULL,
4952       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4953   };
4954   bi->dl_data = TRUE;
4955   bi->ul_data = FALSE;
4956
4957   decode_pdu_general(ies, 3, bi);
4958 }
4959
4960 static void
4961 decode_pdu_resume(build_info_t *bi) {
4962   bssgp_ie_t ies[] = {
4963     { BSSGP_IEI_TLLI, NULL,
4964       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4965
4966     { BSSGP_IEI_ROUTING_AREA, NULL,
4967       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 8 },
4968
4969     { BSSGP_IEI_SUSPEND_REFERENCE_NUMBER, NULL,
4970       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
4971   };
4972   bi->dl_data = FALSE;
4973   bi->ul_data = TRUE;
4974
4975   decode_pdu_general(ies, 3, bi);
4976 }
4977
4978 static void
4979 decode_pdu_resume_ack(build_info_t *bi) {
4980   bssgp_ie_t ies[] = {
4981     { BSSGP_IEI_TLLI, NULL,
4982       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4983
4984     { BSSGP_IEI_ROUTING_AREA, NULL,
4985       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 8 },
4986
4987   };
4988   bi->dl_data = TRUE;
4989   bi->ul_data = FALSE;
4990
4991   decode_pdu_general(ies, 2, bi);
4992 }
4993
4994 static void
4995 decode_pdu_resume_nack(build_info_t *bi) {
4996   bssgp_ie_t ies[] = {
4997     { BSSGP_IEI_TLLI, NULL,
4998       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
4999
5000     { BSSGP_IEI_ROUTING_AREA, NULL,
5001       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 8 },
5002
5003     { BSSGP_IEI_CAUSE, NULL,
5004       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5005   };
5006   bi->dl_data = TRUE;
5007   bi->ul_data = FALSE;
5008
5009   decode_pdu_general(ies, 3, bi);
5010 }
5011
5012 static void
5013 decode_pdu_bvc_block(build_info_t *bi) {
5014   bssgp_ie_t ies[] = {
5015     { BSSGP_IEI_BVCI, NULL,
5016       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5017
5018     { BSSGP_IEI_CAUSE, NULL,
5019       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5020   };
5021   bi->dl_data = FALSE;
5022   bi->ul_data = TRUE;
5023
5024   decode_pdu_general(ies, 2, bi);
5025 }
5026
5027 static void
5028 decode_pdu_bvc_block_ack(build_info_t *bi) {
5029   bssgp_ie_t ies[] = {
5030     { BSSGP_IEI_BVCI, NULL,
5031       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4},
5032   };
5033   bi->dl_data = TRUE;
5034   bi->ul_data = FALSE;
5035
5036   decode_pdu_general(ies, 1, bi);
5037 }
5038
5039 static void
5040 decode_pdu_bvc_reset(build_info_t *bi) {
5041   bssgp_ie_t ies[] = {
5042     { BSSGP_IEI_BVCI, NULL,
5043       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5044
5045     { BSSGP_IEI_CAUSE, NULL,
5046       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5047
5048     { BSSGP_IEI_CELL_IDENTIFIER, NULL,
5049       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5050
5051     { BSSGP_IEI_FEATURE_BITMAP, NULL,
5052       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5053   };
5054   bi->dl_data = TRUE;
5055   bi->ul_data = TRUE;
5056
5057   decode_pdu_general(ies, 4, bi);
5058 }
5059
5060 static void
5061 decode_pdu_bvc_reset_ack(build_info_t *bi) {
5062   bssgp_ie_t ies[] = {
5063     { BSSGP_IEI_BVCI, NULL,
5064       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5065
5066     { BSSGP_IEI_CELL_IDENTIFIER, NULL,
5067       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5068
5069     { BSSGP_IEI_FEATURE_BITMAP, NULL,
5070       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5071   };
5072   bi->dl_data = TRUE;
5073   bi->ul_data = TRUE;
5074
5075   decode_pdu_general(ies, 3, bi);
5076 }
5077
5078 static void
5079 decode_pdu_bvc_unblock(build_info_t *bi) {
5080   bssgp_ie_t ies[] = {
5081     { BSSGP_IEI_BVCI, NULL,
5082       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5083   };
5084   bi->dl_data = FALSE;
5085   bi->ul_data = TRUE;
5086
5087   decode_pdu_general(ies, 1, bi);
5088 }
5089
5090 static void
5091 decode_pdu_bvc_unblock_ack(build_info_t *bi) {
5092   bssgp_ie_t ies[] = {
5093     { BSSGP_IEI_BVCI, NULL,
5094       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5095   };
5096   bi->dl_data = TRUE;
5097   bi->ul_data = FALSE;
5098
5099   decode_pdu_general(ies, 1, bi);
5100 }
5101
5102 static void
5103 decode_pdu_flow_control_bvc(build_info_t *bi) {
5104   bssgp_ie_t ies[] = {
5105     { BSSGP_IEI_TAG, NULL,
5106       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5107
5108     { BSSGP_IEI_BVC_BUCKET_SIZE, NULL,
5109       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5110
5111     { BSSGP_IEI_BUCKET_LEAK_RATE, NULL,
5112       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5113
5114     { BSSGP_IEI_BMAX_DEFAULT_MS, NULL,
5115       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5116
5117     { BSSGP_IEI_R_DEFAULT_MS, NULL,
5118       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5119
5120     { BSSGP_IEI_BUCKET_FULL_RATIO, NULL,
5121       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5122
5123     { BSSGP_IEI_BVC_MEASUREMENT, NULL,
5124       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5125   };
5126   bi->dl_data = FALSE;
5127   bi->ul_data = TRUE;
5128
5129   decode_pdu_general(ies, 7, bi);
5130 }
5131
5132 static void
5133 decode_pdu_flow_control_bvc_ack(build_info_t *bi) {
5134   bssgp_ie_t ies[] = {
5135     { BSSGP_IEI_TAG, NULL,
5136       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5137   };
5138   bi->dl_data = TRUE;
5139   bi->ul_data = FALSE;
5140
5141   decode_pdu_general(ies, 1, bi);
5142 }
5143
5144 static void
5145 decode_pdu_flow_control_ms(build_info_t *bi) {
5146   bssgp_ie_t ies[] = {
5147     { BSSGP_IEI_TLLI, NULL,
5148       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5149
5150     { BSSGP_IEI_TAG, NULL,
5151       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5152
5153     { BSSGP_IEI_MS_BUCKET_SIZE, NULL,
5154       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5155
5156     { BSSGP_IEI_BUCKET_LEAK_RATE, NULL,
5157       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5158
5159     { BSSGP_IEI_BUCKET_FULL_RATIO, NULL,
5160       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5161   };
5162   bi->dl_data = FALSE;
5163   bi->ul_data = TRUE;
5164
5165   decode_pdu_general(ies, 5, bi);
5166 }
5167
5168 static void
5169 decode_pdu_flow_control_ms_ack(build_info_t *bi) {
5170   bssgp_ie_t ies[] = {
5171     { BSSGP_IEI_TLLI, NULL,
5172       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5173
5174     { BSSGP_IEI_TAG, NULL,
5175       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5176   };
5177   bi->dl_data = TRUE;
5178   bi->ul_data = FALSE;
5179
5180   decode_pdu_general(ies, 2, bi);
5181 }
5182
5183 static void
5184 decode_pdu_flush_ll(build_info_t *bi) {
5185   bssgp_ie_t ies[] = {
5186     { BSSGP_IEI_TLLI, NULL,
5187       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5188
5189     { BSSGP_IEI_BVCI, "BVCI (old)",
5190       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5191
5192     { BSSGP_IEI_BVCI, "BVCI (new)",
5193       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5194
5195     { BSSGP_IEI_NSEI, "NSEI (new)",
5196       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5197   };
5198   bi->dl_data = TRUE;
5199   bi->ul_data = FALSE;
5200
5201   decode_pdu_general(ies, 4, bi);
5202 }
5203
5204 static void
5205 decode_pdu_flush_ll_ack(build_info_t *bi) {
5206   bssgp_ie_t ies[] = {
5207     { BSSGP_IEI_TLLI, NULL,
5208       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5209
5210     { BSSGP_IEI_FLUSH_ACTION, NULL,
5211       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5212
5213     { BSSGP_IEI_BVCI, "BVCI (new)",
5214       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5215
5216     { BSSGP_IEI_NUMBER_OF_OCTETS_AFFECTED, NULL,
5217       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 5 },
5218
5219     { BSSGP_IEI_NSEI, "NSEI (new)",
5220       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5221   };
5222   bi->dl_data = FALSE;
5223   bi->ul_data = TRUE;
5224
5225   decode_pdu_general(ies, 5, bi);
5226 }
5227
5228 static void
5229 decode_pdu_llc_discarded(build_info_t *bi) {
5230   bssgp_ie_t ies[] = {
5231     { BSSGP_IEI_TLLI, NULL,
5232       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5233
5234     { BSSGP_IEI_LLC_FRAMES_DISCARDED, NULL,
5235       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5236
5237     { BSSGP_IEI_BVCI, NULL,
5238       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5239
5240     { BSSGP_IEI_NUMBER_OF_OCTETS_AFFECTED, "Number of octets deleted",
5241       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 5 },
5242
5243     { BSSGP_IEI_PFI, NULL,
5244       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5245   };
5246   bi->dl_data = FALSE;
5247   bi->ul_data = TRUE;
5248
5249   decode_pdu_general(ies, 5, bi);
5250 }
5251
5252 static void
5253 decode_pdu_flow_control_pfc(build_info_t *bi) {
5254   bssgp_ie_t ies[] = {
5255     { BSSGP_IEI_TLLI, NULL,
5256       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5257
5258     { BSSGP_IEI_TAG, NULL,
5259       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5260
5261     { BSSGP_IEI_MS_BUCKET_SIZE, NULL,
5262       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5263
5264     { BSSGP_IEI_BUCKET_LEAK_RATE, NULL,
5265       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5266
5267     { BSSGP_IEI_BUCKET_FULL_RATIO, NULL,
5268       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5269
5270     { BSSGP_IEI_PFC_FLOW_CONTROL_PARAMETERS, NULL,
5271       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5272   };
5273   bi->dl_data = FALSE;
5274   bi->ul_data = TRUE;
5275
5276   decode_pdu_general(ies, 6, bi);
5277 }
5278
5279 static void
5280 decode_pdu_flow_control_pfc_ack(build_info_t *bi) {
5281   bssgp_ie_t ies[] = {
5282     { BSSGP_IEI_TLLI, NULL,
5283       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5284
5285     { BSSGP_IEI_TAG, NULL,
5286       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5287   };
5288   bi->dl_data = TRUE;
5289   bi->ul_data = FALSE;
5290
5291   decode_pdu_general(ies, 2, bi);
5292 }
5293
5294 static void
5295 decode_pdu_sgsn_invoke_trace(build_info_t *bi) {
5296   bssgp_ie_t ies[] = {
5297     { BSSGP_IEI_TRACE_TYPE, NULL,
5298       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5299
5300     { BSSGP_IEI_TRACE_REFERENCE, NULL,
5301       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5302
5303     { BSSGP_IEI_TRIGGER_ID, NULL,
5304       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5305
5306     { BSSGP_IEI_MOBILE_ID, NULL,
5307       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5308
5309     { BSSGP_IEI_OMC_ID, NULL,
5310       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5311
5312     { BSSGP_IEI_TRANSACTION_ID, NULL,
5313       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5314   };
5315   bi->dl_data = TRUE;
5316   bi->ul_data = FALSE;
5317
5318   decode_pdu_general(ies, 6, bi);
5319 }
5320
5321 static void
5322 decode_pdu_status(build_info_t *bi) {
5323   bssgp_ie_t ies[] = {
5324     { BSSGP_IEI_CAUSE, NULL,
5325       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5326
5327     { BSSGP_IEI_BVCI, NULL,
5328       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5329
5330     { BSSGP_IEI_PDU_IN_ERROR, NULL,
5331       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5332   };
5333   bi->dl_data = TRUE;
5334   bi->ul_data = TRUE;
5335
5336   decode_pdu_general(ies, 3, bi);
5337 }
5338
5339 static void
5340 decode_pdu_download_bss_pfc(build_info_t *bi) {
5341   bssgp_ie_t ies[] = {
5342     { BSSGP_IEI_TLLI, NULL,
5343       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5344
5345     { BSSGP_IEI_PFI, NULL,
5346       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5347   };
5348   bi->dl_data = FALSE;
5349   bi->ul_data = TRUE;
5350
5351   decode_pdu_general(ies, 2, bi);
5352 }
5353
5354 /* 10.4.17 CREATE-BSS-PFC */
5355 static void
5356 decode_pdu_create_bss_pfc(build_info_t *bi) {
5357   bssgp_ie_t ies[] = {
5358     { BSSGP_IEI_TLLI, NULL,
5359       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5360
5361     { BSSGP_IEI_IMSI, NULL,
5362       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5363
5364     { BSSGP_IEI_PFI, NULL,
5365       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5366
5367     { BSSGP_IEI_GPRS_TIMER, "PFT",
5368       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5369
5370     { BSSGP_IEI_ABQP, NULL,
5371       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5372
5373     { BSSGP_IEI_SERVICE_UTRAN_CCO, NULL,
5374       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5375
5376     { BSSGP_IEI_MS_RADIO_ACCESS_CAPABILITY, NULL,
5377       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5378
5379     { BSSGP_IEI_PRIORITY, "Allocation/Retention Priority",
5380       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5381
5382     { BSSGP_IEI_GPRS_TIMER, "T10",
5383       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5384     /* Inter RAT Handover Info 11.3.94 3GPP TS 48.018 version 6.11.0 Release 6 */
5385   };
5386   bi->dl_data = TRUE;
5387   bi->ul_data = FALSE;
5388
5389   decode_pdu_general(ies, 9, bi);
5390 }
5391
5392 static void
5393 decode_pdu_create_bss_pfc_ack(build_info_t *bi) {
5394   bssgp_ie_t ies[] = {
5395     { BSSGP_IEI_TLLI, NULL,
5396       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5397
5398     { BSSGP_IEI_PFI, NULL,
5399       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5400
5401     { BSSGP_IEI_ABQP, NULL,
5402       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5403
5404     { BSSGP_IEI_CAUSE, NULL,
5405       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5406   };
5407   bi->dl_data = FALSE;
5408   bi->ul_data = TRUE;
5409
5410   decode_pdu_general(ies, 4, bi);
5411 }
5412
5413 static void
5414 decode_pdu_create_bss_pfc_nack(build_info_t *bi) {
5415   bssgp_ie_t ies[] = {
5416     { BSSGP_IEI_TLLI, NULL,
5417       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5418
5419     { BSSGP_IEI_PFI, NULL,
5420       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5421
5422     { BSSGP_IEI_CAUSE, NULL,
5423       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5424   };
5425   bi->dl_data = FALSE;
5426   bi->ul_data = TRUE;
5427
5428   decode_pdu_general(ies, 3, bi);
5429 }
5430
5431 static void
5432 decode_pdu_modify_bss_pfc(build_info_t *bi) {
5433   bssgp_ie_t ies[] = {
5434     { BSSGP_IEI_TLLI, NULL,
5435       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5436
5437     { BSSGP_IEI_PFI, NULL,
5438       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5439
5440     { BSSGP_IEI_ABQP, NULL,
5441       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5442   };
5443   bi->dl_data = FALSE;
5444   bi->ul_data = TRUE;
5445
5446   decode_pdu_general(ies, 3, bi);
5447 }
5448
5449 static void
5450 decode_pdu_modify_bss_pfc_ack(build_info_t *bi) {
5451   bssgp_ie_t ies[] = {
5452     { BSSGP_IEI_TLLI, NULL,
5453       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5454
5455     { BSSGP_IEI_PFI, NULL,
5456       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5457
5458     { BSSGP_IEI_GPRS_TIMER, "PFT",
5459       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5460
5461     { BSSGP_IEI_ABQP, NULL,
5462       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5463   };
5464   bi->dl_data = TRUE;
5465   bi->ul_data = FALSE;
5466
5467   decode_pdu_general(ies, 4, bi);
5468 }
5469
5470 static void
5471 decode_pdu_delete_bss_pfc(build_info_t *bi) {
5472   bssgp_ie_t ies[] = {
5473     { BSSGP_IEI_TLLI, NULL,
5474       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5475
5476     { BSSGP_IEI_PFI, NULL,
5477       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5478   };
5479   bi->dl_data = TRUE;
5480   bi->ul_data = FALSE;
5481
5482   decode_pdu_general(ies, 2, bi);
5483 }
5484
5485 static void
5486 decode_pdu_delete_bss_pfc_ack(build_info_t *bi) {
5487   bssgp_ie_t ies[] = {
5488     { BSSGP_IEI_TLLI, NULL,
5489       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5490
5491     { BSSGP_IEI_PFI, NULL,
5492       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5493   };
5494   bi->dl_data = FALSE;
5495   bi->ul_data = TRUE;
5496
5497   decode_pdu_general(ies, 2, bi);
5498 }
5499
5500 static void
5501 decode_pdu_delete_bss_pfc_req(build_info_t *bi) {
5502   bssgp_ie_t ies[] = {
5503     { BSSGP_IEI_TLLI, NULL,
5504       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5505
5506     { BSSGP_IEI_PFI, NULL,
5507       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5508
5509     { BSSGP_IEI_CAUSE, NULL,
5510       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5511   };
5512   bi->dl_data = FALSE;
5513   bi->ul_data = TRUE;
5514
5515   decode_pdu_general(ies, 3, bi);
5516 }
5517
5518 static void
5519 decode_pdu_perform_location_request(build_info_t *bi) {
5520   bssgp_ie_t ies[] = {
5521     { BSSGP_IEI_TLLI, NULL,
5522       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5523
5524     { BSSGP_IEI_IMSI, NULL,
5525       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5526
5527     { BSSGP_IEI_DRX_PARAMETERS, NULL,
5528       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5529
5530     { BSSGP_IEI_BVCI, "BVCI (PCU-PTP)",
5531       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5532
5533     { BSSGP_IEI_NSEI, "NSEI (PCU-PTP)",
5534       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5535
5536     { BSSGP_IEI_LOCATION_TYPE, NULL,
5537       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5538
5539     { BSSGP_IEI_CELL_IDENTIFIER, NULL,
5540       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5541
5542     { BSSGP_IEI_LCS_CAPABILITY, NULL,
5543       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5544
5545     { BSSGP_IEI_LCS_PRIORITY, NULL,
5546       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5547
5548     { BSSGP_IEI_LCS_QOS, NULL,
5549       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5550
5551     { BSSGP_IEI_LCS_CLIENT_TYPE, NULL,
5552       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5553
5554     { BSSGP_IEI_REQUESTED_GPS_ASSISTANCE_DATA, NULL,
5555       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5556   };
5557   bi->dl_data = TRUE;
5558   bi->ul_data = FALSE;
5559
5560   decode_pdu_general(ies, 12, bi);
5561 }
5562
5563 static void
5564 decode_pdu_perform_location_response(build_info_t *bi) {
5565   bssgp_ie_t ies[] = {
5566     { BSSGP_IEI_TLLI, NULL,
5567       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5568
5569     { BSSGP_IEI_BVCI, "BVCI (PCU-PTP)",
5570       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5571
5572     { BSSGP_IEI_LOCATION_ESTIMATE, NULL,
5573       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5574
5575     { BSSGP_IEI_POSITIONING_DATA, NULL,
5576       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5577
5578     { BSSGP_IEI_DECIPHERING_KEYS, NULL,
5579       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5580
5581     { BSSGP_IEI_LCS_CAUSE, NULL,
5582       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5583   };
5584   bi->dl_data = FALSE;
5585   bi->ul_data = TRUE;
5586
5587   decode_pdu_general(ies, 6, bi);
5588 }
5589
5590 static void
5591 decode_pdu_perform_location_abort(build_info_t *bi) {
5592   bssgp_ie_t ies[] = {
5593     { BSSGP_IEI_TLLI, NULL,
5594       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5595
5596     { BSSGP_IEI_BVCI, "BVCI (PCU-PTP)",
5597       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5598
5599     { BSSGP_IEI_LCS_CAUSE, NULL,
5600       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5601   };
5602   bi->dl_data = TRUE;
5603   bi->ul_data = FALSE;
5604
5605   decode_pdu_general(ies, 3, bi);
5606 }
5607
5608 static void
5609 decode_pdu_position_command(build_info_t *bi) {
5610   bssgp_ie_t ies[] = {
5611     { BSSGP_IEI_TLLI, NULL,
5612       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5613
5614     { BSSGP_IEI_BVCI, "BVCI (PCU-PTP)",
5615       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5616
5617     { BSSGP_IEI_RRLP_FLAGS, NULL,
5618       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5619
5620     { BSSGP_IEI_RRLP_APDU, NULL,
5621       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5622   };
5623   bi->dl_data = FALSE;
5624   bi->ul_data = TRUE;
5625
5626   decode_pdu_general(ies, 4, bi);
5627 }
5628
5629 static void
5630 decode_pdu_position_response(build_info_t *bi) {
5631   bssgp_ie_t ies[] = {
5632     { BSSGP_IEI_TLLI, NULL,
5633       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5634
5635     { BSSGP_IEI_BVCI, "BVCI (PCU-PTP)",
5636       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5637
5638     { BSSGP_IEI_RRLP_FLAGS, NULL,
5639       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5640
5641     { BSSGP_IEI_RRLP_APDU, NULL,
5642       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5643
5644     { BSSGP_IEI_LCS_CAUSE, NULL,
5645       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5646   };
5647   bi->dl_data = TRUE;
5648   bi->ul_data = FALSE;
5649
5650   decode_pdu_general(ies, 5, bi);
5651 }
5652
5653
5654 static void
5655 decode_pdu_ran_information(build_info_t *bi) {
5656   bssgp_ie_t ies[] = {
5657
5658     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Destination Cell Identifier",
5659       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5660
5661     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Source Cell Identifier",
5662       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5663
5664     { BSSGP_IEI_RAN_INFORMATION_CONTAINER_UNIT, "RAN-INFORMATION RIM Container",
5665       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 2 },
5666
5667     { BSSGP_IEI_RIM_APPLICATION_IDENTITY, "Application Identity",
5668       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5669
5670     { BSSGP_IEI_RIM_SEQUENCE_NUMBER, "Sequence Number",
5671       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5672
5673     { BSSGP_IEI_RIM_PDU_INDICATIONS, "PDU Indications",
5674       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5675
5676     { BSSGP_IEI_RIM_PROTOCOL_VERSION, "Protocol Version",
5677       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5678
5679     { BSSGP_IEI_RAN_INFORMATION_APPLICATION_CONTAINER, "RAN-INFORMATION RIM Container",
5680       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5681
5682   };
5683
5684   bi->dl_data = TRUE;
5685   bi->ul_data = TRUE;
5686
5687   decode_pdu_general(ies, 8, bi);
5688 }
5689
5690 static void
5691 decode_pdu_ran_information_request(build_info_t *bi) {
5692
5693   bssgp_ie_t ies[] = {
5694
5695     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Destination Cell Identifier",
5696       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5697
5698     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Source Cell Identifier",
5699       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5700
5701     { BSSGP_IEI_RAN_INFORMATION_REQUEST_CONTAINER_UNIT, "RAN-INFORMATION-REQUEST RIM Container",
5702       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 2 },
5703
5704     { BSSGP_IEI_RIM_APPLICATION_IDENTITY, "Application Identity",
5705       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5706
5707     { BSSGP_IEI_RIM_SEQUENCE_NUMBER, "Sequence Number",
5708       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5709
5710     { BSSGP_IEI_RIM_PDU_INDICATIONS, "PDU Indications",
5711       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5712
5713     { BSSGP_IEI_RIM_PROTOCOL_VERSION, "Protocol Version",
5714       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5715
5716     { BSSGP_IEI_RAN_INFORMATION_REQUEST_APPLICATION_CONTAINER, "RAN-INFORMATION-REQUEST Application Container",
5717       BSSGP_IE_PRESENCE_C, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5718
5719   };
5720
5721   bi->dl_data = TRUE;
5722   bi->ul_data = TRUE;
5723
5724   decode_pdu_general(ies, 8, bi);
5725
5726 }
5727
5728 static void
5729 decode_pdu_ran_information_ack(build_info_t *bi) {
5730   bssgp_ie_t ies[] = {
5731     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Destination Cell Identifier",
5732       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5733
5734     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Source Cell Identifier",
5735       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5736
5737     { BSSGP_IEI_RAN_INFORMATION_REQUEST_CONTAINER_UNIT, "RAN-INFORMATION-ACK RIM Container",
5738       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 2 },
5739
5740     { BSSGP_IEI_RIM_APPLICATION_IDENTITY, "Application Identity",
5741       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5742
5743     { BSSGP_IEI_RIM_SEQUENCE_NUMBER, "Sequence Number",
5744       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5745
5746     { BSSGP_IEI_RIM_PROTOCOL_VERSION, "Protocol Version",
5747       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 4 },
5748
5749   };
5750   bi->dl_data = TRUE;
5751   bi->ul_data = TRUE;
5752
5753   decode_pdu_general(ies, 6, bi);
5754 }
5755
5756 static void
5757 decode_pdu_ran_information_error(build_info_t *bi) {
5758   bssgp_ie_t ies[] = {
5759     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Destination Cell Identifier",
5760       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5761
5762     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Source Cell Identifier",
5763       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5764
5765     { BSSGP_IEI_RAN_INFORMATION_REQUEST_CONTAINER_UNIT, "RAN-INFORMATION-ERROR RIM Container",
5766       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 2 },
5767
5768     { BSSGP_IEI_RIM_APPLICATION_IDENTITY, "Application Identity",
5769       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5770
5771     { BSSGP_IEI_CAUSE, "RIM Cause",
5772       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5773
5774     { BSSGP_IEI_RIM_PROTOCOL_VERSION, "Protocol Version",
5775       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5776
5777     { BSSGP_IEI_PDU_IN_ERROR, NULL,
5778       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5779   };
5780   bi->dl_data = TRUE;
5781   bi->ul_data = TRUE;
5782
5783   decode_pdu_general(ies, 7, bi);
5784 }
5785
5786 static void
5787 decode_pdu_ran_information_application_error(build_info_t *bi) {
5788   bssgp_ie_t ies[] = {
5789     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Destination Cell Identifier",
5790       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5791
5792     { BSSGP_IEI_RIM_ROUTING_INFORMATION, "Source Cell Identifier",
5793       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 10 },
5794
5795     { BSSGP_IEI_RAN_INFORMATION_REQUEST_CONTAINER_UNIT, "RAN-INFORMATION-APPLICATION RIM Container",
5796       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 2 },
5797
5798     { BSSGP_IEI_RIM_APPLICATION_IDENTITY, "Application Identity",
5799       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5800
5801     /* pdu indication, I hope RIM_PDU_INDICATIONS decode it right, it use the same IEI so it should... */
5802     { BSSGP_IEI_RIM_PDU_INDICATIONS, "PDU Indications",
5803       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5804
5805     { BSSGP_IEI_RIM_SEQUENCE_NUMBER, "Sequence Number",
5806       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 6 },
5807
5808     { BSSGP_IEI_RIM_PROTOCOL_VERSION, "Protocol Version",
5809       BSSGP_IE_PRESENCE_O, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, 3 },
5810
5811     { BSSGP_IEI_APPLICATION_ERROR_CONTAINER, NULL,
5812       BSSGP_IE_PRESENCE_M, BSSGP_IE_FORMAT_TLV, BSSGP_UNKNOWN, BSSGP_UNKNOWN },
5813
5814   };
5815   bi->dl_data = TRUE;
5816   bi->ul_data = TRUE;
5817
5818   decode_pdu_general(ies, 8, bi);
5819 }
5820
5821
5822 static void
5823 decode_pdu(build_info_t *bi) {
5824
5825   switch (bi->pdutype) {
5826   case BSSGP_PDU_DL_UNITDATA:
5827     decode_pdu_dl_unitdata(bi);
5828     break;
5829   case BSSGP_PDU_UL_UNITDATA:
5830     decode_pdu_ul_unitdata(bi);
5831     break;
5832   case BSSGP_PDU_RA_CAPABILITY:
5833     decode_pdu_ra_capability(bi);
5834     break;
5835   case BSSGP_PDU_PTM_UNITDATA:
5836     decode_pdu_ptm_unitdata(bi);
5837     break;
5838   case BSSGP_PDU_PAGING_PS:
5839     decode_pdu_paging_ps(bi);
5840     break;
5841   case BSSGP_PDU_PAGING_CS:
5842     decode_pdu_paging_cs(bi);
5843     break;
5844   case BSSGP_PDU_RA_CAPABILITY_UPDATE:
5845     decode_pdu_ra_capability_update(bi);
5846     break;
5847   case BSSGP_PDU_RA_CAPABILITY_UPDATE_ACK:
5848     decode_pdu_ra_capability_update_ack(bi);
5849     break;
5850   case BSSGP_PDU_RADIO_STATUS:
5851     decode_pdu_radio_status(bi);
5852     break;
5853   case BSSGP_PDU_SUSPEND:
5854     decode_pdu_suspend(bi);
5855     break;
5856   case BSSGP_PDU_SUSPEND_ACK:
5857     decode_pdu_suspend_ack(bi);
5858     break;
5859   case BSSGP_PDU_SUSPEND_NACK:
5860     decode_pdu_suspend_nack(bi);
5861     break;
5862   case BSSGP_PDU_RESUME:
5863     decode_pdu_resume(bi);
5864     break;
5865   case BSSGP_PDU_RESUME_ACK:
5866     decode_pdu_resume_ack(bi);
5867     break;
5868   case BSSGP_PDU_RESUME_NACK:
5869     decode_pdu_resume_nack(bi);
5870     break;
5871   case BSSGP_PDU_BVC_BLOCK:
5872     decode_pdu_bvc_block(bi);
5873     break;
5874   case BSSGP_PDU_BVC_BLOCK_ACK:
5875     decode_pdu_bvc_block_ack(bi);
5876     break;
5877   case BSSGP_PDU_BVC_RESET:
5878     decode_pdu_bvc_reset(bi);
5879     break;
5880   case BSSGP_PDU_BVC_RESET_ACK:
5881     decode_pdu_bvc_reset_ack(bi);
5882     break;
5883   case BSSGP_PDU_BVC_UNBLOCK:
5884     decode_pdu_bvc_unblock(bi);
5885     break;
5886   case BSSGP_PDU_BVC_UNBLOCK_ACK:
5887     decode_pdu_bvc_unblock_ack(bi);
5888     break;
5889   case BSSGP_PDU_FLOW_CONTROL_BVC:
5890     decode_pdu_flow_control_bvc(bi);
5891     break;
5892   case BSSGP_PDU_FLOW_CONTROL_BVC_ACK:
5893     decode_pdu_flow_control_bvc_ack(bi);
5894     break;
5895   case BSSGP_PDU_FLOW_CONTROL_MS:
5896     decode_pdu_flow_control_ms(bi);
5897     break;
5898   case BSSGP_PDU_FLOW_CONTROL_MS_ACK:
5899     decode_pdu_flow_control_ms_ack(bi);
5900     break;
5901   case BSSGP_PDU_FLUSH_LL:
5902     decode_pdu_flush_ll(bi);
5903     break;
5904   case BSSGP_PDU_FLUSH_LL_ACK:
5905     decode_pdu_flush_ll_ack(bi);
5906     break;
5907   case BSSGP_PDU_LLC_DISCARDED:
5908     decode_pdu_llc_discarded(bi);
5909     break;
5910   case BSSGP_PDU_FLOW_CONTROL_PFC:
5911     decode_pdu_flow_control_pfc(bi);
5912     break;
5913   case BSSGP_PDU_FLOW_CONTROL_PFC_ACK:
5914     decode_pdu_flow_control_pfc_ack(bi);
5915     break;
5916   case BSSGP_PDU_SGSN_INVOKE_TRACE:
5917     decode_pdu_sgsn_invoke_trace(bi);
5918     break;
5919   case BSSGP_PDU_STATUS:
5920     decode_pdu_status(bi);
5921     break;
5922   case BSSGP_PDU_DOWNLOAD_BSS_PFC:
5923     decode_pdu_download_bss_pfc(bi);
5924     break;
5925   case BSSGP_PDU_CREATE_BSS_PFC:
5926     decode_pdu_create_bss_pfc(bi);
5927     break;
5928   case BSSGP_PDU_CREATE_BSS_PFC_ACK:
5929     decode_pdu_create_bss_pfc_ack(bi);
5930     break;
5931   case BSSGP_PDU_CREATE_BSS_PFC_NACK:
5932     decode_pdu_create_bss_pfc_nack(bi);
5933     break;
5934   case BSSGP_PDU_MODIFY_BSS_PFC:
5935     decode_pdu_modify_bss_pfc(bi);
5936     break;
5937   case BSSGP_PDU_MODIFY_BSS_PFC_ACK:
5938     decode_pdu_modify_bss_pfc_ack(bi);
5939     break;
5940   case BSSGP_PDU_DELETE_BSS_PFC:
5941     decode_pdu_delete_bss_pfc(bi);
5942     break;
5943   case BSSGP_PDU_DELETE_BSS_PFC_ACK:
5944     decode_pdu_delete_bss_pfc_ack(bi);
5945     break;
5946   case BSSGP_PDU_DELETE_BSS_PFC_REQ:
5947     decode_pdu_delete_bss_pfc_req(bi);
5948     break;
5949   case BSSGP_PDU_PERFORM_LOCATION_REQUEST:
5950     decode_pdu_perform_location_request(bi);
5951     break;
5952   case BSSGP_PDU_PERFORM_LOCATION_RESPONSE:
5953     decode_pdu_perform_location_response(bi);
5954     break;
5955   case BSSGP_PDU_PERFORM_LOCATION_ABORT:
5956     decode_pdu_perform_location_abort(bi);
5957     break;
5958   case BSSGP_PDU_POSITION_COMMAND:
5959     decode_pdu_position_command(bi);
5960     break;
5961   case BSSGP_PDU_POSITION_RESPONSE:
5962     decode_pdu_position_response(bi);
5963     break;
5964   case BSSGP_PDU_RAN_INFORMATION:
5965     decode_pdu_ran_information(bi);
5966     break;
5967   case BSSGP_PDU_RAN_INFORMATION_REQUEST:
5968     decode_pdu_ran_information_request(bi);
5969     break;
5970   case BSSGP_PDU_RAN_INFORMATION_ACK:
5971     decode_pdu_ran_information_ack(bi);
5972     break;
5973   case BSSGP_PDU_RAN_APPLICATION_ERROR:
5974     decode_pdu_ran_information_application_error(bi);
5975     break;
5976   case BSSGP_PDU_RAN_INFORMATION_ERROR:
5977     decode_pdu_ran_information_error(bi);
5978     break;
5979   default:
5980     ;
5981   }
5982 }
5983
5984 static void
5985 dissect_bssgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5986 {
5987   build_info_t bi = { NULL, 0, NULL, NULL, NULL, FALSE, FALSE, 0 };
5988
5989   proto_item *ti;
5990   proto_tree *bssgp_tree;
5991
5992   bi.tvb = tvb;
5993   bi.pinfo = pinfo;
5994   bi.parent_tree = tree;
5995
5996   pinfo->current_proto = "BSSGP";
5997
5998   if (check_col(pinfo->cinfo, COL_PROTOCOL))
5999     col_set_str(pinfo->cinfo, COL_PROTOCOL, "BSSGP");
6000
6001   if (check_col(pinfo->cinfo, COL_INFO))
6002     col_clear(pinfo->cinfo, COL_INFO);
6003
6004   bi.pdutype = tvb_get_guint8(tvb, 0);
6005   bi.offset++;
6006
6007   if (tree) {
6008     ti = proto_tree_add_item(tree, proto_bssgp, tvb, 0, -1, FALSE);
6009     bssgp_tree = proto_item_add_subtree(ti, ett_bssgp);
6010     proto_tree_add_uint_format_value(bssgp_tree, hf_bssgp_pdu_type, tvb, 0, 1,
6011                                      bi.pdutype,
6012                                      "%s (%#02x)",
6013                                      val_to_str(bi.pdutype, tab_bssgp_pdu_types,
6014                                                 "Unknown"), bi.pdutype);
6015     bi.bssgp_tree = bssgp_tree;
6016   }
6017
6018   if (check_col(pinfo->cinfo, COL_INFO)) {
6019     col_add_str(pinfo->cinfo, COL_INFO, val_to_str(bi.pdutype,
6020                                                    tab_bssgp_pdu_types,
6021                                                    "Unknown PDU type"));
6022   }
6023   decode_pdu(&bi);
6024 }
6025
6026 void
6027 proto_register_bssgp(void)
6028 {
6029   static hf_register_info hf[] = {
6030     { &hf_bssgp_pdu_type,
6031       { "PDU Type", "bssgp.pdu_type",
6032         FT_UINT8, BASE_HEX, VALS(tab_bssgp_pdu_types), 0x0,
6033         NULL, HFILL }
6034     },
6035     { &hf_bssgp_iei_nacc_cause,
6036       { "NACC Cause", "bssgp.iei.nacc_cause",
6037         FT_UINT8, BASE_HEX, VALS(tab_nacc_cause), 0x0,
6038         NULL, HFILL }
6039     },
6040     { &hf_bssgp_ie_type,
6041       { "IE Type", "bssgp.ie_type",
6042         FT_UINT8, BASE_HEX, VALS(tab_bssgp_ie_types), 0x0,
6043         "Information element type", HFILL }
6044     },
6045     { &hf_bssgp_bvci,
6046       { "BVCI", "bssgp.bvci",
6047         FT_UINT16, BASE_HEX, NULL, 0x0,
6048         NULL, HFILL }
6049     },
6050     { &hf_bssgp_tlli,
6051       { "TLLI", "bssgp.tlli",
6052         FT_UINT32, BASE_HEX, NULL, 0x0,
6053         NULL, HFILL }
6054     },
6055     { &hf_bssgp_nsei,
6056       { "NSEI", "bssgp.nsei",
6057         FT_UINT16, BASE_HEX, NULL, 0x0,
6058         NULL, HFILL }
6059     },
6060     { &hf_bssgp_mcc,
6061       { "MCC", "bssgp.mcc",
6062         FT_UINT8, BASE_DEC, VALS(E212_codes), 0x0,
6063         NULL, HFILL }
6064     },
6065     { &hf_bssgp_mnc,
6066       { "MNC", "bssgp.mnc",
6067         FT_UINT8, BASE_DEC, NULL, 0x0,
6068         NULL, HFILL }
6069     },
6070     { &hf_bssgp_lac,
6071       { "LAC", "bssgp.lac",
6072         FT_UINT16, BASE_DEC, NULL, 0x0,
6073         NULL, HFILL }
6074     },
6075     { &hf_bssgp_rac,
6076       { "RAC", "bssgp.rac",
6077         FT_UINT8, BASE_DEC, NULL, 0x0,
6078         NULL, HFILL }
6079     },
6080     { &hf_bssgp_ci,
6081       { "CI", "bssgp.ci",
6082         FT_UINT16, BASE_HEX, NULL, 0x0,
6083         "Cell Identity", HFILL }
6084     },
6085     { &hf_bssgp_ra_discriminator,
6086       { "Routing Address Discriminator", "bssgp.rad",
6087         FT_UINT8, BASE_DEC, VALS(ra_discriminator_vals), 0x0f,
6088         NULL, HFILL }
6089     },
6090     { &hf_bssgp_appid,
6091       { "Application ID", "bssgp.appid",
6092         FT_UINT8, BASE_HEX, NULL, 0x0,
6093         NULL, HFILL }
6094     },
6095     { &hf_bssgp_rcid,
6096       { "Reporting Cell Identity", "bssgp.rcid",
6097         FT_UINT64, BASE_HEX, NULL, 0x0,
6098         NULL, HFILL }
6099     },
6100     { &hf_bssgp_rrc_si_msg_type,
6101       { "RRC SI type", "bssgp.rrc_si_type",
6102         FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_rr_strings), 0x0,
6103         NULL, HFILL }
6104     },
6105     { &hf_ran_inf_req_pdu_type_ext,
6106       { "PDU Type Extension", "bssgp.ran_inf_req_pdu_type_ext",
6107         FT_UINT8, BASE_DEC, VALS(ran_inf_req_pdu_type_ext_vals), 0x0e,
6108         NULL, HFILL }
6109     },
6110     { &hf_ran_inf_pdu_type_ext,
6111       { "PDU Type Extension", "bssgp.ran_req_pdu_type_ext",
6112         FT_UINT8, BASE_DEC, VALS(ran_inf_pdu_type_ext_vals), 0x0e,
6113         NULL, HFILL }
6114     },
6115     { &hf_bssgp_tmsi_ptmsi,
6116       { "TMSI/PTMSI", "bssgp.tmsi_ptmsi",
6117         FT_UINT32, BASE_HEX, NULL, 0x0,
6118         NULL, HFILL }
6119     },
6120     { &hf_bssgp_imsi,
6121       { "IMSI", "bssgp.imsi",
6122         FT_STRING, BASE_NONE, NULL, 0x0,
6123         NULL, HFILL }
6124     },
6125     { &hf_bssgp_imei,
6126       { "IMEI", "bssgp.imei",
6127         FT_STRING, BASE_NONE, NULL, 0x0,
6128         NULL, HFILL }
6129     },
6130     { &hf_bssgp_imeisv,
6131       { "IMEISV", "bssgp.imeisv",
6132         FT_STRING, BASE_NONE, NULL, 0x0,
6133         NULL, HFILL }
6134     },
6135     { &hf_bssgp_nri,
6136       { "NRI", "bssgp.nri",
6137         FT_UINT16, BASE_DEC, NULL, 0x0,
6138         NULL, HFILL }
6139     },
6140   };
6141
6142   /* Setup protocol subtree array */
6143   static gint *ett[] = {
6144     &ett_bssgp,
6145     &ett_bssgp_qos_profile,
6146     &ett_bssgp_gprs_timer,
6147     &ett_bssgp_cell_identifier,
6148     &ett_bssgp_channel_needed,
6149     &ett_bssgp_drx_parameters,
6150     &ett_bssgp_mobile_identity,
6151     &ett_bssgp_priority,
6152     &ett_bssgp_lsa_identifier_list,
6153     &ett_bssgp_lsa_information,
6154     &ett_bssgp_lsa_information_lsa_identification_and_attributes,
6155     &ett_bssgp_abqp,
6156     &ett_bssgp_lcs_qos,
6157     &ett_bssgp_lcs_client_type,
6158     &ett_bssgp_requested_gps_assistance_data,
6159     &ett_bssgp_requested_gps_assistance_data_satellite,
6160     &ett_bssgp_location_type,
6161     &ett_bssgp_positioning_data_positioning_method,
6162     &ett_bssgp_lcs_cause,
6163     &ett_bssgp_lcs_capability,
6164     &ett_bssgp_rrlp_flags,
6165     &ett_bssgp_rim_pdu_indications,
6166     &ett_bssgp_mcc,
6167     &ett_bssgp_mnc,
6168     &ett_bssgp_routing_area,
6169     &ett_bssgp_location_area,
6170     &ett_bssgp_rai_ci,
6171     &ett_bssgp_ran_information_request_application_container,
6172     &ett_bssgp_rim_routing_information,
6173     &ett_bssgp_ran_information_request_container_unit,
6174     &ett_bssgp_ran_information_container_unit,
6175     &ett_bssgp_pfc_flow_control_parameters,
6176     &ett_bssgp_pfc_flow_control_parameters_pfc,
6177     &ett_bssgp_global_cn_id,
6178     &ett_bssgp_ms_radio_access_capability,
6179     &ett_bssgp_feature_bitmap,
6180     &ett_bssgp_positioning_data,
6181     &ett_bssgp_msrac_value_part,
6182     &ett_bssgp_msrac_additional_access_technologies,
6183     &ett_bssgp_msrac_access_capabilities,
6184     &ett_bssgp_msrac_a5_bits,
6185     &ett_bssgp_msrac_multislot_capability,
6186     &ett_bssgp_tlli,
6187     &ett_bssgp_tmsi_ptmsi,
6188   };
6189
6190   /* Register the protocol name and description */
6191   proto_bssgp = proto_register_protocol("Base Station Subsystem GPRS Protocol", "BSSGP", "bssgp");
6192
6193   /* Required function calls to register the header fields and subtrees used */
6194   proto_register_field_array(proto_bssgp, hf, array_length(hf));
6195   proto_register_subtree_array(ett, array_length(ett));
6196   register_dissector("bssgp", dissect_bssgp, proto_bssgp);
6197
6198   /* Register configuration options */
6199   bssgp_module = prefs_register_protocol(proto_bssgp, NULL);
6200   prefs_register_bool_preference(bssgp_module, "decode_nri",
6201                                  "Decode NRI",
6202                                  "Decode NRI (for use with SGSN in Pool)",
6203                                  &bssgp_decode_nri);
6204   prefs_register_uint_preference(bssgp_module, "nri_length", "NRI length",
6205                                  "NRI length, in bits",
6206                                  10, &bssgp_nri_length);
6207 }
6208
6209 /* If this dissector uses sub-dissector registration add a registration routine.
6210  */
6211 void
6212 proto_reg_handoff_bssgp(void)
6213 {
6214   llc_handle = find_dissector("llcgprs");
6215   rrlp_handle = find_dissector("rrlp");
6216   data_handle = find_dissector("data");
6217 }