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>
This commit is contained in:
Michael Mann 2015-07-05 17:31:14 -04:00
parent 1d708cef72
commit cdeae7e72b
15 changed files with 1035 additions and 539 deletions

View File

@ -527,6 +527,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
find_dissector@Base 1.9.1
find_dissector_table@Base 1.9.1
find_heur_dissector_by_short_name@Base 1.99.8
find_heur_dissector_by_unique_short_name@Base 1.99.8
find_heur_dissector_list@Base 1.99.2
find_or_create_conversation@Base 1.9.1
find_protocol_by_id@Base 1.9.1

View File

@ -508,12 +508,13 @@ static void preinit_epan(char* argv0, int (*main)(int, char **)) {
/* disabled protocols as per configuration file */
set_disabled_protos_list();
set_disabled_heur_dissector_list();
setlocale(LC_ALL, "");
DISP_DBG((1,"---5"));
read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno, &dp_path, &dp_open_errno, &dp_read_errno);
read_disabled_heur_dissector_list(&gdp_path, &gdp_open_errno, &gdp_read_errno, &dp_path, &dp_open_errno, &dp_read_errno);
DISP_DBG((1,"---6"));

View File

@ -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
*

View File

@ -28,13 +28,6 @@
extern "C" {
#endif /* __cplusplus */
/*
* Item in a list of disabled protocols.
*/
typedef struct {
char *name; /* protocol name */
} protocol_def;
/*
* Read in a list of disabled protocols.
*
@ -68,6 +61,40 @@ set_disabled_protos_list(void);
WS_DLL_PUBLIC void
save_disabled_protos_list(char **pref_path_return, int *errno_return);
/*
* Read in a list of disabled protocols.
*
* On success, "*pref_path_return" is set to NULL.
* On error, "*pref_path_return" is set to point to the pathname of
* the file we tried to read - it should be freed by our caller -
* and "*open_errno_return" is set to the error if we couldn't open the file
* or "*read_errno_return" is set to the error if we got an error reading
* the file.
*/
WS_DLL_PUBLIC 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);
/*
* Disable protocols as per the stored configuration
*/
WS_DLL_PUBLIC void
set_disabled_heur_dissector_list(void);
/*
* Write out a list of disabled heuristic dissectors.
*
* On success, "*pref_path_return" is set to NULL.
* On error, "*pref_path_return" is set to point to the pathname of
* the file we tried to read - it should be freed by our caller -
* and "*errno_return" is set to the error.
*/
WS_DLL_PUBLIC void
save_disabled_heur_dissector_list(char **pref_path_return, int *errno_return);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -1981,6 +1981,11 @@ find_heur_dissector_by_short_name(heur_dissector_list_t heur_list, const char *s
return found_entry ? (heur_dtbl_entry_t *)(found_entry->data) : NULL;
}
heur_dtbl_entry_t* find_heur_dissector_by_unique_short_name(const char *short_name)
{
return (heur_dtbl_entry_t*)g_hash_table_lookup(heuristic_short_names, (gpointer)short_name);
}
void
heur_dissector_add(const char *name, heur_dissector_t dissector, const char *display_name, const char *short_name, const int proto)
{
@ -2041,7 +2046,7 @@ heur_dissector_add(const char *name, heur_dissector_t dissector, const char *dis
hdtbl_entry->enabled = TRUE;
/* do the table insertion */
g_hash_table_insert(heuristic_short_names, (gpointer)short_name, hdtbl_entry); /* Just a copy */
g_hash_table_insert(heuristic_short_names, (gpointer)short_name, hdtbl_entry);
sub_dissectors->dissectors = g_slist_prepend(sub_dissectors->dissectors,
(gpointer)hdtbl_entry);

View File

@ -448,6 +448,13 @@ WS_DLL_PUBLIC heur_dissector_list_t find_heur_dissector_list(const char *name);
WS_DLL_PUBLIC heur_dtbl_entry_t* find_heur_dissector_by_short_name(heur_dissector_list_t heur_list,
const char *short_name);
/** Find a heuristic dissector by the unique short protocol name provided during registration.
*
* @param short_name short name of the protocol to look at
* @return pointer to the heuristic dissector entry, NULL if not such dissector exists
*/
WS_DLL_PUBLIC heur_dtbl_entry_t* find_heur_dissector_by_unique_short_name(const char *short_name);
/** Add a sub-dissector to a heuristic dissector list.
* Call this in the proto_handoff function of the sub-dissector.
*

View File

@ -559,6 +559,8 @@ DIAG_ON(cast-qual)
/* Read the disabled protocols file. */
read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
&dp_path, &dp_open_errno, &dp_read_errno);
read_disabled_heur_dissector_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
&dp_path, &dp_open_errno, &dp_read_errno);
if (gdp_path != NULL) {
if (gdp_open_errno != 0) {
cmdarg_err("Could not open global disabled protocols file\n\"%s\": %s.",
@ -797,6 +799,7 @@ DIAG_ON(cast-qual)
/* disabled protocols as per configuration file */
if (gdp_path == NULL && dp_path == NULL) {
set_disabled_protos_list();
set_disabled_heur_dissector_list();
}
/* Build the column format array */

View File

@ -1070,6 +1070,8 @@ DIAG_ON(cast-qual)
/* Read the disabled protocols file. */
read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
&dp_path, &dp_open_errno, &dp_read_errno);
read_disabled_heur_dissector_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
&dp_path, &dp_open_errno, &dp_read_errno);
if (gdp_path != NULL) {
if (gdp_open_errno != 0) {
cmdarg_err("Could not open global disabled protocols file\n\"%s\": %s.",
@ -1428,6 +1430,7 @@ DIAG_ON(cast-qual)
/* disabled protocols as per configuration file */
if (gdp_path == NULL && dp_path == NULL) {
set_disabled_protos_list();
set_disabled_heur_dissector_list();
}
/* Build the column format array */

View File

@ -1308,6 +1308,8 @@ DIAG_ON(cast-qual)
/* Read the disabled protocols file. */
read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
&dp_path, &dp_open_errno, &dp_read_errno);
read_disabled_heur_dissector_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
&dp_path, &dp_open_errno, &dp_read_errno);
if (gdp_path != NULL) {
if (gdp_open_errno != 0) {
cmdarg_err("Could not open global disabled protocols file\n\"%s\": %s.",
@ -2027,6 +2029,7 @@ DIAG_ON(cast-qual)
/* disabled protocols as per configuration file */
if (gdp_path == NULL && dp_path == NULL) {
set_disabled_protos_list();
set_disabled_heur_dissector_list();
}
/* Build the column format array */

View File

@ -2054,6 +2054,8 @@ read_configuration_files(char **gdp_path, char **dp_path)
/* Read the disabled protocols file. */
read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
dp_path, &dp_open_errno, &dp_read_errno);
read_disabled_heur_dissector_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
dp_path, &dp_open_errno, &dp_read_errno);
if (*gdp_path != NULL) {
if (gdp_open_errno != 0) {
simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
@ -3002,6 +3004,7 @@ DIAG_ON(cast-qual)
/* disabled protocols as per configuration file */
if (gdp_path == NULL && dp_path == NULL) {
set_disabled_protos_list();
set_disabled_heur_dissector_list();
}
build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
@ -3844,6 +3847,7 @@ void change_configuration_profile (const gchar *profile_name)
proto_enable_all();
if (gdp_path == NULL && dp_path == NULL) {
set_disabled_protos_list();
set_disabled_heur_dissector_list();
}
/* Reload color filters */

File diff suppressed because it is too large Load Diff

View File

@ -250,6 +250,9 @@ topic_action_url(topic_action_e action)
case(HELP_ENABLED_PROTOCOLS_DIALOG):
url = user_guide_url("ChCustProtocolDissectionSection.html");
break;
case(HELP_ENABLED_HEURISTICS_DIALOG):
url = user_guide_url("ChCustProtocolDissectionSection.html");
break;
case(HELP_DECODE_AS_DIALOG):
url = user_guide_url("ChCustProtocolDissectionSection.html");
break;

View File

@ -80,6 +80,7 @@ typedef enum {
HELP_CAPTURE_INTERFACES_DIALOG,
HELP_CAPTURE_MANAGE_INTERFACES_DIALOG,
HELP_ENABLED_PROTOCOLS_DIALOG,
HELP_ENABLED_HEURISTICS_DIALOG,
HELP_DECODE_AS_DIALOG,
HELP_DECODE_AS_SHOW_DIALOG,
HELP_FOLLOW_STREAM_DIALOG,

View File

@ -372,6 +372,7 @@ void WiresharkApplication::setConfigurationProfile(const gchar *profile_name)
proto_enable_all();
if (gdp_path == NULL && dp_path == NULL) {
set_disabled_protos_list();
set_disabled_heur_dissector_list();
}
/* Reload color filters */
@ -768,6 +769,8 @@ _e_prefs *WiresharkApplication::readConfigurationFiles(char **gdp_path, char **d
/* Read the disabled protocols file. */
read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
dp_path, &dp_open_errno, &dp_read_errno);
read_disabled_heur_dissector_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
dp_path, &dp_open_errno, &dp_read_errno);
if (*gdp_path != NULL) {
if (gdp_open_errno != 0) {
simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,

View File

@ -1291,6 +1291,7 @@ DIAG_ON(cast-qual)
/* disabled protocols as per configuration file */
if (gdp_path == NULL && dp_path == NULL) {
set_disabled_protos_list();
set_disabled_heur_dissector_list();
}
build_column_format_array(&CaptureFile::globalCapFile()->cinfo, prefs_p->num_cols, TRUE);