drsuapi_SupportedExtensionsExt
[wireshark-sm.git] / epan / disabled_protos.c
blobac79aac8cefb06a14712b0e0db7273587e7ed699
1 /* disabled_protos.c
2 * Declarations of routines for reading and writing protocols file that determine
3 * enabling and disabling of protocols.
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
13 #define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
15 #include <stdio.h>
16 #include <string.h>
17 #include <errno.h>
19 #include <glib.h>
21 #include <wsutil/filesystem.h>
22 #include <epan/proto.h>
23 #include <epan/packet.h>
25 #include "disabled_protos.h"
26 #include <wsutil/file_util.h>
27 #include <wsutil/report_message.h>
28 #include <wsutil/wslog.h>
30 #define ENABLED_PROTOCOLS_FILE_NAME "enabled_protos"
31 #define DISABLED_PROTOCOLS_FILE_NAME "disabled_protos"
32 #define HEURISTICS_FILE_NAME "heuristic_protos"
35 * Item in a list of disabled protocols.
37 typedef struct {
38 char *name; /* protocol name */
39 } protocol_def;
42 * Item in a list of heuristic dissectors and their enabled state.
44 typedef struct {
45 char *name; /* heuristic short name */
46 bool enabled; /* heuristic enabled */
47 } heur_protocol_def;
50 * List of disabled protocols
52 static GList *global_disabled_protos;
53 static GList *disabled_protos;
55 * List of enabled protocols (that are disabled by default)
57 static GList *global_enabled_protos;
58 static GList *enabled_protos;
60 * List of disabled heuristics
62 static GList *global_disabled_heuristics;
63 static GList *disabled_heuristics;
65 static bool unsaved_changes;
67 #define INIT_BUF_SIZE 128
69 bool
70 enabled_protos_unsaved_changes(void)
72 return unsaved_changes;
75 static void
76 discard_existing_list (GList **flp)
78 GList *fl_ent;
79 protocol_def *prot;
81 if (*flp != NULL) {
82 fl_ent = g_list_first(*flp);
83 while (fl_ent != NULL) {
84 prot = (protocol_def *) fl_ent->data;
85 g_free(prot->name);
86 g_free(prot);
87 fl_ent = fl_ent->next;
89 g_list_free(*flp);
90 *flp = NULL;
94 static void
95 heur_discard_existing_list (GList **flp)
97 GList *fl_ent;
98 heur_protocol_def *prot;
100 if (*flp != NULL) {
101 fl_ent = g_list_first(*flp);
102 while (fl_ent != NULL) {
103 prot = (heur_protocol_def *) fl_ent->data;
104 g_free(prot->name);
105 g_free(prot);
106 fl_ent = fl_ent->next;
108 g_list_free(*flp);
109 *flp = NULL;
114 * Enable/Disable protocols as per the stored configuration
116 static void
117 set_protos_list(GList *protos_list, GList *global_protos_list, bool enable)
119 int i;
120 GList *fl_ent;
121 protocol_def *prot;
124 * Assume no protocols disabled by default wants to be enabled
126 if (protos_list == NULL)
127 goto skip;
129 fl_ent = g_list_first(protos_list);
131 while (fl_ent != NULL) {
132 prot = (protocol_def *) fl_ent->data;
133 i = proto_get_id_by_filter_name(prot->name);
134 if (i == -1) {
135 /* XXX - complain here? */
136 } else {
137 if (proto_can_toggle_protocol(i))
138 proto_set_decoding(i, enable);
141 fl_ent = fl_ent->next;
144 skip:
145 if (global_protos_list == NULL)
146 return;
148 fl_ent = g_list_first(global_protos_list);
150 while (fl_ent != NULL) {
151 prot = (protocol_def *) fl_ent->data;
152 i = proto_get_id_by_filter_name(prot->name);
153 if (i == -1) {
154 /* XXX - complain here? */
155 } else {
156 if (proto_can_toggle_protocol(i)) {
157 proto_set_decoding(i, enable);
158 proto_set_cant_toggle(i);
162 fl_ent = fl_ent->next;
167 * Write out a list of protocols based on condition
169 * On success, "*pref_path_return" is set to NULL.
170 * On error, "*pref_path_return" is set to point to the pathname of
171 * the file we tried to read - it should be freed by our caller -
172 * and "*errno_return" is set to the error.
174 static void
175 save_protos_list(char **pref_path_return, int *errno_return, const char* filename,
176 const char* header_comment, bool (*protocol_check)(protocol_t *protocol))
178 char *ff_path, *ff_path_new;
179 FILE *ff;
180 int i;
181 protocol_t *protocol;
182 void *cookie;
183 bool first = true;
185 *pref_path_return = NULL; /* assume no error */
187 ff_path = get_persconffile_path(filename, true);
189 /* Write to "XXX.new", and rename if that succeeds.
190 That means we don't trash the file if we fail to write it out
191 completely. */
192 ff_path_new = ws_strdup_printf("%s.new", ff_path);
194 if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
195 *pref_path_return = ff_path;
196 *errno_return = errno;
197 g_free(ff_path_new);
198 return;
201 /* Iterate over all the protocols */
202 for (i = proto_get_first_protocol(&cookie); i != -1;
203 i = proto_get_next_protocol(&cookie)) {
205 if (!proto_can_toggle_protocol(i)) {
206 continue;
209 protocol = find_protocol_by_id(i);
210 if (protocol_check(protocol) == false)
211 continue;
213 if (first) {
214 if (header_comment != NULL) {
215 /* Write out a comment explaining what the file is */
216 fprintf(ff, "%s\n", header_comment);
218 first = false;
221 /* Write out the protocol name. */
222 fprintf(ff, "%s\n", proto_get_protocol_filter_name(i));
225 if (fclose(ff) == EOF) {
226 *pref_path_return = ff_path;
227 *errno_return = errno;
228 ws_unlink(ff_path_new);
229 g_free(ff_path_new);
230 return;
233 #ifdef _WIN32
234 /* ANSI C doesn't say whether "rename()" removes the target if it
235 exists; the Win32 call to rename files doesn't do so, which I
236 infer is the reason why the MSVC++ "rename()" doesn't do so.
237 We must therefore remove the target file first, on Windows.
239 XXX - ws_rename() should be ws_stdio_rename() on Windows,
240 and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
241 so it should remove the target if it exists, so this stuff
242 shouldn't be necessary. Perhaps it dates back to when we were
243 calling rename(), with that being a wrapper around Microsoft's
244 _rename(), which didn't remove the target. */
245 if (ws_remove(ff_path) < 0 && errno != ENOENT) {
246 /* It failed for some reason other than "it's not there"; if
247 it's not there, we don't need to remove it, so we just
248 drive on. */
249 *pref_path_return = ff_path;
250 *errno_return = errno;
251 ws_unlink(ff_path_new);
252 g_free(ff_path_new);
253 return;
255 #endif
257 if (ws_rename(ff_path_new, ff_path) < 0) {
258 *pref_path_return = ff_path;
259 *errno_return = errno;
260 ws_unlink(ff_path_new);
261 g_free(ff_path_new);
262 return;
264 g_free(ff_path_new);
265 g_free(ff_path);
268 static int
269 read_protos_list_file(const char *ff_path, FILE *ff, GList **flp)
271 protocol_def *prot;
272 int c;
273 char *prot_name;
274 int prot_name_len;
275 int prot_name_index;
276 int line = 1;
277 bool in_comment = false;
280 /* Allocate the protocol name buffer. */
281 prot_name_len = INIT_BUF_SIZE;
282 prot_name = (char *)g_malloc(prot_name_len + 1);
284 for (line = 1; ; line++) {
285 /* Lines in a protocol file contain the "filter name" of a protocol
286 to be enabled or disabled. */
288 /* Skip over leading white space, if any. */
289 while ((c = ws_getc_unlocked(ff)) != EOF && g_ascii_isspace(c)) {
290 if (c == '\n') {
291 /* Blank line. */
292 continue;
296 if (c == EOF) {
297 if (ferror(ff))
298 goto error; /* I/O error */
299 else
300 break; /* Nothing more to read */
302 ungetc(c, ff); /* Unread the non-white-space character. */
304 /* Get the name of the protocol. */
305 prot_name_index = 0;
306 for (;;) {
307 c = ws_getc_unlocked(ff);
308 if (c == EOF)
309 break; /* End of file, or I/O error */
310 if (g_ascii_isspace(c))
311 break; /* Trailing white space, or end of line. */
312 if (c == '#') {
313 in_comment = true;
314 break; /* Start of comment, running to end of line. */
316 /* Add this character to the protocol name string. */
317 if (prot_name_index >= prot_name_len) {
318 /* protocol name buffer isn't long enough; double its length. */
319 prot_name_len *= 2;
320 prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
322 prot_name[prot_name_index] = c;
323 prot_name_index++;
326 if (g_ascii_isspace(c) && c != '\n') {
327 /* Skip over trailing white space. */
328 while ((c = ws_getc_unlocked(ff)) != EOF && c != '\n' && g_ascii_isspace(c))
330 if (c != EOF && c != '\n' && c != '#') {
331 /* Non-white-space after the protocol name; warn about it,
332 in case we come up with a reason to use it. */
333 ws_warning("'%s' line %d has extra stuff after the protocol name.",
334 ff_path, line);
337 if (c != EOF && c != '\n' && in_comment == true) {
338 /* Skip to end of line. */
339 while ((c = ws_getc_unlocked(ff)) != EOF && c != '\n')
343 if (c == EOF) {
344 if (ferror(ff))
345 goto error; /* I/O error */
346 else {
347 /* EOF, not error; no newline seen before EOF */
348 ws_warning("'%s' line %d doesn't have a newline.", ff_path,
349 line);
351 break; /* nothing more to read */
354 if (in_comment) {
355 in_comment = false;
356 continue;
359 /* Null-terminate the protocol name. */
360 if (prot_name_index >= prot_name_len) {
361 /* protocol name buffer isn't long enough; double its length. */
362 prot_name_len *= 2;
363 prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
365 prot_name[prot_name_index] = '\0';
367 /* Add the new protocol to the list of disabled protocols */
368 prot = g_new(protocol_def, 1);
369 prot->name = g_strdup(prot_name);
370 *flp = g_list_append(*flp, prot);
372 g_free(prot_name);
373 return 0;
375 error:
376 g_free(prot_name);
377 return errno;
381 * Read in global and personal versions of a list of protocols.
383 * If we can open and read the global version, *gpath_return is set to
384 * NULL. Otherwise, *gpath_return is set to point to the pathname of
385 * the file we tried to read - it should be freed by our caller - and
386 * *gopen_errno_return is set to the error if an open failed or
387 * *gread_errno_return is set to the error if a read failed.
389 * If we can open and read the personal version, *path_return is set to
390 * NULL. Otherwise, *path_return is set to point to the pathname of
391 * the file we tried to read - it should be freed by our caller - and
392 * *open_errno_return is set to the error if an open failed or
393 * *read_errno_return is set to the error if a read failed.
395 static void
396 read_protos_list(char **gpath_return, int *gopen_errno_return,
397 int *gread_errno_return,
398 char **path_return, int *open_errno_return,
399 int *read_errno_return,
400 const char* filename,
401 GList **global_protos_list, GList **protos_list)
403 int err;
404 char *gff_path, *ff_path;
405 FILE *ff;
407 /* Construct the pathname of the global disabled protocols file. */
408 gff_path = get_datafile_path(filename);
410 /* If we already have a list of protocols, discard it. */
411 discard_existing_list (global_protos_list);
413 /* Read the global disabled protocols file, if it exists. */
414 *gpath_return = NULL;
415 if ((ff = ws_fopen(gff_path, "r")) != NULL) {
416 /* We succeeded in opening it; read it. */
417 err = read_protos_list_file(gff_path, ff, global_protos_list);
418 if (err != 0) {
419 /* We had an error reading the file; return the errno and the
420 pathname, so our caller can report the error. */
421 *gopen_errno_return = 0;
422 *gread_errno_return = err;
423 *gpath_return = gff_path;
424 } else
425 g_free(gff_path);
426 fclose(ff);
427 } else {
428 /* We failed to open it. If we failed for some reason other than
429 "it doesn't exist", return the errno and the pathname, so our
430 caller can report the error. */
431 if (errno != ENOENT) {
432 *gopen_errno_return = errno;
433 *gread_errno_return = 0;
434 *gpath_return = gff_path;
435 } else
436 g_free(gff_path);
439 /* Construct the pathname of the user's disabled protocols file. */
440 ff_path = get_persconffile_path(filename, true);
442 /* If we already have a list of protocols, discard it. */
443 discard_existing_list (protos_list);
445 /* Read the user's disabled protocols file, if it exists. */
446 *path_return = NULL;
447 if ((ff = ws_fopen(ff_path, "r")) != NULL) {
448 /* We succeeded in opening it; read it. */
449 err = read_protos_list_file(ff_path, ff, protos_list);
450 if (err != 0) {
451 /* We had an error reading the file; return the errno and the
452 pathname, so our caller can report the error. */
453 *open_errno_return = 0;
454 *read_errno_return = err;
455 *path_return = ff_path;
456 } else
457 g_free(ff_path);
458 fclose(ff);
459 } else {
460 /* We failed to open it. If we failed for some reason other than
461 "it doesn't exist", return the errno and the pathname, so our
462 caller can report the error. */
463 if (errno != ENOENT) {
464 *open_errno_return = errno;
465 *read_errno_return = 0;
466 *path_return = ff_path;
467 } else
468 g_free(ff_path);
472 /************************************************************************
473 * Disabling dissectors
474 ************************************************************************/
477 * Disable a particular protocol by name
479 bool
480 proto_disable_proto_by_name(const char *name)
482 protocol_t *protocol;
483 int proto_id;
485 proto_id = proto_get_id_by_filter_name(name);
486 if (proto_id >= 0 ) {
487 protocol = find_protocol_by_id(proto_id);
488 if (proto_is_protocol_enabled(protocol) == true) {
489 if (proto_can_toggle_protocol(proto_id) == true) {
490 unsaved_changes = true;
491 proto_set_decoding(proto_id, false);
494 return true;
496 else if (!strcmp(name, "ALL")) {
497 unsaved_changes = true;
498 proto_disable_all();
499 return true;
501 else {
502 return false;
506 static bool disable_proto_list_check(protocol_t *protocol)
508 if (proto_is_protocol_enabled(protocol) == false)
509 return true;
511 return false;
514 /************************************************************************
515 * Enabling dissectors (that are disabled by default)
516 ************************************************************************/
518 bool
519 proto_enable_proto_by_name(const char *name)
521 protocol_t *protocol;
522 int proto_id;
524 proto_id = proto_get_id_by_filter_name(name);
525 if (proto_id >= 0 ) {
526 protocol = find_protocol_by_id(proto_id);
527 if ((proto_is_protocol_enabled(protocol) == false)) {
528 if (proto_can_toggle_protocol(proto_id) == true) {
529 unsaved_changes = true;
530 proto_set_decoding(proto_id, true);
533 return true;
535 else if (!strcmp(name, "ALL")) {
536 unsaved_changes = true;
537 proto_reenable_all();
538 return true;
540 else {
541 return false;
545 static bool enable_proto_list_check(protocol_t *protocol)
547 if ((proto_is_protocol_enabled_by_default(protocol) == false) &&
548 (proto_is_protocol_enabled(protocol) == true))
549 return true;
551 return false;
554 /************************************************************************
555 * Heuristic dissectors
556 ************************************************************************/
559 static void
560 set_disabled_heur_dissector_list(void)
562 GList *fl_ent;
563 heur_protocol_def *heur;
564 heur_dtbl_entry_t* h;
566 if (disabled_heuristics == NULL)
567 goto skip;
569 fl_ent = g_list_first(disabled_heuristics);
571 while (fl_ent != NULL) {
572 heur = (heur_protocol_def *) fl_ent->data;
573 h = find_heur_dissector_by_unique_short_name(heur->name);
574 if (h != NULL) {
575 h->enabled = heur->enabled;
578 fl_ent = fl_ent->next;
581 skip:
582 if (global_disabled_heuristics == NULL)
583 return;
585 fl_ent = g_list_first(global_disabled_heuristics);
587 while (fl_ent != NULL) {
588 heur = (heur_protocol_def *) fl_ent->data;
590 h = find_heur_dissector_by_unique_short_name(heur->name);
591 if (h != NULL) {
592 h->enabled = heur->enabled;
595 fl_ent = fl_ent->next;
599 static int
600 read_heur_dissector_list_file(const char *ff_path, FILE *ff, GList **flp)
602 heur_protocol_def *heur;
603 int c;
604 char *heuristic_name;
605 int heuristic_name_len;
606 int name_index;
607 bool parse_enabled;
608 bool enabled;
609 int line = 1;
612 /* Allocate the protocol name buffer. */
613 heuristic_name_len = INIT_BUF_SIZE;
614 heuristic_name = (char *)g_malloc(heuristic_name_len + 1);
616 for (line = 1; ; line++) {
617 /* Lines in a disabled protocol file contain the "filter name" of
618 a protocol to be disabled. */
620 /* Skip over leading white space, if any. */
621 while ((c = ws_getc_unlocked(ff)) != EOF && g_ascii_isspace(c)) {
622 if (c == '\n') {
623 /* Blank line. */
624 continue;
628 if (c == EOF) {
629 if (ferror(ff))
630 goto error; /* I/O error */
631 else
632 break; /* Nothing more to read */
634 ungetc(c, ff); /* Unread the non-white-space character. */
636 /* Get the name of the protocol. */
637 name_index = 0;
638 enabled = false;
639 parse_enabled = false;
640 for (;;) {
641 c = ws_getc_unlocked(ff);
642 if (c == EOF)
643 break; /* End of file, or I/O error */
644 if (g_ascii_isspace(c))
645 break; /* Trailing white space, or end of line. */
646 if (c == ',') {/* Separator for enable/disable */
647 parse_enabled = true;
648 continue;
650 if (c == '#')
651 break; /* Start of comment, running to end of line. */
652 if (parse_enabled) {
653 enabled = ((c == '1') ? true : false);
654 break;
656 /* Add this character to the protocol name string. */
657 if (name_index >= heuristic_name_len) {
658 /* protocol name buffer isn't long enough; double its length. */
659 heuristic_name_len *= 2;
660 heuristic_name = (char *)g_realloc(heuristic_name, heuristic_name_len + 1);
662 heuristic_name[name_index] = c;
663 name_index++;
666 if (g_ascii_isspace(c) && c != '\n') {
667 /* Skip over trailing white space. */
668 while ((c = ws_getc_unlocked(ff)) != EOF && c != '\n' && g_ascii_isspace(c))
670 if (c != EOF && c != '\n' && c != '#') {
671 /* Non-white-space after the protocol name; warn about it,
672 in case we come up with a reason to use it. */
673 ws_warning("'%s' line %d has extra stuff after the protocol name.",
674 ff_path, line);
677 if (c != EOF && c != '\n') {
678 /* Skip to end of line. */
679 while ((c = ws_getc_unlocked(ff)) != EOF && c != '\n')
683 if (c == EOF) {
684 if (ferror(ff))
685 goto error; /* I/O error */
686 else {
687 /* EOF, not error; no newline seen before EOF */
688 ws_warning("'%s' line %d doesn't have a newline.", ff_path,
689 line);
691 break; /* nothing more to read */
694 /* Null-terminate the protocol name. */
695 if (name_index >= heuristic_name_len) {
696 /* protocol name buffer isn't long enough; double its length. */
697 heuristic_name_len *= 2;
698 heuristic_name = (char *)g_realloc(heuristic_name, heuristic_name_len + 1);
700 heuristic_name[name_index] = '\0';
702 /* Add the new protocol to the list of protocols */
703 heur = g_new(heur_protocol_def, 1);
704 heur->name = g_strdup(heuristic_name);
705 heur->enabled = enabled;
706 *flp = g_list_append(*flp, heur);
708 g_free(heuristic_name);
709 return 0;
711 error:
712 g_free(heuristic_name);
713 return errno;
716 static void
717 read_heur_dissector_list(char **gpath_return, int *gopen_errno_return,
718 int *gread_errno_return,
719 char **path_return, int *open_errno_return,
720 int *read_errno_return)
722 int err;
723 char *gff_path, *ff_path;
724 FILE *ff;
726 /* If we already have a list of protocols, discard it. */
727 heur_discard_existing_list(&global_disabled_heuristics);
729 /* Construct the pathname of the global disabled heuristic dissectors file. */
730 gff_path = get_datafile_path(HEURISTICS_FILE_NAME);
732 /* Read the global disabled protocols file, if it exists. */
733 *gpath_return = NULL;
734 if ((ff = ws_fopen(gff_path, "r")) != NULL) {
735 /* We succeeded in opening it; read it. */
736 err = read_heur_dissector_list_file(gff_path, ff,
737 &global_disabled_heuristics);
738 if (err != 0) {
739 /* We had an error reading the file; return the errno and the
740 pathname, so our caller can report the error. */
741 *gopen_errno_return = 0;
742 *gread_errno_return = err;
743 *gpath_return = gff_path;
744 } else
745 g_free(gff_path);
746 fclose(ff);
747 } else {
748 /* We failed to open it. If we failed for some reason other than
749 "it doesn't exist", return the errno and the pathname, so our
750 caller can report the error. */
751 if (errno != ENOENT) {
752 *gopen_errno_return = errno;
753 *gread_errno_return = 0;
754 *gpath_return = gff_path;
755 } else
756 g_free(gff_path);
759 /* Construct the pathname of the user's disabled protocols file. */
760 ff_path = get_persconffile_path(HEURISTICS_FILE_NAME, true);
762 /* If we already have a list of protocols, discard it. */
763 heur_discard_existing_list (&disabled_heuristics);
765 /* Read the user's disabled protocols file, if it exists. */
766 *path_return = NULL;
767 if ((ff = ws_fopen(ff_path, "r")) != NULL) {
768 /* We succeeded in opening it; read it. */
769 err = read_heur_dissector_list_file(ff_path, ff, &disabled_heuristics);
770 if (err != 0) {
771 /* We had an error reading the file; return the errno and the
772 pathname, so our caller can report the error. */
773 *open_errno_return = 0;
774 *read_errno_return = err;
775 *path_return = ff_path;
776 } else
777 g_free(ff_path);
778 fclose(ff);
779 } else {
780 /* We failed to open it. If we failed for some reason other than
781 "it doesn't exist", return the errno and the pathname, so our
782 caller can report the error. */
783 if (errno != ENOENT) {
784 *open_errno_return = errno;
785 *read_errno_return = 0;
786 *path_return = ff_path;
787 } else
788 g_free(ff_path);
792 static int
793 heur_compare(const void *a, const void *b)
795 return strcmp(((const heur_dtbl_entry_t *)a)->short_name,
796 ((const heur_dtbl_entry_t *)b)->short_name);
799 static void
800 write_heur_dissector(void *data, void *user_data)
802 heur_dtbl_entry_t* dtbl_entry = (heur_dtbl_entry_t*)data;
803 FILE *ff = (FILE*)user_data;
805 /* Write out the heuristic short name and its enabled state */
806 fprintf(ff, "%s,%d\n", dtbl_entry->short_name, dtbl_entry->enabled ? 1 : 0);
809 static void
810 sort_dissector_table_entries(const char *table_name _U_,
811 heur_dtbl_entry_t *dtbl_entry, void *user_data)
813 GSList **list = (GSList**)user_data;
814 *list = g_slist_insert_sorted(*list, dtbl_entry, heur_compare);
817 static void
818 sort_heur_dissector_tables(const char *table_name, struct heur_dissector_list *list, void *w)
820 if (list) {
821 heur_dissector_table_foreach(table_name, sort_dissector_table_entries, w);
825 static void
826 save_disabled_heur_dissector_list(char **pref_path_return, int *errno_return)
828 char *ff_path, *ff_path_new;
829 GSList *sorted_heur_list = NULL;
830 FILE *ff;
832 *pref_path_return = NULL; /* assume no error */
834 ff_path = get_persconffile_path(HEURISTICS_FILE_NAME, true);
836 /* Write to "XXX.new", and rename if that succeeds.
837 That means we don't trash the file if we fail to write it out
838 completely. */
839 ff_path_new = ws_strdup_printf("%s.new", ff_path);
841 if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
842 *pref_path_return = ff_path;
843 *errno_return = errno;
844 g_free(ff_path_new);
845 return;
848 /* Iterate over all the heuristic dissectors to sort them in alphabetical order by short name */
849 dissector_all_heur_tables_foreach_table(sort_heur_dissector_tables, &sorted_heur_list, NULL);
851 /* Write the list */
852 g_slist_foreach(sorted_heur_list, write_heur_dissector, ff);
853 g_slist_free(sorted_heur_list);
855 if (fclose(ff) == EOF) {
856 *pref_path_return = ff_path;
857 *errno_return = errno;
858 ws_unlink(ff_path_new);
859 g_free(ff_path_new);
860 return;
863 #ifdef _WIN32
864 /* ANSI C doesn't say whether "rename()" removes the target if it
865 exists; the Win32 call to rename files doesn't do so, which I
866 infer is the reason why the MSVC++ "rename()" doesn't do so.
867 We must therefore remove the target file first, on Windows.
869 XXX - ws_rename() should be ws_stdio_rename() on Windows,
870 and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
871 so it should remove the target if it exists, so this stuff
872 shouldn't be necessary. Perhaps it dates back to when we were
873 calling rename(), with that being a wrapper around Microsoft's
874 _rename(), which didn't remove the target. */
875 if (ws_remove(ff_path) < 0 && errno != ENOENT) {
876 /* It failed for some reason other than "it's not there"; if
877 it's not there, we don't need to remove it, so we just
878 drive on. */
879 *pref_path_return = ff_path;
880 *errno_return = errno;
881 ws_unlink(ff_path_new);
882 g_free(ff_path_new);
883 return;
885 #endif
887 if (ws_rename(ff_path_new, ff_path) < 0) {
888 *pref_path_return = ff_path;
889 *errno_return = errno;
890 ws_unlink(ff_path_new);
891 g_free(ff_path_new);
892 return;
894 g_free(ff_path_new);
895 g_free(ff_path);
898 static bool
899 proto_set_heuristic_by_name(const char *name, bool enable)
901 heur_dtbl_entry_t* heur = find_heur_dissector_by_unique_short_name(name);
902 if (heur != NULL) {
903 unsaved_changes |= (heur->enabled != enable);
904 heur->enabled = enable;
905 return true;
906 } else {
907 return false;
911 bool
912 proto_enable_heuristic_by_name(const char *name)
914 return proto_set_heuristic_by_name(name, true);
917 bool
918 proto_disable_heuristic_by_name(const char *name)
920 return proto_set_heuristic_by_name(name, false);
923 static void
924 disabled_protos_free(void *p, void *user_data _U_)
926 protocol_def* pd = (protocol_def*)p;
927 g_free(pd->name);
928 g_free(p);
932 * Read the files that enable and disable protocols and heuristic
933 * dissectors. Report errors through the UI.
935 void
936 read_enabled_and_disabled_lists(void)
938 char *gpath, *path;
939 int gopen_errno, gread_errno;
940 int open_errno, read_errno;
943 * Read the global and personal disabled protocols files.
945 read_protos_list(&gpath, &gopen_errno, &gread_errno,
946 &path, &open_errno, &read_errno,
947 DISABLED_PROTOCOLS_FILE_NAME,
948 &global_disabled_protos, &disabled_protos);
949 if (gpath != NULL) {
950 if (gopen_errno != 0) {
951 report_warning("Could not open global disabled protocols file\n\"%s\": %s.",
952 gpath, g_strerror(gopen_errno));
954 if (gread_errno != 0) {
955 report_warning("I/O error reading global disabled protocols file\n\"%s\": %s.",
956 gpath, g_strerror(gread_errno));
958 g_free(gpath);
959 gpath = NULL;
961 if (path != NULL) {
962 if (open_errno != 0) {
963 report_warning("Could not open your disabled protocols file\n\"%s\": %s.",
964 path, g_strerror(open_errno));
966 if (read_errno != 0) {
967 report_warning("I/O error reading your disabled protocols file\n\"%s\": %s.",
968 path, g_strerror(read_errno));
970 g_free(path);
971 path = NULL;
975 * Read the global and personal enabled protocols files.
977 read_protos_list(&gpath, &gopen_errno, &gread_errno,
978 &path, &open_errno, &read_errno,
979 ENABLED_PROTOCOLS_FILE_NAME,
980 &global_enabled_protos, &enabled_protos);
981 if (gpath != NULL) {
982 if (gopen_errno != 0) {
983 report_warning("Could not open global enabled protocols file\n\"%s\": %s.",
984 gpath, g_strerror(gopen_errno));
986 if (gread_errno != 0) {
987 report_warning("I/O error reading global enabled protocols file\n\"%s\": %s.",
988 gpath, g_strerror(gread_errno));
990 g_free(gpath);
991 gpath = NULL;
993 if (path != NULL) {
994 if (open_errno != 0) {
995 report_warning("Could not open your enabled protocols file\n\"%s\": %s.",
996 path, g_strerror(open_errno));
998 if (read_errno != 0) {
999 report_warning("I/O error reading your enabled protocols file\n\"%s\": %s.",
1000 path, g_strerror(read_errno));
1002 g_free(path);
1003 path = NULL;
1007 * Read the global and personal heuristic dissector list files.
1009 read_heur_dissector_list(&gpath, &gopen_errno, &gread_errno,
1010 &path, &open_errno, &read_errno);
1011 if (gpath != NULL) {
1012 if (gopen_errno != 0) {
1013 report_warning("Could not open global heuristic dissectors file\n\"%s\": %s.",
1014 gpath, g_strerror(gopen_errno));
1016 if (gread_errno != 0) {
1017 report_warning("I/O error reading global heuristic dissectors file\n\"%s\": %s.",
1018 gpath, g_strerror(gread_errno));
1020 g_free(gpath);
1021 gpath = NULL;
1023 if (path != NULL) {
1024 if (open_errno != 0) {
1025 report_warning("Could not open your heuristic dissectors file\n\"%s\": %s.",
1026 path, g_strerror(open_errno));
1028 if (read_errno != 0) {
1029 report_warning("I/O error reading your heuristic dissectors file\n\"%s\": %s.",
1030 path, g_strerror(read_errno));
1032 g_free(path);
1033 path = NULL;
1037 * Enable/disable protocols and heuristic dissectors as per the
1038 * contents of the files we just read.
1040 set_protos_list(disabled_protos, global_disabled_protos, false);
1041 set_protos_list(enabled_protos, global_enabled_protos, true);
1042 set_disabled_heur_dissector_list();
1043 unsaved_changes = false;
1047 * Write out the lists of enabled and disabled protocols and heuristic
1048 * dissectors to the corresponding files. Report errors through the UI.
1050 void
1051 save_enabled_and_disabled_lists(void)
1053 char *pf_dir_path;
1054 char *pf_path;
1055 int pf_save_errno;
1056 bool ok = true;
1058 /* Create the directory that holds personal configuration files, if
1059 necessary. */
1060 if (create_persconffile_dir(&pf_dir_path) == -1) {
1061 report_failure("Can't create directory\n\"%s\"\nfor disabled protocols file: %s.",
1062 pf_dir_path, g_strerror(errno));
1063 g_free(pf_dir_path);
1064 return;
1067 save_protos_list(&pf_path, &pf_save_errno, DISABLED_PROTOCOLS_FILE_NAME,
1068 NULL, disable_proto_list_check);
1069 if (pf_path != NULL) {
1070 report_failure("Could not save to your disabled protocols file\n\"%s\": %s.",
1071 pf_path, g_strerror(pf_save_errno));
1072 g_free(pf_path);
1073 ok = false;
1076 save_protos_list(&pf_path, &pf_save_errno, ENABLED_PROTOCOLS_FILE_NAME,
1077 "#This file is for enabling protocols that are disabled by default",
1078 enable_proto_list_check);
1079 if (pf_path != NULL) {
1080 report_failure("Could not save to your enabled protocols file\n\"%s\": %s.",
1081 pf_path, g_strerror(pf_save_errno));
1082 g_free(pf_path);
1083 ok = false;
1086 save_disabled_heur_dissector_list(&pf_path, &pf_save_errno);
1087 if (pf_path != NULL) {
1088 report_failure("Could not save to your disabled heuristic protocol file\n\"%s\": %s.",
1089 pf_path, g_strerror(pf_save_errno));
1090 g_free(pf_path);
1091 ok = false;
1094 if (ok)
1095 unsaved_changes = false;
1098 void
1099 cleanup_enabled_and_disabled_lists(void)
1101 g_list_foreach(global_disabled_heuristics, disabled_protos_free, NULL);
1102 g_list_free(global_disabled_heuristics);
1103 g_list_foreach(disabled_heuristics, disabled_protos_free, NULL);
1104 g_list_free(disabled_heuristics);
1105 g_list_foreach(global_disabled_protos, disabled_protos_free, NULL);
1106 g_list_free(global_disabled_protos);
1107 g_list_foreach(disabled_protos, disabled_protos_free, NULL);
1108 g_list_free(disabled_protos);
1112 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1114 * Local Variables:
1115 * c-basic-offset: 2
1116 * tab-width: 8
1117 * indent-tabs-mode: nil
1118 * End:
1120 * ex: set shiftwidth=2 tabstop=8 expandtab:
1121 * :indentSize=2:tabSize=8:noTabs=true: