avpops.c

Go to the documentation of this file.
00001 /*
00002  * $Id: avpops.c 5499 2009-01-22 16:26:13Z henningw $
00003  *
00004  * Copyright (C) 2004-2006 Voice Sistem SRL
00005  *
00006  * This file is part of Kamailio.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation; either version 2
00011  * of the License, or (at your option) any later version.
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00021  *
00022  * History:
00023  * ---------
00024  *  2004-10-04  first version (ramona)
00025  *  2004-11-15  added support for db schemes for avp_db_load (ramona)
00026  *  2004-11-17  aligned to new AVP core global aliases (ramona)
00027  *  2005-01-30  "fm" (fast match) operator added (ramona)
00028  *  2005-01-30  avp_copy (copy/move operation) added (ramona)
00029  */
00030 
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <sys/types.h> /* for regex */
00036 #include <regex.h>
00037 
00038 #include "../../mem/shm_mem.h"
00039 #include "../../mem/mem.h"
00040 #include "../../parser/parse_hname2.h"
00041 #include "../../sr_module.h"
00042 #include "../../str.h"
00043 #include "../../dprint.h"
00044 #include "../../error.h"
00045 #include "../../ut.h"
00046 #include "avpops_parse.h"
00047 #include "avpops_impl.h"
00048 #include "avpops_db.h"
00049 
00050 
00051 MODULE_VERSION
00052 
00053 /* modules param variables */
00054 static str db_url          = {NULL, 0};  /* database url */
00055 static str db_table        = {NULL, 0};  /* table */
00056 static int use_domain      = 0;  /* if domain should be use for avp matching */
00057 static str uuid_col        = str_init("uuid");
00058 static str attribute_col   = str_init("attribute");
00059 static str value_col       = str_init("value");
00060 static str type_col        = str_init("type");
00061 static str username_col    = str_init("username");
00062 static str domain_col      = str_init("domain");
00063 static str* db_columns[6] = {&uuid_col, &attribute_col, &value_col, &type_col, &username_col, &domain_col};
00064 
00065 
00066 static int avpops_init(void);
00067 static int avpops_child_init(int rank);
00068 
00069 static int fixup_db_load_avp(void** param, int param_no);
00070 static int fixup_db_delete_avp(void** param, int param_no);
00071 static int fixup_db_store_avp(void** param, int param_no);
00072 static int fixup_db_query_avp(void** param, int param_no);
00073 static int fixup_delete_avp(void** param, int param_no);
00074 static int fixup_copy_avp(void** param, int param_no);
00075 static int fixup_pushto_avp(void** param, int param_no);
00076 static int fixup_check_avp(void** param, int param_no);
00077 static int fixup_op_avp(void** param, int param_no);
00078 static int fixup_subst(void** param, int param_no);
00079 static int fixup_is_avp_set(void** param, int param_no);
00080 
00081 static int w_print_avps(struct sip_msg* msg, char* foo, char *bar);
00082 static int w_dbload_avps(struct sip_msg* msg, char* source, char* param);
00083 static int w_dbdelete_avps(struct sip_msg* msg, char* source, char* param);
00084 static int w_dbstore_avps(struct sip_msg* msg, char* source, char* param);
00085 static int w_dbquery1_avps(struct sip_msg* msg, char* query, char* param);
00086 static int w_dbquery2_avps(struct sip_msg* msg, char* query, char* dest);
00087 static int w_delete_avps(struct sip_msg* msg, char* param, char *foo);
00088 static int w_copy_avps(struct sip_msg* msg, char* param, char *check);
00089 static int w_pushto_avps(struct sip_msg* msg, char* destination, char *param);
00090 static int w_check_avps(struct sip_msg* msg, char* param, char *check);
00091 static int w_op_avps(struct sip_msg* msg, char* param, char *op);
00092 static int w_subst(struct sip_msg* msg, char* src, char *subst);
00093 static int w_is_avp_set(struct sip_msg* msg, char* param, char *foo);
00094 
00095 /*! \brief
00096  * Exported functions
00097  */
00098 static cmd_export_t cmds[] = {
00099    {"avp_print", (cmd_function)w_print_avps, 0, 0, 0,
00100       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00101    {"avp_db_load", (cmd_function)w_dbload_avps,  2, fixup_db_load_avp, 0,
00102       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00103    {"avp_db_delete", (cmd_function)w_dbdelete_avps, 2, fixup_db_delete_avp, 0,
00104       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00105    {"avp_db_store", (cmd_function)w_dbstore_avps,  2, fixup_db_store_avp, 0,
00106       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00107    {"avp_db_query", (cmd_function)w_dbquery1_avps, 1, fixup_db_query_avp, 0,
00108       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00109    {"avp_db_query", (cmd_function)w_dbquery2_avps, 2, fixup_db_query_avp, 0,
00110       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00111    {"avp_delete", (cmd_function)w_delete_avps, 1, fixup_delete_avp, 0,
00112       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00113    {"avp_copy",   (cmd_function)w_copy_avps,  2,  fixup_copy_avp, 0,
00114       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00115    {"avp_pushto", (cmd_function)w_pushto_avps, 2, fixup_pushto_avp, 0,
00116       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00117    {"avp_check",  (cmd_function)w_check_avps, 2, fixup_check_avp, 0,
00118       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00119    {"avp_op",     (cmd_function)w_op_avps, 2, fixup_op_avp, 0,
00120       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00121    {"avp_subst",  (cmd_function)w_subst,   2, fixup_subst, 0,
00122       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00123    {"is_avp_set", (cmd_function)w_is_avp_set, 1, fixup_is_avp_set, 0,
00124       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00125    {0, 0, 0, 0, 0, 0}
00126 };
00127 
00128 
00129 /*! \brief
00130  * Exported parameters
00131  */
00132 static param_export_t params[] = {
00133    {"db_url",            STR_PARAM, &db_url.s        },
00134    {"avp_table",         STR_PARAM, &db_table.s      },
00135    {"use_domain",        INT_PARAM, &use_domain      },
00136    {"uuid_column",       STR_PARAM, &uuid_col.s      },
00137    {"attribute_column",  STR_PARAM, &attribute_col.s },
00138    {"value_column",      STR_PARAM, &value_col.s     },
00139    {"type_column",       STR_PARAM, &type_col.s      },
00140    {"username_column",   STR_PARAM, &username_col.s  },
00141    {"domain_column",     STR_PARAM, &domain_col.s    },
00142    {"db_scheme",         STR_PARAM|USE_FUNC_PARAM, (void*)avp_add_db_scheme },
00143    {0, 0, 0}
00144 };
00145 
00146 
00147 struct module_exports exports = {
00148    "avpops",
00149    DEFAULT_DLFLAGS, /* dlopen flags */
00150    cmds,       /* Exported functions */
00151    params,     /* Exported parameters */
00152    0,          /* exported statistics */
00153    0,          /* exported MI functions */
00154    0,          /* exported pseudo-variables */
00155    0,          /* extra processes */
00156    avpops_init,/* Module initialization function */
00157    0,
00158    0,
00159    (child_init_function) avpops_child_init /* per-child init function */
00160 };
00161 
00162 
00163 static int avpops_init(void)
00164 {
00165    if (db_url.s)
00166       db_url.len = strlen(db_url.s);
00167    if (db_table.s)
00168       db_table.len = strlen(db_table.s);
00169    uuid_col.len = strlen(uuid_col.s);
00170    attribute_col.len = strlen(attribute_col.s);
00171    value_col.len = strlen(value_col.s);
00172    type_col.len = strlen(type_col.s);
00173    username_col.len = strlen(username_col.s);
00174    domain_col.len = strlen(domain_col.s);
00175 
00176    /* if DB_URL defined -> bind to a DB module */
00177    if (db_url.s!=0)
00178    {
00179       /* check AVP_TABLE param */
00180       if (db_table.s==0)
00181       {
00182          LM_CRIT("\"AVP_DB\" present but \"AVP_TABLE\" found empty\n");
00183          goto error;
00184       }
00185       /* bind to the DB module */
00186       if (avpops_db_bind(&db_url)<0)
00187          goto error;
00188    }
00189 
00190    init_store_avps(db_columns);
00191 
00192    return 0;
00193 error:
00194    return -1;
00195 }
00196 
00197 
00198 static int avpops_child_init(int rank)
00199 {
00200    /* init DB only if enabled */
00201    if (db_url.s==0)
00202       return 0;
00203    /* skip main process and TCP manager process */
00204    if (rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00205       return 0;
00206    /* init DB connection */
00207    return avpops_db_init(&db_url, &db_table, db_columns);
00208 }
00209 
00210 
00211 static int fixup_db_avp(void** param, int param_no, int allow_scheme)
00212 {
00213    struct fis_param *sp;
00214    struct db_param  *dbp;
00215    int flags;
00216    int flags0;
00217    str s;
00218    char *p;
00219 
00220    flags=0;
00221    flags0=0;
00222    if (db_url.s==0)
00223    {
00224       LM_ERR("you have to configure a db_url for using avp_db_xxx functions\n");
00225       return E_UNSPEC;
00226    }
00227 
00228    s.s = (char*)*param;
00229    if (param_no==1)
00230    {
00231       /* prepare the fis_param structure */
00232       sp = (struct fis_param*)pkg_malloc(sizeof(struct fis_param));
00233       if (sp==0) {
00234          LM_ERR("no more pkg mem!\n");
00235          return E_OUT_OF_MEM;
00236       }
00237       memset( sp, 0, sizeof(struct fis_param));
00238 
00239       if ( (p=strchr(s.s,'/'))!=0)
00240       {
00241          *(p++) = 0;
00242          /* check for extra flags/params */
00243          if (!strcasecmp("domain",p)) {
00244             flags|=AVPOPS_FLAG_DOMAIN0;
00245          } else if (!strcasecmp("username",p)) {
00246             flags|=AVPOPS_FLAG_USER0;
00247          } else if (!strcasecmp("uri",p)) {
00248             flags|=AVPOPS_FLAG_URI0;
00249          } else if (!strcasecmp("uuid",p)) {
00250             flags|=AVPOPS_FLAG_UUID0;
00251          } else {
00252             LM_ERR("unknow flag "
00253                "<%s>\n",p);
00254             return E_UNSPEC;
00255          }
00256       }
00257       if (*s.s!='$')
00258       {
00259          /* is a constant string -> use it as uuid*/
00260          sp->opd = ((flags==0)?AVPOPS_FLAG_UUID0:flags)|AVPOPS_VAL_STR;
00261          sp->u.s.s = (char*)pkg_malloc(strlen(s.s)+1);
00262          if (sp->u.s.s==0) {
00263             LM_ERR("no more pkg mem!!\n");
00264             return E_OUT_OF_MEM;
00265          }
00266          sp->u.s.len = strlen(s.s);
00267          strcpy(sp->u.s.s, s.s);
00268       } else {
00269          /* is a variable $xxxxx */
00270          s.len = strlen(s.s);
00271          p = pv_parse_spec(&s, &sp->u.sval);
00272          if (p==0 || sp->u.sval.type==PVT_NULL || sp->u.sval.type==PVT_EMPTY)
00273          {
00274             LM_ERR("bad param 1; "
00275                "expected : $pseudo-variable or int/str value\n");
00276             return E_UNSPEC;
00277          }
00278          
00279          if(sp->u.sval.type==PVT_RURI || sp->u.sval.type==PVT_FROM
00280                || sp->u.sval.type==PVT_TO || sp->u.sval.type==PVT_OURI)
00281          {
00282             sp->opd = ((flags==0)?AVPOPS_FLAG_URI0:flags)|AVPOPS_VAL_PVAR;
00283          } else {
00284             sp->opd = ((flags==0)?AVPOPS_FLAG_UUID0:flags)|AVPOPS_VAL_PVAR;
00285          }
00286       }
00287       *param=(void*)sp;
00288    } else if (param_no==2) {
00289       /* compose the db_param structure */
00290       dbp = (struct db_param*)pkg_malloc(sizeof(struct db_param));
00291       if (dbp==0)
00292       {
00293          LM_ERR("no more pkg mem!!!\n");
00294          return E_OUT_OF_MEM;
00295       }
00296       memset( dbp, 0, sizeof(struct db_param));
00297       if ( parse_avp_db( s.s, dbp, allow_scheme)!=0 )
00298       {
00299          LM_ERR("parse failed\n");
00300          return E_UNSPEC;
00301       }
00302       *param=(void*)dbp;
00303    }
00304 
00305    return 0;
00306 }
00307 
00308 
00309 static int fixup_db_load_avp(void** param, int param_no)
00310 {
00311    return fixup_db_avp( param, param_no, 1/*allow scheme*/);
00312 }
00313 
00314 static int fixup_db_delete_avp(void** param, int param_no)
00315 {
00316    return fixup_db_avp( param, param_no, 0/*no scheme*/);
00317 }
00318 
00319 
00320 static int fixup_db_store_avp(void** param, int param_no)
00321 {
00322    return fixup_db_avp( param, param_no, 0/*no scheme*/);
00323 }
00324 
00325 static int fixup_db_query_avp(void** param, int param_no)
00326 {
00327    pv_elem_t *model = NULL;
00328    pvname_list_t *anlist = NULL;
00329    str s;
00330 
00331    if (db_url.s==0)
00332    {
00333       LM_ERR("you have to configure db_url for using avp_db_query function\n");
00334       return E_UNSPEC;
00335    }
00336 
00337    s.s = (char*)(*param);
00338    if (param_no==1)
00339    {
00340       if(s.s==NULL)
00341       {
00342          LM_ERR("null format in P%d\n",
00343                param_no);
00344          return E_UNSPEC;
00345       }
00346       s.len = strlen(s.s);
00347       if(pv_parse_format(&s, &model)<0)
00348       {
00349          LM_ERR("wrong format[%s]\n", s.s);
00350          return E_UNSPEC;
00351       }
00352          
00353       *param = (void*)model;
00354       return 0;
00355    } else if(param_no==2) {
00356       if(s.s==NULL)
00357       {
00358          LM_ERR("null format in P%d\n", param_no);
00359          return E_UNSPEC;
00360       }
00361             s.len = strlen(s.s);
00362 
00363       anlist = parse_pvname_list(&s, PVT_AVP);
00364       if(anlist==NULL)
00365       {
00366          LM_ERR("bad format in P%d [%s]\n", param_no, s.s);
00367          return E_UNSPEC;
00368       }
00369       *param = (void*)anlist;
00370       return 0;
00371    }
00372 
00373    return 0;
00374 }
00375 
00376 
00377 static int fixup_delete_avp(void** param, int param_no)
00378 {
00379    struct fis_param *ap=NULL;
00380    char *p;
00381    char *s;
00382    unsigned int flags;
00383    str s0;
00384 
00385    s = (char*)(*param);
00386    if (param_no==1) {
00387       /* attribute name / alias */
00388       if ( (p=strchr(s,'/'))!=0 )
00389          *(p++)=0;
00390       
00391       if(*s=='$')
00392       {
00393          /* is variable */
00394          ap = avpops_parse_pvar(s);
00395          if (ap==0)
00396          {
00397             LM_ERR("unable to get"
00398                " pseudo-variable in param \n");
00399             return E_UNSPEC;
00400          }
00401          if (ap->u.sval.type!=PVT_AVP)
00402          {
00403             LM_ERR("bad param; expected : $avp(name)\n");
00404             return E_UNSPEC;
00405          }
00406          ap->opd|=AVPOPS_VAL_PVAR;
00407          ap->type = AVPOPS_VAL_PVAR;
00408       } else {
00409          if(strlen(s)<1)
00410          {
00411             LM_ERR("bad param - expected : $avp(name), *, s or i value\n");
00412             return E_UNSPEC;
00413          }
00414          ap = (struct fis_param*)pkg_malloc(sizeof(struct fis_param));
00415          if (ap==0)
00416          {
00417             LM_ERR(" no more pkg mem\n");
00418             return E_OUT_OF_MEM;
00419          }
00420          memset(ap, 0, sizeof(struct fis_param));
00421          ap->opd|=AVPOPS_VAL_NONE;
00422          switch(*s) {
00423             case 's': case 'S':
00424                ap->opd = AVPOPS_VAL_NONE|AVPOPS_VAL_STR;
00425             break;
00426             case 'i': case 'I':
00427                ap->opd = AVPOPS_VAL_NONE|AVPOPS_VAL_INT;
00428             break;
00429             case '*': case 'a': case 'A':
00430                ap->opd = AVPOPS_VAL_NONE;
00431             break;
00432             default:
00433                LM_ERR(" bad param - expected : *, s or i AVP flag\n");
00434                pkg_free(ap);
00435                return E_UNSPEC;
00436          }
00437          /* flags */
00438          flags = 0;
00439          if(*(s+1)!='\0')
00440          {
00441             s0.s = s+1;
00442             s0.len = strlen(s0.s);
00443             if(str2int(&s0, &flags)!=0)
00444             {
00445                LM_ERR("bad avp flags\n");
00446                pkg_free(ap);
00447                return E_UNSPEC;
00448             }
00449          }
00450          ap->type = AVPOPS_VAL_INT;
00451          ap->u.n = flags<<8;
00452       }
00453 
00454       /* flags */
00455       for( ; p&&*p ; p++ )
00456       {
00457          switch (*p)
00458          {
00459             case 'g':
00460             case 'G':
00461                ap->ops|=AVPOPS_FLAG_ALL;
00462                break;
00463             default:
00464                LM_ERR(" bad flag <%c>\n",*p);
00465                if(ap!=NULL)
00466                   pkg_free(ap);
00467                return E_UNSPEC;
00468          }
00469       }
00470       /* force some flags: if no avp name is given, force "all" flag */
00471       if (ap->opd&AVPOPS_VAL_NONE)
00472          ap->ops |= AVPOPS_FLAG_ALL;
00473 
00474       *param=(void*)ap;
00475    }
00476 
00477    return 0;
00478 }
00479 
00480 static int fixup_copy_avp(void** param, int param_no)
00481 {
00482    struct fis_param *ap;
00483    char *s;
00484    char *p;
00485 
00486    s = (char*)*param;
00487    ap = 0;
00488    p = 0;
00489 
00490    if (param_no==2)
00491    {
00492       /* avp / flags */
00493       if ( (p=strchr(s,'/'))!=0 )
00494          *(p++)=0;
00495    }
00496 
00497    ap = avpops_parse_pvar(s);
00498    if (ap==0)
00499    {
00500       LM_ERR("unable to get pseudo-variable in P%d\n", param_no);
00501       return E_OUT_OF_MEM;
00502    }
00503 
00504    /* attr name is mandatory */
00505    if (ap->u.sval.type!=PVT_AVP)
00506    {
00507       LM_ERR("you must specify only AVP as parameter\n");
00508       return E_UNSPEC;
00509    }
00510 
00511    if (param_no==2)
00512    {
00513       /* flags */
00514       for( ; p&&*p ; p++ )
00515       {
00516          switch (*p) {
00517             case 'g':
00518             case 'G':
00519                ap->ops|=AVPOPS_FLAG_ALL;
00520                break;
00521             case 'd':
00522             case 'D':
00523                ap->ops|=AVPOPS_FLAG_DELETE;
00524                break;
00525             case 'n':
00526             case 'N':
00527                ap->ops|=AVPOPS_FLAG_CASTN;
00528                break;
00529             case 's':
00530             case 'S':
00531                ap->ops|=AVPOPS_FLAG_CASTS;
00532                break;
00533             default:
00534                LM_ERR("bad flag <%c>\n",*p);
00535                return E_UNSPEC;
00536          }
00537       }
00538    }
00539 
00540    *param=(void*)ap;
00541    return 0;
00542 }
00543 
00544 static int fixup_pushto_avp(void** param, int param_no)
00545 {
00546    struct fis_param *ap;
00547    char *s;
00548    char *p;
00549 
00550    s = (char*)*param;
00551    ap = 0;
00552 
00553    if (param_no==1)
00554    {
00555       if ( *s!='$')
00556       {
00557          LM_ERR("bad param 1; expected : $ru $du ...\n");
00558          return E_UNSPEC;
00559       }
00560       /* compose the param structure */
00561 
00562       if ( (p=strchr(s,'/'))!=0 )
00563          *(p++)=0;
00564       ap = avpops_parse_pvar(s);
00565       if (ap==0)
00566       {
00567          LM_ERR("unable to get pseudo-variable in param 1\n");
00568          return E_OUT_OF_MEM;
00569       }
00570 
00571       switch(ap->u.sval.type) {
00572          case PVT_RURI:
00573             ap->opd = AVPOPS_VAL_NONE|AVPOPS_USE_RURI;
00574             if ( p && !(
00575                (!strcasecmp("username",p)
00576                      && (ap->opd|=AVPOPS_FLAG_USER0)) ||
00577                (!strcasecmp("domain",p)
00578                      && (ap->opd|=AVPOPS_FLAG_DOMAIN0)) ))
00579             {
00580                LM_ERR("unknown ruri flag \"%s\"!\n",p);
00581                return E_UNSPEC;
00582             }
00583          break;
00584          case PVT_DSTURI:
00585             if ( p!=0 )
00586             {
00587                LM_ERR("unknown duri flag \"%s\"!\n",p);
00588                return E_UNSPEC;
00589             }
00590             ap->opd = AVPOPS_VAL_NONE|AVPOPS_USE_DURI;
00591          break;
00592          case PVT_HDR:
00593             /* what's the hdr destination ? request or reply? */
00594             LM_ERR("push to header  is obsoleted - use append_hf() "
00595                   "or append_to_reply() from textops module!\n");
00596             return E_UNSPEC;
00597          break;
00598          case PVT_BRANCH:
00599             if ( p!=0 )
00600             {
00601                LM_ERR("unknown branch flag \"%s\"!\n",p);
00602                return E_UNSPEC;
00603             }
00604             ap->opd = AVPOPS_VAL_NONE|AVPOPS_USE_BRANCH;
00605          break;
00606          default:
00607             LM_ERR("unsupported destination \"%s\"; "
00608                   "expected $ru,$du,$br\n",s);
00609             return E_UNSPEC;
00610       }
00611    } else if (param_no==2) {
00612       /* attribute name*/
00613       if ( *s!='$')
00614       {
00615          LM_ERR("bad param 2; expected: $pseudo-variable ...\n");
00616          return E_UNSPEC;
00617       }
00618       /* compose the param structure */
00619 
00620       if ( (p=strchr(s,'/'))!=0 )
00621          *(p++)=0;
00622       ap = avpops_parse_pvar(s);
00623       if (ap==0)
00624       {
00625          LM_ERR("unable to get pseudo-variable in param 2\n");
00626          return E_OUT_OF_MEM;
00627       }
00628       if (ap->u.sval.type==PVT_NULL)
00629       {
00630          LM_ERR("bad param 2; expected : $pseudo-variable ...\n");
00631          pkg_free(ap);
00632          return E_UNSPEC;
00633       }
00634       ap->opd |= AVPOPS_VAL_PVAR;
00635 
00636       /* flags */
00637       for( ; p&&*p ; p++ )
00638       {
00639          switch (*p) {
00640             case 'g':
00641             case 'G':
00642                ap->ops|=AVPOPS_FLAG_ALL;
00643                break;
00644             default:
00645                LM_ERR("bad flag <%c>\n",*p);
00646                pkg_free(ap);
00647                return E_UNSPEC;
00648          }
00649       }
00650    }
00651 
00652    *param=(void*)ap;
00653    return 0;
00654 }
00655 
00656 static int fixup_check_avp(void** param, int param_no)
00657 {
00658    struct fis_param *ap;
00659    regex_t* re;
00660    char *s;
00661 
00662    s = (char*)*param;
00663    ap = 0;
00664 
00665    if (param_no==1)
00666    {
00667       ap = avpops_parse_pvar(s);
00668       if (ap==0)
00669       {
00670          LM_ERR("unable to get pseudo-variable in param 1\n");
00671          return E_OUT_OF_MEM;
00672       }
00673       /* attr name is mandatory */
00674       if (ap->u.sval.type==PVT_NULL)
00675       {
00676          LM_ERR("null pseudo-variable in param 1\n");
00677          return E_UNSPEC;
00678       }
00679    } else if (param_no==2) {
00680       if ( (ap=parse_check_value(s))==0 )
00681       {
00682          LM_ERR("failed to parse checked value \n");
00683          return E_UNSPEC;
00684       }
00685       /* if REGEXP op -> compile the expresion */
00686       if (ap->ops&AVPOPS_OP_RE)
00687       {
00688          if ( (ap->opd&AVPOPS_VAL_STR)==0 )
00689          {
00690             LM_ERR("regexp operation requires string value\n");
00691             return E_UNSPEC;
00692          }
00693          re = pkg_malloc(sizeof(regex_t));
00694          if (re==0)
00695          {
00696             LM_ERR("no more pkg mem\n");
00697             return E_OUT_OF_MEM;
00698          }
00699          LM_DBG("compiling regexp <%.*s>\n", ap->u.s.len, ap->u.s.s);
00700          if (regcomp(re, ap->u.s.s,
00701                   REG_EXTENDED|REG_ICASE|REG_NEWLINE))
00702          {
00703             pkg_free(re);
00704             LM_ERR("bad re <%.*s>\n", ap->u.s.len, ap->u.s.s);
00705             return E_BAD_RE;
00706          }
00707          /* free the string and link the regexp */
00708          // pkg_free(ap->sval.p.s);
00709          ap->u.s.s = (char*)re;
00710       } else if (ap->ops&AVPOPS_OP_FM) {
00711          if ( !( ap->opd&AVPOPS_VAL_PVAR ||
00712          (!(ap->opd&AVPOPS_VAL_PVAR) && ap->opd&AVPOPS_VAL_STR) ) )
00713          {
00714             LM_ERR("fast_match operation requires string value or "
00715                   "avp name/alias (%d/%d)\n",   ap->opd, ap->ops);
00716             return E_UNSPEC;
00717          }
00718       }
00719    }
00720 
00721    *param=(void*)ap;
00722    return 0;
00723 }
00724 
00725 static int fixup_subst(void** param, int param_no)
00726 {
00727    struct subst_expr* se;
00728    str subst;
00729    struct fis_param *ap;
00730    struct fis_param **av;
00731    char *s;
00732    char *p;
00733    
00734    if (param_no==1) {
00735       s = (char*)*param;
00736       ap = 0;
00737       p = 0;
00738       av = (struct fis_param**)pkg_malloc(2*sizeof(struct fis_param*));
00739       if(av==NULL)
00740       {
00741          LM_ERR("no more pkg memory\n");
00742          return E_UNSPEC;        
00743       }
00744       memset(av, 0, 2*sizeof(struct fis_param*));
00745 
00746       /* avp src / avp dst /flags */
00747       if ( (p=strchr(s,'/'))!=0 )
00748          *(p++)=0;
00749       ap = avpops_parse_pvar(s);
00750       if (ap==0)
00751       {
00752          LM_ERR("unable to get pseudo-variable in param 2 [%s]\n", s);
00753          return E_OUT_OF_MEM;
00754       }
00755       if (ap->u.sval.type!=PVT_AVP)
00756       {
00757          LM_ERR("bad attribute name <%s>\n", (char*)*param);
00758          pkg_free(av);
00759          return E_UNSPEC;
00760       }
00761       /* attr name is mandatory */
00762       if (ap->opd&AVPOPS_VAL_NONE)
00763       {
00764          LM_ERR("you must specify a name for the AVP\n");
00765          return E_UNSPEC;
00766       }
00767       av[0] = ap;
00768       if(p==0 || *p=='\0')
00769       {
00770          *param=(void*)av;
00771          return 0;
00772       }
00773       
00774       /* dst || flags */
00775       s = p;
00776       if(*s==PV_MARKER)
00777       {
00778          if ( (p=strchr(s,'/'))!=0 )
00779             *(p++)=0;
00780          if(p==0 || (p!=0 && p-s>1))
00781          {
00782             ap = avpops_parse_pvar(s);
00783             if (ap==0)
00784             {
00785                LM_ERR("unable to get pseudo-variable in param 2 [%s]\n",s);
00786                return E_OUT_OF_MEM;
00787             }
00788          
00789             if (ap->u.sval.type!=PVT_AVP)
00790             {
00791                LM_ERR("bad attribute name <%s>!\n", s);
00792                pkg_free(av);
00793                return E_UNSPEC;
00794             }
00795             /* attr name is mandatory */
00796             if (ap->opd&AVPOPS_VAL_NONE)
00797             {
00798                LM_ERR("you must specify a name for the AVP!\n");
00799                return E_UNSPEC;
00800             }
00801             av[1] = ap;
00802          }
00803          if(p==0 || *p=='\0')
00804          {
00805             *param=(void*)av;
00806             return 0;
00807          }
00808       }
00809       
00810       /* flags */
00811       for( ; p&&*p ; p++ )
00812       {
00813          switch (*p) {
00814             case 'g':
00815             case 'G':
00816                av[0]->ops|=AVPOPS_FLAG_ALL;
00817                break;
00818             case 'd':
00819             case 'D':
00820                av[0]->ops|=AVPOPS_FLAG_DELETE;
00821                break;
00822             default:
00823                LM_ERR("bad flag <%c>\n",*p);
00824                return E_UNSPEC;
00825          }
00826       }
00827       *param=(void*)av;
00828    } else if (param_no==2) {
00829       LM_DBG("%s fixing %s\n", exports.name, (char*)(*param));
00830       subst.s=*param;
00831       subst.len=strlen(*param);
00832       se=subst_parser(&subst);
00833       if (se==0){
00834          LM_ERR("%s: bad subst re %s\n",exports.name, (char*)*param);
00835          return E_BAD_RE;
00836       }
00837       /* don't free string -- needed for specifiers */
00838       /* pkg_free(*param); */
00839       /* replace it with the compiled subst. re */
00840       *param=se;
00841    }
00842 
00843    return 0;
00844 }
00845 
00846 static int fixup_op_avp(void** param, int param_no)
00847 {
00848    struct fis_param *ap;
00849    struct fis_param **av;
00850    char *s;
00851    char *p;
00852 
00853    s = (char*)*param;
00854    ap = 0;
00855 
00856    if (param_no==1)
00857    {
00858       av = (struct fis_param**)pkg_malloc(2*sizeof(struct fis_param*));
00859       if(av==NULL)
00860       {
00861          LM_ERR("no more pkg memory\n");
00862          return E_UNSPEC;        
00863       }
00864       memset(av, 0, 2*sizeof(struct fis_param*));
00865       /* avp src / avp dst */
00866       if ( (p=strchr(s,'/'))!=0 )
00867          *(p++)=0;
00868 
00869       av[0] = avpops_parse_pvar(s);
00870       if (av[0]==0)
00871       {
00872          LM_ERR("unable to get pseudo-variable in param 1\n");
00873          return E_OUT_OF_MEM;
00874       }
00875       if (av[0]->u.sval.type!=PVT_AVP)
00876       {
00877          LM_ERR("bad attribute name <%s>\n", (char*)*param);
00878          pkg_free(av);
00879          return E_UNSPEC;
00880       }
00881       if(p==0 || *p=='\0')
00882       {
00883          *param=(void*)av;
00884          return 0;
00885       }
00886       
00887       s = p;
00888       ap = avpops_parse_pvar(s);
00889       if (ap==0)
00890       {
00891          LM_ERR("unable to get pseudo-variable in param 1 (2)\n");
00892          return E_OUT_OF_MEM;
00893       }
00894       if (ap->u.sval.type!=PVT_AVP)
00895       {
00896          LM_ERR("bad attribute name/alias <%s>!\n", s);
00897          pkg_free(av);
00898          return E_UNSPEC;
00899       }
00900       av[1] = ap;
00901       *param=(void*)av;
00902       return 0;
00903    } else if (param_no==2) {
00904       if ( (ap=parse_op_value(s))==0 )
00905       {
00906          LM_ERR("failed to parse the value \n");
00907          return E_UNSPEC;
00908       }
00909       /* only integer values or avps */
00910       if ( (ap->opd&AVPOPS_VAL_STR)!=0 && (ap->opd&AVPOPS_VAL_PVAR)==0)
00911       {
00912          LM_ERR("operations requires integer values\n");
00913          return E_UNSPEC;
00914       }
00915       *param=(void*)ap;
00916       return 0;
00917    }
00918    return -1;
00919 }
00920 
00921 static int fixup_is_avp_set(void** param, int param_no)
00922 {
00923    struct fis_param *ap;
00924    char *p;
00925    char *s;
00926    
00927    s = (char*)(*param);
00928    if (param_no==1) {
00929       /* attribute name | alias / flags */
00930       if ( (p=strchr(s,'/'))!=0 )
00931          *(p++)=0;
00932       
00933       ap = avpops_parse_pvar(s);
00934       if (ap==0)
00935       {
00936          LM_ERR("unable to get pseudo-variable in param\n");
00937          return E_OUT_OF_MEM;
00938       }
00939       
00940       if (ap->u.sval.type!=PVT_AVP)
00941       {
00942          LM_ERR("bad attribute name <%s>\n", (char*)*param);
00943          return E_UNSPEC;
00944       }
00945       if(p==0 || *p=='\0')
00946          ap->ops|=AVPOPS_FLAG_ALL;
00947 
00948       /* flags */
00949       for( ; p&&*p ; p++ )
00950       {
00951          switch (*p) {
00952             case 'e':
00953             case 'E':
00954                ap->ops|=AVPOPS_FLAG_EMPTY;
00955                break;
00956             case 'n':
00957             case 'N':
00958                if(ap->ops&AVPOPS_FLAG_CASTS)
00959                {
00960                   LM_ERR("invalid flag combination <%c> and 's|S'\n",*p);
00961                   return E_UNSPEC;
00962                }
00963                ap->ops|=AVPOPS_FLAG_CASTN;
00964                break;
00965             case 's':
00966             case 'S':
00967                if(ap->ops&AVPOPS_FLAG_CASTN)
00968                {
00969                   LM_ERR("invalid flag combination <%c> and 'n|N'\n",*p);
00970                   return E_UNSPEC;
00971                }
00972                ap->ops|=AVPOPS_FLAG_CASTS;
00973                break;
00974             default:
00975                LM_ERR("bad flag <%c>\n",*p);
00976                return E_UNSPEC;
00977          }
00978       }
00979       
00980       *param=(void*)ap;
00981    }
00982 
00983    return 0;
00984 }
00985 
00986 static int w_dbload_avps(struct sip_msg* msg, char* source, char* param)
00987 {
00988    return ops_dbload_avps ( msg, (struct fis_param*)source,
00989                         (struct db_param*)param, use_domain);
00990 }
00991 
00992 static int w_dbdelete_avps(struct sip_msg* msg, char* source, char* param)
00993 {
00994    return ops_dbdelete_avps ( msg, (struct fis_param*)source,
00995                         (struct db_param*)param, use_domain);
00996 }
00997 
00998 static int w_dbstore_avps(struct sip_msg* msg, char* source, char* param)
00999 {
01000    return ops_dbstore_avps ( msg, (struct fis_param*)source,
01001                         (struct db_param*)param, use_domain);
01002 }
01003 
01004 static int w_dbquery1_avps(struct sip_msg* msg, char* query, char* param)
01005 {
01006    return ops_dbquery_avps ( msg, (pv_elem_t*)query, 0);
01007 }
01008 
01009 static int w_dbquery2_avps(struct sip_msg* msg, char* query, char* dest)
01010 {
01011    return ops_dbquery_avps ( msg, (pv_elem_t*)query, (pvname_list_t*)dest);
01012 }
01013 
01014 static int w_delete_avps(struct sip_msg* msg, char* param, char* foo)
01015 {
01016    return ops_delete_avp ( msg, (struct fis_param*)param);
01017 }
01018 
01019 static int w_copy_avps(struct sip_msg* msg, char* name1, char *name2)
01020 {
01021    return ops_copy_avp ( msg, (struct fis_param*)name1,
01022                         (struct fis_param*)name2);
01023 }
01024 
01025 static int w_pushto_avps(struct sip_msg* msg, char* destination, char *param)
01026 {
01027    return ops_pushto_avp ( msg, (struct fis_param*)destination,
01028                         (struct fis_param*)param);
01029 }
01030 
01031 static int w_check_avps(struct sip_msg* msg, char* param, char *check)
01032 {
01033    return ops_check_avp ( msg, (struct fis_param*)param,
01034                         (struct fis_param*)check);
01035 }
01036 
01037 static int w_op_avps(struct sip_msg* msg, char* param, char *op)
01038 {
01039    return ops_op_avp ( msg, (struct fis_param**)param,
01040                         (struct fis_param*)op);
01041 }
01042 
01043 static int w_subst(struct sip_msg* msg, char* src, char *subst)
01044 {
01045    return ops_subst(msg, (struct fis_param**)src, (struct subst_expr*)subst);
01046 }
01047 
01048 static int w_is_avp_set(struct sip_msg* msg, char* param, char *op)
01049 {
01050    return ops_is_avp_set(msg, (struct fis_param*)param);
01051 }
01052 
01053 static int w_print_avps(struct sip_msg* msg, char* foo, char *bar)
01054 {
01055    return ops_print_avp();
01056 }
01057 

Generated on Thu May 17 12:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6