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 334
 					pkg_free(exp->r.param);
334 335
 					exp->r.re=re;
335 336
 					exp->r_type=RE_ST;
336
-				}else if (exp->r_type!=RE_ST && exp->r_type != AVP_ST && exp->r_type != SELECT_ST){
337
+				}else if (exp->r_type!=RE_ST && exp->r_type != AVP_ST
338
+						&& exp->r_type != SELECT_ST && exp->r_type!= RVE_ST
339
+						&& exp->r_type != PVAR_ST){
337 340
 					LOG(L_CRIT, "BUG: fix_expr : invalid type for match\n");
338 341
 					return E_BUG;
339 342
 				}
... ...
@@ -374,6 +377,19 @@ int fix_expr(struct expr* exp)
374 377
 					return ret;
375 378
 				}
376 379
 			}
380
+			if (exp->l_type==RVEXP_O){
381
+				if ((ret=fix_rval_expr(&exp->l.param))<0){
382
+					ERR("Unable to fix left rval expression\n");
383
+					return ret;
384
+				}
385
+			}
386
+			if (exp->r_type==RVE_ST){
387
+				if ((ret=fix_rval_expr(&exp->r.param))<0){
388
+					ERR("Unable to fix right rval expression\n");
389
+					return ret;
390
+				}
391
+			}
392
+			/* PVAR don't need fixing */
377 393
 			ret=0;
378 394
 	}
379 395
 	return ret;
... ...
@@ -585,40 +601,67 @@ int fix_actions(struct action* a)
585 601
  * attributes. If either of the attributes if of string type then the length of
586 602
  * its value will be used.
587 603
  */
588
-inline static int comp_num(int op, long left, int rtype, union exp_op* r)
604
+inline static int comp_num(int op, long left, int rtype, union exp_op* r,
605
+							struct sip_msg* msg, struct run_act_ctx* h)
589 606
 {
590 607
 	int_str val;
608
+	pv_value_t pval;
591 609
 	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;
610
+	int right;
611
+
612
+	if (unlikely(op==NO_OP)) return !(!left);
613
+	switch(rtype){
614
+		case AVP_ST:
615
+			avp = search_avp_by_index(r->attr->type, r->attr->name,
616
+										&val, r->attr->index);
617
+			if (avp && !(avp->flags & AVP_VAL_STR)) right = val.n;
618
+			else return (op == DIFF_OP);
619
+			break;
620
+		case NUMBER_ST:
621
+			right = r->numval;
622
+			break;
623
+		case RVE_ST:
624
+			if (unlikely(rval_expr_eval_int(h, msg, &right, r->param)<0))
625
+				return (op == DIFF_OP); /* not found/invalid */
626
+			break;
627
+		case PVAR_ST:
628
+			memset(&pval, 0, sizeof(pv_value_t));
629
+			if (unlikely(pv_get_spec_value(msg, r->param, &pval)!=0)){
630
+				return (op == DIFF_OP); /* error, not found => false */
631
+			}
632
+			if (likely(pval.flags & (PV_TYPE_INT|PV_VAL_INT))){
633
+				pv_value_destroy(&pval);
634
+				right=pval.ri;
635
+			}else{
636
+				pv_value_destroy(&pval);
637
+				return (op == DIFF_OP); /* not found or invalid type */
638
+			}
639
+			break;
640
+		default:
641
+			LOG(L_CRIT, "BUG: comp_num: Invalid right operand (%d)\n", rtype);
642
+			return E_BUG;
603 643
 	}
604 644
 
605 645
 	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;
646
+		case EQUAL_OP: return (long)left == (long)right;
647
+		case DIFF_OP:  return (long)left != (long)right;
648
+		case GT_OP:    return (long)left >  (long)right;
649
+		case LT_OP:    return (long)left <  (long)right;
650
+		case GTE_OP:   return (long)left >= (long)right;
651
+		case LTE_OP:   return (long)left <= (long)right;
652
+		default:
653
+			LOG(L_CRIT, "BUG: comp_num: unknown operator: %d\n", op);
654
+			return E_BUG;
615 655
 	}
656
+	return E_BUG;
616 657
 }
