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