2 * Routines for Logical Link Control GPRS dissection ETSI 4.64
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/packet.h>
45 #define UI_MASK_FMT 0xe000
46 #define UI_MASK_SPB 0x1800
47 #define UI_MASK_NU 0x07fc
48 #define UI_MASK_E 0x0002
49 #define UI_MASK_PM 0x0001
51 /* Initialize the protocol and registered fields */
52 static int proto_llcgprs = -1;
53 static int hf_llcgprs_pd = -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 /* MLT CHANGES - Additional display masks */
70 static int hf_llcgprs_k = -1;
71 static int hf_llcgprs_isack_ns = -1;
72 static int hf_llcgprs_isack_nr = -1;
73 static int hf_llcgprs_isack_sfb = -1;
74 static int hf_llcgprs_rbyte = -1;
75 static int hf_llcgprs_kmask = -1;
76 static int hf_llcgprs_ifmt = -1;
77 static int hf_llcgprs_ia = -1;
78 static int hf_llcgprs_izerobit = -1;
79 static int hf_llcgprs_sspare = -1;
80 static int hf_llcgprs_xid_xl = -1;
81 static int hf_llcgprs_xid_type = -1;
82 static int hf_llcgprs_xid_len1 = -1;
83 static int hf_llcgprs_xid_len2 = -1;
84 static int hf_llcgprs_xid_spare = -1;
85 static int hf_llcgprs_xid_byte = -1;
86 static int hf_llcgprs_frmr_cf = -1;
87 static int hf_llcgprs_frmr_spare = -1;
88 static int hf_llcgprs_frmr_vs = -1;
89 static int hf_llcgprs_frmr_vr = -1;
90 static int hf_llcgprs_frmr_cr = -1;
91 static int hf_llcgprs_frmr_w4 = -1;
92 static int hf_llcgprs_frmr_w3 = -1;
93 static int hf_llcgprs_frmr_w2 = -1;
94 static int hf_llcgprs_frmr_w1 = -1;
95 static int hf_llcgprs_tom_rl = -1;
96 static int hf_llcgprs_tom_pd = -1;
97 static int hf_llcgprs_tom_header = -1;
98 static int hf_llcgprs_tom_data = -1;
100 /* Unnumbered Commands and Responses (U Frames) */
109 /* SAPI value constants */
110 #define SAPI_LLGMM 0x01
111 #define SAPI_TOM2 0x02
112 #define SAPI_LL3 0x03
113 #define SAPI_LL5 0x05
114 #define SAPI_LLSMS 0x07
115 #define SAPI_TOM8 0x08
116 #define SAPI_LL9 0x09
117 #define SAPI_LL11 0x0B
119 /* END MLT CHANGES */
121 /* Initialize the subtree pointers */
122 static gint ett_llcgprs = -1;
123 static gint ett_llcgprs_adf = -1;
124 static gint ett_llcgprs_ctrlf = -1;
125 static gint ett_ui = -1;
126 static gint ett_llcgprs_sframe = -1;
128 static dissector_handle_t data_handle;
130 static gboolean ignore_cipher_bit = FALSE;
132 static dissector_table_t llcgprs_subdissector_table;
133 static const value_string sapi_t[] = {
135 { 1, "GPRS Mobility Management" },
136 { 2, "Tunnelling of messages 2" },
139 { 5, "User data 5" },
142 { 8, "Tunneling of messages 8" },
143 { 9, "User data 9" },
145 { 11, "User data 11" },
153 static const value_string sapi_abrv[] = {
164 { 10, "Reserved 10" },
166 { 12, "Reserved 12" },
167 { 13, "Reserved 13" },
168 { 14, "Reserved 14" },
169 { 15, "Reserved 15" },
172 static const true_false_string a_bit = {
173 "To solicit an acknowledgement from the peer LLE. ",
174 "The peer LLE is not requested to send an acknowledgment."
177 static const true_false_string pd_bit = {
178 "Invalid frame PD=1",
181 static const true_false_string e_bit = {
183 " non encrypted frame"
185 static const true_false_string pm_bit = {
186 "FCS covers the frame header and information fields",
187 "FCS covers only the frame header and first N202 octets of the information field"
189 static const true_false_string cr_bit = {
190 "DownLink/UpLink = Command/Response",
191 "DownLink/UpLink = Response/Command"
193 /* bits are swaped comparing with "Table 3" in ETSI document*/
194 static const value_string pme[] = {
195 { 0, "unprotected,non-ciphered information" },
196 { 1, "protected, non-ciphered information" },
197 { 2, "unprotected,ciphered information"},
198 { 3, "protected, ciphered information" },
202 /* MLT CHANGES - adding XID parameter types & TOM protocols */
203 static const value_string xid_param_type_str[] = {
204 {0x0, "Version (LLC version number)"},
205 {0x1, "IOV-UI (ciphering Input offset value for UI frames)"},
206 {0x2, "IOV-I (ciphering Input offset value for I frames)"},
207 {0x3, "T200 (retransmission timeout)"},
208 {0x4, "N200 (max number of retransmissions)"},
209 {0x5, "N201-U (max info field length for U and UI frames)"},
210 {0x6, "N201-I (max info field length for I frames)"},
211 {0x7, "mD (I frame buffer size in the DL direction)"},
212 {0x8, "mU (I frame buffer size in the UL direction)"},
213 {0x9, "kD (window size in the DL direction)"},
214 {0xA, "kU (window size in the UL direction)"},
215 {0xB, "Layer-3 Parameters"},
220 static const value_string tompd_formats[] = {
221 {0x0, "Not specified"},
222 {0x1, "TIA/EIA-136"},
224 {0x3, "Reserved value 3"},
225 {0x4, "Reserved value 4"},
226 {0x5, "Reserved value 5"},
227 {0x6, "Reserved value 6"},
228 {0x7, "Reserved value 7"},
229 {0x8, "Reserved value 8"},
230 {0x9, "Reserved value 9"},
231 {0xA, "Reserved value 10"},
232 {0xB, "Reserved value 11"},
233 {0xC, "Reserved value 12"},
234 {0xD, "Reserved value 13"},
235 {0xE, "Reserved value 14"},
236 {0xF, "Reserved for extension"},
239 /* END MLT CHANGES */
241 static const value_string cr_formats_unnumb[]= {
242 { 0x1, "DM-response" },
243 { 0x4, "DISC-command" },
244 { 0x6, "UA-response" },
250 static const value_string cr_formats_ipluss[] = {
258 /* CRC24 table - FCS */
259 guint32 tbl_crc24[256] = {
260 0x00000000, 0x00d6a776, 0x00f64557, 0x0020e221, 0x00b78115, 0x00612663, 0x0041c442, 0x00976334,
261 0x00340991, 0x00e2aee7, 0x00c24cc6, 0x0014ebb0, 0x00838884, 0x00552ff2, 0x0075cdd3, 0x00a36aa5,
262 0x00681322, 0x00beb454, 0x009e5675, 0x0048f103, 0x00df9237, 0x00093541, 0x0029d760, 0x00ff7016,
263 0x005c1ab3, 0x008abdc5, 0x00aa5fe4, 0x007cf892, 0x00eb9ba6, 0x003d3cd0, 0x001ddef1, 0x00cb7987,
264 0x00d02644, 0x00068132, 0x00266313, 0x00f0c465, 0x0067a751, 0x00b10027, 0x0091e206, 0x00474570,
265 0x00e42fd5, 0x003288a3, 0x00126a82, 0x00c4cdf4, 0x0053aec0, 0x008509b6, 0x00a5eb97, 0x00734ce1,
266 0x00b83566, 0x006e9210, 0x004e7031, 0x0098d747, 0x000fb473, 0x00d91305, 0x00f9f124, 0x002f5652,
267 0x008c3cf7, 0x005a9b81, 0x007a79a0, 0x00acded6, 0x003bbde2, 0x00ed1a94, 0x00cdf8b5, 0x001b5fc3,
268 0x00fb4733, 0x002de045, 0x000d0264, 0x00dba512, 0x004cc626, 0x009a6150, 0x00ba8371, 0x006c2407,
269 0x00cf4ea2, 0x0019e9d4, 0x00390bf5, 0x00efac83, 0x0078cfb7, 0x00ae68c1, 0x008e8ae0, 0x00582d96,
270 0x00935411, 0x0045f367, 0x00651146, 0x00b3b630, 0x0024d504, 0x00f27272, 0x00d29053, 0x00043725,
271 0x00a75d80, 0x0071faf6, 0x005118d7, 0x0087bfa1, 0x0010dc95, 0x00c67be3, 0x00e699c2, 0x00303eb4,
272 0x002b6177, 0x00fdc601, 0x00dd2420, 0x000b8356, 0x009ce062, 0x004a4714, 0x006aa535, 0x00bc0243,
273 0x001f68e6, 0x00c9cf90, 0x00e92db1, 0x003f8ac7, 0x00a8e9f3, 0x007e4e85, 0x005eaca4, 0x00880bd2,
274 0x00437255, 0x0095d523, 0x00b53702, 0x00639074, 0x00f4f340, 0x00225436, 0x0002b617, 0x00d41161,
275 0x00777bc4, 0x00a1dcb2, 0x00813e93, 0x005799e5, 0x00c0fad1, 0x00165da7, 0x0036bf86, 0x00e018f0,
276 0x00ad85dd, 0x007b22ab, 0x005bc08a, 0x008d67fc, 0x001a04c8, 0x00cca3be, 0x00ec419f, 0x003ae6e9,
277 0x00998c4c, 0x004f2b3a, 0x006fc91b, 0x00b96e6d, 0x002e0d59, 0x00f8aa2f, 0x00d8480e, 0x000eef78,
278 0x00c596ff, 0x00133189, 0x0033d3a8, 0x00e574de, 0x007217ea, 0x00a4b09c, 0x008452bd, 0x0052f5cb,
279 0x00f19f6e, 0x00273818, 0x0007da39, 0x00d17d4f, 0x00461e7b, 0x0090b90d, 0x00b05b2c, 0x0066fc5a,
280 0x007da399, 0x00ab04ef, 0x008be6ce, 0x005d41b8, 0x00ca228c, 0x001c85fa, 0x003c67db, 0x00eac0ad,
281 0x0049aa08, 0x009f0d7e, 0x00bfef5f, 0x00694829, 0x00fe2b1d, 0x00288c6b, 0x00086e4a, 0x00dec93c,
282 0x0015b0bb, 0x00c317cd, 0x00e3f5ec, 0x0035529a, 0x00a231ae, 0x007496d8, 0x005474f9, 0x0082d38f,
283 0x0021b92a, 0x00f71e5c, 0x00d7fc7d, 0x00015b0b, 0x0096383f, 0x00409f49, 0x00607d68, 0x00b6da1e,
284 0x0056c2ee, 0x00806598, 0x00a087b9, 0x007620cf, 0x00e143fb, 0x0037e48d, 0x001706ac, 0x00c1a1da,
285 0x0062cb7f, 0x00b46c09, 0x00948e28, 0x0042295e, 0x00d54a6a, 0x0003ed1c, 0x00230f3d, 0x00f5a84b,
286 0x003ed1cc, 0x00e876ba, 0x00c8949b, 0x001e33ed, 0x008950d9, 0x005ff7af, 0x007f158e, 0x00a9b2f8,
287 0x000ad85d, 0x00dc7f2b, 0x00fc9d0a, 0x002a3a7c, 0x00bd5948, 0x006bfe3e, 0x004b1c1f, 0x009dbb69,
288 0x0086e4aa, 0x005043dc, 0x0070a1fd, 0x00a6068b, 0x003165bf, 0x00e7c2c9, 0x00c720e8, 0x0011879e,
289 0x00b2ed3b, 0x00644a4d, 0x0044a86c, 0x00920f1a, 0x00056c2e, 0x00d3cb58, 0x00f32979, 0x00258e0f,
290 0x00eef788, 0x003850fe, 0x0018b2df, 0x00ce15a9, 0x0059769d, 0x008fd1eb, 0x00af33ca, 0x007994bc,
291 0x00dafe19, 0x000c596f, 0x002cbb4e, 0x00fa1c38, 0x006d7f0c, 0x00bbd87a, 0x009b3a5b, 0x004d9d2d
294 #define INIT_CRC24 0xffffff
296 static guint32 crc_calc(guint32 fcs, tvbuff_t *tvb, guint len)
300 cp = tvb_get_ptr(tvb, 0, len);
302 fcs = (fcs >> 8) ^ tbl_crc24[(fcs ^ *cp++) & 0xff];
312 /* Code to actually dissect the packets */
314 dissect_llcgprs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
316 guint8 addr_fld=0, sapi=0, ctrl_fld_fb=0, frame_format, tmp=0 ;
317 guint16 offset=0 , epm = 0, nu=0,ctrl_fld_ui_s=0,crc_start=0 ;
318 proto_item *ti, *addres_field_item, *ctrl_field_item, *ui_ti;
319 proto_tree *llcgprs_tree=NULL , *ad_f_tree =NULL, *ctrl_f_tree=NULL, *ui_tree=NULL;
322 guint32 fcs, fcs_calc;
323 fcs_status_t fcs_status;
325 /* MLT CHANGES - additional variables */
331 proto_item *uinfo_field = NULL;
332 proto_tree *uinfo_tree = NULL;
333 /* END MLT CHANGES */
335 if (check_col(pinfo->cinfo, COL_PROTOCOL))
337 col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-LLC");
340 addr_fld = tvb_get_guint8(tvb,offset);
345 if (check_col(pinfo->cinfo,COL_INFO))
347 col_add_str(pinfo->cinfo,COL_INFO,"Invalid packet - Protocol Discriminator bit is set to 1");
352 sapi = addr_fld & 0xF;
354 if (check_col(pinfo->cinfo, COL_INFO))
356 col_add_fstr(pinfo->cinfo, COL_INFO, "SAPI: %s", match_strval(sapi,sapi_abrv));
360 length = tvb_reported_length(tvb);
361 if (tvb_bytes_exist(tvb, 0, length) && length >= 3)
364 * We have all the packet data, including the full FCS,
365 * so we can compute the FCS.
367 * XXX - do we need to check the PM bit?
369 crc_start = length-3;
370 fcs_calc = crc_calc ( INIT_CRC24 , tvb, crc_start );
371 fcs_calc = ~fcs_calc;
372 fcs_calc &= 0xffffff;
374 fcs = tvb_get_letoh24(tvb, crc_start);
375 if ( fcs_calc == fcs )
377 fcs_status = FCS_VALID;
381 fcs_status = FCS_NOT_VALID;
386 /* We don't have enough data to compute the FCS. */
387 fcs_status = FCS_NOT_COMPUTED;
389 /* Squelch compiler warnings. */
395 /* In the interest of speed, if "tree" is NULL, don't do any work not
396 necessary to generate protocol tree items. */
401 ti = proto_tree_add_protocol_format(tree, proto_llcgprs, tvb, 0, -1,"MS-SGSN LLC (Mobile Station - Serving GPRS Support Node Logical Link Control) SAPI: %s", match_strval(sapi,sapi_t));
403 llcgprs_tree = proto_item_add_subtree(ti, ett_llcgprs);
405 /* add an item to the subtree, see section 1.6 for more information */
406 switch (fcs_status) {
409 proto_tree_add_text (llcgprs_tree, tvb, crc_start, 3,
410 "FCS: 0x%06x (correct)", fcs_calc&0xffffff);
414 proto_tree_add_text (llcgprs_tree, tvb,crc_start, 3,
415 "FCS: 0x%06x (incorrect, should be 0x%06x)", fcs, fcs_calc );
418 case FCS_NOT_COMPUTED:
419 break; /* FCS not present */
422 addres_field_item = proto_tree_add_uint_format(llcgprs_tree,hf_llcgprs_sapi,
423 tvb, 0,1, sapi, "Address field SAPI: %s", match_strval(sapi,sapi_abrv));
425 ad_f_tree = proto_item_add_subtree(addres_field_item, ett_llcgprs_adf);
426 proto_tree_add_boolean(ad_f_tree, hf_llcgprs_pd, tvb, 0, 1, addr_fld );
427 proto_tree_add_boolean(ad_f_tree, hf_llcgprs_cr, tvb, 0, 1, addr_fld );
428 proto_tree_add_uint(ad_f_tree, hf_llcgprs_sapib, tvb, 0, 1, addr_fld );
433 ctrl_fld_fb = tvb_get_guint8(tvb,offset);
434 if (ctrl_fld_fb < 0xC0)
436 frame_format = (ctrl_fld_fb < 0x80)? I_FORMAT : S_FORMAT;
440 frame_format = (ctrl_fld_fb < 0xe0 )? UI_FORMAT : U_FORMAT;
443 switch (frame_format)
446 if (check_col(pinfo->cinfo,COL_INFO))
448 col_append_str(pinfo->cinfo,COL_INFO, ", I, ");
451 /* MLT CHANGES - additional parsing code */
452 ns = tvb_get_ntohs(tvb, offset);
453 ns = (ns >> 4)& 0x01FF;
454 nr = ctrl_fld_ui_s = tvb_get_ntohs(tvb, offset + 1);
455 nr = (nr >> 2) & 0x01FF;
457 epm = ctrl_fld_ui_s & 0x3;
459 /* advance to either R Bitmap or Payload */
462 if (check_col(pinfo->cinfo, COL_INFO))
464 col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm, cr_formats_ipluss));
465 col_append_fstr(pinfo->cinfo, COL_INFO, ", N(S) = %u", ns);
466 col_append_fstr(pinfo->cinfo, COL_INFO, ", N(R) = %u", nr);
473 ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, (offset-3),
474 3,"Information format: %s: N(S) = %u, N(R) = %u",
475 match_strval(epm, cr_formats_ipluss), ns, nr);
476 ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
478 /* retrieve the second octet */
479 tmp = tvb_get_ntohs(tvb, (offset-3)) << 16;
480 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_ifmt, tvb, offset-3, 3, tmp);
481 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_ia, tvb, offset-3, 3, tmp);
482 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_izerobit, tvb, offset-3, 3, tmp);
485 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_isack_ns, tvb, offset-3, 3, tmp);
488 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_isack_nr, tvb, offset-3, 3, tmp);
489 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_isack_sfb, tvb, offset-3, 3, ctrl_fld_ui_s);
492 /* check to see if epm is SACK - meaning this is an ISACK frame */
497 k = kmask = tvb_get_guint8(tvb, offset);
500 /* advance past the k field */
503 /* the real value of k is actually k + 1 */
504 /* account for the off by one representation */
507 if (check_col(pinfo->cinfo, COL_INFO))
509 col_append_fstr(pinfo->cinfo, COL_INFO, ", k = %u", k);
514 guint8 loop_count = 0;
516 guint16 location = offset;
518 ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, (offset-1),
519 (k+1), "SACK FRAME: k = %u", k);
521 ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
522 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_kmask, tvb, offset-1, 1, kmask);
523 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_k, tvb, offset-1, 1, k);
525 /* display the R Bitmap */
526 for (loop_count = 0; loop_count < k; loop_count++)
528 r_byte = tvb_get_guint8(tvb, location);
529 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_rbyte, tvb, location, 1, r_byte);
534 /* step past the R Bitmap */
538 if ((sapi == SAPI_TOM2) || (sapi == SAPI_TOM8))
540 /* if SAPI is TOM do other parsing */
544 guint8 remaining_length = 0;
546 int loop_counter = 0;
548 tom_byte = tvb_get_guint8(tvb, offset);
549 remaining_length = (tom_byte >> 4) & 0x0F;
550 tom_pd = tom_byte & 0x0F;
552 ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset,
553 (crc_start-offset), "TOM Envelope - Protocol: %s",
554 match_strval(tom_pd, tompd_formats));
556 ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
558 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_rl, tvb, offset, 1, tom_byte);
559 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_pd, tvb, offset, 1, tom_byte);
561 /* step past the TOM header first byte */
564 /* TOM remaining length field value 0x0F is reserved for extension */
565 if (remaining_length != 0x0F)
567 /* parse the rest of the TOM header */
568 for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
570 tom_byte = tvb_get_guint8(tvb, offset);
572 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_header, tvb,
573 offset, 1, tom_byte);
575 /* step to the next byte */
579 remaining_length = crc_start - offset;
581 /* parse the TOM message capsule */
582 for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
584 tom_byte = tvb_get_guint8(tvb, offset);
586 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_data, tvb,
587 offset, 1, tom_byte);
589 /* step to the next byte */
597 /* otherwise - call a subdissector */
598 next_tvb = tvb_new_subset(tvb, offset, (crc_start-offset), -1);
599 if (!dissector_try_port(llcgprs_subdissector_table,sapi, next_tvb, pinfo, tree))
600 /* if no subdissector is found, call the data dissector */
602 call_dissector(data_handle, next_tvb, pinfo, tree);
605 /* END MLT CHANGES */
610 nu = ctrl_fld_ui_s = tvb_get_ntohs(tvb, offset);
612 epm = ctrl_fld_ui_s & 0x3;
613 nu = (nu >>2)&0x01FF;
615 if (frame_format == S_FORMAT)
618 if (check_col(pinfo->cinfo, COL_INFO))
620 col_append_str(pinfo->cinfo, COL_INFO, ", S, ");
621 col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm,cr_formats_ipluss));
622 col_append_fstr(pinfo->cinfo, COL_INFO, ", N(R) = %u", nu);
627 ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset-2, 2,
628 "Supervisory format: %s: N(R) = %u",
629 match_strval(epm,cr_formats_ipluss), nu);
631 ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
632 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_S_fmt, tvb, offset-2,
634 proto_tree_add_boolean(ctrl_f_tree, hf_llcgprs_As, tvb, offset-2,
637 /* MLT CHANGES - added spare bits */
638 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_sspare, tvb, offset-2,
640 /* END MLT CHANGES */
641 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_NR, tvb, offset-2,
643 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_sjsd, tvb, offset-2,
647 /* MLT CHANGES - additional parsing code to handle SACK */
648 if ((ctrl_fld_ui_s & 0x03) == 0x03)
649 /* It is a SACK frame */
651 /* TODO: length is fudged - it is not correct */
652 guint32 sack_length = crc_start - offset;
656 guint8 loop_count = 0;
658 guint16 location = offset;
660 ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset,
661 sack_length, "SACK FRAME: length = %u", sack_length);
663 /* display the R Bitmap */
664 for (loop_count = 0; loop_count < sack_length; loop_count++)
666 r_byte = tvb_get_guint8(tvb, location);
667 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_rbyte, tvb,
668 location, 1, r_byte);
673 /* step past the r bitmap */
674 offset += sack_length;
678 /* should parse the rest of the supervisory message based on type */
679 /* if SAPI is TOM do other parsing */
680 if ((sapi == SAPI_TOM2) || (sapi == SAPI_TOM8))
685 guint8 remaining_length = 0;
687 int loop_counter = 0;
689 tom_byte = tvb_get_guint8(tvb, offset);
690 remaining_length = (tom_byte >> 4) & 0x0F;
691 tom_pd = tom_byte & 0x0F;
693 ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset,
694 (crc_start-offset), "TOM Envelope - Protocol: %s",
695 match_strval(tom_pd, tompd_formats));
697 ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
699 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_rl, tvb, offset, 1, tom_byte);
700 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_pd, tvb, offset, 1, tom_byte);
702 /* step past the TOM header first byte */
705 /* TOM remaining length field value 0x0F is reserved for extension */
706 if (remaining_length != 0x0F)
708 /* parse the rest of the TOM header */
709 for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
711 tom_byte = tvb_get_guint8(tvb, offset);
713 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_header, tvb,
714 offset, 1, tom_byte);
716 /* step to the next byte */
720 /* Amount of frame left from offset to crc */
721 remaining_length = crc_start - offset;
723 /* parse the TOM message capsule */
724 for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
726 tom_byte = tvb_get_guint8(tvb, offset);
728 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_data, tvb,
729 offset, 1, tom_byte);
731 /* step to the next byte */
739 /* otherwise - call a subdissector */
740 next_tvb = tvb_new_subset(tvb, offset, (crc_start-offset), -1 );
741 if (!dissector_try_port(llcgprs_subdissector_table,sapi, next_tvb, pinfo, tree))
743 call_dissector(data_handle, next_tvb, pinfo, tree);
746 /* END MLT CHANGES */
751 if (check_col(pinfo->cinfo, COL_INFO))
753 col_append_str(pinfo->cinfo, COL_INFO, ", UI, ");
754 col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm, pme ));
755 col_append_fstr(pinfo->cinfo,COL_INFO, ", N(U) = %u", nu);
760 ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset-2,
761 2, "Unnumbered Information format - UI, N(U) = %u", nu);
762 ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_ctrlf);
764 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_U_fmt, tvb, offset-2,
766 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_sp_bits, tvb, offset-2,
768 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_NU, tvb, offset-2, 2,
770 proto_tree_add_boolean(ctrl_f_tree, hf_llcgprs_E_bit, tvb, offset-2,
772 proto_tree_add_boolean(ctrl_f_tree, hf_llcgprs_PM_bit, tvb, offset-2,
776 /* MLT CHANGES - TOM parsing added */
777 next_tvb = tvb_new_subset(tvb, offset, (crc_start-offset), -1);
779 if ((ignore_cipher_bit && (fcs_status == FCS_VALID)) || !(epm & 0x2))
781 /* Either we're ignoring the cipher bit
782 * (because the bit is set but the
783 * data is unciphered), and the data has
784 * a valid FCS, or the cipher
785 * bit isn't set (indicating that the
786 * data is unciphered). Try dissecting
787 * it with a subdissector. */
789 /* if SAPI is TOM do other parsing */
790 if ((sapi == SAPI_TOM2) || (sapi == SAPI_TOM8))
795 guint8 remaining_length = 0;
797 int loop_counter = 0;
799 tom_byte = tvb_get_guint8(tvb, offset);
800 remaining_length = (tom_byte >> 4) & 0x0F;
801 tom_pd = tom_byte & 0x0F;
803 ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset,
804 (crc_start-offset), "TOM Envelope - Protocol: %s",
805 match_strval(tom_pd, tompd_formats));
807 ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
809 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_rl, tvb, offset, 1, tom_byte);
810 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_pd, tvb, offset, 1, tom_byte);
812 /* step past the TOM header first byte */
815 /* TOM remaining length field value 0x0F is reserved for extension */
816 if (remaining_length != 0x0F)
818 /* parse the rest of the TOM header */
819 for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
821 tom_byte = tvb_get_guint8(tvb, offset);
823 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_header, tvb,
824 offset, 1, tom_byte);
826 /* step to the next byte */
830 /* Amount of frame left from offset to crc */
831 remaining_length = crc_start - offset;
833 /* parse the TOM message capsule */
834 for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
836 tom_byte = tvb_get_guint8(tvb, offset);
838 proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_data, tvb,
839 offset, 1, tom_byte);
841 /* step to the next byte */
849 /* otherwise - call a subdissector */
850 if (!dissector_try_port(llcgprs_subdissector_table, sapi, next_tvb, pinfo, tree))
852 call_dissector(data_handle, next_tvb, pinfo, tree);
858 /* ciphered information - just parse it as data */
859 call_dissector(data_handle, next_tvb, pinfo, tree);
862 /* END MLT CHANGES */
868 tmp = ctrl_fld_fb & 0xf;
870 if (check_col(pinfo->cinfo, COL_INFO))
872 col_append_str(pinfo->cinfo, COL_INFO, ", U, ");
873 col_append_str(pinfo->cinfo, COL_INFO,
874 val_to_str(tmp, cr_formats_unnumb,"Unknown/invalid code:%X"));
878 ui_ti = proto_tree_add_text(llcgprs_tree, tvb, (offset-1), (crc_start-1),
879 "Unnumbered frame: %s",
880 val_to_str(tmp,cr_formats_unnumb, "Unknown/invalid code:%X"));
882 ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
883 proto_tree_add_uint(ui_tree, hf_llcgprs_Un, tvb, (offset-1), 1, ctrl_fld_fb);
884 proto_tree_add_boolean(ui_tree, hf_llcgprs_PF, tvb, (offset-1), 1, ctrl_fld_fb);
885 proto_tree_add_uint(ui_tree, hf_llcgprs_ucom, tvb, (offset-1), 1, ctrl_fld_fb);
889 /* MLT CHANGES - parse rest of the message based on type (M Bits) */
890 m_bits = ctrl_fld_fb & 0x0F;
892 info_len = crc_start - offset;
899 /* These frames SHOULD NOT have an info field */
902 ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
903 "No Information Field");
904 ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
908 /* This frame MAY or MAY NOT have an info field */
909 /* Info field, if it exists, consists of XID parameters */
914 guint8 xid_param_len = 0;
915 guint16 location = offset;
919 int loop_counter = 0;
921 ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
922 "Information Field: Length = %u", info_len);
923 ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
925 while (location < (offset + info_len))
927 /* parse the XID parameters */
928 byte1 = tvb_get_guint8(tvb, location);
932 guint8 xid_param_len_high = 0;
933 guint8 xid_param_len_low = 0;
935 byte2 = tvb_get_guint8(tvb, location + 1);
937 /* XL bit is set - length is continued in second byte */
938 xid_param_len_high = byte1 & 0x03;
939 xid_param_len_low = byte2 & 0xFC;
941 /* bit shift the rest of the length */
942 xid_param_len_low = xid_param_len_low >> 2;
943 xid_param_len_low = xid_param_len_low & 0x3F;
945 xid_param_len_high = xid_param_len_high << 6;
946 xid_param_len_high = xid_param_len_high & 0xC0;
948 /* combine the two */
949 xid_param_len = xid_param_len_high | xid_param_len_low;
954 xid_param_len = byte1 & 0x3;
957 ending = location + xid_param_len;
961 uinfo_field = proto_tree_add_text(ui_tree, tvb, location,
962 (ending - 1), "XID Parameter Type: %s",
963 val_to_str(tmp, xid_param_type_str,"Reserved Type:%X"));
965 uinfo_tree = proto_item_add_subtree(uinfo_field, ett_ui);
966 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_xl, tvb,
968 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_type, tvb,
970 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len1, tvb,
974 /* length continued into byte 2 */
975 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len2, tvb,
977 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_spare, tvb,
980 /* be sure to account for the second byte of length */
985 for (loop_counter = 0; loop_counter < xid_param_len; loop_counter++)
987 /* grab the information in the XID param */
988 byte2 = tvb_get_guint8(tvb, location);
989 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_byte, tvb,
998 ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
999 "No Information Field");
1000 ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
1006 /* These frames do have info fields consisting of XID parameters */
1007 /* Info field consists of XID parameters */
1010 guint8 xid_param_len = 0;
1011 guint16 location = offset;
1015 int loop_counter = 0;
1017 ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
1018 "Information Field: Length = %u", info_len);
1019 ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
1021 while (location < (offset + info_len))
1023 /* parse the XID parameters */
1024 byte1 = tvb_get_guint8(tvb, location);
1028 guint8 xid_param_len_high = 0;
1029 guint8 xid_param_len_low = 0;
1031 byte2 = tvb_get_guint8(tvb, location + 1);
1033 /* XL bit is set - length is continued in second byte */
1034 xid_param_len_high = byte1 & 0x03;
1035 xid_param_len_low = byte2 & 0xFC;
1037 /* bit shift the rest of the length */
1038 xid_param_len_low = xid_param_len_low >> 2;
1039 xid_param_len_low = xid_param_len_low & 0x3F;
1041 xid_param_len_high = xid_param_len_high << 6;
1042 xid_param_len_high = xid_param_len_high & 0xC0;
1044 /* combine the two */
1045 xid_param_len = xid_param_len_high | xid_param_len_low;
1050 xid_param_len = byte1 & 0x3;
1053 ending = location + xid_param_len;
1058 if (( xid_param_len > 0 ) && ( xid_param_len <=4 ))
1060 unsigned long value = 0;
1062 for (i=1;i<=xid_param_len;i++) {
1064 value |= (unsigned long)tvb_get_guint8(tvb, location+i );
1066 uinfo_field = proto_tree_add_text(ui_tree, tvb, location, (ending - 1),
1067 "XID Parameter Type: %s - Value: %lu",
1068 val_to_str(tmp, xid_param_type_str,"Reserved Type:%X"),value);
1071 uinfo_field = proto_tree_add_text(ui_tree, tvb, location, (ending - 1),
1072 "XID Parameter Type: %s",
1073 val_to_str(tmp, xid_param_type_str,"Reserved Type:%X"));
1075 uinfo_tree = proto_item_add_subtree(uinfo_field, ett_ui);
1076 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_xl, tvb, location,
1078 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_type, tvb, location,
1080 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len1, tvb, location,
1084 /* length continued into byte 2 */
1085 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len2, tvb, location,
1087 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_spare, tvb, location,
1090 /* be sure to account for the second byte of length */
1095 for (loop_counter = 0; loop_counter < xid_param_len; loop_counter++)
1097 /* grab the information in the XID param */
1098 byte2 = tvb_get_guint8(tvb, location);
1099 proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_byte, tvb, location,
1108 /* This frame has a special format info field */
1111 guint32 fld_vars = 0;
1112 guint16 cf_byte = 0;
1113 int loop_counter = 0;
1116 ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
1117 "Information Field: Length = %u", info_len);
1118 ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
1120 uinfo_field = proto_tree_add_text(ui_tree, tvb, offset, 6,
1121 "Rejected Frame Control Field");
1122 uinfo_tree = proto_item_add_subtree(uinfo_field, ett_ui);
1125 for (loop_counter = 0; loop_counter < 3; loop_counter++)
1127 /* display the rejected frame control field */
1128 cf_byte = tvb_get_ntohs(tvb, location);
1129 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_cf, tvb, location,
1135 uinfo_field = proto_tree_add_text(ui_tree, tvb, location, 4,
1136 "Information Field Data");
1137 uinfo_tree = proto_item_add_subtree(uinfo_field, ett_ui);
1139 fld_vars = tvb_get_ntohl(tvb, location);
1140 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_spare, tvb, location,
1142 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_vs, tvb, location,
1144 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_vr, tvb, (location + 1),
1146 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_cr, tvb, (location + 2),
1148 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w4, tvb, (location + 3),
1150 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w3, tvb, (location + 3),
1152 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w2, tvb, (location + 3),
1154 proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w1, tvb, (location + 3),
1161 /* END MLT CHANGES */
1167 /* Register the protocol with Wireshark */
1168 /* this format is require because a script is used to build the C function */
1169 /* that calls all the protocol registration. */
1172 proto_register_llcgprs(void)
1174 /* Setup list of header fields See Section 1.6.1 for details*/
1175 static hf_register_info hf[] = {
1177 { "SAPI", "llcgprs.sapi", FT_UINT8, BASE_DEC, VALS(sapi_abrv), 0x0,"Service Access Point Identifier", HFILL }},
1179 { "Protocol Discriminator_bit", "llcgprs.pd", FT_BOOLEAN,8, TFS(&pd_bit), 0x80, " Protocol Discriminator bit (should be 0)", HFILL }},
1181 { "Supervisory function bits","llcgprs.s1s2", FT_UINT16, BASE_HEX, VALS(cr_formats_ipluss),0x3, "Supervisory functions bits",HFILL }},
1183 { "Command/Response bit", "llcgprs.cr", FT_BOOLEAN, 8, TFS(&cr_bit), 0x40, " Command/Response bit", HFILL}},
1184 { &hf_llcgprs_sapib,
1185 { "SAPI", "llcgprs.sapib", FT_UINT8, BASE_DEC , VALS(sapi_t), 0xf, "Service Access Point Identifier ",HFILL }},
1186 { &hf_llcgprs_U_fmt,
1187 { "UI format", "llcgprs.ui", FT_UINT16, BASE_HEX, NULL, UI_MASK_FMT, "UI frame format",HFILL}},
1189 { "U format", "llcgprs.u", FT_UINT8, BASE_DEC, NULL, 0xe0, " U frame format", HFILL}},
1190 { &hf_llcgprs_sp_bits,
1191 { "Spare bits", "llcgprs.ui_sp_bit", FT_UINT16, BASE_HEX, NULL, UI_MASK_SPB, "Spare bits", HFILL}},
1193 { "N(U)", "llcgprs.nu", FT_UINT16, BASE_DEC, NULL, UI_MASK_NU, "Transmited unconfirmed sequence number", HFILL}},
1194 { &hf_llcgprs_E_bit,
1195 { "E bit", "llcgprs.e", FT_BOOLEAN, 16, TFS(&e_bit), UI_MASK_E,"Encryption mode bit",HFILL }},
1196 { &hf_llcgprs_PM_bit,
1197 { "PM bit", "llcgprs.pm", FT_BOOLEAN, 16, TFS(&pm_bit), UI_MASK_PM, "Protected mode bit",HFILL}},
1199 { "Ackn request bit", "llcgprs.as", FT_BOOLEAN, 16, TFS(&a_bit), 0x2000 ,"Acknowledgement request bit A", HFILL}},
1201 { "P/F bit", "llcgprs.pf", FT_BOOLEAN, 8, NULL, 0x10,"Poll /Finall bit", HFILL}},
1203 { "Command/Response","llcgprs.ucom", FT_UINT8, BASE_HEX, VALS(cr_formats_unnumb),0xf,"Commands and Responses",HFILL }},
1205 { "Receive sequence number", "llcgprs.nr",FT_UINT16, BASE_DEC, NULL, UI_MASK_NU,"Receive sequence number N(R)",HFILL }},
1207 { "S format", "llcgprs.s", FT_UINT16, BASE_DEC, NULL, 0xc000,"Supervisory format S", HFILL}},
1208 /* MLT CHANGES - additional masks*/
1210 { "ignored", "llcgprs.kmask", FT_UINT8, BASE_DEC, NULL, 0xE0, "ignored", HFILL}},
1212 { "k", "llcgprs.k", FT_UINT8, BASE_DEC, NULL, 0x1F, "k counter", HFILL}},
1213 {&hf_llcgprs_isack_ns,
1214 { "N(S)", "llcgprs.sackns", FT_UINT24, BASE_DEC, NULL, 0x1FF000, "N(S)", HFILL}},
1215 {&hf_llcgprs_isack_nr,
1216 { "N(R)", "llcgprs.sacknr", FT_UINT24, BASE_DEC, NULL, 0x0007FC, "N(R)", HFILL}},
1217 {&hf_llcgprs_isack_sfb,
1218 { "Supervisory function bits","llcgprs.sacksfb", FT_UINT24, BASE_HEX, VALS(cr_formats_ipluss),0x000003, "Supervisory functions bits",HFILL }},
1220 { "I Format", "llcgprs.ifmt", FT_UINT24, BASE_DEC, NULL, 0x800000, "I Fmt Bit", HFILL}},
1222 { "Ack Bit", "llcgprs.ia", FT_UINT24, BASE_DEC, NULL, 0x400000, "I A Bit", HFILL}},
1223 {&hf_llcgprs_izerobit,
1224 { "Spare", "llcgprs.iignore", FT_UINT24, BASE_DEC, NULL, 0x200000, "Ignore Bit", HFILL}},
1225 {&hf_llcgprs_sspare,
1226 { "Spare", "llcgprs.sspare", FT_UINT16, BASE_DEC, NULL, 0x1800, "Ignore Bit", HFILL}},
1228 { "R Bitmap Bits","llcgprs.sackrbits", FT_UINT8, BASE_HEX, NULL, 0xFF, "R Bitmap", HFILL}},
1229 /* XID Parameter Parsing Info */
1230 {&hf_llcgprs_xid_xl,
1231 { "XL Bit","llcgprs.xidxl", FT_UINT8, BASE_HEX, NULL, 0x80, "XL", HFILL}},
1232 {&hf_llcgprs_xid_type,
1233 { "Type","llcgprs.xidtype", FT_UINT8, BASE_DEC, NULL, 0x7C, "Type", HFILL}},
1234 {&hf_llcgprs_xid_len1,
1235 { "Length","llcgprs.xidlen1", FT_UINT8, BASE_DEC, NULL, 0x03, "Len", HFILL}},
1236 {&hf_llcgprs_xid_len2,
1237 { "Length continued","llcgprs.xidlen2", FT_UINT8, BASE_DEC, NULL, 0xFC, "Len", HFILL}},
1238 {&hf_llcgprs_xid_spare,
1239 { "Spare","llcgprs.xidspare", FT_UINT8, BASE_HEX, NULL, 0x03, "Ignore", HFILL}},
1240 {&hf_llcgprs_xid_byte,
1241 { "Parameter Byte","llcgprs.xidbyte", FT_UINT8, BASE_HEX, NULL, 0xFF, "Data", HFILL}},
1242 /* FRMR Parsing Information */
1243 {&hf_llcgprs_frmr_cf,
1244 { "Control Field Octet","llcgprs.frmrrfcf", FT_UINT16, BASE_DEC, NULL,
1245 0xFFFF, "Rejected Frame CF", HFILL}},
1246 {&hf_llcgprs_frmr_spare,
1247 { "X","llcgprs.frmrspare", FT_UINT32, BASE_HEX, NULL, 0xF00400F0,
1249 {&hf_llcgprs_frmr_vs,
1250 { "V(S)","llcgprs.frmrvs", FT_UINT32, BASE_DEC, NULL, 0x0FF80000,
1251 "Current send state variable", HFILL}},
1252 {&hf_llcgprs_frmr_vr,
1253 { "V(R)","llcgprs.frmrvr", FT_UINT32, BASE_DEC, NULL, 0x0003FE00,
1254 "Current receive state variable", HFILL}},
1255 {&hf_llcgprs_frmr_cr,
1256 { "C/R","llcgprs.frmrcr", FT_UINT32, BASE_DEC, NULL, 0x00000100,
1257 "Rejected command response", HFILL}},
1258 {&hf_llcgprs_frmr_w4,
1259 { "W4","llcgprs.frmrw4", FT_UINT32, BASE_DEC, NULL, 0x00000008,
1260 "LLE was in ABM when rejecting", HFILL}},
1261 {&hf_llcgprs_frmr_w3,
1262 { "W3","llcgprs.frmrw3", FT_UINT32, BASE_DEC, NULL, 0x00000004,
1263 "Undefined control field", HFILL}},
1264 {&hf_llcgprs_frmr_w2,
1265 { "W2","llcgprs.frmrw2", FT_UINT32, BASE_DEC, NULL, 0x00000002,
1266 "Info exceeded N201", HFILL}},
1267 {&hf_llcgprs_frmr_w1,
1268 { "W1","llcgprs.frmrw1", FT_UINT32, BASE_DEC, NULL, 0x00000001,
1269 "Invalid - info not permitted", HFILL}},
1270 {&hf_llcgprs_tom_rl,
1271 { "Remaining Length of TOM Protocol Header","llcgprs.romrl", FT_UINT8,
1272 BASE_DEC, NULL, 0xF0, "RL", HFILL}},
1273 {&hf_llcgprs_tom_pd,
1274 { "TOM Protocol Discriminator","llcgprs.tompd", FT_UINT8, BASE_HEX,
1275 NULL, 0x0F, "TPD", HFILL}},
1276 {&hf_llcgprs_tom_header,
1277 { "TOM Header Byte","llcgprs.tomhead", FT_UINT8, BASE_HEX, NULL, 0xFF,
1279 {&hf_llcgprs_tom_data,
1280 { "TOM Message Capsule Byte","llcgprs.tomdata", FT_UINT8, BASE_HEX, NULL,
1281 0xFF, "tdb", HFILL}},
1282 /* END MLT CHANGES */
1285 /* Setup protocol subtree array */
1286 static gint *ett[] = {
1291 &ett_llcgprs_sframe,
1294 module_t *llcgprs_module;
1296 /* Register the protocol name and description */
1297 proto_llcgprs = proto_register_protocol("Logical Link Control GPRS",
1298 "GPRS-LLC", "llcgprs");
1299 llcgprs_subdissector_table = register_dissector_table("llcgprs.sapi","GPRS LLC SAPI", FT_UINT8,BASE_HEX);
1300 /* Required function calls to register the header fields and subtrees used */
1301 proto_register_field_array(proto_llcgprs, hf, array_length(hf));
1302 proto_register_subtree_array(ett, array_length(ett));
1303 register_dissector("llcgprs", dissect_llcgprs, proto_llcgprs);
1305 llcgprs_module = prefs_register_protocol ( proto_llcgprs, NULL );
1306 prefs_register_bool_preference ( llcgprs_module, "autodetect_cipher_bit",
1307 "Autodetect cipher bit",
1308 "Whether to autodetect the cipher bit (because it might be set on unciphered data)",
1309 &ignore_cipher_bit );
1313 /* If this dissector uses sub-dissector registration add a registration routine. */
1314 /* This format is required because a script is used to find these routines and */
1315 /* create the code that calls these routines. */
1317 proto_reg_handoff_llcgprs(void)
1319 dissector_handle_t gprs_llc_handle;
1321 /* make sure that the top level can call this dissector */
1322 gprs_llc_handle = create_dissector_handle(dissect_llcgprs, proto_llcgprs);
1323 dissector_add("wtap_encap", WTAP_ENCAP_GPRS_LLC, gprs_llc_handle);
1325 data_handle = find_dissector("data");