617 658
 
618 659
 /*
619 660
  * Compare given string "left" with right side of expression
620 661
  */
621
-inline static int comp_str(int op, str* left, int rtype, union exp_op* r, struct sip_msg* msg)
662
+inline static int comp_str(int op, str* left, int rtype, 
663
+							union exp_op* r, struct sip_msg* msg,
664
+							struct run_act_ctx* h)
622 665
 {
623 666
 	str* right;
624 667
 	int_str val;
... ...
@@ -628,33 +671,74 @@ inline static int comp_str(int op, str* left, int rtype, union exp_op* r, struct
628 671
 	char backup;
629 672
 	regex_t* re;
630 673
 	unsigned int l;
674
+	struct rvalue* rv;
675
+	struct rval_cache rv_cache;
676
+	pv_value_t pval;
677
+	int destroy_pval;
631 678
 	
632 679
 	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) {
680
+	rv=0;
681
+	destroy_pval=0;
682
+	if (unlikely(op==NO_OP)) return (left->s!=0);
683
+	switch(rtype){
684
+		case AVP_ST:
685
+			avp = search_avp_by_index(r->attr->type, r->attr->name,
686
+										&val, r->attr->index);
687
+			if (likely(avp && (avp->flags & AVP_VAL_STR))) right = &val.s;
688
+			else return (op == DIFF_OP);
689
+			break;
690
+		case SELECT_ST:
691
+			ret = run_select(&v, r->select, msg);
692
+			if (unlikely(ret != 0)) 
693
+				return (op == DIFF_OP); /* Not found or error */
694
+			right = &v;
695
+			break;
696
+		case RVE_ST:
697
+			rval_cache_init(&rv_cache);
698
+			rv=rval_expr_eval(h, msg, r->param);
699
+			if (unlikely (rv==0)) 
700
+				return (op==DIFF_OP); /* not found or error*/
701
+			if (unlikely(rval_get_tmp_str(h, msg, &v, rv, 0, &rv_cache)<0)){
702
+				goto error;
703
+			}
704
+			right = &v;
705
+			break;
706
+		case PVAR_ST:
707
+			memset(&pval, 0, sizeof(pv_value_t));
708
+			if (unlikely(pv_get_spec_value(msg, r->param, &pval)!=0)){
709
+				return (op == DIFF_OP); /* error, not found => false */
710
+			}
711
+			destroy_pval=1;
712
+			if (likely(pval.flags & PV_VAL_STR)){
713
+				right=&pval.rs;
714
+			}else{
715
+				pv_value_destroy(&pval);
716
+				return (op == DIFF_OP); /* not found or invalid type */
717
+			}
718
+			break;
719
+		case RE_ST:
720
+			if (unlikely(op != MATCH_OP)){
721
+				LOG(L_CRIT, "BUG: comp_str: Bad operator %d,"
722
+							" ~= expected\n", op);
723
+				goto error;
724
+			}
725
+			break;
726
+		case STRING_ST:
727
+			right=&r->str;
728
+			break;
729
+		case NUMBER_ST:
646 730
 			/* "123" > 100 is not allowed by cfg.y rules
647 731
 			 * but can happen as @select or $avp evaluation
648 732
 			 * $test > 10
649 733
 			 * the right operator MUST be number to do the conversion
650 734
 			 */
651
-		if (str2int(left,&l) < 0)
735
+			if (str2int(left,&l) < 0)
736
+				goto error;
737
+			return comp_num(op, l, rtype, r, msg, h);
738
+		default:
739
+			LOG(L_CRIT, "BUG: comp_str: Bad type %d, "
740
+						"string or RE expected\n", rtype);
652 741
 			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 742
 	}
659 743
 
660 744
 	ret=-1;
... ...
@@ -668,111 +752,97 @@ inline static int comp_str(int op, str* left, int rtype, union exp_op* r, struct
668 752
 			ret = (strncasecmp(left->s, right->s, left->len)!=0);
669 753
 			break;
670 754
 		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
-			      */
755
+			/* this is really ugly -- we put a temporary zero-terminating
756
+			 * character in the original string; that's because regexps
757
+			 * take 0-terminated strings and our messages are not
758
+			 * zero-terminated; it should not hurt as long as this function
759
+			 * is applied to content of pkg mem, which is always the case
760
+			 * with calls from route{}; the same goes for fline in 
761
+			 * reply_route{};
762
+			 *
763
+			 * also, the received function should always give us an extra
764
+			 * character, into which we can put the 0-terminator now;
765
+			 * an alternative would be allocating a new piece of memory,
766
+			 * which might be too slow
767
+			 * -jiri
768
+			 *
769
+			 * janakj: AVPs are zero terminated too so this is not problem 
770
+			 * either
771
+			 */
686 772
 			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)) {
773
+			left->s[left->len]='\0';
774
+			switch(rtype){
775
+				case AVP_ST:
776
+				case SELECT_ST:
777
+				case RVE_ST:
778
+				case PVAR_ST:
779
+					/* we need to compile the RE on the fly */
780
+					re=(regex_t*)pkg_malloc(sizeof(regex_t));
781
+					if (re==0){
782
+						LOG(L_CRIT, "ERROR: comp_strstr: memory allocation"
783
+									 " failure\n");
784
+						left->s[left->len] = backup;
785
+						goto error;
786
+					}
787
+					if (regcomp(re, right->s,
788
+								REG_EXTENDED|REG_NOSUB|REG_ICASE)) {
789
+						pkg_free(re);
790
+						left->s[left->len] = backup;
791
+						goto error;
792
+					}
793
+					ret=(regexec(re, left->s, 0, 0, 0)==0);
794
+					regfree(re);
698 795
 					pkg_free(re);
699
-					left->s[left->len] = backup;
796
+					break;
797
+				case RE_ST:
798
+					ret=(regexec(r->re, left->s, 0, 0, 0)==0);
799
+					break;
800
+				case STRING_ST:
801
+				default:
802
+					LOG(L_CRIT, "BUG: comp_str: Bad operator type %d, "
803
+								"for ~= \n", rtype);
700 804
 					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 805
 			}
708
-			if (backup) left->s[left->len] = backup;
806
+			left->s[left->len] = backup;
709 807
 			break;
710 808
 		default:
711 809
 			LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
712 810
 			goto error;
713 811
 	}
812
+	if (rv){
813
+		rval_cache_clean(&rv_cache);
814
+		rval_destroy(rv);
815
+	}
816
+	if (destroy_pval)
817
+		pv_value_destroy(&pval);
714 818
 	return ret;
715 819
 
716 820
 error:
821
+	if (rv){
822
+		rval_cache_clean(&rv_cache);
823
+		rval_destroy(rv);
824
+	}
825
+	if (destroy_pval)
826
+		pv_value_destroy(&pval);
717 827
 	return (op == DIFF_OP) ? 1 : -1;
718 828
 }
