diff --git a/epan/dissectors/packet-gsm_rlcmac.c b/epan/dissectors/packet-gsm_rlcmac.c index f5ce4f669c..397a98f6b6 100644 --- a/epan/dissectors/packet-gsm_rlcmac.c +++ b/epan/dissectors/packet-gsm_rlcmac.c @@ -8549,8 +8549,10 @@ static gint construct_egprs_data_segment_li_array(tvbuff_t *tvb, proto_tree *tre return (offset - initial_offset); } -static guint8 dissect_gprs_data_segments(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 initial_offset, - guint8 octet_length, guint8 li_count, length_indicator_t *li_array) +static guint8 dissect_gprs_data_segments(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + guint8 initial_offset, guint8 octet_length, + gboolean is_uplink, guint8 cs, + guint8 li_count, length_indicator_t *li_array) { guint8 octet_offset = initial_offset; guint8 i; @@ -8558,6 +8560,10 @@ static guint8 dissect_gprs_data_segments(tvbuff_t *tvb, packet_info *pinfo, prot gboolean more = TRUE, first_li = TRUE; proto_tree *subtree = NULL; + guint8 blk_length = gsm_rlcmac_gprs_cs_to_block_length[cs - 1]; + if (blk_length > octet_length) + blk_length = octet_length; /* part of the block or spare bits missing */ + /* decode the LIs and any associated LLC Frames */ for(i = 0; (i < li_count) && more; i++) { @@ -8569,9 +8575,16 @@ static guint8 dissect_gprs_data_segments(tvbuff_t *tvb, packet_info *pinfo, prot switch (li) { case 0: - 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); + /* 3GPP TS 44.060 B.2 Example 2 */ + col_append_str_uint(pinfo->cinfo, COL_INFO, "Len", blk_length - octet_offset, " "); + subtree = proto_tree_add_subtree_format(tree, tvb, li_array[i].offset, 1, ett_data_segments, NULL, + "LI[%d]=%d indicates: The current LLC PDU would fit within current RLC data block but the addition " + "of the length indicator octet (to indicate the LLC PDU boundary) causes the LLC PDU to extend into " + "another RLC data block", + i, li); + data_tvb = tvb_new_subset_length(tvb, octet_offset, blk_length - octet_offset); + call_data_dissector(data_tvb, pinfo, subtree); + octet_offset = blk_length; break; case 63: @@ -8587,9 +8600,9 @@ static guint8 dissect_gprs_data_segments(tvbuff_t *tvb, packet_info *pinfo, prot "data segment: LI[%d]=%d indicates: The remainder of the RLC data block contains filler bits", i, li); } - data_tvb = tvb_new_subset_length(tvb, octet_offset, octet_length - octet_offset); + data_tvb = tvb_new_subset_length(tvb, octet_offset, blk_length - octet_offset); call_data_dissector(data_tvb, pinfo, subtree); - octet_offset = octet_length; + octet_offset = blk_length; break; default: @@ -8604,24 +8617,27 @@ static guint8 dissect_gprs_data_segments(tvbuff_t *tvb, packet_info *pinfo, prot } first_li = FALSE; } - if (octet_offset < octet_length) + + if (octet_offset < blk_length) { /* if there is space left in the RLC Block, then it is a segment of LLC Frame without LI*/ if (more) { - col_append_str_uint(pinfo->cinfo, COL_INFO, "Len", octet_length - octet_offset, " "); - subtree = proto_tree_add_subtree_format(tree, tvb, octet_offset, octet_length - octet_offset, ett_data_segments, NULL, + col_append_str_uint(pinfo->cinfo, COL_INFO, "Len", blk_length - octet_offset, " "); + subtree = proto_tree_add_subtree_format(tree, tvb, octet_offset, blk_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 - { - subtree = proto_tree_add_subtree(tree, tvb, octet_offset, octet_length - octet_offset, ett_data_segments, NULL, "Padding Octets"); - } - data_tvb = tvb_new_subset_length(tvb, octet_offset, octet_length - octet_offset); - call_data_dissector(data_tvb, pinfo, subtree); - octet_offset = octet_length; + data_tvb = tvb_new_subset_length(tvb, octet_offset, blk_length - octet_offset); + call_data_dissector(data_tvb, pinfo, subtree); + } else { + proto_tree_add_bytes_item(tree, hf_padding, tvb, octet_offset, blk_length - octet_offset, ENC_BIG_ENDIAN, NULL, NULL, NULL); + } } - return (octet_offset - initial_offset); + octet_offset = blk_length; + + if(octet_offset < octet_length) + proto_tree_add_bits_item(tree, is_uplink ? hf_ul_data_spare : hf_dl_data_spare, tvb, + octet_offset*8, (octet_length - octet_offset)*8, ENC_BIG_ENDIAN); + return octet_length; } static guint16 dissect_egprs_data_segments(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint initial_offset, guint8 octet_length, guint8 li_count, length_indicator_t *li_array) @@ -9005,13 +9021,13 @@ dissect_dl_gprs_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, RlcMa { length_indicator_t li_array[7]; guint8 li_count = array_length(li_array); + guint8 cs = (data->block_format & 0x0F); guint64 e; col_set_str(pinfo->cinfo, COL_PROTOCOL, "GSM RLC/MAC"); - col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "DATA: CS%d", data->block_format & 0x0F); + col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "DATA: CS%d", cs); ti = proto_tree_add_protocol_format(tree, proto_gsm_rlcmac, tvb, bit_offset >> 3, -1, - "GPRS DL DATA (CS%d)", - data->block_format & 0x0F); + "GPRS DL DATA (CS%d)", cs); rlcmac_tree = proto_item_add_subtree(ti, ett_gsm_rlcmac); csnStreamInit(&ar, 0, bit_length, pinfo); @@ -9040,9 +9056,9 @@ dissect_dl_gprs_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, RlcMa if (e) { /* dissect the data segments */ - /*bit_offset += 8 * */ dissect_gprs_data_segments(tvb, pinfo, rlcmac_tree, bit_offset / 8, bit_length / 8, - li_count, - li_array); + /*bit_offset += 8 * */ dissect_gprs_data_segments(tvb, pinfo, rlcmac_tree, + bit_offset / 8, bit_length / 8, + FALSE, cs, li_count, li_array); } else { @@ -9438,11 +9454,11 @@ dissect_ul_gprs_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, RlcMa guint64 e; length_indicator_t li_array[10]; guint8 li_count = array_length(li_array); + guint8 cs = data->block_format & 0x0F; - col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "DATA: CS%d", data->block_format & 0x0F); + col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "DATA: CS%d", cs); ti = proto_tree_add_protocol_format(tree, proto_gsm_rlcmac, tvb, bit_offset >> 3, -1, - "GPRS UL DATA (CS%d)", - data->block_format & 0x0F); + "GPRS UL DATA (CS%d)", cs); rlcmac_tree = proto_item_add_subtree(ti, ett_gsm_rlcmac); data->u.UL_Data_Block_GPRS.TI = 0; data->u.UL_Data_Block_GPRS.PI = 0; @@ -9482,9 +9498,9 @@ dissect_ul_gprs_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, RlcMa if (e) { /* dissect the data segments */ - /*bit_offset += 8 * */ dissect_gprs_data_segments(tvb, pinfo, rlcmac_tree, bit_offset / 8, bit_length / 8, - li_count, - li_array); + /*bit_offset += 8 * */ dissect_gprs_data_segments(tvb, pinfo, rlcmac_tree, + bit_offset / 8, bit_length / 8, + TRUE, cs, li_count, li_array); } else { @@ -10956,7 +10972,7 @@ proto_register_gsm_rlcmac(void) }, { &hf_padding, { "Padding", "gsm_rlcmac.dl.padding", - FT_UINT8, BASE_DEC, NULL, 0x0, + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },