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