719 829
 
720 830
 
721 831
 /* eval_elem helping function, returns str op param */
722
-inline static int comp_string(int op, char* left, int rtype, union exp_op* r)
832
+inline static int comp_string(int op, char* left, int rtype, union exp_op* r,
833
+								struct sip_msg* msg, struct run_act_ctx* h)
723 834
 {
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;
835
+	str s;
836
+	
837
+	s.s=left;
838
+	s.len=strlen(left);
839
+	return comp_str(op, &s, rtype, r, msg, h);
772 840
 }
773 841
 
774 842
 
775
-inline static int comp_avp(int op, avp_spec_t* spec, int rtype, union exp_op* r, struct sip_msg* msg)
843
+inline static int comp_avp(int op, avp_spec_t* spec, int rtype,
844
+							union exp_op* r, struct sip_msg* msg,
845
+							struct run_act_ctx* h)
776 846
 {
777 847
 	avp_t* avp;
778 848
 	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 851
 	unsigned int uval;
782 852
 
783 853
 	if (spec->type & AVP_INDEX_ALL) {
784
-		avp = search_first_avp(spec->type & ~AVP_INDEX_ALL, spec->name, NULL, NULL);
854
+		avp = search_first_avp(spec->type & ~AVP_INDEX_ALL, spec->name,
855
+								NULL, NULL);
785 856
 		return (avp!=0);
786 857
 	}
787 858
 	avp = search_avp_by_index(spec->type, spec->name, &val, spec->index);
788 859
 	if (!avp) return (op == DIFF_OP);
789 860
 
790
-	switch(op) {
791
-	case NO_OP:
861
+	if (op==NO_OP){
792 862
 		if (avp->flags & AVP_VAL_STR) {
793 863
 			return val.s.len!=0;
794 864
 		} else {
795 865
 			return val.n != 0;
796 866
 		}
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 867
 	}
807
-
808 868
 	if (avp->flags & AVP_VAL_STR) {
809
-		return comp_str(op, &val.s, rtype, r, msg);
869
+		return comp_str(op, &val.s, rtype, r, msg, h);
810 870
 	} else {
811 871
 		switch(rtype){
812 872
 			case NUMBER_ST:
813
-				return comp_num(op, val.n, rtype, r);
873
+			case AVP_ST:
874
+			case RVE_ST:
875
+			case PVAR_ST:
876
+				return comp_num(op, val.n, rtype, r, msg, h);
877
+				break;
814 878
 			case STRING_ST:
815 879
 				tmp.s=r->string;
816 880
 				tmp.len=strlen(r->string);
817 881
 				if (str2int(&tmp, &uval)<0){
818
-					LOG(L_WARN, "WARNING: comp_avp: cannot convert string value"
819
-								" to int (%s)\n", ZSW(r->string));
882
+					LOG(L_WARN, "WARNING: comp_avp: cannot convert"
883
+								" string value to int (%s)\n",
884
+								ZSW(r->string));
820 885
 					goto error;
821 886
 				}
822 887
 				num_val.numval=uval;
823
-				return comp_num(op, val.n, NUMBER_ST, &num_val);
888
+				return comp_num(op, val.n, NUMBER_ST, &num_val, msg, h);
824 889
 			case STR_ST:
825 890
 				if (str2int(&r->str, &uval)<0){
826 891
 					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 893
 					goto error;
829 894
 				}
830 895
 				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);
896
+				return comp_num(op, val.n, NUMBER_ST, &num_val, msg, h);
834 897
 			default:
835 898
 				LOG(L_CRIT, "BUG: comp_avp: invalid type for numeric avp "
836 899
 							"comparison (%d)\n", rtype);
... ...
@@ -844,7 +907,9 @@ error:
844 907
 /*
845 908
  * Left side of expression was select
846 909
  */
847
-inline static int comp_select(int op, select_t* sel, int rtype, union exp_op* r, struct sip_msg* msg)
910
+inline static int comp_select(int op, select_t* sel, int rtype,
911
+								union exp_op* r, struct sip_msg* msg,
912
+								struct run_act_ctx* h)
848 913
 {
849 914
 	int ret;
850 915
 	str val;
... ...
@@ -853,22 +918,68 @@ inline static int comp_select(int op, select_t* sel, int rtype, union exp_op* r,
853 918
 	ret = run_select(&val, sel, msg);
854 919
 	if (ret != 0) return (op == DIFF_OP);
855 920
 
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) {
921
+	if (op==NO_OP) return (val.len>0);
922
+	if (unlikely(val.len==0)) {
864 923
 		/* make sure the string pointer uses accessible memory range
865 924
 		 * the comp_str function might dereference it
866 925
 		 */
867 926
 		val.s=&empty_str;
868 927
 	}
869
-	return comp_str(op, &val, rtype, r, msg);
928
+	return comp_str(op, &val, rtype, r, msg, h);
929
+}
930
+
931
+
932
+inline static int comp_rve(int op, struct rval_expr* rve, int rtype,
933
+							union exp_op* r, struct sip_msg* msg,
934
+							struct run_act_ctx* h)
935
+{
936
+	int i;
937
+	
938
+	if (unlikely(rval_expr_eval_int(h,  msg, &i, rve)<0)){
939
+		ERR("failure evaluating expression: bad type\n");
940
+		i=0; /* false */
941
+	}
942
+	if (op==NO_OP)
943
+		return !(!i); /* transform it into { 0, 1 } */
944
+	return comp_num(op, i, rtype, r, msg, h);
870 945
 }
871 946
 
947
+
948
+
949
+inline static int comp_pvar(int op, pv_spec_t* pvs, int rtype,
950
+							union exp_op* r, struct sip_msg* msg,
951
+							struct run_act_ctx* h)
952
+{
953
+	pv_value_t pval;
954
+	int ret;
955
+	
956
+	ret=0;
957
+	memset(&pval, 0, sizeof(pv_value_t));
958
+	if (unlikely(pv_get_spec_value(msg, r->param, &pval)!=0)){
959
+		return 0; /* error, not found => false */
960
+	}
961
+	if (likely(pval.flags & PV_TYPE_INT)){
962
+		if (op==NO_OP)
963
+			ret=!(!pval.ri);
964
+		else
965
+			ret=comp_num(op, pval.ri, rtype, r, msg, h);
966
+	}else if ((pval.flags==PV_VAL_NONE) ||
967
+			(pval.flags & (PV_VAL_NULL|PV_VAL_EMPTY))){
968
+		if (op==NO_OP)
969
+			ret=0;
970
+		else
971
+			ret=comp_num(op, 0, rtype, r, msg, h);
972
+	}else{
973
+		ret=pval.rs.len!=0;
974
+		if (op!=NO_OP)
975
+			ret=comp_num(op, ret, rtype, r, msg, h);
976
+	}
977
+	pv_value_destroy(&pval);
978
+	return ret;
979
+}
980
+
981
+
982
+
872 983
 /* check_self wrapper -- it checks also for the op */
873 984
 inline static int check_self_op(int op, str* s, unsigned short p)
874 985
 {
... ...
@@ -877,6 +988,7 @@ inline static int check_self_op(int op, str* s, unsigned short p)
877 988
 	ret=check_self(s, p, 0);
878 989
 	switch(op){
879 990
 		case EQUAL_OP:
991
+		case MATCH_OP:
880 992
 			break;
881 993
 		case DIFF_OP:
882 994
 			ret=(ret > 0) ? 0 : 1;
... ...
@@ -890,7 +1002,9 @@ inline static int check_self_op(int op, str* s, unsigned short p)
890 1002
 
891 1003
 
892 1004
 /* 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)
1005
+inline static int comp_ip(int op, struct ip_addr* ip, int rtype,
1006
+							union exp_op* r, struct sip_msg* msg,
1007
+							struct run_act_ctx *ctx )
894 1008
 {
895 1009
 	struct hostent* he;
896 1010
 	char ** h;
... ...
@@ -914,12 +1028,14 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype, union exp_op* r
914 1028
 		case AVP_ST:
915 1029
 		case STRING_ST:
916 1030
 		case RE_ST:
1031
+		case RVE_ST:
1032
+		case SELECT_ST:
917 1033
 			switch(op){
918 1034
 				case EQUAL_OP:
919 1035
 				case MATCH_OP:
920 1036
 					/* 1: compare with ip2str*/
921
-					ret=comp_string(op, ip_addr2a(ip), rtype, r);
922
-					if (ret==1) break;
1037
+					ret=comp_string(op, ip_addr2a(ip), rtype, r, msg, ctx);
1038
+					if (likely(ret==1)) break;
923 1039
 					/* 2: resolve (name) & compare w/ all the ips */
924 1040
 					if (rtype==STRING_ST){
925 1041
 						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 1055
 					if (unlikely((received_dns & DO_REV_DNS) && 
940 1056
 							((he=rev_resolvehost(ip))!=0) )){
941 1057
 						/*  compare with primary host name */
942
-						ret=comp_string(op, he->h_name, rtype, r);
1058
+						ret=comp_string(op, he->h_name, rtype, r, msg, ctx);
943 1059
 						/* compare with all the aliases */
944 1060
 						for(h=he->h_aliases; (ret!=1) && (*h); h++){
945
-							ret=comp_string(op, *h, rtype, r);
1061
+							ret=comp_string(op, *h, rtype, r, msg, ctx);
946 1062
 						}
947 1063
 					}else{
948 1064
 						ret=0;
949 1065
 					}
950 1066
 					break;
951 1067
 				case DIFF_OP:
952
-					ret=(comp_ip(EQUAL_OP, ip, rtype, r) > 0) ? 0 : 1;
1068
+					ret=(comp_ip(EQUAL_OP, ip, rtype, r, msg, ctx) > 0) ?0:1;
953 1069
 					break;
954 1070
 				default:
955 1071
 					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 1085
 error_op:
970 1086
 	LOG(L_CRIT, "BUG: comp_ip: invalid operator %d\n", op);
971 1087
 	return -1;
972
-
973 1088
 }
974 1089
 
975 1090
 
1091
+
976 1092
 /* returns: 0/1 (false/true) or -1 on error */
977 1093
 inline static int eval_elem(struct run_act_ctx* h, struct expr* e, 
978 1094
 								struct sip_msg* msg)
... ...
@@ -990,7 +1106,7 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
990 1106
 	switch(e->l_type){
991 1107
 	case METHOD_O:
992 1108
 		ret=comp_str(e->op, &msg->first_line.u.request.method,
993
-			     e->r_type, &e->r, msg);
1109
+			 			e->r_type, &e->r, msg, h);
994 1110
 		break;
995 1111
 	case URI_O:
996 1112
 		if(msg->new_uri.s) {
... ...
@@ -1001,7 +1117,7 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1001 1117
 						       msg->parsed_uri.port_no:SIP_PORT);
1002 1118
 			}else{
1003 1119
 				ret=comp_str(e->op, &msg->new_uri,
1004
-					     e->r_type, &e->r, msg);
1120
+								e->r_type, &e->r, msg, h);
1005 1121
 			}
1006 1122
 		}else{
1007 1123
 			if (e->r_type==MYSELF_ST){
... ...
@@ -1011,7 +1127,7 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1011 1127
 						       msg->parsed_uri.port_no:SIP_PORT);
1012 1128
 			}else{
1013 1129
 				ret=comp_str(e->op, &msg->first_line.u.request.uri,
1014
-					     e->r_type, &e->r, msg);
1130
+								e->r_type, &e->r, msg, h);
1015 1131
 			}
1016 1132
 		}
1017 1133
 		break;
... ...
@@ -1032,7 +1148,7 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1032 1148
 					  uri.port_no?uri.port_no:SIP_PORT);
