Browse code

- AVPs can be used in place of strings and integers in expressions (if (method == %method)) - Support for AVP assign statements ( %var1 = "value"; %var1 += "value2"; ) - Support for binary operators & and | in expressions - AVPs can be tested in expressions (if (%var1 == 4)) - fixed a bug in string comparisons in expressions - extended parameters of expression evaluation functions - fixed possible buffer overflow vulnerability in log("dfd") script function - default memory buffers enlarged - length of string is calculated in expression fixup - fixed bug in function printing route statements (traversed the list recursively several times)

Jan Janak authored on 30/11/2005 16:26:50
Showing 8 changed files
... ...
@@ -92,6 +92,8 @@ int do_action(struct action* a, struct sip_msg* msg)
92 92
 	struct sip_uri *u;
93 93
 	unsigned short port;
94 94
 	int proto;
95
+	unsigned short flags;
96
+	int_str name, value;
95 97
 
96 98
 	/* reset the value of error to E_UNSPEC so avoid unknowledgable
97 99
 	   functions to return with error (status<0) and not setting it
... ...
@@ -271,7 +273,7 @@ int do_action(struct action* a, struct sip_msg* msg)
271 273
 				ret=E_BUG;
272 274
 				break;
273 275
 			}
274
-			LOG(a->p1.number, a->p2.string);
276
+			LOG(a->p1.number, "%s", a->p2.string);
275 277
 			ret=1;
276 278
 			break;
277 279
 
... ...
@@ -675,6 +677,83 @@ int do_action(struct action* a, struct sip_msg* msg)
675 677
 			msg->force_send_socket=(struct socket_info*)a->p1.data;
676 678
 			ret=1; /* continue processing */
677 679
 			break;
680
+
681
+	        case ADD_T:
682
+	        case ASSIGN_T:
683
+			if (a->p2_type == STRING_ST) {
684
+				value.s = a->p2.str;
685
+				flags = a->p1.attr->type | AVP_VAL_STR;
686
+				name = a->p1.attr->name;
687
+				ret = 1;
688
+			} else if (a->p2_type == NUMBER_ST) {
689
+				value.n = a->p2.number;
690
+				flags = a->p1.attr->type;
691
+				name = a->p1.attr->name;
692
+				ret = 1;
693
+			} else if (a->p2_type == ACTION_ST) {
694
+				flags = a->p1.attr->type;
695
+				name = a->p1.attr->name;
696
+				if (&a->p2.data) {
697
+					value.n = run_actions((struct action*)a->p2.data, msg);
698
+				} else {
699
+					value.n = -1;
700
+				}
701
+				ret = value.n;
702
+			} else if(a->p2_type == EXPR_ST && a->p2.data) {
703
+				v = eval_expr((struct expr*)a->p2.data, msg);
704
+				if (v < 0) {
705
+					if (v == EXPR_DROP){ /* hack to quit on DROP*/
706
+						ret = 0;
707
+						break;
708
+					} else {
709
+						LOG(L_WARN,"WARNING: do_action: error in expression\n");
710
+					}
711
+				}
712
+				
713
+				flags = a->p1.attr->type;
714
+				name = a->p1.attr->name;
715
+				value.n = v;
716
+			} else if (a->p2_type == AVP_ST) {
717
+				struct search_state st;
718
+				avp_t* avp; 
719
+				
720
+				     /* If the action is assign then remove the old avp value before adding
721
+				      * new ones
722
+				      */
723
+				if ((unsigned char)a->type == ASSIGN_T) delete_avp(a->p1.attr->type, a->p1.attr->name);
724
+
725
+				avp = search_first_avp(a->p2.attr->type, a->p2.attr->name, &value, &st);
726
+				while(avp) {
727
+					     /* We take only the type of value and name from the source avp
728
+					      * and reset class and track flags
729
+					      */
730
+					flags = a->p1.attr->type | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
731
+					if (add_avp(flags, name, value) < 0) {
732
+						LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
733
+					 	ret=E_UNSPEC;
734
+						break;
735
+					}
736
+					avp = search_next_avp(&st, &value);
737
+				}
738
+				ret = 1;
739
+				break;
740
+			} else {
741
+				LOG(L_CRIT, "BUG: do_action: Bad right side of avp assignment\n");
742
+				ret=E_BUG;
743
+				break;
744
+			}
745
+
746
+			     /* If the action is assign then remove the old avp value before adding
747
+			      * new ones
748
+			      */
749
+			if ((unsigned char)a->type == ASSIGN_T) delete_avp(flags, name);
750
+			if (add_avp(flags, name, value) < 0) {
751
+				LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
752
+				ret=E_UNSPEC;
753
+				break;
754
+			}
755
+			break;
756
+
678 757
 		default:
679 758
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
680 759
 	}
... ...
@@ -91,7 +91,6 @@
91 91
 #include "ut.h"
92 92
 #include "dset.h"
93 93
 
94
-
95 94
 #include "config.h"
96 95
 #ifdef USE_TLS
97 96
 #include "tls/tls_config.h"
... ...
@@ -116,10 +115,10 @@ static int rt;  /* Type of route block for find_export */
116 115
 static str* str_tmp;
117 116
 static str s_tmp;
118 117
 static struct ip_addr* ip_tmp;
118
+static struct avp_spec* s_attr;
119 119
 
120 120
 static void warn(char* s);
121 121
 static struct socket_id* mk_listen_id(char*, int, int);
122
- 
123 122
 
124 123
 %}
125 124
 
... ...
@@ -132,6 +131,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
132 131
 	struct net* ipnet;
133 132
 	struct ip_addr* ipaddr;
134 133
 	struct socket_id* sockid;
134
+	struct avp_spec* attr;
135 135
 }
136 136
 
137 137
 /* terminals */
... ...
@@ -263,8 +263,13 @@ static struct socket_id* mk_listen_id(char*, int, int);
263 263
 %token MCAST_TTL
264 264
 %token TOS
265 265
 
266
-
267
-
266
+%token ATTR_MARK
267
+%token ATTR_FROM
268
+%token ATTR_TO
269
+%token ATTR_USER
270
+%token ATTR_DOMAIN
271
+%token ATTR_GLOBAL
272
+%token ADD
268 273
 
269 274
 /* operators */
270 275
 %nonassoc EQUAL
... ...
@@ -275,11 +280,12 @@ static struct socket_id* mk_listen_id(char*, int, int);
275 280
 %nonassoc LTE
276 281
 %nonassoc DIFF
277 282
 %nonassoc MATCH
278
-%left OR
279
-%left AND
280
-%left NOT
281
-%left PLUS
282
-%left MINUS
283
+%left LOG_OR
284
+%left LOG_AND
285
+%left BIN_OR
286
+%left BIN_AND 
287
+%left PLUS MINUS
288
+%right NOT
283 289
 
284 290
 /* values */
285 291
 %token <intval> NUMBER
... ...
@@ -305,7 +311,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
305 311
 
306 312
 /*non-terminals */
307 313
 %type <expr> exp exp_elem /*, condition*/
308
-%type <action> action actions cmd if_cmd stm exp_stm
314
+%type <action> action actions cmd if_cmd stm exp_stm assign_action
309 315
 %type <ipaddr> ipv4 ipv6 ipv6addr ip
310 316
 %type <ipnet> ipnet
311 317
 %type <strval> host
... ...
@@ -313,9 +319,12 @@ static struct socket_id* mk_listen_id(char*, int, int);
313 319
 %type <sockid>  id_lst
314 320
 %type <sockid>  phostport
315 321
 %type <intval> proto port
316
-%type <intval> equalop strop intop
322
+%type <intval> equalop strop intop binop
317 323
 %type <strval> host_sep
318 324
 %type <intval> uri_type
325
+%type <attr> attr_id
326
+%type <intval> class_id
327
+%type <intval> assign_op
319 328
 /*%type <route_el> rules;
320 329
   %type <route_el> rule;
321 330
 */
