00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "sr_module.h"
00043 #include "dprint.h"
00044 #include "error.h"
00045 #include "mem/mem.h"
00046 #include "pt.h"
00047
00048 #include <strings.h>
00049 #include <stdlib.h>
00050 #include <string.h>
00051
00052
00053 struct sr_module* modules=0;
00054
00055
00056
00057
00058 int register_module(struct module_exports* e, char* path, void* handle)
00059 {
00060 int ret;
00061 struct sr_module* mod;
00062
00063 ret=-1;
00064
00065
00066 if ((mod=pkg_malloc(sizeof(struct sr_module)))==0){
00067 LM_ERR("no more pkg memory\n");
00068 ret=E_OUT_OF_MEM;
00069 goto error;
00070 }
00071 memset(mod,0, sizeof(struct sr_module));
00072 mod->path=path;
00073 mod->handle=handle;
00074 mod->exports=e;
00075 mod->next=modules;
00076 modules=mod;
00077
00078
00079 if (e->items) {
00080 LM_DBG("register_pv: %s\n", e->name);
00081 if (register_pvars_mod(e->name, e->items)!=0) {
00082 LM_ERR("failed to register pseudo-variables for module %s\n",
00083 e->name);
00084 pkg_free(mod);
00085 return -1;
00086 }
00087 }
00088
00089 return 0;
00090 error:
00091 return ret;
00092 }
00093
00094 #ifndef DLSYM_PREFIX
00095
00096 #define DLSYM_PREFIX
00097 #endif
00098
00099 static inline int version_control(void *handle, char *path)
00100 {
00101 char **m_ver;
00102 char **m_flags;
00103 char* error;
00104
00105 m_ver=(char **)dlsym(handle, DLSYM_PREFIX "module_version");
00106 if ((error=(char *)dlerror())!=0) {
00107 LM_CRIT("BUG - no version info in module <%s>: %s\n",
00108 path, error );
00109 return 0;
00110 }
00111 m_flags=(char **)dlsym(handle, DLSYM_PREFIX "module_flags");
00112 if ((error=(char *)dlerror())!=0) {
00113 LM_CRIT("BUG - no compile flags info in module <%s>: %s\n",
00114 path, error );
00115 return 0;
00116 }
00117 if (!m_ver || !(*m_ver)) {
00118 LM_CRIT("BUG - no version in module <%s>\n", path );
00119 return 0;
00120 }
00121 if (!m_flags || !(*m_flags)) {
00122 LM_CRIT("BUG - no compile flags in module <%s>\n", path );
00123 return 0;
00124 }
00125
00126 if (strcmp(KAMAILIO_FULL_VERSION, *m_ver)==0){
00127 if (strcmp(KAMAILIO_COMPILE_FLAGS, *m_flags)==0)
00128 return 1;
00129 else {
00130 LM_ERR("module compile flags mismatch for %s "
00131 " \ncore: %s \nmodule: %s\n",
00132 path, KAMAILIO_COMPILE_FLAGS, *m_flags);
00133 return 0;
00134 }
00135 }
00136 LM_ERR("module version mismatch for %s; "
00137 "core: %s; module: %s\n", path, KAMAILIO_FULL_VERSION, *m_ver );
00138 return 0;
00139 }
00140
00141
00142
00143
00144 int sr_load_module(char* path)
00145 {
00146 void* handle;
00147 unsigned int moddlflags;
00148 char* error;
00149 mod_register_function mr;
00150 struct module_exports* exp;
00151 struct sr_module* t;
00152 int dlflags;
00153
00154 handle=dlopen(path, KAMAILIO_DLFLAGS);
00155 if (handle==0){
00156 LM_ERR("could not open module <%s>: %s\n", path, dlerror() );
00157 goto error;
00158 }
00159
00160 for(t=modules;t; t=t->next){
00161 if (t->handle==handle){
00162 LM_WARN("attempting to load the same module twice (%s)\n", path);
00163 goto skip;
00164 }
00165 }
00166
00167 if (!version_control(handle, path)) {
00168 exit(0);
00169 }
00170 mr = (mod_register_function)dlsym(handle, DLSYM_PREFIX "mod_register");
00171 if (((error =(char*)dlerror())==0) && mr) {
00172
00173 if (mr(path, &dlflags, 0, 0)!=0) {
00174 LM_ERR(" %s: mod_register failed\n", path);
00175 goto error1;
00176 }
00177 }
00178
00179 exp = (struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");
00180 if ( (error =(char*)dlerror())!=0 ){
00181 LM_ERR("load_module: %s\n", error);
00182 goto error1;
00183 }
00184 if(exp->dlflags!=DEFAULT_DLFLAGS && exp->dlflags!=KAMAILIO_DLFLAGS) {
00185 moddlflags = exp->dlflags;
00186 dlclose(handle);
00187 LM_DBG("reloading module %s with flags %d\n", path, moddlflags);
00188 handle = dlopen(path, moddlflags);
00189 if (handle==0){
00190 LM_ERR("could not open module <%s>: %s\n", path, dlerror() );
00191 goto error;
00192 }
00193 exp = (struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");
00194 if ( (error =(char*)dlerror())!=0 ){
00195 LM_ERR("failed to load module : %s\n", error);
00196 goto error1;
00197 }
00198 }
00199
00200
00201 if (register_module(exp, path, handle)<0) goto error1;
00202 return 0;
00203
00204 error1:
00205 dlclose(handle);
00206 error:
00207 skip:
00208 return -1;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 cmd_function find_export(char* name, int param_no, int flags)
00218 {
00219 cmd_export_t* cmd;
00220
00221 cmd = find_cmd_export_t(name, param_no, flags);
00222 if (cmd==0)
00223 return 0;
00224 return cmd->function;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234 cmd_export_t* find_cmd_export_t(char* name, int param_no, int flags)
00235 {
00236 struct sr_module* t;
00237 cmd_export_t* cmd;
00238
00239 for(t=modules;t;t=t->next){
00240 for(cmd=t->exports->cmds; cmd && cmd->name; cmd++){
00241 if((strcmp(name, cmd->name)==0)&&
00242 (cmd->param_no==param_no) &&
00243 ((cmd->flags & flags) == flags)
00244 ){
00245 LM_DBG("found <%s>(%d) in module %s [%s]\n",
00246 name, param_no, t->exports->name, t->path);
00247 return cmd;
00248 }
00249 }
00250 }
00251 LM_DBG("<%s> not found \n", name);
00252 return 0;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
00263 {
00264 struct sr_module* t;
00265 cmd_export_t* cmd;
00266
00267 for (t = modules; t; t = t->next) {
00268 if (strcmp(t->exports->name, mod) == 0) {
00269 for (cmd = t->exports->cmds; cmd && cmd->name; cmd++) {
00270 if ((strcmp(name, cmd->name) == 0) &&
00271 (cmd->param_no == param_no) &&
00272 ((cmd->flags & flags) == flags)
00273 ){
00274 LM_DBG("found <%s> in module %s [%s]\n",
00275 name, t->exports->name, t->path);
00276 return cmd->function;
00277 }
00278 }
00279 }
00280 }
00281
00282 LM_DBG("<%s> in module %s not found\n", name, mod);
00283 return 0;
00284 }
00285
00286
00287
00288
00289 void* find_param_export(char* mod, char* name, modparam_t type)
00290 {
00291 struct sr_module* t;
00292 param_export_t* param;
00293
00294 for(t = modules; t; t = t->next) {
00295 if (strcmp(mod, t->exports->name) == 0) {
00296 for(param=t->exports->params;param && param->name ; param++) {
00297 if ((strcmp(name, param->name) == 0) &&
00298 (param->type == type)) {
00299 LM_DBG("found <%s> in module %s [%s]\n",
00300 name, t->exports->name, t->path);
00301 return param->param_pointer;
00302 }
00303 }
00304 }
00305 }
00306 LM_DBG("parameter <%s> or module <%s> not found\n", name, mod);
00307 return 0;
00308 }
00309
00310
00311
00312 void destroy_modules(void)
00313 {
00314 struct sr_module* t, *foo;
00315
00316 t=modules;
00317 while(t) {
00318 foo=t->next;
00319 if ((t->exports)&&(t->exports->destroy_f)) {
00320 LM_DBG("shutting down module %s\n", t->exports->name);
00321 t->exports->destroy_f();
00322 }
00323 pkg_free(t);
00324 t=foo;
00325 }
00326 modules=0;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 static int init_mod_child( struct sr_module* m, int rank, char *type )
00336 {
00337 if (m) {
00338
00339
00340 if (init_mod_child(m->next, rank, type)!=0)
00341 return -1;
00342
00343 if (m->exports && m->exports->init_child_f) {
00344 LM_DBG("initializing module type=%s, rank=%d, module=%s, pid=%d\n",
00345 type, rank, m->exports->name, getpid());
00346 if (m->exports->init_child_f(rank)<0) {
00347 LM_ERR("failed to initializing module %s, rank %d\n",
00348 m->exports->name,rank);
00349 return -1;
00350 } else {
00351
00352 return 0;
00353 }
00354 }
00355
00356
00357 return 0;
00358 } else {
00359
00360 return 0;
00361 }
00362 }
00363
00364
00365
00366
00367
00368 int init_child(int rank)
00369 {
00370 char* type;
00371
00372 type = 0;
00373
00374 switch(rank) {
00375 case PROC_MAIN: type = "PROC_MAIN"; break;
00376 case PROC_TIMER: type = "PROC_TIMER"; break;
00377 case PROC_TCP_MAIN: type = "PROC_TCP_MAIN"; break;
00378 }
00379
00380 if (!type) {
00381 if (rank>0)
00382 type = "CHILD";
00383 else
00384 type = "UNKNOWN";
00385 }
00386
00387 return init_mod_child(modules, rank, type);
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397 static int init_mod( struct sr_module* m )
00398 {
00399 if (m) {
00400
00401
00402
00403 if (init_mod(m->next)!=0) return -1;
00404 if (m->exports==0)
00405 return 0;
00406 if (m->exports->init_f) {
00407 LM_INFO("initializing module %s\n", m->exports->name);
00408 if (m->exports->init_f()!=0) {
00409 LM_ERR("failed to initialize"
00410 " module %s\n", m->exports->name);
00411 return -1;
00412 }
00413 }
00414
00415 #ifdef STATISTICS
00416 if (m->exports->stats) {
00417 LM_DBG("registering stats for %s\n", m->exports->name);
00418 if (register_module_stats(m->exports->name,m->exports->stats)!=0) {
00419 LM_ERR("failed to registering "
00420 "statistics for module %s\n", m->exports->name);
00421 return -1;
00422 }
00423 }
00424 #endif
00425
00426 if (m->exports->mi_cmds) {
00427 LM_DBG("register MI for %s\n", m->exports->name);
00428 if (register_mi_mod(m->exports->name,m->exports->mi_cmds)!=0) {
00429 LM_ERR("failed to register MI functions for module %s\n",
00430 m->exports->name);
00431 }
00432 }
00433
00434
00435 return 0;
00436 } else {
00437
00438 return 0;
00439 }
00440 }
00441
00442
00443
00444
00445
00446 int init_modules(void)
00447 {
00448 return init_mod(modules);
00449 }
00450
00451
00452 int module_loaded(char *name)
00453 {
00454 struct sr_module *currentMod;
00455
00456 for (currentMod=modules; currentMod; currentMod=currentMod->next) {
00457 if (strcasecmp(name,currentMod->exports->name)==0) {
00458 return 1;
00459 }
00460
00461 }
00462
00463 return 0;
00464 }
00465
00466
00467
00468 int count_module_procs(void)
00469 {
00470 struct sr_module *m;
00471 unsigned int cnt;
00472 unsigned int n;
00473
00474 for( m=modules,cnt=0 ; m ; m=m->next) {
00475 if (m->exports->procs) {
00476 for( n=0 ; m->exports->procs[n].name ; n++)
00477 if (m->exports->procs[n].function)
00478 cnt += m->exports->procs[n].no;
00479 }
00480 }
00481 LM_DBG("modules require %d extra processes\n",cnt);
00482 return cnt;
00483 }
00484
00485
00486 int start_module_procs(void)
00487 {
00488 struct sr_module *m;
00489 unsigned int n;
00490 unsigned int l;
00491 pid_t x;
00492
00493 for( m=modules ; m ; m=m->next) {
00494 if (m->exports->procs==NULL)
00495 continue;
00496 for( n=0 ; m->exports->procs[n].name ; n++) {
00497 if ( !m->exports->procs[n].no || !m->exports->procs[n].function )
00498 continue;
00499
00500 if (m->exports->procs[n].pre_fork_function)
00501 if (m->exports->procs[n].pre_fork_function()!=0) {
00502 LM_ERR("pre-fork function failed for process \"%s\" "
00503 "in module %s\n",
00504 m->exports->procs[n].name, m->exports->name);
00505 return -1;
00506 }
00507
00508 for ( l=0; l<m->exports->procs[n].no ; l++) {
00509 LM_DBG("forking process \"%s\"/%d for module %s\n",
00510 m->exports->procs[n].name, l, m->exports->name);
00511 x = internal_fork(m->exports->procs[n].name);
00512 if (x<0) {
00513 LM_ERR("failed to fork process \"%s\"/%d for module %s\n",
00514 m->exports->procs[n].name, l, m->exports->name);
00515 return -1;
00516 } else if (x==0) {
00517
00518 m->exports->procs[n].function(l);
00519
00520 exit(0);
00521 }
00522 }
00523
00524 if (m->exports->procs[n].post_fork_function)
00525 if (m->exports->procs[n].post_fork_function()!=0) {
00526 LM_ERR("post-fork function failed for process \"%s\" "
00527 "in module %s\n",
00528 m->exports->procs[n].name, m->exports->name);
00529 return -1;
00530 }
00531 }
00532 }
00533
00534 return 0;
00535 }