/*! \brief * \return 0/1 (false/true) or -1 on error, -127 EXPR_DROP */ static int eval_elem(struct expr* e, struct sip_msg* msg, pv_value_t *val) { struct sip_uri uri; int ret; int retl; int retr; int ival; pv_value_t lval; pv_value_t rval; char *p; int i,n; ret=E_BUG; if (e->type!=ELEM_T){ LM_CRIT("invalid type\n"); goto error; } if(val) memset(val, 0, sizeof(pv_value_t)); switch(e->left.type){ case METHOD_O: ret=comp_strval(msg, e->op, &msg->first_line.u.request.method, &e->right); break; case URI_O: if(msg->new_uri.s){ if (e->right.type==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &msg->new_uri, &e->right); } }else{ if (e->right.type==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &msg->first_line.u.request.uri, &e->right); } } break; case FROM_URI_O: if (parse_from_header(msg)<0){ LM_ERR("bad or missing From: header\n"); goto error; } if (e->right.type==MYSELF_ST){ if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len, &uri) < 0){ LM_ERR("bad uri in From:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &get_from(msg)->uri, &e->right); } break; case TO_URI_O: if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) || (msg->to==0))){ LM_ERR("bad or missing To: header\n"); goto error; } /* to content is parsed automatically */ if (e->right.type==MYSELF_ST){ if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len, &uri) < 0){ LM_ERR("bad uri in To:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &get_to(msg)->uri, &e->right); } break; case SRCIP_O: ret=comp_ip(msg, e->op, &msg->rcv.src_ip, &e->right); break; case DSTIP_O: ret=comp_ip(msg, e->op, &msg->rcv.dst_ip, &e->right); break; case NUMBER_O: ret=!(!e->right.v.n); /* !! to transform it in {0,1} */ break; case ACTION_O: ret=run_action_list( (struct action*)e->right.v.data, msg); if(val) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = ret; } if (ret<=0) ret=(ret==0)?EXPR_DROP:0; else ret=1; return ret; case EXPR_O: retl = retr = 0; memset(&lval, 0, sizeof(pv_value_t)); memset(&rval, 0, sizeof(pv_value_t)); if(e->left.v.data) retl=eval_expr((struct expr*)e->left.v.data,msg,&lval); if(lval.flags == PV_VAL_NONE) { pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(e->op == BNOT_OP) { if(lval.flags&PV_VAL_INT) { if(val!=NULL) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = ~lval.ri; } pv_value_destroy(&lval); pv_value_destroy(&rval); return (val->ri)?1:0; } LM_ERR("binary NOT on non-numeric value\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(e->right.v.data) retr=eval_expr((struct expr*)e->right.v.data,msg,&rval); if(lval.flags&PV_TYPE_INT) { if( (rval.flags&PV_VAL_NULL) ) { rval.ri = 0; } else if(!(rval.flags&PV_VAL_INT)) { LM_ERR("invalid numeric operands\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(val!=NULL) val->flags = PV_TYPE_INT|PV_VAL_INT; ival = 0; switch(e->op) { case PLUS_OP: ival = lval.ri + rval.ri; break; case MINUS_OP: ival = lval.ri - rval.ri; break; case DIV_OP: if(rval.ri==0) { LM_ERR("divide by 0\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } else ival = lval.ri / rval.ri; break; case MULT_OP: ival = lval.ri * rval.ri; break; case MODULO_OP: if(rval.ri==0) { LM_ERR("divide by 0\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } else ival = lval.ri % rval.ri; break; case BAND_OP: ival = lval.ri & rval.ri; break; case BOR_OP: ival = lval.ri | rval.ri; break; case BXOR_OP: ival = lval.ri ^ rval.ri; break; case BLSHIFT_OP: ival = lval.ri << rval.ri; break; case BRSHIFT_OP: ival = lval.ri >> rval.ri; break; default: LM_ERR("invalid int op %d\n", e->op); val->ri = 0; pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } pv_value_destroy(&lval); pv_value_destroy(&rval); if(val!=NULL) val->ri = ival; return (ival)?1:0; } else if (e->op == PLUS_OP) { if( (rval.flags&PV_VAL_NULL) || (val==NULL)) { if (val) val->flags|=PV_VAL_STR; ret = (lval.rs.len>0 || rval.rs.len>0); pv_value_destroy(&lval); pv_value_destroy(&rval); return ret; } if(!(rval.flags&PV_VAL_STR)) { LM_ERR("invalid string operands\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } val->rs.s=(char*)pkg_malloc((lval.rs.len+rval.rs.len+1) *sizeof(char)); if(val->rs.s==0) { LM_ERR("no more memory\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } val->flags = PV_VAL_PKG|PV_VAL_STR; memcpy(val->rs.s, lval.rs.s, lval.rs.len); memcpy(val->rs.s+lval.rs.len, rval.rs.s, rval.rs.len); val->rs.len = lval.rs.len + rval.rs.len; val->rs.s[val->rs.len] = '\0'; pv_value_destroy(&lval); pv_value_destroy(&rval); return 1; } else if ((lval.flags & PV_VAL_STR) && (rval.flags & PV_VAL_STR)) { if (lval.rs.len != rval.rs.len) { LM_ERR("Different length string operands\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } n = lval.rs.len; val->rs.s = pkg_malloc(n+1); if (!val->rs.s) { LM_ERR("no more memory\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } switch(e->op) { case BAND_OP: for (i=0;i<n;i++) val->rs.s[i] = lval.rs.s[i] & rval.rs.s[i]; break; case BOR_OP: for (i=0;i<n;i++) val->rs.s[i] = lval.rs.s[i] | rval.rs.s[i]; break; case BXOR_OP: for (i=0;i<n;i++) val->rs.s[i] = lval.rs.s[i] ^ rval.rs.s[i]; break; default: LM_ERR("Only bitwise operations can be applied on strings\n"); val->ri = 0; pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } val->flags = PV_VAL_PKG|PV_VAL_STR; val->rs.len = n; val->rs.s[n] = '\0'; pv_value_destroy(&lval); pv_value_destroy(&rval); return 1; } else { LM_ERR("Invalid operator : %d \n",e->op); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } break; case SRCPORT_O: ret=comp_no(msg->rcv.src_port, e->right.v.data, /* e.g., 5060 */ e->op, /* e.g. == */ e->right.type /* 5060 is number */); break; case DSTPORT_O: ret=comp_no(msg->rcv.dst_port, e->right.v.data, e->op, e->right.type); break; case PROTO_O: ret=comp_no(msg->rcv.proto, e->right.v.data, e->op, e->right.type); break; case AF_O: ret=comp_no(msg->rcv.src_ip.af, e->right.v.data, e->op, e->right.type); break; case RETCODE_O: ret=comp_no(return_code, e->right.v.data, e->op, e->right.type); break; case MSGLEN_O: ret=comp_no(msg->len, e->right.v.data, e->op, e->right.type); break; case STRINGV_O: if(val) { val->flags = PV_VAL_STR; val->rs = e->left.v.s; } /* optimization for no dup ?!?! */ return (e->left.v.s.len>0)?1:0; case NUMBERV_O: if(val) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = e->left.v.n; } ret=!(!e->left.v.n); /* !! to transform it in {0,1} */ return ret; case SCRIPTVAR_O: if(e->op==NO_OP) { memset(&rval, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, e->right.v.spec, &rval)==0) { if(rval.flags==PV_VAL_NONE || (rval.flags&PV_VAL_NULL) || (rval.flags&PV_VAL_EMPTY) || ((rval.flags&PV_TYPE_INT)&&rval.ri==0)) { pv_value_destroy(&rval); return 0; } if(rval.flags&PV_TYPE_INT) { pv_value_destroy(&rval); return 1; } if(rval.rs.len!=0) { pv_value_destroy(&rval); return 1; } pv_value_destroy(&rval); } return 0; } if(e->op==VALUE_OP) { if(pv_get_spec_value(msg, e->left.v.spec, &lval)==0) { if(val!=NULL) memcpy(val, &lval, sizeof(pv_value_t)); if(lval.flags&PV_VAL_STR) { if(!((lval.flags&PV_VAL_PKG) || (lval.flags&PV_VAL_SHM))) { if(val!=NULL) { /* do pkg duplicate */ p = (char*)pkg_malloc((val->rs.len+1) *sizeof(char)); if(p==0) { LM_ERR("no more pkg memory\n"); memset(val, 0, sizeof(pv_value_t)); return 0; } memcpy(p, val->rs.s, val->rs.len); p[val->rs.len] = 0; val->rs.s = p; val->flags|= PV_VAL_PKG; } } return 1; } if(lval.flags==PV_VAL_NONE || (lval.flags & PV_VAL_NULL) || (lval.flags & PV_VAL_EMPTY)) return 0; if(lval.flags&PV_TYPE_INT) return (lval.ri!=0); else return (lval.rs.len>0); } return 0; } ret=comp_scriptvar(msg, e->op, &e->left, &e->right); break; default: LM_CRIT("invalid operand %d\n", e->left.type); }
/* returns: 0/1 (false/true) or -1 on error, -127 EXPR_DROP */ static int eval_elem(struct expr* e, struct sip_msg* msg) { struct sip_uri uri; int ret; ret=E_BUG; if (e->type!=ELEM_T){ LOG(L_CRIT," BUG: eval_elem: invalid type\n"); goto error; } switch(e->l.operand){ case METHOD_O: ret=comp_strstr(&msg->first_line.u.request.method, e->r.param, e->op, e->subtype); break; case URI_O: if(msg->new_uri.s){ if (e->subtype==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strstr(&msg->new_uri, e->r.param, e->op, e->subtype); } }else{ if (e->subtype==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strstr(&msg->first_line.u.request.uri, e->r.param, e->op, e->subtype); } } break; case FROM_URI_O: if (parse_from_header(msg)!=0){ LOG(L_ERR, "ERROR: eval_elem: bad or missing" " From: header\n"); goto error; } if (e->subtype==MYSELF_ST){ if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len, &uri) < 0){ LOG(L_ERR, "ERROR: eval_elem: bad uri in From:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strstr(&get_from(msg)->uri, e->r.param, e->op, e->subtype); } break; case TO_URI_O: if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) || (msg->to==0))){ LOG(L_ERR, "ERROR: eval_elem: bad or missing" " To: header\n"); goto error; } /* to content is parsed automatically */ if (e->subtype==MYSELF_ST){ if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len, &uri) < 0){ LOG(L_ERR, "ERROR: eval_elem: bad uri in To:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strstr(&get_to(msg)->uri, e->r.param, e->op, e->subtype); } break; case SRCIP_O: ret=comp_ip(&msg->rcv.src_ip, e->r.param, e->op, e->subtype); break; case DSTIP_O: ret=comp_ip(&msg->rcv.dst_ip, e->r.param, e->op, e->subtype); break; case NUMBER_O: ret=!(!e->r.intval); /* !! to transform it in {0,1} */ break; case ACTION_O: ret=run_action_list( (struct action*)e->r.param, msg); if (ret<=0) ret=(ret==0)?EXPR_DROP:0; else ret=1; break; case SRCPORT_O: ret=comp_no(msg->rcv.src_port, e->r.param, /* e.g., 5060 */ e->op, /* e.g. == */ e->subtype /* 5060 is number */); break; case DSTPORT_O: ret=comp_no(msg->rcv.dst_port, e->r.param, e->op, e->subtype); break; case PROTO_O: ret=comp_no(msg->rcv.proto, e->r.param, e->op, e->subtype); break; case AF_O: ret=comp_no(msg->rcv.src_ip.af, e->r.param, e->op, e->subtype); break; case RETCODE_O: ret=comp_no(return_code, e->r.param, e->op, e->subtype); break; case MSGLEN_O: ret=comp_no(msg->len, e->r.param, e->op, e->subtype); break; default: LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n", e->l.operand); } return ret; error: return -1; }