connectionless cancel PDU's don't have a dg_server_accepting_cancels field
[obnox/wireshark/wip.git] / packet-bssgp.c
1 /* packet-bssgp.c
2  * Routines for BSSGP (BSS GPRS Protocol ETSI GSM 08.18 version 6.7.1 TS 101 343 ) dissection
3  * Copyright 2000, Josef Korelus <jkor@quick.cz>
4  *
5  * $Id: packet-bssgp.c,v 1.9 2004/04/13 04:21:30 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
36 #endif
37
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
40 #endif
41
42 #include <glib.h>
43
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
46 #endif
47
48 #include <epan/packet.h>
49 /*#include "packet-bssgp.h"*/
50
51
52 /*PDU Type GSM 08.18 version 6.7.1 table 11.27 page 53*/
53 #define DL_UNITDATA                     0x0
54 #define UL_UNITDATA                     0x1
55 #define RA_CAPABILITY                   0X2
56 #define PTM_UNITDAT                     0X3
57 #define PAGING_PS                       0X6
58 #define PAGING_CS                       0x7
59 #define RA_CAPABILITY_UPDATE            0X8
60 #define RA_CAPABILITY_UPDATE_ACK        0X9
61 #define RADIO_STATUS                    0xa
62 #define SUSPEND                         0xb
63 #define SUSPEND_ACK                     0xc
64 #define SUSPEND_NACK                    0xd
65 #define RESUME                          0xe
66 #define RESUME_ACK                      0xf
67 #define RESUME_NACK                     0x10
68 #define BVC_BLOCK                       0x20
69 #define BVC_BLOCK_ACK                   0x21
70 #define BVC_RESET                       0X22
71 #define BVC_RESET_ACK                   0X23
72 #define BVC_UNBLOCK                     0x24
73 #define BVC_UNBLOCK_ACK                 0x25
74 #define FLOW_CONTROL_BVC                0x26
75 #define FLOW_CONTROL_BVC_ACK            0x27
76 #define FLOW_CONTROL_MS                 0x28
77 #define FLOW_CONTROL_MS_ACK             0x29
78 #define FLUSH_LL                        0x2a
79 #define FLUSH_LL_ACK                    0x2b
80 #define LLC_DISCARDED                   0x2c
81 #define SGSN_INVOKE_TRACE               0x40
82 #define STATUS                          0x41
83
84
85 #define BSSGP_M 1
86 #define BSSGP_O 2
87 #define BSSGP_C 3
88
89 #define QOSO5CR                         0x20
90 #define QOSO5T                          0x10
91 #define QOSO5A                          0x08
92 #define LOW3B                           0x07
93 #define ODD_EVEN_INDIC                  0x08
94 /*GSM 08.18 version 6.7.1 table 11.27*/
95
96 static const value_string tab_bssgp_pdu_type[] = {
97         { DL_UNITDATA,              "DL-UNITDATA" },    
98         { UL_UNITDATA,              "UL-UNITDATA" },                    
99         { RA_CAPABILITY,            "RA_CAPABILITY" },                  
100         { PTM_UNITDAT,              "PTM-UNITDATA" },   
101         { PAGING_PS,                "PAGING PS" },      
102         { PAGING_CS,                "PAGING CS" },      
103         { RA_CAPABILITY_UPDATE,     "RA-CAPABILITY-UPDATE" },   
104         { RA_CAPABILITY_UPDATE_ACK, "RA-CAPABILITY-UPDATE-ACK" },       
105         { RADIO_STATUS,             "RADIO-STATUS" },           
106         { SUSPEND,                  "SUSPEND" },                        
107         { SUSPEND_ACK,              "SUSPEND-ACK" },    
108         { SUSPEND_NACK,             "SUSPEND-NACK" },                   
109         { RESUME,                   "RESUME" },                         
110         { RESUME_ACK,               "RESUME-ACK" },                     
111         { RESUME_NACK,              "RESUME-NACK" },                    
112         { BVC_BLOCK,                "BVC-BLOCK" },      
113         { BVC_BLOCK_ACK,            "BVC-BLOCK-ACK" },
114         { BVC_RESET,                "BVC-RESET" },      
115         { BVC_RESET_ACK,            "BVC-RESET-ACK" },                  
116         { BVC_UNBLOCK,              "BVC-UNBLOCK" },                    
117         { BVC_UNBLOCK_ACK,          "BVC_UNBLOCK_ACK" },                        
118         { FLOW_CONTROL_BVC,         "FLOW-CONTROL-BVC" },               
119         { FLOW_CONTROL_BVC_ACK,     "FLOW-CONTROL-BVC-ACK" },           
120         { FLOW_CONTROL_MS,          "FLOW-CONTROL-MS" },                        
121         { FLOW_CONTROL_MS_ACK,      "FLOW-CONTROL-MS-ACK" },            
122         { FLUSH_LL,                 "FLUSH-LL" },               
123         { FLUSH_LL_ACK,             "FLUSH-LL-ACK" },   
124         { LLC_DISCARDED,            "LLC-DISCARDED" },                  
125         { SGSN_INVOKE_TRACE,        "SGSN_INVOKE_TRACE" },      
126         { STATUS,                   "STATUS" },
127         { 0,                        NULL },
128 };
129         
130 static const value_string bssgp_iei[] = {
131         { 0x0,   "Alignment Octets" },
132         { 0x1,   "Bmax default MS" },
133         { 0x2,   "BSS Area Indication" },
134         { 0x3,   "Bucket Leak Rate" },
135         { 0x4,   "BVCI" },
136         { 0x5,   "BVC Bucket Size" },
137         { 0x6,   "BVC Measurment" },
138         { 0x7,   "Cause" },
139         { 0x8,   "Cell Identifier" },
140         { 0x9,   "Channel needed" },
141         { 0xa,   "DRX Parameters" },
142         { 0xb,   "eMLPP-Priority" },
143         { 0xc,   "Flush Action" },
144         { 0xd,   "IMSI" },
145         { 0xe,   "LLC-PDU"},
146         { 0xf,   "LLC Frames Discarded" },
147         { 0x10,  "Location Area" },
148         { 0x11,  "Mobile Id" },
149         { 0x12,  "MS Bucket Size" },
150         { 0x13,  "MS Radio Access Capability" },
151         { 0x14,  "OMC Id" },
152         { 0x15,  "PDU In Error" },
153         { 0x16,  "PDU Lifetime" },
154         { 0x17,  "Priority" },
155         { 0x18,  "QoS Profile" },
156         { 0x19,  "Radio Cause" },
157         { 0x1a,  "RA-Cap-UPD-Cause" },
158         { 0x1b,  "Routeing Area" },
159         { 0x1c,  "R_default_MS" },
160         { 0x1d,  "Suspend Reference Number" },
161         { 0x1e,  "Tag" },
162         { 0x1f,  "TLLI" },
163         { 0x20,  "TMSI" },
164         { 0x21,  "Trace Reference" },
165         { 0x22,  "Trace Type" },
166         { 0x23,  "Transaction Id" },
167         { 0x24,  "Trigger Id" },
168         { 0x25,  "Number of octets affected" },
169         { 0, NULL },
170 };
171
172 static const value_string bssgp_cause[] = {
173         { 0x0,  "Processor overload" },
174         { 0x1,  "Equipment failure"  },
175         { 0x2,  "Transit network service failure" },
176         { 0x3,  "Network service transmission capacity modified from zero kbps to greater than zero" },
177         { 0x4,  "Unknown MS" },
178         { 0x5,  "BVCI unknown" },
179         { 0x6,  "Cell traffic congestion" },
180         { 0x7,  "SGSN congestion" },
181         { 0x8,  "O&M intervention" },
182         { 0x9,  "BVCI-blocked" },
183         { 0x20, "Semantically incorect PDU" },
184         { 0x21, "Invalid mandatory information" },
185         { 0x22, "Missing mandatory information" },
186         { 0x23, "Missing conditional IE" },
187         { 0x24, "Unexpected conditional IE" },
188         { 0x25, "Conditional IE error" },
189         { 0x26, "PDU not compatible with protocol state" },
190         { 0x27, "Protocol error-unspecified" },
191         { 0,   NULL },
192 };
193
194 #define TOI_IMSI        0x01
195 #define TOI_IMEI        0x02
196 #define TOI_IMEISV      0x03
197 #define TOI_TMSI_P_TMSI 0x04
198 #define TOI_NO_IDENTITY 0x00
199
200 static const value_string type_of_identity[] = {
201         { TOI_IMSI,        "IMSI" },
202         { TOI_IMEI,        "IMEI" },
203         { TOI_IMEISV,      "IMEISV" },
204         { TOI_TMSI_P_TMSI, "TMSI/P-TMSI" },
205         { TOI_NO_IDENTITY, "No identity" },
206         { 0,    NULL }, 
207 };
208 static const value_string radio_cause[] = {
209         { 0x0, "Radio contact lost with the MS" },
210         { 0x1, "Radio link quality insufficient to continue communication" },
211         { 0x2, "cell-reselction ordered" },
212         { 0, NULL },
213 };
214 static const true_false_string cr_string = {
215         "The SDU does not contain a LLC ACK or SACK command/response frame type",
216         "The SDU contains a LLC ACK or SACK command/response frame type",
217 };
218 static const true_false_string t_string = {
219         "The SDU contains data",
220         "The SDU contains signalling "
221 };
222 static const true_false_string a_string = {
223         "Radio interface uses RLC/MAC-UNITDATA functionality",
224         "Radio interface uses RLC/MAC ARQ functionality"
225 };
226 static const true_false_string imsi_odd_even = {
227         "even number of identity digits and also when the TMSI/P-TMSI is used",
228         "odd number of identity digits"
229 };
230 static const value_string prec_dl[] = {
231         { 0, "High priority"},
232         { 1, "Normal priority"},
233         { 2, "Low priority"},
234         { 3, "Reserved:Taken like Low priority"},
235         { 4, "Reserved:Taken like Low priority"},
236         { 0, NULL},
237 };      
238 static const value_string prec[] = {
239         { 0, "Radio priority 1" },
240         { 1, "Radio priority 2" },
241         { 2, "Radio priority 3" },
242         { 3, "Radio priority 4" },
243         { 4, "Radio priority Unknown" },
244         { 0, NULL },
245 };
246 static const value_string prec_both[] = {
247         { 0, "High priority/Radio priority 1"},
248         { 1, "Normal priority/Radio priority 2"},
249         { 2, "Low priority/Radio priority 3"},
250         { 3, "Reserved/Radio priority 4"},
251         { 4, "Reserved/Radio priority Unknown"},
252         { 0, NULL},
253 };
254
255 /* Initialize the protocol and registered fields */
256 static int proto_bssgp = -1;
257 static int hf_bssgp_pdu_type= -1;
258 static int hf_bssgp_cause = -1;
259 static int hf_bssgp_cid = -1;
260 static int hf_bssgp_imsi = -1;
261 static int hf_bssgp_imsi_toi = -1;
262 static int hf_bssgp_imsi_even_odd_indic = -1;
263 static int hf_bssgp_imsi_lsix = -1;
264 static int hf_bssgp_tlli = -1;
265 /*static int hf_bssgp_tag = -1;
266 static int hf_bssgp_tlli_old = -1;
267 static int hf_bssgp_aligment = -1;
268 static int hf_bssgp_drx_param = -1;
269 static int hf_bssgp_ms_radio_cap = -1;
270 */
271 static int hf_bssgp_qos = -1;
272 static int hf_bssgp_pbr = -1;
273 static int hf_bssgp_pdu_lifetime = -1;
274 /*static int hf_bssgp_priority = -1;
275 static int hf_bssgp_llc_pdu = -1;
276 static int hf_bssgp_ptmsi = -1;
277 */
278 static int hf_bssgp_bvci = -1;
279 /*static int hf_bssgp_la = -1;
280 */
281 static int hf_bssgp_ra_mccmnc = -1;
282 static int hf_bssgp_ra_lac = -1;
283 static int hf_bssgp_ra_rac = -1;
284 /*static int hf_bssgp_bss_area = -1;
285 static int hf_bssgp_channel_needed = -1;
286 static int hf_bssgp_emlpp_priority = -1;
287 static int hf_bssgp_ra_cap_upd_cause = -1;
288 */
289 static int hf_bssgp_radio_cause = -1;
290 /*static int hf_bssgp_sus_ref_num = -1;
291 */
292 static int hf_bssgp_bvci_new = -1;
293 /*static int hf_bssgp_flush_action = -1;
294 static int hf_bssgp_num_oct_affect = -1;
295 static int hf_bssgp_llc_disc = -1;
296 */
297 static int hf_bssgp_bvc_buck_size = -1;
298 static int hf_bssgp_buck_leak_rate = -1;
299 static int hf_bssgp_bmax_def_ms = -1;
300 static int hf_bssgp_r_defau_ms = -1;
301 /*static int hf_bssgp_bvc_measur = -1;
302 static int hf_bssgp_ms_buck_size = -1;
303 static int hf_bssgp_trace_type = -1;
304 static int hf_bssgp_trace_ref = -1;
305 static int hf_bssgp_trigg_id = -1;
306 static int hf_bssgp_mobile_id = -1;
307 static int hf_bssgp_omc_id = -1;
308 static int hf_bssgp_transactionid = -1;
309 */
310 static int hf_bssgp_ietype = -1;
311 static int hf_bssgp_qos_cr = -1;
312 static int hf_bssgp_qos_t = -1;
313 static int hf_bssgp_qos_a = -1;
314 static int hf_bssgp_qos_prec = -1;
315 static int hf_bssgp_frdsc = -1;
316 static int hf_bssgp_noaff = -1;
317 /*static int hf_bssgp_FIELDABBREV = -1;*/
318
319 /*static dissector_handle_t data_handle;
320 */
321 static dissector_handle_t llcgprs_handle;
322
323 /* Initialize the subtree pointers */
324 static gint ett_bssgp = -1;
325 static gint ett_bssgp_tlli = -1;
326 static gint ett_bssgp_qos = -1;
327 static gint ett_bssgp_o5 = -1;
328 static gint ett_bssgp_lft = -1;
329 static gint ett_bssgp_racc = -1;
330 static gint ett_prio_tree = -1;
331 static gint ett_drx_tree = -1;
332 static gint ett_bssgp_imsi = -1;
333 static gint ett_bssgp_imsi_stru_tree = -1;
334 static gint ett_algn_tree = -1;
335 static gint ett_b_llc_tree = -1;
336 static gint ett_celid_tree = -1;
337 static gint ett_tag_tree = -1;
338 static gint ett_bsize_tree = -1;
339 static gint ett_bucklr_tree = -1;
340 static gint ett_bmaxms_tree = -1;
341 static gint ett_rdefms_tree = -1;
342 static gint ett_bvci_tree = -1;
343 static gint ett_bvcin_tree = -1;
344 static gint ett_cause_tree = -1;
345 static gint ett_frdsc_tree = -1;
346 static gint ett_noaff_tree = -1;
347 static gint ett_racaus_tree = -1;
348 static gint ett_ra_tree = -1;
349 /*Functions for decoding IEs of BSSGP V6.7.1 */
350 typedef struct {
351         int type;
352         packet_info *pinfo;
353         proto_tree *tree;
354         int k;
355 } dec_fu_param_stru_t;  
356 static int dcd_bssgp_algn       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
357 static int dcd_bssgp_bmaxms     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
358 /*static int dcd_bssgp_bss_aind ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
359 */
360 static int dcd_bssgp_bucklr     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
361 static int dcd_bssgp_bvci       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
362 static int dcd_bssgp_bvci_n     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
363 static int dcd_bssgp_bvc_bsize  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
364 /*static int dcd_bssgp_bvc_meas ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
365 */
366 static int dcd_bssgp_cause      ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
367 static int dcd_bssgp_cellid     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
368 /*static int dcd_bssgp_chan_need        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
369 */
370 static int dcd_bssgp_drx        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
371 /*static int dcd_bssgp_emlpp_prio       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
372 static int dcd_bssgp_flush_act  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
373 */
374 static int dcd_bssgp_imsi       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
375 static int dcd_bssgp_llc_pdu    ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
376 static int dcd_bssgp_llc_frdsc  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
377 /*static int dcd_bssgp_la               ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
378 static int dcd_bssgp_mid        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
379 static int dcd_bssgp_ms_buck    ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
380 */
381 static int dcd_bssgp_radio_acc  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
382 /*static int dcd_bssgp_omc_id   ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
383 */
384 /*static int dcd_bssgp_pdu_err  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
385 */
386 static int dcd_bssgp_pdu_life   ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
387 static int dcd_bssgp_prio       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
388 static int dcd_bssgp_qos        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
389 static int dcd_bssgp_radio_caus ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
390 /*static int dcd_bssgp_racap_upd        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
391 */
392 static int dcd_bssgp_ra         ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
393 static int dcd_bssgp_r_def_ms   ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
394 /*static int dcd_bssgp_sus_ref_num( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
395 */
396 static int dcd_bssgp_tag        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
397 static int dcd_bssgp_tlli       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
398 /*static int dcd_bssgp_tlli_o   ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
399 */
400 /*static int dcd_bssgp_tmsi     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
401 */
402 /*static int dcd_bssgp_trace_ref        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
403 */
404 /*static int dcd_bssgp_trace_type       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
405 */
406 /*static int dcd_bssgp_trans_id ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
407 */
408 /*static int dcd_bssgp_trig_id  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
409 */
410 static int dcd_bssgp_num_oct_aff( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
411 static int dcd_bssgp_not_yet_dcd( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
412 static void mccmnc(guint32 mcmn, char buf[]);
413 /*---------------------------------------------------------*/
414 typedef struct _bssgp_ie {
415         guint8  code;
416         guint8 presence;
417         guint8 type;
418 /*      int (*decode)(tvbuff_t *, int, int, packet_info *, proto_tree *);
419 */
420         int (*decode)(tvbuff_t *, int, dec_fu_param_stru_t *);
421         } bssgp_ie_t;
422 typedef struct _bssgp_pdu {
423         guint8 pdu;
424         bssgp_ie_t infe[12];
425 } _bssgp_pdu_t;
426 /*------------------------------------------------------------*/
427 static _bssgp_pdu_t bssgp_pdu[] = {
428         {
429                 DL_UNITDATA, {
430                         { 0x1f, BSSGP_M, 3, dcd_bssgp_tlli },
431                         { 0x18, BSSGP_M, 3, dcd_bssgp_qos },
432                         { 0x16, BSSGP_M, 4, dcd_bssgp_pdu_life },
433                         { 0x13, BSSGP_O, 4, dcd_bssgp_radio_acc },
434                         { 0x17, BSSGP_O, 4, dcd_bssgp_prio },
435                         { 0x0a, BSSGP_O, 4, dcd_bssgp_drx },
436                         { 0x0d, BSSGP_O, 4, dcd_bssgp_imsi },
437 /*                      { 0x1f, BSSGP_O, 4, dcd_bssgp_tlli_o },
438 */                      
439                         { 0x1f, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
440                         { 0x00, BSSGP_O, 4, dcd_bssgp_algn },
441                         { 0x0e, BSSGP_M, 4, dcd_bssgp_llc_pdu },
442                         { 0,0,0,NULL }
443                 }       
444                 
445         },
446         {
447                 UL_UNITDATA, {
448                         { 0x1f, BSSGP_M, 3, dcd_bssgp_tlli },
449                         { 0x18, BSSGP_M, 3, dcd_bssgp_qos },
450                         { 0x08, BSSGP_M, 4, dcd_bssgp_cellid },
451                         { 0x00, BSSGP_O, 4, dcd_bssgp_algn },
452                         { 0x0e, BSSGP_M, 4, dcd_bssgp_llc_pdu },
453                         { 0,0,0,NULL }
454                 }
455         },
456         {
457                 RA_CAPABILITY, {
458                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
459                         { 0x13, BSSGP_M, 4, dcd_bssgp_radio_acc },
460                         { 0,0,0,NULL }
461                 }
462         },
463         {
464                 PAGING_PS, {
465                         { 0x0d, BSSGP_M, 4, dcd_bssgp_imsi },
466                         { 0x0a, BSSGP_O, 4, dcd_bssgp_drx },
467                         { 0x04, BSSGP_C, 4, dcd_bssgp_bvci },
468 /*                      { 0x10, BSSGP_C, 4, dcd_bssgp_la },
469 */                      
470                         { 0x10, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
471                         { 0x1b, BSSGP_C, 4, dcd_bssgp_ra },
472 /*                      { 0x02, BSSGP_C, 4, dcd_bssgp_bss_aind },
473 */                      
474                         { 0x02, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
475                         { 0x18, BSSGP_M, 4, dcd_bssgp_qos },
476 /*                      { 0x20, BSSGP_O, 4, dcd_bssgp_tmsi },
477 */                      
478                         { 0x20, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
479                         { 0,0,0,NULL }
480                 }
481         },
482         {
483                 PAGING_CS, {
484                         { 0x0d, BSSGP_M, 4, dcd_bssgp_imsi },
485                         { 0x0a, BSSGP_M, 4, dcd_bssgp_drx },
486                         { 0x04, BSSGP_C, 4, dcd_bssgp_bvci },
487 /*                      { 0x10, BSSGP_C, 4, dcd_bssgp_la },
488 */                      
489                         { 0x10, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
490                         { 0x1b, BSSGP_C, 4, dcd_bssgp_ra },
491 /*                      { 0x02, BSSGP_C, 4, dcd_bssgp_bss_aind },
492 */                      
493                         { 0x02, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
494                         { 0x1f, BSSGP_O, 4, dcd_bssgp_tlli },
495 /*                      { 0x09, BSSGP_O, 4, dcd_bssgp_chan_need },
496 */                      
497                         { 0x09, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
498 /*                      { 0x0b, BSSGP_O, 4, dcd_bssgp_emlpp_prio },
499 */                      
500                         { 0x0b, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
501 /*                      { 0x20, BSSGP_O, 4, dcd_bssgp_tmsi },
502 */                      
503                         { 0x20, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
504                         { 0,0,0,NULL }
505                 }
506         },
507         {
508                 RA_CAPABILITY_UPDATE, {
509                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
510                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
511                         { 0,0,0,NULL }
512                 }
513                 
514         },
515         {
516                  RA_CAPABILITY_UPDATE_ACK, {
517                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
518                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
519                         { 0x0d, BSSGP_O, 4, dcd_bssgp_imsi },
520 /*                      { 0x1a, BSSGP_M, 4, dcd_bssgp_racap_upd },
521 */                      
522                         { 0x1a, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
523                         { 0x13, BSSGP_C, 4, dcd_bssgp_radio_acc },
524                         { 0,0,0,NULL }
525                  }
526         },
527         {
528                 RADIO_STATUS, {
529                         { 0x1f, BSSGP_C, 4, dcd_bssgp_tlli },
530 /*                      { 0x20, BSSGP_C, 4, dcd_bssgp_tmsi },
531 */                      
532                         { 0x20, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
533                         { 0x0d, BSSGP_C, 4, dcd_bssgp_imsi },
534                         { 0x19, BSSGP_M, 4, dcd_bssgp_radio_caus },
535                         { 0,0,0,NULL }
536                 }
537         },
538         {
539                 SUSPEND, {
540                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
541                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
542                         { 0,0,0,NULL }
543                 }
544         },
545         {
546                  SUSPEND_ACK, {
547                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
548                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
549 /*                      { 0x1d, BSSGP_M, 4, dcd_bssgp_sus_ref_num },
550 */                      
551                         { 0x1d, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
552                         { 0,0,0,NULL }
553                  }
554         },
555         {
556                  SUSPEND_NACK, {
557                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
558                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
559                         { 0x07, BSSGP_O, 4, dcd_bssgp_cause },
560                         { 0,0,0,NULL }
561                  }
562         },
563         {
564                 RESUME, {
565                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
566                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
567 /*                      { 0x1d, BSSGP_M, 4, dcd_bssgp_sus_ref_num },
568 */                      
569                         { 0x1d, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
570                         { 0,0,0,NULL }
571                 }
572         },
573         {
574                 RESUME_ACK, {
575                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
576                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
577                         { 0,0,0,NULL }
578                 }
579         },
580         {
581                  RESUME_NACK, {
582                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
583                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
584                         { 0x07, BSSGP_O, 4, dcd_bssgp_cause },
585                         { 0,0,0,NULL }
586                  }
587         },
588         {
589                 BVC_BLOCK, {
590                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
591                         { 0x07, BSSGP_M, 4, dcd_bssgp_cause },
592                         { 0,0,0,NULL }
593                 }
594         },
595         {
596                 BVC_BLOCK_ACK, {
597                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
598                         { 0,0,0,NULL }
599                 }
600         },
601         {
602                 BVC_RESET, {
603                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
604                         { 0x07, BSSGP_M, 4, dcd_bssgp_cause },
605                         { 0x08, BSSGP_C, 4, dcd_bssgp_cellid },
606                         { 0,0,0,NULL }
607                 }
608         },
609         {
610                 BVC_RESET_ACK, {
611                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
612                         { 0x08, BSSGP_C, 4, dcd_bssgp_cellid },
613                         { 0,0,0,NULL }
614                 }
615         },
616         {
617                  BVC_UNBLOCK, {
618                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
619                         { 0,0,0,NULL }
620                  }
621         },
622         {
623                  BVC_UNBLOCK_ACK, {
624                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
625                         { 0,0,0,NULL }
626                  }
627         },
628         {
629                 FLOW_CONTROL_BVC, {
630                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
631                         { 0x05, BSSGP_M, 4, dcd_bssgp_bvc_bsize },
632                         { 0x03, BSSGP_M, 4, dcd_bssgp_bucklr },
633                         { 0x01, BSSGP_M, 4, dcd_bssgp_bmaxms },
634                         { 0x1c, BSSGP_M, 4, dcd_bssgp_r_def_ms },
635 /*                      { 0x06, BSSGP_O, 4, dcd_bssgp_bvc_meas }, */
636                         { 0x06, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
637                         { 0,0,0,NULL }
638                 }
639         },
640         {
641                  FLOW_CONTROL_BVC_ACK, {
642                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
643                         { 0,0,0,NULL }
644                  }
645         },
646         {
647                  FLOW_CONTROL_MS, {
648                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
649                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
650 /*                      { 0x12, BSSGP_M, 4, dcd_bssgp_ms_buck},
651 */                      
652                         { 0x12, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
653                         { 0x03, BSSGP_M, 4, dcd_bssgp_bucklr },
654                         { 0,0,0,NULL }
655                  }
656         },
657         {
658                 FLOW_CONTROL_MS_ACK, {
659                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
660                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
661                         { 0,0,0,NULL }
662                 }
663         },
664         {
665                 FLUSH_LL, {
666                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
667                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
668                         { 0x04, BSSGP_O, 4, dcd_bssgp_bvci_n },
669                         { 0,0,0,NULL }
670                 }
671         },
672         {
673                 FLUSH_LL_ACK, {
674                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
675 /*                      { 0x0c, BSSGP_M, 4, dcd_bssgp_flush_act },
676 */                      
677                         { 0x0c, BSSGP_M, 4, dcd_bssgp_not_yet_dcd },
678                         { 0x04, BSSGP_C, 4, dcd_bssgp_bvci_n },
679                         { 0x25, BSSGP_M, 4, dcd_bssgp_num_oct_aff }, 
680                         { 0,0,0,NULL }
681                 }
682         },
683         {
684                 LLC_DISCARDED, {
685                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
686                         { 0x0f, BSSGP_M, 4, dcd_bssgp_llc_frdsc },
687                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
688                         { 0x25, BSSGP_M, 4, dcd_bssgp_num_oct_aff }, 
689                         { 0,0,0,NULL }
690                 }
691         },
692         {
693                 SGSN_INVOKE_TRACE, {
694 /*                      { 0x22, BSSGP_M, 4, dcd_bssgp_trace_type },
695                         { 0x21, BSSGP_M, 4, dcd_bssgp_trace_ref },
696                         { 0x24, BSSGP_O, 4, dcd_bssgp_trig_id },
697                         { 0x11, BSSGP_O, 4, dcd_bssgp_mid },
698                         { 0x14, BSSGP_O, 4, dcd_bssgp_omc_id },
699                         { 0x23, BSSGP_O, 4, dcd_bssgp_trans_id },
700 */                      
701                         { 0x22, BSSGP_M, 4, dcd_bssgp_not_yet_dcd },
702                         { 0x21, BSSGP_M, 4, dcd_bssgp_not_yet_dcd },
703                         { 0x24, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
704                         { 0x11, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
705                         { 0x14, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
706                         { 0x23, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
707                         { 0,0,0,NULL }
708                 }
709         },
710         {
711                 STATUS, {
712                         { 0x07, BSSGP_M, 4, dcd_bssgp_cause },
713                         { 0x04, BSSGP_C, 4, dcd_bssgp_bvci },
714 /*                      { 0x15, BSSGP_O, 4, dcd_bssgp_pdu_err },
715 */                      
716                         { 0x15, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
717                         { 0,0,0,NULL }
718                 }
719         },
720         {
721                 0, {
722                         { 0,0,0,NULL }
723                 }
724         }
725 };
726 /*-----------------------------------------------------------------------------------------------------------------*/
727 static void mccmnc(guint32 mcmn, char buf[]){
728        typedef struct {
729                 guint32 mnc1 : 4 ;
730                 guint32 mnc2 : 4 ;
731                 guint32 mcc3 : 4 ;
732                 guint32 mnc3 : 4 ;
733                 guint32 mcc1 : 4 ;
734                 guint32 mcc2 : 4 ;              
735         } stru_mncmcc;
736         typedef union {
737                 guint32 i;
738                 stru_mncmcc s;
739         } u_mncmcc;
740         u_mncmcc  *r_mncmcc;
741         guint8 pom =0,i=0 ;
742                 r_mncmcc = (u_mncmcc *)&mcmn;
743                 for (i=0;i<8;i++){
744                   switch (i) {
745                           case 0 :
746                                   pom = r_mncmcc->s.mcc1;
747                                 break;
748                           case 1 :      
749                                   pom = r_mncmcc->s.mcc2;
750                                 break;
751                           case 2 :
752                                   pom = r_mncmcc->s.mcc3;
753                                 break;
754                           case 3 :
755                                   pom = 0x61;/* 0x61 because i need space " " (0x61-1)^0x40*/   
756                                 break;
757                           case 4 :
758                                   pom = r_mncmcc->s.mnc1;
759                                 break;
760                           case 5 :
761                                   pom = r_mncmcc->s.mnc2;
762                                 break;
763                           case 6 :
764                                   pom = r_mncmcc->s.mnc3;         
765                                   pom = (pom == 0xf)?0x41: pom;/* 0x41 because i need null on the end of string (0x41-1)^0x40*/
766                                 break;
767                           case 7 :
768                                  pom = 0x41;
769                                 break;           
770                                           
771                   }
772                                   pom = (pom > 9)?(pom-1) ^ 0x40: pom ^ 0x30;
773                                   buf[i] = pom;
774                 }
775 }
776 static int dcd_bssgp_not_yet_dcd(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
777         guint8 code=0, pom=0,k=2;
778         guint16 llen=0;
779         
780         pom = tvb_get_guint8(tvb,offset+1);
781         if ( pom >= 128 ){
782                 llen = pom & 0x7f;
783                 k = 2;
784         }
785         else{ 
786                 llen = tvb_get_ntohs( tvb, offset+1);
787                 k=3;    
788         }
789         if (dprm_p->tree){
790                 code = tvb_get_guint8(tvb,offset);
791                 proto_tree_add_uint_format(dprm_p->tree,hf_bssgp_ietype,tvb,offset,llen+k,code,"IE type: %s  (%#.2x) ....Not yet decoded",match_strval(code,bssgp_iei),code);
792         }
793 return llen+k;
794 }
795 static int dcd_bssgp_algn(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
796         guint8 code=0, len=0;
797         proto_item *ti=NULL;
798         proto_tree *algn_tree=NULL;
799         
800         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
801         if (dprm_p->tree){
802                 code = tvb_get_guint8(tvb,offset);
803                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%u Aligment octets", len+2 );
804                 algn_tree = proto_item_add_subtree(ti, ett_algn_tree);
805                 proto_tree_add_uint_format(algn_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
806                 proto_tree_add_text(algn_tree,tvb,offset+1,1,"Length:%u",len);
807         }
808 return len+2;
809 }
810 static int dcd_bssgp_bmaxms(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
811         guint8 code=0, len=0;
812         guint16 bucket=0;
813         proto_item *ti=NULL;
814         proto_tree *bmaxms_tree=NULL;
815         
816         if (dprm_p->tree){
817                 len = tvb_get_guint8(tvb,offset+1) & 0x7f;
818                 code = tvb_get_guint8(tvb,offset);
819                 bucket = tvb_get_ntohs(tvb,offset+2);
820                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u bytes", match_strval(code,bssgp_iei),100*bucket);
821                 bmaxms_tree = proto_item_add_subtree(ti, ett_bmaxms_tree);
822                 proto_tree_add_uint_format(bmaxms_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
823                 proto_tree_add_uint_format(bmaxms_tree, hf_bssgp_bmax_def_ms,tvb,offset+2,len,bucket,"%s in 100 octet increments: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
824                 proto_tree_add_text(bmaxms_tree,tvb,offset+1,1,"Length:%u",len);
825         }
826 return len+2;
827 }
828 /*static int dcd_bssgp_bss_aind(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){        
829 };
830 */
831 static int dcd_bssgp_bucklr(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
832         guint8 code=0, len=0;
833         guint16 bucket=0;
834         proto_item *ti=NULL;
835         proto_tree *bucklr_tree=NULL;
836         
837         bucket = tvb_get_ntohs(tvb,offset+2);
838         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
839         code = tvb_get_guint8(tvb,offset);
840         
841         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
842                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u bits/sec",match_strval(code,bssgp_iei),bucket*100 );
843                 }       
844         if (dprm_p->tree){
845                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "Bucket Leak Rate(R): %u bits/sec", 100*bucket);
846                 bucklr_tree = proto_item_add_subtree(ti, ett_bucklr_tree);
847                 proto_tree_add_uint_format(bucklr_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
848                 proto_tree_add_uint_format(bucklr_tree, hf_bssgp_buck_leak_rate,tvb,offset+2,len,bucket,"%s in 100 bits/sec increments: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
849                 proto_tree_add_text(bucklr_tree,tvb,offset+1,1,"Length:%u",len);
850         }
851 return len+2;
852 }
853 static int dcd_bssgp_bvci(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
854         guint8 code=0, len=0;
855         guint16 bucket=0;
856         proto_item *ti=NULL;
857         proto_tree *bvci_tree=NULL;
858         
859         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
860         code = tvb_get_guint8(tvb,offset);
861         bucket = tvb_get_ntohs(tvb,offset+2);
862         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
863                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u",match_strval(code,bssgp_iei),bucket );
864                 }       
865         if (dprm_p->tree){
866                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u", match_strval(code,bssgp_iei), bucket);
867                 bvci_tree = proto_item_add_subtree(ti, ett_bvci_tree);
868                 proto_tree_add_uint_format(bvci_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
869                 proto_tree_add_uint_format(bvci_tree, hf_bssgp_bvci,tvb,offset+2,len,bucket,"%s: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
870                 proto_tree_add_text(bvci_tree,tvb,offset+1,1,"Length:%u",len);
871         }
872 return len+2;
873 }
874 static int dcd_bssgp_bvci_n(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
875         guint8 code=0, len=0;
876         guint16 bucket=0;
877         proto_item *ti=NULL;
878         proto_tree *bvcin_tree=NULL;
879         
880         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
881         code = tvb_get_guint8(tvb,offset);
882         bucket = tvb_get_ntohs(tvb,offset+2);
883         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
884                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, " New %s: %u",match_strval(code,bssgp_iei),bucket );
885                 }       
886         if (dprm_p->tree){
887                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "New %s: %u", match_strval(code,bssgp_iei), bucket);
888                 bvcin_tree = proto_item_add_subtree(ti, ett_bvcin_tree);
889                 proto_tree_add_uint_format(bvcin_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s(New) %#.2x",match_strval(code,bssgp_iei),code);
890                 proto_tree_add_uint_format(bvcin_tree, hf_bssgp_bvci_new,tvb,offset+2,len,bucket,"New %s: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
891                 proto_tree_add_text(bvcin_tree,tvb,offset+1,1,"Length:%u",len);
892         }
893 return len+2;
894 }
895 static int dcd_bssgp_bvc_bsize(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
896         guint8 code=0, len=0;
897         guint16 bucket=0;
898         proto_item *ti=NULL;
899         proto_tree *bsize_tree=NULL;
900         
901         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
902         code = tvb_get_guint8(tvb,offset);
903         bucket = tvb_get_ntohs(tvb,offset+2);
904         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
905                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u bytes",match_strval(code,bssgp_iei),bucket*100 );
906                 }       
907         if (dprm_p->tree){
908                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "BVC Bucket Size: %u bytes", 100*bucket);
909                 bsize_tree = proto_item_add_subtree(ti, ett_bsize_tree);
910                 proto_tree_add_uint_format(bsize_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
911                 proto_tree_add_uint_format(bsize_tree, hf_bssgp_bvc_buck_size,tvb,offset+2,len,bucket,"%s in 100 octet increments: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
912                 proto_tree_add_text(bsize_tree,tvb,offset+1,1,"Length:%u",len);
913         }
914 return len+2;
915 }
916 /*static int dcd_bssgp_bvc_meas(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){        
917 return 4;
918 };
919 */
920 static int dcd_bssgp_cause(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){     
921         guint8 code=0, len=0,cause=0;
922         proto_item *ti=NULL;
923         proto_tree *cause_tree=NULL;
924         
925         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
926         code = tvb_get_guint8(tvb,offset);
927         cause = tvb_get_guint8(tvb,offset+2);
928         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
929                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %s",match_strval(code,bssgp_iei),match_strval(cause,bssgp_cause));
930                 }       
931         if (dprm_p->tree){
932                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %s", match_strval(code,bssgp_iei),match_strval(cause,bssgp_cause));
933                 cause_tree = proto_item_add_subtree(ti, ett_cause_tree);
934                 proto_tree_add_uint_format(cause_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
935                 proto_tree_add_uint_format(cause_tree, hf_bssgp_cause,tvb,offset+2,len,cause,"%s: %s (%#.2x)",match_strval(code,bssgp_iei),match_strval(cause,bssgp_cause),cause);
936                 proto_tree_add_text(cause_tree,tvb,offset+1,1,"Length:%u",len);
937         }
938 return len+2;
939 }
940
941 static int dcd_bssgp_cellid(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
942         char mccmnc_str[8];
943         guint32 mnccc;
944         guint16 lac,cid;
945         guint8 len=8, code=0,rac;
946         proto_item *ti = NULL;
947         proto_tree *celid_tree = NULL;
948         
949         if (dprm_p->tree){
950                 code = tvb_get_guint8(tvb,offset);
951                 mnccc = tvb_get_ntoh24(tvb,offset+2);
952                 lac = tvb_get_ntohs(tvb,offset+5);
953                 rac = tvb_get_guint8(tvb,offset+7);
954                 cid = tvb_get_ntohs(tvb,offset+8);
955                 mccmnc(mnccc, mccmnc_str);
956
957                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "Cell Identifier: %s %u %u %u",mccmnc_str,lac,rac,cid);
958                 celid_tree = proto_item_add_subtree(ti, ett_celid_tree);
959                 proto_tree_add_uint_format(celid_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
960                 proto_tree_add_string_format(celid_tree,hf_bssgp_ra_mccmnc,tvb,offset+2,3,mccmnc_str,"MCC MNC: %s",mccmnc_str);
961                 proto_tree_add_uint_format(celid_tree,hf_bssgp_ra_lac,tvb,offset+5,2,lac,"LAC: %u",lac);
962                 proto_tree_add_uint_format(celid_tree,hf_bssgp_ra_rac,tvb,offset+7,1,rac,"RAC: %u",rac);
963                 proto_tree_add_uint_format(celid_tree,hf_bssgp_cid,tvb,offset+8,2,cid,"Cell Id: %u",cid);
964                 proto_tree_add_text(celid_tree,tvb,offset+1,1,"Length:%u",len);
965                 
966         }
967          
968         return len+2;
969 }
970
971 /*static int dcd_bssgp_chan_need(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
972 };
973 */
974 static int dcd_bssgp_drx(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
975         guint8 code=0, len=0;
976         proto_item *ti=NULL;
977         proto_tree *drx_tree=NULL;
978         
979         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
980         if (dprm_p->tree){
981                 code = tvb_get_guint8(tvb,offset);
982                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, 4,"DRX Parameters");
983                 drx_tree = proto_item_add_subtree(ti, ett_drx_tree);
984                 proto_tree_add_uint_format(drx_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
985                 proto_tree_add_text(drx_tree,tvb,offset+1,1,"Length:%u",len);
986         }
987 return len+2;
988         
989 }
990
991 /*static int dcd_bssgp_emlpp_prio(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
992 };
993 */
994
995 /*static int dcd_bssgp_flush_act(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
996 };
997 */
998
999 static int dcd_bssgp_imsi(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
1000         guint8  nextb=0, first_b=0, toi=0, i, k;
1001         guint8  num=0,code=0,len=0;
1002         char buf[17],imsi_mccn[6],imsi_val[11], toibuf[9];
1003         proto_item *ti=NULL, *ti2=NULL;
1004         proto_tree *imsi_tree = NULL, *imsi_stru_tree = NULL;
1005
1006         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1007         first_b = tvb_get_guint8(tvb,offset+2);
1008         if (dprm_p->tree){
1009                 code = tvb_get_guint8(tvb,offset);
1010                 decode_bitfield_value(toibuf,toi,LOW3B,8);
1011                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+2 ,"IMSI");
1012                 imsi_tree = proto_item_add_subtree(ti, ett_bssgp_imsi);
1013                 proto_tree_add_uint_format(imsi_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1014                 proto_tree_add_text(imsi_tree,tvb,offset+1,1,"Length:%u",len);
1015         }
1016         toi = first_b & LOW3B;
1017         switch (toi) {
1018
1019         case TOI_IMSI:
1020         case TOI_IMEI:
1021         case TOI_IMEISV:
1022                 num = first_b >> 4;
1023                 buf[0] = num + '0';
1024                 for (i=1,k=1;i<len;i++){
1025                         nextb = tvb_get_guint8(tvb, offset+2+i);
1026                         num = nextb & 0x0f;
1027                         buf[k] = num + '0';
1028                         k++;
1029                         if (i < len - 1 || (first_b & ODD_EVEN_INDIC)) {
1030                                 /*
1031                                  * Either this isn't the last octet
1032                                  * of the number, or it is, but there's
1033                                  * an odd number of digits, so the last
1034                                  * nibble is part of the number.
1035                                  */
1036                                 num = nextb >> 4;
1037                                 buf[k] = num + '0';
1038                                 k++;
1039                         }
1040                         buf[k] = '\0';
1041                         switch (i*2){
1042                                 case 4:
1043                                         memcpy(&imsi_mccn,&buf,6);
1044                                         break;
1045                                 case 14:
1046                                         memcpy(&imsi_val, &buf[5],11);  
1047                                         break;
1048                         }
1049         
1050                 }
1051                 if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1052                         col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO,
1053                             ", %s: %s %s",
1054                             val_to_str(toi,type_of_identity,"Unknown TOI (0x%x)"),
1055                                 imsi_mccn, imsi_val );
1056                 }
1057         
1058                 if (dprm_p->tree){
1059                         proto_item_append_text(ti, ": %s", buf);
1060                         ti2 = proto_tree_add_text(imsi_tree,tvb,offset+2,len,"Mobile identity: %s",buf);
1061                         imsi_stru_tree = proto_item_add_subtree( ti2, ett_bssgp_imsi_stru_tree);
1062                         proto_tree_add_uint(imsi_stru_tree,hf_bssgp_imsi_toi,tvb,offset+2,1,first_b);
1063                         proto_tree_add_boolean(imsi_stru_tree,hf_bssgp_imsi_even_odd_indic,tvb,offset+2,1,first_b);
1064                         proto_tree_add_string(imsi_stru_tree,hf_bssgp_imsi,tvb,offset+2,len,buf);
1065                         proto_tree_add_string_hidden(imsi_stru_tree,hf_bssgp_imsi_lsix,tvb,offset+2,len,imsi_val);
1066                 }
1067                 break;
1068         }
1069 return len+2;   
1070 }
1071
1072 static int dcd_bssgp_llc_pdu(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){   
1073         guint8 code=0, pom=0,k=0;
1074         guint16 llen=0;
1075         proto_item *ti=NULL;
1076         proto_tree *b_llc_tree=NULL;
1077
1078         pom = tvb_get_guint8(tvb,offset+1);
1079         if ( pom >= 128 ){
1080                 llen = pom & 0x7f;
1081                 k = 2;
1082         }
1083         else{ 
1084                 llen = tvb_get_ntohs( tvb, offset+1);
1085                 k=3;    
1086         }
1087
1088         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1089                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", LLC PDU length %u bytes", llen );
1090                 }       
1091         
1092         if (dprm_p->tree){
1093                 code = tvb_get_guint8(tvb,offset);
1094                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,llen+2 ,"LLC PDU %u bytes", llen);
1095                 b_llc_tree = proto_item_add_subtree(ti, ett_b_llc_tree);
1096                 proto_tree_add_uint_format(b_llc_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1097                 proto_tree_add_text(b_llc_tree,tvb,offset+1,k-1,"Length:%u",llen);
1098         }
1099         
1100 dprm_p->k=offset+k;     
1101 return llen+k;  
1102 }
1103
1104 static int dcd_bssgp_llc_frdsc(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1105         guint8 code=0, len=0,frdsc=0;
1106         proto_item *ti=NULL;
1107         proto_tree *frdsc_tree=NULL;
1108         
1109         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1110         frdsc = tvb_get_guint8(tvb,offset+2);
1111         code = tvb_get_guint8(tvb,offset);
1112         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1113                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u",match_strval(code,bssgp_iei), frdsc);
1114                 }       
1115         if (dprm_p->tree){
1116                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u", match_strval(code,bssgp_iei), frdsc);
1117                 frdsc_tree = proto_item_add_subtree(ti, ett_frdsc_tree);
1118                 proto_tree_add_uint_format(frdsc_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1119                 proto_tree_add_uint_format(frdsc_tree, hf_bssgp_frdsc,tvb,offset+2,len,frdsc,"%s: %u",match_strval(code,bssgp_iei),frdsc);
1120                 proto_tree_add_text(frdsc_tree,tvb,offset+1,1,"Length:%u",len);
1121         }
1122 return len+2;
1123 }
1124
1125 /*static int dcd_bssgp_la(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){              
1126 };
1127 */
1128
1129 /*static int dcd_bssgp_mid(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){     
1130 };
1131 */
1132
1133 /*static int dcd_bssgp_ms_buck(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1134 };
1135 */
1136
1137 static int dcd_bssgp_radio_acc(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1138         guint8 code=0,len=0;
1139         proto_item *ti=NULL;
1140         proto_tree *racc_tree = NULL;
1141
1142         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1143         if (dprm_p->tree){
1144                 code = tvb_get_guint8(tvb,offset);
1145                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+2 ,"MS Radio Access Capability: ");
1146                 racc_tree = proto_item_add_subtree(ti, ett_bssgp_racc);
1147                 proto_tree_add_uint_format(racc_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1148                 proto_tree_add_text(racc_tree,tvb,offset+1,1,"Length:%u",len);
1149         }
1150 return len+2;
1151 }
1152
1153 /*static int dcd_bssgp_omc_id(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){  
1154 };
1155 */
1156
1157 /*static int dcd_bssgp_pdu_err(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1158 };
1159 */
1160
1161 static int dcd_bssgp_pdu_life(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
1162         gfloat ms_lifetime;
1163         guint16 lifetime;
1164         guint8 code=0, len=0;
1165         proto_item *ti=NULL;
1166         proto_tree *lft_tree=NULL;
1167         
1168         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1169         if (dprm_p->tree){
1170                 code = tvb_get_guint8(tvb,offset);
1171                 lifetime = tvb_get_ntohs(tvb,offset+2);
1172                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, 4,"PDU Lifetime (s): ");
1173                 lft_tree = proto_item_add_subtree(ti, ett_bssgp_lft);
1174                 proto_tree_add_uint_format(lft_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1175                 proto_tree_add_text(lft_tree,tvb,offset+1,1,"Length:%u",len);
1176                 if (lifetime == 0xFFFF){
1177                         proto_item_append_text(ti,"infinite delay");
1178                         proto_tree_add_uint_format(lft_tree,hf_bssgp_pdu_lifetime,tvb,offset+2,2,lifetime,"PDU Life time: infinite delay (%#.4x centi seconds)", lifetime);
1179                 }
1180                 else{
1181                         ms_lifetime = (gfloat) (lifetime/100);
1182                         proto_item_append_text(ti,"%f",ms_lifetime);
1183                         proto_tree_add_uint_format(lft_tree,hf_bssgp_pdu_lifetime,tvb,offset+2,2,lifetime,"PDU Life time: %fs (%#.4x centi seconds)", ms_lifetime, lifetime);
1184                 }       
1185         }
1186 return 4;
1187 }
1188
1189 static int dcd_bssgp_prio(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
1190         guint8 code=0, len=0;
1191         proto_item *ti=NULL;
1192         proto_tree *prio_tree=NULL;
1193         
1194         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1195         if (dprm_p->tree){
1196                 code = tvb_get_guint8(tvb,offset);
1197                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, 4,"Priority");
1198                 prio_tree = proto_item_add_subtree(ti, ett_prio_tree);
1199                 proto_tree_add_uint_format(prio_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1200                 proto_tree_add_text(prio_tree,tvb,offset+1,1,"Length:%u",len);
1201         }
1202 return len+2;
1203 }
1204
1205 static int dcd_bssgp_qos(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
1206         guint16 blr=0;
1207         guint32 bps=0;
1208         char buf[16];
1209         gint8 disp=0, opet=0, code=0,len=0,start=0,pre=0;
1210         proto_item *ti=NULL, *ti2=NULL;
1211         proto_tree *qos_tree=NULL,*o5_tree;
1212         switch (dprm_p->type){
1213                 case 3:
1214                 break;  
1215                 case 4:
1216                        code = tvb_get_guint8(tvb,offset);
1217                        disp++;
1218                        len = tvb_get_guint8(tvb,offset+disp);
1219                        disp++;
1220                        len = len & 0x7f;
1221                 break;
1222         }
1223         start=disp;     
1224         blr = tvb_get_ntohs(tvb, offset+disp);
1225         disp = disp+2;
1226         opet = tvb_get_guint8(tvb,offset+disp);
1227         disp++;
1228         if (dprm_p->tree){
1229                 bps = 100*blr/8;
1230                 decode_bitfield_value(buf,opet,LOW3B,8);
1231                 pre = opet & LOW3B;
1232                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+disp,"QoS Profile IE");
1233                 qos_tree = proto_item_add_subtree(ti,ett_bssgp_qos);
1234                 switch (dprm_p->type){
1235                         case 4:
1236                                 proto_tree_add_uint_format(qos_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1237                                 proto_tree_add_text(qos_tree,tvb,offset+1,1,"Length:%u",len);
1238                         case 3:
1239                                 if (blr){
1240                                 proto_tree_add_uint_format(qos_tree,hf_bssgp_pbr,tvb,offset+start,2,blr,"Peak bit rate: %u bytes/s, (%#.4x)in 100bits/sec increments",bps,blr);
1241                                 }
1242                                 else{
1243                                 proto_tree_add_uint_format(qos_tree,hf_bssgp_pbr,tvb,offset+start,2,blr,"Peak bit rate: best effort (%#.4x)in  100bits/sec increments",blr);
1244                                 }
1245                                 ti2 = proto_tree_add_item(qos_tree,hf_bssgp_qos,tvb,offset+(disp-1),1,FALSE);
1246                                 o5_tree = proto_item_add_subtree(ti2, ett_bssgp_o5);
1247                                 proto_tree_add_boolean(o5_tree,hf_bssgp_qos_cr,tvb,offset+(disp-1),1,opet);
1248                                 proto_tree_add_boolean(o5_tree,hf_bssgp_qos_t,tvb,offset+(disp-1),1,opet);
1249                                 proto_tree_add_boolean(o5_tree,hf_bssgp_qos_a,tvb,offset+(disp-1),1,opet);
1250                                 if(tvb_get_guint8(tvb,0)){
1251                                 proto_tree_add_uint_format(o5_tree,hf_bssgp_qos_prec,tvb,offset+(disp-1),1,pre,"%s %s", buf,match_strval(pre,prec));
1252
1253                                 }
1254                                 else{
1255                                 proto_tree_add_uint_format(o5_tree,hf_bssgp_qos_prec,tvb,offset+(disp-1),1,pre,"%s %s", buf,match_strval(pre,prec_dl));
1256                                 }
1257                 }
1258                                 
1259         }
1260         return disp;
1261 }
1262
1263 static int dcd_bssgp_radio_caus(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){        
1264         guint8 code=0, len=0,racaus=0;
1265         proto_item *ti=NULL;
1266         proto_tree *racaus_tree=NULL;
1267         
1268         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1269         racaus = tvb_get_guint8(tvb,offset+2);
1270         code = tvb_get_guint8(tvb,offset);
1271         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1272                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %s",match_strval(code,bssgp_iei), val_to_str(racaus,radio_cause,"%u reserved value"));
1273                 }       
1274         if (dprm_p->tree){
1275                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %s", match_strval(code,bssgp_iei), val_to_str(racaus,radio_cause,"%u  reserved value, if received , it shall be handled as ""radio contact lost with MS"""));
1276                 racaus_tree = proto_item_add_subtree(ti, ett_racaus_tree);
1277                 proto_tree_add_uint_format(racaus_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1278                 proto_tree_add_uint_format(racaus_tree, hf_bssgp_radio_cause,tvb,offset+2,len,racaus,"%s: %#.2x",match_strval(code,bssgp_iei),racaus);
1279                 proto_tree_add_text(racaus_tree,tvb,offset+1,1,"Length:%u",len);
1280         }
1281 return len+2;
1282 }
1283
1284 /*static int dcd_bssgp_racap_upd(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
1285 };
1286 */
1287
1288 static int dcd_bssgp_ra(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){                
1289        guint16 lac;
1290         guint32 mnccc;
1291         guint8 rac, len = 0,code=0 ;
1292         char st_mccn[8];
1293         proto_item *ti=NULL;
1294         proto_tree *ra_tree = NULL;
1295         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1296         if (dprm_p->tree){
1297                 code = tvb_get_guint8(tvb,offset);
1298                 mnccc = tvb_get_ntoh24(tvb,offset+2);
1299                 lac = tvb_get_ntohs(tvb,offset+5);
1300                 rac = tvb_get_guint8(tvb,offset+7);
1301                 mccmnc(mnccc, st_mccn);
1302                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+2, "Routing area: %s %u %u",st_mccn,lac,rac);
1303                 ra_tree = proto_item_add_subtree(ti, ett_ra_tree);
1304                 proto_tree_add_uint_format(ra_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1305                 proto_tree_add_string_format(ra_tree,hf_bssgp_ra_mccmnc,tvb,offset+2,3,st_mccn,"MCC MNC: %s",st_mccn);
1306                 proto_tree_add_uint_format(ra_tree,hf_bssgp_ra_lac,tvb,offset+5,2,lac,"LAC: %u",lac);
1307                 proto_tree_add_uint_format(ra_tree,hf_bssgp_ra_rac,tvb,offset+7,1,rac,"RAC: %u",rac);
1308                 proto_tree_add_text(ra_tree,tvb,offset+1,1,"Length:%u",len);
1309         }
1310 return len+2;
1311 }
1312
1313 static int dcd_bssgp_r_def_ms(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){  
1314         guint8 code=0, len=0;
1315         guint16 bucket=0;
1316         proto_item *ti=NULL;
1317         proto_tree *rdefms_tree=NULL;
1318         
1319         if (dprm_p->tree){
1320                 len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1321                 code = tvb_get_guint8(tvb,offset);
1322                 bucket = tvb_get_ntohs(tvb,offset+2);
1323                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u bits/sec", match_strval(code,bssgp_iei),100*bucket);
1324                 rdefms_tree = proto_item_add_subtree(ti, ett_rdefms_tree);
1325                 proto_tree_add_uint_format(rdefms_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1326                 proto_tree_add_uint_format(rdefms_tree, hf_bssgp_r_defau_ms,tvb,offset+2,len,bucket,"%s in 100 bits/sec increments: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
1327                 proto_tree_add_text(rdefms_tree,tvb,offset+1,1,"Length:%u",len);
1328         }
1329 return len+2;
1330 }
1331
1332 /*static int dcd_bssgp_sus_ref_num(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
1333 };
1334 */
1335
1336 static int dcd_bssgp_tag(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
1337         guint8 code=0, len=0,tag=0;
1338         proto_item *ti=NULL;
1339         proto_tree *tag_tree=NULL;
1340         
1341         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1342         if (dprm_p->tree){
1343                 code = tvb_get_guint8(tvb,offset);
1344                 tag = tvb_get_guint8(tvb,offset+2);
1345                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2,"Tag: %u", tag);
1346                 tag_tree = proto_item_add_subtree(ti, ett_tag_tree);
1347                 proto_tree_add_uint_format(tag_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1348                 proto_tree_add_text(tag_tree,tvb,offset+1,1,"Length:%u",len);
1349         }
1350 return len+2;
1351 }
1352
1353 static int dcd_bssgp_tlli(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
1354         guint32 tlli;
1355         guint8 len=0, code=0, disp=0;
1356         proto_item *ti=NULL;
1357         proto_tree *tlli_tree=NULL;
1358         switch (dprm_p->type){
1359           case 3:
1360                  disp = 0;
1361                  break; 
1362           case 4:
1363                  code = tvb_get_guint8(tvb, offset);
1364                  disp++;
1365                  len = tvb_get_guint8(tvb,offset+disp);
1366                  len = len & 0x7f;
1367                  disp++;
1368                  break;
1369         }
1370         tlli = tvb_get_ntohl(tvb, offset+disp);
1371         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1372                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO,", TLLI: %X", tlli);
1373         }
1374         if (dprm_p->tree){
1375                 switch (dprm_p->type){
1376                         case 3:
1377                                 proto_tree_add_uint_format(dprm_p->tree,hf_bssgp_tlli,tvb,offset,4,tlli,"TLLI: %#.4x", tlli ); 
1378                         break;
1379                         case 4:
1380                                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+disp,"TLLI: %#.4x",tlli);
1381                                 tlli_tree =proto_item_add_subtree(ti,ett_bssgp_tlli);
1382                                 proto_tree_add_uint_format(tlli_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1383
1384                                 proto_tree_add_text(tlli_tree,tvb,offset+1,1,"Length:%u",len);
1385                                 proto_tree_add_uint_format(tlli_tree,hf_bssgp_tlli,tvb,offset+disp,len,tlli,"TLLI: %#.4x", tlli ); 
1386                                 
1387                 }
1388         }         
1389                   return 4 + disp;
1390 }
1391 /*static int dcd_bssgp_tlli_o(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
1392         return 6;
1393 };      
1394 */
1395
1396 /*static int dcd_bssgp_tmsi(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
1397 };
1398 */
1399 /*static int dcd_bssgp_trace_ref(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
1400 };
1401 */
1402 /*static int dcd_bssgp_trace_type(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
1403 };
1404 */
1405 /*static int dcd_bssgp_trans_id(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){        
1406 };
1407 */
1408 /*static int dcd_bssgp_trig_id(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1409 };
1410 */
1411 static int dcd_bssgp_num_oct_aff(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
1412         guint8 code=0, len=0;
1413         guint32 bucket=0;
1414         proto_item *ti=NULL;
1415         proto_tree *noaff_tree=NULL;
1416         
1417         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1418         if (dprm_p->tree){
1419                 code = tvb_get_guint8(tvb,offset);
1420                 bucket = tvb_get_ntoh24(tvb,offset+2);
1421                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u", match_strval(code,bssgp_iei), bucket);
1422                 noaff_tree = proto_item_add_subtree(ti, ett_noaff_tree);
1423                 proto_tree_add_uint_format(noaff_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1424                 proto_tree_add_uint_format(noaff_tree, hf_bssgp_noaff,tvb,offset+2,len,bucket,"%s: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
1425                 proto_tree_add_text(noaff_tree,tvb,offset+1,1,"Length:%u",len);
1426         }
1427 return len+2;
1428 }
1429
1430
1431 /* Code to actually dissect the packets */
1432 static void
1433 dissect_bssgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1434 {
1435 static dec_fu_param_stru_t decp , *decodeparam=&decp;
1436 guint8 pdutype, i, j , iele , stay;
1437 guint16 offset=1;
1438 tvbuff_t *next_tvb;
1439
1440 /* Set up structures needed to add the protocol subtree and manage it */
1441         proto_item *ti=NULL;
1442         proto_tree *bssgp_tree=NULL;
1443
1444         pdutype=tvb_get_guint8(tvb,0);
1445 /* Make entries in Protocol column and Info column on summary display */
1446         if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
1447                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BSSGP");
1448     
1449 /* This field shows up as the "Info" column in the display; you should make
1450    it, if possible, summarize what's in the packet, so that a user looking
1451    at the list of packets can tell what type of packet it is. See section 1.5
1452    for more information.
1453
1454    If you are setting it to a constant string, use "col_set_str()", as
1455    it's more efficient than the other "col_set_XXX()" calls.
1456
1457    If you're setting it to a string you've constructed, or will be
1458    appending to the column later, use "col_add_str()".
1459
1460    "col_add_fstr()" can be used instead of "col_add_str()"; it takes
1461    "printf()"-like arguments.  Don't use "col_add_fstr()" with a format
1462    string of "%s" - just use "col_add_str()" or "col_set_str()", as it's
1463    more efficient than "col_add_fstr()".
1464
1465    If you will be fetching any data from the packet before filling in
1466    the Info column, clear that column first, in case the calls to fetch
1467    data from the packet throw an exception because they're fetching data
1468    past the end of the packet, so that the Info column doesn't have data
1469    left over from the previous dissector; do
1470 */
1471         if (check_col(pinfo->cinfo, COL_INFO)) {
1472                 col_clear(pinfo->cinfo, COL_INFO);
1473                 col_add_str(pinfo->cinfo, COL_INFO,match_strval(pdutype,tab_bssgp_pdu_type));
1474         }
1475 /* In the interest of speed, if "tree" is NULL, don't do any work not
1476    necessary to generate protocol tree items. */
1477 /*        if (tree) { */
1478
1479 /* NOTE: The offset and length values in the call to
1480    "proto_tree_add_item()" define what data bytes to highlight in the hex
1481    display window when the line in the protocol tree display
1482    corresponding to that item is selected.
1483
1484    tvb_length(tvb) is a handy way to highlight all data from the offset to
1485    the end of the packet. */
1486
1487 /* create display subtree for the protocol */
1488 /*                ti = proto_tree_add_item(tree, proto_bssgp, tvb, 0, tvb_length(tvb), FALSE );
1489
1490                 bssgp_tree = proto_item_add_subtree(ti, ett_bssgp);
1491 */
1492         decodeparam->pinfo=pinfo;
1493         decodeparam->tree=tree;
1494                 i = 0;
1495                 stay = 1;
1496                 while (bssgp_pdu[i].infe[0].presence && stay){ 
1497                     if (bssgp_pdu[i].pdu == pdutype) { 
1498                          j = 0;   
1499                          stay = 0;
1500                          if (tree){
1501                                 ti = proto_tree_add_protocol_format(tree, proto_bssgp, tvb, 0, tvb_length(tvb),"BSS GPRS protocol PDU type: %s (%#.2x)", match_strval(pdutype,tab_bssgp_pdu_type), pdutype);
1502                                 bssgp_tree = proto_item_add_subtree(ti, ett_bssgp);
1503                                 proto_tree_add_uint_format(bssgp_tree, hf_bssgp_pdu_type, tvb, 0, offset, pdutype, "PDU type: %s  (%#.2x)",match_strval(pdutype,tab_bssgp_pdu_type), pdutype );
1504                         decodeparam->tree=bssgp_tree;   
1505                          }
1506                          while (bssgp_pdu[i].infe[j].presence){
1507                              switch(bssgp_pdu[i].infe[j].type){
1508                                case 3:
1509                                      decodeparam->type=3; 
1510                                      offset=offset+( *bssgp_pdu[i].infe[j].decode)(tvb, offset, decodeparam );     
1511                                      j++;
1512                                break;
1513                                case 4:
1514                                   decodeparam->type=4; 
1515                                   if (offset >= tvb_length(tvb)) {
1516                                       j++;
1517                                       break;
1518                                   }  
1519                                   iele = tvb_get_guint8( tvb, offset);
1520                                   while ((bssgp_pdu[i].infe[j].code != iele) && bssgp_pdu[i].infe[j].presence ) {
1521                                      if (bssgp_pdu[i].infe[j].presence > 1) j++;
1522                                      else break;
1523                                   }
1524                                   if (bssgp_pdu[i].infe[j].presence){
1525                                       offset=offset+( *bssgp_pdu[i].infe[j].decode)(tvb, offset, decodeparam );     
1526                                       if (iele == 0x0e ){
1527                                               next_tvb = tvb_new_subset(tvb, decodeparam->k, -1, -1);
1528                                               call_dissector(llcgprs_handle, next_tvb, pinfo, tree);
1529 /*                                            call_dissector(data_handle, next_tvb, pinfo, tree);
1530 */                                            
1531                                       }
1532                                       j++;
1533                                   }
1534                                 break;  
1535                              }
1536                          }    
1537                     }      
1538                     i++;                    
1539                   };
1540                         
1541 /* add an item to the subtree, see section 1.6 for more information */
1542 /*
1543                 proto_tree_add_uint(tree, hf_bssgp_FIELDABBREV, tvb, offset, len, value);
1544 */              
1545 /*                proto_tree_add_uint_format(bssgp_tree, hf_bssgp_pdu_type, tvb, 0, 1, pdutype, "PDU type: %s  (%#.2x)",match_strval(pdutype,tab_bssgp_pdu_type), pdutype );
1546 */
1547
1548 /* Continue adding tree items to process the packet here */
1549
1550
1551 /*        }*/
1552
1553 /* If this protocol has a sub-dissector call it here, see section 1.8 */
1554 }
1555
1556
1557 /* Register the protocol with Ethereal */
1558
1559 /* this format is require because a script is used to build the C function
1560    that calls all the protocol registration.
1561 */
1562
1563 void
1564 proto_register_bssgp(void)
1565 {                 
1566         static hf_register_info hf[] = {
1567                 { &hf_bssgp_pdu_type,
1568                         { "PDU", "bssgp.pdu",
1569                         FT_UINT8, BASE_HEX, VALS(tab_bssgp_pdu_type), 0x0,          
1570                         "BSSGP PDU", HFILL }},
1571                 {&hf_bssgp_tlli,
1572                         { "TLLI","bssgp.tlli",FT_UINT32, BASE_HEX, NULL,0x0,"Current TLLI",HFILL}},
1573                 {&hf_bssgp_ietype,
1574                         {"IE Type", "bssgp.ietype", FT_UINT8, BASE_HEX, VALS(bssgp_iei),0x0,"Information element", HFILL }},
1575                 {&hf_bssgp_pbr,
1576                          {"QoS_Profile","bssgp.pbr",FT_UINT16, BASE_HEX, NULL, 0x0, "Peak bit rate",HFILL }},
1577                 {&hf_bssgp_qos,
1578                         {"Last byte QoS Profile","bssgp.qos",FT_UINT8, BASE_HEX, NULL, 0x0,"5th byte of QoS profile(contains Precedence..)",HFILL}},
1579                 {&hf_bssgp_qos_cr,
1580                         {"C/R bit","bssgp.qos.cr",FT_BOOLEAN,8, TFS(&cr_string),QOSO5CR,"The SDU contains LLC ACK/SACK command/responce frame type",HFILL }},
1581                 {&hf_bssgp_qos_t,
1582                         {"T bit", "bssgp.qos.t", FT_BOOLEAN, 8, TFS( &t_string) , QOSO5T, "The SDU contains signaling/data" , HFILL}},
1583                 {&hf_bssgp_qos_a,
1584                         {"A bit" , "bssgp.qos.a" , FT_BOOLEAN,8, TFS( &a_string), QOSO5A, "Radio interface uses ARQ/UNITDATA functionality",HFILL}},
1585                 {&hf_bssgp_qos_prec,
1586                         {"Precedence", "bssgp.qos.prec", FT_UINT8,BASE_HEX ,VALS(prec_both), 0x0,"Precedence coding", HFILL }},
1587                 {&hf_bssgp_pdu_lifetime,
1588                         {"PDU Lifetime","bssgp.lft", FT_UINT16, BASE_HEX, NULL, 0x0, "PDU Lifetime for PDU inside the BSS",HFILL}},
1589                 {&hf_bssgp_imsi,
1590                         {"IMSI","bssgp.imsi", FT_STRING, BASE_DEC, NULL, 0x0, "International Mobile Subscriber Identity",HFILL}},
1591                 {&hf_bssgp_imsi_toi,
1592                         { "Type of Mobile identity", "bssgp.mobid", FT_UINT8, BASE_HEX, VALS(type_of_identity), LOW3B, "Type of mobile identity",HFILL }},
1593                 {&hf_bssgp_imsi_even_odd_indic,
1594                         { "Odd/even indication", "bssgp.oei", FT_BOOLEAN, 8, TFS(&imsi_odd_even), ODD_EVEN_INDIC, "Odd/even indication",HFILL }},
1595                 {&hf_bssgp_imsi_lsix,
1596                         {"IMSI last ten numbers","bssgp.imsi.last10num",FT_STRING, BASE_NONE, NULL, 0x0, "Last ten numbers of IMSI",HFILL}},
1597                 {&hf_bssgp_bvc_buck_size,
1598                         {"Bmax(in 100 oct incr)","bssgp.bmax", FT_UINT16, BASE_HEX, NULL, 0x0, "BVC Bucket Size in 100 octet increments",HFILL}},
1599                 {&hf_bssgp_buck_leak_rate,
1600                         {"Bucket Leak Rate","bssgp.R", FT_UINT16, BASE_HEX, NULL, 0x0, "Bucket Leak Rate in 100 bits/sec increments",HFILL}},
1601                 {&hf_bssgp_bmax_def_ms,
1602                         {"Bmax default MS","bssgp.bmaxms", FT_UINT16, BASE_HEX, NULL, 0x0, "Default bucket size in 100 octetsincrement for an MS",HFILL}},
1603                 {&hf_bssgp_r_defau_ms,
1604                         {"R default MS","bssgp.Rms", FT_UINT16, BASE_HEX,NULL, 0x0, "Dfeault bucket leak rate to be applied to a flow control bucket for an MS", HFILL}},
1605                 {&hf_bssgp_bvci,
1606                         {"BVCI","bssgp.bvci",FT_UINT16, BASE_HEX, NULL, 0x0, "BSSGP Virtual Connection Identifier", HFILL}},
1607                 {&hf_bssgp_cause,
1608                         {"Cause","bssgp.cause", FT_UINT8, BASE_HEX, NULL,0x0, " Cause information element  indicates the reason for an exception condition",HFILL }},
1609                 {&hf_bssgp_bvci_new,{"BVCI(New)","bssgp.bvci.new",FT_UINT16, BASE_HEX, NULL, 0x0, "BSSGP Virtual Connection Identifier", HFILL}},
1610                 {&hf_bssgp_frdsc,
1611                         {"LLC frames discarded","bssgp.llcdisc.frames", FT_UINT8, BASE_HEX, NULL, 0x0,"LLC frames that have been discarded inside BSS", HFILL}},
1612                 {&hf_bssgp_noaff,
1613                         {"Number of octets affected","bssgp.noaff", FT_UINT24, BASE_HEX,NULL,0x0,"It indicates,for MS,the number of octets transferred or deleted by BSS",HFILL}},
1614                 {&hf_bssgp_radio_cause,
1615                         {"Radio Cause","bssgp.racase", FT_UINT8, BASE_HEX, NULL, 0x0, "Reason for an exception condition on the radio interface",HFILL}},
1616                 {&hf_bssgp_ra_mccmnc,
1617                         {"MCC and MNC","bssgp.ra.mccmnc", FT_STRING, BASE_DEC, NULL, 0x0, "Mobile country code and Mobile network code", HFILL}},
1618                 {&hf_bssgp_ra_lac,
1619                         {"LAC","bssgp.ra.lac",FT_UINT16, BASE_HEX, NULL, 0x0, "Location area code",HFILL }},
1620                 {&hf_bssgp_ra_rac,
1621                         {"RAC","bssgp.ra.rac",FT_UINT8, BASE_HEX, NULL, 0x0, "Routing area code", HFILL }},
1622                 {&hf_bssgp_cid,
1623                         {"Cell id","bssgp.cid",FT_UINT16, BASE_HEX, NULL, 0x0, "Cell identity", HFILL }},
1624         };
1625
1626 /* Setup protocol subtree array */
1627         static gint *ett[] = {
1628                 &ett_bssgp,
1629                 &ett_bssgp_tlli,
1630                 &ett_bssgp_qos,
1631                 &ett_bssgp_o5,
1632                 &ett_bssgp_lft,
1633                 &ett_bssgp_racc,
1634                 &ett_prio_tree,
1635                 &ett_drx_tree,
1636                 &ett_bssgp_imsi,
1637                 &ett_bssgp_imsi_stru_tree,
1638                 &ett_algn_tree,
1639                 &ett_b_llc_tree,
1640                 &ett_celid_tree,
1641                 &ett_tag_tree,
1642                 &ett_bsize_tree,
1643                 &ett_bucklr_tree,
1644                 &ett_bmaxms_tree,
1645                 &ett_rdefms_tree,
1646                 &ett_bvci_tree,
1647                 &ett_bvcin_tree,
1648                 &ett_cause_tree,
1649                 &ett_frdsc_tree,
1650                 &ett_noaff_tree,
1651                 &ett_racaus_tree,
1652                 &ett_ra_tree
1653         };
1654
1655 /* Register the protocol name and description */
1656         proto_bssgp = proto_register_protocol("BSS GPRS Protocol",
1657             "BSSGP", "bssgp");
1658
1659 /* Required function calls to register the header fields and subtrees used */
1660         proto_register_field_array(proto_bssgp, hf, array_length(hf));
1661         proto_register_subtree_array(ett, array_length(ett));
1662         register_dissector("bssgp", dissect_bssgp, proto_bssgp);
1663 }
1664
1665
1666 /* If this dissector uses sub-dissector registration add a registration routine.
1667    This format is required because a script is used to find these routines and
1668    create the code that calls these routines.
1669 */
1670 void
1671 proto_reg_handoff_bssgp(void)
1672 {
1673 /*        dissector_handle_t bssgp_handle;
1674
1675         bssgp_handle = create_dissector_handle(dissect_bssgp,
1676             proto_bssgp);
1677 */
1678 /*        dissector_add("fr.nspduname", NS_UNITDATA, bssgp_handle);*/
1679 /*        dissector_add("fr.nspduname", 0x0, bssgp_handle);
1680 */      
1681 /*        dissector_add("fr.ietf", 0x0, bssgp_handle);
1682 */        
1683 /*        data_handle = find_dissector("data");
1684 */
1685           llcgprs_handle = find_dissector ("llcgprs");
1686 }