Dissect the FCS after dissecting the header.
[metze/wireshark/wip.git] / epan / dissectors / packet-gprs-llc.c
1 /* packet-llcgprs.c
2  * Routines for Logical Link Control GPRS dissection ETSI 4.64(TS 101 351 V8.7.0)
3  * Copyright 2000, Josef Korelus <jkor@quick.cz>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include "config.h"
25
26 #include <epan/packet.h>
27 #include <epan/prefs.h>
28 #include <epan/expert.h>
29 #include <wiretap/wtap.h>
30
31 void proto_register_llcgprs(void);
32 void proto_reg_handoff_llcgprs(void);
33
34 #define I_FORMAT        1
35 #define S_FORMAT        2
36 #define UI_FORMAT       3
37 #define U_FORMAT        4
38 #define I_SACK          5
39 #define S_SACK          6
40 #define UI_MASK_FMT    0xe000
41 #define UI_MASK_SPB    0x1800
42 #define UI_MASK_NU     0x07fc
43 #define UI_MASK_E      0x0002
44 #define UI_MASK_PM     0x0001
45
46 #define N202           4U
47 #define CRC_LENGTH     3U
48 #define UI_HDR_LENGTH  3U
49
50 /* Initialize the protocol and registered fields */
51 static int proto_llcgprs          = -1;
52 static int hf_llcgprs_pd          = -1;
53 static int hf_llcgprs_fcs         = -1;
54 static int hf_llcgprs_cr          = -1;
55 static int hf_llcgprs_sapi        = -1;
56 static int hf_llcgprs_sapib       = -1;
57 static int hf_llcgprs_U_fmt       = -1; /* 3 upper bits in controlfield (UI format) */
58 static int hf_llcgprs_sp_bits     = -1; /* Spare bits in control field */
59 static int hf_llcgprs_NU          = -1; /* Transmited unconfirmed sequence number */
60 static int hf_llcgprs_E_bit       = -1; /* Encryption mode bit */
61 static int hf_llcgprs_PM_bit      = -1;
62 static int hf_llcgprs_Un          = -1;
63 static int hf_llcgprs_As          = -1;
64 static int hf_llcgprs_ucom        = -1;
65 static int hf_llcgprs_PF          = -1;
66 static int hf_llcgprs_S_fmt       = -1;
67 static int hf_llcgprs_NR          = -1;
68 static int hf_llcgprs_sjsd        = -1;
69 static int hf_llcgprs_k           = -1;
70 static int hf_llcgprs_isack_ns    = -1;
71 static int hf_llcgprs_isack_nr    = -1;
72 static int hf_llcgprs_isack_sfb   = -1;
73 static int hf_llcgprs_rbyte       = -1;
74 static int hf_llcgprs_kmask       = -1;
75 static int hf_llcgprs_ifmt        = -1;
76 static int hf_llcgprs_ia          = -1;
77 static int hf_llcgprs_izerobit    = -1;
78 static int hf_llcgprs_sspare      = -1;
79 static int hf_llcgprs_xid_xl      = -1;
80 static int hf_llcgprs_xid_type    = -1;
81 static int hf_llcgprs_xid_len1    = -1;
82 static int hf_llcgprs_xid_len2    = -1;
83 static int hf_llcgprs_xid_spare   = -1;
84 static int hf_llcgprs_xid_byte    = -1;
85 static int hf_llcgprs_frmr_cf     = -1;
86 static int hf_llcgprs_frmr_spare  = -1;
87 static int hf_llcgprs_frmr_vs     = -1;
88 static int hf_llcgprs_frmr_vr     = -1;
89 static int hf_llcgprs_frmr_cr     = -1;
90 static int hf_llcgprs_frmr_w4     = -1;
91 static int hf_llcgprs_frmr_w3     = -1;
92 static int hf_llcgprs_frmr_w2     = -1;
93 static int hf_llcgprs_frmr_w1     = -1;
94 static int hf_llcgprs_tom_rl      = -1;
95 static int hf_llcgprs_tom_pd      = -1;
96 static int hf_llcgprs_tom_header  = -1;
97 static int hf_llcgprs_tom_data    = -1;
98
99 /* Unnumbered Commands and Responses (U Frames) */
100 #define U_DM    0x01
101 #define U_DISC  0x04
102 #define U_UA    0x06
103 #define U_SABM  0x07
104 #define U_FRMR  0x08
105 #define U_XID   0x0B
106 #define U_NULL  0x00
107
108 /* SAPI value constants */
109 #define SAPI_LLGMM      0x01
110 #define SAPI_TOM2       0x02
111 #define SAPI_LL3        0x03
112 #define SAPI_LL5        0x05
113 #define SAPI_LLSMS      0x07
114 #define SAPI_TOM8       0x08
115 #define SAPI_LL9        0x09
116 #define SAPI_LL11       0x0B
117
118 /* Initialize the subtree pointers */
119 static gint ett_llcgprs = -1;
120 static gint ett_llcgprs_adf = -1;
121 static gint ett_llcgprs_ctrlf = -1;
122 static gint ett_ui = -1;
123 static gint ett_llcgprs_sframe = -1;
124
125 static expert_field ei_llcgprs_no_info_field = EI_INIT;
126
127 static dissector_handle_t data_handle;
128 static dissector_handle_t sndcp_xid_handle;
129
130 static gboolean ignore_cipher_bit = FALSE;
131
132 static dissector_table_t llcgprs_subdissector_table;
133
134 static const value_string sapi_t[] = {
135         {  0, "Reserved"},
136         {  1, "GPRS Mobility Management" },
137         {  2, "Tunneling of messages 2" },
138         {  3, "User data 3"},
139         {  4, "Reserved" },
140         {  5, "User data 5" },
141         {  6, "Reserved" },
142         {  7, "SMS" },
143         {  8, "Tunneling of messages 8" },
144         {  9, "User data 9" },
145         { 10, "Reserved" },
146         { 11, "User data 11" },
147         { 12, "Reserved" },
148         { 13, "Reserved" },
149         { 14, "Reserved" },
150         { 15, "Reserved" },
151         {  0, NULL },
152 };
153 static value_string_ext sapi_t_ext = VALUE_STRING_EXT_INIT(sapi_t);
154
155 static const value_string sapi_abrv[] = {
156         {  0, "Reserved 0"},
157         {  1, "LLGMM" },
158         {  2, "TOM2" },
159         {  3, "LL3"},
160         {  4, "Reserved 4" },
161         {  5, "LL5" },
162         {  6, "Reserved 6" },
163         {  7, "LLSMS" },
164         {  8, "TOM8" },
165         {  9, "LL9" },
166         { 10, "Reserved 10" },
167         { 11, "LL11" },
168         { 12, "Reserved 12" },
169         { 13, "Reserved 13" },
170         { 14, "Reserved 14" },
171         { 15, "Reserved 15" },
172         { 0, NULL }
173 };
174 static value_string_ext sapi_abrv_ext = VALUE_STRING_EXT_INIT(sapi_abrv);
175
176 static const true_false_string a_bit = {
177         "To solicit an acknowledgement from the peer LLE. ",
178         "The peer LLE is not requested to send an acknowledgment."
179 };
180
181 static const true_false_string pd_bit = {
182         "Invalid frame PD=1",
183         "OK"
184 };
185 static const true_false_string e_bit = {
186         " encrypted frame",
187         " non encrypted frame"
188 };
189 static const true_false_string pm_bit = {
190         "FCS covers the frame header and information fields",
191         "FCS covers only the frame header and first N202 octets of the information field"
192 };
193 static const true_false_string cr_bit = {
194         "DownLink/UpLink = Command/Response",
195         "DownLink/UpLink = Response/Command"
196 };
197 /* bits are swaped comparing with "Table 3" in ETSI document */
198 static const value_string pme[] = {
199         { 0, "unprotected,non-ciphered information" },
200         { 1, "protected, non-ciphered information" },
201         { 2, "unprotected,ciphered information"},
202         { 3, "protected, ciphered information" },
203         { 0, NULL},
204 };
205
206 static const value_string xid_param_type_str[] = {
207         {0x0, "Version (LLC version number)"},
208         {0x1, "IOV-UI (ciphering Input offset value for UI frames)"},
209         {0x2, "IOV-I (ciphering Input offset value for I frames)"},
210         {0x3, "T200 (retransmission timeout)"},
211         {0x4, "N200 (max number of retransmissions)"},
212         {0x5, "N201-U (max info field length for U and UI frames)"},
213         {0x6, "N201-I (max info field length for I frames)"},
214         {0x7, "mD (I frame buffer size in the DL direction)"},
215         {0x8, "mU (I frame buffer size in the UL direction)"},
216         {0x9, "kD (window size in the DL direction)"},
217         {0xA, "kU (window size in the UL direction)"},
218         {0xB, "Layer-3 Parameters"},
219         {0xC, "Reset"},
220         {0, NULL}
221 };
222 static value_string_ext xid_param_type_str_ext = VALUE_STRING_EXT_INIT(xid_param_type_str);
223
224 static const value_string tompd_formats[] = {
225         {0x0, "Not specified"},
226         {0x1, "TIA/EIA-136"},
227         {0x2, "RRLP"},
228         {0x3, "Reserved value 3"},
229         {0x4, "Reserved value 4"},
230         {0x5, "Reserved value 5"},
231         {0x6, "Reserved value 6"},
232         {0x7, "Reserved value 7"},
233         {0x8, "Reserved value 8"},
234         {0x9, "Reserved value 9"},
235         {0xA, "Reserved value 10"},
236         {0xB, "Reserved value 11"},
237         {0xC, "Reserved value 12"},
238         {0xD, "Reserved value 13"},
239         {0xE, "Reserved value 14"},
240         {0xF, "Reserved for extension"},
241         {0, NULL}
242 };
243
244 static const value_string cr_formats_unnumb[]= {
245         {  0x1, "DM-response" },
246         {  0x4, "DISC-command" },
247         {  0x6, "UA-response" },
248         {  0x7, "SABM" },
249         {  0x8, "FRMR" },
250         { 0xb, "XID" },
251         { 0, NULL },
252 };
253 static const value_string cr_formats_ipluss[] = {
254         { 0x0, "RR" },
255         { 0x1, "ACK" },
256         { 0x2, "RNR" },
257         { 0x3, "SACK" },
258         { 0, NULL },
259 };
260
261 /* CRC24 table - FCS */
262 guint32 tbl_crc24[256] = {
263         0x00000000, 0x00d6a776, 0x00f64557, 0x0020e221, 0x00b78115, 0x00612663, 0x0041c442, 0x00976334,
264         0x00340991, 0x00e2aee7, 0x00c24cc6, 0x0014ebb0, 0x00838884, 0x00552ff2, 0x0075cdd3, 0x00a36aa5,
265         0x00681322, 0x00beb454, 0x009e5675, 0x0048f103, 0x00df9237, 0x00093541, 0x0029d760, 0x00ff7016,
266         0x005c1ab3, 0x008abdc5, 0x00aa5fe4, 0x007cf892, 0x00eb9ba6, 0x003d3cd0, 0x001ddef1, 0x00cb7987,
267         0x00d02644, 0x00068132, 0x00266313, 0x00f0c465, 0x0067a751, 0x00b10027, 0x0091e206, 0x00474570,
268         0x00e42fd5, 0x003288a3, 0x00126a82, 0x00c4cdf4, 0x0053aec0, 0x008509b6, 0x00a5eb97, 0x00734ce1,
269         0x00b83566, 0x006e9210, 0x004e7031, 0x0098d747, 0x000fb473, 0x00d91305, 0x00f9f124, 0x002f5652,
270         0x008c3cf7, 0x005a9b81, 0x007a79a0, 0x00acded6, 0x003bbde2, 0x00ed1a94, 0x00cdf8b5, 0x001b5fc3,
271         0x00fb4733, 0x002de045, 0x000d0264, 0x00dba512, 0x004cc626, 0x009a6150, 0x00ba8371, 0x006c2407,
272         0x00cf4ea2, 0x0019e9d4, 0x00390bf5, 0x00efac83, 0x0078cfb7, 0x00ae68c1, 0x008e8ae0, 0x00582d96,
273         0x00935411, 0x0045f367, 0x00651146, 0x00b3b630, 0x0024d504, 0x00f27272, 0x00d29053, 0x00043725,
274         0x00a75d80, 0x0071faf6, 0x005118d7, 0x0087bfa1, 0x0010dc95, 0x00c67be3, 0x00e699c2, 0x00303eb4,
275         0x002b6177, 0x00fdc601, 0x00dd2420, 0x000b8356, 0x009ce062, 0x004a4714, 0x006aa535, 0x00bc0243,
276         0x001f68e6, 0x00c9cf90, 0x00e92db1, 0x003f8ac7, 0x00a8e9f3, 0x007e4e85, 0x005eaca4, 0x00880bd2,
277         0x00437255, 0x0095d523, 0x00b53702, 0x00639074, 0x00f4f340, 0x00225436, 0x0002b617, 0x00d41161,
278         0x00777bc4, 0x00a1dcb2, 0x00813e93, 0x005799e5, 0x00c0fad1, 0x00165da7, 0x0036bf86, 0x00e018f0,
279         0x00ad85dd, 0x007b22ab, 0x005bc08a, 0x008d67fc, 0x001a04c8, 0x00cca3be, 0x00ec419f, 0x003ae6e9,
280         0x00998c4c, 0x004f2b3a, 0x006fc91b, 0x00b96e6d, 0x002e0d59, 0x00f8aa2f, 0x00d8480e, 0x000eef78,
281         0x00c596ff, 0x00133189, 0x0033d3a8, 0x00e574de, 0x007217ea, 0x00a4b09c, 0x008452bd, 0x0052f5cb,
282         0x00f19f6e, 0x00273818, 0x0007da39, 0x00d17d4f, 0x00461e7b, 0x0090b90d, 0x00b05b2c, 0x0066fc5a,
283         0x007da399, 0x00ab04ef, 0x008be6ce, 0x005d41b8, 0x00ca228c, 0x001c85fa, 0x003c67db, 0x00eac0ad,
284         0x0049aa08, 0x009f0d7e, 0x00bfef5f, 0x00694829, 0x00fe2b1d, 0x00288c6b, 0x00086e4a, 0x00dec93c,
285         0x0015b0bb, 0x00c317cd, 0x00e3f5ec, 0x0035529a, 0x00a231ae, 0x007496d8, 0x005474f9, 0x0082d38f,
286         0x0021b92a, 0x00f71e5c, 0x00d7fc7d, 0x00015b0b, 0x0096383f, 0x00409f49, 0x00607d68, 0x00b6da1e,
287         0x0056c2ee, 0x00806598, 0x00a087b9, 0x007620cf, 0x00e143fb, 0x0037e48d, 0x001706ac, 0x00c1a1da,
288         0x0062cb7f, 0x00b46c09, 0x00948e28, 0x0042295e, 0x00d54a6a, 0x0003ed1c, 0x00230f3d, 0x00f5a84b,
289         0x003ed1cc, 0x00e876ba, 0x00c8949b, 0x001e33ed, 0x008950d9, 0x005ff7af, 0x007f158e, 0x00a9b2f8,
290         0x000ad85d, 0x00dc7f2b, 0x00fc9d0a, 0x002a3a7c, 0x00bd5948, 0x006bfe3e, 0x004b1c1f, 0x009dbb69,
291         0x0086e4aa, 0x005043dc, 0x0070a1fd, 0x00a6068b, 0x003165bf, 0x00e7c2c9, 0x00c720e8, 0x0011879e,
292         0x00b2ed3b, 0x00644a4d, 0x0044a86c, 0x00920f1a, 0x00056c2e, 0x00d3cb58, 0x00f32979, 0x00258e0f,
293         0x00eef788, 0x003850fe, 0x0018b2df, 0x00ce15a9, 0x0059769d, 0x008fd1eb, 0x00af33ca, 0x007994bc,
294         0x00dafe19, 0x000c596f, 0x002cbb4e, 0x00fa1c38, 0x006d7f0c, 0x00bbd87a, 0x009b3a5b, 0x004d9d2d
295 };
296
297 #define INIT_CRC24      0xffffff
298
299 static guint32 crc_calc(guint32 fcs, tvbuff_t *tvb, guint len)
300 {
301         const guchar *cp;
302
303         cp = tvb_get_ptr(tvb, 0, len);
304         while (len--)
305                 fcs = (fcs >> 8) ^ tbl_crc24[(fcs ^ *cp++) & 0xff];
306         return fcs;
307 }
308
309 typedef enum {
310         FCS_VALID,
311         FCS_NOT_VALID,
312         FCS_NOT_VALID_DUE_TO_CIPHERING,
313         FCS_NOT_COMPUTED
314 } fcs_status_t;
315
316
317 /* sub-dissector for XID data */
318 static void llc_gprs_dissect_xid(tvbuff_t *tvb,
319                                                                  packet_info *pinfo,
320                                                                  proto_item *llcgprs_tree)
321
322 {
323         guint8 xid_param_len = 0, byte1 = 0, byte2 = 0, item_len = 0, tmp = 0;
324         guint16 location = 0;
325         guint16 loop_counter = 0;
326         proto_tree *uinfo_tree = NULL;
327         proto_tree *xid_tree = NULL;
328         guint16 info_len;
329
330         info_len = tvb_reported_length(tvb);
331
332         xid_tree = proto_tree_add_subtree_format(llcgprs_tree, tvb, 0, info_len,
333                                 ett_ui, NULL, "Information Field: Length = %u", info_len);
334
335         while (location < info_len)
336         {
337                 /* parse the XID parameters */
338                 byte1 = tvb_get_guint8(tvb, location);
339
340                 if (byte1 & 0x80)
341                 {
342                         guint8 xid_param_len_high = 0;
343                         guint8 xid_param_len_low = 0;
344                         byte2 = tvb_get_guint8(tvb, location + 1);
345
346                         /* XL bit is set - length is continued in second byte */
347                         xid_param_len_high = byte1 & 0x03;
348                         xid_param_len_low = byte2 & 0xFC;
349
350                         /* bit shift the rest of the length */
351                         xid_param_len_low = xid_param_len_low >> 2;
352                         xid_param_len_low = xid_param_len_low & 0x3F;
353
354                         xid_param_len_high = xid_param_len_high << 6;
355                         xid_param_len_high = xid_param_len_high & 0xC0;
356
357                         /* combine the two */
358                         xid_param_len = xid_param_len_high | xid_param_len_low;
359                         item_len = xid_param_len + 2;
360
361                 }
362                 else
363                 {
364                         xid_param_len = byte1 & 0x3;
365                         item_len = xid_param_len + 1;
366                 }
367
368                 tmp =  byte1 & 0x7C;
369                 tmp = tmp >> 2;
370
371                 if (tmp == 0xB) /* L3 XID parameters, call the SNDCP-XID dissector */
372                 {
373                         tvbuff_t        *sndcp_xid_tvb;
374                         guint8 sndcp_xid_offset;
375
376                         uinfo_tree = proto_tree_add_subtree(xid_tree, tvb, location, item_len,
377                                 ett_ui, NULL, "XID parameter Type: L3 parameters");
378                         proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_xl, tvb, location, 1, byte1);
379                         proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_type, tvb, location, 1, byte1);
380                         proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len1, tvb, location, 1, byte1);
381                         if (byte1 & 0x80) {
382                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len2, tvb, location+1, 1, byte2);
383                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_spare, tvb, location+1, 1, byte2);
384                                 sndcp_xid_offset = 2;
385                         }
386                         else
387                         {
388                                 sndcp_xid_offset = 1;
389                         }
390
391                         if (xid_param_len) {
392
393                                 sndcp_xid_tvb = tvb_new_subset_length (tvb, location+sndcp_xid_offset, xid_param_len);
394
395                                 if(sndcp_xid_handle)
396                                 {
397                                         call_dissector(sndcp_xid_handle, sndcp_xid_tvb, pinfo, uinfo_tree);
398                                 }
399                         }
400
401                         location += item_len;
402                 }
403                 else
404                 {
405                         if (( xid_param_len > 0 ) && ( xid_param_len <=4 ))
406                         {
407                                 guint32 value = 0;
408                                 guint8 i;
409                                 for (i=1;i<=xid_param_len;i++)
410                                 {
411                                         value <<= 8;
412                                         value |= (guint32)tvb_get_guint8(tvb, location+i );
413                                 }
414                                 uinfo_tree = proto_tree_add_subtree_format(xid_tree, tvb, location, item_len,
415                                         ett_ui, NULL, "XID Parameter Type: %s - Value: %u",
416                                         val_to_str_ext_const(tmp, &xid_param_type_str_ext, "Reserved Type:%X"), value);
417                         }
418                         else
419                         {
420                                 uinfo_tree = proto_tree_add_subtree_format(xid_tree, tvb, location, item_len,
421                                         ett_ui, NULL, "XID Parameter Type: %s",
422                                         val_to_str_ext_const(tmp, &xid_param_type_str_ext, "Reserved Type:%X"));
423                         }
424                         proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_xl, tvb, location,
425                                 1, byte1);
426                         proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_type, tvb, location,
427                                 1, byte1);
428                         proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len1, tvb, location,
429                                 1, byte1);
430
431                         if (byte1 & 0x80) {
432                                 /* length continued into byte 2 */
433                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len2, tvb, location,
434                                         1, byte2);
435                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_spare, tvb, location,
436                                         1, byte2);
437
438                                 /* be sure to account for the second byte of length */
439                                 location++;
440                         }
441
442                         location++;
443                         for (loop_counter = 0; loop_counter < xid_param_len; loop_counter++)
444                         {
445                                 /* grab the information in the XID param */
446                                 byte2 = tvb_get_guint8(tvb, location);
447                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_byte, tvb, location,
448                                         1, byte2);
449                                 location++;
450                         }
451                 }
452         }
453 }
454
455
456 static int
457 dissect_llcgprs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
458 {
459         guint8 addr_fld=0, sapi=0, ctrl_fld_fb=0, frame_format, tmp=0;
460         guint16 offset=0 , epm = 0, nu=0, ctrl_fld_ui_s=0;
461         guint16 crc_length=0, llc_data_length=0;
462         proto_item *ti, *addres_field_item;
463         proto_tree *llcgprs_tree=NULL , *ad_f_tree =NULL, *ctrl_f_tree=NULL, *ui_tree=NULL;
464         tvbuff_t *next_tvb;
465         guint length, captured_length;
466         guint32 fcs=0;
467         guint32 fcs_calc=0;
468         fcs_status_t fcs_status;
469         guint16 ns = 0;
470         guint16 nr = 0;
471         guint8 k = 0;
472         guint8 m_bits = 0;
473         guint8 info_len = 0;
474         proto_tree *uinfo_tree = NULL;
475         gboolean ciphered_ui_frame = FALSE;
476
477         col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-LLC");
478
479         /* llc_data_length includes the header and the payload */
480         llc_data_length = length = tvb_reported_length(tvb);
481         if (length >= CRC_LENGTH) {
482                 /*
483                  * The packet is big enough to have a CRC.
484                  */
485                 llc_data_length -= CRC_LENGTH;
486         }
487         else
488         {
489                 /*
490                  * The packet isn't big enough to have a CRC; claim
491                  * the data length is 0.
492                  */
493                 llc_data_length = 0;
494         }
495         captured_length = tvb_captured_length(tvb);
496
497         /*
498          * Address field.
499          */
500         addr_fld = tvb_get_guint8(tvb, offset);
501         offset++;
502
503         if (addr_fld > 128 )
504         {
505                 col_set_str(pinfo->cinfo, COL_INFO, "Invalid packet - Protocol Discriminator bit is set to 1");
506                 return offset;
507         }
508
509         sapi = addr_fld & 0xF;
510
511         col_add_fstr(pinfo->cinfo, COL_INFO, "SAPI: %s", val_to_str_ext_const(sapi, &sapi_abrv_ext, "Unknown (%d)"));
512
513         /* In the interest of speed, if "tree" is NULL, don't do any work not
514                 necessary to generate protocol tree items. */
515         if (tree)
516         {
517                 ti = proto_tree_add_protocol_format(tree, proto_llcgprs, tvb, 0, -1,
518                                                     "MS-SGSN LLC (Mobile Station - Serving GPRS Support Node Logical Link Control)  SAPI: %s",
519                                                     val_to_str_ext_const(sapi, &sapi_t_ext, "Unknown (%u)"));
520
521                 llcgprs_tree = proto_item_add_subtree(ti, ett_llcgprs);
522
523                 /* add an item to the subtree, see section 1.6 for more information */
524                 addres_field_item = proto_tree_add_uint_format(llcgprs_tree, hf_llcgprs_sapi,
525                      tvb, 0, 1, sapi, "Address field  SAPI: %s", val_to_str_ext_const(sapi, &sapi_abrv_ext, "Unknown (%d)"));
526
527                 ad_f_tree = proto_item_add_subtree(addres_field_item, ett_llcgprs_adf);
528                 proto_tree_add_boolean(ad_f_tree, hf_llcgprs_pd, tvb, 0, 1, addr_fld );
529                 proto_tree_add_boolean(ad_f_tree, hf_llcgprs_cr, tvb, 0, 1, addr_fld );
530                 proto_tree_add_uint(ad_f_tree, hf_llcgprs_sapib, tvb, 0, 1, addr_fld );
531         }
532
533         /*
534          * Control field.
535          */
536         ctrl_fld_fb = tvb_get_guint8(tvb, offset);
537         if (ctrl_fld_fb < 0xC0)
538         {
539                 frame_format = (ctrl_fld_fb < 0x80)? I_FORMAT : S_FORMAT;
540         }
541         else
542         {
543                 frame_format = (ctrl_fld_fb < 0xe0 )? UI_FORMAT : U_FORMAT;
544         }
545
546         switch (frame_format)
547         {
548         case I_FORMAT:
549                 col_append_str(pinfo->cinfo, COL_INFO, ", I, ");
550
551                 ns = tvb_get_ntohs(tvb, offset);
552                 ns = (ns >> 4)& 0x01FF;
553                 nr = ctrl_fld_ui_s = tvb_get_ntohs(tvb, offset + 1);
554                 nr = (nr >> 2) & 0x01FF;
555
556                 epm = ctrl_fld_ui_s & 0x3;
557
558                 col_append_str(pinfo->cinfo, COL_INFO, val_to_str(epm, cr_formats_ipluss, "Unknown (%d)"));
559                 col_append_fstr(pinfo->cinfo, COL_INFO, ", N(S) = %u", ns);
560                 col_append_fstr(pinfo->cinfo, COL_INFO, ", N(R) = %u", nr);
561
562                 if (tree)
563                 {
564                         guint32 tmpx;
565
566                         ctrl_f_tree = proto_tree_add_subtree_format(llcgprs_tree, tvb, offset,
567                                                               3, ett_llcgprs_sframe, NULL, "Information format: %s: N(S) = %u,  N(R) = %u",
568                                                               val_to_str(epm, cr_formats_ipluss, "Unknown (%d)"), ns, nr);
569
570                         /* retrieve the second octet */
571                         tmpx = tvb_get_ntohs(tvb, offset)  << 16;
572                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_ifmt, tvb, offset, 3, tmpx);
573                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_ia, tvb, offset, 3, tmpx);
574                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_izerobit, tvb, offset, 3, tmpx);
575
576                         tmpx = ns << 12;
577                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_isack_ns, tvb, offset, 3, tmpx);
578
579                         tmpx = nr << 2;
580                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_isack_nr, tvb, offset, 3, tmpx);
581                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_isack_sfb, tvb, offset, 3, ctrl_fld_ui_s);
582                 }
583
584                 /* advance to either R Bitmap or Payload */
585                 offset += 3;
586
587                 /* check to see if epm is SACK - meaning this is an ISACK frame */
588                 if (epm == 0x03)
589                 {
590                         guint8 kmask;
591                         /* SACK Frame */
592                         k = kmask = tvb_get_guint8(tvb, offset);
593                         k = k & 0x1F;
594
595                         /* advance past the k field */
596                         offset++;
597
598                         /* the real value of k is actually k + 1 */
599                         /* account for the off by one representation */
600                         k++;
601
602                         col_append_fstr(pinfo->cinfo, COL_INFO, ", k = %u", k);
603
604                         if (tree)
605                         {
606                                 guint8 loop_count = 0;
607                                 guint8 r_byte = 0;
608                                 guint16 location = offset;
609
610                                 ctrl_f_tree = proto_tree_add_subtree_format(llcgprs_tree, tvb, (offset-1),
611                                                                       (k+1), ett_llcgprs_sframe, NULL, "SACK FRAME: k = %u", k);
612
613                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_kmask, tvb, offset-1, 1, kmask);
614                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_k, tvb, offset-1, 1, k);
615
616                                 /* display the R Bitmap */
617                                 for (loop_count = 0; loop_count < k; loop_count++)
618                                 {
619                                         r_byte = tvb_get_guint8(tvb, location);
620                                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_rbyte, tvb, location, 1, r_byte);
621                                         location++;
622                                 }
623                         }
624
625                         /* step past the R Bitmap */
626                         offset += k;
627                 }
628
629                 crc_length = llc_data_length;
630                 break;
631
632         case S_FORMAT:
633                 col_append_str(pinfo->cinfo, COL_INFO, ", S, ");
634
635                 nu = ctrl_fld_ui_s = tvb_get_ntohs(tvb, offset);
636                 epm = ctrl_fld_ui_s & 0x3;
637                 nu = (nu >>2)&0x01FF;
638
639                 col_append_str(pinfo->cinfo, COL_INFO, val_to_str(epm, cr_formats_ipluss, "Unknown (%d)"));
640                 col_append_fstr(pinfo->cinfo, COL_INFO, ", N(R) = %u", nu);
641
642                 if (tree)
643                 {
644                         static const int * s_formats[] = {
645                                 &hf_llcgprs_S_fmt,
646                                 &hf_llcgprs_As,
647                                 &hf_llcgprs_sspare,
648                                 &hf_llcgprs_NR,
649                                 &hf_llcgprs_sjsd,
650                                 NULL
651                         };
652
653                         proto_tree_add_bitmask_text(llcgprs_tree, tvb, offset, 2,
654                                                               "Supervisory format: ", NULL, ett_llcgprs_sframe, s_formats, ENC_BIG_ENDIAN, 0);
655                 }
656                 offset += 2;
657
658                 if ((ctrl_fld_ui_s & 0x03) == 0x03)
659                         /* It is a SACK frame */
660                 {
661                         /* TODO: length is fudged - it is not correct */
662                         guint32 sack_length = llc_data_length - offset;
663
664                         if (tree)
665                         {
666                                 guint loop_count;
667                                 guint8 r_byte;
668                                 guint16 location = offset;
669                                 ctrl_f_tree = proto_tree_add_subtree_format(llcgprs_tree, tvb, offset, sack_length,
670                                                                       ett_llcgprs_sframe, NULL, "SACK FRAME: length = %u", sack_length);
671                                 /* display the R Bitmap */
672                                 for (loop_count = 0; loop_count < sack_length; loop_count++)
673                                 {
674                                         r_byte = tvb_get_guint8(tvb, location);
675                                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_rbyte, tvb,
676                                                             location, 1, r_byte);
677                                         location++;
678                                 }
679
680                                 /* step past the r bitmap */
681                                 offset += sack_length;
682                         }
683                 }
684
685                 crc_length = llc_data_length;
686                 break;
687
688         case UI_FORMAT:
689                 col_append_str(pinfo->cinfo, COL_INFO, ", UI, ");
690
691                 nu = ctrl_fld_ui_s = tvb_get_ntohs(tvb, offset);
692                 epm = ctrl_fld_ui_s & 0x3;
693                 nu = (nu >>2)&0x01FF;
694
695                 /* If the frame is ciphered, the calculated FCS will not be valid (unless it has been unciphered) */
696                 if (epm & UI_MASK_E)
697                 {
698                         ciphered_ui_frame = TRUE;
699                 }
700                 if ((epm & UI_MASK_PM)== 0)
701                 {
702                         /* FCS covers at maximum the LLC header and N202 bytes */
703                         crc_length = MIN(UI_HDR_LENGTH + N202, llc_data_length);
704                 }
705                 else
706                 {
707                         crc_length = llc_data_length;
708                 }
709
710                 col_append_str(pinfo->cinfo, COL_INFO, val_to_str(epm, pme, "Unknown (%d)"));
711                 col_append_fstr(pinfo->cinfo, COL_INFO, ", N(U) = %u", nu);
712
713                 if (tree)
714                 {
715                         static const int * i_formats[] = {
716                                 &hf_llcgprs_U_fmt,
717                                 &hf_llcgprs_sp_bits,
718                                 &hf_llcgprs_NU,
719                                 &hf_llcgprs_E_bit,
720                                 &hf_llcgprs_PM_bit,
721                                 NULL
722                         };
723
724                         proto_tree_add_bitmask_text(llcgprs_tree, tvb, offset, 2,
725                                                               "Unconfirmed Information format - UI: ", NULL, ett_llcgprs_ctrlf, i_formats, ENC_BIG_ENDIAN, 0);
726                 }
727                 offset += 2;
728                 break;
729
730         case U_FORMAT:
731                 col_append_str(pinfo->cinfo, COL_INFO, ", U, ");
732
733                 tmp =  ctrl_fld_fb & 0xf;
734
735                 col_append_str(pinfo->cinfo, COL_INFO,
736                                val_to_str(tmp, cr_formats_unnumb, "Unknown/invalid code:%X"));
737
738                 ui_tree = proto_tree_add_subtree_format(llcgprs_tree, tvb, offset, (llc_data_length-1),
739                                                     ett_ui, NULL, "Unnumbered frame: %s",
740                                                     val_to_str(tmp, cr_formats_unnumb, "Unknown/invalid code:%X"));
741
742                 proto_tree_add_uint(ui_tree, hf_llcgprs_Un, tvb, offset, 1, ctrl_fld_fb);
743                 proto_tree_add_boolean(ui_tree, hf_llcgprs_PF, tvb, offset, 1, ctrl_fld_fb);
744                 proto_tree_add_uint(ui_tree, hf_llcgprs_ucom, tvb, offset, 1, ctrl_fld_fb);
745                 offset += 1;
746                 crc_length = llc_data_length;
747                 break;
748         }
749
750         /*
751          * FCS.
752          */
753         if (captured_length >= length && length >= CRC_LENGTH)
754         {
755                 /*
756                  * We have all the packet data, including the full FCS,
757                  * so we can compute the FCS.
758                  */
759                 fcs_calc = crc_calc ( INIT_CRC24 , tvb, crc_length );
760                 fcs_calc = ~fcs_calc;
761                 fcs_calc &= 0xffffff;
762
763                 fcs = tvb_get_letoh24(tvb, llc_data_length);
764                 if ( fcs_calc == fcs )
765                 {
766                         fcs_status = FCS_VALID;
767                         proto_tree_add_uint_format_value(llcgprs_tree, hf_llcgprs_fcs, tvb, llc_data_length, CRC_LENGTH,
768                                 fcs_calc&0xffffff, "0x%06x (correct)", fcs_calc&0xffffff);
769                 }
770                 else
771                 {
772                         if (ciphered_ui_frame)
773                         {
774                                 fcs_status = FCS_NOT_VALID_DUE_TO_CIPHERING;
775                                 proto_tree_add_uint_format_value(llcgprs_tree, hf_llcgprs_fcs, tvb, llc_data_length, CRC_LENGTH,
776                                         fcs, "0x%06x  (incorrect, maybe due to ciphering, calculated 0x%06x)", fcs, fcs_calc );
777                         }
778                         else
779                         {
780                                 fcs_status = FCS_NOT_VALID;
781                                 proto_tree_add_uint_format_value(llcgprs_tree, hf_llcgprs_fcs, tvb, llc_data_length, CRC_LENGTH,
782                                         fcs, "0x%06x  (incorrect, should be 0x%06x)", fcs, fcs_calc );
783                         }
784                 }
785         }
786         else
787         {
788                 /* We don't have enough data to compute the FCS. */
789                 fcs_status = FCS_NOT_COMPUTED;
790                 proto_tree_add_uint_format_value(llcgprs_tree, hf_llcgprs_fcs, tvb, 0, 0, 0,
791                         "FCS: Not enough data to compute the FCS");
792         }
793
794         /*
795          * Information field.
796          */
797         switch (frame_format)
798         {
799         case I_FORMAT:
800                 if ((sapi == SAPI_TOM2) || (sapi == SAPI_TOM8))
801                 {
802                         /* if SAPI is TOM do other parsing */
803                         if (tree)
804                         {
805                                 guint8 tom_byte = 0;
806                                 guint8 remaining_length = 0;
807                                 guint8 tom_pd = 0;
808                                 int loop_counter = 0;
809
810                                 tom_byte = tvb_get_guint8(tvb, offset);
811                                 remaining_length = (tom_byte >> 4) & 0x0F;
812                                 tom_pd = tom_byte & 0x0F;
813
814                                 ctrl_f_tree = proto_tree_add_subtree_format(llcgprs_tree, tvb, offset,
815                                                                       (llc_data_length-offset), ett_llcgprs_sframe, NULL,
816                                                                       "TOM Envelope - Protocol: %s",
817                                                                       val_to_str(tom_pd, tompd_formats, "Unknown (%d)"));
818
819                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_rl, tvb, offset, 1, tom_byte);
820                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_pd, tvb, offset, 1, tom_byte);
821
822                                 /* step past the TOM header first byte */
823                                 offset++;
824
825                                 /* TOM remaining length field value 0x0F is reserved for extension */
826                                 if (remaining_length != 0x0F)
827                                 {
828                                         /* parse the rest of the TOM header */
829                                         for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
830                                         {
831                                                 tom_byte = tvb_get_guint8(tvb, offset);
832
833                                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_header, tvb,
834                                                                     offset, 1, tom_byte);
835
836                                                 /* step to the next byte */
837                                                 offset++;
838                                         }
839
840                                         remaining_length = llc_data_length - offset;
841
842                                         /* parse the TOM message capsule */
843                                         for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
844                                         {
845                                                 tom_byte = tvb_get_guint8(tvb, offset);
846
847                                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_data, tvb,
848                                                                     offset, 1, tom_byte);
849
850                                                 /* step to the next byte */
851                                                 offset++;
852                                         }
853                                 }
854                         }
855                 }
856                 else
857                 {
858                         /* otherwise - call a subdissector */
859                         next_tvb = tvb_new_subset_length(tvb, offset, (llc_data_length-offset));
860                         if (!dissector_try_uint(llcgprs_subdissector_table, sapi, next_tvb, pinfo, tree))
861                                 /* if no subdissector is found, call the data dissector */
862                         {
863                                 call_dissector(data_handle, next_tvb, pinfo, tree);
864                         }
865                 }
866                 break;
867
868         case S_FORMAT:
869                 /* should parse the rest of the supervisory message based on type */
870                 /* if SAPI is TOM do other parsing */
871                 if ((sapi == SAPI_TOM2) || (sapi == SAPI_TOM8))
872                 {
873                         if (tree)
874                         {
875                                 guint8 tom_byte = 0;
876                                 guint8 remaining_length = 0;
877                                 guint8 tom_pd = 0;
878                                 int loop_counter = 0;
879
880                                 tom_byte = tvb_get_guint8(tvb, offset);
881                                 remaining_length = (tom_byte >> 4) & 0x0F;
882                                 tom_pd = tom_byte & 0x0F;
883
884                                 ctrl_f_tree = proto_tree_add_subtree_format(llcgprs_tree, tvb, offset,
885                                                                       (llc_data_length-offset), ett_llcgprs_sframe, NULL,
886                                                                       "TOM Envelope - Protocol: %s",
887                                                                       val_to_str(tom_pd, tompd_formats, "Unknown (%d)"));
888
889                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_rl, tvb, offset, 1, tom_byte);
890                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_pd, tvb, offset, 1, tom_byte);
891
892                                 /* step past the TOM header first byte */
893                                 offset++;
894
895                                 /* TOM remaining length field value 0x0F is reserved for extension */
896                                 if (remaining_length != 0x0F)
897                                 {
898                                         /* parse the rest of the TOM header */
899                                         for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
900                                         {
901                                                 tom_byte = tvb_get_guint8(tvb, offset);
902                                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_header, tvb,
903                                                                     offset, 1, tom_byte);
904
905                                                 /* step to the next byte */
906                                                 offset++;
907                                         }
908
909                                         /* Amount of frame left from offset to crc */
910                                         remaining_length = llc_data_length - offset;
911
912                                         /* parse the TOM message capsule */
913                                         for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
914                                         {
915                                                 tom_byte = tvb_get_guint8(tvb, offset);
916                                                 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_data, tvb,
917                                                                     offset, 1, tom_byte);
918
919                                                 /* step to the next byte */
920                                                 offset++;
921                                         }
922                                 }
923                         }
924                 }
925                 else if (llc_data_length>offset)
926                 {
927                         /* otherwise - call a subdissector */
928                         next_tvb = tvb_new_subset_length(tvb, offset, (llc_data_length-offset));
929                         if (!dissector_try_uint(llcgprs_subdissector_table, sapi, next_tvb, pinfo, tree))
930                         {
931                                 call_dissector(data_handle, next_tvb, pinfo, tree);
932                         }
933                 }
934                 break;
935
936         case UI_FORMAT:
937                 next_tvb = tvb_new_subset_length(tvb, offset, (llc_data_length-offset));
938
939                 if ((ignore_cipher_bit && (fcs_status == FCS_VALID)) || !(epm & 0x2))
940                 {
941                         /* Either we're ignoring the cipher bit
942                          * (because the bit is set but the
943                          * data is unciphered), and the data has
944                          * a valid FCS, or the cipher
945                          * bit isn't set (indicating that the
946                          * data is unciphered).  Try dissecting
947                          * it with a subdissector. */
948
949                         /* if SAPI is TOM do other parsing */
950                         if ((sapi == SAPI_TOM2) || (sapi == SAPI_TOM8))
951                         {
952                                 if (tree)
953                                 {
954                                         guint8 tom_byte = 0;
955                                         guint8 remaining_length = 0;
956                                         guint8 tom_pd = 0;
957                                         int loop_counter = 0;
958
959                                         tom_byte = tvb_get_guint8(tvb, offset);
960                                         remaining_length = (tom_byte >> 4) & 0x0F;
961                                         tom_pd = tom_byte & 0x0F;
962
963                                         ctrl_f_tree = proto_tree_add_subtree_format(llcgprs_tree, tvb, offset,
964                                                                               (llc_data_length-offset), ett_llcgprs_sframe, NULL,
965                                                                               "TOM Envelope - Protocol: %s",
966                                                                               val_to_str(tom_pd, tompd_formats, "Unknown (%d)"));
967
968                                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_rl, tvb, offset, 1, tom_byte);
969                                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_pd, tvb, offset, 1, tom_byte);
970
971                                         /* step past the TOM header first byte */
972                                         offset++;
973
974                                         /* TOM remaining length field value 0x0F is reserved for extension */
975                                         if (remaining_length != 0x0F)
976                                         {
977                                                 /* parse the rest of the TOM header */
978                                                 for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
979                                                 {
980                                                         tom_byte = tvb_get_guint8(tvb, offset);
981
982                                                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_header, tvb,
983                                                                             offset, 1, tom_byte);
984
985                                                         /* step to the next byte */
986                                                         offset++;
987                                                 }
988
989                                                 /* Amount of frame left from offset to crc */
990                                                 remaining_length = llc_data_length - offset;
991
992                                                 /* parse the TOM message capsule */
993                                                 for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
994                                                 {
995                                                         tom_byte = tvb_get_guint8(tvb, offset);
996
997                                                         proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_data, tvb,
998                                                                             offset, 1, tom_byte);
999
1000                                                         /* step to the next byte */
1001                                                         offset++;
1002                                                 }
1003                                         }
1004                                 }
1005                         }
1006                         else if (llc_data_length>offset)
1007                         {
1008                                 /* otherwise - call a subdissector */
1009                                 if (!dissector_try_uint(llcgprs_subdissector_table, sapi, next_tvb, pinfo, tree))
1010                                 {
1011                                         call_dissector(data_handle, next_tvb, pinfo, tree);
1012                                 }
1013                         }
1014                 }
1015                 else
1016                 {
1017                         /* ciphered information - just parse it as data */
1018                         call_dissector(data_handle, next_tvb, pinfo, tree);
1019                 }
1020                 break;
1021
1022         case U_FORMAT:
1023                 m_bits = ctrl_fld_fb & 0x0F;
1024
1025                 info_len = llc_data_length - offset;
1026
1027                 switch (m_bits)
1028                 {
1029                 case U_DM:
1030                 case U_DISC:
1031                 case U_NULL:
1032                         /* These frames SHOULD NOT have an info field */
1033                         proto_tree_add_expert(llcgprs_tree, pinfo, &ei_llcgprs_no_info_field, tvb, offset, (llc_data_length-2));
1034                         break;
1035                 case U_UA:
1036                         /* This frame MAY or MAY NOT have an info field */
1037                         /* Info field, if it exists, consists of XID parameters */
1038                         if (tree)
1039                         {
1040                                 tvbuff_t        *xid_tvb;
1041                                 xid_tvb = tvb_new_subset_length (tvb, offset, info_len);
1042
1043                                 llc_gprs_dissect_xid(xid_tvb, pinfo, llcgprs_tree);
1044                         }
1045                         break;
1046                 case U_SABM:
1047                 case U_XID:
1048                         /* These frames do have info fields consisting of XID parameters */
1049                         /* Info field consists of XID parameters */
1050                         if (tree)
1051                         {
1052                                 tvbuff_t        *xid_tvb;
1053                                 xid_tvb = tvb_new_subset_length (tvb, offset, info_len);
1054
1055                                 llc_gprs_dissect_xid(xid_tvb, pinfo, llcgprs_tree);
1056                         }
1057                         break;
1058                 case U_FRMR:
1059                         /* This frame has a special format info field */
1060                         if (tree)
1061                         {
1062                                 guint32 fld_vars = 0;
1063                                 guint16 cf_byte = 0;
1064                                 int loop_counter = 0;
1065                                 int location = 0;
1066
1067                                 ui_tree = proto_tree_add_subtree_format(llcgprs_tree, tvb, offset, (llc_data_length-2),
1068                                                             ett_ui, NULL, "Information Field: Length = %u", info_len);
1069
1070                                 uinfo_tree = proto_tree_add_subtree(ui_tree, tvb, offset, 6,
1071                                                                   ett_ui, NULL, "Rejected Frame Control Field");
1072
1073                                 location = offset;
1074                                 for (loop_counter = 0; loop_counter < 3; loop_counter++)
1075                                 {
1076                                         /* display the rejected frame control field */
1077                                         cf_byte = tvb_get_ntohs(tvb, location);
1078                                         proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_cf, tvb, location,
1079                                                             2, cf_byte);
1080
1081                                         location += 2;
1082                                 }
1083
1084                                 uinfo_tree = proto_tree_add_subtree(ui_tree, tvb, location, 4,
1085                                                                   ett_ui, NULL, "Information Field Data");
1086
1087                                 fld_vars = tvb_get_ntohl(tvb, location);
1088                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_spare, tvb, location,
1089                                                     4, fld_vars);
1090                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_vs, tvb, location,
1091                                                     2, fld_vars);
1092                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_vr, tvb, (location + 1),
1093                                                     2, fld_vars);
1094                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_cr, tvb, (location + 2),
1095                                                     1, fld_vars);
1096                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w4, tvb, (location + 3),
1097                                                     1, fld_vars);
1098                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w3, tvb, (location + 3),
1099                                                     1, fld_vars);
1100                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w2, tvb, (location + 3),
1101                                                     1, fld_vars);
1102                                 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w1, tvb, (location + 3),
1103                                                     1, fld_vars);
1104                         }
1105                         break;
1106                 default:
1107                         break;
1108                 }
1109                 crc_length = llc_data_length;
1110                 break;
1111         }
1112
1113         return tvb_captured_length(tvb);
1114 }
1115
1116
1117 /* Register the protocol with Wireshark */
1118
1119 void
1120 proto_register_llcgprs(void)
1121 {
1122 /* Setup list of header fields  See Section 1.6.1 for details */
1123         static hf_register_info hf[] = {
1124                 { &hf_llcgprs_sapi,
1125                   { "SAPI", "llcgprs.sapi", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
1126                     &sapi_abrv_ext, 0x0, "Service Access Point Identifier", HFILL }},
1127
1128                 { &hf_llcgprs_pd,
1129                   { "Protocol Discriminator_bit", "llcgprs.pd", FT_BOOLEAN, 8,
1130                     TFS(&pd_bit), 0x80, "Protocol Discriminator bit (should be 0)", HFILL }},
1131
1132                 { &hf_llcgprs_fcs,
1133                   { "FCS", "llcgprs.fcs", FT_UINT24, BASE_HEX,
1134                     NULL, 0, NULL, HFILL }},
1135
1136                 {&hf_llcgprs_sjsd,
1137                  { "Supervisory function bits", "llcgprs.s1s2", FT_UINT16, BASE_HEX,
1138                    VALS(cr_formats_ipluss), 0x3, NULL, HFILL }},
1139
1140                 { &hf_llcgprs_cr,
1141                   { "Command/Response bit", "llcgprs.cr", FT_BOOLEAN, 8,
1142                     TFS(&cr_bit), 0x40, NULL, HFILL}},
1143
1144                 { &hf_llcgprs_sapib,
1145                   { "SAPI", "llcgprs.sapib", FT_UINT8, BASE_DEC|BASE_EXT_STRING ,
1146                     &sapi_t_ext, 0xf, "Service Access Point Identifier", HFILL }},
1147
1148                 { &hf_llcgprs_U_fmt,
1149                   { "UI format", "llcgprs.ui", FT_UINT16, BASE_HEX,
1150                     NULL, UI_MASK_FMT, "UI frame format", HFILL}},
1151
1152                 { &hf_llcgprs_Un,
1153                   { "U format", "llcgprs.u", FT_UINT8, BASE_DEC,
1154                     NULL, 0xe0, "U frame format", HFILL}},
1155
1156                 { &hf_llcgprs_sp_bits,
1157                   { "Spare bits", "llcgprs.ui_sp_bit", FT_UINT16, BASE_HEX,
1158                     NULL, UI_MASK_SPB, NULL, HFILL}},
1159
1160                 { &hf_llcgprs_NU,
1161                   { "N(U)", "llcgprs.nu", FT_UINT16, BASE_DEC,
1162                     NULL, UI_MASK_NU, "Transmitted unconfirmed sequence number", HFILL}},
1163
1164                 { &hf_llcgprs_E_bit,
1165                   { "E bit", "llcgprs.e", FT_BOOLEAN, 16,
1166                     TFS(&e_bit), UI_MASK_E, "Encryption mode bit", HFILL }},
1167
1168                 { &hf_llcgprs_PM_bit,
1169                   { "PM bit", "llcgprs.pm", FT_BOOLEAN, 16,
1170                     TFS(&pm_bit), UI_MASK_PM, "Protected mode bit", HFILL}},
1171
1172                 { &hf_llcgprs_As,
1173                   { "Ackn request bit", "llcgprs.as", FT_BOOLEAN, 16,
1174                     TFS(&a_bit), 0x2000 , "Acknowledgement request bit A", HFILL}},
1175
1176                 { &hf_llcgprs_PF,
1177                   { "P/F bit", "llcgprs.pf", FT_BOOLEAN, 8,
1178                     NULL, 0x10, "Poll/Final bit", HFILL}},
1179
1180                 { &hf_llcgprs_ucom,
1181                   { "Command/Response", "llcgprs.ucom", FT_UINT8, BASE_HEX,
1182                     VALS(cr_formats_unnumb), 0xf, "Commands and Responses", HFILL }},
1183
1184                 { &hf_llcgprs_NR,
1185                   { "Receive sequence number", "llcgprs.nr", FT_UINT16, BASE_DEC,
1186                     NULL, UI_MASK_NU, "Receive sequence number N(R)", HFILL }},
1187
1188                 {&hf_llcgprs_S_fmt,
1189                  { "S format", "llcgprs.s", FT_UINT16, BASE_DEC,
1190                    NULL, 0xc000, "Supervisory format S", HFILL}},
1191
1192                 {&hf_llcgprs_kmask,
1193                  { "ignored", "llcgprs.kmask", FT_UINT8,
1194                    BASE_DEC, NULL, 0xE0, NULL, HFILL}},
1195
1196                 {&hf_llcgprs_k,
1197                  { "k", "llcgprs.k", FT_UINT8, BASE_DEC,
1198                    NULL, 0x1F, "k counter", HFILL}},
1199
1200                 {&hf_llcgprs_isack_ns,
1201                  { "N(S)", "llcgprs.sackns", FT_UINT24, BASE_DEC,
1202                    NULL, 0x1FF000, NULL, HFILL}},
1203
1204                 {&hf_llcgprs_isack_nr,
1205                  { "N(R)", "llcgprs.sacknr", FT_UINT24, BASE_DEC,
1206                    NULL, 0x0007FC, NULL, HFILL}},
1207
1208                 {&hf_llcgprs_isack_sfb,
1209                  { "Supervisory function bits", "llcgprs.sacksfb", FT_UINT24, BASE_HEX,
1210                    VALS(cr_formats_ipluss), 0x000003, NULL, HFILL }},
1211
1212                 {&hf_llcgprs_ifmt,
1213                  { "I Format", "llcgprs.ifmt", FT_UINT24, BASE_DEC,
1214                    NULL, 0x800000, "I Fmt Bit", HFILL}},
1215
1216                 {&hf_llcgprs_ia,
1217                  { "Ack Bit", "llcgprs.ia", FT_UINT24, BASE_DEC,
1218                    NULL, 0x400000, "I A Bit", HFILL}},
1219
1220                 {&hf_llcgprs_izerobit,
1221                  { "Spare", "llcgprs.iignore", FT_UINT24, BASE_DEC,
1222                    NULL, 0x200000, "Ignore Bit", HFILL}},
1223
1224                 {&hf_llcgprs_sspare,
1225                  { "Spare", "llcgprs.sspare", FT_UINT16, BASE_DEC,
1226                    NULL, 0x1800, "Ignore Bit", HFILL}},
1227
1228                 {&hf_llcgprs_rbyte,
1229                  { "R Bitmap Bits", "llcgprs.sackrbits", FT_UINT8, BASE_HEX,
1230                    NULL, 0xFF, "R Bitmap", HFILL}},
1231
1232                 /* XID Parameter Parsing Info */
1233                 {&hf_llcgprs_xid_xl,
1234                  { "XL Bit", "llcgprs.xidxl", FT_UINT8,
1235                    BASE_HEX, NULL, 0x80, "XL", HFILL}},
1236
1237                 {&hf_llcgprs_xid_type,
1238                  { "Type", "llcgprs.xidtype", FT_UINT8, BASE_DEC,
1239                    NULL, 0x7C, NULL, HFILL}},
1240
1241                 {&hf_llcgprs_xid_len1,
1242                  { "Length", "llcgprs.xidlen1", FT_UINT8, BASE_DEC,
1243                    NULL, 0x03, NULL, HFILL}},
1244
1245                 {&hf_llcgprs_xid_len2,
1246                  { "Length continued", "llcgprs.xidlen2", FT_UINT8, BASE_DEC,
1247                    NULL, 0xFC, NULL, HFILL}},
1248
1249                 {&hf_llcgprs_xid_spare,
1250                  { "Spare", "llcgprs.xidspare", FT_UINT8, BASE_HEX,
1251                    NULL, 0x03, "Ignore", HFILL}},
1252
1253                 {&hf_llcgprs_xid_byte,
1254                  { "Parameter Byte", "llcgprs.xidbyte", FT_UINT8, BASE_HEX,
1255                    NULL, 0xFF, "Data", HFILL}},
1256
1257                 /* FRMR Parsing Information */
1258                 {&hf_llcgprs_frmr_cf,
1259                  { "Control Field Octet", "llcgprs.frmrrfcf", FT_UINT16,
1260                    BASE_DEC, NULL, 0xFFFF, "Rejected Frame CF", HFILL}},
1261
1262                 {&hf_llcgprs_frmr_spare,
1263                  { "X", "llcgprs.frmrspare", FT_UINT32, BASE_HEX,
1264                    NULL, 0xF00400F0, "Filler", HFILL}},
1265
1266                 {&hf_llcgprs_frmr_vs,
1267                  { "V(S)", "llcgprs.frmrvs", FT_UINT32, BASE_DEC,
1268                    NULL, 0x0FF80000, "Current send state variable", HFILL}},
1269
1270                 {&hf_llcgprs_frmr_vr,
1271                  { "V(R)", "llcgprs.frmrvr", FT_UINT32, BASE_DEC,
1272                    NULL, 0x0003FE00, "Current receive state variable", HFILL}},
1273
1274                 {&hf_llcgprs_frmr_cr,
1275                  { "C/R", "llcgprs.frmrcr", FT_UINT32, BASE_DEC,
1276                    NULL, 0x00000100, "Rejected command response", HFILL}},
1277
1278                 {&hf_llcgprs_frmr_w4,
1279                  { "W4", "llcgprs.frmrw4", FT_UINT32, BASE_DEC,
1280                    NULL, 0x00000008, "LLE was in ABM when rejecting", HFILL}},
1281
1282                 {&hf_llcgprs_frmr_w3,
1283                  { "W3", "llcgprs.frmrw3", FT_UINT32, BASE_DEC,
1284                    NULL, 0x00000004, "Undefined control field", HFILL}},
1285
1286                 {&hf_llcgprs_frmr_w2,
1287                  { "W2", "llcgprs.frmrw2", FT_UINT32, BASE_DEC,
1288                    NULL, 0x00000002, "Info exceeded N201", HFILL}},
1289
1290                 {&hf_llcgprs_frmr_w1,
1291                  { "W1", "llcgprs.frmrw1", FT_UINT32, BASE_DEC,
1292                    NULL, 0x00000001, "Invalid - info not permitted", HFILL}},
1293
1294                 {&hf_llcgprs_tom_rl,
1295                  { "Remaining Length of TOM Protocol Header", "llcgprs.romrl", FT_UINT8, BASE_DEC,
1296                    NULL, 0xF0, "RL", HFILL}},
1297
1298                 {&hf_llcgprs_tom_pd,
1299                  { "TOM Protocol Discriminator", "llcgprs.tompd", FT_UINT8, BASE_HEX,
1300                    NULL, 0x0F, "TPD", HFILL}},
1301
1302                 {&hf_llcgprs_tom_header,
1303                  { "TOM Header Byte", "llcgprs.tomhead", FT_UINT8, BASE_HEX,
1304                    NULL, 0xFF, "thb", HFILL}},
1305
1306                 {&hf_llcgprs_tom_data,
1307                  { "TOM Message Capsule Byte", "llcgprs.tomdata", FT_UINT8, BASE_HEX,
1308                    NULL, 0xFF, "tdb", HFILL}},
1309         };
1310
1311 /* Setup protocol subtree array */
1312         static gint *ett[] = {
1313                 &ett_llcgprs,
1314                 &ett_llcgprs_adf,
1315                 &ett_llcgprs_ctrlf,
1316                 &ett_ui,
1317                 &ett_llcgprs_sframe,
1318         };
1319
1320         static ei_register_info ei[] = {
1321                 { &ei_llcgprs_no_info_field, { "llcgprs.no_info_field", PI_PROTOCOL, PI_WARN, "No Information Field", EXPFILL }},
1322         };
1323
1324         module_t *llcgprs_module;
1325         expert_module_t* expert_llcgprs;
1326
1327 /* Register the protocol name and description */
1328         proto_llcgprs = proto_register_protocol("Logical Link Control GPRS",
1329             "GPRS-LLC", "llcgprs");
1330         llcgprs_subdissector_table = register_dissector_table("llcgprs.sapi", "GPRS LLC SAPI", FT_UINT8, BASE_HEX, DISSECTOR_TABLE_NOT_ALLOW_DUPLICATE);
1331
1332 /* Required function calls to register the header fields and subtrees used */
1333         proto_register_field_array(proto_llcgprs, hf, array_length(hf));
1334         proto_register_subtree_array(ett, array_length(ett));
1335         expert_llcgprs = expert_register_protocol(proto_llcgprs);
1336         expert_register_field_array(expert_llcgprs, ei, array_length(ei));
1337         register_dissector("llcgprs", dissect_llcgprs, proto_llcgprs);
1338
1339         llcgprs_module = prefs_register_protocol ( proto_llcgprs, NULL );
1340         prefs_register_bool_preference ( llcgprs_module, "autodetect_cipher_bit",
1341             "Autodetect cipher bit",
1342             "Whether to autodetect the cipher bit (because it might be set on unciphered data)",
1343             &ignore_cipher_bit );
1344 }
1345
1346
1347 void
1348 proto_reg_handoff_llcgprs(void)
1349 {
1350         dissector_handle_t gprs_llc_handle;
1351
1352         /* make sure that the top level can call this dissector */
1353         gprs_llc_handle = find_dissector("llcgprs");
1354         dissector_add_uint("wtap_encap", WTAP_ENCAP_GPRS_LLC, gprs_llc_handle);
1355
1356         data_handle = find_dissector("data");
1357         sndcp_xid_handle  = find_dissector("sndcpxid");
1358 }
1359
1360 /*
1361  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1362  *
1363  * Local variables:
1364  * c-basic-offset: 8
1365  * tab-width: 8
1366  * indent-tabs-mode: t
1367  * End:
1368  *
1369  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1370  * :indentSize=8:tabSize=8:noTabs=false:
1371  */