diff options
author | Christoph Schlosser <christoph.schlosser@br-automation.com> | 2016-03-21 09:27:03 +0100 |
---|---|---|
committer | Roland Knall <rknall@gmail.com> | 2016-03-29 19:42:11 +0000 |
commit | 070ea6f58739ff747727974d226fd101a7632c01 (patch) | |
tree | 85f25258c261ba9a222764fea1c00909a0466b5b /epan/dissectors/packet-epl.c | |
parent | 93ac8364f1397f1bb758d9387016b1cd0fff3eb0 (diff) | |
download | wireshark-070ea6f58739ff747727974d226fd101a7632c01.tar.gz |
EPL: Fix segmented transfer complete detection
In case of a segmented SDO transfer, the transfer complete response can
contain additional data that should not be evaluated by the dissector.
Change-Id: I7016eb88b93aac8c318e703fe60a90c3adbf9eeb
Reviewed-on: https://code.wireshark.org/review/14692
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Roland Knall <rknall@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-epl.c')
-rw-r--r-- | epan/dissectors/packet-epl.c | 149 |
1 files changed, 96 insertions, 53 deletions
diff --git a/epan/dissectors/packet-epl.c b/epan/dissectors/packet-epl.c index 2203fc643a..97e67a588e 100644 --- a/epan/dissectors/packet-epl.c +++ b/epan/dissectors/packet-epl.c @@ -446,6 +446,8 @@ static struct _epl_segmentation{ static epl_sdo_reassembly epl_asnd_sdo_reassembly_write; static epl_sdo_reassembly epl_asnd_sdo_reassembly_read; +static gboolean first_read = TRUE; +static gboolean first_write = TRUE; /* Priority values for EPL message type "ASnd", "", "", field PR */ #define EPL_PR_GENERICREQUEST 0x03 @@ -1650,6 +1652,10 @@ static void cleanup_dissector(void) { reassembly_table_destroy(&epl_reassembly_table); + count = 0; + ct = 0; + first_read = TRUE; + first_write = TRUE; } /* preference whether or not display the SoC flags in info column */ @@ -2820,14 +2826,15 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gboolean response, abort_flag; guint32 abort_code = 0; guint32 fragmentId = 0, remlength = 0; - guint16 segment_size; + guint16 segment_size = 0; proto_tree *sdo_cmd_tree = NULL; - proto_tree *payload = NULL; proto_item *item; - fragment_head *frag_msg = NULL; + guint8 sendCon = 0; offset += 1; + sendCon = tvb_get_guint8(tvb, 5) & EPL_ASND_SDO_SEQ_SEND_CON_ERROR_VALID_ACK_REQ; + command_id = tvb_get_guint8(tvb, offset + 2); abort_flag = tvb_get_guint8(tvb, offset + 1) & EPL_ASND_SDO_CMD_ABORT_FILTER; @@ -2840,6 +2847,7 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, transaction_id = tvb_get_guint8(tvb, offset); response = tvb_get_guint8(tvb, offset + 1) & EPL_ASND_SDO_CMD_RESPONSE_FILTER; segmented = (tvb_get_guint8(tvb, offset + 1) & EPL_ASND_SDO_CMD_SEGMENTATION_FILTER) >> 4; + segment_size = tvb_get_letohs(tvb, offset + 3); col_append_fstr(pinfo->cinfo, COL_INFO, "Cmd:%s,TID=%02d ", @@ -2852,14 +2860,16 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, proto_tree_add_item(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_abort, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_segmentation, tvb, offset, 1, ENC_LITTLE_ENDIAN); - offset += 1; - proto_tree_add_item(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_command_id, tvb, offset, 1, ENC_LITTLE_ENDIAN); - offset += 1; - - proto_tree_add_item(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_segment_size, tvb, offset, 2, ENC_LITTLE_ENDIAN); - offset += 4; + if (segment_size != 0) + { + offset += 1; + proto_tree_add_item(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_command_id, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + proto_tree_add_item(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_segment_size, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 4; + } /* adjust size of packet */ tvb_set_reported_length(tvb, offset + segment_size); @@ -2867,12 +2877,15 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, { if((command_id == EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX) || (command_id == EPL_ASND_SDO_COMMAND_READ_BY_INDEX)) { - /* if download => reset counter */ - if(command_id == EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX) - ct = 0x00; - /* if upload => reset counter */ - else if(command_id == EPL_ASND_SDO_COMMAND_READ_BY_INDEX) - count = 0x00; + if (sendCon != EPL_ASND_SDO_SEQ_SEND_CON_ERROR_VALID_ACK_REQ) + { + /* if download => reset counter */ + if(command_id == EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX) + ct = 0x00; + /* if upload => reset counter */ + else if(command_id == EPL_ASND_SDO_COMMAND_READ_BY_INDEX) + count = 0x00; + } /* payload length */ payload_length = tvb_reported_length_remaining(tvb, offset); /* create a key for reassembly => first 16 bit are src-address and @@ -2880,20 +2893,21 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, fragmentId = (guint32)((((guint32)epl_segmentation.src)<<16)+epl_segmentation.dest); /* set fragmented flag */ pinfo->fragmented = TRUE; - frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, + fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, fragmentId, NULL, 0, payload_length, TRUE ); fragment_add_seq_offset ( &epl_reassembly_table, pinfo, fragmentId, NULL, 0 ); + if (command_id == EPL_ASND_SDO_COMMAND_WRITE_BY_INDEX) + { + first_write = FALSE; + } + else + { + first_read = FALSE; + } /* if Segmentation = Initiate then print DataSize */ proto_tree_add_item(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_data_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); segmented = TRUE; - if(frag_msg != NULL) - { - item = proto_tree_add_uint_format(sdo_cmd_tree, hf_epl_asnd_sdo_cmd_reassembled, tvb, offset ,payload_length, 0, - "Reassembled: %d bytes total (%d bytes in this frame)",frag_msg->len,payload_length); - payload = proto_item_add_subtree(item, ett_epl_asnd_sdo_data_reassembled); - process_reassembled_data(tvb, 0, pinfo, "Reassembled Message", frag_msg, &epl_frag_items, NULL, payload ); - } offset += 4; } else @@ -2965,7 +2979,7 @@ dissect_epl_sdo_command(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, guint8 segmented, gboolean response, guint16 segment_size) { - gint size, payload_length; + gint size, payload_length = 0; guint16 idx = 0x00, nosub = 0x00, sod_index = 0x00, error = 0xFF, entries = 0x00, sub_val = 0x00; guint8 subindex = 0x00; guint32 fragmentId = 0; @@ -3091,6 +3105,7 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack fragmentId = (guint32)((((guint32)epl_segmentation.src)<<16)+epl_segmentation.dest); /* set the fragmented flag */ pinfo->fragmented = TRUE; + /* get payloade size */ payload_length = tvb_reported_length_remaining(tvb, offset); /* if the frame is the last frame */ @@ -3109,14 +3124,34 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, fragmentId, NULL, ct, payload_length, end_segment ? FALSE : TRUE ); } - else if(epl_asnd_sdo_reassembly_write.frame[epl_segmentation.recv][epl_segmentation.send] == 0x00) + else { - /* save the current frame and increase counter */ - epl_asnd_sdo_reassembly_write.frame[epl_segmentation.recv][epl_segmentation.send] = frame; - ct += 1; - /* add the frame to reassembly_table */ - frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, - fragmentId, NULL, ct, payload_length, end_segment ? FALSE : TRUE ); + if(epl_asnd_sdo_reassembly_write.frame[epl_segmentation.recv][epl_segmentation.send] == 0x00) + { + /* save the current frame and increase counter */ + epl_asnd_sdo_reassembly_write.frame[epl_segmentation.recv][epl_segmentation.send] = frame; + ct += 1; + /* add the frame to reassembly_table */ + if (first_write) + { + frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, + fragmentId, NULL, 0, payload_length, end_segment ? FALSE : TRUE ); + fragment_add_seq_offset(&epl_reassembly_table, pinfo, fragmentId, NULL, ct); + + first_write = FALSE; + } + else + { + frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, + fragmentId, NULL, ct, payload_length, end_segment ? FALSE : TRUE ); + } + } + else + { + frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, + fragmentId, NULL, 0, payload_length, end_segment ? FALSE : TRUE); + epl_asnd_sdo_reassembly_write.frame[epl_segmentation.recv][epl_segmentation.send] = frame; + } } /* if the reassembly_table is not Null and the frame stored is the same as the current frame */ @@ -3133,8 +3168,6 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack proto_tree_add_uint_format_value(payload_tree, hf_epl_asnd_sdo_cmd_reassembled, tvb, 0, 0, payload_length, "%d bytes (over all fragments)", frag_msg->len); col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)" ); - /* reset memory */ - memset(&epl_asnd_sdo_reassembly_write,0,sizeof(epl_sdo_reassembly)); } else { @@ -3144,9 +3177,10 @@ dissect_epl_sdo_command_write_by_index(proto_tree *epl_tree, tvbuff_t *tvb, pack /* add reassemble field => Reassembled in: */ process_reassembled_data(tvb, 0, pinfo, "Reassembled Message", frag_msg, &epl_frag_items, NULL, payload_tree ); } + first_write = TRUE; + ct = 0; } } - size = tvb_reported_length_remaining(tvb, offset); /* if the frame is a PDO Mapping and the subindex is bigger than 0x00 */ @@ -3451,12 +3485,11 @@ dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packe segment_size, idx, subindex); col_append_fstr(pinfo->cinfo, COL_INFO, " (%s", val_to_str_ext_const(((guint32) (idx << 16)), &sod_index_names, "User Defined")); col_append_fstr(pinfo->cinfo, COL_INFO, "/%s)",val_to_str_ext_const((subindex|(idx<<16)), &sod_index_names, "User Defined")); - } else { - /* upload */ - if(segmented > 0x01) + /* upload and no response */ + if(segmented > 0x01 && segment_size != 0) { /* get the fragmentId */ fragmentId = (guint32)((((guint32)epl_segmentation.src)<<16)+epl_segmentation.dest); @@ -3468,28 +3501,34 @@ dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packe if(segmented == EPL_ASND_SDO_CMD_SEGMENTATION_TRANSFER_COMPLETE) end_segment = TRUE; - /* if the send-sequence-number is at the end or the beginning of a sequence */ - if(epl_segmentation.send == 0x3f || epl_segmentation.send <= 0x01 ) - { - /* reset memory */ - memset(&epl_asnd_sdo_reassembly_read,0,sizeof(epl_sdo_reassembly)); - epl_asnd_sdo_reassembly_read.frame[epl_segmentation.recv][epl_segmentation.send] = frame; - count += 1; - } - else if(epl_asnd_sdo_reassembly_read.frame[epl_segmentation.recv][epl_segmentation.send] == 0x00) + if(epl_asnd_sdo_reassembly_read.frame[epl_segmentation.recv][epl_segmentation.send] == 0x00 || + epl_asnd_sdo_reassembly_read.frame[epl_segmentation.recv][epl_segmentation.send] == frame) { + if (epl_asnd_sdo_reassembly_read.frame[epl_segmentation.recv][epl_segmentation.send] == 0x00) + count += 1; /* store the current frame and increase the counter */ epl_asnd_sdo_reassembly_read.frame[epl_segmentation.recv][epl_segmentation.send] = frame; - count += 1; - } - /* add the frame to reassembly_table */ - frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, + + /* add the frame to reassembly_table */ + if (first_read) + { + frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, + fragmentId, NULL, 0, payload_length, end_segment ? FALSE : TRUE ); + fragment_add_seq_offset(&epl_reassembly_table, pinfo, fragmentId, NULL, count); + + first_read = FALSE; + } + else + { + frag_msg = fragment_add_seq_check(&epl_reassembly_table, tvb, offset, pinfo, fragmentId, NULL, count, payload_length, end_segment ? FALSE : TRUE ); + } + } /* if the reassembly_table is not Null and the frame stored is the same as the current frame */ if(frag_msg != NULL && (epl_asnd_sdo_reassembly_read.frame[epl_segmentation.recv][epl_segmentation.send] == frame)) { - if(end_segment) + if(end_segment || payload_length > 0) { cmd_payload = proto_tree_add_uint_format(epl_tree, hf_epl_asnd_sdo_cmd_reassembled, tvb, offset, payload_length,0, "Reassembled: %d bytes total (%d bytes in this frame)",frag_msg->len,payload_length); @@ -3498,9 +3537,10 @@ dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packe process_reassembled_data(tvb, 0, pinfo, "Reassembled Message", frag_msg, &epl_frag_items, NULL, payload_tree ); proto_tree_add_uint_format_value(payload_tree, hf_epl_asnd_sdo_cmd_reassembled, tvb, 0, 0, payload_length, "%d bytes (over all fragments)", frag_msg->len); - col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)" ); + if (frag_msg->reassembled_in == frame) + col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)" ); /* reset memory */ - memset(&epl_asnd_sdo_reassembly_read,0,sizeof(epl_sdo_reassembly)); + memset(&epl_asnd_sdo_reassembly_read.frame[epl_segmentation.recv], 0, sizeof(guint32) * EPL_MAX_SEQUENCE); } else { @@ -3510,6 +3550,9 @@ dissect_epl_sdo_command_read_by_index(proto_tree *epl_tree, tvbuff_t *tvb, packe /* add reassemble field => Reassembled in: */ process_reassembled_data(tvb, 0, pinfo, "Reassembled Message", frag_msg, &epl_frag_items, NULL, payload_tree ); } + + first_read = TRUE; + count = 0; } } /* response */ |