Coverage Report

Created: 2026-04-12 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensips/sr_module.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2001-2003 FhG Fokus
3
 *
4
 * This file is part of opensips, a free SIP server.
5
 *
6
 * opensips is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version
10
 *
11
 * opensips is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19
 *
20
 * History:
21
 * --------
22
 *  2003-03-10  switched to new module_exports format: updated find_export,
23
 *               find_export_param, find_module (andrei)
24
 *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
25
 *  2003-03-19  Support for flags in find_export (janakj)
26
 *  2003-03-29  cleaning pkg_mallocs introduced (jiri)
27
 *  2003-04-24  module version checking introduced (jiri)
28
 *  2004-09-19  compile flags are checked too (andrei)
29
 *  2006-03-02  added find_cmd_export_t(), killed find_exportp() and
30
 *              find_module() (bogdan)
31
 *  2006-11-28  added module_loaded() (Jeffrey Magder - SOMA Networks)
32
 */
33
34
/*!
35
 * \file
36
 * \brief modules/plug-in structures declarations
37
 */
38
39
40
#include "sr_module.h"
41
#include "dprint.h"
42
#include "error.h"
43
#include "globals.h"
44
#include "mem/mem.h"
45
#include "pt.h"
46
#include "ut.h"
47
#include "daemonize.h"
48
49
#include <strings.h>
50
#include <stdlib.h>
51
#include <string.h>
52
53
#include <sys/types.h>
54
#include <sys/stat.h>
55
#include <unistd.h>
56
57
#include "net/api_proto.h"
58
#include "net/proto_udp/proto_udp_handler.h"
59
#include "net/proto_tcp/proto_tcp_handler.h"
60
61
#include "test/unit_tests.h"
62
63
#include "libgen.h"
64
65
struct sr_module* modules=0;
66
int modload_check_rev=1;
67
68
#ifdef STATIC_EXEC
69
  extern struct module_exports exec_exports;
70
#endif
71
#ifdef STATIC_TM
72
  extern struct module_exports tm_exports;
73
#endif
74
75
#ifdef STATIC_MAXFWD
76
  extern struct module_exports maxfwd_exports;
77
#endif
78
79
#ifdef STATIC_AUTH
80
  extern struct module_exports auth_exports;
81
#endif
82
83
#ifdef STATIC_RR
84
  extern struct module_exports rr_exports;
85
#endif
86
87
#ifdef STATIC_USRLOC
88
  extern struct module_exports usrloc_exports;
89
#endif
90
91
#ifdef STATIC_SL
92
  extern struct module_exports sl_exports;
93
#endif
94
95
0
#define MPATH_LEN 256
96
struct mpath {
97
  char buf[MPATH_LEN + 1];
98
  int len;
99
  struct mpath *next;
100
};
101
static struct mpath *mpaths, *last_mpath;
102
103
/* initializes statically built (compiled in) modules*/
104
int register_builtin_modules(void)
105
0
{
106
0
  int ret;
107
108
0
  ret=0;
109
#ifdef STATIC_TM
110
  ret=register_module(&tm_exports,"built-in", 0);
111
  if (ret<0) return ret;
112
#endif
113
114
#ifdef STATIC_EXEC
115
  ret=register_module(&exec_exports,"built-in", 0);
116
  if (ret<0) return ret;
117
#endif
118
119
#ifdef STATIC_MAXFWD
120
  ret=register_module(&maxfwd_exports, "built-in", 0);
121
  if (ret<0) return ret;
122
#endif
123
124
#ifdef STATIC_AUTH
125
  ret=register_module(&auth_exports, "built-in", 0);
126
  if (ret<0) return ret;
127
#endif
128
129
#ifdef STATIC_RR
130
  ret=register_module(&rr_exports, "built-in", 0);
131
  if (ret<0) return ret;
132
#endif
133
134
#ifdef STATIC_USRLOC
135
  ret=register_module(&usrloc_exports, "built-in", 0);
136
  if (ret<0) return ret;
137
#endif
138
139
#ifdef STATIC_SL
140
  ret=register_module(&sl_exports, "built-in", 0);
141
  if (ret<0) return ret;
142
#endif
143
144
0
  return ret;
145
0
}
146
147
/* registers a module,  register_f= module register  functions
148
 * returns <0 on error, 0 on success */
