Coverage Report

Created: 2025-07-12 06:13

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