• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

sr_module.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2003 FhG Fokus
00003  *
00004  * This file is part of ser, a free SIP server.
00005  *
00006  * ser is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version
00010  *
00011  * For a license to use the ser software under conditions
00012  * other than those described here, or to purchase support for this
00013  * software, please contact iptel.org by e-mail at the following addresses:
00014  *    info@iptel.org
00015  *
00016  * ser is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  */
00025 
00026 /*
00027  * History:
00028  * --------
00029  *  2003-03-10  switched to new module_exports format: updated find_export,
00030  *               find_export_param, find_module (andrei)
00031  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
00032  *  2003-03-19  Support for flags in find_export (janakj)
00033  *  2003-03-29  cleaning pkg_mallocs introduced (jiri)
00034  *  2003-04-24  module version checking introduced (jiri)
00035  *  2004-09-19  compile flags are checked too (andrei)
00036  *  2005-01-07  removed find_module-overloading problems, added
00037  *               find_export_record
00038  *  2006-02-07  added fix_flag (andrei)
00039  *  2008-02-29  store all the reponse callbacks in their own array (andrei)
00040  *  2008-11-17  support dual module interface: ser & kamailio (andrei)
00041  *  2008-11-26  added fparam_free_contents() and fix_param_types (andrei)
00042  */
00043 
00052 #include "sr_module.h"
00053 #include "mod_fix.h"
00054 #include "dprint.h"
00055 #include "error.h"
00056 #include "mem/mem.h"
00057 #include "core_cmd.h"
00058 #include "ut.h"
00059 #include "re.h"
00060 #include "route_struct.h"
00061 #include "flags.h"
00062 #include "trim.h"
00063 #include "pvapi.h"
00064 #include "globals.h"
00065 #include "rpc_lookup.h"
00066 #include "sr_compat.h"
00067 
00068 #include <sys/stat.h>
00069 #include <regex.h>
00070 #include <dlfcn.h>
00071 #include <strings.h>
00072 #include <stdlib.h>
00073 #include <string.h>
00074 #include <stddef.h> /* for offsetof */
00075 
00076 
00077 struct sr_module* modules=0;
00078 
00079 /*We need to define this symbol on Solaris becuase libcurl relies on libnspr which looks for this symbol.
00080   If it is not defined, dynamic module loading (dlsym) fails */
00081 #ifdef __OS_solaris
00082         int nspr_use_zone_allocator = 0;
00083 #endif
00084 
00085 
00086 #ifdef STATIC_EXEC
00087         extern struct module_exports exec_exports;
00088 #endif
00089 #ifdef STATIC_TM
00090         extern struct module_exports tm_exports;
00091 #endif
00092 
00093 #ifdef STATIC_MAXFWD
00094         extern struct module_exports maxfwd_exports;
00095 #endif
00096 
00097 #ifdef STATIC_AUTH
00098         extern struct module_exports auth_exports;
00099 #endif
00100 
00101 #ifdef STATIC_RR
00102         extern struct module_exports rr_exports;
00103 #endif
00104 
00105 #ifdef STATIC_USRLOC
00106         extern struct module_exports usrloc_exports;
00107 #endif
00108 
00109 #ifdef STATIC_SL
00110         extern struct module_exports sl_exports;
00111 #endif
00112 
00113 #ifndef offsetof
00114 #warning "use null pointer dereference for offsetof"
00115 #define offsetof(st, m) \
00116                 ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))
00117 #endif
00118 
00119 int mod_response_cbk_no=0;
00120 response_function* mod_response_cbks=0;
00121 
00126 static int child_sip_rpc_mode = 0;
00127 
00128 #define CHILD_SIP_RPC   1<<0
00129 #define CHILD_RPC_SIP   1<<1
00130 
00131 void set_child_sip_rpc_mode(void)
00132 {
00133         child_sip_rpc_mode |= CHILD_SIP_RPC;
00134 }
00135 
00136 void set_child_rpc_sip_mode(void)
00137 {
00138         child_sip_rpc_mode |= CHILD_RPC_SIP;
00139 }
00140 
00141 int is_rpc_worker(int rank)
00142 {
00143         if(rank==PROC_RPC
00144                         || (rank>PROC_MAIN && (child_sip_rpc_mode&CHILD_SIP_RPC)!=0))
00145                 return 1;
00146         return 0;
00147 }
00148 
00149 int is_sip_worker(int rank)
00150 {
00151         if(rank>PROC_MAIN
00152                         || ((rank==PROC_RPC || rank==PROC_NOCHLDINIT)
00153                                         && (child_sip_rpc_mode&CHILD_RPC_SIP)!=0))
00154                 return 1;
00155         return 0;
00156 }
00157 
00158 /* initializes statically built (compiled in) modules*/
00159 int register_builtin_modules()
00160 {
00161         int ret;
00162 
00163         ret=0;
00164 #ifdef STATIC_TM
00165         ret=register_module(MODULE_INTERFACE_VER, &tm_exports,"built-in", 0);
00166         if (ret<0) return ret;
00167 #endif
00168 
00169 #ifdef STATIC_EXEC
00170         ret=register_module(MODULE_INTERFACE_VER, &exec_exports,"built-in", 0);
00171         if (ret<0) return ret;
00172 #endif
00173 
00174 #ifdef STATIC_MAXFWD
00175         ret=register_module(MODULE_INTERFACE_VER, &maxfwd_exports, "built-in", 0);
00176         if (ret<0) return ret;
00177 #endif
00178 
00179 #ifdef STATIC_AUTH
00180         ret=register_module(MODULE_INTERFACE_VER, &auth_exports, "built-in", 0);
00181         if (ret<0) return ret;
00182 #endif
00183 
00184 #ifdef STATIC_RR
00185         ret=register_module(MODULE_INTERFACE_VER, &rr_exports, "built-in", 0);
00186         if (ret<0) return ret;
00187 #endif
00188 
00189 #ifdef STATIC_USRLOC
00190         ret=register_module(MODULE_INTERFACE_VER, &usrloc_exports, "built-in", 0);
00191         if (ret<0) return ret;
00192 #endif
00193 
00194 #ifdef STATIC_SL
00195         ret=register_module(MODULE_INTERFACE_VER, &sl_exports, "built-in", 0);
00196         if (ret<0) return ret;
00197 #endif
00198 
00199         return ret;
00200 }
00201 
00202 
00203 
00213 static sr31_cmd_export_t* sr_cmd_exports_convert(unsigned ver,
00214                                                                                                         void* src, void* mod)
00215 {
00216         int i, n;
00217         ser_cmd_export_t* ser_cmd;
00218         kam_cmd_export_t* kam_cmd;
00219         sr31_cmd_export_t* ret;
00220         
00221         ser_cmd = 0;
00222         kam_cmd = 0;
00223         ret = 0;
00224         n = 0;
00225         /* count the number of elements */
00226         if (ver == 0) {
00227                 ser_cmd = src;
00228                 for (; ser_cmd[n].name; n++);
00229         } else if (ver == 1) {
00230                 kam_cmd = src;
00231                 for (; kam_cmd[n].name; n++);
00232         } else goto error; /* unknown interface version */
00233         /* alloc & init new array */
00234         ret = pkg_malloc(sizeof(*ret)*(n+1));
00235         memset(ret, 0, sizeof(*ret)*(n+1));
00236         /* convert/copy */
00237         for (i=0; i < n; i++) {
00238                 if (ver == 0) {
00239                         ret[i].name = ser_cmd[i].name;
00240                         ret[i].function = ser_cmd[i].function;
00241                         ret[i].param_no = ser_cmd[i].param_no;
00242                         ret[i].fixup = ser_cmd[i].fixup;
00243                         ret[i].free_fixup = 0; /* no present in ser  <= 2.1 */
00244                         ret[i].flags = ser_cmd[i].flags;
00245                 } else {
00246                         ret[i].name = kam_cmd[i].name;
00247                         ret[i].function = kam_cmd[i].function;
00248                         ret[i].param_no = kam_cmd[i].param_no;
00249                         ret[i].fixup = kam_cmd[i].fixup;
00250                         ret[i].free_fixup = kam_cmd[i].free_fixup;
00251                         ret[i].flags = kam_cmd[i].flags;
00252                 }
00253                 /* 3.1+ specific stuff */
00254                 ret[i].fixup_flags = 0;
00255                 ret[i].module_exports = mod;
00256                 /* fill known free fixups */
00257                 if (ret[i].fixup && ret[i].free_fixup == 0)
00258                         ret[i].free_fixup = get_fixup_free(ret[i].fixup);
00259         }
00260         return ret;
00261 error:
00262         return 0;
00263 }
00264 
00265 
00266 
00267 /* registers a module,  register_f= module register  functions
00268  * returns <0 on error, 0 on success */
00269 static int register_module(unsigned ver, union module_exports_u* e,
00270                                         char* path, void* handle)
00271 {
00272         int ret, i;
00273         struct sr_module* mod;
00274 
00275         ret=-1;
00276 
00277         /* add module to the list */
00278         if ((mod=pkg_malloc(sizeof(struct sr_module)))==0){
00279                 LOG(L_ERR, "load_module: memory allocation failure\n");
00280                 ret=E_OUT_OF_MEM;
00281                 goto error;
00282         }
00283         memset(mod,0, sizeof(struct sr_module));
00284         mod->path=path;
00285         mod->handle=handle;
00286         mod->orig_mod_interface_ver=ver;
00287         /* convert exports to sr31 format */
00288         if (ver == 0) {
00289                 /* ser <= 3.0 */
00290                 mod->exports.name = e->v0.name;
00291                 if (e->v0.cmds) {
00292                         mod->exports.cmds = sr_cmd_exports_convert(ver, e->v0.cmds, mod);
00293                         if (mod->exports.cmds == 0) {
00294                                 ERR("failed to convert module command exports to 3.1 format"
00295                                                 " for module \"%s\" (%s), interface version %d\n",
00296                                                 mod->exports.name, mod->path, ver);
00297                                 ret = E_UNSPEC;
00298                                 goto error;
00299                         }
00300                 }
00301                 mod->exports.params = e->v0.params;
00302                 mod->exports.init_f = e->v0.init_f;
00303                 mod->exports.response_f = e->v0.response_f;
00304                 mod->exports.destroy_f = e->v0.destroy_f;
00305                 mod->exports.onbreak_f = e->v0.onbreak_f;
00306                 mod->exports.init_child_f = e->v0.init_child_f;
00307                 mod->exports.dlflags = 0; /* not used in ser <= 3.0 */
00308                 mod->exports.rpc_methods = e->v0.rpc_methods;
00309                 /* the rest are 0, not used in ser */
00310         } else if (ver == 1) {
00311                 /* kamailio <= 3.0 */
00312                 mod->exports.name = e->v1.name;
00313                 if (e->v1.cmds) {
00314                         mod->exports.cmds = sr_cmd_exports_convert(ver, e->v1.cmds, mod);
00315                         if (mod->exports.cmds == 0) {
00316                                 ERR("failed to convert module command exports to 3.1 format"
00317                                                 " for module \"%s\" (%s), interface version %d\n",
00318                                                 mod->exports.name, mod->path, ver);
00319                                 ret = E_UNSPEC;
00320                                 goto error;
00321                         }
00322                 }
00323                 mod->exports.params = e->v1.params;
00324                 mod->exports.init_f = e->v1.init_f;
00325                 mod->exports.response_f = e->v1.response_f;
00326                 mod->exports.destroy_f = e->v1.destroy_f;
00327                 mod->exports.onbreak_f = 0; /* not used in k <= 3.0 */
00328                 mod->exports.init_child_f = e->v1.init_child_f;
00329                 mod->exports.dlflags = e->v1.dlflags;
00330                 mod->exports.rpc_methods = 0; /* not used in k <= 3.0 */
00331                 mod->exports.stats = e->v1.stats;
00332                 mod->exports.mi_cmds = e->v1.mi_cmds;
00333                 mod->exports.items = e->v1.items;
00334                 mod->exports.procs = e->v1.procs;
00335         } else {
00336                 ERR("unsupported module interface version %d\n", ver);
00337                 ret = E_UNSPEC;
00338                 goto error;
00339         }
00340 
00341         if (mod->exports.items) {
00342                 /* register module pseudo-variables for kamailio modules */
00343                 LM_DBG("register PV from: %s\n", mod->exports.name);
00344                 if (register_pvars_mod(mod->exports.name, mod->exports.items)!=0) {
00345                         LM_ERR("failed to register pseudo-variables for module %s (%s)\n",
00346                                 mod->exports.name, path);
00347                         ret = E_UNSPEC;
00348                         goto error;
00349                 }
00350         }
00351         if (mod->exports.rpc_methods){
00352                 /* register rpcs for ser modules */
00353                 i=rpc_register_array(mod->exports.rpc_methods);
00354                 if (i<0){
00355                         ERR("failed to register RPCs for module %s (%s)\n",
00356                                         mod->exports.name, path);
00357                         ret = E_UNSPEC;
00358                         goto error;
00359                 }else if (i>0){
00360                         ERR("%d duplicate RPCs name detected while registering RPCs"
00361                                         " declared in module %s (%s)\n",
00362                                         i, mod->exports.name, path);
00363                         ret = E_UNSPEC;
00364                         goto error;
00365                 }
00366                 /* i==0 => success */
00367         }
00368 
00369         /* link module in the list */
00370         mod->next=modules;
00371         modules=mod;
00372         return 0;
00373 error:
00374         if (mod)
00375                 pkg_free(mod);
00376         return ret;
00377 }
00378 
00379 #ifndef DLSYM_PREFIX
00380 /* define it to null */
00381 #define DLSYM_PREFIX
00382 #endif
00383 
00384 static inline int version_control(void *handle, char *path)
00385 {
00386         char **m_ver;
00387         char **m_flags;
00388         char* error;
00389 
00390         m_ver=(char **)dlsym(handle, DLSYM_PREFIX "module_version");
00391         if ((error=(char *)dlerror())!=0) {
00392                 LOG(L_ERR, "ERROR: no version info in module <%s>: %s\n",
00393                         path, error );
00394                 return 0;
00395         }
00396         m_flags=(char **)dlsym(handle, DLSYM_PREFIX "module_flags");
00397         if ((error=(char *)dlerror())!=0) {
00398                 LOG(L_ERR, "ERROR: no compile flags info in module <%s>: %s\n",
00399                         path, error );
00400                 return 0;
00401         }
00402         if (!m_ver || !(*m_ver)) {
00403                 LOG(L_ERR, "ERROR: no version in module <%s>\n", path );
00404                 return 0;
00405         }
00406         if (!m_flags || !(*m_flags)) {
00407                 LOG(L_ERR, "ERROR: no compile flags in module <%s>\n", path );
00408                 return 0;
00409         }
00410 
00411         if (strcmp(SER_FULL_VERSION, *m_ver)==0){
00412                 if (strcmp(SER_COMPILE_FLAGS, *m_flags)==0)
00413                         return 1;
00414                 else {
00415                         LOG(L_ERR, "ERROR: module compile flags mismatch for %s "
00416                                                 " \ncore: %s \nmodule: %s\n",
00417                                                 path, SER_COMPILE_FLAGS, *m_flags);
00418                         return 0;
00419                 }
00420         }
00421         LOG(L_ERR, "ERROR: module version mismatch for %s; "
00422                 "core: %s; module: %s\n", path, SER_FULL_VERSION, *m_ver );
00423         return 0;
00424 }
00425 
00440 int load_module(char* mod_path)
00441 {
00442         void* handle;
00443         char* error;
00444         mod_register_function mr;
00445         union module_exports_u* exp;
00446         unsigned* mod_if_ver;
00447         struct sr_module* t;
00448         struct stat stat_buf;
00449         str modname;
00450         char* mdir;
00451         char* nxt_mdir;
00452         char* path;
00453         int mdir_len;
00454         int len;
00455         int dlflags;
00456         int new_dlflags;
00457         int retries;
00458         int path_type;
00459 
00460 #ifndef RTLD_NOW
00461 /* for openbsd */
00462 #define RTLD_NOW DL_LAZY
00463 #endif
00464         path=mod_path;
00465         path_type = 0;
00466         modname.s = path;
00467         modname.len = strlen(mod_path);
00468         if(modname.len>3 && strcmp(modname.s+modname.len-3, ".so")==0) {
00469                 path_type = 1;
00470                 modname.len -= 3;
00471         }
00472         if (!strchr(path, '/'))
00473                 path_type |= 2;
00474         if((path_type&2) || path[0] != '/') {
00475                 /* module name was given, we try to construct the path */
00476                 mdir=mods_dir; /* search path */
00477                 do{
00478                         nxt_mdir=strchr(mdir, ':');
00479                         if (nxt_mdir) mdir_len=(int)(nxt_mdir-mdir);
00480                         else mdir_len=strlen(mdir);
00481                         
00482                         if(path_type&2) {
00483                                 /* try path <MODS_DIR>/<modname>.so */
00484                                 path = (char*)pkg_malloc(mdir_len + 1 /* "/" */ +
00485                                                                         modname.len + 3 /* ".so" */ + 1);
00486                                 if (path==0) goto error;
00487                                 memcpy(path, mdir, mdir_len);
00488                                 len = mdir_len;
00489                                 if (len != 0 && path[len - 1] != '/'){
00490                                         path[len]='/';
00491                                         len++;
00492                                 }
00493                                 path[len]=0;
00494                                 strcat(path, modname.s);
00495                                 if(!(path_type&1))
00496                                         strcat(path, ".so");
00497 
00498                                 if (stat(path, &stat_buf) == -1) {
00499                                         DBG("load_module: module file not found <%s>\n", path);
00500                                         pkg_free(path);
00501 
00502                                         /* try path <MODS_DIR>/<modname>/<modname>.so */
00503                                         path = (char*)pkg_malloc(
00504                                                 mdir_len + 1 /* "/" */ +
00505                                                 modname.len + 1 /* "/" */ +
00506                                                 modname.len + 3 /* ".so" */ + 1);
00507                                         if (path==0) goto error;
00508                                         memcpy(path, mdir, mdir_len);
00509                                         len = mdir_len;
00510                                         if (len != 0 && path[len - 1] != '/') {
00511                                                 path[len]='/';
00512                                                 len++;
00513                                         }
00514                                         path[len]=0;
00515                                         strncat(path, modname.s, modname.len);
00516                                         strcat(path, "/");
00517                                         strcat(path, modname.s);
00518                                         if(!(path_type&1))
00519                                                 strcat(path, ".so");
00520 
00521                                         if (stat(path, &stat_buf) == -1) {
00522                                                 DBG("load_module: module file not found <%s>\n", path);
00523                                                 pkg_free(path);
00524                                                 path=0;
00525                                         }
00526                                 }
00527                         } else {
00528                                 /* try mod_path - S compat */
00529                                 if(path==mod_path) {
00530                                         if (stat(path, &stat_buf) == -1) {
00531                                                 DBG("load_module: module file not found <%s>\n", path);
00532                                                 path=0;
00533                                         }
00534                                 }
00535                                 if(path==0) {
00536                                         /* try path <MODS_DIR>/mod_path - K compat */
00537                                         path = (char*)pkg_malloc(mdir_len + 1 /* "/" */ +
00538                                                                         strlen(mod_path) + 1);
00539                                         if (path==0) goto error;
00540                                         memcpy(path, mdir, mdir_len);
00541                                         len = mdir_len;
00542                                         if (len != 0 && path[len - 1] != '/'){
00543                                                 path[len]='/';
00544                                                 len++;
00545                                         }
00546                                         path[len]=0;
00547                                         strcat(path, mod_path);
00548 
00549                                         if (stat(path, &stat_buf) == -1) {
00550                                                 DBG("load_module: module file not found <%s>\n", path);
00551                                                 pkg_free(path);
00552                                                 path=0;
00553                                         }
00554                                 }
00555                         }
00556                         mdir=nxt_mdir?nxt_mdir+1:0;
00557                 }while(path==0 && mdir);
00558                 if (path==0){
00559                         LOG(L_ERR, "ERROR: load_module: could not find module <%.*s> in"
00560                                                 " <%s>\n", modname.len, modname.s, mods_dir);
00561                         goto error;
00562                 }
00563         }
00564         DBG("load_module: trying to load <%s>\n", path);
00565 
00566         retries=2;
00567         dlflags=RTLD_NOW;
00568 reload:
00569         handle=dlopen(path, dlflags); /* resolve all symbols now */
00570         if (handle==0){
00571                 LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n",
00572                         path, dlerror());
00573                 goto error;
00574         }
00575 
00576         for(t=modules;t; t=t->next){
00577                 if (t->handle==handle){
00578                         LOG(L_WARN, "WARNING: load_module: attempting to load the same"
00579                                                 " module twice (%s)\n", path);
00580                         goto skip;
00581                 }
00582         }
00583         /* version control */
00584         if (!version_control(handle, path)) {
00585                 exit(0);
00586         }
00587         mod_if_ver = (unsigned *)dlsym(handle,
00588                                                                         DLSYM_PREFIX "module_interface_ver");
00589         if ( (error =(char*)dlerror())!=0 ){
00590                 LOG(L_ERR, "ERROR: no module interface version in module <%s>\n",
00591                                         path );
00592                 goto error1;
00593         }
00594         /* launch register */
00595         mr = (mod_register_function)dlsym(handle, DLSYM_PREFIX "mod_register");
00596         if (((error =(char*)dlerror())==0) && mr) {
00597                 /* no error call it */
00598                 new_dlflags=dlflags;
00599                 if (mr(path, &new_dlflags, 0, 0)!=0) {
00600                         LOG(L_ERR, "ERROR: load_module: %s: mod_register failed\n", path);
00601                         goto error1;
00602                 }
00603                 if (new_dlflags!=dlflags && new_dlflags!=0) {
00604                         /* we have to reload the module */
00605                         dlclose(handle);
00606                         dlflags=new_dlflags;
00607                         retries--;
00608                         if (retries>0) goto reload;
00609                         LOG(L_ERR, "ERROR: load_module: %s: cannot agree"
00610                                         " on the dlflags\n", path);
00611                         goto error;
00612                 }
00613         }
00614         exp = (union module_exports_u*)dlsym(handle, DLSYM_PREFIX "exports");
00615         if ( (error =(char*)dlerror())!=0 ){
00616                 LOG(L_ERR, "ERROR: load_module: %s\n", error);
00617                 goto error1;
00618         }
00619         /* hack to allow for kamailio style dlflags inside exports */
00620         if (*mod_if_ver == 1) {
00621                 new_dlflags = exp->v1.dlflags;
00622                 if (new_dlflags!=dlflags && new_dlflags!=DEFAULT_DLFLAGS) {
00623                         /* we have to reload the module */
00624                         dlclose(handle);
00625                         NOTICE("%s: exports dlflags interface is deprecated and it will not"
00626                                         " be supported in newer versions; consider using"
00627                                         " mod_register() instead\n", path);
00628                         dlflags=new_dlflags;
00629                         retries--;
00630                         if (retries>0) goto reload;
00631                         LOG(L_ERR, "ERROR: load_module: %s: cannot agree"
00632                                         " on the dlflags\n", path);
00633                         goto error;
00634                 }
00635         }
00636         if (register_module(*mod_if_ver, exp, path, handle)<0) goto error1;
00637         return 0;
00638 
00639 error1:
00640         dlclose(handle);
00641 error:
00642 skip:
00643         if (path && path!=mod_path)
00644                 pkg_free(path);
00645         return -1;
00646 }
00647 
00648 
00649 
00650 /* searches the module list for function name in module mod and returns 
00651  *  a pointer to the "name" function record union or 0 if not found
00652  * sets also *mod_if_ver to the original module interface version.
00653  * mod==0 is a wildcard matching all modules
00654  * flags parameter is OR value of all flags that must match
00655  */
00656 sr31_cmd_export_t* find_mod_export_record(char* mod, char* name,
00657                                                                                         int param_no, int flags,
00658                                                                                         unsigned* mod_if_ver)
00659 {
00660         struct sr_module* t;
00661         sr31_cmd_export_t* cmd;
00662 
00663         for(t=modules;t;t=t->next){
00664                 if (mod!=0 && (strcmp(t->exports.name, mod) !=0))
00665                         continue;
00666                 if (t->exports.cmds)
00667                         for(cmd=&t->exports.cmds[0]; cmd->name; cmd++) {
00668                                 if((strcmp(name, cmd->name) == 0) &&
00669                                         ((cmd->param_no == param_no) ||
00670                                          (cmd->param_no==VAR_PARAM_NO)) &&
00671                                         ((cmd->flags & flags) == flags)
00672                                 ){
00673                                         DBG("find_export_record: found <%s> in module %s [%s]\n",
00674                                                 name, t->exports.name, t->path);
00675                                         *mod_if_ver=t->orig_mod_interface_ver;
00676                                         return cmd;
00677                                 }
00678                         }
00679         }
00680         DBG("find_export_record: <%s> not found \n", name);
00681         return 0;
00682 }
00683 
00684 
00685 
00686 /* searches the module list for function name and returns 
00687  *  a pointer to the "name" function record union or 0 if not found
00688  * sets also *mod_if_ver to the module interface version (needed to know
00689  * which member of the union should be accessed v0 or v1)
00690  * mod==0 is a wildcard matching all modules
00691  * flags parameter is OR value of all flags that must match
00692  */
00693 sr31_cmd_export_t* find_export_record(char* name,
00694                                                                                         int param_no, int flags,
00695                                                                                         unsigned* mod_if_ver)
00696 {
00697         return find_mod_export_record(0, name, param_no, flags, mod_if_ver);
00698 }
00699 
00700 
00701 
00702 cmd_function find_export(char* name, int param_no, int flags)
00703 {
00704         sr31_cmd_export_t* cmd;
00705         unsigned mver;
00706         
00707         cmd = find_export_record(name, param_no, flags, &mver);
00708         return cmd?cmd->function:0;
00709 }
00710 
00711 
00712 rpc_export_t* find_rpc_export(char* name, int flags)
00713 {
00714         return rpc_lookup((char*)name, strlen(name));
00715 }
00716 
00717 
00718 /*
00719  * searches the module list and returns pointer to "name" function in module
00720  * "mod"
00721  * 0 if not found
00722  * flags parameter is OR value of all flags that must match
00723  */
00724 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
00725 {
00726         sr31_cmd_export_t* cmd;
00727         unsigned mver;
00728 
00729         cmd=find_mod_export_record(mod, name, param_no, flags, &mver);
00730         if (cmd)
00731                 return cmd->function;
00732         
00733         DBG("find_mod_export: <%s> in module <%s> not found\n", name, mod);
00734         return 0;
00735 }
00736 
00737 
00738 struct sr_module* find_module_by_name(char* mod) {
00739         struct sr_module* t;
00740 
00741         for(t = modules; t; t = t->next) {
00742                 if (strcmp(mod, t->exports.name) == 0) {
00743                         return t;
00744                 }
00745         }
00746         DBG("find_module_by_name: module <%s> not found\n", mod);
00747         return 0;
00748 }
00749 
00750 
00759 void* find_param_export(struct sr_module* mod, char* name,
00760                                                 modparam_t type_mask, modparam_t *param_type)
00761 {
00762         param_export_t* param;
00763 
00764         if (!mod)
00765                 return 0;
00766         for(param = mod->exports.params ;param && param->name ; param++) {
00767                 if ((strcmp(name, param->name) == 0) &&
00768                         ((param->type & PARAM_TYPE_MASK(type_mask)) != 0)) {
00769                         DBG("find_param_export: found <%s> in module %s [%s]\n",
00770                                 name, mod->exports.name, mod->path);
00771                         *param_type = param->type;
00772                         return param->param_pointer;
00773                 }
00774         }
00775         DBG("find_param_export: parameter <%s> not found in module <%s>\n",
00776                         name, mod->exports.name);
00777         return 0;
00778 }
00779 
00780 
00781 void destroy_modules()
00782 {
00783         struct sr_module* t, *foo;
00784 
00785         /* call first destroy function from each module */
00786         t=modules;
00787         while(t) {
00788                 foo=t->next;
00789                 if (t->exports.destroy_f){
00790                         t->exports.destroy_f();
00791                 }
00792                 t=foo;
00793         }
00794         /* free module exports structures */
00795         t=modules;
00796         while(t) {
00797                 foo=t->next;
00798                 pkg_free(t);
00799                 t=foo;
00800         }
00801         modules=0;
00802         if (mod_response_cbks){
00803                 pkg_free(mod_response_cbks);
00804                 mod_response_cbks=0;
00805         }
00806 }
00807 
00808 #ifdef NO_REVERSE_INIT
00809 
00810 /*
00811  * Initialize all loaded modules, the initialization
00812  * is done *AFTER* the configuration file is parsed
00813  */
00814 int init_modules(void)
00815 {
00816         struct sr_module* t;
00817 
00818         for(t = modules; t; t = t->next) {
00819                 if (t->exports.init_f)
00820                         if (t->exports.init_f() != 0) {
00821                                 LOG(L_ERR, "init_modules(): Error while"
00822                                                 " initializing module %s\n", t->exports.name);
00823                                 return -1;
00824                         }
00825                 if (t->exports.response_f)
00826                         mod_response_cbk_no++;
00827         }
00828         mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
00829                                                                         sizeof(response_function));
00830         if (mod_response_cbks==0){
00831                 LOG(L_ERR, "init_modules(): memory allocation failure"
00832                                         " for %d response_f callbacks\n", mod_response_cbk_no);
00833                 return -1;
00834         }
00835         for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next) {
00836                 if (t->exports.response_f) {
00837                         mod_response_cbks[i]=t->exports.response_f;
00838                         i++;
00839                 }
00840         }
00841         return 0;
00842 }
00843 
00844 
00845 
00846 /*
00847  * per-child initialization
00848  */
00849 int init_child(int rank)
00850 {
00851         struct sr_module* t;
00852         char* type;
00853 
00854         switch(rank) {
00855         case PROC_MAIN:     type = "PROC_MAIN";     break;
00856         case PROC_TIMER:    type = "PROC_TIMER";    break;
00857         case PROC_FIFO:     type = "PROC_FIFO";     break;
00858         case PROC_TCP_MAIN: type = "PROC_TCP_MAIN"; break;
00859         default:            type = "CHILD";         break;
00860         }
00861         DBG("init_child: initializing %s with rank %d\n", type, rank);
00862 
00863 
00864         for(t = modules; t; t = t->next) {
00865                 if (t->exports.init_child_f) {
00866                         if ((t->exports.init_child_f(rank)) < 0) {
00867                                 LOG(L_ERR, "init_child(): Initialization of child"
00868                                                         " %d failed\n", rank);
00869                                 return -1;
00870                         }
00871                 }
00872         }
00873         return 0;
00874 }
00875 
00876 #else
00877 
00878 
00879 /* recursive module child initialization; (recursion is used to
00880    process the module linear list in the same order in
00881    which modules are loaded in config file
00882 */
00883 
00884 static int init_mod_child( struct sr_module* m, int rank )
00885 {
00886         if (m) {
00887                 /* iterate through the list; if error occurs,
00888                    propagate it up the stack
00889                  */
00890                 if (init_mod_child(m->next, rank)!=0) return -1;
00891                 if (m->exports.init_child_f) {
00892                         DBG("DEBUG: init_mod_child (%d): %s\n", rank, m->exports.name);
00893                         if (m->exports.init_child_f(rank)<0) {
00894                                 LOG(L_ERR, "init_mod_child(): Error while"
00895                                                         " initializing module %s (%s)\n",
00896                                                         m->exports.name, m->path);
00897                                 return -1;
00898                         } else {
00899                                 /* module correctly initialized */
00900                                 return 0;
00901                         }
00902                 }
00903                 /* no init function -- proceed with success */
00904                 return 0;
00905         } else {
00906                 /* end of list */
00907                 return 0;
00908         }
00909 }
00910 
00911 
00912 /*
00913  * per-child initialization
00914  */
00915 int init_child(int rank)
00916 {
00917         return init_mod_child(modules, rank);
00918 }
00919 
00920 
00921 
00922 /* recursive module initialization; (recursion is used to
00923    process the module linear list in the same order in
00924    which modules are loaded in config file
00925 */
00926 
00927 static int init_mod( struct sr_module* m )
00928 {
00929         if (m) {
00930                 /* iterate through the list; if error occurs,
00931                    propagate it up the stack
00932                  */
00933                 if (init_mod(m->next)!=0) return -1;
00934                         if (m->exports.init_f) {
00935                                 DBG("DEBUG: init_mod: %s\n", m->exports.name);
00936                                 if (m->exports.init_f()!=0) {
00937                                         LOG(L_ERR, "init_mod(): Error while initializing"
00938                                                                 " module %s (%s)\n",
00939                                                                 m->exports.name, m->path);
00940                                         return -1;
00941                                 } else {
00942                                         /* module correctly initialized */
00943                                         return 0;
00944                                 }
00945                         }
00946                         /* no init function -- proceed with success */
00947                         return 0;
00948         } else {
00949                 /* end of list */
00950                 return 0;
00951         }
00952 }
00953 
00954 /*
00955  * Initialize all loaded modules, the initialization
00956  * is done *AFTER* the configuration file is parsed
00957  */
00958 int init_modules(void)
00959 {
00960         struct sr_module* t;
00961         int i;
00962         
00963         i = init_mod(modules);
00964         if(i!=0)
00965                 return i;
00966 
00967         for(t = modules; t; t = t->next)
00968                 if (t->exports.response_f)
00969                         mod_response_cbk_no++;
00970         mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
00971                                                                         sizeof(response_function));
00972         if (mod_response_cbks==0){
00973                 LOG(L_ERR, "init_modules(): memory allocation failure"
00974                                         " for %d response_f callbacks\n", mod_response_cbk_no);
00975                 return -1;
00976         }
00977         for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next)
00978                 if (t->exports.response_f) {
00979                         mod_response_cbks[i]=t->exports.response_f;
00980                         i++;
00981                 }
00982         
00983         return 0;
00984 }
00985 
00986 #endif
00987 
00988 
00989 action_u_t *fixup_get_param(void **cur_param, int cur_param_no,
00990                                                         int required_param_no)
00991 {
00992         action_u_t *a;
00993         /* cur_param points to a->u.string, get pointer to a */
00994         a = (void*) ((char *)cur_param - offsetof(action_u_t, u.string));
00995         return a + required_param_no - cur_param_no;
00996 }
00997 
00998 int fixup_get_param_count(void **cur_param, int cur_param_no)
00999 {
01000         action_u_t *a;
01001         a = fixup_get_param(cur_param, cur_param_no, 0);
01002         if (a)
01003                 return a->u.number;
01004         else
01005                 return -1;
01006 }
01007 
01008 
01009 
01014 action_param_type* fixup_get_param_ptype(void** param)
01015 {
01016         action_u_t* a;
01017         a = (void*)((char*)param - offsetof(action_u_t, u.string));
01018         return &a->type;
01019 }
01020 
01021 
01026 action_param_type fixup_get_param_type(void** param)
01027 {
01028         return *fixup_get_param_ptype(param);
01029 }
01030 
01031 
01032 
01033 /* fixes flag params (resolves possible named flags)
01034  * use PARAM_USE_FUNC|PARAM_STRING as a param. type and create
01035  * a wrapper function that does just:
01036  * return fix_flag(type, val, "my_module", "my_param", &flag_var)
01037  * see also param_func_t.
01038  */
01039 int fix_flag( modparam_t type, void* val,
01040                                         char* mod_name, char* param_name, int* flag)
01041 {
01042         int num;
01043         int err;
01044         int f, len;
01045         char* s;
01046         char *p;
01047 
01048         if ((type & PARAM_STRING)==0){
01049                 LOG(L_CRIT, "BUG: %s: fix_flag(%s): bad parameter type\n",
01050                                         mod_name, param_name);
01051                 return -1;
01052         }
01053         s=(char*)val;
01054         len=strlen(s);
01055         f=-1;
01056         /* try to see if it's a number */
01057         num = str2s(s, len, &err);
01058         if (err != 0) {
01059                 /* see if it's in the name:<no> format */
01060                 p=strchr(s, ':');
01061                 if (p){
01062                         f= str2s(p+1, strlen(p+1), &err);
01063                         if (err!=0){
01064                                 LOG(L_ERR, "ERROR: %s: invalid %s format:"
01065                                                 " \"%s\"", mod_name, param_name, s);
01066                                 return -1;
01067                         }
01068                         *p=0;
01069                 }
01070                 if ((num=get_flag_no(s, len))<0){
01071                         /* not declared yet, declare it */
01072                         num=register_flag(s, f);
01073                 }
01074                 if (num<0){
01075                         LOG(L_ERR, "ERROR: %s: bad %s %s\n", mod_name, param_name, s);
01076                         return -1;
01077                 } else if ((f>0) && (num!=f)){
01078                         LOG(L_ERR, "WARNING: %s: flag %s already defined"
01079                                         " as %d (and not %d), using %s:%d\n",
01080                                         mod_name, s, num, f, s, num);
01081                 }
01082         }
01083         *flag=num;
01084         return 0;
01085 }
01086 
01087 /*
01088  * Common function parameter fixups
01089  */
01090 
01101 int fix_param(int type, void** param)
01102 {
01103         fparam_t* p;
01104         str name, s;
01105         int num;
01106         int err;
01107 
01108         p = (fparam_t*)pkg_malloc(sizeof(fparam_t));
01109         if (!p) {
01110                 ERR("No memory left\n");
01111                 return E_OUT_OF_MEM;
01112         }
01113         memset(p, 0, sizeof(fparam_t));
01114         p->orig = *param;
01115         
01116         switch(type) {
01117                 case FPARAM_UNSPEC:
01118                         ERR("Invalid type value\n");
01119                         goto error;
01120                 case FPARAM_STRING:
01121                         p->v.asciiz = *param;
01122                         /* no break */
01123                 case FPARAM_STR:
01124                         p->v.str.s = (char*)*param;
01125                         p->v.str.len = strlen(p->v.str.s);
01126                         p->fixed = &p->v;
01127                         break;
01128                 case FPARAM_INT:
01129                         s.s = (char*)*param;
01130                         s.len = strlen(s.s);
01131                         err = str2sint(&s, &num);
01132                         if (err == 0) {
01133                                 p->v.i = (int)num;
01134                         } else {
01135                                 /* Not a number */
01136                                 pkg_free(p);
01137                                 return 1;
01138                         }
01139                         p->fixed = (void*)(long)num;
01140                         break;
01141                 case FPARAM_REGEX:
01142                         if ((p->v.regex = pkg_malloc(sizeof(regex_t))) == 0) {
01143                                 ERR("No memory left\n");
01144                                 goto error;
01145                         }
01146                         if (regcomp(p->v.regex, *param,
01147                                                 REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
01148                                 pkg_free(p->v.regex);
01149                                 p->v.regex=0;
01150                                 /* not a valid regex */
01151                                 goto no_match;
01152                         }
01153                         p->fixed = p->v.regex;
01154                         break;
01155                 case FPARAM_AVP:
01156                         name.s = (char*)*param;
01157                         name.len = strlen(name.s);
01158                         trim(&name);
01159                         if (!name.len || name.s[0] != '$') {
01160                                 /* Not an AVP identifier */
01161                                 goto no_match;
01162                         }
01163                         name.s++;
01164                         name.len--;
01165                         if (parse_avp_ident(&name, &p->v.avp) < 0) {
01166                                 /* invalid avp identifier (=> no match) */
01167                                 goto no_match;
01168                         }
01169                         p->fixed = &p->v;
01170                         break;
01171                 case FPARAM_SELECT:
01172                         name.s = (char*)*param;
01173                         name.len = strlen(name.s);
01174                         trim(&name);
01175                         if (!name.len || name.s[0] != '@') {
01176                                 /* Not a select identifier */
01177                                 goto no_match;
01178                         }
01179                         if (parse_select(&name.s, &p->v.select) < 0) {
01180                                 ERR("Error while parsing select identifier\n");
01181                                 goto error;
01182                         }
01183                         p->fixed = &p->v;
01184                         break;
01185                 case FPARAM_SUBST:
01186                         s.s = *param;
01187                         s.len = strlen(s.s);
01188                         p->v.subst = subst_parser(&s);
01189                         if (!p->v.subst) {
01190                                 ERR("Error while parsing regex substitution\n");
01191                                 goto error;
01192                         }
01193                         p->fixed = &p->v;
01194                         break;
01195                 case FPARAM_PVS:
01196                         name.s = (char*)*param;
01197                         name.len = strlen(name.s);
01198                         trim(&name);
01199                         if (!name.len || name.s[0] != '$'){
01200                                 /* not a pvs identifier */
01201                                 goto no_match;
01202                         }
01203                         p->v.pvs=pkg_malloc(sizeof(pv_spec_t));
01204                         if (p->v.pvs==0){
01205                                 ERR("out of memory while parsing pv_spec_t\n");
01206                                 goto error;
01207                         }
01208                         if (pv_parse_spec2(&name, p->v.pvs, 1)==0){
01209                                 /* not a valid pvs identifier (but it might be an avp) */
01210                                 pkg_free(p->v.pvs);
01211                                 p->v.pvs=0;
01212                                 goto no_match;
01213                         }
01214                         p->fixed = p->v.pvs;
01215                         break;
01216                 case FPARAM_PVE:
01217                         name.s = (char*)*param;
01218                         name.len = strlen(name.s);
01219                         if (pv_parse_format(&name, &p->v.pve)<0){
01220                                 ERR("bad PVE format: \"%.*s\"\n", name.len, name.s);
01221                                 goto error;
01222                         }
01223                         p->fixed = &p->v;
01224                         break;
01225         }
01226         
01227         p->type = type;
01228         *param = (void*)p;
01229         return 0;
01230         
01231 no_match:
01232         pkg_free(p);
01233         return 1;
01234 error:
01235         pkg_free(p);
01236         return E_UNSPEC;
01237 }
01238 
01239 
01240 
01248 void fparam_free_contents(fparam_t* fp)
01249 {
01250 
01251         if (fp==0)
01252                 return;
01253         switch(fp->type) {
01254                 case FPARAM_UNSPEC:
01255                 case FPARAM_STRING: /* asciiz string, not str */
01256                 case FPARAM_INT:
01257                 case FPARAM_STR:
01258                         /* nothing to do */
01259                         break;
01260                 case FPARAM_REGEX:
01261                         if (fp->v.regex){
01262                                 regfree(fp->v.regex);
01263                                 pkg_free(fp->v.regex);
01264                                 fp->v.regex=0;
01265                         }
01266                         break;
01267                 case FPARAM_AVP:
01268                         free_avp_name(&fp->v.avp.flags, &fp->v.avp.name);
01269                         break;
01270                 case FPARAM_SELECT:
01271                         if (fp->v.select){
01272                                 free_select(fp->v.select);
01273                                 fp->v.select=0;
01274                         }
01275                         break;
01276                 case FPARAM_SUBST:
01277                         if (fp->v.subst){
01278                                 subst_expr_free(fp->v.subst);
01279                                 fp->v.subst=0;
01280                         }
01281                         break;
01282                 case FPARAM_PVS:
01283                         if (fp->v.pvs){
01284                                 pv_spec_free(fp->v.pvs);
01285                                 fp->v.pvs=0;
01286                         }
01287                         break;
01288                 case FPARAM_PVE:
01289                         if (fp->v.pve){
01290                                 pv_elem_free_all(fp->v.pve);
01291                                 fp->v.pve=0;
01292                         }
01293                         break;
01294         }
01295 }
01296 
01297 
01306 void fparam_free_restore(void** param)
01307 {
01308         fparam_t *fp;
01309         void *orig;
01310         
01311         fp = *param;
01312         orig = fp->orig;
01313         fp->orig = 0;
01314         fparam_free_contents(fp);
01315         pkg_free(fp);
01316         *param = orig;
01317 }
01318 
01319 
01320 
01328 int fix_param_types(int types, void** param)
01329 {
01330         int ret;
01331         int t;
01332         
01333         if (fixup_get_param_type(param) == STRING_RVE_ST &&
01334                         (types & (FPARAM_INT|FPARAM_STR|FPARAM_STRING))) {
01335                 /* if called with a RVE already converted to string =>
01336                    don't try AVP, PVAR or SELECT (to avoid double
01337                    deref., e.g.: $foo="$bar"; f($foo) ) */
01338                 types &= ~ (FPARAM_AVP|FPARAM_PVS|FPARAM_SELECT|FPARAM_PVE);
01339         }
01340         for (t=types & ~(types-1); types; types&=(types-1), t=types & ~(types-1)){
01341                 if ((ret=fix_param(t, param))<=0) return ret;
01342         }
01343         return E_UNSPEC;
01344 }
01345 
01346 
01347 
01348 /*
01349  * Fixup variable string, the parameter can be
01350  * AVP, SELECT, or ordinary string. AVP and select
01351  * identifiers will be resolved to their values during
01352  * runtime
01353  *
01354  * The parameter value will be converted to fparam structure
01355  * This function returns -1 on an error
01356  */
01357 int fixup_var_str_12(void** param, int param_no)
01358 {
01359         int ret;
01360         if (fixup_get_param_type(param) != STRING_RVE_ST) {
01361                 /* if called with a RVE already converted to string =>
01362                    don't try AVP, PVAR or SELECT (to avoid double
01363                    deref., e.g.: $foo="$bar"; f($foo) ) */
01364                 if ((ret = fix_param(FPARAM_PVS, param)) <= 0) return ret;
01365                 if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
01366                 if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
01367         }
01368         if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
01369         ERR("Error while fixing parameter, PV, AVP, SELECT, and str conversions"
01370                         " failed\n");
01371         return -1;
01372 }
01373 
01374 /* Same as fixup_var_str_12 but applies to the 1st parameter only */
01375 int fixup_var_str_1(void** param, int param_no)
01376 {
01377         if (param_no == 1) return fixup_var_str_12(param, param_no);
01378         else return 0;
01379 }
01380 
01381 /* Same as fixup_var_str_12 but applies to the 2nd parameter only */
01382 int fixup_var_str_2(void** param, int param_no)
01383 {
01384         if (param_no == 2) return fixup_var_str_12(param, param_no);
01385         else return 0;
01386 }
01387 
01398 int fixup_var_pve_12(void** param, int param_no)
01399 {
01400         int ret;
01401         fparam_t* fp;
01402         if (fixup_get_param_type(param) != STRING_RVE_ST) {
01403                 /* if called with a RVE already converted to string =>
01404                    don't try PVE again (to avoid double
01405                    deref., e.g.: $foo="$bar"; f($foo) ) */
01406                 if ((ret = fix_param(FPARAM_PVE, param)) <= 0) {
01407                         if (ret < 0)
01408                                 return ret;
01409                         /* check if it resolved to a dynamic or "static" PVE.
01410                            If the resulting PVE is static (normal string), discard
01411                            it and use the normal string fixup (faster at runtime) */
01412                         fp = (fparam_t*)*param;
01413                         if (fp->v.pve->spec.getf == 0)
01414                                 fparam_free_restore(param); /* fallback to STR below */
01415                         else
01416                                 return ret; /* dynamic PVE => return */
01417                 }
01418                 
01419         }
01420         if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
01421         ERR("Error while fixing parameter - PVE or str conversions failed\n");
01422         return -1;
01423 }
01424 
01425 
01426 
01437 int fixup_var_pve_str_12(void** param, int param_no)
01438 {
01439         int ret;
01440         fparam_t* fp;
01441         if (fixup_get_param_type(param) != STRING_RVE_ST) {
01442                 /* if called with a RVE already converted to string =>
01443                    don't try AVP, PVAR, SELECT or PVE again (to avoid double
01444                    deref., e.g.: $foo="$bar"; f($foo) ) */
01445                 if ((ret = fix_param(FPARAM_PVS, param)) <= 0) return ret;
01446                 if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
01447                 if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
01448                 if ((ret = fix_param(FPARAM_PVE, param)) <= 0) {
01449                         if (ret < 0)
01450                                 return ret;
01451                         /* check if it resolved to a dynamic or "static" PVE.
01452                            If the resulting PVE is static (normal string), discard
01453                            it and use the normal string fixup (faster at runtime) */
01454                         fp = (fparam_t*)*param;
01455                         if (fp->v.pve->spec.getf == 0)
01456                                 fparam_free_restore(param); /* fallback to STR below */
01457                         else
01458                                 return ret; /* dynamic PVE => return */
01459                 }
01460                 
01461         }
01462         if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
01463         ERR("Error while fixing parameter, PV, AVP, SELECT, and str conversions"
01464                         " failed\n");
01465         return -1;
01466 }
01467 
01468 /* Same as fixup_var_pve_str_12 but applies to the 1st parameter only */
01469 int fixup_var_pve_str_1(void** param, int param_no)
01470 {
01471         if (param_no == 1) return fixup_var_pve_str_12(param, param_no);
01472         else return 0;
01473 }
01474 
01475 /* Same as fixup_var_pve_str_12 but applies to the 2nd parameter only */
01476 int fixup_var_pve_str_2(void** param, int param_no)
01477 {
01478         if (param_no == 2) return fixup_var_pve_str_12(param, param_no);
01479         else return 0;
01480 }
01481 
01482 
01483 
01484 /*
01485  * Fixup variable integer, the parameter can be
01486  * AVP, SELECT, or ordinary integer. AVP and select
01487  * identifiers will be resolved to their values and
01488  * converted to int if necessary during runtime
01489  *
01490  * The parameter value will be converted to fparam structure
01491  * This function returns -1 on an error
01492  */
01493 int fixup_var_int_12(void** param, int param_no)
01494 {
01495         int ret;
01496         if (fixup_get_param_type(param) != STRING_RVE_ST) {
01497                 /* if called with a RVE already converted to string =>
01498                    don't try AVP, PVAR or SELECT (to avoid double
01499                    deref., e.g.: $foo="$bar"; f($foo) ) */
01500                 if ((ret = fix_param(FPARAM_PVS, param)) <= 0) return ret;
01501                 if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
01502                 if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
01503         }
01504         if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
01505         ERR("Error while fixing parameter, PV, AVP, SELECT, and int conversions"
01506                         " failed\n");
01507         return -1;
01508 }
01509 
01510 /* Same as fixup_var_int_12 but applies to the 1st parameter only */
01511 int fixup_var_int_1(void** param, int param_no)
01512 {
01513         if (param_no == 1) return fixup_var_int_12(param, param_no);
01514         else return 0;
01515 }
01516 
01517 /* Same as fixup_var_int_12 but applies to the 2nd parameter only */
01518 int fixup_var_int_2(void** param, int param_no)
01519 {
01520         if (param_no == 2) return fixup_var_int_12(param, param_no);
01521         else return 0;
01522 }
01523 
01524 
01525 /*
01526  * The parameter must be a regular expression which must compile, the
01527  * parameter will be converted to compiled regex
01528  */
01529 int fixup_regex_12(void** param, int param_no)
01530 {
01531         int ret;
01532 
01533         if ((ret = fix_param(FPARAM_REGEX, param)) <= 0) return ret;
01534         ERR("Error while compiling regex in function parameter\n");
01535         return -1;
01536 }
01537 
01538 /* Same as fixup_regex_12 but applies to the 1st parameter only */
01539 int fixup_regex_1(void** param, int param_no)
01540 {
01541         if (param_no == 1) return fixup_regex_12(param, param_no);
01542         else return 0;
01543 }
01544 
01545 /* Same as fixup_regex_12 but applies to the 2nd parameter only */
01546 int fixup_regex_2(void** param, int param_no)
01547 {
01548         if (param_no == 2) return fixup_regex_12(param, param_no);
01549         else return 0;
01550 }
01551 
01552 /*
01553  * The string parameter will be converted to integer
01554  */
01555 int fixup_int_12(void** param, int param_no)
01556 {
01557         int ret;
01558 
01559         if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
01560         ERR("Cannot function parameter to integer\n");
01561         return -1;
01562 
01563 }
01564 
01565 /* Same as fixup_int_12 but applies to the 1st parameter only */
01566 int fixup_int_1(void** param, int param_no)
01567 {
01568         if (param_no == 1) return fixup_int_12(param, param_no);
01569         else return 0;
01570 }
01571 
01572 /* Same as fixup_int_12 but applies to the 2nd parameter only */
01573 int fixup_int_2(void** param, int param_no)
01574 {
01575         if (param_no == 2) return fixup_int_12(param, param_no);
01576         else return 0;
01577 }
01578 
01579 /*
01580  * Parse the parameter as static string, do not resolve
01581  * AVPs or selects, convert the parameter to str structure
01582  */
01583 int fixup_str_12(void** param, int param_no)
01584 {
01585         int ret;
01586 
01587         if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
01588         ERR("Cannot function parameter to string\n");
01589         return -1;
01590 }
01591 
01592 /* Same as fixup_str_12 but applies to the 1st parameter only */
01593 int fixup_str_1(void** param, int param_no)
01594 {
01595         if (param_no == 1) return fixup_str_12(param, param_no);
01596         else return 0;
01597 }
01598 
01599 /* Same as fixup_str_12 but applies to the 2nd parameter only */
01600 int fixup_str_2(void** param, int param_no)
01601 {
01602         if (param_no == 2) return fixup_str_12(param, param_no);
01603         else return 0;
01604 }
01605 
01606 
01607 
01612 int get_str_fparam(str* dst, struct sip_msg* msg, fparam_t* param)
01613 {
01614         int_str val;
01615         int ret;
01616         avp_t* avp;
01617         pv_value_t pv_val;
01618         
01619         switch(param->type) {
01620                 case FPARAM_REGEX:
01621                 case FPARAM_UNSPEC:
01622                 case FPARAM_INT:
01623                         return -1;
01624                 case FPARAM_STRING:
01625                         dst->s = param->v.asciiz;
01626                         dst->len = strlen(param->v.asciiz);
01627                         break;
01628                 case FPARAM_STR:
01629                         *dst = param->v.str;
01630                         break;
01631                 case FPARAM_AVP:
01632                         avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
01633                                                                         &val, 0);
01634                         if (unlikely(!avp)) {
01635                                 DBG("Could not find AVP from function parameter '%s'\n",
01636                                                 param->orig);
01637                                 return -1;
01638                         }
01639                         if (likely(avp->flags & AVP_VAL_STR)) {
01640                                 *dst = val.s;
01641                         } else {
01642                                 /* The caller does not know of what type the AVP will be so
01643                                  * convert int AVPs into string here
01644                                  */
01645                                 dst->s = int2str(val.n, &dst->len);
01646                         }
01647                         break;
01648                 case FPARAM_SELECT:
01649                         ret = run_select(dst, param->v.select, msg);
01650                         if (unlikely(ret < 0 || ret > 0)) return -1;
01651                         break;
01652                 case FPARAM_PVS:
01653                         if (likely((pv_get_spec_value(msg, param->v.pvs, &pv_val)==0) &&
01654                                            ((pv_val.flags&(PV_VAL_NULL|PV_VAL_STR))==PV_VAL_STR))){
01655                                         *dst=pv_val.rs;
01656                         }else{
01657                                 ERR("Could not convert PV to str\n");
01658                                 return -1;
01659                         }
01660                         break;
01661                 case FPARAM_PVE:
01662                         dst->s=pv_get_buffer();
01663                         dst->len=pv_get_buffer_size();
01664                         if (unlikely(pv_printf(msg, param->v.pve, dst->s, &dst->len)!=0)){
01665                                 ERR("Could not convert the PV-formated string to str\n");
01666                                 dst->len=0;
01667                                 return -1;
01668                         };
01669                         break;
01670         }
01671         return 0;
01672 }
01673 
01674 
01679 int get_int_fparam(int* dst, struct sip_msg* msg, fparam_t* param)
01680 {
01681         int_str val;
01682         int ret;
01683         avp_t* avp;
01684         str tmp;
01685         pv_value_t pv_val;
01686 
01687         switch(param->type) {
01688                 case FPARAM_INT:
01689                         *dst = param->v.i;
01690                         return 0;
01691                 case FPARAM_REGEX:
01692                 case FPARAM_UNSPEC:
01693                 case FPARAM_STRING:
01694                 case FPARAM_STR:
01695                         return -1;
01696                 case FPARAM_AVP:
01697                         avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
01698                                                                         &val, 0);
01699                         if (unlikely(!avp)) {
01700                                 DBG("Could not find AVP from function parameter '%s'\n",
01701                                                 param->orig);
01702                                 return -1;
01703                         }
01704                         if (avp->flags & AVP_VAL_STR) {
01705                                 if (str2int(&val.s, (unsigned int*)dst) < 0) {
01706                                         ERR("Could not convert AVP string value to int\n");
01707                                         return -1;
01708                                 }
01709                         } else {
01710                                 *dst = val.n;
01711                         }
01712                         break;
01713                 case FPARAM_SELECT:
01714                         ret = run_select(&tmp, param->v.select, msg);
01715                         if (unlikely(ret < 0 || ret > 0)) return -1;
01716                         if (unlikely(str2int(&tmp, (unsigned int*)dst) < 0)) {
01717                                 ERR("Could not convert select result to int\n");
01718                                 return -1;
01719                         }
01720                         break;
01721                 case FPARAM_PVS:
01722                         if (likely((pv_get_spec_value(msg, param->v.pvs, &pv_val)==0) &&
01723                                            ((pv_val.flags&(PV_VAL_NULL|PV_VAL_INT))==PV_VAL_INT))){
01724                                         *dst=pv_val.ri;
01725                         }else{
01726                                 ERR("Could not convert PV to int\n");
01727                                 return -1;
01728                         }
01729                         break;
01730                 case FPARAM_PVE:
01731                         return -1;
01732         }
01733         return 0;
01734 }
01735 
01740 int get_regex_fparam(regex_t *dst, struct sip_msg* msg, fparam_t* param)
01741 {
01742         switch (param->type) {
01743                 case FPARAM_REGEX:
01744                         *dst = *param->v.regex;
01745                         return 0;
01746                 default:
01747                         ERR("unexpected parameter type (%d), instead of regexp.\n", 
01748                                         param->type);
01749         }
01750         return -1;
01751 }
01752 
01753 
01754 
01760 int fixup_free_fparam_all(void** param, int param_no)
01761 {
01762         fparam_free_restore(param);
01763         return 0;
01764 }
01765 
01766 
01767 
01774 int fixup_free_fparam_1(void** param, int param_no)
01775 {
01776         if (param_no == 1)
01777                 fparam_free_restore(param);
01778         return 0;
01779 }
01780 
01781 
01782 
01789 int fixup_free_fparam_2(void** param, int param_no)
01790 {
01791         if (param_no == 2)
01792                 fparam_free_restore(param);
01793         return 0;
01794 }
01795 
01796 
01797 
01804 int is_fparam_rve_fixup(fixup_function f)
01805 {
01806         if (f == fixup_var_str_12 ||
01807                 f == fixup_var_str_1 ||
01808                 f == fixup_var_str_2 ||
01809                 f == fixup_var_pve_str_12 ||
01810                 f == fixup_var_pve_str_1 ||
01811                 f == fixup_var_pve_str_2 ||
01812                 f == fixup_var_int_12 ||
01813                 f == fixup_var_int_1 ||
01814                 f == fixup_var_int_2 ||
01815                 f == fixup_int_12 ||
01816                 f == fixup_int_1 ||
01817                 f == fixup_int_2 ||
01818                 f == fixup_str_12 ||
01819                 f == fixup_str_1 ||
01820                 f == fixup_str_2 ||
01821                 f == fixup_regex_12 ||
01822                 f == fixup_regex_1 ||
01823                 f == fixup_regex_2
01824                 )
01825                 return 1;
01826         return 0;
01827 }
01828 
01829 
01839 free_fixup_function get_fixup_free(fixup_function f)
01840 {
01841         free_fixup_function ret;
01842         /* "pure" fparam, all parameters */
01843         if (f == fixup_var_str_12 ||
01844                 f == fixup_var_pve_str_12 ||
01845                 f == fixup_var_int_12 ||
01846                 f == fixup_int_12 ||
01847                 f == fixup_str_12 ||
01848                 f == fixup_regex_12)
01849                 return fixup_free_fparam_all;
01850         
01851         /* "pure" fparam, 1st parameter */
01852         if (f == fixup_var_str_1 ||
01853                 f == fixup_var_pve_str_1 ||
01854                 f == fixup_var_int_1 ||
01855                 f == fixup_int_1 ||
01856                 f == fixup_str_1 ||
01857                 f == fixup_regex_1)
01858                 return fixup_free_fparam_1;
01859         
01860         /* "pure" fparam, 2nd parameters */
01861         if (f == fixup_var_str_2 ||
01862                 f == fixup_var_pve_str_2 ||
01863                 f == fixup_var_int_2 ||
01864                 f == fixup_int_2 ||
01865                 f == fixup_str_2 ||
01866                 f == fixup_regex_2)
01867                 return fixup_free_fparam_2;
01868         
01869         /* mod_fix.h kamailio style fixups */
01870         if ((ret = mod_fix_get_fixup_free(f)) != 0)
01871                 return ret;
01872         
01873         /* unknown */
01874         return 0;
01875 }

Generated on Tue May 22 2012 13:10:15 for SIP Router by  doxygen 1.7.1