Ethereal-dev: [ethereal-dev] plugins+gryphon

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

From: Olivier Abad <abad@xxxxxxxxxxxxx>
Date: Wed, 8 Dec 1999 23:59:27 +0100
Hi,

I'm sending the status of my work on plugins, and a plugified version of
Steve Limkemann's gryphon dissector.
After extracting the sources from gryphon.tar.gz, you should update the
INCLUDES line in Makefile.am to point to ethereal's source directory.
The plugin should be built with "./autogen.sh && make", and copied in
one of these directories :
/usr/share/ethereal/plugins
/usr/local/share/ethereal/plugins
~/.ethereal/plugins

Updated TODO :
- add hooks for plugins in more dissectors : tcp and udp are done.
- add support for other types of plugins
- enable/disable plugins : done

If nobody objects, I'll commit the patch to the CVS tree tomorrow.

Olivier

diff -Nru ethereal/Makefile.am ethereal.plug/Makefile.am
--- ethereal/Makefile.am	Tue Dec  7 07:41:15 1999
+++ ethereal.plug/Makefile.am	Wed Dec  8 22:26:20 1999
@@ -185,6 +185,8 @@
 	ipv4.h         \
 	packet.c       \
 	packet.h       \
+	plugins.c      \
+	plugins.h      \
 	prefs.c        \
 	prefs.h        \
 	print.c        \
diff -Nru ethereal/configure.in ethereal.plug/configure.in
--- ethereal/configure.in	Sun Dec  5 10:30:12 1999
+++ ethereal.plug/configure.in	Wed Dec  8 22:26:20 1999
@@ -142,6 +142,7 @@
 AC_CHECK_HEADERS(sys/stat.h sys/sockio.h sys/types.h netinet/in.h sys/socket.h net/if.h)
 AC_CHECK_HEADERS(sys/wait.h)
 AC_CHECK_HEADERS(stddef.h)
