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