summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarien Spencer <cusneud@mail.com>2017-06-23 04:43:05 -0700
committerPascal Quantin <pascal.quantin@gmail.com>2017-06-28 21:01:05 +0000
commitf48305069ca93cca5ecb9a66fcc8b42d84dd6cf7 (patch)
tree97616fcd307c422a2720481633280a0e1f6974d1
parent5c25e7442f8aa394de723af09a2ba2e38bd456c0 (diff)
downloadwireshark-f48305069ca93cca5ecb9a66fcc8b42d84dd6cf7.tar.gz
FP: Combining heuristic dissectors
Combining all seperate heuristic dissector into one 'fp over udp' dissector. Also refactored the 'unknown format' dissector (formarly heur_dissect_fp) so it could work 'chained' to the others. Change-Id: I396c362a400f51171ee091317b6735dfd8bd19df Reviewed-on: https://code.wireshark.org/review/22368 Petri-Dish: Pascal Quantin <pascal.quantin@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
-rw-r--r--epan/dissectors/packet-catapult-dct2000.c2
-rw-r--r--epan/dissectors/packet-umts_fp.c382
-rw-r--r--epan/dissectors/packet-umts_fp.h1
3 files changed, 240 insertions, 145 deletions
diff --git a/epan/dissectors/packet-catapult-dct2000.c b/epan/dissectors/packet-catapult-dct2000.c
index a0474d1d5c..914daea796 100644
--- a/epan/dissectors/packet-catapult-dct2000.c
+++ b/epan/dissectors/packet-catapult-dct2000.c
@@ -1692,7 +1692,7 @@ static void attach_rlc_info(packet_info *pinfo, guint32 urnti, guint8 rbid,
/* Allocate structs */
p_rlc_info = wmem_new(wmem_file_scope(), struct rlc_info);
- p_fp_info = wmem_new(wmem_file_scope(), struct fp_info);
+ p_fp_info = wmem_new0(wmem_file_scope(), struct fp_info);
/* Fill in struct fields for first (only) PDU in this frame */
diff --git a/epan/dissectors/packet-umts_fp.c b/epan/dissectors/packet-umts_fp.c
index 8a1bdc9f92..cafe80d1f3 100644
--- a/epan/dissectors/packet-umts_fp.c
+++ b/epan/dissectors/packet-umts_fp.c
@@ -50,6 +50,7 @@
* - Set the logical channel properly for non multiplexed, channels
* for channels that doesn't have the C/T flag! This should be based
* on the RRC message RadioBearerSetup.
+ * - E-DCH (T1 & T2) heuristic dissectors
*/
void proto_register_fp(void);
void proto_reg_handoff_fp(void);
@@ -3910,6 +3911,10 @@ check_control_frame_crc_for_heur(tvbuff_t * tvb)
guint8 crc = 0;
guint8 calc_crc = 0;
guint8 * data = NULL;
+ guint reported_length = tvb_reported_length(tvb);
+
+ if (reported_length == 0 || reported_length > tvb_captured_length(tvb))
+ return FALSE;
crc = tvb_get_guint8(tvb, 0) >> 1;
/* Get data. */
@@ -3930,6 +3935,9 @@ check_header_crc_for_heur(tvbuff_t *tvb, guint16 header_length)
guint8 calc_crc = 0;
guint8 * data = NULL;
+ if (header_length > tvb_captured_length(tvb))
+ return FALSE;
+
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);
@@ -3944,7 +3952,7 @@ check_header_crc_for_heur(tvbuff_t *tvb, guint16 header_length)
static gboolean
check_payload_crc_for_heur(tvbuff_t *tvb, guint16 header_length)
{
- guint16 frame_length;
+ guint16 reported_length;
guint16 crc_index;
guint16 crc = 0;
guint16 calc_crc = 0;
@@ -3952,16 +3960,16 @@ check_payload_crc_for_heur(tvbuff_t *tvb, guint16 header_length)
guint16 payload_length;
guint8 *data = NULL;
- frame_length = tvb_reported_length(tvb);
- if (frame_length < 2) {
+ reported_length = tvb_reported_length(tvb);
+ if (reported_length < 2 || reported_length > tvb_captured_length(tvb)) {
return FALSE;
}
/* Payload CRC is in the last 2 bytes of the packet */
- crc_index = frame_length - 2;
+ crc_index = reported_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;
+ payload_length = (reported_length - payload_index) - 2;
data = (guint8 *)tvb_get_ptr(tvb, payload_index, payload_length);
calc_crc = crc16_8005_noreflect_noxor(data, payload_length);
@@ -4060,9 +4068,10 @@ 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;
+ umts_fp_conversation_info_t* umts_fp_conversation_info = NULL;
struct fp_info *p_fp_info;
- int length;
+ guint32 captured_length;
+ guint32 reported_length;
guint8 frame_type;
guint8 tfi;
@@ -4080,7 +4089,8 @@ heur_dissect_fp_dcch_over_dch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
dissect_fp(tvb, pinfo, tree, data);
return TRUE;
}
- else {
+ else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){
+ /* This conversation was successfuly framed as ANOTHER type */
return FALSE;
}
}
@@ -4094,28 +4104,21 @@ heur_dissect_fp_dcch_over_dch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
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) {
- 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);
+ /* Making sure we have at least enough bytes for header (3) + footer (2) */
+ captured_length = tvb_captured_length(tvb);
+ reported_length = tvb_reported_length(tvb);
+ if (captured_length < 5) {
+ return FALSE;
+ }
tfi = tvb_get_guint8(tvb, 2) & 0x1f;
/* Checking if this is a DCH frame with 0 TBs*/
- if (tfi == 0x00)
+ if (captured_length == 0x00)
{
- if (length != 5 /* DL */ && length != 7 /* UL */) {
+ if (reported_length != 5 /* DL */ && reported_length != 7 /* UL */) {
return FALSE;
}
if (!check_header_crc_for_heur(tvb, 3)) {
@@ -4142,8 +4145,7 @@ heur_dissect_fp_dcch_over_dch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
/* Expecting specific lengths: 24 for downlink frames, 26 for uplink frames */
/* This is the common Transport Format of DCCH over DCH ( See 3GPP TR 25.944 / 4.1.1.3.1.1 ) */
- length = tvb_reported_length(tvb);
- if (length != 24 /* DL */ && length != 26 /* UL */) {
+ if (reported_length != 24 /* DL */ && reported_length != 26 /* UL */) {
return FALSE;
}
@@ -4154,7 +4156,10 @@ heur_dissect_fp_dcch_over_dch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
return FALSE;
}
- umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ 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;
@@ -4162,7 +4167,7 @@ heur_dissect_fp_dcch_over_dch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
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) { /* Downlink */
+ if (reported_length == 24) { /* Downlink */
copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src);
umts_fp_conversation_info->crnc_port = pinfo->srcport;
}
@@ -4179,7 +4184,6 @@ heur_dissect_fp_dcch_over_dch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
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;
@@ -4189,9 +4193,10 @@ heur_dissect_fp_fach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
{
conversation_t *p_conv;
fp_fach_channel_info_t* fp_fach_channel_info;
- umts_fp_conversation_info_t* umts_fp_conversation_info;
+ umts_fp_conversation_info_t* umts_fp_conversation_info = NULL;
struct fp_info *p_fp_info;
- int length;
+ guint32 captured_length;
+ guint32 reported_length;
guint8 frame_type;
guint8 tfi;
guint8 tctf;
@@ -4210,16 +4215,22 @@ heur_dissect_fp_fach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
dissect_fp(tvb, pinfo, tree, data);
return TRUE;
}
- else {
+ else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){
+ /* This conversation was successfuly framed as ANOTHER type */
return FALSE;
}
}
}
+ /* Making sure we have at least enough bytes for header (4) + footer (2) */
+ captured_length = tvb_captured_length(tvb);
+ if(captured_length < 6) {
+ return FALSE;
+ }
/* Expecting specific lengths: 27 for frames with 1 TB, 48 for frames with 2 TBs */
/* This is the common Transport Format of FACH ( See 3GPP TR 25.944 / 4.1.1.2 'FACH2' ) */
- length = tvb_reported_length(tvb);
- if (length != 27 && length != 48) {
+ reported_length = tvb_reported_length(tvb);
+ if (reported_length != 27 && reported_length != 48) {
return FALSE;
}
@@ -4237,10 +4248,10 @@ heur_dissect_fp_fach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
}
tfi = tvb_get_guint8(tvb, 2) & 0x1f;
- if (length == 27 && tfi != 0x01) {
+ if (reported_length == 27 && tfi != 0x01) {
return FALSE;
}
- if (length == 48 && tfi != 0x02) {
+ if (reported_length == 48 && tfi != 0x02) {
return FALSE;
}
@@ -4263,7 +4274,10 @@ heur_dissect_fp_fach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
return FALSE;
}
- umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ 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;
@@ -4285,7 +4299,6 @@ heur_dissect_fp_fach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
fp_fach_channel_info->crnti_to_urnti_map = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
umts_fp_conversation_info->channel_specific_info = (void*)fp_fach_channel_info;
- 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;
@@ -4295,9 +4308,10 @@ heur_dissect_fp_rach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
{
conversation_t *p_conv;
fp_rach_channel_info_t* fp_rach_channel_info;
- umts_fp_conversation_info_t* umts_fp_conversation_info;
+ umts_fp_conversation_info_t* umts_fp_conversation_info = NULL;
struct fp_info *p_fp_info;
- int length;
+ guint32 captured_length;
+ guint32 reported_length;
guint8 frame_type;
guint8 tfi;
guint8 tctf;
@@ -4316,16 +4330,23 @@ heur_dissect_fp_rach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
dissect_fp(tvb, pinfo, tree, data);
return TRUE;
}
- else {
+ else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){
+ /* This conversation was successfuly framed as ANOTHER type */
return FALSE;
}
}
}
+ /* Making sure we have at least enough bytes for header (4) + footer (2) */
+ captured_length = tvb_captured_length(tvb);
+ if(captured_length < 6) {
+ return FALSE;
+ }
+
/* Expecting specific lengths: rach frames are either 28 or 52 bytes long */
/* This is the common Transport Formats of RACH ( See 3GPP TR 25.944 / 4.1.2.1 ) */
- length = tvb_reported_length(tvb);
- if (length != 28 && length != 52) {
+ reported_length = tvb_reported_length(tvb);
+ if (reported_length != 28 && reported_length != 52) {
return FALSE;
}
@@ -4343,10 +4364,10 @@ heur_dissect_fp_rach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
}
tfi = tvb_get_guint8(tvb, 2) & 0x1f;
- if (length == 28 && tfi != 0x00) {
+ if (reported_length == 28 && tfi != 0x00) {
return FALSE;
}
- if (length == 52 && tfi != 0x01) {
+ if (reported_length == 52 && tfi != 0x01) {
return FALSE;
}
@@ -4365,7 +4386,10 @@ heur_dissect_fp_rach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
return FALSE;
}
- umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ 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;
@@ -4388,7 +4412,6 @@ heur_dissect_fp_rach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
fp_rach_channel_info->crnti_to_urnti_map = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
umts_fp_conversation_info->channel_specific_info = (void*)fp_rach_channel_info;
- 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;
@@ -4400,7 +4423,8 @@ heur_dissect_fp_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *d
umts_fp_conversation_info_t* umts_fp_conversation_info = NULL;
fp_pch_channel_info_t* fp_pch_channel_info = NULL;
struct fp_info *p_fp_info;
- int length;
+ guint32 captured_length;
+ guint32 reported_length;
guint8 frame_type;
guint8 reserved_bits;
guint8 tfi;
@@ -4415,8 +4439,6 @@ heur_dissect_fp_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *d
/* is not helpful.*/
/* Hence gathering the info from 2 different frames is 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,
@@ -4437,24 +4459,31 @@ heur_dissect_fp_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *d
return TRUE;
}
}
- else {
+ else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){
+ /* This conversation was successfuly framed as ANOTHER type */
return FALSE;
}
+ else {
+ /* FP conversation info attached and the channel type is UNKNOWN - might be PCH */
+ tb_size_found = FALSE;
+ pi_length_found = FALSE;
+ }
}
else {
- /* FP conversatio info not attached - no PCH info is known */
+ /* FP conversation 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 */
+ /* A conversation does not exist yet - no PCH info is known */
tb_size_found = FALSE;
pi_length_found = FALSE;
}
/* Making sure we have at least enough bytes for header (4) + footer (2) */
- if (length < 6) {
+ captured_length = tvb_captured_length(tvb);
+ if(captured_length < 6) {
return FALSE;
}
@@ -4488,12 +4517,13 @@ heur_dissect_fp_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *d
return FALSE;
}
+ reported_length = tvb_reported_length(tvb);
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)*/
+ pi_byte_length = reported_length - 6; /* Removing header length (4) and footer length (2)*/
switch (pi_byte_length)
{
case 3: /* 18 bits bitmap + padding */
@@ -4514,10 +4544,10 @@ heur_dissect_fp_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *d
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);
+ set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
fp_pch_channel_info = (fp_pch_channel_info_t*)umts_fp_conversation_info->channel_specific_info;
}
fp_pch_channel_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_length_found) {
@@ -4525,13 +4555,13 @@ heur_dissect_fp_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *d
pi_byte_length = (fp_pch_channel_info->paging_indications + 7) / 8;
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);
fill_pch_coversation_info_for_heur(umts_fp_conversation_info, pinfo);
}
- tb_byte_length = (length - (pi_byte_length + 6)); /* Removing header length (4), footer length (2) and PI bitmap length*/
+ tb_byte_length = (reported_length - (pi_byte_length + 6)); /* Removing header length (4), footer length (2) and PI bitmap length*/
/* Possible TB lengths for PCH is 10 or 30 bytes ( See 3GPP TR 25.944 / 4.1.1.2 ) */
if (tb_byte_length == 10 || tb_byte_length == 30) {
umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = tb_byte_length * 8;
- set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
tb_size_found = TRUE;
}
}
@@ -4548,8 +4578,9 @@ heur_dissect_fp_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *d
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);
+ set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
}
- tb_byte_length = (length - 6); /* Removing header length (4), footer length (2) */
+ tb_byte_length = (reported_length - 6); /* Removing header length (4), footer length (2) */
/* Possible TB lengths for PCH is 10 or 30 bytes ( See 3GPP TR 25.944 / 4.1.1.2 ) */
if (tb_byte_length == 10 || tb_byte_length == 30) {
umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = tb_byte_length * 8;
@@ -4574,10 +4605,11 @@ static gboolean
heur_dissect_fp_hsdsch_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;
+ umts_fp_conversation_info_t* umts_fp_conversation_info = NULL;
fp_hsdsch_channel_info_t* fp_hsdsch_channel_info;
struct fp_info *p_fp_info;
- guint32 length;
+ guint32 captured_length;
+ guint32 reported_length;
guint8 frame_type;
guint16 mac_d_pdu_length;
guint16 num_of_pdus;
@@ -4601,7 +4633,8 @@ heur_dissect_fp_hsdsch_type_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
dissect_fp(tvb, pinfo, tree, data);
return TRUE;
}
- else {
+ else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){
+ /* This conversation was successfuly framed as ANOTHER type */
return FALSE;
}
}
@@ -4613,26 +4646,20 @@ heur_dissect_fp_hsdsch_type_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
return FALSE;
}
+ captured_length = tvb_reported_length(tvb);
+ /* Lengths limit: header size (7) + at least 1 PDU Block (2) + CRC Payload size (2)*/
+ if (captured_length < 11) {
+ 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) {
- 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);
/* Lengths limit: Smallest HS-DSCH type 1 data frame is 55 bytes (1 PDU of 336 bits) */
- if (length < 55) {
+ reported_length = tvb_reported_length(tvb);
+ if (reported_length < 55) {
return FALSE;
}
@@ -4654,7 +4681,7 @@ heur_dissect_fp_hsdsch_type_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
/* Making sure the expected packet size is smaller/equals to the entire packet's size */
expected_total_size = (num_of_pdus * mac_d_pdu_length / 8) + 7 /*Header length*/ + 2 /*Footer length*/;
- if (expected_total_size > length) {
+ if (expected_total_size > captured_length || expected_total_size > reported_length) {
return FALSE;
}
@@ -4679,7 +4706,10 @@ heur_dissect_fp_hsdsch_type_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
return FALSE;
}
- umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ 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;
@@ -4694,7 +4724,7 @@ heur_dissect_fp_hsdsch_type_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
fp_hsdsch_channel_info->hsdsch_entity = hs;
fp_hsdsch_channel_info->hsdsch_macdflow_id = 0;
umts_fp_conversation_info->channel_specific_info = (void*)fp_hsdsch_channel_info;
- 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;
@@ -4703,10 +4733,11 @@ static gboolean
heur_dissect_fp_hsdsch_type_2(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;
+ umts_fp_conversation_info_t* umts_fp_conversation_info = NULL;
fp_hsdsch_channel_info_t* fp_hsdsch_channel_info;
struct fp_info *p_fp_info;
- guint32 length;
+ guint32 captured_length;
+ guint32 reported_length;
guint8 frame_type;
guint8 reserved_fach_ind_bits;
guint8 pdu_block_header_reserved_bit;
@@ -4715,8 +4746,8 @@ heur_dissect_fp_hsdsch_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
guint16 pdu_block_header_pdu_length;
guint8 pdu_block_header_pdus_count;
guint8 pdu_block_header_lchid;
- guint8 total_header_length;
- guint16 expected_payload_length;
+ guint32 total_header_length;
+ guint32 expected_payload_length;
/* Trying to find existing conversation */
p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
@@ -4733,7 +4764,8 @@ heur_dissect_fp_hsdsch_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
dissect_fp(tvb, pinfo, tree, data);
return TRUE;
}
- else {
+ else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){
+ /* This conversation was successfuly framed as ANOTHER type */
return FALSE;
}
}
@@ -4745,26 +4777,15 @@ heur_dissect_fp_hsdsch_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
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) {
- conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
- pinfo->ptype,
- pinfo->destport, pinfo->srcport, NO_ADDR_B);
- }
+ captured_length = tvb_reported_length(tvb);
+ reported_length = tvb_reported_length(tvb);
+ /* Lengths limit: header size + at least 1 PDU Block Header + CRC Payload size */
+ if (captured_length < 11) {
return FALSE;
}
- length = tvb_reported_length(tvb);
- /* Lengths limit: header size + at least 1 PDU Block Header + CRC Payload size */
- if (length < 11) {
+ frame_type = tvb_get_guint8(tvb, 0) & 0x01;
+ if (frame_type == 1) { /* is 'control' frame type*/
return FALSE;
}
@@ -4792,7 +4813,7 @@ heur_dissect_fp_hsdsch_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
for (int i = 0; i < pdu_block_headers_count; i++)
{
/* Making sure the next index is not out of range */
- if (((guint32)(8 + (i * 3))) >= length) {
+ if (((guint32)(8 + (i * 3))) >= captured_length) {
return FALSE;
}
@@ -4839,8 +4860,8 @@ heur_dissect_fp_hsdsch_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
}
/* Adding Payload CRC'slength to payload length*/
expected_payload_length += 2;
- /* Calculated expected packet size must not exceed captured length */
- if ((guint32)(total_header_length + expected_payload_length) > length) {
+ /* Calculated expected packet size must not exceed captured length or reported length*/
+ if ((total_header_length + expected_payload_length) > captured_length || (total_header_length + expected_payload_length) > reported_length) {
return FALSE;
}
@@ -4851,7 +4872,10 @@ heur_dissect_fp_hsdsch_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
return FALSE;
}
- umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ 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;
@@ -4866,66 +4890,142 @@ heur_dissect_fp_hsdsch_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
fp_hsdsch_channel_info->hsdsch_entity = ehs;
fp_hsdsch_channel_info->hsdsch_macdflow_id = 1;
umts_fp_conversation_info->channel_specific_info = (void*)fp_hsdsch_channel_info;
- 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;
}
/* 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 */
static gboolean
-heur_dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+heur_dissect_fp_unknown_format(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;
+ guint32 length;
+ guint8 frame_type;
+ gboolean is_control = FALSE;
- p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
-
- /* if no FP info is present, this might be FP in a pcap(ng) file */
- if (!p_fp_info) {
- /* We only know the header length of control frames, so check that bit first */
- int offset = 0, length;
- guint8 oct, calc_crc = 0, crc;
- unsigned char *buf;
+ /* 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);
- oct = tvb_get_guint8(tvb, offset);
- crc = oct & 0xfe;
- if ((oct & 0x01) == 1) {
- /*
- * 6.3.2.1 Frame CRC
- * Description: It is the result of the CRC applied to the remaining part of the frame,
- * i.e. from bit 0 of the first byte of the header (the FT IE) to bit 0 of the last byte of the payload,
- * with the corresponding generator polynomial: G(D) = D7+D6+D2+1. See subclause 7.2.
- */
- length = tvb_reported_length(tvb);
- buf = (unsigned char *)tvb_memdup(wmem_packet_scope(), tvb, 0, length);
- buf[0] = 01;
-
- calc_crc = crc7update(calc_crc, buf, length);
- if (calc_crc == crc) {
- /* assume this is FP, set conversatio dissector to catch the data frames too */
- conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle);
+ /* Check if FP Conversation Info is attached */
+ if (p_conv != NULL) {
+ 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_UNKNOWN) {
+ /* This stream was framed using a previous control frame, we can call FP dissector without further tests*/
dissect_fp(tvb, pinfo, tree, data);
return TRUE;
}
+ else {
+ return FALSE;
+ }
+ }
+ }
+
+ p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
+
+ /* Check if per-frame FP Info is attached*/
+ if(p_fp_info) {
+ /* if FP info is present, check that it really is an ethernet link */
+ if (p_fp_info->link_type != FP_Link_Ethernet) {
+ return FALSE;
}
+
+ /* discriminate 'lower' UDP layer from 'user data' UDP layer
+ * (i.e. if an FP over UDP packet contains a user UDP packet */
+ if (p_fp_info->srcport != pinfo->srcport ||
+ p_fp_info->destport != pinfo->destport)
+ return FALSE;
+
+ /* assume this is FP */
+ dissect_fp(tvb, pinfo, tree, data);
+ return TRUE;
+ }
+
+ /* Both per-frame FP info and conversation FP info are missing */
+ /* Try to frame control frames using header CRC */
+ is_control = (tvb_get_guint8(tvb, 0) & 0x01) == 1;
+ if(!is_control) {
+ /* This is a Data frame, can't tell if it's FP. */
return FALSE;
}
- /* if FP info is present, check that it really is an ethernet link */
- if (p_fp_info->link_type != FP_Link_Ethernet) {
+ length = tvb_captured_length(tvb);
+ /* Length limit: control frames header is 2 bytes */
+ if (length < 2) {
return FALSE;
}
- /* discriminate 'lower' UDP layer from 'user data' UDP layer
- * (i.e. if an FP over UDP packet contains a user UDP packet */
- if (p_fp_info->srcport != pinfo->srcport ||
- p_fp_info->destport != pinfo->destport)
+ /* Check 'Frame Type' */
+ frame_type = tvb_get_guint8(tvb, 1);
+ /* 0x00 is unused for both dedicated & common FP */
+ if( frame_type == 0x00 ) {
+ return FALSE;
+ }
+ /* Max frame types are: */
+ /* For common channels: 0x0E */
+ /* For dedicated channels: 0x0B */
+ /* The left nibble is zeroed in both cases */
+ if( (frame_type & 0xF0) != 0x00) {
return FALSE;
+ }
+
+ /* Checking Header CRC*/
+ if (!check_control_frame_crc_for_heur(tvb)) {
+ /* The CRC is incorrect */
+ return FALSE;
+ }
- /* assume this is FP */
+ /* The CRC is correct! */
+ /* Attaching 'FP Conversation Info' the the UDP conversation so other */
+ /* packets (both Control AND Data) will be marked as FP */
+ umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t);
+ umts_fp_conversation_info->channel = CHANNEL_UNKNOWN;
+ set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info);
+ /* Call FP Dissector for the current frame */
dissect_fp(tvb, pinfo, tree, data);
return TRUE;
}
+
+/* This method wraps the heuristic dissectors of all supported channels */
+static gboolean
+heur_dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ gboolean match;
+
+ match = heur_dissect_fp_dcch_over_dch(tvb, pinfo, tree, data);
+ if(match)
+ return TRUE;
+ match = heur_dissect_fp_fach(tvb, pinfo, tree, data);
+ if(match)
+ return TRUE;
+ match = heur_dissect_fp_rach(tvb, pinfo, tree, data);
+ if(match)
+ return TRUE;
+ match = heur_dissect_fp_pch(tvb, pinfo, tree, data);
+ if(match)
+ return TRUE;
+ match = heur_dissect_fp_hsdsch_type_1(tvb, pinfo, tree, data);
+ if(match)
+ return TRUE;
+ match = heur_dissect_fp_hsdsch_type_2(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);
+ if(match)
+ return TRUE;
+
+ return FALSE;
+}
+
static guint8 fakes =5; /*[] ={1,5,8};*/
static guint8 fake_map[256];
@@ -6834,12 +6934,6 @@ 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);
- heur_dissector_add("udp", heur_dissect_fp_hsdsch_type_1, "FP over UDP (HS-DSCH Type 1)", "fp_udp_hsdsch_type_1", proto_fp, HEURISTIC_DISABLE);
- heur_dissector_add("udp", heur_dissect_fp_hsdsch_type_2, "FP over UDP (HS-DSCH Type 2)", "fp_udp_hsdsch_type_2", 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 bd7b6f4e76..7718b7b996 100644
--- a/epan/dissectors/packet-umts_fp.h
+++ b/epan/dissectors/packet-umts_fp.h
@@ -24,6 +24,7 @@
#include <glib.h>
/* Channel types */
+#define CHANNEL_UNKNOWN 0
#define CHANNEL_RACH_FDD 1
#define CHANNEL_RACH_TDD 2
#define CHANNEL_FACH_FDD 3