static int fixup_subst(void** param, int param_no) { struct subst_expr* se; str subst; struct fis_param *ap; struct fis_param **av; char *s; char *p; if (param_no==1) { s = (char*)*param; ap = 0; p = 0; av = (struct fis_param**)pkg_malloc(2*sizeof(struct fis_param*)); if(av==NULL) { LM_ERR("no more pkg memory\n"); return E_UNSPEC; } memset(av, 0, 2*sizeof(struct fis_param*)); /* avp src / avp dst /flags */ if ( (p=strchr(s,'/'))!=0 ) *(p++)=0; ap = avpops_parse_pvar(s); if (ap==0) { LM_ERR("unable to get pseudo-variable in param 2 [%s]\n", s); return E_OUT_OF_MEM; } if (ap->u.sval.type!=PVT_AVP) { LM_ERR("bad attribute name <%s>\n", (char*)*param); pkg_free(av); return E_UNSPEC; } /* attr name is mandatory */ if (ap->opd&AVPOPS_VAL_NONE) { LM_ERR("you must specify a name for the AVP\n"); return E_UNSPEC; } av[0] = ap; if(p==0 || *p=='\0') { *param=(void*)av; return 0; } /* dst || flags */ s = p; if(*s==PV_MARKER) { if ( (p=strchr(s,'/'))!=0 ) *(p++)=0; if(p==0 || (p!=0 && p-s>1)) { ap = avpops_parse_pvar(s); if (ap==0) { LM_ERR("unable to get pseudo-variable in param 2 [%s]\n",s); return E_OUT_OF_MEM; } if (ap->u.sval.type!=PVT_AVP) { LM_ERR("bad attribute name <%s>!\n", s); pkg_free(av); return E_UNSPEC; } /* attr name is mandatory */ if (ap->opd&AVPOPS_VAL_NONE) { LM_ERR("you must specify a name for the AVP!\n"); return E_UNSPEC; } av[1] = ap; } if(p==0 || *p=='\0') { *param=(void*)av; return 0; } } /* flags */ for( ; p&&*p ; p++ ) { switch (*p) { case 'g': case 'G': av[0]->ops|=AVPOPS_FLAG_ALL; break; case 'd': case 'D': av[0]->ops|=AVPOPS_FLAG_DELETE; break; default: LM_ERR("bad flag <%c>\n",*p); return E_UNSPEC; } } *param=(void*)av; } else if (param_no==2) { LM_DBG("%s fixing %s\n", exports.name, (char*)(*param)); subst.s=*param; subst.len=strlen(*param); se=subst_parser(&subst); if (se==0){ LM_ERR("%s: bad subst re %s\n",exports.name, (char*)*param); return E_BAD_RE; } /* don't free string -- needed for specifiers */ /* pkg_free(*param); */ /* replace it with the compiled subst. re */ *param=se; } return 0; }
static int fixup_op_avp(void** param, int param_no) { struct fis_param *ap; struct fis_param **av; char *s; char *p; s = (char*)*param; ap = 0; if (param_no==1) { av = (struct fis_param**)pkg_malloc(2*sizeof(struct fis_param*)); if(av==NULL) { LM_ERR("no more pkg memory\n"); return E_UNSPEC; } memset(av, 0, 2*sizeof(struct fis_param*)); /* avp src / avp dst */ if ( (p=strchr(s,'/'))!=0 ) *(p++)=0; av[0] = avpops_parse_pvar(s); if (av[0]==0) { LM_ERR("unable to get pseudo-variable in param 1\n"); return E_OUT_OF_MEM; } if (av[0]->u.sval.type!=PVT_AVP) { LM_ERR("bad attribute name <%s>\n", (char*)*param); pkg_free(av); return E_UNSPEC; } if(p==0 || *p=='\0') { *param=(void*)av; return 0; } s = p; ap = avpops_parse_pvar(s); if (ap==0) { LM_ERR("unable to get pseudo-variable in param 1 (2)\n"); return E_OUT_OF_MEM; } if (ap->u.sval.type!=PVT_AVP) { LM_ERR("bad attribute name/alias <%s>!\n", s); pkg_free(av); return E_UNSPEC; } av[1] = ap; *param=(void*)av; return 0; } else if (param_no==2) { if ( (ap=parse_op_value(s))==0 ) { LM_ERR("failed to parse the value \n"); return E_UNSPEC; } /* only integer values or avps */ if ( (ap->opd&AVPOPS_VAL_STR)!=0 && (ap->opd&AVPOPS_VAL_PVAR)==0) { LM_ERR("operations requires integer values\n"); return E_UNSPEC; } *param=(void*)ap; return 0; } return -1; }
static int fixup_pushto_avp(void** param, int param_no) { struct fis_param *ap; char *s; char *p; s = (char*)*param; ap = 0; if (param_no==1) { if ( *s!='$') { LM_ERR("bad param 1; expected : $ru $du ...\n"); return E_UNSPEC; } /* compose the param structure */ if ( (p=strchr(s,'/'))!=0 ) *(p++)=0; ap = avpops_parse_pvar(s); if (ap==0) { LM_ERR("unable to get pseudo-variable in param 1\n"); return E_OUT_OF_MEM; } switch(ap->u.sval.type) { case PVT_RURI: ap->opd = AVPOPS_VAL_NONE|AVPOPS_USE_RURI; if ( p && !( (!strcasecmp("username",p) && (ap->opd|=AVPOPS_FLAG_USER0)) || (!strcasecmp("domain",p) && (ap->opd|=AVPOPS_FLAG_DOMAIN0)) )) { LM_ERR("unknown ruri flag \"%s\"!\n",p); return E_UNSPEC; } break; case PVT_DSTURI: if ( p!=0 ) { LM_ERR("unknown duri flag \"%s\"!\n",p); return E_UNSPEC; } ap->opd = AVPOPS_VAL_NONE|AVPOPS_USE_DURI; break; case PVT_HDR: /* what's the hdr destination ? request or reply? */ LM_ERR("push to header is obsolete - use append_hf() " "or append_to_reply() from textops module!\n"); return E_UNSPEC; break; case PVT_BRANCH: if ( p!=0 ) { LM_ERR("unknown branch flag \"%s\"!\n",p); return E_UNSPEC; } ap->opd = AVPOPS_VAL_NONE|AVPOPS_USE_BRANCH; break; default: LM_ERR("unsupported destination \"%s\"; " "expected $ru,$du,$br\n",s); return E_UNSPEC; } } else if (param_no==2) { /* attribute name*/ if ( *s!='$') { LM_ERR("bad param 1; expected :$pseudo-variable ...\n"); return E_UNSPEC; } /* compose the param structure */ if ( (p=strchr(s,'/'))!=0 ) *(p++)=0; ap = avpops_parse_pvar(s); if (ap==0) { LM_ERR("unable to get pseudo-variable in param 2\n"); return E_OUT_OF_MEM; } if (ap->u.sval.type==PVT_NULL) { LM_ERR("bad param 2; expected : $pseudo-variable ...\n"); pkg_free(ap); return E_UNSPEC; } ap->opd |= AVPOPS_VAL_PVAR; /* flags */ for( ; p&&*p ; p++ ) { switch (*p) { case 'g': case 'G': ap->ops|=AVPOPS_FLAG_ALL; break; default: LM_ERR("bad flag <%c>\n",*p); pkg_free(ap); return E_UNSPEC; } } } *param=(void*)ap; return 0; }
static int fixup_check_avp(void** param, int param_no) { struct fis_param *ap; regex_t* re; char *s; s = (char*)*param; ap = 0; if (param_no==1) { ap = avpops_parse_pvar(s); if (ap==0) { LM_ERR(" unable to get pseudo-variable in P1\n"); return E_OUT_OF_MEM; } /* attr name is mandatory */ if (ap->u.sval.type==PVT_NULL) { LM_ERR("null pseudo-variable in P1\n"); return E_UNSPEC; } } else if (param_no==2) { if ( (ap=parse_check_value(s))==0 ) { LM_ERR(" failed to parse checked value \n"); return E_UNSPEC; } /* if REGEXP op -> compile the expresion */ if (ap->ops&AVPOPS_OP_RE) { if ( (ap->opd&AVPOPS_VAL_STR)==0 ) { LM_ERR(" regexp operation requires string value\n"); return E_UNSPEC; } re = pkg_malloc(sizeof(regex_t)); if (re==0) { LM_ERR(" no more pkg mem\n"); return E_OUT_OF_MEM; } LM_DBG("compiling regexp <%.*s>\n", ap->u.s.len, ap->u.s.s); if (regcomp(re, ap->u.s.s, REG_EXTENDED|REG_ICASE|REG_NEWLINE)) { pkg_free(re); LM_ERR("bad re <%.*s>\n", ap->u.s.len, ap->u.s.s); return E_BAD_RE; } /* free the string and link the regexp */ // pkg_free(ap->sval.p.s); ap->u.s.s = (char*)re; } else if (ap->ops&AVPOPS_OP_FM) { if ( !( ap->opd&AVPOPS_VAL_PVAR || (!(ap->opd&AVPOPS_VAL_PVAR) && ap->opd&AVPOPS_VAL_STR) ) ) { LM_ERR(" fast_match operation requires string value or " "avp name/alias (%d/%d)\n", ap->opd, ap->ops); return E_UNSPEC; } } } *param=(void*)ap; return 0; }
static int fixup_copy_avp(void** param, int param_no) { struct fis_param *ap; char *s; char *p; s = (char*)*param; ap = 0; p = 0; if (param_no==2) { /* avp / flags */ if ( (p=strchr(s,'/'))!=0 ) *(p++)=0; } ap = avpops_parse_pvar(s); if (ap==0) { LM_ERR("unable to get pseudo-variable in P%d\n", param_no); return E_OUT_OF_MEM; } /* attr name is mandatory */ if (ap->u.sval.type!=PVT_AVP) { LM_ERR("you must specify only AVP as parameter\n"); return E_UNSPEC; } if (param_no==2) { /* flags */ for( ; p&&*p ; p++ ) { switch (*p) { case 'g': case 'G': ap->ops|=AVPOPS_FLAG_ALL; break; case 'd': case 'D': ap->ops|=AVPOPS_FLAG_DELETE; break; case 'n': case 'N': ap->ops|=AVPOPS_FLAG_CASTN; break; case 's': case 'S': ap->ops|=AVPOPS_FLAG_CASTS; break; default: LM_ERR("bad flag <%c>\n",*p); return E_UNSPEC; } } } *param=(void*)ap; return 0; }
static int fixup_delete_avp(void** param, int param_no) { struct fis_param *ap=NULL; char *p; char *s; unsigned int flags; str s0; s = (char*)(*param); if (param_no==1) { /* attribute name / alias */ if ( (p=strchr(s,'/'))!=0 ) *(p++)=0; if(*s=='$') { /* is variable */ ap = avpops_parse_pvar(s); if (ap==0) { LM_ERR("unable to get" " pseudo-variable in param \n"); return E_UNSPEC; } if (ap->u.sval.type!=PVT_AVP) { LM_ERR("bad param; expected : $avp(name)\n"); return E_UNSPEC; } ap->opd|=AVPOPS_VAL_PVAR; ap->type = AVPOPS_VAL_PVAR; } else { if(strlen(s)<1) { LM_ERR("bad param - expected : $avp(name), *, s or i value\n"); return E_UNSPEC; } ap = (struct fis_param*)pkg_malloc(sizeof(struct fis_param)); if (ap==0) { LM_ERR(" no more pkg mem\n"); return E_OUT_OF_MEM; } memset(ap, 0, sizeof(struct fis_param)); ap->opd|=AVPOPS_VAL_NONE; switch(*s) { case 's': case 'S': ap->opd = AVPOPS_VAL_NONE|AVPOPS_VAL_STR; break; case 'i': case 'I': ap->opd = AVPOPS_VAL_NONE|AVPOPS_VAL_INT; break; case '*': case 'a': case 'A': ap->opd = AVPOPS_VAL_NONE; break; default: LM_ERR(" bad param - expected : *, s or i AVP flag\n"); pkg_free(ap); return E_UNSPEC; } /* flags */ flags = 0; if(*(s+1)!='\0') { s0.s = s+1; s0.len = strlen(s0.s); if(str2int(&s0, &flags)!=0) { LM_ERR("bad avp flags\n"); pkg_free(ap); return E_UNSPEC; } } ap->type = AVPOPS_VAL_INT; ap->u.n = flags<<8; } /* flags */ for( ; p&&*p ; p++ ) { switch (*p) { case 'g': case 'G': ap->ops|=AVPOPS_FLAG_ALL; break; default: LM_ERR(" bad flag <%c>\n",*p); if(ap!=NULL) pkg_free(ap); return E_UNSPEC; } } /* force some flags: if no avp name is given, force "all" flag */ if (ap->opd&AVPOPS_VAL_NONE) ap->ops |= AVPOPS_FLAG_ALL; *param=(void*)ap; } return 0; }
static int fixup_is_avp_set(void** param, int param_no) { struct fis_param *ap; char *p; char *s; s = (char*)(*param); if (param_no==1) { /* attribute name | alias / flags */ if ( (p=strchr(s,'/'))!=0 ) *(p++)=0; ap = avpops_parse_pvar(s); if (ap==0) { LM_ERR("unable to get pseudo-variable in param\n"); return E_OUT_OF_MEM; } if (ap->u.sval.type!=PVT_AVP) { LM_ERR("bad attribute name <%s>\n", (char*)*param); return E_UNSPEC; } if(p==0 || *p=='\0') ap->ops|=AVPOPS_FLAG_ALL; /* flags */ for( ; p&&*p ; p++ ) { switch (*p) { case 'e': case 'E': ap->ops|=AVPOPS_FLAG_EMPTY; break; case 'n': case 'N': if(ap->ops&AVPOPS_FLAG_CASTS) { LM_ERR("invalid flag combination <%c> and 's|S'\n",*p); return E_UNSPEC; } ap->ops|=AVPOPS_FLAG_CASTN; break; case 's': case 'S': if(ap->ops&AVPOPS_FLAG_CASTN) { LM_ERR("invalid flag combination <%c> and 'n|N'\n",*p); return E_UNSPEC; } ap->ops|=AVPOPS_FLAG_CASTS; break; default: LM_ERR("bad flag <%c>\n",*p); return E_UNSPEC; } } *param=(void*)ap; } return 0; }
struct fis_param* parse_op_value(char *s) { struct fis_param *vp; int ops; int opd; char *p; char *t; int len; ops = 0; opd = 0; vp = 0; if ( (p=strchr(s,'/'))==0 || (p-s!=2&&p-s!=3) ) goto parse_error; /* get the operation */ if (strncasecmp(s,"add",3)==0) { ops |= AVPOPS_OP_ADD; } else if (strncasecmp(s,"sub",3)==0) { ops |= AVPOPS_OP_SUB; } else if (strncasecmp(s,"mul",3)==0) { ops |= AVPOPS_OP_MUL; } else if (strncasecmp(s,"div",3)==0) { ops |= AVPOPS_OP_DIV; } else if (strncasecmp(s,"mod",3)==0) { ops |= AVPOPS_OP_MOD; } else if (strncasecmp(s,"and",3)==0) { ops |= AVPOPS_OP_BAND; } else if (strncasecmp(s,"or",2)==0) { ops |= AVPOPS_OP_BOR; } else if (strncasecmp(s,"xor",3)==0) { ops |= AVPOPS_OP_BXOR; } else if (strncasecmp(s,"not",3)==0) { ops |= AVPOPS_OP_BNOT; } else { LM_ERR("unknown operation <%.*s>\n",2,s); goto error; } /* get the value */ if (*(++p)==0) goto parse_error; if ( (t=strchr(p,'/'))==0) len = strlen(p); else len = t-p; if (*p=='$') { /* is variable */ vp = avpops_parse_pvar(p); if (vp==0) { LM_ERR("unable to get pseudo-variable\n"); goto error; } if (vp->u.sval.type==PVT_NULL) { LM_ERR("bad param; expected : $pseudo-variable or int/str value\n"); goto error; } opd |= AVPOPS_VAL_PVAR; LM_DBG("flag==%d/%d\n", opd, ops); } else { /* value is explicitly given */ if ( (vp=parse_intstr_value(p,len))==0) { LM_ERR("unable to parse value\n"); goto error; } if((vp->opd&AVPOPS_VAL_INT)==0) { LM_ERR("value must be int\n"); goto error; } } /* any flags */ p = t; if (p!=0 && *p!=0 ) { if (*p!='/' || *(++p)==0) goto parse_error; while (*p) { switch (*p) { case 'g': case 'G': ops|=AVPOPS_FLAG_ALL; break; case 'd': case 'D': ops|=AVPOPS_FLAG_DELETE; break; default: LM_ERR("unknown flag <%c>\n",*p); goto error; } p++; } } vp->ops |= ops; vp->opd |= opd; return vp; parse_error: LM_ERR("parse error in <%s> pos %ld\n", s,(long)(p-s)); error: if (vp) pkg_free(vp); return 0; }
struct fis_param* parse_check_value(char *s) { struct fis_param *vp; int ops; int opd; char *p; char *t; int len; ops = 0; opd = 0; vp = 0; if ( (p=strchr(s,'/'))==0 || (p-s!=2&&p-s!=3) ) goto parse_error; /* get the operation */ if (strncasecmp(s,"eq",2)==0) { ops |= AVPOPS_OP_EQ; } else if (strncasecmp(s,"ne",2)==0) { ops |= AVPOPS_OP_NE; } else if (strncasecmp(s,"lt",2)==0) { ops |= AVPOPS_OP_LT; } else if (strncasecmp(s,"le",2)==0) { ops |= AVPOPS_OP_LE; } else if (strncasecmp(s,"gt",2)==0) { ops |= AVPOPS_OP_GT; } else if (strncasecmp(s,"ge",2)==0) { ops |= AVPOPS_OP_GE; } else if (strncasecmp(s,"re",2)==0) { ops |= AVPOPS_OP_RE; } else if (strncasecmp(s,"fm",2)==0) { ops |= AVPOPS_OP_FM; } else if (strncasecmp(s,"and",3)==0) { ops |= AVPOPS_OP_BAND; } else if (strncasecmp(s,"or",2)==0) { ops |= AVPOPS_OP_BOR; } else if (strncasecmp(s,"xor",3)==0) { ops |= AVPOPS_OP_BXOR; } else { LM_ERR("unknown operation <%.*s>\n",2,s); goto error; } /* get the value */ if (*(++p)==0) goto parse_error; if ( (t=strchr(p,'/'))==0) len = strlen(p); else len = t-p; if (*p=='$') { /* is variable */ vp = avpops_parse_pvar(p); if (vp==0) { LM_ERR("unable to get pseudo-variable\n"); goto error; } if (vp->u.sval.type==PVT_NULL) { LM_ERR("bad param; expected : $pseudo-variable or int/str value\n"); goto error; } opd |= AVPOPS_VAL_PVAR; LM_DBG("flag==%d/%d\n", opd, ops); } else { /* value is explicitly given */ if ( (vp=parse_intstr_value(p,len))==0) { LM_ERR("unable to parse value\n"); goto error; } } p = t; /* any flags */ if (p!=NULL && *p!=0) { if (*p!='/' || *(++p)==0) goto parse_error; while (*p) { switch (*p) { case 'g': case 'G': ops|=AVPOPS_FLAG_ALL; break; case 'i': case 'I': ops|=AVPOPS_FLAG_CI; break; default: LM_ERR("unknown flag <%c>\n",*p); goto error; } p++; } } vp->ops |= ops; vp->opd |= opd; return vp; parse_error: LM_ERR("parse error in <%s> pos %ld\n", s,(long)(p-s)); error: if (vp) pkg_free(vp); return 0; }