1033 1149
 		}else{
1034 1150
 			ret=comp_str(e->op, &get_from(msg)->uri,
1035
-				     e->r_type, &e->r, msg);
1151
+							e->r_type, &e->r, msg, h);
1036 1152
 		}
1037 1153
 		break;
1038 1154
 
... ...
@@ -1054,22 +1170,23 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1054 1170
 					  uri.port_no?uri.port_no:SIP_PORT);
1055 1171
 		}else{
1056 1172
 			ret=comp_str(e->op, &get_to(msg)->uri,
1057
-				     e->r_type, &e->r, msg);
1173
+							e->r_type, &e->r, msg, h);
1058 1174
 		}
1059 1175
 		break;
1060 1176
 
1061 1177
 	case SRCIP_O:
1062
-		ret=comp_ip(e->op, &msg->rcv.src_ip, e->r_type, &e->r);
1178
+		ret=comp_ip(e->op, &msg->rcv.src_ip, e->r_type, &e->r, msg, h);
1063 1179
 		break;
1064 1180
 
1065 1181
 	case DSTIP_O:
1066
-		ret=comp_ip(e->op, &msg->rcv.dst_ip, e->r_type, &e->r);
1182
+		ret=comp_ip(e->op, &msg->rcv.dst_ip, e->r_type, &e->r, msg, h);
1067 1183
 		break;
