Coverage Report

Created: 2025-11-24 06:09

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
  if ( !exp->ver_info.version ) {
211
0
    LM_CRIT("BUG - version not defined in module <%s>\n", path );
212
0
    return 0;
213
0
  }
214
0
  if ( !exp->ver_info.compile_flags ) {
215
0
    LM_CRIT("BUG - compile flags not defined in module <%s>\n", path );
216
0
    return 0;
217
0
  }
218
0
  if ( !exp->ver_info.scm.type ) {
219
0
    LM_CRIT("BUG - %s type not defined in module <%s> %s\n",
220
0
      scm_nm, path, hint );
221
0
    return 0;
222
0
  }
223
0
  if ( !exp->ver_info.scm.rev ) {
224
0
    LM_CRIT("BUG - %s revision not defined in module <%s> %s\n",
225
0
      scm_nm, path, hint );
226
0
    return 0;
227
0
  }
228
229
0
  if (strcmp(OPENSIPS_FULL_VERSION, exp->ver_info.version)!=0) {
230
0
    LM_CRIT("module version mismatch for %s; core: %s; module: %s\n",
231
0
      exp->name, OPENSIPS_FULL_VERSION, exp->ver_info.version );
232
0
    return 0;
233
0
  }
234
0
  if (strcmp(OPENSIPS_COMPILE_FLAGS, exp->ver_info.compile_flags)!=0) {
235
0
    LM_CRIT("module compile flags mismatch for %s "
236
0
      " \ncore: %s \nmodule: %s\n", exp->name,
237
0
      OPENSIPS_COMPILE_FLAGS, exp->ver_info.compile_flags);
238
0
    return 0;
239
0
  }
240
0
  if (strcmp(core_scm_ver.type, exp->ver_info.scm.type) != 0) {
241
0
    LM_CRIT("module %s type mismatch for %s "
242
0
      " \ncore: %s \nmodule: %s %s\n", scm_nm, exp->name,
243
0
      core_scm_ver.type, exp->ver_info.scm.type, hint);
244
0
    return 0;
245
0
  }
246
0
  if (modload_check_rev && strcmp(core_scm_ver.rev, exp->ver_info.scm.rev)) {
247
0
    LM_CRIT("module %s revision mismatch for %s "
248
0
      " \ncore: %s \nmodule: %s %s\n", scm_nm, exp->name,
249
0
      core_scm_ver.rev, exp->ver_info.scm.rev, hint);
250
0
    return 0;
251
0
  }
252
0
  return 1;
