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.
38 #include <epan/filesystem.h>
39 #include <epan/proto.h>
41 #include "disabled_protos.h"
42 #include <wsutil/file_util.h>
44 #define GLOBAL_PROTOCOLS_FILE_NAME "disabled_protos"
45 #define PROTOCOLS_FILE_NAME "disabled_protos"
48 * List of disabled protocols
50 static GList
*global_disabled_protos
= NULL
;
51 static GList
*disabled_protos
= NULL
;
53 #define INIT_BUF_SIZE 128
56 discard_existing_list (GList
**flp
)
62 fl_ent
= g_list_first(*flp
);
63 while (fl_ent
!= NULL
) {
64 prot
= (protocol_def
*) fl_ent
->data
;
67 fl_ent
= fl_ent
->next
;
75 * Read in a list of disabled protocols.
77 * On success, "*pref_path_return" is set to NULL.
78 * On error, "*pref_path_return" is set to point to the pathname of
79 * the file we tried to read - it should be freed by our caller -
80 * and "*open_errno_return" is set to the error if an open failed
81 * or "*read_errno_return" is set to the error if a read failed.
84 static int read_disabled_protos_list_file(const char *ff_path
, FILE *ff
,
88 read_disabled_protos_list(char **gpath_return
, int *gopen_errno_return
,
89 int *gread_errno_return
,
90 char **path_return
, int *open_errno_return
,
91 int *read_errno_return
)
94 char *gff_path
, *ff_path
;
97 /* Construct the pathname of the global disabled protocols file. */
98 gff_path
= get_datafile_path(GLOBAL_PROTOCOLS_FILE_NAME
);
100 /* If we already have a list of protocols, discard it. */
101 discard_existing_list (&global_disabled_protos
);
103 /* Read the global disabled protocols file, if it exists. */
104 *gpath_return
= NULL
;
105 if ((ff
= ws_fopen(gff_path
, "r")) != NULL
) {
106 /* We succeeded in opening it; read it. */
107 err
= read_disabled_protos_list_file(gff_path
, ff
,
108 &global_disabled_protos
);
110 /* We had an error reading the file; return the errno and the
111 pathname, so our caller can report the error. */
112 *gopen_errno_return
= 0;
113 *gread_errno_return
= err
;
114 *gpath_return
= gff_path
;
119 /* We failed to open it. If we failed for some reason other than
120 "it doesn't exist", return the errno and the pathname, so our
121 caller can report the error. */
122 if (errno
!= ENOENT
) {
123 *gopen_errno_return
= errno
;
124 *gread_errno_return
= 0;
125 *gpath_return
= gff_path
;
130 /* Construct the pathname of the user's disabled protocols file. */
131 ff_path
= get_persconffile_path(PROTOCOLS_FILE_NAME
, TRUE
);
133 /* If we already have a list of protocols, discard it. */
134 discard_existing_list (&disabled_protos
);
136 /* Read the user's disabled protocols file, if it exists. */
138 if ((ff
= ws_fopen(ff_path
, "r")) != NULL
) {
139 /* We succeeded in opening it; read it. */
140 err
= read_disabled_protos_list_file(ff_path
, ff
, &disabled_protos
);
142 /* We had an error reading the file; return the errno and the
143 pathname, so our caller can report the error. */
144 *open_errno_return
= 0;
145 *read_errno_return
= err
;
146 *path_return
= ff_path
;
151 /* We failed to open it. If we failed for some reason other than
152 "it doesn't exist", return the errno and the pathname, so our
153 caller can report the error. */
154 if (errno
!= ENOENT
) {
155 *open_errno_return
= errno
;
156 *read_errno_return
= 0;
157 *path_return
= ff_path
;
164 read_disabled_protos_list_file(const char *ff_path
, FILE *ff
,
175 /* Allocate the protocol name buffer. */
176 prot_name_len
= INIT_BUF_SIZE
;
177 prot_name
= (char *)g_malloc(prot_name_len
+ 1);
179 for (line
= 1; ; line
++) {
180 /* Lines in a disabled protocol file contain the "filter name" of
181 a protocol to be disabled. */
183 /* Skip over leading white space, if any. */
184 while ((c
= getc(ff
)) != EOF
&& isspace(c
)) {
193 goto error
; /* I/O error */
195 break; /* Nothing more to read */
197 ungetc(c
, ff
); /* Unread the non-white-space character. */
199 /* Get the name of the protocol. */
204 break; /* End of file, or I/O error */
206 break; /* Trailing white space, or end of line. */
208 break; /* Start of comment, running to end of line. */
209 /* Add this character to the protocol name string. */
210 if (prot_name_index
>= prot_name_len
) {
211 /* protocol name buffer isn't long enough; double its length. */
213 prot_name
= (char *)g_realloc(prot_name
, prot_name_len
+ 1);
215 prot_name
[prot_name_index
] = c
;
219 if (isspace(c
) && c
!= '\n') {
220 /* Skip over trailing white space. */
221 while ((c
= getc(ff
)) != EOF
&& c
!= '\n' && isspace(c
))
223 if (c
!= EOF
&& c
!= '\n' && c
!= '#') {
224 /* Non-white-space after the protocol name; warn about it,
225 in case we come up with a reason to use it. */
226 g_warning("'%s' line %d has extra stuff after the protocol name.",
230 if (c
!= EOF
&& c
!= '\n') {
231 /* Skip to end of line. */
232 while ((c
= getc(ff
)) != EOF
&& c
!= '\n')
238 goto error
; /* I/O error */
240 /* EOF, not error; no newline seen before EOF */
241 g_warning("'%s' line %d doesn't have a newline.", ff_path
,
244 break; /* nothing more to read */
247 /* Null-terminate the protocol name. */
248 if (prot_name_index
>= prot_name_len
) {
249 /* protocol name buffer isn't long enough; double its length. */
251 prot_name
= (char *)g_realloc(prot_name
, prot_name_len
+ 1);
253 prot_name
[prot_name_index
] = '\0';
255 /* Add the new protocol to the list of disabled protocols */
256 prot
= (protocol_def
*) g_malloc(sizeof(protocol_def
));
257 prot
->name
= g_strdup(prot_name
);
258 *flp
= g_list_append(*flp
, prot
);
268 * Disable protocols as per the stored configuration
271 set_disabled_protos_list(void)
278 * assume all protocols are enabled by default
280 if (disabled_protos
== NULL
)
283 fl_ent
= g_list_first(disabled_protos
);
285 while (fl_ent
!= NULL
) {
286 prot
= (protocol_def
*) fl_ent
->data
;
287 i
= proto_get_id_by_filter_name(prot
->name
);
289 /* XXX - complain here? */
291 if (proto_can_toggle_protocol(i
))
292 proto_set_decoding(i
, FALSE
);
295 fl_ent
= fl_ent
->next
;
299 if (global_disabled_protos
== NULL
)
302 fl_ent
= g_list_first(global_disabled_protos
);
304 while (fl_ent
!= NULL
) {
305 prot
= (protocol_def
*) fl_ent
->data
;
306 i
= proto_get_id_by_filter_name(prot
->name
);
308 /* XXX - complain here? */
310 if (proto_can_toggle_protocol(i
)) {
311 proto_set_decoding(i
, FALSE
);
312 proto_set_cant_toggle(i
);
316 fl_ent
= fl_ent
->next
;
321 * Write out a list of disabled protocols.
323 * On success, "*pref_path_return" is set to NULL.
324 * On error, "*pref_path_return" is set to point to the pathname of
325 * the file we tried to read - it should be freed by our caller -
326 * and "*errno_return" is set to the error.
329 save_disabled_protos_list(char **pref_path_return
, int *errno_return
)
331 gchar
*ff_path
, *ff_path_new
;
334 protocol_t
*protocol
;
337 *pref_path_return
= NULL
; /* assume no error */
339 ff_path
= get_persconffile_path(PROTOCOLS_FILE_NAME
, TRUE
);
341 /* Write to "XXX.new", and rename if that succeeds.
342 That means we don't trash the file if we fail to write it out
344 ff_path_new
= g_strdup_printf("%s.new", ff_path
);
346 if ((ff
= ws_fopen(ff_path_new
, "w")) == NULL
) {
347 *pref_path_return
= ff_path
;
348 *errno_return
= errno
;
353 /* Iterate over all the protocols */
355 for (i
= proto_get_first_protocol(&cookie
); i
!= -1;
356 i
= proto_get_next_protocol(&cookie
)) {
358 if (!proto_can_toggle_protocol(i
)) {
362 protocol
= find_protocol_by_id(i
);
363 if (proto_is_protocol_enabled(protocol
)) {
367 /* Write out the protocol name. */
368 fprintf(ff
, "%s\n", proto_get_protocol_filter_name(i
));
371 if (fclose(ff
) == EOF
) {
372 *pref_path_return
= ff_path
;
373 *errno_return
= errno
;
374 ws_unlink(ff_path_new
);
380 /* ANSI C doesn't say whether "rename()" removes the target if it
381 exists; the Win32 call to rename files doesn't do so, which I
382 infer is the reason why the MSVC++ "rename()" doesn't do so.
383 We must therefore remove the target file first, on Windows.
385 XXX - ws_rename() should be ws_stdio_rename() on Windows,
386 and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING,
387 so it should remove the target if it exists, so this stuff
388 shouldn't be necessary. Perhaps it dates back to when we were
389 calling rename(), with that being a wrapper around Microsoft's
390 _rename(), which didn't remove the target. */
391 if (ws_remove(ff_path
) < 0 && errno
!= ENOENT
) {
392 /* It failed for some reason other than "it's not there"; if
393 it's not there, we don't need to remove it, so we just
395 *pref_path_return
= ff_path
;
396 *errno_return
= errno
;
397 ws_unlink(ff_path_new
);
403 if (ws_rename(ff_path_new
, ff_path
) < 0) {
404 *pref_path_return
= ff_path
;
405 *errno_return
= errno
;
406 ws_unlink(ff_path_new
);