Ethereal-dev: Re: [ethereal-dev] plugins support
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: Mon, 8 Nov 1999 22:46:11 +0100
On dim, nov 07, 1999 at 10:44:26 +0100, Olivier Abad wrote: > > I should have an implementation ready for tomorrow. Here it is. This patch adds a "Plugins..." entry in the File menu. It opens a dialog which lists available plugins. The user must enable the plugins he wants to use. Plugins are searched in /usr/share/ethereal/plugins, /usr/local/share/ethereal/plugins and $HOME/.ethereal/plugins The design is not perfect, and there is some more work to do : - the "name" symbol provided by the plugin must match the file name of the plugin (so the symbol is not very useful, I may remove it in the future) - I added a "version" string but I don't use it yet (it is displayed in the dialog) - the "Enable" button doesn't refresh the packet list - the "Details" button does nothing. It should allow to change the "filter_string" used by a plugin - there is no way to disable a plugin - if the same plugin is found in several directories, it will be listed several times - plugins should use ETT_NONE when creating subtrees (maybe we could dynamically allocate ETT_xxx values). - I only put the hooks for calling the plugins in dissect_tcp - plugins are only enabled on platforms which support dlopen. I don't know what could be done on other platforms. I'm also attaching an http.c which should generate ... an http plugin ! It is the standard packet-http.c, slightly modified (dissect_http is renamed dissector, proto_register_http is renamed proto_init, ETT_HTTP is replaced with ETT_NONE). To compile it : $ gcc -DHAVE_CONFIG_H -Wall -g -O2 -I/usr/lib/glib/include -c http.c $ ld -shared -o http http.o $ mkdir ~/.ethereal/plugins $ cp http ~/.ethereal/plugins Remove dissect_http from packet-tcp.c if you want to be sure the plugin works. Olivier -- Good day to avoid cops. Crawl to school.
diff -Nru ethereal/Makefile.am ethereal.plug/Makefile.am
--- ethereal/Makefile.am Fri Oct 29 03:04:16 1999
+++ ethereal.plug/Makefile.am Mon Nov 8 21:47:15 1999
@@ -145,6 +145,8 @@
ipproto.c \
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 Thu Oct 28 05:33:19 1999
+++ ethereal.plug/configure.in Mon Nov 8 21:47:15 1999
@@ -131,6 +131,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 Mon Nov 8 07:53:18 1999
+++ ethereal.plug/file.c Mon Nov 8 21:47:15 1999
@@ -85,6 +85,10 @@
#include "timestamp.h"
#include "conversation.h"
+#ifdef HAVE_DLFCN_H
+#include "plugins.h"
+#endif
+
#ifndef __RESOLV_H__
#include "resolv.h"
#endif
@@ -834,7 +838,7 @@
gint i, row;
gint crow;
gint color;
- proto_tree *protocol_tree;
+ proto_tree *protocol_tree = NULL;
fdata->num = cf->count;
@@ -887,9 +891,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 Mon Nov 8 07:53:19 1999
+++ ethereal.plug/gtk/Makefile.am Mon Nov 8 21:47:15 1999
@@ -53,6 +53,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/main.h ethereal.plug/gtk/main.h
--- ethereal/gtk/main.h Fri Oct 8 09:29:42 1999
+++ ethereal.plug/gtk/main.h Mon Nov 8 21:47:15 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 Sun Nov 7 14:37:25 1999
+++ ethereal.plug/gtk/menu.c Mon Nov 8 21:47:15 1999
@@ -82,6 +82,10 @@
{"/File/Save _As...", NULL, GTK_MENU_FUNC(file_save_as_cmd_cb), 0, NULL},
{"/File/_Reload", "<control>R", GTK_MENU_FUNC(file_reload_cmd_cb), 0, NULL},
{"/File/<separator>", NULL, NULL, 0, "<Separator>"},
+#ifdef HAVE_DLFCN_H
+ {"/File/Plu_gins...", "<control>G", GTK_MENU_FUNC(file_plugins_cmd_cb), 0, NULL},
+ {"/File/<separator>", NULL, NULL, 0, "<Separator>"},
+#endif
{"/File/Print...", NULL, GTK_MENU_FUNC(file_print_cmd_cb), 0, NULL},
{"/File/Print Pac_ket", "<control>P", GTK_MENU_FUNC(file_print_packet_cmd_cb), 0, NULL},
{"/File/<separator>", NULL, NULL, 0, "<Separator>"},
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 Mon Nov 8 21:47:33 1999
@@ -0,0 +1,334 @@
+/* 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 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 *, 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_details_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, *details_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, std_plug_dir);
+ plugins_scan(plugins_clist, 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(plugins_clist, user_plug_dir);
+ 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);
+ details_bn = gtk_button_new_with_label("Details");
+ gtk_container_add(GTK_CONTAINER(frame_vbnbox), details_bn);
+ gtk_signal_connect(GTK_OBJECT(details_bn), "clicked",
+ GTK_SIGNAL_FUNC(plugins_details_cb), GTK_OBJECT(plugins_clist));
+ gtk_widget_show(details_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, 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 *plugent[4]; /* new entry added in clist */
+ gint row; /* index of the new row */
+
+ 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;
+ /* plugin name */
+ if ((plugent[0] = (gchar *)dlsym(handle, "name")) == NULL)
+ {
+ dlclose(handle);
+ continue;
+ }
+ /* plugin description */
+ if ((plugent[1] = (gchar *)dlsym(handle, "desc")) == NULL)
+ {
+ dlclose(handle);
+ continue;
+ }
+ /* plugin version */
+ if ((plugent[2] = (gchar *)dlsym(handle, "version")) == NULL)
+ {
+ dlclose(handle);
+ continue;
+ }
+ /* check if plugin already loaded */
+ if (is_enabled(plugent[0], plugent[2]))
+ plugent[3] = "Yes";
+ else
+ plugent[3] = "No";
+ row = gtk_clist_append(GTK_CLIST(clist), plugent);
+ gtk_clist_set_row_data(GTK_CLIST(clist), row, (gpointer)dirname);
+ dlclose(handle);
+ }
+ 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;
+}
+
+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)
+{
+ gchar *pl_name, *dirname, *filename;
+ void *handle;
+ gchar *name, *version, *protocol;
+ gchar *filter_string;
+ dfilter *filter = NULL;
+ void (*dissector) (const u_char *, int, frame_data *, proto_tree *);
+ void (*proto_init) ();
+
+ if (selected_row == -1) return;
+ dirname = (gchar *)gtk_clist_get_row_data(GTK_CLIST(clist), selected_row);
+ if (!dirname) return;
+ gtk_clist_get_text(GTK_CLIST(clist), selected_row, 0, &filename);
+ if (!filename) return;
+
+ pl_name = g_strdup_printf("%s/%s", dirname, filename);
+
+ if ((handle = dlopen(pl_name, RTLD_LAZY)) == NULL) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Can't load plugin");
+ g_free(pl_name);
+ return;
+ }
+
+ if ((name = (gchar *)dlsym(handle, "name")) == NULL)
+ {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Invalid plugin");
+ dlclose(handle);
+ g_free(pl_name);
+ return;
+ }
+ if ((version = (gchar *)dlsym(handle, "version")) == NULL)
+ {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Invalid plugin");
+ dlclose(handle);
+ g_free(pl_name);
+ return;
+ }
+ if ((protocol = (gchar *)dlsym(handle, "protocol")) == NULL)
+ {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Invalid plugin");
+ dlclose(handle);
+ g_free(pl_name);
+ return;
+ }
+ if ((filter_string = (gchar *)dlsym(handle, "filter_string")) == NULL)
+ {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Invalid plugin");
+ dlclose(handle);
+ g_free(pl_name);
+ return;
+ }
+ if (dfilter_compile(filter_string, &filter) != 0) {
+ simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
+ dlclose(handle);
+ g_free(pl_name);
+ return;
+ }
+ if ((dissector = (void (*)(const u_char *, int,
+ frame_data *,
+ proto_tree *)) dlsym(handle, "dissector")) == NULL)
+ {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Invalid plugin");
+ if (filter != NULL)
+ dfilter_destroy(filter);
+ dlclose(handle);
+ g_free(pl_name);
+ return;
+ }
+ if ((proto_init = (void (*)()) dlsym(handle, "proto_init")) == NULL)
+ {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Invalid plugin");
+ if (filter != NULL)
+ dfilter_destroy(filter);
+ dlclose(handle);
+ g_free(pl_name);
+ return;
+ }
+
+ if (enable_plugin(handle, name, version, protocol, filter, dissector)) {
+ simple_dialog(ESD_TYPE_WARN, NULL, "Can't load new plugin");
+ if (filter != NULL)
+ dfilter_destroy(filter);
+ dlclose(handle);
+ g_free(pl_name);
+ return;
+ }
+ proto_init();
+
+ gtk_clist_set_text(GTK_CLIST(clist), selected_row, 3, "Yes");
+ g_free(pl_name);
+}
+
+static void
+plugins_details_cb(GtkWidget *button, gpointer clist)
+{
+}
+
+#endif
diff -Nru ethereal/packet-tcp.c ethereal.plug/packet-tcp.c
--- ethereal/packet-tcp.c Tue Nov 2 08:04:46 1999
+++ ethereal.plug/packet-tcp.c Mon Nov 8 21:47:15 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
@@ -468,6 +472,22 @@
/* Check the packet length to see if there's more data
(it could be an ACK-only packet) */
if (packet_max > offset) {
+#ifdef HAVE_DLFCN_H
+ plugin *pt_plug = plugin_list;
+
+ if (pt_plug) {
+ while (pt_plug) {
+ if (!strcmp(pt_plug->protocol, "tcp")) {
+ if (tree && dfilter_apply(pt_plug->filter, tree, pd)) {
+ pt_plug->dissector(pd, offset, fd, tree);
+ goto dissect_end;
+ }
+ }
+ pt_plug = pt_plug->next;
+ }
+ }
+#endif
+
/* XXX - this should be handled the way UDP handles this, with a table
of port numbers to which stuff can be added */
#define PORT_IS(port) (th.th_sport == port || th.th_dport == port)
@@ -522,6 +542,8 @@
}
}
+dissect_end:
+
if( data_out_file ) {
reassemble_tcp( th.th_seq, /* sequence number */
( pi.len - offset ), /* data length */
diff -Nru ethereal/plugins.c ethereal.plug/plugins.c
--- ethereal/plugins.c Thu Jan 1 01:00:00 1970
+++ ethereal.plug/plugins.c Mon Nov 8 21:47:25 1999
@@ -0,0 +1,84 @@
+/* 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"
+
+plugin *plugin_list;
+
+int
+enable_plugin(void *handle, gchar *name, gchar *version, gchar *protocol, dfilter *filter,
+ void (*dissector) (const u_char *,
+ int,
+ frame_data *,
+ proto_tree *))
+{
+ plugin *new_plug, *pt_plug;
+
+ new_plug = (plugin *)g_malloc(sizeof(plugin));
+ if (new_plug == 0) return -1;
+
+ pt_plug = plugin_list;
+ if (!pt_plug)
+ plugin_list = new_plug;
+ else
+ {
+ while (pt_plug->next) pt_plug = pt_plug->next;
+ pt_plug->next = new_plug;
+ }
+
+ new_plug->handle = handle;
+ new_plug->name = name;
+ new_plug->version = version;
+ new_plug->protocol = protocol;
+ new_plug->filter = filter;
+ new_plug->dissector = dissector;
+ new_plug->next = NULL;
+ return 0;
+}
+
+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 TRUE;
+ pt_plug = pt_plug->next;
+ }
+ return FALSE;
+}
+
+#endif
diff -Nru ethereal/plugins.h ethereal.plug/plugins.h
--- ethereal/plugins.h Thu Jan 1 01:00:00 1970
+++ ethereal.plug/plugins.h Mon Nov 8 21:47:15 1999
@@ -0,0 +1,46 @@
+/* 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 */
+ gchar *protocol; /* protocol which should call the dissector
+ * for this plugin eg "tcp" */
+ dfilter *filter; /* display filter matching frames for which
+ * the dissector should be used */
+ /* the dissector */
+ void (*dissector) (const u_char *, int, frame_data *, proto_tree *);
+ struct _plugin *next; /* forward link */
+} plugin;
+
+extern plugin *plugin_list;
+
+int enable_plugin(void *, gchar *, gchar *, gchar *, dfilter *,
+ void (*) (const u_char *, int, frame_data *, proto_tree *));
+gboolean is_enabled(const gchar *, const gchar *);
+
+#endif /* __PLUGINS_H__ */
/* packet-http.c
* Routines for HTTP packet disassembly
*
* Guy Harris <guy@xxxxxxxxxx>
*
* $Id: packet-http.c,v 1.10 1999/10/16 20:30:14 deniel Exp $
*
* 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_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <string.h>
#include <ctype.h>
#include <glib.h>
#include "globals.h"
#include "dfilter.h"
gchar name[] = "http";
gchar version[] = "1.0";
gchar desc[] = "HTTP packet disassembly";
gchar protocol[] = "tcp";
gchar filter_string[] = "tcp.port == 80 || tcp.port == 8080 || tcp.port == 631";
static int proto_http = -1;
static int hf_http_response = -1;
static int hf_http_request = -1;
static proto_tree *http_tree;
static int is_http_request_or_reply(const u_char *data, int linelen);
void dissector(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
{
gboolean is_ipp = (pi.srcport == 631 || pi.destport == 631);
proto_item *ti;
const u_char *data, *dataend;
const u_char *linep, *lineend, *eol;
int linelen;
u_char c;
data = &pd[offset];
dataend = data + END_OF_FRAME;
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, is_ipp ? "IPP" : "HTTP");
if (check_col(fd, COL_INFO)) {
/*
* Put the first line from the buffer into the summary,
* if it's an HTTP request or reply.
* Otherwise, just call it a continuation.
*/
lineend = find_line_end(data, dataend, &eol);
linelen = lineend - data;
if (is_http_request_or_reply(data, linelen))
col_add_str(fd, COL_INFO, format_text(data, linelen));
else
col_add_str(fd, COL_INFO, "Continuation");
}
if (tree) {
ti = proto_tree_add_item(tree, proto_http, offset, END_OF_FRAME, NULL);
http_tree = proto_item_add_subtree(ti, ETT_NONE);
while (data < dataend) {
/*
* Find the end of the line.
*/
lineend = find_line_end(data, dataend, &eol);
linelen = lineend - data;
/*
* OK, does it look like an HTTP request or
* response?
*/
if (is_http_request_or_reply(data, linelen))
goto is_http;
/*
* No. Does it look like a blank line (as would
* appear at the end of an HTTP request)?
*/
if (linelen == 1) {
if (*data == '\n')
goto is_http;
}
if (linelen == 2) {
if (strncmp(data, "\r\n", 2) == 0 ||
strncmp(data, "\n\r", 2) == 0)
goto is_http;
}
/*
* No. Does it look like a MIME header?
*/
linep = data;
while (linep < lineend) {
c = *linep++;
if (!isprint(c))
break; /* not printable, not a MIME header */
switch (c) {
case '(':
case ')':
case '<':
case '>':
case '@':
case ',':
case ';':
case '\\':
case '"':
case '/':
case '[':
case ']':
case '?':
case '=':
case '{':
case '}':
/*
* It's a tspecial, so it's not
* part of a token, so it's not
* a field name for the beginning
* of a MIME header.
*/
goto not_http;
case ':':
/*
* This ends the token; we consider
* this to be a MIME header.
*/
goto is_http;
}
}
not_http:
/*
* We don't consider this part of an HTTP request or
* reply, so we don't display it.
* (Yeah, that means we don't display, say, a
* text/http page, but you can get that from the
* data pane.)
*/
break;
is_http:
/*
* Put this line.
*/
proto_tree_add_text(http_tree, offset, linelen, "%s",
format_text(data, linelen));
offset += linelen;
data = lineend;
}
if (data < dataend) {
if (is_ipp)
dissect_ipp(pd, offset, fd, tree);
else
dissect_data(&pd[offset], offset, fd, http_tree);
}
}
}
/*
* XXX - this won't handle HTTP 0.9 replies, but they're all data
* anyway.
*/
static int
is_http_request_or_reply(const u_char *data, int linelen)
{
if (linelen >= 3) {
if (strncasecmp(data, "GET", 3) == 0 ||
strncasecmp(data, "PUT", 3) == 0) {
proto_tree_add_item_hidden(http_tree,
hf_http_request, 0, 0, 1);
return TRUE;
}
}
if (linelen >= 4) {
if (strncasecmp(data, "HEAD", 4) == 0 ||
strncasecmp(data, "POST", 4) == 0) {
proto_tree_add_item_hidden(http_tree,
hf_http_request, 0, 0, 1);
return TRUE;
}
}
if (linelen >= 5) {
if (strncasecmp(data, "TRACE", 5) == 0)
return TRUE;
if (strncasecmp(data, "HTTP/", 5) == 0) {
proto_tree_add_item_hidden(http_tree,
hf_http_response, 0, 0, 1);
return TRUE; /* response */
}
}
if (linelen >= 6) {
if (strncasecmp(data, "DELETE", 6) == 0)
return TRUE;
}
if (linelen >= 7) {
if (strncasecmp(data, "OPTIONS", 7) == 0)
return TRUE;
}
return FALSE;
}
void
proto_init(void)
{
static hf_register_info hf[] = {
{ &hf_http_response,
{ "Response", "http.response",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"TRUE if HTTP response" }},
{ &hf_http_request,
{ "Request", "http.request",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"TRUE if HTTP request (GET, PUT, HEAD, POST)" }},
};
dfilter_cleanup();
proto_http = proto_register_protocol("Hypertext Transfer Protocol", "http");
proto_register_field_array(proto_http, hf, array_length(hf));
dfilter_init();
}
- Follow-Ups:
- Re: [ethereal-dev] plugins support
- From: Guy Harris
- Re: [ethereal-dev] plugins support
- References:
- [ethereal-dev] plugins support
- From: Olivier Abad
- [ethereal-dev] plugins support
- Prev by Date: [ethereal-dev] Re: [ethereal-users] Ethereal - Displaying IPX Net names and hostnames in capture mode?
- Next by Date: [ethereal-dev] Re: [ethereal-users] Ethereal - Displaying IPX Net names and hostnames in capture mode?
- Previous by thread: Re: [ethereal-dev] plugins support
- Next by thread: Re: [ethereal-dev] plugins support
- Index(es):