253
0
}
254
255
256
257
/* returns 0 on success , <0 on error */
258
int sr_load_module(char* path)
259
0
{
260
0
  void* handle;
261
0
  unsigned int moddlflags;
262
0
  char* error;
263
0
  const struct module_exports* exp;
264
0
  struct sr_module* t;
265
266
  /* load module */
267
0
  handle=dlopen(path, OPENSIPS_DLFLAGS); /* resolve all symbols now */
268
0
  if (handle==0){
269
0
    LM_ERR("could not open module <%s>: %s\n", path, dlerror() );
270
0
    goto error;
271
0
  }
272
273
  /* check for duplicates */
274
0
  for(t=modules;t; t=t->next){
275
0
    if (t->handle==handle){
276
0
      LM_WARN("attempting to load the same module twice (%s)\n", path);
277
0
      goto skip;
278
0
    }
279
0
  }
280
281
  /* import module interface */
282
0
  exp = (const struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");
283
0
  if ( (error =(char*)dlerror())!=0 ){
284
0
    LM_ERR("load_module: %s\n", error);
285
0
    goto error1;
286
0
  }
287
  /* version control */
288
0
  if (!version_control(exp, path)) {
289
0
    exit(1);
290
0
  }
291
0
  if(exp->dlflags!=DEFAULT_DLFLAGS && exp->dlflags!=OPENSIPS_DLFLAGS) {
292
0
    moddlflags = exp->dlflags;
293
0
    dlclose(handle);
294
0
    LM_DBG("reloading module %s with flags %d\n", path, moddlflags);
295
0
    handle = dlopen(path, moddlflags);
296
0
    if (handle==0){
297
0
      LM_ERR("could not open module <%s>: %s\n", path, dlerror() );
298
0
      goto error;
299
0
    }
300
0
    exp = (const struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");
301
0
    if ( (error =(char*)dlerror())!=0 ){
302
0
      LM_ERR("failed to load module : %s\n", error);
303
0
      goto error1;
304
0
    }
305
0
  }
306
307
0
  if (exp->load_f && exp->load_f() < 0) {
308
0
    LM_ERR("could not initialize module %s\n", path);
309
0
    goto error1;
310
0
  }
311
312
  /* launch register */
313
0
  if (register_module(exp, path, handle)<0) goto error1;
314
0
  return 0;
315
316
0
error1:
317
0
  dlclose(handle);
318
0
error:
319
0
skip:
320
0
  return -1;
321
0
}
322
323
/* built-in modules with static exports */
324
struct static_modules {
325
  str name;
326
  struct module_exports *exp;
327
};
328
329
struct static_modules static_modules[] = {
330
  { str_init(PROTO_PREFIX "udp"), &proto_udp_exports },
331
  { str_init(PROTO_PREFIX "tcp"), &proto_tcp_exports },
332
};
333
334
static int load_static_module(char *path)
335
0
{
336
0
  int len = strlen(path);
337
0
  char *end = path + len;
338
0
  struct sr_module* t;
339
0
  unsigned int i;
340
341
  /* eliminate the .so, if found */
342
0
  if (len > 3 && strncmp(end - 3, ".so", 3)==0) {
343
0
    end -= 3;
344
0
    len -= 3;
345
0
  }
346
  /* we check whether the protocol is found within the static_modules */
347
0
  for (i = 0; i < (sizeof(static_modules)/sizeof(static_modules[0])); i++) {
348
0
    if (len >= static_modules[i].name.len &&
349
        /* the path ends in the module's name */
350
0
        memcmp(end - static_modules[i].name.len,
351
0
          static_modules[i].name.s, static_modules[i].name.len) == 0 &&
352
        /* check if the previous char is '/' or nothing */
353
0
        (len == static_modules[i].name.len || (*(end-len-1) == '/'))) {
354
355
      /* yey, found the module - check if it was loaded twice */
356
0
      for(t=modules;t; t=t->next){
357
0
        if (t->handle==static_modules[i].exp){
358
0
          LM_WARN("attempting to load the same module twice (%s)\n", path);
359
0
          return 0;
360
0
        }
361
0
      }
362
363
      /* version control */
364
0
      if (!version_control(static_modules[i].exp, path)) {
365
0
        exit(0);
366
0
      }
367
368
      /* launch register */
369
0
      if (register_module(static_modules[i].exp, path, static_modules[i].exp)<0)
370
0
        return -1;
371
0
      return 0;
372
0
    }
373
0
  }
374
375
0
  return -1;
376
0
}
377
378
void add_mpath(const char *new_mpath)
379
0
{
380
0
  struct mpath *nmpath;
381
0
  int len = strlen(new_mpath);
382
0
  if (len >= MPATH_LEN) {
383
0
    LM_ERR("mpath %s too long!\n", new_mpath);
384
0
    return;
385
0
  }
386
0
  nmpath = pkg_malloc(sizeof *nmpath);
387
0
  if (!nmpath) {
388
0
    LM_ERR("could not allocate space for %s mpath!\n", new_mpath);
389
0
    return;
390
0
  }
391
0
  memset(nmpath, 0, sizeof *nmpath);
392
  /* link it in the list */
393
0
  if (last_mpath)
394
0
    last_mpath->next = nmpath;
395
0
  else
396
0
    mpaths = nmpath;
397
0
  last_mpath = nmpath;
398
0
  memcpy(nmpath->buf, new_mpath, len);
399
0
  nmpath->len = len;
400
0
  if (nmpath->len == 0 || nmpath->buf[nmpath->len - 1] != '/') {
401
0
    nmpath->buf[nmpath->len] = '/';
402
0
    nmpath->len++;
403
0
  }
404
0
  nmpath->buf[nmpath->len] = '\0';
405
0
}
406
407
static struct {
408
 char *module;
409
 char *name;
410
 unsigned int flags;
411
} module_warnings[] = {
412
  { "rabbitmq", "'rabbitmq' module has been dropped - please use 'event_rabbitmq' instead!", MOD_WARN_EXIT },
413
  { "event_route", "'event_route' module has been integrated in core file. You no longer need to load the module.", MOD_WARN_SKIP }
414
};
415
416
/* returns 0 on success , <0 on error */
417
int load_module(char* name)
418
0
{
419
0
  int i_tmp, len;
420
0
  struct stat statf;
421
0
  struct mpath *mp;
422
0
  int module_warnings_len;
423
0
  char *base_name;
424
425
0
  base_name = basename(name);
426
0
  len = strlen(base_name);
427
0
  if (strstr(base_name, ".so"))
428
0
    len -= 3;
429
430
0
  module_warnings_len = sizeof(module_warnings) / sizeof(module_warnings[0]);
431
432
0
  for (i_tmp = 0; i_tmp < module_warnings_len; i_tmp++) {
433
0
    if (strncmp(base_name, module_warnings[i_tmp].module, len) == 0) {
434
0
      switch (module_warnings[i_tmp].flags)
435
0
      {
436
0
        case MOD_WARN_EXIT:
437
0
          LM_ERR("%s\n", module_warnings[i_tmp].name);
438
0
          return -1;
439
440
0
        case MOD_WARN_SKIP:
441
0
          LM_WARN("%s\n", module_warnings[i_tmp].name);
442
0
          return 0;
443
444
0
        default:
445
0
          break;
446
0
      }
447
0
    }
448
0
  }
449
450
  /* if this is a static module, load it directly */
451
0
  if (load_static_module(name) == 0)
452
0
    return 0;
453
454
0
  if (*name=='/' || mpaths==NULL) {
455
0
    LM_DBG("loading module %s\n", name);
456
0
    if (sr_load_module(name)!=0){
457
0
      LM_ERR("failed to load module\n");
458
0
      return -1;
459
0
    }
460
0
    return 0;
461
0
  }
462
0
  for (mp = mpaths; mp; mp = mp->next) {
463
0
    len = strlen(name);
464
0
    if (len + mp->len >= MPATH_LEN)
465
0
      continue;
466
0
    memcpy(mp->buf + mp->len, name, len);
467
0
    mp->buf[mp->len + len] = '\0';
468
0
    if (stat(mp->buf, &statf) == -1 || S_ISDIR(statf.st_mode)) {
469
0
      i_tmp = strlen(mp->buf);
470
0
      if(strchr(name, '/')==NULL &&
471
0
        strncmp(mp->buf+i_tmp-3, ".so", 3)==0)
472
0
      {
473
0
        if(i_tmp+len<MPATH_LEN)
474
0
        {
475
0
          strcpy(mp->buf+i_tmp-3, "/");
476
0
          strcpy(mp->buf+i_tmp-2, name);
477
0
          if (stat(mp->buf, &statf) == -1) {
478
0
            mp->buf[mp->len]='\0';
479
0
            LM_DBG("module '%s' not found in '%s'\n",
480
0
                name, mp->buf);
481
0
            goto next;
482
0
          }
483
0
        } else {
484
0
          LM_DBG("failed to load module '%s' from '%s' - path too long\n", name, mp->buf);
485
0
          goto next;
486
0
        }
487
0
      } else {
488
0
        goto next;
489
0
      }
490
0
    }
491
0
    LM_DBG("trying module %s\n", mp->buf);
492
0
    if (sr_load_module(mp->buf)!=0) {
493
0
      LM_DBG("failed to load module '%s'\n", mp->buf);
494
0
    } else {
495
0
      mp->buf[mp->len]='\0';
496
0
      return 0;
497
0
    }
498
0
next:
499
0
    mp->buf[mp->len]='\0';
500
0
  }
501
0
  LM_ERR("failed to load module '%s' - not found\n", name);
502
0
  return -1;
503
0
}
504
505
506
507
/* searches the module list and returns pointer to the "name" function or
508
 * 0 if not found
509
 * flags parameter is OR value of all flags that must match
510
 */
511
cmd_function find_export(const char* name, int flags)
512
0
{
513
0
  const cmd_export_t* cmd;
514
515
0
  cmd = find_mod_cmd_export_t(name, flags);
516
0
  if (cmd==0)
517
0
    return 0;
518
519
0
  return cmd->function;
520
0
}
521
522
523
524
/* Searches the module list for the "name" cmd_export_t structure.
525
 */
526
const cmd_export_t* find_mod_cmd_export_t(const char* name, int flags)
527
0
{
528
0
  struct sr_module* t;
529
0
  const cmd_export_t* cmd;
530
531
0
  for(t=modules;t;t=t->next){
532
0
    for(cmd=t->exports->cmds; cmd && cmd->name; cmd++){
533
0
      if((strcmp(name, cmd->name)==0)&&((cmd->flags & flags) == flags)){
534
0
        LM_DBG("found <%s> in module %s [%s]\n",
535
0
            name, t->exports->name, t->path);
536
0
        return cmd;
537
0
      }
538
0
    }
539
0
  }
540
541
0
  LM_DBG("<%s> not found \n", name);
542
0
  return 0;
543
0
}
544
545
546
547
/* Searches the module list for the "name" acmd_export_t structure.
548
 */
549
const acmd_export_t* find_mod_acmd_export_t(const char* name)
550
0
{
551
0
  struct sr_module* t;
552
0
  const acmd_export_t* cmd;
553
554
0
  for(t=modules;t;t=t->next){
555
0
    for(cmd=t->exports->acmds; cmd && cmd->name; cmd++){
556
0
      if((strcmp(name, cmd->name)==0)){
557
0
        LM_DBG("found <%s> in module %s [%s]\n",
558
0
            name, t->exports->name, t->path);
559
0
        return cmd;
560
0
      }
561
0
    }
562
0
  }
563
0
  LM_DBG("async <%s> not found \n", name);
564
0
  return 0;
565
0
}
566
567
/*
568
 * searches the module list and returns pointer to "name" function in module
569
 * "mod" or 0 if not found
570
 * flags parameter is OR value of all flags that must match
571
 */
572
cmd_function find_mod_export(const char* mod, const char* name, int flags)
573
0
{
574
0
  struct sr_module* t;
575
0
  const cmd_export_t* cmd;
576
577
0
  for (t = modules; t; t = t->next) {
578
0
    if (strcmp(t->exports->name, mod) == 0) {
579
0
      for (cmd = t->exports->cmds;  cmd && cmd->name; cmd++) {
580
0
        if ((strcmp(name, cmd->name) == 0) &&
581
0
            ((cmd->flags & flags) == flags)
582
0
           ){
583
0
          LM_DBG("found <%s> in module %s [%s]\n",
584
0
              name, t->exports->name, t->path);
585
0
          return cmd->function;
586
0
        }
587
0
      }
588
0
    }
589
0
  }
590
591
0
  LM_DBG("<%s> in module %s not found\n", name, mod);
592
0
  return 0;
593
0
}
594
595
596
597
void* find_param_export(const char* mod, const char* name, modparam_t type)
598
0
{
599
0
  struct sr_module* t;
600
0
  const param_export_t* param;
601
602
0
  for(t = modules; t; t = t->next) {
603
0
    if (strcmp(mod, t->exports->name) == 0) {
604
0
      for(param=t->exports->params;param && param->name ; param++) {
605
0
        if ((strcmp(name, param->name) == 0) &&
606
0
            (param->type == type)) {
607
0
          LM_DBG("found <%s> in module %s [%s]\n",
608
0
            name, t->exports->name, t->path);
609
0
          return param->param_pointer;
610
0
        }
611
0
      }
612
0
    }
613
0
  }
614
0
  LM_DBG("parameter <%s> or module <%s> not found\n", name, mod);
615
0
  return 0;
616
0
}
617
618
619
static void destroy_module(struct sr_module *m, int skip_others)
620
0
{
621
0
  struct sr_module_dep *dep;
622
623
0
  if (!m)
624
0
    return;
625
626
  /* destroy the modules in script load order using backwards iteration */
627
0
  if (!skip_others)
628
0
    destroy_module(m->next, 0);
629
630
0
  if (m->destroy_done || !m->exports)
631
0
    return;
632
633
  /* make sure certain modules get destroyed before this one */
634
0
  for (dep = m->sr_deps_destroy; dep; dep = dep->next)
635
0
    if (!dep->mod->destroy_done)
636
0
      destroy_module(dep->mod, 1);
637
638
0
  if (m->init_done && m->exports->destroy_f)
639
0
    m->exports->destroy_f();
640
641
0
  m->destroy_done = 1;
642
0
}
643
644
645
void destroy_modules(void)
646
0
{
647
0
  struct sr_module *mod, *aux;
648
649
0
  destroy_module(modules, 0);
650
0
  free_module_dependencies(modules);
651
652
0
  mod = modules;
653
0
  while (mod) {
654
0
    aux = mod;
655
0
    mod = mod->next;
656
0
    pkg_free(aux);
657
0
  }
658
0
}
659
660
661
/* recursive module child initialization; (recursion is used to
662
   process the module linear list in the same order in
663
   which modules are loaded in config file
664
*/
665
666
static int init_mod_child( struct sr_module* m, int rank, char *type,
667
                          int skip_others)
668
0
{
669
0
  struct sr_module_dep *dep;
670
671
0
  if (!m || m->init_child_done)
672
0
    return 0;
673
674
  /* iterate through the list; if error occurs,
675
     propagate it up the stack */
676
0
  if (!skip_others && init_mod_child(m->next, rank, type, 0) != 0)
677
0
    return -1;
678
679
0
  for (dep = m->sr_deps_cinit; dep; dep = dep->next)
680
0
    if (!dep->mod->init_child_done)
681
0
      if (init_mod_child(dep->mod, rank, type, 1) != 0)
682
0
        return -1;
683
684
0
  if (m->init_child_done)
685
0
    return 0;
686
687
0
  if (m->exports && m->exports->init_child_f) {
688
0
    LM_DBG("type=%s, rank=%d, module=%s\n",
689
0
        type, rank, m->exports->name);
690
0
    if (m->exports->init_child_f(rank)<0) {
691
0
      LM_ERR("failed to initializing module %s, rank %d\n",
692
0
        m->exports->name,rank);
693
0
      return -1;
694
0
    }
695
0
  }
696
697
0
  m->init_child_done = 1;
698
0
  return 0;
699
0
}
700
701
702
/*
703
 * per-child initialization
704
 */
705
int init_child(int rank)
706
0
{
707
0
  char* type;
708
0
  int rc;
709
710
0
  type = 0;
711
712
0
  switch(rank) {
713
0
  case PROC_MAIN:     type = "PROC_MAIN";     break;
714
0
  case PROC_TIMER:    type = "PROC_TIMER";    break;
715
0
  case PROC_MODULE:   type = "PROC_MODULE";   break;
716
0
  case PROC_TCP_MAIN: type = "PROC_TCP_MAIN"; break;
717
0
  }
718
719
0
  if (!type) {
720
0
    if (rank>0)
721
0
      type = "CHILD";
722
0
    else
723
0
      type = "UNKNOWN";
724
0
  }
725
726
0
  rc = init_mod_child(modules, rank, type, 0);
727
0
  ready_time = time(NULL);
728
0
  ready_delay = ready_time - startup_time;
729
730
0
  return rc;
731
0
}
732
733
734
735
/* recursive module initialization; (recursion is used to
736
   process the module linear list in the same order in
737
   which modules are loaded in config file
738
*/
739
740
static int init_mod( struct sr_module* m, int skip_others)
741
0
{
742
0
  struct sr_module_dep *dep;
743
744
0
  if (m) {
745
    /* iterate through the list; if error occurs,
746
       propagate it up the stack
747
     */
748
0
    if (!skip_others && init_mod(m->next, 0) != 0)
749
0
      return -1;
750
751
    /* our module might have been already init'ed through dependencies! */
752
0
    if (m->init_done)
753
0
      return 0;
754
755
0
    if (!m->exports)
756
0
      return 0;
757
758
    /* make sure certain modules get loaded before this one */
759
0
    for (dep = m->sr_deps_init; dep; dep = dep->next) {
760
0
      if (!dep->mod->init_done)
761
0
        if (init_mod(dep->mod, 1) != 0)
762
0
          return -1;
763
0
    }
764
765
0
    if (m->exports->init_f) {
766
0
      LM_DBG("initializing module %s\n", m->exports->name);
767
0
      if (m->exports->init_f()!=0) {
768
0
        LM_ERR("failed to initialize module %s\n", m->exports->name);
769
0
        return -1;
770
0
      }
771
0
    }
772
773
0
    m->init_done = 1;
774
775
    /* no init function -- proceed further */
776
0
#ifdef STATISTICS
777
0
    if (m->exports->stats) {
778
0
      LM_DBG("registering stats for %s\n", m->exports->name);
779
0
      if (register_module_stats(m->exports->name,m->exports->stats)!=0) {
780
0
        LM_ERR("failed to registering "
781
0
          "statistics for module %s\n", m->exports->name);
782
0
        return -1;
783
0
      }
784
0
    }
785
0
#endif
786
    /* register MI functions */
787
0
    if (m->exports->mi_cmds) {
788
0
      LM_DBG("register MI for %s\n", m->exports->name);
789
0
      if (register_mi_mod(m->exports->name,m->exports->mi_cmds)!=0) {
790
0
        LM_ERR("failed to register MI functions for module %s\n",
791
0
          m->exports->name);
792
0
      }
793
0
    }
794
795
    /* proceed with success */
796
0
    return 0;
797
0
  } else {
798
    /* end of list */
799
0
    return 0;
800
0
  }
801
0
}
802
803
/*
804
 * Initialize all loaded modules, the initialization
805
 * is done *AFTER* the configuration file is parsed
806
 */
807
int init_modules(void)
808
0
{
809
0
  struct sr_module *currentMod;
810
0
  int ret;
811
812
0
  if (testing_framework)
813
0
    init_unit_tests();
814
815
  /* pre-initialize all modules */
816
0
  for (currentMod=modules; currentMod; currentMod=currentMod->next) {
817
0
    if (currentMod->exports->preinit_f == NULL)
818
0
      continue;
819
0
    ret = currentMod->exports->preinit_f();
820
0
    if (ret < 0) {
821
0
      LM_ERR("could not pre-initialize module %s!\n",
822
0
          currentMod->exports->name);
823
0
      return ret;
824
0
    }
825
0
  }
826
827
0
  return init_mod(modules, 0);
828
0
}
829
830
831
/* Returns 1 if the module with name 'name' is loaded, and zero otherwise. */
832
int module_loaded(char *name)
833
0
{
834
0
  struct sr_module *currentMod;
835
836
0
  for (currentMod=modules; currentMod; currentMod=currentMod->next) {
837
0
    if (strcasecmp(name,currentMod->exports->name)==0) {
838
0
      return 1;
839
0
    }
840
841
0
  }
842
843
0
  return 0;
844
0
}
845
846
847
void *get_mod_handle(const char *name)
848
0
{
849
0
  struct sr_module *mod;
850
851
0
  for (mod = modules; mod; mod = mod->next)
852
0
    if (!strcasecmp(name, mod->exports->name))
853
0
      return mod->handle;
854
855
0
  return NULL;
856
0
}
857
858
859
/* Counts the additional the number of processes requested by modules */
860
int count_module_procs(int flags)
861
0
{
862
0
  struct sr_module *m;
863
0
  unsigned int cnt;
864
0
  unsigned int n;
865
866
0
  for( m=modules,cnt=0 ; m ; m=m->next) {
867
0
    if (m->exports->procs==NULL)
868
0
      continue;
869
0
    for ( n=0 ; m->exports->procs[n].name ; n++) {
870
0
      if (!m->exports->procs[n].no || !m->exports->procs[n].function)
871
0
        continue;
872
873
0
      if (!flags || (m->exports->procs[n].flags & flags))
874
0
        cnt+=m->exports->procs[n].no;
875
0
    }
876
0
  }
877
0
  LM_DBG("modules require %d extra processes\n",cnt);
878
0
  return cnt;
879
0
}
880
881
882
int start_module_procs(void)
883
0
{
884
0
  struct sr_module *m;
885
0
  unsigned int n;
886
0
  unsigned int l;
887
0
  unsigned int flags;
888
0
  int x;
889
890
0
  for( m=modules ; m ; m=m->next) {
891
0
    if (m->exports->procs==NULL)
892
0
      continue;
893
0
    for( n=0 ; m->exports->procs[n].name ; n++) {
894
0
      if ( !m->exports->procs[n].no || !m->exports->procs[n].function )
895
0
        continue;
896
      /* run pre-fork function */
897
0
      if (m->exports->procs[n].pre_fork_function)
898
0
        if (m->exports->procs[n].pre_fork_function()!=0) {
899
0
          LM_ERR("pre-fork function failed for process \"%s\" "
900
0
            "in module %s\n",
901
0
            m->exports->procs[n].name, m->exports->name);
902
0
          return -1;
903
0
        }
904
      /* fork the processes */
905
0
      for ( l=0; l<m->exports->procs[n].no ; l++) {
906
0
        LM_DBG("forking process \"%s\"/%d for module %s\n",
907
0
          m->exports->procs[n].name, l, m->exports->name);
908
        /* conver the module proc flags to internal proc flgas
909
         * NOTE that the PROC_FLAG_NEEDS_SCRIPT automatically
910
         * assumes PROC_FLAG_HAS_IPC - IPC is needed for script
911
         * reload */
912
0
        flags = OSS_PROC_IS_EXTRA;
913
0
        if (m->exports->procs[n].flags&PROC_FLAG_NEEDS_SCRIPT)
914
0
          flags |= OSS_PROC_NEEDS_SCRIPT;
915
0
        if ( (m->exports->procs[n].flags&PROC_FLAG_HAS_IPC)==0)
916
0
          flags |= OSS_PROC_NO_IPC;
917
0
        struct internal_fork_params ifp = {
918
0
          .proc_desc = m->exports->procs[n].name,
919
0
          .flags = flags,
920
0
          .type = TYPE_MODULE,
921
0
        };
922
0
        x = internal_fork(&ifp);
923
0
        if (x<0) {
924
0
          LM_ERR("failed to fork process \"%s\"/%d for module %s\n",
925
0
            m->exports->procs[n].name, l, m->exports->name);
926
0
          return -1;
927
0
        } else if (x==0) {
928
          /* new process */
929
          /* initialize the process for the rest of the modules */
930
0
          if ( m->exports->procs[n].flags&PROC_FLAG_INITCHILD ) {
931
0
            if (init_child(PROC_MODULE) < 0) {
932
0
              LM_ERR("error in init_child for PROC_MODULE\n");
933
0
              report_failure_status();
934
0
              exit(-1);
935
0
            }
936
937
0
            report_conditional_status( (!no_daemon_mode), 0);
938
0
          } else
939
0
            clean_write_pipeend();
940
941
          /* run the function */
942
0
          m->exports->procs[n].function(l);
943
          /* we shouldn't get here */
944
0
          exit(0);
945
0
        }
946
0
      }
947
      /* run post-fork function */
948
0
      if (m->exports->procs[n].post_fork_function)
949
0
        if (m->exports->procs[n].post_fork_function()!=0) {
950
0
          LM_ERR("post-fork function failed for process \"%s\" "
951
0
            "in module %s\n",
952
0
            m->exports->procs[n].name, m->exports->name);
953
0
          return -1;
954
0
        }
955
0
    }
956
0
  }
957
958
0
  return 0;
959
0
}
960
961
962
int modules_validate_reload(void)
963
0
{
964
0
  struct sr_module *m;
965
0
  int ret = 1;
966
967
0
  for( m=modules ; m ; m=m->next) {
968
0
    if (m->exports->reload_ack_f==NULL)
969
0
      continue;
970
0
    if (!m->exports->reload_ack_f()) {
971
0
      LM_ERR("module <%s> did not validated the cfg file\n",
972
0
        m->exports->name);
973
0
      ret = 0;
974
0
    }
975
0
  }
976
977
0
  return ret;
978
0
}
979