summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS.src4
-rw-r--r--epan/dissectors/packet-umts_fp.c681
-rw-r--r--epan/dissectors/packet-umts_fp.h3
3 files changed, 668 insertions, 20 deletions
diff --git a/AUTHORS.src b/AUTHORS.src
index 076fce214d..c9dfea721f 100644
--- a/AUTHORS.src
+++ b/AUTHORS.src
@@ -3699,6 +3699,10 @@ Kim Kempf <kim.kempf[AT]apcon.com> {
802.1BR E-Tag dissector
}
+S. Shapira <sswsdev[AT]gmail.com> {
+ UMTS FP heuristic dissectors
+}
+
and by:
Georgi Guninski <guninski[AT]guninski.com>
diff --git a/epan/dissectors/packet-umts_fp.c b/epan/dissectors/packet-umts_fp.c
index e384ebcac2..f1e024018a 100644
--- a/epan/dissectors/packet-umts_fp.c
+++ b/epan/dissectors/packet-umts_fp.c
@@ -480,30 +480,30 @@ static const value_string common_control_frame_type_vals[] = {
/* 0 to 7*/
static const guint8 hsdsch_macdflow_id_rlc_map[] = {
- RLC_UM, /*0 SRB */
- RLC_AM, /*1 Interactive PS*/
- RLC_AM, /*2 Interatcive PS*/
- RLC_UNKNOWN_MODE, /*3 ???*/
- RLC_AM, /*4 Streaming PS*/
- RLC_UNKNOWN_MODE,
- RLC_UNKNOWN_MODE,
- RLC_UNKNOWN_MODE
+ RLC_UM, /*0 SRB */
+ RLC_AM, /*1 Interactive PS*/
+ RLC_AM, /*2 Interatcive PS*/
+ RLC_UNKNOWN_MODE, /*3 ???*/
+ RLC_AM, /*4 Streaming PS*/
+ RLC_UNKNOWN_MODE,
+ RLC_UNKNOWN_MODE,
+ RLC_UNKNOWN_MODE
};
/* Mapping hsdsch MACd-FlowId to MAC_CONTENT, basically flowid = 1 (0) => SRB*/
/* 1 to 8*/
static const guint8 hsdsch_macdflow_id_mac_content_map[] = {
- MAC_CONTENT_DCCH, /*1 SRB */
- MAC_CONTENT_PS_DTCH, /*2 Interactive PS*/
- MAC_CONTENT_PS_DTCH, /*3 Interatcive PS*/
- RLC_UNKNOWN_MODE, /*4 ???*/
- MAC_CONTENT_PS_DTCH, /*5 Streaming PS*/
- RLC_UNKNOWN_MODE,
- RLC_UNKNOWN_MODE,
- RLC_UNKNOWN_MODE
- };
-
-/* Make fake logical channel id's based on MACdFlow-ID's,
+ MAC_CONTENT_DCCH, /*1 SRB */
+ MAC_CONTENT_PS_DTCH, /*2 Interactive PS*/
+ MAC_CONTENT_PS_DTCH, /*3 Interatcive PS*/
+ RLC_UNKNOWN_MODE, /*4 ???*/
+ MAC_CONTENT_PS_DTCH, /*5 Streaming PS*/
+ RLC_UNKNOWN_MODE,
+ RLC_UNKNOWN_MODE,
+ RLC_UNKNOWN_MODE
+};
+
+/* Make fake logical channel id's based on MACdFlow-ID's,
* XXXX Bug 12121 expanded the number of entries to 8(+2),
* not at all sure what the proper value should be 0xfF?
*/
@@ -3828,6 +3828,645 @@ void dissect_hsdsch_common_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto
dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length);
}
}
+/* Validates the header CRC in a Control FP frame */
+/* Should only be used in heuristic dissectors! */
+static gboolean
+check_control_frame_crc_for_heur(tvbuff_t * tvb)
+{
+ guint8 crc = 0;
+ guint8 calc_crc = 0;
+ guint8 * data = NULL;
+
+ crc = tvb_get_guint8(tvb, 0) >> 1;
+ /* Get data. */
+ data = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_reported_length(tvb));
+ /* Include only FT flag bit in CRC calculation. */
+ data[0] = data[0] & 1;
+ calc_crc = crc7update(0, data, tvb_reported_length(tvb));
+ calc_crc = crc7finalize(calc_crc);
+
+ return calc_crc == crc;
+}
+/* Validates the header CRC in a Data FP frame */
+/* Should only be used in heuristic dissectors! */
+static gboolean
+check_header_crc_for_heur(tvbuff_t *tvb, guint16 header_length)
+{
+ guint8 crc = 0;
+ guint8 calc_crc = 0;
+ guint8 * data = NULL;
+
+ crc = tvb_get_guint8(tvb, 0) >> 1;
+ /* Get data of header excluding the first byte */
+ data = (guint8 *)tvb_get_ptr(tvb, 1, header_length - 1);
+
+ calc_crc = crc7update(0, data, header_length - 1);
+ calc_crc = crc7finalize(calc_crc);
+
+ return calc_crc == crc;
+}
+/* Validates the payload CRC in a Data FP frame */
+/* Should only be used in heuristic dissectors! */
+static gboolean
+check_payload_crc_for_heur(tvbuff_t *tvb, guint16 header_length)
+{
+ guint16 frame_length;
+ guint16 crc_index;
+ guint16 crc = 0;
+ guint16 calc_crc = 0;
+ guint16 payload_index;
+ guint16 payload_length;
+ guint8 *data = NULL;
+
+ frame_length = tvb_reported_length(tvb);
+ if (frame_length < 2) {
+ return FALSE;
+ }
+ /* Payload CRC is in the last 2 bytes of the packet */
+ crc_index = frame_length - 2;
+ crc = tvb_get_bits16(tvb, crc_index * 8, 16, ENC_BIG_ENDIAN);
+
+ payload_index = header_length; /* payload first index is the same as the header length */
+ payload_length = (frame_length - payload_index) - 2;
+ data = (guint8 *)tvb_get_ptr(tvb, payload_index, payload_length);
+ calc_crc = crc16_8005_noreflect_noxor(data, payload_length);
+
+ return calc_crc == crc;
+}
+/* Generates a unique 32bit identifier based on the frame's meta data */
+/* This ID is used in the RLC dissector for reassembly */
+/* Should only be used in heuristic dissectors! */
+static guint32
+generate_ue_id_for_heur(packet_info *pinfo)
+{
+ if (pinfo->ptype != PT_UDP && pinfo->src.type == AT_IPv4 && pinfo->dst.type == AT_IPv4) {
+ /* This logic assumes FP is delivered over IP/UDP*/
+ /* Will return the same ID even if the address and ports are reversed */
+
+ /* srcXor: [ ------- Source Address ------- ] (4 bytes)*/
+ /* XOR */
+ /* [ Source Port ][ Source Port ] (4 bytes)*/
+ int srcXor = *((guint32*)pinfo->src.data) ^ ((pinfo->srcport << 16) | (pinfo->srcport));
+
+ /* dstXor: [ ---- Destination Address ---- ] (4 bytes)*/
+ /* XOR */
+ /* [ - Dest Port - ][ - Dest Port - ] (4 bytes)*/
+ int dstXor = *((guint32*)pinfo->dst.data) ^ ((pinfo->destport << 16) | (pinfo->destport));
+ return srcXor ^ dstXor;
+ }
+ else {
+ /* Fallback - When IP and/or UDP are missing for whatever reason */
+ /* Using the frame number of the first heuristicly dissected frame as the UE ID should be unique enough */
+ /* The bitwise NOT operator is used to prevent low UE ID values which are likely to collide with legitimate UE IDs derived from C-RNTIs in FACH/RACH */
+ return ~(pinfo->num);
+ }
+}
+/*
+* Attaches conversation info to both the downlink and uplink 'conversations' (streams)
+* (Required since only one of them is checked in every dissected FP packet)
+*/
+static void
+fill_pch_coversation_info_for_heur(umts_fp_conversation_info_t* umts_fp_conversation_info ,packet_info *pinfo)
+{
+ 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_PCH;
+ umts_fp_conversation_info->num_dch_in_flow = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].num_dl_chans = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_num_tbs[1] = 1;
+}
+static void
+set_both_sides_umts_fp_conv_data(packet_info *pinfo, umts_fp_conversation_info_t *umts_fp_conversation_info)
+{
+ conversation_t *packet_direction_conv;
+ conversation_t *other_direction_conv;
+
+ if (pinfo == NULL) {
+ return;
+ }
+
+ /* Finding or creating conversation for the way the packet is heading */
+ packet_direction_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ pinfo->ptype,
+ pinfo->destport, pinfo->srcport, NO_ADDR_B);
+
+ if (packet_direction_conv == NULL) {
+ /* Conversation does not exist yet, creating one now. */
+ packet_direction_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ pinfo->ptype,
+ pinfo->destport, pinfo->srcport, NO_ADDR_B);
+ }
+ conversation_add_proto_data(packet_direction_conv, proto_fp, umts_fp_conversation_info);
+
+ /* Finding or creating conversation for the other side */
+ other_direction_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_src, &pinfo->net_dst,
+ pinfo->ptype,
+ pinfo->srcport, pinfo->destport, NO_ADDR_B);
+
+ if (other_direction_conv == NULL) {
+ /* Conversation does not exist yet, creating one now. */
+ other_direction_conv = conversation_new(pinfo->num, &pinfo->net_src, &pinfo->net_dst,
+ pinfo->ptype,
+ pinfo->srcport, pinfo->destport, NO_ADDR_B);
+ }
+ conversation_add_proto_data(other_direction_conv, proto_fp, umts_fp_conversation_info);
+
+}
+static gboolean
+heur_dissect_fp_dcch_over_dch(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;
+ struct fp_info *p_fp_info;
+ int length;
+ guint8 frame_type;
+ guint8 tfi;
+
+ /* Trying to find existing conversation */
+ p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ 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) {
+ if (umts_fp_conversation_info->channel == CHANNEL_DCH) {
+ conversation_set_dissector(p_conv, fp_handle);
+ dissect_fp(tvb, pinfo, tree, data);
+ return TRUE;
+ }
+ else {
+ 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;
+ }
+
+ frame_type = tvb_get_guint8(tvb, 0) & 0x01;
+ if (frame_type == 1) { /* is 'control' frame type*/
+ /* Asserting that the Header CRC is correct */
+ if (!check_control_frame_crc_for_heur(tvb)) {
+ return FALSE;
+ }
+ /* All checks passed - This is an unknown FP frame. */
+ /* To allow dissection of this frame after umts_fp_conversation_info will be added in a later frame */
+ /* the conversation must be created here if it doesn't exist yet*/
+ if (p_conv == NULL) {
+ p_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ pinfo->ptype,
+ pinfo->destport, pinfo->srcport, NO_ADDR_B);
+ }
+ return FALSE;
+ }
+
+ length = tvb_reported_length(tvb);
+ tfi = tvb_get_guint8(tvb, 2) & 0x1f;
+
+ /* Checking if this is a DCH frame with 0 TBs*/
+ if (tfi == 0x00)
+ {
+ if (length != 5 /* DL */ && length != 7 /* UL */) {
+ return FALSE;
+ }
+ if (!check_header_crc_for_heur(tvb, 3)) {
+ return FALSE;
+ }
+ if (!check_payload_crc_for_heur(tvb, 3)) {
+ return FALSE;
+ }
+ /* All checks passed - This is an unknown DCH FP frame. */
+ /* To allow dissection of this frame after umts_fp_conversation_info will be added in a later frame */
+ /* the conversation must be created here if it doesn't exist yet*/
+ if (p_conv == NULL) {
+ p_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ pinfo->ptype,
+ pinfo->destport, pinfo->srcport, NO_ADDR_B);
+ }
+ return FALSE;
+ }
+
+ /* Checking this is a DCH frame with 1 TB */
+ if (tfi != 0x01) {
+ return FALSE;
+ }
+
+ /* Expecting specific lengths: 24 for downlink frames, 26 for uplink frames */
+ length = tvb_reported_length(tvb);
+ if (length != 24 /* DL */ && length != 26 /* UL */) {
+ return FALSE;
+ }
+
+ if (!check_header_crc_for_heur(tvb, 3)) {
+ return FALSE;
+ }
+ if (!check_payload_crc_for_heur(tvb, 3)) {
+ return FALSE;
+ }
+
+ umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ 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;
+ if (length == 24 || length == 5) { /* Downlink */
+ copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src);
+ umts_fp_conversation_info->crnc_port = pinfo->srcport;
+ }
+ else { /* Uplink*/
+ copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->dst);
+ umts_fp_conversation_info->crnc_port = pinfo->destport;
+ }
+ umts_fp_conversation_info->channel = CHANNEL_DCH;
+ umts_fp_conversation_info->num_dch_in_flow = 1;
+ umts_fp_conversation_info->dchs_in_flow_list[0] = 31;
+ umts_fp_conversation_info->fp_dch_channel_info[0].num_dl_chans = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_num_tbs[1] = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = 148;
+ umts_fp_conversation_info->fp_dch_channel_info[0].num_ul_chans = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_num_tbs[1] = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_tf_size[1] = 148;
+ set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
+ conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle);
+ dissect_fp(tvb, pinfo, tree, data);
+ return TRUE;
+}
+static gboolean
+heur_dissect_fp_fach(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;
+ struct fp_info *p_fp_info;
+ int length;
+ guint8 frame_type;
+ guint8 tfi;
+ guint8 tctf;
+
+ /* Finding or creating conversation */
+ p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ 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) {
+ if (umts_fp_conversation_info->channel == CHANNEL_FACH_FDD) {
+ conversation_set_dissector(p_conv, fp_handle);
+ dissect_fp(tvb, pinfo, tree, data);
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+ }
+ }
+
+ /* Expecting specific lengths: 27 for frames with 1 TB, 48 for frames with 2 TBs */
+ length = tvb_reported_length(tvb);
+ if (length != 27 && length != 48) {
+ return FALSE;
+ }
+
+ p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
+
+ /* Making sure FP info isn't already attached */
+ if (p_fp_info) {
+ return FALSE;
+ }
+
+ frame_type = tvb_get_guint8(tvb, 0) & 0x01;
+ if (frame_type == 1) { /* is 'control' frame type*/
+ /* We can't tell the FP type and content of control frames */
+ return FALSE;
+ }
+
+ tfi = tvb_get_guint8(tvb, 2) & 0x1f;
+ if (length == 27 && tfi != 0x01) {
+ return FALSE;
+ }
+ if (length == 48 && tfi != 0x02) {
+ return FALSE;
+ }
+
+ tctf = tvb_get_guint8(tvb, 4);
+ /* Asserting the TCTF field contains a valid (non reserved) value according to TS 25.321 Table 9.2.1-2 */
+ if (tctf != 0x40 && /* CCCH */
+ tctf != 0x50 && /* MCCH */
+ tctf != 0x5F && /* MSCH */
+ tctf != 0x80 && /* CTCH */
+ (tctf >> 4) != 0x06 && /* MTCH */
+ (tctf >> 6) != 0x00 && /* BCCH */
+ (tctf >> 6) != 0x03) { /* DCCH or DTCH over FACH */
+ return FALSE;
+ }
+
+ if (!check_header_crc_for_heur(tvb, 4)) {
+ return FALSE;
+ }
+ if (!check_payload_crc_for_heur(tvb, 4)) {
+ return FALSE;
+ }
+
+ umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ 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_FACH_FDD;
+ umts_fp_conversation_info->num_dch_in_flow = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].num_dl_chans = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_num_tbs[1] = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = 168;
+ umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_num_tbs[2] = 2;
+ umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[2] = 168;
+ set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
+ conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle);
+ dissect_fp(tvb, pinfo, tree, data);
+ return TRUE;
+}
+static gboolean
+heur_dissect_fp_rach(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;
+ struct fp_info *p_fp_info;
+ int length;
+ guint8 frame_type;
+ guint8 tfi;
+ guint8 tctf;
+
+ /* Finding or creating conversation */
+ p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ 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) {
+ if (umts_fp_conversation_info->channel == CHANNEL_RACH_FDD) {
+ conversation_set_dissector(p_conv, fp_handle);
+ dissect_fp(tvb, pinfo, tree, data);
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+ }
+ }
+
+ /* Expecting specific lengths: all rach frames are 28 bytes long */
+ length = tvb_reported_length(tvb);
+ if (length != 28) {
+ return FALSE;
+ }
+
+ p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
+
+ /* Making sure FP info isn't already attached */
+ if (p_fp_info) {
+ return FALSE;
+ }
+
+ frame_type = tvb_get_guint8(tvb, 0) & 0x01;
+ if (frame_type == 1) { /* is 'control' frame type*/
+ /* We can't tell the FP type and content of control frames */
+ return FALSE;
+ }
+
+ tfi = tvb_get_guint8(tvb, 2) & 0x1f;
+ if (tfi != 0x00) {
+ return FALSE;
+ }
+
+ tctf = tvb_get_guint8(tvb, 4) >> 6;
+ /* Asserting the TCTF field contains a valid (non reserved) value according to TS 25.321 Table 9.2.1-4 */
+ if (tctf != 0x00 && /* CCCH */
+ tctf != 0x01) /* DCCH over RACH */
+ {
+ return FALSE;
+ }
+
+ if (!check_header_crc_for_heur(tvb, 4)) {
+ return FALSE;
+ }
+ if (!check_payload_crc_for_heur(tvb, 4)) {
+ return FALSE;
+ }
+
+ umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ 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->dst);
+ umts_fp_conversation_info->crnc_port = pinfo->destport;
+ umts_fp_conversation_info->channel = CHANNEL_RACH_FDD;
+ umts_fp_conversation_info->num_dch_in_flow = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].num_ul_chans = 0;
+ umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_num_tbs[0] = 1;
+ umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_tf_size[0] = 168;
+ set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
+ conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle);
+ dissect_fp(tvb, pinfo, tree, data);
+ return TRUE;
+}
+static gboolean
+heur_dissect_fp_pch(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;
+ struct fp_info *p_fp_info;
+ int length;
+ guint8 frame_type;
+ guint8 reserved_bits;
+ guint8 tfi;
+ guint8 pi_byte_length;
+ gboolean pi_present;
+ gboolean tb_size_found;
+ gboolean pi_length_found;
+
+ /* To correctly dissect a PCH stream 2 parameters are required: PI Bitmap length & TB length */
+ /* Unfortunately, both are optional in each packet and in some cases no packet will contain both */
+ /* Hence gathering the info from 2 different frames is sometimes required. */
+
+ length = tvb_reported_length(tvb);
+
+ /* Finding or creating conversation */
+ p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ 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) {
+ if (umts_fp_conversation_info->channel == CHANNEL_PCH) {
+ pi_length_found = umts_fp_conversation_info->paging_indications != 0;
+ tb_size_found = umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] != 0;
+ if (pi_length_found && tb_size_found) {
+ /* Stream already framed - contains both PI length and TB size */
+ dissect_fp(tvb, pinfo, tree, data);
+ return TRUE;
+ }
+ }
+ else {
+ return FALSE;
+ }
+ }
+ else {
+ /* FP conversatio info not attached - no PCH info is known */
+ tb_size_found = FALSE;
+ pi_length_found = FALSE;
+ }
+ }
+ else {
+ /* A conversatio does not exist yet - no PCH info is known */
+ tb_size_found = FALSE;
+ pi_length_found = FALSE;
+ }
+
+ p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
+ /* Making sure FP info isn't already attached */
+ if (p_fp_info) {
+ return FALSE;
+ }
+
+ frame_type = tvb_get_guint8(tvb, 0) & 0x01;
+ if (frame_type == 1) { /* is 'control' frame type*/
+ /* We can't tell the FP type and content of control frames */
+ return FALSE;
+ }
+
+ /* Checking bits after CFN and before PI indicator are zeroed */
+ reserved_bits = tvb_get_guint8(tvb, 2) & 0x0E;
+ if (reserved_bits != 0x00) {
+ return FALSE;
+ }
+
+ tfi = tvb_get_guint8(tvb, 3) & 0x1f;
+ if (tfi != 0x00 && tfi != 0x01) {
+ return FALSE;
+ }
+
+ if (!check_header_crc_for_heur(tvb, 4)) {
+ return FALSE;
+ }
+ if (!check_payload_crc_for_heur(tvb, 4)) {
+ return FALSE;
+ }
+
+ pi_present = tvb_get_guint8(tvb, 2) & 0x01; /* Rightmost bit in the 3rd byte */
+ if (pi_present) {
+ if (tfi == 0x00 && !pi_length_found) {
+ /* PI Bitmap present and No TB. Can calculate PI bitmap length */
+ guint8 pi_bit_length;
+ pi_byte_length = length - 6; /* Removing header length (4) and footer length (2)*/
+ switch (pi_byte_length)
+ {
+ case 3: /* 18 bits bitmap + padding */
+ pi_bit_length = 18;
+ break;
+ case 5: /* 36 bits bitmap + padding */
+ pi_bit_length = 36;
+ break;
+ case 9: /* 72 bits bitmap */
+ pi_bit_length = 72;
+ break;
+ case 18: /* 144 bits bitmap */
+ pi_bit_length = 144;
+ break;
+ default:
+ return FALSE;
+ }
+ if (p_conv == NULL) {
+ /* Conversation does not exist yet, creating one now. */
+ p_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ pinfo->ptype,
+ pinfo->destport, pinfo->srcport, NO_ADDR_B);
+ }
+ if (!umts_fp_conversation_info) {
+ umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ fill_pch_coversation_info_for_heur(umts_fp_conversation_info, pinfo);
+ }
+ umts_fp_conversation_info->paging_indications = pi_bit_length;
+ set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
+ pi_length_found = TRUE;
+ }
+ else if (tfi == 0x01 && !tb_size_found && pi_present) {
+ /* TB present and PI bitmap length is known. Can calculate TB length.*/
+ pi_byte_length = (umts_fp_conversation_info->paging_indications + 7) / 8;
+ if (p_conv == NULL) {
+ /* Conversation does not exist yet, creating one now. */
+ p_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ pinfo->ptype,
+ pinfo->destport, pinfo->srcport, NO_ADDR_B);
+ }
+ if (!umts_fp_conversation_info) {
+ umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ fill_pch_coversation_info_for_heur(umts_fp_conversation_info, pinfo);
+ }
+ umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = (length - (pi_byte_length + 6)) * 8; /* Removing header length (4), footer length (2) and PI bitmap length*/
+ set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
+ tb_size_found = TRUE;
+ }
+ }
+ else {
+ if (tfi == 0x01 && !tb_size_found) {
+ /* TB present and PI bitmap is missing. Can calculate TB length.*/
+ if (p_conv == NULL) {
+ /* Conversation does not exist yet, creating one now. */
+ p_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
+ pinfo->ptype,
+ pinfo->destport, pinfo->srcport, NO_ADDR_B);
+ }
+ if (!umts_fp_conversation_info) {
+ umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ fill_pch_coversation_info_for_heur(umts_fp_conversation_info, pinfo);
+ }
+ umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = (length - 6) * 8; /* Removing header length (4), footer length (2) */
+ set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
+ tb_size_found = TRUE;
+ }
+ }
+
+ if (pi_length_found && tb_size_found) {
+ /* Stream completely framed! */
+ conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle);
+ dissect_fp(tvb, pinfo, tree, data);
+ return TRUE;
+ }
+ else {
+ /* Some data still missing */
+ return FALSE;
+ }
+}
+/* This method can frame UDP streams containing FP packets but dissection of those packets will */
+/* fail since the FP conversation info is never attached */
static gboolean
heur_dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
@@ -5744,6 +6383,10 @@ void proto_reg_handoff_fp(void)
mac_fdd_hsdsch_handle = find_dissector_add_dependency("mac.fdd.hsdsch", proto_fp);
heur_dissector_add("udp", heur_dissect_fp, "FP over UDP", "fp_udp", proto_fp, HEURISTIC_DISABLE);
+ heur_dissector_add("udp", heur_dissect_fp_dcch_over_dch, "FP over UDP (DCCH over DCH)", "fp_udp_dcch_dch", proto_fp, HEURISTIC_DISABLE);
+ heur_dissector_add("udp", heur_dissect_fp_fach, "FP over UDP (FACH)", "fp_udp_fach", proto_fp, HEURISTIC_DISABLE);
+ heur_dissector_add("udp", heur_dissect_fp_rach, "FP over UDP (RACH)", "fp_udp_rach", proto_fp, HEURISTIC_DISABLE);
+ heur_dissector_add("udp", heur_dissect_fp_pch, "FP over UDP (PCH)", "fp_udp_pch", proto_fp, HEURISTIC_DISABLE);
fp_aal2_handle = create_dissector_handle(dissect_fp_aal2, proto_fp);
dissector_add_uint("atm.aal2.type", TRAF_UMTS_FP, fp_aal2_handle);
diff --git a/epan/dissectors/packet-umts_fp.h b/epan/dissectors/packet-umts_fp.h
index 9a1365df7f..3d7ac5107c 100644
--- a/epan/dissectors/packet-umts_fp.h
+++ b/epan/dissectors/packet-umts_fp.h
@@ -146,7 +146,8 @@ typedef struct
guint32 dl_frame_number; /* the frame where this conversation is started from CRNC */
guint32 ul_frame_number; /* the frame where this conversation is started from Node B */
address crnc_address;
- guint16 crnc_port;
+ guint16 /* Expecting specific lengths: 27 for frames with 1 TB, 48 for frames with 2 TBs */
+ crnc_port;
gint com_context_id; /*Identifies a single UE in the network*/
/* For PCH channel */