00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
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>
00075
00076
00077 struct sr_module* modules=0;
00078
00079
00080
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
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
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;
00233
00234 ret = pkg_malloc(sizeof(*ret)*(n+1));
00235 memset(ret, 0, sizeof(*ret)*(n+1));
00236
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;
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
00254 ret[i].fixup_flags = 0;
00255 ret[i].module_exports = mod;
00256
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
00268
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
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
00288 if (ver == 0) {
00289
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;
00308 mod->exports.rpc_methods = e->v0.rpc_methods;
00309
00310 } else if (ver == 1) {
00311
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;
00328 mod->exports.init_child_f = e->v1.init_child_f;
00329 mod->exports.dlflags = e->v1.dlflags;
00330 mod->exports.rpc_methods = 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
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
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
00367 }
00368
00369
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
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
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
00476 mdir=mods_dir;
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
00484 path = (char*)pkg_malloc(mdir_len + 1 +
00485 modname.len + 3 + 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
00503 path = (char*)pkg_malloc(
00504 mdir_len + 1 +
00505 modname.len + 1 +
00506 modname.len + 3 + 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
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
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);
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
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
00595 mr = (mod_register_function)dlsym(handle, DLSYM_PREFIX "mod_register");
00596 if (((error =(char*)dlerror())==0) && mr) {
00597
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
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
00620 if (*mod_if_ver == 1) {
00621 new_dlflags = exp->v1.dlflags;
00622 if (new_dlflags!=dlflags && new_dlflags!=DEFAULT_DLFLAGS) {
00623
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
00651
00652
00653
00654
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
00687
00688
00689
00690
00691
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
00720
00721
00722
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
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
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
00812
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
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
00880
00881
00882
00883
00884 static int init_mod_child( struct sr_module* m, int rank )
00885 {
00886 if (m) {
00887
00888
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
00900 return 0;
00901 }
00902 }
00903
00904 return 0;
00905 } else {
00906
00907 return 0;
00908 }
00909 }
00910
00911
00912
00913
00914
00915 int init_child(int rank)
00916 {
00917 return init_mod_child(modules, rank);
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927 static int init_mod( struct sr_module* m )
00928 {
00929 if (m) {
00930
00931
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
00943 return 0;
00944 }
00945 }
00946
00947 return 0;
00948 } else {
00949
00950 return 0;
00951 }
00952 }
00953
00954
00955
00956
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
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
01034
01035
01036
01037
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
01057 num = str2s(s, len, &err);
01058 if (err != 0) {
01059
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
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
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
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
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
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
01161 goto no_match;
01162 }
01163 name.s++;
01164 name.len--;
01165 if (parse_avp_ident(&name, &p->v.avp) < 0) {
01166
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
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
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
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:
01256 case FPARAM_INT:
01257 case FPARAM_STR:
01258
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
01336
01337
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
01350
01351
01352
01353
01354
01355
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
01362
01363
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
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
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
01404
01405
01406 if ((ret = fix_param(FPARAM_PVE, param)) <= 0) {
01407 if (ret < 0)
01408 return ret;
01409
01410
01411
01412 fp = (fparam_t*)*param;
01413 if (fp->v.pve->spec.getf == 0)
01414 fparam_free_restore(param);
01415 else
01416 return ret;
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
01443
01444
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
01452
01453
01454 fp = (fparam_t*)*param;
01455 if (fp->v.pve->spec.getf == 0)
01456 fparam_free_restore(param);
01457 else
01458 return ret;
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
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
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
01486
01487
01488
01489
01490
01491
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
01498
01499
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
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
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
01527
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
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
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
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
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
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
01581
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
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
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
01643
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
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
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
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
01870 if ((ret = mod_fix_get_fixup_free(f)) != 0)
01871 return ret;
01872
01873
01874 return 0;
01875 }