GPLization banner introduced to *.[hc] files
[sip-router] / sr_module.c
1 /* $Id$
2  *
3  * Copyright (C) 2001-2003 Fhg Fokus
4  *
5  * This file is part of ser, a free SIP server.
6  *
7  * ser is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version
11  *
12  * For a license to use the ser software under conditions
13  * other than those described here, or to purchase support for this
14  * software, please contact iptel.org by e-mail at the following addresses:
15  *    info@iptel.org
16  *
17  * ser is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License 
23  * along with this program; if not, write to the Free Software 
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26
27
28 #include "sr_module.h"
29 #include "dprint.h"
30 #include "error.h"
31
32 #include <dlfcn.h>
33 #include <strings.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37
38 struct sr_module* modules=0;
39
40 #ifdef STATIC_EXEC
41         extern struct module_exports* exec_exports();
42 #endif
43 #ifdef STATIC_TM
44         extern struct module_exports* tm_exports();
45 #endif
46
47 #ifdef STATIC_MAXFWD
48         extern struct module_exports* maxfwd_exports();
49 #endif
50
51 #ifdef STATIC_AUTH
52         extern struct module_exports* auth_exports();
53 #endif
54
55 #ifdef STATIC_RR
56         extern struct module_exports* rr_exports();
57 #endif
58
59 #ifdef STATIC_USRLOC
60         extern struct module_exports* usrloc_exports();
61 #endif
62
63
64 /* initializes statically built (compiled in) modules*/
65 int register_builtin_modules()
66 {
67         int ret;
68
69         ret=0;
70 #ifdef STATIC_TM
71         ret=register_module(tm_exports,"built-in", 0); 
72         if (ret<0) return ret;
73 #endif
74
75 #ifdef EXEC_TM
76         ret=register_module(exec_exports,"built-in", 0); 
77         if (ret<0) return ret;
78 #endif
79
80 #ifdef STATIC_MAXFWD
81         ret=register_module(maxfwd_exports, "built-in", 0);
82         if (ret<0) return ret;
83 #endif
84
85 #ifdef STATIC_AUTH
86         ret=register_module(auth_exports, "built-in", 0); 
87         if (ret<0) return ret;
88 #endif
89         
90 #ifdef STATIC_RR
91         ret=register_module(rr_exports, "built-in", 0);
92         if (ret<0) return ret;
93 #endif
94         
95 #ifdef STATIC_USRLOC
96         ret=register_module(usrloc_exports, "built-in", 0);
97         if (ret<0) return ret;
98 #endif
99         
100         return ret;
101 }
102
103
104
105 /* registers a module,  register_f= module register  functions
106  * returns <0 on error, 0 on success */
107 int register_module(struct module_exports* e, char* path, void* handle)
108 {
109         int ret;
110         struct sr_module* mod;
111         
112         ret=-1;
113
114         /* add module to the list */
115         if ((mod=malloc(sizeof(struct sr_module)))==0){
116                 LOG(L_ERR, "load_module: memory allocation failure\n");
117                 ret=E_OUT_OF_MEM;
118                 goto error;
119         }
120         memset(mod,0, sizeof(struct sr_module));
121         mod->path=path;
122         mod->handle=handle;
123         mod->exports=e;
124         mod->next=modules;
125         modules=mod;
126         return 0;
127 error:
128         return ret;
129 }
130
131 /*
132  * per-child initialization
133  */
134 int init_child(int rank)
135 {
136         struct sr_module* t;
137
138         for(t = modules; t; t = t->next) {
139                 if (t->exports->init_child_f) {
140                         if ((t->exports->init_child_f(rank)) < 0) {
141                                 LOG(L_ERR, "init_child(): Initialization of child %d failed\n",
142                                                 rank);
143                                 return -1;
144                         }
145                 }
146         }
147         return 0;
148 }
149
150
151
152 /* returns 0 on success , <0 on error */
153 int load_module(char* path)
154 {
155         void* handle;
156         char* error;
157         struct module_exports* exp;
158         struct sr_module* t;
159         
160         handle=dlopen(path, RTLD_NOW); /* resolve all symbols now */
161         if (handle==0){
162                 LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n",
163                                         path, dlerror() );
164                 goto error;
165         }
166         
167         for(t=modules;t; t=t->next){
168                 if (t->handle==handle){
169                         LOG(L_WARN, "WARNING: load_module: attempting to load the same"
170                                                 " module twice (%s)\n", path);
171                         goto skip;
172                 }
173         }
174         /* launch register */
175         exp = (struct module_exports*)dlsym(handle, "exports");
176         if ( (error =(char*)dlerror())!=0 ){
177                 LOG(L_ERR, "ERROR: load_module: %s\n", error);
178                 goto error1;
179         }
180         if (register_module(exp, path, handle)<0) goto error1;
181         return 0;
182
183 error1:
184         dlclose(handle);
185 error:
186 skip:
187         return -1;
188 }
189
190
191
192 /* searches the module list and returns a pointer to the "name" function or
193  * 0 if not found */
194 cmd_function find_export(char* name, int param_no)
195 {
196         struct sr_module* t;
197         int r;
198
199         for(t=modules;t;t=t->next){
200                 for(r=0;r<t->exports->cmd_no;r++){
201                         if((strcmp(name, t->exports->cmd_names[r])==0)&&
202                                 (t->exports->param_no[r]==param_no) ){
203                                 DBG("find_export: found <%s> in module %s [%s]\n",
204                                                 name, t->exports->name, t->path);
205                                 return t->exports->cmd_pointers[r];
206                         }
207                 }
208         }
209         DBG("find_export: <%s> not found \n", name);
210         return 0;
211 }
212
213
214 void* find_param_export(char* mod, char* name, modparam_t type)
215 {
216         struct sr_module* t;
217         int r;
218
219         for(t = modules; t; t = t->next) {
220                 if (strcmp(mod, t->exports->name) == 0) {
221                         for(r = 0; r < t->exports->par_no; r++) {
222                                 if ((strcmp(name, t->exports->param_names[r]) == 0) &&
223                                     (t->exports->param_types[r] == type)) {
224                                         DBG("find_param_export: found <%s> in module %s [%s]\n",
225                                             name, t->exports->name, t->path);
226                                         return t->exports->param_pointers[r];
227                                 }
228                         }
229                 }
230         }
231         DBG("find_param_export: parameter <%s> or module <%s> not found\n", name, mod);
232         return 0;
233 }
234
235
236
237 /* finds a module, given a pointer to a module function *
238  * returns pointer to module, & if i i!=0, *i=the function index */
239 struct sr_module* find_module(void* f, int *i)
240 {
241         struct sr_module* t;
242         int r;
243         for (t=modules;t;t=t->next){
244                 for(r=0;r<t->exports->cmd_no;r++) 
245                         if (f==(void*)t->exports->cmd_pointers[r]) {
246                                 if (i) *i=r;
247                                 return t;
248                         }
249         }
250         return 0;
251 }
252
253
254
255 void destroy_modules()
256 {
257         struct sr_module* t;
258
259         for(t=modules;t;t=t->next)
260                 if  ((t->exports)&&(t->exports->destroy_f)) t->exports->destroy_f();
261 }
262
263
264 /*
265  * Initialize all loaded modules, the initialization
266  * is done *AFTER* the configuration file is parsed
267  */
268 int init_modules(void)
269 {
270         struct sr_module* t;
271         
272         for(t = modules; t; t = t->next) {
273                 if ((t->exports) && (t->exports->init_f))
274                         if (t->exports->init_f() != 0) {
275                                 LOG(L_ERR, "init_modules(): Error while initializing module %s\n", t->exports->name);
276                                 return -1;
277                         }
278         }
279         return 0;
280 }