aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-gprs-llc.c
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2005-08-05 19:16:29 +0000
committerAnders Broman <anders.broman@ericsson.com>2005-08-05 19:16:29 +0000
commit6ced262fdf8c8ea8df54b23f8c71361c19349771 (patch)
treea4558c6098a564aacce6529363f2a112accc8b06 /epan/dissectors/packet-gprs-llc.c
parent74a75d72fe65e59e075409b988bb436acfc1534e (diff)
From THORNTON, MATT
Some changes that I made to flesh out GPRS message parsing. More information is displayed about the various frame formats. I have also added some code to parse XID parameters in the U frame. I have also fixed a couple of display bugs in the GSM and GPRS LLC parser. svn path=/trunk/; revision=15224
Diffstat (limited to 'epan/dissectors/packet-gprs-llc.c')
-rw-r--r--epan/dissectors/packet-gprs-llc.c1045
1 files changed, 926 insertions, 119 deletions
diff --git a/epan/dissectors/packet-gprs-llc.c b/epan/dissectors/packet-gprs-llc.c
index 00857e2c91..ed21f1a0cf 100644
--- a/epan/dissectors/packet-gprs-llc.c
+++ b/epan/dissectors/packet-gprs-llc.c
@@ -39,9 +39,7 @@
#include <epan/packet.h>
#include "prefs.h"
-/*
-#include "packet-llcgprs.h"
-*/
+
#define I_FORMAT 1
#define S_FORMAT 2
#define UI_FORMAT 3
@@ -72,8 +70,58 @@ static int hf_llcgprs_PF = -1;
static int hf_llcgprs_S_fmt = -1;
static int hf_llcgprs_NR = -1;
static int hf_llcgprs_sjsd = -1;
-/*static int hf_llcgprs_pd = -1;
-*/
+/* MLT CHANGES - Additional display masks */
+static int hf_llcgprs_k = -1;
+static int hf_llcgprs_isack_ns = -1;
+static int hf_llcgprs_isack_nr = -1;
+static int hf_llcgprs_isack_sfb = -1;
+static int hf_llcgprs_rbyte = -1;
+static int hf_llcgprs_kmask = -1;
+static int hf_llcgprs_ifmt = -1;
+static int hf_llcgprs_ia = -1;
+static int hf_llcgprs_izerobit = -1;
+static int hf_llcgprs_sspare = -1;
+static int hf_llcgprs_xid_xl = -1;
+static int hf_llcgprs_xid_type = -1;
+static int hf_llcgprs_xid_len1 = -1;
+static int hf_llcgprs_xid_len2 = -1;
+static int hf_llcgprs_xid_spare = -1;
+static int hf_llcgprs_xid_byte = -1;
+static int hf_llcgprs_frmr_cf = -1;
+static int hf_llcgprs_frmr_spare = -1;
+static int hf_llcgprs_frmr_vs = -1;
+static int hf_llcgprs_frmr_vr = -1;
+static int hf_llcgprs_frmr_cr = -1;
+static int hf_llcgprs_frmr_w4 = -1;
+static int hf_llcgprs_frmr_w3 = -1;
+static int hf_llcgprs_frmr_w2 = -1;
+static int hf_llcgprs_frmr_w1 = -1;
+static int hf_llcgprs_tom_rl = -1;
+static int hf_llcgprs_tom_pd = -1;
+static int hf_llcgprs_tom_header = -1;
+static int hf_llcgprs_tom_data = -1;
+
+/* Unnumbered Commands and Responses (U Frames) */
+#define U_DM 0x01
+#define U_DISC 0x04
+#define U_UA 0x06
+#define U_SABM 0x07
+#define U_FRMR 0x08
+#define U_XID 0x0B
+#define U_NULL 0x00
+
+/* SAPI value constants */
+#define SAPI_LLGMM 0x01
+#define SAPI_TOM2 0x02
+#define SAPI_LL3 0x03
+#define SAPI_LL5 0x05
+#define SAPI_LLSMS 0x07
+#define SAPI_TOM8 0x08
+#define SAPI_LL9 0x09
+#define SAPI_LL11 0x0B
+
+/* END MLT CHANGES */
+
/* Initialize the subtree pointers */
static gint ett_llcgprs = -1;
static gint ett_llcgprs_adf = -1;
@@ -107,23 +155,22 @@ static const value_string sapi_t[] = {
};
static const value_string sapi_abrv[] = {
- { 0, "0"},
+ { 0, "Reserved 0"},
{ 1, "LLGMM" },
{ 2, "TOM2" },
{ 3, "LL3"},
- { 4, "4" },
+ { 4, "Reserved 4" },
{ 5, "LL5" },
- { 6, "6" },
+ { 6, "Reserved 6" },
{ 7, "LLSMS" },
{ 8, "TOM8" },
{ 9, "LL9" },
- { 10, "10" },
+ { 10, "Reserved 10" },
{ 11, "LL11" },
- { 12, "12" },
- { 13, "13" },
- { 14, "14" },
- { 15, "15" },
- { 0, NULL },
+ { 12, "Reserved 12" },
+ { 13, "Reserved 13" },
+ { 14, "Reserved 14" },
+ { 15, "Reserved 15" },
};
static const true_false_string a_bit = {
"To solicit an acknowledgement from the peer LLE. ",
@@ -155,6 +202,43 @@ static const value_string pme[] = {
{ 0, NULL},
};
+/* MLT CHANGES - adding XID parameter types & TOM protocols */
+static const value_string xid_param_type_str[] = {
+ {0x0, "Version (LLC version number)"},
+ {0x1, "IOV-UI (ciphering Input offset value for UI frames)"},
+ {0x2, "IOV-I (ciphering Input offset value for I frames)"},
+ {0x3, "T200 (retransmission timeout)"},
+ {0x4, "N200 (max number of retransmissions)"},
+ {0x5, "N201-U (max info field length for U and UI frames)"},
+ {0x6, "N201-I (max info field length for I frames)"},
+ {0x7, "mD (I frame buffer size in the DL direction)"},
+ {0x8, "mU (I frame buffer size in the UL direction)"},
+ {0x9, "kD (window size in the DL direction)"},
+ {0xA, "kU (window size in the UL direction)"},
+ {0xB, "Layer-3 Parameters"},
+ {0xC, "Reset"},
+};
+
+static const value_string tompd_formats[] = {
+ {0x0, "Not specified"},
+ {0x1, "TIA/EIA-136"},
+ {0x2, "Reserved value 2"},
+ {0x3, "Reserved value 3"},
+ {0x4, "Reserved value 4"},
+ {0x5, "Reserved value 5"},
+ {0x6, "Reserved value 6"},
+ {0x7, "Reserved value 7"},
+ {0x8, "Reserved value 8"},
+ {0x9, "Reserved value 9"},
+ {0xA, "Reserved value 10"},
+ {0xB, "Reserved value 11"},
+ {0xC, "Reserved value 12"},
+ {0xD, "Reserved value 13"},
+ {0xE, "Reserved value 14"},
+ {0xF, "Reserved for extension"},
+};
+/* END MLT CHANGES */
+
static const value_string cr_formats_unnumb[]= {
{ 0x1, "DM-response" },
{ 0x4, "DISC-command" },
@@ -239,98 +323,287 @@ dissect_llcgprs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
guint32 fcs, fcs_calc;
fcs_status_t fcs_status;
+ /* MLT CHANGES - additional variables */
+ guint16 ns = 0;
+ guint16 nr = 0;
+ guint8 k = 0;
+ guint8 m_bits = 0;
+ guint8 info_len = 0;
+ proto_item *uinfo_field = NULL;
+ proto_tree *uinfo_tree = NULL;
+ /* END MLT CHANGES */
+
if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-LLC");
+ }
- addr_fld = tvb_get_guint8(tvb,offset);
+ addr_fld = tvb_get_guint8(tvb,offset);
offset++;
- if (addr_fld > 128 ) {
+
+ if (addr_fld > 128 )
+ {
if (check_col(pinfo->cinfo,COL_INFO))
+ {
col_add_str(pinfo->cinfo,COL_INFO,"Invalid packet - Protocol Discriminator bit is set to 1");
+ }
return;
}
- sapi = addr_fld & 0xF;
+
+ sapi = addr_fld & 0xF;
+
if (check_col(pinfo->cinfo, COL_INFO))
+ {
col_add_fstr(pinfo->cinfo, COL_INFO, "SAPI: %s", match_strval(sapi,sapi_abrv));
+ }
length = tvb_reported_length(tvb);
- if (tvb_bytes_exist(tvb, 0, length) && length >= 3) {
+ if (tvb_bytes_exist(tvb, 0, length) && length >= 3)
+ {
/*
* We have all the packet data, including the full FCS,
* so we can compute the FCS.
*
* XXX - do we need to check the PM bit?
*/
- crc_start = length-3;
+ crc_start = length-3;
fcs_calc = crc_calc ( INIT_CRC24 , tvb, crc_start );
fcs_calc = ~fcs_calc;
fcs_calc &= 0xffffff;
fcs = tvb_get_letoh24(tvb, crc_start);
if ( fcs_calc == fcs )
+ {
fcs_status = FCS_VALID;
+ }
else
+ {
fcs_status = FCS_NOT_VALID;
- } else {
- /*
- * We don't have enough data to compute the FCS.
- */
+ }
+ }
+ else
+ {
+ /* We don't have enough data to compute the FCS. */
fcs_status = FCS_NOT_COMPUTED;
- /*
- * Squelch compiler warnings.
- */
+ /* Squelch compiler warnings. */
fcs = 0;
fcs_calc = 0;
crc_start = 0;
}
-/* In the interest of speed, if "tree" is NULL, don't do any work not
- necessary to generate protocol tree items. */
- if (tree) {
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+
+ if (tree)
+ {
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));
llcgprs_tree = proto_item_add_subtree(ti, ett_llcgprs);
-/* add an item to the subtree, see section 1.6 for more information */
- switch ( fcs_status ) {
+ /* add an item to the subtree, see section 1.6 for more information */
+ switch (fcs_status) {
case FCS_VALID:
- proto_tree_add_text ( llcgprs_tree , tvb , crc_start , 3 , "FCS: 0x%06x [correct]" , fcs_calc&0xffffff );
+ proto_tree_add_text (llcgprs_tree, tvb, crc_start, 3,
+ "FCS: 0x%06x (correct)", fcs_calc&0xffffff);
break;
case FCS_NOT_VALID:
- proto_tree_add_text ( llcgprs_tree , tvb , crc_start , 3 , "FCS: 0x%06x [incorrect, should be 0x%06x]",
- fcs, fcs_calc );
+ proto_tree_add_text (llcgprs_tree, tvb,crc_start, 3,
+ "FCS: 0x%06x (incorrect, should be 0x%06x)", fcs, fcs_calc );
break;
case FCS_NOT_COMPUTED:
break; /* FCS not present */
}
+
addres_field_item = proto_tree_add_uint_format(llcgprs_tree,hf_llcgprs_sapi,
tvb, 0,1, sapi, "Address field SAPI: %s", match_strval(sapi,sapi_abrv));
+
ad_f_tree = proto_item_add_subtree(addres_field_item, ett_llcgprs_adf);
- proto_tree_add_boolean(ad_f_tree, hf_llcgprs_pd, tvb,0,1, addr_fld );
- proto_tree_add_boolean(ad_f_tree, hf_llcgprs_cr, tvb,0,1, addr_fld );
- proto_tree_add_uint(ad_f_tree, hf_llcgprs_sapib, tvb, 0, 1, addr_fld );
+ proto_tree_add_boolean(ad_f_tree, hf_llcgprs_pd, tvb, 0, 1, addr_fld );
+ proto_tree_add_boolean(ad_f_tree, hf_llcgprs_cr, tvb, 0, 1, addr_fld );
+ proto_tree_add_uint(ad_f_tree, hf_llcgprs_sapib, tvb, 0, 1, addr_fld );
}
ctrl_fld_fb = tvb_get_guint8(tvb,offset);
- if ( ctrl_fld_fb < 0xc0 ){
- frame_format = ( ctrl_fld_fb < 0x80)? I_FORMAT : S_FORMAT;
+ if (ctrl_fld_fb < 0xC0)
+ {
+ frame_format = (ctrl_fld_fb < 0x80)? I_FORMAT : S_FORMAT;
}
- else {
- frame_format = ( ctrl_fld_fb < 0xe0 )? UI_FORMAT : U_FORMAT;
+ else
+ {
+ frame_format = (ctrl_fld_fb < 0xe0 )? UI_FORMAT : U_FORMAT;
}
- switch (frame_format){
+
+ switch (frame_format)
+ {
case I_FORMAT:
- if (check_col(pinfo->cinfo,COL_INFO)){
- col_append_str(pinfo->cinfo,COL_INFO, ", I");
+ if (check_col(pinfo->cinfo,COL_INFO))
+ {
+ col_append_str(pinfo->cinfo,COL_INFO, ", I, ");
+ }
+
+ /* MLT CHANGES - additional parsing code */
+ ns = tvb_get_ntohs(tvb, offset);
+ ns = (ns >> 4)& 0x01FF;
+ nr = ctrl_fld_ui_s = tvb_get_ntohs(tvb, offset + 1);
+ nr = (nr >> 2) & 0x01FF;
+
+ epm = ctrl_fld_ui_s & 0x3;
+
+ /* advance to either R Bitmap or Payload */
+ offset += 3;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm, cr_formats_ipluss));
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", N(S) = %u", ns);
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", N(R) = %u", nr);
+ }
+
+ if (tree)
+ {
+ guint32 tmp;
+
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, (offset-3),
+ 3,"Information format: %s: N(S) = %u, N(R) = %u",
+ match_strval(epm, cr_formats_ipluss), ns, nr);
+ ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
+
+ /* retrieve the second octet */
+ tmp = tvb_get_ntohs(tvb, (offset-3)) << 16;
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_ifmt, tvb, offset-3, 3, tmp);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_ia, tvb, offset-3, 3, tmp);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_izerobit, tvb, offset-3, 3, tmp);
+
+ tmp = ns << 12;
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_isack_ns, tvb, offset-3, 3, tmp);
+
+ tmp = nr << 2;
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_isack_nr, tvb, offset-3, 3, tmp);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_isack_sfb, tvb, offset-3, 3, ctrl_fld_ui_s);
}
+
+ /* check to see if epm is SACK - meaning this is an ISACK frame */
+ if (epm == 0x03)
+ {
+ guint8 kmask;
+ /* SACK Frame */
+ k = kmask = tvb_get_guint8(tvb, offset);
+ k = k & 0x1F;
+
+ /* advance past the k field */
+ offset++;
+
+ /* the real value of k is actually k + 1 */
+ /* account for the off by one representation */
+ k++;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", k = %u", k);
+ }
+
+ if (tree)
+ {
+ guint8 loop_count = 0;
+ guint8 r_byte = 0;
+ guint16 location = offset;
+
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, (offset-1),
+ (k+1), "SACK FRAME: k = %u", k);
+
+ ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_kmask, tvb, offset-1, 1, kmask);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_k, tvb, offset-1, 1, k);
+
+ /* display the R Bitmap */
+ for (loop_count = 0; loop_count < k; loop_count++)
+ {
+ r_byte = tvb_get_guint8(tvb, location);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_rbyte, tvb, location, 1, r_byte);
+ location++;
+ }
+ }
+
+ /* step past the R Bitmap */
+ offset += k;
+ }
+
+ if ((sapi == SAPI_TOM2) || (sapi == SAPI_TOM8))
+ {
+ /* if SAPI is TOM do other parsing */
+ if (tree)
+ {
+ guint8 tom_byte = 0;
+ guint8 remaining_length = 0;
+ guint8 tom_pd = 0;
+ int loop_counter = 0;
+
+ tom_byte = tvb_get_guint8(tvb, offset);
+ remaining_length = (tom_byte >> 4) & 0x0F;
+ tom_pd = tom_byte & 0x0F;
+
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset,
+ (crc_start-offset), "TOM Envelope - Protocol: %s",
+ match_strval(tom_pd, tompd_formats));
+
+ ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_rl, tvb, offset, 1, tom_byte);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_pd, tvb, offset, 1, tom_byte);
+
+ /* step past the TOM header first byte */
+ offset++;
+
+ /* TOM remaining length field value 0x0F is reserved for extension */
+ if (remaining_length != 0x0F)
+ {
+ /* parse the rest of the TOM header */
+ for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
+ {
+ tom_byte = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_header, tvb,
+ offset, 1, tom_byte);
+
+ /* step to the next byte */
+ offset++;
+ }
+
+ remaining_length = crc_start - offset;
+
+ /* parse the TOM message capsule */
+ for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
+ {
+ tom_byte = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_data, tvb,
+ offset, 1, tom_byte);
+
+ /* step to the next byte */
+ offset++;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* otherwise - call a subdissector */
+ next_tvb = tvb_new_subset(tvb, offset, (crc_start-offset), -1);
+ if (!dissector_try_port(llcgprs_subdissector_table,sapi, next_tvb, pinfo, tree))
+ /* if no subdissector is found, call the data dissector */
+ {
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ }
+ /* END MLT CHANGES */
break;
case S_FORMAT:
@@ -339,98 +612,552 @@ dissect_llcgprs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset +=2;
epm = ctrl_fld_ui_s & 0x3;
nu = (nu >>2)&0x01FF;
- if (frame_format == S_FORMAT){
- if (check_col(pinfo->cinfo, COL_INFO)){
- col_append_str(pinfo->cinfo, COL_INFO, ", S, ");
- col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm,cr_formats_ipluss));
- col_append_fstr(pinfo->cinfo, COL_INFO, ", N(R) = %u", nu);
- }
- if (tree){
- ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset-2,2,"Supervisory format: %s: N(R) = %u",match_strval(epm,cr_formats_ipluss), nu);
- ctrl_f_tree = proto_item_add_subtree( ctrl_field_item, ett_llcgprs_sframe);
- proto_tree_add_uint( ctrl_f_tree, hf_llcgprs_S_fmt, tvb, offset-2,2, ctrl_fld_ui_s );
- proto_tree_add_boolean( ctrl_f_tree, hf_llcgprs_As, tvb, offset-2, 2, ctrl_fld_ui_s );
- proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_NR, tvb, offset-2, 2, ctrl_fld_ui_s );
- proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_sjsd, tvb, offset-2, 2, ctrl_fld_ui_s );
- }
- }else{
-/*UI format*/
- if (check_col(pinfo->cinfo, COL_INFO)) {
- col_append_str(pinfo->cinfo, COL_INFO, ", UI, ");
- col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm, pme ));
- col_append_fstr(pinfo->cinfo,COL_INFO, ", N(U) = %u", nu);
- }
- if (tree){
- ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset-2, 2, "Unnumbered Information format - UI, N(U) = %u", nu);
- ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_ctrlf);
- proto_tree_add_uint( ctrl_f_tree, hf_llcgprs_U_fmt, tvb, offset-2, 2, ctrl_fld_ui_s);
- proto_tree_add_uint( ctrl_f_tree, hf_llcgprs_sp_bits, tvb, offset-2,2,ctrl_fld_ui_s);
- proto_tree_add_uint( ctrl_f_tree, hf_llcgprs_NU, tvb, offset-2, 2, ctrl_fld_ui_s);
- proto_tree_add_boolean( ctrl_f_tree, hf_llcgprs_E_bit, tvb, offset-2,2,ctrl_fld_ui_s);
- proto_tree_add_boolean( ctrl_f_tree, hf_llcgprs_PM_bit, tvb, offset-2,2,ctrl_fld_ui_s);
- }
+ if (frame_format == S_FORMAT)
+ {
+/* S format */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", S, ");
+ col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm,cr_formats_ipluss));
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", N(R) = %u", nu);
+ }
- next_tvb = tvb_new_subset(tvb, offset,crc_start-3, -1 );
- if ((ignore_cipher_bit && (fcs_status == FCS_VALID)) || !(epm & 0x2)){
- /*
- * Either we're ignoring the cipher bit
- * (because the bit is set but the
- * data is unciphered), and the data has
- * a valid FCS, or the cipher
- * bit isn't set (indicating that the
- * data is unciphered). Try dissecting
- * it with a subdissector.
- */
- if (!dissector_try_port(llcgprs_subdissector_table,sapi, next_tvb, pinfo, tree))
- call_dissector(data_handle, next_tvb, pinfo, tree);
- }
- else call_dissector(data_handle, next_tvb, pinfo, tree);
+ if (tree)
+ {
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset-2, 2,
+ "Supervisory format: %s: N(R) = %u",
+ match_strval(epm,cr_formats_ipluss), nu);
+
+ ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_S_fmt, tvb, offset-2,
+ 2, ctrl_fld_ui_s);
+ proto_tree_add_boolean(ctrl_f_tree, hf_llcgprs_As, tvb, offset-2,
+ 2, ctrl_fld_ui_s);
+
+ /* MLT CHANGES - added spare bits */
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_sspare, tvb, offset-2,
+ 2, ctrl_fld_ui_s);
+ /* END MLT CHANGES */
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_NR, tvb, offset-2,
+ 2, ctrl_fld_ui_s);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_sjsd, tvb, offset-2,
+ 2, ctrl_fld_ui_s);
+ }
+
+ /* MLT CHANGES - additional parsing code to handle SACK */
+ if ((ctrl_fld_ui_s & 0x03) == 0x03)
+ /* It is a SACK frame */
+ {
+ /* TODO: length is fudged - it is not correct */
+ guint32 sack_length = crc_start - offset;
+
+ if (tree)
+ {
+ guint8 loop_count = 0;
+ guint8 r_byte = 0;
+ guint16 location = offset;
+
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset,
+ sack_length, "SACK FRAME: length = %u", sack_length);
+
+ /* display the R Bitmap */
+ for (loop_count = 0; loop_count < sack_length; loop_count++)
+ {
+ r_byte = tvb_get_guint8(tvb, location);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_rbyte, tvb,
+ location, 1, r_byte);
+
+ location++;
+ }
+
+ /* step past the r bitmap */
+ offset += sack_length;
+ }
+ }
+
+ /* should parse the rest of the supervisory message based on type */
+ /* if SAPI is TOM do other parsing */
+ if ((sapi == SAPI_TOM2) || (sapi == SAPI_TOM8))
+ {
+ if (tree)
+ {
+ guint8 tom_byte = 0;
+ guint8 remaining_length = 0;
+ guint8 tom_pd = 0;
+ int loop_counter = 0;
+
+ tom_byte = tvb_get_guint8(tvb, offset);
+ remaining_length = (tom_byte >> 4) & 0x0F;
+ tom_pd = tom_byte & 0x0F;
+
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset,
+ (crc_start-offset), "TOM Envelope - Protocol: %s",
+ match_strval(tom_pd, tompd_formats));
+
+ ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_rl, tvb, offset, 1, tom_byte);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_pd, tvb, offset, 1, tom_byte);
+
+ /* step past the TOM header first byte */
+ offset++;
+
+ /* TOM remaining length field value 0x0F is reserved for extension */
+ if (remaining_length != 0x0F)
+ {
+ /* parse the rest of the TOM header */
+ for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
+ {
+ tom_byte = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_header, tvb,
+ offset, 1, tom_byte);
+
+ /* step to the next byte */
+ offset++;
+ }
+
+ /* Amount of frame left from offset to crc */
+ remaining_length = crc_start - offset;
+
+ /* parse the TOM message capsule */
+ for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
+ {
+ tom_byte = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_data, tvb,
+ offset, 1, tom_byte);
+
+ /* step to the next byte */
+ offset++;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* otherwise - call a subdissector */
+ next_tvb = tvb_new_subset(tvb, offset, (crc_start-offset), -1 );
+ if (!dissector_try_port(llcgprs_subdissector_table,sapi, next_tvb, pinfo, tree))
+ {
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ }
+ /* END MLT CHANGES */
+ }
+ else
+ {
+/*UI format*/
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", UI, ");
+ col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm, pme ));
+ col_append_fstr(pinfo->cinfo,COL_INFO, ", N(U) = %u", nu);
+ }
+
+ if (tree)
+ {
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset-2,
+ 2, "Unnumbered Information format - UI, N(U) = %u", nu);
+ ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_ctrlf);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_U_fmt, tvb, offset-2,
+ 2, ctrl_fld_ui_s);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_sp_bits, tvb, offset-2,
+ 2, ctrl_fld_ui_s);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_NU, tvb, offset-2, 2,
+ ctrl_fld_ui_s);
+ proto_tree_add_boolean(ctrl_f_tree, hf_llcgprs_E_bit, tvb, offset-2,
+ 2, ctrl_fld_ui_s);
+ proto_tree_add_boolean(ctrl_f_tree, hf_llcgprs_PM_bit, tvb, offset-2,
+ 2, ctrl_fld_ui_s);
+ }
+
+ /* MLT CHANGES - TOM parsing added */
+ next_tvb = tvb_new_subset(tvb, offset, (crc_start-offset), -1);
+
+ if ((ignore_cipher_bit && (fcs_status == FCS_VALID)) || !(epm & 0x2))
+ {
+ /* Either we're ignoring the cipher bit
+ * (because the bit is set but the
+ * data is unciphered), and the data has
+ * a valid FCS, or the cipher
+ * bit isn't set (indicating that the
+ * data is unciphered). Try dissecting
+ * it with a subdissector. */
+
+ /* if SAPI is TOM do other parsing */
+ if ((sapi == SAPI_TOM2) || (sapi == SAPI_TOM8))
+ {
+ if (tree)
+ {
+ guint8 tom_byte = 0;
+ guint8 remaining_length = 0;
+ guint8 tom_pd = 0;
+ int loop_counter = 0;
+
+ tom_byte = tvb_get_guint8(tvb, offset);
+ remaining_length = (tom_byte >> 4) & 0x0F;
+ tom_pd = tom_byte & 0x0F;
+
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset,
+ (crc_start-offset), "TOM Envelope - Protocol: %s",
+ match_strval(tom_pd, tompd_formats));
+
+ ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_sframe);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_rl, tvb, offset, 1, tom_byte);
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_pd, tvb, offset, 1, tom_byte);
+
+ /* step past the TOM header first byte */
+ offset++;
+
+ /* TOM remaining length field value 0x0F is reserved for extension */
+ if (remaining_length != 0x0F)
+ {
+ /* parse the rest of the TOM header */
+ for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
+ {
+ tom_byte = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_header, tvb,
+ offset, 1, tom_byte);
+
+ /* step to the next byte */
+ offset++;
+ }
+
+ /* Amount of frame left from offset to crc */
+ remaining_length = crc_start - offset;
+
+ /* parse the TOM message capsule */
+ for (loop_counter = 0; loop_counter < remaining_length; loop_counter++)
+ {
+ tom_byte = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_tom_data, tvb,
+ offset, 1, tom_byte);
+
+ /* step to the next byte */
+ offset++;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* otherwise - call a subdissector */
+ if (!dissector_try_port(llcgprs_subdissector_table, sapi, next_tvb, pinfo, tree))
+ {
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ }
+ }
+ else
+ {
+ /* ciphered information - just parse it as data */
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+
+ /* END MLT CHANGES */
}
break;
case U_FORMAT:
offset +=1;
tmp = 0;
tmp = ctrl_fld_fb & 0xf;
- if (check_col(pinfo->cinfo, COL_INFO)) {
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
col_append_str(pinfo->cinfo, COL_INFO, ", U, ");
- col_append_str(pinfo->cinfo, COL_INFO, val_to_str(tmp, cr_formats_unnumb,"Unknown/invalid code:%X"));
+ col_append_str(pinfo->cinfo, COL_INFO,
+ val_to_str(tmp, cr_formats_unnumb,"Unknown/invalid code:%X"));
}
+
if(tree){
- ui_ti = proto_tree_add_text(llcgprs_tree,tvb,offset-1,crc_start-1,"Unnumbered frame: %s",val_to_str(tmp,cr_formats_unnumb,"Unknown/invalid code:%X"));
- ui_tree = proto_item_add_subtree( ui_ti, ett_ui);
- proto_tree_add_uint( ui_tree, hf_llcgprs_Un, tvb, offset-1, 1, ctrl_fld_fb);
- proto_tree_add_boolean( ui_tree, hf_llcgprs_PF, tvb, offset-1, 1, ctrl_fld_fb);
- proto_tree_add_uint( ui_tree, hf_llcgprs_ucom, tvb, offset-1, 1, ctrl_fld_fb);
+ ui_ti = proto_tree_add_text(llcgprs_tree, tvb, (offset-1), (crc_start-1),
+ "Unnumbered frame: %s",
+ val_to_str(tmp,cr_formats_unnumb, "Unknown/invalid code:%X"));
+
+ ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
+ proto_tree_add_uint(ui_tree, hf_llcgprs_Un, tvb, (offset-1), 1, ctrl_fld_fb);
+ proto_tree_add_boolean(ui_tree, hf_llcgprs_PF, tvb, (offset-1), 1, ctrl_fld_fb);
+ proto_tree_add_uint(ui_tree, hf_llcgprs_ucom, tvb, (offset-1), 1, ctrl_fld_fb);
+
}
- break;
-/* case I_SACK:
- break;
- case S_SACK:
- break;
-*/
- }
-/* proto_tree_add_item(llcgprs_tree,
- hf_llcgprs_FIELDABBREV, tvb, offset, len, FALSE)
-*/
-/* Continue adding tree items to process the packet here */
+ /* MLT CHANGES - parse rest of the message based on type (M Bits) */
+ m_bits = ctrl_fld_fb & 0x0F;
+
+ info_len = crc_start - offset;
+
+ switch (m_bits)
+ {
+ case U_DM:
+ case U_DISC:
+ case U_NULL:
+ /* These frames SHOULD NOT have an info field */
+ if (tree)
+ {
+ ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
+ "No Information Field");
+ ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
+ }
+ break;
+ case U_UA:
+ /* This frame MAY or MAY NOT have an info field */
+ /* Info field, if it exists, consists of XID parameters */
+ if (tree)
+ {
+ if (info_len > 0)
+ {
+ guint8 xid_param_len = 0;
+ guint16 location = offset;
+ guint8 byte1 = 0;
+ guint8 byte2 = 0;
+ guint8 ending = 0;
+ int loop_counter = 0;
+
+ ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
+ "Information Field: Length = %u", info_len);
+ ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
+
+ while (location < (offset + info_len))
+ {
+ /* parse the XID parameters */
+ byte1 = tvb_get_guint8(tvb, location);
+
+ if (byte1 & 0x80)
+ {
+ guint8 xid_param_len_high = 0;
+ guint8 xid_param_len_low = 0;
+
+ byte2 = tvb_get_guint8(tvb, location + 1);
+
+ /* XL bit is set - length is continued in second byte */
+ xid_param_len_high = byte1 & 0x03;
+ xid_param_len_low = byte2 & 0xFC;
+ /* bit shift the rest of the length */
+ xid_param_len_low = xid_param_len_low >> 2;
+ xid_param_len_low = xid_param_len_low & 0x3F;
-/* If this protocol has a sub-dissector call it here, see section 1.8 */
+ xid_param_len_high = xid_param_len_high << 6;
+ xid_param_len_high = xid_param_len_high & 0xC0;
+
+ /* combine the two */
+ xid_param_len = xid_param_len_high | xid_param_len_low;
+
+ }
+ else
+ {
+ xid_param_len = byte1 & 0x3;
+ }
+
+ ending = location + xid_param_len;
+
+ tmp = byte1 & 0x7C;
+ tmp = tmp >> 2;
+ uinfo_field = proto_tree_add_text(ui_tree, tvb, location,
+ (ending - 1), "XID Parameter Type: %s",
+ val_to_str(tmp, xid_param_type_str,"Reserved Type:%X"));
+
+ uinfo_tree = proto_item_add_subtree(uinfo_field, ett_ui);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_xl, tvb,
+ location, 1, byte1);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_type, tvb,
+ location, 1, byte1);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len1, tvb,
+ location, 1, byte1);
+
+ if (byte1 & 0x80) {
+ /* length continued into byte 2 */
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len2, tvb,
+ location, 1, byte2);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_spare, tvb,
+ location, 1, byte2);
+
+ /* be sure to account for the second byte of length */
+ location++;
+ }
+
+ location++;
+ for (loop_counter = 0; loop_counter < xid_param_len; loop_counter++)
+ {
+ /* grab the information in the XID param */
+ byte2 = tvb_get_guint8(tvb, location);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_byte, tvb,
+ location, 1, byte2);
+
+ location++;
+ }
+ }
+ }
+ else
+ {
+ ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
+ "No Information Field");
+ ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
+ }
+ }
+ break;
+ case U_SABM:
+ case U_XID:
+ /* These frames do have info fields consisting of XID parameters */
+ /* Info field consists of XID parameters */
+ if (tree)
+ {
+ guint8 xid_param_len = 0;
+ guint16 location = offset;
+ guint8 byte1 = 0;
+ guint8 byte2 = 0;
+ guint8 ending = 0;
+ int loop_counter = 0;
+
+ ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
+ "Information Field: Length = %u", info_len);
+ ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
+
+ while (location < (offset + info_len))
+ {
+ /* parse the XID parameters */
+ byte1 = tvb_get_guint8(tvb, location);
+
+ if (byte1 & 0x80)
+ {
+ guint8 xid_param_len_high = 0;
+ guint8 xid_param_len_low = 0;
+
+ byte2 = tvb_get_guint8(tvb, location + 1);
+
+ /* XL bit is set - length is continued in second byte */
+ xid_param_len_high = byte1 & 0x03;
+ xid_param_len_low = byte2 & 0xFC;
+
+ /* bit shift the rest of the length */
+ xid_param_len_low = xid_param_len_low >> 2;
+ xid_param_len_low = xid_param_len_low & 0x3F;
+
+ xid_param_len_high = xid_param_len_high << 6;
+ xid_param_len_high = xid_param_len_high & 0xC0;
+
+ /* combine the two */
+ xid_param_len = xid_param_len_high | xid_param_len_low;
+
+ }
+ else
+ {
+ xid_param_len = byte1 & 0x3;
+ }
+
+ ending = location + xid_param_len;
+
+ tmp = byte1 & 0x7C;
+ tmp = tmp >> 2;
+ uinfo_field = proto_tree_add_text(ui_tree, tvb, location, (ending - 1),
+ "XID Parameter Type: %s",
+ val_to_str(tmp, xid_param_type_str,"Reserved Type:%X"));
+
+ uinfo_tree = proto_item_add_subtree(uinfo_field, ett_ui);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_xl, tvb, location,
+ 1, byte1);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_type, tvb, location,
+ 1, byte1);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len1, tvb, location,
+ 1, byte1);
+
+ if (byte1 & 0x80) {
+ /* length continued into byte 2 */
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_len2, tvb, location,
+ 1, byte2);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_spare, tvb, location,
+ 1, byte2);
+
+ /* be sure to account for the second byte of length */
+ location++;
+ }
+
+ location++;
+ for (loop_counter = 0; loop_counter < xid_param_len; loop_counter++)
+ {
+ /* grab the information in the XID param */
+ byte2 = tvb_get_guint8(tvb, location);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_xid_byte, tvb, location,
+ 1, byte2);
+
+ location++;
+ }
+ }
+ }
+ break;
+ case U_FRMR:
+ /* This frame has a special format info field */
+ if (tree)
+ {
+ guint32 fld_vars = 0;
+ guint16 cf_byte = 0;
+ int loop_counter = 0;
+ int location = 0;
+
+ ui_ti = proto_tree_add_text(llcgprs_tree, tvb, offset, (crc_start-2),
+ "Information Field: Length = %u", info_len);
+ ui_tree = proto_item_add_subtree(ui_ti, ett_ui);
+
+ uinfo_field = proto_tree_add_text(ui_tree, tvb, offset, 6,
+ "Rejected Frame Control Field");
+ uinfo_tree = proto_item_add_subtree(uinfo_field, ett_ui);
+
+ location = offset;
+ for (loop_counter = 0; loop_counter < 3; loop_counter++)
+ {
+ /* display the rejected frame control field */
+ cf_byte = tvb_get_ntohs(tvb, location);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_cf, tvb, location,
+ 2, cf_byte);
+
+ location += 2;
+ }
+
+ uinfo_field = proto_tree_add_text(ui_tree, tvb, location, 4,
+ "Information Field Data");
+ uinfo_tree = proto_item_add_subtree(uinfo_field, ett_ui);
+
+ fld_vars = tvb_get_ntohl(tvb, location);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_spare, tvb, location,
+ 4, fld_vars);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_vs, tvb, location,
+ 2, fld_vars);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_vr, tvb, (location + 1),
+ 2, fld_vars);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_cr, tvb, (location + 2),
+ 1, fld_vars);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w4, tvb, (location + 3),
+ 1, fld_vars);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w3, tvb, (location + 3),
+ 1, fld_vars);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w2, tvb, (location + 3),
+ 1, fld_vars);
+ proto_tree_add_uint(uinfo_tree, hf_llcgprs_frmr_w1, tvb, (location + 3),
+ 1, fld_vars);
+ }
+ break;
+ default:
+ break;
+ }
+ /* END MLT CHANGES */
+ break;
+ }
}
/* Register the protocol with Ethereal */
-
-/* this format is require because a script is used to build the C function
- that calls all the protocol registration.
-*/
+/* this format is require because a script is used to build the C function */
+/* that calls all the protocol registration. */
void
proto_register_llcgprs(void)
{
-
/* Setup list of header fields See Section 1.6.1 for details*/
static hf_register_info hf[] = {
{ &hf_llcgprs_sapi,
@@ -464,7 +1191,82 @@ proto_register_llcgprs(void)
{ &hf_llcgprs_NR,
{ "Receive sequence number", "llcgprs.nr",FT_UINT16, BASE_DEC, NULL, UI_MASK_NU,"Receive sequence number N(R)",HFILL }},
{&hf_llcgprs_S_fmt,
- { "S format", "llcgprs.s", FT_UINT16, BASE_DEC, NULL, 0xc000,"Supervisory format S", HFILL}}
+ { "S format", "llcgprs.s", FT_UINT16, BASE_DEC, NULL, 0xc000,"Supervisory format S", HFILL}},
+ /* MLT CHANGES - additional masks*/
+ {&hf_llcgprs_kmask,
+ { "ignored", "llcgprs.kmask", FT_UINT8, BASE_DEC, NULL, 0xE0, "ignored", HFILL}},
+ {&hf_llcgprs_k,
+ { "k", "llcgprs.k", FT_UINT8, BASE_DEC, NULL, 0x1F, "k counter", HFILL}},
+ {&hf_llcgprs_isack_ns,
+ { "N(S)", "llcgprs.sackns", FT_UINT24, BASE_DEC, NULL, 0x1FF000, "N(S)", HFILL}},
+ {&hf_llcgprs_isack_nr,
+ { "N(R)", "llcgprs.sacknr", FT_UINT24, BASE_DEC, NULL, 0x0007FC, "N(R)", HFILL}},
+ {&hf_llcgprs_isack_sfb,
+ { "Supervisory function bits","llcgprs.sacksfb", FT_UINT24, BASE_HEX, VALS(cr_formats_ipluss),0x000003, "Supervisory functions bits",HFILL }},
+ {&hf_llcgprs_ifmt,
+ { "I Format", "llcgprs.ifmt", FT_UINT24, BASE_DEC, NULL, 0x800000, "I Fmt Bit", HFILL}},
+ {&hf_llcgprs_ia,
+ { "Ack Bit", "llcgprs.ia", FT_UINT24, BASE_DEC, NULL, 0x400000, "I A Bit", HFILL}},
+ {&hf_llcgprs_izerobit,
+ { "Spare", "llcgprs.iignore", FT_UINT24, BASE_DEC, NULL, 0x200000, "Ignore Bit", HFILL}},
+ {&hf_llcgprs_sspare,
+ { "Spare", "llcgprs.sspare", FT_UINT16, BASE_DEC, NULL, 0x1800, "Ignore Bit", HFILL}},
+ {&hf_llcgprs_rbyte,
+ { "R Bitmap Bits","llcgprs.sackrbits", FT_UINT8, BASE_HEX, NULL, 0xFF, "R Bitmap", HFILL}},
+ /* XID Parameter Parsing Info */
+ {&hf_llcgprs_xid_xl,
+ { "XL Bit","llcgprs.xidxl", FT_UINT8, BASE_HEX, NULL, 0x80, "XL", HFILL}},
+ {&hf_llcgprs_xid_type,
+ { "Type","llcgprs.xidtype", FT_UINT8, BASE_DEC, NULL, 0x7C, "Type", HFILL}},
+ {&hf_llcgprs_xid_len1,
+ { "Length","llcgprs.xidlen1", FT_UINT8, BASE_DEC, NULL, 0x03, "Len", HFILL}},
+ {&hf_llcgprs_xid_len2,
+ { "Length continued","llcgprs.xidlen2", FT_UINT8, BASE_DEC, NULL, 0xFC, "Len", HFILL}},
+ {&hf_llcgprs_xid_spare,
+ { "Spare","llcgprs.xidspare", FT_UINT8, BASE_HEX, NULL, 0x03, "Ignore", HFILL}},
+ {&hf_llcgprs_xid_byte,
+ { "Parameter Byte","llcgprs.xidbyte", FT_UINT8, BASE_HEX, NULL, 0xFF, "Data", HFILL}},
+ /* FRMR Parsing Information */
+ {&hf_llcgprs_frmr_cf,
+ { "Control Field Octet","llcgprs.frmrrfcf", FT_UINT16, BASE_DEC, NULL,
+ 0xFFFF, "Rejected Frame CF", HFILL}},
+ {&hf_llcgprs_frmr_spare,
+ { "X","llcgprs.frmrspare", FT_UINT32, BASE_HEX, NULL, 0xF00400F0,
+ "Filler", HFILL}},
+ {&hf_llcgprs_frmr_vs,
+ { "V(S)","llcgprs.frmrvs", FT_UINT32, BASE_DEC, NULL, 0x0FF80000,
+ "Current send state variable", HFILL}},
+ {&hf_llcgprs_frmr_vr,
+ { "V(R)","llcgprs.frmrvr", FT_UINT32, BASE_DEC, NULL, 0x0003FE00,
+ "Current receive state variable", HFILL}},
+ {&hf_llcgprs_frmr_cr,
+ { "C/R","llcgprs.frmrcr", FT_UINT32, BASE_DEC, NULL, 0x00000100,
+ "Rejected command response", HFILL}},
+ {&hf_llcgprs_frmr_w4,
+ { "W4","llcgprs.frmrw4", FT_UINT32, BASE_DEC, NULL, 0x00000008,
+ "LLE was in ABM when rejecting", HFILL}},
+ {&hf_llcgprs_frmr_w3,
+ { "W3","llcgprs.frmrw3", FT_UINT32, BASE_DEC, NULL, 0x00000004,
+ "Undefined control field", HFILL}},
+ {&hf_llcgprs_frmr_w2,
+ { "W2","llcgprs.frmrw2", FT_UINT32, BASE_DEC, NULL, 0x00000002,
+ "Info exceeded N201", HFILL}},
+ {&hf_llcgprs_frmr_w1,
+ { "W1","llcgprs.frmrw1", FT_UINT32, BASE_DEC, NULL, 0x00000001,
+ "Invalid - info not permitted", HFILL}},
+ {&hf_llcgprs_tom_rl,
+ { "Remaining Length of TOM Protocol Header","llcgprs.romrl", FT_UINT8,
+ BASE_DEC, NULL, 0xF0, "RL", HFILL}},
+ {&hf_llcgprs_tom_pd,
+ { "TOM Protocol Discriminator","llcgprs.tompd", FT_UINT8, BASE_HEX,
+ NULL, 0x0F, "TPD", HFILL}},
+ {&hf_llcgprs_tom_header,
+ { "TOM Header Byte","llcgprs.tomhead", FT_UINT8, BASE_HEX, NULL, 0xFF,
+ "thb", HFILL}},
+ {&hf_llcgprs_tom_data,
+ { "TOM Message Capsule Byte","llcgprs.tomdata", FT_UINT8, BASE_HEX, NULL,
+ 0xFF, "tdb", HFILL}},
+ /* END MLT CHANGES */
};
/* Setup protocol subtree array */
@@ -485,7 +1287,7 @@ proto_register_llcgprs(void)
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_llcgprs, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
- register_dissector( "llcgprs", dissect_llcgprs, proto_llcgprs);
+ register_dissector("llcgprs", dissect_llcgprs, proto_llcgprs);
llcgprs_module = prefs_register_protocol ( proto_llcgprs, NULL );
prefs_register_bool_preference ( llcgprs_module, "autodetect_cipher_bit",
@@ -495,12 +1297,17 @@ proto_register_llcgprs(void)
}
-/* If this dissector uses sub-dissector registration add a registration routine.
- This format is required because a script is used to find these routines and
- create the code that calls these routines.
-*/
+/* If this dissector uses sub-dissector registration add a registration routine. */
+/* This format is required because a script is used to find these routines and */
+/* create the code that calls these routines. */
void
proto_reg_handoff_llcgprs(void)
{
+ dissector_handle_t gprs_llc_handle;
+
+ /* make sure that the top level can call this dissector */
+ gprs_llc_handle = create_dissector_handle(dissect_llcgprs, proto_llcgprs);
+ dissector_add("wtap_encap", WTAP_ENCAP_GPRS_LLC, gprs_llc_handle);
+
data_handle = find_dissector("data");
}