Apache HTTPD
mod_so.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * This module is used to load Apache modules at runtime. This means that the
19 * server functionality can be extended without recompiling and even without
20 * taking the server down at all. Only a HUP or AP_SIG_GRACEFUL signal
21 * needs to be sent to the server to reload the dynamically loaded modules.
22 *
23 * To use, you'll first need to build your module as a shared library, then
24 * update your configuration (httpd.conf) to get the Apache core to load the
25 * module at start-up.
26 *
27 * The easiest way to build a module as a shared library is to use the
28 * `SharedModule' command in the Configuration file, instead of `AddModule'.
29 * You should also change the file extension from `.o' to `.so'. So, for
30 * example, to build the status module as a shared library edit Configuration
31 * and change
32 * AddModule modules/standard/mod_status.o
33 * to
34 * SharedModule modules/standard/mod_status.so
35 *
36 * Run Configure and make. Now Apache's httpd binary will _not_ include
37 * mod_status. Instead a shared object called mod_status.so will be build, in
38 * the modules/standard directory. You can build most of the modules as shared
39 * libraries like this.
40 *
41 * To use the shared module, move the .so file(s) into an appropriate
42 * directory. You might like to create a directory called "modules" under you
43 * server root for this (e.g. /usr/local/httpd/modules).
44 *
45 * Then edit your conf/httpd.conf file, and add LoadModule lines. For
46 * example
47 * LoadModule status_module modules/mod_status.so
48 *
49 * The first argument is the module's structure name (look at the end of the
50 * module source to find this). The second option is the path to the module
51 * file, relative to the server root. Put these directives right at the top
52 * of your httpd.conf file.
53 *
54 * Now you can start Apache. A message will be logged at "debug" level to your
55 * error_log to confirm that the module(s) are loaded (use "LogLevel debug"
56 * directive to get these log messages).
57 *
58 * If you edit the LoadModule directives while the server is live you can get
59 * Apache to re-load the modules by sending it a HUP or AP_SIG_GRACEFUL
60 * signal as normal. You can use this to dynamically change the capability
61 * of your server without bringing it down.
62 *
63 * Because currently there is only limited builtin support in the Configure
64 * script for creating the shared library files (`.so'), please consult your
65 * vendors cc(1), ld(1) and dlopen(3) manpages to find out the appropriate
66 * compiler and linker flags and insert them manually into the Configuration
67 * file under CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT.
68 *
69 * If you still have problems figuring out the flags both try the paper
70 * http://developer.netscape.com/library/documentation/enterprise
71 * /unix/svrplug.htm#1013807
72 * or install a Perl 5 interpreter on your platform and then run the command
73 *
74 * $ perl -V:usedl -V:ccdlflags -V:cccdlflags -V:lddlflags
75 *
76 * This gives you what type of dynamic loading Perl 5 uses on your platform
77 * and which compiler and linker flags Perl 5 uses to create the shared object
78 * files.
79 *
80 * Another location where you can find useful hints is the `ltconfig' script
81 * of the GNU libtool 1.2 package. Search for your platform name inside the
82 * various "case" constructs.
83 *
84 */
85
86#include "apr.h"
87#include "apr_dso.h"
88#include "apr_strings.h"
89#include "apr_errno.h"
90
91#include "ap_config.h"
92#include "httpd.h"
93#include "http_config.h"
94#include "http_log.h"
95#include "http_core.h"
96
97#include "mod_so.h"
98
99module AP_MODULE_DECLARE_DATA so_module;
100
101
102/*
103 * Server configuration to keep track of actually
104 * loaded modules and the corresponding module name.
105 */
106
110
112{
114
117 sizeof(ap_module_symbol_t));
118
119 return (void *)soc;
120}
121
122#ifndef NO_DLOPEN
123
124/*
125 * This is the cleanup for a loaded shared object. It unloads the module.
126 * This is called as a cleanup function from the core.
127 */
128
130{
132
133 /* only unload if module information is still existing */
134 if (modi->modp == NULL)
135 return APR_SUCCESS;
136
137 /* remove the module pointer from the core structure */
139
140 /* destroy the module information */
141 modi->modp = NULL;
142 modi->name = NULL;
143 return APR_SUCCESS;
144}
145
147 const char *filename, const char **used_filename)
148{
149 int retry = 0;
150 const char *fullname = ap_server_root_relative(cmd->temp_pool, filename);
151 char my_error[256];
152 if (filename != NULL && ap_strchr_c(filename, '/') == NULL) {
153 /* retry on error without path to use dlopen()'s search path */
154 retry = 1;
155 }
156
157 if (fullname == NULL && !retry) {
158 return apr_psprintf(cmd->temp_pool, "Invalid %s path %s",
159 cmd->cmd->name, filename);
160 }
163 return NULL;
164 }
165 if (retry) {
168 return NULL;
169 }
170
171 return apr_pstrcat(cmd->temp_pool, "Cannot load ", filename,
172 " into server: ",
174 NULL);
175}
176
177/*
178 * This is called for the directive LoadModule and actually loads
179 * a shared object file into the address space of the server process.
180 */
181
182static const char *load_module(cmd_parms *cmd, void *dummy,
183 const char *modname, const char *filename)
184{
187 module *modp;
188 const char *module_file;
192 int i;
193 const char *error;
194
195 /* we need to setup this value for dummy to make sure that we don't try
196 * to add a non-existent tree into the build when we return to
197 * execute_now.
198 */
200
201 /*
202 * check for already existing module
203 * If it already exists, we have nothing to do
204 * Check both dynamically-loaded modules and statically-linked modules.
205 */
206 sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config,
207 &so_module);
208 modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
209 for (i = 0; i < sconf->loaded_modules->nelts; i++) {
210 modi = &modie[i];
211 if (modi->name != NULL && strcmp(modi->name, modname) == 0) {
213 "module %s is already loaded, skipping",
214 modname);
215 return NULL;
216 }
217 }
218
219 for (i = 0; ap_preloaded_modules[i]; i++) {
220 const char *preload_name;
223
225
226 /* make sure we're comparing apples with apples
227 * make sure name of preloaded module is mod_FOO.c
228 * make sure name of structure being loaded is FOO_module
229 */
230
231 if (memcmp(modp->name, "mod_", 4)) {
232 continue;
233 }
234
235 preload_name = modp->name + strlen("mod_");
236 preload_len = strlen(preload_name) - 2;
237
238 if (strlen(modname) <= strlen("_module")) {
239 continue;
240 }
241 thismod_len = strlen(modname) - strlen("_module");
242 if (strcmp(modname + thismod_len, "_module")) {
243 continue;
244 }
245
246 if (thismod_len != preload_len) {
247 continue;
248 }
249
251 return apr_pstrcat(cmd->pool, "module ", modname,
252 " is built-in and can't be loaded",
253 NULL);
254 }
255 }
256
257 modi = apr_array_push(sconf->loaded_modules);
258 modi->name = modname;
259
260 /*
261 * Load the file into the Apache address space
262 */
264 if (error)
265 return error;
267 "loaded module %s from %s", modname, module_file);
268
269 /*
270 * Retrieve the pointer to the module structure through the module name:
271 * First with the hidden variant (prefix `AP_') and then with the plain
272 * symbol name.
273 */
275 char my_error[256];
276
277 return apr_pstrcat(cmd->pool, "Can't locate API module structure `",
278 modname, "' in file ", module_file, ": ",
280 NULL);
281 }
282 modp = (module*) modsym;
283 modp->dynamic_load_handle = (apr_dso_handle_t *)modhandle;
284 modi->modp = modp;
285
286 /*
287 * Make sure the found module structure is really a module structure
288 *
289 */
290 if (modp->magic != MODULE_MAGIC_COOKIE) {
291 return apr_psprintf(cmd->pool, "API module structure '%s' in file %s "
292 "is garbled - expected signature %08lx but saw "
293 "%08lx - perhaps this is not an Apache module DSO, "
294 "or was compiled for a different Apache version?",
296 MODULE_MAGIC_COOKIE, modp->magic);
297 }
298
299 /*
300 * Add this module to the Apache core structures
301 */
303 if (error) {
304 return error;
305 }
306
307 /*
308 * Register a cleanup in the config apr_pool_t (normally pconf). When
309 * we do a restart (or shutdown) this cleanup will cause the
310 * shared object to be unloaded.
311 */
313
314 /*
315 * Finally we need to run the configuration process for the module
316 */
317 ap_single_module_configure(cmd->pool, cmd->server, modp);
318
319 return NULL;
320}
321
322/*
323 * This implements the LoadFile directive and loads an arbitrary
324 * shared object file into the address space of the server process.
325 */
326
327static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename)
328{
330 const char *used_file, *error;
331
333 if (error)
334 return error;
335
337 "loaded file %s", used_file);
338
339 return NULL;
340}
341
342static module *ap_find_loaded_module_symbol(server_rec *s, const char *modname)
343{
344 so_server_conf *sconf;
347 int i;
348
350 &so_module);
351 modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
352
353 for (i = 0; i < sconf->loaded_modules->nelts; i++) {
354 modi = &modie[i];
355 if (modi->name != NULL && strcmp(modi->name, modname) == 0) {
356 return modi->modp;
357 }
358 }
359 return NULL;
360}
361
363{
367 int i;
369
370 if (!ap_exists_config_define("DUMP_MODULES")) {
371 return;
372 }
373
375
376 apr_file_printf(out, "Loaded Modules:\n");
377
378 sconf = (so_server_conf *)ap_get_module_config(s->module_config,
379 &so_module);
380 for (i = 0; ; i++) {
382 if (modi->name != NULL) {
383 apr_file_printf(out, " %s (static)\n", modi->name);
384 }
385 else {
386 break;
387 }
388 }
389
390 modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
391 for (i = 0; i < sconf->loaded_modules->nelts; i++) {
392 modi = &modie[i];
393 if (modi->name != NULL) {
394 apr_file_printf(out, " %s (shared)\n", modi->name);
395 }
396 }
397}
398
399#else /* not NO_DLOPEN */
400
401static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename)
402{
404 "WARNING: LoadFile not supported on this platform");
405 return NULL;
406}
407
408static const char *load_module(cmd_parms *cmd, void *dummy,
409 const char *modname, const char *filename)
410{
412 "WARNING: LoadModule not supported on this platform");
413 return NULL;
414}
415
416#endif /* NO_DLOPEN */
417
425
426static const command_rec so_cmds[] = {
428 "a module name and the name of a shared object file to load it from"),
430 "shared object file or library to load into the server at runtime"),
431 { NULL }
432};
433
436 NULL, /* create per-dir config */
437 NULL, /* merge per-dir config */
438 so_sconf_create, /* server config */
439 NULL, /* merge server config */
440 so_cmds, /* command apr_table_t */
441 register_hooks /* register hooks */
442};
Symbol export macros and hook functions.
APR Dynamic Object Handling Routines.
APR Error Codes.
APR Strings library.
#define ap_get_module_config(v, m)
ap_module_symbol_t ap_prelinked_module_symbols[]
void ap_remove_loaded_module(module *mod)
Definition config.c:733
void ap_hook_test_config(ap_HOOK_test_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:100
#define AP_DECLARE_MODULE(foo)
#define AP_INIT_ITERATE(directive, func, mconfig, where, help)
char * ap_server_root_relative(apr_pool_t *p, const char *fname)
Definition config.c:1594
const char * ap_add_loaded_module(module *mod, apr_pool_t *p, const char *s)
Definition config.c:703
void ap_single_module_configure(apr_pool_t *p, server_rec *s, module *m)
Definition config.c:2367
#define AP_INIT_TAKE2(directive, func, mconfig, where, help)
#define DYNAMIC_MODULE_LIMIT
Definition httpd.h:119
int ap_exists_config_define(const char *name)
Definition core.c:2896
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_STARTUP
Definition http_log.h:105
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define ap_log_perror
Definition http_log.h:412
#define APLOG_WARNING
Definition http_log.h:68
#define APLOG_DEBUG
Definition http_log.h:71
#define MODULE_MAGIC_COOKIE
Definition ap_mmn.h:608
void * dummy
Definition http_vhost.h:62
apr_pool_t const char apr_dbd_t const char ** error
Definition apr_dbd.h:143
apr_pool_t const char apr_dbd_t ** handle
Definition apr_dbd.h:142
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
#define APR_REGISTER_OPTIONAL_FN(name)
#define RSRC_CONF
#define EXEC_ON_READ
#define STANDARD20_MODULE_STUFF
#define ap_strchr_c(s, c)
Definition httpd.h:2353
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void * data
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
apr_size_t const char * filename
Definition apr_shm.h:72
const char * s
Definition apr_strings.h:95
apr_cmdtype_e cmd
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
static apr_file_t * out
Definition mod_info.c:85
static const char * load_file(cmd_parms *cmd, void *dummy, const char *filename)
Definition mod_so.c:327
return NULL
Definition mod_so.c:359
static apr_status_t unload_module(void *data)
Definition mod_so.c:129
static const char * load_module(cmd_parms *cmd, void *dummy, const char *modname, const char *filename)
Definition mod_so.c:182
ap_module_symbol_t * modie
Definition mod_so.c:346
ap_module_symbol_t * modi
Definition mod_so.c:345
static void register_hooks(apr_pool_t *p)
Definition mod_so.c:418
static const command_rec so_cmds[]
Definition mod_so.c:426
static void dump_loaded_modules(apr_pool_t *p, server_rec *s)
Definition mod_so.c:362
int i
Definition mod_so.c:347
static void * so_sconf_create(apr_pool_t *p, server_rec *s)
Definition mod_so.c:111
sconf
Definition mod_so.c:349
static const char * dso_load(cmd_parms *cmd, apr_dso_handle_t **modhandlep, const char *filename, const char **used_filename)
Definition mod_so.c:146
Shared Object Loader Extension Module for Apache.
Structure used to build the config tree.
This structure is used to assign symbol names to module pointers.
const char * name
A structure to store information for each virtual server.
Definition httpd.h:1322
apr_array_header_t * loaded_modules
Definition mod_so.c:108