~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to modules/mappers/mod_so.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#define CORE_PRIVATE
 
92
#include "ap_config.h"
 
93
#include "httpd.h"
 
94
#include "http_config.h"
 
95
#include "http_log.h"
 
96
#include "http_core.h"
 
97
 
 
98
#include "mod_so.h"
 
99
 
 
100
module AP_MODULE_DECLARE_DATA so_module;
 
101
 
 
102
 
 
103
/*
 
104
 * Server configuration to keep track of actually
 
105
 * loaded modules and the corresponding module name.
 
106
 */
 
107
 
 
108
typedef struct so_server_conf {
 
109
    apr_array_header_t *loaded_modules;
 
110
} so_server_conf;
 
111
 
 
112
static void *so_sconf_create(apr_pool_t *p, server_rec *s)
 
113
{
 
114
    so_server_conf *soc;
 
115
 
 
116
    soc = (so_server_conf *)apr_pcalloc(p, sizeof(so_server_conf));
 
117
    soc->loaded_modules = apr_array_make(p, DYNAMIC_MODULE_LIMIT,
 
118
                                     sizeof(ap_module_symbol_t));
 
119
 
 
120
    return (void *)soc;
 
121
}
 
122
 
 
123
#ifndef NO_DLOPEN
 
124
 
 
125
/*
 
126
 * This is the cleanup for a loaded shared object. It unloads the module.
 
127
 * This is called as a cleanup function from the core.
 
128
 */
 
129
 
 
130
static apr_status_t unload_module(void *data)
 
131
{
 
132
    ap_module_symbol_t *modi = (ap_module_symbol_t*)data;
 
133
 
 
134
    /* only unload if module information is still existing */
 
135
    if (modi->modp == NULL)
 
136
        return APR_SUCCESS;
 
137
 
 
138
    /* remove the module pointer from the core structure */
 
139
    ap_remove_loaded_module(modi->modp);
 
140
 
 
141
    /* destroy the module information */
 
142
    modi->modp = NULL;
 
143
    modi->name = NULL;
 
144
    return APR_SUCCESS;
 
145
}
 
146
 
 
147
/*
 
148
 * This is called for the directive LoadModule and actually loads
 
149
 * a shared object file into the address space of the server process.
 
150
 */
 
151
 
 
152
static const char *load_module(cmd_parms *cmd, void *dummy,
 
153
                               const char *modname, const char *filename)
 
154
{
 
155
    apr_dso_handle_t *modhandle;
 
156
    apr_dso_handle_sym_t modsym;
 
157
    module *modp;
 
158
    const char *szModuleFile = ap_server_root_relative(cmd->pool, filename);
 
159
    so_server_conf *sconf;
 
160
    ap_module_symbol_t *modi;
 
161
    ap_module_symbol_t *modie;
 
162
    int i;
 
163
    const char *error;
 
164
 
 
165
    /* we need to setup this value for dummy to make sure that we don't try
 
166
     * to add a non-existant tree into the build when we return to
 
167
     * execute_now.
 
168
     */
 
169
    *(ap_directive_t **)dummy = NULL;
 
170
 
 
171
    if (!szModuleFile) {
 
172
        return apr_pstrcat(cmd->pool, "Invalid LoadModule path ",
 
173
                           filename, NULL);
 
174
    }
 
175
 
 
176
    /*
 
177
     * check for already existing module
 
178
     * If it already exists, we have nothing to do
 
179
     * Check both dynamically-loaded modules and statically-linked modules.
 
180
     */
 
181
    sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config,
 
182
                                                &so_module);
 
183
    modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
 
184
    for (i = 0; i < sconf->loaded_modules->nelts; i++) {
 
185
        modi = &modie[i];
 
186
        if (modi->name != NULL && strcmp(modi->name, modname) == 0) {
 
187
            ap_log_perror(APLOG_MARK, APLOG_WARNING, 0,
 
188
                          cmd->pool, "module %s is already loaded, skipping",
 
189
                          modname);
 
190
            return NULL;
 
191
        }
 
192
    }
 
