the code forgot to update offset *offset++ is not the same as offset++ :-)
[metze/wireshark/wip.git] / epan / dissectors / packet-bssap.c
1 /* packet-bssap.c
2  * Routines for Base Station Subsystem Application Part (BSSAP/BSAP) dissection
3  * Specifications from 3GPP2 (www.3gpp2.org) and 3GPP (www.3gpp.org)
4  *      IOS 4.0.1 (BSAP)
5  *      GSM 08.06 (BSSAP)
6  *
7  * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
8  * In association with Telos Technology Inc.
9  *
10  * Added BSSAP+ according to ETSI TS 129 018 V6.3.0 (2005-3GPP TS 29.018 version 6.3.0 Release 6)
11  * Copyright 2006, Anders Broman <Anders.Broman [AT] ericsson.com>
12  *
13  * $Id$
14  *
15  * Ethereal - Network traffic analyzer
16  * By Gerald Combs <gerald@ethereal.com>
17  * Copyright 1998 Gerald Combs
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <gmodule.h>
41
42 #ifdef HAVE_SYS_TYPES_H
43 # include <sys/types.h>
44 #endif
45
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49
50 #include <string.h>
51
52 #include "epan/packet.h"
53 #include <epan/prefs.h>
54 #include <epan/emem.h>
55
56 #include "packet-bssap.h"
57 #include "packet-gsm_a.h"
58 #include "packet-e212.h"
59
60 #define BSSAP 0
61 #define BSAP  1
62
63 #define BSSAP_OR_BSAP_DEFAULT BSSAP
64
65 #define PDU_TYPE_OFFSET 0
66 #define PDU_TYPE_LENGTH 1
67
68 /* Same as below but with names typed out */
69 static const value_string bssap_pdu_type_values[] = {
70     { BSSAP_PDU_TYPE_BSSMAP,    "BSS Management" },
71     { BSSAP_PDU_TYPE_DTAP,      "Direct Transfer" },
72     { 0,                        NULL } };
73
74 static const value_string bsap_pdu_type_values[] = {
75     { BSSAP_PDU_TYPE_BSSMAP,    "BS Management" },
76     { BSSAP_PDU_TYPE_DTAP,      "Direct Transfer" },
77     { 0,                        NULL } };
78
79 /* Same as above but in acronym for (for the Info column) */
80 static const value_string bssap_pdu_type_acro_values[] = {
81     { BSSAP_PDU_TYPE_BSSMAP,    "BSSMAP" },
82     { BSSAP_PDU_TYPE_DTAP,      "DTAP" },
83     { 0,                        NULL } };
84
85 /* Same as above but in acronym for (for the Info column) */
86 static const value_string bsap_pdu_type_acro_values[] = {
87     { BSSAP_PDU_TYPE_BSSMAP,    "BSMAP" },
88     { BSSAP_PDU_TYPE_DTAP,      "DTAP" },
89     { 0,                        NULL } };
90
91 #define PARAMETER_DLCI          0x00
92 #define PARAMETER_LENGTH        0x01
93 #define PARAMETER_DATA          0x02
94
95 #define DLCI_LENGTH             1
96 #define LENGTH_LENGTH           1
97 #define DATA_LENGTH             1
98
99 #define CC_MASK                 0xc0
100 #define SPARE_MASK              0x38
101 #define SAPI_MASK               0x07
102
103 #define SCCP_SSN_BSSAP_PLUS 98
104
105 static const value_string bssap_cc_values[] = {
106     { 0x00,             "not further specified" },
107     { 0x80,             "FACCH or SDCCH" },
108     { 0xc0,             "SACCH" },
109     { 0,                NULL } };
110
111 static const value_string bsap_cc_values[] = {
112     { 0x00,             "default for TIA/EIA/IS-2000" },
113     { 0,                NULL } };
114
115 static const value_string bssap_sapi_values[] = {
116     { 0x00,             "RR/MM/CC" },
117     { 0x03,             "SMS" },
118     { 0,                NULL } };
119
120 static const value_string bsap_sapi_values[] = {
121     { 0x00,             "Not used" },
122     { 0,                NULL } };
123
124 #define BSSAP_PAGING_REQUEST                            1
125 #define BSSAP_PAGING_REJECT                                     2                                       /*  17.1.18 */
126 #define BSSAP_DOWNLINK_TUNNEL_REQUEST           7                                       /*  17.1.4  */
127 #define BSSAP_UPLINK_TUNNEL_REQUEST                     8                                       /*  17.1.23 */
128 #define BSSAP_LOCATION_UPDATE_REQUEST           9                                       /*  17.1.11 */
129 #define BSSAP_LOCATION_UPDATE_ACCEPT            10                                      /*  17.1.9  */
130 #define BSSAP_LOCATION_UPDATE_REJECT            11                                      /*  17.1.10 */
131 #define BSSAP_TMSI_REALLOCATION_COMPLETE        12                                      /*  17.1.22 */
132 #define BSSAP_ALERT_REQUEST                                     13                                      /*  17.1.3  */
133 #define BSSAP_ALERT_ACK                                         14                                      /*  17.1.1  */
134 #define BSSAP_ALERT_REJECT                                      15                                      /*  17.1.2  */
135 #define BSSAP_MS_ACTIVITY_INDICATION            16                                      /*  17.1.14 */
136 #define BSSAP_GPRS_DETACH_INDICATION            17                                      /*  17.1.6  */
137 #define BSSAP_GPRS_DETACH_ACK                           18                                      /*  17.1.5  */
138 #define BSSAP_IMSI_DETACH_INDICATION            19                                      /*  17.1.8  */
139 #define BSSAP_IMSI_DETACH_ACK                           20                                      /*  17.1.7  */
140 #define BSSAP_RESET_INDICATION                          21                                      /*  17.1.21 */
141 #define BSSAP_RESET_ACK                                         22                                      /*  17.1.20 */
142 #define BSSAP_MS_INFORMATION_REQUEST            23                                      /*  17.1.15 */
143 #define BSSAP_MS_INFORMATION_RESPONSE           24                                      /*  17.1.16 */
144 #define BSSAP_MM_INFORMATION_REQUEST            26                                      /*  17.1.12 */
145 #define BSSAP_MOBILE_STATUS                                     29                                      /*  17.1.13 */
146 #define BSSAP_MS_UNREACHABLE                            31                                      /*  17.1.17 */
147
148 static const value_string bssap_plus_message_type_values[] = {
149     { 0x00,                                                                     "Unassigned: treated as an unknown Message type." },
150     { BSSAP_PAGING_REQUEST,                                     "BSSAP+-PAGING-REQUEST" },                                                              /*  17.1.19 */
151     { BSSAP_PAGING_REJECT,                                      "BSSAP+-PAGING-REJECT" },                                                               /*  17.1.18 */
152     { 0x03,                                                                     "Unassigned: treated as an unknown Message type." },
153     { 0x04,                                                                     "Unassigned: treated as an unknown Message type." },
154     { 0x05,                                                                     "Unassigned: treated as an unknown Message type." },
155     { 0x06,                                                                     "Unassigned: treated as an unknown Message type." },
156     { BSSAP_DOWNLINK_TUNNEL_REQUEST,            "BSSAP+-DOWNLINK-TUNNEL-REQUEST" },                                             /*  17.1.4  */
157     { BSSAP_UPLINK_TUNNEL_REQUEST,                      "BSSAP+-UPLINK-TUNNEL-REQUEST" },                                               /*  17.1.23 */
158     { BSSAP_LOCATION_UPDATE_REQUEST,            "BSSAP+-LOCATION-UPDATE-REQUEST" },                                             /*  17.1.11 */
159     { BSSAP_LOCATION_UPDATE_ACCEPT,                     "BSSAP+-LOCATION-UPDATE-ACCEPT" },                                              /*  17.1.9  */
160     { BSSAP_LOCATION_UPDATE_REJECT,                     "BSSAP+-LOCATION-UPDATE-REJECT" },                                              /*  17.1.10 */
161     { BSSAP_TMSI_REALLOCATION_COMPLETE,         "BSSAP+-TMSI-REALLOCATION-COMPLETE" },                                  /*  17.1.22 */
162     { BSSAP_ALERT_REQUEST,                                      "BSSAP+-ALERT-REQUEST" },                                                               /*  17.1.3  */
163     { BSSAP_ALERT_ACK,                                          "BSSAP+-ALERT-ACK" },                                                                   /*  17.1.1  */
164     { BSSAP_ALERT_REJECT,                                       "BSSAP+-ALERT-REJECT" },                                                                /*  17.1.2  */
165     { BSSAP_MS_ACTIVITY_INDICATION,                     "BSSAP+-MS-ACTIVITY-INDICATION" },                                              /*  17.1.14 */
166     { BSSAP_GPRS_DETACH_INDICATION,                     "BSSAP+-GPRS-DETACH-INDICATION" },                                              /*  17.1.6  */
167     { BSSAP_GPRS_DETACH_ACK,                            "BSSAP+-GPRS-DETACH-ACK" },                                                             /*  17.1.5  */
168     { BSSAP_IMSI_DETACH_INDICATION,                     "BSSAP+-IMSI-DETACH-INDICATION" },                                              /*  17.1.8  */
169     { BSSAP_IMSI_DETACH_ACK,                            "BSSAP+-IMSI-DETACH-ACK" },                                                             /*  17.1.7  */
170     { BSSAP_RESET_INDICATION,                           "BSSAP+-RESET-INDICATION" },                                                    /*  17.1.21 */
171     { BSSAP_RESET_ACK,                                          "BSSAP+-RESET-ACK" },                                                                   /*  17.1.20 */
172     { BSSAP_MS_INFORMATION_REQUEST,                     "BSSAP+-MS-INFORMATION-REQUEST" },                                              /*  17.1.15 */
173     { BSSAP_MS_INFORMATION_RESPONSE,            "BSSAP+-MS-INFORMATION-RESPONSE" },                                             /*  17.1.16 */
174     { 0x19,                                                                     "Unassigned: treated as an unknown Message type." },
175     { BSSAP_MM_INFORMATION_REQUEST,                     "BSSAP+-MM-INFORMATION-REQUEST" },                                              /*  17.1.12 */
176     { BSSAP_MOBILE_STATUS,                                      "BSSAP+-MOBILE-STATUS" },                                                               /*  17.1.13 */
177     { 0x1e,                                                                     "Unassigned: treated as an unknown Message type." },
178     { BSSAP_MS_UNREACHABLE,                                     "BSSAP+-MS-UNREACHABLE" },                                                              /*  17.1.17 */
179     { 0,                NULL }
180 };
181
182 #define BSSAP_IMSI                                              1
183 #define BSSAP_VLR_NUMBER                                2
184 #define BSSAP_TMSI                                              3
185 #define BSSAP_LOC_AREA_ID                               4
186 #define BSSAP_CHANNEL_NEEDED                    5
187 #define BSSAP_EMLPP_PRIORITY                    6
188 #define BSSAP_TMSI_STATUS                               7
189 #define BSSAP_GS_CAUSE                                  8
190 #define BSSAP_SGSN_NUMBER                               9
191 #define BSSAP_GPRS_LOC_UPD_TYPE                 0x0a
192 #define BSSAP_GLOBAL_CN_ID                              0x0b
193 #define BSSAP_MOBILE_STN_CLS_MRK1               0x0d
194 #define BSSAP_MOBILE_ID                                 0x0e
195 #define BSSAP_REJECT_CAUSE                              0x0f
196 #define BSSAP_IMSI_DET_FROM_GPRS_SERV_TYPE              0x10
197 #define BSSAP_IMSI_DET_FROM_NON_GPRS_SERV_TYPE  0x11
198 #define BSSAP_INFO_REQ                                  0x12
199 #define BSSAP_PTMSI                                             0x13
200 #define BSSAP_IMEI                                              0x14
201 #define BSSAP_IMEISV                                    0x15
202 #define BSSAP_MM_INFORMATION                    0x17
203 #define BSSAP_CELL_GBL_ID                               0x18
204 #define BSSAP_LOC_INF_AGE                               0x19
205 #define BSSAP_MOBILE_STN_STATE                  0x1a
206 #define BSSAP_SERVICE_AREA_ID                   0x1e
207 #define BSSAP_ERRONEOUS_MSG                             0x1b
208 #define BSSAP_DLINK_TNL_PLD_CTR_AND_INF 0x1c
209 #define BSSAP_ULINK_TNL_PLD_CTR_AND_INF 0x1d
210
211
212
213 static const value_string bssap_plus_ie_id_values[] = { 
214     { BSSAP_IMSI,                                                               "IMSI" },                                                                               /* 18.4.10 */
215     { BSSAP_VLR_NUMBER,                                                 "VLR number" },                                                                 /* 18.4.26 */ 
216     { BSSAP_TMSI,                                                               "TMSI" },                                                                               /* 18.4.23 */
217     { BSSAP_LOC_AREA_ID,                                                "Location area identifier" },                                   /* 18.4.14 */ 
218     { BSSAP_CHANNEL_NEEDED,                                             "Channel Needed" },                                                             /* 18.4.2  */ 
219     { BSSAP_EMLPP_PRIORITY,                                             "eMLPP Priority" },                                                             /* 18.4.4  */ 
220     { BSSAP_TMSI_STATUS,                                                "TMSI status" },                                                                /* 18.4.24 */ 
221     { BSSAP_GS_CAUSE,                                                   "Gs cause" },                                                                   /* 18.4.7  */ 
222     { BSSAP_SGSN_NUMBER,                                                "SGSN number" },                                                                /* 18.4.22 */ 
223     { BSSAP_GPRS_LOC_UPD_TYPE,                                  "GPRS location update type" },                                  /* 18.4.6  */ 
224     { BSSAP_GLOBAL_CN_ID,                                               "Global CN-Id" },                                                               /* 18.4.27 */ 
225     { 0x0c,                                                                             "Unassigned: treated as an unknown IEI." },             /* 18 and 16 */ 
226     { BSSAP_MOBILE_STN_CLS_MRK1,                                "Mobile station classmark 1" },                                 /* 18.4.18 */ 
227     { BSSAP_MOBILE_ID,                                                  "Mobile identity" },                                                    /* 18.4.17 */ 
228     { BSSAP_REJECT_CAUSE,                                               "Reject cause" },                                                               /* 18.4.21 */ 
229     { BSSAP_IMSI_DET_FROM_GPRS_SERV_TYPE,               "IMSI detach from GPRS service type" },                 /* 18.4.11 */ 
230     { BSSAP_IMSI_DET_FROM_NON_GPRS_SERV_TYPE,   "IMSI detach from non-GPRS service type" },             /* 18.4.12 */ 
231     { BSSAP_INFO_REQ,                                                   "Information requested" },                                              /* 18.4.13 */
232     { BSSAP_PTMSI,                                                              "PTMSI" },                                                                              /* 18.4.20 */
233     { BSSAP_IMEI,                                                               "IMEI" },                                                                               /* 18.4.8  */
234     { BSSAP_IMEISV,                                                             "IMEISV" },                                                                             /* 18.4.9 */
235     { 0x16,                                                                             "Unassigned: treated as an unknown IEI." },             /* 18 and 16 */ 
236     { BSSAP_MM_INFORMATION,                                             "MM information" },                                                             /* 18.4.16 */ 
237     { BSSAP_CELL_GBL_ID,                                                "Cell Global Identity" },                                               /* 18.4.1 */ 
238     { BSSAP_LOC_INF_AGE,                                                "Location information age" },                                   /* 18.4.15 */ 
239     { BSSAP_MOBILE_STN_STATE,                                   "Mobile station state" },                                               /* 18.4.19 */ 
240     { BSSAP_ERRONEOUS_MSG,                                              "Erroneous message" },                                                  /* 18.4.5 */ 
241     { BSSAP_DLINK_TNL_PLD_CTR_AND_INF,                  "Downlink Tunnel Payload Control and Info" },   /* 18.4.3 */ 
242     { BSSAP_ULINK_TNL_PLD_CTR_AND_INF,                  "Uplink Tunnel Payload Control and Info" },             /* 18.4.25 */ 
243     { BSSAP_SERVICE_AREA_ID,                                    "Service Area Identification" },                                /* 18.4.21b */ 
244     { 0,                NULL } 
245 }; 
246
247 /* Initialize the protocol and registered fields */
248 static int proto_bssap = -1;
249 static int proto_bssap_plus = -1;
250 static int hf_bssap_pdu_type = -1;
251 static int hf_bsap_pdu_type = -1;
252 static int hf_bssap_dlci_cc = -1;
253 static int hf_bsap_dlci_cc = -1;
254 static int hf_bssap_dlci_spare = -1;
255 static int hf_bsap_dlci_rsvd = -1;
256 static int hf_bssap_dlci_sapi = -1;
257 static int hf_bsap_dlci_sapi = -1;
258 static int hf_bssap_length = -1;
259 static int hf_bssap_plus_ie = -1;
260 static int hf_bssap_plus_ie_len = -1;
261
262 static int hf_bssap_plus_message_type = -1;
263 static int hf_bssap_imsi_ie = -1;
264 static int hf_bssap_imsi_det_from_gprs_serv_type_ie = -1;
265 static int hf_bssap_imsi_det_from_non_gprs_serv_type_ie = -1;
266 static int hf_bssap_info_req_ie = -1;
267 static int hf_bssap_loc_area_id_ie = -1;
268 static int hf_bssap_loc_inf_age_ie = -1;
269 static int hf_bssap_mm_information_ie = -1;
270 static int hf_bssap_mobile_id_ie = -1;
271 static int hf_bssap_mobile_stn_cls_mrk1_ie = -1;
272 static int hf_bssap_mobile_station_state_ie = -1;
273 static int hf_bssap_ptmsi_ie = -1;
274 static int hf_bssap_reject_cause_ie = -1;
275 static int hf_bssap_service_area_id_ie = -1;
276 static int hf_bssap_sgsn_nr_ie = -1;
277 static int hf_bssap_tmsi_ie = -1;
278 static int hf_bssap_tmsi_status_ie = -1;
279 static int hf_bssap_vlr_number_ie = -1;
280 static int hf_bssap_global_cn_id_ie = -1;
281 static int hf_bssap_plus_ie_data = -1;
282
283 static int hf_bssap_extension = -1;
284 static int hf_bssap_type_of_number = -1; 
285 static int hf_bssap_numbering_plan_id = -1;
286 static int hf_bssap_sgsn_number = -1;
287 static int hf_bssap_vlr_number = -1;
288 static int hf_bssap_call_priority = -1;
289 static int hf_bssap_gprs_loc_upd_type_ie = -1;
290 static int hf_bssap_Gs_cause_ie = -1;
291 static int hf_bssap_imei_ie = -1;
292 static int hf_bssap_imesiv_ie = -1;
293 static int hf_bssap_cell_global_id_ie = -1;
294 static int hf_bssap_channel_needed_ie = -1;
295 static int hf_bssap_dlink_tnl_pld_cntrl_amd_inf_ie = -1;
296 static int hf_bssap_ulink_tnl_pld_cntrl_amd_inf_ie = -1;
297 static int hf_bssap_emlpp_prio_ie = -1;
298 static int hf_bssap_gprs_erroneous_msg_ie = -1;
299
300 static int hf_bssap_gprs_loc_upd_type = -1;
301 static int hf_bssap_Gs_cause = -1;
302 static int hf_bssap_imei = -1;
303 static int hf_bssap_imeisv = -1;
304 static int hf_bssap_imsi = -1;
305 static int hf_bssap_imsi_det_from_gprs_serv_type = -1;
306 static int hf_bssap_info_req = -1;
307 static int hf_bssap_loc_inf_age = -1;
308 static int hf_bssap_mobile_station_state = -1;
309 static int hf_bssap_ptmsi = -1;
310 static int hf_bssap_tmsi = -1;
311 static int hf_bssap_tmsi_status = -1;
312 static int hf_bssap_tom_prot_disc = -1;
313 static int hf_bssap_e_bit = -1;
314 static int hf_bssap_tunnel_prio = -1;
315 static int hf_bssap_global_cn_id = -1;
316 static int hf_bssap_plmn_id = -1;
317 static int hf_bssap_cn_id = -1;
318 static int hf_bssap_cell_global_id = -1;
319
320 /* Initialize the subtree pointers */
321 static gint ett_bssap = -1;
322 static gint ett_bssap_dlci = -1;
323 static gint     ett_bssap_imsi = -1;
324 static gint ett_bssap_imsi_det_from_gprs_serv_type = -1;
325 static gint ett_bssap_imsi_det_from_non_gprs_serv_type = -1;
326 static gint ett_bssap_info_req = -1;
327 static gint ett_bssap_loc_area_id = -1;
328 static gint ett_bssap_loc_inf_age = -1;
329 static gint ett_bssap_mm_information = -1;
330 static gint ett_bssap_mobile_id = -1;
331 static gint ett_bssap_sgsn_nr = -1;
332 static gint ett_bssap_tmsi = -1;
333 static gint ett_bssap_tmsi_status = -1;
334 static gint ett_bssap_vlr_number = -1;
335 static gint ett_bssap_global_cn = -1;
336 static gint ett_bssap_gprs_loc_upd = -1;
337 static gint ett_bassp_Gs_cause = -1;
338 static gint ett_bassp_imei = -1;
339 static gint ett_bassp_imesiv = -1;
340 static gint ett_bssap_cell_global_id = -1;
341 static gint ett_bssap_cgi = -1;
342 static gint ett_bssap_channel_needed = -1;
343 static gint ett_bssap_dlink_tnl_pld_cntrl_amd_inf = -1;
344 static gint ett_bssap_ulink_tnl_pld_cntrl_amd_inf = -1;
345 static gint ett_bssap_emlpp_prio = -1;
346 static gint ett_bssap_erroneous_msg = -1;
347 static gint ett_bssap_mobile_stn_cls_mrk1 = -1;
348 static gint ett_bssap_mobile_station_state = -1;
349 static gint ett_bssap_ptmsi = -1;
350 static gint ett_bssap_reject_cause = -1;
351 static gint ett_bssap_service_area_id =-1;
352 static gint ett_bssap_global_cn_id = -1;
353 static gint ett_bssap_plmn = -1;
354
355 static dissector_handle_t data_handle;
356
357 static dissector_table_t bssap_dissector_table;
358 static dissector_table_t bsap_dissector_table;
359
360 /*
361  * Keep track of pdu_type so we can call appropriate sub-dissector
362  */
363 static guint8   pdu_type = 0xFF;
364
365 static gint     bssap_or_bsap_global = BSSAP_OR_BSAP_DEFAULT;
366
367
368 static void
369 dissect_bssap_unknown_message(tvbuff_t *message_tvb, proto_tree *bssap_tree)
370 {
371     guint32     message_length;
372
373     message_length = tvb_length(message_tvb);
374
375     proto_tree_add_text(bssap_tree, message_tvb, 0, message_length,
376         "Unknown message (%u byte%s)",
377         message_length, plurality(message_length, "", "s"));
378 }
379
380 static void
381 dissect_bssap_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint16 length)
382 {
383     proto_tree_add_text(tree, tvb, 0, length,
384         "Unknown parameter 0x%x (%u byte%s)",
385         type, length, plurality(length, "", "s"));
386 }
387
388 static void
389 dissect_bssap_data_param(tvbuff_t *tvb, packet_info *pinfo,
390                         proto_tree *bssap_tree, proto_tree *tree)
391 {
392     if ((pdu_type <= 0x01))
393     {
394         if (bssap_or_bsap_global == BSSAP)
395         {
396             /* BSSAP */
397             if (dissector_try_port(bssap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
398         }
399         else
400         {
401             /* BSAP */
402             if (dissector_try_port(bsap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
403         }
404     }
405
406     /* No sub-dissection occured, treat it as raw data */
407     call_dissector(data_handle, tvb, pinfo, bssap_tree);
408 }
409
410 static void
411 dissect_bssap_dlci_param(tvbuff_t *tvb, proto_tree *tree, guint16 length)
412 {
413     proto_item  *dlci_item = 0;
414     proto_tree  *dlci_tree = 0;
415     guint8      oct;
416
417     dlci_item =
418         proto_tree_add_text(tree, tvb, 0, length,
419             "Data Link Connection Identifier");
420
421     dlci_tree = proto_item_add_subtree(dlci_item, ett_bssap_dlci);
422
423     oct = tvb_get_guint8(tvb, 0);
424
425     if (bssap_or_bsap_global == BSSAP)
426     {
427         proto_tree_add_uint(dlci_tree, hf_bssap_dlci_cc, tvb, 0, length, oct);
428         proto_tree_add_uint(dlci_tree, hf_bssap_dlci_spare, tvb, 0, length, oct);
429         proto_tree_add_uint(dlci_tree, hf_bssap_dlci_sapi, tvb, 0, length, oct);
430     }
431     else
432     {
433         proto_tree_add_uint(dlci_tree, hf_bsap_dlci_cc, tvb, 0, length, oct);
434         proto_tree_add_uint(dlci_tree, hf_bsap_dlci_rsvd, tvb, 0, length, oct);
435         proto_tree_add_uint(dlci_tree, hf_bsap_dlci_sapi, tvb, 0, length, oct);
436     }
437 }
438
439 static void
440 dissect_bssap_length_param(tvbuff_t *tvb, proto_tree *tree, guint16 length)
441 {
442     guint8      data_length;
443
444     data_length = tvb_get_guint8(tvb, 0);
445     proto_tree_add_uint(tree, hf_bssap_length, tvb, 0, length, data_length);
446 }
447
448 /*
449  * Dissect a parameter given its type, offset into tvb, and length.
450  */
451 static guint16
452 dissect_bssap_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
453                        proto_tree *tree, guint8 parameter_type, gint offset,
454                        guint16 parameter_length)
455 {
456     tvbuff_t *parameter_tvb;
457
458     parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
459
460     switch (parameter_type)
461     {
462     case PARAMETER_DLCI:
463         dissect_bssap_dlci_param(parameter_tvb, bssap_tree, parameter_length);
464         break;
465
466     case PARAMETER_LENGTH:
467         dissect_bssap_length_param(parameter_tvb, bssap_tree, parameter_length);
468         break;
469
470     case PARAMETER_DATA:
471         dissect_bssap_data_param(parameter_tvb, pinfo, bssap_tree, tree);
472         break;
473
474     default:
475         dissect_bssap_unknown_param(parameter_tvb, bssap_tree, parameter_type,
476             parameter_length);
477         break;
478     }
479
480     return(parameter_length);
481 }
482
483 static guint16
484 dissect_bssap_var_parameter(tvbuff_t *tvb, packet_info *pinfo,
485                                 proto_tree *bssap_tree, proto_tree *tree,
486                                 guint8 parameter_type, gint offset)
487 {
488     guint16     parameter_length;
489     guint8      length_length;
490
491     parameter_length = tvb_get_guint8(tvb, offset);
492     length_length = LENGTH_LENGTH;
493
494     offset += length_length;
495
496     dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree, parameter_type,
497         offset, parameter_length);
498
499     return(parameter_length + length_length);
500 }
501
502 static void
503 dissect_bssap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
504                      proto_tree *tree)
505 {
506     gint        offset = 0;
507
508     /*
509      * Extract the PDU type
510      */
511     pdu_type = tvb_get_guint8(tvb, PDU_TYPE_OFFSET);
512     offset = PDU_TYPE_LENGTH;
513
514     if (bssap_tree)
515     {
516         /*
517          * add the message type to the protocol tree
518          */
519         proto_tree_add_uint(bssap_tree,
520             (bssap_or_bsap_global == BSSAP) ? hf_bssap_pdu_type : hf_bsap_pdu_type,
521             tvb, PDU_TYPE_OFFSET, PDU_TYPE_LENGTH, pdu_type);
522     }
523
524     /* Starting a new message dissection */
525
526     switch (pdu_type)
527     {
528     case BSSAP_PDU_TYPE_BSSMAP:
529         offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
530                                      PARAMETER_LENGTH, offset,
531                                      LENGTH_LENGTH);
532         offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
533                                     PARAMETER_DATA,
534                                     (offset - LENGTH_LENGTH));
535         break;
536
537     case BSSAP_PDU_TYPE_DTAP:
538         offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
539                                      PARAMETER_DLCI,
540                                      offset, DLCI_LENGTH);
541         offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
542                                      PARAMETER_LENGTH, offset,
543                                      LENGTH_LENGTH);
544         offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
545                                     PARAMETER_DATA,
546                                     (offset - LENGTH_LENGTH));
547         break;
548
549     default:
550         if (check_col(pinfo->cinfo, COL_INFO))
551         {
552             col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
553                 val_to_str(pdu_type, ((bssap_or_bsap_global == BSSAP) ?
554                     bssap_pdu_type_acro_values : bsap_pdu_type_acro_values),
555                     "Unknown"));
556
557         }
558
559         dissect_bssap_unknown_message(tvb, bssap_tree);
560         break;
561     }
562 }
563
564 static void
565 dissect_bssap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
566 {
567     proto_item  *bssap_item;
568     proto_tree  *bssap_tree = NULL;
569
570     /*
571      * Make entry in the Protocol column on summary display
572      */
573     if (check_col(pinfo->cinfo, COL_PROTOCOL))
574     {
575         col_set_str(pinfo->cinfo, COL_PROTOCOL, ((bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP"));
576     }
577
578     /*
579      * create the bssap protocol tree
580      */
581     proto_tree_add_item_hidden(tree, proto_bssap, tvb, 0, -1, FALSE);
582     bssap_item = proto_tree_add_text(tree, tvb, 0, -1, (bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP");
583     bssap_tree = proto_item_add_subtree(bssap_item, ett_bssap);
584
585     /* dissect the message */
586
587     dissect_bssap_message(tvb, pinfo, bssap_tree, tree);
588 }
589
590
591 /* 
592  * BSSAP+ Routines
593  */
594
595 typedef struct dgt_set_t
596 {
597     unsigned char out[15];
598 }
599 dgt_set_t;
600
601 static dgt_set_t Dgt_tbcd = {
602     {
603   /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
604      '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#'
605     }
606 };
607 static dgt_set_t Dgt1_9_bcd = {
608     {
609   /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
610      '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
611     }
612 };
613 /* Assumes the rest of the tvb contains the digits to be turned into a string 
614  */
615 static char*
616 unpack_digits(tvbuff_t *tvb, int offset,dgt_set_t *dgt,gboolean skip_first){
617
618         int length;
619         guint8 octet;
620         int i=0;
621         char *digit_str;
622
623         length = tvb_length(tvb);
624         if (length < offset)
625                 return "";
626         digit_str = ep_alloc((length - offset)*2+1);
627
628         while ( offset < length ){
629
630                 octet = tvb_get_guint8(tvb,offset);
631                 if (!skip_first){
632                         digit_str[i] = dgt->out[octet & 0x0f]; 
633                         i++;
634                 }
635                 skip_first = FALSE;
636
637                 /*
638                  * unpack second value in byte
639                  */
640                 octet = octet >> 4;
641
642                 if (octet == 0x0f)      /* odd number bytes - hit filler */
643                         break;
644
645                 digit_str[i] = dgt->out[octet & 0x0f]; 
646                 i++;
647                 offset++;
648
649         }
650         digit_str[i]= '\0';
651         return digit_str;
652 }
653
654 static gboolean
655 check_ie(tvbuff_t *tvb, proto_tree *tree, int *offset, guint8 expected_ie){
656         guint8  ie_type;
657         guint8  ie_len;
658
659         ie_type = tvb_get_guint8(tvb,*offset);
660         if (ie_type != expected_ie){
661                 proto_tree_add_text(tree, tvb, *offset, 1, "Mandatory IE %s expected but IE %s Found",
662                         val_to_str(expected_ie,bssap_plus_ie_id_values,"Unknown %u"), val_to_str(ie_type,bssap_plus_ie_id_values,"Unknown %u"));
663                 offset++;
664                 ie_len = tvb_get_guint8(tvb,*offset);
665                 *offset = *offset + ie_len;
666                 return FALSE;
667         }
668
669         return TRUE;
670
671 }
672
673 static gboolean
674 check_optional_ie(tvbuff_t *tvb, proto_tree *tree, int offset, guint8 expected_ie){
675         guint8  ie_type;
676
677         ie_type = tvb_get_guint8(tvb,offset);
678         if (ie_type != expected_ie){
679                 return FALSE;
680         }
681         return TRUE;
682
683 }
684
685 /* 18.4.1 Cell global identity */
686 static int
687 dissect_bssap_cell_global_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
688 {
689     proto_item  *item = NULL;
690     proto_tree  *ie_tree = NULL;
691     proto_item  *cgi_item = NULL;
692     proto_tree  *cgi_tree = NULL;
693         guint8 ie_len;
694         
695         ie_len = tvb_get_guint8(tvb,offset+1);
696         item = proto_tree_add_item(tree, hf_bssap_cell_global_id_ie, tvb, offset, ie_len+2, FALSE);
697         ie_tree = proto_item_add_subtree(item, ett_bssap_cell_global_id);
698
699         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
700         offset++;
701         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
702         offset++;
703         /*
704          * The rest of the information element is coded as the the value part
705          * of the cell global id IE defined in 3GPP TS 48.018 (not including
706          * 3GPP TS 48.018 IEI and 3GPP TS 48.018 length indicator).
707          */
708         cgi_item= proto_tree_add_item(ie_tree, hf_bssap_cell_global_id, tvb, offset, ie_len, FALSE);
709         cgi_tree = proto_item_add_subtree(cgi_item, ett_bssap_cgi);
710         /*      octets 3-8 Octets 3 to 8 contain the value part (starting with octet 2) of the
711          *      Routing Area Identification IE defined in 3GPP TS 24.008, not
712          *      including 3GPP TS 24.008 IEI
713          */
714         de_gmm_rai(tvb, cgi_tree, offset, ie_len, NULL, 0);
715         /*      Octets 9 and 10 contain the value part (starting with octet 2) of the
716          *      Cell Identity IE defined in 3GPP TS 24.008, not including
717          *      3GPP TS 24.008 IEI
718          */
719         offset = offset + 6;
720         de_cell_id(tvb, cgi_tree, offset, ie_len, NULL, 0);
721         offset = offset + 2;
722
723         return offset;
724
725 }
726 /* 18.4.2 Channel needed */
727 static int
728 dissect_bssap_channel_needed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
729 {
730     proto_item  *item = NULL;
731     proto_tree  *ie_tree = NULL;
732         guint8 ie_len;
733         
734         ie_len = tvb_get_guint8(tvb,offset+1);
735         item = proto_tree_add_item(tree, hf_bssap_channel_needed_ie, tvb, offset, ie_len+2, FALSE);
736         ie_tree = proto_item_add_subtree(item, ett_bssap_channel_needed);
737
738         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
739         offset++;
740         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
741         offset++;
742         /*
743          * The rest of the information element is coded as the IEI part and the
744          * value part of the Channel Needed IE defined in 3GPP TS 44.018.
745          * 10.5.2.8 Channel Needed
746          */
747         de_rr_chnl_needed(tvb, ie_tree, offset, ie_len, NULL, 0);
748
749         return offset + ie_len;
750
751 }
752 /* 18.4.3 Downlink Tunnel Payload Control and Info */
753 static int
754 dissect_bssap_dlink_tunnel_paylod_control_and_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
755 {
756     proto_item  *item = NULL;
757     proto_tree  *ie_tree = NULL;
758         guint8 ie_len;
759         
760         ie_len = tvb_get_guint8(tvb,offset+1);
761         item = proto_tree_add_item(tree, hf_bssap_dlink_tnl_pld_cntrl_amd_inf_ie, tvb, offset, ie_len+2, FALSE);
762         ie_tree = proto_item_add_subtree(item, ett_bssap_dlink_tnl_pld_cntrl_amd_inf);
763
764         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
765         offset++;
766         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
767         offset++;
768         /* Bit 8 Spare */
769         /* Bit 7 - 4
770          * TOM Protocol Discriminator: Identifies the protocol using tunnelling of non-GSM signalling.
771          * For coding, see 3GPP TS 44.064.
772          */
773         /* Bit 3
774          * E: Cipher Request. When set to 1 indicates that the SGSN shall cipher the payload, when
775          * set to 0 indicates that the SGSN shall not cipher the payload.
776          */
777         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_data, tvb, offset, ie_len, FALSE);
778
779
780         return offset + ie_len;
781
782 }
783
784 /* 18.4.4 eMLPP Priority */
785 /* Call priority */
786 static const value_string bssap_call_priority_values[] = { 
787     { 0x00,             "No priority applied" },
788     { 0x01,             "Call priority level 4" }, 
789     { 0x02,             "Call priority level 3" },       
790     { 0x03,             "Call priority level 2" },       
791     { 0x04,             "Call priority level 1" },       
792     { 0x05,             "Call priority level 0" },       
793     { 0x06,             "Call priority level B" },       
794     { 0x07,             "Call priority level A" },       
795     { 0,                NULL } 
796 };
797 static int
798 dissect_bssap_emlpp_priority(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
799 {
800     proto_item  *item = NULL;
801     proto_tree  *ie_tree = NULL;
802         guint8 ie_len;
803         
804         ie_len = tvb_get_guint8(tvb,offset+1);
805         item = proto_tree_add_item(tree, hf_bssap_emlpp_prio_ie, tvb, offset, ie_len+2, FALSE);
806         ie_tree = proto_item_add_subtree(item, ett_bssap_emlpp_prio);
807
808         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
809         offset++;
810         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
811         offset++;
812         /*      The rest of the information element is coded as the value part of
813                 the eMLPP-Priority IE defined in 3GPP TS 48.008 (not including
814                 3GPP TS 48.008 IEI and 3GPP TS 48.008 length indicator).
815                 3.2.2.56 eMLPP Priority
816                 The call priority field (bit 3 to 1 of octet 2) is coded in the same way 
817                 as the call priority field (bit 3 to 1 of octet 5) in the Descriptive group
818                 or broadcast call reference information element as defined in 3GPP TS 24.008.
819          */
820         proto_tree_add_item(ie_tree, hf_bssap_call_priority, tvb, offset, ie_len, FALSE);
821
822         return offset + ie_len;
823
824 }
825 /* 18.4.5 Erroneous message */
826         /* Erroneous message including the message type. */
827
828 static int
829 dissect_bssap_gprs_erroneous_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
830 {
831     proto_item  *item = NULL;
832     proto_tree  *ie_tree = NULL;
833         guint8 ie_len;
834         
835         ie_len = tvb_get_guint8(tvb,offset+1);
836         item = proto_tree_add_item(tree, hf_bssap_gprs_erroneous_msg_ie, tvb, offset, ie_len+2, FALSE);
837         ie_tree = proto_item_add_subtree(item, ett_bssap_erroneous_msg);
838
839         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
840         offset++;
841         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
842         offset++;
843
844         /* Erroneous message including the message type. */
845         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_data, tvb, offset, ie_len, FALSE);
846
847         return offset + ie_len;
848
849 }
850
851
852 static const value_string bssap_plus_GPRS_loc_upd_type_values[] = { 
853     { 0x00,             "Shall not be sent in this version of the protocol. If received, shall be treated as '00000010'." },
854     { 0x01,             "IMSI attach" }, 
855     { 0x02,             "Normal location update" },      
856     { 0,                NULL } 
857 }; 
858 /* 18.4.6 GPRS location update type */
859 static int
860 dissect_bssap_gprs_location_update_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
861 {
862     proto_item  *item = NULL;
863     proto_tree  *ie_tree = NULL;
864         guint8 ie_len;
865         
866         ie_len = tvb_get_guint8(tvb,offset+1);
867         item = proto_tree_add_item(tree, hf_bssap_gprs_loc_upd_type_ie, tvb, offset, ie_len+2, FALSE);
868         ie_tree = proto_item_add_subtree(item, ett_bssap_gprs_loc_upd);
869
870         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
871         offset++;
872         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
873         offset++;
874         
875         /* GPRS location update type value (octet 3) */
876         proto_tree_add_item(ie_tree, hf_bssap_gprs_loc_upd_type, tvb, offset, ie_len, FALSE);
877         
878         return offset + ie_len;
879 }
880
881 /* Gs Cause value (octet 3) */
882 static const value_string bssap_Gs_cause_values[] = { 
883
884     { 0x00,             "Normal, unspecified in this version of the protocol." },
885     { 0x01,             "IMSI detached for GPRS services" },
886     { 0x02,             "IMSI detached for GPRS and non-GPRS services" },
887     { 0x03,             "IMSI unknown" },
888     { 0x04,             "IMSI detached for non-GPRS services" },
889     { 0x05,             "IMSI implicitly detached for non-GPRS services" },
890     { 0x06,             "MS unreachable" },
891     { 0x07,             "Message not compatible with the protocol state" },
892     { 0x08,             "Missing mandatory information element" },
893     { 0x09,             "Invalid mandatory information" },
894     { 0x0a,             "Conditional IE error" },
895     { 0x0b,             "Semantically incorrect message" },
896     { 0x0c,             "Message unknown" },
897     { 0x0d,             "Address error" },
898     { 0x0e,             "TOM functionality not supported" },
899     { 0x0f,             "Ciphering request cannot be accommodated" },
900     { 0,                NULL } 
901 }; 
902
903 /* 18.4.7 Gs cause */
904 static int
905 dissect_bssap_Gs_cause(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
906 {
907     proto_item  *item = NULL;
908     proto_tree  *ie_tree = NULL;
909         guint8 ie_len;
910         
911         ie_len = tvb_get_guint8(tvb,offset+1);
912         item = proto_tree_add_item(tree, hf_bssap_Gs_cause_ie, tvb, offset, ie_len+2, FALSE);
913         ie_tree = proto_item_add_subtree(item, ett_bassp_Gs_cause);
914
915         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
916         offset++;
917         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
918         offset++;
919         /* Gs Cause value (octet 3) */
920         proto_tree_add_item(ie_tree, hf_bssap_Gs_cause, tvb, offset, ie_len, FALSE);
921
922
923         return offset + ie_len;
924
925 }
926 /* 18.4.8 IMEI */
927 static int
928 dissect_bssap_imei(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
929 {
930     proto_item  *item = NULL;
931     proto_tree  *ie_tree = NULL;
932         guint8 ie_len;
933         tvbuff_t *ie_tvb;
934         char *digit_str;
935
936         ie_len = tvb_get_guint8(tvb,offset+1);
937         item = proto_tree_add_item(tree, hf_bssap_imei_ie, tvb, offset, ie_len+2, FALSE);
938         ie_tree = proto_item_add_subtree(item, ett_bassp_imei);
939
940         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
941         offset++;
942         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
943         offset++;
944         /* The IMEI is coded as a sequence of BCD digits, compressed two into each octet.
945          * The IMEI consists of 15 digits (see 3GPP TS 23.003).
946          */
947         ie_tvb = tvb_new_subset(tvb, offset, ie_len, ie_len);
948         digit_str = unpack_digits(ie_tvb, 0, &Dgt1_9_bcd, FALSE);
949         proto_tree_add_string(ie_tree, hf_bssap_imei, ie_tvb, 0, -1, digit_str);
950
951         return offset + ie_len;
952
953 }
954 /* 18.4.9 IMEISV */
955 static int
956 dissect_bssap_imesiv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
957 {
958     proto_item  *item = NULL;
959     proto_tree  *ie_tree = NULL;
960         guint8 ie_len;
961         tvbuff_t *ie_tvb;
962         char *digit_str;
963         
964         ie_len = tvb_get_guint8(tvb,offset+1);
965         item = proto_tree_add_item(tree, hf_bssap_imesiv_ie, tvb, offset, ie_len+2, FALSE);
966         ie_tree = proto_item_add_subtree(item, ett_bassp_imesiv);
967
968         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
969         offset++;
970         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
971         offset++;
972         /*      The IMEISV is coded as a sequence of BCD digits, compressed two into each octet.
973          *      The IMEISV consists of 16 digits (see 3GPP TS 23.003).
974          */
975         ie_tvb = tvb_new_subset(tvb, offset, ie_len, ie_len);
976         digit_str = unpack_digits(ie_tvb, 0, &Dgt1_9_bcd, FALSE);
977         proto_tree_add_string(ie_tree, hf_bssap_imeisv, ie_tvb, 0, -1, digit_str);
978
979         return offset + ie_len;
980
981 }
982 /* 18.4.10 IMSI 
983  * The IMSI is coded as a sequence of BCD digits, compressed two into each octet. 
984  * This is a variable length element, and includes a length indicator.
985  * The IMSI is defined in 3GPP TS 23.003. It shall not exceed 15 digits (see 3GPP TS 23.003).
986  */
987
988
989 static int
990 dissect_bssap_imsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
991 {
992     proto_item  *item = NULL;
993     proto_tree  *ie_tree = NULL;
994         guint8 ie_len;
995         tvbuff_t *ie_tvb;
996         char *digit_str;
997         
998         ie_len = tvb_get_guint8(tvb,offset+1);
999         item = proto_tree_add_item(tree, hf_bssap_imsi_ie, tvb, offset, ie_len+2, FALSE);
1000         ie_tree = proto_item_add_subtree(item, ett_bssap_imsi);
1001
1002         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1003         offset++;
1004         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1005         offset++;
1006         ie_tvb = tvb_new_subset(tvb, offset, ie_len,ie_len);
1007         digit_str = unpack_digits(ie_tvb, 0, &Dgt1_9_bcd, TRUE);
1008         proto_tree_add_string(ie_tree, hf_bssap_imsi, ie_tvb, 0, -1, digit_str);
1009         
1010         return offset + ie_len;
1011
1012 }
1013 static const value_string bssap_imsi_det_from_gprs_serv_type_values[] = { 
1014     { 0x00,             "Interpreted as reserved in this version of the protocol" },
1015     { 0x01,             "Network initiated IMSI detach from GPRS service" }, 
1016     { 0x02,             "MS initiated IMSI detach from GPRS service" },
1017     { 0x03,             "GPRS services not allowed" },
1018     { 0,                NULL } 
1019 }; 
1020
1021 /* 18.4.11 IMSI detach from GPRS service type */
1022 static int
1023 dissect_bssap_imsi_det_from_gprs_serv_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1024 {
1025     proto_item  *item = NULL;
1026     proto_tree  *ie_tree = NULL;
1027         guint8 ie_len;
1028         
1029         ie_len = tvb_get_guint8(tvb,offset+1);
1030         item = proto_tree_add_item(tree, hf_bssap_imsi_det_from_gprs_serv_type_ie, tvb, offset, ie_len+2, FALSE);
1031         ie_tree = proto_item_add_subtree(item, ett_bssap_imsi_det_from_gprs_serv_type);
1032
1033         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1034         offset++;
1035         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1036         offset++;
1037         /* IMSI detach from GPRS service type value (octet 3)*/
1038         proto_tree_add_item(ie_tree, hf_bssap_imsi_det_from_gprs_serv_type, tvb, offset, ie_len, FALSE);
1039
1040
1041         return offset + ie_len;
1042
1043 }
1044 /* 18.4.12 IMSI detach from non-GPRS service type */
1045 static int
1046 dissect_bssap_imsi_det_from_non_gprs_serv_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1047 {
1048     proto_item  *item = NULL;
1049     proto_tree  *ie_tree = NULL;
1050         guint8 ie_len;
1051         
1052         ie_len = tvb_get_guint8(tvb,offset+1);
1053         item = proto_tree_add_item(tree, hf_bssap_imsi_det_from_non_gprs_serv_type_ie, tvb, offset, ie_len+2, FALSE);
1054         ie_tree = proto_item_add_subtree(item, ett_bssap_imsi_det_from_non_gprs_serv_type);
1055
1056         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1057         offset++;
1058         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1059         offset++;
1060         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_data, tvb, offset, ie_len, FALSE);
1061
1062
1063         return offset + ie_len;
1064
1065 }
1066 static const value_string bssap_info_req_values[] = { 
1067     { 0x00,             "Interpreted as Not supported in this version of the protocol." },
1068     { 0x01,             "PTMSI" }, 
1069     { 0x02,             "IMEI" },
1070     { 0x03,             "IMEISV" },
1071     { 0x04,             "PTMSI and IMEI" },
1072     { 0x05,             "PTMSI and IMEISV" },
1073     { 0x06,             "IMEI and IMEISV" },
1074     { 0x07,             "PTMSI, IMEI, and IMEISV" },
1075     { 0x08,             "Mobile location information" },
1076     { 0x09,             "TMSI" },
1077     { 0,                NULL } 
1078 }; 
1079 /* 18.4.13 Information requested */
1080 static int
1081 dissect_bssap_info_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1082 {
1083     proto_item  *item = NULL;
1084     proto_tree  *ie_tree = NULL;
1085         guint8 ie_len;
1086         
1087         ie_len = tvb_get_guint8(tvb,offset+1);
1088         item = proto_tree_add_item(tree, hf_bssap_info_req_ie, tvb, offset, ie_len+2, FALSE);
1089         ie_tree = proto_item_add_subtree(item, ett_bssap_info_req);
1090
1091         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1092         offset++;
1093         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1094         offset++;
1095         /*Information requested value (octet 3) */
1096         proto_tree_add_item(ie_tree, hf_bssap_info_req, tvb, offset, ie_len, FALSE);
1097
1098
1099         return offset + ie_len;
1100
1101 }
1102 /* 18.4.14 Location area identifier */
1103 static int
1104 dissect_bssap_loc_area_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1105 {
1106     proto_item  *item = NULL;
1107     proto_tree  *ie_tree = NULL;
1108         guint8 ie_len;
1109         
1110         ie_len = tvb_get_guint8(tvb,offset+1);
1111         item = proto_tree_add_item(tree, hf_bssap_loc_area_id_ie, tvb, offset, ie_len+2, FALSE);
1112         ie_tree = proto_item_add_subtree(item, ett_bssap_loc_area_id);
1113
1114         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1115         offset++;
1116         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1117         offset++;
1118         /*      The rest of the information element is coded as the value part of
1119          *      the location area identifier IE defined in 3GPP TS 48.018 (not
1120          *      including 3GPP TS 48.018 IEI and 3GPP TS 48.018 length
1121          *      indicator).
1122          */
1123         de_lai(tvb, ie_tree, offset, ie_len, NULL, 0);
1124
1125         return offset + ie_len;
1126
1127 }
1128 /* 18.4.15 Location information age */
1129 static int
1130 dissect_bssap_loaction_information_age(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1131 {
1132     proto_item  *item = NULL;
1133     proto_tree  *ie_tree = NULL;
1134         guint8 ie_len;
1135         
1136         ie_len = tvb_get_guint8(tvb,offset+1);
1137         item = proto_tree_add_item(tree, hf_bssap_loc_inf_age_ie, tvb, offset, ie_len+2, FALSE);
1138         ie_tree = proto_item_add_subtree(item, ett_bssap_loc_inf_age);
1139
1140         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1141         offset++;
1142         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1143         offset++;
1144         /* The rest of the IE is coded as the value part of the
1145          * AgeOfLocationInformation as specified in 3GPP TS 29.002.:
1146          *   AgeOfLocationInformation ::= INTEGER (0..32767)
1147          * -- the value represents the elapsed time in minutes since the last
1148          * -- network contact of the mobile station (i.e. the actuality of the
1149          * -- location information).
1150          * -- value '0' indicates that the MS is currently in contact with the
1151          * -- network
1152          * -- value '32767' indicates that the location information is at least
1153          * -- 32767 minutes old
1154          */
1155         proto_tree_add_item(ie_tree, hf_bssap_loc_inf_age, tvb, offset, ie_len, FALSE);
1156
1157
1158         return offset + ie_len;
1159
1160 }
1161 /* 18.4.16 MM information */
1162 static int
1163 dissect_bssap_MM_information(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1164 {
1165     proto_item  *item = NULL;
1166     proto_tree  *ie_tree = NULL;
1167         guint8 ie_len;
1168         
1169         ie_len = tvb_get_guint8(tvb,offset+1);
1170         item = proto_tree_add_item(tree, hf_bssap_mm_information_ie, tvb, offset, ie_len+2, FALSE);
1171         ie_tree = proto_item_add_subtree(item, ett_bssap_mm_information);
1172
1173         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1174         offset++;
1175         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1176         offset++;
1177         /* User information: This field is composed of one or more of the
1178          *      information elements of the MM information message as defined
1179          *      3GPP TS 24.008, excluding the Protocol discriminator, Skip
1180          *      indicator and Message type. This field includes the IEI and length
1181          *      indicatior of the other information elements.
1182          */
1183         dtap_mm_mm_info(tvb, ie_tree, offset, ie_len);
1184         
1185
1186         return offset + ie_len;
1187
1188 }
1189 /* 18.4.17 Mobile identity */
1190 static int
1191 dissect_bssap_mobile_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1192 {
1193     proto_item  *item = NULL;
1194     proto_tree  *ie_tree = NULL;
1195         guint ie_len;
1196         
1197         ie_len = tvb_get_guint8(tvb,offset+1);
1198         item = proto_tree_add_item(tree, hf_bssap_mobile_id_ie, tvb, offset, ie_len+2, FALSE);
1199         ie_tree = proto_item_add_subtree(item, ett_bssap_mobile_id);
1200
1201         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1202         offset++;
1203         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1204         offset++;
1205         /*      The rest of the information element is coded as the value part of
1206          *      the mobile identity IE defined in 3GPP TS 24.008 (not including
1207          *      3GPP TS 24.008 IEI and 3GPP TS 24.008 length indicator).
1208          */
1209         de_mid(tvb, ie_tree, offset, ie_len, NULL, 0);
1210
1211
1212         return offset + ie_len;
1213
1214 }
1215 /* 18.4.18 Mobile station classmark 1 */
1216 static int
1217 dissect_bssap_mobile_stn_cls_mrk1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1218 {
1219     proto_item  *item = NULL;
1220     proto_tree  *ie_tree = NULL;
1221         guint8 ie_len;
1222         
1223         ie_len = tvb_get_guint8(tvb,offset+1);
1224         item = proto_tree_add_item(tree, hf_bssap_mobile_stn_cls_mrk1_ie, tvb, offset, ie_len+2, FALSE);
1225         ie_tree = proto_item_add_subtree(item, ett_bssap_mobile_stn_cls_mrk1);
1226
1227         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1228         offset++;
1229         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1230         offset++;
1231         /*      The rest of the information element is coded as the value part of
1232          *      the mobile station classmark 1 IE defined in 3GPP TS 24.008 (not
1233          *      including 3GPP TS 24.008 IEI)
1234          */
1235         de_ms_cm_1(tvb, ie_tree, offset, ie_len, NULL, 0);
1236
1237         return offset + ie_len;
1238
1239 }
1240 /* 18.4.19 Mobile station state */
1241 static const value_string bssap_mobile_station_state_values[] = { 
1242     { 0x00,             "IDLE or PMM-DETACHED" },
1243     { 0x01,             "STANDBY or PMM-IDLE, 0 PDP contexts active" }, 
1244     { 0x02,             "STANDBY or PMM-IDLE, 1 or more PDP contexts active" },
1245     { 0x03,             "SUSPENDED, 0 PDP contexts active" },
1246     { 0x04,             "SUSPENDED, 1 or more PDP contexts active" },
1247     { 0x05,             "READY or PMM-CONNECTED, 0 PDP contexts active" },
1248     { 0x06,             "READY or PMM-CONNECTED, 1 or more PDP contexts active" },
1249     { 0x07,             "IMSI unknown" },
1250     { 0x08,             "Information requested not supported" },
1251     { 0,                NULL } 
1252 };
1253 static int
1254 dissect_bssap_mobile_station_state(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1255 {
1256     proto_item  *item = NULL;
1257     proto_tree  *ie_tree = NULL;
1258         guint8 ie_len;
1259         
1260         ie_len = tvb_get_guint8(tvb,offset+1);
1261         item = proto_tree_add_item(tree, hf_bssap_mobile_station_state_ie, tvb, offset, ie_len+2, FALSE);
1262         ie_tree = proto_item_add_subtree(item, ett_bssap_mobile_station_state);
1263
1264         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1265         offset++;
1266         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1267         offset++;
1268         /* Mobile station state value (octet 3) */
1269         proto_tree_add_item(ie_tree, hf_bssap_mobile_station_state, tvb, offset, ie_len, FALSE);
1270
1271         return offset + ie_len;
1272
1273 }
1274 /* 18.4.20 PTMSI */
1275 static int
1276 dissect_bssap_ptmsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1277 {
1278     proto_item  *item = NULL;
1279     proto_tree  *ie_tree = NULL;
1280         guint8 ie_len;
1281         
1282         ie_len = tvb_get_guint8(tvb,offset+1);
1283         item = proto_tree_add_item(tree, hf_bssap_ptmsi_ie, tvb, offset, ie_len+2, FALSE);
1284         ie_tree = proto_item_add_subtree(item, ett_bssap_ptmsi);
1285
1286         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1287         offset++;
1288         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1289         offset++;
1290         /* The PTMSI consists of 4 octets. It can be coded using a full hexadecimal representation
1291          * (see 3GPP TS 23.003).
1292          */
1293         proto_tree_add_item(ie_tree, hf_bssap_ptmsi, tvb, offset, ie_len, FALSE);
1294
1295         return offset + ie_len;
1296
1297 }
1298 /* 18.4.21 Reject cause */
1299 static int
1300 dissect_bssap_reject_cause(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1301 {
1302     proto_item  *item = NULL;
1303     proto_tree  *ie_tree = NULL;
1304         guint8 ie_len;
1305         
1306         ie_len = tvb_get_guint8(tvb,offset+1);
1307         item = proto_tree_add_item(tree, hf_bssap_reject_cause_ie, tvb, offset, ie_len+2, FALSE);
1308         ie_tree = proto_item_add_subtree(item, ett_bssap_reject_cause);
1309
1310         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1311         offset++;
1312         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1313         offset++;
1314         /*      The rest of the information element is coded as the value part of
1315          *      the reject cause IE defined in 3GPP TS 24.008, not including
1316          *      3GPP TS 24.008 IEI.
1317          */
1318         de_rej_cause(tvb, ie_tree, offset, ie_len, NULL, 0);
1319
1320         return offset + ie_len;
1321
1322 }
1323
1324 /* 18.4.21b Service Area Identification */
1325 static int
1326 dissect_bssap_service_area_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1327 {
1328     proto_item  *item = NULL;
1329     proto_tree  *ie_tree = NULL;
1330         guint8 ie_len;
1331         
1332         ie_len = tvb_get_guint8(tvb,offset+1);
1333         item = proto_tree_add_item(tree, hf_bssap_service_area_id_ie, tvb, offset, ie_len+2, FALSE);
1334         ie_tree = proto_item_add_subtree(item, ett_bssap_service_area_id);
1335
1336         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1337         offset++;
1338         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1339         offset++;
1340         /*      The rest of the information element is coded as the the value part
1341          *      of the SAI IE defined in 3GPP TS 25.413 (not including
1342          *      3GPP TS 25.413 IEI and 3GPP TS 25.413 length indicator).
1343          */
1344         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_data, tvb, offset, ie_len, FALSE);
1345
1346         return offset + ie_len;
1347
1348 }
1349
1350 /* 18.4.22 SGSN number */
1351
1352 static const true_false_string bssap_extension_value = {
1353   "No Extension",
1354   "Extension"
1355 };
1356
1357 static int
1358 dissect_bssap_sgsn_number(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1359 {
1360     proto_item  *item = NULL;
1361     proto_tree  *ie_tree = NULL;
1362         guint8 ie_len;
1363         tvbuff_t *number_tvb;
1364         char *digit_str;
1365         
1366         ie_len = tvb_get_guint8(tvb,offset+1);
1367         item = proto_tree_add_item(tree, hf_bssap_sgsn_nr_ie, tvb, offset, ie_len+2, FALSE);
1368         ie_tree = proto_item_add_subtree(item, ett_bssap_sgsn_nr);
1369
1370         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1371         offset++;
1372         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1373         offset++;
1374         /* The SGSN number is coded as a sequence of TBCD digits (as specified in 3GPP TS 29.002), 
1375          * compressed two into each octet. The Number is in international E.164 format as indicated by Octet 3
1376          * which coding is specified in 3GPP TS 29.002. This is a variable length information element, 
1377          * and includes a length indicator. The value part of the SGSN number information element 
1378          * (not including IEI, Length indicator and Octet 3) shall not exceed 15 digits.
1379          */
1380         proto_tree_add_item(ie_tree, hf_bssap_extension, tvb, offset, 1, FALSE);
1381         proto_tree_add_item(ie_tree, hf_bssap_type_of_number, tvb, offset, 1, FALSE);
1382         proto_tree_add_item(ie_tree, hf_bssap_numbering_plan_id, tvb, offset, 1, FALSE);
1383         offset++;
1384         number_tvb = tvb_new_subset(tvb, offset, ie_len-1,ie_len-1);
1385         digit_str = unpack_digits(number_tvb, 0, &Dgt1_9_bcd, FALSE);
1386         proto_tree_add_string(ie_tree, hf_bssap_sgsn_number, number_tvb, 0, -1, digit_str);
1387
1388
1389         return offset + ie_len-1;
1390
1391 }
1392 /* 18.4.23 TMSI */
1393 static int
1394 dissect_bssap_tmsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1395 {
1396     proto_item  *item = NULL;
1397     proto_tree  *ie_tree = NULL;
1398         guint8 ie_len;
1399         
1400         ie_len = tvb_get_guint8(tvb,offset+1);
1401         item = proto_tree_add_item(tree, hf_bssap_tmsi_ie, tvb, offset, ie_len+2, FALSE);
1402         ie_tree = proto_item_add_subtree(item, ett_bssap_tmsi);
1403
1404         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1405         offset++;
1406         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1407         offset++;
1408         /* The TMSI consists of 4 octets. It can be coded using a full hexadecimal representation 
1409          * (see 3GPP TS 23.003).
1410          */
1411         proto_tree_add_item(ie_tree, hf_bssap_tmsi, tvb, offset, ie_len, FALSE);
1412
1413
1414         return offset + ie_len;
1415
1416 }
1417
1418 /* 18.4.24 TMSI status */
1419 static const true_false_string bssap_tmsi_flag = {
1420   "Valid TMSI available",
1421   "No valid TMSI available"
1422 };
1423 static int
1424 dissect_bssap_tmsi_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1425 {
1426     proto_item  *item = NULL;
1427     proto_tree  *ie_tree = NULL;
1428         guint8 ie_len;
1429         
1430         ie_len = tvb_get_guint8(tvb,offset+1);
1431         item = proto_tree_add_item(tree, hf_bssap_tmsi_status_ie, tvb, offset, ie_len+2, FALSE);
1432         ie_tree = proto_item_add_subtree(item, ett_bssap_tmsi_status);
1433
1434         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1435         offset++;
1436         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1437         offset++;
1438         /* TMSI flag (octet 3) */
1439         proto_tree_add_item(ie_tree, hf_bssap_tmsi_status, tvb, offset, ie_len, FALSE);
1440
1441
1442         return offset + ie_len;
1443
1444 }
1445 /* 18.4.25 Uplink Tunnel Payload Control and Info */
1446 static const true_false_string bssap_E_flag = {
1447   "SGSN received the payload in ciphered",
1448   "SGSN did not receive the payload in ciphered form"
1449 };
1450 /* 3GPP TS 44.064 B.1.1 TOM Protocol Discriminator */
1451 static const value_string bssap_tom_prot_disc_values[] = { 
1452     { 0x00,             "Not specified" },
1453     { 0x01,             "TIA/EIA-136" }, 
1454     { 0x02,             "RRLP" },
1455     { 0x03,             "Reserved for extension" },
1456     { 0,                NULL } 
1457 };
1458 static int
1459 dissect_bssap_ulink_tunnel_paylod_control_and_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1460 {
1461     proto_item  *item = NULL;
1462     proto_tree  *ie_tree = NULL;
1463         guint8 ie_len;
1464         
1465         ie_len = tvb_get_guint8(tvb,offset+1);
1466         item = proto_tree_add_item(tree, hf_bssap_ulink_tnl_pld_cntrl_amd_inf_ie, tvb, offset, ie_len+2, FALSE);
1467         ie_tree = proto_item_add_subtree(item, ett_bssap_ulink_tnl_pld_cntrl_amd_inf);
1468
1469         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1470         offset++;
1471         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1472         offset++;
1473         /* octet 3 bit 8 Spare */
1474         /* octet 3 bit 7 - 4 
1475          * TOM Protocol Discriminator: Identifies the protocol using tunnelling of non-GSM signalling.
1476          * For coding, see 3GPP TS 44.064.
1477          */
1478         proto_tree_add_item(ie_tree, hf_bssap_tom_prot_disc, tvb, offset, 1, FALSE);
1479
1480         /* octet 3 bit 3 E: Cipher Request. When set to 1 indicates that the SGSN received the payload in ciphered form,
1481          * when set to 0 indicates that the SGSN did not receive the payload in ciphered form.
1482          */
1483         proto_tree_add_item(ie_tree, hf_bssap_e_bit, tvb, offset, 1, FALSE);
1484
1485         /* octet 3 bit 2 - 1 
1486          * Tunnel Priority: Indicates the priority of the Tunnel Payload. For coding, see Table 20.1: Association
1487          * between Tunnel Priority and LLC SAPs.
1488          */
1489         proto_tree_add_item(ie_tree, hf_bssap_tunnel_prio, tvb, offset, 1, FALSE);
1490
1491         return offset + ie_len;
1492
1493 }
1494
1495 /* 18.4.26 VLR number */
1496 static int
1497 dissect_bssap_vlr_number(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1498 {
1499     proto_item  *item = NULL;
1500     proto_tree  *ie_tree = NULL;
1501         guint8 ie_len;
1502         tvbuff_t *number_tvb;
1503         char *digit_str;
1504         
1505         ie_len = tvb_get_guint8(tvb,offset+1);
1506         item = proto_tree_add_item(tree, hf_bssap_vlr_number_ie, tvb, offset, ie_len+2, FALSE);
1507         ie_tree = proto_item_add_subtree(item, ett_bssap_vlr_number);
1508
1509         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1510         offset++;
1511         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1512         offset++;
1513         /*      The VLR number is coded as a sequence of TBCD digits (as specified in 3GPP TS 29.002), 
1514          *      compressed two into each octet. The Number is in international E.164 format as indicated by Octet 3
1515          *      which coding is specified in 3GPP TS 29.002. This is a variable length information element,
1516          *      and includes a length indicator. The value part of the VLR number information element
1517          *      (not including IEI, length indicator and Octet 3), shall not exceed 15 digits.
1518          */
1519
1520         proto_tree_add_item(ie_tree, hf_bssap_extension, tvb, offset, 1, FALSE);
1521         proto_tree_add_item(ie_tree, hf_bssap_type_of_number, tvb, offset, 1, FALSE);
1522         proto_tree_add_item(ie_tree, hf_bssap_numbering_plan_id, tvb, offset, 1, FALSE);
1523         offset++;
1524         number_tvb = tvb_new_subset(tvb, offset, ie_len-1,ie_len-1);
1525         digit_str = unpack_digits(number_tvb, 0, &Dgt1_9_bcd, FALSE);
1526         proto_tree_add_string(ie_tree, hf_bssap_sgsn_number, number_tvb, 0, -1, digit_str);
1527
1528         return offset + ie_len-1;
1529
1530 }
1531 /* 18.4.27 Global CN-Id */
1532 static int
1533 dissect_bssap_global_cn_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1534 {
1535     proto_item  *item = NULL;
1536     proto_tree  *ie_tree = NULL;
1537     proto_item  *plmn_item = NULL;
1538     proto_tree  *plmn_tree = NULL;
1539     proto_item  *global_cn_id_item = NULL;
1540     proto_tree  *global_cn_id_tree = NULL;
1541         guint8 ie_len;
1542         
1543         ie_len = tvb_get_guint8(tvb,offset+1);
1544         item = proto_tree_add_item(tree, hf_bssap_global_cn_id_ie, tvb, offset, ie_len+2, FALSE);
1545         ie_tree = proto_item_add_subtree(item, ett_bssap_global_cn);
1546
1547         proto_tree_add_item(ie_tree, hf_bssap_plus_ie, tvb, offset, 1, FALSE);
1548         offset++;
1549         proto_tree_add_item(ie_tree, hf_bssap_plus_ie_len, tvb, offset, 1, FALSE);
1550         offset++;
1551         /* The Global CN-Id consists of a PLMN-Id and a CN-Id, see 3GPP TS 23.003. 
1552          *      The PLMN-Id consists of MCC and MNC coded according to Location Area Identification
1553          * in 3GPP TS 24.008. The CN-Id is an integer defined by O&M.
1554          * The least significant bit of the CN-Id field is bit 1 of octet 7 and
1555          * the most significant bit is bit 8 of octet 6. If the CN-Id does not fill the field reserved for it,
1556          * the rest of the bits are set to '0'.
1557          */
1558         global_cn_id_item = proto_tree_add_item(ie_tree, hf_bssap_global_cn_id, tvb, offset, ie_len, FALSE);
1559         global_cn_id_tree = proto_item_add_subtree(global_cn_id_item, ett_bssap_global_cn_id);
1560         /* Octet 3 - 5 PLMN-Id Coded as octets 2 to 4 of the Location Area Identification IE,
1561          * defined in 3GPP TS 24.008 (not including 3GPP TS 24.008 IEI and LAC).
1562          */
1563         plmn_item = proto_tree_add_item(global_cn_id_tree, hf_bssap_plmn_id, tvb, offset, 3, FALSE);
1564         plmn_tree = proto_item_add_subtree(plmn_item, ett_bssap_plmn);
1565         dissect_e212_mcc_mnc(tvb, plmn_tree, offset);
1566         offset = offset + 3;
1567
1568         /* Octet 6 - 7 CN-Id (INTEGER 0..4095) */
1569         proto_tree_add_item(global_cn_id_tree, hf_bssap_cn_id, tvb, offset, 2, FALSE);
1570         offset = offset+2;
1571
1572         return offset;
1573
1574 }
1575
1576 static void dissect_bssap_plus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1577 {
1578     proto_item  *bssap_item;
1579     proto_tree  *bssap_tree = NULL;
1580         guint8          message_type;
1581         int                     offset = 0;
1582
1583     /*
1584      * Make entry in the Protocol column on summary display
1585      */
1586     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1587     {
1588         col_set_str(pinfo->cinfo, COL_PROTOCOL, "BSSAP+");
1589     }
1590     /* create the BSSAP+ protocol tree */
1591     bssap_item = proto_tree_add_item(tree, proto_bssap, tvb, 0, -1, FALSE);
1592     bssap_tree = proto_item_add_subtree(bssap_item, ett_bssap);
1593         
1594         message_type = tvb_get_guint8(tvb,offset);
1595         proto_tree_add_item(bssap_tree, hf_bssap_plus_message_type, tvb, offset, 1,FALSE);
1596         offset++;
1597
1598         if (check_col(pinfo->cinfo, COL_INFO)){
1599                 col_set_str(pinfo->cinfo,COL_INFO, val_to_str(message_type,bssap_plus_message_type_values,"Unknown %u"));
1600         }
1601
1602         switch(message_type){
1603         case BSSAP_PAGING_REQUEST:
1604                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1605                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1606                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1607
1608                 /* VLR number VLR number 18.4.26 M TLV 5-11 */ 
1609                 if ( check_ie(tvb, tree, &offset, BSSAP_VLR_NUMBER))
1610                         offset = dissect_bssap_vlr_number(tvb, pinfo, bssap_tree, offset);
1611                 
1612                 /* End of mandatory elements */
1613                 if (tvb_length_remaining(tvb,offset) == 0)
1614                         return;
1615
1616                 /* TMSI TMSI 18.4.23 O TLV 6 */
1617                 if ( check_optional_ie(tvb, tree, offset, BSSAP_TMSI))
1618                         offset = dissect_bssap_tmsi(tvb, pinfo, bssap_tree, offset);
1619                 if (tvb_length_remaining(tvb,offset) == 0)
1620                         return;
1621
1622                 /* Location area identifier Location area identifier 18.4.14 O TLV 7 */
1623                 if ( check_optional_ie(tvb, tree, offset, BSSAP_LOC_AREA_ID))
1624                         offset = dissect_bssap_loc_area_id(tvb, pinfo, bssap_tree, offset);
1625                 if (tvb_length_remaining(tvb,offset) == 0)
1626                         return;
1627
1628                 /* Channel needed Channel needed 18.4.2 O TLV 3 */
1629                 if ( check_optional_ie(tvb, tree, offset, BSSAP_CHANNEL_NEEDED))
1630                         offset = dissect_bssap_channel_needed(tvb, pinfo, bssap_tree, offset);
1631                 if (tvb_length_remaining(tvb,offset) == 0)
1632                         return;
1633
1634                 /* eMLPP Priority eMLPP Priority 18.4.4 O TLV 3 */
1635                 if ( check_optional_ie(tvb, tree, offset, BSSAP_EMLPP_PRIORITY))
1636                         offset = dissect_bssap_emlpp_priority(tvb, pinfo, bssap_tree, offset);
1637                 if (tvb_length_remaining(tvb,offset) == 0)
1638                         return;
1639
1640                 /* Global CN-Id Global CN-Id 18.4.27 O TLV 7 */
1641                 if ( check_optional_ie(tvb, tree, offset, BSSAP_GLOBAL_CN_ID))
1642                         offset = dissect_bssap_global_cn_id(tvb, pinfo, bssap_tree, offset);
1643                 if (tvb_length_remaining(tvb,offset) == 0)
1644                         return;
1645
1646                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1647                 break;
1648         case BSSAP_PAGING_REJECT:                                       /*  17.1.18 */
1649                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1650                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1651                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1652                 /* Gs Cause Gs Cause 18.4.7 M TLV 3 */
1653                 if ( check_ie(tvb, tree, &offset, BSSAP_GS_CAUSE))
1654                         offset = dissect_bssap_Gs_cause(tvb, pinfo, bssap_tree, offset);
1655
1656                 if (tvb_length_remaining(tvb,offset) == 0)
1657                         return;
1658                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1659                 break;
1660         case BSSAP_DOWNLINK_TUNNEL_REQUEST:                     /*  17.1.4  */
1661                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1662                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1663                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1664
1665                 /* VLR number VLR number 18.4.26 M TLV 5-11 */
1666                 if ( check_ie(tvb, tree, &offset, BSSAP_VLR_NUMBER))
1667                         offset = dissect_bssap_vlr_number(tvb, pinfo, bssap_tree, offset);
1668
1669                 /* Downlink Tunnel Payload Control and Info 18.4.3 M TLV 3-223 */ 
1670                 if ( check_ie(tvb, tree, &offset, BSSAP_DLINK_TNL_PLD_CTR_AND_INF))
1671                         offset = dissect_bssap_dlink_tunnel_paylod_control_and_info(tvb, pinfo, bssap_tree, offset);
1672
1673                 if (tvb_length_remaining(tvb,offset) == 0)
1674                         return;
1675                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1676                 break;
1677         case BSSAP_UPLINK_TUNNEL_REQUEST:                       /*  17.1.23 */
1678                 /* SGSN number 18.4.22 M TLV 5-11 */
1679                 if ( check_ie(tvb, tree, &offset, BSSAP_SGSN_NUMBER))
1680                         offset = dissect_bssap_sgsn_number(tvb, pinfo, bssap_tree, offset);
1681
1682                 /* Uplink Tunnel Payload Control and Info 18.4.25 M TLV 3-223 */
1683                 if ( check_ie(tvb, tree, &offset, BSSAP_ULINK_TNL_PLD_CTR_AND_INF))
1684                         offset = dissect_bssap_ulink_tunnel_paylod_control_and_info(tvb, pinfo, bssap_tree, offset);
1685
1686                 if (tvb_length_remaining(tvb,offset) == 0)
1687                         return;
1688                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1689                 break;
1690
1691                 break;
1692         case BSSAP_LOCATION_UPDATE_REQUEST:                     /*  17.1.11 BSSAP+-LOCATION-UPDATE-REQUEST */
1693                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1694                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1695                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1696
1697                 /* SGSN number SGSN number 18.4.22 M TLV 5-11 */
1698                 if ( check_ie(tvb, tree, &offset, BSSAP_SGSN_NUMBER))
1699                         offset = dissect_bssap_sgsn_number(tvb, pinfo, bssap_tree, offset);
1700
1701                 /* Update type GPRS location update type 18.4.6 M TLV 3 */
1702                 if ( check_ie(tvb, tree, &offset, BSSAP_GPRS_LOC_UPD_TYPE))
1703                         offset = dissect_bssap_gprs_location_update_type(tvb, pinfo, bssap_tree, offset);
1704
1705                 /* New Cell global identity Cell global identity 18.4.1 M TLV 10 */
1706                 if ( check_ie(tvb, tree, &offset, BSSAP_CELL_GBL_ID))
1707                         offset = dissect_bssap_cell_global_id(tvb, pinfo, bssap_tree, offset);
1708                 
1709                 /* Mobile station classmark Mobile station classmark 1 18.4.18 M TLV 3 */
1710                 if ( check_ie(tvb, tree, &offset, BSSAP_MOBILE_STN_CLS_MRK1))
1711                         offset = dissect_bssap_mobile_stn_cls_mrk1(tvb, pinfo, bssap_tree, offset);
1712                 if (tvb_length_remaining(tvb,offset) == 0)
1713                         return;
1714                 
1715                 /* Old location area identifier Location area identifier 18.4.14 O TLV 7 */
1716                 if ( check_optional_ie(tvb, tree, offset, BSSAP_LOC_AREA_ID))
1717                         offset = dissect_bssap_loc_area_id(tvb, pinfo, bssap_tree, offset);
1718                 if (tvb_length_remaining(tvb,offset) == 0)
1719                         return;
1720                 
1721                 /* TMSI status TMSI status 18.4.24 O TLV 3 */
1722                 if ( check_optional_ie(tvb, tree, offset, BSSAP_TMSI_STATUS))
1723                         offset = dissect_bssap_tmsi_status(tvb, pinfo, bssap_tree, offset);
1724                 if (tvb_length_remaining(tvb,offset) == 0)
1725                         return;
1726
1727                 /* New service area identification Service area identification 18.4.21b O TLV 9 */
1728                 if ( check_optional_ie(tvb, tree, offset, BSSAP_SERVICE_AREA_ID))
1729                         offset = dissect_bssap_service_area_id(tvb, pinfo, bssap_tree, offset);
1730                 if (tvb_length_remaining(tvb,offset) == 0)
1731                         return;
1732
1733                 /* IMEISV IMEISV 18.4.9 O TLV 10 */
1734                 if ( check_optional_ie(tvb, tree, offset, BSSAP_IMEISV))
1735                         offset = dissect_bssap_imesiv(tvb, pinfo, bssap_tree, offset);
1736                 if (tvb_length_remaining(tvb,offset) == 0)
1737                         return;
1738                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1739                 break;
1740         case BSSAP_LOCATION_UPDATE_ACCEPT:                      /*  17.1.9  */
1741                 /* IMSI 18.4.10 M TLV 6-10 */
1742                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1743                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1744
1745                 /* Location area identifier Location area identifier 18.4.14 M TLV 7 */
1746                 if ( check_ie(tvb, tree, &offset, BSSAP_LOC_AREA_ID))
1747                         offset = dissect_bssap_loc_area_id(tvb, pinfo, bssap_tree, offset);
1748
1749                 if (tvb_length_remaining(tvb,offset) == 0)
1750                         return;
1751
1752                 /* New TMSI, or IMSI Mobile identity 18.4.17 O TLV 6-10 */ 
1753                 if ( check_optional_ie(tvb, tree, offset, BSSAP_MOBILE_ID))
1754                         offset = dissect_bssap_mobile_id(tvb, pinfo, bssap_tree, offset);
1755                 if (tvb_length_remaining(tvb,offset) == 0)
1756                         return;
1757                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1758                 break;
1759         case BSSAP_LOCATION_UPDATE_REJECT:                      /*  17.1.10 */
1760                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1761                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1762                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1763                 /* Reject cause Reject cause 18.4.21 M TLV 3 */
1764                 if ( check_ie(tvb, tree, &offset, BSSAP_REJECT_CAUSE))
1765                         offset = dissect_bssap_reject_cause(tvb, pinfo, bssap_tree, offset);
1766                 if (tvb_length_remaining(tvb,offset) == 0)
1767                         return;
1768                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1769                 break;
1770         case BSSAP_TMSI_REALLOCATION_COMPLETE:          /*  17.1.22 */
1771                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1772                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1773                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1774
1775                 if (tvb_length_remaining(tvb,offset) == 0)
1776                         return;
1777
1778                 /* Cell global identity Cell global identity 18.4.1 O TLV 10 */
1779                 if ( check_optional_ie(tvb, tree, offset, BSSAP_CELL_GBL_ID))
1780                         offset = dissect_bssap_cell_global_id(tvb, pinfo, bssap_tree, offset);
1781
1782                 if (tvb_length_remaining(tvb,offset) == 0)
1783                         return;
1784
1785                 /* Service area identification Service area identification 18.4.21b O TLV 9 */
1786                 if ( check_optional_ie(tvb, tree, offset, BSSAP_SERVICE_AREA_ID))
1787                         offset = dissect_bssap_service_area_id(tvb, pinfo, bssap_tree, offset);
1788                 if (tvb_length_remaining(tvb,offset) == 0)
1789                         return;
1790                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1791                 break;
1792         case BSSAP_ALERT_REQUEST:                                       /*  17.1.3  */
1793                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1794                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1795                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1796
1797                 if (tvb_length_remaining(tvb,offset) == 0)
1798                         return;
1799                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1800                 break;
1801         case BSSAP_ALERT_ACK:                                           /*  17.1.1  */
1802                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1803                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1804                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1805
1806                 if (tvb_length_remaining(tvb,offset) == 0)
1807                         return;
1808                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1809                 break;
1810         case BSSAP_ALERT_REJECT:                                        /*  17.1.2  */
1811                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1812                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1813                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1814
1815                 /* Gs Cause Gs Cause 18.4.7 M TLV 3 */
1816                 if ( check_ie(tvb, tree, &offset, BSSAP_GS_CAUSE))
1817                         offset = dissect_bssap_Gs_cause(tvb, pinfo, bssap_tree, offset);
1818
1819                 if (tvb_length_remaining(tvb,offset) == 0)
1820                         return;
1821                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1822                 break;
1823         case BSSAP_MS_ACTIVITY_INDICATION:                      /*  17.1.14 */
1824                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1825                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1826                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1827
1828                 if (tvb_length_remaining(tvb,offset) == 0)
1829                         return;
1830
1831                 /* Cell global identity Cell global identity 18.4.1 O TLV 10 */
1832                 if ( check_optional_ie(tvb, tree, offset, BSSAP_CELL_GBL_ID))
1833                         offset = dissect_bssap_cell_global_id(tvb, pinfo, bssap_tree, offset);
1834
1835                 if (tvb_length_remaining(tvb,offset) == 0)
1836                         return;
1837
1838                 /* Service area identification Service area identification 18.4.21b O TLV 9 */
1839                 if ( check_optional_ie(tvb, tree, offset, BSSAP_SERVICE_AREA_ID))
1840                         offset = dissect_bssap_service_area_id(tvb, pinfo, bssap_tree, offset);
1841                 if (tvb_length_remaining(tvb,offset) == 0)
1842                         return;
1843                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1844                 break;
1845         case BSSAP_GPRS_DETACH_INDICATION:                      /*  17.1.6  */
1846                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1847                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1848                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1849
1850                 /* SGSN number SGSN number 18.4.22 M TLV 5-11 */
1851                 if ( check_ie(tvb, tree, &offset, BSSAP_SGSN_NUMBER))
1852                         offset = dissect_bssap_sgsn_number(tvb, pinfo, bssap_tree, offset);
1853
1854                 /* IMSI detach from GPRS service type IMSI detach from GPRS service type 18.4.17 M TLV 3 */
1855                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI_DET_FROM_GPRS_SERV_TYPE))
1856                         offset = dissect_bssap_imsi_det_from_gprs_serv_type(tvb, pinfo, bssap_tree, offset);
1857
1858                 if (tvb_length_remaining(tvb,offset) == 0)
1859                         return;
1860
1861                 /* Cell global identity Cell global identity 18.4.1 O TLV 10 */
1862                 if ( check_optional_ie(tvb, tree, offset, BSSAP_CELL_GBL_ID))
1863                         offset = dissect_bssap_cell_global_id(tvb, pinfo, bssap_tree, offset);
1864
1865                 if (tvb_length_remaining(tvb,offset) == 0)
1866                         return;
1867
1868                 /* Service area identification Service area identification 18.4.21b O TLV 9 */
1869                 if ( check_optional_ie(tvb, tree, offset, BSSAP_SERVICE_AREA_ID))
1870                         offset = dissect_bssap_service_area_id(tvb, pinfo, bssap_tree, offset);
1871                 if (tvb_length_remaining(tvb,offset) == 0)
1872                         return;
1873                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1874                 break;
1875         case BSSAP_GPRS_DETACH_ACK:                                     /*  17.1.5  */
1876                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1877                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1878                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1879
1880                 if (tvb_length_remaining(tvb,offset) == 0)
1881                         return;
1882                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1883                 break;
1884         case BSSAP_IMSI_DETACH_INDICATION:                      /*  17.1.8  */
1885                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1886                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1887                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1888
1889                 /* SGSN number SGSN number 18.4.22 M TLV 5-11 */
1890                 if ( check_ie(tvb, tree, &offset, BSSAP_SGSN_NUMBER))
1891                         offset = dissect_bssap_sgsn_number(tvb, pinfo, bssap_tree, offset);
1892
1893                 /* Detach type IMSI detach from non-GPRS service type 18.4.11 M TLV 3 */ 
1894                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI_DET_FROM_NON_GPRS_SERV_TYPE))
1895                         offset = dissect_bssap_imsi_det_from_non_gprs_serv_type(tvb, pinfo, bssap_tree, offset);
1896
1897                 if (tvb_length_remaining(tvb,offset) == 0)
1898                         return;
1899
1900                 /* Cell global identity Cell global identity 18.4.1 O TLV 10 */
1901                 if ( check_optional_ie(tvb, tree, offset, BSSAP_CELL_GBL_ID))
1902                         offset = dissect_bssap_cell_global_id(tvb, pinfo, bssap_tree, offset);
1903
1904                 if (tvb_length_remaining(tvb,offset) == 0)
1905                         return;
1906
1907                 /* Location information age Location information age 18.4.14 O TLV 4 */
1908                 if ( check_optional_ie(tvb, tree, offset, BSSAP_LOC_INF_AGE))
1909                         offset = dissect_bssap_loaction_information_age(tvb, pinfo, bssap_tree, offset);
1910
1911                 if (tvb_length_remaining(tvb,offset) == 0)
1912                         return;
1913
1914                 /* Service area identification Service area identification 18.4.21b O TLV 9 */
1915                 if ( check_optional_ie(tvb, tree, offset, BSSAP_SERVICE_AREA_ID))
1916                         offset = dissect_bssap_service_area_id(tvb, pinfo, bssap_tree, offset);
1917                 if (tvb_length_remaining(tvb,offset) == 0)
1918                         return;
1919                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1920                 break;
1921         case BSSAP_IMSI_DETACH_ACK:                                     /*  17.1.7  */
1922                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1923                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1924                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1925
1926                 if (tvb_length_remaining(tvb,offset) == 0)
1927                         return;
1928                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1929                 break;
1930         case BSSAP_RESET_INDICATION:                            /*  17.1.21 */
1931                 /* Conditional IE:s */
1932                 /* SGSN number SGSN number 18.4.22 C TLV 5-11 */
1933                 if ( check_optional_ie(tvb, tree, offset, BSSAP_SGSN_NUMBER)){
1934                         offset = dissect_bssap_sgsn_number(tvb, pinfo, bssap_tree, offset);
1935                         if (tvb_length_remaining(tvb,offset) == 0)
1936                                 return;
1937                         proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1938                 }else{
1939                         /* VLR number VLR number 18.4.26 C TLV 5-11 */
1940                         if ( check_optional_ie(tvb, tree, offset, BSSAP_VLR_NUMBER)){
1941                                 offset = dissect_bssap_vlr_number(tvb, pinfo, bssap_tree, offset);
1942                                 return;
1943                                 if (tvb_length_remaining(tvb,offset) == 0)
1944                                         return;
1945                                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1946                         }
1947                 }
1948                 proto_tree_add_text(tree, tvb, offset, -1, "Conditional IE");
1949                 break;
1950         case BSSAP_RESET_ACK:                                           /*  17.1.20 */
1951                 /* Conditional IE:s */
1952                 /* SGSN number SGSN number 18.4.22 C TLV 5-11 */
1953                 if ( check_optional_ie(tvb, tree, offset, BSSAP_SGSN_NUMBER)){
1954                         offset = dissect_bssap_sgsn_number(tvb, pinfo, bssap_tree, offset);
1955                         if (tvb_length_remaining(tvb,offset) == 0)
1956                                 return;
1957                         proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1958                 }else{
1959                         /* VLR number VLR number 18.4.26 C TLV 5-11 */
1960                         if ( check_optional_ie(tvb, tree, offset, BSSAP_VLR_NUMBER)){
1961                                 offset = dissect_bssap_vlr_number(tvb, pinfo, bssap_tree, offset);
1962                                 return;
1963                                 if (tvb_length_remaining(tvb,offset) == 0)
1964                                         return;
1965                                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1966                         }
1967                 }
1968                 proto_tree_add_text(tree, tvb, offset, -1, "Conditional IE");
1969                 break;
1970         case BSSAP_MS_INFORMATION_REQUEST:                      /*  17.1.15 */
1971                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1972                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1973                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1974
1975                 /* Information requested Information requested 18.4.13 M TLV 3 */
1976                 if ( check_ie(tvb, tree, &offset, BSSAP_INFO_REQ))
1977                         offset = dissect_bssap_info_req(tvb, pinfo, bssap_tree, offset);
1978
1979                 if (tvb_length_remaining(tvb,offset) == 0)
1980                         return;
1981
1982                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
1983                 break;
1984         case BSSAP_MS_INFORMATION_RESPONSE:                     /*  17.1.16 */
1985                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
1986                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
1987                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
1988                 if (tvb_length_remaining(tvb,offset) == 0)
1989                         return;
1990
1991                 /* TMSI TMSI 18.4.23 O TLV 6 */
1992                 if ( check_optional_ie(tvb, tree, offset, BSSAP_TMSI))
1993                         offset = dissect_bssap_tmsi(tvb, pinfo, bssap_tree, offset);
1994                 if (tvb_length_remaining(tvb,offset) == 0)
1995                         return;
1996
1997                 /* PTMSI PTMSI 18.4.20 O TLV 6 BSSAP_PTMSI*/
1998                 if ( check_optional_ie(tvb, tree, offset, BSSAP_PTMSI))
1999                         offset = dissect_bssap_ptmsi(tvb, pinfo, bssap_tree, offset);
2000                 if (tvb_length_remaining(tvb,offset) == 0)
2001                         return;
2002
2003                 /* IMEI IMEI 18.4.8 O TLV 10 */
2004                 if ( check_optional_ie(tvb, tree, offset, BSSAP_IMEI))
2005                         offset = dissect_bssap_imei(tvb, pinfo, bssap_tree, offset);
2006                 if (tvb_length_remaining(tvb,offset) == 0)
2007                         return;
2008                 /* IMEISV IMEISV 18.4.9 O TLV 10 BSSAP_IMEISV*/
2009                 if ( check_optional_ie(tvb, tree, offset, BSSAP_IMEISV))
2010                         offset = dissect_bssap_imesiv(tvb, pinfo, bssap_tree, offset);
2011                 if (tvb_length_remaining(tvb,offset) == 0)
2012                         return;
2013
2014                 /* Cell global identity Cell global identity 18.4.1 O TLV 10 */
2015                 if ( check_optional_ie(tvb, tree, offset, BSSAP_CELL_GBL_ID))
2016                         offset = dissect_bssap_cell_global_id(tvb, pinfo, bssap_tree, offset);
2017
2018                 if (tvb_length_remaining(tvb,offset) == 0)
2019                         return;
2020                 /* Location information age Location information age 18.4.15 O TLV 4 */
2021                 if ( check_optional_ie(tvb, tree, offset, BSSAP_LOC_INF_AGE))
2022                         offset = dissect_bssap_loaction_information_age(tvb, pinfo, bssap_tree, offset);
2023
2024                 if (tvb_length_remaining(tvb,offset) == 0)
2025                         return;
2026
2027                 /* Mobile station state Mobile station state 18.4.19 O TLV 3 */
2028                 if ( check_optional_ie(tvb, tree, offset, BSSAP_MOBILE_STN_STATE))
2029                         offset = dissect_bssap_mobile_station_state(tvb, pinfo, bssap_tree, offset);
2030
2031                 if (tvb_length_remaining(tvb,offset) == 0)
2032                         return;
2033
2034                 /* Service area identification Service area identification 18.4.21b O TLV 9 */
2035                 if ( check_optional_ie(tvb, tree, offset, BSSAP_SERVICE_AREA_ID))
2036                         offset = dissect_bssap_service_area_id(tvb, pinfo, bssap_tree, offset);
2037                 if (tvb_length_remaining(tvb,offset) == 0)
2038                         return;
2039                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
2040                 break;
2041         case BSSAP_MM_INFORMATION_REQUEST:                      /*  17.1.12 */
2042                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
2043                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
2044                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
2045
2046                 if (tvb_length_remaining(tvb,offset) == 0)
2047                         return;
2048                 /* MM information MM information 18.4.16 O TLV 3-n */
2049                 if ( check_optional_ie(tvb, tree, offset, BSSAP_MM_INFORMATION))
2050                         offset = dissect_bssap_MM_information(tvb, pinfo, bssap_tree, offset);
2051                 if (tvb_length_remaining(tvb,offset) == 0)
2052                         return;
2053                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
2054                 break;
2055         case BSSAP_MOBILE_STATUS:                                       /*  17.1.13 */
2056                 /* IMSI IMSI 18.4.10 O TLV 6-10 */
2057                 if ( check_optional_ie(tvb, tree, offset, BSSAP_MM_INFORMATION))
2058                                 offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
2059                 /* Gs Cause Gs Cause 18.4.7 M TLV 3 */
2060                 if ( check_ie(tvb, tree, &offset, BSSAP_GS_CAUSE))
2061                         offset = dissect_bssap_Gs_cause(tvb, pinfo, bssap_tree, offset);
2062
2063                 /* Erroneous message Erroneous message 18.4.5 M TLV 3-n BSSAP_ERRONEOUS_MSG*/
2064                 if ( check_ie(tvb, tree, &offset, BSSAP_ERRONEOUS_MSG))
2065                         offset = dissect_bssap_gprs_erroneous_msg(tvb, pinfo, bssap_tree, offset);
2066
2067                 if (tvb_length_remaining(tvb,offset) == 0)
2068                         return;
2069                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
2070                 break;
2071         case BSSAP_MS_UNREACHABLE:                                      /*  17.1.17 */
2072                 /* IMSI IMSI 18.4.10 M TLV 6-10 */
2073                 if ( check_ie(tvb, tree, &offset, BSSAP_IMSI))
2074                         offset = dissect_bssap_imsi(tvb, pinfo, bssap_tree, offset);
2075
2076                 /* Gs Cause Gs Cause 18.4.7 M TLV 3 */
2077                 if ( check_ie(tvb, tree, &offset, BSSAP_GS_CAUSE))
2078                         offset = dissect_bssap_Gs_cause(tvb, pinfo, bssap_tree, offset);
2079
2080                 if (tvb_length_remaining(tvb,offset) == 0)
2081                         return;
2082                 proto_tree_add_text(tree, tvb, offset, -1, "Extraneous data");
2083                 break;
2084         default:
2085                 break;
2086         }
2087 }
2088
2089 static gboolean
2090 dissect_bssap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2091 {
2092     /* Is it a BSSAP/BSAP packet?
2093      *    If octet_1 == 0x00 and octet_2 == length(tvb) - 2
2094      * or if octet_1 == 0x01 and octet_3 == length(tvb) - 3
2095      * then we'll assume it is a bssap packet
2096      */
2097     switch (tvb_get_guint8(tvb, 0))
2098     {
2099     case 0x00:
2100         if (tvb_get_guint8(tvb, 1) != (tvb_length(tvb) - 2)) { return(FALSE); }
2101         break;
2102
2103     case 0x01:
2104         if (tvb_get_guint8(tvb, 2) != (tvb_length(tvb) - 3)) { return(FALSE); }
2105         break;
2106
2107     default:
2108         return(FALSE);
2109     }
2110
2111     dissect_bssap(tvb, pinfo, tree);
2112
2113     return(TRUE);
2114 }
2115
2116 /* Register the protocol with Ethereal */
2117 void
2118 proto_register_bssap(void)
2119 {
2120     module_t    *bssap_module;
2121
2122     /* Setup list of header fields */
2123     static hf_register_info hf[] = {
2124         { &hf_bssap_pdu_type,
2125             { "Message Type", "bssap.pdu_type",
2126                 FT_UINT8, BASE_HEX, VALS(bssap_pdu_type_values), 0x0,
2127                 "", HFILL}},
2128         { &hf_bsap_pdu_type,
2129             { "Message Type", "bsap.pdu_type",
2130                 FT_UINT8, BASE_HEX, VALS(bsap_pdu_type_values), 0x0,
2131                 "", HFILL}},
2132         { &hf_bssap_dlci_cc,
2133             { "Control Channel", "bssap.dlci.cc",
2134                 FT_UINT8, BASE_HEX, VALS(bssap_cc_values), CC_MASK,
2135                 "", HFILL}},
2136         { &hf_bsap_dlci_cc,
2137             { "Control Channel", "bsap.dlci.cc",
2138                 FT_UINT8, BASE_HEX, VALS(bsap_cc_values), CC_MASK,
2139                 "", HFILL}},
2140         { &hf_bssap_dlci_spare,
2141             { "Spare", "bssap.dlci.spare",
2142                 FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
2143                 "", HFILL}},
2144         { &hf_bsap_dlci_rsvd,
2145             { "Reserved", "bsap.dlci.rsvd",
2146                 FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
2147                 "", HFILL}},
2148         { &hf_bssap_dlci_sapi,
2149             { "SAPI", "bssap.dlci.sapi",
2150                 FT_UINT8, BASE_HEX, VALS(bssap_sapi_values), SAPI_MASK,
2151                 "", HFILL}},
2152         { &hf_bsap_dlci_sapi,
2153             { "SAPI", "bsap.dlci.sapi",
2154                 FT_UINT8, BASE_HEX, VALS(bsap_sapi_values), SAPI_MASK,
2155                 "", HFILL}},
2156         { &hf_bssap_length,
2157             { "Length", "bssap.length",
2158                 FT_UINT8, BASE_DEC, NULL, 0x0,
2159                 "", HFILL}},
2160
2161         { &hf_bssap_plus_message_type,
2162             { "Message Type", "bssap_plus.msg_type",
2163                 FT_UINT8, BASE_DEC, VALS(bssap_plus_message_type_values), 0x0,
2164                 "Message Type", HFILL}},
2165         { &hf_bssap_plus_ie,
2166             { "IEI", "bssap_plus.iei",
2167                 FT_UINT8, BASE_DEC, VALS(bssap_plus_ie_id_values), 0x0,
2168                 "", HFILL}},
2169         { &hf_bssap_plus_ie_len,
2170             { "Length indicator", "bssap_plus.iei",
2171                 FT_UINT8, BASE_DEC, NULL, 0x0,
2172                 "Length indicator", HFILL}},
2173     { &hf_bssap_extension,
2174       { "Extension", "bssap.extension",
2175         FT_BOOLEAN, 8, TFS(&bssap_extension_value), 0x80,
2176         "Extension", HFILL }},
2177     { &hf_bssap_type_of_number,
2178       { "Type of number", "bssap.type_of_number",
2179         FT_UINT8, BASE_HEX, VALS(gsm_a_type_of_number_values), 0x70,
2180         "Type of number", HFILL }},
2181     { &hf_bssap_numbering_plan_id,
2182       { "Numbering plan identification", "bssap.number_plan",
2183         FT_UINT8, BASE_HEX, VALS(gsm_a_numbering_plan_id_values), 0x0f,
2184         "Numbering plan identification", HFILL }},
2185         { &hf_bssap_sgsn_number,
2186       { "SGSN number", "bssap.sgsn_number",
2187         FT_STRING, BASE_NONE, NULL, 0,
2188         "SGSN number", HFILL }},
2189         { &hf_bssap_vlr_number,
2190       { "VLR number", "bssap.vlr_number",
2191         FT_STRING, BASE_NONE, NULL, 0,
2192         "VLR number", HFILL }},
2193         { &hf_bssap_cell_global_id_ie,
2194       { "Cell global identity IE", "bssap.cell_global_id_ie",
2195         FT_NONE, BASE_NONE, NULL, 0,
2196         "Cell global identity IE", HFILL }},
2197         { &hf_bssap_channel_needed_ie,
2198       { "Channel needed IE", "bssap.cell_global_id_ie",
2199         FT_NONE, BASE_NONE, NULL, 0,
2200         "Channel needed IE", HFILL }},
2201         { &hf_bssap_dlink_tnl_pld_cntrl_amd_inf_ie,
2202       { "Downlink Tunnel Payload Control and Info IE", "bssap.dlink_tnl_pld_cntrl_amd_inf_ie",
2203         FT_NONE, BASE_NONE, NULL, 0,
2204         "Downlink Tunnel Payload Control and Info IE", HFILL }},
2205         { &hf_bssap_ulink_tnl_pld_cntrl_amd_inf_ie,
2206       { "Uplink Tunnel Payload Control and Info IE", "bssap.ulink_tnl_pld_cntrl_amd_inf_ie",
2207         FT_NONE, BASE_NONE, NULL, 0,
2208         "Uplink Tunnel Payload Control and Info IE", HFILL }},
2209         { &hf_bssap_emlpp_prio_ie,
2210       { "eMLPP Priority IE", "bssap.emlpp_prio_ie",
2211         FT_NONE, BASE_NONE, NULL, 0,
2212         "eMLPP Priority IE", HFILL }},
2213         { &hf_bssap_gprs_erroneous_msg_ie,
2214       { "Erroneous message IE", "bssap.erroneous_msg_ie",
2215         FT_NONE, BASE_NONE, NULL, 0,
2216         "Erroneous message IE", HFILL }},
2217         { &hf_bssap_gprs_loc_upd_type_ie,
2218       { "GPRS location update type IE", "bssap.loc_upd_type_ie",
2219         FT_NONE, BASE_NONE, NULL, 0,
2220         "GPRS location update type IE", HFILL }},
2221         { &hf_bssap_Gs_cause_ie,
2222       { "Gs Cause IE", "bssap.Gs_cause_ie",
2223         FT_NONE, BASE_NONE, NULL, 0,
2224         "Gs Cause IE", HFILL }},
2225         { &hf_bssap_imei_ie,
2226       { "IMEI IE", "bssap.imei_ie",
2227         FT_NONE, BASE_NONE, NULL, 0,
2228         "IMEI IE", HFILL }},
2229         { &hf_bssap_imesiv_ie,
2230       { "IMEISV IE", "bssap.imesiv",
2231         FT_NONE, BASE_NONE, NULL, 0,
2232         "IMEISV IE", HFILL }},
2233         { &hf_bssap_imsi_ie,
2234       { "IMSI IE", "bssap.imsi_ie",
2235         FT_NONE, BASE_NONE, NULL, 0,
2236         "IMSI IE", HFILL }},
2237         { &hf_bssap_imsi_det_from_gprs_serv_type_ie,
2238       { "IMSI detach from GPRS service type IE", "bssap.msi_det_from_gprs_serv_type_ie",
2239         FT_NONE, BASE_NONE, NULL, 0,
2240         "IMSI detach from GPRS service type IE", HFILL }},
2241         { &hf_bssap_imsi_det_from_non_gprs_serv_type_ie,
2242       { "IMSI detach from non-GPRS servic IE", "bssap.msi_det_from_non_gprs_serv_type_ie",
2243         FT_NONE, BASE_NONE, NULL, 0,
2244         "IMSI detach from non-GPRS servic IE", HFILL }},
2245         { &hf_bssap_info_req_ie,
2246       { "Information requested IE", "bssap.info_req_ie",
2247         FT_NONE, BASE_NONE, NULL, 0,
2248         "Information requested IE", HFILL }},
2249         { &hf_bssap_loc_area_id_ie,
2250       { "Location area identifier IE", "bssap.loc_area_id_ie",
2251         FT_NONE, BASE_NONE, NULL, 0,
2252         "Location area identifier IE", HFILL }},
2253         { &hf_bssap_loc_inf_age_ie,
2254       { "Location information age IE", "bssap.loc_inf_age",
2255         FT_NONE, BASE_NONE, NULL, 0,
2256         "Location information age IE", HFILL }},
2257         { &hf_bssap_mm_information_ie,
2258       { "MM information IE", "bssap.mm_information",
2259         FT_NONE, BASE_NONE, NULL, 0,
2260         "MM information IE", HFILL }},
2261         { &hf_bssap_mobile_id_ie,
2262       { "Mobile identity IE", "bssap.mobile_id_ie",
2263         FT_NONE, BASE_NONE, NULL, 0,
2264         "Mobile identity IE", HFILL }},
2265         { &hf_bssap_mobile_stn_cls_mrk1_ie,
2266       { "Mobile station classmark 1 IE", "bssap.mobile_stn_cls_mrk1_ie",
2267         FT_NONE, BASE_NONE, NULL, 0,
2268         "Mobile station classmark 1 IE", HFILL }},
2269         { &hf_bssap_mobile_station_state_ie,
2270       { "Mobile station state IE", "bssap.mobile_station_state_ie",
2271         FT_NONE, BASE_NONE, NULL, 0,
2272         "Mobile station state IE", HFILL }},
2273         { &hf_bssap_ptmsi_ie,
2274       { "PTMSI IE", "bssap.ptmsi_ie",
2275         FT_NONE, BASE_NONE, NULL, 0,
2276         "PTMSI IE", HFILL }},
2277         { &hf_bssap_reject_cause_ie,
2278       { "Reject cause IE", "bssap.reject_cause_ie",
2279         FT_NONE, BASE_NONE, NULL, 0,
2280         "Reject cause IE", HFILL }},
2281         { &hf_bssap_service_area_id_ie,
2282       { "Service area identification IE", "bssap.mobile_stn_cls_mrk1_ie",
2283         FT_NONE, BASE_NONE, NULL, 0,
2284         "Mobile station classmark 1", HFILL }},
2285         { &hf_bssap_sgsn_nr_ie,
2286       { "SGSN number IE", "bssap.imsi_ie",
2287         FT_NONE, BASE_NONE, NULL, 0,
2288         "SGSN number IE", HFILL }},     
2289         { &hf_bssap_tmsi_ie,
2290       { "TMSI IE", "bssap.tmsi_ie",
2291         FT_NONE, BASE_NONE, NULL, 0,
2292         "TMSI IE", HFILL }},    
2293         { &hf_bssap_tmsi_status_ie,
2294       { "TMSI status IE", "bssap.tmsi_status_ie",
2295         FT_NONE, BASE_NONE, NULL, 0,
2296         "TMSI status IE", HFILL }},
2297         { &hf_bssap_vlr_number_ie,
2298       { "VLR number IE", "bssap.vlr_number_ie",
2299         FT_NONE, BASE_NONE, NULL, 0,
2300         "VLR number IE", HFILL }},
2301         { &hf_bssap_global_cn_id_ie,
2302       { "Global CN-Id IE", "bssap.global_cn_id_ie",
2303         FT_NONE, BASE_NONE, NULL, 0,
2304         "Global CN-Id IE", HFILL }},
2305
2306         { &hf_bssap_plus_ie_data,
2307       { "IE Data", "bssap.ie_data",
2308         FT_BYTES, BASE_NONE, NULL, 0,
2309         "IE Data", HFILL }},
2310
2311         { &hf_bssap_call_priority,
2312             { "eMLPP Priority", "bssap.gprs_loc_upd_type",
2313                 FT_UINT8, BASE_DEC, VALS(bssap_call_priority_values), 0x07,
2314                 "eMLPP Priority", HFILL}},
2315         { &hf_bssap_gprs_loc_upd_type,
2316             { "GPRS location update type", "bssap.gprs_loc_upd_type",
2317                 FT_UINT8, BASE_DEC, VALS(bssap_plus_GPRS_loc_upd_type_values), 0x0,
2318                 "GPRS location update type", HFILL}},
2319         { &hf_bssap_Gs_cause,
2320             { "Gs cause", "bssap.gprs_loc_upd_type",
2321                 FT_UINT8, BASE_DEC, VALS(bssap_Gs_cause_values), 0x0,
2322                 "Gs cause", HFILL}},
2323         { &hf_bssap_imei,
2324       { "IMEI", "bssap.imei",
2325         FT_STRING, BASE_NONE, NULL, 0,
2326         "IMEI", HFILL }},
2327         { &hf_bssap_imeisv,
2328       { "IMEISV", "bssap.imeisv",
2329         FT_STRING, BASE_NONE, NULL, 0,
2330         "IMEISV", HFILL }},
2331         { &hf_bssap_imsi,
2332       { "IMSI", "bssap.imsi",
2333         FT_STRING, BASE_NONE, NULL, 0,
2334         "IMSI", HFILL }},
2335         { &hf_bssap_imsi_det_from_gprs_serv_type,
2336             { "IMSI detach from GPRS service type", "bssap.imsi_det_from_gprs_serv_type",
2337                 FT_UINT8, BASE_DEC, VALS(bssap_Gs_cause_values), 0x0,
2338                 "IMSI detach from GPRS service type", HFILL}},
2339         { &hf_bssap_info_req,
2340             { "Information requested", "bssap.info_req",
2341                 FT_UINT8, BASE_DEC, VALS(bssap_info_req_values), 0x0,
2342                 "Information requested", HFILL}},
2343         { &hf_bssap_loc_inf_age,
2344             { "AgeOfLocationInformation in minutes", "bssap.loc_inf_age",
2345                 FT_UINT16, BASE_DEC, NULL, 0x0,
2346                 "AgeOfLocationInformation in minutes", HFILL}},
2347         { &hf_bssap_mobile_station_state,
2348             { "Mobile station state", "bssap.mobile_station_state",
2349                 FT_UINT8, BASE_DEC, VALS(bssap_mobile_station_state_values), 0x0,
2350                 "Mobile station state", HFILL}},
2351         { &hf_bssap_ptmsi,
2352             { "PTMSI", "bssap.ptmsi",
2353                 FT_BYTES, BASE_HEX, NULL, 0x0,
2354                 "PTMSI", HFILL}},
2355         { &hf_bssap_tmsi,
2356             { "TMSI", "bssap.tmsi",
2357                 FT_BYTES, BASE_HEX, NULL, 0x0,
2358                 "TMSI", HFILL}},
2359         { &hf_bssap_tmsi_status,
2360             { "TMSI status", "bssap.tmsi_status",
2361         FT_BOOLEAN, 8, TFS(&bssap_tmsi_flag), 0x01,
2362         "TMSI status", HFILL }},
2363         { &hf_bssap_tom_prot_disc,
2364             { "TOM Protocol Discriminator", "bssap.Tom_prot_disc",
2365                 FT_UINT8, BASE_DEC, VALS(bssap_tom_prot_disc_values), 0x78,
2366                 "TOM Protocol Discriminator", HFILL}},
2367         { &hf_bssap_e_bit,
2368             { "E: Cipher Request", "bssap.tmsi_status",
2369         FT_BOOLEAN, 8, TFS(&bssap_E_flag), 0x04,
2370         "E: Cipher Request", HFILL }},
2371         { &hf_bssap_tunnel_prio,
2372             { "Tunnel Priority", "bssap.tunnel_prio",
2373                 FT_UINT8, BASE_DEC, NULL, 0x0,
2374                 "Tunnel Priority", HFILL}},
2375         { &hf_bssap_global_cn_id,
2376             { "Global CN-Id", "bssap.global_cn_id",
2377                 FT_BYTES, BASE_HEX, NULL, 0x0,
2378                 "Global CN-Id", HFILL}},
2379         { &hf_bssap_plmn_id,
2380             { "PLMN-Id", "bssap.plmn_id",
2381                 FT_BYTES, BASE_HEX, NULL, 0x0,
2382                 "PLMN-Id", HFILL}},
2383         { &hf_bssap_cn_id,
2384             { "CN-Id", "bssap.cn_id",
2385                 FT_UINT16, BASE_DEC, NULL, 0x0,
2386                 "CN-Id", HFILL}},
2387         { &hf_bssap_cell_global_id,
2388             { "Cell global identity", "bssap.plmn_id",
2389                 FT_BYTES, BASE_HEX, NULL, 0x0,
2390                 "Cell global identity", HFILL}},
2391         };
2392
2393     /* Setup protocol subtree array */
2394     static gint *ett[] = {
2395         &ett_bssap,
2396         &ett_bssap_dlci,
2397         &ett_bssap_imsi,
2398         &ett_bssap_imsi_det_from_gprs_serv_type,
2399         &ett_bssap_imsi_det_from_non_gprs_serv_type,
2400         &ett_bssap_info_req,
2401         &ett_bssap_loc_area_id,
2402         &ett_bssap_loc_inf_age,
2403         &ett_bssap_mm_information,
2404         &ett_bssap_mobile_id,
2405         &ett_bssap_sgsn_nr,
2406         &ett_bssap_tmsi,
2407         &ett_bssap_tmsi_status,
2408         &ett_bssap_vlr_number,
2409         &ett_bssap_global_cn,
2410         &ett_bssap_gprs_loc_upd,
2411         &ett_bassp_Gs_cause,
2412         &ett_bassp_imei,
2413         &ett_bassp_imesiv,
2414         &ett_bssap_cell_global_id,
2415         &ett_bssap_cgi,
2416         &ett_bssap_channel_needed,
2417         &ett_bssap_dlink_tnl_pld_cntrl_amd_inf,
2418         &ett_bssap_ulink_tnl_pld_cntrl_amd_inf,
2419         &ett_bssap_emlpp_prio,
2420         &ett_bssap_erroneous_msg,
2421         &ett_bssap_mobile_stn_cls_mrk1,
2422         &ett_bssap_mobile_station_state,
2423         &ett_bssap_ptmsi,
2424         &ett_bssap_reject_cause,
2425         &ett_bssap_service_area_id,
2426         &ett_bssap_global_cn_id,
2427         &ett_bssap_plmn,
2428     };
2429
2430     static enum_val_t bssap_or_bsap_options[] = {
2431         { "bssap",      "BSSAP",        BSSAP },
2432         { "bsap",       "BSAP",         BSAP  },
2433         { NULL,         NULL,           0 }
2434     };
2435
2436
2437     /* Register the protocol name and description */
2438     proto_bssap = proto_register_protocol("BSSAP/BSAP", "BSSAP", "bssap");
2439         /*proto_bssap_plus = proto_register_protocol("BSSAP2", "BSSAP2", "bssap2");*/
2440
2441     /* Required function calls to register the header fields and subtrees used */
2442     proto_register_field_array(proto_bssap, hf, array_length(hf));
2443     proto_register_subtree_array(ett, array_length(ett));
2444
2445     bssap_module = prefs_register_protocol(proto_bssap, NULL);
2446
2447     prefs_register_enum_preference(bssap_module,
2448         "bsap_or_bssap",
2449         "Identify to sub-dissector as",
2450         "For the sake of sub-dissectors registering to accept data from the BSSAP/BSAP dissector, this defines whether it is identified as BSSAP or BSAP.",
2451         &bssap_or_bsap_global,
2452         bssap_or_bsap_options,
2453         FALSE);
2454
2455     bssap_dissector_table = register_dissector_table("bssap.pdu_type", "BSSAP Message Type", FT_UINT8, BASE_DEC);
2456     bsap_dissector_table = register_dissector_table("bsap.pdu_type", "BSAP Message Type", FT_UINT8, BASE_DEC);
2457 }
2458
2459 void
2460 proto_reg_handoff_bssap(void)
2461 {
2462         dissector_handle_t      bssap_plus_handle;
2463
2464     heur_dissector_add("sccp", dissect_bssap_heur, proto_bssap);
2465         /* BSSAP+ */
2466         bssap_plus_handle = create_dissector_handle(dissect_bssap_plus, proto_bssap);
2467         dissector_add("sccp.ssn", SCCP_SSN_BSSAP_PLUS, bssap_plus_handle);
2468
2469     data_handle = find_dissector("data");
2470 }