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