2 * Copyright (C) 2010 Tobias Brunner
3 * Copyright (C) 2007 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "plugin_loader.h"
27 #include <integrity_checker.h>
28 #include <utils/linked_list.h>
29 #include <plugins/plugin.h>
31 typedef struct private_plugin_loader_t private_plugin_loader_t
;
34 * private data of plugin_loader
36 struct private_plugin_loader_t
{
41 plugin_loader_t
public;
44 * list of loaded plugins
46 linked_list_t
*plugins
;
51 * returns: NOT_FOUND, if the constructor was not found
52 * FAILED, if the plugin could not be constructed
54 static status_t
create_plugin(private_plugin_loader_t
*this, void *handle
,
55 char *name
, bool integrity
, plugin_t
**plugin
)
58 plugin_constructor_t constructor
;
60 if (snprintf(create
, sizeof(create
), "%s_plugin_create",
61 name
) >= sizeof(create
))
65 translate(create
, "-", "_");
66 constructor
= dlsym(handle
, create
);
67 if (constructor
== NULL
)
71 if (integrity
&& lib
->integrity
)
73 if (!lib
->integrity
->check_segment(lib
->integrity
, name
, constructor
))
75 DBG1(DBG_LIB
, "plugin '%s': failed segment integrity test", name
);
78 DBG1(DBG_LIB
, "plugin '%s': passed file and segment integrity tests",
81 *plugin
= constructor();
84 DBG1(DBG_LIB
, "plugin '%s': failed to load - %s returned NULL", name
,
88 DBG2(DBG_LIB
, "plugin '%s': loaded successfully", name
);
93 * load a single plugin
95 static plugin_t
* load_plugin(private_plugin_loader_t
*this,
96 char *path
, char *name
)
102 switch (create_plugin(this, RTLD_DEFAULT
, name
, FALSE
, &plugin
))
107 /* try to load the plugin from a file */
113 if (snprintf(file
, sizeof(file
), "%s/libstrongswan-%s.so", path
,
114 name
) >= sizeof(file
))
120 if (!lib
->integrity
->check_file(lib
->integrity
, name
, file
))
122 DBG1(DBG_LIB
, "plugin '%s': failed file integrity test of '%s'",
127 handle
= dlopen(file
, RTLD_LAZY
);
130 DBG1(DBG_LIB
, "plugin '%s' failed to load: %s", name
, dlerror());
133 if (create_plugin(this, handle
, name
, TRUE
, &plugin
) != SUCCESS
)
138 /* we do not store or free dlopen() handles, leak_detective requires
139 * the modules to keep loaded until leak report */
144 * Check if a plugin is already loaded
146 static bool plugin_loaded(private_plugin_loader_t
*this, char *name
)
148 enumerator_t
*enumerator
;
152 enumerator
= this->plugins
->create_enumerator(this->plugins
);
153 while (enumerator
->enumerate(enumerator
, &plugin
))
155 if (streq(plugin
->get_name(plugin
), name
))
161 enumerator
->destroy(enumerator
);
165 METHOD(plugin_loader_t
, load_plugins
, bool,
166 private_plugin_loader_t
*this, char *path
, char *list
)
168 enumerator_t
*enumerator
;
170 bool critical_failed
= FALSE
;
177 enumerator
= enumerator_create_token(list
, " ", " ");
178 while (!critical_failed
&& enumerator
->enumerate(enumerator
, &token
))
181 bool critical
= FALSE
;
184 token
= strdup(token
);
186 if (token
[len
-1] == '!')
191 if (plugin_loaded(this, token
))
196 plugin
= load_plugin(this, path
, token
);
199 this->plugins
->insert_last(this->plugins
, plugin
);
205 critical_failed
= TRUE
;
206 DBG1(DBG_LIB
, "loading critical plugin '%s' failed", token
);
211 enumerator
->destroy(enumerator
);
212 return !critical_failed
;
215 METHOD(plugin_loader_t
, unload
, void,
216 private_plugin_loader_t
*this)
220 /* unload plugins in reverse order */
221 while (this->plugins
->remove_last(this->plugins
,
222 (void**)&plugin
) == SUCCESS
)
224 plugin
->destroy(plugin
);
228 METHOD(plugin_loader_t
, create_plugin_enumerator
, enumerator_t
*,
229 private_plugin_loader_t
*this)
231 return this->plugins
->create_enumerator(this->plugins
);
235 * Reload a plugin by name, NULL for all
237 static u_int
reload_by_name(private_plugin_loader_t
*this, char *name
)
240 enumerator_t
*enumerator
;
243 enumerator
= create_plugin_enumerator(this);
244 while (enumerator
->enumerate(enumerator
, &plugin
))
246 if (name
== NULL
|| streq(name
, plugin
->get_name(plugin
)))
248 if (plugin
->reload(plugin
))
250 DBG2(DBG_LIB
, "reloaded configuration of '%s' plugin",
251 plugin
->get_name(plugin
));
256 enumerator
->destroy(enumerator
);
260 METHOD(plugin_loader_t
, reload
, u_int
,
261 private_plugin_loader_t
*this, char *list
)
264 enumerator_t
*enumerator
;
269 return reload_by_name(this, NULL
);
271 enumerator
= enumerator_create_token(list
, " ", "");
272 while (enumerator
->enumerate(enumerator
, &name
))
274 reloaded
+= reload_by_name(this, name
);
276 enumerator
->destroy(enumerator
);
280 METHOD(plugin_loader_t
, destroy
, void,
281 private_plugin_loader_t
*this)
283 this->plugins
->destroy_offset(this->plugins
, offsetof(plugin_t
, destroy
));
290 plugin_loader_t
*plugin_loader_create()
292 private_plugin_loader_t
*this;
296 .load
= _load_plugins
,
299 .create_plugin_enumerator
= _create_plugin_enumerator
,
302 .plugins
= linked_list_create(),
305 return &this->public;