diff options
author | Darien Spencer <cusneud@mail.com> | 2018-09-23 13:57:37 +0300 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2018-10-15 05:13:50 +0000 |
commit | c6dc4095b7aba75113e24868f174c3d4962075ca (patch) | |
tree | 9a377a4362952e0f27d871cbf3f0eb3119f27f0f /epan/dissectors/packet-umts_fp.c | |
parent | b0759a02bb0759aaa6ec3cfdac345d27c6108494 (diff) |
FP: Added E-DCH T1 heuristic dissector
Change-Id: I22a3ba4a7caab1e4885292e6d28b2bc3d1e22bb7
Reviewed-on: https://code.wireshark.org/review/30208
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-umts_fp.c')
-rw-r--r-- | epan/dissectors/packet-umts_fp.c | 198 |
1 files changed, 197 insertions, 1 deletions
diff --git a/epan/dissectors/packet-umts_fp.c b/epan/dissectors/packet-umts_fp.c index fbe0789b7a..7c626c039f 100644 --- a/epan/dissectors/packet-umts_fp.c +++ b/epan/dissectors/packet-umts_fp.c @@ -37,7 +37,7 @@ * - Set the logical channel properly for non multiplexed, channels * for channels that doesn't have the C/T field! This should be based * on the RRC message RadioBearerSetup. - * - E-DCH (T1 & T2) heuristic dissectors + * - E-DCH T2 heuristic dissector */ void proto_register_fp(void); void proto_reg_handoff_fp(void); @@ -3933,6 +3933,28 @@ check_payload_crc_for_heur(tvbuff_t *tvb, guint16 header_length) return calc_crc == crc; } +/* Validates the header CRC in a E-DCH Data FP frame */ +/* Should only be used in heuristic dissectors! */ +static gboolean +check_edch_header_crc_for_heur(tvbuff_t *tvb, guint16 header_length) +{ + guint16 crc = 0; + guint16 calc_crc = 0; + guint8 * data = NULL; + + if (header_length > tvb_captured_length(tvb)) + return FALSE; + + crc = (tvb_get_bits8(tvb, 0, 7) << 4) + tvb_get_bits8(tvb, 8, 4); + /* Get data of header excluding the first byte */ + data = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 1, header_length-1); + /*Zero the part in the second byte which contains part of the CRC*/ + data[0] = data[0] & 0x0f; + + calc_crc = crc11_307_noreflect_noxor(data, header_length-1); + + return calc_crc == crc; +} /* Generates a unique 32bit identifier based on the frame's metadata */ /* This ID is used in the RLC dissector for reassembly */ /* Should only be used in heuristic dissectors! */ @@ -5000,6 +5022,177 @@ heur_dissect_fp_hsdsch_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre dissect_fp(tvb, pinfo, tree, data); return TRUE; } + +static gboolean +heur_dissect_fp_edch_type_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + conversation_t *p_conv; + umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; + fp_edch_channel_info_t* fp_edch_channel_info; + struct fp_info *p_fp_info; + guint32 captured_length; + guint8 frame_type; + guint8 num_sub_frames_byte; + guint8 number_of_subframes; + guint8 number_of_mac_es_pdus; + guint32 subframe_number; + guint32 total_sub_headers_len; + guint32 total_header_length; + guint32 payload_length; + guint32 total_mac_pdus_count; + guint32 macd_pdu_bit_size; + guint32 bit_offset; + guint32 offset; + guint32 i = 0; + guint32 n = 0; + + /* Trying to find existing conversation */ + p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, + conversation_pt_to_endpoint_type(pinfo->ptype), + pinfo->destport, pinfo->srcport, NO_ADDR_B); + + if (p_conv != NULL) { + /* Checking if the conversation was already framed */ + umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); + if (umts_fp_conversation_info) { + fp_edch_channel_info = (fp_edch_channel_info_t*)umts_fp_conversation_info->channel_specific_info; + if (umts_fp_conversation_info->channel == CHANNEL_EDCH && fp_edch_channel_info->edch_type == 0) { + conversation_set_dissector(p_conv, fp_handle); + dissect_fp(tvb, pinfo, tree, data); + return TRUE; + } + else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){ + /* This conversation was successfuly framed as ANOTHER type */ + return FALSE; + } + } + } + + /* Making sure FP info isn't already attached */ + p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); + if (p_fp_info) { + return FALSE; + } + + captured_length = tvb_reported_length(tvb); + /* Lengths limit: header size + at least 1 Subframe Header + CRC Payload size */ + if (captured_length < 9) { + return FALSE; + } + + frame_type = tvb_get_guint8(tvb, 0) & 0x01; + if (frame_type == 1) { /* is 'control' frame type*/ + return FALSE; + } + + num_sub_frames_byte = tvb_get_guint8(tvb, 2); + /* Checking 4 leftmost bits in the 'Number of Subframes' byte, which are reserved and should be 0 */ + if (num_sub_frames_byte & 0xf0) { + return FALSE; + } + + /* Values {11-16} are reserved */ + number_of_subframes = (num_sub_frames_byte & 0x0f) + 1; + if (number_of_subframes >= 11) { + return FALSE; + } + + /* Iterating through the block headers looking for invalid fields */ + total_header_length = 4; + offset = 4; + total_mac_pdus_count = 0; + /* EDCH subframe header list */ + for (n=0; n < number_of_subframes; n++) { + + /* Making sure the next index is not out of range */ + if (((guint32)(offset + 3)) >= captured_length) { + return FALSE; + } + + /* Subframe number */ + subframe_number = (tvb_get_guint8(tvb, offset) & 0x07); + if (subframe_number > 4) { + return FALSE; + } + offset++; + + /* Number of MAC-es PDUs */ + number_of_mac_es_pdus = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4; + if (number_of_mac_es_pdus == 0) { + return FALSE; + } + bit_offset = 4; + + /* Making sure enough bytes are presesnt for all sub-header */ + total_sub_headers_len = ((int)((((1.5 + (number_of_mac_es_pdus * 1.5))*8+7)/8))); + if ((offset + total_sub_headers_len) >= captured_length) { + return FALSE; + } + /* Details of each MAC-es PDU */ + for (i=0; i < number_of_mac_es_pdus; i++) { + guint32 n_pdus; /*Size of the PDU*/ + + /* DDI (6 bits) */ + bit_offset += 6; + + /* Number of MAC-d PDUs (6 bits) */ + n_pdus = tvb_get_bits8( tvb, offset*8 + bit_offset, 6); + total_mac_pdus_count += n_pdus; + bit_offset += 6; + } + + total_header_length += total_sub_headers_len; + offset += ((bit_offset+7)/8); + } + + /* Figure MAC bit size */ + payload_length = captured_length - total_header_length - 3; /* Removing 3 bytes for Payload CRC and TSN */ + if (payload_length == (total_mac_pdus_count * 42)) { + macd_pdu_bit_size = 336; + } + else if (payload_length == (total_mac_pdus_count * 18)) { + macd_pdu_bit_size = 144; + } + else { + /* Unexpected payload length or DDIs combination */ + return FALSE; + } + + if (!check_edch_header_crc_for_heur(tvb, total_header_length)) { + return FALSE; + } + if (!check_payload_crc_for_heur(tvb, total_header_length)) { + return FALSE; + } + + if(!umts_fp_conversation_info) { + umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); + set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); + } + umts_fp_conversation_info->iface_type = IuB_Interface; + umts_fp_conversation_info->division = Division_FDD; + umts_fp_conversation_info->dl_frame_number = pinfo->num; + umts_fp_conversation_info->ul_frame_number = pinfo->num; + umts_fp_conversation_info->dch_crc_present = 1; + umts_fp_conversation_info->com_context_id = generate_ue_id_for_heur(pinfo); + umts_fp_conversation_info->rlc_mode = FP_RLC_AM; + copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src); + umts_fp_conversation_info->crnc_port = pinfo->srcport; + umts_fp_conversation_info->channel = CHANNEL_EDCH; + fp_edch_channel_info = wmem_new0(wmem_file_scope(), fp_edch_channel_info_t); + fp_edch_channel_info->no_ddi_entries = 0x0f; + for(i = 0;i<0x0f;i++) { + fp_edch_channel_info->edch_ddi[i] = i; + fp_edch_channel_info->edch_macd_pdu_size[i] = macd_pdu_bit_size; + fp_edch_channel_info->edch_lchId[i] = 9; + } + fp_edch_channel_info->edch_type = 0; /* Type 1 */ + umts_fp_conversation_info->channel_specific_info = (void*)fp_edch_channel_info; + + conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle); + dissect_fp(tvb, pinfo, tree, data); + return TRUE; +} /* This method can frame UDP streams containing FP packets but dissection of those packets will */ /* fail since the FP conversation info is never attached */ /* Usefull for DCH streams containing CS data and don't have their own heuristic method */ @@ -5125,6 +5318,9 @@ heur_dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data match = heur_dissect_fp_hsdsch_type_2(tvb, pinfo, tree, data); if(match) return TRUE; + match = heur_dissect_fp_edch_type_1(tvb, pinfo, tree, data); + if(match) + return TRUE; /* NOTE: Add new heuristic dissectors BEFORE the 'unknown format' dissector */ /* since it might 'swallow' packets if the UDP stream is framed as 'CHANNEL_UNKNOWN' */ match = heur_dissect_fp_unknown_format(tvb, pinfo, tree, data); |