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>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <epan/prefs.h>
16 #include <epan/expert.h>
18 #include <wiretap/wtap.h>
20 void proto_register_llcgprs(void);
21 void proto_reg_handoff_llcgprs(void);
29 #define UI_MASK_FMT 0xe000
30 #define UI_MASK_SPB 0x1800
31 #define UI_MASK_NU 0x07fc
32 #define UI_MASK_E 0x0002
33 #define UI_MASK_PM 0x0001
37 #define UI_HDR_LENGTH 3U
39 /* Initialize the protocol and registered fields */
40 static int proto_llcgprs
;
41 static int hf_llcgprs_pd
;
42 static int hf_llcgprs_fcs
;
43 static int hf_llcgprs_cr
;
44 static int hf_llcgprs_sapi
;
45 static int hf_llcgprs_sapib
;
46 static int hf_llcgprs_U_fmt
; /* 3 upper bits in controlfield (UI format) */
47 static int hf_llcgprs_sp_bits
; /* Spare bits in control field */
48 static int hf_llcgprs_NU
; /* Transmited unconfirmed sequence number */
49 static int hf_llcgprs_E_bit
; /* Encryption mode bit */
50 static int hf_llcgprs_PM_bit
;
51 static int hf_llcgprs_Un
;
52 static int hf_llcgprs_As
;
53 static int hf_llcgprs_ucom
;
54 static int hf_llcgprs_PF
;
55 static int hf_llcgprs_S_fmt
;
56 static int hf_llcgprs_NR
;
57 static int hf_llcgprs_sjsd
;
58 static int hf_llcgprs_k
;
59 static int hf_llcgprs_isack_ns
;
60 static int hf_llcgprs_isack_nr
;
61 static int hf_llcgprs_isack_sfb
;
62 static int hf_llcgprs_rbyte
;
63 static int hf_llcgprs_kmask
;
64 static int hf_llcgprs_ifmt
;
65 static int hf_llcgprs_Ai
;
66 static int hf_llcgprs_izerobit
;
67 static int hf_llcgprs_sspare
;
68 static int hf_llcgprs_xid_xl
;
69 static int hf_llcgprs_xid_type
;
70 static int hf_llcgprs_xid_len1
;
71 static int hf_llcgprs_xid_len2
;
72 static int hf_llcgprs_xid_spare
;
73 static int hf_llcgprs_xid_byte
;
74 static int hf_llcgprs_frmr_cf
;
75 static int hf_llcgprs_frmr_spare
;
76 static int hf_llcgprs_frmr_vs
;
77 static int hf_llcgprs_frmr_vr
;
78 static int hf_llcgprs_frmr_cr
;
79 static int hf_llcgprs_frmr_w4
;
80 static int hf_llcgprs_frmr_w3
;
81 static int hf_llcgprs_frmr_w2
;
82 static int hf_llcgprs_frmr_w1
;
83 static int hf_llcgprs_tom_rl
;
84 static int hf_llcgprs_tom_pd
;
85 static int hf_llcgprs_tom_header
;
86 static int hf_llcgprs_tom_data
;
87 static int hf_llcgprs_dummy_ui
;
89 /* Unnumbered Commands and Responses (U Frames) */
98 /* SAPI value constants */
99 #define SAPI_LLGMM 0x01
100 #define SAPI_TOM2 0x02
101 #define SAPI_LL3 0x03
102 #define SAPI_LL5 0x05
103 #define SAPI_LLSMS 0x07
104 #define SAPI_TOM8 0x08
105 #define SAPI_LL9 0x09
106 #define SAPI_LL11 0x0B
108 /* Initialize the subtree pointers */
109 static int ett_llcgprs
;
110 static int ett_llcgprs_adf
;
111 static int ett_llcgprs_ctrlf
;
112 static int ett_llcgprs_ui
;
113 static int ett_llcgprs_sframe
;
115 static expert_field ei_llcgprs_no_info_field
;
117 static dissector_handle_t sndcp_xid_handle
;
118 static dissector_handle_t gprs_llc_handle
;
120 static bool ignore_cipher_bit
;
122 static dissector_table_t llcgprs_subdissector_table
;
124 static const value_string sapi_t
[] = {
126 { 1, "GPRS Mobility Management" },
127 { 2, "Tunneling of messages 2" },
130 { 5, "User data 5" },
133 { 8, "Tunneling of messages 8" },
134 { 9, "User data 9" },
136 { 11, "User data 11" },
143 static value_string_ext sapi_t_ext
= VALUE_STRING_EXT_INIT(sapi_t
);
145 static const value_string sapi_abrv
[] = {
156 { 10, "Reserved 10" },
158 { 12, "Reserved 12" },
159 { 13, "Reserved 13" },
160 { 14, "Reserved 14" },
161 { 15, "Reserved 15" },
164 static value_string_ext sapi_abrv_ext
= VALUE_STRING_EXT_INIT(sapi_abrv
);
166 static const true_false_string a_bit
= {
167 "To solicit an acknowledgement from the peer LLE. ",
168 "The peer LLE is not requested to send an acknowledgment."
171 static const true_false_string pd_bit
= {
172 "Invalid frame PD=1",
175 static const true_false_string e_bit
= {
177 "non encrypted frame"
179 static const true_false_string pm_bit
= {
180 "FCS covers the frame header and information fields",
181 "FCS covers only the frame header and first N202 octets of the information field"
183 static const true_false_string cr_bit
= {
184 "DownLink/UpLink = Command/Response",
185 "DownLink/UpLink = Response/Command"
187 /* bits are swaped comparing with "Table 3" in ETSI document */
188 static const value_string pme
[] = {
189 { 0, "unprotected,non-ciphered information" },
190 { 1, "protected, non-ciphered information" },
191 { 2, "unprotected,ciphered information"},
192 { 3, "protected, ciphered information" },
196 static const value_string xid_param_type_str
[] = {
197 { 0x0, "Version (LLC version number)" },
198 { 0x1, "IOV-UI (ciphering Input offset value for UI frames)" },
199 { 0x2, "IOV-I (ciphering Input offset value for I frames)" },
200 { 0x3, "T200 (retransmission timeout)" },
201 { 0x4, "N200 (max number of retransmissions)" },
202 { 0x5, "N201-U (max info field length for U and UI frames)" },
203 { 0x6, "N201-I (max info field length for I frames)" },
204 { 0x7, "mD (I frame buffer size in the DL direction)" },
205 { 0x8, "mU (I frame buffer size in the UL direction)" },
206 { 0x9, "kD (window size in the DL direction)" },
207 { 0xA, "kU (window size in the UL direction)" },
208 { 0xB, "Layer-3 Parameters" },
212 static value_string_ext xid_param_type_str_ext
= VALUE_STRING_EXT_INIT(xid_param_type_str
);
214 static const value_string tompd_formats
[] = {
215 { 0x0, "Not specified" },
216 { 0x1, "TIA/EIA-136" },
218 { 0x3, "Reserved value 3" },
219 { 0x4, "Reserved value 4" },
220 { 0x5, "Reserved value 5" },
221 { 0x6, "Reserved value 6" },
222 { 0x7, "Reserved value 7" },
223 { 0x8, "Reserved value 8" },
224 { 0x9, "Reserved value 9" },
225 { 0xA, "Reserved value 10" },
226 { 0xB, "Reserved value 11" },
227 { 0xC, "Reserved value 12" },
228 { 0xD, "Reserved value 13" },
229 { 0xE, "Reserved value 14" },
230 { 0xF, "Reserved for extension" },
234 static const value_string cr_formats_unnumb
[]= {
235 { 0x1, "DM-response" },
236 { 0x4, "DISC-command" },
237 { 0x6, "UA-response" },
243 static const value_string cr_formats_ipluss
[] = {
251 /* CRC24 table - FCS */
252 static uint32_t tbl_crc24
[256] = {
253 0x00000000, 0x00d6a776, 0x00f64557, 0x0020e221, 0x00b78115, 0x00612663, 0x0041c442, 0x00976334,
254 0x00340991, 0x00e2aee7, 0x00c24cc6, 0x0014ebb0, 0x00838884, 0x00552ff2, 0x0075cdd3, 0x00a36aa5,
255 0x00681322, 0x00beb454, 0x009e5675, 0x0048f103, 0x00df9237, 0x00093541, 0x0029d760, 0x00ff7016,
256 0x005c1ab3, 0x008abdc5, 0x00aa5fe4, 0x007cf892, 0x00eb9ba6, 0x003d3cd0, 0x001ddef1, 0x00cb7987,
257 0x00d02644, 0x00068132, 0x00266313, 0x00f0c465, 0x0067a751, 0x00b10027, 0x0091e206, 0x00474570,
258 0x00e42fd5, 0x003288a3, 0x00126a82, 0x00c4cdf4, 0x0053aec0, 0x008509b6, 0x00a5eb97, 0x00734ce1,
259 0x00b83566, 0x006e9210, 0x004e7031, 0x0098d747, 0x000fb473, 0x00d91305, 0x00f9f124, 0x002f5652,
260 0x008c3cf7, 0x005a9b81, 0x007a79a0, 0x00acded6, 0x003bbde2, 0x00ed1a94, 0x00cdf8b5, 0x001b5fc3,
261 0x00fb4733, 0x002de045, 0x000d0264, 0x00dba512, 0x004cc626, 0x009a6150, 0x00ba8371, 0x006c2407,
262 0x00cf4ea2, 0x0019e9d4, 0x00390bf5, 0x00efac83, 0x0078cfb7, 0x00ae68c1, 0x008e8ae0, 0x00582d96,
263 0x00935411, 0x0045f367, 0x00651146, 0x00b3b630, 0x0024d504, 0x00f27272, 0x00d29053, 0x00043725,
264 0x00a75d80, 0x0071faf6, 0x005118d7, 0x0087bfa1, 0x0010dc95, 0x00c67be3, 0x00e699c2, 0x00303eb4,
265 0x002b6177, 0x00fdc601, 0x00dd2420, 0x000b8356, 0x009ce062, 0x004a4714, 0x006aa535, 0x00bc0243,
266 0x001f68e6, 0x00c9cf90, 0x00e92db1, 0x003f8ac7, 0x00a8e9f3, 0x007e4e85, 0x005eaca4, 0x00880bd2,
267 0x00437255, 0x0095d523, 0x00b53702, 0x00639074, 0x00f4f340, 0x00225436, 0x0002b617, 0x00d41161,
268 0x00777bc4, 0x00a1dcb2, 0x00813e93, 0x005799e5, 0x00c0fad1, 0x00165da7, 0x0036bf86, 0x00e018f0,
269 0x00ad85dd, 0x007b22ab, 0x005bc08a, 0x008d67fc, 0x001a04c8, 0x00cca3be, 0x00ec419f, 0x003ae6e9,
270 0x00998c4c, 0x004f2b3a, 0x006fc91b, 0x00b96e6d, 0x002e0d59, 0x00f8aa2f, 0x00d8480e, 0x000eef78,
271 0x00c596ff, 0x00133189, 0x0033d3a8, 0x00e574de, 0x007217ea, 0x00a4b09c, 0x008452bd, 0x0052f5cb,
272 0x00f19f6e, 0x00273818, 0x0007da39, 0x00d17d4f, 0x00461e7b, 0x0090b90d, 0x00b05b2c, 0x0066fc5a,
273 0x007da399, 0x00ab04ef, 0x008be6ce, 0x005d41b8, 0x00ca228c, 0x001c85fa, 0x003c67db, 0x00eac0ad,
274 0x0049aa08, 0x009f0d7e, 0x00bfef5f, 0x00694829, 0x00fe2b1d, 0x00288c6b, 0x00086e4a, 0x00dec93c,
275 0x0015b0bb, 0x00c317cd, 0x00e3f5ec, 0x0035529a, 0x00a231ae, 0x007496d8, 0x005474f9, 0x0082d38f,
276 0x0021b92a, 0x00f71e5c, 0x00d7fc7d, 0x00015b0b, 0x0096383f, 0x00409f49, 0x00607d68, 0x00b6da1e,
277 0x0056c2ee, 0x00806598, 0x00a087b9, 0x007620cf, 0x00e143fb, 0x0037e48d, 0x001706ac, 0x00c1a1da,
278 0x0062cb7f, 0x00b46c09, 0x00948e28, 0x0042295e, 0x00d54a6a, 0x0003ed1c, 0x00230f3d, 0x00f5a84b,
279 0x003ed1cc, 0x00e876ba, 0x00c8949b, 0x001e33ed, 0x008950d9, 0x005ff7af, 0x007f158e, 0x00a9b2f8,
280 0x000ad85d, 0x00dc7f2b, 0x00fc9d0a, 0x002a3a7c, 0x00bd5948, 0x006bfe3e, 0x004b1c1f, 0x009dbb69,
281 0x0086e4aa, 0x005043dc, 0x0070a1fd, 0x00a6068b, 0x003165bf, 0x00e7c2c9, 0x00c720e8, 0x0011879e,
282 0x00b2ed3b, 0x00644a4d, 0x0044a86c, 0x00920f1a, 0x00056c2e, 0x00d3cb58, 0x00f32979, 0x00258e0f,
283 0x00eef788, 0x003850fe, 0x0018b2df, 0x00ce15a9, 0x0059769d, 0x008fd1eb, 0x00af33ca, 0x007994bc,
284 0x00dafe19, 0x000c596f, 0x002cbb4e, 0x00fa1c38, 0x006d7f0c, 0x00bbd87a, 0x009b3a5b, 0x004d9d2d
287 #define INIT_CRC24 0xffffff
289 static uint32_t crc_calc(uint32_t fcs
, tvbuff_t
*tvb
, unsigned len
)
291 const unsigned char *cp
;
293 cp
= tvb_get_ptr(tvb
, 0, len
);
295 fcs
= (fcs
>> 8) ^ tbl_crc24
[(fcs
^ *cp
++) & 0xff];
302 FCS_NOT_VALID_DUE_TO_CIPHERING
,
307 /* sub-dissector for XID data */
309 llc_gprs_dissect_xid(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_item
*llcgprs_tree
)
311 uint8_t xid_param_len
= 0, byte1
= 0, byte2
= 0, tmp
= 0;
312 unsigned item_len
= 0;
313 unsigned location
= 0;
314 unsigned loop_counter
= 0;
315 proto_tree
*uinfo_tree
= NULL
;
316 proto_tree
*xid_tree
= NULL
;
319 info_len
= tvb_reported_length(tvb
);
321 xid_tree
= proto_tree_add_subtree_format(llcgprs_tree
, tvb
, 0, info_len
,
322 ett_llcgprs_ui
, NULL
, "Information Field: Length = %u", info_len
);
324 while (location
< info_len
)
326 /* parse the XID parameters */
327 byte1
= tvb_get_uint8(tvb
, location
);
331 uint8_t xid_param_len_high
= 0;
332 uint8_t xid_param_len_low
= 0;
333 byte2
= tvb_get_uint8(tvb
, location
+ 1);
335 /* XL bit is set - length is continued in second byte */
336 xid_param_len_high
= byte1
& 0x03;
337 xid_param_len_low
= byte2
& 0xFC;
339 /* bit shift the rest of the length */
340 xid_param_len_low
= xid_param_len_low
>> 2;
341 xid_param_len_low
= xid_param_len_low
& 0x3F;
343 xid_param_len_high
= xid_param_len_high
<< 6;
344 xid_param_len_high
= xid_param_len_high
& 0xC0;
346 /* combine the two */
347 xid_param_len
= xid_param_len_high
| xid_param_len_low
;
348 item_len
= xid_param_len
+ 2;
353 xid_param_len
= byte1
& 0x3;
354 item_len
= xid_param_len
+ 1;
360 if (tmp
== 0xB) /* L3 XID parameters, call the SNDCP-XID dissector */
362 tvbuff_t
*sndcp_xid_tvb
;
363 uint8_t sndcp_xid_offset
;
365 uinfo_tree
= proto_tree_add_subtree(xid_tree
, tvb
, location
, item_len
,
366 ett_llcgprs_ui
, NULL
, "XID parameter Type: L3 parameters");
367 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_xl
, tvb
, location
, 1, byte1
);
368 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_type
, tvb
, location
, 1, byte1
);
369 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_len1
, tvb
, location
, 1, byte1
);
371 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_len2
, tvb
, location
+1, 1, byte2
);
372 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_spare
, tvb
, location
+1, 1, byte2
);
373 sndcp_xid_offset
= 2;
377 sndcp_xid_offset
= 1;
382 sndcp_xid_tvb
= tvb_new_subset_length (tvb
, location
+sndcp_xid_offset
, xid_param_len
);
386 call_dissector(sndcp_xid_handle
, sndcp_xid_tvb
, pinfo
, uinfo_tree
);
390 location
+= item_len
;
394 if (( xid_param_len
> 0 ) && ( xid_param_len
<=4 ))
398 for (i
=1;i
<=xid_param_len
;i
++)
401 value
|= (uint32_t)tvb_get_uint8(tvb
, location
+i
);
403 uinfo_tree
= proto_tree_add_subtree_format(xid_tree
, tvb
, location
, item_len
,
404 ett_llcgprs_ui
, NULL
, "XID Parameter Type: %s - Value: %u",
405 val_to_str_ext(tmp
, &xid_param_type_str_ext
, "Reserved Type:%X"), value
);
409 uinfo_tree
= proto_tree_add_subtree_format(xid_tree
, tvb
, location
, item_len
,
410 ett_llcgprs_ui
, NULL
, "XID Parameter Type: %s",
411 val_to_str_ext(tmp
, &xid_param_type_str_ext
, "Reserved Type:%X"));
413 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_xl
, tvb
, location
,
415 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_type
, tvb
, location
,
417 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_len1
, tvb
, location
,
421 /* length continued into byte 2 */
422 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_len2
, tvb
, location
,
424 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_spare
, tvb
, location
,
427 /* be sure to account for the second byte of length */
432 for (loop_counter
= 0; loop_counter
< xid_param_len
; loop_counter
++)
434 /* grab the information in the XID param */
435 byte2
= tvb_get_uint8(tvb
, location
);
436 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_byte
, tvb
, location
,
444 /* shortest dummy UI command as per TS 44.064 Section 6.4.2.2 */
445 static const uint8_t dummy_ui_cmd
[] = { 0x43, 0xc0, 0x01, 0x2b, 0x2b, 0x2b };
448 dissect_llcgprs(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
451 uint8_t addr_fld
=0, sapi
=0, ctrl_fld_fb
=0, frame_format
, tmp
=0;
452 uint16_t epm
= 0, nu
=0, ctrl_fld_ui_s
=0;
453 proto_item
*ti
, *addres_field_item
;
454 proto_tree
*llcgprs_tree
=NULL
, *ad_f_tree
=NULL
, *ctrl_f_tree
=NULL
, *ui_tree
=NULL
;
456 unsigned length
, captured_length
;
457 unsigned crc_length
= 0, llc_data_length
;
460 fcs_status_t fcs_status
;
466 proto_tree
*uinfo_tree
= NULL
;
467 bool ciphered_ui_frame
= false;
469 if (!tvb_memeql(tvb
, 0, dummy_ui_cmd
, sizeof(dummy_ui_cmd
))) {
470 proto_tree_add_boolean(tree
, hf_llcgprs_dummy_ui
, tvb
, offset
,
471 tvb_captured_length(tvb
), true);
472 return tvb_captured_length(tvb
);
475 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "GPRS-LLC");
477 /* llc_data_length includes the header and the payload */
478 llc_data_length
= length
= tvb_reported_length(tvb
);
479 if (length
>= CRC_LENGTH
) {
481 * The packet is big enough to have a CRC.
483 llc_data_length
-= CRC_LENGTH
;
488 * The packet isn't big enough to have a CRC; claim
489 * the data length is 0.
493 captured_length
= tvb_captured_length(tvb
);
498 addr_fld
= tvb_get_uint8(tvb
, offset
);
503 col_set_str(pinfo
->cinfo
, COL_INFO
, "Invalid packet - Protocol Discriminator bit is set to 1");
507 sapi
= addr_fld
& 0xF;
509 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "SAPI: %s", val_to_str_ext(sapi
, &sapi_abrv_ext
, "Unknown (%u)"));
511 /* In the interest of speed, if "tree" is NULL, don't do any work not
512 necessary to generate protocol tree items. */
515 ti
= proto_tree_add_protocol_format(tree
, proto_llcgprs
, tvb
, 0, -1,
516 "MS-SGSN LLC (Mobile Station - Serving GPRS Support Node Logical Link Control) SAPI: %s",
517 val_to_str_ext(sapi
, &sapi_t_ext
, "Unknown (%u)"));
519 llcgprs_tree
= proto_item_add_subtree(ti
, ett_llcgprs
);
521 /* add an item to the subtree, see section 1.6 for more information */
522 addres_field_item
= proto_tree_add_uint_format(llcgprs_tree
, hf_llcgprs_sapi
,
523 tvb
, 0, 1, sapi
, "Address field SAPI: %s", val_to_str_ext(sapi
, &sapi_abrv_ext
, "Unknown (%u)"));
525 ad_f_tree
= proto_item_add_subtree(addres_field_item
, ett_llcgprs_adf
);
526 proto_tree_add_boolean(ad_f_tree
, hf_llcgprs_pd
, tvb
, 0, 1, addr_fld
);
527 proto_tree_add_boolean(ad_f_tree
, hf_llcgprs_cr
, tvb
, 0, 1, addr_fld
);
528 proto_tree_add_uint(ad_f_tree
, hf_llcgprs_sapib
, tvb
, 0, 1, addr_fld
);
534 ctrl_fld_fb
= tvb_get_uint8(tvb
, offset
);
535 if (ctrl_fld_fb
< 0xC0)
537 frame_format
= (ctrl_fld_fb
< 0x80)? I_FORMAT
: S_FORMAT
;
541 frame_format
= (ctrl_fld_fb
< 0xe0 )? UI_FORMAT
: U_FORMAT
;
544 switch (frame_format
)
547 col_append_str(pinfo
->cinfo
, COL_INFO
, ", I, ");
549 ns
= tvb_get_ntohs(tvb
, offset
);
550 ns
= (ns
>> 4)& 0x01FF;
551 nr
= ctrl_fld_ui_s
= tvb_get_ntohs(tvb
, offset
+ 1);
552 nr
= (nr
>> 2) & 0x01FF;
554 epm
= ctrl_fld_ui_s
& 0x3;
556 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str(epm
, cr_formats_ipluss
, "Unknown (%d)"));
557 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", N(S) = %u", ns
);
558 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", N(R) = %u", nr
);
564 ctrl_f_tree
= proto_tree_add_subtree_format(llcgprs_tree
, tvb
, offset
,
565 3, ett_llcgprs_sframe
, NULL
, "Information format: %s: N(S) = %u, N(R) = %u",
566 val_to_str(epm
, cr_formats_ipluss
, "Unknown (%d)"), ns
, nr
);
568 /* retrieve the second octet */
569 tmpx
= tvb_get_ntohs(tvb
, offset
) << 16;
570 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_ifmt
, tvb
, offset
, 3, tmpx
);
571 proto_tree_add_boolean(ctrl_f_tree
, hf_llcgprs_Ai
, tvb
, offset
, 3, tmpx
);
572 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_izerobit
, tvb
, offset
, 3, tmpx
);
575 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_isack_ns
, tvb
, offset
, 3, tmpx
);
578 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_isack_nr
, tvb
, offset
, 3, tmpx
);
579 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_isack_sfb
, tvb
, offset
, 3, ctrl_fld_ui_s
);
582 /* advance to either R Bitmap or Payload */
585 /* check to see if epm is SACK - meaning this is an ISACK frame */
590 k
= kmask
= tvb_get_uint8(tvb
, offset
);
593 /* advance past the k field */
596 /* the real value of k is actually k + 1 */
597 /* account for the off by one representation */
600 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", k = %u", k
);
604 uint8_t loop_count
= 0;
606 unsigned location
= offset
;
608 ctrl_f_tree
= proto_tree_add_subtree_format(llcgprs_tree
, tvb
, (offset
-1),
609 (k
+1), ett_llcgprs_sframe
, NULL
, "SACK FRAME: k = %u", k
);
611 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_kmask
, tvb
, offset
-1, 1, kmask
);
612 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_k
, tvb
, offset
-1, 1, k
);
614 /* display the R Bitmap */
615 for (loop_count
= 0; loop_count
< k
; loop_count
++)
617 r_byte
= tvb_get_uint8(tvb
, location
);
618 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_rbyte
, tvb
, location
, 1, r_byte
);
623 /* step past the R Bitmap */
627 crc_length
= llc_data_length
;
631 col_append_str(pinfo
->cinfo
, COL_INFO
, ", S, ");
633 nu
= ctrl_fld_ui_s
= tvb_get_ntohs(tvb
, offset
);
634 epm
= ctrl_fld_ui_s
& 0x3;
635 nu
= (nu
>>2)&0x01FF;
637 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str(epm
, cr_formats_ipluss
, "Unknown (%d)"));
638 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", N(R) = %u", nu
);
642 static int * const s_formats
[] = {
651 proto_tree_add_bitmask_text(llcgprs_tree
, tvb
, offset
, 2,
652 "Supervisory format: ", NULL
, ett_llcgprs_sframe
, s_formats
, ENC_BIG_ENDIAN
, 0);
656 if ((ctrl_fld_ui_s
& 0x03) == 0x03)
657 /* It is a SACK frame */
659 /* TODO: length is fudged - it is not correct */
660 uint32_t sack_length
= llc_data_length
- offset
;
666 uint16_t location
= offset
;
667 ctrl_f_tree
= proto_tree_add_subtree_format(llcgprs_tree
, tvb
, offset
, sack_length
,
668 ett_llcgprs_sframe
, NULL
, "SACK FRAME: length = %u", sack_length
);
669 /* display the R Bitmap */
670 for (loop_count
= 0; loop_count
< sack_length
; loop_count
++)
672 r_byte
= tvb_get_uint8(tvb
, location
);
673 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_rbyte
, tvb
,
674 location
, 1, r_byte
);
678 /* step past the r bitmap */
679 offset
+= sack_length
;
683 crc_length
= llc_data_length
;
687 col_append_str(pinfo
->cinfo
, COL_INFO
, ", UI, ");
689 nu
= ctrl_fld_ui_s
= tvb_get_ntohs(tvb
, offset
);
690 epm
= ctrl_fld_ui_s
& 0x3;
691 nu
= (nu
>>2)&0x01FF;
693 /* If the frame is ciphered, the calculated FCS will not be valid (unless it has been unciphered) */
696 ciphered_ui_frame
= true;
698 if ((epm
& UI_MASK_PM
)== 0)
700 /* FCS covers at maximum the LLC header and N202 bytes */
701 crc_length
= MIN(UI_HDR_LENGTH
+ N202
, llc_data_length
);
705 crc_length
= llc_data_length
;
708 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str(epm
, pme
, "Unknown (%d)"));
709 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", N(U) = %u", nu
);
713 static int * const i_formats
[] = {
722 proto_tree_add_bitmask_text(llcgprs_tree
, tvb
, offset
, 2,
723 "Unconfirmed Information format - UI: ", NULL
, ett_llcgprs_ctrlf
, i_formats
, ENC_BIG_ENDIAN
, 0);
729 col_append_str(pinfo
->cinfo
, COL_INFO
, ", U, ");
731 tmp
= ctrl_fld_fb
& 0xf;
733 col_append_str(pinfo
->cinfo
, COL_INFO
,
734 val_to_str(tmp
, cr_formats_unnumb
, "Unknown/invalid code:%X"));
736 ui_tree
= proto_tree_add_subtree_format(llcgprs_tree
, tvb
, offset
, (llc_data_length
-1),
737 ett_llcgprs_ui
, NULL
, "Unnumbered frame: %s",
738 val_to_str(tmp
, cr_formats_unnumb
, "Unknown/invalid code:%X"));
740 proto_tree_add_uint(ui_tree
, hf_llcgprs_Un
, tvb
, offset
, 1, ctrl_fld_fb
);
741 proto_tree_add_boolean(ui_tree
, hf_llcgprs_PF
, tvb
, offset
, 1, ctrl_fld_fb
);
742 proto_tree_add_uint(ui_tree
, hf_llcgprs_ucom
, tvb
, offset
, 1, ctrl_fld_fb
);
744 crc_length
= llc_data_length
;
751 if (captured_length
>= length
&& length
>= CRC_LENGTH
)
754 * We have all the packet data, including the full FCS,
755 * so we can compute the FCS.
757 fcs_calc
= crc_calc ( INIT_CRC24
, tvb
, crc_length
);
758 fcs_calc
= ~fcs_calc
;
759 fcs_calc
&= 0xffffff;
761 fcs
= tvb_get_letoh24(tvb
, llc_data_length
);
762 if ( fcs_calc
== fcs
)
764 fcs_status
= FCS_VALID
;
765 proto_tree_add_uint_format_value(llcgprs_tree
, hf_llcgprs_fcs
, tvb
, llc_data_length
, CRC_LENGTH
,
766 fcs_calc
&0xffffff, "0x%06x (correct)", fcs_calc
&0xffffff);
770 if (ciphered_ui_frame
)
772 fcs_status
= FCS_NOT_VALID_DUE_TO_CIPHERING
;
773 proto_tree_add_uint_format_value(llcgprs_tree
, hf_llcgprs_fcs
, tvb
, llc_data_length
, CRC_LENGTH
,
774 fcs
, "0x%06x (incorrect, maybe due to ciphering, calculated 0x%06x)", fcs
, fcs_calc
);
778 fcs_status
= FCS_NOT_VALID
;
779 proto_tree_add_uint_format_value(llcgprs_tree
, hf_llcgprs_fcs
, tvb
, llc_data_length
, CRC_LENGTH
,
780 fcs
, "0x%06x (incorrect, should be 0x%06x)", fcs
, fcs_calc
);
786 /* We don't have enough data to compute the FCS. */
787 fcs_status
= FCS_NOT_COMPUTED
;
788 proto_tree_add_uint_format_value(llcgprs_tree
, hf_llcgprs_fcs
, tvb
, 0, 0, 0,
789 "FCS: Not enough data to compute the FCS");
795 switch (frame_format
)
798 if ((sapi
== SAPI_TOM2
) || (sapi
== SAPI_TOM8
))
800 /* if SAPI is TOM do other parsing */
803 uint8_t tom_byte
= 0;
804 uint8_t remaining_length
= 0;
806 int loop_counter
= 0;
808 tom_byte
= tvb_get_uint8(tvb
, offset
);
809 remaining_length
= (tom_byte
>> 4) & 0x0F;
810 tom_pd
= tom_byte
& 0x0F;
812 ctrl_f_tree
= proto_tree_add_subtree_format(llcgprs_tree
, tvb
, offset
,
813 (llc_data_length
-offset
), ett_llcgprs_sframe
, NULL
,
814 "TOM Envelope - Protocol: %s",
815 val_to_str(tom_pd
, tompd_formats
, "Unknown (%d)"));
817 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_rl
, tvb
, offset
, 1, tom_byte
);
818 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_pd
, tvb
, offset
, 1, tom_byte
);
820 /* step past the TOM header first byte */
823 /* TOM remaining length field value 0x0F is reserved for extension */
824 if (remaining_length
!= 0x0F)
826 /* parse the rest of the TOM header */
827 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
829 tom_byte
= tvb_get_uint8(tvb
, offset
);
831 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_header
, tvb
,
832 offset
, 1, tom_byte
);
834 /* step to the next byte */
838 remaining_length
= llc_data_length
- offset
;
840 /* parse the TOM message capsule */
841 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
843 tom_byte
= tvb_get_uint8(tvb
, offset
);
845 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_data
, tvb
,
846 offset
, 1, tom_byte
);
848 /* step to the next byte */
856 /* otherwise - call a subdissector */
857 next_tvb
= tvb_new_subset_length(tvb
, offset
, (llc_data_length
-offset
));
858 if (!dissector_try_uint(llcgprs_subdissector_table
, sapi
, next_tvb
, pinfo
, tree
))
859 /* if no subdissector is found, call the data dissector */
861 call_data_dissector(next_tvb
, pinfo
, tree
);
867 /* should parse the rest of the supervisory message based on type */
868 /* if SAPI is TOM do other parsing */
869 if ((sapi
== SAPI_TOM2
) || (sapi
== SAPI_TOM8
))
873 uint8_t tom_byte
= 0;
874 uint8_t remaining_length
= 0;
876 int loop_counter
= 0;
878 tom_byte
= tvb_get_uint8(tvb
, offset
);
879 remaining_length
= (tom_byte
>> 4) & 0x0F;
880 tom_pd
= tom_byte
& 0x0F;
882 ctrl_f_tree
= proto_tree_add_subtree_format(llcgprs_tree
, tvb
, offset
,
883 (llc_data_length
-offset
), ett_llcgprs_sframe
, NULL
,
884 "TOM Envelope - Protocol: %s",
885 val_to_str(tom_pd
, tompd_formats
, "Unknown (%d)"));
887 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_rl
, tvb
, offset
, 1, tom_byte
);
888 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_pd
, tvb
, offset
, 1, tom_byte
);
890 /* step past the TOM header first byte */
893 /* TOM remaining length field value 0x0F is reserved for extension */
894 if (remaining_length
!= 0x0F)
896 /* parse the rest of the TOM header */
897 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
899 tom_byte
= tvb_get_uint8(tvb
, offset
);
900 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_header
, tvb
,
901 offset
, 1, tom_byte
);
903 /* step to the next byte */
907 /* Amount of frame left from offset to crc */
908 remaining_length
= llc_data_length
- offset
;
910 /* parse the TOM message capsule */
911 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
913 tom_byte
= tvb_get_uint8(tvb
, offset
);
914 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_data
, tvb
,
915 offset
, 1, tom_byte
);
917 /* step to the next byte */
923 else if (llc_data_length
>offset
)
925 /* otherwise - call a subdissector */
926 next_tvb
= tvb_new_subset_length(tvb
, offset
, (llc_data_length
-offset
));
927 if (!dissector_try_uint(llcgprs_subdissector_table
, sapi
, next_tvb
, pinfo
, tree
))
929 call_data_dissector(next_tvb
, pinfo
, tree
);
935 next_tvb
= tvb_new_subset_length(tvb
, offset
, (llc_data_length
-offset
));
937 if ((ignore_cipher_bit
&& (fcs_status
== FCS_VALID
)) || !(epm
& 0x2))
939 /* Either we're ignoring the cipher bit
940 * (because the bit is set but the
941 * data is unciphered), and the data has
942 * a valid FCS, or the cipher
943 * bit isn't set (indicating that the
944 * data is unciphered). Try dissecting
945 * it with a subdissector. */
947 /* if SAPI is TOM do other parsing */
948 if ((sapi
== SAPI_TOM2
) || (sapi
== SAPI_TOM8
))
952 uint8_t tom_byte
= 0;
953 uint8_t remaining_length
= 0;
955 int loop_counter
= 0;
957 tom_byte
= tvb_get_uint8(tvb
, offset
);
958 remaining_length
= (tom_byte
>> 4) & 0x0F;
959 tom_pd
= tom_byte
& 0x0F;
961 ctrl_f_tree
= proto_tree_add_subtree_format(llcgprs_tree
, tvb
, offset
,
962 (llc_data_length
-offset
), ett_llcgprs_sframe
, NULL
,
963 "TOM Envelope - Protocol: %s",
964 val_to_str(tom_pd
, tompd_formats
, "Unknown (%d)"));
966 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_rl
, tvb
, offset
, 1, tom_byte
);
967 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_pd
, tvb
, offset
, 1, tom_byte
);
969 /* step past the TOM header first byte */
972 /* TOM remaining length field value 0x0F is reserved for extension */
973 if (remaining_length
!= 0x0F)
975 /* parse the rest of the TOM header */
976 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
978 tom_byte
= tvb_get_uint8(tvb
, offset
);
980 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_header
, tvb
,
981 offset
, 1, tom_byte
);
983 /* step to the next byte */
987 /* Amount of frame left from offset to crc */
988 remaining_length
= llc_data_length
- offset
;
990 /* parse the TOM message capsule */
991 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
993 tom_byte
= tvb_get_uint8(tvb
, offset
);
995 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_data
, tvb
,
996 offset
, 1, tom_byte
);
998 /* step to the next byte */
1004 else if (llc_data_length
>offset
)
1006 /* otherwise - call a subdissector */
1007 if (!dissector_try_uint(llcgprs_subdissector_table
, sapi
, next_tvb
, pinfo
, tree
))
1009 call_data_dissector(next_tvb
, pinfo
, tree
);
1015 /* ciphered information - just parse it as data */
1016 call_data_dissector(next_tvb
, pinfo
, tree
);
1021 m_bits
= ctrl_fld_fb
& 0x0F;
1023 info_len
= llc_data_length
- offset
;
1030 /* These frames SHOULD NOT have an info field */
1031 proto_tree_add_expert(llcgprs_tree
, pinfo
, &ei_llcgprs_no_info_field
, tvb
, offset
, (llc_data_length
-2));
1034 /* This frame MAY or MAY NOT have an info field */
1035 /* Info field, if it exists, consists of XID parameters */
1039 xid_tvb
= tvb_new_subset_length (tvb
, offset
, info_len
);
1041 llc_gprs_dissect_xid(xid_tvb
, pinfo
, llcgprs_tree
);
1046 /* These frames do have info fields consisting of XID parameters */
1047 /* Info field consists of XID parameters */
1051 xid_tvb
= tvb_new_subset_length (tvb
, offset
, info_len
);
1053 llc_gprs_dissect_xid(xid_tvb
, pinfo
, llcgprs_tree
);
1057 /* This frame has a special format info field */
1060 uint32_t fld_vars
= 0;
1061 uint16_t cf_byte
= 0;
1062 int loop_counter
= 0;
1065 ui_tree
= proto_tree_add_subtree_format(llcgprs_tree
, tvb
, offset
, (llc_data_length
-2),
1066 ett_llcgprs_ui
, NULL
, "Information Field: Length = %u", info_len
);
1068 uinfo_tree
= proto_tree_add_subtree(ui_tree
, tvb
, offset
, 6,
1069 ett_llcgprs_ui
, NULL
, "Rejected Frame Control Field");
1072 for (loop_counter
= 0; loop_counter
< 3; loop_counter
++)
1074 /* display the rejected frame control field */
1075 cf_byte
= tvb_get_ntohs(tvb
, location
);
1076 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_cf
, tvb
, location
,
1082 uinfo_tree
= proto_tree_add_subtree(ui_tree
, tvb
, location
, 4,
1083 ett_llcgprs_ui
, NULL
, "Information Field Data");
1085 fld_vars
= tvb_get_ntohl(tvb
, location
);
1086 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_spare
, tvb
, location
,
1088 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_vs
, tvb
, location
,
1090 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_vr
, tvb
, (location
+ 1),
1092 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_cr
, tvb
, (location
+ 2),
1094 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_w4
, tvb
, (location
+ 3),
1096 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_w3
, tvb
, (location
+ 3),
1098 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_w2
, tvb
, (location
+ 3),
1100 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_w1
, tvb
, (location
+ 3),
1110 return tvb_captured_length(tvb
);
1114 /* Register the protocol with Wireshark */
1117 proto_register_llcgprs(void)
1119 /* Setup list of header fields See Section 1.6.1 for details */
1120 static hf_register_info hf
[] = {
1122 { "SAPI", "llcgprs.sapi", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
1123 &sapi_abrv_ext
, 0x0, "Service Access Point Identifier", HFILL
}},
1126 { "Protocol Discriminator_bit", "llcgprs.pd", FT_BOOLEAN
, 8,
1127 TFS(&pd_bit
), 0x80, "Protocol Discriminator bit (should be 0)", HFILL
}},
1130 { "FCS", "llcgprs.fcs", FT_UINT24
, BASE_HEX
,
1131 NULL
, 0, NULL
, HFILL
}},
1134 { "Supervisory function bits", "llcgprs.s1s2", FT_UINT16
, BASE_HEX
,
1135 VALS(cr_formats_ipluss
), 0x3, NULL
, HFILL
}},
1138 { "Command/Response bit", "llcgprs.cr", FT_BOOLEAN
, 8,
1139 TFS(&cr_bit
), 0x40, NULL
, HFILL
}},
1141 { &hf_llcgprs_sapib
,
1142 { "SAPI", "llcgprs.sapib", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
1143 &sapi_t_ext
, 0xf, "Service Access Point Identifier", HFILL
}},
1145 { &hf_llcgprs_U_fmt
,
1146 { "UI format", "llcgprs.ui", FT_UINT16
, BASE_HEX
,
1147 NULL
, UI_MASK_FMT
, "UI frame format", HFILL
}},
1150 { "U format", "llcgprs.u", FT_UINT8
, BASE_HEX
,
1151 NULL
, 0xe0, "U frame format", HFILL
}},
1153 { &hf_llcgprs_sp_bits
,
1154 { "Spare bits", "llcgprs.ui_sp_bit", FT_UINT16
, BASE_HEX
,
1155 NULL
, UI_MASK_SPB
, NULL
, HFILL
}},
1158 { "N(U)", "llcgprs.nu", FT_UINT16
, BASE_DEC
,
1159 NULL
, UI_MASK_NU
, "Transmitted unconfirmed sequence number", HFILL
}},
1161 { &hf_llcgprs_E_bit
,
1162 { "E bit", "llcgprs.e", FT_BOOLEAN
, 16,
1163 TFS(&e_bit
), UI_MASK_E
, "Encryption mode bit", HFILL
}},
1165 { &hf_llcgprs_PM_bit
,
1166 { "PM bit", "llcgprs.pm", FT_BOOLEAN
, 16,
1167 TFS(&pm_bit
), UI_MASK_PM
, "Protected mode bit", HFILL
}},
1170 { "Ackn request bit", "llcgprs.as", FT_BOOLEAN
, 16,
1171 TFS(&a_bit
), 0x2000, "Acknowledgement request bit A", HFILL
}},
1174 { "P/F bit", "llcgprs.pf", FT_BOOLEAN
, 8,
1175 NULL
, 0x10, "Poll/Final bit", HFILL
}},
1178 { "Command/Response", "llcgprs.ucom", FT_UINT8
, BASE_HEX
,
1179 VALS(cr_formats_unnumb
), 0xf, "Commands and Responses", HFILL
}},
1182 { "Receive sequence number", "llcgprs.nr", FT_UINT16
, BASE_DEC
,
1183 NULL
, UI_MASK_NU
, "Receive sequence number N(R)", HFILL
}},
1185 { &hf_llcgprs_S_fmt
,
1186 { "S format", "llcgprs.s", FT_UINT16
, BASE_HEX
,
1187 NULL
, 0xc000, "Supervisory format S", HFILL
}},
1189 { &hf_llcgprs_kmask
,
1190 { "ignored", "llcgprs.kmask", FT_UINT8
, BASE_DEC
,
1191 NULL
, 0xE0, NULL
, HFILL
}},
1194 { "k", "llcgprs.k", FT_UINT8
, BASE_DEC
,
1195 NULL
, 0x1F, "k counter", HFILL
}},
1197 { &hf_llcgprs_isack_ns
,
1198 { "N(S)", "llcgprs.sackns", FT_UINT24
, BASE_DEC
,
1199 NULL
, 0x1FF000, NULL
, HFILL
}},
1201 { &hf_llcgprs_isack_nr
,
1202 { "N(R)", "llcgprs.sacknr", FT_UINT24
, BASE_DEC
,
1203 NULL
, 0x0007FC, NULL
, HFILL
}},
1205 { &hf_llcgprs_isack_sfb
,
1206 { "Supervisory function bits", "llcgprs.sacksfb", FT_UINT24
, BASE_HEX
,
1207 VALS(cr_formats_ipluss
), 0x000003, NULL
, HFILL
}},
1210 { "I Format", "llcgprs.ifmt", FT_UINT24
, BASE_HEX
,
1211 NULL
, 0x800000, "I Fmt Bit", HFILL
}},
1214 { "Ackn request bit", "llcgprs.ai", FT_BOOLEAN
, 24,
1215 TFS(&a_bit
), 0x400000, "Acknowledgement request bit A", HFILL
}},
1217 { &hf_llcgprs_izerobit
,
1218 { "Spare", "llcgprs.iignore", FT_UINT24
, BASE_DEC
,
1219 NULL
, 0x200000, "Ignore Bit", HFILL
}},
1221 { &hf_llcgprs_sspare
,
1222 { "Spare", "llcgprs.sspare", FT_UINT16
, BASE_DEC
,
1223 NULL
, 0x1800, "Ignore Bit", HFILL
}},
1225 { &hf_llcgprs_rbyte
,
1226 { "R Bitmap Bits", "llcgprs.sackrbits", FT_UINT8
, BASE_HEX
,
1227 NULL
, 0xFF, NULL
, HFILL
}},
1229 /* XID Parameter Parsing Info */
1230 { &hf_llcgprs_xid_xl
,
1231 { "XL Bit", "llcgprs.xidxl", FT_UINT8
, BASE_HEX
,
1232 NULL
, 0x80, NULL
, HFILL
}},
1234 { &hf_llcgprs_xid_type
,
1235 { "Type", "llcgprs.xidtype", FT_UINT8
, BASE_DEC
,
1236 NULL
, 0x7C, NULL
, HFILL
}},
1238 { &hf_llcgprs_xid_len1
,
1239 { "Length", "llcgprs.xidlen1", FT_UINT8
, BASE_DEC
,
1240 NULL
, 0x03, NULL
, HFILL
}},
1242 { &hf_llcgprs_xid_len2
,
1243 { "Length continued", "llcgprs.xidlen2", FT_UINT8
, BASE_DEC
,
1244 NULL
, 0xFC, NULL
, HFILL
}},
1246 { &hf_llcgprs_xid_spare
,
1247 { "Spare", "llcgprs.xidspare", FT_UINT8
, BASE_HEX
,
1248 NULL
, 0x03, "Ignore", HFILL
}},
1250 { &hf_llcgprs_xid_byte
,
1251 { "Parameter Byte", "llcgprs.xidbyte", FT_UINT8
, BASE_HEX
,
1252 NULL
, 0xFF, "Data", HFILL
}},
1254 /* FRMR Parsing Information */
1255 { &hf_llcgprs_frmr_cf
,
1256 { "Control Field Octet", "llcgprs.frmrrfcf", FT_UINT16
, BASE_DEC
,
1257 NULL
, 0xFFFF, "Rejected Frame CF", HFILL
}},
1259 { &hf_llcgprs_frmr_spare
,
1260 { "X", "llcgprs.frmrspare", FT_UINT32
, BASE_HEX
,
1261 NULL
, 0xF00400F0, "Filler", HFILL
}},
1263 { &hf_llcgprs_frmr_vs
,
1264 { "V(S)", "llcgprs.frmrvs", FT_UINT32
, BASE_DEC
,
1265 NULL
, 0x0FF80000, "Current send state variable", HFILL
}},
1267 { &hf_llcgprs_frmr_vr
,
1268 { "V(R)", "llcgprs.frmrvr", FT_UINT32
, BASE_DEC
,
1269 NULL
, 0x0003FE00, "Current receive state variable", HFILL
}},
1271 { &hf_llcgprs_frmr_cr
,
1272 { "C/R", "llcgprs.frmrcr", FT_UINT32
, BASE_DEC
,
1273 NULL
, 0x00000100, "Rejected command response", HFILL
}},
1275 { &hf_llcgprs_frmr_w4
,
1276 { "W4", "llcgprs.frmrw4", FT_UINT32
, BASE_DEC
,
1277 NULL
, 0x00000008, "LLE was in ABM when rejecting", HFILL
}},
1279 { &hf_llcgprs_frmr_w3
,
1280 { "W3", "llcgprs.frmrw3", FT_UINT32
, BASE_DEC
,
1281 NULL
, 0x00000004, "Undefined control field", HFILL
}},
1283 { &hf_llcgprs_frmr_w2
,
1284 { "W2", "llcgprs.frmrw2", FT_UINT32
, BASE_DEC
,
1285 NULL
, 0x00000002, "Info exceeded N201", HFILL
}},
1287 { &hf_llcgprs_frmr_w1
,
1288 { "W1", "llcgprs.frmrw1", FT_UINT32
, BASE_DEC
,
1289 NULL
, 0x00000001, "Invalid - info not permitted", HFILL
}},
1291 { &hf_llcgprs_tom_rl
,
1292 { "Remaining Length of TOM Protocol Header", "llcgprs.romrl", FT_UINT8
, BASE_DEC
,
1293 NULL
, 0xF0, "RL", HFILL
}},
1295 { &hf_llcgprs_tom_pd
,
1296 { "TOM Protocol Discriminator", "llcgprs.tompd", FT_UINT8
, BASE_HEX
,
1297 NULL
, 0x0F, "TPD", HFILL
}},
1299 { &hf_llcgprs_tom_header
,
1300 { "TOM Header Byte", "llcgprs.tomhead", FT_UINT8
, BASE_HEX
,
1301 NULL
, 0xFF, "thb", HFILL
}},
1303 { &hf_llcgprs_tom_data
,
1304 { "TOM Message Capsule Byte", "llcgprs.tomdata", FT_UINT8
, BASE_HEX
,
1305 NULL
, 0xFF, "tdb", HFILL
}},
1307 { &hf_llcgprs_dummy_ui
,
1308 { "Dummy UI Command", "llcgprs.dummy_ui", FT_BOOLEAN
, BASE_NONE
,
1309 NULL
, 0x00, NULL
, HFILL
}},
1312 /* Setup protocol subtree array */
1313 static int *ett
[] = {
1318 &ett_llcgprs_sframe
,
1321 static ei_register_info ei
[] = {
1322 { &ei_llcgprs_no_info_field
, { "llcgprs.no_info_field", PI_PROTOCOL
, PI_WARN
, "No Information Field", EXPFILL
}},
1325 module_t
*llcgprs_module
;
1326 expert_module_t
* expert_llcgprs
;
1328 /* Register the protocol name and description */
1329 proto_llcgprs
= proto_register_protocol("Logical Link Control GPRS",
1330 "GPRS-LLC", "llcgprs");
1331 llcgprs_subdissector_table
= register_dissector_table("llcgprs.sapi", "GPRS LLC SAPI", proto_llcgprs
, FT_UINT8
, BASE_HEX
);
1333 /* Required function calls to register the header fields and subtrees used */
1334 proto_register_field_array(proto_llcgprs
, hf
, array_length(hf
));
1335 proto_register_subtree_array(ett
, array_length(ett
));
1336 expert_llcgprs
= expert_register_protocol(proto_llcgprs
);
1337 expert_register_field_array(expert_llcgprs
, ei
, array_length(ei
));
1338 gprs_llc_handle
= register_dissector("llcgprs", dissect_llcgprs
, proto_llcgprs
);
1340 llcgprs_module
= prefs_register_protocol ( proto_llcgprs
, NULL
);
1341 prefs_register_bool_preference ( llcgprs_module
, "autodetect_cipher_bit",
1342 "Autodetect cipher bit",
1343 "Whether to autodetect the cipher bit (because it might be set on unciphered data)",
1344 &ignore_cipher_bit
);
1349 proto_reg_handoff_llcgprs(void)
1351 /* make sure that the top level can call this dissector */
1352 dissector_add_uint("wtap_encap", WTAP_ENCAP_GPRS_LLC
, gprs_llc_handle
);
1354 sndcp_xid_handle
= find_dissector_add_dependency("sndcpxid", proto_llcgprs
);
1358 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1363 * indent-tabs-mode: t
1366 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1367 * :indentSize=8:tabSize=8:noTabs=false: