Ethereal-dev: [Ethereal-dev] Packet Comparision

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

Date: Sun, 3 Mar 2002 01:59:04 +0000 (GMT)
 Godday.

 Attached to this letter is a simple (yet working)
 code to compare two packets to eachother.

 This is just a simple draft, missing things like
 modifing colors, saving and printing.

 It currently works by letting the user mark the
 two frames he/she wants to compare, and then
 uses some simple coloring to show the differences.

 Hope you like it.

 -s
Index: gtk/menu.c
===================================================================
RCS file: /cvsroot/ethereal/gtk/menu.c,v
retrieving revision 1.62
diff -u -r1.62 gtk/menu.c
--- gtk/menu.c	2002/01/21 07:37:41	1.62
+++ gtk/menu.c	2002/03/03 00:43:05
@@ -45,6 +45,7 @@
 #include "prefs.h"
 #include "capture_dlg.h"
 #include "color_dlg.h"
+#include "compare_pkts_dlg.h"
 #include "file_dlg.h"
 #include "filter_prefs.h"
 #include "find_dlg.h"
@@ -174,6 +175,7 @@
   {"/_Tools/TCP Stream Analysis/RTT Graph", NULL, GTK_MENU_FUNC (tcp_graph_cb), 3, NULL},
   {"/Tools/_Summary", NULL, GTK_MENU_FUNC(summary_open_cb), 0, NULL},
   {"/Tools/Protocol Hierarchy Statistics", NULL, GTK_MENU_FUNC(proto_hier_stats_cb), 0, NULL},
+  {"/Tools/_Compare Packets", NULL, GTK_MENU_FUNC(compare_pkts_cb), 0, NULL},
   {"/_Help", NULL, NULL, 0, "<LastBranch>" },
   {"/Help/_Help", NULL, GTK_MENU_FUNC(help_cb), 0, NULL},
   {"/Help/<separator>", NULL, NULL, 0, "<Separator>"},
@@ -469,6 +471,7 @@
   set_menu_sensitivity("/Display/Colorize Display...", have_captured_packets);
   set_menu_sensitivity("/Tools/Summary", have_captured_packets);
   set_menu_sensitivity("/Tools/Protocol Hierarchy Statistics", have_captured_packets);
+  set_menu_sensitivity("/Tools/Compare Packets", have_captured_packets);
   set_menu_sensitivity("<PacketList>/Display/Match", have_captured_packets);
   set_menu_sensitivity("<PacketList>/Display/Prepare", have_captured_packets);
 }
Index: gtk/Makefile.am
===================================================================
RCS file: /cvsroot/ethereal/gtk/Makefile.am,v
retrieving revision 1.38
diff -u -r1.38 gtk/Makefile.am
--- gtk/Makefile.am	2002/01/13 20:35:11	1.38
+++ gtk/Makefile.am	2002/03/03 00:42:38
@@ -41,6 +41,8 @@
 	color_utils.h	\
 	column_prefs.c	\
 	column_prefs.h	\
+	compare_pkts_dlg.c \
+	compare_pkts_dlg.h \
  	decode_as_dlg.c	\
  	decode_as_dlg.h	\
 	dfilter_expr_dlg.c \
#ifndef __COMPARE_PKTS_DLG_H
#define __COMPARE_PKTS_DLG_H

void compare_pkts_cb(GtkWidget *widget, gpointer data);

#endif
/*
	compare_pkts_dlg.c

	suid 2002 

	Compares two packets using neat colors.
*/
#ifdef HAVE_CONFIG_H
#	include "config.h"
#endif

#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>

#ifdef HAVE_SYS_TYPES_H
#	include <sys/types.h>
#endif

#ifdef HAVE_UNISTD_H
#	include <unistd.h>
#endif

#include <ctype.h>

#include "main.h"
#include <epan/packet.h>
#include "util.h"
#include "menu.h"
#include "colors.h"
#include "prefs.h"
#include "ui_util.h"
#include "gtkglobals.h"
#include "globals.h"
#include "color_utils.h"
#include "file.h"
#include "compare_pkts_dlg.h"
#include "dlg_utils.h"
#include "simple_dialog.h"

