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