From 93c358cb5d2a6620d997862ef39e1082e47e8329 Mon Sep 17 00:00:00 2001 From: Martin Mathieson Date: Mon, 30 Oct 2017 21:28:44 +0000 Subject: FTP: links between setup and command frames Change-Id: I8a231f8616952ed119b85126d6d25af7512e6cd8 Reviewed-on: https://code.wireshark.org/review/24194 Petri-Dish: Martin Mathieson Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- epan/dissectors/packet-ftp.c | 109 +++++++++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 31 deletions(-) (limited to 'epan') diff --git a/epan/dissectors/packet-ftp.c b/epan/dissectors/packet-ftp.c index 1e797c35f4..ad307877f7 100644 --- a/epan/dissectors/packet-ftp.c +++ b/epan/dissectors/packet-ftp.c @@ -65,7 +65,9 @@ static int hf_ftp_command_response_frames = -1; static int hf_ftp_command_response_first_frame_num = -1; static int hf_ftp_command_response_last_frame_num = -1; static int hf_ftp_command_response_duration = -1; - +static int hf_ftp_command_setup_frame = -1; +static int hf_ftp_command_command_frame = -1; +static int hf_ftp_command_command = -1; static int hf_ftp_data_setup_frame = -1; static int hf_ftp_data_setup_method = -1; @@ -166,6 +168,7 @@ typedef struct ftp_data_conversation_t const gchar *command; /* Command that this data answers */ guint32 command_frame; /* Frame command was seen */ const gchar *setup_method; /* Type of command used to set up data conversation */ + guint32 setup_frame; /* Frame where this happened */ wmem_strbuf_t *current_working_directory; /* Summary details of stream to show in command frame. */ @@ -189,6 +192,7 @@ typedef struct ftp_conversation_t guint32 last_command_frame; /* When request was seen */ wmem_strbuf_t *current_working_directory; ftp_data_conversation_t *current_data_conv; /* Current data conversation (during first pass) */ + guint32 current_data_setup_frame; } ftp_conversation_t; /* For a given packet, retrieve or initialise a new conversation, and return it */ @@ -243,6 +247,7 @@ static void create_and_link_data_conversation(packet_info *pinfo, /* Allocate data for data conversation. Note that control conversation will update it with commands. */ p_ftp_data_conv = wmem_new0(wmem_file_scope(), ftp_data_conversation_t); + /* Set method */ p_ftp_data_conv->setup_method = method; /* Copy snapshot of what cwd is at this point */ p_ftp_data_conv->current_working_directory = p_ftp_conv->current_working_directory; @@ -251,6 +256,7 @@ static void create_and_link_data_conversation(packet_info *pinfo, conversation_add_proto_data(data_conversation, proto_ftp_data, p_ftp_data_conv); p_ftp_conv->current_data_conv = p_ftp_data_conv; + p_ftp_conv->current_data_setup_frame = pinfo->num; } /********************************************************************/ @@ -950,11 +956,15 @@ dissect_ftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) } /* And make sure set for FTP data conversation */ if (p_ftp_conv && p_ftp_conv->current_data_conv && !p_ftp_conv->current_data_conv->command) { + /* Store command and frame where it happened */ p_ftp_conv->current_data_conv->command = wmem_strndup(wmem_file_scope(), line, linelen); p_ftp_conv->current_data_conv->command_frame = pinfo->num; /* Add to table to ftp-data response can be shown with this frame on later passes */ - g_hash_table_insert(ftp_command_to_data_hash, GUINT_TO_POINTER(pinfo->num), p_ftp_conv->current_data_conv); + g_hash_table_insert(ftp_command_to_data_hash, GUINT_TO_POINTER(pinfo->num), + p_ftp_conv->current_data_conv); + g_hash_table_insert(ftp_command_to_data_hash, GUINT_TO_POINTER(p_ftp_conv->current_data_setup_frame), + p_ftp_conv->current_data_conv); } } else { /* @@ -1250,36 +1260,55 @@ dissect_ftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) /* If this is a command resulting in an ftp-data stream, show details */ if (pinfo->fd->flags.visited) { + /* Look up what has been stored for this frame */ ftp_data_conversation_t *ftp_data = (ftp_data_conversation_t *)g_hash_table_lookup(ftp_command_to_data_hash, GUINT_TO_POINTER(pinfo->num)); if (ftp_data) { - /* Number of frames */ - ti = proto_tree_add_uint(tree, hf_ftp_command_response_frames, - tvb, 0, 0, ftp_data->frames_seen); - PROTO_ITEM_SET_GENERATED(ti); - - /* First frame */ - ti = proto_tree_add_uint(tree, hf_ftp_command_response_first_frame_num, - tvb, 0, 0, ftp_data->first_frame_num); - PROTO_ITEM_SET_GENERATED(ti); - - /* Last frame */ - ti = proto_tree_add_uint(tree, hf_ftp_command_response_last_frame_num, - tvb, 0, 0, ftp_data->last_frame_num); - PROTO_ITEM_SET_GENERATED(ti); - - /* Length of stream */ - if (ftp_data->frames_seen > 1) { - /* Work out gap between frames */ - gint seconds = (gint) - (ftp_data->last_frame_time.secs - ftp_data->first_frame_time.secs); - gint nseconds = - ftp_data->last_frame_time.nsecs - ftp_data->first_frame_time.nsecs; - - /* Round gap to nearest ms. */ - gint gap_ms = (seconds*1000) + ((nseconds+500000) / 1000000); - ti = proto_tree_add_uint(tree, hf_ftp_command_response_duration, + /* Show these for the command frame only */ + if (pinfo->num == ftp_data->command_frame) { + /* Number of frames */ + ti = proto_tree_add_uint(tree, hf_ftp_command_response_frames, + tvb, 0, 0, ftp_data->frames_seen); + PROTO_ITEM_SET_GENERATED(ti); + + /* First frame */ + ti = proto_tree_add_uint(tree, hf_ftp_command_response_first_frame_num, + tvb, 0, 0, ftp_data->first_frame_num); + PROTO_ITEM_SET_GENERATED(ti); + + /* Last frame */ + ti = proto_tree_add_uint(tree, hf_ftp_command_response_last_frame_num, + tvb, 0, 0, ftp_data->last_frame_num); + PROTO_ITEM_SET_GENERATED(ti); + + /* Length of stream */ + if (ftp_data->frames_seen > 1) { + /* Work out gap between frames */ + gint seconds = (gint) + (ftp_data->last_frame_time.secs - ftp_data->first_frame_time.secs); + gint nseconds = + ftp_data->last_frame_time.nsecs - ftp_data->first_frame_time.nsecs; + + /* Round gap to nearest ms. */ + gint gap_ms = (seconds*1000) + ((nseconds+500000) / 1000000); + ti = proto_tree_add_uint(tree, hf_ftp_command_response_duration, tvb, 0, 0, gap_ms); + PROTO_ITEM_SET_GENERATED(ti); + } + + ti = proto_tree_add_uint(tree, hf_ftp_command_setup_frame, + tvb, 0, 0, ftp_data->setup_frame); + PROTO_ITEM_SET_GENERATED(ti); + } + + /* Show this only under the setup frame */ + if (pinfo->num == ftp_data->setup_frame) { + ti = proto_tree_add_string(tree, hf_ftp_command_command, + tvb, 0, 0, ftp_data->command); + PROTO_ITEM_SET_GENERATED(ti); + + ti = proto_tree_add_uint(tree, hf_ftp_command_command_frame, + tvb, 0, 0, ftp_data->command_frame); PROTO_ITEM_SET_GENERATED(ti); } } @@ -1328,6 +1357,9 @@ dissect_ftpdata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data p_ftp_data_conv->last_frame_time = pinfo->abs_ts; } p_ftp_data_conv->frames_seen++; + + /* Also store setup_frame here for benefit of ftp (control) */ + p_ftp_data_conv->setup_frame = p_conv->setup_frame; } /* Show setup method as field and in info column */ @@ -1496,12 +1528,12 @@ proto_register_ftp(void) { &hf_ftp_command_response_first_frame_num, { "Command response first frame", "ftp.command-response.first-frame-num", - FT_FRAMENUM, BASE_NONE, NULL, 0, + FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0, "First frame seen in resulting ftp-data stream", HFILL }}, { &hf_ftp_command_response_last_frame_num, { "Command response last frame", "ftp.command-response.last-frame-num", - FT_FRAMENUM, BASE_NONE, NULL, 0, + FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0, "Last frame seen in resulting ftp-data stream", HFILL }}, { &hf_ftp_command_response_duration, @@ -1512,7 +1544,22 @@ proto_register_ftp(void) { &hf_ftp_command_response_frames, { "Command response frames", "ftp.command-response.frames", FT_UINT32, BASE_DEC, NULL, 0, - "Number of frames seen in resulting ftp-data stream", HFILL }} + "Number of frames seen in resulting ftp-data stream", HFILL }}, + + { &hf_ftp_command_setup_frame, + { "Setup frame", "ftp.setup-frame", + FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0, + "Where ftp-data conversation for this command was signalled", HFILL }}, + + { &hf_ftp_command_command_frame, + { "Command frame", "ftp.command-frame", + FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0, + "Where command for setup was seen", HFILL }}, + + { &hf_ftp_command_command, + { "Command", "ftp.command", + FT_STRING, BASE_NONE, NULL, 0, + "Command corresponding to this setup frame", HFILL }}, }; static gint *ett[] = { &ett_ftp, -- cgit v1.2.3