Wireshark-dev: [Wireshark-dev] Bug #1138 fix: 'Follow TP streams gets stream direction wrong...

From: Stephen Fisher <stephentfisher@xxxxxxxxx>
Date: Wed, 25 Oct 2006 20:05:25 -0700
Attached is a patch to fix bug #1138: "Follow TCP Streams gets stream 
direction wrong if started from a server->client frame."

THE PROBLEM: The drop-down list of which direction's flow you want to 
see is based on the source port of the currently selected packet.  The 
actual text is based on a temporary file that starts with "follow".  If 
you clicked on a packet from the server back to the client, the source 
port would be of the server not the client.  This caused the drop-down 
list's results to be the reverse of what it shows.  When you clicked on 
a packet from client to server, it works correctly.

MY SOLUTION: I rewind() back to the top of the "follow" text file after 
writing it to get the client's source port (the first line written to 
the file).  I compare the first packet's source port to the source port 
of the currently selected packet and reverse the output in the drop-down 
if they don't match.  This causes the drop-down box to always be tied to 
the correct data above.  The client->server is always shown first in the 
drop-down.


Thanks,
  Steve

Index: gtk/follow_dlg.c
===================================================================
--- gtk/follow_dlg.c	(revision 19694)
+++ gtk/follow_dlg.c	(working copy)
@@ -176,6 +176,7 @@
 	char		string[128];
 	follow_tcp_stats_t stats;
 	follow_info_t	*follow_info;
+	tcp_stream_chunk sc;
 
 	/* we got tcp so we can follow */
 	if (cfile.edt->pi.ipproto != IP_PROTO_TCP) {
@@ -206,7 +207,7 @@
 	    return;
 	}
 
-	data_out_file = fdopen(tmp_fd, "wb");
+	data_out_file = fdopen(tmp_fd, "w+b");
 	if (data_out_file == NULL) {
 	    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
 			  "Could not create temporary file %s: %s",
@@ -256,9 +257,6 @@
 	/* Free the filter string, as we're done with it. */
 	g_free(follow_filter);
 
-	/* The data_out_file should now be full of the streams information */
-	fclose(data_out_file);
-
 	/* The data_out_filename file now has all the text that was in the session */
 	streamwindow = dlg_window_new("Follow TCP Stream");
 
@@ -361,10 +359,28 @@
 	gtk_widget_show(stream_mi);
 	follow_info->show_stream = BOTH_HOSTS;
 
+	/* Go back to the top of the file and read the first tcp_stream_chunk
+	 * to ensure that the IP addresses and port numbers in the drop-down
+	 * list are tied to the correct lines displayed by follow_read_stream()
+	 * later on (which also reads from this file).  Close the file when
+	 * we're done.
+	 */
+
+	rewind(data_out_file);
+	fread(&sc, 1, sizeof(sc), data_out_file);
+	fclose(data_out_file);
+
 	/* Host 0 --> Host 1 */
-	g_snprintf(string, sizeof(string), "%s:%s --> %s:%s (%u bytes)",
-		 hostname0, port0, hostname1, port1,
-		 stats.bytes_written[0]);
+	if(sc.src_port == strtol(port0, NULL, 10)) {
+		g_snprintf(string, sizeof(string), "%s:%s --> %s:%s (%u bytes)",
+			   hostname0, port0, hostname1, port1,
+			   stats.bytes_written[0]);
+	} else {
+		g_snprintf(string, sizeof(string), "%s:%s --> %s:%s (%u bytes)",
+			   hostname1, port1, hostname0, port0,
+			   stats.bytes_written[0]);
+	}
+
 	stream_mi = gtk_menu_item_new_with_label(string);
 	SIGNAL_CONNECT(stream_mi, "activate", follow_stream_om_client,
                        follow_info);
@@ -372,9 +388,16 @@
 	gtk_widget_show(stream_mi);
 
 	/* Host 1 --> Host 0 */
-	g_snprintf(string, sizeof(string), "%s:%s --> %s:%s (%u bytes)",
-		 hostname1, port1, hostname0, port0,
-		 stats.bytes_written[1]);
+	if(sc.src_port == strtol(port0, NULL, 10)) {
+		g_snprintf(string, sizeof(string), "%s:%s --> %s:%s (%u bytes)",
+			   hostname1, port1, hostname0, port0,
+			   stats.bytes_written[1]);
+	} else {
+		g_snprintf(string, sizeof(string), "%s:%s --> %s:%s (%u bytes)",
+			   hostname0, port0, hostname1, port1,
+			   stats.bytes_written[1]);
+	}
+
 	stream_mi = gtk_menu_item_new_with_label(string);
 	SIGNAL_CONNECT(stream_mi, "activate", follow_stream_om_server,
                        follow_info);