+AC_CHECK_HEADERS(dlfcn.h)
 
 dnl SNMP Check
 AC_ARG_ENABLE(snmp,
diff -Nru ethereal/file.c ethereal.plug/file.c
--- ethereal/file.c	Sun Dec  5 10:30:12 1999
+++ ethereal.plug/file.c	Wed Dec  8 22:26:20 1999
@@ -82,6 +82,10 @@
 #include "conversation.h"
 #include "globals.h"
 
+#ifdef HAVE_DLFCN_H
+#include "plugins.h"
+#endif
+
 #ifndef __RESOLV_H__
 #include "resolv.h"
 #endif
@@ -763,7 +767,7 @@
   gint          i, row;
   gint		crow;
   gint 		color;
-  proto_tree   *protocol_tree;
+  proto_tree   *protocol_tree = NULL;
 
   fdata->num = cf->count;
 
@@ -815,9 +819,17 @@
 	proto_tree_free(protocol_tree);
   }
   else {
-	dissect_packet(buf, fdata, NULL);
+#ifdef HAVE_DLFCN_H
+	if (plugin_list)
+	    protocol_tree = proto_tree_create_root();
+#endif
+	dissect_packet(buf, fdata, protocol_tree);
 	fdata->passed_dfilter = TRUE;
 	color = -1;
+#ifdef HAVE_DLFCN_H
+	if (protocol_tree)
+	    proto_tree_free(protocol_tree);
+#endif
   }
   if (fdata->passed_dfilter) {
     /* If we don't have the time stamp of the previous displayed packet,
diff -Nru ethereal/gtk/Makefile.am ethereal.plug/gtk/Makefile.am
--- ethereal/gtk/Makefile.am	Wed Dec  8 00:45:05 1999
+++ ethereal.plug/gtk/Makefile.am	Wed Dec  8 22:26:20 1999
@@ -50,6 +50,7 @@
 	menu.h		\
 	prefs_dlg.c	\
 	prefs_dlg.h	\
+	plugins_dlg.c	\
 	print_dlg.c	\
 	print_prefs.c   \
 	print_prefs.h	\
diff -Nru ethereal/gtk/keys.h ethereal.plug/gtk/keys.h
--- ethereal/gtk/keys.h	Thu Nov 25 19:02:24 1999
+++ ethereal.plug/gtk/keys.h	Wed Dec  8 22:26:20 1999
@@ -39,4 +39,6 @@
 #define PRINT_FILE_TE_KEY         "printer_file_entry"
 #define PRINT_DEST_RB_KEY         "printer_destination_radio_button"
 
+#define PLUGINS_DFILTER_TE        "plugins_dfilter_te"
+
 #endif
diff -Nru ethereal/gtk/main.h ethereal.plug/gtk/main.h
--- ethereal/gtk/main.h	Fri Oct  8 09:29:42 1999
+++ ethereal.plug/gtk/main.h	Wed Dec  8 22:26:20 1999
@@ -64,6 +64,9 @@
 void file_reload_cmd_cb(GtkWidget *, gpointer);
 void file_print_cmd_cb(GtkWidget *, gpointer);
 void file_print_packet_cmd_cb(GtkWidget *, gpointer);
+#ifdef HAVE_DLFCN_H
+void file_plugins_cmd_cb(GtkWidget *, gpointer);
+#endif
 void expand_all_cb(GtkWidget *, gpointer);
 void collapse_all_cb(GtkWidget *, gpointer);
 
diff -Nru ethereal/gtk/menu.c ethereal.plug/gtk/menu.c
--- ethereal/gtk/menu.c	Mon Dec  6 07:27:31 1999
+++ ethereal.plug/gtk/menu.c	Wed Dec  8 22:26:20 1999
@@ -108,6 +108,9 @@
   {"/Display/Collapse _All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
   {"/Display/_Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL},
   {"/_Tools", NULL, NULL, 0, "<Branch>" },
+#ifdef HAVE_DLFCN_H
+  {"/Tools/_Plugins...", NULL, GTK_MENU_FUNC(file_plugins_cmd_cb), 0, NULL},
+#endif
   {"/Tools/_Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
 /*  {"/Tools/Graph", NULL, NULL, 0, NULL}, future use */
   {"/Tools/_Summary", NULL, GTK_MENU_FUNC(summary_prep_cb), 0, NULL},
diff -Nru ethereal/gtk/plugins_dlg.c ethereal.plug/gtk/plugins_dlg.c
--- ethereal/gtk/plugins_dlg.c	Thu Jan  1 01:00:00 1970
+++ ethereal.plug/gtk/plugins_dlg.c	Wed Dec  8 22:25:26 1999
@@ -0,0 +1,426 @@
+/* plugins_dlg.c
+ * Dialog boxes for plugins
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_DLFCN_H
+
+#include <errno.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#ifndef __GLOBALS_H__
+#include "globals.h"
+#endif
+
+#ifndef __PLUGINS_H__
+#include "plugins.h"
+#endif
+
+#ifndef __KEYS_H__
+#include "keys.h"
+#endif
+
+#ifndef __PREFS_DLG_H__
+#include "prefs_dlg.h"
+#endif
+
+#ifndef __UTIL_H__
+#include "util.h"
+#endif
+
+static gint selected_row;
+static gchar *selected_name;
+static gchar *selected_version;
+static gchar *selected_enabled;
+static gchar std_plug_dir[] = "/usr/share/ethereal/plugins";
+static gchar local_plug_dir[] = "/usr/local/share/ethereal/plugins";
+static gchar *user_plug_dir = NULL;
+
+static void plugins_close_cb(GtkWidget *, gpointer);
+static void plugins_scan(GtkWidget *);
+static void plugins_scan_dir(const char *);
+static void plugins_clist_select_cb(GtkWidget *, gint, gint,
+	GdkEventButton *, gpointer);
+static void plugins_clist_unselect_cb(GtkWidget *, gint, gint,
+	GdkEventButton *, gpointer);
+static void plugins_enable_cb(GtkWidget *, gpointer);
+static void plugins_disable_cb(GtkWidget *, gpointer);
+static void plugins_filter_cb(GtkWidget *, gpointer);
+static void filter_ok_cb(GtkWidget *, gpointer);
+static void filter_cancel_cb(GtkWidget *, gpointer);
+
+void
+file_plugins_cmd_cb(GtkWidget *widget, gpointer data)
+{
+    GtkWidget *plugins_window;
+    GtkWidget *main_vbox;
+    GtkWidget *main_frame;
+    GtkWidget *frame_hbox;
+    GtkWidget *scrolledwindow;
+    GtkWidget *plugins_clist;
+    GtkWidget *frame_vbnbox;
+    GtkWidget *enable_bn;
+    GtkWidget *disable_bn;
+    GtkWidget *filter_bn;
+    GtkWidget *main_hbnbox;
+    GtkWidget *close_bn;
+    gchar     *titles[] = {"Name", "Description", "Version", "Enabled"};
+
+    plugins_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_title(GTK_WINDOW(plugins_window), "Ethereal: Plugins");
+
+    main_vbox = gtk_vbox_new(FALSE, 0);
+    gtk_container_add(GTK_CONTAINER(plugins_window), main_vbox);
+    gtk_widget_show(main_vbox);
+
+    main_frame = gtk_frame_new("Plugins List");
+    gtk_box_pack_start(GTK_BOX(main_vbox), main_frame, TRUE, TRUE, 0);
+    gtk_container_set_border_width(GTK_CONTAINER(main_frame), 10);
+    gtk_widget_show(main_frame);
+
+    frame_hbox = gtk_hbox_new(FALSE,0);
+    gtk_container_add(GTK_CONTAINER(main_frame), frame_hbox);
+    gtk_container_set_border_width(GTK_CONTAINER(frame_hbox), 5);
+    gtk_widget_show(frame_hbox);
+
+    scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
+    gtk_box_pack_start(GTK_BOX(frame_hbox), scrolledwindow, TRUE, TRUE, 0);
+    gtk_widget_set_usize(scrolledwindow, 400, 150);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow),
+	    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_widget_show(scrolledwindow);
+
+    plugins_clist = gtk_clist_new_with_titles(4, titles);
+    gtk_container_add(GTK_CONTAINER(scrolledwindow), plugins_clist);
+    gtk_clist_set_selection_mode(GTK_CLIST(plugins_clist), GTK_SELECTION_SINGLE);
+    gtk_clist_column_titles_passive(GTK_CLIST(plugins_clist));
+    gtk_clist_column_titles_show(GTK_CLIST(plugins_clist));
+    gtk_clist_set_column_auto_resize(GTK_CLIST(plugins_clist), 0, TRUE);
+    gtk_clist_set_column_auto_resize(GTK_CLIST(plugins_clist), 1, TRUE);
+    gtk_clist_set_column_auto_resize(GTK_CLIST(plugins_clist), 2, TRUE);
+    gtk_clist_set_column_auto_resize(GTK_CLIST(plugins_clist), 3, TRUE);
+    plugins_scan(plugins_clist);
+    gtk_signal_connect(GTK_OBJECT(plugins_clist), "select_row",
+	    GTK_SIGNAL_FUNC(plugins_clist_select_cb), NULL);
+    gtk_signal_connect(GTK_OBJECT(plugins_clist), "unselect_row",
+	    GTK_SIGNAL_FUNC(plugins_clist_unselect_cb), NULL);
+    gtk_widget_show(plugins_clist);
+    selected_row = -1;
+
+    frame_vbnbox = gtk_vbutton_box_new();
+    gtk_box_pack_start(GTK_BOX(frame_hbox), frame_vbnbox, FALSE, TRUE, 0);
+    gtk_container_set_border_width(GTK_CONTAINER(frame_vbnbox), 20);
+    gtk_button_box_set_layout(GTK_BUTTON_BOX(frame_vbnbox), GTK_BUTTONBOX_START);
+    gtk_widget_show(frame_vbnbox);
+
+    enable_bn = gtk_button_new_with_label("Enable");
+    gtk_container_add(GTK_CONTAINER(frame_vbnbox), enable_bn);
+    gtk_signal_connect(GTK_OBJECT(enable_bn), "clicked",
+	    GTK_SIGNAL_FUNC(plugins_enable_cb), GTK_OBJECT(plugins_clist));
+    gtk_widget_show(enable_bn);
+    disable_bn = gtk_button_new_with_label("Disable");
+    gtk_container_add(GTK_CONTAINER(frame_vbnbox), disable_bn);
+    gtk_signal_connect(GTK_OBJECT(disable_bn), "clicked",
+	    GTK_SIGNAL_FUNC(plugins_disable_cb), GTK_OBJECT(plugins_clist));
+    gtk_widget_show(disable_bn);
+    filter_bn = gtk_button_new_with_label("Filter");
+    gtk_container_add(GTK_CONTAINER(frame_vbnbox), filter_bn);
+    gtk_signal_connect(GTK_OBJECT(filter_bn), "clicked",
+	    GTK_SIGNAL_FUNC(plugins_filter_cb), GTK_OBJECT(plugins_clist));
+    gtk_widget_show(filter_bn);
+
+    main_hbnbox = gtk_hbutton_box_new();
+    gtk_box_pack_start(GTK_BOX(main_vbox), main_hbnbox, FALSE, TRUE, 0);
+    gtk_container_set_border_width(GTK_CONTAINER(main_hbnbox), 10);
+    gtk_widget_show(main_hbnbox);
+
+    close_bn = gtk_button_new_with_label("Close");
+    gtk_container_add(GTK_CONTAINER(main_hbnbox), close_bn);
+    gtk_widget_show(close_bn);
+    gtk_signal_connect(GTK_OBJECT(close_bn), "clicked",
+	    GTK_SIGNAL_FUNC(plugins_close_cb), GTK_OBJECT(plugins_window));
+
+    gtk_widget_show(plugins_window);
+}
+
+/*
+ * scan /usr/share/ethereal/plugins, /usr/local/share/ethereal/plugins and
+ * ~/.ethereal/plugins and fill the clist widget
+ */
+static void
+plugins_scan(GtkWidget *clist)
+{
+    plugin *pt_plug;
+    gchar  *plugent[4];               /* new entry added in clist */
+
+    if (plugin_list == NULL)          /* first intialisation */
+    {
+	plugins_scan_dir(std_plug_dir);
+	plugins_scan_dir(local_plug_dir);
+	if (!user_plug_dir)
+	{
+	    user_plug_dir = (gchar *)g_malloc(strlen(getenv("HOME")) + 19);
+	    sprintf(user_plug_dir, "%s/.ethereal/plugins", getenv("HOME"));
+	}
+	plugins_scan_dir(user_plug_dir);
+    }
+
+    pt_plug = plugin_list;
+    while (pt_plug)
+    {
+	plugent[0] = pt_plug->name;
+	plugent[1] = (gchar *)dlsym(pt_plug->handle, "desc");
+	plugent[2] = pt_plug->version;
+	plugent[3] = (pt_plug->enabled ? "Yes" : "No");
+	gtk_clist_append(GTK_CLIST(clist), plugent);
+	pt_plug = pt_plug->next;
+    }
+}
+
+static void
+plugins_scan_dir(const char *dirname)
+{
+    DIR           *dir;             /* scanned directory */
+    struct dirent *file;            /* current file */
+    gchar          filename[512];   /* current file name */
+    void          *handle;          /* handle returned by dlopen */
+    gchar         *name;
+    gchar         *version;
+    gchar         *protocol;
+    gchar         *filter_string;
+    dfilter       *filter = NULL;
+    void         (*dissector) (const u_char *, int, frame_data *, proto_tree *);
+    int            cr;
+
+    if ((dir = opendir(dirname)) != NULL)
+    {
+	while ((file = readdir(dir)) != NULL)
+	{
+	    sprintf(filename, "%s/%s", dirname, file->d_name);
+
+	    if ((handle = dlopen(filename, RTLD_LAZY)) == NULL) continue;
+	    name = (gchar *)file->d_name;
+	    if ((version = (gchar *)dlsym(handle, "version")) == NULL)
+	    {
+		dlclose(handle);
+		continue;
+	    }
+	    if ((protocol = (gchar *)dlsym(handle, "protocol")) == NULL)
+	    {
+		dlclose(handle);
+		continue;
+	    }
+	    if ((filter_string = (gchar *)dlsym(handle, "filter_string")) == NULL)
+	    {
+		dlclose(handle);
+		continue;
+	    }
+	    if (dfilter_compile(filter_string, &filter) != 0) {
+		dlclose(handle);
+		continue;
+	    }
+	    if ((dissector = (void (*)(const u_char *, int,
+				frame_data *,
+				proto_tree *)) dlsym(handle, "dissector")) == NULL)
+	    {
+		if (filter != NULL)
+		    dfilter_destroy(filter);
+		dlclose(handle);
+		continue;
+	    }
+
+	    if ((cr = add_plugin(handle, g_strdup(file->d_name), version,
+				 protocol, filter_string, filter, dissector)))
+	    {
+		if (cr == EEXIST)
+		    simple_dialog(ESD_TYPE_WARN, NULL, "The plugin : %s, version %s\n"
+			"was found in multiple directories", name, version);
+		else
+		    simple_dialog(ESD_TYPE_WARN, NULL, "Memory allocation problem");
+		if (filter != NULL)
+		    dfilter_destroy(filter);
+		dlclose(handle);
+		continue;
+	    }
+	}
+	closedir(dir);
+    }
+}
+
+static void
+plugins_close_cb(GtkWidget *close_bt, gpointer parent_w)
+{
+    gtk_grab_remove(GTK_WIDGET(parent_w));
+    gtk_widget_destroy(GTK_WIDGET(parent_w));
+}
+
+void plugins_clist_select_cb(GtkWidget *clist, gint row, gint column,
+	GdkEventButton *event, gpointer data)
+{
+    selected_row = row;
+    gtk_clist_get_text(GTK_CLIST(clist), selected_row, 0, &selected_name);
+    gtk_clist_get_text(GTK_CLIST(clist), selected_row, 2, &selected_version);
+    gtk_clist_get_text(GTK_CLIST(clist), selected_row, 3, &selected_enabled);
+}
+
+void plugins_clist_unselect_cb(GtkWidget *clist, gint row, gint column,
+	GdkEventButton *event, gpointer data)
+{
+    selected_row = -1;
+}
+
+static void
+plugins_enable_cb(GtkWidget *button, gpointer clist)
+{
+    plugin    *pt_plug;
+    void     (*proto_init) ();
+
+    /* nothing selected */
+    if (selected_row == -1) return;
+    /* already enabled */
+    if (!strcmp(selected_enabled, "Yes")) return;
+
+    if ((pt_plug = enable_plugin(selected_name, selected_version)) == NULL)
+    {
+	simple_dialog(ESD_TYPE_WARN, NULL, "Plugin not found");
+	return;
+    }
+    proto_init = (void (*)())dlsym(pt_plug->handle, "proto_init");
+    if (proto_init)
+	proto_init();
+
+    gtk_clist_set_text(GTK_CLIST(clist), selected_row, 3, "Yes");
+}
+
+static void
+plugins_disable_cb(GtkWidget *button, gpointer clist)
+{
+    plugin    *pt_plug;
+
+    /* nothing selected */
+    if (selected_row == -1) return;
+    /* already disabled */
+    if (!strcmp(selected_enabled, "No")) return;
+
+    if ((pt_plug = disable_plugin(selected_name, selected_version)) == NULL)
+    {
+	simple_dialog(ESD_TYPE_WARN, NULL, "Plugin not found");
+	return;
+    }
+    gtk_clist_set_text(GTK_CLIST(clist), selected_row, 3, "No");
+}
+
+static void
+plugins_filter_cb(GtkWidget *button, gpointer clist)
+{
+    GtkWidget *filter_window;
+    GtkWidget *filter_vbox;
+    GtkWidget *filter_frame;
+    GtkWidget *filter_entry;
+    GtkWidget *filter_hbnbox;
+    GtkWidget *ok_bn;
+    GtkWidget *cancel_bn;
+    plugin    *pt_plug;
+
+    if (selected_row == -1) return;
+    pt_plug = find_plugin(selected_name, selected_version);
+
+    filter_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_title(GTK_WINDOW(filter_window), "Ethereal: Plugin Filter");
+    gtk_window_set_modal(GTK_WINDOW(filter_window), TRUE);
+
+    filter_vbox = gtk_vbox_new(FALSE, 0);
+    gtk_container_add(GTK_CONTAINER(filter_window), filter_vbox);
+    gtk_widget_show(filter_vbox);
+
+    filter_frame = gtk_frame_new("Plugin Filter");
+    gtk_box_pack_start(GTK_BOX(filter_vbox), filter_frame, TRUE, TRUE, 0);
+    gtk_container_set_border_width(GTK_CONTAINER(filter_frame), 10);
+    gtk_widget_show(filter_frame);
+
+    filter_entry = gtk_entry_new();
+    gtk_object_set_data(GTK_OBJECT(filter_window), PLUGINS_DFILTER_TE,
+	                filter_entry);
+    gtk_container_add(GTK_CONTAINER(filter_frame), filter_entry);
+    gtk_entry_set_text(GTK_ENTRY(filter_entry), pt_plug->filter_string);
+    if (!strcmp(selected_enabled, "Yes"))
+	gtk_entry_set_editable(GTK_ENTRY(filter_entry), TRUE);
+    else
+	gtk_entry_set_editable(GTK_ENTRY(filter_entry), FALSE);
+    gtk_widget_show(filter_entry);
+
+    filter_hbnbox = gtk_hbutton_box_new();
+    gtk_box_pack_start(GTK_BOX(filter_vbox), filter_hbnbox, FALSE, TRUE, 0);
+    gtk_container_set_border_width(GTK_CONTAINER(filter_hbnbox), 10);
+    gtk_widget_show(filter_hbnbox);
+
+    ok_bn = gtk_button_new_with_label("Ok");
+    gtk_container_add(GTK_CONTAINER(filter_hbnbox), ok_bn);
+    gtk_widget_show(ok_bn);
+    gtk_signal_connect(GTK_OBJECT(ok_bn), "clicked",
+	    GTK_SIGNAL_FUNC(filter_ok_cb), GTK_OBJECT(filter_window));
+
+    cancel_bn = gtk_button_new_with_label("Cancel");
+    gtk_container_add(GTK_CONTAINER(filter_hbnbox), cancel_bn);
+    gtk_widget_show(cancel_bn);
+    gtk_signal_connect(GTK_OBJECT(cancel_bn), "clicked",
+	    GTK_SIGNAL_FUNC(filter_cancel_cb), GTK_OBJECT(filter_window));
+
+    gtk_widget_show(filter_window);
+}
+
+static void
+filter_ok_cb(GtkWidget *close_bt, gpointer parent_w)
+{
+    GtkWidget *filter_entry;
+    gchar     *filter_string;
+    dfilter   *filter = NULL;
+
+    if (!strcmp(selected_enabled, "Yes"))
+    {
+	filter_entry = gtk_object_get_data(GTK_OBJECT(parent_w), PLUGINS_DFILTER_TE);
+	filter_string = gtk_entry_get_text(GTK_ENTRY(filter_entry));
+	if (dfilter_compile(filter_string, &filter) != 0)
+	{
+	    simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
+	}
+	else
+	    plugin_replace_filter(selected_name, selected_version,
+		                  filter_string, filter);
+    }
+    gtk_grab_remove(GTK_WIDGET(parent_w));
+    gtk_widget_destroy(GTK_WIDGET(parent_w));
+}
+
+static void
+filter_cancel_cb(GtkWidget *close_bt, gpointer parent_w)
+{
+    gtk_grab_remove(GTK_WIDGET(parent_w));
+    gtk_widget_destroy(GTK_WIDGET(parent_w));
+}
+#endif
diff -Nru ethereal/packet-tcp.c ethereal.plug/packet-tcp.c
--- ethereal/packet-tcp.c	Tue Dec  7 07:41:20 1999
+++ ethereal.plug/packet-tcp.c	Wed Dec  8 22:26:20 1999
@@ -37,7 +37,7 @@
 
 #include <stdio.h>
 #include <glib.h>
-#include "packet.h"
+#include "globals.h"
 #include "resolv.h"
 #include "follow.h"
 #include "util.h"
@@ -51,6 +51,10 @@
 # include "snprintf.h"
 #endif
 
+#ifdef HAVE_DLFCN_H
+#include "plugins.h"
+#endif
+
 #ifndef __PACKET_IP_H__
 #include "packet-ip.h"
 #endif
@@ -480,6 +484,22 @@
   /* Check the packet length to see if there's more data
      (it could be an ACK-only packet) */
   if (packet_max > offset) {
+
+    /* try to apply the plugins */
+#ifdef HAVE_DLFCN_H
+    plugin *pt_plug = plugin_list;
+
+    if (pt_plug) {
+      while (pt_plug) {
+	if (pt_plug->enabled && !strcmp(pt_plug->protocol, "tcp") &&
+	    tree && dfilter_apply(pt_plug->filter, tree, pd)) {
+	  pt_plug->dissector(pd, offset, fd, tree);
+	  goto reas;
+	}
+	pt_plug = pt_plug->next;
+      }
+    }
+#endif
 
     /* ONC RPC.  We can't base this on anything in the TCP header; we have
        to look at the payload.  If "dissect_rpc()" returns TRUE, it was
diff -Nru ethereal/packet-udp.c ethereal.plug/packet-udp.c
--- ethereal/packet-udp.c	Tue Dec  7 07:41:20 1999
+++ ethereal.plug/packet-udp.c	Wed Dec  8 22:26:20 1999
@@ -41,9 +41,13 @@
 #include <stdlib.h>
 
 #include <glib.h>
-#include "packet.h"
+#include "globals.h"
 #include "resolv.h"
 
+#ifdef HAVE_DLFCN_H
+#include "plugins.h"
+#endif
+
 static int proto_udp = -1;		
 static int hf_udp_srcport = -1;
 static int hf_udp_dstport = -1;
@@ -238,6 +242,24 @@
      an RPC packet, otherwise it's some other type of packet. */
   if (dissect_rpc(pd, offset, fd, tree))
     return;
+
+  /* try to apply the plugins */
+#ifdef HAVE_DLFCN_H
+  {
+      plugin *pt_plug = plugin_list;
+
+      if (pt_plug) {
+	  while (pt_plug) {
+	      if (pt_plug->enabled && !strcmp(pt_plug->protocol, "udp") &&
+		  tree && dfilter_apply(pt_plug->filter, tree, pd)) {
+		  pt_plug->dissector(pd, offset, fd, tree);
+		  return;
+	      }
+	      pt_plug = pt_plug->next;
+	  }
+      }
+  }
+#endif
 
   /* XXX - we should do all of this through the table of ports. */
 #define PORT_IS(port)	(uh_sport == port || uh_dport == port)
diff -Nru ethereal/plugins.c ethereal.plug/plugins.c
--- ethereal/plugins.c	Thu Jan  1 01:00:00 1970
+++ ethereal.plug/plugins.c	Wed Dec  8 22:26:20 1999
@@ -0,0 +1,204 @@
+/* plugins.c
+ * definitions for plugins structures
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_DLFCN_H
+
+#include <time.h>
+
+#include "globals.h"
+
+#include "plugins.h"
+
+/* linked list of all plugins */
+plugin *plugin_list;
+
+/*
+ * add a new plugin to the list
+ * returns :
+ * - 0 : OK
+ * - ENOMEM : memory allocation problem
+ * - EEXIST : the same plugin (i.e. name/version) was already registered.
+ */
+int
+add_plugin(void *handle, gchar *name, gchar *version, gchar *protocol,
+	   gchar *filter_string, dfilter *filter,
+	   void (*dissector) (const u_char *,
+	                      int,
+			      frame_data *,
+			      proto_tree *))
+{
+    plugin *new_plug, *pt_plug;
+
+    pt_plug = plugin_list;
+    if (!pt_plug) /* the list is empty */
+    {
+	new_plug = (plugin *)g_malloc(sizeof(plugin));
+	if (new_plug == NULL) return ENOMEM;
+        plugin_list = new_plug;
+    }
+    else
+    {
+	while (1)
+	{
+	    /* check if the same name/version is already registered */
+	    if (!strcmp(pt_plug->name, name) &&
+		!strcmp(pt_plug->version, version))
+	    {
+		return EEXIST;
+	    }
+
+	    /* we found the last plugin in the list */
+	    if (pt_plug->next == NULL) break;
+
+	    pt_plug = pt_plug->next;
+	}
+	new_plug = (plugin *)g_malloc(sizeof(plugin));
+	if (new_plug == NULL) return ENOMEM;
+	pt_plug->next = new_plug;
+    }
+
+    new_plug->handle = handle;
+    new_plug->name = name;
+    new_plug->version = version;
+    new_plug->enabled = FALSE;
+    new_plug->protocol = protocol;
+    new_plug->filter_string = g_strdup(filter_string);
+    new_plug->filter = filter;
+    new_plug->dissector = dissector;
+    new_plug->next = NULL;
+    return 0;
+}
+
+/*
+ * enable a plugin
+ * returns a pointer to the enabled plugin, or NULL if the plugin wasn't found
+ * in the list
+ */
+void *
+enable_plugin(const gchar *name, const gchar *version)
+{
+    plugin *pt_plug;
+
+    pt_plug = plugin_list;
+    while (pt_plug)
+    {
+	if (!strcmp(pt_plug->name, name) && !strcmp(pt_plug->version, version))
+	{
+	    pt_plug->enabled = TRUE;
+	    return pt_plug;
+	}
+	pt_plug = pt_plug->next;
+    }
+    return NULL;
+}
+
+/*
+ * disable a plugin
+ * returns a pointer to the disabled plugin, or NULL if the plugin wasn't found
+ * in the list
+ */
+void *
+disable_plugin(const gchar *name, const gchar *version)
+{
+    plugin *pt_plug;
+
+    pt_plug = plugin_list;
+    while (pt_plug)
+    {
+	if (!strcmp(pt_plug->name, name) && !strcmp(pt_plug->version, version))
+	{
+	    pt_plug->enabled = FALSE;
+	    return pt_plug;
+	}
+	pt_plug = pt_plug->next;
+    }
+    return NULL;
+}
+
+/*
+ * find a plugin using its name/version
+ */
+void *
+find_plugin(const gchar *name, const gchar *version)
+{
+    plugin *pt_plug;
+
+    pt_plug = plugin_list;
+    while (pt_plug)
+    {
+	if (!strcmp(pt_plug->name, name) && !strcmp(pt_plug->version, version))
+	{
+	    return pt_plug;
+	}
+	pt_plug = pt_plug->next;
+    }
+    return NULL;
+}
+
+/*
+ * check if a plugin is enabled
+ */
+gboolean
+is_enabled(const gchar *name, const gchar *version)
+{
+    plugin *pt_plug;
+
+    pt_plug = plugin_list;
+    while (pt_plug)
+    {
+	if (!strcmp(pt_plug->name, name) && !strcmp(pt_plug->version, version))
+	    return pt_plug->enabled;
+	pt_plug = pt_plug->next;
+    }
+    return FALSE;
+}
+
+/*
+ * replace the filter used by a plugin (filter string and dfilter)
+ */
+void
+plugin_replace_filter(const gchar *name, const gchar *version,
+	const gchar *filter_string, dfilter *filter)
+{
+    plugin *pt_plug;
+
+    pt_plug = plugin_list;
+    while (pt_plug)
+    {
+	if (!strcmp(pt_plug->name, name) && !strcmp(pt_plug->version, version))
+	{
+	    g_free(pt_plug->filter_string);
+	    pt_plug->filter_string = g_strdup(filter_string);
+	    dfilter_destroy(pt_plug->filter);
+	    pt_plug->filter = filter;
+	    return;
+	}
+	pt_plug = pt_plug->next;
+    }
+}
+
+#endif
diff -Nru ethereal/plugins.h ethereal.plug/plugins.h
--- ethereal/plugins.h	Thu Jan  1 01:00:00 1970
+++ ethereal.plug/plugins.h	Wed Dec  8 22:26:20 1999
@@ -0,0 +1,52 @@
+/* plugins.h
+ * definitions for plugins structures
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __PLUGINS_H__
+#define __PLUGINS_H__
+
+typedef struct _plugin {
+    void    *handle;          /* handle returned by dlopen */
+    gchar   *name;            /* plugin name */
+    gchar   *version;         /* plugin version */
+    gboolean enabled;         /* is it active ? */
+    gchar   *protocol;        /* protocol which should call the dissector
+			       * for this plugin eg "tcp" */
+    gchar   *filter_string;   /* display filter string matching frames for
+			       * which the dissector should be used */
+    dfilter *filter;          /* compiled display filter */
+    /* the dissector */
+    void (*dissector) (const u_char *, int, frame_data *, proto_tree *);
+    struct _plugin *next;     /* forward link */
+} plugin;
+
+extern plugin *plugin_list;
+
+int add_plugin(void *, gchar *, gchar *, gchar *, gchar *, dfilter *,
+	          void (*) (const u_char *, int, frame_data *, proto_tree *));
+void *enable_plugin(const gchar *, const gchar *);
+void *disable_plugin(const gchar *, const gchar *);
+void *find_plugin(const gchar *, const gchar *);
+gboolean is_enabled(const gchar *, const gchar *);
+void plugin_replace_filter(const gchar *, const gchar *, const gchar *, dfilter *);
+
+#endif /* __PLUGINS_H__ */


-- 
"Everyone is entitled to an *informed* opinion."
-- Harlan Ellison

Attachment: gryphon.tar.gz
Description: Binary data