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