f124a8e8bf85357b4e7db1e3257a1ce3904a6766
[strongswan.git] / src / libstrongswan / plugins / plugin_loader.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #define _GNU_SOURCE
17 #include "plugin_loader.h"
18
19 #include <string.h>
20 #include <dlfcn.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <link.h>
24
25 #include <debug.h>
26 #include <integrity_checker.h>
27 #include <utils/linked_list.h>
28 #include <plugins/plugin.h>
29
30 typedef struct private_plugin_loader_t private_plugin_loader_t;
31
32 /**
33 * private data of plugin_loader
34 */
35 struct private_plugin_loader_t {
36
37 /**
38 * public functions
39 */
40 plugin_loader_t public;
41
42 /**
43 * list of loaded plugins
44 */
45 linked_list_t *plugins;
46
47 /**
48 * names of loaded plugins
49 */
50 linked_list_t *names;
51 };
52
53 /**
54 * load a single plugin
55 */
56 static plugin_t* load_plugin(private_plugin_loader_t *this,
57 char *path, char *name)
58 {
59 char file[PATH_MAX];
60 void *handle;
61 plugin_t *plugin;
62 plugin_constructor_t constructor;
63
64 snprintf(file, sizeof(file), "%s/libstrongswan-%s.so", path, name);
65
66 if (lib->integrity &&
67 !lib->integrity->check_file(lib->integrity, name, file))
68 {
69 DBG1("file integrity test of plugin '%s' failed", name);
70 return NULL;
71 }
72 handle = dlopen(file, RTLD_LAZY);
73 if (handle == NULL)
74 {
75 DBG1("loading plugin '%s' failed: %s", name, dlerror());
76 return NULL;
77 }
78 constructor = dlsym(handle, "plugin_create");
79 if (constructor == NULL)
80 {
81 DBG1("loading plugin '%s' failed: no plugin_create() function", name);
82 dlclose(handle);
83 return NULL;
84 }
85 if (lib->integrity &&
86 !lib->integrity->check_segment(lib->integrity, name, constructor))
87 {
88 DBG1("segment integrity test of plugin '%s' failed", name);
89 dlclose(handle);
90 return NULL;
91 }
92 plugin = constructor();
93 if (plugin == NULL)
94 {
95 DBG1("loading plugin '%s' failed: plugin_create() returned NULL", name);
96 dlclose(handle);
97 return NULL;
98 }
99 DBG2("plugin '%s' loaded successfully", name);
100
101 /* we do not store or free dlopen() handles, leak_detective requires
102 * the modules to keep loaded until leak report */
103 return plugin;
104 }
105
106 /**
107 * Implementation of plugin_loader_t.load_plugins.
108 */
109 static int load(private_plugin_loader_t *this, char *path, char *list)
110 {
111 plugin_t *plugin;
112 enumerator_t *enumerator;
113 char *token;
114 int count = 0;
115
116 enumerator = enumerator_create_token(list, " ", " ");
117 while (enumerator->enumerate(enumerator, &token))
118 {
119 plugin = load_plugin(this, path, token);
120 if (plugin)
121 { /* insert in front to destroy them in reverse order */
122 this->plugins->insert_last(this->plugins, plugin);
123 this->names->insert_last(this->names, strdup(token));
124 count++;
125 }
126 }
127 enumerator->destroy(enumerator);
128 return count;
129 }
130
131 /**
132 * Implementation of plugin_loader_t.unload
133 */
134 static void unload(private_plugin_loader_t *this)
135 {
136 plugin_t *plugin;
137 char *name;
138
139 while (this->plugins->remove_first(this->plugins,
140 (void**)&plugin) == SUCCESS)
141 {
142 plugin->destroy(plugin);
143 }
144 while (this->names->remove_first(this->names, (void**)&name) == SUCCESS)
145 {
146 free(name);
147 }
148 }
149
150 /**
151 * Implementation of plugin_loader_t.create_plugin_enumerator
152 */
153 static enumerator_t* create_plugin_enumerator(private_plugin_loader_t *this)
154 {
155 return this->names->create_enumerator(this->names);
156 }
157
158 /**
159 * Implementation of plugin_loader_t.destroy
160 */
161 static void destroy(private_plugin_loader_t *this)
162 {
163 this->plugins->destroy_offset(this->plugins, offsetof(plugin_t, destroy));
164 this->names->destroy_function(this->names, free);
165 free(this);
166 }
167
168 /*
169 * see header file
170 */
171 plugin_loader_t *plugin_loader_create()
172 {
173 private_plugin_loader_t *this = malloc_thing(private_plugin_loader_t);
174
175 this->public.load = (int(*)(plugin_loader_t*, char *path, char *prefix))load;
176 this->public.unload = (void(*)(plugin_loader_t*))unload;
177 this->public.create_plugin_enumerator = (enumerator_t*(*)(plugin_loader_t*))create_plugin_enumerator;
178 this->public.destroy = (void(*)(plugin_loader_t*))destroy;
179
180 this->plugins = linked_list_create();
181 this->names = linked_list_create();
182
183 return &this->public;
184 }
185