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>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/prefs.h>
39 #define UI_MASK_FMT 0xe000
40 #define UI_MASK_SPB 0x1800
41 #define UI_MASK_NU 0x07fc
42 #define UI_MASK_E 0x0002
43 #define UI_MASK_PM 0x0001
47 #define UI_HDR_LENGTH 3U
49 /* Initialize the protocol and registered fields */
50 static int proto_llcgprs
= -1;
51 static int hf_llcgprs_pd
= -1;
52 static int hf_llcgprs_cr
= -1;
53 static int hf_llcgprs_sapi
= -1;
54 static int hf_llcgprs_sapib
= -1;
55 static int hf_llcgprs_U_fmt
= -1; /* 3 upper bits in controlfield (UI format) */
56 static int hf_llcgprs_sp_bits
= -1; /* Spare bits in control field */
57 static int hf_llcgprs_NU
= -1; /* Transmited unconfirmed sequence number */
58 static int hf_llcgprs_E_bit
= -1; /* Encryption mode bit */
59 static int hf_llcgprs_PM_bit
= -1;
60 static int hf_llcgprs_Un
= -1;
61 static int hf_llcgprs_As
= -1;
62 static int hf_llcgprs_ucom
= -1;
63 static int hf_llcgprs_PF
= -1;
64 static int hf_llcgprs_S_fmt
= -1;
65 static int hf_llcgprs_NR
= -1;
66 static int hf_llcgprs_sjsd
= -1;
67 /* MLT CHANGES - Additional display masks */
68 static int hf_llcgprs_k
= -1;
69 static int hf_llcgprs_isack_ns
= -1;
70 static int hf_llcgprs_isack_nr
= -1;
71 static int hf_llcgprs_isack_sfb
= -1;
72 static int hf_llcgprs_rbyte
= -1;
73 static int hf_llcgprs_kmask
= -1;
74 static int hf_llcgprs_ifmt
= -1;
75 static int hf_llcgprs_ia
= -1;
76 static int hf_llcgprs_izerobit
= -1;
77 static int hf_llcgprs_sspare
= -1;
78 static int hf_llcgprs_xid_xl
= -1;
79 static int hf_llcgprs_xid_type
= -1;
80 static int hf_llcgprs_xid_len1
= -1;
81 static int hf_llcgprs_xid_len2
= -1;
82 static int hf_llcgprs_xid_spare
= -1;
83 static int hf_llcgprs_xid_byte
= -1;
84 static int hf_llcgprs_frmr_cf
= -1;
85 static int hf_llcgprs_frmr_spare
= -1;
86 static int hf_llcgprs_frmr_vs
= -1;
87 static int hf_llcgprs_frmr_vr
= -1;
88 static int hf_llcgprs_frmr_cr
= -1;
89 static int hf_llcgprs_frmr_w4
= -1;
90 static int hf_llcgprs_frmr_w3
= -1;
91 static int hf_llcgprs_frmr_w2
= -1;
92 static int hf_llcgprs_frmr_w1
= -1;
93 static int hf_llcgprs_tom_rl
= -1;
94 static int hf_llcgprs_tom_pd
= -1;
95 static int hf_llcgprs_tom_header
= -1;
96 static int hf_llcgprs_tom_data
= -1;
98 /* Unnumbered Commands and Responses (U Frames) */
107 /* SAPI value constants */
108 #define SAPI_LLGMM 0x01
109 #define SAPI_TOM2 0x02
110 #define SAPI_LL3 0x03
111 #define SAPI_LL5 0x05
112 #define SAPI_LLSMS 0x07
113 #define SAPI_TOM8 0x08
114 #define SAPI_LL9 0x09
115 #define SAPI_LL11 0x0B
117 /* END MLT CHANGES */
119 /* Initialize the subtree pointers */
120 static gint ett_llcgprs
= -1;
121 static gint ett_llcgprs_adf
= -1;
122 static gint ett_llcgprs_ctrlf
= -1;
123 static gint ett_ui
= -1;
124 static gint ett_llcgprs_sframe
= -1;
126 static dissector_handle_t data_handle
;
127 static dissector_handle_t sndcp_xid_handle
;
129 static gboolean ignore_cipher_bit
= FALSE
;
131 static dissector_table_t llcgprs_subdissector_table
;
133 static const value_string sapi_t
[] = {
135 { 1, "GPRS Mobility Management" },
136 { 2, "Tunneling of messages 2" },
139 { 5, "User data 5" },
142 { 8, "Tunneling of messages 8" },
143 { 9, "User data 9" },
145 { 11, "User data 11" },
152 static value_string_ext sapi_t_ext
= VALUE_STRING_EXT_INIT(sapi_t
);
154 static const value_string sapi_abrv
[] = {
165 { 10, "Reserved 10" },
167 { 12, "Reserved 12" },
168 { 13, "Reserved 13" },
169 { 14, "Reserved 14" },
170 { 15, "Reserved 15" },
173 static value_string_ext sapi_abrv_ext
= VALUE_STRING_EXT_INIT(sapi_abrv
);
175 static const true_false_string a_bit
= {
176 "To solicit an acknowledgement from the peer LLE. ",
177 "The peer LLE is not requested to send an acknowledgment."
180 static const true_false_string pd_bit
= {
181 "Invalid frame PD=1",
184 static const true_false_string e_bit
= {
186 " non encrypted frame"
188 static const true_false_string pm_bit
= {
189 "FCS covers the frame header and information fields",
190 "FCS covers only the frame header and first N202 octets of the information field"
192 static const true_false_string cr_bit
= {
193 "DownLink/UpLink = Command/Response",
194 "DownLink/UpLink = Response/Command"
196 /* bits are swaped comparing with "Table 3" in ETSI document */
197 static const value_string pme
[] = {
198 { 0, "unprotected,non-ciphered information" },
199 { 1, "protected, non-ciphered information" },
200 { 2, "unprotected,ciphered information"},
201 { 3, "protected, ciphered information" },
205 /* MLT CHANGES - adding XID parameter types & TOM protocols */
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"},
222 static value_string_ext xid_param_type_str_ext
= VALUE_STRING_EXT_INIT(xid_param_type_str
);
224 static const value_string tompd_formats
[] = {
225 {0x0, "Not specified"},
226 {0x1, "TIA/EIA-136"},
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"},
243 /* END MLT CHANGES */
245 static const value_string cr_formats_unnumb
[]= {
246 { 0x1, "DM-response" },
247 { 0x4, "DISC-command" },
248 { 0x6, "UA-response" },
254 static const value_string cr_formats_ipluss
[] = {
262 /* CRC24 table - FCS */
263 guint32 tbl_crc24
[256] = {
264 0x00000000, 0x00d6a776, 0x00f64557, 0x0020e221, 0x00b78115, 0x00612663, 0x0041c442, 0x00976334,
265 0x00340991, 0x00e2aee7, 0x00c24cc6, 0x0014ebb0, 0x00838884, 0x00552ff2, 0x0075cdd3, 0x00a36aa5,
266 0x00681322, 0x00beb454, 0x009e5675, 0x0048f103, 0x00df9237, 0x00093541, 0x0029d760, 0x00ff7016,
267 0x005c1ab3, 0x008abdc5, 0x00aa5fe4, 0x007cf892, 0x00eb9ba6, 0x003d3cd0, 0x001ddef1, 0x00cb7987,
268 0x00d02644, 0x00068132, 0x00266313, 0x00f0c465, 0x0067a751, 0x00b10027, 0x0091e206, 0x00474570,
269 0x00e42fd5, 0x003288a3, 0x00126a82, 0x00c4cdf4, 0x0053aec0, 0x008509b6, 0x00a5eb97, 0x00734ce1,
270 0x00b83566, 0x006e9210, 0x004e7031, 0x0098d747, 0x000fb473, 0x00d91305, 0x00f9f124, 0x002f5652,
271 0x008c3cf7, 0x005a9b81, 0x007a79a0, 0x00acded6, 0x003bbde2, 0x00ed1a94, 0x00cdf8b5, 0x001b5fc3,
272 0x00fb4733, 0x002de045, 0x000d0264, 0x00dba512, 0x004cc626, 0x009a6150, 0x00ba8371, 0x006c2407,
273 0x00cf4ea2, 0x0019e9d4, 0x00390bf5, 0x00efac83, 0x0078cfb7, 0x00ae68c1, 0x008e8ae0, 0x00582d96,
274 0x00935411, 0x0045f367, 0x00651146, 0x00b3b630, 0x0024d504, 0x00f27272, 0x00d29053, 0x00043725,
275 0x00a75d80, 0x0071faf6, 0x005118d7, 0x0087bfa1, 0x0010dc95, 0x00c67be3, 0x00e699c2, 0x00303eb4,
276 0x002b6177, 0x00fdc601, 0x00dd2420, 0x000b8356, 0x009ce062, 0x004a4714, 0x006aa535, 0x00bc0243,
277 0x001f68e6, 0x00c9cf90, 0x00e92db1, 0x003f8ac7, 0x00a8e9f3, 0x007e4e85, 0x005eaca4, 0x00880bd2,
278 0x00437255, 0x0095d523, 0x00b53702, 0x00639074, 0x00f4f340, 0x00225436, 0x0002b617, 0x00d41161,
279 0x00777bc4, 0x00a1dcb2, 0x00813e93, 0x005799e5, 0x00c0fad1, 0x00165da7, 0x0036bf86, 0x00e018f0,
280 0x00ad85dd, 0x007b22ab, 0x005bc08a, 0x008d67fc, 0x001a04c8, 0x00cca3be, 0x00ec419f, 0x003ae6e9,
281 0x00998c4c, 0x004f2b3a, 0x006fc91b, 0x00b96e6d, 0x002e0d59, 0x00f8aa2f, 0x00d8480e, 0x000eef78,
282 0x00c596ff, 0x00133189, 0x0033d3a8, 0x00e574de, 0x007217ea, 0x00a4b09c, 0x008452bd, 0x0052f5cb,
283 0x00f19f6e, 0x00273818, 0x0007da39, 0x00d17d4f, 0x00461e7b, 0x0090b90d, 0x00b05b2c, 0x0066fc5a,
284 0x007da399, 0x00ab04ef, 0x008be6ce, 0x005d41b8, 0x00ca228c, 0x001c85fa, 0x003c67db, 0x00eac0ad,
285 0x0049aa08, 0x009f0d7e, 0x00bfef5f, 0x00694829, 0x00fe2b1d, 0x00288c6b, 0x00086e4a, 0x00dec93c,
286 0x0015b0bb, 0x00c317cd, 0x00e3f5ec, 0x0035529a, 0x00a231ae, 0x007496d8, 0x005474f9, 0x0082d38f,
287 0x0021b92a, 0x00f71e5c, 0x00d7fc7d, 0x00015b0b, 0x0096383f, 0x00409f49, 0x00607d68, 0x00b6da1e,
288 0x0056c2ee, 0x00806598, 0x00a087b9, 0x007620cf, 0x00e143fb, 0x0037e48d, 0x001706ac, 0x00c1a1da,
289 0x0062cb7f, 0x00b46c09, 0x00948e28, 0x0042295e, 0x00d54a6a, 0x0003ed1c, 0x00230f3d, 0x00f5a84b,
290 0x003ed1cc, 0x00e876ba, 0x00c8949b, 0x001e33ed, 0x008950d9, 0x005ff7af, 0x007f158e, 0x00a9b2f8,
291 0x000ad85d, 0x00dc7f2b, 0x00fc9d0a, 0x002a3a7c, 0x00bd5948, 0x006bfe3e, 0x004b1c1f, 0x009dbb69,
292 0x0086e4aa, 0x005043dc, 0x0070a1fd, 0x00a6068b, 0x003165bf, 0x00e7c2c9, 0x00c720e8, 0x0011879e,
293 0x00b2ed3b, 0x00644a4d, 0x0044a86c, 0x00920f1a, 0x00056c2e, 0x00d3cb58, 0x00f32979, 0x00258e0f,
294 0x00eef788, 0x003850fe, 0x0018b2df, 0x00ce15a9, 0x0059769d, 0x008fd1eb, 0x00af33ca, 0x007994bc,
295 0x00dafe19, 0x000c596f, 0x002cbb4e, 0x00fa1c38, 0x006d7f0c, 0x00bbd87a, 0x009b3a5b, 0x004d9d2d
298 #define INIT_CRC24 0xffffff
300 static guint32
crc_calc(guint32 fcs
, tvbuff_t
*tvb
, guint len
)
304 cp
= tvb_get_ptr(tvb
, 0, len
);
306 fcs
= (fcs
>> 8) ^ tbl_crc24
[(fcs
^ *cp
++) & 0xff];
313 FCS_NOT_VALID_DUE_TO_CIPHERING
,
318 /* sub-dissector for XID data */
319 static void llc_gprs_dissect_xid(tvbuff_t
*tvb
,
321 proto_item
*llcgprs_tree
)
324 guint8 xid_param_len
= 0, byte1
= 0, byte2
= 0, item_len
= 0, tmp
= 0;
325 guint16 location
= 0;
326 guint16 loop_counter
= 0;
327 proto_item
*u_ti
= NULL
;
328 proto_item
*uinfo_field
= NULL
;
329 proto_tree
*uinfo_tree
= NULL
;
330 proto_tree
*xid_tree
= NULL
;
333 info_len
= tvb_reported_length(tvb
);
335 u_ti
= proto_tree_add_text(llcgprs_tree
, tvb
, 0, info_len
,
336 "Information Field: Length = %u", info_len
);
337 xid_tree
= proto_item_add_subtree(u_ti
, ett_ui
);
339 while (location
< info_len
)
341 /* parse the XID parameters */
342 byte1
= tvb_get_guint8(tvb
, location
);
346 guint8 xid_param_len_high
= 0;
347 guint8 xid_param_len_low
= 0;
348 byte2
= tvb_get_guint8(tvb
, location
+ 1);
350 /* XL bit is set - length is continued in second byte */
351 xid_param_len_high
= byte1
& 0x03;
352 xid_param_len_low
= byte2
& 0xFC;
354 /* bit shift the rest of the length */
355 xid_param_len_low
= xid_param_len_low
>> 2;
356 xid_param_len_low
= xid_param_len_low
& 0x3F;
358 xid_param_len_high
= xid_param_len_high
<< 6;
359 xid_param_len_high
= xid_param_len_high
& 0xC0;
361 /* combine the two */
362 xid_param_len
= xid_param_len_high
| xid_param_len_low
;
363 item_len
= xid_param_len
+ 2;
368 xid_param_len
= byte1
& 0x3;
369 item_len
= xid_param_len
+ 1;
375 if (tmp
== 0xB) /* L3 XID parameters, call the SNDCP-XID dissector */
377 tvbuff_t
*sndcp_xid_tvb
;
378 guint8 sndcp_xid_offset
;
380 uinfo_field
= proto_tree_add_text(xid_tree
, tvb
, location
, item_len
,
381 "XID parameter Type: L3 parameters");
382 uinfo_tree
= proto_item_add_subtree(uinfo_field
, ett_ui
);
383 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_xl
, tvb
, location
, 1, byte1
);
384 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_type
, tvb
, location
, 1, byte1
);
385 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_len1
, tvb
, location
, 1, byte1
);
387 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_len2
, tvb
, location
+1, 1, byte2
);
388 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_spare
, tvb
, location
+1, 1, byte2
);
389 sndcp_xid_offset
= 2;
393 sndcp_xid_offset
= 1;
398 sndcp_xid_tvb
= tvb_new_subset (tvb
, location
+sndcp_xid_offset
, xid_param_len
, xid_param_len
);
402 call_dissector(sndcp_xid_handle
, sndcp_xid_tvb
, pinfo
, uinfo_tree
);
406 location
+= item_len
;
410 if (( xid_param_len
> 0 ) && ( xid_param_len
<=4 ))
414 for (i
=1;i
<=xid_param_len
;i
++)
417 value
|= (guint32
)tvb_get_guint8(tvb
, location
+i
);
419 uinfo_field
= proto_tree_add_text(xid_tree
, tvb
, location
, item_len
,
420 "XID Parameter Type: %s - Value: %u",
421 val_to_str_ext_const(tmp
, &xid_param_type_str_ext
, "Reserved Type:%X"), value
);
425 uinfo_field
= proto_tree_add_text(xid_tree
, tvb
, location
, item_len
,
426 "XID Parameter Type: %s",
427 val_to_str_ext_const(tmp
, &xid_param_type_str_ext
, "Reserved Type:%X"));
429 uinfo_tree
= proto_item_add_subtree(uinfo_field
, ett_ui
);
430 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_xl
, tvb
, location
,
432 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_type
, tvb
, location
,
434 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_len1
, tvb
, location
,
438 /* length continued into byte 2 */
439 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_len2
, tvb
, location
,
441 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_spare
, tvb
, location
,
444 /* be sure to account for the second byte of length */
449 for (loop_counter
= 0; loop_counter
< xid_param_len
; loop_counter
++)
451 /* grab the information in the XID param */
452 byte2
= tvb_get_guint8(tvb
, location
);
453 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_xid_byte
, tvb
, location
,
462 /* Code to actually dissect the packets */
464 dissect_llcgprs(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
466 guint8 addr_fld
=0, sapi
=0, ctrl_fld_fb
=0, frame_format
, tmp
=0;
467 guint16 offset
=0 , epm
= 0, nu
=0, ctrl_fld_ui_s
=0;
468 guint16 crc_length
=0, llc_data_reported_length
=0, llc_data_length
= 0;
469 proto_item
*ti
, *addres_field_item
, *ctrl_field_item
, *ui_ti
;
470 proto_tree
*llcgprs_tree
=NULL
, *ad_f_tree
=NULL
, *ctrl_f_tree
=NULL
, *ui_tree
=NULL
;
475 fcs_status_t fcs_status
;
477 /* MLT CHANGES - additional variables */
483 proto_item
*uinfo_field
= NULL
;
484 proto_tree
*uinfo_tree
= NULL
;
485 /* END MLT CHANGES */
486 proto_item
* fcs_item
= NULL
;
487 gboolean ciphered_ui_frame
= FALSE
;
489 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "GPRS-LLC");
491 addr_fld
= tvb_get_guint8(tvb
, offset
);
496 col_set_str(pinfo
->cinfo
, COL_INFO
, "Invalid packet - Protocol Discriminator bit is set to 1");
500 sapi
= addr_fld
& 0xF;
502 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "SAPI: %s", val_to_str_ext_const(sapi
, &sapi_abrv_ext
, "Unknown (%d)"));
504 ctrl_fld_fb
= tvb_get_guint8(tvb
, offset
);
505 if (ctrl_fld_fb
< 0xC0)
507 frame_format
= (ctrl_fld_fb
< 0x80)? I_FORMAT
: S_FORMAT
;
511 frame_format
= (ctrl_fld_fb
< 0xe0 )? UI_FORMAT
: U_FORMAT
;
513 length
= tvb_reported_length(tvb
);
514 llc_data_length
= tvb_length(tvb
);
515 if(llc_data_length
==length
){
516 llc_data_length
= length
- CRC_LENGTH
;
518 llc_data_reported_length
= length
- CRC_LENGTH
; /* llc_data_reported_length includes the header and the payload */
519 if (tvb_length(tvb
) >= length
&& length
>= CRC_LENGTH
)
522 * We have all the packet data, including the full FCS,
523 * so we can compute the FCS.
525 fcs_status
= FCS_VALID
;
529 /* We don't have enough data to compute the FCS. */
530 fcs_status
= FCS_NOT_COMPUTED
;
534 * We need to check the PM bit for UI frames. Read the control field here.
536 if (frame_format
== UI_FORMAT
)
538 nu
= ctrl_fld_ui_s
= tvb_get_ntohs(tvb
, offset
);
540 epm
= ctrl_fld_ui_s
& 0x3;
541 nu
= (nu
>>2)&0x01FF;
543 /* If the frame is ciphered, the calculated FCS will not be valid (unless it has been unciphered) */
546 ciphered_ui_frame
= TRUE
;
548 if ((epm
& UI_MASK_PM
)== 0)
550 /* FCS covers at maximum the LLC header and N202 bytes */
551 crc_length
= MIN(UI_HDR_LENGTH
+ N202
, llc_data_reported_length
);
555 crc_length
= llc_data_reported_length
;
560 crc_length
= llc_data_reported_length
;
562 if(fcs_status
== FCS_VALID
)
564 fcs_calc
= crc_calc ( INIT_CRC24
, tvb
, crc_length
);
565 fcs_calc
= ~fcs_calc
;
566 fcs_calc
&= 0xffffff;
568 fcs
= tvb_get_letoh24(tvb
, llc_data_reported_length
);
569 if ( fcs_calc
== fcs
)
571 fcs_status
= FCS_VALID
;
575 if (ciphered_ui_frame
)
577 fcs_status
= FCS_NOT_VALID_DUE_TO_CIPHERING
;
581 fcs_status
= FCS_NOT_VALID
;
586 /* In the interest of speed, if "tree" is NULL, don't do any work not
587 necessary to generate protocol tree items. */
592 ti
= proto_tree_add_protocol_format(tree
, proto_llcgprs
, tvb
, 0, -1,
593 "MS-SGSN LLC (Mobile Station - Serving GPRS Support Node Logical Link Control) SAPI: %s",
594 val_to_str_ext_const(sapi
, &sapi_t_ext
, "Unknown (%u)"));
596 llcgprs_tree
= proto_item_add_subtree(ti
, ett_llcgprs
);
598 /* add an item to the subtree, see section 1.6 for more information */
599 switch (fcs_status
) {
602 proto_tree_add_text (llcgprs_tree
, tvb
, llc_data_reported_length
, CRC_LENGTH
,
603 "FCS: 0x%06x (correct)", fcs_calc
&0xffffff);
607 proto_tree_add_text (llcgprs_tree
, tvb
, llc_data_reported_length
, CRC_LENGTH
,
608 "FCS: 0x%06x (incorrect, should be 0x%06x)", fcs
, fcs_calc
);
611 case FCS_NOT_VALID_DUE_TO_CIPHERING
:
612 proto_tree_add_text (llcgprs_tree
, tvb
, llc_data_reported_length
, CRC_LENGTH
,
613 "FCS: 0x%06x (incorrect, maybe due to ciphering, calculated 0x%06x)", fcs
, fcs_calc
);
616 case FCS_NOT_COMPUTED
:
617 fcs_item
= proto_tree_add_text (llcgprs_tree
, tvb
, 0, 0,
618 "FCS: Not enough data to compute the FCS");
619 PROTO_ITEM_SET_GENERATED(fcs_item
);
620 break; /* FCS not present */
623 addres_field_item
= proto_tree_add_uint_format(llcgprs_tree
, hf_llcgprs_sapi
,
624 tvb
, 0, 1, sapi
, "Address field SAPI: %s", val_to_str_ext_const(sapi
, &sapi_abrv_ext
, "Unknown (%d)"));
626 ad_f_tree
= proto_item_add_subtree(addres_field_item
, ett_llcgprs_adf
);
627 proto_tree_add_boolean(ad_f_tree
, hf_llcgprs_pd
, tvb
, 0, 1, addr_fld
);
628 proto_tree_add_boolean(ad_f_tree
, hf_llcgprs_cr
, tvb
, 0, 1, addr_fld
);
629 proto_tree_add_uint(ad_f_tree
, hf_llcgprs_sapib
, tvb
, 0, 1, addr_fld
);
632 switch (frame_format
)
635 col_append_str(pinfo
->cinfo
, COL_INFO
, ", I, ");
637 /* MLT CHANGES - additional parsing code */
638 ns
= tvb_get_ntohs(tvb
, offset
);
639 ns
= (ns
>> 4)& 0x01FF;
640 nr
= ctrl_fld_ui_s
= tvb_get_ntohs(tvb
, offset
+ 1);
641 nr
= (nr
>> 2) & 0x01FF;
643 epm
= ctrl_fld_ui_s
& 0x3;
645 /* advance to either R Bitmap or Payload */
648 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str(epm
, cr_formats_ipluss
, "Unknown (%d)"));
649 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", N(S) = %u", ns
);
650 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", N(R) = %u", nr
);
656 ctrl_field_item
= proto_tree_add_text(llcgprs_tree
, tvb
, (offset
-3),
657 3, "Information format: %s: N(S) = %u, N(R) = %u",
658 val_to_str(epm
, cr_formats_ipluss
, "Unknown (%d)"), ns
, nr
);
659 ctrl_f_tree
= proto_item_add_subtree(ctrl_field_item
, ett_llcgprs_sframe
);
661 /* retrieve the second octet */
662 tmpx
= tvb_get_ntohs(tvb
, (offset
-3)) << 16;
663 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_ifmt
, tvb
, offset
-3, 3, tmpx
);
664 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_ia
, tvb
, offset
-3, 3, tmpx
);
665 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_izerobit
, tvb
, offset
-3, 3, tmpx
);
668 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_isack_ns
, tvb
, offset
-3, 3, tmpx
);
671 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_isack_nr
, tvb
, offset
-3, 3, tmpx
);
672 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_isack_sfb
, tvb
, offset
-3, 3, ctrl_fld_ui_s
);
675 /* check to see if epm is SACK - meaning this is an ISACK frame */
680 k
= kmask
= tvb_get_guint8(tvb
, offset
);
683 /* advance past the k field */
686 /* the real value of k is actually k + 1 */
687 /* account for the off by one representation */
690 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", k = %u", k
);
694 guint8 loop_count
= 0;
696 guint16 location
= offset
;
698 ctrl_field_item
= proto_tree_add_text(llcgprs_tree
, tvb
, (offset
-1),
699 (k
+1), "SACK FRAME: k = %u", k
);
701 ctrl_f_tree
= proto_item_add_subtree(ctrl_field_item
, ett_llcgprs_sframe
);
702 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_kmask
, tvb
, offset
-1, 1, kmask
);
703 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_k
, tvb
, offset
-1, 1, k
);
705 /* display the R Bitmap */
706 for (loop_count
= 0; loop_count
< k
; loop_count
++)
708 r_byte
= tvb_get_guint8(tvb
, location
);
709 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_rbyte
, tvb
, location
, 1, r_byte
);
714 /* step past the R Bitmap */
718 if ((sapi
== SAPI_TOM2
) || (sapi
== SAPI_TOM8
))
720 /* if SAPI is TOM do other parsing */
724 guint8 remaining_length
= 0;
726 int loop_counter
= 0;
728 tom_byte
= tvb_get_guint8(tvb
, offset
);
729 remaining_length
= (tom_byte
>> 4) & 0x0F;
730 tom_pd
= tom_byte
& 0x0F;
732 ctrl_field_item
= proto_tree_add_text(llcgprs_tree
, tvb
, offset
,
733 (llc_data_reported_length
-offset
), "TOM Envelope - Protocol: %s",
734 val_to_str(tom_pd
, tompd_formats
, "Unknown (%d)"));
736 ctrl_f_tree
= proto_item_add_subtree(ctrl_field_item
, ett_llcgprs_sframe
);
738 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_rl
, tvb
, offset
, 1, tom_byte
);
739 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_pd
, tvb
, offset
, 1, tom_byte
);
741 /* step past the TOM header first byte */
744 /* TOM remaining length field value 0x0F is reserved for extension */
745 if (remaining_length
!= 0x0F)
747 /* parse the rest of the TOM header */
748 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
750 tom_byte
= tvb_get_guint8(tvb
, offset
);
752 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_header
, tvb
,
753 offset
, 1, tom_byte
);
755 /* step to the next byte */
759 remaining_length
= llc_data_reported_length
- offset
;
761 /* parse the TOM message capsule */
762 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
764 tom_byte
= tvb_get_guint8(tvb
, offset
);
766 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_data
, tvb
,
767 offset
, 1, tom_byte
);
769 /* step to the next byte */
777 /* otherwise - call a subdissector */
778 next_tvb
= tvb_new_subset(tvb
, offset
, (llc_data_length
-offset
), (llc_data_reported_length
-offset
));
779 if (!dissector_try_uint(llcgprs_subdissector_table
, sapi
, next_tvb
, pinfo
, tree
))
780 /* if no subdissector is found, call the data dissector */
782 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
785 /* END MLT CHANGES */
789 nu
= ctrl_fld_ui_s
= tvb_get_ntohs(tvb
, offset
);
791 epm
= ctrl_fld_ui_s
& 0x3;
792 nu
= (nu
>>2)&0x01FF;
794 col_append_str(pinfo
->cinfo
, COL_INFO
, ", S, ");
795 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str(epm
, cr_formats_ipluss
, "Unknown (%d)"));
796 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", N(R) = %u", nu
);
800 ctrl_field_item
= proto_tree_add_text(llcgprs_tree
, tvb
, offset
-2, 2,
801 "Supervisory format: %s: N(R) = %u",
802 val_to_str(epm
, cr_formats_ipluss
, "Unknown (%d)"), nu
);
804 ctrl_f_tree
= proto_item_add_subtree(ctrl_field_item
, ett_llcgprs_sframe
);
805 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_S_fmt
, tvb
, offset
-2,
807 proto_tree_add_boolean(ctrl_f_tree
, hf_llcgprs_As
, tvb
, offset
-2,
810 /* MLT CHANGES - added spare bits */
811 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_sspare
, tvb
, offset
-2,
813 /* END MLT CHANGES */
814 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_NR
, tvb
, offset
-2,
816 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_sjsd
, tvb
, offset
-2,
819 /* MLT CHANGES - additional parsing code to handle SACK */
820 if ((ctrl_fld_ui_s
& 0x03) == 0x03)
821 /* It is a SACK frame */
823 /* TODO: length is fudged - it is not correct */
824 guint32 sack_length
= llc_data_reported_length
- offset
;
830 guint16 location
= offset
;
831 ctrl_field_item
= proto_tree_add_text(llcgprs_tree
, tvb
, offset
,
832 sack_length
, "SACK FRAME: length = %u", sack_length
);
833 ctrl_f_tree
= proto_item_add_subtree(ctrl_field_item
, ett_llcgprs_sframe
);
834 /* display the R Bitmap */
835 for (loop_count
= 0; loop_count
< sack_length
; loop_count
++)
837 r_byte
= tvb_get_guint8(tvb
, location
);
838 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_rbyte
, tvb
,
839 location
, 1, r_byte
);
843 /* step past the r bitmap */
844 offset
+= sack_length
;
848 /* should parse the rest of the supervisory message based on type */
849 /* if SAPI is TOM do other parsing */
850 if ((sapi
== SAPI_TOM2
) || (sapi
== SAPI_TOM8
))
855 guint8 remaining_length
= 0;
857 int loop_counter
= 0;
859 tom_byte
= tvb_get_guint8(tvb
, offset
);
860 remaining_length
= (tom_byte
>> 4) & 0x0F;
861 tom_pd
= tom_byte
& 0x0F;
863 ctrl_field_item
= proto_tree_add_text(llcgprs_tree
, tvb
, offset
,
864 (llc_data_reported_length
-offset
), "TOM Envelope - Protocol: %s",
865 val_to_str(tom_pd
, tompd_formats
, "Unknown (%d)"));
867 ctrl_f_tree
= proto_item_add_subtree(ctrl_field_item
, ett_llcgprs_sframe
);
869 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_rl
, tvb
, offset
, 1, tom_byte
);
870 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_pd
, tvb
, offset
, 1, tom_byte
);
872 /* step past the TOM header first byte */
875 /* TOM remaining length field value 0x0F is reserved for extension */
876 if (remaining_length
!= 0x0F)
878 /* parse the rest of the TOM header */
879 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
881 tom_byte
= tvb_get_guint8(tvb
, offset
);
882 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_header
, tvb
,
883 offset
, 1, tom_byte
);
885 /* step to the next byte */
889 /* Amount of frame left from offset to crc */
890 remaining_length
= llc_data_reported_length
- offset
;
892 /* parse the TOM message capsule */
893 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
895 tom_byte
= tvb_get_guint8(tvb
, offset
);
896 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_data
, tvb
,
897 offset
, 1, tom_byte
);
899 /* step to the next byte */
905 else if (llc_data_reported_length
>offset
)
907 /* otherwise - call a subdissector */
908 next_tvb
= tvb_new_subset(tvb
, offset
, (llc_data_length
-offset
), (llc_data_reported_length
-offset
));
909 if (!dissector_try_uint(llcgprs_subdissector_table
, sapi
, next_tvb
, pinfo
, tree
))
911 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
914 /* END MLT CHANGES */
917 /* nu and epm calculated before FCS check for UI frame */
919 col_append_str(pinfo
->cinfo
, COL_INFO
, ", UI, ");
920 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str(epm
, pme
, "Unknown (%d)"));
921 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", N(U) = %u", nu
);
925 ctrl_field_item
= proto_tree_add_text(llcgprs_tree
, tvb
, offset
-2,
926 2, "Unconfirmed Information format - UI, N(U) = %u", nu
);
927 ctrl_f_tree
= proto_item_add_subtree(ctrl_field_item
, ett_llcgprs_ctrlf
);
929 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_U_fmt
, tvb
, offset
-2,
931 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_sp_bits
, tvb
, offset
-2,
933 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_NU
, tvb
, offset
-2, 2,
935 proto_tree_add_boolean(ctrl_f_tree
, hf_llcgprs_E_bit
, tvb
, offset
-2,
937 proto_tree_add_boolean(ctrl_f_tree
, hf_llcgprs_PM_bit
, tvb
, offset
-2,
941 /* MLT CHANGES - TOM parsing added */
942 next_tvb
= tvb_new_subset(tvb
, offset
, (llc_data_length
-offset
), (llc_data_reported_length
-offset
));
944 if ((ignore_cipher_bit
&& (fcs_status
== FCS_VALID
)) || !(epm
& 0x2))
946 /* Either we're ignoring the cipher bit
947 * (because the bit is set but the
948 * data is unciphered), and the data has
949 * a valid FCS, or the cipher
950 * bit isn't set (indicating that the
951 * data is unciphered). Try dissecting
952 * it with a subdissector. */
954 /* if SAPI is TOM do other parsing */
955 if ((sapi
== SAPI_TOM2
) || (sapi
== SAPI_TOM8
))
960 guint8 remaining_length
= 0;
962 int loop_counter
= 0;
964 tom_byte
= tvb_get_guint8(tvb
, offset
);
965 remaining_length
= (tom_byte
>> 4) & 0x0F;
966 tom_pd
= tom_byte
& 0x0F;
968 ctrl_field_item
= proto_tree_add_text(llcgprs_tree
, tvb
, offset
,
969 (llc_data_reported_length
-offset
), "TOM Envelope - Protocol: %s",
970 val_to_str(tom_pd
, tompd_formats
, "Unknown (%d)"));
972 ctrl_f_tree
= proto_item_add_subtree(ctrl_field_item
, ett_llcgprs_sframe
);
974 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_rl
, tvb
, offset
, 1, tom_byte
);
975 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_pd
, tvb
, offset
, 1, tom_byte
);
977 /* step past the TOM header first byte */
980 /* TOM remaining length field value 0x0F is reserved for extension */
981 if (remaining_length
!= 0x0F)
983 /* parse the rest of the TOM header */
984 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
986 tom_byte
= tvb_get_guint8(tvb
, offset
);
988 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_header
, tvb
,
989 offset
, 1, tom_byte
);
991 /* step to the next byte */
995 /* Amount of frame left from offset to crc */
996 remaining_length
= llc_data_reported_length
- offset
;
998 /* parse the TOM message capsule */
999 for (loop_counter
= 0; loop_counter
< remaining_length
; loop_counter
++)
1001 tom_byte
= tvb_get_guint8(tvb
, offset
);
1003 proto_tree_add_uint(ctrl_f_tree
, hf_llcgprs_tom_data
, tvb
,
1004 offset
, 1, tom_byte
);
1006 /* step to the next byte */
1012 else if (llc_data_reported_length
>offset
)
1014 /* otherwise - call a subdissector */
1015 if (!dissector_try_uint(llcgprs_subdissector_table
, sapi
, next_tvb
, pinfo
, tree
))
1017 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
1023 /* ciphered information - just parse it as data */
1024 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
1026 /* END MLT CHANGES */
1031 tmp
= ctrl_fld_fb
& 0xf;
1033 col_append_str(pinfo
->cinfo
, COL_INFO
, ", U, ");
1034 col_append_str(pinfo
->cinfo
, COL_INFO
,
1035 val_to_str(tmp
, cr_formats_unnumb
, "Unknown/invalid code:%X"));
1038 ui_ti
= proto_tree_add_text(llcgprs_tree
, tvb
, (offset
-1), (llc_data_reported_length
-1),
1039 "Unnumbered frame: %s",
1040 val_to_str(tmp
, cr_formats_unnumb
, "Unknown/invalid code:%X"));
1042 ui_tree
= proto_item_add_subtree(ui_ti
, ett_ui
);
1043 proto_tree_add_uint(ui_tree
, hf_llcgprs_Un
, tvb
, (offset
-1), 1, ctrl_fld_fb
);
1044 proto_tree_add_boolean(ui_tree
, hf_llcgprs_PF
, tvb
, (offset
-1), 1, ctrl_fld_fb
);
1045 proto_tree_add_uint(ui_tree
, hf_llcgprs_ucom
, tvb
, (offset
-1), 1, ctrl_fld_fb
);
1049 /* MLT CHANGES - parse rest of the message based on type (M Bits) */
1050 m_bits
= ctrl_fld_fb
& 0x0F;
1052 info_len
= llc_data_reported_length
- offset
;
1059 /* These frames SHOULD NOT have an info field */
1062 proto_tree_add_text(llcgprs_tree
, tvb
, offset
, (llc_data_reported_length
-2),
1063 "No Information Field");
1067 /* This frame MAY or MAY NOT have an info field */
1068 /* Info field, if it exists, consists of XID parameters */
1072 xid_tvb
= tvb_new_subset (tvb
, offset
, info_len
, info_len
);
1074 llc_gprs_dissect_xid(xid_tvb
, pinfo
, llcgprs_tree
);
1079 /* These frames do have info fields consisting of XID parameters */
1080 /* Info field consists of XID parameters */
1084 xid_tvb
= tvb_new_subset (tvb
, offset
, info_len
, info_len
);
1086 llc_gprs_dissect_xid(xid_tvb
, pinfo
, llcgprs_tree
);
1090 /* This frame has a special format info field */
1093 guint32 fld_vars
= 0;
1094 guint16 cf_byte
= 0;
1095 int loop_counter
= 0;
1098 ui_ti
= proto_tree_add_text(llcgprs_tree
, tvb
, offset
, (llc_data_reported_length
-2),
1099 "Information Field: Length = %u", info_len
);
1100 ui_tree
= proto_item_add_subtree(ui_ti
, ett_ui
);
1102 uinfo_field
= proto_tree_add_text(ui_tree
, tvb
, offset
, 6,
1103 "Rejected Frame Control Field");
1104 uinfo_tree
= proto_item_add_subtree(uinfo_field
, ett_ui
);
1107 for (loop_counter
= 0; loop_counter
< 3; loop_counter
++)
1109 /* display the rejected frame control field */
1110 cf_byte
= tvb_get_ntohs(tvb
, location
);
1111 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_cf
, tvb
, location
,
1117 uinfo_field
= proto_tree_add_text(ui_tree
, tvb
, location
, 4,
1118 "Information Field Data");
1119 uinfo_tree
= proto_item_add_subtree(uinfo_field
, ett_ui
);
1121 fld_vars
= tvb_get_ntohl(tvb
, location
);
1122 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_spare
, tvb
, location
,
1124 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_vs
, tvb
, location
,
1126 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_vr
, tvb
, (location
+ 1),
1128 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_cr
, tvb
, (location
+ 2),
1130 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_w4
, tvb
, (location
+ 3),
1132 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_w3
, tvb
, (location
+ 3),
1134 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_w2
, tvb
, (location
+ 3),
1136 proto_tree_add_uint(uinfo_tree
, hf_llcgprs_frmr_w1
, tvb
, (location
+ 3),
1143 /* END MLT CHANGES */
1149 /* Register the protocol with Wireshark */
1150 /* this format is require because a script is used to build the C function */
1151 /* that calls all the protocol registration. */
1154 proto_register_llcgprs(void)
1156 /* Setup list of header fields See Section 1.6.1 for details */
1157 static hf_register_info hf
[] = {
1159 { "SAPI", "llcgprs.sapi", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
1160 &sapi_abrv_ext
, 0x0, "Service Access Point Identifier", HFILL
}},
1163 { "Protocol Discriminator_bit", "llcgprs.pd", FT_BOOLEAN
, 8,
1164 TFS(&pd_bit
), 0x80, "Protocol Discriminator bit (should be 0)", HFILL
}},
1167 { "Supervisory function bits", "llcgprs.s1s2", FT_UINT16
, BASE_HEX
,
1168 VALS(cr_formats_ipluss
), 0x3, NULL
, HFILL
}},
1171 { "Command/Response bit", "llcgprs.cr", FT_BOOLEAN
, 8,
1172 TFS(&cr_bit
), 0x40, NULL
, HFILL
}},
1174 { &hf_llcgprs_sapib
,
1175 { "SAPI", "llcgprs.sapib", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
1176 &sapi_t_ext
, 0xf, "Service Access Point Identifier", HFILL
}},
1178 { &hf_llcgprs_U_fmt
,
1179 { "UI format", "llcgprs.ui", FT_UINT16
, BASE_HEX
,
1180 NULL
, UI_MASK_FMT
, "UI frame format", HFILL
}},
1183 { "U format", "llcgprs.u", FT_UINT8
, BASE_DEC
,
1184 NULL
, 0xe0, "U frame format", HFILL
}},
1186 { &hf_llcgprs_sp_bits
,
1187 { "Spare bits", "llcgprs.ui_sp_bit", FT_UINT16
, BASE_HEX
,
1188 NULL
, UI_MASK_SPB
, NULL
, HFILL
}},
1191 { "N(U)", "llcgprs.nu", FT_UINT16
, BASE_DEC
,
1192 NULL
, UI_MASK_NU
, "Transmitted unconfirmed sequence number", HFILL
}},
1194 { &hf_llcgprs_E_bit
,
1195 { "E bit", "llcgprs.e", FT_BOOLEAN
, 16,
1196 TFS(&e_bit
), UI_MASK_E
, "Encryption mode bit", HFILL
}},
1198 { &hf_llcgprs_PM_bit
,
1199 { "PM bit", "llcgprs.pm", FT_BOOLEAN
, 16,
1200 TFS(&pm_bit
), UI_MASK_PM
, "Protected mode bit", HFILL
}},
1203 { "Ackn request bit", "llcgprs.as", FT_BOOLEAN
, 16,
1204 TFS(&a_bit
), 0x2000 , "Acknowledgement request bit A", HFILL
}},
1207 { "P/F bit", "llcgprs.pf", FT_BOOLEAN
, 8,
1208 NULL
, 0x10, "Poll/Final bit", HFILL
}},
1211 { "Command/Response", "llcgprs.ucom", FT_UINT8
, BASE_HEX
,
1212 VALS(cr_formats_unnumb
), 0xf, "Commands and Responses", HFILL
}},
1215 { "Receive sequence number", "llcgprs.nr", FT_UINT16
, BASE_DEC
,
1216 NULL
, UI_MASK_NU
, "Receive sequence number N(R)", HFILL
}},
1219 { "S format", "llcgprs.s", FT_UINT16
, BASE_DEC
,
1220 NULL
, 0xc000, "Supervisory format S", HFILL
}},
1222 /* MLT CHANGES - additional masks */
1224 { "ignored", "llcgprs.kmask", FT_UINT8
,
1225 BASE_DEC
, NULL
, 0xE0, NULL
, HFILL
}},
1228 { "k", "llcgprs.k", FT_UINT8
, BASE_DEC
,
1229 NULL
, 0x1F, "k counter", HFILL
}},
1231 {&hf_llcgprs_isack_ns
,
1232 { "N(S)", "llcgprs.sackns", FT_UINT24
, BASE_DEC
,
1233 NULL
, 0x1FF000, NULL
, HFILL
}},
1235 {&hf_llcgprs_isack_nr
,
1236 { "N(R)", "llcgprs.sacknr", FT_UINT24
, BASE_DEC
,
1237 NULL
, 0x0007FC, NULL
, HFILL
}},
1239 {&hf_llcgprs_isack_sfb
,
1240 { "Supervisory function bits", "llcgprs.sacksfb", FT_UINT24
, BASE_HEX
,
1241 VALS(cr_formats_ipluss
), 0x000003, NULL
, HFILL
}},
1244 { "I Format", "llcgprs.ifmt", FT_UINT24
, BASE_DEC
,
1245 NULL
, 0x800000, "I Fmt Bit", HFILL
}},
1248 { "Ack Bit", "llcgprs.ia", FT_UINT24
, BASE_DEC
,
1249 NULL
, 0x400000, "I A Bit", HFILL
}},
1251 {&hf_llcgprs_izerobit
,
1252 { "Spare", "llcgprs.iignore", FT_UINT24
, BASE_DEC
,
1253 NULL
, 0x200000, "Ignore Bit", HFILL
}},
1255 {&hf_llcgprs_sspare
,
1256 { "Spare", "llcgprs.sspare", FT_UINT16
, BASE_DEC
,
1257 NULL
, 0x1800, "Ignore Bit", HFILL
}},
1260 { "R Bitmap Bits", "llcgprs.sackrbits", FT_UINT8
, BASE_HEX
,
1261 NULL
, 0xFF, "R Bitmap", HFILL
}},
1263 /* XID Parameter Parsing Info */
1264 {&hf_llcgprs_xid_xl
,
1265 { "XL Bit", "llcgprs.xidxl", FT_UINT8
,
1266 BASE_HEX
, NULL
, 0x80, "XL", HFILL
}},
1268 {&hf_llcgprs_xid_type
,
1269 { "Type", "llcgprs.xidtype", FT_UINT8
, BASE_DEC
,
1270 NULL
, 0x7C, NULL
, HFILL
}},
1272 {&hf_llcgprs_xid_len1
,
1273 { "Length", "llcgprs.xidlen1", FT_UINT8
, BASE_DEC
,
1274 NULL
, 0x03, NULL
, HFILL
}},
1276 {&hf_llcgprs_xid_len2
,
1277 { "Length continued", "llcgprs.xidlen2", FT_UINT8
, BASE_DEC
,
1278 NULL
, 0xFC, NULL
, HFILL
}},
1280 {&hf_llcgprs_xid_spare
,
1281 { "Spare", "llcgprs.xidspare", FT_UINT8
, BASE_HEX
,
1282 NULL
, 0x03, "Ignore", HFILL
}},
1284 {&hf_llcgprs_xid_byte
,
1285 { "Parameter Byte", "llcgprs.xidbyte", FT_UINT8
, BASE_HEX
,
1286 NULL
, 0xFF, "Data", HFILL
}},
1288 /* FRMR Parsing Information */
1289 {&hf_llcgprs_frmr_cf
,
1290 { "Control Field Octet", "llcgprs.frmrrfcf", FT_UINT16
,
1291 BASE_DEC
, NULL
, 0xFFFF, "Rejected Frame CF", HFILL
}},
1293 {&hf_llcgprs_frmr_spare
,
1294 { "X", "llcgprs.frmrspare", FT_UINT32
, BASE_HEX
,
1295 NULL
, 0xF00400F0, "Filler", HFILL
}},
1297 {&hf_llcgprs_frmr_vs
,
1298 { "V(S)", "llcgprs.frmrvs", FT_UINT32
, BASE_DEC
,
1299 NULL
, 0x0FF80000, "Current send state variable", HFILL
}},
1301 {&hf_llcgprs_frmr_vr
,
1302 { "V(R)", "llcgprs.frmrvr", FT_UINT32
, BASE_DEC
,
1303 NULL
, 0x0003FE00, "Current receive state variable", HFILL
}},
1305 {&hf_llcgprs_frmr_cr
,
1306 { "C/R", "llcgprs.frmrcr", FT_UINT32
, BASE_DEC
,
1307 NULL
, 0x00000100, "Rejected command response", HFILL
}},
1309 {&hf_llcgprs_frmr_w4
,
1310 { "W4", "llcgprs.frmrw4", FT_UINT32
, BASE_DEC
,
1311 NULL
, 0x00000008, "LLE was in ABM when rejecting", HFILL
}},
1313 {&hf_llcgprs_frmr_w3
,
1314 { "W3", "llcgprs.frmrw3", FT_UINT32
, BASE_DEC
,
1315 NULL
, 0x00000004, "Undefined control field", HFILL
}},
1317 {&hf_llcgprs_frmr_w2
,
1318 { "W2", "llcgprs.frmrw2", FT_UINT32
, BASE_DEC
,
1319 NULL
, 0x00000002, "Info exceeded N201", HFILL
}},
1321 {&hf_llcgprs_frmr_w1
,
1322 { "W1", "llcgprs.frmrw1", FT_UINT32
, BASE_DEC
,
1323 NULL
, 0x00000001, "Invalid - info not permitted", HFILL
}},
1325 {&hf_llcgprs_tom_rl
,
1326 { "Remaining Length of TOM Protocol Header", "llcgprs.romrl", FT_UINT8
, BASE_DEC
,
1327 NULL
, 0xF0, "RL", HFILL
}},
1329 {&hf_llcgprs_tom_pd
,
1330 { "TOM Protocol Discriminator", "llcgprs.tompd", FT_UINT8
, BASE_HEX
,
1331 NULL
, 0x0F, "TPD", HFILL
}},
1333 {&hf_llcgprs_tom_header
,
1334 { "TOM Header Byte", "llcgprs.tomhead", FT_UINT8
, BASE_HEX
,
1335 NULL
, 0xFF, "thb", HFILL
}},
1337 {&hf_llcgprs_tom_data
,
1338 { "TOM Message Capsule Byte", "llcgprs.tomdata", FT_UINT8
, BASE_HEX
,
1339 NULL
, 0xFF, "tdb", HFILL
}},
1340 /* END MLT CHANGES */
1343 /* Setup protocol subtree array */
1344 static gint
*ett
[] = {
1349 &ett_llcgprs_sframe
,
1352 module_t
*llcgprs_module
;
1354 /* Register the protocol name and description */
1355 proto_llcgprs
= proto_register_protocol("Logical Link Control GPRS",
1356 "GPRS-LLC", "llcgprs");
1357 llcgprs_subdissector_table
= register_dissector_table("llcgprs.sapi", "GPRS LLC SAPI", FT_UINT8
, BASE_HEX
);
1359 /* Required function calls to register the header fields and subtrees used */
1360 proto_register_field_array(proto_llcgprs
, hf
, array_length(hf
));
1361 proto_register_subtree_array(ett
, array_length(ett
));
1362 register_dissector("llcgprs", dissect_llcgprs
, proto_llcgprs
);
1364 llcgprs_module
= prefs_register_protocol ( proto_llcgprs
, NULL
);
1365 prefs_register_bool_preference ( llcgprs_module
, "autodetect_cipher_bit",
1366 "Autodetect cipher bit",
1367 "Whether to autodetect the cipher bit (because it might be set on unciphered data)",
1368 &ignore_cipher_bit
);
1372 /* If this dissector uses sub-dissector registration add a registration routine. */
1373 /* This format is required because a script is used to find these routines and */
1374 /* create the code that calls these routines. */
1376 proto_reg_handoff_llcgprs(void)
1378 dissector_handle_t gprs_llc_handle
;
1380 /* make sure that the top level can call this dissector */
1381 gprs_llc_handle
= find_dissector("llcgprs");
1382 dissector_add_uint("wtap_encap", WTAP_ENCAP_GPRS_LLC
, gprs_llc_handle
);
1384 data_handle
= find_dissector("data");
1385 sndcp_xid_handle
= find_dissector("sndcpxid");