Browse code

script engine: rvalue support in logical expr.

- hard coded expressions elements (e.g. method==xxx) support now
rvalues as operands (e.g. uri=="sip:"+$a)
- small cleanups

Andrei Pelinescu-Onciul authored on 09/12/2008 15:15:21
Showing 3 changed files
... ...
@@ -81,6 +81,7 @@
81 81
 #include "onsend.h"
82 82
 #include "str_hash.h"
83 83
 #include "ut.h"
84
+#include "rvalue.h"
84 85
 
85 86
 #define RT_HASH_SIZE	8 /* route names hash */
86 87
 
... ...
@@ -333,7 +334,9 @@ int fix_expr(struct expr* exp)
333 333
 					pkg_free(exp->r.param);
334 334
 					exp->r.re=re;
335 335
 					exp->r_type=RE_ST;
336
-				}else if (exp->r_type!=RE_ST && exp->r_type != AVP_ST && exp->r_type != SELECT_ST){
336
+				}else if (exp->r_type!=RE_ST && exp->r_type != AVP_ST
337
+						&& exp->r_type != SELECT_ST && exp->r_type!= RVE_ST
338
+						&& exp->r_type != PVAR_ST){
337 339
 					LOG(L_CRIT, "BUG: fix_expr : invalid type for match\n");
338 340
 					return E_BUG;
339 341
 				}
... ...
@@ -374,6 +377,19 @@ int fix_expr(struct expr* exp)
374 374
 					return ret;
375 375
 				}
376 376
 			}
377
+			if (exp->l_type==RVEXP_O){
378
+				if ((ret=fix_rval_expr(&exp->l.param))<0){
379
+					ERR("Unable to fix left rval expression\n");
380
+					return ret;
381
+				}
382
+			}
383
+			if (exp->r_type==RVE_ST){
384
+				if ((ret=fix_rval_expr(&exp->r.param))<0){
385
+					ERR("Unable to fix right rval expression\n");
386
+					return ret;
387
+				}
388
+			}
389
+			/* PVAR don't need fixing */
377 390
 			ret=0;
378 391
 	}
379 392
 	return ret;
... ...
@@ -585,40 +601,67 @@ int fix_actions(struct action* a)
585 585
  * attributes. If either of the attributes if of string type then the length of
586 586
  * its value will be used.
587 587
  */
