2 * Code for reading and writing the disabled protocols file.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
40 #include <epan/filesystem.h>
41 #include <epan/proto.h>
43 #include "disabled_protos.h"
44 #include <wsutil/file_util.h>
46 #define GLOBAL_PROTOCOLS_FILE_NAME "disabled_protos"
47 #define PROTOCOLS_FILE_NAME "disabled_protos"
50 * List of disabled protocols
52 static GList *global_disabled_protos = NULL;
53 static GList *disabled_protos = NULL;
55 #define INIT_BUF_SIZE 128
58 discard_existing_list (GList **flp)
64 fl_ent = g_list_first(*flp);
65 while (fl_ent != NULL) {
66 prot = (protocol_def *) fl_ent->data;
69 fl_ent = fl_ent->next;
77 * Read in a list of disabled protocols.
79 * On success, "*pref_path_return" is set to NULL.
80 * On error, "*pref_path_return" is set to point to the pathname of
81 * the file we tried to read - it should be freed by our caller -
82 * and "*open_errno_return" is set to the error if an open failed
83 * or "*read_errno_return" is set to the error if a read failed.
86 static int read_disabled_protos_list_file(const char *ff_path, FILE *ff,
90 read_disabled_protos_list(char **gpath_return, int *gopen_errno_return,
91 int *gread_errno_return,
92 char **path_return, int *open_errno_return,
93 int *read_errno_return)
96 char *gff_path, *ff_path;
99 /* Construct the pathname of the global disabled protocols file. */
100 gff_path = get_datafile_path(GLOBAL_PROTOCOLS_FILE_NAME);
102 /* If we already have a list of protocols, discard it. */
103 discard_existing_list (&global_disabled_protos);
105 /* Read the global disabled protocols file, if it exists. */
106 *gpath_return = NULL;
107 if ((ff = ws_fopen(gff_path, "r")) != NULL) {
108 /* We succeeded in opening it; read it. */
109 err = read_disabled_protos_list_file(gff_path, ff,
110 &global_disabled_protos);
112 /* We had an error reading the file; return the errno and the
113 pathname, so our caller can report the error. */
114 *gopen_errno_return = 0;
115 *gread_errno_return = err;
116 *gpath_return = gff_path;
121 /* We failed to open it. If we failed for some reason other than
122 "it doesn't exist", return the errno and the pathname, so our
123 caller can report the error. */
124 if (errno != ENOENT) {
125 *gopen_errno_return = errno;
126 *gread_errno_return = 0;
127 *gpath_return = gff_path;
132 /* Construct the pathname of the user's disabled protocols file. */
133 ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE, FALSE);
135 /* If we already have a list of protocols, discard it. */
136 discard_existing_list (&disabled_protos);
138 /* Read the user's disabled protocols file, if it exists. */
140 if ((ff = ws_fopen(ff_path, "r")) != NULL) {
141 /* We succeeded in opening it; read it. */
142 err = read_disabled_protos_list_file(ff_path, ff, &disabled_protos);
144 /* We had an error reading the file; return the errno and the
145 pathname, so our caller can report the error. */
146 *open_errno_return = 0;
147 *read_errno_return = err;
148 *path_return = ff_path;
153 /* We failed to open it. If we failed for some reason other than
154 "it doesn't exist", return the errno and the pathname, so our
155 caller can report the error. */
156 if (errno != ENOENT) {
157 *open_errno_return = errno;
158 *read_errno_return = 0;
159 *path_return = ff_path;
166 read_disabled_protos_list_file(const char *ff_path, FILE *ff,
177 /* Allocate the protocol name buffer. */
178 prot_name_len = INIT_BUF_SIZE;
179 prot_name = (char *)g_malloc(prot_name_len + 1);
181 for (line = 1; ; line++) {
182 /* Lines in a disabled protocol file contain the "filter name" of
183 a protocol to be disabled. */
185 /* Skip over leading white space, if any. */
186 while ((c = getc(ff)) != EOF && isspace(c)) {
195 goto error; /* I/O error */
197 break; /* Nothing more to read */
199 ungetc(c, ff); /* Unread the non-white-space character. */
201 /* Get the name of the protocol. */
206 break; /* End of file, or I/O error */
208 break; /* Trailing white space, or end of line. */
210 break; /* Start of comment, running to end of line. */
211 /* Add this character to the protocol name string. */
212 if (prot_name_index >= prot_name_len) {
213 /* protocol name buffer isn't long enough; double its length. */
215 prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
217 prot_name[prot_name_index] = c;
221 if (isspace(c) && c != '\n') {
222 /* Skip over trailing white space. */
223 while ((c = getc(ff)) != EOF && c != '\n' && isspace(c))
225 if (c != EOF && c != '\n' && c != '#') {
226 /* Non-white-space after the protocol name; warn about it,
227 in case we come up with a reason to use it. */
228 g_warning("'%s' line %d has extra stuff after the protocol name.",
232 if (c != EOF && c != '\n') {
233 /* Skip to end of line. */
234 while ((c = getc(ff)) != EOF && c != '\n')
240 goto error; /* I/O error */
242 /* EOF, not error; no newline seen before EOF */
243 g_warning("'%s' line %d doesn't have a newline.", ff_path,
246 break; /* nothing more to read */
249 /* Null-terminate the protocol name. */
250 if (prot_name_index >= prot_name_len) {
251 /* protocol name buffer isn't long enough; double its length. */
253 prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
255 prot_name[prot_name_index] = '\0';
257 /* Add the new protocol to the list of disabled protocols */
258 prot = (protocol_def *) g_malloc(sizeof(protocol_def));
259 prot->name = g_strdup(prot_name);
260 *flp = g_list_append(*flp, prot);
270 * Disable protocols as per the stored configuration
273 set_disabled_protos_list(void)
280 * assume all protocols are enabled by default
282 if (disabled_protos == NULL)
285 fl_ent = g_list_first(disabled_protos);
287 while (fl_ent != NULL) {
288 prot = (protocol_def *) fl_ent->data;
289 i = proto_get_id_by_filter_name(prot->name);
291 /* XXX - complain here? */
293 if (proto_can_toggle_protocol(i))
294 proto_set_decoding(i, FALSE);
297 fl_ent = fl_ent->next;
301 if (global_disabled_protos == NULL)
304 fl_ent = g_list_first(global_disabled_protos);
306 while (fl_ent != NULL) {
307 prot = (protocol_def *) fl_ent->data;
308 i = proto_get_id_by_filter_name(prot->name);
310 /* XXX - complain here? */
312 if (proto_can_toggle_protocol(i)) {
313 proto_set_decoding(i, FALSE);
314 proto_set_cant_toggle(i);
318 fl_ent = fl_ent->next;
323 * Write out a list of disabled protocols.
325 * On success, "*pref_path_return" is set to NULL.
326 * On error, "*pref_path_return" is set to point to the pathname of
327 * the file we tried to read - it should be freed by our caller -
328 * and "*errno_return" is set to the error.
331 save_disabled_protos_list(char **pref_path_return, int *errno_return)
333 gchar *ff_path, *ff_path_new;
336 protocol_t *protocol;
339 *pref_path_return = NULL; /* assume no error */
341 ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE, TRUE);
343 /* Write to "XXX.new", and rename if that succeeds.
344 That means we don't trash the file if we fail to write it out
346 ff_path_new = g_strdup_printf("%s.new", ff_path);
348 if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
349 *pref_path_return = ff_path;
350 *errno_return = errno;
355 /* Iterate over all the protocols */
357 for (i = proto_get_first_protocol(&cookie); i != -1;
358 i = proto_get_next_protocol(&cookie)) {
360 if (!proto_can_toggle_protocol(i)) {
364 protocol = find_protocol_by_id(i);
365 if (proto_is_protocol_enabled(protocol)) {
369 /* Write out the protocol name. */
370 fprintf(ff, "%s\n", proto_get_protocol_filter_name(i));
373 if (fclose(ff) == EOF) {
374 *pref_path_return = ff_path;
375 *errno_return = errno;
376 ws_unlink(ff_path_new);
382 /* ANSI C doesn't say whether "rename()" removes the target if it
383 exists; the Win32 call to rename files doesn't do so, which I
384 infer is the reason why the MSVC++ "rename()" doesn't do so.
385 We must therefore remove the target file first, on Windows.
387 XXX - ws_rename() should be ws_stdio_rename() on Windows,
388 and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
389 so it should remove the target if it exists, so this stuff
390 shouldn't be necessary. Perhaps it dates back to when we were
391 calling rename(), with that being a wrapper around Microsoft's
392 _rename(), which didn't remove the target. */
393 if (ws_remove(ff_path) < 0 && errno != ENOENT) {
394 /* It failed for some reason other than "it's not there"; if
395 it's not there, we don't need to remove it, so we just
397 *pref_path_return = ff_path;
398 *errno_return = errno;
399 ws_unlink(ff_path_new);
405 if (ws_rename(ff_path_new, ff_path) < 0) {
406 *pref_path_return = ff_path;
407 *errno_return = errno;
408 ws_unlink(ff_path_new);