aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-umts_fp.c
diff options
context:
space:
mode:
authorDarien Spencer <cusneud@mail.com>2018-09-23 13:57:37 +0300
committerAnders Broman <a.broman58@gmail.com>2018-10-15 05:13:50 +0000
commitc6dc4095b7aba75113e24868f174c3d4962075ca (patch)
tree9a377a4362952e0f27d871cbf3f0eb3119f27f0f /epan/dissectors/packet-umts_fp.c
parentb0759a02bb0759aaa6ec3cfdac345d27c6108494 (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.c198
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);