rpc: added register function and switched to hash table
[sip-router] / sr_module.c
1 /* $Id$
2  *
3  * Copyright (C) 2001-2003 FhG Fokus
4  *
5  * This file is part of ser, a free SIP server.
6  *
7  * ser is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version
11  *
12  * For a license to use the ser software under conditions
13  * other than those described here, or to purchase support for this
14  * software, please contact iptel.org by e-mail at the following addresses:
15  *    info@iptel.org
16  *
17  * ser is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26 /*
27  * History:
28  * --------
29  *  2003-03-10  switched to new module_exports format: updated find_export,
30  *               find_export_param, find_module (andrei)
31  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
32  *  2003-03-19  Support for flags in find_export (janakj)
33  *  2003-03-29  cleaning pkg_mallocs introduced (jiri)
34  *  2003-04-24  module version checking introduced (jiri)
35  *  2004-09-19  compile flags are checked too (andrei)
36  *  2005-01-07  removed find_module-overloading problems, added
37  *               find_export_record
38  *  2006-02-07  added fix_flag (andrei)
39  *  2008-02-29  store all the reponse callbacks in their own array (andrei)
40  *  2008-11-17  support dual module interface: ser & kamailio (andrei)
41  *  2008-11-26  added fparam_free_contents() and fix_param_types (andrei)
42  */
43
44
45 #include "sr_module.h"
46 #include "dprint.h"
47 #include "error.h"
48 #include "mem/mem.h"
49 #include "core_cmd.h"
50 #include "ut.h"
51 #include "re.h"
52 #include "route_struct.h"
53 #include "flags.h"
54 #include "trim.h"
55 #include "globals.h"
56 #include "rpc_lookup.h"
57
58 #include <sys/stat.h>
59 #include <regex.h>
60 #include <dlfcn.h>
61 #include <strings.h>
62 #include <stdlib.h>
63 #include <string.h>
64
65
66 struct sr_module* modules=0;
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
96 int mod_response_cbk_no=0;
97 response_function* mod_response_cbks=0;
98
99
100 /* initializes statically built (compiled in) modules*/
101 int register_builtin_modules()
102 {
103         int ret;
104
105         ret=0;
106 #ifdef STATIC_TM
107         ret=register_module(MODULE_INTERFACE_VER, &tm_exports,"built-in", 0);
108         if (ret<0) return ret;
109 #endif
110
111 #ifdef STATIC_EXEC
112         ret=register_module(MODULE_INTERFACE_VER, &exec_exports,"built-in", 0);
113         if (ret<0) return ret;
114 #endif
115
116 #ifdef STATIC_MAXFWD
117         ret=register_module(MODULE_INTERFACE_VER, &maxfwd_exports, "built-in", 0);
118         if (ret<0) return ret;
119 #endif
120
121 #ifdef STATIC_AUTH
122         ret=register_module(MODULE_INTERFACE_VER, &auth_exports, "built-in", 0);
123         if (ret<0) return ret;
124 #endif
125
126 #ifdef STATIC_RR
127         ret=register_module(MODULE_INTERFACE_VER, &rr_exports, "built-in", 0);
128         if (ret<0) return ret;
129 #endif
130
131 #ifdef STATIC_USRLOC
132         ret=register_module(MODULE_INTERFACE_VER, &usrloc_exports, "built-in", 0);
133         if (ret<0) return ret;
134 #endif
135
136 #ifdef STATIC_SL
137         ret=register_module(MODULE_INTERFACE_VER, &sl_exports, "built-in", 0);
138         if (ret<0) return ret;
139 #endif
140
141         return ret;
142 }
143
144
145
146 /* registers a module,  register_f= module register  functions
147  * returns <0 on error, 0 on success */
148 static int register_module(unsigned ver, union module_exports_u* e,
149                                         char* path, void* handle)
150 {
151         int ret, i;
152         struct sr_module* mod;
153
154         ret=-1;
155
156         /* add module to the list */
157         if ((mod=pkg_malloc(sizeof(struct sr_module)))==0){
158                 LOG(L_ERR, "load_module: memory allocation failure\n");
159                 ret=E_OUT_OF_MEM;
160                 goto error;
161         }
162         memset(mod,0, sizeof(struct sr_module));
163         mod->path=path;
164         mod->handle=handle;
165         mod->mod_interface_ver=ver;
166         mod->exports=e;
167         mod->next=modules;
168         modules=mod;
169
170         if (ver==1 && e->v1.items) {
171                 /* register module pseudo-variables for kamailio modules */
172                 LM_DBG("register PV from: %s\n", e->c.name);
173                 if (register_pvars_mod(e->c.name, e->v1.items)!=0) {
174                         LM_ERR("failed to register pseudo-variables for module %s\n",
175                                 e->c.name);
176                         pkg_free(mod);
177                         return -1;
178                 }
179         }else if (ver==0 && e->v0.rpc_methods){
180                 /* register rpcs for ser modules */
181                 i=rpc_register_array(e->v0.rpc_methods);
182                 if (i<0){
183                         ERR("failed to register RPCs for module %s\n", e->c.name);
184                         goto error;
185                 }else if (i>0){
186                         ERR("%d duplicate RPCs name detected while registering RPCs"
187                                         " declared in modules %s\n", i, e->c.name);
188                         goto error;
189                 }
190                 /* i==0 => success */
191         }
192
193         return 0;
194 error:
195         return ret;
196 }
197
198 #ifndef DLSYM_PREFIX
199 /* define it to null */
200 #define DLSYM_PREFIX
201 #endif
202
203 static inline int version_control(void *handle, char *path)
204 {
205         char **m_ver;
206         char **m_flags;
207         char* error;
208
209         m_ver=(char **)dlsym(handle, DLSYM_PREFIX "module_version");
210         if ((error=(char *)dlerror())!=0) {
211                 LOG(L_ERR, "ERROR: no version info in module <%s>: %s\n",
212                         path, error );
213                 return 0;
214         }
215         m_flags=(char **)dlsym(handle, DLSYM_PREFIX "module_flags");
216         if ((error=(char *)dlerror())!=0) {
217                 LOG(L_ERR, "ERROR: no compile flags info in module <%s>: %s\n",
218                         path, error );
219                 return 0;
220         }
221         if (!m_ver || !(*m_ver)) {
222                 LOG(L_ERR, "ERROR: no version in module <%s>\n", path );
223                 return 0;
224         }
225         if (!m_flags || !(*m_flags)) {
226                 LOG(L_ERR, "ERROR: no compile flags in module <%s>\n", path );
227                 return 0;
228         }
229
230         if (strcmp(SER_FULL_VERSION, *m_ver)==0){
231                 if (strcmp(SER_COMPILE_FLAGS, *m_flags)==0)
232                         return 1;
233                 else {
234                         LOG(L_ERR, "ERROR: module compile flags mismatch for %s "
235                                                 " \ncore: %s \nmodule: %s\n",
236                                                 path, SER_COMPILE_FLAGS, *m_flags);
237                         return 0;
238                 }
239         }
240         LOG(L_ERR, "ERROR: module version mismatch for %s; "
241                 "core: %s; module: %s\n", path, SER_FULL_VERSION, *m_ver );
242         return 0;
243 }
244
245 /** load a sr module.
246  * tries to load the module specified by path.
247  * If modname does contain a '/' or a '.' it would be assumed to contain a 
248  * path to the module and it will be used as give.
249  * else <MODS_DIR>/<modname>.so will be tried and if this fails
250  *  <MODS_DIR>/<modname>/<modname>.so
251  * @param modname - path or module name
252  * @return 0 on success , <0 on error
253  */
254 int load_module(char* mod_path)
255 {
256         void* handle;
257         char* error;
258         mod_register_function mr;
259         union module_exports_u* exp;
260         unsigned* mod_if_ver;
261         struct sr_module* t;
262         struct stat stat_buf;
263         char* modname;
264         char* mdir;
265         char* nxt_mdir;
266         char* path;
267         int mdir_len;
268         int len;
269         int dlflags;
270         int new_dlflags;
271         int retries;
272
273 #ifndef RTLD_NOW
274 /* for openbsd */
275 #define RTLD_NOW DL_LAZY
276 #endif
277         path=mod_path;
278         if (!strchr(path, '/') && !strchr(path, '.')) {
279                 /* module name was given, we try to construct the path */
280                 modname = path;
281                 mdir=mods_dir; /* search path */
282                 do{
283                         nxt_mdir=strchr(mdir, ':');
284                         if (nxt_mdir) mdir_len=(int)(nxt_mdir-mdir);
285                         else mdir_len=strlen(mdir);
286                         
287                         /* try path <MODS_DIR>/<modname>.so */
288                         path = (char*)pkg_malloc(mdir_len + 1 /* "/" */ +
289                                                                         strlen(modname) + 3 /* ".so" */ + 1);
290                         if (path==0) goto error;
291                         memcpy(path, mdir, mdir_len);
292                         len = mdir_len;
293                         if (len != 0 && path[len - 1] != '/'){
294                                 path[len]='/';
295                                 len++;
296                         }
297                         path[len]=0;
298                         strcat(path, modname);
299                         strcat(path, ".so");
300
301                         if (stat(path, &stat_buf) == -1) {
302                                 DBG("load_module: module file not found <%s>\n", path);
303                                 pkg_free(path);
304
305                                 /* try path <MODS_DIR>/<modname>/<modname>.so */
306                                 path = (char*)pkg_malloc(
307                                         mdir_len + 1 /* "/" */ +
308                                         strlen(modname) + 1 /* "/" */ +
309                                         strlen(modname) + 3 /* ".so" */ + 1);
310                                 if (path==0) goto error;
311                                 memcpy(path, mdir, mdir_len);
312                                 len = mdir_len;
313                                 if (len != 0 && path[len - 1] != '/') {
314                                         path[len]='/';
315                                         len++;
316                                 }
317                                 path[len]=0;
318                                 strcat(path, modname);
319                                 strcat(path, "/");
320                                 strcat(path, modname);
321                                 strcat(path, ".so");
322
323                                 if (stat(path, &stat_buf) == -1) {
324                                         DBG("load_module: module file not found <%s>\n", path);
325                                         pkg_free(path);
326                                         path=0;
327                                 }
328                         }
329                         mdir=nxt_mdir?nxt_mdir+1:0;
330                 }while(path==0 && mdir);
331                 if (path==0){
332                         LOG(L_ERR, "ERROR: load_module: could not find module <%s> in"
333                                                 " <%s>\n", modname, mods_dir);
334                         goto error;
335                 }
336         }
337         retries=2;
338         dlflags=RTLD_NOW;
339 reload:
340         handle=dlopen(path, RTLD_NOW); /* resolve all symbols now */
341         if (handle==0){
342                 LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n",
343                         path, dlerror());
344                 goto error;
345         }
346
347         for(t=modules;t; t=t->next){
348                 if (t->handle==handle){
349                         LOG(L_WARN, "WARNING: load_module: attempting to load the same"
350                                                 " module twice (%s)\n", path);
351                         goto skip;
352                 }
353         }
354         /* version control */
355         if (!version_control(handle, path)) {
356                 exit(0);
357         }
358         mod_if_ver = (unsigned *)dlsym(handle,
359                                                                         DLSYM_PREFIX "module_interface_ver");
360         if ( (error =(char*)dlerror())!=0 ){
361                 LOG(L_ERR, "ERROR: no module interface version in module <%s>\n",
362                                         path );
363                 goto error1;
364         }
365         /* launch register */
366         mr = (mod_register_function)dlsym(handle, DLSYM_PREFIX "mod_register");
367         if (((error =(char*)dlerror())==0) && mr) {
368                 /* no error call it */
369                 new_dlflags=dlflags;
370                 if (mr(path, &dlflags, 0, 0)!=0) {
371                         LOG(L_ERR, "ERROR: load_module: %s: mod_register failed\n", path);
372                         goto error1;
373                 }
374                 if (new_dlflags!=dlflags && new_dlflags!=0) {
375                         /* we have to reload the module */
376                         dlclose(handle);
377                         dlflags=new_dlflags;
378                         retries--;
379                         if (retries>0) goto reload;
380                         LOG(L_ERR, "ERROR: load_module: %s: cannot agree"
381                                         " on the dlflags\n", path);
382                         goto error;
383                 }
384         }
385         exp = (union module_exports_u*)dlsym(handle, DLSYM_PREFIX "exports");
386         if ( (error =(char*)dlerror())!=0 ){
387                 LOG(L_ERR, "ERROR: load_module: %s\n", error);
388                 goto error1;
389         }
390         /* hack to allow for kamailio style dlflags inside exports */
391         if (*mod_if_ver == 1) {
392                 new_dlflags = exp->v1.dlflags;
393                 if (new_dlflags!=dlflags && new_dlflags!=DEFAULT_DLFLAGS) {
394                         /* we have to reload the module */
395                         dlclose(handle);
396                         WARN("%s: exports dlflags interface is deprecated and it will not"
397                                         "be supported in newer versions; consider using"
398                                         " mod_register() instead", path);
399                         dlflags=new_dlflags;
400                         retries--;
401                         if (retries>0) goto reload;
402                         LOG(L_ERR, "ERROR: load_module: %s: cannot agree"
403                                         " on the dlflags\n", path);
404                         goto error;
405                 }
406         }
407         if (register_module(*mod_if_ver, exp, path, handle)<0) goto error1;
408         if (path && path!=mod_path)
409                 pkg_free(path);
410         return 0;
411
412 error1:
413         dlclose(handle);
414 error:
415 skip:
416         if (path && path!=mod_path)
417                 pkg_free(path);
418         return -1;
419 }
420
421
422
423 /* searches the module list for function name in module mod and returns 
424  *  a pointer to the "name" function record union or 0 if not found
425  * sets also *mod_if_ver to the module interface version (needed to know
426  * which member of the union should be accessed v0 or v1)
427  * mod==0 is a wildcard matching all modules
428  * flags parameter is OR value of all flags that must match
429  */
430 union cmd_export_u* find_mod_export_record(char* mod, char* name,
431                                                                                         int param_no, int flags,
432                                                                                         unsigned* mod_if_ver)
433 {
434         struct sr_module* t;
435         union cmd_export_u* cmd;
436         int i;
437         unsigned mver;
438
439 #define FIND_EXPORT_IN_MOD(VER) \
440                 if (t->exports->VER.cmds) \
441                         for(i=0, cmd=(void*)&t->exports->VER.cmds[0]; cmd->VER.name; \
442                                         i++, cmd=(void*)&t->exports->VER.cmds[i]){\
443                                 if((strcmp(name, cmd->VER.name)==0)&& \
444                                         ((cmd->VER.param_no==param_no) || \
445                                          (cmd->VER.param_no==VAR_PARAM_NO)) && \
446                                         ((cmd->VER.flags & flags) == flags) \
447                                 ){ \
448                                         DBG("find_export_record: found <%s> in module %s [%s]\n", \
449                                                 name, t->exports->VER.name, t->path); \
450                                         *mod_if_ver=mver; \
451                                         return cmd; \
452                                 } \
453                         }
454
455         for(t=modules;t;t=t->next){
456                 if (mod!=0 && (strcmp(t->exports->c.name, mod) !=0))
457                         continue;
458                 mver=t->mod_interface_ver;
459                 switch (mver){
460                         case 0:
461                                 FIND_EXPORT_IN_MOD(v0);
462                                 break;
463                         case 1:
464                                 FIND_EXPORT_IN_MOD(v1);
465                                 break;
466                         default:
467                                 BUG("invalid module interface version %d for modules %s\n",
468                                                 t->mod_interface_ver, t->path);
469                 }
470         }
471         DBG("find_export_record: <%s> not found \n", name);
472         return 0;
473 }
474
475
476
477 /* searches the module list for function name and returns 
478  *  a pointer to the "name" function record union or 0 if not found
479  * sets also *mod_if_ver to the module interface version (needed to know
480  * which member of the union should be accessed v0 or v1)
481  * mod==0 is a wildcard matching all modules
482  * flags parameter is OR value of all flags that must match
483  */
484 union cmd_export_u* find_export_record(char* name,
485                                                                                         int param_no, int flags,
486                                                                                         unsigned* mod_if_ver)
487 {
488         return find_mod_export_record(0, name, param_no, flags, mod_if_ver);
489 }
490
491
492
493 cmd_function find_export(char* name, int param_no, int flags)
494 {
495         union cmd_export_u* cmd;
496         unsigned mver;
497         
498         cmd = find_export_record(name, param_no, flags, &mver);
499         return cmd?cmd->c.function:0;
500 }
501
502
503 rpc_export_t* find_rpc_export(char* name, int flags)
504 {
505         return rpc_lookup((char*)name, strlen(name));
506 }
507
508
509 /*
510  * searches the module list and returns pointer to "name" function in module
511  * "mod"
512  * 0 if not found
513  * flags parameter is OR value of all flags that must match
514  */
515 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
516 {
517         union cmd_export_u* cmd;
518         unsigned mver;
519
520         cmd=find_mod_export_record(mod, name, param_no, flags, &mver);
521         if (cmd)
522                 return cmd->c.function;
523         
524         DBG("find_mod_export: <%s> in module <%s> not found\n", name, mod);
525         return 0;
526 }
527
528
529 struct sr_module* find_module_by_name(char* mod) {
530         struct sr_module* t;
531
532         for(t = modules; t; t = t->next) {
533                 if (strcmp(mod, t->exports->c.name) == 0) {
534                         return t;
535                 }
536         }
537         DBG("find_module_by_name: module <%s> not found\n", mod);
538         return 0;
539 }
540
541
542 void* find_param_export(struct sr_module* mod, char* name,
543                                                 modparam_t type_mask, modparam_t *param_type)
544 {
545         param_export_t* param;
546
547         if (!mod)
548                 return 0;
549         param=0;
550         switch(mod->mod_interface_ver){
551                 case 0:
552                         param=mod->exports->v0.params;
553                         break;
554                 case 1:
555                         param=mod->exports->v1.params;
556                         break;
557                 default:
558                         BUG("bad module interface version %d in module %s [%s]\n",
559                                         mod->mod_interface_ver, mod->exports->c.name, mod->path);
560                         return 0;
561         }
562         for(;param && param->name ; param++) {
563                 if ((strcmp(name, param->name) == 0) &&
564                         ((param->type & PARAM_TYPE_MASK(type_mask)) != 0)) {
565                         DBG("find_param_export: found <%s> in module %s [%s]\n",
566                                 name, mod->exports->c.name, mod->path);
567                         *param_type = param->type;
568                         return param->param_pointer;
569                 }
570         }
571         DBG("find_param_export: parameter <%s> not found in module <%s>\n",
572                         name, mod->exports->c.name);
573         return 0;
574 }
575
576
577 void destroy_modules()
578 {
579         struct sr_module* t, *foo;
580
581         t=modules;
582         while(t) {
583                 foo=t->next;
584                 if (t->exports){
585                         switch(t->mod_interface_ver){
586                                 case 0:
587                                         if ((t->exports->v0.destroy_f)) t->exports->v0.destroy_f();
588                                         break;
589                                 case 1:
590                                         if ((t->exports->v1.destroy_f)) t->exports->v1.destroy_f();
591                                         break;
592                                 default:
593                                         BUG("bad module interface version %d in module %s [%s]\n",
594                                                 t->mod_interface_ver, t->exports->c.name,
595                                                 t->path);
596                         }
597                 }
598                 pkg_free(t);
599                 t=foo;
600         }
601         modules=0;
602         if (mod_response_cbks){
603                 pkg_free(mod_response_cbks);
604                 mod_response_cbks=0;
605         }
606 }
607
608 #ifdef NO_REVERSE_INIT
609
610 /*
611  * Initialize all loaded modules, the initialization
612  * is done *AFTER* the configuration file is parsed
613  */
614 int init_modules(void)
615 {
616         struct sr_module* t;
617
618         for(t = modules; t; t = t->next) {
619                 if (t->exports){
620                         switch(t->mod_interface_ver){
621                                 case 0:
622                                         if (t->exports->v0.init_f)
623                                                 if (t->exports->v0.init_f() != 0) {
624                                                         LOG(L_ERR, "init_modules(): Error while"
625                                                                                 " initializing module %s\n",
626                                                                                 t->exports->v0.name);
627                                                         return -1;
628                                                 }
629                                         if (t->exports->v0.response_f)
630                                                 mod_response_cbk_no++;
631                                         break;
632                                 case 1:
633                                         if (t->exports->v1.init_f)
634                                                 if (t->exports->v1.init_f() != 0) {
635                                                         LOG(L_ERR, "init_modules(): Error while"
636                                                                                 " initializing module %s\n",
637                                                                                 t->exports->v1.name);
638                                                         return -1;
639                                                 }
640                                         if (t->exports->v1.response_f)
641                                                 mod_response_cbk_no++;
642                                         break;
643                                 default:
644                                         BUG("bad module interface version %d in module %s [%s]\n",
645                                                 t->exports->c.name, t->path);
646                                         return -1;
647                         }
648                 }
649         }
650         mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
651                                                                         sizeof(response_function));
652         if (mod_response_cbks==0){
653                 LOG(L_ERR, "init_modules(): memory allocation failure"
654                                         " for %d response_f callbacks\n", mod_response_cbk_no);
655                 return -1;
656         }
657         for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
658                 if (t->exports){
659                         switch(t->mod_interface_ver){
660                                 case 0:
661                                         if (t->exports->v0.response_f){
662                                                 mod_response_cbks[i]=t->exports->v0.response_f;
663                                                 i++;
664                                         }
665                                         break;
666                                 case 1:
667                                         if (t->exports->v1.response_f){
668                                                 mod_response_cbks[i]=t->exports->v1.response_f;
669                                                 i++;
670                                         }
671                                         break;
672                         }
673                 }
674         }
675         return 0;
676 }
677
678 /*
679  * per-child initialization
680  */
681 int init_child(int rank)
682 {
683         struct sr_module* t;
684         char* type;
685
686         switch(rank) {
687         case PROC_MAIN:     type = "PROC_MAIN";     break;
688         case PROC_TIMER:    type = "PROC_TIMER";    break;
689         case PROC_FIFO:     type = "PROC_FIFO";     break;
690         case PROC_TCP_MAIN: type = "PROC_TCP_MAIN"; break;
691         default:            type = "CHILD";         break;
692         }
693         DBG("init_child: initializing %s with rank %d\n", type, rank);
694
695
696         for(t = modules; t; t = t->next) {
697                 switch(t->mod_interface_ver){
698                         case 0:
699                                 if (t->exports->v0.init_child_f) {
700                                         if ((t->exports->v0.init_child_f(rank)) < 0) {
701                                                 LOG(L_ERR, "init_child(): Initialization of child"
702                                                                         " %d failed\n", rank);
703                                                 return -1;
704                                         }
705                                 }
706                                 break;
707                         case 1:
708                                 if (t->exports->v1.init_child_f) {
709                                         if ((t->exports->v1.init_child_f(rank)) < 0) {
710                                                 LOG(L_ERR, "init_child(): Initialization of child"
711                                                                         " %d failed\n", rank);
712                                                 return -1;
713                                         }
714                                 }
715                                 break;
716                         default:
717                                 BUG("bad module interface version %d in module %s [%s]\n",
718                                                 t->mod_interface_ver, t->exports->c.name,
719                                                 t->path);
720                                 return -1;
721                 }
722         }
723         return 0;
724 }
725
726 #else
727
728
729 /* recursive module child initialization; (recursion is used to
730    process the module linear list in the same order in
731    which modules are loaded in config file
732 */
733
734 static int init_mod_child( struct sr_module* m, int rank )
735 {
736         if (m) {
737                 /* iterate through the list; if error occurs,
738                    propagate it up the stack
739                  */
740                 if (init_mod_child(m->next, rank)!=0) return -1;
741                 if (m->exports){
742                         switch(m->mod_interface_ver){
743                                 case 0:
744                                         if (m->exports->v0.init_child_f) {
745                                                 DBG("DEBUG: init_mod_child (%d): %s\n",
746                                                                 rank, m->exports->v0.name);
747                                                 if (m->exports->v0.init_child_f(rank)<0) {
748                                                         LOG(L_ERR, "init_mod_child(): Error while"
749                                                                                 " initializing module %s\n",
750                                                                                 m->exports->v0.name);
751                                                         return -1;
752                                                 } else {
753                                                         /* module correctly initialized */
754                                                         return 0;
755                                                 }
756                                         }
757                                         /* no init function -- proceed with success */
758                                         return 0;
759                                 case 1:
760                                         if (m->exports->v1.init_child_f) {
761                                                 DBG("DEBUG: init_mod_child (%d): %s\n",
762                                                                 rank, m->exports->v1.name);
763                                                 if (m->exports->v1.init_child_f(rank)<0) {
764                                                         LOG(L_ERR, "init_mod_child(): Error while"
765                                                                                 " initializing module %s\n",
766                                                                                 m->exports->v1.name);
767                                                         return -1;
768                                                 } else {
769                                                         /* module correctly initialized */
770                                                         return 0;
771                                                 }
772                                         }
773                                         /* no init function -- proceed with success */
774                                         return 0;
775                         }
776                 }
777                 /* no exports -- proceed with success */
778                 return 0;
779         } else {
780                 /* end of list */
781                 return 0;
782         }
783 }
784
785
786 /*
787  * per-child initialization
788  */
789 int init_child(int rank)
790 {
791         return init_mod_child(modules, rank);
792 }
793
794
795
796 /* recursive module initialization; (recursion is used to
797    process the module linear list in the same order in
798    which modules are loaded in config file
799 */
800
801 static int init_mod( struct sr_module* m )
802 {
803         if (m) {
804                 /* iterate through the list; if error occurs,
805                    propagate it up the stack
806                  */
807                 if (init_mod(m->next)!=0) return -1;
808                 if (m->exports){
809                         switch(m->mod_interface_ver){
810                                 case 0:
811                                         if ( m->exports->v0.init_f) {
812                                                 DBG("DEBUG: init_mod: %s\n", m->exports->v0.name);
813                                                 if (m->exports->v0.init_f()!=0) {
814                                                         LOG(L_ERR, "init_mod(): Error while initializing"
815                                                                                 " module %s\n", m->exports->v0.name);
816                                                         return -1;
817                                                 } else {
818                                                         /* module correctly initialized */
819                                                         return 0;
820                                                 }
821                                         }
822                                         /* no init function -- proceed with success */
823                                         return 0;
824                                 case 1:
825                                         if ( m->exports->v1.init_f) {
826                                                 DBG("DEBUG: init_mod: %s\n", m->exports->v1.name);
827                                                 if (m->exports->v1.init_f()!=0) {
828                                                         LOG(L_ERR, "init_mod(): Error while initializing"
829                                                                                 " module %s\n", m->exports->v1.name);
830                                                         return -1;
831                                                 } else {
832                                                         /* module correctly initialized */
833                                                         return 0;
834                                                 }
835                                         }
836                                         /* no init function -- proceed with success */
837                                         return 0;
838                         }
839                 }
840                 /* no exports -- proceed with success */
841                 return 0;
842         } else {
843                 /* end of list */
844                 return 0;
845         }
846 }
847
848 /*
849  * Initialize all loaded modules, the initialization
850  * is done *AFTER* the configuration file is parsed
851  */
852 int init_modules(void)
853 {
854         struct sr_module* t;
855         int i;
856         
857         for(t = modules; t; t = t->next)
858                 if (t->exports){
859                         switch(t->mod_interface_ver){
860                                 case 0:
861                                         if (t->exports->v0.response_f)
862                                                 mod_response_cbk_no++;
863                                         break;
864                                 case 1:
865                                         if (t->exports->v1.response_f)
866                                                 mod_response_cbk_no++;
867                                         break;
868                         }
869                 }
870         mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
871                                                                         sizeof(response_function));
872         if (mod_response_cbks==0){
873                 LOG(L_ERR, "init_modules(): memory allocation failure"
874                                         " for %d response_f callbacks\n", mod_response_cbk_no);
875                 return -1;
876         }
877         for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
878                 if (t->exports){
879                         switch(t->mod_interface_ver){
880                                 case 0:
881                                         if (t->exports->v0.response_f){
882                                                 mod_response_cbks[i]=t->exports->v0.response_f;
883                                                 i++;
884                                         }
885                                         break;
886                                 case 1:
887                                         if (t->exports->v1.response_f){
888                                                 mod_response_cbks[i]=t->exports->v1.response_f;
889                                                 i++;
890                                         }
891                                         break;
892                         }
893                 }
894         }
895         
896         return init_mod(modules);
897 }
898
899 #endif
900
901
902 action_u_t *fixup_get_param(void **cur_param, int cur_param_no,
903                                                         int required_param_no)
904 {
905         action_u_t *a, a2;
906         /* cur_param points to a->u.string, get pointer to a */
907         a = (void*) ((char *)cur_param - ((char *)&a2.u.string-(char *)&a2));
908         return a + required_param_no - cur_param_no;
909 }
910
911 int fixup_get_param_count(void **cur_param, int cur_param_no)
912 {
913         action_u_t *a;
914         a = fixup_get_param(cur_param, cur_param_no, 0);
915         if (a)
916                 return a->u.number;
917         else
918                 return -1;
919 }
920
921
922 /* fixes flag params (resolves possible named flags)
923  * use PARAM_USE_FUNC|PARAM_STRING as a param. type and create
924  * a wrapper function that does just:
925  * return fix_flag(type, val, "my_module", "my_param", &flag_var)
926  * see also param_func_t.
927  */
928 int fix_flag( modparam_t type, void* val,
929                                         char* mod_name, char* param_name, int* flag)
930 {
931         int num;
932         int err;
933         int f, len;
934         char* s;
935         char *p;
936
937         if ((type & PARAM_STRING)==0){
938                 LOG(L_CRIT, "BUG: %s: fix_flag(%s): bad parameter type\n",
939                                         mod_name, param_name);
940                 return -1;
941         }
942         s=(char*)val;
943         len=strlen(s);
944         f=-1;
945         /* try to see if it's a number */
946         num = str2s(s, len, &err);
947         if (err != 0) {
948                 /* see if it's in the name:<no> format */
949                 p=strchr(s, ':');
950                 if (p){
951                         f= str2s(p+1, strlen(p+1), &err);
952                         if (err!=0){
953                                 LOG(L_ERR, "ERROR: %s: invalid %s format:"
954                                                 " \"%s\"", mod_name, param_name, s);
955                                 return -1;
956                         }
957                         *p=0;
958                 }
959                 if ((num=get_flag_no(s, len))<0){
960                         /* not declared yet, declare it */
961                         num=register_flag(s, f);
962                 }
963                 if (num<0){
964                         LOG(L_ERR, "ERROR: %s: bad %s %s\n", mod_name, param_name, s);
965                         return -1;
966                 } else if ((f>0) && (num!=f)){
967                         LOG(L_ERR, "WARNING: %s: flag %s already defined"
968                                         " as %d (and not %d), using %s:%d\n",
969                                         mod_name, s, num, f, s, num);
970                 }
971         }
972         *flag=num;
973         return 0;
974 }
975
976 /*
977  * Common function parameter fixups
978  */
979
980 /** Generic parameter fixup function.
981  *  Creates a fparam_t structure.
982  *  @param type  contains allowed parameter types
983  *  @param param is the parameter that will be fixed-up
984  *
985  * @return
986  *    0 on success, 
987  *    1 if the param doesn't match the specified type
988  *    <0 on failure
989  */
990 int fix_param(int type, void** param)
991 {
992         fparam_t* p;
993         str name, s;
994         unsigned int num;
995         int err;
996
997         p = (fparam_t*)pkg_malloc(sizeof(fparam_t));
998         if (!p) {
999                 ERR("No memory left\n");
1000                 return E_OUT_OF_MEM;
1001         }
1002         memset(p, 0, sizeof(fparam_t));
1003         p->orig = *param;
1004         
1005         switch(type) {
1006                 case FPARAM_UNSPEC:
1007                         ERR("Invalid type value\n");
1008                         goto error;
1009                 case FPARAM_STRING:
1010                         p->v.asciiz = *param;
1011                 
1012                 case FPARAM_STR:
1013                         p->v.str.s = (char*)*param;
1014                         p->v.str.len = strlen(p->v.str.s);
1015                         break;
1016                 case FPARAM_INT:
1017                         s.s = (char*)*param;
1018                         s.len = strlen(s.s);
1019                         err = str2int(&s, &num);
1020                         if (err == 0) {
1021                                 p->v.i = (int)num;
1022                         } else {
1023                                 /* Not a number */
1024                                 pkg_free(p);
1025                                 return 1;
1026                         }
1027                         break;
1028                 case FPARAM_REGEX:
1029                         if ((p->v.regex = pkg_malloc(sizeof(regex_t))) == 0) {
1030                                 ERR("No memory left\n");
1031                         goto error;
1032                         }
1033                         if (regcomp(p->v.regex, *param,
1034                                                 REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
1035                                 pkg_free(p->v.regex);
1036                                 p->v.regex=0;
1037                                 ERR("Bad regular expression '%s'\n", (char*)*param);
1038                                 goto error;
1039                         }
1040                         break;
1041                 case FPARAM_AVP:
1042                         name.s = (char*)*param;
1043                         name.len = strlen(name.s);
1044                         trim(&name);
1045                         if (!name.len || name.s[0] != '$') {
1046                                 /* Not an AVP identifier */
1047                                 pkg_free(p);
1048                                 return 1;
1049                         }
1050                         name.s++;
1051                         name.len--;
1052                         if (parse_avp_ident(&name, &p->v.avp) < 0) {
1053                                 ERR("Error while parsing attribute name\n");
1054                                 goto error;
1055                         }
1056                         break;
1057                 case FPARAM_SELECT:
1058                         name.s = (char*)*param;
1059                         name.len = strlen(name.s);
1060                         trim(&name);
1061                         if (!name.len || name.s[0] != '@') {
1062                                 /* Not a select identifier */
1063                                 pkg_free(p);
1064                                 return 1;
1065                         }
1066                         if (parse_select(&name.s, &p->v.select) < 0) {
1067                                 ERR("Error while parsing select identifier\n");
1068                                 goto error;
1069                         }
1070                         break;
1071                 case FPARAM_SUBST:
1072                         s.s = *param;
1073                         s.len = strlen(s.s);
1074                         p->v.subst = subst_parser(&s);
1075                         if (!p->v.subst) {
1076                                 ERR("Error while parsing regex substitution\n");
1077                                 goto error;
1078                         }
1079                         break;
1080                 case FPARAM_PVS:
1081                         name.s = (char*)*param;
1082                         name.len = strlen(name.s);
1083                         trim(&name);
1084                         if (!name.len || name.s[0] != '$'){
1085                                 /* not a pvs identifier */
1086                                 pkg_free(p);
1087                                 return 1;
1088                         }
1089                         p->v.pvs=pkg_malloc(sizeof(pv_spec_t));
1090                         if (p->v.pvs==0){
1091                                 ERR("out of memory while parsing pv_spec_t\n");
1092                                 goto error;
1093                         }
1094                         if (pv_parse_spec(&name, p->v.pvs)==0){
1095                                 ERR("unsupported user field indentifier \"%.*s\"\n",
1096                                                 name.len, name.s);
1097                                 pkg_free(p->v.pvs);
1098                                 p->v.pvs=0;
1099                                 goto error;
1100                         }
1101                         break;
1102                 case FPARAM_PVE:
1103                         name.s = (char*)*param;
1104                         name.len = strlen(name.s);
1105                         if (pv_parse_format(&name, &p->v.pve)<0){
1106                                 ERR("bad PVE format: \"%.*s\"\n", name.len, name.s);
1107                                 goto error;
1108                         }
1109                         break;
1110         }
1111         
1112         p->type = type;
1113         *param = (void*)p;
1114         return 0;
1115         
1116 error:
1117         pkg_free(p);
1118         return E_UNSPEC;
1119 }
1120
1121
1122
1123 /** fparam_t free function.
1124  *  Frees the "content" of a fparam, but not the fparam itself.
1125  *  Assumes pkg_malloc'ed content.
1126  *  @param fp -  fparam to be freed
1127  *
1128  */
1129 void fparam_free_contents(fparam_t* fp)
1130 {
1131
1132         if (fp==0)
1133                 return;
1134         switch(fp->type) {
1135                 case FPARAM_UNSPEC:
1136                 case FPARAM_STRING: /* asciiz string, not str */
1137                 case FPARAM_INT:
1138                 case FPARAM_STR:
1139                         /* nothing to do */
1140                         return;
1141                 case FPARAM_REGEX:
1142                         if (fp->v.regex){
1143                                 regfree(fp->v.regex);
1144                                 pkg_free(fp->v.regex);
1145                                 fp->v.regex=0;
1146                         }
1147                         break;
1148                 case FPARAM_AVP:
1149                         free_avp_name(&fp->v.avp.flags, &fp->v.avp.name);
1150                         break;
1151                 case FPARAM_SELECT:
1152                         if (fp->v.select){
1153                                 free_select(fp->v.select);
1154                                 fp->v.select=0;
1155                         }
1156                         break;
1157                 case FPARAM_SUBST:
1158                         if (fp->v.subst){
1159                                 subst_expr_free(fp->v.subst);
1160                                 fp->v.subst=0;
1161                         }
1162                         break;
1163                 case FPARAM_PVS:
1164                         if (fp->v.pvs){
1165                                 pv_spec_free(fp->v.pvs);
1166                                 fp->v.pvs=0;
1167                         }
1168                         break;
1169                 case FPARAM_PVE:
1170                         if (fp->v.pve){
1171                                 pv_elem_free_all(fp->v.pve);
1172                                 fp->v.pve=0;
1173                         }
1174                         break;
1175         }
1176 }
1177
1178
1179
1180 /** fix a param to one of the given types (mask).
1181   *
1182   * @param types - bitmap of the allowed types (e.g. FPARAM_INT|FPARAM_STR)
1183   * @param param - value/result
1184   * @return - 0 on success, -1 on error, 1 if param doesn't
1185   *           match any of the types
1186   */
1187 int fix_param_types(int types, void** param)
1188 {
1189         int ret;
1190         int t;
1191         
1192         for (t=types & ~(types-1); types; types&=(types-1), t=types & ~(types-1)){
1193                 if ((ret=fix_param(t, param))<=0) return ret;
1194         }
1195         return E_UNSPEC;
1196 }
1197
1198
1199
1200 /*
1201  * Fixup variable string, the parameter can be
1202  * AVP, SELECT, or ordinary string. AVP and select
1203  * identifiers will be resolved to their values during
1204  * runtime
1205  *
1206  * The parameter value will be converted to fparam structure
1207  * This function returns -1 on an error
1208  */
1209 int fixup_var_str_12(void** param, int param_no)
1210 {
1211         int ret;
1212         if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
1213         if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
1214         if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
1215         ERR("Error while fixing parameter, AVP, SELECT, and str conversions"
1216                         " failed\n");
1217         return -1;
1218 }
1219
1220 /* Same as fixup_var_str_12 but applies to the 1st parameter only */
1221 int fixup_var_str_1(void** param, int param_no)
1222 {
1223         if (param_no == 1) return fixup_var_str_12(param, param_no);
1224         else return 0;
1225 }
1226
1227 /* Same as fixup_var_str_12 but applies to the 2nd parameter only */
1228 int fixup_var_str_2(void** param, int param_no)
1229 {
1230         if (param_no == 2) return fixup_var_str_12(param, param_no);
1231         else return 0;
1232 }
1233
1234
1235 /*
1236  * Fixup variable integer, the parameter can be
1237  * AVP, SELECT, or ordinary integer. AVP and select
1238  * identifiers will be resolved to their values and
1239  * converted to int if necessary during runtime
1240  *
1241  * The parameter value will be converted to fparam structure
1242  * This function returns -1 on an error
1243  */
1244 int fixup_var_int_12(void** param, int param_no)
1245 {
1246         int ret;
1247         if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
1248         if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
1249         if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
1250         ERR("Error while fixing parameter, AVP, SELECT, and int conversions"
1251                         " failed\n");
1252         return -1;
1253 }
1254
1255 /* Same as fixup_var_int_12 but applies to the 1st parameter only */
1256 int fixup_var_int_1(void** param, int param_no)
1257 {
1258         if (param_no == 1) return fixup_var_int_12(param, param_no);
1259         else return 0;
1260 }
1261
1262 /* Same as fixup_var_int_12 but applies to the 2nd parameter only */
1263 int fixup_var_int_2(void** param, int param_no)
1264 {
1265         if (param_no == 2) return fixup_var_int_12(param, param_no);
1266         else return 0;
1267 }
1268
1269
1270 /*
1271  * The parameter must be a regular expression which must compile, the
1272  * parameter will be converted to compiled regex
1273  */
1274 int fixup_regex_12(void** param, int param_no)
1275 {
1276         int ret;
1277
1278         if ((ret = fix_param(FPARAM_REGEX, param)) <= 0) return ret;
1279         ERR("Error while compiling regex in function parameter\n");
1280         return -1;
1281 }
1282
1283 /* Same as fixup_regex_12 but applies to the 1st parameter only */
1284 int fixup_regex_1(void** param, int param_no)
1285 {
1286         if (param_no == 1) return fixup_regex_12(param, param_no);
1287         else return 0;
1288 }
1289
1290 /* Same as fixup_regex_12 but applies to the 2nd parameter only */
1291 int fixup_regex_2(void** param, int param_no)
1292 {
1293         if (param_no == 2) return fixup_regex_12(param, param_no);
1294         else return 0;
1295 }
1296
1297 /*
1298  * The string parameter will be converted to integer
1299  */
1300 int fixup_int_12(void** param, int param_no)
1301 {
1302         int ret;
1303
1304         if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
1305         ERR("Cannot function parameter to integer\n");
1306         return -1;
1307
1308 }
1309
1310 /* Same as fixup_int_12 but applies to the 1st parameter only */
1311 int fixup_int_1(void** param, int param_no)
1312 {
1313         if (param_no == 1) return fixup_int_12(param, param_no);
1314         else return 0;
1315 }
1316
1317 /* Same as fixup_int_12 but applies to the 2nd parameter only */
1318 int fixup_int_2(void** param, int param_no)
1319 {
1320         if (param_no == 2) return fixup_int_12(param, param_no);
1321         else return 0;
1322 }
1323
1324 /*
1325  * Parse the parameter as static string, do not resolve
1326  * AVPs or selects, convert the parameter to str structure
1327  */
1328 int fixup_str_12(void** param, int param_no)
1329 {
1330         int ret;
1331
1332         if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
1333         ERR("Cannot function parameter to string\n");
1334         return -1;
1335 }
1336
1337 /* Same as fixup_str_12 but applies to the 1st parameter only */
1338 int fixup_str_1(void** param, int param_no)
1339 {
1340         if (param_no == 1) return fixup_str_12(param, param_no);
1341         else return 0;
1342 }
1343
1344 /* Same as fixup_str_12 but applies to the 2nd parameter only */
1345 int fixup_str_2(void** param, int param_no)
1346 {
1347         if (param_no == 2) return fixup_str_12(param, param_no);
1348         else return 0;
1349 }
1350
1351
1352 /** Get the function parameter value as string.
1353  *  @return  0 - Success
1354  *          -1 - Cannot get value
1355  */
1356 int get_str_fparam(str* dst, struct sip_msg* msg, fparam_t* param)
1357 {
1358         int_str val;
1359         int ret;
1360         avp_t* avp;
1361         pv_value_t pv_val;
1362         static char pve_buf[256]; /* ugly hack needed for PVE */
1363         
1364         switch(param->type) {
1365                 case FPARAM_REGEX:
1366                 case FPARAM_UNSPEC:
1367                 case FPARAM_INT:
1368                         return -1;
1369                 case FPARAM_STRING:
1370                         dst->s = param->v.asciiz;
1371                         dst->len = strlen(param->v.asciiz);
1372                         break;
1373                 case FPARAM_STR:
1374                         *dst = param->v.str;
1375                         break;
1376                 case FPARAM_AVP:
1377                         avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
1378                                                                         &val, 0);
1379                         if (unlikely(!avp)) {
1380                                 DBG("Could not find AVP from function parameter '%s'\n",
1381                                                 param->orig);
1382                                 return -1;
1383                         }
1384                         if (likely(avp->flags & AVP_VAL_STR)) {
1385                                 *dst = val.s;
1386                         } else {
1387                                 /* The caller does not know of what type the AVP will be so
1388                                  * convert int AVPs into string here
1389                                  */
1390                                 dst->s = int2str(val.n, &dst->len);
1391                         }
1392                         break;
1393                 case FPARAM_SELECT:
1394                         ret = run_select(dst, param->v.select, msg);
1395                         if (unlikely(ret < 0 || ret > 0)) return -1;
1396                         break;
1397                 case FPARAM_PVS:
1398                         if (likely((pv_get_spec_value(msg, param->v.pvs, &pv_val)==0) &&
1399                                            ((pv_val.flags&(PV_VAL_NULL|PV_VAL_STR))==PV_VAL_STR))){
1400                                         *dst=pv_val.rs;
1401                         }else{
1402                                 ERR("Could not convert PV to str\n");
1403                                 return -1;
1404                         }
1405                         break;
1406                 case FPARAM_PVE:
1407                         dst->len=sizeof(pve_buf);
1408                         if (unlikely(pv_printf(msg, param->v.pve, pve_buf, &dst->len)!=0)){
1409                                 ERR("Could not convert the PV-formated string to str\n");
1410                                 dst->len=0;
1411                                 return -1;
1412                         };
1413                         dst->s=pve_buf;
1414                         break;
1415         }
1416         return 0;
1417 }
1418
1419
1420 /** Get the function parameter value as integer.
1421  *  @return  0 - Success
1422  *          -1 - Cannot get value
1423  */
1424 int get_int_fparam(int* dst, struct sip_msg* msg, fparam_t* param)
1425 {
1426         int_str val;
1427         int ret;
1428         avp_t* avp;
1429         str tmp;
1430         pv_value_t pv_val;
1431
1432         switch(param->type) {
1433                 case FPARAM_INT:
1434                         *dst = param->v.i;
1435                         return 0;
1436                 case FPARAM_REGEX:
1437                 case FPARAM_UNSPEC:
1438                 case FPARAM_STRING:
1439                 case FPARAM_STR:
1440                         return -1;
1441                 case FPARAM_AVP:
1442                         avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
1443                                                                         &val, 0);
1444                         if (unlikely(!avp)) {
1445                                 DBG("Could not find AVP from function parameter '%s'\n",
1446                                                 param->orig);
1447                                 return -1;
1448                         }
1449                         if (avp->flags & AVP_VAL_STR) {
1450                                 if (str2int(&val.s, (unsigned int*)dst) < 0) {
1451                                         ERR("Could not convert AVP string value to int\n");
1452                                         return -1;
1453                                 }
1454                         } else {
1455                                 *dst = val.n;
1456                         }
1457                         break;
1458                 case FPARAM_SELECT:
1459                         ret = run_select(&tmp, param->v.select, msg);
1460                         if (unlikely(ret < 0 || ret > 0)) return -1;
1461                         if (unlikely(str2int(&tmp, (unsigned int*)dst) < 0)) {
1462                                 ERR("Could not convert select result to int\n");
1463                                 return -1;
1464                         }
1465                         break;
1466                 case FPARAM_PVS:
1467                         if (likely((pv_get_spec_value(msg, param->v.pvs, &pv_val)==0) &&
1468                                            ((pv_val.flags&(PV_VAL_NULL|PV_VAL_INT))==PV_VAL_INT))){
1469                                         *dst=pv_val.ri;
1470                         }else{
1471                                 ERR("Could not convert PV to int\n");
1472                                 return -1;
1473                         }
1474                         break;
1475                 case FPARAM_PVE:
1476                         return -1;
1477         }
1478         return 0;
1479 }
1480
1481 /**
1482  * Retrieve the compiled RegExp.
1483  * @return: 0 for success, negative on error.
1484  */
1485 int get_regex_fparam(regex_t *dst, struct sip_msg* msg, fparam_t* param)
1486 {
1487         switch (param->type) {
1488                 case FPARAM_REGEX:
1489                         *dst = *param->v.regex;
1490                         return 0;
1491                 default:
1492                         ERR("unexpected parameter type (%d), instead of regexp.\n", 
1493                                         param->type);
1494         }
1495         return -1;
1496 }