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):