193
 
 
194
    for (i = 0; ap_preloaded_modules[i]; i++) {
 
195
        const char *preload_name;
 
196
        apr_size_t preload_len;
 
197
        apr_size_t thismod_len;
 
198
 
 
199
        modp = ap_preloaded_modules[i];
 
200
 
 
201
        /* make sure we're comparing apples with apples
 
202
         * make sure name of preloaded module is mod_FOO.c
 
203
         * make sure name of structure being loaded is FOO_module
 
204
         */
 
205
 
 
206
        if (memcmp(modp->name, "mod_", 4)) {
 
207
            continue;
 
208
        }
 
209
 
 
210
        preload_name = modp->name + strlen("mod_");
 
211
        preload_len = strlen(preload_name) - 2;
 
212
 
 
213
        if (strlen(modname) <= strlen("_module")) {
 
214
            continue;
 
215
        }
 
216
        thismod_len = strlen(modname) - strlen("_module");
 
217
        if (strcmp(modname + thismod_len, "_module")) {
 
218
            continue;
 
219
        }
 
220
 
 
221
        if (thismod_len != preload_len) {
 
222
            continue;
 
223
        }
 
224
 
 
225
        if (!memcmp(modname, preload_name, preload_len)) {
 
226
            return apr_pstrcat(cmd->pool, "module ", modname,
 
227
                               " is built-in and can't be loaded",
 
228
                               NULL);
 
229
        }
 
230
    }
 
231
 
 
232
    modi = apr_array_push(sconf->loaded_modules);
 
233
    modi->name = modname;
 
234
 
 
235
    /*
 
236
     * Load the file into the Apache address space
 
237
     */
 
238
    if (apr_dso_load(&modhandle, szModuleFile, cmd->pool) != APR_SUCCESS) {
 
239
        char my_error[256];
 
240
 
 
241
        return apr_pstrcat(cmd->pool, "Cannot load ", szModuleFile,
 
242
                          " into server: ",
 
243
                          apr_dso_error(modhandle, my_error, sizeof(my_error)),
 
244
                          NULL);
 
245
    }
 
246
    ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, cmd->pool,
 
247
                 "loaded module %s", modname);
 
248
 
 
249
    /*
 
250
     * Retrieve the pointer to the module structure through the module name:
 
251
     * First with the hidden variant (prefix `AP_') and then with the plain
 
252
     * symbol name.
 
253
     */
 
254
    if (apr_dso_sym(&modsym, modhandle, modname) != APR_SUCCESS) {
 
255
        char my_error[256];
 
256
 
 
257
        return apr_pstrcat(cmd->pool, "Can't locate API module structure `",
 
258
                          modname, "' in file ", szModuleFile, ": ",
 
259
                          apr_dso_error(modhandle, my_error, sizeof(my_error)),
 
260
                          NULL);
 
261
    }
 
262
    modp = (module*) modsym;
 
263
    modp->dynamic_load_handle = (apr_dso_handle_t *)modhandle;
 
264
    modi->modp = modp;
 
265
 
 
266
    /*
 
267
     * Make sure the found module structure is really a module structure
 
268
     *
 
269
     */
 
270
    if (modp->magic != MODULE_MAGIC_COOKIE) {
 
271
        return apr_pstrcat(cmd->pool, "API module structure `", modname,
 
272
                          "' in file ", szModuleFile, " is garbled -"
 
273
                          " perhaps this is not an Apache module DSO?", NULL);
 
274
    }
 
275
 
 
276
    /*
 
277
     * Add this module to the Apache core structures
 
278
     */
 
279
    error = ap_add_loaded_module(modp, cmd->pool);
 
280
    if (error) {
 
281
        return error;
 
282
    }
 
283
 
 
284
    /*
 
285
     * Register a cleanup in the config apr_pool_t (normally pconf). When
 
286
     * we do a restart (or shutdown) this cleanup will cause the
 
287
     * shared object to be unloaded.
 
288
     */
 
289
    apr_pool_cleanup_register(cmd->pool, modi, unload_module, apr_pool_cleanup_null);
 
290
 
 
291
    /*
 
292
     * Finally we need to run the configuration process for the module
 
293
     */
 
294
    ap_single_module_configure(cmd->pool, cmd->server, modp);
 
295
 
 
296
    return NULL;
 
297
}
 
298
 
 
299
/*
 
300
 * This implements the LoadFile directive and loads an arbitrary
 
301
 * shared object file into the adress space of the server process.
 
302
 */
 
303
 
 
304
static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename)
 
305
{
 
306
    apr_dso_handle_t *handle;
 
307
    const char *file;
 
308
 
 
309
    file = ap_server_root_relative(cmd->pool, filename);
 
310
 
 
311
    if (!file) {
 
312
        return apr_pstrcat(cmd->pool, "Invalid LoadFile path ",
 
313
                           filename, NULL);
 
314
    }
 
315
 
 
316
    if (apr_dso_load(&handle, file, cmd->pool) != APR_SUCCESS) {
 
317
        char my_error[256];
 
318
 
 
319
        return apr_pstrcat(cmd->pool, "Cannot load ", filename,
 
320
                          " into server: ",
 
321
                          apr_dso_error(handle, my_error, sizeof(my_error)),
 
322
                          NULL);
 
323
    }
 
324
 
 
325
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
 
326
                 "loaded file %s", filename);
 