1068 1184
 
1069 1185
 	case SNDIP_O:
1070 1186
 		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);
1187
+		if (likely(snd_inf && snd_inf->send_sock)){
1188
+			ret=comp_ip(e->op, &snd_inf->send_sock->address,
1189
+						e->r_type, &e->r, msg, h);
1073 1190
 		}else{
1074 1191
 			BUG("eval_elem: snd_ip unknown (not in a onsend_route?)\n");
1075 1192
 		}
... ...
@@ -1077,9 +1194,9 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1077 1194
 
1078 1195
 	case TOIP_O:
1079 1196
 		snd_inf=get_onsend_info();
1080
-		if (snd_inf && snd_inf->to){
1197
+		if (likely(snd_inf && snd_inf->to)){
1081 1198
 			su2ip_addr(&ip, snd_inf->to);
1082
-			ret=comp_ip(e->op, &ip, e->r_type, &e->r);
1199
+			ret=comp_ip(e->op, &ip, e->r_type, &e->r, msg, h);
1083 1200
 		}else{
1084 1201
 			BUG("eval_elem: to_ip unknown (not in a onsend_route?)\n");
1085 1202
 		}
... ...
@@ -1096,20 +1213,18 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1096 1213
 		break;
1097 1214
 
1098 1215
 	case SRCPORT_O:
1099
-		ret=comp_num(e->op, (int)msg->rcv.src_port,
1100
-			     e->r_type, &e->r);
1216
+		ret=comp_num(e->op, (int)msg->rcv.src_port, e->r_type, &e->r, msg, h);
1101 1217
 		break;
1102 1218
 
1103 1219
 	case DSTPORT_O:
1104
-		ret=comp_num(e->op, (int)msg->rcv.dst_port,
1105
-			     e->r_type, &e->r);
1220
+		ret=comp_num(e->op, (int)msg->rcv.dst_port, e->r_type, &e->r, msg, h);
1106 1221
 		break;
1107 1222
 
1108 1223
 	case SNDPORT_O:
1109 1224
 		snd_inf=get_onsend_info();
1110
-		if (snd_inf && snd_inf->send_sock){
1225
+		if (likely(snd_inf && snd_inf->send_sock)){
1111 1226
 			ret=comp_num(e->op, (int)snd_inf->send_sock->port_no,
1112
-				     e->r_type, &e->r);
1227
+							e->r_type, &e->r, msg, h);
1113 1228
 		}else{
1114 1229
 			BUG("eval_elem: snd_port unknown (not in a onsend_route?)\n");
1115 1230
 		}
... ...
@@ -1117,39 +1232,37 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1117 1232
 
1118 1233
 	case TOPORT_O:
1119 1234
 		snd_inf=get_onsend_info();
1120
-		if (snd_inf && snd_inf->to){
1235
+		if (likely(snd_inf && snd_inf->to)){
1121 1236
 			ret=comp_num(e->op, (int)su_getport(snd_inf->to),
1122
-				     e->r_type, &e->r);
1237
+								e->r_type, &e->r, msg, h);
1123 1238
 		}else{
1124 1239
 			BUG("eval_elem: to_port unknown (not in a onsend_route?)\n");
1125 1240
 		}
1126 1241
 		break;
1127 1242
 
1128 1243
 	case PROTO_O:
1129
-		ret=comp_num(e->op, msg->rcv.proto,
1130
-			     e->r_type, &e->r);
1244
+		ret=comp_num(e->op, msg->rcv.proto, e->r_type, &e->r, msg, h);
1131 1245
 		break;
1132 1246
 
1133 1247
 	case SNDPROTO_O:
1134 1248
 		snd_inf=get_onsend_info();
1135
-		if (snd_inf && snd_inf->send_sock){
1249
+		if (likely(snd_inf && snd_inf->send_sock)){
1136 1250
 			ret=comp_num(e->op, snd_inf->send_sock->proto,
1137
-				     e->r_type, &e->r);
1251
+							e->r_type, &e->r, msg, h);
1138 1252
 		}else{
1139 1253
 			BUG("eval_elem: snd_proto unknown (not in a onsend_route?)\n");
1140 1254
 		}
1141 1255
 		break;
1142 1256
 
1143 1257
 	case AF_O:
1144
-		ret=comp_num(e->op, (int)msg->rcv.src_ip.af,
1145
-			     e->r_type, &e->r);
1258
+		ret=comp_num(e->op, (int)msg->rcv.src_ip.af, e->r_type, &e->r, msg, h);
1146 1259
 		break;
1147 1260
 
1148 1261
 	case SNDAF_O:
1149 1262
 		snd_inf=get_onsend_info();
1150
-		if (snd_inf && snd_inf->send_sock){
1263
+		if (likely(snd_inf && snd_inf->send_sock)){
1151 1264
 			ret=comp_num(e->op, snd_inf->send_sock->address.af,
1152
-							e->r_type, &e->r);
1265
+							e->r_type, &e->r, msg, h);
1153 1266
 		}else{
1154 1267
 			BUG("eval_elem: snd_af unknown (not in a onsend_route?)\n");
1155 1268
 		}
... ...
@@ -1157,24 +1270,30 @@ inline static int eval_elem(struct run_act_ctx* h, struct expr* e,
1157 1270
 
1158 1271
 	case MSGLEN_O:
1159 1272
 		if ((snd_inf=get_onsend_info())!=0){
1160
-			ret=comp_num(e->op, (int)snd_inf->len,
1161
-					e->r_type, &e->r);
1273
+			ret=comp_num(e->op, (int)snd_inf->len, e->r_type, &e->r, msg, h);
1162 1274
 		}else{
1163
-			ret=comp_num(e->op, (int)msg->len,
1164
-					e->r_type, &e->r);
1275
+			ret=comp_num(e->op, (int)msg->len, e->r_type, &e->r, msg, h);
1165 1276
 		}
1166 1277
 		break;
1167 1278
 
1168 1279
 	case RETCODE_O:
1169
-		ret=comp_num(e->op, h->last_retcode, e->r_type, &e->r);
1280
+		ret=comp_num(e->op, h->last_retcode, e->r_type, &e->r, msg, h);
1170 1281
 		break;
1171 1282
 
1172 1283
 	case AVP_O:
1173
-		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r, msg);
1284
+		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r, msg, h);
1174 1285
 		break;