149
int register_module(const struct module_exports* e, char* path, void* handle)
150
0
{
151
0
  int ret;
152
0
  struct sr_module* mod;
153
154
0
  ret=-1;
155
156
  /* add module to the list */
157
0
  if ((mod=pkg_malloc(sizeof(struct sr_module)))==0){
158
0
    LM_ERR("no more pkg memory\n");
159
0
    ret=E_OUT_OF_MEM;
160
0
    goto error;
161
0
  }
162
0
  memset(mod,0, sizeof(struct sr_module));
163
0
  mod->path=path;
164
0
  mod->handle=handle;
165
0
  mod->exports=e;
166
0
  mod->next=modules;
167
0
  modules=mod;
168
169
  /* register module pseudo-variables */
170
0
  if (e->items) {
171
0
    LM_DBG("register_pv: %s\n", e->name);
172
0
    if (register_pvars_mod(e->name, e->items)!=0) {
173
0
      LM_ERR("failed to register pseudo-variables for module %s\n",
174
0
        e->name);
175
0
      pkg_free(mod);
176
0
      return -1;
177
0
    }
178
0
  }
179
180
  /* register module transformations */
181
0
  if (e->trans) {
182
0
    LM_DBG("register_trans: %s\n", e->name);
183
0
    if (register_trans_mod(e->name, e->trans) !=0) {
184
0
      LM_ERR("failed to register transformations for module %s\n",
185
0
        e->name);
186
0
      pkg_free(mod);
187
0
      return -1;
188
0
    }
189
0
  }
190
191
  /* register all module dependencies */
192
0
  if (e->deps) {
193
0
    ret = add_module_dependencies(mod);
194
0
    if (ret != 0) {
195
0
      LM_CRIT("failed to add module dependencies [%d]\n", ret);
196
0
      return ret;
197
0
    }
198
0
  }
199
200
0
  return 0;
201
0
error:
202
0
  return ret;
203
0
}
204
205
206
static inline int version_control(const struct module_exports* exp, char *path)
207
0
{
208
0
  const char *hint = "(try `make clean all modules' and reinstall everything)";
209
0
  const char *scm_nm = "version control system";
210
0
  int len;
211
0
  if ( !exp->ver_info.version ) {
212
0
    LM_CRIT("BUG - version not defined in module <%s>\n", path );
213
0
    return 0;
214
0
  }
215
0
  if ( !exp->ver_info.compile_flags ) {
216
0
    LM_CRIT("BUG - compile flags not defined in module <%s>\n", path );
217
0
    return 0;
218
0
  }
219
0
  if ( !exp->ver_info.scm.type ) {
220
0
    LM_CRIT("BUG - %s type not defined in module <%s> %s\n",
221
0
      scm_nm, path, hint );
222
0
    return 0;
223
0
  }
224
0
  if ( !exp->ver_info.scm.rev ) {
225
0
    LM_CRIT("BUG - %s revision not defined in module <%s> %s\n",
226
0
      scm_nm, path, hint );
227
0
    return 0;
228
0
  }
229
230
0
  if (strcmp(OPENSIPS_FULL_VERSION, exp->ver_info.version)!=0) {
231
0
    LM_CRIT("module version mismatch for %s; core: %s; module: %s\n",
232
0
      exp->name, OPENSIPS_FULL_VERSION, exp->ver_info.version );
233
0
    return 0;
234
0
  }
235
0
  if (strcmp(OPENSIPS_COMPILE_FLAGS, exp->ver_info.compile_flags)!=0) {
236
0
    LM_CRIT("module compile flags mismatch for %s "
237
0
      " \ncore: %s \nmodule: %s\n", exp->name,
238
0
      OPENSIPS_COMPILE_FLAGS, exp->ver_info.compile_flags);
239
0
    return 0;
240
0
  }
241
0
  if (strcmp(core_scm_ver.type, exp->ver_info.scm.type) != 0) {
242
0
    LM_CRIT("module %s type mismatch for %s "
243
0
      " \ncore: %s \nmodule: %s %s\n", scm_nm, exp->name,
244
0
      core_scm_ver.type, exp->ver_info.scm.type, hint);
245
0
    return 0;
246
0
  }
247
0
  if (modload_check_rev) {
248
0
    len = (strlen(core_scm_ver.rev) < strlen(exp->ver_info.scm.rev))?
249
0
      strlen(core_scm_ver.rev): strlen(exp->ver_info.scm.rev);
250
0
    if (strncmp(core_scm_ver.rev, exp->ver_info.scm.rev, len) != 0) {
251
0
      LM_CRIT("module %s revision mismatch for %s "
252
0
          " \ncore: %s \nmodule: %s %s\n", scm_nm, exp->name,
253
0
          core_scm_ver.rev, exp->ver_info.scm.rev, hint);
254
0
      return 0;
255
0
    }
256
0
  }
257
0
  return 1;
258
0
}
259
260
261
262
/* returns 0 on success , <0 on error */
263
int sr_load_module(char* path)
264
0
{
265
0
  void* handle;
266
0
  unsigned int moddlflags;
267
0
  char* error;
268
0
  const struct module_exports* exp;
269
0
  struct sr_module* t;
270
271
  /* load module */
272
0
  handle=dlopen(path, OPENSIPS_DLFLAGS); /* resolve all symbols now */
273
0
  if (handle==0){
274
0
    LM_ERR("could not open module <%s>: %s\n", path, dlerror() );
275
0
    goto error;
276
0
  }
277
278
  /* check for duplicates */
279
0
  for(t=modules;t; t=t->next){
280
0
    if (t->handle==handle){
281
0
      LM_WARN("attempting to load the same module twice (%s)\n", path);
282
0
      goto skip;
283
0
    }
284
0
  }
285
286
  /* import module interface */
287
0
  exp = (const struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");
288
0
  if ( (error =(char*)dlerror())!=0 ){
289
0
    LM_ERR("load_module: %s\n", error);
290
0
    goto error1;
291
0
  }
292
  /* version control */
293
0
  if (!version_control(exp, path)) {
294
0
    exit(1);
295
0
  }
296
0
  if(exp->dlflags!=DEFAULT_DLFLAGS && exp->dlflags!=OPENSIPS_DLFLAGS) {
297
0
    moddlflags = exp->dlflags;
298
0
    dlclose(handle);
299
0
    LM_DBG("reloading module %s with flags %d\n", path, moddlflags);
300
0
    handle = dlopen(path, moddlflags);
301
0
    if (handle==0){
302
0
      LM_ERR("could not open module <%s>: %s\n", path, dlerror() );
303
0
      goto error;
304
0
    }
305
0
    exp = (const struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");
306
0
    if ( (error =(char*)dlerror())!=0 ){
307
0
      LM_ERR("failed to load module : %s\n", error);
308
0
      goto error1;
309
0
    }
310
0
  }
311
312
0
  if (exp->load_f && exp->load_f() < 0) {
313
0
    LM_ERR("could not initialize module %s\n", path);
314
0
    goto error1;
315
0
  }
316
317
  /* launch register */
318
0
  if (register_module(exp, path, handle)<0) goto error1;
319
0
  return 0;
320
321
0
error1:
322
0
  dlclose(handle);
323
0
error:
324
0
skip:
325
0
  return -1;
326
0
}
327
328
/* built-in modules with static exports */
329
struct static_modules {
330
  str name;
331
  struct module_exports *exp;
332
};
333
334
struct static_modules static_modules[] = {
335
  { str_init(PROTO_PREFIX "udp"), &proto_udp_exports },
336
  { str_init(PROTO_PREFIX "tcp"), &proto_tcp_exports },
337
};
338
339
static int load_static_module(char *path)
340
0
{
341
0
  int len = strlen(path);
342
0
  char *end = path + len;
343
0
  struct sr_module* t;
344
0
  unsigned int i;
345
346
  /* eliminate the .so, if found */
347
0
  if (len > 3 && strncmp(end - 3, ".so", 3)==0) {
348
0
    end -= 3;
349
0
    len -= 3;
350
0
  }
351
  /* we check whether the protocol is found within the static_modules */
352
0
  for (i = 0; i < (sizeof(static_modules)/sizeof(static_modules[0])); i++) {
353
0
    if (len >= static_modules[i].name.len &&
354
        /* the path ends in the module's name */
355
0
        memcmp(end - static_modules[i].name.len,
356
0
          static_modules[i].name.s, static_modules[i].name.len) == 0 &&
357
        /* check if the previous char is '/' or nothing */
358
0
        (len == static_modules[i].name.len || (*(end-len-1) == '/'))) {
359
360
      /* yey, found the module - check if it was loaded twice */
361
0
      for(t=modules;t; t=t->next){
362
0
        if (t->handle==static_modules[i].exp){
363
0
          LM_WARN("attempting to load the same module twice (%s)\n", path);
364
0
          return 0;
365
0
        }
366
0
      }
367
368
      /* version control */
369
0
      if (!version_control(static_modules[i].exp, path)) {
370
0
        exit(0);
371
0
      }
372
373
      /* launch register */
374
0
      if (register_module(static_modules[i].exp, path, static_modules[i].exp)<0)
375
0
        return -1;
376
0
      return 0;
377
0
    }
378
0
  }
379
380
0
  return -1;
381
0
}
382
383
void add_mpath(const char *new_mpath)
384
0
{
385
0
  struct mpath *nmpath;
386
0
  int len = strlen(new_mpath);
387
0
  if (len >= MPATH_LEN) {
388
0
    LM_ERR("mpath %s too long!\n", new_mpath);
389
0
    return;
390
0
  }
391
0
  nmpath = pkg_malloc(sizeof *nmpath);
392
0
  if (!nmpath) {
393
0
    LM_ERR("could not allocate space for %s mpath!\n", new_mpath);
394
0
    return;
395
0
  }
396
0
  memset(nmpath, 0, sizeof *nmpath);
397
  /* link it in the list */
398
0
  if (last_mpath)
399
0
    last_mpath->next = nmpath;
400
0
  else
401
0
    mpaths = nmpath;
402
0
  last_mpath = nmpath;
403
0
  memcpy(nmpath->buf, new_mpath, len);
404
0
  nmpath->len = len;
405
0
  if (nmpath->len == 0 || nmpath->buf[nmpath->len - 1] != '/') {
406
0
    nmpath->buf[nmpath->len] = '/';
407
0
    nmpath->len++;
408
0
  }
409
0
  nmpath->buf[nmpath->len] = '\0';
410
0
}
411
412
static struct {
413
 char *module;
414
 char *name;
415
 unsigned int flags;
416
} module_warnings[] = {
417
  { "rabbitmq", "'rabbitmq' module has been dropped - please use 'event_rabbitmq' instead!", MOD_WARN_EXIT },
418
  { "event_route", "'event_route' module has been integrated in core file. You no longer need to load the module.", MOD_WARN_SKIP }
419
};
420
421
/* returns 0 on success , <0 on error */
422
int load_module(char* name)
423
0
{
424
0
  int i_tmp, len;
425
0
  struct stat statf;
426
0
  struct mpath *mp;
427
0
  int module_warnings_len;
428
0
  char *base_name;
429
430
0
  base_name = basename(name);
431
0
  len = strlen(base_name);
432
0
  if (strstr(base_name, ".so"))
433
0
    len -= 3;
434
435
0
  module_warnings_len = sizeof(module_warnings) / sizeof(module_warnings[0]);
436
437
0
  for (i_tmp = 0; i_tmp < module_warnings_len; i_tmp++) {
438
0
    if (strncmp(base_name, module_warnings[i_tmp].module, len) == 0) {
439
0
      switch (module_warnings[i_tmp].flags)
440
0
      {
441
0
        case MOD_WARN_EXIT:
442
0
          LM_ERR("%s\n", module_warnings[i_tmp].name);
443
0
          return -1;
444
445
0
        case MOD_WARN_SKIP:
446
0
          LM_WARN("%s\n", module_warnings[i_tmp].name);
447
0
          return 0;
448
449
0
        default:
450
0
          break;
451
0
      }
452
0
    }
453
0
  }
454
455
  /* if this is a static module, load it directly */
456
0
  if (load_static_module(name) == 0)
457
0
    return 0;
458
459
0
  if (*name=='/' || mpaths==NULL) {
460
0
    LM_DBG("loading module %s\n", name);
461
0
    if (sr_load_module(name)!=0){
462
0
      LM_ERR("failed to load module\n");
463
0
      return -1;
464
0
    }
465
0
    return 0;
466
0
  }
467
0
  for (mp = mpaths; mp; mp = mp->next) {
468
0
    len = strlen(name);
469
0
    if (len + mp->len >= MPATH_LEN)
470
0
      continue;
471
0
    memcpy(mp->buf + mp->len, name, len);
472
0
    mp->buf[mp->len + len] = '\0';
473
0
    if (stat(mp->buf, &statf) == -1 || S_ISDIR(statf.st_mode)) {
474
0
      i_tmp = strlen(mp->buf);
475
0
      if(strchr(name, '/')==NULL &&
476
0
        strncmp(mp->buf+i_tmp-3, ".so", 3)==0)
477
0
      {
478
0
        if(i_tmp+len<MPATH_LEN)
479
0
        {
480
0
          strcpy(mp->buf+i_tmp-3, "/");
481
0
          strcpy(mp->buf+i_tmp-2, name);
482
0
          if (stat(mp->buf, &statf) == -1) {
483
0
            mp->buf[mp->len]='\0';
484
0
            LM_DBG("module '%s' not found in '%s'\n",
485
0
                name, mp->buf);
486
0
            goto next;
487
0
          }
488
0
        } else {
489
0
          LM_DBG("failed to load module '%s' from '%s' - path too long\n", name, mp->buf);
490
0
          goto next;
491
0
        }
492
0
      } else {
493
0
        goto next;
494
0
      }
495
0
    }
496
0
    LM_DBG("trying module %s\n", mp->buf);
497
0
    if (sr_load_module(mp->buf)!=0) {
498
0
      LM_DBG("failed to load module '%s'\n", mp->buf);
499
0
    } else {
500
0
      mp->buf[mp->len]='\0';
501
0
      return 0;
502
0
    }
503
0
next:
504
0
    mp->buf[mp->len]='\0';
505
0
  }
506
0
  LM_ERR("failed to load module '%s' - not found\n", name);
507
0
  return -1;
508
0
}
509
510
511
512
/* searches the module list and returns pointer to the "name" function or
513
 * 0 if not found
514
 * flags parameter is OR value of all flags that must match
515
 */
516
cmd_function find_export(const char* name, int flags)
517
0
{
518
0
  const cmd_export_t* cmd;
519
520
0
  cmd = find_mod_cmd_export_t(name, flags);
521
0
  if (cmd==0)
522
0
    return 0;
523
524
0
  return cmd->function;
525
0
}
526
527
528
529
/* Searches the module list for the "name" cmd_export_t structure.
530
 */
531
const cmd_export_t* find_mod_cmd_export_t(const char* name, int flags)
532
0
{
533
0
  struct sr_module* t;
534
0
  const cmd_export_t* cmd;
535
536
0
  for(t=modules;t;t=t->next){
537
0
    for(cmd=t->exports->cmds; cmd && cmd->name; cmd++){
538
0
      if((strcmp(name, cmd->name)==0)&&((cmd->flags & flags) == flags)){
539
0
        LM_DBG("found <%s> in module %s [%s]\n",
540
0
            name, t->exports->name, t->path);
541
0
        return cmd;
542
0
      }
543
0
    }
544
0
  }
545
546
0
  LM_DBG("<%s> not found \n", name);
547
0
  return 0;
548
0
}
549
550
551
552
/* Searches the module list for the "name" acmd_export_t structure.
553
 */
554
const acmd_export_t* find_mod_acmd_export_t(const char* name)
555
0
{
556
0
  struct sr_module* t;
557
0
  const acmd_export_t* cmd;
558
559
0
  for(t=modules;t;t=t->next){
560
0
    for(cmd=t->exports->acmds; cmd && cmd->name; cmd++){
561
0
      if((strcmp(name, cmd->name)==0)){
562
0
        LM_DBG("found <%s> in module %s [%s]\n",
563
0
            name, t->exports->name, t->path);
564
0
        return cmd;
565
0
      }
566
0
    }
567
0
  }
568
0
  LM_DBG("async <%s> not found \n", name);
569
0
  return 0;
570
0
}
571
572
/*
573
 * searches the module list and returns pointer to "name" function in module
574
 * "mod" or 0 if not found
575
 * flags parameter is OR value of all flags that must match
576
 */
577
cmd_function find_mod_export(const char* mod, const char* name, int flags)
578
0
{
579
0
  struct sr_module* t;
580
0
  const cmd_export_t* cmd;
581
582
0
  for (t = modules; t; t = t->next) {
583
0
    if (strcmp(t->exports->name, mod) == 0) {
584
0
      for (cmd = t->exports->cmds;  cmd && cmd->name; cmd++) {
585
0
        if ((strcmp(name, cmd->name) == 0) &&
586
0
            ((cmd->flags & flags) == flags)
587
0
           ){
588
0
          LM_DBG("found <%s> in module %s [%s]\n",
589
0
              name, t->exports->name, t->path);
590
0
          return cmd->function;
591
0
        }
592
0
      }
593
0
    }
594
0
  }
595
596
0
  LM_DBG("<%s> in module %s not found\n", name, mod);
597
0
  return 0;
598
0
}
599
600
601
602
void* find_param_export(const char* mod, const char* name, modparam_t type)
603
0
{
604
0
  struct sr_module* t;
605
0
  const param_export_t* param;
606
607
0
  for(t = modules; t; t = t->next) {
608
0
    if (strcmp(mod, t->exports->name) == 0) {
609
0
      for(param=t->exports->params;param && param->name ; param++) {
610
0
        if ((strcmp(name, param->name) == 0) &&
611
0
            (param->type == type)) {
612
0
          LM_DBG("found <%s> in module %s [%s]\n",
613
0
            name, t->exports->name, t->path);
614
0
          return param->param_pointer;
615
0
        }
616
0
      }
617
0
    }
618
0
  }
619
0
  LM_DBG("parameter <%s> or module <%s> not found\n", name, mod);
620
0
  return 0;
621
0
}
622
623
624
static void destroy_module(struct sr_module *m, int skip_others)
625
0
{
626
0
  struct sr_module_dep *dep;
627
628
0
  if (!m)
629
0
    return;
630
631
  /* destroy the modules in script load order using backwards iteration */
632
0
  if (!skip_others)
633
0
    destroy_module(m->next, 0);
634
635
0
  if (m->destroy_done || !m->exports)
636
0
    return;
637
638
  /* make sure certain modules get destroyed before this one */
639
0
  for (dep = m->sr_deps_destroy; dep; dep = dep->next)
640
0
    if (!dep->mod->destroy_done)
641
0
      destroy_module(dep->mod, 1);
642
643
0
  if (m->init_done && m->exports->destroy_f)
644
0
    m->exports->destroy_f();
645
646
0
  m->destroy_done = 1;
647
0
}
648
649
650
void destroy_modules(void)
651
0
{
652
0
  struct sr_module *mod, *aux;
653
654
0
  destroy_module(modules, 0);
655
0
  free_module_dependencies(modules);
656
657
0
  mod = modules;
658
0
  while (mod) {
659
0
    aux = mod;
660
0
    mod = mod->next;
661
0
    pkg_free(aux);
662
0
  }
663
0
}
664
665
666
/* recursive module child initialization; (recursion is used to
667
   process the module linear list in the same order in
668
   which modules are loaded in config file
669
*/
670
671
static int init_mod_child( struct sr_module* m, int rank, char *type,
672
                          int skip_others)
673
0
{
674
0
  struct sr_module_dep *dep;
675
676
0
  if (!m || m->init_child_done)
677
0
    return 0;
678
679
  /* iterate through the list; if error occurs,
680
     propagate it up the stack */
681
0
  if (!skip_others && init_mod_child(m->next, rank, type, 0) != 0)
682
0
    return -1;
683
684
0
  for (dep = m->sr_deps_cinit; dep; dep = dep->next)
685
0
    if (!dep->mod->init_child_done)
686
0
      if (init_mod_child(dep->mod, rank, type, 1) != 0)
687
0
        return -1;
688
689
0
  if (m->init_child_done)
690
0
    return 0;
691
692
0
  if (m->exports && m->exports->init_child_f) {
693
0
    LM_DBG("type=%s, rank=%d, module=%s\n",
694
0
        type, rank, m->exports->name);
695
0
    if (m->exports->init_child_f(rank)<0) {
696
0
      LM_ERR("failed to initializing module %s, rank %d\n",
697
0
        m->exports->name,rank);
698
0
      return -1;
699
0
    }
700
0
  }
701
702
0
  m->init_child_done = 1;
703
0
  return 0;
704
0
}
705
706
707
/*
708
 * per-child initialization
709
 */
710
int init_child(int rank)
711
0
{
712
0
  char* type;
713
0
  int rc;
714
715
0
  type = 0;
716
717
0
  switch(rank) {
718
0
  case PROC_MAIN:     type = "PROC_MAIN";     break;
719
0
  case PROC_TIMER:    type = "PROC_TIMER";    break;
720
0
  case PROC_MODULE:   type = "PROC_MODULE";   break;
721
0
  case PROC_TCP_MAIN: type = "PROC_TCP_MAIN"; break;
722
0
  }
723
724
0
  if (!type) {
725
0
    if (rank>0)
726
0
      type = "CHILD";
727
0
    else
728
0
      type = "UNKNOWN";
729
0
  }
730
731
0
  rc = init_mod_child(modules, rank, type, 0);
732
0
  ready_time = time(NULL);
733
0
  ready_delay = ready_time - startup_time;
734
735
0
  return rc;
736
0
}
737
738
739
740
/* recursive module initialization; (recursion is used to
741
   process the module linear list in the same order in
742
   which modules are loaded in config file
743
*/
744
745
static int init_mod( struct sr_module* m, int skip_others)
746
0
{
747
0
  struct sr_module_dep *dep;
748
749
0
  if (m) {
750
    /* iterate through the list; if error occurs,
751
       propagate it up the stack
752
     */
753
0
    if (!skip_others && init_mod(m->next, 0) != 0)
754
0
      return -1;
755
756
    /* our module might have been already init'ed through dependencies! */
757
0
    if (m->init_done)
758
0
      return 0;
759
760
0
    if (!m->exports)
761
0
      return 0;
762
763
    /* make sure certain modules get loaded before this one */
764
0
    for (dep = m->sr_deps_init; dep; dep = dep->next) {
765
0
      if (!dep->mod->init_done)
766
0
        if (init_mod(dep->mod, 1) != 0)
767
0
          return -1;
768
0
    }
769
770
0
    if (m->exports->init_f) {
771
0
      LM_DBG("initializing module %s\n", m->exports->name);
772
0
      if (m->exports->init_f()!=0) {
773
0
        LM_ERR("failed to initialize module %s\n", m->exports->name);
774
0
        return -1;
775
0
      }
776
0
    }
777
778
0
    m->init_done = 1;
779
780
    /* no init function -- proceed further */
781
0
#ifdef STATISTICS
782
0
    if (m->exports->stats) {
783
0
      LM_DBG("registering stats for %s\n", m->exports->name);
784
0
      if (register_module_stats(m->exports->name,m->exports->stats)!=0) {
785
0
        LM_ERR("failed to registering "
786
0
          "statistics for module %s\n", m->exports->name);
787
0
        return -1;
788
0
      }
789
0
    }
790
0
#endif
791
    /* register MI functions */
792
0
    if (m->exports->mi_cmds) {
793
0
      LM_DBG("register MI for %s\n", m->exports->name);
794
0
      if (register_mi_mod(m->exports->name,m->exports->mi_cmds)!=0) {
795
0
        LM_ERR("failed to register MI functions for module %s\n",
796
0
          m->exports->name);
797
0
      }
798
0
    }
799
800
    /* proceed with success */
801
0
    return 0;
802
0
  } else {
803
    /* end of list */
804
0
    return 0;
805
0
  }
806
0
}
807
808
/*
809
 * Initialize all loaded modules, the initialization
810
 * is done *AFTER* the configuration file is parsed
811
 */
812
int init_modules(void)
813
0
{
814
0
  struct sr_module *currentMod;
815
0
  int ret;
816
817
0
  if (testing_framework)
818
0
    init_unit_tests();
819
820
  /* pre-initialize all modules */
821
0
  for (currentMod=modules; currentMod; currentMod=currentMod->next) {
822
0
    if (currentMod->exports->preinit_f == NULL)
823
0
      continue;
824
0
    ret = currentMod->exports->preinit_f();
825
0
    if (ret < 0) {
826
0
      LM_ERR("could not pre-initialize module %s!\n",
827
0
          currentMod->exports->name);
828
0
      return ret;
829
0
    }
830
0
  }
831
832
0
  return init_mod(modules, 0);
833
0
}
834
835
836
/* Returns 1 if the module with name 'name' is loaded, and zero otherwise. */
837
int module_loaded(char *name)
838
0
{
839
0
  struct sr_module *currentMod;
840
841
0
  for (currentMod=modules; currentMod; currentMod=currentMod->next) {
842
0
    if (strcasecmp(name,currentMod->exports->name)==0) {
843
0
      return 1;
844
0
    }
845
846
0
  }
847
848
0
  return 0;
849
0
}
850
851
852
void *get_mod_handle(const char *name)
853
0
{
854
0
  struct sr_module *mod;
855
856
0
  for (mod = modules; mod; mod = mod->next)
857
0
    if (!strcasecmp(name, mod->exports->name))
858
0
      return mod->handle;
859
860
0
  return NULL;
861
0
}
862
863
864
/* Counts the additional the number of processes requested by modules */
865
int count_module_procs(int flags)
866
0
{
867
0
  struct sr_module *m;
868
0
  unsigned int cnt;
869
0
  unsigned int n;
870
871
0
  for( m=modules,cnt=0 ; m ; m=m->next) {
872
0
    if (m->exports->procs==NULL)
873
0
      continue;
874
0
    for ( n=0 ; m->exports->procs[n].name ; n++) {
875
0
      if (!m->exports->procs[n].no || !m->exports->procs[n].function)
876
0
        continue;
877
878
0
      if (!flags || (m->exports->procs[n].flags & flags))
879
0
        cnt+=m->exports->procs[n].no;
880
0
    }
881
0
  }
882
0
  LM_DBG("modules require %d extra processes\n",cnt);
883
0
  return cnt;
884
0
}
885
886
887
int start_module_procs(void)
888
0
{
889
0
  struct sr_module *m;
890
0
  unsigned int n;
891
0
  unsigned int l;
892
0
  unsigned int flags;
893
0
  int x;
894
895
0
  for( m=modules ; m ; m=m->next) {
896
0
    if (m->exports->procs==NULL)
897
0
      continue;
898
0
    for( n=0 ; m->exports->procs[n].name ; n++) {
899
0
      if ( !m->exports->procs[n].no || !m->exports->procs[n].function )
900
0
        continue;
901
      /* run pre-fork function */
902
0
      if (m->exports->procs[n].pre_fork_function)
903
0
        if (m->exports->procs[n].pre_fork_function()!=0) {
904
0
          LM_ERR("pre-fork function failed for process \"%s\" "
905
0
            "in module %s\n",
906
0
            m->exports->procs[n].name, m->exports->name);
907
0
          return -1;
908
0
        }
909
      /* fork the processes */
910
0
      for ( l=0; l<m->exports->procs[n].no ; l++) {
911
0
        LM_DBG("forking process \"%s\"/%d for module %s\n",
912
0
          m->exports->procs[n].name, l, m->exports->name);
913
        /* conver the module proc flags to internal proc flgas
914
         * NOTE that the PROC_FLAG_NEEDS_SCRIPT automatically
915
         * assumes PROC_FLAG_HAS_IPC - IPC is needed for script
916
         * reload */
917
0
        flags = OSS_PROC_IS_EXTRA;
918
0
        if (m->exports->procs[n].flags&PROC_FLAG_NEEDS_SCRIPT)
919
0
          flags |= OSS_PROC_NEEDS_SCRIPT;
920
0
        if ( (m->exports->procs[n].flags&PROC_FLAG_HAS_IPC)==0)
921
0
          flags |= OSS_PROC_NO_IPC;
922
0
        struct internal_fork_params ifp = {
923
0
          .proc_desc = m->exports->procs[n].name,
924
0
          .flags = flags,
925
0
          .type = TYPE_MODULE,
926
0
        };
927
0
        x = internal_fork(&ifp);
928
0
        if (x<0) {
929
0
          LM_ERR("failed to fork process \"%s\"/%d for module %s\n",
930
0
            m->exports->procs[n].name, l, m->exports->name);
931
0
          return -1;
932
0
        } else if (x==0) {
933
          /* new process */
934
          /* initialize the process for the rest of the modules */
935
0
          if ( m->exports->procs[n].flags&PROC_FLAG_INITCHILD ) {
936
0
            if (init_child(PROC_MODULE) < 0) {
937
0
              LM_ERR("error in init_child for PROC_MODULE\n");
938
0
              report_failure_status();
939
0
              exit(-1);
940
0
            }
941
942
0
            report_conditional_status( (!no_daemon_mode), 0);
943
0
          } else
944
0
            clean_write_pipeend();
945
946
          /* run the function */
947
0
          m->exports->procs[n].function(l);
948
          /* we shouldn't get here */
949
0
          exit(0);
950
0
        }
951
0
      }
952
      /* run post-fork function */
953
0
      if (m->exports->procs[n].post_fork_function)
954
0
        if (m->exports->procs[n].post_fork_function()!=0) {
955
0
          LM_ERR("post-fork function failed for process \"%s\" "
956
0
            "in module %s\n",
957
0
            m->exports->procs[n].name, m->exports->name);
958
0
          return -1;
959
0
        }
960
0
    }
961
0
  }
962
963
0
  return 0;
964
0
}
965
966
967
int modules_validate_reload(void)
968
0
{
969
0
  struct sr_module *m;
970
0
  int ret = 1;
971
972
0
  for( m=modules ; m ; m=m->next) {
973
0
    if (m->exports->reload_ack_f==NULL)
974
0
      continue;
975
0
    if (!m->exports->reload_ack_f()) {
976
0
      LM_ERR("module <%s> did not validated the cfg file\n",
977
0
        m->exports->name);
978
0
      ret = 0;
979
0
    }
980
0
  }
981
982
0
  return ret;
983
0
}
984