327
 
 
328
    return NULL;
 
329
}
 
330
 
 
331
static module *ap_find_loaded_module_symbol(server_rec *s, const char *modname)
 
332
{
 
333
    so_server_conf *sconf;
 
334
    ap_module_symbol_t *modi;
 
335
    ap_module_symbol_t *modie;
 
336
    int i;
 
337
 
 
338
    sconf = (so_server_conf *)ap_get_module_config(s->module_config,
 
339
                                                   &so_module);
 
340
    modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
 
341
 
 
342
    for (i = 0; i < sconf->loaded_modules->nelts; i++) {
 
343
        modi = &modie[i];
 
344
        if (modi->name != NULL && strcmp(modi->name, modname) == 0) {
 
345
            return modi->modp;
 
346
        }
 
347
    }
 
348
    return NULL;
 
349
}
 
350
 
 
351
static void dump_loaded_modules(apr_pool_t *p, server_rec *s)
 
352
{
 
353
    ap_module_symbol_t *modie;
 
354
    ap_module_symbol_t *modi;
 
355
    so_server_conf *sconf;
 
356
    int i;
 
357
    apr_file_t *out = NULL;
 
358
 
 
359
    if (!ap_exists_config_define("DUMP_MODULES")) {
 
360
        return;
 
361
    }
 
362
 
 
363
    apr_file_open_stderr(&out, p);
 
364
 
 
365
    apr_file_printf(out, "Loaded Modules:\n");
 
366
 
 
367
    sconf = (so_server_conf *)ap_get_module_config(s->module_config,
 
368
                                                   &so_module);
 
369
    for (i = 0; ; i++) {
 
370
        modi = &ap_prelinked_module_symbols[i];
 
371
        if (modi->name != NULL) {
 
372
            apr_file_printf(out, " %s (static)\n", modi->name);
 
373
        }
 
374
        else {
 
375
            break;
 
376
        }
 
377
    }
 
378
 
 
379
    modie = (ap_module_symbol_t *)sconf->loaded_modules->elts;
 
380
    for (i = 0; i < sconf->loaded_modules->nelts; i++) {
 
381
        modi = &modie[i];
 
382
        if (modi->name != NULL) {
 
383
            apr_file_printf(out, " %s (shared)\n", modi->name);
 
384
        }
 
385
    }
 
386
}
 
387
 
 
388
#else /* not NO_DLOPEN */
 
389
 
 
390
static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename)
 
391
{
 
392
    ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, cmd->pool,
 
393
                 "WARNING: LoadFile not supported on this platform");
 
394
    return NULL;
 
395
}
 
396
 
 
397
static const char *load_module(cmd_parms *cmd, void *dummy,
 
398
                               const char *modname, const char *filename)
 
399
{
 
400
    ap_log_perror(APLOG_MARK, APLOG_STARTUP, 0, cmd->pool,
 
401
                 "WARNING: LoadModule not supported on this platform");
 
402
    return NULL;
 
403
}
 
404
 
 
405
#endif /* NO_DLOPEN */
 
406
 
 
407
static void register_hooks(apr_pool_t *p)
 
408
{
 
409
#ifndef NO_DLOPEN
 
410
    APR_REGISTER_OPTIONAL_FN(ap_find_loaded_module_symbol);
 
411
    ap_hook_test_config(dump_loaded_modules, NULL, NULL, APR_HOOK_MIDDLE);
 
412
#endif
 
413
}
 
414
 
 
415
static const command_rec so_cmds[] = {
 
416
    AP_INIT_TAKE2("LoadModule", load_module, NULL, RSRC_CONF | EXEC_ON_READ,
 
417
      "a module name and the name of a shared object file to load it from"),
 
418
    AP_INIT_ITERATE("LoadFile", load_file, NULL, RSRC_CONF  | EXEC_ON_READ,
 
419
      "shared object file or library to load into the server at runtime"),
 
420
    { NULL }
 
421
};
 
422
 
 
423
module AP_MODULE_DECLARE_DATA so_module = {
 
424
   STANDARD20_MODULE_STUFF,
 
425
   NULL,                 /* create per-dir config */
 
426
   NULL,                 /* merge per-dir config */
 
427
   so_sconf_create,      /* server config */
 
428
   NULL,                 /* merge server config */
 
429
   so_cmds,              /* command apr_table_t */
 
430
   register_hooks        /* register hooks */
 
431
};