]> git.sur5r.net Git - openldap/blob - servers/slapd/module.c
ITS#2607: improve socket() error logging with AF info
[openldap] / servers / slapd / module.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 #include "portable.h"
7 #include <stdio.h>
8 #include "slap.h"
9
10 #ifdef SLAPD_MODULES
11
12 #include <ltdl.h>
13
14 typedef int (*MODULE_INIT_FN)(
15         int argc,
16         char *argv[]);
17 typedef int (*MODULE_LOAD_FN)(
18         const void *module,
19         const char *filename);
20 typedef int (*MODULE_TERM_FN)(void);
21
22
23 struct module_regtable_t {
24         char *type;
25         MODULE_LOAD_FN proc;
26 } module_regtable[] = {
27                 { "null", load_null_module },
28 #ifdef SLAPD_EXTERNAL_EXTENSIONS
29                 { "extension", load_extop_module },
30 #endif
31                 { NULL, NULL }
32 };
33
34 typedef struct module_loaded_t {
35         struct module_loaded_t *next;
36         lt_dlhandle lib;
37 } module_loaded_t;
38
39 module_loaded_t *module_list = NULL;
40
41 static int module_unload (module_loaded_t *module);
42
43 #ifdef HAVE_EBCDIC
44 static char ebuf[BUFSIZ];
45 #endif
46
47 int module_init (void)
48 {
49         if (lt_dlinit()) {
50                 const char *error = lt_dlerror();
51 #ifdef HAVE_EBCDIC
52                 strcpy( ebuf, error );
53                 __etoa( ebuf );
54                 error = ebuf;
55 #endif
56 #ifdef NEW_LOGGING
57                 LDAP_LOG( SLAPD, CRIT, 
58                         "module_init: lt_dlinit failed: %s\n", error, 0, 0 );
59 #else
60                 Debug(LDAP_DEBUG_ANY, "lt_dlinit failed: %s\n", error, 0, 0);
61 #endif
62
63                 return -1;
64         }
65         return 0;
66 }
67
68 int module_kill (void)
69 {
70         /* unload all modules before shutdown */
71         while (module_list != NULL) {
72                 module_unload(module_list);
73         }
74
75         if (lt_dlexit()) {
76                 const char *error = lt_dlerror();
77 #ifdef HAVE_EBCDIC
78                 strcpy( ebuf, error );
79                 __etoa( ebuf );
80                 error = ebuf;
81 #endif
82 #ifdef NEW_LOGGING
83                 LDAP_LOG( SLAPD, CRIT, "module_kill: lt_dlexit failed: %s\n", 
84                         error, 0, 0 );
85 #else
86                 Debug(LDAP_DEBUG_ANY, "lt_dlexit failed: %s\n", error, 0, 0);
87 #endif
88
89                 return -1;
90         }
91         return 0;
92 }
93
94 int module_load(const char* file_name, int argc, char *argv[])
95 {
96         module_loaded_t *module = NULL;
97         const char *error;
98         int rc;
99         MODULE_INIT_FN initialize;
100 #ifdef HAVE_EBCDIC
101 #define file    ebuf
102 #else
103 #define file    file_name
104 #endif
105
106         module = (module_loaded_t *)ch_calloc(1, sizeof(module_loaded_t));
107         if (module == NULL) {
108 #ifdef NEW_LOGGING
109                 LDAP_LOG( SLAPD, CRIT, 
110                         "module_load:  (%s) out of memory.\n", file_name, 0, 0 );
111 #else
112                 Debug(LDAP_DEBUG_ANY, "module_load failed: (%s) out of memory\n", file_name,
113                         0, 0);
114 #endif
115
116                 return -1;
117         }
118
119 #ifdef HAVE_EBCDIC
120         strcpy( file, file_name );
121         __atoe( file );
122 #endif
123         /*
124          * The result of lt_dlerror(), when called, must be cached prior
125          * to calling Debug. This is because Debug is a macro that expands
126          * into multiple function calls.
127          */
128         if ((module->lib = lt_dlopenext(file)) == NULL) {
129                 error = lt_dlerror();
130 #ifdef HAVE_EBCDIC
131                 strcpy( ebuf, error );
132                 __etoa( ebuf );
133                 error = ebuf;
134 #endif
135 #ifdef NEW_LOGGING
136                 LDAP_LOG( SLAPD, CRIT, 
137                         "module_load: lt_dlopenext failed: (%s) %s.\n", 
138                         file_name, error, 0 );
139 #else
140                 Debug(LDAP_DEBUG_ANY, "lt_dlopenext failed: (%s) %s\n", file_name,
141                         error, 0);
142 #endif
143
144                 ch_free(module);
145                 return -1;
146         }
147
148 #ifdef NEW_LOGGING
149         LDAP_LOG( SLAPD, INFO, "module_load: loaded module %s\n", file_name, 0, 0 );
150 #else
151         Debug(LDAP_DEBUG_CONFIG, "loaded module %s\n", file_name, 0, 0);
152 #endif
153
154    
155 #ifdef HAVE_EBCDIC
156 #pragma convlit(suspend)
157 #endif
158         if ((initialize = lt_dlsym(module->lib, "init_module")) == NULL) {
159 #ifdef HAVE_EBCDIC
160 #pragma convlit(resume)
161 #endif
162 #ifdef NEW_LOGGING
163                 LDAP_LOG( SLAPD, ERR, 
164                         "module_load: module %s : no init_module() function found\n",
165                     file_name, 0, 0 );
166 #else
167                 Debug(LDAP_DEBUG_CONFIG, "module %s: no init_module() function found\n",
168                         file_name, 0, 0);
169 #endif
170
171                 lt_dlclose(module->lib);
172                 ch_free(module);
173                 return -1;
174         }
175
176         /* The imported init_module() routine passes back the type of
177          * module (i.e., which part of slapd it should be hooked into)
178          * or -1 for error.  If it passes back 0, then you get the 
179          * old behavior (i.e., the library is loaded and not hooked
180          * into anything).
181          *
182          * It might be better if the conf file could specify the type
183          * of module.  That way, a single module could support multiple
184          * type of hooks. This could be done by using something like:
185          *
186          *    moduleload extension /usr/local/openldap/whatever.so
187          *
188          * then we'd search through module_regtable for a matching
189          * module type, and hook in there.
190          */
191         rc = initialize(argc, argv);
192         if (rc == -1) {
193 #ifdef NEW_LOGGING
194                 LDAP_LOG( SLAPD, ERR, 
195                         "module_load:  module %s init_module() failed\n", file_name, 0, 0);
196 #else
197                 Debug(LDAP_DEBUG_CONFIG, "module %s: init_module() failed\n",
198                         file_name, 0, 0);
199 #endif
200
201                 lt_dlclose(module->lib);
202                 ch_free(module);
203                 return rc;
204         }
205
206         if (rc >= (int)(sizeof(module_regtable) / sizeof(struct module_regtable_t))
207                 || module_regtable[rc].proc == NULL)
208         {
209 #ifdef NEW_LOGGING
210                 LDAP_LOG( SLAPD, ERR, 
211                         "module_load: module %s: unknown registration type (%d).\n", 
212                         file_name, rc, 0);
213 #else
214                 Debug(LDAP_DEBUG_CONFIG, "module %s: unknown registration type (%d)\n",
215                         file_name, rc, 0);
216 #endif
217
218                 module_unload(module);
219                 return -1;
220         }
221
222         rc = (module_regtable[rc].proc)(module, file_name);
223         if (rc != 0) {
224 #ifdef NEW_LOGGING
225                 LDAP_LOG( SLAPD, ERR, 
226                         "module_load: module %s:%s could not be registered.\n",
227                         file_name, module_regtable[rc].type, 0 );
228 #else
229                 Debug(LDAP_DEBUG_CONFIG, "module %s: %s module could not be registered\n",
230                         file_name, module_regtable[rc].type, 0);
231 #endif
232
233                 module_unload(module);
234                 return rc;
235         }
236
237         module->next = module_list;
238         module_list = module;
239
240 #ifdef NEW_LOGGING
241         LDAP_LOG( SLAPD, INFO, 
242                 "module_load: module %s:%s registered\n", file_name,
243                 module_regtable[rc].type, 0 );
244 #else
245         Debug(LDAP_DEBUG_CONFIG, "module %s: %s module registered\n",
246                 file_name, module_regtable[rc].type, 0);
247 #endif
248
249         return 0;
250 }
251
252 int module_path(const char *path)
253 {
254 #ifdef HAVE_EBCDIC
255         strcpy(ebuf, path);
256         __atoe(ebuf);
257         path = ebuf;
258 #endif
259         return lt_dlsetsearchpath( path );
260 }
261
262 void *module_resolve (const void *module, const char *name)
263 {
264 #ifdef HAVE_EBCDIC
265         strcpy(ebuf, name);
266         __atoe(ebuf);
267         name = ebuf;
268 #endif
269         if (module == NULL || name == NULL)
270                 return(NULL);
271         return(lt_dlsym(((module_loaded_t *)module)->lib, name));
272 }
273
274 static int module_unload (module_loaded_t *module)
275 {
276         module_loaded_t *mod;
277         MODULE_TERM_FN terminate;
278
279         if (module != NULL) {
280                 /* remove module from tracking list */
281                 if (module_list == module) {
282                         module_list = module->next;
283                 } else {
284                         for (mod = module_list; mod; mod = mod->next) {
285                                 if (mod->next == module) {
286                                         mod->next = module->next;
287                                         break;
288                                 }
289                         }
290                 }
291
292                 /* call module's terminate routine, if present */
293 #ifdef HAVE_EBCDIC
294 #pragma convlit(suspend)
295 #endif
296                 if ((terminate = lt_dlsym(module->lib, "term_module"))) {
297 #ifdef HAVE_EBCDIC
298 #pragma convlit(resume)
299 #endif
300                         terminate();
301                 }
302
303                 /* close the library and free the memory */
304                 lt_dlclose(module->lib);
305                 ch_free(module);
306         }
307         return 0;
308 }
309
310 int load_null_module (const void *module, const char *file_name)
311 {
312         return 0;
313 }
314
315 #ifdef SLAPD_EXTERNAL_EXTENSIONS
316 int
317 load_extop_module (
318         const void *module,
319         const char *file_name
320 )
321 {
322         SLAP_EXTOP_MAIN_FN *ext_main;
323         SLAP_EXTOP_GETOID_FN *ext_getoid;
324         struct berval oid;
325         int rc;
326
327         ext_main = (SLAP_EXTOP_MAIN_FN *)module_resolve(module, "ext_main");
328         if (ext_main == NULL) {
329                 return(-1);
330         }
331
332         ext_getoid = module_resolve(module, "ext_getoid");
333         if (ext_getoid == NULL) {
334                 return(-1);
335         }
336
337         rc = (ext_getoid)(0, &oid, 256);
338         if (rc != 0) {
339                 return(rc);
340         }
341         if (oid.bv_val == NULL || oid.bv_len == 0) {
342                 return(-1);
343         }
344
345         rc = load_extop( &oid, ext_main );
346         return rc;
347 }
348 #endif /* SLAPD_EXTERNAL_EXTENSIONS */
349 #endif /* SLAPD_MODULES */
350