... ...
@@ -908,8 +917,8 @@ rule:	condition	actions CR {
908 917
 condition:	exp {$$=$1;}
909 918
 */
910 919
 
911
-exp:	exp AND exp 	{ $$=mk_exp(AND_OP, $1, $3); }
912
-	| exp OR  exp		{ $$=mk_exp(OR_OP, $1, $3);  }
920
+exp:	exp LOG_AND exp 	{ $$=mk_exp(LOGAND_OP, $1, $3); }
921
+	| exp LOG_OR  exp		{ $$=mk_exp(LOGOR_OP, $1, $3);  }
913 922
 	| NOT exp 			{ $$=mk_exp(NOT_OP, $2, 0);  }
914 923
 	| LPAREN exp RPAREN	{ $$=$2; }
915 924
 	| exp_elem			{ $$=$1; }
... ...
@@ -925,6 +934,10 @@ intop:	equalop	{$$=$1; }
925 934
 		| GTE	{$$=GTE_OP; }
926 935
 		| LTE	{$$=LTE_OP; }
927 936
 		;
937
+
938
+binop : BIN_OR { $$= BINOR_OP; }
939
+      | BIN_AND { $$ = BINAND_OP; }
940
+;
928 941
 		
929 942
 strop:	equalop	{$$=$1; }
930 943
 		| MATCH	{$$=MATCH_OP; }
... ...
@@ -935,82 +948,74 @@ uri_type:	URI			{$$=URI_O;}
935 948
 		|	TO_URI		{$$=TO_URI_O;}
936 949
 		;
937 950
 
938
-exp_elem:	METHOD strop STRING	{$$= mk_elem(	$2, STRING_ST, 
939
-													METHOD_O, $3);
940
-									}
941
-		| METHOD strop  ID	{$$ = mk_elem(	$2, STRING_ST,
942
-											METHOD_O, $3); 
943
-				 			}
951
+exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
952
+                | METHOD strop attr_id  {$$ = mk_elem($2, METHOD_O, 0, AVP_ST, $3); }
953
+		| METHOD strop  ID	{$$ = mk_elem($2, METHOD_O, 0, STRING_ST,$3); }
944 954
 		| METHOD strop error { $$=0; yyerror("string expected"); }
945 955
 		| METHOD error	{ $$=0; yyerror("invalid operator,"
946 956
 										"== , !=, or =~ expected");
947 957
 						}
948
-		| uri_type strop STRING	{$$ = mk_elem(	$2, STRING_ST,
949
-												$1, $3); 
950
-				 				}
951
-		| uri_type strop host 	{$$ = mk_elem(	$2, STRING_ST,
952
-											$1, $3); 
953
-				 			}
954
-		| uri_type equalop MYSELF	{ $$=mk_elem(	$2, MYSELF_ST,
955
-													$1, 0);
956
-								}
958
+		| uri_type strop STRING	{$$ = mk_elem($2, $1, 0, STRING_ST, $3); }
959
+                | uri_type strop host 	{$$ = mk_elem($2, $1, 0, STRING_ST, $3); }
960
+                | uri_type strop attr_id {$$ = mk_elem($2, $1, 0, AVP_ST, $3); }
961
+                | uri_type equalop MYSELF {$$=mk_elem($2, $1, 0, MYSELF_ST, 0); }
957 962
 		| uri_type strop error { $$=0; yyerror("string or MYSELF expected"); }
958 963
 		| uri_type error	{ $$=0; yyerror("invalid operator,"
959 964
 									" == , != or =~ expected");
960 965
 					}
961
-		| SRCPORT intop NUMBER	{ $$=mk_elem(	$2, NUMBER_ST,
962
-												SRCPORT_O, (void *) $3 ); }
966
+		| SRCPORT intop NUMBER	{ $$=mk_elem($2, SRCPORT_O, 0, NUMBER_ST, (void*)$3 ); }
967
+                | SRCPORT intop attr_id { $$=mk_elem($2, SRCPORT_O, 0, AVP_ST, (void*)$3 ); }
963 968
 		| SRCPORT intop error { $$=0; yyerror("number expected"); }
964 969
 		| SRCPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
965
-		| DSTPORT intop NUMBER	{ $$=mk_elem(	$2, NUMBER_ST,
966
-												DSTPORT_O, (void *) $3 ); }
970
+
971
+		| DSTPORT intop NUMBER	{ $$=mk_elem($2, DSTPORT_O, 0, NUMBER_ST, (void*)$3 ); }
972
+		| DSTPORT intop attr_id	{ $$=mk_elem($2, DSTPORT_O, 0, AVP_ST, (void*)$3 ); }
967 973
 		| DSTPORT intop error { $$=0; yyerror("number expected"); }
968 974
 		| DSTPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
969
-		| PROTO intop proto	{ $$=mk_elem(	$2, NUMBER_ST,
970
-												PROTO_O, (void *) $3 ); }
975
+
976
+		| PROTO intop proto	{ $$=mk_elem($2, PROTO_O, 0, NUMBER_ST, (void*)$3 ); }
977
+		| PROTO intop attr_id	{ $$=mk_elem($2, PROTO_O, 0, AVP_ST, (void*)$3 ); }
971 978
 		| PROTO intop error { $$=0;
972 979
 								yyerror("protocol expected (udp, tcp or tls)");
973 980
 							}
974 981
 		| PROTO error { $$=0; yyerror("equal/!= operator expected"); }
975
-		| AF intop NUMBER	{ $$=mk_elem(	$2, NUMBER_ST,
976
-												AF_O, (void *) $3 ); }
982
+
983
+		| AF intop NUMBER	{ $$=mk_elem($2, AF_O, 0, NUMBER_ST,(void *) $3 ); }
984
+		| AF intop attr_id	{ $$=mk_elem($2, AF_O, 0, AVP_ST,(void *) $3 ); }
977 985
 		| AF intop error { $$=0; yyerror("number expected"); }
978 986
 		| AF error { $$=0; yyerror("equal/!= operator expected"); }
979
-		| MSGLEN intop NUMBER	{ $$=mk_elem(	$2, NUMBER_ST,
980
-												MSGLEN_O, (void *) $3 ); }
981
-		| MSGLEN intop MAX_LEN	{ $$=mk_elem(	$2, NUMBER_ST,
982
-												MSGLEN_O, (void *) BUF_SIZE); }
987
+
988
+		| MSGLEN intop NUMBER	{ $$=mk_elem($2, MSGLEN_O, 0, NUMBER_ST, (void *) $3 ); }
989
+		| MSGLEN intop attr_id	{ $$=mk_elem($2, MSGLEN_O, 0, AVP_ST, (void *) $3 ); }
990
+		| MSGLEN intop MAX_LEN	{ $$=mk_elem($2, MSGLEN_O, 0, NUMBER_ST, (void *) BUF_SIZE); }
983 991
 		| MSGLEN intop error { $$=0; yyerror("number expected"); }
984 992
 		| MSGLEN error { $$=0; yyerror("equal/!= operator expected"); }
985
-		| SRCIP equalop ipnet	{ $$=mk_elem(	$2, NET_ST,
986
-												SRCIP_O, $3);
987
-								}
993
+
994
+		| SRCIP equalop ipnet	{ $$=mk_elem($2, SRCIP_O, 0, NET_ST, $3); }
988 995
 		| SRCIP strop STRING	{	s_tmp.s=$3;
989 996
 									s_tmp.len=strlen($3);
990 997
 									ip_tmp=str2ip(&s_tmp);
991 998
 									if (ip_tmp==0)
992 999
 										ip_tmp=str2ip6(&s_tmp);
993 1000
 									if (ip_tmp){
994
-										$$=mk_elem(	$2, NET_ST, SRCIP_O,
1001
+										$$=mk_elem(	$2, SRCIP_O, 0, NET_ST,
995 1002
 												mk_net_bitlen(ip_tmp, 
996 1003
 														ip_tmp->len*8) );
997 1004
 									}else{
998
-										$$=mk_elem(	$2, STRING_ST,
999
-												SRCIP_O, $3);
1005
+										$$=mk_elem(	$2, SRCIP_O, 0, STRING_ST,
1006
+												$3);
1000 1007
 									}
1001 1008
 								}
1002
-		| SRCIP strop host	{ $$=mk_elem(	$2, STRING_ST,
1003
-												SRCIP_O, $3);
1004
-								}
1005
-		| SRCIP equalop MYSELF  { $$=mk_elem(	$2, MYSELF_ST,
1006
-												SRCIP_O, 0);
1009
+		| SRCIP strop host	{ $$=mk_elem(	$2, SRCIP_O, 0, STRING_ST, $3); }
1010
+		| SRCIP equalop MYSELF  { $$=mk_elem(	$2, SRCIP_O, 0, MYSELF_ST,
1011
+												0);
1007 1012
 								}
1008 1013
 		| SRCIP strop error { $$=0; yyerror( "ip address or hostname"
1009 1014
 						 "expected" ); }
1010 1015
 		| SRCIP error  { $$=0; 
1011 1016
 						 yyerror("invalid operator, ==, != or =~ expected");}
1012
-		| DSTIP equalop ipnet	{ $$=mk_elem(	$2, NET_ST,
1013
-												DSTIP_O, $3);
1017
+		| DSTIP equalop ipnet	{ $$=mk_elem(	$2, DSTIP_O, 0, NET_ST,
1018
+												(void*)$3);
1014 1019
 								}
1015 1020
 		| DSTIP strop STRING	{	s_tmp.s=$3;
1016 1021
 									s_tmp.len=strlen($3);
... ...
@@ -1018,41 +1023,49 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem(	$2, STRING_ST,
1018 1023
 									if (ip_tmp==0)
1019 1024
 										ip_tmp=str2ip6(&s_tmp);
1020 1025
 									if (ip_tmp){
1021
-										$$=mk_elem(	$2, NET_ST, DSTIP_O,
1026
+										$$=mk_elem(	$2, DSTIP_O, 0, NET_ST,
1022 1027
 												mk_net_bitlen(ip_tmp, 
1023 1028
 														ip_tmp->len*8) );
1024 1029
 									}else{
1025
-										$$=mk_elem(	$2, STRING_ST,
1026
-												DSTIP_O, $3);
1030
+										$$=mk_elem(	$2, DSTIP_O, 0, STRING_ST,
1031
+												$3);
1027 1032
 									}
1028 1033
 								}
1029
-		| DSTIP strop host	{ $$=mk_elem(	$2, STRING_ST,
1030
-												DSTIP_O, $3);
1034
+		| DSTIP strop host	{ $$=mk_elem(	$2, DSTIP_O, 0, STRING_ST,
1035
+												$3);
1031 1036
 								}
1032
-		| DSTIP equalop MYSELF  { $$=mk_elem(	$2, MYSELF_ST,
1033
-												DSTIP_O, 0);
1037
+		| DSTIP equalop MYSELF  { $$=mk_elem(	$2, DSTIP_O, 0, MYSELF_ST,
1038
+												0);
1034 1039
 								}
1035 1040
 		| DSTIP strop error { $$=0; yyerror( "ip address or hostname"
1036 1041
 						 			"expected" ); }
1037 1042
 		| DSTIP error { $$=0; 
1038 1043
 						yyerror("invalid operator, ==, != or =~ expected");}
1039
-		| MYSELF equalop uri_type	{ $$=mk_elem(	$2, MYSELF_ST,
1040
-													$3, 0);
1044
+
1045
+		| MYSELF equalop uri_type	{ $$=mk_elem(	$2, $3, 0, MYSELF_ST,
1046
+												       0);
1041 1047
 								}
1042
-		| MYSELF equalop SRCIP  { $$=mk_elem(	$2, MYSELF_ST,
1043
-												SRCIP_O, 0);
1048
+		| MYSELF equalop SRCIP  { $$=mk_elem(	$2, SRCIP_O, 0, MYSELF_ST,
1049
+												0);
1044 1050
 								}
1045
-		| MYSELF equalop DSTIP  { $$=mk_elem(	$2, MYSELF_ST,
1046
-												DSTIP_O, 0);
1051
+                | MYSELF equalop DSTIP  { $$=mk_elem(	$2, DSTIP_O, 0, MYSELF_ST,
1052
+							0);
1047 1053
 								}
1048 1054
 		| MYSELF equalop error {	$$=0; 
1049 1055
 									yyerror(" URI, SRCIP or DSTIP expected"); }
1050 1056
 		| MYSELF error	{ $$=0; 
1051 1057
 							yyerror ("invalid operator, == or != expected");
1052 1058
 						}
1053
-		| exp_stm			{ $$=mk_elem( NO_OP, ACTIONS_ST, ACTION_O, $1 );  }
1054
-		| NUMBER		{$$=mk_elem( NO_OP, NUMBER_ST, NUMBER_O, (void*)$1 ); }
1055
-	;
1059
+		| exp_stm			{ $$=mk_elem( NO_OP, ACTION_O, 0, ACTIONS_ST, $1);  }
1060
+		| NUMBER		{$$=mk_elem( NO_OP, NUMBER_O, 0, NUMBER_ST, (void*)$1 ); }
1061
+
1062
+		| attr_id		{$$=mk_elem( NO_OP, AVP_ST, (void*)$1, 0, 0); }
1063
+		| attr_id strop STRING	{$$=mk_elem( $2, AVP_ST, (void*)$1, STRING_ST, $3); }
1064
+		| attr_id intop NUMBER	{$$=mk_elem( $2, AVP_ST, (void*)$1, NUMBER_ST, (void*)$3); }
1065
+		| attr_id binop NUMBER	{$$=mk_elem( $2, AVP_ST, (void*)$1, NUMBER_ST, (void*)$3); }
1066
+                | attr_id strop attr_id {$$=mk_elem( $2, AVP_ST, (void*)$1, AVP_ST, (void*)$3); }
1067
+;
1068
+
1056 1069
 
1057 1070
 ipnet:	ip SLASH ip	{ $$=mk_net($1, $3); } 
1058 1071
 	| ip SLASH NUMBER 	{	if (($3<0) || ($3>$1->len*8)){
... ...
@@ -1097,6 +1110,7 @@ host:	ID				{ $$=$1; }
1097 1110
 
1098 1111
 exp_stm:	cmd						{ $$=$1; }
1099 1112
 		|	if_cmd					{ $$=$1; }
1113
+                |       assign_action { $$ = $1; }
1100 1114
 		|	LBRACE actions RBRACE	{ $$=$2; }
1101 1115
 	;
1102 1116
 
... ...
@@ -1111,6 +1125,7 @@ actions:	actions action	{$$=append_action($1, $2); }
1111 1125
 
1112 1126
 action:		cmd SEMICOLON {$$=$1;}
1113 1127
 		| if_cmd {$$=$1;}
1128
+                | assign_action SEMICOLON {$$=$1}
1114 1129
 		| SEMICOLON /* null action */ {$$=0;}
1115 1130
 		| cmd error { $$=0; yyerror("bad command: missing ';'?"); }
1116 1131
 	;
... ...
@@ -1133,6 +1148,61 @@ if_cmd:		IF exp stm				{ $$=mk_action3( IF_T,
1133 1148
 									}
1134 1149
 	;
1135 1150
 
1151
+class_id : LBRACK ATTR_USER RBRACK { $$ = AVP_CLASS_USER; }
1152
+         | LBRACK ATTR_DOMAIN RBRACK { $$ = AVP_CLASS_DOMAIN; }
1153
+         | LBRACK ATTR_GLOBAL RBRACK { $$ = AVP_CLASS_GLOBAL; }
1154
+;
1155
+
1156
+attr_id : ATTR_MARK ID { s_attr = (struct avp_spec*)pkg_malloc(sizeof(struct avp_spec));
1157
+                         if (!s_attr) { LOG(L_CRIT, "No memory left"); return 0;}
1158
+                         s_attr->type = AVP_NAME_STR;                   
1159
+                         s_attr->name.s.s = $2; s_attr->name.s.len = strlen($2); 
1160
+                         $$ = s_attr; 
1161
+                       }
1162
+        | ATTR_MARK class_id DOT ID { s_attr = (struct avp_spec*)pkg_malloc(sizeof(struct avp_spec));
1163
+                                      if (!s_attr) { LOG(L_CRIT, "No memory left"); return 0;}
1164
+                                      s_attr->type = AVP_NAME_STR | $2;
1165
+                                      s_attr->name.s.s = $4; s_attr->name.s.len = strlen($4); 
1166
+                                      $$ = s_attr; 
1167
+                                    }
1168
+        | ATTR_MARK ATTR_FROM DOT ID { s_attr = (struct avp_spec*)pkg_malloc(sizeof(struct avp_spec));
1169
+                                       if (!s_attr) { LOG(L_CRIT, "No memory left"); return 0;}
1170
+                                       s_attr->type = AVP_NAME_STR | AVP_TRACK_FROM;
1171
+                                       s_attr->name.s.s = $4; s_attr->name.s.len = strlen($4);
1172
+                                       $$ = s_attr;
1173
+                                     }
1174
+        | ATTR_MARK ATTR_TO DOT ID { s_attr = (struct avp_spec*)pkg_malloc(sizeof(struct avp_spec));
1175
+                                     if (!s_attr) { LOG(L_CRIT, "No memory left"); return 0;}
1176
+                                     s_attr->type = AVP_NAME_STR | AVP_TRACK_TO; 
1177
+                                     s_attr->name.s.s = $4; s_attr->name.s.len = strlen($4); 
1178
+                                     $$ = s_attr;
1179
+                                   }
1180
+        | ATTR_MARK ATTR_FROM class_id DOT ID { s_attr = (struct avp_spec*)pkg_malloc(sizeof(struct avp_spec));
1181
+                                               if (!s_attr) { LOG(L_CRIT, "No memory left"); return 0;}
1182
+                                               s_attr->type = AVP_NAME_STR | AVP_TRACK_FROM | $3; 
1183
+                                               s_attr->name.s.s = $5; 
1184
+                                               s_attr->name.s.len = strlen($5);
1185
+                                               $$ = s_attr;
1186
+                                              }
1187
+        | ATTR_MARK ATTR_TO class_id DOT ID { s_attr = (struct avp_spec*)pkg_malloc(sizeof(struct avp_spec));
1188
+                                              if (!s_attr) { LOG(L_CRIT, "No memory left"); return 0;}
1189
+                                              s_attr->type = AVP_NAME_STR | AVP_TRACK_TO | $3;
1190
+                                              s_attr->name.s.s = $5; s_attr->name.s.len = strlen($5);
1191
+                                             $$ = s_attr;
1192
+                                            }
1193
+;
1194
+
1195
+assign_op : ADD { $$ = ADD_T; }
1196
+          | EQUAL { $$ = ASSIGN_T; }
1197
+;
1198
+
1199
+assign_action:   attr_id assign_op STRING  { $$=mk_action($2, AVP_ST, STRING_ST, $1, $3); }
1200
+               | attr_id assign_op NUMBER  { $$=mk_action($2, AVP_ST, NUMBER_ST, $1, (void*)$3); }
1201
+               | attr_id assign_op cmd     { $$=mk_action($2, AVP_ST, ACTION_ST, $1, $3); }
1202
+               | attr_id assign_op attr_id { $$=mk_action($2, AVP_ST, AVP_ST, $1, $3); }
1203
+               | attr_id assign_op LPAREN exp RPAREN { $$ = mk_action($2, AVP_ST, EXPR_ST, $1, $4); }
1204
+;
1205
+
1136 1206
 cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
1137 1207
 														STRING_ST,
1138 1208
 														NUMBER_ST,
... ...
@@ -119,10 +119,10 @@
119 119
 #define SRV_MAX_PREFIX_LEN SRV_TLS_PREFIX_LEN
120 120
 
121 121
 /*used only if PKG_MALLOC is defined*/
122
-#define PKG_MEM_POOL_SIZE 1024*1024
122
+#define PKG_MEM_POOL_SIZE 4*1024*1024
123 123
 
124 124
 /*used if SH_MEM is defined*/
125
-#define SHM_MEM_SIZE 32
125
+#define SHM_MEM_SIZE 128
126 126
 
127 127
 #define TIMER_TICK 1
128 128
 
... ...
@@ -142,25 +142,25 @@ int str2facility(char *s);
142 142
 					else { \
143 143
 						switch(lev){ \
144 144
 							case L_CRIT: \
145
-								syslog(LOG_CRIT|log_facility, fmt, ##args); \
145
+								syslog(LOG_CRIT|log_facility, "CRIT: " fmt, ##args); \
146 146
 								break; \
147 147
 							case L_ALERT: \
148
-								syslog(LOG_ALERT|log_facility, fmt, ##args); \
148
+								syslog(LOG_ALERT|log_facility, "ALERT: " fmt, ##args); \
149 149
 								break; \
150 150
 							case L_ERR: \
151
-								syslog(LOG_ERR|log_facility, fmt, ##args); \
151
+								syslog(LOG_ERR|log_facility, "ERROR: " fmt, ##args); \
152 152
 								break; \
153 153
 							case L_WARN: \
154
-								syslog(LOG_WARNING|log_facility, fmt, ##args);\
154
+								syslog(LOG_WARNING|log_facility, "WARNING: " fmt, ##args);\
155 155
 								break; \
156 156
 							case L_NOTICE: \
157
-								syslog(LOG_NOTICE|log_facility, fmt, ##args); \
157
+								syslog(LOG_NOTICE|log_facility, "NOTICE: " fmt, ##args); \
158 158
 								break; \
159 159
 							case L_INFO: \
160
-								syslog(LOG_INFO|log_facility, fmt, ##args); \
160
+								syslog(LOG_INFO|log_facility, "INFO: " fmt, ##args); \
161 161
 								break; \
162 162
 							case L_DBG: \
163
-								syslog(LOG_DEBUG|log_facility, fmt, ##args); \
163
+								syslog(LOG_DEBUG|log_facility, "DEBUG: " fmt, ##args); \
164 164
 								break; \
165 165
 						} \
166 166
 					} \
... ...
@@ -126,7 +126,7 @@
126 126
 #include "tls/tls_init.h"
127 127
 #endif
128 128
 #endif
129
-
129
+#include "usr_avp.h"
130 130
 
131 131
 
132 132
 #include "stats.h"
... ...
@@ -1568,6 +1568,8 @@ try_again:
1568 1568
 		goto error;
1569 1569
 	}
1570 1570
 	
1571
+	if (init_avps()<0) goto error;
1572
+
1571 1573
 #ifdef USE_TCP
1572 1574
 	if (!tcp_disable){
1573 1575
 		/*init tcp*/
... ...
@@ -92,8 +92,8 @@ static int fix_expr(struct expr* exp)
92 92
 	}
93 93
 	if (exp->type==EXP_T){
94 94
 		switch(exp->op){
95
-			case AND_OP:
96
-			case OR_OP:
95
+			case LOGAND_OP:
96
+			case LOGOR_OP:
97 97
 						if ((ret=fix_expr(exp->l.expr))!=0)
98 98
 							return ret;
99 99
 						ret=fix_expr(exp->r.expr);
... ...
@@ -107,7 +107,11 @@ static int fix_expr(struct expr* exp)
107 107
 		}
108 108
 	}else if (exp->type==ELEM_T){
109 109
 			if (exp->op==MATCH_OP){
110
-				if (exp->subtype==STRING_ST){
110
+				     /* right side either has to be string, in which case
111
+				      * we turn it into regular expression, or it is regular
112
+				      * expression already. In that case we do nothing
113
+				      */
114
+				if (exp->r_type==STRING_ST){
111 115
 					re=(regex_t*)pkg_malloc(sizeof(regex_t));
112 116
 					if (re==0){
113 117
 						LOG(L_CRIT, "ERROR: fix_expr: memory allocation"
... ...
@@ -123,19 +127,34 @@ static int fix_expr(struct expr* exp)
123 127
 					}
124 128
 					/* replace the string with the re */
125 129
 					pkg_free(exp->r.param);
126
-					exp->r.param=re;
127
-					exp->subtype=RE_ST;
128
-				}else if (exp->subtype!=RE_ST){
130
+					exp->r.re=re;
131
+					exp->r_type=RE_ST;
132
+				}else if (exp->r_type!=RE_ST && exp->r_type != AVP_ST){
129 133
 					LOG(L_CRIT, "BUG: fix_expr : invalid type for match\n");
130 134
 					return E_BUG;
131 135
 				}
132 136
 			}
133
-			if (exp->l.operand==ACTION_O){
137
+			if (exp->l_type==ACTION_O){
134 138
 				ret=fix_actions((struct action*)exp->r.param);
135 139
 				if (ret!=0){
136 140
 					LOG(L_CRIT, "ERROR: fix_expr : fix_actions error\n");
137 141
 					return ret;
138 142
 				}
143
+			}
144
+			     /* Calculate lengths of strings */
145
+			if (exp->l_type==STRING_ST) {
146
+				int len;
147
+				if (exp->l.string) len = strlen(exp->l.string);
148
+				else len = 0;
149
+				exp->l.str.s = exp->l.string;
150
+				exp->l.str.len = len;
151
+			}
152
+			if (exp->r_type==STRING_ST) {
153
+				int len;
154
+				if (exp->l.string) len = strlen(exp->r.string);
155
+				else len = 0;
156
+				exp->r.str.s = exp->r.string;
157
+				exp->r.str.len = len;
139 158
 			}
140 159
 			ret=0;
141 160
 	}
... ...
@@ -230,6 +249,37 @@ static int fix_actions(struct action* a)
230 249
 						return ret;
231 250
 				}
232 251
 				break;
252
+
253
+		        case ASSIGN_T:
254
+		        case ADD_T:
255
+				if (t->p1_type != AVP_ST) {
256
+					LOG(L_CRIT, "BUG: fix_actions: Invalid left side of assignment\n");
257
+					return E_BUG;
258
+				}
259
+				if (t->p1.attr->type & AVP_CLASS_DOMAIN) {
260
+					LOG(L_ERR, "ERROR: You cannot change domain attributes from the script, they are read-only\n");
261
+					return E_BUG;
262
+				} else if (t->p1.attr->type & AVP_CLASS_GLOBAL) {
263
+					LOG(L_ERR, "ERROR: You cannot change global attributes from the script, they are read-only\n");
264
+					return E_BUG;
265
+				}
266
+
267
+				if (t->p2_type == ACTION_ST && t->p2.data) {
268
+					if ((ret = fix_actions((struct action*)t->p2.data)) < 0) {
269
+						return ret;
270
+					}
271
+				} else if (t->p2_type == EXPR_ST && t->p2.data) {
272
+					if ((ret = fix_expr((struct expr*)t->p2.data)) < 0) {
273
+						return ret;
274
+					}
275
+				} else if (t->p2_type == STRING_ST) {
276
+					int len;
277
+					len = strlen(t->p2.data);
278
+					t->p2.str.s = t->p2.data;
279
+					t->p2.str.len = len;
280
+				}
281
+				break;
282
+
233 283
 			case MODULE_T:
234 284
 				if ((mod=find_module(t->p1.data, &cmd))!=0){
235 285
 					DBG("fixing %s %s\n", mod->path, cmd->name);
... ...
@@ -280,78 +330,113 @@ static int fix_actions(struct action* a)
280 330
 }
281 331
 
282 332
 
283
-inline static int comp_no( int port, void *param, int op, int subtype )
333
+/* Compare parameters as ordinary numbers
334
+ *
335
+ * Left and right operands can be either numbers or
336
+ * attributes. If either of the attributes if of string type then the length of
337
+ * its value will be used.
338
+ */
339
+inline static int comp_num(int op, long left, int rtype, union exp_op* r)
284 340
 {
341
+	int_str val;
342
+	avp_t* avp;
343
+	long right;
285 344
 	
286
-	if (subtype!=NUMBER_ST) {
287
-		LOG(L_CRIT, "BUG: comp_no: number expected: %d\n", subtype );
345
+	if (rtype == AVP_ST) {
346
+		avp = search_first_avp(r->attr->type, r->attr->name, &val, 0);
347
+		if (avp && !(avp->flags & AVP_VAL_STR)) right = val.n;
348
+		else return 0; /* Always fail */
349
+	} else if (rtype == NUMBER_ST) {
350
+		right = r->intval;
351
+	} else {
352
+		LOG(L_CRIT, "BUG: comp_num: Invalid right operand (%d)\n", rtype);
288 353
 		return E_BUG;
289 354
 	}
355
+
290 356
 	switch (op){
291
-		case EQUAL_OP:
292
-			return port==(long)param;
293
-		case DIFF_OP:
294
-			return port!=(long)param;
295
-		case GT_OP:
296
-			return port>(long)param;
297
-		case LT_OP:
298
-			return port<(long)param;
299
-		case GTE_OP:
300
-			return port>=(long)param;
301
-		case LTE_OP:
302
-			return port<=(long)param;
303
-		default:
304
-		LOG(L_CRIT, "BUG: comp_no: unknown operator: %d\n", op );
357
+	case EQUAL_OP: return (long)left == (long)right;
358
+	case DIFF_OP:  return (long)left != (long)right;
359
+	case GT_OP:    return (long)left >  (long)right;
360
+	case LT_OP:    return (long)left <  (long)right;
361
+	case GTE_OP:   return (long)left >= (long)right;
362
+	case LTE_OP:   return (long)left <= (long)right;
363
+	default:
364
+		LOG(L_CRIT, "BUG: comp_num: unknown operator: %d\n", op);
305 365
 		return E_BUG;
306 366
 	}
307 367
 }
308 368
 
309
-/* eval_elem helping function, returns str op param */
310
-inline static int comp_strstr(str* str, void* param, int op, int subtype)
369
+/*
370
+ * Compare given string "left" with right side of expression
371
+ */
372
+inline static int comp_str(int op, str* left, int rtype, union exp_op* r)
311 373
 {
374
+	str* right;
375
+	int_str val;
376
+	avp_t* avp;
312 377
 	int ret;
313 378
 	char backup;
314 379
 	
380
+	if (rtype == AVP_ST) {
381
+		avp = search_first_avp(r->attr->type, r->attr->name, &val, 0);
382
+		if (avp && (avp->flags & AVP_VAL_STR)) right = &val.s;
383
+		else return 0;
384
+	} else if ((op == MATCH_OP && rtype == RE_ST)) {
385
+	} else if (op != MATCH_OP && rtype == STRING_ST) {
386
+		right = &r->str;
387
+	} else {
388
+		LOG(L_CRIT, "BUG: comp_str: Bad type %d, "
389
+		    "string or RE expected\n", rtype);
390
+		goto error;
391
+	}
392
+
315 393
 	ret=-1;
316 394
 	switch(op){
317 395
 		case EQUAL_OP:
318
-			if (subtype!=STRING_ST){
319
-				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
320
-						"string expected\n", subtype);
321
-				goto error;
322
-			}
323
-			ret=(strncasecmp(str->s, (char*)param, str->len)==0);
396
+			if (left->len != right->len) return 0;
397
+			ret=(strncasecmp(left->s, right->s, left->len)==0);
324 398
 			break;
325 399
 		case DIFF_OP:
326
-			if (subtype!=STRING_ST){
327
-				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
328
-						"string expected\n", subtype);
329
-				goto error;
330
-			}
331
-			ret=(strncasecmp(str->s, (char*)param, str->len)!=0);
400
+			if (left->len != right->len) return 1;
401
+			ret = (strncasecmp(left->s, right->s, left->len)!=0);
332 402
 			break;
333 403
 		case MATCH_OP:
334
-			if (subtype!=RE_ST){
335
-				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
336
-						" RE expected\n", subtype);
337
-				goto error;
404
+			     /* this is really ugly -- we put a temporary zero-terminating
405
+			      * character in the original string; that's because regexps
406
+			      * take 0-terminated strings and our messages are not
407
+			      * zero-terminated; it should not hurt as long as this function
408
+			      * is applied to content of pkg mem, which is always the case
409
+			      * with calls from route{}; the same goes for fline in reply_route{};
410
+			      *
411
+			      * also, the received function should always give us an extra
412
+			      * character, into which we can put the 0-terminator now;
413
+			      * an alternative would be allocating a new piece of memory,
414
+			      * which might be too slow
415
+			      * -jiri
416
+			      *
417
+			      * janakj: AVPs are zero terminated too so this is not problem either
418
+			      */
419
+			backup=left->s[left->len];
420
+			left->s[left->len]='\0';
421
+			if (rtype == AVP_ST) {
422
+				regex_t* re;
423
+				     /* For AVPs we need to compile the RE on the fly */
424
+				re=(regex_t*)pkg_malloc(sizeof(regex_t));
425
+				if (re==0){
426
+					LOG(L_CRIT, "ERROR: comp_strstr: memory allocation"
427
+					    " failure\n");
428
+					goto error;
429
+				}
430
+				if (regcomp(re, right->s, REG_EXTENDED|REG_NOSUB|REG_ICASE)) {
431
+					pkg_free(re);
432
+					goto error;
433
+				}				
434
+				ret=(regexec(re, left->s, 0, 0, 0)==0);
435
+				pkg_free(re);
436
+			} else {
437
+				ret=(regexec(r->re, left->s, 0, 0, 0)==0);
338 438
 			}
339
-		/* this is really ugly -- we put a temporary zero-terminating
340
-		 * character in the original string; that's because regexps
341
-         * take 0-terminated strings and our messages are not
342
-         * zero-terminated; it should not hurt as long as this function
343
-		 * is applied to content of pkg mem, which is always the case
344
-		 * with calls from route{}; the same goes for fline in reply_route{};
345
-         *
346
-         * also, the received function should always give us an extra
347
-         * character, into which we can put the 0-terminator now;
348
-         * an alternative would be allocating a new piece of memory,
349
-         * which might be too slow
350
-         * -jiri
351
-         */
352
-			backup=str->s[str->len];str->s[str->len]=0;
353
-			ret=(regexec((regex_t*)param, str->s, 0, 0, 0)==0);
354
-			str->s[str->len]=backup;
439
+			left->s[left->len] = backup;
355 440
 			break;
356 441
 		default:
357 442
 			LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
... ...
@@ -363,39 +448,40 @@ error:
363 448
 	return -1;
364 449
 }
365 450
 
451
+
366 452
 /* eval_elem helping function, returns str op param */
367
-inline static int comp_str(char* str, void* param, int op, int subtype)
453
+inline static int comp_string(int op, char* left, int rtype, union exp_op* r)
368 454
 {
369 455
 	int ret;
370 456
 	
371 457
 	ret=-1;
372 458
 	switch(op){
373 459
 		case EQUAL_OP:
374
-			if (subtype!=STRING_ST){
375
-				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
376
-						"string expected\n", subtype);
460
+			if (rtype!=STRING_ST){
461
+				LOG(L_CRIT, "BUG: comp_string: bad type %d, "
462
+						"string expected\n", rtype);
377 463
 				goto error;
378 464
 			}
379
-			ret=(strcasecmp(str, (char*)param)==0);
465
+			ret=(strcasecmp(left, r->str.s)==0);
380 466
 			break;
381 467
 		case DIFF_OP:
382
-			if (subtype!=STRING_ST){
383
-				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
384
-						"string expected\n", subtype);
468
+			if (rtype!=STRING_ST){
469
+				LOG(L_CRIT, "BUG: comp_string: bad type %d, "
470
+						"string expected\n", rtype);
385 471
 				goto error;
386 472
 			}
387
-			ret=(strcasecmp(str, (char*)param)!=0);
473
+			ret=(strcasecmp(left, r->str.s)!=0);
388 474
 			break;
389 475
 		case MATCH_OP:
390
-			if (subtype!=RE_ST){
391
-				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
392
-						" RE expected\n", subtype);
476
+			if (rtype!=RE_ST){
477
+				LOG(L_CRIT, "BUG: comp_string: bad type %d, "
478
+						" RE expected\n", rtype);
393 479
 				goto error;
394 480
 			}
395
-			ret=(regexec((regex_t*)param, str, 0, 0, 0)==0);
481
+			ret=(regexec(r->re, left, 0, 0, 0)==0);
396 482
 			break;
397 483
 		default:
398
-			LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
484
+			LOG(L_CRIT, "BUG: comp_string: unknown op %d\n", op);
399 485
 			goto error;
400 486
 	}
401 487
 	return ret;
... ...
@@ -405,6 +491,42 @@ error:
405 491
 }
406 492
 
407 493
 
494
+inline static int comp_avp(int op, avp_spec_t* spec, int rtype, union exp_op* r)
495
+{
496
+	avp_t* avp;
497
+	int_str val;
498
+
499
+	avp = search_first_avp(spec->type, spec->name, &val, 0);
500
+	if (!avp) return 0;
501
+
502
+	switch(op) {
503
+	case NO_OP:
504
+		if (avp->flags & AVP_VAL_STR) {
505
+			return val.s.len;
506
+		} else {
507
+			return val.n != 0;
508
+		}
509
+		break;
510
+
511
+	case BINOR_OP:
512
+		return val.n | r->intval;
513
+		break;
514
+
515
+	case BINAND_OP:
516
+		return val.n & r->intval;
517
+		break;
518
+	}
519
+
520
+	if (avp->flags & AVP_VAL_STR) {
521
+		return comp_str(op, &val.s, rtype, r);
522
+	} else {
523
+		return comp_num(op, val.n, rtype, r);
524
+	}
525
+}
526
+
527
+
528
+
529
+
408 530
 /* check_self wrapper -- it checks also for the op */
409 531
 inline static int check_self_op(int op, str* s, unsigned short p)
410 532
 {
... ...
@@ -426,7 +548,7 @@ inline static int check_self_op(int op, str* s, unsigned short p)
426 548
 
427 549
 
428 550
 /* eval_elem helping function, returns an op param */
429
-inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
551
+inline static int comp_ip(int op, struct ip_addr* ip, int rtype, union exp_op* r)
430 552
 {
431 553
 	struct hostent* he;
432 554
 	char ** h;
... ...
@@ -434,14 +556,14 @@ inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
434 556
 	str tmp;
435 557
 
436 558
 	ret=-1;
437
-	switch(subtype){
559
+	switch(rtype){
438 560
 		case NET_ST:
439 561
 			switch(op){
440 562
 				case EQUAL_OP:
441
-					ret=(matchnet(ip, (struct net*) param)==1);
563
+					ret=(matchnet(ip, r->net)==1);
442 564
 					break;
443 565
 				case DIFF_OP:
444
-					ret=(matchnet(ip, (struct net*) param)!=1);
566
+					ret=(matchnet(ip, r->net)!=1);
445 567
 					break;
446 568
 				default:
447 569
 					goto error_op;
... ...
@@ -453,14 +575,14 @@ inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
453 575
 				case EQUAL_OP:
454 576
 				case MATCH_OP:
455 577
 					/* 1: compare with ip2str*/
456
-					ret=comp_str(ip_addr2a(ip), param, op, subtype);
578
+					ret=comp_string(op, ip_addr2a(ip), rtype, r);
457 579
 					if (ret==1) break;
458 580
 					/* 2: resolve (name) & compare w/ all the ips */
459
-					if (subtype==STRING_ST){
460
-						he=resolvehost((char*)param);
581
+					if (rtype==STRING_ST){
582
+						he=resolvehost(r->str.s);
461 583
 						if (he==0){
462 584
 							DBG("comp_ip: could not resolve %s\n",
463
-									(char*)param);
585
+							    r->str.s);
464 586
 						}else if (he->h_addrtype==ip->af){
465 587
 							for(h=he->h_addr_list;(ret!=1)&& (*h); h++){
466 588
 								ret=(memcmp(ip->u.addr, *h, ip->len)==0);
... ...
@@ -478,15 +600,15 @@ inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
478 600
 					ret=0;
479 601
 					}else{
480 602
 						/*  compare with primary host name */
481
-						ret=comp_str(he->h_name, param, op, subtype);
603
+						ret=comp_string(op, he->h_name, rtype, r);
482 604
 						/* compare with all the aliases */
483 605
 						for(h=he->h_aliases; (ret!=1) && (*h); h++){
484
-							ret=comp_str(*h, param, op, subtype);
606
+							ret=comp_string(op, *h, rtype, r);
485 607
 						}
486 608
 					}
487 609
 					break;
488 610
 				case DIFF_OP:
489
-					ret=comp_ip(ip, param, EQUAL_OP, subtype);
611
+					ret=comp_ip(EQUAL_OP, ip, rtype, r);
490 612
 					if (ret>=0) ret=!ret;
491 613
 					break;
492 614
 				default:
... ...
@@ -500,7 +622,7 @@ inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
500 622
 			break;
501 623
 		default:
502 624
 			LOG(L_CRIT, "BUG: comp_ip: invalid type for "
503
-						" src_ip or dst_ip (%d)\n", subtype);
625
+						" src_ip or dst_ip (%d)\n", rtype);
504 626
 			ret=-1;
505 627
 	}
506 628
 	return ret;
... ...
@@ -511,11 +633,9 @@ error_op:
511 633
 }
512 634
 
513 635
 
514
-
515 636
 /* returns: 0/1 (false/true) or -1 on error, -127 EXPR_DROP */
516 637
 static int eval_elem(struct expr* e, struct sip_msg* msg)
517 638
 {
518
-
519 639
 	struct sip_uri uri;
520 640
 	int ret;
521 641
 	ret=E_BUG;
... ...
@@ -524,110 +644,127 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
524 644
 		LOG(L_CRIT," BUG: eval_elem: invalid type\n");
525 645
 		goto error;
526 646
 	}
527
-	switch(e->l.operand){
528
-		case METHOD_O:
529
-				ret=comp_strstr(&msg->first_line.u.request.method, e->r.param,
530
-								e->op, e->subtype);
531
-				break;
532
-		case URI_O:
533
-				if(msg->new_uri.s){
534
-					if (e->subtype==MYSELF_ST){
535
-						if (parse_sip_msg_uri(msg)<0) ret=-1;
536
-						else	ret=check_self_op(e->op, &msg->parsed_uri.host,
537
-									msg->parsed_uri.port_no?
538
-									msg->parsed_uri.port_no:SIP_PORT);
539
-					}else{
540
-						ret=comp_strstr(&msg->new_uri, e->r.param,
541
-										e->op, e->subtype);
542
-					}
543
-				}else{
544
-					if (e->subtype==MYSELF_ST){
545
-						if (parse_sip_msg_uri(msg)<0) ret=-1;
546
-						else	ret=check_self_op(e->op, &msg->parsed_uri.host,
547
-									msg->parsed_uri.port_no?
548
-									msg->parsed_uri.port_no:SIP_PORT);
549
-					}else{
550
-						ret=comp_strstr(&msg->first_line.u.request.uri,
551
-										 e->r.param, e->op, e->subtype);
552
-					}
553
-				}
554
-				break;
555
-		case FROM_URI_O:
556
-				if (parse_from_header(msg)!=0){
557
-					LOG(L_ERR, "ERROR: eval_elem: bad or missing"
558
-								" From: header\n");
559
-					goto error;
560
-				}
561
-				if (e->subtype==MYSELF_ST){
562
-					if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len,
563
-									&uri) < 0){
564
-						LOG(L_ERR, "ERROR: eval_elem: bad uri in From:\n");
565
-						goto error;
566
-					}
567
-					ret=check_self_op(e->op, &uri.host,
568
-										uri.port_no?uri.port_no:SIP_PORT);
569
-				}else{
570
-					ret=comp_strstr(&get_from(msg)->uri,
571
-							e->r.param, e->op, e->subtype);
572
-				}
573
-				break;
574
-		case TO_URI_O:
575
-				if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) ||
576
-							(msg->to==0))){
577
-					LOG(L_ERR, "ERROR: eval_elem: bad or missing"
578
-								" To: header\n");
579
-					goto error;
580
-				}
581
-				/* to content is parsed automatically */
582
-				if (e->subtype==MYSELF_ST){
583
-					if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len,
584
-									&uri) < 0){
585
-						LOG(L_ERR, "ERROR: eval_elem: bad uri in To:\n");
586
-						goto error;
587
-					}
588
-					ret=check_self_op(e->op, &uri.host,
589
-										uri.port_no?uri.port_no:SIP_PORT);
590
-				}else{
591
-					ret=comp_strstr(&get_to(msg)->uri,
592
-										e->r.param, e->op, e->subtype);
593
-				}
594
-				break;
595
-		case SRCIP_O:
596
-				ret=comp_ip(&msg->rcv.src_ip, e->r.param, e->op, e->subtype);
597
-				break;
598
-		case DSTIP_O:
599
-				ret=comp_ip(&msg->rcv.dst_ip, e->r.param, e->op, e->subtype);
600
-				break;
601
-		case NUMBER_O:
602
-				ret=!(!e->r.intval); /* !! to transform it in {0,1} */
603
-				break;
604
-		case ACTION_O:
605
-				ret=run_actions( (struct action*)e->r.param, msg);
606
-				if (ret<=0) ret=(ret==0)?EXPR_DROP:0;
607
-				else ret=1;
608
-				break;
609
-		case SRCPORT_O:
610
-				ret=comp_no(msg->rcv.src_port, 
611
-					e->r.param, /* e.g., 5060 */
612
-					e->op, /* e.g. == */
613
-					e->subtype /* 5060 is number */);
614
-				break;
615
-		case DSTPORT_O:
616
-				ret=comp_no(msg->rcv.dst_port, e->r.param, e->op, 
617
-							e->subtype);
618
-				break;
619
-		case PROTO_O:
620
-				ret=comp_no(msg->rcv.proto, e->r.param, e->op, e->subtype);
621
-				break;
622
-		case AF_O:
623
-				ret=comp_no(msg->rcv.src_ip.af, e->r.param, e->op, e->subtype);
624
-				break;
625
-		case MSGLEN_O:
626
-				ret=comp_no(msg->len, e->r.param, e->op, e->subtype);
627
-				break;
628
-		default:
629
-				LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n",
630
-							e->l.operand);
647
+	switch(e->l_type){
648
+	case METHOD_O:
649
+		ret=comp_str(e->op, &msg->first_line.u.request.method, 
650
+			     e->r_type, &e->r);
651
+		break;
652
+	case URI_O:
653
+		if(msg->new_uri.s) {
654
+			if (e->r_type==MYSELF_ST){
655
+				if (parse_sip_msg_uri(msg)<0) ret=-1;
656
+				else ret=check_self_op(e->op, &msg->parsed_uri.host,
657
+						       msg->parsed_uri.port_no?
658
+						       msg->parsed_uri.port_no:SIP_PORT);
659
+			}else{
660
+				ret=comp_str(e->op, &msg->new_uri, 
661
+					     e->r_type, &e->r);
662
+			}
663
+		}else{
664
+			if (e->r_type==MYSELF_ST){
665
+				if (parse_sip_msg_uri(msg)<0) ret=-1;
666
+				else ret=check_self_op(e->op, &msg->parsed_uri.host,
667
+						       msg->parsed_uri.port_no?
668
+						       msg->parsed_uri.port_no:SIP_PORT);
669
+			}else{
670
+				ret=comp_str(e->op, &msg->first_line.u.request.uri,
671
+					     e->r_type, &e->r);
672
+			}
673
+		}
674
+		break;
675
+		
676
+	case FROM_URI_O:
677
+		if (parse_from_header(msg)!=0){
678
+			LOG(L_ERR, "ERROR: eval_elem: bad or missing"
679
+			    " From: header\n");
680
+			goto error;
681
+		}
682
+		if (e->r_type==MYSELF_ST){
683
+			if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len,
684
+				      &uri) < 0){
685
+				LOG(L_ERR, "ERROR: eval_elem: bad uri in From:\n");
686
+				goto error;
687
+			}
688
+			ret=check_self_op(e->op, &uri.host,
689
+					  uri.port_no?uri.port_no:SIP_PORT);
690
+		}else{
691
+			ret=comp_str(e->op, &get_from(msg)->uri,
692
+				     e->r_type, &e->r);
693
+		}
694
+		break;
695
+
696
+	case TO_URI_O:
697
+		if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) ||
698
+				     (msg->to==0))){
699
+			LOG(L_ERR, "ERROR: eval_elem: bad or missing"
700
+			    " To: header\n");
701
+			goto error;
702
+		}
703
+		     /* to content is parsed automatically */
704
+		if (e->r_type==MYSELF_ST){
705
+			if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len,
706
+				      &uri) < 0){
707
+				LOG(L_ERR, "ERROR: eval_elem: bad uri in To:\n");
708
+				goto error;
709
+			}
710
+			ret=check_self_op(e->op, &uri.host,
711
+					  uri.port_no?uri.port_no:SIP_PORT);
712
+		}else{
713
+			ret=comp_str(e->op, &get_to(msg)->uri,
714
+				     e->r_type, &e->r);
715
+		}
716
+		break;
717
+		
718
+	case SRCIP_O:
719
+		ret=comp_ip(e->op, &msg->rcv.src_ip, e->r_type, &e->r);
720
+		break;
721
+		
722
+	case DSTIP_O:
723
+		ret=comp_ip(e->op, &msg->rcv.dst_ip, e->r_type, &e->r);
724
+		break;
725
+
726
+	case NUMBER_O:
727
+		ret=!(!e->r.intval); /* !! to transform it in {0,1} */
728
+		break;
729
+
730
+	case ACTION_O:
731
+		ret=run_actions( (struct action*)e->r.param, msg);
732
+		if (ret<=0) ret=(ret==0)?EXPR_DROP:0;
733
+		else ret=1;
734
+		break;
735
+		
736
+	case SRCPORT_O:
737
+		ret=comp_num(e->op, (int)msg->rcv.src_port, 
738
+			     e->r_type, &e->r);
739
+		break;
740
+		
741
+	case DSTPORT_O:
742
+		ret=comp_num(e->op, (int)msg->rcv.dst_port, 
743
+			     e->r_type, &e->r);
744
+		break;
745
+		
746
+	case PROTO_O:
747
+		ret=comp_num(e->op, msg->rcv.proto, 
748
+			     e->r_type, &e->r);
749
+		break;
750
+		
751
+	case AF_O:
752
+		ret=comp_num(e->op, (int)msg->rcv.src_ip.af, 
753
+			     e->r_type, &e->r);
754
+		break;
755
+
756
+	case MSGLEN_O:
757
+		ret=comp_num(e->op, (int)msg->len, 
758
+				e->r_type, &e->r);
759
+		break;
760
+
761
+	case AVP_ST:
762
+		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r);
763
+		break;
764
+		
765
+	default:
766
+		LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n",
767
+		    e->l_type);
631 768
 	}
632 769
 	return ret;
633 770
 error:
... ...
@@ -654,13 +791,13 @@ int eval_expr(struct expr* e, struct sip_msg* msg)
654 791
 		ret=eval_elem(e, msg);
655 792
 	}else if (e->type==EXP_T){
656 793
 		switch(e->op){
657
-			case AND_OP:
794
+			case LOGAND_OP:
658 795
 				ret=eval_expr(e->l.expr, msg);
659 796
 				/* if error or false stop evaluating the rest */
660 797
 				if (ret!=1) break;
661 798
 				ret=eval_expr(e->r.expr, msg); /*ret1 is 1*/
662 799
 				break;
663
-			case OR_OP:
800
+			case LOGOR_OP:
664 801
 				ret=eval_expr(e->l.expr, msg);
665 802
 				/* if true or error stop evaluating the rest */
666 803
 				if (ret!=0) break;
... ...
@@ -756,8 +893,7 @@ int fix_rls()
756 893
 /* debug function, prints main routing table */
757 894
 void print_rl()
758 895
 {
759
-	struct action* t;
760
-	int i,j;
896
+	int j;
761 897
 
762 898
 	for(j=0; j<RT_NO; j++){
763 899
 		if (rlist[j]==0){
... ...
@@ -765,9 +901,7 @@ void print_rl()
765 901
 			continue;
766 902
 		}
767 903
 		DBG("routing table %d:\n",j);
768
-		for (t=rlist[j],i=0; t; i++, t=t->next){
769
-			print_action(t);
770
-		}
904
+		print_actions(rlist[j]);
771 905
 		DBG("\n");
772 906
 	}
773 907
 	for(j=0; j<ONREPLY_RT_NO; j++){
... ...
@@ -775,9 +909,7 @@ void print_rl()
775 909
 			continue;
776 910
 		}
777 911
 		DBG("onreply routing table %d:\n",j);
778
-		for (t=onreply_rlist[j],i=0; t; i++, t=t->next){
779
-			print_action(t);
780
-		}
912
+		print_actions(onreply_rlist[j]);
781 913
 		DBG("\n");
782 914
 	}
783 915
 	for(j=0; j<FAILURE_RT_NO; j++){
... ...
@@ -785,9 +917,7 @@ void print_rl()
785 917
 			continue;
786 918
 		}
787 919
 		DBG("failure routing table %d:\n",j);
788
-		for (t=failure_rlist[j],i=0; t; i++, t=t->next){
789
-			print_action(t);
790
-		}
920
+		print_actions(failure_rlist[j]);
791 921
 		DBG("\n");
792 922
 	}
793 923
 	for(j=0; j<BRANCH_RT_NO; j++){
... ...
@@ -795,9 +925,7 @@ void print_rl()
795 925
 			continue;
796 926
 		}
797 927
 		DBG("branch routing table %d:\n",j);
798
-		for (t=branch_rlist[j],i=0; t; i++, t=t->next){
799
-			print_action(t);
800
-		}
928
+		print_actions(branch_rlist[j]);
801 929
 		DBG("\n");
802 930
 	}
803 931
 }
... ...
@@ -46,6 +46,7 @@
46 46
 #include "dprint.h"
47 47
 #include "ip_addr.h"
48 48
 #include "mem/mem.h"
49
+#include "usr_avp.h"
49 50
 #include "ut.h" /* ZSW() */
50 51
 
51 52
 
... ...
@@ -65,16 +66,17 @@ error:
65 66
 }
66 67
 
67 68
 
68
-struct expr* mk_elem(int op, int subtype, int operand, void* param)
69
+struct expr* mk_elem(int op, int ltype, void* lparam, int rtype, void* rparam)
69 70
 {
70 71
 	struct expr * e;
71 72
 	e=(struct expr*)pkg_malloc(sizeof (struct expr));
72 73
 	if (e==0) goto error;
73 74
 	e->type=ELEM_T;
74 75
 	e->op=op;
75
-	e->subtype=subtype;
76
-	e->l.operand=operand;
77
-	e->r.param=param;
76
+	e->l_type=ltype;
77
+	e->l.param=lparam;
78
+	e->r_type = rtype;
79
+	e->r.param=rparam;
78 80
 	return e;
79 81
 error:
80 82
 	LOG(L_CRIT, "ERROR: mk_elem: memory allocation failure\n");
... ...
@@ -84,7 +86,7 @@ error:
84 86
 
85 87
 
86 88
 struct action* mk_action(int type, int p1_type, int p2_type,
87
-											void* p1, void* p2)
89
+			 void* p1, void* p2)
88 90
 {
89 91
 	struct action* a;
90 92
 	a=(struct action*)pkg_malloc(sizeof(struct action));
... ...
@@ -140,7 +142,7 @@ void print_expr(struct expr* exp)
140 142
 		return;
141 143
 	}
142 144
 	if (exp->type==ELEM_T){
143
-		switch(exp->l.operand){
145
+		switch(exp->l_type){
144 146
 			case METHOD_O:
145 147
 				DBG("method");
146 148
 				break;
... ...
@@ -169,6 +171,10 @@ void print_expr(struct expr* exp)
169 171
 				break;
170 172
 			case ACTION_O:
171 173
 				break;
174
+		        case AVP_ST:
175
+				DBG("attr");
176
+				break;
177
+			
172 178
 			default:
173 179
 				DBG("UNKNOWN");
174 180
 		}
... ...
@@ -199,7 +205,7 @@ void print_expr(struct expr* exp)
199 205
 			default:
200 206
 				DBG("<UNKNOWN>");
201 207
 		}
202
-		switch(exp->subtype){
208
+		switch(exp->r_type){
203 209
 			case NOSUBTYPE: 
204 210
 					DBG("N/A");
205 211
 					break;
... ...
@@ -213,7 +219,7 @@ void print_expr(struct expr* exp)
213 219
 					print_ip("", (struct ip_addr*)exp->r.param, "");
214 220
 					break;
215 221
 			case ACTIONS_ST:
216
-					print_action((struct action*)exp->r.param);
222
+					print_actions((struct action*)exp->r.param);
217 223
 					break;
218 224
 			case NUMBER_ST:
219 225
 					DBG("%d",exp->r.intval);
... ...
@@ -221,19 +227,23 @@ void print_expr(struct expr* exp)
221 227
 			case MYSELF_ST:
222 228
 					DBG("_myself_");
223 229
 					break;
230
+		        case AVP_ST:
231
+				DBG("attr");
232
+				break;
233
+			
224 234
 			default:
225
-					DBG("type<%d>", exp->subtype);
235
+					DBG("type<%d>", exp->r_type);
226 236
 		}
227 237
 	}else if (exp->type==EXP_T){
228 238
 		switch(exp->op){
229
-			case AND_OP:
239
+			case LOGAND_OP:
230 240
 					DBG("AND( ");
231 241
 					print_expr(exp->l.expr);
232 242
 					DBG(", ");
233 243
 					print_expr(exp->r.expr);
234 244
 					DBG(" )");
235 245
 					break;
236
-			case OR_OP:
246
+			case LOGOR_OP:
237 247
 					DBG("OR( ");
238 248
 					print_expr(exp->l.expr);
239 249
 					DBG(", ");
... ...
@@ -257,201 +267,214 @@ void print_expr(struct expr* exp)
257 267
 
258 268
 					
259 269
 
260
-void print_action(struct action* a)
270
+void print_action(struct action* t)
261 271
 {
262
-	struct action* t;
263
-	for(t=a; t!=0;t=t->next){
264
-		switch(t->type){
265
-			case FORWARD_T:
266
-					DBG("forward(");
267
-					break;
268
-			case FORWARD_TCP_T:
269
-					DBG("forward_tcp(");
270
-					break;
271
-			case FORWARD_UDP_T:
272
-					DBG("forward_udp(");
273
-					break;
274
-			case SEND_T:
275
-					DBG("send(");
276
-					break;
277
-			case SEND_TCP_T:
278
-					DBG("send_tcp(");
279
-					break;
280
-			case DROP_T:
281
-					DBG("drop(");
282
-					break;
283
-			case LOG_T:
284
-					DBG("log(");
285
-					break;
286
-			case ERROR_T:
287
-					DBG("error(");
288
-					break;
289
-			case ROUTE_T:
290
-					DBG("route(");
291
-					break;
292
-