588
-inline static int comp_num(int op, long left, int rtype, union exp_op* r)
588
+inline static int comp_num(int op, long left, int rtype, union exp_op* r,
589
+							struct sip_msg* msg, struct run_act_ctx* h)
589 590
 {
590 591
 	int_str val;
592
+	pv_value_t pval;
591 593
 	avp_t* avp;
592
-	long right;
593
-
594
-	if (rtype == AVP_ST) {
595
-		avp = search_avp_by_index(r->attr->type, r->attr->name, &val, r->attr->index);
596
-		if (avp && !(avp->flags & AVP_VAL_STR)) right = val.n;
597
-		else return (op == DIFF_OP);
598
-	} else if (rtype == NUMBER_ST) {
599
-		right = r->numval;
600
-	} else {
601
-		LOG(L_CRIT, "BUG: comp_num: Invalid right operand (%d)\n", rtype);
602
-		return E_BUG;
594
+	int right;
595
+
596
+	if (unlikely(op==NO_OP)) return !(!left);
597
+	switch(rtype){
598
+		case AVP_ST:
599
+			avp = search_avp_by_index(r->attr->type, r->attr->name,
600
+										&val, r->attr->index);
601
+			if (avp && !(avp->flags & AVP_VAL_STR)) right = val.n;
602
+			else return (op == DIFF_OP);
603
+			break;
604
+		case NUMBER_ST:
605
+			right = r->numval;
606
+			break;
607
+		case RVE_ST:
608
+			if (unlikely(rval_expr_eval_int(h, msg, &right, r->param)<0))
609
+				return (op == DIFF_OP); /* not found/invalid */
610
+			break;
611
+		case PVAR_ST:
612
+			memset(&pval, 0, sizeof(pv_value_t));
613
+			if (unlikely(pv_get_spec_value(msg, r->param, &pval)!=0)){
614
+				return (op == DIFF_OP); /* error, not found => false */
615
+			}
616
+			if (likely(pval.flags & (PV_TYPE_INT|PV_VAL_INT))){
617
+				pv_value_destroy(&pval);
618
+				right=pval.ri;
619
+			}else{
620
+				pv_value_destroy(&pval);
621
+				return (op == DIFF_OP); /* not found or invalid type */
622
+			}
623
+			break;
624
+		default:
625
+			LOG(L_CRIT, "BUG: comp_num: Invalid right operand (%d)\n", rtype);
626
+			return E_BUG;
603 627
 	}
604 628
 
605 629
 	switch (op){
606
-	case EQUAL_OP: return (long)left == (long)right;
607
-	case DIFF_OP:  return (long)left != (long)right;
608
-	case GT_OP:    return (long)left >  (long)right;
609
-	case LT_OP:    return (long)left <  (long)right;
610
-	case GTE_OP:   return (long)left >= (long)right;
611
-	case LTE_OP:   return (long)left <= (long)right;
612
-	default:
613
-		LOG(L_CRIT, "BUG: comp_num: unknown operator: %d\n", op);
614
-		return E_BUG;
630
+		case EQUAL_OP: return (long)left == (long)right;
631
+		case DIFF_OP:  return (long)left != (long)right;
632
+		case GT_OP:    return (long)left >  (long)right;
633
+		case LT_OP:    return (long)left <  (long)right;
634
+		case GTE_OP:   return (long)left >= (long)right;
635
+		case LTE_OP:   return (long)left <= (long)right;
636
+		default:
637
+			LOG(L_CRIT, "BUG: comp_num: unknown operator: %d\n", op);
638
+			return E_BUG;
615 639
 	}
640
+	return E_BUG;
616 641
 }
617 642
 
618 643
 /*
619 644
  * Compare given string "left" with right side of expression
620 645
  */
621
-inline static int comp_str(int op, str* left, int rtype, union exp_op* r, struct sip_msg* msg)
646
+inline static int comp_str(int op, str* left, int rtype, 
647
+							union exp_op* r, struct sip_msg* msg,
648
+							struct run_act_ctx* h)
622 649
 {
623 650
 	str* right;
624 651
 	int_str val;
... ...
@@ -628,33 +671,74 @@ inline static int comp_str(int op, str* left, int rtype, union exp_op* r, struct
628 628
 	char backup;
629 629
 	regex_t* re;
630 630
 	unsigned int l;
631
+	struct rvalue* rv;
632
+	struct rval_cache rv_cache;
633
+	pv_value_t pval;
634
+	int destroy_pval;
631 635
 	
632 636
 	right=0; /* warning fix */
633
-
634
-	if (rtype == AVP_ST) {
635
-		avp = search_avp_by_index(r->attr->type, r->attr->name, &val, r->attr->index);
636
-		if (avp && (avp->flags & AVP_VAL_STR)) right = &val.s;
637
-		else return (op == DIFF_OP);
638
-	} else if (rtype == SELECT_ST) {
639
-		ret = run_select(&v, r->select, msg);
640
-		if (ret != 0) return (op == DIFF_OP); /* Not found or error */
641
-		right = &v;
642
-	} else if ((op == MATCH_OP && rtype == RE_ST)) {
643
-	} else if (op != MATCH_OP && rtype == STRING_ST) {
644
-		right = &r->str;
645
-	} else if (rtype == NUMBER_ST) {
637
+	rv=0;
638
+	destroy_pval=0;
639
+	if (unlikely(op==NO_OP)) return (left->s!=0);
640
+	switch(rtype){
641
+		case AVP_ST:
642
+			avp = search_avp_by_index(r->attr->type, r->attr->name,
643
+										&val, r->attr->index);
644
+			if (likely(avp && (avp->flags & AVP_VAL_STR))) right = &val.s;
645
+			else return (op == DIFF_OP);
646
+			break;
647
+		case SELECT_ST:
648
+			ret = run_select(&v, r->select, msg);
649
+			if (unlikely(ret != 0)) 
650
+				return (op == DIFF_OP); /* Not found or error */
651
+			right = &v;
652
+			break;
653
+		case RVE_ST:
654
+			rval_cache_init(&rv_cache);
655
+			rv=rval_expr_eval(h, msg, r->param);
656
+			if (unlikely (rv==0)) 
657
+				return (op==DIFF_OP); /* not found or error*/
658
+			if (unlikely(rval_get_tmp_str(h, msg, &v, rv, 0, &rv_cache)<0)){
659
+				goto error;
660
+			}
661
+			right = &v;
662
+			break;
663
+		case PVAR_ST:
664
+			memset(&pval, 0, sizeof(pv_value_t));
665
+			if (unlikely(pv_get_spec_value(msg, r->param, &pval)!=0)){
666
+				return (op == DIFF_OP); /* error, not found => false */
667
+			}
668
+			destroy_pval=1;
669
+			if (likely(pval.flags & PV_VAL_STR)){
670
+				right=&pval.rs;
671
+			}else{
672
+				pv_value_destroy(&pval);
673
+				return (op == DIFF_OP); /* not found or invalid type */
674
+			}
675
+			break;
676
+		case RE_ST:
677
+			if (unlikely(op != MATCH_OP)){
678
+				LOG(L_CRIT, "BUG: comp_str: Bad operator %d,"
679
+							" ~= expected\n", op);
680
+				goto error;
681
+			}
682
+			break;
683
+		case STRING_ST:
684
+			right=&r->str;
685
+			break;
686
+		case NUMBER_ST:
646 687
 			/* "123" > 100 is not allowed by cfg.y rules
647 688
 			 * but can happen as @select or $avp evaluation
648 689
 			 * $test > 10
649 690
 			 * the right operator MUST be number to do the conversion
650 691
 			 */
651
-		if (str2int(left,&l) < 0)
692
+			if (str2int(left,&l) < 0)
693
+				goto error;
694
+			return comp_num(op, l, rtype, r, msg, h);
695
+		default:
696
+			LOG(L_CRIT, "BUG: comp_str: Bad type %d, "
697
+						"string or RE expected\n", rtype);
652 698
 			goto error;
653
-		return comp_num(op, l, rtype, r);
654
-	} else {
655
-		LOG(L_CRIT, "BUG: comp_str: Bad type %d, "
656
-		    "string or RE expected\n", rtype);
657
-		goto error;
658 699
 	}
659 700
 
660 701
 	ret=-1;
... ...
@@ -668,111 +752,97 @@ inline static int comp_str(int op, str* left, int rtype, union exp_op* r, struct
668 668
 			ret = (strncasecmp(left->s, right->s, left->len)!=0);
669 669
 			break;
670 670
 		case MATCH_OP:
671
-			     /* this is really ugly -- we put a temporary zero-terminating
672
-			      * character in the original string; that's because regexps
673
-			      * take 0-terminated strings and our messages are not
674
-			      * zero-terminated; it should not hurt as long as this function
675
-			      * is applied to content of pkg mem, which is always the case
676
-			      * with calls from route{}; the same goes for fline in reply_route{};
677
-			      *
678
-			      * also, the received function should always give us an extra
679
-			      * character, into which we can put the 0-terminator now;
680
-			      * an alternative would be allocating a new piece of memory,
681
-			      * which might be too slow
682
-			      * -jiri
683
-			      *
684
-			      * janakj: AVPs are zero terminated too so this is not problem either
685
-			      */
671
+			/* this is really ugly -- we put a temporary zero-terminating
672
+			 * character in the original string; that's because regexps
673
+			 * take 0-terminated strings and our messages are not
674
+			 * zero-terminated; it should not hurt as long as this function
675
+			 * is applied to content of pkg mem, which is always the case
676
+			 * with calls from route{}; the same goes for fline in 
677
+			 * reply_route{};
678
+			 *
679
+			 * also, the received function should always give us an extra
680
+			 * character, into which we can put the 0-terminator now;
681
+			 * an alternative would be allocating a new piece of memory,
682
+			 * which might be too slow
683
+			 * -jiri
684
+			 *
685
+			 * janakj: AVPs are zero terminated too so this is not problem 
686
+			 * either
687
+			 */
686 688
 			backup=left->s[left->len];
687
-			if (backup) left->s[left->len]='\0';
688
-			if (rtype == AVP_ST || rtype == SELECT_ST) {
689
-				     /* For AVPs we need to compile the RE on the fly */
690
-				re=(regex_t*)pkg_malloc(sizeof(regex_t));
691
-				if (re==0){
692
-					LOG(L_CRIT, "ERROR: comp_strstr: memory allocation"
693
-					    " failure\n");
694
-					left->s[left->len] = backup;
695
-					goto error;
696
-				}
697
-				if (regcomp(re, right->s, REG_EXTENDED|REG_NOSUB|REG_ICASE)) {
689
+			left->s[left->len]='\0';
690
+			switch(rtype){
691
+				case AVP_ST:
692
+				case SELECT_ST:
693
+				case RVE_ST:
694
+				case PVAR_ST:
695
+					/* we need to compile the RE on the fly */
696
+					re=(regex_t*)pkg_malloc(sizeof(regex_t));
697
+					if (re==0){
698
+						LOG(L_CRIT, "ERROR: comp_strstr: memory allocation"
699
+									 " failure\n");
700
+						left->s[left->len] = backup;
701
+						goto error;
702
+					}
703
+					if (regcomp(re, right->s,
704
+								REG_EXTENDED|REG_NOSUB|REG_ICASE)) {
705
+						pkg_free(re);
706
+						left->s[left->len] = backup;
707
+						goto error;
708
+					}
709
+					ret=(regexec(re, left->s, 0, 0, 0)==0);
710
+					regfree(re);
698 711
 					pkg_free(re);
699
-					left->s[left->len] = backup;
712
+					break;
713
+				case RE_ST:
714
+					ret=(regexec(r->re, left->s, 0, 0, 0)==0);
715
+					break;
716
+				case STRING_ST:
717
+				default:
718
+					LOG(L_CRIT, "BUG: comp_str: Bad operator type %d, "
719
+								"for ~= \n", rtype);
700 720
 					goto error;
701
-				}
702
-				ret=(regexec(re, left->s, 0, 0, 0)==0);
703
-				regfree(re);
704
-				pkg_free(re);
705
-			} else {
706
-				ret=(regexec(r->re, left->s, 0, 0, 0)==0);
707 721
 			}
708
-			if (backup) left->s[left->len] = backup;
722
+			left->s[left->len] = backup;
709 723
 			break;
710 724
 		default:
711 725
 			LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
712 726
 			goto error;
713 727
 	}
728
+	if (rv){
729
+		rval_cache_clean(&rv_cache);
730
+		rval_destroy(rv);
731
+	}
732
+	if (destroy_pval)
733
+		pv_value_destroy(&pval);
714 734
 	return ret;
715 735
 
716 736
 error:
737
+	if (rv){
738
+		rval_cache_clean(&rv_cache);
739
+		rval_destroy(rv);
740
+	}
741
+	if (destroy_pval)
742
+		pv_value_destroy(&pval);
717 743
 	return (op == DIFF_OP) ? 1 : -1;
718 744
 }
719 745
 
720 746
 
721 747
 /* eval_elem helping function, returns str op param */
722
-inline static int comp_string(int op, char* left, int rtype, union exp_op* r)
748
+inline static int comp_string(int op, char* left, int rtype, union exp_op* r,
749
+								struct sip_msg* msg, struct run_act_ctx* h)
723 750
 {
724
-	int ret;
725
-	int_str val;
726
-	avp_t* avp;
727
-	char* right;
728
-
729
-	ret=-1;
730
-	right=0;
731
-	if (rtype == AVP_ST) {
732
-		avp = search_avp_by_index(r->attr->type, r->attr->name, &val, r->attr->index);
733
-		if (avp && (avp->flags & AVP_VAL_STR)) right = val.s.s;
734
-		else return (op == DIFF_OP);
735
-	} else if (rtype == STRING_ST) {
736
-		right = r->str.s;
737
-	}
738
-
739
-	switch(op){
740
-		case EQUAL_OP:
741
-			if (rtype!=STRING_ST && rtype!=AVP_ST){
742
-				LOG(L_CRIT, "BUG: comp_string: bad type %d, "
743
-						"string or attr expected\n", rtype);
744
-				goto error;
745
-			}
746
-			ret=(strcasecmp(left, right)==0);
747
-			break;
748
-		case DIFF_OP:
749
-			if (rtype!=STRING_ST && rtype!=AVP_ST){
750
-				LOG(L_CRIT, "BUG: comp_string: bad type %d, "
751
-						"string or attr expected\n", rtype);
752
-				goto error;
753
-			}
754
-			ret=(strcasecmp(left, right)!=0);
755
-			break;
756
-		case MATCH_OP:
757
-			if (rtype!=RE_ST){
758
-				LOG(L_CRIT, "BUG: comp_string: bad type %d, "
759
-						" RE expected\n", rtype);
760
-				goto error;
761
-			}
762
-			ret=(regexec(r->re, left, 0, 0, 0)==0);
763
-			break;
764
-		default:
765
-			LOG(L_CRIT, "BUG: comp_string: unknown op %d\n", op);
766
-			goto error;
767
-	}
768
-	return ret;
769
-
770
-error:
771
-	return -1;
751
+	str s;
752
+	
753
+	s.s=left;
754
+	s.len=strlen(left);
755
+	return comp_str(op, &s, rtype, r, msg, h);
772 756
 }
773 757
 
774 758
 
775
-inline static int comp_avp(int op, avp_spec_t* spec, int rtype, union exp_op* r, struct sip_msg* msg)
759
+inline static int comp_avp(int op, avp_spec_t* spec, int rtype,
760
+							union exp_op* r, struct sip_msg* msg,
761
+							struct run_act_ctx* h)
776 762
 {
777 763
 	avp_t* avp;
778 764
 	int_str val;
... ...
@@ -781,46 +851,41 @@ inline static int comp_avp(int op, avp_spec_t* spec, int rtype, union exp_op* r,
781 781
 	unsigned int uval;
782 782
 
783 783
 	if (spec->type & AVP_INDEX_ALL) {
784
-		avp = search_first_avp(spec->type & ~AVP_INDEX_ALL, spec->name, NULL, NULL);
784
+		avp = search_first_avp(spec->type & ~AVP_INDEX_ALL, spec->name,
785
+								NULL, NULL);
785 786
 		return (avp!=0);
786 787
 	}
787 788
 	avp = search_avp_by_index(spec->type, spec->name, &val, spec->index);
788 789
 	if (!avp) return (op == DIFF_OP);
789 790
 
790
-	switch(op) {
791
-	case NO_OP:
791
+	if (op==NO_OP){
792 792
 		if (avp->flags & AVP_VAL_STR) {
793 793
 			return val.s.len!=0;
794 794
 		} else {
795 795
 			return val.n != 0;
796 796
 		}
797
-		break;
798
-
799
-	case BINOR_OP:
800
-		return (val.n | r->numval)!=0;
801
-		break;
802
-
803
-	case BINAND_OP:
804
-		return (val.n & r->numval)!=0;
805
-		break;
806 797
 	}
807
-
808 798
 	if (avp->flags & AVP_VAL_STR) {
809
-		return comp_str(op, &val.s, rtype, r, msg);
799
+		return comp_str(op, &val.s, rtype, r, msg, h);
810 800
 	} else {
811 801
 		switch(rtype){
812 802
 			case NUMBER_ST:
813
-				return comp_num(op, val.n, rtype, r);
803
+			case AVP_ST:
804
+			case RVE_ST:
805
+			case PVAR_ST:
806
+				return comp_num(op, val.n, rtype, r, msg, h);
807
+				break;
814 808
 			case STRING_ST:
815 809
 				tmp.s=r->string;
816 810
 				tmp.len=strlen(r->string);
817 811
 				if (str2int(&tmp, &uval)<0){
818
-					LOG(L_WARN, "WARNING: comp_avp: cannot convert string value"
819
-								" to int (%s)\n", ZSW(r->string));
812
+					LOG(L_WARN, "WARNING: comp_avp: cannot convert"
813
+								" string value to int (%s)\n",
814
+								ZSW(r->string));
820 815
 					goto error;
821 816
 				}
822 817
 				num_val.numval=uval;
823
-				return comp_num(op, val.n, NUMBER_ST, &num_val);
818
+				return comp_num(op, val.n, NUMBER_ST, &num_val, msg, h);
824 819
 			case STR_ST:
825 820
 				if (str2int(&r->str, &uval)<0){
826 821
 					LOG(L_WARN, "WARNING: comp_avp: cannot convert str value"
... ...
@@ -828,9 +893,7 @@ inline static int comp_avp(int op, avp_spec_t* spec, int rtype, union exp_op* r,
828 828
 					goto error;
829 829
 				}
830 830
 				num_val.numval=uval;
831
-				return comp_num(op, val.n, NUMBER_ST, &num_val);
832
-			case AVP_ST:
833
-				return comp_num(op, val.n, rtype, r);
831
+				return comp_num(op, val.n, NUMBER_ST, &num_val, msg, h);
834 832
 			default:
835 833
 				LOG(L_CRIT, "BUG: comp_avp: invalid type for numeric avp "
836 834
 							"comparison (%d)\n", rtype);
... ...
@@ -844,7 +907,9 @@ error:
844 844
 /*
845 845
  * Left side of expression was select
846 846
  */
847
-inline static int comp_select(int op, select_t* sel, int rtype, union exp_op* r, struct sip_msg* msg)
847
+inline static int comp_select(int op, select_t* sel, int rtype,
848
+								union exp_op* r, struct sip_msg* msg,
849
+								struct run_act_ctx* h)
848 850
 {
849 851
 	int ret;
850 852
 	str val;
... ...
@@ -853,22 +918,68 @@ inline static int comp_select(int op, select_t* sel, int rtype, union exp_op* r,
853 853
 	ret = run_select(&val, sel, msg);
854 854
 	if (ret != 0) return (op == DIFF_OP);
855 855
 
856
-	switch(op) {
857
-	case NO_OP: return (val.len>0);
858
-	case BINOR_OP:
859
-	case BINAND_OP:
860
-		ERR("Binary operators cannot be used with string selects\n");
861
-		return -1;
862
-	}
863
-	if (val.len==0) {
856
+	if (op==NO_OP) return (val.len>0);
857
+	if (unlikely(val.len==0)) {
864 858
 		/* make sure the string pointer uses accessible memory range
865 859
 		 * the comp_str function might dereference it
866 860
 		 */
867 861
 		val.s=&empty_str;
868 862
 	}
869
-	return comp_str(op, &val, rtype, r, msg);
863
+	return comp_str(op, &val, rtype, r, msg, h);
864
+}
865
+
866
+
867
+inline static int comp_rve(int op, struct rval_expr* rve, int rtype,
868
+							union exp_op* r, struct sip_msg* msg,
869
+							struct run_act_ctx* h)
870
+{
871
+	int i;
872
+	
873
+	if (unlikely(rval_expr_eval_int(h,  msg, &i, rve)<0)){
874
+		ERR("failure evaluating expression: bad type\n");
875
+		i=0; /* false */
876
+	}
877
+	if (op==NO_OP)
878
+		return !(!i); /* transform it into { 0, 1 } */
879
+	return comp_num(op, i, rtype, r, msg, h);
870 880
 }
871 881
 
882
+
883
+
884
+inline static int comp_pvar(int op, pv_spec_t* pvs, int rtype,
885
+							union exp_op* r, struct sip_msg* msg,
886
+							struct run_act_ctx* h)
887
+{
888
+	pv_value_t pval;
889
+	int ret;
890
+	
891
+	ret=0;
892
+	memset(&pval, 0, sizeof(pv_value_t));
893
+	if (unlikely(pv_get_spec_value(msg, r->param, &pval)!=0)){
894
+		return 0; /* error, not found => false */
895
+	}
896
+	if (likely(pval.flags & PV_TYPE_INT)){
897
+		if (op==NO_OP)
898
+			ret=!(!pval.ri);
899
+		else
900
+			ret=comp_num(op, pval.ri, rtype, r, msg, h);
901
+	}else if ((pval.flags==PV_VAL_NONE) ||
902
+			(pval.flags & (PV_VAL_NULL|PV_VAL_EMPTY))){
903
+		if (op==NO_OP)
904
+			ret=0;
905
+		else
906
+			ret=comp_num(op, 0, rtype, r, msg, h);
907
+	}else{
908
+		ret=pval.rs.len!=0;
909
+		if (op!=NO_OP)
910
+			ret=comp_num(op, ret, rtype, r, msg, h);
911
+	}
912
+	pv_value_destroy(&pval);
913
+	return ret;
914
+}
915
+
916
+
917
+
872 918
 /* check_self wrapper -- it checks also for the op */
873 919
 inline static int check_self_op(int op, str* s, unsigned short p)
874 920
 {
... ...
@@ -877,6 +988,7 @@ inline static int check_self_op(int op, str* s, unsigned short p)
877 877
 	ret=check_self(s, p, 0);
878 878
 	switch(op){
879 879
 		case EQUAL_OP:
880
+		case MATCH_OP:
880 881
 			break;
881 882
 		case DIFF_OP:
882 883
 			ret=(ret > 0) ? 0 : 1;
... ...
@@ -890,7 +1002,9 @@ inline static int check_self_op(int op, str* s, unsigned short p)
890 890
 
891 891
 
892 892
 /* eval_elem helping function, returns an op param */
893
-inline static int comp_ip(int op, struct ip_addr* ip, int rtype, union exp_op* r)
893
+inline static int comp_ip(int op, struct ip_addr* ip, int rtype,
894
+							union exp_op* r, struct sip_msg* msg,
895
+							struct run_act_ctx *ctx )
894 896
 {
895 897
 	struct hostent* he;
896 898
 	char ** h;
... ...
@@ -914,12 +1028,14 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype, union exp_op* r
914 914
 		case AVP_ST:
915 915
 		case STRING_ST:
916 916
 		case RE_ST:
917
+		case RVE_ST:
918
+		case SELECT_ST:
917 919
 			switch(op){
918 920
 				case EQUAL_OP:
919 921
 				case MATCH_OP:
920 922
 					/* 1: compare with ip2str*/
921
-					ret=comp_string(op, ip_addr2a(ip), rtype, r);
922
-					if (ret==1) break;
923
+					ret=comp_string(op, ip_addr2a(ip), rtype, r, msg, ctx);
924
+					if (likely(ret==1)) break;
923 925
 					/* 2: resolve (name) & compare w/ all the ips */
924 926
 					if (rtype==STRING_ST){
925 927
 						he=resolvehost(r->str.s);
... ...
@@ -939,17 +1055,17 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype, union exp_op* r
939 939
 					if (unlikely((received_dns & DO_REV_DNS) && 
940 940
 							((he=rev_resolvehost(ip))!=0) )){
941 941
 						/*  compare with primary host name */
942
-						ret=comp_string(op, he->h_name, rtype, r);
942
+						ret=comp_string(op, he->h_name, rtype, r, msg, ctx);
943 943
 						/* compare with all the aliases */
944 944
 						for(h=he->h_aliases; (ret!=1) && (*h); h++){
945
-							ret=comp_string(op, *h, rtype, r);
945
+							ret=comp_string(op, *h, rtype, r, msg, ctx);
946 946
 						}
947 947
 					}else{
948 948
 						ret=0;
949 949
 					}
950 950
 					break;
951 951
 				case DIFF_OP:
952
-					ret=(comp_ip(EQUAL_OP, ip, rtype, r) > 0) ? 0 : 1;
952
+					ret=(comp_ip(EQUAL_OP, ip, rtype, r, msg, ctx) > 0) ?0:1;
953 953
 					break;
954 954
 				default:
955 955
 					goto error_op;
... ...
@@ -969,10 +1085,10 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype, union exp_op* r
969 969
 error_op:
970 970
 	LOG(L_CRIT, "BUG: comp_ip: invalid operator %d\n", op);
971 971
 	return -1;
972
-
973 972
 }
974 973
 
975 974
 
975
+
976 976
 /* returns: 0/1 (false/true) or -1 on error */
977 977
 inline static int eval_elem(struct run_act_ctx* h, struct expr* e, 
978 978
 								struct sip_msg* msg)
... ...
@@ -990,7 +1106,7 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
990 990
 	switch(e->l_type){
991 991
 	case METHOD_O:
992 992
 		ret=comp_str(e->op, &msg->first_line.u.request.method,
993
-			     e->r_type, &e->r, msg);
993
+			 			e->r_type, &e->r, msg, h);
994 994
 		break;
995 995
 	case URI_O:
996 996
 		if(msg->new_uri.s) {
... ...
@@ -1001,7 +1117,7 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1001 1001
 						       msg->parsed_uri.port_no:SIP_PORT);
1002 1002
 			}else{
1003 1003
 				ret=comp_str(e->op, &msg->new_uri,
1004
-					     e->r_type, &e->r, msg);
1004
+								e->r_type, &e->r, msg, h);
1005 1005
 			}
1006 1006
 		}else{
1007 1007
 			if (e->r_type==MYSELF_ST){
... ...
@@ -1011,7 +1127,7 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1011 1011
 						       msg->parsed_uri.port_no:SIP_PORT);
1012 1012
 			}else{
1013 1013
 				ret=comp_str(e->op, &msg->first_line.u.request.uri,
1014
-					     e->r_type, &e->r, msg);
1014
+								e->r_type, &e->r, msg, h);
1015 1015
 			}
1016 1016
 		}
1017 1017
 		break;
... ...
@@ -1032,7 +1148,7 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1032 1032
 					  uri.port_no?uri.port_no:SIP_PORT);
1033 1033
 		}else{
1034 1034
 			ret=comp_str(e->op, &get_from(msg)->uri,
1035
-				     e->r_type, &e->r, msg);
1035
+							e->r_type, &e->r, msg, h);
1036 1036
 		}
1037 1037
 		break;
1038 1038
 
... ...
@@ -1054,22 +1170,23 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1054 1054
 					  uri.port_no?uri.port_no:SIP_PORT);
1055 1055
 		}else{
1056 1056
 			ret=comp_str(e->op, &get_to(msg)->uri,
1057
-				     e->r_type, &e->r, msg);
1057
+							e->r_type, &e->r, msg, h);
1058 1058
 		}
1059 1059
 		break;
1060 1060
 
1061 1061
 	case SRCIP_O:
1062
-		ret=comp_ip(e->op, &msg->rcv.src_ip, e->r_type, &e->r);
1062
+		ret=comp_ip(e->op, &msg->rcv.src_ip, e->r_type, &e->r, msg, h);
1063 1063
 		break;
1064 1064
 
1065 1065
 	case DSTIP_O:
1066
-		ret=comp_ip(e->op, &msg->rcv.dst_ip, e->r_type, &e->r);
1066
+		ret=comp_ip(e->op, &msg->rcv.dst_ip, e->r_type, &e->r, msg, h);
1067 1067
 		break;
1068 1068
 
1069 1069
 	case SNDIP_O:
1070 1070
 		snd_inf=get_onsend_info();
1071
-		if (snd_inf && snd_inf->send_sock){
1072
-			ret=comp_ip(e->op, &snd_inf->send_sock->address, e->r_type, &e->r);
1071
+		if (likely(snd_inf && snd_inf->send_sock)){
1072
+			ret=comp_ip(e->op, &snd_inf->send_sock->address,
1073
+						e->r_type, &e->r, msg, h);
1073 1074
 		}else{
1074 1075
 			BUG("eval_elem: snd_ip unknown (not in a onsend_route?)\n");
1075 1076
 		}
... ...
@@ -1077,9 +1194,9 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1077 1077
 
1078 1078
 	case TOIP_O:
1079 1079
 		snd_inf=get_onsend_info();
1080
-		if (snd_inf && snd_inf->to){
1080
+		if (likely(snd_inf && snd_inf->to)){
1081 1081
 			su2ip_addr(&ip, snd_inf->to);
1082
-			ret=comp_ip(e->op, &ip, e->r_type, &e->r);
1082
+			ret=comp_ip(e->op, &ip, e->r_type, &e->r, msg, h);
1083 1083
 		}else{
1084 1084
 			BUG("eval_elem: to_ip unknown (not in a onsend_route?)\n");
1085 1085
 		}
... ...
@@ -1096,20 +1213,18 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1096 1096
 		break;
1097 1097
 
1098 1098
 	case SRCPORT_O:
1099
-		ret=comp_num(e->op, (int)msg->rcv.src_port,
1100
-			     e->r_type, &e->r);
1099
+		ret=comp_num(e->op, (int)msg->rcv.src_port, e->r_type, &e->r, msg, h);
1101 1100
 		break;
1102 1101
 
1103 1102
 	case DSTPORT_O:
1104
-		ret=comp_num(e->op, (int)msg->rcv.dst_port,
1105
-			     e->r_type, &e->r);
1103
+		ret=comp_num(e->op, (int)msg->rcv.dst_port, e->r_type, &e->r, msg, h);
1106 1104
 		break;
1107 1105
 
1108 1106
 	case SNDPORT_O:
1109 1107
 		snd_inf=get_onsend_info();
1110
-		if (snd_inf && snd_inf->send_sock){
1108
+		if (likely(snd_inf && snd_inf->send_sock)){
1111 1109
 			ret=comp_num(e->op, (int)snd_inf->send_sock->port_no,
1112
-				     e->r_type, &e->r);
1110
+							e->r_type, &e->r, msg, h);
1113 1111
 		}else{
1114 1112
 			BUG("eval_elem: snd_port unknown (not in a onsend_route?)\n");
1115 1113
 		}
... ...
@@ -1117,39 +1232,37 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1117 1117
 
1118 1118
 	case TOPORT_O:
1119 1119
 		snd_inf=get_onsend_info();
1120
-		if (snd_inf && snd_inf->to){
1120
+		if (likely(snd_inf && snd_inf->to)){
1121 1121
 			ret=comp_num(e->op, (int)su_getport(snd_inf->to),
1122
-				     e->r_type, &e->r);
1122
+								e->r_type, &e->r, msg, h);
1123 1123
 		}else{
1124 1124
 			BUG("eval_elem: to_port unknown (not in a onsend_route?)\n");
1125 1125
 		}
1126 1126
 		break;
1127 1127
 
1128 1128
 	case PROTO_O:
1129
-		ret=comp_num(e->op, msg->rcv.proto,
1130
-			     e->r_type, &e->r);
1129
+		ret=comp_num(e->op, msg->rcv.proto, e->r_type, &e->r, msg, h);
1131 1130
 		break;
1132 1131
 
1133 1132
 	case SNDPROTO_O:
1134 1133
 		snd_inf=get_onsend_info();
1135
-		if (snd_inf && snd_inf->send_sock){
1134
+		if (likely(snd_inf && snd_inf->send_sock)){
1136 1135
 			ret=comp_num(e->op, snd_inf->send_sock->proto,
1137
-				     e->r_type, &e->r);
1136
+							e->r_type, &e->r, msg, h);
1138 1137
 		}else{
1139 1138
 			BUG("eval_elem: snd_proto unknown (not in a onsend_route?)\n");
1140 1139
 		}
1141 1140
 		break;
1142 1141
 
1143 1142
 	case AF_O:
1144
-		ret=comp_num(e->op, (int)msg->rcv.src_ip.af,
1145
-			     e->r_type, &e->r);
1143
+		ret=comp_num(e->op, (int)msg->rcv.src_ip.af, e->r_type, &e->r, msg, h);
1146 1144
 		break;
1147 1145
 
1148 1146
 	case SNDAF_O:
1149 1147
 		snd_inf=get_onsend_info();
1150
-		if (snd_inf && snd_inf->send_sock){
1148
+		if (likely(snd_inf && snd_inf->send_sock)){
1151 1149
 			ret=comp_num(e->op, snd_inf->send_sock->address.af,
1152
-							e->r_type, &e->r);
1150
+							e->r_type, &e->r, msg, h);
1153 1151
 		}else{
1154 1152
 			BUG("eval_elem: snd_af unknown (not in a onsend_route?)\n");
1155 1153
 		}
... ...
@@ -1157,24 +1270,30 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1157 1157
 
1158 1158
 	case MSGLEN_O:
1159 1159
 		if ((snd_inf=get_onsend_info())!=0){
1160
-			ret=comp_num(e->op, (int)snd_inf->len,
1161
-					e->r_type, &e->r);
1160
+			ret=comp_num(e->op, (int)snd_inf->len, e->r_type, &e->r, msg, h);
1162 1161
 		}else{
1163
-			ret=comp_num(e->op, (int)msg->len,
1164
-					e->r_type, &e->r);
1162
+			ret=comp_num(e->op, (int)msg->len, e->r_type, &e->r, msg, h);
1165 1163
 		}
1166 1164
 		break;
1167 1165
 
1168 1166
 	case RETCODE_O:
1169
-		ret=comp_num(e->op, h->last_retcode, e->r_type, &e->r);
1167
+		ret=comp_num(e->op, h->last_retcode, e->r_type, &e->r, msg, h);
1170 1168
 		break;
1171 1169
 
1172 1170
 	case AVP_O:
1173
-		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r, msg);
1171
+		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r, msg, h);
1174 1172
 		break;
1175 1173
 
1176 1174
 	case SELECT_O:
1177
-		ret = comp_select(e->op, e->l.select, e->r_type, &e->r, msg);
1175
+		ret = comp_select(e->op, e->l.select, e->r_type, &e->r, msg, h);
1176
+		break;
1177
+
1178
+	case RVEXP_O:
1179
+		ret = comp_rve(e->op, e->l.param, e->r_type, &e->r, msg, h);
1180
+		break;
1181
+
1182
+	case PVAR_O:
1183
+		ret=comp_pvar(e->op, e->l.param, e->r_type, &e->r, msg, h);
1178 1184
 		break;
1179 1185
 
1180 1186
 	default:
... ...
@@ -68,6 +68,27 @@ error:
68 68
 }
69 69
 
70 70
 
71
+struct expr* mk_exp_rve(int op, void* left, void* right)
72
+{
73
+	struct expr * e;
74
+	e=(struct expr*)pkg_malloc(sizeof (struct expr));
75
+	if (e==0) goto error;
76
+	e->type=EXP_T;
77
+	e->op=op;
78
+	e->l.param=mk_elem(RVEXP_O, RVE_ST, left, 0, 0);
79
+	e->r.param=mk_elem(RVEXP_O, RVE_ST, right, 0, 0);
80
+	if (e->l.param==0 || e->r.param==0){
81
+		if (e->l.param) pkg_free(e->l.param);
82
+		if (e->r.param) pkg_free(e->r.param);
83
+		pkg_free(e);
84
+		goto error;
85
+	}
86
+	return e;
87
+error:
88
+	LOG(L_CRIT, "ERROR: mk_exp_rve: memory allocation failure\n");
89
+	return 0;
90
+}
91
+
71 92
 struct expr* mk_elem(int op, int ltype, void* lparam, int rtype, void* rparam)
72 93
 {
73 94
 	struct expr * e;
... ...
@@ -160,15 +181,48 @@ void print_expr(struct expr* exp)
160 160
 			case DSTPORT_O:
161 161
 				DBG("dstport");
162 162
 				break;
163
-			case NUMBER_O:
163
+			case PROTO_O:
164
+				DBG("proto");
165
+				break;
166
+			case AF_O:
167
+				DBG("af");
168
+				break;
169
+			case MSGLEN_O:
170
+				DBG("msglen");
164 171
 				break;
165 172
 			case ACTION_O:
166 173
 				break;
167
-		        case AVP_ST:
168
-				DBG("attr");
174
+			case NUMBER_O:
169 175
 				break;
170
-		        case SELECT_ST:
171
-			        DBG("select");
176
+			case AVP_O:
177
+				DBG("avp");
178
+				break;
179
+			case SNDIP_O:
180
+				DBG("sndip");
181
+				break;
182
+			case SNDPORT_O:
183
+				DBG("sndport");
184
+				break;
185
+			case TOIP_O:
186
+				DBG("toip");
187
+				break;
188
+			case TOPORT_O:
189
+				DBG("toport");
190
+				break;
191
+			case SNDPROTO_O:
192
+				DBG("sndproto");
193
+				break;
194
+			case SNDAF_O:
195
+				DBG("sndaf");
196
+				break;
197
+			case RETCODE_O:
198
+				DBG("retcode");
199
+				break;
200
+			case SELECT_O:
201
+				DBG("select");
202
+				break;
203
+			case RVEXP_O:
204
+				DBG("rval");
172 205
 				break;
173 206
 
174 207
 			default:
... ...
@@ -65,7 +65,7 @@ enum { EQUAL_OP=10, MATCH_OP, GT_OP, LT_OP, GTE_OP, LTE_OP, DIFF_OP, NO_OP };
65 65
 enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O,
66 66
 	   DSTIP_O, DSTPORT_O, PROTO_O, AF_O, MSGLEN_O, DEFAULT_O, ACTION_O,
67 67
 	   NUMBER_O, AVP_O, SNDIP_O, SNDPORT_O, TOIP_O, TOPORT_O, SNDPROTO_O,
68
-	   SNDAF_O, RETCODE_O, SELECT_O};
68
+	   SNDAF_O, RETCODE_O, SELECT_O, PVAR_O, RVEXP_O};
69 69
 
70 70
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
71 71
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T,
... ...
@@ -94,8 +94,8 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
94 94
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
95 95
 		EXPR_ST, ACTIONS_ST, MODEXP_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST,
96 96
 		MYSELF_ST, STR_ST, SOCKID_ST, SOCKETINFO_ST, ACTION_ST, AVP_ST,
97
-		SELECT_ST, /* obsolete */
98
-		LVAL_ST, RVE_ST,
97
+		SELECT_ST, PVAR_ST,
98
+		LVAL_ST,  RVE_ST,
99 99
 		RETCODE_ST};
100 100
 
101 101
 /* run flags */