| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108 |
- /* $Id$
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- * [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- /*
- * History:
- * --------
- * 2003-03-10 switched to new module_exports format: updated find_export,
- * find_export_param, find_module (andrei)
- * 2003-03-19 replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
- * 2003-03-19 Support for flags in find_export (janakj)
- * 2003-03-29 cleaning pkg_mallocs introduced (jiri)
- * 2003-04-24 module version checking introduced (jiri)
- * 2004-09-19 compile flags are checked too (andrei)
- * 2005-01-07 removed find_module-overloading problems, added
- * find_export_record
- * 2006-02-07 added fix_flag (andrei)
- * 2008-02-29 store all the reponse callbacks in their own array (andrei)
- */
- #include "sr_module.h"
- #include "dprint.h"
- #include "error.h"
- #include "mem/mem.h"
- #include "core_cmd.h"
- #include "ut.h"
- #include "re.h"
- #include "route_struct.h"
- #include "flags.h"
- #include "trim.h"
- #include "globals.h"
- #include <sys/stat.h>
- #include <regex.h>
- #include <dlfcn.h>
- #include <strings.h>
- #include <stdlib.h>
- #include <string.h>
- struct sr_module* modules=0;
- #ifdef STATIC_EXEC
- extern struct module_exports* exec_exports();
- #endif
- #ifdef STATIC_TM
- extern struct module_exports* tm_exports();
- #endif
- #ifdef STATIC_MAXFWD
- extern struct module_exports* maxfwd_exports();
- #endif
- #ifdef STATIC_AUTH
- extern struct module_exports* auth_exports();
- #endif
- #ifdef STATIC_RR
- extern struct module_exports* rr_exports();
- #endif
- #ifdef STATIC_USRLOC
- extern struct module_exports* usrloc_exports();
- #endif
- #ifdef STATIC_SL
- extern struct module_exports* sl_exports();
- #endif
- int mod_response_cbk_no=0;
- response_function* mod_response_cbks=0;
- /* initializes statically built (compiled in) modules*/
- int register_builtin_modules()
- {
- int ret;
- ret=0;
- #ifdef STATIC_TM
- ret=register_module(tm_exports,"built-in", 0);
- if (ret<0) return ret;
- #endif
- #ifdef STATIC_EXEC
- ret=register_module(exec_exports,"built-in", 0);
- if (ret<0) return ret;
- #endif
- #ifdef STATIC_MAXFWD
- ret=register_module(maxfwd_exports, "built-in", 0);
- if (ret<0) return ret;
- #endif
- #ifdef STATIC_AUTH
- ret=register_module(auth_exports, "built-in", 0);
- if (ret<0) return ret;
- #endif
- #ifdef STATIC_RR
- ret=register_module(rr_exports, "built-in", 0);
- if (ret<0) return ret;
- #endif
- #ifdef STATIC_USRLOC
- ret=register_module(usrloc_exports, "built-in", 0);
- if (ret<0) return ret;
- #endif
- #ifdef STATIC_SL
- ret=register_module(sl_exports, "built-in", 0);
- if (ret<0) return ret;
- #endif
- return ret;
- }
- /* registers a module, register_f= module register functions
- * returns <0 on error, 0 on success */
- int register_module(struct module_exports* e, char* path, void* handle)
- {
- int ret;
- struct sr_module* mod;
- ret=-1;
- /* add module to the list */
- if ((mod=pkg_malloc(sizeof(struct sr_module)))==0){
- LOG(L_ERR, "load_module: memory allocation failure\n");
- ret=E_OUT_OF_MEM;
- goto error;
- }
- memset(mod,0, sizeof(struct sr_module));
- mod->path=path;
- mod->handle=handle;
- mod->exports=e;
- mod->next=modules;
- modules=mod;
- return 0;
- error:
- return ret;
- }
- #ifndef DLSYM_PREFIX
- /* define it to null */
- #define DLSYM_PREFIX
- #endif
- static inline int version_control(void *handle, char *path)
- {
- char **m_ver;
- char **m_flags;
- char* error;
- m_ver=(char **)dlsym(handle, DLSYM_PREFIX "module_version");
- if ((error=(char *)dlerror())!=0) {
- LOG(L_ERR, "ERROR: no version info in module <%s>: %s\n",
- path, error );
- return 0;
- }
- m_flags=(char **)dlsym(handle, DLSYM_PREFIX "module_flags");
- if ((error=(char *)dlerror())!=0) {
- LOG(L_ERR, "ERROR: no compile flags info in module <%s>: %s\n",
- path, error );
- return 0;
- }
- if (!m_ver || !(*m_ver)) {
- LOG(L_ERR, "ERROR: no version in module <%s>\n", path );
- return 0;
- }
- if (!m_flags || !(*m_flags)) {
- LOG(L_ERR, "ERROR: no compile flags in module <%s>\n", path );
- return 0;
- }
- if (strcmp(SER_FULL_VERSION, *m_ver)==0){
- if (strcmp(SER_COMPILE_FLAGS, *m_flags)==0)
- return 1;
- else {
- LOG(L_ERR, "ERROR: module compile flags mismatch for %s "
- " \ncore: %s \nmodule: %s\n",
- path, SER_COMPILE_FLAGS, *m_flags);
- return 0;
- }
- }
- LOG(L_ERR, "ERROR: module version mismatch for %s; "
- "core: %s; module: %s\n", path, SER_FULL_VERSION, *m_ver );
- return 0;
- }
- /* returns 0 on success , <0 on error */
- int load_module(char* path)
- {
- void* handle;
- char* error;
- struct module_exports* exp;
- struct sr_module* t;
- struct stat stat_buf;
- char* modname;
- int len;
- #ifndef RTLD_NOW
- /* for openbsd */
- #define RTLD_NOW DL_LAZY
- #endif
- if (!strchr(path, '/') && !strchr(path, '.')) {
- /* module name was given, we try to construct the path */
- modname = path;
- /* try path <MODS_DIR>/<modname>.so */
- path = (char*)pkg_malloc(
- strlen(mods_dir) + 1 /* "/" */ +
- strlen(modname) + 3 /* ".so" */ + 1);
- strcpy(path, mods_dir);
- len = strlen(path);
- if (len != 0 && path[len - 1] != '/') {
- strcat(path, "/");
- }
- strcat(path, modname);
- strcat(path, ".so");
- #ifdef EXTRA_DEBUG
- if (stat(path, &stat_buf) == -1) {
- DBG("load_module: module file not found <%s>\n", path);
- pkg_free(path);
- /* try path <MODS_DIR>/<modname>/<modname>.so */
- path = (char*)pkg_malloc(
- strlen(mods_dir) + 1 /* "/" */ +
- strlen(modname) + 1 /* "/" */ +
- strlen(modname) + 3 /* ".so" */ + 1);
- strcpy(path, mods_dir);
- len = strlen(path);
- if (len != 0 && path[len - 1] != '/') {
- strcat(path, "/");
- }
- strcat(path, modname);
- strcat(path, "/");
- strcat(path, modname);
- strcat(path, ".so");
- if (stat(path, &stat_buf) == -1) {
- DBG("load_module: module file not found <%s>\n", path);
- pkg_free(path);
- LOG(L_ERR, "ERROR: load_module: could not find module <%s>\n",
- modname);
- goto error;
- }
- }
- #else /* !EXTRA_DEBUG */
- if (stat(path, &stat_buf) == -1) {
- DBG("load_module: module file not found <%s>\n", path);
- pkg_free(path);
- LOG(L_ERR, "ERROR: load_module: could not find module <%s>\n",
- modname);
- goto error;
- }
- #endif /* !EXTRA_DEBUG */
- }
- handle=dlopen(path, RTLD_NOW); /* resolve all symbols now */
- if (handle==0){
- LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n",
- path, dlerror());
- goto error;
- }
- for(t=modules;t; t=t->next){
- if (t->handle==handle){
- LOG(L_WARN, "WARNING: load_module: attempting to load the same"
- " module twice (%s)\n", path);
- goto skip;
- }
- }
- /* version control */
- if (!version_control(handle, path)) {
- exit(0);
- }
- /* launch register */
- exp = (struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");
- if ( (error =(char*)dlerror())!=0 ){
- LOG(L_ERR, "ERROR: load_module: %s\n", error);
- goto error1;
- }
- if (register_module(exp, path, handle)<0) goto error1;
- return 0;
- error1:
- dlclose(handle);
- error:
- skip:
- return -1;
- }
- /* searches the module list and returns pointer to the "name" function record or
- * 0 if not found
- * flags parameter is OR value of all flags that must match
- */
- cmd_export_t* find_export_record(char* name, int param_no, int flags)
- {
- struct sr_module* t;
- cmd_export_t* cmd;
- for(t=modules;t;t=t->next){
- for(cmd=t->exports->cmds; cmd && cmd->name; cmd++){
- if((strcmp(name, cmd->name)==0)&&
- (cmd->param_no==param_no) &&
- ((cmd->flags & flags) == flags)
- ){
- DBG("find_export_record: found <%s> in module %s [%s]\n",
- name, t->exports->name, t->path);
- return cmd;
- }
- }
- }
- DBG("find_export_record: <%s> not found \n", name);
- return 0;
- }
- cmd_function find_export(char* name, int param_no, int flags)
- {
- cmd_export_t* cmd;
- cmd = find_export_record(name, param_no, flags);
- return cmd?cmd->function:0;
- }
- rpc_export_t* find_rpc_export(char* name, int flags)
- {
- struct sr_module* t;
- rpc_export_t* rpc;
- /* Scan the list of core methods first, they are always
- * present
- */
- for(rpc = core_rpc_methods; rpc && rpc->name; rpc++) {
- if ((strcmp(name, rpc->name) == 0) &&
- ((rpc->flags & flags) == flags)
- ) {
- return rpc;
- }
- }
- /* Continue with modules if not found */
- for(t = modules; t; t = t->next) {
- for(rpc = t->exports->rpc_methods; rpc && rpc->name; rpc++) {
- if ((strcmp(name, rpc->name) == 0) &&
- ((rpc->flags & flags) == flags)
- ) {
- return rpc;
- }
- }
- }
- return 0;
- }
- /*
- * searches the module list and returns pointer to "name" function in module "mod"
- * 0 if not found
- * flags parameter is OR value of all flags that must match
- */
- cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
- {
- struct sr_module* t;
- cmd_export_t* cmd;
- for (t = modules; t; t = t->next) {
- if (strcmp(t->exports->name, mod) == 0) {
- for (cmd = t->exports->cmds; cmd && cmd->name; cmd++) {
- if ((strcmp(name, cmd->name) == 0) &&
- (cmd->param_no == param_no) &&
- ((cmd->flags & flags) == flags)
- ){
- DBG("find_mod_export: found <%s> in module %s [%s]\n",
- name, t->exports->name, t->path);
- return cmd->function;
- }
- }
- }
- }
- DBG("find_mod_export: <%s> in module <%s> not found\n", name, mod);
- return 0;
- }
- struct sr_module* find_module_by_name(char* mod) {
- struct sr_module* t;
- for(t = modules; t; t = t->next) {
- if (strcmp(mod, t->exports->name) == 0) {
- return t;
- }
- }
- DBG("find_module_by_name: module <%s> not found\n", mod);
- return 0;
- }
- void* find_param_export(struct sr_module* mod, char* name, modparam_t type_mask, modparam_t *param_type)
- {
- param_export_t* param;
- if (!mod)
- return 0;
- for(param=mod->exports->params;param && param->name ; param++) {
- if ((strcmp(name, param->name) == 0) &&
- ((param->type & PARAM_TYPE_MASK(type_mask)) != 0)) {
- DBG("find_param_export: found <%s> in module %s [%s]\n",
- name, mod->exports->name, mod->path);
- *param_type = param->type;
- return param->param_pointer;
- }
- }
- DBG("find_param_export: parameter <%s> not found in module <%s>\n",
- name, mod->exports->name);
- return 0;
- }
- void destroy_modules()
- {
- struct sr_module* t, *foo;
- t=modules;
- while(t) {
- foo=t->next;
- if ((t->exports)&&(t->exports->destroy_f)) t->exports->destroy_f();
- pkg_free(t);
- t=foo;
- }
- modules=0;
- if (mod_response_cbks){
- pkg_free(mod_response_cbks);
- mod_response_cbks=0;
- }
- }
- #ifdef NO_REVERSE_INIT
- /*
- * Initialize all loaded modules, the initialization
- * is done *AFTER* the configuration file is parsed
- */
- int init_modules(void)
- {
- struct sr_module* t;
- for(t = modules; t; t = t->next) {
- if ((t->exports) && (t->exports->init_f))
- if (t->exports->init_f() != 0) {
- LOG(L_ERR, "init_modules(): Error while initializing"
- " module %s\n", t->exports->name);
- return -1;
- }
- if ( t->exports && t->exports->response_f)
- mod_response_cbk_no++;
- }
- mod_response_cbks=pkg_malloc(mod_response_cbk_no *
- sizeof(response_function));
- if (mod_response_cbks==0){
- LOG(L_ERR, "init_modules(): memory allocation failure"
- " for %d response_f callbacks\n", mod_response_cbk_no);
- return -1;
- }
- for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
- if (t->exports && t->exports->response_f){
- mod_response_cbks[i]=t->exports->response_f;
- i++;
- }
- }
- return 0;
- }
- /*
- * per-child initialization
- */
- int init_child(int rank)
- {
- struct sr_module* t;
- char* type;
- switch(rank) {
- case PROC_MAIN: type = "PROC_MAIN"; break;
- case PROC_TIMER: type = "PROC_TIMER"; break;
- case PROC_FIFO: type = "PROC_FIFO"; break;
- case PROC_TCP_MAIN: type = "PROC_TCP_MAIN"; break;
- default: type = "CHILD"; break;
- }
- DBG("init_child: initializing %s with rank %d\n", type, rank);
- for(t = modules; t; t = t->next) {
- if (t->exports->init_child_f) {
- if ((t->exports->init_child_f(rank)) < 0) {
- LOG(L_ERR, "init_child(): Initialization of child %d failed\n",
- rank);
- return -1;
- }
- }
- }
- return 0;
- }
- #else
- /* recursive module child initialization; (recursion is used to
- process the module linear list in the same order in
- which modules are loaded in config file
- */
- static int init_mod_child( struct sr_module* m, int rank )
- {
- if (m) {
- /* iterate through the list; if error occurs,
- propagate it up the stack
- */
- if (init_mod_child(m->next, rank)!=0) return -1;
- if (m->exports && m->exports->init_child_f) {
- DBG("DEBUG: init_mod_child (%d): %s\n",
- rank, m->exports->name);
- if (m->exports->init_child_f(rank)<0) {
- LOG(L_ERR, "init_mod_child(): Error while initializing"
- " module %s\n", m->exports->name);
- return -1;
- } else {
- /* module correctly initialized */
- return 0;
- }
- }
- /* no init function -- proceed with success */
- return 0;
- } else {
- /* end of list */
- return 0;
- }
- }
- /*
- * per-child initialization
- */
- int init_child(int rank)
- {
- return init_mod_child(modules, rank);
- }
- /* recursive module initialization; (recursion is used to
- process the module linear list in the same order in
- which modules are loaded in config file
- */
- static int init_mod( struct sr_module* m )
- {
- if (m) {
- /* iterate through the list; if error occurs,
- propagate it up the stack
- */
- if (init_mod(m->next)!=0) return -1;
- if (m->exports && m->exports->init_f) {
- DBG("DEBUG: init_mod: %s\n", m->exports->name);
- if (m->exports->init_f()!=0) {
- LOG(L_ERR, "init_mod(): Error while initializing"
- " module %s\n", m->exports->name);
- return -1;
- } else {
- /* module correctly initialized */
- return 0;
- }
- }
- /* no init function -- proceed with success */
- return 0;
- } else {
- /* end of list */
- return 0;
- }
- }
- /*
- * Initialize all loaded modules, the initialization
- * is done *AFTER* the configuration file is parsed
- */
- int init_modules(void)
- {
- struct sr_module* t;
- int i;
-
- for(t = modules; t; t = t->next)
- if ( t->exports && t->exports->response_f)
- mod_response_cbk_no++;
- mod_response_cbks=pkg_malloc(mod_response_cbk_no *
- sizeof(response_function));
- if (mod_response_cbks==0){
- LOG(L_ERR, "init_modules(): memory allocation failure"
- " for %d response_f callbacks\n", mod_response_cbk_no);
- return -1;
- }
- for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
- if (t->exports && t->exports->response_f){
- mod_response_cbks[i]=t->exports->response_f;
- i++;
- }
- }
-
- return init_mod(modules);
- }
- #endif
- action_u_t *fixup_get_param(void **cur_param, int cur_param_no, int required_param_no) {
- action_u_t *a, a2;
- /* cur_param points to a->u.string, get pointer to a */
- a = (void*) ((char *)cur_param - ((char *)&a2.u.string-(char *)&a2));
- return a + required_param_no - cur_param_no;
- }
- int fixup_get_param_count(void **cur_param, int cur_param_no) {
- action_u_t *a;
- a = fixup_get_param(cur_param, cur_param_no, 0);
- if (a)
- return a->u.number;
- else
- return -1;
- }
- /* fixes flag params (resolves possible named flags)
- * use PARAM_USE_FUNC|PARAM_STRING as a param. type and create
- * a wrapper function that does just:
- * return fix_flag(type, val, "my_module", "my_param", &flag_var)
- * see also param_func_t.
- */
- int fix_flag( modparam_t type, void* val,
- char* mod_name, char* param_name, int* flag)
- {
- int num;
- int err;
- int f, len;
- char* s;
- char *p;
- if ((type & PARAM_STRING)==0){
- LOG(L_CRIT, "BUG: %s: fix_flag(%s): bad parameter type\n",
- mod_name, param_name);
- return -1;
- }
- s=(char*)val;
- len=strlen(s);
- f=-1;
- /* try to see if it's a number */
- num = str2s(s, len, &err);
- if (err != 0) {
- /* see if it's in the name:<no> format */
- p=strchr(s, ':');
- if (p){
- f= str2s(p+1, strlen(p+1), &err);
- if (err!=0){
- LOG(L_ERR, "ERROR: %s: invalid %s format:"
- " \"%s\"", mod_name, param_name, s);
- return -1;
- }
- *p=0;
- }
- if ((num=get_flag_no(s, len))<0){
- /* not declared yet, declare it */
- num=register_flag(s, f);
- }
- if (num<0){
- LOG(L_ERR, "ERROR: %s: bad %s %s\n", mod_name, param_name, s);
- return -1;
- } else if ((f>0) && (num!=f)){
- LOG(L_ERR, "WARNING: %s: flag %s already defined"
- " as %d (and not %d), using %s:%d\n",
- mod_name, s, num, f, s, num);
- }
- }
- *flag=num;
- return 0;
- }
- /*
- * Common function parameter fixups
- */
- /*
- * Generic parameter fixup function which creates
- * fparam_t structure. type parameter contains allowed
- * parameter types
- *
- * Returns:
- * 0 on success,
- * 1 if the param doesn't match the specified type
- * <0 on failure
- */
- int fix_param(int type, void** param)
- {
- fparam_t* p;
- str name, s;
- unsigned int num;
- int err;
- p = (fparam_t*)pkg_malloc(sizeof(fparam_t));
- if (!p) {
- ERR("No memory left\n");
- return E_OUT_OF_MEM;
- }
- memset(p, 0, sizeof(fparam_t));
- p->orig = *param;
- switch(type) {
- case FPARAM_UNSPEC:
- ERR("Invalid type value\n");
- goto error;
- case FPARAM_STRING:
- p->v.asciiz = *param;
- break;
- case FPARAM_STR:
- p->v.str.s = (char*)*param;
- p->v.str.len = strlen(p->v.str.s);
- break;
- case FPARAM_INT:
- s.s = (char*)*param;
- s.len = strlen(s.s);
- err = str2int(&s, &num);
- if (err == 0) {
- p->v.i = (int)num;
- } else {
- /* Not a number */
- pkg_free(p);
- return 1;
- }
- break;
- case FPARAM_REGEX:
- if ((p->v.regex = pkg_malloc(sizeof(regex_t))) == 0) {
- ERR("No memory left\n");
- goto error;
- }
- if (regcomp(p->v.regex, *param, REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
- pkg_free(p->v.regex);
- ERR("Bad regular expression '%s'\n", (char*)*param);
- goto error;
- }
- break;
- case FPARAM_AVP:
- name.s = (char*)*param;
- name.len = strlen(name.s);
- trim(&name);
- if (!name.len || name.s[0] != '$') {
- /* Not an AVP identifier */
- pkg_free(p);
- return 1;
- }
- name.s++;
- name.len--;
- if (parse_avp_ident(&name, &p->v.avp) < 0) {
- ERR("Error while parsing attribute name\n");
- goto error;
- }
- break;
- case FPARAM_SELECT:
- name.s = (char*)*param;
- name.len = strlen(name.s);
- trim(&name);
- if (!name.len || name.s[0] != '@') {
- /* Not a select identifier */
- pkg_free(p);
- return 1;
- }
- if (parse_select(&name.s, &p->v.select) < 0) {
- ERR("Error while parsing select identifier\n");
- goto error;
- }
- break;
- case FPARAM_SUBST:
- s.s = *param;
- s.len = strlen(s.s);
- p->v.subst = subst_parser(&s);
- if (!p->v.subst) {
- ERR("Error while parsing regex substitution\n");
- goto error;
- }
- break;
- }
- p->type = type;
- *param = (void*)p;
- return 0;
- error:
- pkg_free(p);
- return E_UNSPEC;
- }
- /*
- * Fixup variable string, the parameter can be
- * AVP, SELECT, or ordinary string. AVP and select
- * identifiers will be resolved to their values during
- * runtime
- *
- * The parameter value will be converted to fparam structure
- * This function returns -1 on an error
- */
- int fixup_var_str_12(void** param, int param_no)
- {
- int ret;
- if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
- if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
- if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
- ERR("Error while fixing parameter, AVP, SELECT, and str conversions failed\n");
- return -1;
- }
- /* Same as fixup_var_str_12 but applies to the 1st parameter only */
- int fixup_var_str_1(void** param, int param_no)
- {
- if (param_no == 1) return fixup_var_str_12(param, param_no);
- else return 0;
- }
- /* Same as fixup_var_str_12 but applies to the 2nd parameter only */
- int fixup_var_str_2(void** param, int param_no)
- {
- if (param_no == 2) return fixup_var_str_12(param, param_no);
- else return 0;
- }
- /*
- * Fixup variable integer, the parameter can be
- * AVP, SELECT, or ordinary integer. AVP and select
- * identifiers will be resolved to their values and
- * converted to int if necessary during runtime
- *
- * The parameter value will be converted to fparam structure
- * This function returns -1 on an error
- */
- int fixup_var_int_12(void** param, int param_no)
- {
- int ret;
- if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
- if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
- if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
- ERR("Error while fixing parameter, AVP, SELECT, and int conversions failed\n");
- return -1;
- }
- /* Same as fixup_var_int_12 but applies to the 1st parameter only */
- int fixup_var_int_1(void** param, int param_no)
- {
- if (param_no == 1) return fixup_var_int_12(param, param_no);
- else return 0;
- }
- /* Same as fixup_var_int_12 but applies to the 2nd parameter only */
- int fixup_var_int_2(void** param, int param_no)
- {
- if (param_no == 2) return fixup_var_int_12(param, param_no);
- else return 0;
- }
- /*
- * The parameter must be a regular expression which must compile, the
- * parameter will be converted to compiled regex
- */
- int fixup_regex_12(void** param, int param_no)
- {
- int ret;
- if ((ret = fix_param(FPARAM_REGEX, param)) <= 0) return ret;
- ERR("Error while compiling regex in function parameter\n");
- return -1;
- }
- /* Same as fixup_regex_12 but applies to the 1st parameter only */
- int fixup_regex_1(void** param, int param_no)
- {
- if (param_no == 1) return fixup_regex_12(param, param_no);
- else return 0;
- }
- /* Same as fixup_regex_12 but applies to the 2nd parameter only */
- int fixup_regex_2(void** param, int param_no)
- {
- if (param_no == 2) return fixup_regex_12(param, param_no);
- else return 0;
- }
- /*
- * The string parameter will be converted to integer
- */
- int fixup_int_12(void** param, int param_no)
- {
- int ret;
- if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
- ERR("Cannot function parameter to integer\n");
- return -1;
- }
- /* Same as fixup_int_12 but applies to the 1st parameter only */
- int fixup_int_1(void** param, int param_no)
- {
- if (param_no == 1) return fixup_int_12(param, param_no);
- else return 0;
- }
- /* Same as fixup_int_12 but applies to the 2nd parameter only */
- int fixup_int_2(void** param, int param_no)
- {
- if (param_no == 2) return fixup_int_12(param, param_no);
- else return 0;
- }
- /*
- * Parse the parameter as static string, do not resolve
- * AVPs or selects, convert the parameter to str structure
- */
- int fixup_str_12(void** param, int param_no)
- {
- int ret;
- if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
- ERR("Cannot function parameter to string\n");
- return -1;
- }
- /* Same as fixup_str_12 but applies to the 1st parameter only */
- int fixup_str_1(void** param, int param_no)
- {
- if (param_no == 1) return fixup_str_12(param, param_no);
- else return 0;
- }
- /* Same as fixup_str_12 but applies to the 2nd parameter only */
- int fixup_str_2(void** param, int param_no)
- {
- if (param_no == 2) return fixup_str_12(param, param_no);
- else return 0;
- }
- /*
- * Get the function parameter value as string
- * Return values: 0 - Success
- * -1 - Cannot get value
- */
- int get_str_fparam(str* dst, struct sip_msg* msg, fparam_t* param)
- {
- int_str val;
- int ret;
- avp_t* avp;
- switch(param->type) {
- case FPARAM_REGEX:
- case FPARAM_UNSPEC:
- case FPARAM_INT:
- return -1;
- case FPARAM_STRING:
- dst->s = param->v.asciiz;
- dst->len = strlen(param->v.asciiz);
- break;
- case FPARAM_STR:
- *dst = param->v.str;
- break;
- case FPARAM_AVP:
- avp = search_first_avp(param->v.avp.flags, param->v.avp.name, &val, 0);
- if (!avp) {
- DBG("Could not find AVP from function parameter '%s'\n", param->orig);
- return -1;
- }
- if (avp->flags & AVP_VAL_STR) {
- *dst = val.s;
- } else {
- /* The caller does not know of what type the AVP will be so
- * convert int AVPs into string here
- */
- dst->s = int2str(val.n, &dst->len);
- }
- break;
- case FPARAM_SELECT:
- ret = run_select(dst, param->v.select, msg);
- if (ret < 0 || ret > 0) return -1;
- break;
- }
- return 0;
- }
- /*
- * Get the function parameter value as integer
- * Return values: 0 - Success
- * -1 - Cannot get value
- */
- int get_int_fparam(int* dst, struct sip_msg* msg, fparam_t* param)
- {
- int_str val;
- int ret;
- avp_t* avp;
- str tmp;
- switch(param->type) {
- case FPARAM_INT:
- *dst = param->v.i;
- return 0;
- case FPARAM_REGEX:
- case FPARAM_UNSPEC:
- case FPARAM_STRING:
- case FPARAM_STR:
- return -1;
- case FPARAM_AVP:
- avp = search_first_avp(param->v.avp.flags, param->v.avp.name, &val, 0);
- if (!avp) {
- DBG("Could not find AVP from function parameter '%s'\n", param->orig);
- return -1;
- }
- if (avp->flags & AVP_VAL_STR) {
- if (str2int(&val.s, (unsigned int*)dst) < 0) {
- ERR("Could not convert AVP string value to int\n");
- return -1;
- }
- } else {
- *dst = val.n;
- }
- break;
- case FPARAM_SELECT:
- ret = run_select(&tmp, param->v.select, msg);
- if (ret < 0 || ret > 0) return -1;
- if (str2int(&tmp, (unsigned int*)dst) < 0) {
- ERR("Could not convert select result to int\n");
- return -1;
- }
- break;
- }
- return 0;
- }
- /**
- * Retrieve the compiled RegExp.
- * @return: 0 for success, negative on error.
- */
- int get_regex_fparam(regex_t *dst, struct sip_msg* msg, fparam_t* param)
- {
- switch (param->type) {
- case FPARAM_REGEX:
- *dst = *param->v.regex;
- return 0;
- default:
- ERR("unexpected parameter type (%d), instead of regexp.\n",
- param->type);
- }
- return -1;
- }
|