Regenerate a few more of the ASN.1 dissectors
[obnox/wireshark/wip.git] / epan / plugins.c
1 /* plugins.c
2  * plugin routines
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include "plugins.h"
30
31 #ifdef HAVE_PLUGINS
32
33 #include <time.h>
34
35 #ifdef HAVE_DIRENT_H
36 #include <dirent.h>
37 #endif
38
39 #ifdef HAVE_DIRECT_H
40 #include <direct.h>
41 #endif
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <errno.h>
47
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51
52 #include "filesystem.h"
53 #include <wsutil/privileges.h>
54 #include <wsutil/file_util.h>
55 #include "report_err.h"
56
57 /* linked list of all plugins */
58 plugin *plugin_list = NULL;
59
60 /*
61  * add a new plugin to the list
62  * returns :
63  * - 0 : OK
64  * - ENOMEM : memory allocation problem
65  * - EEXIST : the same plugin (i.e. name/version) was already registered.
66  */
67 static int
68 add_plugin(void *handle, gchar *name, gchar *version,
69            void (*register_protoinfo)(void),
70            void (*reg_handoff)(void),
71            void (*register_tap_listener)(void),
72            void (*register_wtap_module)(void),
73            void (*register_codec_module)(void))
74 {
75     plugin *new_plug, *pt_plug;
76
77     pt_plug = plugin_list;
78     if (!pt_plug) /* the list is empty */
79     {
80         new_plug = (plugin *)g_malloc(sizeof(plugin));
81         if (new_plug == NULL)
82             return ENOMEM;
83         plugin_list = new_plug;
84     }
85     else
86     {
87         while (1)
88         {
89             /* check if the same name/version is already registered */
90             if (!strcmp(pt_plug->name, name) &&
91                 !strcmp(pt_plug->version, version))
92             {
93                 return EEXIST;
94             }
95
96             /* we found the last plugin in the list */
97             if (pt_plug->next == NULL)
98                 break;
99
100             pt_plug = pt_plug->next;
101         }
102         new_plug = (plugin *)g_malloc(sizeof(plugin));
103         if (new_plug == NULL)
104             return ENOMEM;
105         pt_plug->next = new_plug;
106     }
107
108     new_plug->handle = handle;
109     new_plug->name = name;
110     new_plug->version = version;
111     new_plug->register_protoinfo = register_protoinfo;
112     new_plug->reg_handoff = reg_handoff;
113     new_plug->register_tap_listener = register_tap_listener;
114     new_plug->register_wtap_module = register_wtap_module;
115     new_plug->register_codec_module = register_codec_module;
116     new_plug->next = NULL;
117
118     return 0;
119 }
120
121 /*
122  * XXX - when we remove support for old-style plugins (which we should
123  * probably do eventually, as all plugins should be written as new-style
124  * ones), we may want to have "init_plugins()" merely save a pointer
125  * to the plugin's "init" routine, just as we save a pointer to its
126  * "reg_handoff" routine, and have a "register_all_plugins()" routine
127  * to go through the list of plugins and call all of them.
128  *
129  * Then we'd have "epan_init()", or perhaps even something higher up
130  * in the call tree, call "init_plugins()", and have "proto_init()"
131  * call "register_all_plugins()" right after calling "register_all_protocols()";
132  * this might be a bit cleaner.
133  */
134 static void
135 plugins_scan_dir(const char *dirname)
136 {
137 #define FILENAME_LEN        1024
138     WS_DIR        *dir;             /* scanned directory */
139     WS_DIRENT     *file;            /* current file */
140     const char    *name;
141     gchar          filename[FILENAME_LEN];   /* current file name */
142     GModule       *handle;          /* handle returned by dlopen */
143     gchar         *version;
144     gpointer       gp;
145     void         (*register_protoinfo)(void);
146     void         (*reg_handoff)(void);
147     void         (*register_tap_listener)(void);
148     void         (*register_wtap_module)(void);
149     void         (*register_codec_module)(void);
150
151     gchar         *dot;
152     int            cr;
153
154     if ((dir = ws_dir_open(dirname, 0, NULL)) != NULL)
155     {
156         while ((file = ws_dir_read_name(dir)) != NULL)
157         {
158             name = ws_dir_get_name(file);
159
160             /*
161              * GLib 2.x defines G_MODULE_SUFFIX as the extension used on
162              * this platform for loadable modules.
163              */
164             /* skip anything but files with G_MODULE_SUFFIX */
165             dot = strrchr(name, '.');
166             if (dot == NULL || strcmp(dot+1, G_MODULE_SUFFIX) != 0)
167                 continue;
168
169             g_snprintf(filename, FILENAME_LEN, "%s" G_DIR_SEPARATOR_S "%s",
170                        dirname, name);
171             if ((handle = g_module_open(filename, 0)) == NULL)
172             {
173                 report_failure("Couldn't load module %s: %s", filename,
174                                g_module_error());
175                 continue;
176             }
177
178             if (!g_module_symbol(handle, "version", &gp))
179             {
180                 report_failure("The plugin %s has no version symbol", name);
181                 g_module_close(handle);
182                 continue;
183             }
184             version = gp;
185
186             /*
187              * Do we have a register routine?
188              */
189             if (g_module_symbol(handle, "plugin_register", &gp))
190             {
191                 /*
192                  * Yes - this plugin includes one or more dissectors.
193                  */
194                 register_protoinfo = gp;
195             }
196             else
197             {
198                 /*
199                  * No - no dissectors.
200                  */
201                 register_protoinfo = NULL;
202             }
203
204             /*
205              * Do we have a reg_handoff routine?
206              */
207             if (g_module_symbol(handle, "plugin_reg_handoff", &gp))
208             {
209                 /*
210                  * Yes.
211                  */
212                 reg_handoff = gp;
213             }
214             else
215             {
216                 /*
217                  * No - that's OK even if we have dissectors, as long
218                  * as the plugin registers by name *and* there's
219                  * a caller looking for that name.
220                  */
221                 reg_handoff = NULL;
222             }
223
224             /*
225              * Do we have a register_tap_listener routine?
226              */
227             if (g_module_symbol(handle, "plugin_register_tap_listener", &gp))
228             {
229                 /*
230                  * Yes - this plugin includes one or more taps.
231                  */
232                 register_tap_listener = gp;
233             }
234             else
235             {
236                 /*
237                  * No - no taps here.
238                  */
239                 register_tap_listener = NULL;
240             }
241
242             /*
243              * Do we have an old-style init routine?
244              */
245             if (g_module_symbol(handle, "plugin_init", &gp))
246             {
247                 /*
248                  * Yes - do we also have a register routine or a
249                  * register_tap_listener routine?  If so, this is a bogus
250                  * hybrid of an old-style and new-style plugin.
251                  */
252                 if (register_protoinfo != NULL || register_tap_listener != NULL)
253                 {
254                     report_failure("The plugin '%s' has an old plugin init routine\nand a new register or register_tap_listener routine.",
255                                    name);
256                     g_module_close(handle);
257                     continue;
258                 }
259
260                 /*
261                  * It's just an unsupported old-style plugin;
262                  */
263                 report_failure("The plugin '%s' has an old plugin init routine. Support has been dropped.\n Information on how to update your plugin is available at \nhttp://anonsvn.wireshark.org/wireshark/trunk/doc/README.plugins",
264                                name);
265                 g_module_close(handle);
266                 continue;
267             }
268
269             /*
270              * Do we have a register_wtap_module routine?
271              */
272             if (g_module_symbol(handle, "register_wtap_module", &gp))
273             {
274                 register_wtap_module = gp;
275             }
276             else
277             {
278                 register_wtap_module = NULL;
279             }
280
281             /*
282              * Do we have a register_codec_module routine?
283              */
284             if (g_module_symbol(handle, "register_codec_module", &gp))
285             {
286                 register_codec_module = gp;
287             }
288             else
289             {
290                 register_codec_module = NULL;
291             }
292
293             /*
294              * Does this dissector do anything useful?
295              */
296             if (register_protoinfo == NULL &&
297                 register_tap_listener == NULL &&
298                 register_wtap_module == NULL &&
299                 register_codec_module == NULL )
300             {
301                 /*
302                  * No.
303                  */
304                 report_failure("The plugin '%s' has neither a register routine, "
305                                "a register_tap_listener or a register_wtap_module or a register_codec_module routine",
306                                name);
307                 g_module_close(handle);
308                 continue;
309             }
310
311             /*
312              * OK, attempt to add it to the list of plugins.
313              */
314             if ((cr = add_plugin(handle, g_strdup(name), version,
315                                  register_protoinfo, reg_handoff,
316                                  register_tap_listener,register_wtap_module,register_codec_module)))
317             {
318                 if (cr == EEXIST)
319                     fprintf(stderr, "The plugin %s, version %s\n"
320                             "was found in multiple directories\n", name, version);
321                 else
322                     fprintf(stderr, "Memory allocation problem\n"
323                             "when processing plugin %s, version %s\n",
324                             name, version);
325                 g_module_close(handle);
326                 continue;
327             }
328
329         }
330         ws_dir_close(dir);
331     }
332 }
333
334
335 /*
336  * init plugins
337  */
338 void
339 init_plugins(void)
340 {
341     const char *plugin_dir;
342     const char *name;
343     char *plugin_dir_path;
344     char *plugins_pers_dir;
345     WS_DIR *dir;                /* scanned directory */
346     WS_DIRENT *file;                /* current file */
347
348     if (plugin_list == NULL)      /* ensure init_plugins is only run once */
349     {
350         /*
351          * Scan the global plugin directory.
352          * If we're running from a build directory, scan the subdirectories
353          * of that directory, as the global plugin directory is the
354          * "plugins" directory of the source tree, and the subdirectories
355          * are the source directories for the plugins, with the plugins
356          * built in those subdirectories.
357          */
358         plugin_dir = get_plugin_dir();
359         if (running_in_build_directory())
360         {
361             if ((dir = ws_dir_open(plugin_dir, 0, NULL)) != NULL)
362             {
363                 while ((file = ws_dir_read_name(dir)) != NULL)
364                 {
365                     name = ws_dir_get_name(file);
366                     if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
367                         continue;        /* skip "." and ".." */
368                     /*
369                      * Get the full path of a ".libs" subdirectory of that
370                      * directory.
371                      */
372                     plugin_dir_path = g_strdup_printf(
373                         "%s" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S ".libs",
374                         plugin_dir, name);
375                     if (test_for_directory(plugin_dir_path) != EISDIR) {
376                         /*
377                          * Either it doesn't refer to a directory or it
378                          * refers to something that doesn't exist.
379                          *
380                          * Assume that means that the plugins are in
381                          * the subdirectory of the plugin directory, not
382                          * a ".libs" subdirectory of that subdirectory.
383                          */
384                         g_free(plugin_dir_path);
385                         plugin_dir_path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
386                             plugin_dir, name);
387                     }
388                     plugins_scan_dir(plugin_dir_path);
389                     g_free(plugin_dir_path);
390                 }
391                 ws_dir_close(dir);
392             }
393         }
394         else
395             plugins_scan_dir(plugin_dir);
396
397         /*
398          * If the program wasn't started with special privileges,
399          * scan the users plugin directory.  (Even if we relinquish
400          * them, plugins aren't safe unless we've *permanently*
401          * relinquished them, and we can't do that in Wireshark as,
402          * if we need privileges to start capturing, we'd need to
403          * reclaim them before each time we start capturing.)
404          */
405         if (!started_with_special_privs())
406         {
407             plugins_pers_dir = get_plugins_pers_dir();
408             plugins_scan_dir(plugins_pers_dir);
409             g_free(plugins_pers_dir);
410         }
411     }
412
413     register_all_wiretap_modules();
414     register_all_codecs();
415 }
416
417 void
418 register_all_plugin_registrations(void)
419 {
420     plugin *pt_plug;
421
422     /*
423      * For all plugins with register-handoff routines, call the routines.
424      * This is called from "proto_init()"; it must be called after
425      * "register_all_protocols()" and "init_plugins()" are called,
426      * in case one plugin registers itself either with a built-in
427      * dissector or with another plugin; we must first register all
428      * dissectors, whether built-in or plugin, so their dissector tables
429      * are initialized, and only then register all handoffs.
430      */
431     for (pt_plug = plugin_list; pt_plug != NULL; pt_plug = pt_plug->next)
432     {
433         if (pt_plug->register_protoinfo)
434             (pt_plug->register_protoinfo)();
435     }
436 }
437
438 void
439 register_all_plugin_handoffs(void)
440 {
441     plugin *pt_plug;
442
443     /*
444      * For all plugins with register-handoff routines, call the routines.
445      * This is called from "proto_init()"; it must be called after
446      * "register_all_protocols()" and "init_plugins()" are called,
447      * in case one plugin registers itself either with a built-in
448      * dissector or with another plugin; we must first register all
449      * dissectors, whether built-in or plugin, so their dissector tables
450      * are initialized, and only then register all handoffs.
451      */
452     for (pt_plug = plugin_list; pt_plug != NULL; pt_plug = pt_plug->next)
453     {
454         if (pt_plug->reg_handoff)
455             (pt_plug->reg_handoff)();
456     }
457 }
458
459 void
460 register_all_plugin_tap_listeners(void)
461 {
462     plugin *pt_plug;
463
464     /*
465      * For all plugins with register-tap-listener routines, call the
466      * routines.
467      */
468     for (pt_plug = plugin_list; pt_plug != NULL; pt_plug = pt_plug->next)
469     {
470         if (pt_plug->register_tap_listener)
471             (pt_plug->register_tap_listener)();
472     }
473 }
474
475 void
476 register_all_wiretap_modules(void)
477 {
478     plugin *pt_plug;
479
480     /*
481      * For all plugins with register_wtap_module routines, call the
482      * routines.
483      */
484     for (pt_plug = plugin_list; pt_plug != NULL; pt_plug = pt_plug->next)
485     {
486         if (pt_plug->register_wtap_module)
487             (pt_plug->register_wtap_module)();
488     }
489 }
490
491 void
492 register_all_codecs(void)
493 {
494     plugin *pt_plug;
495
496     /*
497      * For all plugins with register_wtap_module routines, call the
498      * routines.
499      */
500     for (pt_plug = plugin_list; pt_plug != NULL; pt_plug = pt_plug->next)
501     {
502         if (pt_plug->register_codec_module)
503               (pt_plug->register_codec_module)();
504     }
505 }
506 #endif