Revert r44049, frame_data_cleanup() is called when redissecting.
[metze/wireshark/wip.git] / disabled_protos.c
1 /* disabled_protos.c
2  * Code for reading and writing the disabled protocols file.
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <errno.h>
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include <glib.h>
39
40 #include <epan/filesystem.h>
41 #include <epan/proto.h>
42
43 #include "disabled_protos.h"
44 #include <wsutil/file_util.h>
45
46 #define GLOBAL_PROTOCOLS_FILE_NAME      "disabled_protos"
47 #define PROTOCOLS_FILE_NAME             "disabled_protos"
48
49 /*
50  * List of disabled protocols
51  */
52 static GList *global_disabled_protos = NULL;
53 static GList *disabled_protos = NULL;
54
55 #define INIT_BUF_SIZE   128
56
57 static void
58 discard_existing_list (GList **flp)
59 {
60   GList      *fl_ent;
61   protocol_def *prot;
62
63   if (*flp != NULL) {
64     fl_ent = g_list_first(*flp);
65     while (fl_ent != NULL) {
66       prot = (protocol_def *) fl_ent->data;
67       g_free(prot->name);
68       g_free(prot);
69       fl_ent = fl_ent->next;
70     }
71     g_list_free(*flp);
72     *flp = NULL;
73   }
74 }
75
76 /*
77  * Read in a list of disabled protocols.
78  *
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.
84  */
85
86 static int read_disabled_protos_list_file(const char *ff_path, FILE *ff,
87                                           GList **flp);
88
89 void
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)
94 {
95   int         err;
96   char       *gff_path, *ff_path;
97   FILE       *ff;
98
99   /* Construct the pathname of the global disabled protocols file. */
100   gff_path = get_datafile_path(GLOBAL_PROTOCOLS_FILE_NAME);
101
102   /* If we already have a list of protocols, discard it. */
103   discard_existing_list (&global_disabled_protos);
104
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);
111     if (err != 0) {
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;
117     } else
118       g_free(gff_path);
119     fclose(ff);
120   } else {
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;
128     } else
129       g_free(gff_path);
130   }
131
132   /* Construct the pathname of the user's disabled protocols file. */
133   ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE, FALSE);
134
135   /* If we already have a list of protocols, discard it. */
136   discard_existing_list (&disabled_protos);
137
138   /* Read the user's disabled protocols file, if it exists. */
139   *path_return = NULL;
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);
143     if (err != 0) {
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;
149     } else
150       g_free(ff_path);
151     fclose(ff);
152   } else {
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;
160     } else
161       g_free(ff_path);
162   }
163 }
164
165 static int
166 read_disabled_protos_list_file(const char *ff_path, FILE *ff,
167                                GList **flp)
168 {
169   protocol_def *prot;
170   int         c;
171   char       *prot_name;
172   int         prot_name_len;
173   int         prot_name_index;
174   int         line = 1;
175
176
177   /* Allocate the protocol name buffer. */
178   prot_name_len = INIT_BUF_SIZE;
179   prot_name = (char *)g_malloc(prot_name_len + 1);
180
181   for (line = 1; ; line++) {
182     /* Lines in a disabled protocol file contain the "filter name" of
183        a protocol to be disabled. */
184
185     /* Skip over leading white space, if any. */
186     while ((c = getc(ff)) != EOF && isspace(c)) {
187       if (c == '\n') {
188         /* Blank line. */
189         continue;
190       }
191     }
192
193     if (c == EOF) {
194       if (ferror(ff))
195         goto error;     /* I/O error */
196       else
197         break;  /* Nothing more to read */
198     }
199     ungetc(c, ff);      /* Unread the non-white-space character. */
200
201     /* Get the name of the protocol. */
202     prot_name_index = 0;
203     for (;;) {
204       c = getc(ff);
205       if (c == EOF)
206         break;  /* End of file, or I/O error */
207       if (isspace(c))
208         break;  /* Trailing white space, or end of line. */
209       if (c == '#')
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. */
214         prot_name_len *= 2;
215         prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
216       }
217       prot_name[prot_name_index] = c;
218       prot_name_index++;
219     }
220
221     if (isspace(c) && c != '\n') {
222       /* Skip over trailing white space. */
223       while ((c = getc(ff)) != EOF && c != '\n' && isspace(c))
224         ;
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.",
229                   ff_path, line);
230       }
231     }
232     if (c != EOF && c != '\n') {
233       /* Skip to end of line. */
234       while ((c = getc(ff)) != EOF && c != '\n')
235         ;
236     }
237
238     if (c == EOF) {
239       if (ferror(ff))
240         goto error;     /* I/O error */
241       else {
242         /* EOF, not error; no newline seen before EOF */
243         g_warning("'%s' line %d doesn't have a newline.", ff_path,
244                   line);
245       }
246       break;    /* nothing more to read */
247     }
248
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. */
252       prot_name_len *= 2;
253       prot_name = (char *)g_realloc(prot_name, prot_name_len + 1);
254     }
255     prot_name[prot_name_index] = '\0';
256
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);
261   }
262   g_free(prot_name);
263   return 0;
264
265 error:
266   return errno;
267 }
268
269 /*
270  * Disable protocols as per the stored configuration
271  */
272 void
273 set_disabled_protos_list(void)
274 {
275   gint i;
276   GList *fl_ent;
277   protocol_def *prot;
278
279   /*
280    * assume all protocols are enabled by default
281    */
282   if (disabled_protos == NULL)
283     goto skip;
284
285   fl_ent = g_list_first(disabled_protos);
286
287   while (fl_ent != NULL) {
288     prot = (protocol_def *) fl_ent->data;
289     i = proto_get_id_by_filter_name(prot->name);
290     if (i == -1) {
291       /* XXX - complain here? */
292     } else {
293       if (proto_can_toggle_protocol(i))
294         proto_set_decoding(i, FALSE);
295     }
296
297     fl_ent = fl_ent->next;
298   }
299
300 skip:
301   if (global_disabled_protos == NULL)
302     return;
303
304   fl_ent = g_list_first(global_disabled_protos);
305
306   while (fl_ent != NULL) {
307     prot = (protocol_def *) fl_ent->data;
308     i = proto_get_id_by_filter_name(prot->name);
309     if (i == -1) {
310       /* XXX - complain here? */
311     } else {
312       if (proto_can_toggle_protocol(i)) {
313         proto_set_decoding(i, FALSE);
314         proto_set_cant_toggle(i);
315       }
316     }
317
318     fl_ent = fl_ent->next;
319   }
320 }
321
322 /*
323  * Write out a list of disabled protocols.
324  *
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.
329  */
330 void
331 save_disabled_protos_list(char **pref_path_return, int *errno_return)
332 {
333   gchar       *ff_path, *ff_path_new;
334   FILE        *ff;
335   gint         i;
336   protocol_t  *protocol;
337   void        *cookie;
338
339   *pref_path_return = NULL;     /* assume no error */
340
341   ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE, TRUE);
342
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
345      completely. */
346   ff_path_new = g_strdup_printf("%s.new", ff_path);
347
348   if ((ff = ws_fopen(ff_path_new, "w")) == NULL) {
349     *pref_path_return = ff_path;
350     *errno_return = errno;
351     g_free(ff_path_new);
352     return;
353   }
354
355   /* Iterate over all the protocols */
356
357   for (i = proto_get_first_protocol(&cookie); i != -1;
358        i = proto_get_next_protocol(&cookie)) {
359
360     if (!proto_can_toggle_protocol(i)) {
361       continue;
362     }
363
364     protocol = find_protocol_by_id(i);
365     if (proto_is_protocol_enabled(protocol)) {
366       continue;
367     }
368
369     /* Write out the protocol name. */
370     fprintf(ff, "%s\n", proto_get_protocol_filter_name(i));
371   }
372
373   if (fclose(ff) == EOF) {
374     *pref_path_return = ff_path;
375     *errno_return = errno;
376     ws_unlink(ff_path_new);
377     g_free(ff_path_new);
378     return;
379   }
380
381 #ifdef _WIN32
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.
386
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
396        drive on. */
397     *pref_path_return = ff_path;
398     *errno_return = errno;
399     ws_unlink(ff_path_new);
400     g_free(ff_path_new);
401     return;
402   }
403 #endif
404
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);
409     g_free(ff_path_new);
410     return;
411   }
412   g_free(ff_path_new);
413   g_free(ff_path);
414 }