/* global variables */
GtkWidget *file_selection=NULL;
GtkWidget *text_box;

void compare_frames( frame_data *frame_1, frame_data *frame_2, gint startpos){
	gint32 size_ar[2];
	GdkColormap *colormap;
	GdkColor color_diff;
	GdkColor color_add;
	gchar i, j;
	gint pos = 0;
	guchar buf[64];
	guint8 *buf1;
	guint8 *buf2;
	frame_data *temp_frame;

	temp_frame = cfile.current_frame;

	/* setup buffers and arrays */
	cfile.current_frame = frame_1;
	buf1 = (guint8*)g_malloc( frame_1->cap_len * sizeof(guint8) );
	buf2 = (guint8*)g_malloc( frame_2->cap_len * sizeof(guint8) );
	size_ar[0] = frame_1->cap_len - 1;
	size_ar[1] = frame_2->cap_len - 1;

	/* read and save the first packet */
	wtap_seek_read(cfile.wth, frame_1->file_off, &cfile.pseudo_header,
			cfile.pd, frame_1->cap_len);
	memcpy(buf1,cfile.pd,frame_1->cap_len);
	cfile.current_frame = frame_2;

	/* read and save the second packet */
	wtap_seek_read(cfile.wth, frame_2->file_off, &cfile.pseudo_header,
			cfile.pd, frame_2->cap_len);
	memcpy(buf2,cfile.pd,frame_2->cap_len);

	/* now reread the old frame that was selected */
	if( temp_frame->num != frame_2->num ){
		cfile.current_frame = temp_frame;
		wtap_seek_read(cfile.wth, temp_frame->file_off, &cfile.pseudo_header,
			cfile.pd, temp_frame->cap_len);
	}

	/* create some colors for the textbox */
	colormap = gdk_colormap_get_system();
	color_diff.red = 0xffff; color_diff.green = 0; color_diff.blue = 0;
	if( !gdk_color_alloc(colormap,&color_diff)){
		g_error("Cannot allocate color!\n");
	}

	color_add.red = 0; color_add.green = 0; color_add.blue = 0xffff;
	if( !gdk_color_alloc(colormap,&color_add)){
		g_error("Cannot allocate color!\n");
	}

	/* add a simple header */
	sprintf(buf,"Packet %.4d                                Packet %.4d\n",frame_1->num, frame_2->num);
	gtk_text_insert( GTK_TEXT(text_box), m_r_font, NULL, NULL, buf, -1);

	while( pos < size_ar[0] || pos < size_ar[1]){

		sprintf(buf,"%.4x ",pos);
		gtk_text_insert( GTK_TEXT(text_box), m_r_font, NULL, NULL, buf, -1);

		for(i=0;i<4;i++){
			if( pos >= size_ar[i>>1] )
				j = 0;
			else
			for( j=0; j<8; j++ ){
				switch(i){
					case 0:
						sprintf(buf,"%.2x ", buf1[pos] & 0xff); break;
					case 1:
						sprintf(buf,"%c", isprint(buf1[pos]) ? buf1[pos] : '.'); break;
					case 2:
						sprintf(buf,"%.2x ", buf2[pos] & 0xff); break;
					case 3:
						sprintf(buf,"%c", isprint(buf2[pos]) ? buf2[pos] : '.'); break;
				}

				if( size_ar[((i+2)&2)>>1] < pos ){
					gtk_text_insert( GTK_TEXT(text_box),
									m_r_font, &color_add, NULL, buf, -1);
				}else if( buf1[pos] != buf2[pos] ){
					gtk_text_insert( GTK_TEXT(text_box),
									m_r_font, &color_diff, NULL, buf, -1);
				}else{
					gtk_text_insert( GTK_TEXT(text_box),
									m_r_font, NULL, NULL, buf, -1);
				}
				
				if( pos >= size_ar[i>>1] ){
					break;
				}
				pos++;
			}

			if( i == 0 || i == 2 ){
				buf[0] = ' '; buf[1] = ' '; buf[2] = ' '; buf[3] = '\0';
				pos -= j;
				if( !j ) j--;
				if( j < 7 )
					for(;j<7;j++)
						strcat(buf,"   "); 
			}else if( i == 1 ){
				buf[0] = ' '; buf[1] = ' '; buf[2] = ' '; buf[3] = '\0';
				pos -= j;
				if( !j ) j--;
				if( j < 7 )
					for(;j<7;j++)
						strcat(buf," ");	
			}else if( i == 3){
				pos += (8-j);
				buf[0] = '\n'; buf[1] = '\0';
			}

			gtk_text_insert( GTK_TEXT(text_box),
							m_r_font, NULL, NULL, buf, -1);
		}
	}

	/* free the buffers */
	g_free(buf1);
	g_free(buf2);
}

gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data){
	return(FALSE);
}

void compare_pkts_cb(GtkWidget *widget, gpointer data){
	GtkWidget *compare_win, *scroll_win;
	GtkWidget *vbox = NULL,*hbox = NULL;
	GtkWidget *button = NULL;
	frame_data *frame1 = NULL, *frame2 = NULL;

	/* this should not happen ! */
	if( !cfile.count ){
		simple_dialog(ESD_TYPE_CRIT, NULL,
					"You have no captured packets!");
		return;
	}

	if( cfile.marked_count == 2 ){		/* we have 2 marked entries, so */
													/* we'll compare those */
		/* find the first frame */
		for(frame1 = cfile.plist; frame1 != NULL && !frame1->flags.marked ; frame1 = frame1->next)
				;

		/* find the second frame */
		if( frame1 != NULL )
		for( frame2 = frame1->next; frame2 != NULL && !frame2->flags.marked ; frame2 = frame2->next)
				;

		/* this should NEVER happen */
		if( frame1 == NULL || frame2 == NULL ){
			simple_dialog(ESD_TYPE_CRIT, NULL,
					"Corrupt capture! Try restarting ethereal!");
			gtk_widget_destroy(compare_win);
			return;
		}
	}else{
		simple_dialog(ESD_TYPE_INFO, NULL,
				"You must mark two packets to compare.");
		return;
	}

	compare_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_widget_set_name(compare_win, "Packet Comparision Window");

	gtk_signal_connect(GTK_OBJECT(compare_win), "destroy",
				GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(compare_win));

	gtk_widget_set_usize(GTK_WIDGET(compare_win), DEF_WIDTH, DEF_HEIGHT);

	gtk_container_set_border_width( GTK_CONTAINER(compare_win), 5);

	/* create a vbox... */
	vbox = gtk_vbox_new(FALSE, 5);
	gtk_container_add(GTK_CONTAINER(compare_win),vbox);

	/* create a scroll-win */
	scroll_win = scrolled_window_new(NULL, NULL);
	gtk_box_pack_start( GTK_BOX(vbox), scroll_win, TRUE, TRUE, FALSE);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win),
								GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);

	/* create a text-box */
	text_box = gtk_text_new( NULL, NULL);
	gtk_container_add( GTK_CONTAINER(scroll_win), text_box );

	/* pack the stuff into a hbox and show them */
	gtk_widget_show(text_box);
	gtk_widget_show(scroll_win);

	/* create a hbox for the button */
	hbox = gtk_hbox_new(FALSE,5);
	gtk_box_pack_start( GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, FALSE);

	/* create a 'Close' button */
	button = gtk_button_new_with_label("Close");
	gtk_signal_connect_object( GTK_OBJECT(button), "clicked",
						GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(compare_win));

	gtk_widget_set_usize(GTK_WIDGET(button), 80, 20);
	gtk_widget_show(button);
	gtk_box_pack_end( GTK_BOX(hbox), GTK_WIDGET(button), FALSE, FALSE, FALSE);

	gtk_widget_show(vbox);
	gtk_widget_show(hbox);
	gtk_widget_show(compare_win);
 	compare_frames( frame1, frame2, 0);
}