Added some de-initializing funcs to plugins, lq_plugins, netfilter, parser
[olsrd.git] / src / plugin_loader.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #include "plugin_loader.h"
42 #include "olsrd_plugin.h"
43 #include "plugin_util.h"
44 #include "defs.h"
45 #include "olsr.h"
46
47 #include <dlfcn.h>
48 #include <errno.h>
49 #include <stdlib.h>
50
51
52 /* Local functions */
53 static int init_olsr_plugin(struct olsr_plugin *);
54 static int olsr_load_dl(char *, struct plugin_param *);
55 static int olsr_add_dl(struct olsr_plugin *);
56
57 static struct olsr_plugin *olsr_plugins = NULL;
58
59
60 /**
61  *Function that loads all registered plugins
62  *
63  *@return the number of plugins loaded
64  */
65 void olsr_load_plugins(void)
66 {
67     struct plugin_entry *entry = olsr_cnf->plugins;
68     int rv = 0;
69     for (entry = olsr_cnf->plugins; entry != NULL; entry = entry->next) {
70         if(olsr_load_dl(entry->name, entry->params) < 0) {
71             rv = 1;
72         }
73     }
74     if (rv != 0) {
75         OLSR_PRINTF(0, "-- PLUGIN LOADING FAILED! --\n");
76         exit(1);
77     }
78     OLSR_PRINTF(0, "-- ALL PLUGINS LOADED! --\n\n");
79 }
80
81 /**
82  *Try to load a shared library and extract
83  *the required information
84  *
85  *@param libname the name of the library(file)
86  *
87  *@return negative on error
88  */
89 static int olsr_load_dl(char *libname, struct plugin_param *params)
90 {
91     struct olsr_plugin *plugin = olsr_malloc(sizeof(struct olsr_plugin), "Plugin entry");
92     int rv;
93
94     OLSR_PRINTF(0, "---------- LOADING LIBRARY %s ----------\n", libname);
95
96     plugin->dlhandle = dlopen(libname, RTLD_NOW);
97     if(plugin->dlhandle == NULL) {
98         const int save_errno = errno;
99         OLSR_PRINTF(0, "DL loading failed: \"%s\"!\n", dlerror());
100         free(plugin);
101         errno = save_errno;
102         return -1;
103     }
104
105     rv = olsr_add_dl(plugin);
106     if (rv == -1) {
107         const int save_errno = errno;
108         dlclose(plugin->dlhandle);
109         free(plugin);
110         errno = save_errno;
111     } else {
112         plugin->params = params;
113
114         /* Initialize the plugin */
115         if (init_olsr_plugin(plugin) != 0) {
116             rv = -1;
117         }
118
119         /* queue */
120         plugin->next = olsr_plugins;
121         olsr_plugins = plugin;
122     }
123     OLSR_PRINTF(0, "---------- LIBRARY %s %s ----------\n\n", libname, rv == 0 ? "LOADED" : "FAILED");
124     return rv;
125 }
126
127 #if SUPPORT_OLD_PLUGIN_VERSIONS
128 static int try_old_versions(const struct olsr_plugin *plugin)
129 {
130     get_interface_version_func get_interface_version;
131     int *interface_version;
132
133     OLSR_PRINTF(1, "trying v2 detection... ");
134     get_interface_version = dlsym(plugin->dlhandle, "get_plugin_interface_version");
135     if (get_interface_version != NULL) {
136         return get_interface_version();
137     }
138
139     OLSR_PRINTF(1, "trying v1 detection... ");
140     interface_version = dlsym(plugin->dlhandle, "plugin_interface_version");
141     if (interface_version != NULL) {
142         return *interface_version;
143     }
144     OLSR_PRINTF(0, "FAILED: \"%s\"\n", dlerror());
145     return -1;
146 }
147 #else
148 #define try_old_versions(plugin) -1
149 #endif
150
151 static int olsr_add_dl(struct olsr_plugin *plugin)
152 {
153     get_interface_version_func get_interface_version;
154     get_plugin_parameters_func get_plugin_parameters;
155     int plugin_interface_version;
156
157     /* Fetch the interface version function, 3 different ways */
158     OLSR_PRINTF(0, "Checking plugin interface version: ");
159     get_interface_version = dlsym(plugin->dlhandle, "olsrd_plugin_interface_version");
160     if (get_interface_version == NULL) {
161         plugin_interface_version = try_old_versions(plugin);
162     } else {
163         plugin_interface_version = get_interface_version();
164     }
165     if (plugin_interface_version == -1) {
166         OLSR_PRINTF(0, "FAILED: \"%s\"\n", dlerror());
167         return -1;
168     }
169     OLSR_PRINTF(0, " %d - OK\n", plugin_interface_version);
170
171     if (plugin_interface_version < 5){
172         /* old plugin interface */
173         OLSR_PRINTF(0, "\nWARNING: YOU ARE USING AN OLD DEPRECATED PLUGIN INTERFACE!\n"
174                     "DETECTED VERSION %d AND THE CURRENT VERSION IS %d\n"
175                     "PLEASE UPGRADE YOUR PLUGIN!\n", plugin_interface_version, MOST_RECENT_PLUGIN_INTERFACE_VERSION);
176 #if SUPPORT_OLD_PLUGIN_VERSIONS
177         OLSR_PRINTF(0, "WILL CONTINUE IN 5 SECONDS...\n\n");
178         sleep(5);
179 #else
180         return -1;
181 #endif
182     }
183
184 #if SUPPORT_OLD_PLUGIN_VERSIONS
185     /* new plugin interface */
186     if (plugin_interface_version < LAST_SUPPORTED_PLUGIN_INTERFACE_VERSION) {
187         OLSR_PRINTF(0, "\n\nWARNING: VERSION MISMATCH!\n"
188                     "DETECTED %d AND LAST SUPPORTED VERSION IS %d\n"
189                     "THIS CAN CAUSE UNEXPECTED BEHAVIOUR AND CRASHES!\n"
190                     "WILL CONTINUE IN 5 SECONDS...\n\n", get_interface_version(), LAST_SUPPORTED_PLUGIN_INTERFACE_VERSION);
191         sleep(5);
192     }
193 #endif
194
195     /* Fetch the init function */
196     OLSR_PRINTF(1, "Trying to fetch plugin init function: ");
197     plugin->plugin_init = dlsym(plugin->dlhandle, "olsrd_plugin_init");
198     if (plugin->plugin_init == NULL) {
199         OLSR_PRINTF(0, "FAILED: \"%s\"\n", dlerror());
200         return -1;
201     }
202     OLSR_PRINTF(1, "OK\n");
203
204     OLSR_PRINTF(1, "Trying to fetch parameter table and it's size... \n");
205
206     get_plugin_parameters = dlsym(plugin->dlhandle, "olsrd_get_plugin_parameters");
207     if (get_plugin_parameters != NULL) {
208         (*get_plugin_parameters)(&plugin->plugin_parameters, &plugin->plugin_parameters_size);
209     } else {
210 #if SUPPORT_OLD_PLUGIN_VERSIONS
211         /* Fetch the parameter function */
212         OLSR_PRINTF(1, "Trying to fetch param function: ");
213
214         plugin->register_param = dlsym(plugin->dlhandle, "olsrd_plugin_register_param");
215         if(plugin->register_param == NULL) {
216             OLSR_PRINTF(0, "FAILED: \"%s\"\n", dlerror());
217             return -1;
218         } else {
219             OLSR_PRINTF(1, "OK\n");
220         }
221
222         plugin->plugin_parameters      = NULL;
223         plugin->plugin_parameters_size = 0;
224 #else
225         OLSR_PRINTF(0, "Old plugin interfaces are not supported\n");
226         return -1;
227 #endif
228     }
229     return 0;
230 }
231
232
233 /**
234  *Initialize a loaded plugin
235  *This includes sending information
236  *from olsrd to the plugin and
237  *register the functions from the plugin with olsrd
238  *
239  *@param entry the plugin to initialize
240  *
241  *@return -1 if there was an error
242  */
243 static int init_olsr_plugin(struct olsr_plugin *entry)
244 {
245     int rv = 0;
246     struct plugin_param *params;
247     OLSR_PRINTF(1, "Sending parameters...\n");
248     for(params = entry->params; params != NULL; params = params->next) {
249         OLSR_PRINTF(1, "\"%s\"/\"%s\"... ", params->key, params->value);
250         if (entry->plugin_parameters_size != 0) {
251             unsigned int i;
252             int rc = 0;
253             for (i = 0; i < entry->plugin_parameters_size; i++) {
254                 if (0 == entry->plugin_parameters[i].name[0] ||
255                     0 == strcasecmp(entry->plugin_parameters[i].name, params->key))
256                 {
257                     /* we have found it! */
258                     rc = entry->plugin_parameters[i].set_plugin_parameter(params->value, entry->plugin_parameters[i].data,
259                         0 == entry->plugin_parameters[i].name[0] ? (set_plugin_parameter_addon)params->key : entry->plugin_parameters[i].addon);
260                     if (rc != 0) {
261                         fprintf(stderr, "\nFatal error in plugin parameter \"%s\"/\"%s\"\n", params->key, params->value);
262                         rv = -1;
263                     }
264                     break;
265                 }
266             }
267             if (i >= entry->plugin_parameters_size) {
268                 OLSR_PRINTF(0, "Ignored parameter \"%s\"\n", params->key);
269             } else {
270                 OLSR_PRINTF(1, "%s: %s\n", params->key, rc == 0 ? "OK" : "FAILED");
271                 if (rc != 0) {
272                     rv = -1;
273                 }
274             }
275 #if SUPPORT_OLD_PLUGIN_VERSIONS
276         } else if(entry->register_param != NULL) {
277             int rc;
278             OLSR_PRINTF(0, "Registering parameter \"%s\": ", params->key);
279             rc = entry->register_param(params->key, params->value);
280             if(rc < 0) {
281                 fprintf(stderr, "\nFatal error in plugin parameter \"%s\"/\"%s\"\n", params->key, params->value);
282                 exit(EXIT_FAILURE);
283             }
284             OLSR_PRINTF(0, "%s\n", rc == 0 ? "FAILED" : "OK");
285 #endif
286         } else {
287             OLSR_PRINTF(0, "I don't know what to do with \"%s\"!\n", params->key);
288             rv = -1;
289         }
290     }
291
292     OLSR_PRINTF(1, "Running plugin_init function...\n");
293     entry->plugin_init();
294     return rv;
295 }
296
297
298 /**
299  *Close all loaded plugins
300  */
301 void olsr_close_plugins(void)
302 {
303     struct olsr_plugin *entry;
304
305     OLSR_PRINTF(0, "Closing plugins...\n");
306     while (olsr_plugins) {
307         entry = olsr_plugins;
308         olsr_plugins = entry->next;
309         dlclose(entry->dlhandle);
310         free(entry);
311     }
312 }
313
314 /*
315  * Local Variables:
316  * mode: c
317  * style: linux
318  * c-basic-offset: 4
319  * indent-tabs-mode: nil
320  * End:
321  */