Note that for THE3GPP_IPV6_DNS_SERVERS we probably *do* need to handle
[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.8 2003/12/28 12:43:38 ulfl 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 /*static dissector_handle_t llcgprs_handle;
321 */
322 /* Initialize the subtree pointers */
323 static gint ett_bssgp = -1;
324 static gint ett_bssgp_tlli = -1;
325 static gint ett_bssgp_qos = -1;
326 static gint ett_bssgp_o5 = -1;
327 static gint ett_bssgp_lft = -1;
328 static gint ett_bssgp_racc = -1;
329 static gint ett_prio_tree = -1;
330 static gint ett_drx_tree = -1;
331 static gint ett_bssgp_imsi = -1;
332 static gint ett_bssgp_imsi_stru_tree = -1;
333 static gint ett_algn_tree = -1;
334 static gint ett_b_llc_tree = -1;
335 static gint ett_celid_tree = -1;
336 static gint ett_tag_tree = -1;
337 static gint ett_bsize_tree = -1;
338 static gint ett_bucklr_tree = -1;
339 static gint ett_bmaxms_tree = -1;
340 static gint ett_rdefms_tree = -1;
341 static gint ett_bvci_tree = -1;
342 static gint ett_bvcin_tree = -1;
343 static gint ett_cause_tree = -1;
344 static gint ett_frdsc_tree = -1;
345 static gint ett_noaff_tree = -1;
346 static gint ett_racaus_tree = -1;
347 static gint ett_ra_tree = -1;
348 /*Functions for decoding IEs of BSSGP V6.7.1 */
349 typedef struct {
350         int type;
351         packet_info *pinfo;
352         proto_tree *tree;
353         int k;
354 } dec_fu_param_stru_t;  
355 static int dcd_bssgp_algn       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
356 static int dcd_bssgp_bmaxms     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
357 /*static int dcd_bssgp_bss_aind ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
358 */
359 static int dcd_bssgp_bucklr     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
360 static int dcd_bssgp_bvci       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
361 static int dcd_bssgp_bvci_n     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
362 static int dcd_bssgp_bvc_bsize  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
363 /*static int dcd_bssgp_bvc_meas ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
364 */
365 static int dcd_bssgp_cause      ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
366 static int dcd_bssgp_cellid     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
367 /*static int dcd_bssgp_chan_need        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
368 */
369 static int dcd_bssgp_drx        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
370 /*static int dcd_bssgp_emlpp_prio       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
371 static int dcd_bssgp_flush_act  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
372 */
373 static int dcd_bssgp_imsi       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
374 static int dcd_bssgp_llc_pdu    ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
375 static int dcd_bssgp_llc_frdsc  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
376 /*static int dcd_bssgp_la               ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
377 static int dcd_bssgp_mid        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
378 static int dcd_bssgp_ms_buck    ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
379 */
380 static int dcd_bssgp_radio_acc  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
381 /*static int dcd_bssgp_omc_id   ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
382 */
383 /*static int dcd_bssgp_pdu_err  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
384 */
385 static int dcd_bssgp_pdu_life   ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
386 static int dcd_bssgp_prio       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
387 static int dcd_bssgp_qos        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
388 static int dcd_bssgp_radio_caus ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
389 /*static int dcd_bssgp_racap_upd        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
390 */
391 static int dcd_bssgp_ra         ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
392 static int dcd_bssgp_r_def_ms   ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
393 /*static int dcd_bssgp_sus_ref_num( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
394 */
395 static int dcd_bssgp_tag        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
396 static int dcd_bssgp_tlli       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
397 /*static int dcd_bssgp_tlli_o   ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
398 */
399 /*static int dcd_bssgp_tmsi     ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
400 */
401 /*static int dcd_bssgp_trace_ref        ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
402 */
403 /*static int dcd_bssgp_trace_type       ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
404 */
405 /*static int dcd_bssgp_trans_id ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
406 */
407 /*static int dcd_bssgp_trig_id  ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
408 */
409 static int dcd_bssgp_num_oct_aff( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
410 static int dcd_bssgp_not_yet_dcd( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
411 static void mccmnc(guint32 mcmn, char buf[]);
412 /*---------------------------------------------------------*/
413 typedef struct _bssgp_ie {
414         guint8  code;
415         guint8 presence;
416         guint8 type;
417 /*      int (*decode)(tvbuff_t *, int, int, packet_info *, proto_tree *);
418 */
419         int (*decode)(tvbuff_t *, int, dec_fu_param_stru_t *);
420         } bssgp_ie_t;
421 typedef struct _bssgp_pdu {
422         guint8 pdu;
423         bssgp_ie_t infe[12];
424 } _bssgp_pdu_t;
425 /*------------------------------------------------------------*/
426 static _bssgp_pdu_t bssgp_pdu[] = {
427         {
428                 DL_UNITDATA, {
429                         { 0x1f, BSSGP_M, 3, dcd_bssgp_tlli },
430                         { 0x18, BSSGP_M, 3, dcd_bssgp_qos },
431                         { 0x16, BSSGP_M, 4, dcd_bssgp_pdu_life },
432                         { 0x13, BSSGP_O, 4, dcd_bssgp_radio_acc },
433                         { 0x17, BSSGP_O, 4, dcd_bssgp_prio },
434                         { 0x0a, BSSGP_O, 4, dcd_bssgp_drx },
435                         { 0x0d, BSSGP_O, 4, dcd_bssgp_imsi },
436 /*                      { 0x1f, BSSGP_O, 4, dcd_bssgp_tlli_o },
437 */                      
438                         { 0x1f, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
439                         { 0x00, BSSGP_O, 4, dcd_bssgp_algn },
440                         { 0x0e, BSSGP_M, 4, dcd_bssgp_llc_pdu },
441                         { 0,0,0,NULL }
442                 }       
443                 
444         },
445         {
446                 UL_UNITDATA, {
447                         { 0x1f, BSSGP_M, 3, dcd_bssgp_tlli },
448                         { 0x18, BSSGP_M, 3, dcd_bssgp_qos },
449                         { 0x08, BSSGP_M, 4, dcd_bssgp_cellid },
450                         { 0x00, BSSGP_O, 4, dcd_bssgp_algn },
451                         { 0x0e, BSSGP_M, 4, dcd_bssgp_llc_pdu },
452                         { 0,0,0,NULL }
453                 }
454         },
455         {
456                 RA_CAPABILITY, {
457                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
458                         { 0x13, BSSGP_M, 4, dcd_bssgp_radio_acc },
459                         { 0,0,0,NULL }
460                 }
461         },
462         {
463                 PAGING_PS, {
464                         { 0x0d, BSSGP_M, 4, dcd_bssgp_imsi },
465                         { 0x0a, BSSGP_O, 4, dcd_bssgp_drx },
466                         { 0x04, BSSGP_C, 4, dcd_bssgp_bvci },
467 /*                      { 0x10, BSSGP_C, 4, dcd_bssgp_la },
468 */                      
469                         { 0x10, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
470                         { 0x1b, BSSGP_C, 4, dcd_bssgp_ra },
471 /*                      { 0x02, BSSGP_C, 4, dcd_bssgp_bss_aind },
472 */                      
473                         { 0x02, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
474                         { 0x18, BSSGP_M, 4, dcd_bssgp_qos },
475 /*                      { 0x20, BSSGP_O, 4, dcd_bssgp_tmsi },
476 */                      
477                         { 0x20, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
478                         { 0,0,0,NULL }
479                 }
480         },
481         {
482                 PAGING_CS, {
483                         { 0x0d, BSSGP_M, 4, dcd_bssgp_imsi },
484                         { 0x0a, BSSGP_M, 4, dcd_bssgp_drx },
485                         { 0x04, BSSGP_C, 4, dcd_bssgp_bvci },
486 /*                      { 0x10, BSSGP_C, 4, dcd_bssgp_la },
487 */                      
488                         { 0x10, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
489                         { 0x1b, BSSGP_C, 4, dcd_bssgp_ra },
490 /*                      { 0x02, BSSGP_C, 4, dcd_bssgp_bss_aind },
491 */                      
492                         { 0x02, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
493                         { 0x1f, BSSGP_O, 4, dcd_bssgp_tlli },
494 /*                      { 0x09, BSSGP_O, 4, dcd_bssgp_chan_need },
495 */                      
496                         { 0x09, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
497 /*                      { 0x0b, BSSGP_O, 4, dcd_bssgp_emlpp_prio },
498 */                      
499                         { 0x0b, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
500 /*                      { 0x20, BSSGP_O, 4, dcd_bssgp_tmsi },
501 */                      
502                         { 0x20, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
503                         { 0,0,0,NULL }
504                 }
505         },
506         {
507                 RA_CAPABILITY_UPDATE, {
508                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
509                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
510                         { 0,0,0,NULL }
511                 }
512                 
513         },
514         {
515                  RA_CAPABILITY_UPDATE_ACK, {
516                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
517                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
518                         { 0x0d, BSSGP_O, 4, dcd_bssgp_imsi },
519 /*                      { 0x1a, BSSGP_M, 4, dcd_bssgp_racap_upd },
520 */                      
521                         { 0x1a, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
522                         { 0x13, BSSGP_C, 4, dcd_bssgp_radio_acc },
523                         { 0,0,0,NULL }
524                  }
525         },
526         {
527                 RADIO_STATUS, {
528                         { 0x1f, BSSGP_C, 4, dcd_bssgp_tlli },
529 /*                      { 0x20, BSSGP_C, 4, dcd_bssgp_tmsi },
530 */                      
531                         { 0x20, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
532                         { 0x0d, BSSGP_C, 4, dcd_bssgp_imsi },
533                         { 0x19, BSSGP_M, 4, dcd_bssgp_radio_caus },
534                         { 0,0,0,NULL }
535                 }
536         },
537         {
538                 SUSPEND, {
539                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
540                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
541                         { 0,0,0,NULL }
542                 }
543         },
544         {
545                  SUSPEND_ACK, {
546                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
547                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
548 /*                      { 0x1d, BSSGP_M, 4, dcd_bssgp_sus_ref_num },
549 */                      
550                         { 0x1d, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
551                         { 0,0,0,NULL }
552                  }
553         },
554         {
555                  SUSPEND_NACK, {
556                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
557                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
558                         { 0x07, BSSGP_O, 4, dcd_bssgp_cause },
559                         { 0,0,0,NULL }
560                  }
561         },
562         {
563                 RESUME, {
564                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
565                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
566 /*                      { 0x1d, BSSGP_M, 4, dcd_bssgp_sus_ref_num },
567 */                      
568                         { 0x1d, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
569                         { 0,0,0,NULL }
570                 }
571         },
572         {
573                 RESUME_ACK, {
574                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
575                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
576                         { 0,0,0,NULL }
577                 }
578         },
579         {
580                  RESUME_NACK, {
581                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
582                         { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
583                         { 0x07, BSSGP_O, 4, dcd_bssgp_cause },
584                         { 0,0,0,NULL }
585                  }
586         },
587         {
588                 BVC_BLOCK, {
589                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
590                         { 0x07, BSSGP_M, 4, dcd_bssgp_cause },
591                         { 0,0,0,NULL }
592                 }
593         },
594         {
595                 BVC_BLOCK_ACK, {
596                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
597                         { 0,0,0,NULL }
598                 }
599         },
600         {
601                 BVC_RESET, {
602                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
603                         { 0x07, BSSGP_M, 4, dcd_bssgp_cause },
604                         { 0x08, BSSGP_C, 4, dcd_bssgp_cellid },
605                         { 0,0,0,NULL }
606                 }
607         },
608         {
609                 BVC_RESET_ACK, {
610                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
611                         { 0x08, BSSGP_C, 4, dcd_bssgp_cellid },
612                         { 0,0,0,NULL }
613                 }
614         },
615         {
616                  BVC_UNBLOCK, {
617                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
618                         { 0,0,0,NULL }
619                  }
620         },
621         {
622                  BVC_UNBLOCK_ACK, {
623                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
624                         { 0,0,0,NULL }
625                  }
626         },
627         {
628                 FLOW_CONTROL_BVC, {
629                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
630                         { 0x05, BSSGP_M, 4, dcd_bssgp_bvc_bsize },
631                         { 0x03, BSSGP_M, 4, dcd_bssgp_bucklr },
632                         { 0x01, BSSGP_M, 4, dcd_bssgp_bmaxms },
633                         { 0x1c, BSSGP_M, 4, dcd_bssgp_r_def_ms },
634 /*                      { 0x06, BSSGP_O, 4, dcd_bssgp_bvc_meas }, */
635                         { 0x06, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
636                         { 0,0,0,NULL }
637                 }
638         },
639         {
640                  FLOW_CONTROL_BVC_ACK, {
641                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
642                         { 0,0,0,NULL }
643                  }
644         },
645         {
646                  FLOW_CONTROL_MS, {
647                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
648                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
649 /*                      { 0x12, BSSGP_M, 4, dcd_bssgp_ms_buck},
650 */                      
651                         { 0x12, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
652                         { 0x03, BSSGP_M, 4, dcd_bssgp_bucklr },
653                         { 0,0,0,NULL }
654                  }
655         },
656         {
657                 FLOW_CONTROL_MS_ACK, {
658                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
659                         { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
660                         { 0,0,0,NULL }
661                 }
662         },
663         {
664                 FLUSH_LL, {
665                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
666                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
667                         { 0x04, BSSGP_O, 4, dcd_bssgp_bvci_n },
668                         { 0,0,0,NULL }
669                 }
670         },
671         {
672                 FLUSH_LL_ACK, {
673                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
674 /*                      { 0x0c, BSSGP_M, 4, dcd_bssgp_flush_act },
675 */                      
676                         { 0x0c, BSSGP_M, 4, dcd_bssgp_not_yet_dcd },
677                         { 0x04, BSSGP_C, 4, dcd_bssgp_bvci_n },
678                         { 0x25, BSSGP_M, 4, dcd_bssgp_num_oct_aff }, 
679                         { 0,0,0,NULL }
680                 }
681         },
682         {
683                 LLC_DISCARDED, {
684                         { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
685                         { 0x0f, BSSGP_M, 4, dcd_bssgp_llc_frdsc },
686                         { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
687                         { 0x25, BSSGP_M, 4, dcd_bssgp_num_oct_aff }, 
688                         { 0,0,0,NULL }
689                 }
690         },
691         {
692                 SGSN_INVOKE_TRACE, {
693 /*                      { 0x22, BSSGP_M, 4, dcd_bssgp_trace_type },
694                         { 0x21, BSSGP_M, 4, dcd_bssgp_trace_ref },
695                         { 0x24, BSSGP_O, 4, dcd_bssgp_trig_id },
696                         { 0x11, BSSGP_O, 4, dcd_bssgp_mid },
697                         { 0x14, BSSGP_O, 4, dcd_bssgp_omc_id },
698                         { 0x23, BSSGP_O, 4, dcd_bssgp_trans_id },
699 */                      
700                         { 0x22, BSSGP_M, 4, dcd_bssgp_not_yet_dcd },
701                         { 0x21, BSSGP_M, 4, dcd_bssgp_not_yet_dcd },
702                         { 0x24, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
703                         { 0x11, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
704                         { 0x14, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
705                         { 0x23, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
706                         { 0,0,0,NULL }
707                 }
708         },
709         {
710                 STATUS, {
711                         { 0x07, BSSGP_M, 4, dcd_bssgp_cause },
712                         { 0x04, BSSGP_C, 4, dcd_bssgp_bvci },
713 /*                      { 0x15, BSSGP_O, 4, dcd_bssgp_pdu_err },
714 */                      
715                         { 0x15, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
716                         { 0,0,0,NULL }
717                 }
718         },
719         {
720                 0, {
721                         { 0,0,0,NULL }
722                 }
723         }
724 };
725 /*-----------------------------------------------------------------------------------------------------------------*/
726 static void mccmnc(guint32 mcmn, char buf[]){
727        typedef struct {
728                 guint32 mnc1 : 4 ;
729                 guint32 mnc2 : 4 ;
730                 guint32 mcc3 : 4 ;
731                 guint32 mnc3 : 4 ;
732                 guint32 mcc1 : 4 ;
733                 guint32 mcc2 : 4 ;              
734         } stru_mncmcc;
735         typedef union {
736                 guint32 i;
737                 stru_mncmcc s;
738         } u_mncmcc;
739         u_mncmcc  *r_mncmcc;
740         guint8 pom =0,i=0 ;
741                 r_mncmcc = (u_mncmcc *)&mcmn;
742                 for (i=0;i<8;i++){
743                   switch (i) {
744                           case 0 :
745                                   pom = r_mncmcc->s.mcc1;
746                                 break;
747                           case 1 :      
748                                   pom = r_mncmcc->s.mcc2;
749                                 break;
750                           case 2 :
751                                   pom = r_mncmcc->s.mcc3;
752                                 break;
753                           case 3 :
754                                   pom = 0x61;/* 0x61 because i need space " " (0x61-1)^0x40*/   
755                                 break;
756                           case 4 :
757                                   pom = r_mncmcc->s.mnc1;
758                                 break;
759                           case 5 :
760                                   pom = r_mncmcc->s.mnc2;
761                                 break;
762                           case 6 :
763                                   pom = r_mncmcc->s.mnc3;         
764                                   pom = (pom == 0xf)?0x41: pom;/* 0x41 because i need null on the end of string (0x41-1)^0x40*/
765                                 break;
766                           case 7 :
767                                  pom = 0x41;
768                                 break;           
769                                           
770                   }
771                                   pom = (pom > 9)?(pom-1) ^ 0x40: pom ^ 0x30;
772                                   buf[i] = pom;
773                 }
774 }
775 static int dcd_bssgp_not_yet_dcd(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
776         guint8 code=0, pom=0,k=2;
777         guint16 llen=0;
778         
779         pom = tvb_get_guint8(tvb,offset+1);
780         if ( pom >= 128 ){
781                 llen = pom & 0x7f;
782                 k = 2;
783         }
784         else{ 
785                 llen = tvb_get_ntohs( tvb, offset+1);
786                 k=3;    
787         }
788         if (dprm_p->tree){
789                 code = tvb_get_guint8(tvb,offset);
790                 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);
791         }
792 return llen+k;
793 }
794 static int dcd_bssgp_algn(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
795         guint8 code=0, len=0;
796         proto_item *ti=NULL;
797         proto_tree *algn_tree=NULL;
798         
799         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
800         if (dprm_p->tree){
801                 code = tvb_get_guint8(tvb,offset);
802                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%u Aligment octets", len+2 );
803                 algn_tree = proto_item_add_subtree(ti, ett_algn_tree);
804                 proto_tree_add_uint_format(algn_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
805                 proto_tree_add_text(algn_tree,tvb,offset+1,1,"Length:%u",len);
806         }
807 return len+2;
808 }
809 static int dcd_bssgp_bmaxms(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
810         guint8 code=0, len=0;
811         guint16 bucket=0;
812         proto_item *ti=NULL;
813         proto_tree *bmaxms_tree=NULL;
814         
815         if (dprm_p->tree){
816                 len = tvb_get_guint8(tvb,offset+1) & 0x7f;
817                 code = tvb_get_guint8(tvb,offset);
818                 bucket = tvb_get_ntohs(tvb,offset+2);
819                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u bytes", match_strval(code,bssgp_iei),100*bucket);
820                 bmaxms_tree = proto_item_add_subtree(ti, ett_bmaxms_tree);
821                 proto_tree_add_uint_format(bmaxms_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
822                 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);
823                 proto_tree_add_text(bmaxms_tree,tvb,offset+1,1,"Length:%u",len);
824         }
825 return len+2;
826 }
827 /*static int dcd_bssgp_bss_aind(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){        
828 };
829 */
830 static int dcd_bssgp_bucklr(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
831         guint8 code=0, len=0;
832         guint16 bucket=0;
833         proto_item *ti=NULL;
834         proto_tree *bucklr_tree=NULL;
835         
836         bucket = tvb_get_ntohs(tvb,offset+2);
837         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
838         code = tvb_get_guint8(tvb,offset);
839         
840         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
841                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u bits/sec",match_strval(code,bssgp_iei),bucket*100 );
842                 }       
843         if (dprm_p->tree){
844                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "Bucket Leak Rate(R): %u bits/sec", 100*bucket);
845                 bucklr_tree = proto_item_add_subtree(ti, ett_bucklr_tree);
846                 proto_tree_add_uint_format(bucklr_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
847                 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);
848                 proto_tree_add_text(bucklr_tree,tvb,offset+1,1,"Length:%u",len);
849         }
850 return len+2;
851 }
852 static int dcd_bssgp_bvci(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
853         guint8 code=0, len=0;
854         guint16 bucket=0;
855         proto_item *ti=NULL;
856         proto_tree *bvci_tree=NULL;
857         
858         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
859         code = tvb_get_guint8(tvb,offset);
860         bucket = tvb_get_ntohs(tvb,offset+2);
861         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
862                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u",match_strval(code,bssgp_iei),bucket );
863                 }       
864         if (dprm_p->tree){
865                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u", match_strval(code,bssgp_iei), bucket);
866                 bvci_tree = proto_item_add_subtree(ti, ett_bvci_tree);
867                 proto_tree_add_uint_format(bvci_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
868                 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);
869                 proto_tree_add_text(bvci_tree,tvb,offset+1,1,"Length:%u",len);
870         }
871 return len+2;
872 }
873 static int dcd_bssgp_bvci_n(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
874         guint8 code=0, len=0;
875         guint16 bucket=0;
876         proto_item *ti=NULL;
877         proto_tree *bvcin_tree=NULL;
878         
879         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
880         code = tvb_get_guint8(tvb,offset);
881         bucket = tvb_get_ntohs(tvb,offset+2);
882         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
883                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, " New %s: %u",match_strval(code,bssgp_iei),bucket );
884                 }       
885         if (dprm_p->tree){
886                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "New %s: %u", match_strval(code,bssgp_iei), bucket);
887                 bvcin_tree = proto_item_add_subtree(ti, ett_bvcin_tree);
888                 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);
889                 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);
890                 proto_tree_add_text(bvcin_tree,tvb,offset+1,1,"Length:%u",len);
891         }
892 return len+2;
893 }
894 static int dcd_bssgp_bvc_bsize(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
895         guint8 code=0, len=0;
896         guint16 bucket=0;
897         proto_item *ti=NULL;
898         proto_tree *bsize_tree=NULL;
899         
900         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
901         code = tvb_get_guint8(tvb,offset);
902         bucket = tvb_get_ntohs(tvb,offset+2);
903         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
904                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u bytes",match_strval(code,bssgp_iei),bucket*100 );
905                 }       
906         if (dprm_p->tree){
907                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "BVC Bucket Size: %u bytes", 100*bucket);
908                 bsize_tree = proto_item_add_subtree(ti, ett_bsize_tree);
909                 proto_tree_add_uint_format(bsize_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
910                 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);
911                 proto_tree_add_text(bsize_tree,tvb,offset+1,1,"Length:%u",len);
912         }
913 return len+2;
914 }
915 /*static int dcd_bssgp_bvc_meas(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){        
916 return 4;
917 };
918 */
919 static int dcd_bssgp_cause(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){     
920         guint8 code=0, len=0,cause=0;
921         proto_item *ti=NULL;
922         proto_tree *cause_tree=NULL;
923         
924         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
925         code = tvb_get_guint8(tvb,offset);
926         cause = tvb_get_guint8(tvb,offset+2);
927         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
928                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %s",match_strval(code,bssgp_iei),match_strval(cause,bssgp_cause));
929                 }       
930         if (dprm_p->tree){
931                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %s", match_strval(code,bssgp_iei),match_strval(cause,bssgp_cause));
932                 cause_tree = proto_item_add_subtree(ti, ett_cause_tree);
933                 proto_tree_add_uint_format(cause_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
934                 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);
935                 proto_tree_add_text(cause_tree,tvb,offset+1,1,"Length:%u",len);
936         }
937 return len+2;
938 }
939
940 static int dcd_bssgp_cellid(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
941         char mccmnc_str[8];
942         guint32 mnccc;
943         guint16 lac,cid;
944         guint8 len=8, code=0,rac;
945         proto_item *ti = NULL;
946         proto_tree *celid_tree = NULL;
947         
948         if (dprm_p->tree){
949                 code = tvb_get_guint8(tvb,offset);
950                 mnccc = tvb_get_ntoh24(tvb,offset+2);
951                 lac = tvb_get_ntohs(tvb,offset+5);
952                 rac = tvb_get_guint8(tvb,offset+7);
953                 cid = tvb_get_ntohs(tvb,offset+8);
954                 mccmnc(mnccc, mccmnc_str);
955
956                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "Cell Identifier: %s %u %u %u",mccmnc_str,lac,rac,cid);
957                 celid_tree = proto_item_add_subtree(ti, ett_celid_tree);
958                 proto_tree_add_uint_format(celid_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
959                 proto_tree_add_string_format(celid_tree,hf_bssgp_ra_mccmnc,tvb,offset+2,3,mccmnc_str,"MCC MNC: %s",mccmnc_str);
960                 proto_tree_add_uint_format(celid_tree,hf_bssgp_ra_lac,tvb,offset+5,2,lac,"LAC: %u",lac);
961                 proto_tree_add_uint_format(celid_tree,hf_bssgp_ra_rac,tvb,offset+7,1,rac,"RAC: %u",rac);
962                 proto_tree_add_uint_format(celid_tree,hf_bssgp_cid,tvb,offset+8,2,cid,"Cell Id: %u",cid);
963                 proto_tree_add_text(celid_tree,tvb,offset+1,1,"Length:%u",len);
964                 
965         }
966          
967         return len+2;
968 }
969
970 /*static int dcd_bssgp_chan_need(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
971 };
972 */
973 static int dcd_bssgp_drx(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
974         guint8 code=0, len=0;
975         proto_item *ti=NULL;
976         proto_tree *drx_tree=NULL;
977         
978         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
979         if (dprm_p->tree){
980                 code = tvb_get_guint8(tvb,offset);
981                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, 4,"DRX Parameters");
982                 drx_tree = proto_item_add_subtree(ti, ett_drx_tree);
983                 proto_tree_add_uint_format(drx_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
984                 proto_tree_add_text(drx_tree,tvb,offset+1,1,"Length:%u",len);
985         }
986 return len+2;
987         
988 }
989
990 /*static int dcd_bssgp_emlpp_prio(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
991 };
992 */
993
994 /*static int dcd_bssgp_flush_act(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
995 };
996 */
997
998 static int dcd_bssgp_imsi(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
999         guint8  nextb=0, first_b=0, toi=0, i, k;
1000         guint8  num=0,code=0,len=0;
1001         char buf[17],imsi_mccn[6],imsi_val[11], toibuf[9];
1002         proto_item *ti=NULL, *ti2=NULL;
1003         proto_tree *imsi_tree = NULL, *imsi_stru_tree = NULL;
1004
1005         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1006         first_b = tvb_get_guint8(tvb,offset+2);
1007         if (dprm_p->tree){
1008                 code = tvb_get_guint8(tvb,offset);
1009                 decode_bitfield_value(toibuf,toi,LOW3B,8);
1010                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+2 ,"IMSI");
1011                 imsi_tree = proto_item_add_subtree(ti, ett_bssgp_imsi);
1012                 proto_tree_add_uint_format(imsi_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1013                 proto_tree_add_text(imsi_tree,tvb,offset+1,1,"Length:%u",len);
1014         }
1015         toi = first_b & LOW3B;
1016         switch (toi) {
1017
1018         case TOI_IMSI:
1019         case TOI_IMEI:
1020         case TOI_IMEISV:
1021                 num = first_b >> 4;
1022                 buf[0] = num + '0';
1023                 for (i=1,k=1;i<len;i++){
1024                         nextb = tvb_get_guint8(tvb, offset+2+i);
1025                         num = nextb & 0x0f;
1026                         buf[k] = num + '0';
1027                         k++;
1028                         if (i < len - 1 || (first_b & ODD_EVEN_INDIC)) {
1029                                 /*
1030                                  * Either this isn't the last octet
1031                                  * of the number, or it is, but there's
1032                                  * an odd number of digits, so the last
1033                                  * nibble is part of the number.
1034                                  */
1035                                 num = nextb >> 4;
1036                                 buf[k] = num + '0';
1037                                 k++;
1038                         }
1039                         buf[k] = '\0';
1040                         switch (i*2){
1041                                 case 4:
1042                                         memcpy(&imsi_mccn,&buf,6);
1043                                         break;
1044                                 case 14:
1045                                         memcpy(&imsi_val, &buf[5],11);  
1046                                         break;
1047                         }
1048         
1049                 }
1050                 if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1051                         col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO,
1052                             ", %s: %s %s",
1053                             val_to_str(toi,type_of_identity,"Unknown TOI (0x%x)"),
1054                                 imsi_mccn, imsi_val );
1055                 }
1056         
1057                 if (dprm_p->tree){
1058                         proto_item_append_text(ti, ": %s", buf);
1059                         ti2 = proto_tree_add_text(imsi_tree,tvb,offset+2,len,"Mobile identity: %s",buf);
1060                         imsi_stru_tree = proto_item_add_subtree( ti2, ett_bssgp_imsi_stru_tree);
1061                         proto_tree_add_uint(imsi_stru_tree,hf_bssgp_imsi_toi,tvb,offset+2,1,first_b);
1062                         proto_tree_add_boolean(imsi_stru_tree,hf_bssgp_imsi_even_odd_indic,tvb,offset+2,1,first_b);
1063                         proto_tree_add_string(imsi_stru_tree,hf_bssgp_imsi,tvb,offset+2,len,buf);
1064                         proto_tree_add_string_hidden(imsi_stru_tree,hf_bssgp_imsi_lsix,tvb,offset+2,len,imsi_val);
1065                 }
1066                 break;
1067         }
1068 return len+2;   
1069 }
1070
1071 static int dcd_bssgp_llc_pdu(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){   
1072         guint8 code=0, pom=0,k=0;
1073         guint16 llen=0;
1074         proto_item *ti=NULL;
1075         proto_tree *b_llc_tree=NULL;
1076
1077         pom = tvb_get_guint8(tvb,offset+1);
1078         if ( pom >= 128 ){
1079                 llen = pom & 0x7f;
1080                 k = 2;
1081         }
1082         else{ 
1083                 llen = tvb_get_ntohs( tvb, offset+1);
1084                 k=3;    
1085         }
1086
1087         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1088                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", LLC PDU length %u bytes", llen );
1089                 }       
1090         
1091         if (dprm_p->tree){
1092                 code = tvb_get_guint8(tvb,offset);
1093                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,llen ,"LLC PDU %u bytes", llen);
1094                 b_llc_tree = proto_item_add_subtree(ti, ett_b_llc_tree);
1095                 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);
1096                 proto_tree_add_text(b_llc_tree,tvb,offset+1,k-1,"Length:%u",llen);
1097         }
1098         
1099 dprm_p->k=offset+k;     
1100 return llen+k;  
1101 }
1102
1103 static int dcd_bssgp_llc_frdsc(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1104         guint8 code=0, len=0,frdsc=0;
1105         proto_item *ti=NULL;
1106         proto_tree *frdsc_tree=NULL;
1107         
1108         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1109         frdsc = tvb_get_guint8(tvb,offset+2);
1110         code = tvb_get_guint8(tvb,offset);
1111         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1112                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u",match_strval(code,bssgp_iei), frdsc);
1113                 }       
1114         if (dprm_p->tree){
1115                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u", match_strval(code,bssgp_iei), frdsc);
1116                 frdsc_tree = proto_item_add_subtree(ti, ett_frdsc_tree);
1117                 proto_tree_add_uint_format(frdsc_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1118                 proto_tree_add_uint_format(frdsc_tree, hf_bssgp_frdsc,tvb,offset+2,len,frdsc,"%s: %u",match_strval(code,bssgp_iei),frdsc);
1119                 proto_tree_add_text(frdsc_tree,tvb,offset+1,1,"Length:%u",len);
1120         }
1121 return len+2;
1122 }
1123
1124 /*static int dcd_bssgp_la(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){              
1125 };
1126 */
1127
1128 /*static int dcd_bssgp_mid(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){     
1129 };
1130 */
1131
1132 /*static int dcd_bssgp_ms_buck(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1133 };
1134 */
1135
1136 static int dcd_bssgp_radio_acc(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1137         guint8 code=0,len=0;
1138         proto_item *ti=NULL;
1139         proto_tree *racc_tree = NULL;
1140
1141         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1142         if (dprm_p->tree){
1143                 code = tvb_get_guint8(tvb,offset);
1144                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+2 ,"MS Radio Access Capability: ");
1145                 racc_tree = proto_item_add_subtree(ti, ett_bssgp_racc);
1146                 proto_tree_add_uint_format(racc_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1147                 proto_tree_add_text(racc_tree,tvb,offset+1,1,"Length:%u",len);
1148         }
1149 return len+2;
1150 }
1151
1152 /*static int dcd_bssgp_omc_id(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){  
1153 };
1154 */
1155
1156 /*static int dcd_bssgp_pdu_err(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1157 };
1158 */
1159
1160 static int dcd_bssgp_pdu_life(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
1161         gfloat ms_lifetime;
1162         guint16 lifetime;
1163         guint8 code=0, len=0;
1164         proto_item *ti=NULL;
1165         proto_tree *lft_tree=NULL;
1166         
1167         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1168         if (dprm_p->tree){
1169                 code = tvb_get_guint8(tvb,offset);
1170                 lifetime = tvb_get_ntohs(tvb,offset+2);
1171                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, 4,"PDU Lifetime (s): ");
1172                 lft_tree = proto_item_add_subtree(ti, ett_bssgp_lft);
1173                 proto_tree_add_uint_format(lft_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1174                 proto_tree_add_text(lft_tree,tvb,offset+1,1,"Length:%u",len);
1175                 if (lifetime == 0xFFFF){
1176                         proto_item_append_text(ti,"infinite delay");
1177                         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);
1178                 }
1179                 else{
1180                         ms_lifetime = (gfloat) (lifetime/100);
1181                         proto_item_append_text(ti,"%f",ms_lifetime);
1182                         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);
1183                 }       
1184         }
1185 return 4;
1186 }
1187
1188 static int dcd_bssgp_prio(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
1189         guint8 code=0, len=0;
1190         proto_item *ti=NULL;
1191         proto_tree *prio_tree=NULL;
1192         
1193         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1194         if (dprm_p->tree){
1195                 code = tvb_get_guint8(tvb,offset);
1196                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, 4,"Priority");
1197                 prio_tree = proto_item_add_subtree(ti, ett_prio_tree);
1198                 proto_tree_add_uint_format(prio_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1199                 proto_tree_add_text(prio_tree,tvb,offset+1,1,"Length:%u",len);
1200         }
1201 return len+2;
1202 }
1203
1204 static int dcd_bssgp_qos(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
1205         guint16 blr=0;
1206         guint32 bps=0;
1207         char buf[16];
1208         gint8 disp=0, opet=0, code=0,len=0,start=0,pre=0;
1209         proto_item *ti=NULL, *ti2=NULL;
1210         proto_tree *qos_tree=NULL,*o5_tree;
1211         switch (dprm_p->type){
1212                 case 3:
1213                 break;  
1214                 case 4:
1215                        code = tvb_get_guint8(tvb,offset);
1216                        disp++;
1217                        len = tvb_get_guint8(tvb,offset+disp);
1218                        disp++;
1219                        len = len & 0x7f;
1220                 break;
1221         }
1222         start=disp;     
1223         blr = tvb_get_ntohs(tvb, offset+disp);
1224         disp = disp+2;
1225         opet = tvb_get_guint8(tvb,offset+disp);
1226         disp++;
1227         if (dprm_p->tree){
1228                 bps = 100*blr/8;
1229                 decode_bitfield_value(buf,opet,LOW3B,8);
1230                 pre = opet & LOW3B;
1231                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+disp,"QoS Profile IE");
1232                 qos_tree = proto_item_add_subtree(ti,ett_bssgp_qos);
1233                 switch (dprm_p->type){
1234                         case 4:
1235                                 proto_tree_add_uint_format(qos_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1236                                 proto_tree_add_text(qos_tree,tvb,offset+1,1,"Length:%u",len);
1237                         case 3:
1238                                 if (blr){
1239                                 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);
1240                                 }
1241                                 else{
1242                                 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);
1243                                 }
1244                                 ti2 = proto_tree_add_item(qos_tree,hf_bssgp_qos,tvb,offset+(disp-1),1,FALSE);
1245                                 o5_tree = proto_item_add_subtree(ti2, ett_bssgp_o5);
1246                                 proto_tree_add_boolean(o5_tree,hf_bssgp_qos_cr,tvb,offset+(disp-1),1,opet);
1247                                 proto_tree_add_boolean(o5_tree,hf_bssgp_qos_t,tvb,offset+(disp-1),1,opet);
1248                                 proto_tree_add_boolean(o5_tree,hf_bssgp_qos_a,tvb,offset+(disp-1),1,opet);
1249                                 if(tvb_get_guint8(tvb,0)){
1250                                 proto_tree_add_uint_format(o5_tree,hf_bssgp_qos_prec,tvb,offset+(disp-1),1,pre,"%s %s", buf,match_strval(pre,prec));
1251
1252                                 }
1253                                 else{
1254                                 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));
1255                                 }
1256                 }
1257                                 
1258         }
1259         return disp;
1260 }
1261
1262 static int dcd_bssgp_radio_caus(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){        
1263         guint8 code=0, len=0,racaus=0;
1264         proto_item *ti=NULL;
1265         proto_tree *racaus_tree=NULL;
1266         
1267         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1268         racaus = tvb_get_guint8(tvb,offset+2);
1269         code = tvb_get_guint8(tvb,offset);
1270         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1271                 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"));
1272                 }       
1273         if (dprm_p->tree){
1274                 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"""));
1275                 racaus_tree = proto_item_add_subtree(ti, ett_racaus_tree);
1276                 proto_tree_add_uint_format(racaus_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1277                 proto_tree_add_uint_format(racaus_tree, hf_bssgp_radio_cause,tvb,offset+2,len,racaus,"%s: %#.2x",match_strval(code,bssgp_iei),racaus);
1278                 proto_tree_add_text(racaus_tree,tvb,offset+1,1,"Length:%u",len);
1279         }
1280 return len+2;
1281 }
1282
1283 /*static int dcd_bssgp_racap_upd(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
1284 };
1285 */
1286
1287 static int dcd_bssgp_ra(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){                
1288        guint16 lac;
1289         guint32 mnccc;
1290         guint8 rac, len = 0,code=0 ;
1291         char st_mccn[8];
1292         proto_item *ti=NULL;
1293         proto_tree *ra_tree = NULL;
1294         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1295         if (dprm_p->tree){
1296                 code = tvb_get_guint8(tvb,offset);
1297                 mnccc = tvb_get_ntoh24(tvb,offset+2);
1298                 lac = tvb_get_ntohs(tvb,offset+5);
1299                 rac = tvb_get_guint8(tvb,offset+7);
1300                 mccmnc(mnccc, st_mccn);
1301                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+2, "Routing area: %s %u %u",st_mccn,lac,rac);
1302                 ra_tree = proto_item_add_subtree(ti, ett_ra_tree);
1303                 proto_tree_add_uint_format(ra_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1304                 proto_tree_add_string_format(ra_tree,hf_bssgp_ra_mccmnc,tvb,offset+2,3,st_mccn,"MCC MNC: %s",st_mccn);
1305                 proto_tree_add_uint_format(ra_tree,hf_bssgp_ra_lac,tvb,offset+5,2,lac,"LAC: %u",lac);
1306                 proto_tree_add_uint_format(ra_tree,hf_bssgp_ra_rac,tvb,offset+7,1,rac,"RAC: %u",rac);
1307                 proto_tree_add_text(ra_tree,tvb,offset+1,1,"Length:%u",len);
1308         }
1309 return len+2;
1310 }
1311
1312 static int dcd_bssgp_r_def_ms(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){  
1313         guint8 code=0, len=0;
1314         guint16 bucket=0;
1315         proto_item *ti=NULL;
1316         proto_tree *rdefms_tree=NULL;
1317         
1318         if (dprm_p->tree){
1319                 len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1320                 code = tvb_get_guint8(tvb,offset);
1321                 bucket = tvb_get_ntohs(tvb,offset+2);
1322                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u bits/sec", match_strval(code,bssgp_iei),100*bucket);
1323                 rdefms_tree = proto_item_add_subtree(ti, ett_rdefms_tree);
1324                 proto_tree_add_uint_format(rdefms_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1325                 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);
1326                 proto_tree_add_text(rdefms_tree,tvb,offset+1,1,"Length:%u",len);
1327         }
1328 return len+2;
1329 }
1330
1331 /*static int dcd_bssgp_sus_ref_num(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
1332 };
1333 */
1334
1335 static int dcd_bssgp_tag(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
1336         guint8 code=0, len=0,tag=0;
1337         proto_item *ti=NULL;
1338         proto_tree *tag_tree=NULL;
1339         
1340         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1341         if (dprm_p->tree){
1342                 code = tvb_get_guint8(tvb,offset);
1343                 tag = tvb_get_guint8(tvb,offset+2);
1344                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2,"Tag: %u", tag);
1345                 tag_tree = proto_item_add_subtree(ti, ett_tag_tree);
1346                 proto_tree_add_uint_format(tag_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1347                 proto_tree_add_text(tag_tree,tvb,offset+1,1,"Length:%u",len);
1348         }
1349 return len+2;
1350 }
1351
1352 static int dcd_bssgp_tlli(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
1353         guint32 tlli;
1354         guint8 len=0, code=0, disp=0;
1355         proto_item *ti=NULL;
1356         proto_tree *tlli_tree=NULL;
1357         switch (dprm_p->type){
1358           case 3:
1359                  disp = 0;
1360                  break; 
1361           case 4:
1362                  code = tvb_get_guint8(tvb, offset);
1363                  disp++;
1364                  len = tvb_get_guint8(tvb,offset+disp);
1365                  len = len & 0x7f;
1366                  disp++;
1367                  break;
1368         }
1369         tlli = tvb_get_ntohl(tvb, offset+disp);
1370         if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
1371                 col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO,", TLLI: %X", tlli);
1372         }
1373         if (dprm_p->tree){
1374                 switch (dprm_p->type){
1375                         case 3:
1376                                 proto_tree_add_uint_format(dprm_p->tree,hf_bssgp_tlli,tvb,offset,4,tlli,"TLLI: %#.4x", tlli ); 
1377                         break;
1378                         case 4:
1379                                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+disp,"TLLI: %#.4x",tlli);
1380                                 tlli_tree =proto_item_add_subtree(ti,ett_bssgp_tlli);
1381                                 proto_tree_add_uint_format(tlli_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1382
1383                                 proto_tree_add_text(tlli_tree,tvb,offset+1,1,"Length:%u",len);
1384                                 proto_tree_add_uint_format(tlli_tree,hf_bssgp_tlli,tvb,offset+disp,len,tlli,"TLLI: %#.4x", tlli ); 
1385                                 
1386                 }
1387         }         
1388                   return 4 + disp;
1389 }
1390 /*static int dcd_bssgp_tlli_o(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
1391         return 6;
1392 };      
1393 */
1394
1395 /*static int dcd_bssgp_tmsi(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){    
1396 };
1397 */
1398 /*static int dcd_bssgp_trace_ref(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){       
1399 };
1400 */
1401 /*static int dcd_bssgp_trace_type(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){      
1402 };
1403 */
1404 /*static int dcd_bssgp_trans_id(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){        
1405 };
1406 */
1407 /*static int dcd_bssgp_trig_id(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){ 
1408 };
1409 */
1410 static int dcd_bssgp_num_oct_aff(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
1411         guint8 code=0, len=0;
1412         guint32 bucket=0;
1413         proto_item *ti=NULL;
1414         proto_tree *noaff_tree=NULL;
1415         
1416         len = tvb_get_guint8(tvb,offset+1) & 0x7f;
1417         if (dprm_p->tree){
1418                 code = tvb_get_guint8(tvb,offset);
1419                 bucket = tvb_get_ntoh24(tvb,offset+2);
1420                 ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u", match_strval(code,bssgp_iei), bucket);
1421                 noaff_tree = proto_item_add_subtree(ti, ett_noaff_tree);
1422                 proto_tree_add_uint_format(noaff_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
1423                 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);
1424                 proto_tree_add_text(noaff_tree,tvb,offset+1,1,"Length:%u",len);
1425         }
1426 return len+2;
1427 }
1428
1429
1430 /* Code to actually dissect the packets */
1431 static void
1432 dissect_bssgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1433 {
1434 static dec_fu_param_stru_t decp , *decodeparam=&decp;
1435 guint8 pdutype, i, j , iele , stay;
1436 guint16 offset=1;
1437 tvbuff_t *next_tvb;
1438
1439 /* Set up structures needed to add the protocol subtree and manage it */
1440         proto_item *ti=NULL;
1441         proto_tree *bssgp_tree=NULL;
1442
1443         pdutype=tvb_get_guint8(tvb,0);
1444 /* Make entries in Protocol column and Info column on summary display */
1445         if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
1446                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BSSGP");
1447     
1448 /* This field shows up as the "Info" column in the display; you should make
1449    it, if possible, summarize what's in the packet, so that a user looking
1450    at the list of packets can tell what type of packet it is. See section 1.5
1451    for more information.
1452
1453    If you are setting it to a constant string, use "col_set_str()", as
1454    it's more efficient than the other "col_set_XXX()" calls.
1455
1456    If you're setting it to a string you've constructed, or will be
1457    appending to the column later, use "col_add_str()".
1458
1459    "col_add_fstr()" can be used instead of "col_add_str()"; it takes
1460    "printf()"-like arguments.  Don't use "col_add_fstr()" with a format
1461    string of "%s" - just use "col_add_str()" or "col_set_str()", as it's
1462    more efficient than "col_add_fstr()".
1463
1464    If you will be fetching any data from the packet before filling in
1465    the Info column, clear that column first, in case the calls to fetch
1466    data from the packet throw an exception because they're fetching data
1467    past the end of the packet, so that the Info column doesn't have data
1468    left over from the previous dissector; do
1469 */
1470         if (check_col(pinfo->cinfo, COL_INFO)) {
1471                 col_clear(pinfo->cinfo, COL_INFO);
1472                 col_add_str(pinfo->cinfo, COL_INFO,match_strval(pdutype,tab_bssgp_pdu_type));
1473         }
1474 /* In the interest of speed, if "tree" is NULL, don't do any work not
1475    necessary to generate protocol tree items. */
1476 /*        if (tree) { */
1477
1478 /* NOTE: The offset and length values in the call to
1479    "proto_tree_add_item()" define what data bytes to highlight in the hex
1480    display window when the line in the protocol tree display
1481    corresponding to that item is selected.
1482
1483    tvb_length(tvb) is a handy way to highlight all data from the offset to
1484    the end of the packet. */
1485
1486 /* create display subtree for the protocol */
1487 /*                ti = proto_tree_add_item(tree, proto_bssgp, tvb, 0, tvb_length(tvb), FALSE );
1488
1489                 bssgp_tree = proto_item_add_subtree(ti, ett_bssgp);
1490 */
1491         decodeparam->pinfo=pinfo;
1492         decodeparam->tree=tree;
1493                 i = 0;
1494                 stay = 1;
1495                 while (bssgp_pdu[i].infe[0].presence && stay){ 
1496                     if (bssgp_pdu[i].pdu == pdutype) { 
1497                          j = 0;   
1498                          stay = 0;
1499                          if (tree){
1500                                 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);
1501                                 bssgp_tree = proto_item_add_subtree(ti, ett_bssgp);
1502                                 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 );
1503                         decodeparam->tree=bssgp_tree;   
1504                          }
1505                          while (bssgp_pdu[i].infe[j].presence){
1506                              switch(bssgp_pdu[i].infe[j].type){
1507                                case 3:
1508                                      decodeparam->type=3; 
1509                                      offset=offset+( *bssgp_pdu[i].infe[j].decode)(tvb, offset, decodeparam );     
1510                                      j++;
1511                                break;
1512                                case 4:
1513                                   decodeparam->type=4; 
1514                                   if (offset >= tvb_length(tvb)) {
1515                                       j++;
1516                                       break;
1517                                   }  
1518                                   iele = tvb_get_guint8( tvb, offset);
1519                                   while ((bssgp_pdu[i].infe[j].code != iele) && bssgp_pdu[i].infe[j].presence ) {
1520                                      if (bssgp_pdu[i].infe[j].presence > 1) j++;
1521                                      else break;
1522                                   }
1523                                   if (bssgp_pdu[i].infe[j].presence){
1524                                       offset=offset+( *bssgp_pdu[i].infe[j].decode)(tvb, offset, decodeparam );     
1525                                       if (iele == 0x0e ){
1526                                               next_tvb = tvb_new_subset(tvb, decodeparam->k, -1, -1);
1527 /*                                            call_dissector(llcgprs_handle, next_tvb, pinfo, tree);
1528 */
1529                                               call_dissector(data_handle, next_tvb, pinfo, tree);
1530                                       }
1531                                       j++;
1532                                   }
1533                                 break;  
1534                              }
1535                          }    
1536                     }      
1537                     i++;                    
1538                   };
1539                         
1540 /* add an item to the subtree, see section 1.6 for more information */
1541 /*
1542                 proto_tree_add_uint(tree, hf_bssgp_FIELDABBREV, tvb, offset, len, value);
1543 */              
1544 /*                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 );
1545 */
1546
1547 /* Continue adding tree items to process the packet here */
1548
1549
1550 /*        }*/
1551
1552 /* If this protocol has a sub-dissector call it here, see section 1.8 */
1553 }
1554
1555
1556 /* Register the protocol with Ethereal */
1557
1558 /* this format is require because a script is used to build the C function
1559    that calls all the protocol registration.
1560 */
1561
1562 void
1563 proto_register_bssgp(void)
1564 {                 
1565         static hf_register_info hf[] = {
1566                 { &hf_bssgp_pdu_type,
1567                         { "PDU", "bssgp.pdu",
1568                         FT_UINT8, BASE_HEX, VALS(tab_bssgp_pdu_type), 0x0,          
1569                         "BSSGP PDU", HFILL }},
1570                 {&hf_bssgp_tlli,
1571                         { "TLLI","bssgp.tlli",FT_UINT32, BASE_HEX, NULL,0x0,"Current TLLI",HFILL}},
1572                 {&hf_bssgp_ietype,
1573                         {"IE Type", "bssgp.ietype", FT_UINT8, BASE_HEX, VALS(bssgp_iei),0x0,"Information element", HFILL }},
1574                 {&hf_bssgp_pbr,
1575                          {"QoS_Profile","bssgp.pbr",FT_UINT16, BASE_HEX, NULL, 0x0, "Peak bit rate",HFILL }},
1576                 {&hf_bssgp_qos,
1577                         {"Last byte QoS Profile","bssgp.qos",FT_UINT8, BASE_HEX, NULL, 0x0,"5th byte of QoS profile(contains Precedence..)",HFILL}},
1578                 {&hf_bssgp_qos_cr,
1579                         {"C/R bit","bssgp.qos.cr",FT_BOOLEAN,8, TFS(&cr_string),QOSO5CR,"The SDU contains LLC ACK/SACK command/responce frame type",HFILL }},
1580                 {&hf_bssgp_qos_t,
1581                         {"T bit", "bssgp.qos.t", FT_BOOLEAN, 8, TFS( &t_string) , QOSO5T, "The SDU contains signaling/data" , HFILL}},
1582                 {&hf_bssgp_qos_a,
1583                         {"A bit" , "bssgp.qos.a" , FT_BOOLEAN,8, TFS( &a_string), QOSO5A, "Radio interface uses ARQ/UNITDATA functionality",HFILL}},
1584                 {&hf_bssgp_qos_prec,
1585                         {"Precedence", "bssgp.qos.prec", FT_UINT8,BASE_HEX ,VALS(prec_both), 0x0,"Precedence coding", HFILL }},
1586                 {&hf_bssgp_pdu_lifetime,
1587                         {"PDU Lifetime","bssgp.lft", FT_UINT16, BASE_HEX, NULL, 0x0, "PDU Lifetime for PDU inside the BSS",HFILL}},
1588                 {&hf_bssgp_imsi,
1589                         {"IMSI","bssgp.imsi", FT_STRING, BASE_DEC, NULL, 0x0, "International Mobile Subscriber Identity",HFILL}},
1590                 {&hf_bssgp_imsi_toi,
1591                         { "Type of Mobile identity", "bssgp.mobid", FT_UINT8, BASE_HEX, VALS(type_of_identity), LOW3B, "Type of mobile identity",HFILL }},
1592                 {&hf_bssgp_imsi_even_odd_indic,
1593                         { "Odd/even indication", "bssgp.oei", FT_BOOLEAN, 8, TFS(&imsi_odd_even), ODD_EVEN_INDIC, "Odd/even indication",HFILL }},
1594                 {&hf_bssgp_imsi_lsix,
1595                         {"IMSI last ten numbers","bssgp.imsi.last10num",FT_STRING, BASE_NONE, NULL, 0x0, "Last ten numbers of IMSI",HFILL}},
1596                 {&hf_bssgp_bvc_buck_size,
1597                         {"Bmax(in 100 oct incr)","bssgp.bmax", FT_UINT16, BASE_HEX, NULL, 0x0, "BVC Bucket Size in 100 octet increments",HFILL}},
1598                 {&hf_bssgp_buck_leak_rate,
1599                         {"Bucket Leak Rate","bssgp.R", FT_UINT16, BASE_HEX, NULL, 0x0, "Bucket Leak Rate in 100 bits/sec increments",HFILL}},
1600                 {&hf_bssgp_bmax_def_ms,
1601                         {"Bmax default MS","bssgp.bmaxms", FT_UINT16, BASE_HEX, NULL, 0x0, "Default bucket size in 100 octetsincrement for an MS",HFILL}},
1602                 {&hf_bssgp_r_defau_ms,
1603                         {"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}},
1604                 {&hf_bssgp_bvci,
1605                         {"BVCI","bssgp.bvci",FT_UINT16, BASE_HEX, NULL, 0x0, "BSSGP Virtual Connection Identifier", HFILL}},
1606                 {&hf_bssgp_cause,
1607                         {"Cause","bssgp.cause", FT_UINT8, BASE_HEX, NULL,0x0, " Cause information element  indicates the reason for an exception condition",HFILL }},
1608                 {&hf_bssgp_bvci_new,{"BVCI(New)","bssgp.bvci.new",FT_UINT16, BASE_HEX, NULL, 0x0, "BSSGP Virtual Connection Identifier", HFILL}},
1609                 {&hf_bssgp_frdsc,
1610                         {"LLC frames discarded","bssgp.llcdisc.frames", FT_UINT8, BASE_HEX, NULL, 0x0,"LLC frames that have been discarded inside BSS", HFILL}},
1611                 {&hf_bssgp_noaff,
1612                         {"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}},
1613                 {&hf_bssgp_radio_cause,
1614                         {"Radio Cause","bssgp.racase", FT_UINT8, BASE_HEX, NULL, 0x0, "Reason for an exception condition on the radio interface",HFILL}},
1615                 {&hf_bssgp_ra_mccmnc,
1616                         {"MCC and MNC","bssgp.ra.mccmnc", FT_STRING, BASE_DEC, NULL, 0x0, "Mobile country code and Mobile network code", HFILL}},
1617                 {&hf_bssgp_ra_lac,
1618                         {"LAC","bssgp.ra.lac",FT_UINT16, BASE_HEX, NULL, 0x0, "Location area code",HFILL }},
1619                 {&hf_bssgp_ra_rac,
1620                         {"RAC","bssgp.ra.rac",FT_UINT8, BASE_HEX, NULL, 0x0, "Routing area code", HFILL }},
1621                 {&hf_bssgp_cid,
1622                         {"Cell id","bssgp.cid",FT_UINT16, BASE_HEX, NULL, 0x0, "Cell identity", HFILL }},
1623         };
1624
1625 /* Setup protocol subtree array */
1626         static gint *ett[] = {
1627                 &ett_bssgp,
1628                 &ett_bssgp_tlli,
1629                 &ett_bssgp_qos,
1630                 &ett_bssgp_o5,
1631                 &ett_bssgp_lft,
1632                 &ett_bssgp_racc,
1633                 &ett_prio_tree,
1634                 &ett_drx_tree,
1635                 &ett_bssgp_imsi,
1636                 &ett_bssgp_imsi_stru_tree,
1637                 &ett_algn_tree,
1638                 &ett_b_llc_tree,
1639                 &ett_celid_tree,
1640                 &ett_tag_tree,
1641                 &ett_bsize_tree,
1642                 &ett_bucklr_tree,
1643                 &ett_bmaxms_tree,
1644                 &ett_rdefms_tree,
1645                 &ett_bvci_tree,
1646                 &ett_bvcin_tree,
1647                 &ett_cause_tree,
1648                 &ett_frdsc_tree,
1649                 &ett_noaff_tree,
1650                 &ett_racaus_tree,
1651                 &ett_ra_tree
1652         };
1653
1654 /* Register the protocol name and description */
1655         proto_bssgp = proto_register_protocol("BSS GPRS Protocol",
1656             "BSSGP", "bssgp");
1657
1658 /* Required function calls to register the header fields and subtrees used */
1659         proto_register_field_array(proto_bssgp, hf, array_length(hf));
1660         proto_register_subtree_array(ett, array_length(ett));
1661         register_dissector("bssgp", dissect_bssgp, proto_bssgp);
1662 }
1663
1664
1665 /* If this dissector uses sub-dissector registration add a registration routine.
1666    This format is required because a script is used to find these routines and
1667    create the code that calls these routines.
1668 */
1669 void
1670 proto_reg_handoff_bssgp(void)
1671 {
1672 /*        dissector_handle_t bssgp_handle;
1673
1674         bssgp_handle = create_dissector_handle(dissect_bssgp,
1675             proto_bssgp);
1676 */
1677 /*        dissector_add("fr.nspduname", NS_UNITDATA, bssgp_handle);*/
1678 /*        dissector_add("fr.nspduname", 0x0, bssgp_handle);
1679 */      
1680 /*        dissector_add("fr.ietf", 0x0, bssgp_handle);
1681 */        
1682         data_handle = find_dissector("data");
1683
1684 /*
1685           llcgprs_handle = find_dissector ("llcgprs");
1686 */        
1687 }