2 * Code for reading and writing the disabled protocols file.
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include <wsutil/filesystem.h>
36 #include <epan/proto.h>
37 #include <epan/packet.h>
39 #include "disabled_protos.h"
40 #include <wsutil/file_util.h>
42 #define PROTOCOLS_FILE_NAME "disabled_protos"
43 #define HEURISTICS_FILE_NAME "heuristic_protos"
46 * Item in a list of disabled protocols.
49 char *name; /* protocol name */
53 * Item in a list of heuristic dissectors and their enabled state.
56 char *name; /* heuristic short name */
57 gboolean enabled; /* heuristc enabled */
61 * List of disabled protocols
63 static GList *global_disabled_protos = NULL;
64 static GList *disabled_protos = NULL;
66 * List of disabled heuristics
68 static GList *global_disabled_heuristics = NULL;
69 static GList *disabled_heuristics = NULL;
71 #define INIT_BUF_SIZE 128
74 discard_existing_list (GList **flp)
80 fl_ent = g_list_first(*flp);
81 while (fl_ent != NULL) {
82 prot = (protocol_def *) fl_ent->data;
85 fl_ent = fl_ent->next;
93 heur_discard_existing_list (GList **flp)
96 heur_protocol_def *prot;
99 fl_ent = g_list_first(*flp);
100 while (fl_ent != NULL) {
101 prot = (heur_protocol_def *) fl_ent->data;
104 fl_ent = fl_ent->next;
112 * Read in a list of disabled protocols.
114 * On success, "*pref_path_return" is set to NULL.
115 * On error, "*pref_path_return" is set to point to the pathname of
116 * the file we tried to read - it should be freed by our caller -
117 * and "*open_errno_return" is set to the error if an open failed
118 * or "*read_errno_return" is set to the error if a read failed.
121 static int read_disabled_protos_list_file(const char *ff_path, FILE *ff,
125 read_disabled_protos_list(char **gpath_return, int *gopen_errno_return,
126 int *gread_errno_return,
127 char **path_return, int *open_errno_return,
128 int *read_errno_return)
131 char *gff_path, *ff_path;
134 /* Construct the pathname of the global disabled protocols file. */
135 gff_path = get_datafile_path(PROTOCOLS_FILE_NAME);
137 /* If we already have a list of protocols, discard it. */
138 discard_existing_list (&global_disabled_protos);
140 /* Read the global disabled protocols file, if it exists. */
141 *gpath_return = NULL;
142 if ((ff = ws_fopen(gff_path, "r")) != NULL) {
143 /* We succeeded in opening it; read it. */
144 err = read_disabled_protos_list_file(gff_path, ff,
145 &global_disabled_protos);
147 /* We had an error reading the file; return the errno and the
148 pathname, so our caller can report the error. */
149 *gopen_errno_return = 0;
150 *gread_errno_return = err;
151 *gpath_return = gff_path;
156 /* We failed to open it. If we failed for some reason other than
157 "it doesn't exist", return the errno and the pathname, so our
158 caller can report the error. */
159 if (errno != ENOENT) {
160 *gopen_errno_return = errno;
161 *gread_errno_return = 0;
162 *gpath_return = gff_path;
167 /* Construct the pathname of the user's disabled protocols file. */
168 ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE);
170 /* If we already have a list of protocols, discard it. */
171 discard_existing_list (&disabled_protos);
173 /* Read the user's disabled protocols file, if it exists. */
175 if ((ff = ws_fopen(ff_path, "r")) != NULL) {
176 /* We succeeded in opening it; read it. */
177 err = read_disabled_protos_list_file(ff_path, ff, &disabled_protos);
179 /* We had an error reading the file; return the errno and the
180 pathname, so our caller can report the error. */
181 *open_errno_return = 0;
182 *read_errno_return = err;
183 *path_return = ff_path;
188 /* We failed to open it. If we failed for some reason other than
189 "it doesn't exist", return the errno and the pathname, so our
190 caller can report the error. */
191 if (errno != ENOENT) {
192 *open_errno_return = errno;
193 *read_errno_return = 0;
194 *path_return = ff_path;
201 read_disabled_protos_list_file(const char *ff_path, FILE *ff,
212 /* Allocate the protocol name buffer. */
213 prot_name_len = INIT_BUF_SIZE;
214 prot_name = (char *)g_malloc(prot_name_len + 1);
216 for (line = 1; ; line++) {
217 /* Lines in a disabled protocol file contain the "filter name" of
218 a protocol to be disabled. */
220 /* Skip over leading white space, if any. */
221 while ((c = getc(ff)) != EOF && g_ascii_isspace(c)) {
230 goto error; /* I/O error */
232 break; /* Nothing more to read */
234 ungetc(c, ff); /* Unread the non-white-space character. */
236 /* Get the name of the protocol. */
241 break; /* End of file, or I/O error */
242 if (g_ascii_isspace(c))
243 break; /* Trailing white space, or end of line. */
245 break; /* Start of comment, running to end of line. */
246 /* Add this character to the protocol name string. */
247 if (prot_name_index >= prot_name_len) {
248 /* protocol name buffer isn't long enough; double its length. */
250 prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
252 prot_name[prot_name_index] = c;
256 if (g_ascii_isspace(c) && c != '\n') {
257 /* Skip over trailing white space. */
258 while ((c = getc(ff)) != EOF && c != '\n' && g_ascii_isspace(c))
260 if (c != EOF && c != '\n' && c != '#') {
261 /* Non-white-space after the protocol name; warn about it,
262 in case we come up with a reason to use it. */
263 g_warning("'%s' line %d has extra stuff after the protocol name.",
267 if (c != EOF && c != '\n') {
268 /* Skip to end of line. */
269 while ((c = getc(ff)) != EOF && c != '\n')
275 goto error; /* I/O error */
277 /* EOF, not error; no newline seen before EOF */
278 g_warning("'%s' line %d doesn't have a newline.", ff_path,
281 break; /* nothing more to read */
284 /* Null-terminate the protocol name. */
285 if (prot_name_index >= prot_name_len) {
286 /* protocol name buffer isn't long enough; double its length. */
288 prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
290 prot_name[prot_name_index] = '\0';
292 /* Add the new protocol to the list of disabled protocols */
293 prot = (protocol_def *) g_malloc(sizeof(protocol_def));
294 prot->name = g_strdup(prot_name);
295 *flp = g_list_append(*flp, prot);
306 * Disable protocols as per the stored configuration
309 set_disabled_protos_list(void)
316 * assume all protocols are enabled by default
318 if (disabled_protos == NULL)
321 fl_ent = g_list_first(disabled_protos);
323 while (fl_ent != NULL) {
324 prot = (protocol_def *) fl_ent->data;
325 i = proto_get_id_by_filter_name(prot->name);
327 /* XXX - complain here? */
329 if (proto_can_toggle_protocol(i))
330 proto_set_decoding(i, FALSE);
333 fl_ent = fl_ent->next;
337 if (global_disabled_protos == NULL)
340 fl_ent = g_list_first(global_disabled_protos);
342 while (fl_ent != NULL) {
343 prot = (protocol_def *) fl_ent->data;
344 i = proto_get_id_by_filter_name(prot->name);
346 /* XXX - complain here? */
348 if (proto_can_toggle_protocol(i)) {
349 proto_set_decoding(i, FALSE);
350 proto_set_cant_toggle(i);
354 fl_ent = fl_ent->next;
359 * Disable a particular protocol by name
363 proto_disable_proto_by_name(const char *name)
365 protocol_t *protocol;
368 proto_id = proto_get_id_by_filter_name(name);
369 if (proto_id >= 0 ) {
370 protocol = find_protocol_by_id(proto_id);
371 if (proto_is_protocol_enabled(protocol) == TRUE) {
372 if (proto_can_toggle_protocol(proto_id) == TRUE) {
373 proto_set_decoding(proto_id, FALSE);
380 * Write out a list of disabled protocols.
382 * On success, "*pref_path_return" is set to NULL.
383 * On error, "*pref_path_return" is set to point to the pathname of
384 * the file we tried to read - it should be freed by our caller -
385 * and "*errno_return" is set to the error.
388 save_disabled_protos_list(char **pref_path_return, int *errno_return)
390 gchar *ff_path, *ff_path_new;
393 protocol_t *protocol;
396 *pref_path_return = NULL; /* assume no error */
398 ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE);
400 /* Write to "XXX.new", and rename if that succeeds.
401 That means we don't trash the file if we fail to write it out
403 ff_path_new = g_strdup_printf("%s.new", ff_path);
405 if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
406 *pref_path_return = ff_path;
407 *errno_return = errno;
412 /* Iterate over all the protocols */
414 for (i = proto_get_first_protocol(&cookie); i != -1;
415 i = proto_get_next_protocol(&cookie)) {
417 if (!proto_can_toggle_protocol(i)) {
421 protocol = find_protocol_by_id(i);
422 if (proto_is_protocol_enabled(protocol)) {
426 /* Write out the protocol name. */
427 fprintf(ff, "%s\n", proto_get_protocol_filter_name(i));
430 if (fclose(ff) == EOF) {
431 *pref_path_return = ff_path;
432 *errno_return = errno;
433 ws_unlink(ff_path_new);
439 /* ANSI C doesn't say whether "rename()" removes the target if it
440 exists; the Win32 call to rename files doesn't do so, which I
441 infer is the reason why the MSVC++ "rename()" doesn't do so.
442 We must therefore remove the target file first, on Windows.
444 XXX - ws_rename() should be ws_stdio_rename() on Windows,
445 and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
446 so it should remove the target if it exists, so this stuff
447 shouldn't be necessary. Perhaps it dates back to when we were
448 calling rename(), with that being a wrapper around Microsoft's
449 _rename(), which didn't remove the target. */
450 if (ws_remove(ff_path) < 0 && errno != ENOENT) {
451 /* It failed for some reason other than "it's not there"; if
452 it's not there, we don't need to remove it, so we just
454 *pref_path_return = ff_path;
455 *errno_return = errno;
456 ws_unlink(ff_path_new);
462 if (ws_rename(ff_path_new, ff_path) < 0) {
463 *pref_path_return = ff_path;
464 *errno_return = errno;
465 ws_unlink(ff_path_new);
474 set_disabled_heur_dissector_list(void)
477 heur_protocol_def *heur;
478 heur_dtbl_entry_t* h;
480 if (disabled_heuristics == NULL)
483 fl_ent = g_list_first(disabled_heuristics);
485 while (fl_ent != NULL) {
486 heur = (heur_protocol_def *) fl_ent->data;
487 h = find_heur_dissector_by_unique_short_name(heur->name);
489 h->enabled = heur->enabled;
492 fl_ent = fl_ent->next;
496 if (global_disabled_heuristics == NULL)
499 fl_ent = g_list_first(global_disabled_heuristics);
501 while (fl_ent != NULL) {
502 heur = (heur_protocol_def *) fl_ent->data;
504 h = find_heur_dissector_by_unique_short_name(heur->name);
506 h->enabled = heur->enabled;
509 fl_ent = fl_ent->next;
514 read_disabled_heur_dissector_list_file(const char *ff_path, FILE *ff,
517 heur_protocol_def *heur;
519 char *heuristic_name;
520 int heuristic_name_len;
522 gboolean parse_enabled;
527 /* Allocate the protocol name buffer. */
528 heuristic_name_len = INIT_BUF_SIZE;
529 heuristic_name = (char *)g_malloc(heuristic_name_len + 1);
531 for (line = 1; ; line++) {
532 /* Lines in a disabled protocol file contain the "filter name" of
533 a protocol to be disabled. */
535 /* Skip over leading white space, if any. */
536 while ((c = getc(ff)) != EOF && g_ascii_isspace(c)) {
545 goto error; /* I/O error */
547 break; /* Nothing more to read */
549 ungetc(c, ff); /* Unread the non-white-space character. */
551 /* Get the name of the protocol. */
554 parse_enabled = FALSE;
558 break; /* End of file, or I/O error */
559 if (g_ascii_isspace(c))
560 break; /* Trailing white space, or end of line. */
561 if (c == ',') {/* Separator for enable/disable */
562 parse_enabled = TRUE;
566 break; /* Start of comment, running to end of line. */
568 enabled = ((c == '1') ? TRUE : FALSE);
571 /* Add this character to the protocol name string. */
572 if (name_index >= heuristic_name_len) {
573 /* protocol name buffer isn't long enough; double its length. */
574 heuristic_name_len *= 2;
575 heuristic_name = (char *)g_realloc(heuristic_name, heuristic_name_len + 1);
577 heuristic_name[name_index] = c;
581 if (g_ascii_isspace(c) && c != '\n') {
582 /* Skip over trailing white space. */
583 while ((c = getc(ff)) != EOF && c != '\n' && g_ascii_isspace(c))
585 if (c != EOF && c != '\n' && c != '#') {
586 /* Non-white-space after the protocol name; warn about it,
587 in case we come up with a reason to use it. */
588 g_warning("'%s' line %d has extra stuff after the protocol name.",
592 if (c != EOF && c != '\n') {
593 /* Skip to end of line. */
594 while ((c = getc(ff)) != EOF && c != '\n')
600 goto error; /* I/O error */
602 /* EOF, not error; no newline seen before EOF */
603 g_warning("'%s' line %d doesn't have a newline.", ff_path,
606 break; /* nothing more to read */
609 /* Null-terminate the protocol name. */
610 if (name_index >= heuristic_name_len) {
611 /* protocol name buffer isn't long enough; double its length. */
612 heuristic_name_len *= 2;
613 heuristic_name = (char *)g_realloc(heuristic_name, heuristic_name_len + 1);
615 heuristic_name[name_index] = '\0';
617 /* Add the new protocol to the list of disabled protocols */
618 heur = (heur_protocol_def *) g_malloc(sizeof(heur_protocol_def));
619 heur->name = g_strdup(heuristic_name);
620 heur->enabled = enabled;
621 *flp = g_list_append(*flp, heur);
623 g_free(heuristic_name);
627 g_free(heuristic_name);
632 read_disabled_heur_dissector_list(char **gpath_return, int *gopen_errno_return,
633 int *gread_errno_return,
634 char **path_return, int *open_errno_return,
635 int *read_errno_return)
638 char *gff_path, *ff_path;
641 /* Construct the pathname of the global disabled heuristic dissectors file. */
642 gff_path = get_datafile_path(HEURISTICS_FILE_NAME);
644 /* If we already have a list of protocols, discard it. */
645 heur_discard_existing_list(&global_disabled_heuristics);
647 /* Read the global disabled protocols file, if it exists. */
648 *gpath_return = NULL;
649 if ((ff = ws_fopen(gff_path, "r")) != NULL) {
650 /* We succeeded in opening it; read it. */
651 err = read_disabled_heur_dissector_list_file(gff_path, ff,
652 &global_disabled_heuristics);
654 /* We had an error reading the file; return the errno and the
655 pathname, so our caller can report the error. */
656 *gopen_errno_return = 0;
657 *gread_errno_return = err;
658 *gpath_return = gff_path;
663 /* We failed to open it. If we failed for some reason other than
664 "it doesn't exist", return the errno and the pathname, so our
665 caller can report the error. */
666 if (errno != ENOENT) {
667 *gopen_errno_return = errno;
668 *gread_errno_return = 0;
669 *gpath_return = gff_path;
674 /* Construct the pathname of the user's disabled protocols file. */
675 ff_path = get_persconffile_path(HEURISTICS_FILE_NAME, TRUE);
677 /* If we already have a list of protocols, discard it. */
678 heur_discard_existing_list (&disabled_heuristics);
680 /* Read the user's disabled protocols file, if it exists. */
682 if ((ff = ws_fopen(ff_path, "r")) != NULL) {
683 /* We succeeded in opening it; read it. */
684 err = read_disabled_heur_dissector_list_file(ff_path, ff, &disabled_heuristics);
686 /* We had an error reading the file; return the errno and the
687 pathname, so our caller can report the error. */
688 *open_errno_return = 0;
689 *read_errno_return = err;
690 *path_return = ff_path;
695 /* We failed to open it. If we failed for some reason other than
696 "it doesn't exist", return the errno and the pathname, so our
697 caller can report the error. */
698 if (errno != ENOENT) {
699 *open_errno_return = errno;
700 *read_errno_return = 0;
701 *path_return = ff_path;
708 heur_compare(gconstpointer a, gconstpointer b)
710 return strcmp(((heur_dtbl_entry_t*)a)->short_name,
711 ((heur_dtbl_entry_t*)b)->short_name);
715 write_heur_dissector(gpointer data, gpointer user_data)
717 heur_dtbl_entry_t* dtbl_entry = (heur_dtbl_entry_t*)data;
718 FILE *ff = (FILE*)user_data;
720 /* Write out the heuristic short name and its enabled state */
721 fprintf(ff, "%s,%d\n", dtbl_entry->short_name, dtbl_entry->enabled ? 1 : 0);
725 sort_dissector_table_entries(const char *table_name _U_,
726 heur_dtbl_entry_t *dtbl_entry, gpointer user_data)
728 GSList **list = (GSList**)user_data;
729 *list = g_slist_insert_sorted(*list, dtbl_entry, heur_compare);
733 sort_heur_dissector_tables(const char *table_name, struct heur_dissector_list *list, gpointer w)
736 heur_dissector_table_foreach(table_name, sort_dissector_table_entries, w);
741 save_disabled_heur_dissector_list(char **pref_path_return, int *errno_return)
743 gchar *ff_path, *ff_path_new;
744 GSList *sorted_heur_list = NULL;
747 *pref_path_return = NULL; /* assume no error */
749 ff_path = get_persconffile_path(HEURISTICS_FILE_NAME, TRUE);
751 /* Write to "XXX.new", and rename if that succeeds.
752 That means we don't trash the file if we fail to write it out
754 ff_path_new = g_strdup_printf("%s.new", ff_path);
756 if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
757 *pref_path_return = ff_path;
758 *errno_return = errno;
763 /* Iterate over all the heuristic dissectors to sort them in alphabetical order by short name */
764 dissector_all_heur_tables_foreach_table(sort_heur_dissector_tables, &sorted_heur_list, NULL);
767 g_slist_foreach(sorted_heur_list, write_heur_dissector, ff);
768 g_slist_free(sorted_heur_list);
770 if (fclose(ff) == EOF) {
771 *pref_path_return = ff_path;
772 *errno_return = errno;
773 ws_unlink(ff_path_new);
779 /* ANSI C doesn't say whether "rename()" removes the target if it
780 exists; the Win32 call to rename files doesn't do so, which I
781 infer is the reason why the MSVC++ "rename()" doesn't do so.
782 We must therefore remove the target file first, on Windows.
784 XXX - ws_rename() should be ws_stdio_rename() on Windows,
785 and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
786 so it should remove the target if it exists, so this stuff
787 shouldn't be necessary. Perhaps it dates back to when we were
788 calling rename(), with that being a wrapper around Microsoft's
789 _rename(), which didn't remove the target. */
790 if (ws_remove(ff_path) < 0 && errno != ENOENT) {
791 /* It failed for some reason other than "it's not there"; if
792 it's not there, we don't need to remove it, so we just
794 *pref_path_return = ff_path;
795 *errno_return = errno;
796 ws_unlink(ff_path_new);
802 if (ws_rename(ff_path_new, ff_path) < 0) {
803 *pref_path_return = ff_path;
804 *errno_return = errno;
805 ws_unlink(ff_path_new);
814 proto_enable_heuristic_by_name(const char *name, gboolean enable)
816 heur_dtbl_entry_t* heur = find_heur_dissector_by_unique_short_name(name);
818 heur->enabled = enable;
823 * Editor modelines - http://www.wireshark.org/tools/modelines.html
828 * indent-tabs-mode: nil
831 * ex: set shiftwidth=2 tabstop=8 expandtab:
832 * :indentSize=2:tabSize=8:noTabs=true: