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