summaryrefslogtreecommitdiff
path: root/epan/disabled_protos.c
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2015-07-05 17:31:14 -0400
committerMichael Mann <mmann78@netscape.net>2015-07-14 11:28:55 +0000
commitcdeae7e72b749cdd68207d6e97dafb67783e2de4 (patch)
tree6a9efe436eb41c2b9681a2c90917baeb51127353 /epan/disabled_protos.c
parent1d708cef72dc230f58a9ed046a6a27355d98de1c (diff)
downloadwireshark-cdeae7e72b749cdd68207d6e97dafb67783e2de4.tar.gz
Add a "heuristic dissectors" tab to the Enable Protocols dialog.
This allows for a global place to enable/disable all heuristic dissectors. This removes the need for individual dissector preferences, but those will be removed at a later date. The more important part is the epan code to save/restore the enabled state of the heuristic dissector. The GTK dialog was more for quickly testing the feature (there was already some GTK code in place that started the heuristic dialog tab) Change-Id: Ie10687505c27a4456c49d5c4c69a5fc5f6394275 Ping-Bug:11152 Reviewed-on: https://code.wireshark.org/review/9508 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/disabled_protos.c')
-rw-r--r--epan/disabled_protos.c388
1 files changed, 386 insertions, 2 deletions
diff --git a/epan/disabled_protos.c b/epan/disabled_protos.c
index 1afe9c96db..4d30e13510 100644
--- a/epan/disabled_protos.c
+++ b/epan/disabled_protos.c
@@ -34,18 +34,39 @@
#include <wsutil/filesystem.h>
#include <epan/proto.h>
+#include <epan/packet.h>
#include "disabled_protos.h"
#include <wsutil/file_util.h>
-#define GLOBAL_PROTOCOLS_FILE_NAME "disabled_protos"
#define PROTOCOLS_FILE_NAME "disabled_protos"
+#define HEURISTICS_FILE_NAME "heuristic_protos"
+
+/*
+ * Item in a list of disabled protocols.
+ */
+typedef struct {
+ char *name; /* protocol name */
+} protocol_def;
+
+/*
+ * Item in a list of heuristic dissectors and their enabled state.
+ */
+typedef struct {
+ char *name; /* heuristic short name */
+ gboolean enabled; /* heuristc enabled */
+} heur_protocol_def;
/*
* List of disabled protocols
*/
static GList *global_disabled_protos = NULL;
static GList *disabled_protos = NULL;
+/*
+ * List of disabled heuristics
+ */
+static GList *global_disabled_heuristics = NULL;
+static GList *disabled_heuristics = NULL;
#define INIT_BUF_SIZE 128
@@ -68,6 +89,25 @@ discard_existing_list (GList **flp)
}
}
+static void
+heur_discard_existing_list (GList **flp)
+{
+ GList *fl_ent;
+ heur_protocol_def *prot;
+
+ if (*flp != NULL) {
+ fl_ent = g_list_first(*flp);
+ while (fl_ent != NULL) {
+ prot = (heur_protocol_def *) fl_ent->data;
+ g_free(prot->name);
+ g_free(prot);
+ fl_ent = fl_ent->next;
+ }
+ g_list_free(*flp);
+ *flp = NULL;
+ }
+}
+
/*
* Read in a list of disabled protocols.
*
@@ -92,7 +132,7 @@ read_disabled_protos_list(char **gpath_return, int *gopen_errno_return,
FILE *ff;
/* Construct the pathname of the global disabled protocols file. */
- gff_path = get_datafile_path(GLOBAL_PROTOCOLS_FILE_NAME);
+ gff_path = get_datafile_path(PROTOCOLS_FILE_NAME);
/* If we already have a list of protocols, discard it. */
discard_existing_list (&global_disabled_protos);
@@ -258,6 +298,7 @@ read_disabled_protos_list_file(const char *ff_path, FILE *ff,
return 0;
error:
+ g_free(prot_name);
return errno;
}
@@ -408,6 +449,349 @@ save_disabled_protos_list(char **pref_path_return, int *errno_return)
g_free(ff_path);
}
+void
+set_disabled_heur_dissector_list(void)
+{
+ GList *fl_ent;
+ heur_protocol_def *heur;
+ heur_dtbl_entry_t* h;
+
+ /*
+ * assume all heuristics are enabled by default
+ */
+ if (disabled_heuristics == NULL)
+ goto skip;
+
+ fl_ent = g_list_first(disabled_heuristics);
+
+ while (fl_ent != NULL) {
+ heur = (heur_protocol_def *) fl_ent->data;
+ h = find_heur_dissector_by_unique_short_name(heur->name);
+ if (h != NULL) {
+ h->enabled = heur->enabled;
+ }
+
+ fl_ent = fl_ent->next;
+ }
+
+skip:
+ if (global_disabled_heuristics == NULL)
+ return;
+
+ fl_ent = g_list_first(global_disabled_heuristics);
+
+ while (fl_ent != NULL) {
+ heur = (heur_protocol_def *) fl_ent->data;
+
+ h = find_heur_dissector_by_unique_short_name(heur->name);
+ if (h != NULL) {
+ h->enabled = heur->enabled;
+ }
+
+ fl_ent = fl_ent->next;
+ }
+}
+
+static int
+read_disabled_heur_dissector_list_file(const char *ff_path, FILE *ff,
+ GList **flp)
+{
+ heur_protocol_def *heur;
+ int c;
+ char *heuristic_name;
+ int heuristic_name_len;
+ int name_index;
+ gboolean parse_enabled;
+ gboolean enabled;
+ int line = 1;
+
+
+ /* Allocate the protocol name buffer. */
+ heuristic_name_len = INIT_BUF_SIZE;
+ heuristic_name = (char *)g_malloc(heuristic_name_len + 1);
+
+ for (line = 1; ; line++) {
+ /* Lines in a disabled protocol file contain the "filter name" of
+ a protocol to be disabled. */
+
+ /* Skip over leading white space, if any. */
+ while ((c = getc(ff)) != EOF && g_ascii_isspace(c)) {
+ if (c == '\n') {
+ /* Blank line. */
+ continue;
+ }
+ }
+
+ if (c == EOF) {
+ if (ferror(ff))
+ goto error; /* I/O error */
+ else
+ break; /* Nothing more to read */
+ }
+ ungetc(c, ff); /* Unread the non-white-space character. */
+
+ /* Get the name of the protocol. */
+ name_index = 0;
+ enabled = FALSE;
+ parse_enabled = FALSE;
+ for (;;) {
+ c = getc(ff);
+ if (c == EOF)
+ break; /* End of file, or I/O error */
+ if (g_ascii_isspace(c))
+ break; /* Trailing white space, or end of line. */
+ if (c == ',') {/* Separator for enable/disable */
+ parse_enabled = TRUE;
+ continue;
+ }
+ if (c == '#')
+ break; /* Start of comment, running to end of line. */
+ if (parse_enabled) {
+ enabled = ((c == '1') ? TRUE : FALSE);
+ break;
+ }
+ /* Add this character to the protocol name string. */
+ if (name_index >= heuristic_name_len) {
+ /* protocol name buffer isn't long enough; double its length. */
+ heuristic_name_len *= 2;
+ heuristic_name = (char *)g_realloc(heuristic_name, heuristic_name_len + 1);
+ }
+ heuristic_name[name_index] = c;
+ name_index++;
+ }
+
+ if (g_ascii_isspace(c) && c != '\n') {
+ /* Skip over trailing white space. */
+ while ((c = getc(ff)) != EOF && c != '\n' && g_ascii_isspace(c))
+ ;
+ if (c != EOF && c != '\n' && c != '#') {
+ /* Non-white-space after the protocol name; warn about it,
+ in case we come up with a reason to use it. */
+ g_warning("'%s' line %d has extra stuff after the protocol name.",
+ ff_path, line);
+ }
+ }
+ if (c != EOF && c != '\n') {
+ /* Skip to end of line. */
+ while ((c = getc(ff)) != EOF && c != '\n')
+ ;
+ }
+
+ if (c == EOF) {
+ if (ferror(ff))
+ goto error; /* I/O error */
+ else {
+ /* EOF, not error; no newline seen before EOF */
+ g_warning("'%s' line %d doesn't have a newline.", ff_path,
+ line);
+ }
+ break; /* nothing more to read */
+ }
+
+ /* Null-terminate the protocol name. */
+ if (name_index >= heuristic_name_len) {
+ /* protocol name buffer isn't long enough; double its length. */
+ heuristic_name_len *= 2;
+ heuristic_name = (char *)g_realloc(heuristic_name, heuristic_name_len + 1);
+ }
+ heuristic_name[name_index] = '\0';
+
+ /* Add the new protocol to the list of disabled protocols */
+ heur = (heur_protocol_def *) g_malloc(sizeof(heur_protocol_def));
+ heur->name = g_strdup(heuristic_name);
+ heur->enabled = enabled;
+ *flp = g_list_append(*flp, heur);
+ }
+ g_free(heuristic_name);
+ return 0;
+
+error:
+ g_free(heuristic_name);
+ return errno;
+}
+
+void
+read_disabled_heur_dissector_list(char **gpath_return, int *gopen_errno_return,
+ int *gread_errno_return,
+ char **path_return, int *open_errno_return,
+ int *read_errno_return)
+{
+ int err;
+ char *gff_path, *ff_path;
+ FILE *ff;
+
+ /* Construct the pathname of the global disabled heuristic dissectors file. */
+ gff_path = get_datafile_path(HEURISTICS_FILE_NAME);
+
+ /* If we already have a list of protocols, discard it. */
+ heur_discard_existing_list(&global_disabled_heuristics);
+
+ /* Read the global disabled protocols file, if it exists. */
+ *gpath_return = NULL;
+ if ((ff = ws_fopen(gff_path, "r")) != NULL) {
+ /* We succeeded in opening it; read it. */
+ err = read_disabled_heur_dissector_list_file(gff_path, ff,
+ &global_disabled_heuristics);
+ if (err != 0) {
+ /* We had an error reading the file; return the errno and the
+ pathname, so our caller can report the error. */
+ *gopen_errno_return = 0;
+ *gread_errno_return = err;
+ *gpath_return = gff_path;
+ } else
+ g_free(gff_path);
+ fclose(ff);
+ } else {
+ /* We failed to open it. If we failed for some reason other than
+ "it doesn't exist", return the errno and the pathname, so our
+ caller can report the error. */
+ if (errno != ENOENT) {
+ *gopen_errno_return = errno;
+ *gread_errno_return = 0;
+ *gpath_return = gff_path;
+ } else
+ g_free(gff_path);
+ }
+
+ /* Construct the pathname of the user's disabled protocols file. */
+ ff_path = get_persconffile_path(HEURISTICS_FILE_NAME, TRUE);
+
+ /* If we already have a list of protocols, discard it. */
+ heur_discard_existing_list (&disabled_heuristics);
+
+ /* Read the user's disabled protocols file, if it exists. */
+ *path_return = NULL;
+ if ((ff = ws_fopen(ff_path, "r")) != NULL) {
+ /* We succeeded in opening it; read it. */
+ err = read_disabled_heur_dissector_list_file(ff_path, ff, &disabled_heuristics);
+ if (err != 0) {
+ /* We had an error reading the file; return the errno and the
+ pathname, so our caller can report the error. */
+ *open_errno_return = 0;
+ *read_errno_return = err;
+ *path_return = ff_path;
+ } else
+ g_free(ff_path);
+ fclose(ff);
+ } else {
+ /* We failed to open it. If we failed for some reason other than
+ "it doesn't exist", return the errno and the pathname, so our
+ caller can report the error. */
+ if (errno != ENOENT) {
+ *open_errno_return = errno;
+ *read_errno_return = 0;
+ *path_return = ff_path;
+ } else
+ g_free(ff_path);
+ }
+}
+
+static gint
+heur_compare(gconstpointer a, gconstpointer b)
+{
+ return strcmp(((heur_dtbl_entry_t*)a)->short_name,
+ ((heur_dtbl_entry_t*)b)->short_name);
+}
+
+static void
+write_heur_dissector(gpointer data, gpointer user_data)
+{
+ heur_dtbl_entry_t* dtbl_entry = (heur_dtbl_entry_t*)data;
+ FILE *ff = (FILE*)user_data;
+
+ /* Write out the heuristic short name and its enabled state */
+ fprintf(ff, "%s,%d\n", dtbl_entry->short_name, dtbl_entry->enabled ? 1 : 0);
+}
+
+static void
+sort_dissector_table_entries(const char *table_name _U_,
+ heur_dtbl_entry_t *dtbl_entry, gpointer user_data)
+{
+ GSList **list = (GSList**)user_data;
+ *list = g_slist_insert_sorted(*list, dtbl_entry, heur_compare);
+}
+
+static void
+sort_heur_dissector_tables(const char *table_name, heur_dissector_list_t *list, gpointer w)
+{
+ if (list) {
+ heur_dissector_table_foreach(table_name, sort_dissector_table_entries, w);
+ }
+}
+
+WS_DLL_PUBLIC void
+save_disabled_heur_dissector_list(char **pref_path_return, int *errno_return)
+{
+ gchar *ff_path, *ff_path_new;
+ GSList *sorted_heur_list = NULL;
+ FILE *ff;
+
+ *pref_path_return = NULL; /* assume no error */
+
+ ff_path = get_persconffile_path(HEURISTICS_FILE_NAME, TRUE);
+
+ /* Write to "XXX.new", and rename if that succeeds.
+ That means we don't trash the file if we fail to write it out
+ completely. */
+ ff_path_new = g_strdup_printf("%s.new", ff_path);
+
+ if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ g_free(ff_path_new);
+ return;
+ }
+
+ /* Iterate over all the heuristic dissectors to sort them in alphabetical order by short name */
+ dissector_all_heur_tables_foreach_table(sort_heur_dissector_tables, &sorted_heur_list, NULL);
+
+ /* Write the list */
+ g_slist_foreach(sorted_heur_list, write_heur_dissector, ff);
+ g_slist_free(sorted_heur_list);
+
+ if (fclose(ff) == EOF) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ ws_unlink(ff_path_new);
+ g_free(ff_path_new);
+ return;
+ }
+
+#ifdef _WIN32
+ /* ANSI C doesn't say whether "rename()" removes the target if it
+ exists; the Win32 call to rename files doesn't do so, which I
+ infer is the reason why the MSVC++ "rename()" doesn't do so.
+ We must therefore remove the target file first, on Windows.
+
+ XXX - ws_rename() should be ws_stdio_rename() on Windows,
+ and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
+ so it should remove the target if it exists, so this stuff
+ shouldn't be necessary. Perhaps it dates back to when we were
+ calling rename(), with that being a wrapper around Microsoft's
+ _rename(), which didn't remove the target. */
+ if (ws_remove(ff_path) < 0 && errno != ENOENT) {
+ /* It failed for some reason other than "it's not there"; if
+ it's not there, we don't need to remove it, so we just
+ drive on. */
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ ws_unlink(ff_path_new);
+ g_free(ff_path_new);
+ return;
+ }
+#endif
+
+ if (ws_rename(ff_path_new, ff_path) < 0) {
+ *pref_path_return = ff_path;
+ *errno_return = errno;
+ ws_unlink(ff_path_new);
+ g_free(ff_path_new);
+ return;
+ }
+ g_free(ff_path_new);
+ g_free(ff_path);
+}
+
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*