Exemplo n.º 1
0
/*! \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);
	}
Exemplo n.º 2
0
/* 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;
}