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