static int hf_gsm_a_rr_single_channel_arfcn = -1;
static int hf_gsm_a_rr_rtd_index = -1;
static int hf_gsm_a_rr_ti_flag = -1;
+static int hf_gsm_a_rr_arfcn_list = -1;
+static int hf_gsm_a_rr_da_list = -1;
+static int hf_gsm_a_rr_ua_list = -1;
+static int hf_gsm_a_rr_field_bit_long = -1;
+static int hf_gsm_a_rr_ma_bitmap = -1;
+static int hf_gsm_a_rr_inc_arfcn_bitmap = -1;
+static int hf_gsm_a_rr_ccn_supported = -1;
+static int hf_gsm_a_rr_pbcch_use_bcch = -1;
+static int hf_gsm_a_rr_ia_rest_oct_reserved = -1;
+static int hf_gsm_a_rr_tch_facch_sacchm = -1;
+static int hf_gsm_a_rr_tch_facch_sacchf = -1;
+static int hf_gsm_a_rr_tch_facch_sacchm_bi = -1;
+static int hf_gsm_a_rr_tch_acch = -1;
+static int hf_gsm_a_rr_sdcch4_sdcchc4_cbch = -1;
+static int hf_gsm_a_rr_sdcch8_sdcchc8_cbch = -1;
+static int hf_gsm_a_rr_tch_facchf_sacchm_bi = -1;
+static int hf_gsm_a_rr_tch_facchf_sacchm_uni = -1;
+static int hf_gsm_a_rr_tchf_acchs = -1;
+static int hf_gsm_a_rr_unknown_channel_info = -1;
+static int hf_gsm_a_rr_subchannel = -1;
+static int hf_gsm_a_rr_w_elements = -1;
+
/* gsm_rr_csn_flag() fields */
static int hf_gsm_a_rr_fdd_repeat_freq = -1;
static expert_field ei_gsm_a_rr_unknown_version = EI_INIT;
static expert_field ei_gsm_a_rr_extraneous_data = EI_INIT;
-static char a_bigbuf[1024];
-
static dissector_handle_t data_handle;
static dissector_handle_t rrlp_dissector;
int arfcn;
proto_item *ti = NULL;
- ti = proto_tree_add_text(tree, tvb, offset, len, "List of ARFCNs =");
+ ti = proto_tree_add_bytes_format(tree, hf_gsm_a_rr_arfcn_list, tvb, offset, len, NULL, "List of ARFCNs =");
for (arfcn=0; arfcn<ARFCN_MAX; arfcn++) {
if (list[arfcn])
proto_item_append_text(ti, " %d", arfcn);
/* extract the variable size w[] elements */
for (i=1; i<=imax; i++) {
w[i] = (gint) tvb_get_bits(tvb, bit_offset, wsize, FALSE);
- proto_tree_add_text(subtree, tvb, bit_offset>>3, ((bit_offset+wsize-1)>>3) - (bit_offset>>3) + 1 , "%s %s(%d): %d",
+ proto_tree_add_bytes_format(subtree, hf_gsm_a_rr_w_elements, tvb, bit_offset>>3, ((bit_offset+wsize-1)>>3) - (bit_offset>>3) + 1 , NULL, "%s W(%d): %d",
decode_bits_in_field(bit_offset, wsize, w[i]),
- "W",
i,
w[i]);
bit_offset += wsize;
if ((format & 0xc0) == 0x00)
{
/* bit map 0 */
- item = proto_tree_add_text(tree,tvb, curr_offset, len, "List of ARFCNs =");
+ item = proto_tree_add_bytes_format(tree, hf_gsm_a_rr_arfcn_list, tvb, curr_offset, len, NULL, "List of ARFCNs =");
bit = 4;
arfcn = 125;
for (byte = 0; byte <= len-1; byte++)
{
/* variable bit map */
arfcn = ((format & 0x01) << 9) | (tvb_get_guint8(tvb, curr_offset+1) << 1) | ((tvb_get_guint8(tvb, curr_offset + 2) & 0x80) >> 7);
- item = proto_tree_add_text(tree,tvb,curr_offset,len,"List of ARFCNs = %d",arfcn);
+ item = proto_tree_add_bytes_format(tree, hf_gsm_a_rr_arfcn_list, tvb, curr_offset, len, NULL, "List of ARFCNs = %d",arfcn);
curr_offset = curr_offset + 2;
bit = 7;
for (byte = 0; byte <= len-3; byte++)
subtree2 = proto_tree_add_subtree(subtree,tvb, bit_offset>>3, (idx>>3)+1,
ett_gsm_rr_rest_octets_elem[DE_RR_REST_OCTETS_FDD_CELL_INFORMATION_FIELD], NULL,
gsm_rr_rest_octets_elem_strings[DE_RR_REST_OCTETS_UTRAN_FDD_DESC].strptr);
- proto_tree_add_text(subtree2,tvb, bit_offset>>3, (idx>>3)+1, "Field is %d bits long", idx);
+ proto_tree_add_bytes_format(subtree2, hf_gsm_a_rr_field_bit_long, tvb, bit_offset>>3, (idx>>3)+1, NULL, "Field is %d bits long", idx);
if (xdd_indic0)
{
proto_tree_add_uint(subtree2, hf_gsm_a_rr_scrambling_code, tvb, bit_offset>>3, 0, 0);
subtree2 = proto_tree_add_subtree(subtree,tvb, bit_offset>>3, (idx>>3)+1,
ett_gsm_rr_rest_octets_elem[DE_RR_REST_OCTETS_TDD_CELL_INFORMATION_FIELD], NULL,
gsm_rr_rest_octets_elem_strings[DE_RR_REST_OCTETS_UTRAN_TDD_DESC].strptr);
- proto_tree_add_text(subtree2,tvb, bit_offset>>3, (idx>>3)+1, "Field is %d bits long", idx);
+ proto_tree_add_bytes_format(subtree2, hf_gsm_a_rr_field_bit_long, tvb, bit_offset>>3, (idx>>3)+1, NULL, "Field is %d bits long", idx);
if (xdd_indic0)
{
proto_tree_add_uint(subtree2, hf_gsm_a_rr_cell_parameter, tvb, bit_offset>>3, 0, 0);
guint32 curr_offset;
guint8 oct8,subchannel;
guint16 arfcn, hsn, maio;
- const gchar *str;
+ int hf_subchannel;
curr_offset = offset;
if ((oct8 & 0xf8) == 0x08)
{
- str = "TCH/F + ACCHs";
- other_decode_bitfield_value(a_bigbuf, oct8, 0xf8, 8);
- proto_tree_add_text(subtree,tvb, curr_offset, 1,"%s = %s",a_bigbuf,str);
+ proto_tree_add_item(subtree, hf_gsm_a_rr_tchf_acchs, tvb, curr_offset, 1, ENC_NA);
}
else
{
if ((oct8 & 0xf0) == 0x10)
{
- str = "TCH/H + ACCHs, Subchannel";
+ hf_subchannel = hf_gsm_a_rr_tch_acch;
subchannel = ((oct8 & 0x08)>>3);
}
else if ((oct8 & 0xe0) == 0x20)
{
- str = "SDCCH/4 + SACCH/C4 or CBCH (SDCCH/4), Subchannel";
+ hf_subchannel = hf_gsm_a_rr_sdcch4_sdcchc4_cbch;
subchannel = ((oct8 & 0x18)>>3);
}
else if ((oct8 & 0xc0) == 0x40)
{
- str = "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), Subchannel";
+ hf_subchannel = hf_gsm_a_rr_sdcch8_sdcchc8_cbch;
subchannel = ((oct8 & 0x38)>>3);
} else {
- str = "Unknown channel information";
+ hf_subchannel = hf_gsm_a_rr_unknown_channel_info;
subchannel = oct8;
}
- other_decode_bitfield_value(a_bigbuf, oct8, 0xf8, 8);
- proto_tree_add_text(subtree,tvb, curr_offset, 1,"%s = %s %d",a_bigbuf,str,subchannel);
+ proto_tree_add_item(subtree, hf_subchannel, tvb, curr_offset, 1, ENC_NA);
+ proto_tree_add_uint(subtree, hf_gsm_a_rr_subchannel, tvb, curr_offset, 1, subchannel);
}
proto_tree_add_item(subtree, hf_gsm_a_rr_timeslot, tvb, curr_offset, 1, ENC_BIG_ENDIAN);
guint32 curr_offset;
guint8 oct8,subchannel;
guint16 arfcn, hsn, maio;
- const gchar *str;
+ int hf_subchannel;
curr_offset = offset;
/* Octet 2 */
oct8 = tvb_get_guint8(tvb, curr_offset);
- other_decode_bitfield_value(a_bigbuf, oct8, 0xf8, 8);
if ((oct8 & 0xf8) == 0x0)
{
- str = "TCH/F + FACCH/F and SACCH/M";
- proto_tree_add_text(subtree,tvb, curr_offset, 1,"%s = %s",a_bigbuf,str);
+ proto_tree_add_item(subtree, hf_gsm_a_rr_tch_facch_sacchm, tvb, curr_offset, 1, ENC_NA);
}
else if ((oct8 & 0xf8) == 0x08)
{
- str = "TCH/F + FACCH/F and SACCH/F";
- proto_tree_add_text(subtree,tvb, curr_offset, 1,"%s = %s",a_bigbuf,str);
+ proto_tree_add_item(subtree, hf_gsm_a_rr_tch_facch_sacchf, tvb, curr_offset, 1, ENC_NA);
}
else if ((oct8 & 0xf8) == 0xf0)
{
- str = "TCH/F + FACCH/F and SACCH/M + bi- and unidirectional channels";
- proto_tree_add_text(subtree,tvb, curr_offset, 1,"%s = %s",a_bigbuf,str);
+ proto_tree_add_item(subtree, hf_gsm_a_rr_tch_facch_sacchm_bi, tvb, curr_offset, 1, ENC_NA);
}
else
{
if ((oct8 & 0xf0) == 0x10)
{
- str = "TCH/H + ACCHs, Subchannel";
+ hf_subchannel = hf_gsm_a_rr_tch_acch;
subchannel = ((oct8 & 0x08)>>3);
}
else if ((oct8 & 0xe0) == 0x20)
{
- str = "SDCCH/4 + SACCH/C4 or CBCH (SDCCH/4), Subchannel";
+ hf_subchannel = hf_gsm_a_rr_sdcch4_sdcchc4_cbch;
subchannel = ((oct8 & 0x18)>>3);
}
else if ((oct8 & 0xc0) == 0x40)
{
- str = "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), Subchannel";
+ hf_subchannel = hf_gsm_a_rr_sdcch8_sdcchc8_cbch;
subchannel = ((oct8 % 0x38)>>3);
}
else if ((oct8 & 0xc0) == 0x80)
{
- str = "TCH/F + FACCH/F and SACCH/M + bidirectional channels at timeslot";
+ hf_subchannel = hf_gsm_a_rr_tch_facchf_sacchm_bi;
subchannel = ((oct8 % 0x38)>>3);
}
else if ((oct8 & 0xe0) == 0xc0)
{
- str = "TCH/F + FACCH/F and SACCH/M + unidirectional channels at timeslot";
+ hf_subchannel = hf_gsm_a_rr_tch_facchf_sacchm_uni;
subchannel = ((oct8 % 0x38)>>3);
} else {
- str = "Unknown channel information";
+ hf_subchannel = hf_gsm_a_rr_unknown_channel_info;
subchannel = oct8;
}
- proto_tree_add_text(subtree,tvb, curr_offset, 1,"%s = %s %d",a_bigbuf,str,subchannel);
+ proto_tree_add_item(subtree, hf_subchannel, tvb, curr_offset, 1, ENC_NA);
+ proto_tree_add_uint(subtree, hf_gsm_a_rr_subchannel, tvb, curr_offset, 1, subchannel);
}
proto_tree_add_item(subtree, hf_gsm_a_rr_timeslot, tvb, curr_offset, 1, ENC_BIG_ENDIAN);
}
else
{
- proto_tree_add_text(subtree, tvb, bit_offset>>3, 1, "reserved for future use (however the value 7C for the first octet shall not be used)");
+ proto_tree_add_item(subtree, hf_gsm_a_rr_ia_rest_oct_reserved, tvb, bit_offset>>3, 1, ENC_NA);
}
}
}
proto_tree_add_uint(subtree, hf_gsm_a_rr_maio, tvb, bit_offset>>3, 1, tvb_get_bits8(tvb,bit_offset,6));
bit_offset += 6;
length = (gint)ma_length;
- item = proto_tree_add_text(subtree,tvb, bit_offset>>3, (length>>3)-1, "MA Bitmap: ");
+ item = proto_tree_add_bytes_format(subtree, hf_gsm_a_rr_ma_bitmap, tvb, bit_offset>>3, (length>>3)-1, NULL, "MA Bitmap: ");
length = (length-1)*8;
while (length)
{
curr_offset = offset;
- item = proto_tree_add_text(tree, tvb, curr_offset, len, "Bitmap of increasing ARFCNs included in the Mobile Allocation: ");
+ item = proto_tree_add_bytes_format(tree, hf_gsm_a_rr_inc_arfcn_bitmap, tvb, curr_offset, len, NULL,
+ "Bitmap of increasing ARFCNs included in the Mobile Allocation: ");
for(i=len; i>0; i--)
{
value = tvb_get_guint8(tvb,curr_offset+i-1);
curr_offset = offset;
- item = proto_tree_add_text(tree,tvb, curr_offset, 1 ,"List of DA:");
-
oct = tvb_get_guint8(tvb, curr_offset);
+ item = proto_tree_add_uint_format(tree, hf_gsm_a_rr_da_list, tvb, curr_offset, 1, oct, "List of DA:");
+
curr_offset++;
for( i=0;i<7;i++ )
{
if( oct & 0x80 ) /* octet 3a present */
{
- item = proto_tree_add_text(tree,tvb, curr_offset, 1 ,"List of UA:");
oct = tvb_get_guint8(tvb, curr_offset);
+ item = proto_tree_add_uint_format(tree, hf_gsm_a_rr_ua_list, tvb, curr_offset, 1, oct, "List of UA:");
curr_offset++;
for( i=0;i<7;i++ )
{
}
}
}
- proto_tree_add_text(subtree,tvb, bit_offset_sav>>3, (bit_offset-bit_offset_sav)>>3,"Group Call Information: Data(Not decoded)");
+ proto_tree_add_expert_format(subtree, pinfo, &ei_gsm_a_rr_data_not_dissected, tvb, bit_offset_sav>>3, (bit_offset-bit_offset_sav)>>3,
+ "Group Call Information: Data(Not decoded)");
}
gsm_rr_csn_HL_flag(tvb, subtree, bit_len, bit_offset++, hf_gsm_a_rr_packet_page_indication_1);
gsm_rr_csn_HL_flag(tvb, subtree, bit_len, bit_offset++, hf_gsm_a_rr_packet_page_indication_2);
idx = convert_n_to_p[idx];
subtree2 = proto_tree_add_subtree(subtree,tvb, curr_bit_offset>>3, (idx>>3)+1, ett_gsm_rr_rest_octets_elem[DE_RR_REST_OCTETS_FDD_CELL_INFORMATION_FIELD], &item2,
gsm_rr_rest_octets_elem_strings[DE_RR_REST_OCTETS_UTRAN_FDD_DESC].strptr);
- proto_tree_add_text(subtree2,tvb, curr_bit_offset>>3, (idx>>3)+1, "Field is %d bits long", idx);
+ proto_tree_add_bytes_format(subtree2, hf_gsm_a_rr_field_bit_long, tvb, curr_bit_offset>>3, (idx>>3)+1, NULL, "Field is %d bits long", idx);
if (xdd_indic0)
{
proto_tree_add_uint(subtree2, hf_gsm_a_rr_scrambling_code, tvb, curr_bit_offset>>3, 0, 0);
idx = convert_n_to_q[idx];
subtree2 = proto_tree_add_subtree(subtree,tvb, curr_bit_offset>>3, (idx>>3)+1, ett_gsm_rr_rest_octets_elem[DE_RR_REST_OCTETS_TDD_CELL_INFORMATION_FIELD], &item,
gsm_rr_rest_octets_elem_strings[DE_RR_REST_OCTETS_UTRAN_TDD_DESC].strptr);
- proto_tree_add_text(subtree2,tvb, curr_bit_offset>>3, (idx>>3)+1, "Field is %d bits long", idx);
+ proto_tree_add_bytes_format(subtree2, hf_gsm_a_rr_field_bit_long, tvb, curr_bit_offset>>3, (idx>>3)+1, NULL, "Field is %d bits long", idx);
if (xdd_indic0)
{
proto_tree_add_uint(subtree2, hf_gsm_a_rr_cell_parameter, tvb, curr_bit_offset>>3, 0, 0);
proto_tree_add_uint(subtree3, hf_gsm_a_rr_number_cells, tvb, bit_offset>>3, 1, value);
bit_offset += 7;
idx -= 7;
- item2 = proto_tree_add_text(subtree3,tvb, bit_offset>>3, (value>>3)+1, "CCN Supported: ");
+ item2 = proto_tree_add_bytes_format(subtree3, hf_gsm_a_rr_ccn_supported, tvb, bit_offset>>3, (value>>3)+1, NULL, "CCN Supported: ");
while (value)
{
proto_item_append_text(item2,"%d",tvb_get_bits8(tvb,bit_offset,1));
proto_tree_add_bits_ret_val(subtree, hf_gsm_a_rr_ma_length, tvb, curr_bit_offset, 6, &ma_length, ENC_BIG_ENDIAN);
curr_bit_offset += 6;
value = (gint)ma_length + 1;
- item = proto_tree_add_text(subtree,tvb, curr_bit_offset>>3, (value>>3)+1, "MA Bitmap: ");
+ item = proto_tree_add_bytes_format(subtree, hf_gsm_a_rr_ma_bitmap, tvb, curr_bit_offset>>3, (value>>3)+1, NULL, "MA Bitmap: ");
while (value)
{
proto_item_append_text(item,"%d",tvb_get_bits8(tvb,curr_bit_offset,1));
bit_offset += 10;
}
else
- proto_tree_add_text(subtree2, tvb, bit_offset>>3, 1, "PBCCH shall use the BCCH carrier");
+ proto_tree_add_item(subtree2, hf_gsm_a_rr_pbcch_use_bcch, tvb, bit_offset>>3, 1, ENC_NA);
}
proto_item_set_len(item2, (bit_offset>>3) - (bit_offset_sav>>3)+1);
}
{ &hf_gsm_a_rr_single_channel_arfcn, { "Single channel ARFCN", "gsm_a.rr.single_channel_arfcn", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_gsm_a_rr_rtd_index, { "RTD index", "gsm_a.rr.rtd_index", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_gsm_a_rr_ti_flag, { "TI flag", "gsm_a.rr.ti_flag", FT_BOOLEAN, 8, TFS(&tfs_allocated_by_receiver_sender), 0x80, NULL, HFILL }},
+ { &hf_gsm_a_rr_arfcn_list, { "List of ARFCNs", "gsm_a.rr.arfcn_list", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_da_list, { "List of DA", "gsm_a.rr.da_list", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_ua_list, { "List of UA", "gsm_a.rr.ua_list", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_ma_bitmap, { "MA Bitmap", "gsm_a.rr.ma_bitmap", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_inc_arfcn_bitmap, { "Bitmap of increasing ARFCNs included in the Mobile Allocation", "gsm_a.rr.inc_arfcn_bitmap", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_ccn_supported, { "CCN Supported", "gsm_a.rr.ccn_supported", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_pbcch_use_bcch, { "PBCCH shall use the BCCH carrier", "gsm_a.rr.pbcch_use_bcch", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_ia_rest_oct_reserved, { "Reserved for future use (however the value 7C for the first octet shall not be used)", "gsm_a.rr.ia_rest_oct_reserved", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_tch_facch_sacchm, { "TCH/F + FACCH/F and SACCH/M", "gsm_a.rr.tch_facch_sacchm", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_tch_facch_sacchf, { "TCH/F + FACCH/F and SACCH/F", "gsm_a.rr.tch_facch_sacchf", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_tch_facch_sacchm_bi, { "TCH/F + FACCH/F and SACCH/M + bi- and unidirectional channels", "gsm_a.rr.tch_facch_sacchm_bi", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_tch_acch, { "TCH/H + ACCHs", "gsm_a.rr.tch_acch", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_sdcch4_sdcchc4_cbch, { "SDCCH/4 + SACCH/C4 or CBCH (SDCCH/4)", "gsm_a.rr.sdcch4_sdcchc4_cbch", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_sdcch8_sdcchc8_cbch, { "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8)", "gsm_a.rr.sdcch8_sdcchc8_cbch", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_tch_facchf_sacchm_bi, { "TCH/F + FACCH/F and SACCH/M + bidirectional channels at timeslot", "gsm_a.rr.tch_facchf_sacchm_bi", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_tch_facchf_sacchm_uni, { "TCH/F + FACCH/F and SACCH/M + unidirectional channels at timeslot", "gsm_a.rr.tch_facchf_sacchm_uni", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_unknown_channel_info, { "Unknown channel information", "gsm_a.rr.unknown_channel_info", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_tchf_acchs, { "TCH/F + ACCHs", "gsm_a.rr.tchf_acchs", FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL }},
+ { &hf_gsm_a_rr_subchannel, { "Subchannel", "gsm_a.rr.tch_facch_sacchm", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_w_elements, { "W elements", "gsm_a.rr.w_elements", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_gsm_a_rr_field_bit_long, { "Field is X bits long", "gsm_a.rr.field_bit_long", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
/* gsm_rr_csn_flag() fields */
{ &hf_gsm_a_rr_fdd_repeat_freq, { "Repeating FDD Frequency", "gsm_a.rr.fdd_repeat_freq", FT_BOOLEAN, BASE_NONE, TFS(&tfs_present_not_present), 0x00, NULL, HFILL }},
#include <epan/packet.h>
#include <epan/reassemble.h>
+#include <epan/expert.h>
void proto_register_gsm_cbch(void);
void proto_reg_handoff_gsm_cbch(void);
static int hf_gsm_cbch_sched_end_slot = -1;
static int hf_gsm_cbch_slot = -1;
/* static int hf_gsm_cbch_sched_msg_id = -1; */
+static int hf_gsm_cbch_padding = -1;
+static int hf_gsm_cbch_block = -1;
/* These fields are used when reassembling cbch fragments
*/
static gint ett_cbch_fragment = -1;
static gint ett_cbch_fragments = -1;
+static expert_field ei_gsm_cbch_sched_end_slot = EI_INIT;
+static expert_field ei_gsm_cbch_seq_num_null = EI_INIT;
+static expert_field ei_gsm_cbch_seq_num_reserved = EI_INIT;
+static expert_field ei_gsm_cbch_lpd = EI_INIT;
+
static dissector_handle_t data_handle;
static dissector_handle_t cbs_handle;
reassembly_table_destroy(&cbch_block_reassembly_table);
}
+static const range_string gsm_cbch_sched_begin_slot_rvals[] = {
+ { 0, 0, "Out of range (ignoring message)" },
+ { 1, 1, "(apparently) Scheduled Scheduling Message" },
+ { 2, 48, "(apparently) Unscheduled Scheduling Message" },
+ { 49, 0xFF, "Out of range (ignoring message)" },
+
+ { 0x00, 0x00, NULL },
+};
+
static void
dissect_schedule_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree)
{
octet1 = tvb_get_guint8(tvb, offset);
if (0 == (octet1 & 0xC0))
{
+ proto_item* slot_item;
sched_begin = octet1 & 0x3F;
proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_begin_slot, tvb, offset++, 1, ENC_BIG_ENDIAN);
- if (1 == sched_begin)
+ if ((sched_begin < 1) || (sched_begin > 48))
{
- proto_tree_add_text(sched_tree, tvb, offset - 1, 1, "(apparently) Scheduled Scheduling Message");
- }
- else if ((2 <= sched_begin) && (48 >= sched_begin))
- {
- proto_tree_add_text(sched_tree, tvb, offset - 1, 1, "(apparently) Unscheduled Scheduling Message");
- }
- else
- {
- proto_tree_add_text(sched_tree, tvb, offset - 1, 1, "Begin Slot Number out of range: ignoring message");
valid_message = FALSE;
}
proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_spare, tvb, offset, 1, ENC_BIG_ENDIAN);
sched_end = tvb_get_guint8(tvb, offset);
- proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_end_slot, tvb, offset++, 1, ENC_BIG_ENDIAN);
+ slot_item = proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_end_slot, tvb, offset++, 1, ENC_BIG_ENDIAN);
if (sched_end < sched_begin)
{
- proto_tree_add_text(sched_tree, tvb, offset - 1, 1, "End Slot Number less than Begin Slot Number: ignoring message");
+ expert_add_info(pinfo, slot_item, &ei_gsm_cbch_sched_end_slot);
valid_message = FALSE;
}
}
}
proto_item_set_end(item, tvb, offset);
- proto_tree_add_text(sched_tree, tvb, offset, -1, "Padding");
+ proto_tree_add_item(sched_tree, hf_gsm_cbch_padding, tvb, offset, -1, ENC_NA);
}
}
}
fragment_head *frag_data = NULL;
guint8 octet, lb, lpd, seq_num;
guint32 offset;
- proto_item *cbch_item;
+ proto_item *cbch_item, *lpd_item, *seq_item;
proto_tree *cbch_tree;
tvbuff_t *reass_tvb = NULL, *msg_tvb = NULL;
cbch_tree = proto_item_add_subtree(cbch_item, ett_cbch_msg);
- proto_tree_add_text(cbch_tree, tvb, offset, 1, "CBCH Block");
+ proto_tree_add_uint(cbch_tree, hf_gsm_cbch_block, tvb, offset, 1, octet);
proto_tree_add_uint(cbch_tree, hf_gsm_cbch_spare_bit, tvb, offset, 1, octet);
- proto_tree_add_uint(cbch_tree, hf_gsm_cbch_lpd, tvb, offset, 1, octet);
+ lpd_item = proto_tree_add_uint(cbch_tree, hf_gsm_cbch_lpd, tvb, offset, 1, octet);
proto_tree_add_uint(cbch_tree, hf_gsm_cbch_lb, tvb, offset, 1, octet);
- proto_tree_add_uint(cbch_tree, hf_gsm_cbch_seq_num, tvb, offset, 1, octet);
+ seq_item = proto_tree_add_uint(cbch_tree, hf_gsm_cbch_seq_num, tvb, offset, 1, octet);
seq_num = octet & 0x0F;
lpd = (octet & 0x60) >> 5;
lb = (octet & 0x10) >> 4;
break;
case 0x0F:
- proto_tree_add_text(cbch_tree, tvb, offset, 1, "NULL message");
+ expert_add_info(pinfo, seq_item, &ei_gsm_cbch_seq_num_null);
call_dissector(data_handle, tvb, pinfo, cbch_tree);
break;
default:
- proto_tree_add_text(cbch_tree, tvb, offset, 1, "reserved Sequence Number");
+ expert_add_info(pinfo, seq_item, &ei_gsm_cbch_seq_num_reserved);
call_dissector(data_handle, tvb, pinfo, cbch_tree);
break;
}
}
else
{
- proto_tree_add_text(cbch_tree, tvb, offset, 1, "invalid Link Protocol Discriminator");
+ expert_add_info(pinfo, lpd_item, &ei_gsm_cbch_lpd);
call_dissector(data_handle, tvb, pinfo, cbch_tree);
}
}
},
{ &hf_gsm_cbch_sched_begin_slot,
{ "GSM CBCH Schedule Begin slot", "gsm_cbch.schedule_begin",
- FT_UINT8, BASE_DEC, NULL, 0x3F,
+ FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_cbch_sched_begin_slot_rvals), 0x3F,
NULL, HFILL}
},
{ &hf_gsm_cbch_sched_spare,
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL}
},
+ { &hf_gsm_cbch_padding,
+ { "Padding", "gsm_cbch.padding",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_gsm_cbch_block,
+ { "CBCH Block", "gsm_cbch.block",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}
+ },
+
#if 0
{ &hf_gsm_cbch_sched_msg_id,
{ "GSM CBCH Schedule Message ID", "gsm_cbch.sched_msg_id",
&ett_cbch_fragments,
};
+ expert_module_t* expert_cbch;
+
+ static ei_register_info ei[] = {
+ { &ei_gsm_cbch_sched_end_slot, { "gsm_cbch.sched_end.bad_range", PI_PROTOCOL, PI_WARN, "End Slot Number less than Begin Slot Number: ignoring message", EXPFILL }},
+ { &ei_gsm_cbch_seq_num_null, { "gsm_cbch.block_type.seq_num.null", PI_PROTOCOL, PI_NOTE, "NULL message", EXPFILL }},
+ { &ei_gsm_cbch_seq_num_reserved, { "gsm_cbch.block_type.seq_num.reserved", PI_PROTOCOL, PI_NOTE, "Reserved Sequence Number", EXPFILL }},
+ { &ei_gsm_cbch_lpd, { "gsm_cbch.block_type.lpd.invalid", PI_PROTOCOL, PI_WARN, "Invalid Link Protocol Discriminator", EXPFILL }},
+ };
+
/* Register the protocol name and description */
proto_cbch = proto_register_protocol("GSM Cell Broadcast Channel", "GSM CBCH", "gsm_cbch");
proto_register_field_array(proto_cbch, hf_smscb, array_length(hf_smscb));
+ expert_cbch = expert_register_protocol(proto_cbch);
+ expert_register_field_array(expert_cbch, ei, array_length(ei));
/* subdissector code */
register_dissector("gsm_cbch", dissect_cbch, proto_cbch);
static expert_field ei_gsm_rlcmac_coding_scheme_unknown = EI_INIT;
static expert_field ei_gsm_rlcmac_egprs_header_type_not_handled = EI_INIT;
static expert_field ei_gsm_rlcmac_unexpected_header_extension = EI_INIT;
+static expert_field ei_gsm_rlcmac_unknown_pacch_access_burst = EI_INIT;
static dissector_handle_t data_handle;
tvbuff_t* data_tvb = NULL;
gboolean more = TRUE, first_li = TRUE;
proto_tree *subtree = NULL;
- proto_item *ti = NULL;
/* decode the LIs and any associated LLC Frames */
for(i = 0; (i < li_count) && more; i++)
switch (li)
{
case 0:
- proto_tree_add_text(tree, tvb, li_array[i].offset, 1,
+ proto_tree_add_subtree_format(tree, tvb, li_array[i].offset, 1, ett_data_segments, NULL,
"LI[%d]=%d indicates: The previous segment of LLC Frame precisely filled the previous RLC Block",
i, li);
break;
case 63:
if (first_li)
{
- ti = proto_tree_add_text(tree, tvb, octet_offset, li,
+ subtree = proto_tree_add_subtree_format(tree, tvb, octet_offset, li, ett_data_segments, NULL,
"data segment: LI[%d]=%d indicates: The RLC data block contains only filler bits",
i, li);
}
else
{
- ti = proto_tree_add_text(tree, tvb, octet_offset, li,
+ subtree = proto_tree_add_subtree_format(tree, tvb, octet_offset, li, ett_data_segments, NULL,
"data segment: LI[%d]=%d indicates: The remainder of the RLC data block contains filler bits",
i, li);
}
- subtree = proto_item_add_subtree(ti, ett_data_segments);
data_tvb = tvb_new_subset_length(tvb, octet_offset, octet_length - octet_offset);
call_dissector(data_handle, data_tvb, pinfo, subtree);
octet_offset = octet_length;
break;
default:
- ti = proto_tree_add_text(tree, tvb, octet_offset, li,
+ subtree = proto_tree_add_subtree_format(tree, tvb, octet_offset, li, ett_data_segments, NULL,
"data segment: LI[%d]=%d indicates: (Last segment of) LLC frame (%d octets)",
i, li, li);
- subtree = proto_item_add_subtree(ti, ett_data_segments);
data_tvb = tvb_new_subset_length(tvb, octet_offset, li);
call_dissector(data_handle, data_tvb, pinfo, subtree);
octet_offset += li;
/* if there is space left in the RLC Block, then it is a segment of LLC Frame without LI*/
if (more)
{
- ti = proto_tree_add_text(tree, tvb, octet_offset, octet_length - octet_offset,
+ subtree = proto_tree_add_subtree_format(tree, tvb, octet_offset, octet_length - octet_offset, ett_data_segments, NULL,
"data segment: LI not present: \n The Upper Layer PDU in the current RLC data block either fills the current RLC data block precisely \nor continues in the following in-sequence RLC data block");
}
else
{
- ti = proto_tree_add_text(tree, tvb, octet_offset, octet_length - octet_offset, "Padding Octets");
+ subtree = proto_tree_add_subtree(tree, tvb, octet_offset, octet_length - octet_offset, ett_data_segments, NULL, "Padding Octets");
}
- subtree = proto_item_add_subtree(ti, ett_data_segments);
data_tvb = tvb_new_subset_length(tvb, octet_offset, octet_length - octet_offset);
call_dissector(data_handle, data_tvb, pinfo, subtree);
octet_offset = octet_length;
tvbuff_t *data_tvb = NULL;
gboolean first_li = TRUE;
proto_tree *subtree = NULL;
- proto_item *ti = NULL;
/* decode the LIs and any associated LLC Frames */
for(i = 0; i < li_count; i++)
{
if (li_array[i].li & 1)
{
- proto_tree_add_text(tree, tvb, li_array[i].offset, 1,
+ proto_tree_add_subtree_format(tree, tvb, li_array[i].offset, 1, ett_data_segments, NULL,
"LI[%d]=%d indicates: The previous RLC data block contains a Upper Layer PDU, or a part of it, \nthat fills precisely the previous data block and for which there is no length indicator in that RLC data block. \nThe current RLC data block contains a Upper Layer PDU that either fills the current RLC data block precisely or \ncontinues in the next RLC data block.",
i, li);
}
else
{
- proto_tree_add_text(tree, tvb, li_array[i].offset, 1,
+ proto_tree_add_subtree_format(tree, tvb, li_array[i].offset, 1, ett_data_segments, NULL,
"LI[%d]=%d indicates: The last Upper Layer PDU of the previous in sequence RLC data block ends \nat the boundary of that RLC data block and it has no LI in the header of that RLC data block. \nThus the current RLC data block contains the first segment of all included Upper Layer PDUs.",
i, li);
}
}
else
{
- proto_tree_add_text(tree, tvb, li_array[i].offset, 1,
+ proto_tree_add_subtree_format(tree, tvb, li_array[i].offset, 1, ett_data_segments, NULL,
"LI[%d]=%d indicates: Unexpected occurrence of LI=0.",
i, li);
}
{
if (li_array[i].li & 1)
{
- proto_tree_add_text(tree, tvb, li_array[i].offset, 1,
+ proto_tree_add_subtree_format(tree, tvb, li_array[i].offset, 1, ett_data_segments, NULL,
"LI[%d]=%d indicates: The current RLC data block contains the first segment of an Upper Layer PDU \nthat either fills the current RLC data block precisely or continues in the next RLC data block.",
i, li);
}
else
{
- proto_tree_add_text(tree, tvb, li_array[i].offset, 1,
+ proto_tree_add_subtree_format(tree, tvb, li_array[i].offset, 1, ett_data_segments, NULL,
"LI[%d]=%d indicates: The current RLC data block contains the first segment of all included Upper Layer PDUs.",
i, li);
}
}
else
{
- proto_tree_add_text(tree, tvb, li_array[i].offset, 1,
+ proto_tree_add_subtree_format(tree, tvb, li_array[i].offset, 1, ett_data_segments, NULL,
"LI[%d]=%d indicates: Unexpected occurrence of LI=126.",
i, li);
}
case 127:
if (first_li)
{
- ti = proto_tree_add_text(tree, tvb, octet_offset, octet_length - octet_offset,
+ subtree = proto_tree_add_subtree_format(tree, tvb, octet_offset, octet_length - octet_offset, ett_data_segments, NULL,
"data segment: LI[%d]=%d indicates: The RLC data block contains only filler bits",
i, li);
}
else
{
- ti = proto_tree_add_text(tree, tvb, octet_offset, octet_length - octet_offset,
+ subtree = proto_tree_add_subtree_format(tree, tvb, octet_offset, octet_length - octet_offset, ett_data_segments, NULL,
"data segment: LI[%d]=%d indicates: The remainder of the RLC data block contains filler bits",
i, li);
}
- subtree = proto_item_add_subtree(ti, ett_data_segments);
data_tvb = tvb_new_subset_length(tvb, octet_offset, octet_length - octet_offset);
call_dissector(data_handle, data_tvb, pinfo, subtree);
octet_offset = octet_length;
break;
default:
- ti = proto_tree_add_text(tree, tvb, octet_offset, li,
+ subtree = proto_tree_add_subtree_format(tree, tvb, octet_offset, li, ett_data_segments, NULL,
"data segment: LI[%d]=%d indicates: (Last segment of) LLC frame (%d octets)",
i, li, li);
- subtree = proto_item_add_subtree(ti, ett_data_segments);
data_tvb = tvb_new_subset_length(tvb, octet_offset, li);
call_dissector(data_handle, data_tvb, pinfo, subtree);
octet_offset += li;
/* if there is space left in the RLC Block, then it is a segment of LLC Frame without LI*/
if (octet_offset < octet_length)
{
- ti = proto_tree_add_text(tree, tvb, octet_offset, octet_length - octet_offset,
+ subtree = proto_tree_add_subtree(tree, tvb, octet_offset, octet_length - octet_offset, ett_data_segments, NULL,
"data segment: LI not present: \n The Upper Layer PDU in the current RLC data block either fills the current RLC data block precisely \nor continues in the following in-sequence RLC data block");
- subtree = proto_item_add_subtree(ti, ett_data_segments);
data_tvb = tvb_new_subset_length(tvb, octet_offset, octet_length - octet_offset);
call_dissector(data_handle, data_tvb, pinfo, subtree);
octet_offset = octet_length;
}
else
{
- proto_tree_add_text(tree, tvb, 0, -1,
- "Unknown PACCH access burst");
+ proto_tree_add_expert(tree, pinfo, &ei_gsm_rlcmac_unknown_pacch_access_burst, tvb, 0, -1);
call_dissector(data_handle, tvb, pinfo, tree);
}
}
{ &ei_gsm_rlcmac_gprs_fanr_header_dissection_not_supported, { "gsm_rlcmac.gprs_fanr_header_dissection_not_supported", PI_UNDECODED, PI_WARN, "GPRS FANR Header dissection not supported (yet)", EXPFILL }},
{ &ei_gsm_rlcmac_egprs_header_type_not_handled, { "gsm_rlcmac.egprs_header_type_not_handled", PI_UNDECODED, PI_WARN, "EGPRS Header Type not handled (yet)", EXPFILL }},
{ &ei_gsm_rlcmac_coding_scheme_unknown, { "gsm_rlcmac.coding_scheme.unknown", PI_PROTOCOL, PI_WARN, "GSM RLCMAC unknown coding scheme", EXPFILL }},
+ { &ei_gsm_rlcmac_unknown_pacch_access_burst, { "gsm_rlcmac.unknown_pacch_access_burst", PI_PROTOCOL, PI_WARN, "Unknown PACCH access burst", EXPFILL }},
};
expert_module_t* expert_gsm_rlcmac;