1175 1286
 
1176 1287
 	case SELECT_O:
1177
-		ret = comp_select(e->op, e->l.select, e->r_type, &e->r, msg);
1288
+		ret = comp_select(e->op, e->l.select, e->r_type, &e->r, msg, h);
1289
+		break;
1290
+
1291
+	case RVEXP_O:
1292
+		ret = comp_rve(e->op, e->l.param, e->r_type, &e->r, msg, h);
1293
+		break;
1294
+
1295
+	case PVAR_O:
1296
+		ret=comp_pvar(e->op, e->l.param, e->r_type, &e->r, msg, h);
1178 1297
 		break;
1179 1298
 
1180 1299
 	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 181
 			case DSTPORT_O:
161 182
 				DBG("dstport");
162 183
 				break;
163
-			case NUMBER_O:
184
+			case PROTO_O:
185
+				DBG("proto");
186
+				break;
187
+			case AF_O:
188
+				DBG("af");
189
+				break;
190
+			case MSGLEN_O:
191
+				DBG("msglen");
164 192
 				break;
165 193
 			case ACTION_O:
166 194
 				break;
167
-		        case AVP_ST:
168
-				DBG("attr");
195
+			case NUMBER_O:
169 196
 				break;
170
-		        case SELECT_ST:
171
-			        DBG("select");
197
+			case AVP_O:
198
+				DBG("avp");
199
+				break;
200
+			case SNDIP_O:
201
+				DBG("sndip");
202
+				break;
203
+			case SNDPORT_O:
204
+				DBG("sndport");
205
+				break;
206
+			case TOIP_O:
207
+				DBG("toip");
208
+				break;
209
+			case TOPORT_O:
210
+				DBG("toport");
211
+				break;
212
+			case SNDPROTO_O:
213
+				DBG("sndproto");
214
+				break;
215
+			case SNDAF_O:
216
+				DBG("sndaf");
217
+				break;
218
+			case RETCODE_O:
219
+				DBG("retcode");
220
+				break;
221
+			case SELECT_O:
222
+				DBG("select");
223
+				break;
224
+			case RVEXP_O:
225
+				DBG("rval");
172 226
 				break;
173 227
 
174 228
 			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 */