ソースを参照

- rewritten module function parsing and call processing (mk_action, struct action, action_u_t)
- API to get other fixup params from fixup
- full function overloading
- optional NUMBER/STRING param in config for module functions
- added oveloaded functions to print_stdout (demostrates overloading)

Tomas Mandys 19 年 前
コミット
f141bc93c5
9 ファイル変更1788 行追加2194 行削除
  1. 154 153
      action.c
  2. 1223 1642
      cfg.y
  3. 1 0
      modparam.c
  4. 5 3
      modules/tm/tm.c
  5. 116 103
      route.c
  6. 227 235
      route_struct.c
  7. 24 29
      route_struct.h
  8. 32 25
      sr_module.c
  9. 6 4
      sr_module.h

+ 154 - 153
action.c

@@ -21,8 +21,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * GNU General Public License for more details.
  *
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  *
  * History:
  * History:
@@ -88,7 +88,7 @@ struct onsend_info* p_onsend=0; /* onsend route send info */
 static unsigned int run_flags=0;
 static unsigned int run_flags=0;
 int last_retcode=0; /* last return from a route() */
 int last_retcode=0; /* last return from a route() */
 
 
-/* ret= 0! if action -> end of list(e.g DROP), 
+/* ret= 0! if action -> end of list(e.g DROP),
       > 0 to continue processing next actions
       > 0 to continue processing next actions
    and <0 on error */
    and <0 on error */
 int do_action(struct action* a, struct sip_msg* msg)
 int do_action(struct action* a, struct sip_msg* msg)
@@ -119,11 +119,11 @@ int do_action(struct action* a, struct sip_msg* msg)
 	ret=E_BUG;
 	ret=E_BUG;
 	switch ((unsigned char)a->type){
 	switch ((unsigned char)a->type){
 		case DROP_T:
 		case DROP_T:
-				if (a->p1_type==RETCODE_ST)
+				if (a->val[0].type==RETCODE_ST)
 					ret=last_retcode;
 					ret=last_retcode;
 				else
 				else
-					ret=(int)a->p1.number;
-				run_flags|=(unsigned int)a->p2.number;
+					ret=(int) a->val[0].u.number;
+				run_flags|=(unsigned int)a->val[1].u.number;
 			break;
 			break;
 		case FORWARD_T:
 		case FORWARD_T:
 #ifdef USE_TCP
 #ifdef USE_TCP
@@ -142,7 +142,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 			else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS;
 			else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS;
 #endif
 #endif
 			else proto= PROTO_NONE;
 			else proto= PROTO_NONE;
-			if (a->p1_type==URIHOST_ST){
+			if (a->val[0].type==URIHOST_ST){
 				/*parse uri*/
 				/*parse uri*/
 
 
 				if (msg->dst_uri.len) {
 				if (msg->dst_uri.len) {
@@ -158,17 +158,17 @@ int do_action(struct action* a, struct sip_msg* msg)
 								" dropping packet\n");
 								" dropping packet\n");
 					break;
 					break;
 				}
 				}
-				
-				switch (a->p2_type){
+
+				switch (a->val[1].type){
 					case URIPORT_ST:
 					case URIPORT_ST:
 									port=u->port_no;
 									port=u->port_no;
 									break;
 									break;
 					case NUMBER_ST:
 					case NUMBER_ST:
-									port=a->p2.number;
+									port=a->val[1].u.number;
 									break;
 									break;
 					default:
 					default:
 							LOG(L_CRIT, "BUG: do_action bad forward 2nd"
 							LOG(L_CRIT, "BUG: do_action bad forward 2nd"
-										" param type (%d)\n", a->p2_type);
+										" param type (%d)\n", a->val[1].type);
 							ret=E_UNSPEC;
 							ret=E_UNSPEC;
 							goto error_fwd_uri;
 							goto error_fwd_uri;
 				}
 				}
@@ -219,22 +219,22 @@ int do_action(struct action* a, struct sip_msg* msg)
 				free_proxy(p); /* frees only p content, not p itself */
 				free_proxy(p); /* frees only p content, not p itself */
 				pkg_free(p);
 				pkg_free(p);
 				if (ret>=0) ret=1;
 				if (ret>=0) ret=1;
-			}else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
+			}else if ((a->val[0].type==PROXY_ST) && (a->val[1].type==NUMBER_ST)){
 				if (proto==PROTO_NONE)
 				if (proto==PROTO_NONE)
 					proto=msg->rcv.proto;
 					proto=msg->rcv.proto;
-				ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto);
+				ret=forward_request(msg,(struct proxy_l*)a->val[0].u.data, proto);
 				if (ret>=0) ret=1;
 				if (ret>=0) ret=1;
 			}else{
 			}else{
 				LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
-						a->p1_type, a->p2_type);
+						a->val[0].type, a->val[1].type);
 				ret=E_BUG;
 				ret=E_BUG;
 			}
 			}
 			break;
 			break;
 		case SEND_T:
 		case SEND_T:
 		case SEND_TCP_T:
 		case SEND_TCP_T:
-			if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
+			if ((a->val[0].type!= PROXY_ST)|(a->val[1].type!=NUMBER_ST)){
 				LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
-						a->p1_type, a->p2_type);
+						a->val[0].type, a->val[1].type);
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
@@ -246,13 +246,13 @@ int do_action(struct action* a, struct sip_msg* msg)
 				ret=E_OUT_OF_MEM;
 				ret=E_OUT_OF_MEM;
 				break;
 				break;
 			}
 			}
-			
-			p=(struct proxy_l*)a->p1.data;
-			
+
+			p=(struct proxy_l*)a->val[0].u.data;
+
 			if (p->ok==0){
 			if (p->ok==0){
 				if (p->host.h_addr_list[p->addr_idx+1])
 				if (p->host.h_addr_list[p->addr_idx+1])
 					p->addr_idx++;
 					p->addr_idx++;
-				else 
+				else
 					p->addr_idx=0;
 					p->addr_idx=0;
 				p->ok=1;
 				p->ok=1;
 			}
 			}
@@ -289,132 +289,132 @@ int do_action(struct action* a, struct sip_msg* msg)
 				p->errors++;
 				p->errors++;
 				p->ok=0;
 				p->ok=0;
 			}else ret=1;
 			}else ret=1;
-			
+
 			break;
 			break;
 		case LOG_T:
 		case LOG_T:
-			if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){
+			if ((a->val[0].type!=NUMBER_ST)|(a->val[1].type!=STRING_ST)){
 				LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n",
-						a->p1_type, a->p2_type);
+						a->val[0].type, a->val[1].type);
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			LOG(a->p1.number, "%s", a->p2.string);
+			LOG(a->val[0].u.number, "%s", a->val[1].u.string);
 			ret=1;
 			ret=1;
 			break;
 			break;
 
 
 		/* jku -- introduce a new branch */
 		/* jku -- introduce a new branch */
 		case APPEND_BRANCH_T:
 		case APPEND_BRANCH_T:
-			if ((a->p1_type!=STRING_ST)) {
+			if ((a->val[0].type!=STRING_ST)) {
 				LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
-					a->p1_type );
+					a->val[0].type );
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			ret=append_branch( msg, a->p1.string, 
-					   a->p1.string ? strlen(a->p1.string):0,
-					   0, 0, a->p2.number, 0);
+			ret=append_branch( msg, a->val[0].u.string,
+					   a->val[0].u.string ? strlen(a->val[0].u.string):0,
+					   0, 0, a->val[1].u.number, 0);
 			break;
 			break;
 
 
 		/* jku begin: is_length_greater_than */
 		/* jku begin: is_length_greater_than */
 		case LEN_GT_T:
 		case LEN_GT_T:
-			if (a->p1_type!=NUMBER_ST) {
+			if (a->val[0].type!=NUMBER_ST) {
 				LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
-					a->p1_type );
+					a->val[0].type );
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			/* DBG("XXX: message length %d, max %d\n", 
-				msg->len, a->p1.number ); */
-			ret = msg->len >= a->p1.number ? 1 : -1;
+			/* DBG("XXX: message length %d, max %d\n",
+				msg->len, a->val[0].u.number ); */
+			ret = msg->len >= a->val[0].u.number ? 1 : -1;
 			break;
 			break;
 		/* jku end: is_length_greater_than */
 		/* jku end: is_length_greater_than */
-			
+
 		/* jku - begin : flag processing */
 		/* jku - begin : flag processing */
 
 
 		case SETFLAG_T:
 		case SETFLAG_T:
-			if (a->p1_type!=NUMBER_ST) {
+			if (a->val[0].type!=NUMBER_ST) {
 				LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n",
-					a->p1_type );
+					a->val[0].type );
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			if (!flag_in_range( a->p1.number )) {
+			if (!flag_in_range( a->val[0].u.number )) {
 				ret=E_CFG;
 				ret=E_CFG;
 				break;
 				break;
 			}
 			}
-			setflag( msg, a->p1.number );
+			setflag( msg, a->val[0].u.number );
 			ret=1;
 			ret=1;
 			break;
 			break;
 
 
 		case RESETFLAG_T:
 		case RESETFLAG_T:
-			if (a->p1_type!=NUMBER_ST) {
+			if (a->val[0].type!=NUMBER_ST) {
 				LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n",
-					a->p1_type );
+					a->val[0].type );
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			if (!flag_in_range( a->p1.number )) {
+			if (!flag_in_range( a->val[0].u.number )) {
 				ret=E_CFG;
 				ret=E_CFG;
 				break;
 				break;
 			}
 			}
-			resetflag( msg, a->p1.number );
+			resetflag( msg, a->val[0].u.number );
 			ret=1;
 			ret=1;
 			break;
 			break;
-			
+
 		case ISFLAGSET_T:
 		case ISFLAGSET_T:
-			if (a->p1_type!=NUMBER_ST) {
+			if (a->val[0].type!=NUMBER_ST) {
 				LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n",
-					a->p1_type );
+					a->val[0].type );
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			if (!flag_in_range( a->p1.number )) {
+			if (!flag_in_range( a->val[0].u.number )) {
 				ret=E_CFG;
 				ret=E_CFG;
 				break;
 				break;
 			}
 			}
-			ret=isflagset( msg, a->p1.number );
+			ret=isflagset( msg, a->val[0].u.number );
 			break;
 			break;
 		/* jku - end : flag processing */
 		/* jku - end : flag processing */
 
 
 		case ERROR_T:
 		case ERROR_T:
-			if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){
+			if ((a->val[0].type!=STRING_ST)|(a->val[1].type!=STRING_ST)){
 				LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
-						a->p1_type, a->p2_type);
+						a->val[0].type, a->val[1].type);
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
 			LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
 			LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") "
-					"not implemented yet\n", a->p1.string, a->p2.string);
+					"not implemented yet\n", a->val[0].u.string, a->val[1].u.string);
 			ret=1;
 			ret=1;
 			break;
 			break;
 		case ROUTE_T:
 		case ROUTE_T:
-			if (a->p1_type!=NUMBER_ST){
+			if (a->val[0].type!=NUMBER_ST){
 				LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
-						a->p1_type);
+						a->val[0].type);
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			if ((a->p1.number>RT_NO)||(a->p1.number<0)){
+			if ((a->val[0].u.number>RT_NO)||(a->val[0].u.number<0)){
 				LOG(L_ERR, "ERROR: invalid routing table number in"
 				LOG(L_ERR, "ERROR: invalid routing table number in"
-							"route(%lu)\n", a->p1.number);
+							"route(%lu)\n", a->val[0].u.number);
 				ret=E_CFG;
 				ret=E_CFG;
 				break;
 				break;
 			}
 			}
-			/*ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;*/
-			ret=run_actions(rlist[a->p1.number], msg);
+			/*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
+			ret=run_actions(rlist[a->val[0].u.number], msg);
 			last_retcode=ret;
 			last_retcode=ret;
 			run_flags&=~RETURN_R_F; /* absorb returns */
 			run_flags&=~RETURN_R_F; /* absorb returns */
 			break;
 			break;
 		case EXEC_T:
 		case EXEC_T:
-			if (a->p1_type!=STRING_ST){
+			if (a->val[0].type!=STRING_ST){
 				LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n",
-						a->p1_type);
+						a->val[0].type);
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
 			LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
 			LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented,"
-						" using dumb version...\n", a->p1.string);
-			ret=system(a->p1.string);
+						" using dumb version...\n", a->val[0].u.string);
+			ret=system(a->val[0].u.string);
 			if (ret!=0){
 			if (ret!=0){
 				LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
 				LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret);
 			}
 			}
@@ -440,14 +440,14 @@ int do_action(struct action* a, struct sip_msg* msg)
 		case STRIP_TAIL_T:
 		case STRIP_TAIL_T:
 				user=0;
 				user=0;
 				if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
 				if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
-					if (a->p1_type!=NUMBER_ST) {
+					if (a->val[0].type!=NUMBER_ST) {
 						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
 						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
-							a->p1_type);
+							a->val[0].type);
 						break;
 						break;
 					}
 					}
-				} else if (a->p1_type!=STRING_ST){
+				} else if (a->val[0].type!=STRING_ST){
 					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
 					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
-							a->p1_type);
+							a->val[0].type);
 					ret=E_BUG;
 					ret=E_BUG;
 					break;
 					break;
 				}
 				}
@@ -457,7 +457,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 							msg->new_uri.len=0;
 							msg->new_uri.len=0;
 					}
 					}
 					msg->parsed_uri_ok=0;
 					msg->parsed_uri_ok=0;
-					len=strlen(a->p1.string);
+					len=strlen(a->val[0].u.string);
 					msg->new_uri.s=pkg_malloc(len+1);
 					msg->new_uri.s=pkg_malloc(len+1);
 					if (msg->new_uri.s==0){
 					if (msg->new_uri.s==0){
 						LOG(L_ERR, "ERROR: do_action: memory allocation"
 						LOG(L_ERR, "ERROR: do_action: memory allocation"
@@ -465,10 +465,10 @@ int do_action(struct action* a, struct sip_msg* msg)
 						ret=E_OUT_OF_MEM;
 						ret=E_OUT_OF_MEM;
 						break;
 						break;
 					}
 					}
-					memcpy(msg->new_uri.s, a->p1.string, len);
+					memcpy(msg->new_uri.s, a->val[0].u.string, len);
 					msg->new_uri.s[len]=0;
 					msg->new_uri.s[len]=0;
 					msg->new_uri.len=len;
 					msg->new_uri.len=len;
-					
+
 					ret=1;
 					ret=1;
 					break;
 					break;
 				}
 				}
@@ -485,7 +485,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 					ret=E_UNSPEC;
 					ret=E_UNSPEC;
 					break;
 					break;
 				}
 				}
-				
+
 				new_uri=pkg_malloc(MAX_URI_SIZE);
 				new_uri=pkg_malloc(MAX_URI_SIZE);
 				if (new_uri==0){
 				if (new_uri==0){
 					LOG(L_ERR, "ERROR: do_action: memory allocation "
 					LOG(L_ERR, "ERROR: do_action: memory allocation "
@@ -503,40 +503,40 @@ int do_action(struct action* a, struct sip_msg* msg)
 
 
 				/* prefix (-jiri) */
 				/* prefix (-jiri) */
 				if (a->type==PREFIX_T) {
 				if (a->type==PREFIX_T) {
-					tmp=a->p1.string;
+					tmp=a->val[0].u.string;
 					len=strlen(tmp); if(crt+len>end) goto error_uri;
 					len=strlen(tmp); if(crt+len>end) goto error_uri;
 					memcpy(crt,tmp,len);crt+=len;
 					memcpy(crt,tmp,len);crt+=len;
-					/* whatever we had before, with prefix we have username 
+					/* whatever we had before, with prefix we have username
 					   now */
 					   now */
 					user=1;
 					user=1;
 				}
 				}
 
 
 				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
 				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
-					tmp=a->p1.string;
+					tmp=a->val[0].u.string;
 					len=strlen(tmp);
 					len=strlen(tmp);
 				} else if (a->type==STRIP_T) {
 				} else if (a->type==STRIP_T) {
-					if (a->p1.number>uri.user.len) {
+					if (a->val[0].u.number>uri.user.len) {
 						LOG(L_WARN, "Error: too long strip asked; "
 						LOG(L_WARN, "Error: too long strip asked; "
 									" deleting username: %lu of <%.*s>\n",
 									" deleting username: %lu of <%.*s>\n",
-									a->p1.number, uri.user.len, uri.user.s );
+									a->val[0].u.number, uri.user.len, uri.user.s );
 						len=0;
 						len=0;
-					} else if (a->p1.number==uri.user.len) {
+					} else if (a->val[0].u.number==uri.user.len) {
 						len=0;
 						len=0;
 					} else {
 					} else {
-						tmp=uri.user.s + a->p1.number;
-						len=uri.user.len - a->p1.number;
+						tmp=uri.user.s + a->val[0].u.number;
+						len=uri.user.len - a->val[0].u.number;
 					}
 					}
 				} else if (a->type==STRIP_TAIL_T) {
 				} else if (a->type==STRIP_TAIL_T) {
-					if (a->p1.number>uri.user.len) {
+					if (a->val[0].u.number>uri.user.len) {
 						LOG(L_WARN, "WARNING: too long strip_tail asked; "
 						LOG(L_WARN, "WARNING: too long strip_tail asked; "
 									" deleting username: %lu of <%.*s>\n",
 									" deleting username: %lu of <%.*s>\n",
-									a->p1.number, uri.user.len, uri.user.s );
+									a->val[0].u.number, uri.user.len, uri.user.s );
 						len=0;
 						len=0;
-					} else if (a->p1.number==uri.user.len) {
+					} else if (a->val[0].u.number==uri.user.len) {
 						len=0;
 						len=0;
 					} else {
 					} else {
 						tmp=uri.user.s;
 						tmp=uri.user.s;
-						len=uri.user.len - a->p1.number;
+						len=uri.user.len - a->val[0].u.number;
 					}
 					}
 				} else {
 				} else {
 					tmp=uri.user.s;
 					tmp=uri.user.s;
@@ -563,7 +563,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 					*crt='@'; crt++;
 					*crt='@'; crt++;
 				}
 				}
 				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
 				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
-					tmp=a->p1.string;
+					tmp=a->val[0].u.string;
 					if (tmp) len = strlen(tmp);
 					if (tmp) len = strlen(tmp);
 					else len=0;
 					else len=0;
 				} else {
 				} else {
@@ -577,7 +577,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 				/* port */
 				/* port */
 				if (a->type==SET_HOSTPORT_T) tmp=0;
 				if (a->type==SET_HOSTPORT_T) tmp=0;
 				else if (a->type==SET_PORT_T) {
 				else if (a->type==SET_PORT_T) {
-					tmp=a->p1.string;
+					tmp=a->val[0].u.string;
 					if (tmp) len = strlen(tmp);
 					if (tmp) len = strlen(tmp);
 					else len = 0;
 					else len = 0;
 				} else {
 				} else {
@@ -613,8 +613,8 @@ int do_action(struct action* a, struct sip_msg* msg)
 				break;
 				break;
 		case IF_T:
 		case IF_T:
 				/* if null expr => ignore if? */
 				/* if null expr => ignore if? */
-				if ((a->p1_type==EXPR_ST)&&a->p1.data){
-					v=eval_expr((struct expr*)a->p1.data, msg);
+				if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
+					v=eval_expr((struct expr*)a->val[0].u.data, msg);
 #if 0
 #if 0
 					if (v<0){
 					if (v<0){
 						if (v==EXPR_DROP){ /* hack to quit on DROP*/
 						if (v==EXPR_DROP){ /* hack to quit on DROP*/
@@ -633,21 +633,22 @@ int do_action(struct action* a, struct sip_msg* msg)
 					run_flags &= ~RETURN_R_F; /* catch returns in expr */
 					run_flags &= ~RETURN_R_F; /* catch returns in expr */
 					ret=1;  /*default is continue */
 					ret=1;  /*default is continue */
 					if (v>0) {
 					if (v>0) {
-						if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
-							ret=run_actions((struct action*)a->p2.data, msg);
+						if ((a->val[1].type==ACTIONS_ST)&&a->val[1].u.data){
+							ret=run_actions((struct action*)a->val[1].u.data, msg);
 						}
 						}
-					}else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
-							ret=run_actions((struct action*)a->p3.data, msg);
+					}else if ((a->val[2].type==ACTIONS_ST)&&a->val[2].u.data){
+							ret=run_actions((struct action*)a->val[2].u.data, msg);
 					}
 					}
 				}
 				}
 			break;
 			break;
 		case MODULE_T:
 		case MODULE_T:
-			if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&&
-					((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
-				ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
-													  (char*)a->p3.data);
+			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && ((cmd_export_t*)a->val[0].u.data)->function ){
+				ret=((cmd_export_t*)a->val[0].u.data)->function(msg,
+					(char*)a->val[2].u.data,
+					(char*)a->val[3].u.data
+				);
 				if (ret==0) run_flags|=EXIT_R_F;
 				if (ret==0) run_flags|=EXIT_R_F;
-			}else{
+			} else {
 				LOG(L_CRIT,"BUG: do_action: bad module call\n");
 				LOG(L_CRIT,"BUG: do_action: bad module call\n");
 			}
 			}
 			break;
 			break;
@@ -656,23 +657,23 @@ int do_action(struct action* a, struct sip_msg* msg)
 			ret=1; /* continue processing */
 			ret=1; /* continue processing */
 			break;
 			break;
 		case SET_ADV_ADDR_T:
 		case SET_ADV_ADDR_T:
-			if (a->p1_type!=STR_ST){
+			if (a->val[0].type!=STR_ST){
 				LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
 				LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
-						"type %d\n", a->p1_type);
+						"type %d\n", a->val[0].type);
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			msg->set_global_address=*((str*)a->p1.data);
+			msg->set_global_address=*((str*)a->val[0].u.data);
 			ret=1; /* continue processing */
 			ret=1; /* continue processing */
 			break;
 			break;
 		case SET_ADV_PORT_T:
 		case SET_ADV_PORT_T:
-			if (a->p1_type!=STR_ST){
+			if (a->val[0].type!=STR_ST){
 				LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
 				LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() "
-						"type %d\n", a->p1_type);
+						"type %d\n", a->val[0].type);
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			msg->set_global_port=*((str*)a->p1.data);
+			msg->set_global_port=*((str*)a->val[0].u.data);
 			ret=1; /* continue processing */
 			ret=1; /* continue processing */
 			break;
 			break;
 #ifdef USE_TCP
 #ifdef USE_TCP
@@ -682,16 +683,16 @@ int do_action(struct action* a, struct sip_msg* msg)
 					|| msg->rcv.proto==PROTO_TLS
 					|| msg->rcv.proto==PROTO_TLS
 #endif
 #endif
 			   ){
 			   ){
-				
-				if (a->p1_type==NOSUBTYPE)	port=msg->via1->port;
-				else if (a->p1_type==NUMBER_ST) port=(int)a->p1.number;
+
+				if (a->val[0].type==NOSUBTYPE)	port=msg->via1->port;
+				else if (a->val[0].type==NUMBER_ST) port=(int)a->val[0].u.number;
 				else{
 				else{
 					LOG(L_CRIT, "BUG: do_action: bad force_tcp_alias"
 					LOG(L_CRIT, "BUG: do_action: bad force_tcp_alias"
-							" port type %d\n", a->p1_type);
+							" port type %d\n", a->val[0].type);
 					ret=E_BUG;
 					ret=E_BUG;
 					break;
 					break;
 				}
 				}
-						
+
 				if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
 				if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
 									msg->rcv.proto)!=0){
 									msg->rcv.proto)!=0){
 					LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
 					LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
@@ -703,45 +704,45 @@ int do_action(struct action* a, struct sip_msg* msg)
 			ret=1; /* continue processing */
 			ret=1; /* continue processing */
 			break;
 			break;
 		case FORCE_SEND_SOCKET_T:
 		case FORCE_SEND_SOCKET_T:
-			if (a->p1_type!=SOCKETINFO_ST){
+			if (a->val[0].type!=SOCKETINFO_ST){
 				LOG(L_CRIT, "BUG: do_action: bad force_send_socket argument"
 				LOG(L_CRIT, "BUG: do_action: bad force_send_socket argument"
-						" type: %d\n", a->p1_type);
+						" type: %d\n", a->val[0].type);
 				ret=E_BUG;
 				ret=E_BUG;
 				break;
 				break;
 			}
 			}
-			msg->force_send_socket=(struct socket_info*)a->p1.data;
+			msg->force_send_socket=(struct socket_info*)a->val[0].u.data;
 			ret=1; /* continue processing */
 			ret=1; /* continue processing */
 			break;
 			break;
 
 
 	        case ADD_T:
 	        case ADD_T:
 	        case ASSIGN_T:
 	        case ASSIGN_T:
-		
+
 			/* If the left attr was specified withou indexing brackets delete
 			/* If the left attr was specified withou indexing brackets delete
 			 * existing AVPs before adding new ones
 			 * existing AVPs before adding new ones
 			 */
 			 */
-			if ((a->p1.attr->type & AVP_INDEX_ALL) != AVP_INDEX_ALL) delete_avp(a->p1.attr->type, a->p1.attr->name);
-			
-			if (a->p2_type == STRING_ST) {
-				value.s = a->p2.str;
-				flags = a->p1.attr->type | AVP_VAL_STR;
-				name = a->p1.attr->name;
+			if ((a->val[0].u.attr->type & AVP_INDEX_ALL) != AVP_INDEX_ALL) delete_avp(a->val[0].u.attr->type, a->val[0].u.attr->name);
+
+			if (a->val[1].type == STRING_ST) {
+				value.s = a->val[1].u.str;
+				flags = a->val[0].u.attr->type | AVP_VAL_STR;
+				name = a->val[0].u.attr->name;
 				ret = 1;
 				ret = 1;
-			} else if (a->p2_type == NUMBER_ST) {
-				value.n = a->p2.number;
-				flags = a->p1.attr->type;
-				name = a->p1.attr->name;
+			} else if (a->val[1].type == NUMBER_ST) {
+				value.n = a->val[1].u.number;
+				flags = a->val[0].u.attr->type;
+				name = a->val[0].u.attr->name;
 				ret = 1;
 				ret = 1;
-			} else if (a->p2_type == ACTION_ST) {
-				flags = a->p1.attr->type;
-				name = a->p1.attr->name;
-				if (a->p2.data) {
-					value.n = run_actions((struct action*)a->p2.data, msg);
+			} else if (a->val[1].type == ACTION_ST) {
+				flags = a->val[0].u.attr->type;
+				name = a->val[0].u.attr->name;
+				if (a->val[1].u.data) {
+					value.n = run_actions((struct action*)a->val[1].u.data, msg);
 				} else {
 				} else {
 					value.n = -1;
 					value.n = -1;
 				}
 				}
 				ret = value.n;
 				ret = value.n;
-			} else if(a->p2_type == EXPR_ST && a->p2.data) {
-				v = eval_expr((struct expr*)a->p2.data, msg);
+			} else if(a->val[1].type == EXPR_ST && a->val[1].u.data) {
+				v = eval_expr((struct expr*)a->val[1].u.data, msg);
 				if (v < 0) {
 				if (v < 0) {
 					if (v == EXPR_DROP){ /* hack to quit on DROP*/
 					if (v == EXPR_DROP){ /* hack to quit on DROP*/
 						ret = 0;
 						ret = 0;
@@ -750,55 +751,55 @@ int do_action(struct action* a, struct sip_msg* msg)
 						LOG(L_WARN,"WARNING: do_action: error in expression\n");
 						LOG(L_WARN,"WARNING: do_action: error in expression\n");
 					}
 					}
 				}
 				}
-				
-				flags = a->p1.attr->type;
-				name = a->p1.attr->name;
+
+				flags = a->val[0].u.attr->type;
+				name = a->val[0].u.attr->name;
 				value.n = v;
 				value.n = v;
-			} else if (a->p2_type == AVP_ST) {
+			} else if (a->val[1].type == AVP_ST) {
 				struct search_state st;
 				struct search_state st;
-				avp_t* avp; 
+				avp_t* avp;
 				avp_t* avp_mark;
 				avp_t* avp_mark;
-				
+
 				avp_mark = NULL;
 				avp_mark = NULL;
-				if ((a->p2.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL) {
-					avp = search_first_avp(a->p2.attr->type, a->p2.attr->name, &value, &st);
+				if ((a->val[1].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL) {
+					avp = search_first_avp(a->val[1].u.attr->type, a->val[1].u.attr->name, &value, &st);
 					while(avp) {
 					while(avp) {
 						     /* We take only the type of value and name from the source avp
 						     /* We take only the type of value and name from the source avp
 						      * and reset class and track flags
 						      * and reset class and track flags
 						      */
 						      */
-						flags = (a->p1.attr->type & ~AVP_INDEX_ALL) | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
-						
-						if (add_avp_before(avp_mark, flags, a->p1.attr->name, value) < 0) {
+						flags = (a->val[0].u.attr->type & ~AVP_INDEX_ALL) | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
+
+						if (add_avp_before(avp_mark, flags, a->val[0].u.attr->name, value) < 0) {
 							LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
 							LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n");
 							ret=E_UNSPEC;
 							ret=E_UNSPEC;
 							break;
 							break;
 						}
 						}
-						
+
 						/* move the mark, so the next found AVP will come before the one currently added
 						/* move the mark, so the next found AVP will come before the one currently added
 						 * so they will have the same order as in the source list
 						 * so they will have the same order as in the source list
 						 */
 						 */
 						if (avp_mark) {
 						if (avp_mark) {
 							avp_mark=avp_mark->next;
 							avp_mark=avp_mark->next;
 						} else {
 						} else {
-							avp_mark=search_first_avp(flags, a->p1.attr->name, NULL, NULL);
+							avp_mark=search_first_avp(flags, a->val[0].u.attr->name, NULL, NULL);
 						}
 						}
-							
+
 						avp = search_next_avp(&st, &value);
 						avp = search_next_avp(&st, &value);
 					}
 					}
 					ret = 1;
 					ret = 1;
 					break;
 					break;
 				} else {
 				} else {
-					avp = search_avp_by_index(a->p2.attr->type, a->p2.attr->name, &value, a->p2.attr->index);
+					avp = search_avp_by_index(a->val[1].u.attr->type, a->val[1].u.attr->name, &value, a->val[1].u.attr->index);
 					if (avp) {
 					if (avp) {
-						flags = a->p1.attr->type | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
+						flags = a->val[0].u.attr->type | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL));
 					} else {
 					} else {
 						ret = E_UNSPEC;
 						ret = E_UNSPEC;
 						break;
 						break;
 					}
 					}
 				}
 				}
-			} else if (a->p2_type == SELECT_ST) {
+			} else if (a->val[1].type == SELECT_ST) {
 				int r;
 				int r;
-				r = run_select(&value.s, a->p2.select, msg);
+				r = run_select(&value.s, a->val[1].u.select, msg);
 				if (r < 0) {
 				if (r < 0) {
 					ret=E_UNSPEC;
 					ret=E_UNSPEC;
 					break;
 					break;
@@ -807,8 +808,8 @@ int do_action(struct action* a, struct sip_msg* msg)
 					value.s.len = 0;
 					value.s.len = 0;
 				}
 				}
 
 
-				flags = a->p1.attr->type | AVP_VAL_STR;
-				name = a->p1.attr->name;
+				flags = a->val[0].u.attr->type | AVP_VAL_STR;
+				name = a->val[0].u.attr->name;
 				ret = 1;
 				ret = 1;
 			} else {
 			} else {
 				LOG(L_CRIT, "BUG: do_action: Bad right side of avp assignment\n");
 				LOG(L_CRIT, "BUG: do_action: Bad right side of avp assignment\n");
@@ -831,7 +832,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 	}
 	}
 /*skip:*/
 /*skip:*/
 	return ret;
 	return ret;
-	
+
 error_uri:
 error_uri:
 	LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
 	LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
 	if (new_uri) pkg_free(new_uri);
 	if (new_uri) pkg_free(new_uri);
@@ -869,9 +870,9 @@ int run_actions(struct action* a, struct sip_msg* msg)
 			goto end;
 			goto end;
 		}
 		}
 	}
 	}
-		
+
 	if (a==0){
 	if (a==0){
-		LOG(L_ERR, "WARNING: run_actions: null action list (rec_level=%d)\n", 
+		LOG(L_ERR, "WARNING: run_actions: null action list (rec_level=%d)\n",
 			rec_lev);
 			rec_lev);
 		ret=0;
 		ret=0;
 	}
 	}
@@ -887,18 +888,18 @@ int run_actions(struct action* a, struct sip_msg* msg)
 		}
 		}
 		/* ignore error returns */
 		/* ignore error returns */
 	}
 	}
-	
+
 	rec_lev--;
 	rec_lev--;
 end:
 end:
 	/* process module onbreak handlers if present */
 	/* process module onbreak handlers if present */
-	if (rec_lev==0 && ret==0) 
-		for (mod=modules;mod;mod=mod->next) 
+	if (rec_lev==0 && ret==0)
+		for (mod=modules;mod;mod=mod->next)
 			if (mod->exports && mod->exports->onbreak_f) {
 			if (mod->exports && mod->exports->onbreak_f) {
 				mod->exports->onbreak_f( msg );
 				mod->exports->onbreak_f( msg );
 				DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);
 				DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);
 			}
 			}
 	return ret;
 	return ret;
-	
+
 
 
 error:
 error:
 	rec_lev--;
 	rec_lev--;

ファイルの差分が大きいため隠しています
+ 1223 - 1642
cfg.y


+ 1 - 0
modparam.c

@@ -87,6 +87,7 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
 		if (regexec(&preg, t->exports->name, 0, 0, 0) == 0) {
 		if (regexec(&preg, t->exports->name, 0, 0, 0) == 0) {
 			DBG("set_mod_param_regex: '%s' matches module '%s'\n", regex, t->exports->name);
 			DBG("set_mod_param_regex: '%s' matches module '%s'\n", regex, t->exports->name);
 			mod_found = 1;
 			mod_found = 1;
+			/* PARAM_STR (PARAM_STRING) may be assigned also to PARAM_STRING(PARAM_STR) so let get both module param */
 			ptr = find_param_export(t, name, type | ((type & (PARAM_STR|PARAM_STRING))?PARAM_STR|PARAM_STRING:0), &param_type);
 			ptr = find_param_export(t, name, type | ((type & (PARAM_STR|PARAM_STRING))?PARAM_STR|PARAM_STRING:0), &param_type);
 			if (ptr) {
 			if (ptr) {
 				     /* type casting */
 				     /* type casting */

+ 5 - 3
modules/tm/tm.c

@@ -260,7 +260,7 @@ static cmd_export_t cmds[]={
 	{"dlg_request_uas",    (cmd_function)dlg_request_uas,   NO_SCRIPT,   0, 0},
 	{"dlg_request_uas",    (cmd_function)dlg_request_uas,   NO_SCRIPT,   0, 0},
 	{"free_dlg",           (cmd_function)free_dlg,          NO_SCRIPT,   0, 0},
 	{"free_dlg",           (cmd_function)free_dlg,          NO_SCRIPT,   0, 0},
 	{"print_dlg",          (cmd_function)print_dlg,         NO_SCRIPT,   0, 0},
 	{"print_dlg",          (cmd_function)print_dlg,         NO_SCRIPT,   0, 0},
-	{T_GETT,               (cmd_function)get_t,             NO_SCRIPT,   0,0},
+	{T_GETT,               (cmd_function)get_t,             NO_SCRIPT,   0, 0},
 	{"calculate_hooks",    (cmd_function)w_calculate_hooks, NO_SCRIPT,   0, 0},
 	{"calculate_hooks",    (cmd_function)w_calculate_hooks, NO_SCRIPT,   0, 0},
 	{0,0,0,0,0}
 	{0,0,0,0,0}
 };
 };
@@ -314,13 +314,15 @@ static int fixup_hostport2proxy(void** param, int param_no)
 	char *host;
 	char *host;
 	int err;
 	int err;
 	struct proxy_l *proxy;
 	struct proxy_l *proxy;
+	action_u_t *a;
 	str s;
 	str s;
 
 
 	DBG("TM module: fixup_hostport2proxy(%s, %d)\n", (char*)*param, param_no);
 	DBG("TM module: fixup_hostport2proxy(%s, %d)\n", (char*)*param, param_no);
 	if (param_no==1){
 	if (param_no==1){
 		return 0;
 		return 0;
 	} else if (param_no==2) {
 	} else if (param_no==2) {
-		host=((action_u_t*)(param)-1)->string;
+		a = fixup_get_param(param, param_no, 1);
+		host= a->u.string;
 		port=str2s(*param, strlen(*param), &err);
 		port=str2s(*param, strlen(*param), &err);
 		if (err!=0) {
 		if (err!=0) {
 			LOG(L_ERR, "TM module:fixup_hostport2proxy: bad port number <%s>\n",
 			LOG(L_ERR, "TM module:fixup_hostport2proxy: bad port number <%s>\n",
@@ -337,7 +339,7 @@ static int fixup_hostport2proxy(void** param, int param_no)
 		}
 		}
 		/* success -- fix the first parameter to proxy now ! */
 		/* success -- fix the first parameter to proxy now ! */
 
 
-		((action_u_t*)(param)-1)->data=proxy;
+		a->u.data=proxy;
 		return 0;
 		return 0;
 	} else {
 	} else {
 		LOG(L_ERR,"ERROR: fixup_hostport2proxy called with parameter #<>{1,2}\n");
 		LOG(L_ERR,"ERROR: fixup_hostport2proxy called with parameter #<>{1,2}\n");

+ 116 - 103
route.c

@@ -23,8 +23,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * GNU General Public License for more details.
  *
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  *
  * History:
  * History:
@@ -44,7 +44,7 @@
  *  2005-12-19  select framework (mma)
  *  2005-12-19  select framework (mma)
  */
  */
 
 
- 
+
 #include <stdlib.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/types.h>
 #include <regex.h>
 #include <regex.h>
@@ -82,13 +82,13 @@ struct action* onsend_rlist[ONSEND_RT_NO];
 static int fix_actions(struct action* a); /*fwd declaration*/
 static int fix_actions(struct action* a); /*fwd declaration*/
 
 
 
 
-/* traverses an expr tree and compiles the REs where necessary) 
+/* traverses an expr tree and compiles the REs where necessary)
  * returns: 0 for ok, <0 if errors */
  * returns: 0 for ok, <0 if errors */
 static int fix_expr(struct expr* exp)
 static int fix_expr(struct expr* exp)
 {
 {
 	regex_t* re;
 	regex_t* re;
 	int ret;
 	int ret;
-	
+
 	ret=E_BUG;
 	ret=E_BUG;
 	if (exp==0){
 	if (exp==0){
 		LOG(L_CRIT, "BUG: fix_expr: null pointer\n");
 		LOG(L_CRIT, "BUG: fix_expr: null pointer\n");
@@ -190,12 +190,11 @@ static int fix_actions(struct action* a)
 	char *tmp;
 	char *tmp;
 	int ret;
 	int ret;
 	cmd_export_t* cmd;
 	cmd_export_t* cmd;
-	struct sr_module* mod;
 	str s;
 	str s;
 	struct hostent* he;
 	struct hostent* he;
 	struct ip_addr ip;
 	struct ip_addr ip;
 	struct socket_info* si;
 	struct socket_info* si;
-	
+
 	if (a==0){
 	if (a==0){
 		LOG(L_CRIT,"BUG: fix_actions: null pointer\n");
 		LOG(L_CRIT,"BUG: fix_actions: null pointer\n");
 		return E_BUG;
 		return E_BUG;
@@ -208,25 +207,25 @@ static int fix_actions(struct action* a)
 			case FORWARD_UDP_T:
 			case FORWARD_UDP_T:
 			case SEND_T:
 			case SEND_T:
 			case SEND_TCP_T:
 			case SEND_TCP_T:
-					switch(t->p1_type){
-						case IP_ST: 
+					switch(t->val[0].type){
+						case IP_ST:
 							tmp=strdup(ip_addr2a(
 							tmp=strdup(ip_addr2a(
-										(struct ip_addr*)t->p1.data));
+										(struct ip_addr*)t->val[0].u.data));
 							if (tmp==0){
 							if (tmp==0){
 								LOG(L_CRIT, "ERROR: fix_actions:"
 								LOG(L_CRIT, "ERROR: fix_actions:"
 										"memory allocation failure\n");
 										"memory allocation failure\n");
 								return E_OUT_OF_MEM;
 								return E_OUT_OF_MEM;
 							}
 							}
-							t->p1_type=STRING_ST;
-							t->p1.string=tmp;
+							t->val[0].type=STRING_ST;
+							t->val[0].u.string=tmp;
 							/* no break */
 							/* no break */
 						case STRING_ST:
 						case STRING_ST:
-							s.s = t->p1.string;
+							s.s = t->val[0].u.string;
 							s.len = strlen(s.s);
 							s.len = strlen(s.s);
-							p=add_proxy(&s, t->p2.number, 0); /* FIXME proto*/
+							p=add_proxy(&s, t->val[1].u.number, 0); /* FIXME proto*/
 							if (p==0) return E_BAD_ADDRESS;
 							if (p==0) return E_BAD_ADDRESS;
-							t->p1.data=p;
-							t->p1_type=PROXY_ST;
+							t->val[0].u.data=p;
+							t->val[0].type=PROXY_ST;
 							break;
 							break;
 						case URIHOST_ST:
 						case URIHOST_ST:
 							break;
 							break;
@@ -238,115 +237,129 @@ static int fix_actions(struct action* a)
 					}
 					}
 					break;
 					break;
 			case IF_T:
 			case IF_T:
-				if (t->p1_type!=EXPR_ST){
+				if (t->val[0].type!=EXPR_ST){
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 								"%d for if (should be expr)\n",
 								"%d for if (should be expr)\n",
-								t->p1_type);
+								t->val[0].type);
 					return E_BUG;
 					return E_BUG;
-				}else if( (t->p2_type!=ACTIONS_ST)&&(t->p2_type!=NOSUBTYPE) ){
+				}else if( (t->val[1].type!=ACTIONS_ST)&&(t->val[1].type!=NOSUBTYPE) ){
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 								"%d for if() {...} (should be action)\n",
 								"%d for if() {...} (should be action)\n",
-								t->p2_type);
+								t->val[1].type);
 					return E_BUG;
 					return E_BUG;
-				}else if( (t->p3_type!=ACTIONS_ST)&&(t->p3_type!=NOSUBTYPE) ){
+				}else if( (t->val[2].type!=ACTIONS_ST)&&(t->val[2].type!=NOSUBTYPE) ){
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 								"%d for if() {} else{...}(should be action)\n",
 								"%d for if() {} else{...}(should be action)\n",
-								t->p3_type);
+								t->val[2].type);
 					return E_BUG;
 					return E_BUG;
 				}
 				}
-				if (t->p1.data){
-					if ((ret=fix_expr((struct expr*)t->p1.data))<0)
+				if (t->val[0].u.data){
+					if ((ret=fix_expr((struct expr*)t->val[0].u.data))<0)
 						return ret;
 						return ret;
 				}
 				}
-				if ( (t->p2_type==ACTIONS_ST)&&(t->p2.data) ){
-					if ((ret=fix_actions((struct action*)t->p2.data))<0)
+				if ( (t->val[1].type==ACTIONS_ST)&&(t->val[1].u.data) ){
+					if ((ret=fix_actions((struct action*)t->val[1].u.data))<0)
 						return ret;
 						return ret;
 				}
 				}
-				if ( (t->p3_type==ACTIONS_ST)&&(t->p3.data) ){
-						if ((ret=fix_actions((struct action*)t->p3.data))<0)
+				if ( (t->val[2].type==ACTIONS_ST)&&(t->val[2].u.data) ){
+						if ((ret=fix_actions((struct action*)t->val[2].u.data))<0)
 						return ret;
 						return ret;
 				}
 				}
 				break;
 				break;
 
 
 		        case ASSIGN_T:
 		        case ASSIGN_T:
 		        case ADD_T:
 		        case ADD_T:
-				if (t->p1_type != AVP_ST) {
+				if (t->val[0].type != AVP_ST) {
 					LOG(L_CRIT, "BUG: fix_actions: Invalid left side of assignment\n");
 					LOG(L_CRIT, "BUG: fix_actions: Invalid left side of assignment\n");
 					return E_BUG;
 					return E_BUG;
 				}
 				}
-				if (t->p1.attr->type & AVP_CLASS_DOMAIN) {
+				if (t->val[0].u.attr->type & AVP_CLASS_DOMAIN) {
 					LOG(L_ERR, "ERROR: You cannot change domain attributes from the script, they are read-only\n");
 					LOG(L_ERR, "ERROR: You cannot change domain attributes from the script, they are read-only\n");
 					return E_BUG;
 					return E_BUG;
-				} else if (t->p1.attr->type & AVP_CLASS_GLOBAL) {
+				} else if (t->val[0].u.attr->type & AVP_CLASS_GLOBAL) {
 					LOG(L_ERR, "ERROR: You cannot change global attributes from the script, they are read-only\n");
 					LOG(L_ERR, "ERROR: You cannot change global attributes from the script, they are read-only\n");
 					return E_BUG;
 					return E_BUG;
 				}
 				}
 
 
-				if (t->p2_type == ACTION_ST && t->p2.data) {
-					if ((ret = fix_actions((struct action*)t->p2.data)) < 0) {
+				if (t->val[1].type == ACTION_ST && t->val[1].u.data) {
+					if ((ret = fix_actions((struct action*)t->val[1].u.data)) < 0) {
 						return ret;
 						return ret;
 					}
 					}
-				} else if (t->p2_type == EXPR_ST && t->p2.data) {
-					if ((ret = fix_expr((struct expr*)t->p2.data)) < 0) {
+				} else if (t->val[1].type == EXPR_ST && t->val[1].u.data) {
+					if ((ret = fix_expr((struct expr*)t->val[1].u.data)) < 0) {
 						return ret;
 						return ret;
 					}
 					}
-				} else if (t->p2_type == STRING_ST) {
+				} else if (t->val[1].type == STRING_ST) {
 					int len;
 					int len;
-					len = strlen(t->p2.data);
-					t->p2.str.s = t->p2.data;
-					t->p2.str.len = len;
-				} else if (t->p2_type == SELECT_ST) {
-					if ((ret=resolve_select(t->p2.select)) < 0) {
+					len = strlen(t->val[1].u.data);
+					t->val[1].u.str.s = t->val[1].u.data;
+					t->val[1].u.str.len = len;
+				} else if (t->val[1].type == SELECT_ST) {
+					if ((ret=resolve_select(t->val[1].u.select)) < 0) {
 						BUG("Unable to resolve select\n");
 						BUG("Unable to resolve select\n");
-						print_select(t->p2.select);
+						print_select(t->val[1].u.select);
 						return ret;
 						return ret;
 					}
 					}
 				}
 				}
 				break;
 				break;
 
 
 			case MODULE_T:
 			case MODULE_T:
-				if ((mod=find_module(t->p1.data, &cmd))!=0){
-					DBG("fixing %s %s\n", mod->path, cmd->name);
-					if (cmd->fixup){
-						if (cmd->param_no>0){
-							ret=cmd->fixup(&t->p2.data, 1);
-							t->p2_type=MODFIXUP_ST;
-							if (ret<0) return ret;
-						}
-						if (cmd->param_no>1){
-							ret=cmd->fixup(&t->p3.data, 2);
-							t->p3_type=MODFIXUP_ST;
-							if (ret<0) return ret;
+				cmd = t->val[0].u.data;
+				if (cmd && cmd->fixup) {
+					int i;
+					DBG("fixing %s()\n", cmd->name);
+					/* type cast NUMBER to STRING, old modules may expect all STRING params during fixup */
+					for (i=0; i<t->val[1].u.number; i++) {
+						if (t->val[i+2].type == NUMBER_ST) {
+							char buf[30];
+							snprintf(buf, sizeof(buf)-1, "%ld", t->val[i+2].u.number);
+							/* fixup currently requires string pkg_malloc-aed */
+							t->val[i+2].u.string = pkg_malloc(strlen(buf)+1);
+							if (!t->val[i+2].u.string) {
+								LOG(L_CRIT, "ERROR: cannot translate NUMBER to STRING\n");
+								return E_OUT_OF_MEM;
+							}
+							strcpy(t->val[i+2].u.string, buf);
+							t->val[i+2].type = STRING_ST;
 						}
 						}
 					}
 					}
+					for (i=0; i<t->val[1].u.number; i++) {
+						void *p;
+						p = t->val[i+2].u.data;
+						ret = cmd->fixup(&t->val[i+2].u.data, i+1);
+						if (t->val[i+2].u.data != p)
+							t->val[i+2].type = MODFIXUP_ST;
+						if (ret < 0)
+							return ret;
+					}
 				}
 				}
 				break;
 				break;
 			case FORCE_SEND_SOCKET_T:
 			case FORCE_SEND_SOCKET_T:
-				if (t->p1_type!=SOCKID_ST){
+				if (t->val[0].type!=SOCKID_ST){
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 								"%d for force_send_socket\n",
 								"%d for force_send_socket\n",
-								t->p1_type);
+								t->val[0].type);
 					return E_BUG;
 					return E_BUG;
 				}
 				}
-				he=resolvehost(((struct socket_id*)t->p1.data)->name);
+				he=resolvehost(((struct socket_id*)t->val[0].u.data)->name);
 				if (he==0){
 				if (he==0){
 					LOG(L_ERR, "ERROR: fix_actions: force_send_socket:"
 					LOG(L_ERR, "ERROR: fix_actions: force_send_socket:"
 								" could not resolve %s\n",
 								" could not resolve %s\n",
-							((struct socket_id*)t->p1.data)->name);
+							((struct socket_id*)t->val[0].u.data)->name);
 					return E_BAD_ADDRESS;
 					return E_BAD_ADDRESS;
 				}
 				}
 				hostent2ip_addr(&ip, he, 0);
 				hostent2ip_addr(&ip, he, 0);
-				si=find_si(&ip, ((struct socket_id*)t->p1.data)->port,
-								((struct socket_id*)t->p1.data)->proto);
+				si=find_si(&ip, ((struct socket_id*)t->val[0].u.data)->port,
+								((struct socket_id*)t->val[0].u.data)->proto);
 				if (si==0){
 				if (si==0){
 					LOG(L_ERR, "ERROR: fix_actions: bad force_send_socket"
 					LOG(L_ERR, "ERROR: fix_actions: bad force_send_socket"
 							" argument: %s:%d (ser doesn't listen on it)\n",
 							" argument: %s:%d (ser doesn't listen on it)\n",
-							((struct socket_id*)t->p1.data)->name,
-							((struct socket_id*)t->p1.data)->port);
+							((struct socket_id*)t->val[0].u.data)->name,
+							((struct socket_id*)t->val[0].u.data)->port);
 					return E_BAD_ADDRESS;
 					return E_BAD_ADDRESS;
 				}
 				}
-				t->p1.data=si;
-				t->p1_type=SOCKETINFO_ST;
+				t->val[0].u.data=si;
+				t->val[0].type=SOCKETINFO_ST;
 				break;
 				break;
 		}
 		}
 	}
 	}
@@ -365,7 +378,7 @@ inline static int comp_num(int op, long left, int rtype, union exp_op* r)
 	int_str val;
 	int_str val;
 	avp_t* avp;
 	avp_t* avp;
 	long right;
 	long right;
-	
+
 	if (rtype == AVP_ST) {
 	if (rtype == AVP_ST) {
 		avp = search_avp_by_index(r->attr->type, r->attr->name, &val, r->attr->index);
 		avp = search_avp_by_index(r->attr->type, r->attr->name, &val, r->attr->index);
 		if (avp && !(avp->flags & AVP_VAL_STR)) right = val.n;
 		if (avp && !(avp->flags & AVP_VAL_STR)) right = val.n;
@@ -402,9 +415,9 @@ inline static int comp_str(int op, str* left, int rtype, union exp_op* r, struct
 	int ret;
 	int ret;
 	char backup;
 	char backup;
 	regex_t* re;
 	regex_t* re;
-	
+
 	right=0; /* warning fix */
 	right=0; /* warning fix */
-	
+
 	if (rtype == AVP_ST) {
 	if (rtype == AVP_ST) {
 		avp = search_avp_by_index(r->attr->type, r->attr->name, &val, r->attr->index);
 		avp = search_avp_by_index(r->attr->type, r->attr->name, &val, r->attr->index);
 		if (avp && (avp->flags & AVP_VAL_STR)) right = &val.s;
 		if (avp && (avp->flags & AVP_VAL_STR)) right = &val.s;
@@ -464,7 +477,7 @@ inline static int comp_str(int op, str* left, int rtype, union exp_op* r, struct
 					pkg_free(re);
 					pkg_free(re);
 					left->s[left->len] = backup;
 					left->s[left->len] = backup;
 					goto error;
 					goto error;
-				}				
+				}
 				ret=(regexec(re, left->s, 0, 0, 0)==0);
 				ret=(regexec(re, left->s, 0, 0, 0)==0);
 				regfree(re);
 				regfree(re);
 				pkg_free(re);
 				pkg_free(re);
@@ -478,7 +491,7 @@ inline static int comp_str(int op, str* left, int rtype, union exp_op* r, struct
 			goto error;
 			goto error;
 	}
 	}
 	return ret;
 	return ret;
-	
+
 error:
 error:
 	return -1;
 	return -1;
 }
 }
@@ -488,7 +501,7 @@ error:
 inline static int comp_string(int op, char* left, int rtype, union exp_op* r)
 inline static int comp_string(int op, char* left, int rtype, union exp_op* r)
 {
 {
 	int ret;
 	int ret;
-	
+
 	ret=-1;
 	ret=-1;
 	switch(op){
 	switch(op){
 		case EQUAL_OP:
 		case EQUAL_OP:
@@ -520,7 +533,7 @@ inline static int comp_string(int op, char* left, int rtype, union exp_op* r)
 			goto error;
 			goto error;
 	}
 	}
 	return ret;
 	return ret;
-	
+
 error:
 error:
 	return -1;
 	return -1;
 }
 }
@@ -574,7 +587,7 @@ inline static int comp_select(int op, select_t* sel, int rtype, union exp_op* r,
 	switch(op) {
 	switch(op) {
 	case NO_OP: return 1;
 	case NO_OP: return 1;
 	case BINOR_OP:
 	case BINOR_OP:
-	case BINAND_OP:  
+	case BINAND_OP:
 		ERR("Binary operators cannot be used with string selects\n");
 		ERR("Binary operators cannot be used with string selects\n");
 		return -1;
 		return -1;
 	}
 	}
@@ -585,7 +598,7 @@ inline static int comp_select(int op, select_t* sel, int rtype, union exp_op* r,
 inline static int check_self_op(int op, str* s, unsigned short p)
 inline static int check_self_op(int op, str* s, unsigned short p)
 {
 {
 	int ret;
 	int ret;
-	
+
 	ret=check_self(s, p, 0);
 	ret=check_self(s, p, 0);
 	switch(op){
 	switch(op){
 		case EQUAL_OP:
 		case EQUAL_OP:
@@ -683,7 +696,7 @@ inline static int comp_ip(int op, struct ip_addr* ip, int rtype, union exp_op* r
 error_op:
 error_op:
 	LOG(L_CRIT, "BUG: comp_ip: invalid operator %d\n", op);
 	LOG(L_CRIT, "BUG: comp_ip: invalid operator %d\n", op);
 	return -1;
 	return -1;
-	
+
 }
 }
 
 
 
 
@@ -695,14 +708,14 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 	struct onsend_info* snd_inf;
 	struct onsend_info* snd_inf;
 	struct ip_addr ip;
 	struct ip_addr ip;
 	ret=E_BUG;
 	ret=E_BUG;
-	
+
 	if (e->type!=ELEM_T){
 	if (e->type!=ELEM_T){
 		LOG(L_CRIT," BUG: eval_elem: invalid type\n");
 		LOG(L_CRIT," BUG: eval_elem: invalid type\n");
 		goto error;
 		goto error;
 	}
 	}
 	switch(e->l_type){
 	switch(e->l_type){
 	case METHOD_O:
 	case METHOD_O:
-		ret=comp_str(e->op, &msg->first_line.u.request.method, 
+		ret=comp_str(e->op, &msg->first_line.u.request.method,
 			     e->r_type, &e->r, msg);
 			     e->r_type, &e->r, msg);
 		break;
 		break;
 	case URI_O:
 	case URI_O:
@@ -713,7 +726,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 						       msg->parsed_uri.port_no?
 						       msg->parsed_uri.port_no?
 						       msg->parsed_uri.port_no:SIP_PORT);
 						       msg->parsed_uri.port_no:SIP_PORT);
 			}else{
 			}else{
-				ret=comp_str(e->op, &msg->new_uri, 
+				ret=comp_str(e->op, &msg->new_uri,
 					     e->r_type, &e->r, msg);
 					     e->r_type, &e->r, msg);
 			}
 			}
 		}else{
 		}else{
@@ -728,7 +741,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 			}
 			}
 		}
 		}
 		break;
 		break;
-		
+
 	case FROM_URI_O:
 	case FROM_URI_O:
 		if (parse_from_header(msg)!=0){
 		if (parse_from_header(msg)!=0){
 			LOG(L_ERR, "ERROR: eval_elem: bad or missing"
 			LOG(L_ERR, "ERROR: eval_elem: bad or missing"
@@ -770,15 +783,15 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 				     e->r_type, &e->r, msg);
 				     e->r_type, &e->r, msg);
 		}
 		}
 		break;
 		break;
-		
+
 	case SRCIP_O:
 	case SRCIP_O:
 		ret=comp_ip(e->op, &msg->rcv.src_ip, e->r_type, &e->r);
 		ret=comp_ip(e->op, &msg->rcv.src_ip, e->r_type, &e->r);
 		break;
 		break;
-		
+
 	case DSTIP_O:
 	case DSTIP_O:
 		ret=comp_ip(e->op, &msg->rcv.dst_ip, e->r_type, &e->r);
 		ret=comp_ip(e->op, &msg->rcv.dst_ip, e->r_type, &e->r);
 		break;
 		break;
-	
+
 	case SNDIP_O:
 	case SNDIP_O:
 		snd_inf=get_onsend_info();
 		snd_inf=get_onsend_info();
 		if (snd_inf && snd_inf->send_sock){
 		if (snd_inf && snd_inf->send_sock){
@@ -787,7 +800,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 			BUG("eval_elem: snd_ip unknown (not in a onsend_route?)\n");
 			BUG("eval_elem: snd_ip unknown (not in a onsend_route?)\n");
 		}
 		}
 		break;
 		break;
-	
+
 	case TOIP_O:
 	case TOIP_O:
 		snd_inf=get_onsend_info();
 		snd_inf=get_onsend_info();
 		if (snd_inf && snd_inf->to){
 		if (snd_inf && snd_inf->to){
@@ -807,57 +820,57 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 		if (ret<=0) ret=0;
 		if (ret<=0) ret=0;
 		else ret=1;
 		else ret=1;
 		break;
 		break;
-		
+
 	case SRCPORT_O:
 	case SRCPORT_O:
-		ret=comp_num(e->op, (int)msg->rcv.src_port, 
+		ret=comp_num(e->op, (int)msg->rcv.src_port,
 			     e->r_type, &e->r);
 			     e->r_type, &e->r);
 		break;
 		break;
-		
+
 	case DSTPORT_O:
 	case DSTPORT_O:
-		ret=comp_num(e->op, (int)msg->rcv.dst_port, 
+		ret=comp_num(e->op, (int)msg->rcv.dst_port,
 			     e->r_type, &e->r);
 			     e->r_type, &e->r);
 		break;
 		break;
-		
+
 	case SNDPORT_O:
 	case SNDPORT_O:
 		snd_inf=get_onsend_info();
 		snd_inf=get_onsend_info();
 		if (snd_inf && snd_inf->send_sock){
 		if (snd_inf && snd_inf->send_sock){
-			ret=comp_num(e->op, (int)snd_inf->send_sock->port_no, 
+			ret=comp_num(e->op, (int)snd_inf->send_sock->port_no,
 				     e->r_type, &e->r);
 				     e->r_type, &e->r);
 		}else{
 		}else{
 			BUG("eval_elem: snd_port unknown (not in a onsend_route?)\n");
 			BUG("eval_elem: snd_port unknown (not in a onsend_route?)\n");
 		}
 		}
 		break;
 		break;
-		
+
 	case TOPORT_O:
 	case TOPORT_O:
 		snd_inf=get_onsend_info();
 		snd_inf=get_onsend_info();
 		if (snd_inf && snd_inf->to){
 		if (snd_inf && snd_inf->to){
-			ret=comp_num(e->op, (int)su_getport(snd_inf->to), 
+			ret=comp_num(e->op, (int)su_getport(snd_inf->to),
 				     e->r_type, &e->r);
 				     e->r_type, &e->r);
 		}else{
 		}else{
 			BUG("eval_elem: to_port unknown (not in a onsend_route?)\n");
 			BUG("eval_elem: to_port unknown (not in a onsend_route?)\n");
 		}
 		}
 		break;
 		break;
-		
+
 	case PROTO_O:
 	case PROTO_O:
-		ret=comp_num(e->op, msg->rcv.proto, 
+		ret=comp_num(e->op, msg->rcv.proto,
 			     e->r_type, &e->r);
 			     e->r_type, &e->r);
 		break;
 		break;
-		
+
 	case SNDPROTO_O:
 	case SNDPROTO_O:
 		snd_inf=get_onsend_info();
 		snd_inf=get_onsend_info();
 		if (snd_inf && snd_inf->send_sock){
 		if (snd_inf && snd_inf->send_sock){
-			ret=comp_num(e->op, snd_inf->send_sock->proto, 
+			ret=comp_num(e->op, snd_inf->send_sock->proto,
 				     e->r_type, &e->r);
 				     e->r_type, &e->r);
 		}else{
 		}else{
 			BUG("eval_elem: snd_proto unknown (not in a onsend_route?)\n");
 			BUG("eval_elem: snd_proto unknown (not in a onsend_route?)\n");
 		}
 		}
 		break;
 		break;
-		
+
 	case AF_O:
 	case AF_O:
-		ret=comp_num(e->op, (int)msg->rcv.src_ip.af, 
+		ret=comp_num(e->op, (int)msg->rcv.src_ip.af,
 			     e->r_type, &e->r);
 			     e->r_type, &e->r);
 		break;
 		break;
-		
+
 	case SNDAF_O:
 	case SNDAF_O:
 		snd_inf=get_onsend_info();
 		snd_inf=get_onsend_info();
 		if (snd_inf && snd_inf->send_sock){
 		if (snd_inf && snd_inf->send_sock){
@@ -870,10 +883,10 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 
 
 	case MSGLEN_O:
 	case MSGLEN_O:
 		if ((snd_inf=get_onsend_info())!=0){
 		if ((snd_inf=get_onsend_info())!=0){
-			ret=comp_num(e->op, (int)snd_inf->len, 
+			ret=comp_num(e->op, (int)snd_inf->len,
 					e->r_type, &e->r);
 					e->r_type, &e->r);
 		}else{
 		}else{
-			ret=comp_num(e->op, (int)msg->len, 
+			ret=comp_num(e->op, (int)msg->len,
 					e->r_type, &e->r);
 					e->r_type, &e->r);
 		}
 		}
 		break;
 		break;
@@ -885,7 +898,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 	case AVP_O:
 	case AVP_O:
 		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r, msg);
 		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r, msg);
 		break;
 		break;
-		
+
 	case SELECT_O:
 	case SELECT_O:
 		ret = comp_select(e->op, e->l.select, e->r_type, &e->r, msg);
 		ret = comp_select(e->op, e->l.select, e->r_type, &e->r, msg);
 		break;
 		break;
@@ -906,7 +919,7 @@ int eval_expr(struct expr* e, struct sip_msg* msg)
 {
 {
 	static int rec_lev=0;
 	static int rec_lev=0;
 	int ret;
 	int ret;
-	
+
 	rec_lev++;
 	rec_lev++;
 	if (rec_lev>MAX_REC_LEV){
 	if (rec_lev>MAX_REC_LEV){
 		LOG(L_CRIT, "ERROR: eval_expr: too many expressions (%d)\n",
 		LOG(L_CRIT, "ERROR: eval_expr: too many expressions (%d)\n",
@@ -914,7 +927,7 @@ int eval_expr(struct expr* e, struct sip_msg* msg)
 		ret=-1;
 		ret=-1;
 		goto skip;
 		goto skip;
 	}
 	}
-	
+
 	if (e->type==ELEM_T){
 	if (e->type==ELEM_T){
 		ret=eval_elem(e, msg);
 		ret=eval_elem(e, msg);
 	}else if (e->type==EXP_T){
 	}else if (e->type==EXP_T){
@@ -974,7 +987,7 @@ int add_actions(struct action* a, struct action** head)
 	if ((ret=fix_actions(a))!=0) goto error;
 	if ((ret=fix_actions(a))!=0) goto error;
 	push(a,head);
 	push(a,head);
 	return 0;
 	return 0;
-	
+
 error:
 error:
 	return ret;
 	return ret;
 }
 }

+ 227 - 235
route_struct.c

@@ -22,8 +22,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * GNU General Public License for more details.
  *
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 /* History:
 /* History:
@@ -43,6 +43,7 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
+#include <stdarg.h>
 
 
 #include "dprint.h"
 #include "dprint.h"
 #include "ip_addr.h"
 #include "ip_addr.h"
@@ -85,51 +86,42 @@ error:
 }
 }
 
 
 
 
-
-struct action* mk_action(int type, int p1_type, int p2_type,
-			 void* p1, void* p2)
-{
+struct action* mk_action(int type, int count/* of couples {type,val} */, .../* int type1, void *val1 [, int type2, void *val2, ...] */) {
+	va_list args;
+	int i;
 	struct action* a;
 	struct action* a;
-	a=(struct action*)pkg_malloc(sizeof(struct action));
+
+	a = (struct action*)pkg_malloc(sizeof(struct action));
 	if (a==0) goto  error;
 	if (a==0) goto  error;
-	memset(a,0,sizeof(struct action));
+	memset(a, 0, sizeof(struct action));
 	a->type=type;
 	a->type=type;
-	a->p1_type=p1_type;
-	a->p2_type=p2_type;
-	a->p1.string=(char*) p1;
-	a->p2.string=(char*) p2;
+	a->count = (count > MAX_ACTIONS)?MAX_ACTIONS:count;
+
+	va_start(args, count);
+	for (i=0; i<a->count; i++) {
+		a->val[i].type = va_arg(args, int);
+		a->val[i].u.data = va_arg(args, void *);
+
+		DBG("ACTION_#%d #%d/%d: %d(%x)/ %p\n", a->type, i, a->count, a->val[i].type, a->val[i].type, a->val[i].u.data);
+	}
+	va_end(args);
+
 	a->next=0;
 	a->next=0;
 	return a;
 	return a;
-	
+
 error:
 error:
 	LOG(L_CRIT, "ERROR: mk_action: memory allocation failure\n");
 	LOG(L_CRIT, "ERROR: mk_action: memory allocation failure\n");
 	return 0;
 	return 0;
-
-}
-
-
-struct action* mk_action3(int type, int p1_type, int p2_type, int p3_type,
-							void* p1, void* p2, void* p3)
-{
-	struct action* a;
-
-	a=mk_action(type, p1_type, p2_type, p1, p2);
-	if (a){
-			a->p3_type=p3_type;
-			a->p3.data=p3;
-	}
-	return a;
 }
 }
 
 
 
 
-
 struct action* append_action(struct action* a, struct action* b)
 struct action* append_action(struct action* a, struct action* b)
 {
 {
 	struct action *t;
 	struct action *t;
 	if (b==0) return a;
 	if (b==0) return a;
 	if (a==0) return b;
 	if (a==0) return b;
-	
-	for(t=a;t->next;t=t->next);
+
+	for(t=a; t->next; t=t->next);
 	t->next=b;
 	t->next=b;
 	return a;
 	return a;
 }
 }
@@ -178,7 +170,7 @@ void print_expr(struct expr* exp)
 		        case SELECT_ST:
 		        case SELECT_ST:
 			        DBG("select");
 			        DBG("select");
 				break;
 				break;
-			
+
 			default:
 			default:
 				DBG("UNKNOWN");
 				DBG("UNKNOWN");
 		}
 		}
@@ -210,7 +202,7 @@ void print_expr(struct expr* exp)
 				DBG("<UNKNOWN>");
 				DBG("<UNKNOWN>");
 		}
 		}
 		switch(exp->r_type){
 		switch(exp->r_type){
-			case NOSUBTYPE: 
+			case NOSUBTYPE:
 					DBG("N/A");
 					DBG("N/A");
 					break;
 					break;
 			case STRING_ST:
 			case STRING_ST:
@@ -256,7 +248,7 @@ void print_expr(struct expr* exp)
 					print_expr(exp->r.expr);
 					print_expr(exp->r.expr);
 					DBG(" )");
 					DBG(" )");
 					break;
 					break;
-			case NOT_OP:	
+			case NOT_OP:
 					DBG("NOT( ");
 					DBG("NOT( ");
 					print_expr(exp->l.expr);
 					print_expr(exp->l.expr);
 					DBG(" )");
 					DBG(" )");
@@ -264,223 +256,223 @@ void print_expr(struct expr* exp)
 			default:
 			default:
 					DBG("UNKNOWN_EXP ");
 					DBG("UNKNOWN_EXP ");
 		}
 		}
-					
+
 	}else{
 	}else{
 		DBG("ERROR:print_expr: unknown type\n");
 		DBG("ERROR:print_expr: unknown type\n");
 	}
 	}
 }
 }
-					
 
 
-					
+
+
 
 
 void print_action(struct action* t)
 void print_action(struct action* t)
 {
 {
 	switch(t->type){
 	switch(t->type){
-	case FORWARD_T:
-		DBG("forward(");
-		break;
-	case FORWARD_TCP_T:
-		DBG("forward_tcp(");
-		break;
-	case FORWARD_UDP_T:
-		DBG("forward_udp(");
-		break;
-	case SEND_T:
-		DBG("send(");
-		break;
-	case SEND_TCP_T:
-		DBG("send_tcp(");
-		break;
-	case DROP_T:
-		DBG("drop(");
-		break;
-	case LOG_T:
-		DBG("log(");
-		break;
-	case ERROR_T:
-		DBG("error(");
-		break;
-	case ROUTE_T:
-		DBG("route(");
-		break;
-	case EXEC_T:
-		DBG("exec(");
-		break;
-	case REVERT_URI_T:
-		DBG("revert_uri(");
-		break;
-	case STRIP_T:
-		DBG("strip(");
-		break;
-	case APPEND_BRANCH_T:
-		DBG("append_branch(");
-		break;
-	case PREFIX_T:
-		DBG("prefix(");
-		break;
-	case LEN_GT_T:
-		DBG("len_gt(");
-		break;
-	case SETFLAG_T:
-		DBG("setflag(");
-		break;
-	case RESETFLAG_T:
-		DBG("resetflag(");
-		break;
-	case ISFLAGSET_T:
-		DBG("isflagset(");
-		break;
-	case SET_HOST_T:
-		DBG("sethost(");
-		break;
-	case SET_HOSTPORT_T:
-		DBG("sethostport(");
-		break;
-	case SET_USER_T:
-		DBG("setuser(");
-		break;
-	case SET_USERPASS_T:
-		DBG("setuserpass(");
-		break;
-	case SET_PORT_T:
-		DBG("setport(");
-		break;
-	case SET_URI_T:
-		DBG("seturi(");
-		break;
-	case IF_T:
-		DBG("if (");
-		break;
-	case MODULE_T:
-		DBG(" external_module_call(");
-		break;
-	case FORCE_RPORT_T:
-		DBG("force_rport(");
-		break;
-	case SET_ADV_ADDR_T:
-		DBG("set_advertised_address(");
-		break;
-	case SET_ADV_PORT_T:
-		DBG("set_advertised_port(");
-		break;
-	case FORCE_TCP_ALIAS_T:
-		DBG("force_tcp_alias(");
-		break;
-	case LOAD_AVP_T:
-		DBG("load_avp(");
-		break;
-	case AVP_TO_URI_T:
-		DBG("avp_to_attr");
-		break;
-	case FORCE_SEND_SOCKET_T:
-		DBG("force_send_socket");
-		break;
-	case ASSIGN_T
-:		DBG("assign(");
-		break;
-	case ADD_T:
-		DBG("assign_add(");
-		break;
-	default:
-		DBG("UNKNOWN(");
+		case FORWARD_T:
+			DBG("forward(");
+			break;
+		case FORWARD_TCP_T:
+			DBG("forward_tcp(");
+			break;
+		case FORWARD_UDP_T:
+			DBG("forward_udp(");
+			break;
+		case SEND_T:
+			DBG("send(");
+			break;
+		case SEND_TCP_T:
+			DBG("send_tcp(");
+			break;
+		case DROP_T:
+			DBG("drop(");
+			break;
+		case LOG_T:
+			DBG("log(");
+			break;
+		case ERROR_T:
+			DBG("error(");
+			break;
+		case ROUTE_T:
+			DBG("route(");
+			break;
+		case EXEC_T:
+			DBG("exec(");
+			break;
+		case REVERT_URI_T:
+			DBG("revert_uri(");
+			break;
+		case STRIP_T:
+			DBG("strip(");
+			break;
+		case APPEND_BRANCH_T:
+			DBG("append_branch(");
+			break;
+		case PREFIX_T:
+			DBG("prefix(");
+			break;
+		case LEN_GT_T:
+			DBG("len_gt(");
+			break;
+		case SETFLAG_T:
+			DBG("setflag(");
+			break;
+		case RESETFLAG_T:
+			DBG("resetflag(");
+			break;
+		case ISFLAGSET_T:
+			DBG("isflagset(");
+			break;
+		case SET_HOST_T:
+			DBG("sethost(");
+			break;
+		case SET_HOSTPORT_T:
+			DBG("sethostport(");
+			break;
+		case SET_USER_T:
+			DBG("setuser(");
+			break;
+		case SET_USERPASS_T:
+			DBG("setuserpass(");
+			break;
+		case SET_PORT_T:
+			DBG("setport(");
+			break;
+		case SET_URI_T:
+			DBG("seturi(");
+			break;
+		case IF_T:
+			DBG("if (");
+			break;
+		case MODULE_T:
+			DBG(" external_module_call(");
+			break;
+		case FORCE_RPORT_T:
+			DBG("force_rport(");
+			break;
+		case SET_ADV_ADDR_T:
+			DBG("set_advertised_address(");
+			break;
+		case SET_ADV_PORT_T:
+			DBG("set_advertised_port(");
+			break;
+		case FORCE_TCP_ALIAS_T:
+			DBG("force_tcp_alias(");
+			break;
+		case LOAD_AVP_T:
+			DBG("load_avp(");
+			break;
+		case AVP_TO_URI_T:
+			DBG("avp_to_attr");
+			break;
+		case FORCE_SEND_SOCKET_T:
+			DBG("force_send_socket");
+			break;
+		case ASSIGN_T
+	:		DBG("assign(");
+			break;
+		case ADD_T:
+			DBG("assign_add(");
+			break;
+		default:
+			DBG("UNKNOWN(");
 	}
 	}
-	switch(t->p1_type){
-	case STRING_ST:
-		DBG("\"%s\"", ZSW(t->p1.string));
-		break;
-	case NUMBER_ST:
-		DBG("%lu",t->p1.number);
-		break;
-	case IP_ST:
-		print_ip("", (struct ip_addr*)t->p1.data, "");
-		break;
-	case EXPR_ST:
-		print_expr((struct expr*)t->p1.data);
-		break;
-	case ACTIONS_ST:
-		print_actions((struct action*)t->p1.data);
-		break;
-	case CMDF_ST:
-		DBG("f_ptr<%p>",t->p1.data);
-		break;
-	case SOCKID_ST:
-		DBG("%d:%s:%d",
-		    ((struct socket_id*)t->p1.data)->proto,
-		    ZSW(((struct socket_id*)t->p1.data)->name),
-		    ((struct socket_id*)t->p1.data)->port
-		    );
-		break;
-	case AVP_ST:
-		DBG("avp(%u,%.*s)", t->p1.attr->type, t->p1.attr->name.s.len, ZSW(t->p1.attr->name.s.s));
-		break;
-	case SELECT_ST:
-		DBG("select");
-		break;
-	default:
-		DBG("type<%d>", t->p1_type);
+	switch(t->val[0].type){
+		case STRING_ST:
+			DBG("\"%s\"", ZSW(t->val[0].u.string));
+			break;
+		case NUMBER_ST:
+			DBG("%lu",t->val[0].u.number);
+			break;
+		case IP_ST:
+			print_ip("", (struct ip_addr*)t->val[0].u.data, "");
+			break;
+		case EXPR_ST:
+			print_expr((struct expr*)t->val[0].u.data);
+			break;
+		case ACTIONS_ST:
+			print_actions((struct action*)t->val[0].u.data);
+			break;
+		case MODEXP_ST:
+			DBG("f_ptr<%p>",t->val[0].u.data);
+			break;
+		case SOCKID_ST:
+			DBG("%d:%s:%d",
+			((struct socket_id*)t->val[0].u.data)->proto,
+			ZSW(((struct socket_id*)t->val[0].u.data)->name),
+			((struct socket_id*)t->val[0].u.data)->port
+			);
+			break;
+		case AVP_ST:
+			DBG("avp(%u,%.*s)", t->val[0].u.attr->type, t->val[0].u.attr->name.s.len, ZSW(t->val[0].u.attr->name.s.s));
+			break;
+		case SELECT_ST:
+			DBG("select");
+			break;
+		default:
+			DBG("type<%d>", t->val[0].type);
 	}
 	}
 	if (t->type==IF_T) DBG(") {");
 	if (t->type==IF_T) DBG(") {");
-	switch(t->p2_type){
-	case NOSUBTYPE:
-		break;
-	case STRING_ST:
-		DBG(", \"%s\"", ZSW(t->p2.string));
-		break;
-	case NUMBER_ST:
-		DBG(", %lu",t->p2.number);
-		break;
-	case EXPR_ST:
-		print_expr((struct expr*)t->p2.data);
-		break;
-	case ACTION_ST:
-	case ACTIONS_ST:
-		print_actions((struct action*)t->p2.data);
-		break;
-		
-	case SOCKID_ST:
-		DBG("%d:%s:%d",
-		    ((struct socket_id*)t->p1.data)->proto,
-		    ZSW(((struct socket_id*)t->p1.data)->name),
-		    ((struct socket_id*)t->p1.data)->port
-		    );
-		break;
-	case AVP_ST:
-		DBG(", avp(%u,%.*s)", t->p2.attr->type, t->p2.attr->name.s.len, ZSW(t->p2.attr->name.s.s));
-		break;
-	case SELECT_ST:
-		DBG("select");
-		break;
-	default:
-		DBG(", type<%d>", t->p2_type);
+	switch(t->val[1].type){
+		case NOSUBTYPE:
+			break;
+		case STRING_ST:
+			DBG(", \"%s\"", ZSW(t->val[1].u.string));
+			break;
+		case NUMBER_ST:
+			DBG(", %lu",t->val[1].u.number);
+			break;
+		case EXPR_ST:
+			print_expr((struct expr*)t->val[1].u.data);
+			break;
+		case ACTION_ST:
+		case ACTIONS_ST:
+			print_actions((struct action*)t->val[1].u.data);
+			break;
+
+		case SOCKID_ST:
+			DBG("%d:%s:%d",
+			((struct socket_id*)t->val[0].u.data)->proto,
+			ZSW(((struct socket_id*)t->val[0].u.data)->name),
+			((struct socket_id*)t->val[0].u.data)->port
+			);
+			break;
+		case AVP_ST:
+			DBG(", avp(%u,%.*s)", t->val[1].u.attr->type, t->val[1].u.attr->name.s.len, ZSW(t->val[1].u.attr->name.s.s));
+			break;
+		case SELECT_ST:
+			DBG("select");
+			break;
+		default:
+			DBG(", type<%d>", t->val[1].type);
 	}
 	}
 	if (t->type==IF_T) DBG("} else {");
 	if (t->type==IF_T) DBG("} else {");
-	switch(t->p3_type){
-	case NOSUBTYPE:
-		break;
-	case STRING_ST:
-		DBG(", \"%s\"", ZSW(t->p3.string));
-		break;
-	case NUMBER_ST:
-		DBG(", %lu",t->p3.number);
-		break;
-	case EXPR_ST:
-		print_expr((struct expr*)t->p3.data);
-		break;
-	case ACTIONS_ST:
-		print_actions((struct action*)t->p3.data);
-		break;
-	case SOCKID_ST:
-		DBG("%d:%s:%d",
-		    ((struct socket_id*)t->p1.data)->proto,
-		    ZSW(((struct socket_id*)t->p1.data)->name),
-		    ((struct socket_id*)t->p1.data)->port
-		    );
-		break;
-	default:
-		DBG(", type<%d>", t->p3_type);
+	switch(t->val[2].type){
+		case NOSUBTYPE:
+			break;
+		case STRING_ST:
+			DBG(", \"%s\"", ZSW(t->val[2].u.string));
+			break;
+		case NUMBER_ST:
+			DBG(", %lu",t->val[2].u.number);
+			break;
+		case EXPR_ST:
+			print_expr((struct expr*)t->val[2].u.data);
+			break;
+		case ACTIONS_ST:
+			print_actions((struct action*)t->val[2].u.data);
+			break;
+		case SOCKID_ST:
+			DBG("%d:%s:%d",
+			((struct socket_id*)t->val[0].u.data)->proto,
+			ZSW(((struct socket_id*)t->val[0].u.data)->name),
+			((struct socket_id*)t->val[0].u.data)->port
+			);
+			break;
+		default:
+			DBG(", type<%d>", t->val[2].type);
 	}
 	}
 	if (t->type==IF_T) DBG("}; ");
 	if (t->type==IF_T) DBG("}; ");
-	else	DBG("); ");
+		else	DBG("); ");
 }
 }
 
 
 void print_actions(struct action* a)
 void print_actions(struct action* a)

+ 24 - 29
route_struct.h

@@ -21,8 +21,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * GNU General Public License for more details.
  *
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 /* History:
 /* History:
@@ -50,11 +50,11 @@
  * Other important values (no macros for them yet):
  * Other important values (no macros for them yet):
  * expr true = 1
  * expr true = 1
  * expr false = 0 (used only inside the expression and if evaluator)
  * expr false = 0 (used only inside the expression and if evaluator)
- * 
+ *
  * action continue  or if used in condition true = 1
  * action continue  or if used in condition true = 1
  * action drop/quit/stop script processing = 0
  * action drop/quit/stop script processing = 0
  * action error or if used in condition false = -1 (<0 and !=EXPR_DROP)
  * action error or if used in condition false = -1 (<0 and !=EXPR_DROP)
- * 
+ *
  */
  */
 
 
 
 
@@ -63,11 +63,11 @@ enum { LOGAND_OP=1, LOGOR_OP, NOT_OP, BINAND_OP, BINOR_OP };
 enum { EQUAL_OP=10, MATCH_OP, GT_OP, LT_OP, GTE_OP, LTE_OP, DIFF_OP, NO_OP };
 enum { EQUAL_OP=10, MATCH_OP, GT_OP, LT_OP, GTE_OP, LTE_OP, DIFF_OP, NO_OP };
 enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O,
 enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O,
 	   DSTIP_O, DSTPORT_O, PROTO_O, AF_O, MSGLEN_O, DEFAULT_O, ACTION_O,
 	   DSTIP_O, DSTPORT_O, PROTO_O, AF_O, MSGLEN_O, DEFAULT_O, ACTION_O,
-	   NUMBER_O, AVP_O, SNDIP_O, SNDPORT_O, TOIP_O, TOPORT_O, SNDPROTO_O, 
+	   NUMBER_O, AVP_O, SNDIP_O, SNDPORT_O, TOIP_O, TOPORT_O, SNDPROTO_O,
 	   SNDAF_O, RETCODE_O, SELECT_O};
 	   SNDAF_O, RETCODE_O, SELECT_O};
 
 
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
-		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, 
+		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T,
 		SET_PORT_T, SET_URI_T, IF_T, MODULE_T,
 		SET_PORT_T, SET_URI_T, IF_T, MODULE_T,
 		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
 		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
 		LEN_GT_T, PREFIX_T, STRIP_T,STRIP_TAIL_T,
 		LEN_GT_T, PREFIX_T, STRIP_T,STRIP_TAIL_T,
@@ -86,10 +86,10 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
                 FORCE_SEND_SOCKET_T,
                 FORCE_SEND_SOCKET_T,
                 ASSIGN_T,
                 ASSIGN_T,
                 ADD_T
                 ADD_T
-       
+
 };
 };
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
-		EXPR_ST, ACTIONS_ST, CMDF_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST,
+		EXPR_ST, ACTIONS_ST, MODEXP_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST,
 		MYSELF_ST, STR_ST, SOCKID_ST, SOCKETINFO_ST, ACTION_ST, AVP_ST, SELECT_ST,
 		MYSELF_ST, STR_ST, SOCKID_ST, SOCKETINFO_ST, ACTION_ST, AVP_ST, SELECT_ST,
 		RETCODE_ST};
 		RETCODE_ST};
 
 
@@ -109,7 +109,7 @@ union exp_op {
 	regex_t* re;
 	regex_t* re;
 	struct net* net;
 	struct net* net;
 };
 };
-	
+
 struct expr{
 struct expr{
 	int type; /* exp, exp_elem */
 	int type; /* exp, exp_elem */
 	int op; /* and, or, not | ==,  =~ */
 	int op; /* and, or, not | ==,  =~ */
@@ -118,41 +118,36 @@ struct expr{
 	union exp_op r;
 	union exp_op r;
 };
 };
 
 
-typedef union {
-	long number;
-	char* string;
-	str str;
-	void* data;
-	avp_spec_t* attr;
-	select_t* select;
+typedef struct {
+	int type;
+	union {
+		long number;
+		char* string;
+		str str;
+		void* data;
+		avp_spec_t* attr;
+		select_t* select;
+	} u;
 } action_u_t;
 } action_u_t;
 
 
+#define MAX_ACTIONS 4
+
 struct action{
 struct action{
 	int type;  /* forward, drop, log, send ...*/
 	int type;  /* forward, drop, log, send ...*/
-	int p1_type;
-	int p2_type;
-	int p3_type;
-	action_u_t p1, p2, p3; /* tm module expects these parameters to be adjacent */
+	int count;
+	action_u_t val[MAX_ACTIONS];
 	struct action* next;
 	struct action* next;
 };
 };
 
 
 struct expr* mk_exp(int op, struct expr* left, struct expr* right);
 struct expr* mk_exp(int op, struct expr* left, struct expr* right);
 struct expr* mk_elem(int op, int ltype, void* lparam, int rtype, void* rparam);
 struct expr* mk_elem(int op, int ltype, void* lparam, int rtype, void* rparam);
 
 
-struct action* mk_action(int type, int p1_type, int p2_type,
-							void* p1, void* p2);
-struct action* mk_action3(int type, int p1_type, int p2_type, int p3_type, 
-							void* p1, void* p2, void* p3);
+struct action* mk_action(int type, int count/* of couples {type,val} */, .../* int type1, void *val1 [, int type2, void *val2, ...] */);
 struct action* append_action(struct action* a, struct action* b);
 struct action* append_action(struct action* a, struct action* b);
 
 
-
 void print_action(struct action* a);
 void print_action(struct action* a);
 void print_actions(struct action* a);
 void print_actions(struct action* a);
 void print_expr(struct expr* exp);
 void print_expr(struct expr* exp);
 
 
-
-
-
-
 #endif
 #endif
 
 

+ 32 - 25
sr_module.c

@@ -33,6 +33,7 @@
  *  2003-03-29  cleaning pkg_mallocs introduced (jiri)
  *  2003-03-29  cleaning pkg_mallocs introduced (jiri)
  *  2003-04-24  module version checking introduced (jiri)
  *  2003-04-24  module version checking introduced (jiri)
  *  2004-09-19  compile flags are checked too (andrei)
  *  2004-09-19  compile flags are checked too (andrei)
+ *  2005-01-07  removed find_module-overloading problems, added find_export_record
  */
  */
 
 
 
 
@@ -42,6 +43,7 @@
 #include "mem/mem.h"
 #include "mem/mem.h"
 #include "core_cmd.h"
 #include "core_cmd.h"
 #include "ut.h"
 #include "ut.h"
+#include "route_struct.h"
 
 
 #include <regex.h>
 #include <regex.h>
 #include <dlfcn.h>
 #include <dlfcn.h>
@@ -247,11 +249,12 @@ skip:
 
 
 
 
 
 
-/* searches the module list and returns pointer to the "name" function or
+
+/* searches the module list and returns pointer to the "name" function record or
  * 0 if not found
  * 0 if not found
  * flags parameter is OR value of all flags that must match
  * flags parameter is OR value of all flags that must match
  */
  */
-cmd_function find_export(char* name, int param_no, int flags)
+cmd_export_t* find_export_record(char* name, int param_no, int flags)
 {
 {
 	struct sr_module* t;
 	struct sr_module* t;
 	cmd_export_t* cmd;
 	cmd_export_t* cmd;
@@ -262,17 +265,25 @@ cmd_function find_export(char* name, int param_no, int flags)
 			   (cmd->param_no==param_no) &&
 			   (cmd->param_no==param_no) &&
 			   ((cmd->flags & flags) == flags)
 			   ((cmd->flags & flags) == flags)
 			  ){
 			  ){
-				DBG("find_export: found <%s> in module %s [%s]\n",
+				DBG("find_export_record: found <%s> in module %s [%s]\n",
 				    name, t->exports->name, t->path);
 				    name, t->exports->name, t->path);
-				return cmd->function;
+				return cmd;
 			}
 			}
 		}
 		}
 	}
 	}
-	DBG("find_export: <%s> not found \n", name);
+	DBG("find_export_record: <%s> not found \n", name);
 	return 0;
 	return 0;
 }
 }
 
 
 
 
+cmd_function find_export(char* name, int param_no, int flags)
+{
+	cmd_export_t* cmd;
+	cmd = find_export_record(name, param_no, flags);
+	return cmd?cmd->function:0;
+}
+
+
 rpc_export_t* find_rpc_export(char* name, int flags)
 rpc_export_t* find_rpc_export(char* name, int flags)
 {
 {
 	struct sr_module* t;
 	struct sr_module* t;
@@ -366,26 +377,6 @@ void* find_param_export(struct sr_module* mod, char* name, modparam_t type_mask,
 }
 }
 
 
 
 
-/* finds a module, given a pointer to a module function *
- * returns pointer to module, & if  c!=0, *c=pointer to the
- * function cmd_export structure*/
-struct sr_module* find_module(void* f, cmd_export_t  **c)
-{
-	struct sr_module* t;
-	cmd_export_t* cmd;
-
-	for (t=modules;t;t=t->next){
-		for(cmd=t->exports->cmds; cmd && cmd->name; cmd++)
-			if (f==(void*)cmd->function) {
-				if (c) *c=cmd;
-				return t;
-			}
-	}
-	return 0;
-}
-
-
-
 void destroy_modules()
 void destroy_modules()
 {
 {
 	struct sr_module* t, *foo;
 	struct sr_module* t, *foo;
@@ -657,3 +648,19 @@ int fixup_regex_2(void** param, int param_no)
 
 
 	return 0;
 	return 0;
 }
 }
+
+action_u_t *fixup_get_param(void **cur_param, int cur_param_no, int required_param_no) {
+	action_u_t *a, a2;
+        /* cur_param points to a->u.string, get pointer to a */
+	a = (void*) ((char *)cur_param - ((char *)&a2.u.string-(char *)&a2));
+	return a + required_param_no - cur_param_no;
+}
+
+int fixup_get_param_count(void **cur_param, int cur_param_no) {
+	action_u_t *a;
+	a = fixup_get_param(cur_param, cur_param_no, 0);
+	if (a)
+		return a->u.number;
+	else
+		return -1;
+}

+ 6 - 4
sr_module.h

@@ -47,6 +47,7 @@
 #include "parser/msg_parser.h" /* for sip_msg */
 #include "parser/msg_parser.h" /* for sip_msg */
 #include "version.h"
 #include "version.h"
 #include "rpc.h"
 #include "rpc.h"
+#include "route_struct.h"
 
 
 typedef  struct module_exports* (*module_register)();
 typedef  struct module_exports* (*module_register)();
 typedef  int (*cmd_function)(struct sip_msg*, char*, char*);
 typedef  int (*cmd_function)(struct sip_msg*, char*, char*);
@@ -133,9 +134,6 @@ struct module_exports{
 };
 };
 
 
 
 
-
-
-
 struct sr_module{
 struct sr_module{
 	char* path;
 	char* path;
 	void* handle;
 	void* handle;
@@ -149,10 +147,10 @@ struct sr_module* modules; /* global module list*/
 int register_builtin_modules();
 int register_builtin_modules();
 int register_module(struct module_exports*, char*,  void*);
 int register_module(struct module_exports*, char*,  void*);
 int load_module(char* path);
 int load_module(char* path);
+cmd_export_t* find_export_record(char* name, int param_no, int flags);
 cmd_function find_export(char* name, int param_no, int flags);
 cmd_function find_export(char* name, int param_no, int flags);
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags);
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags);
 rpc_export_t* find_rpc_export(char* name, int flags);
 rpc_export_t* find_rpc_export(char* name, int flags);
-struct sr_module* find_module(void *f, cmd_export_t** cmd);
 void destroy_modules();
 void destroy_modules();
 int init_child(int rank);
 int init_child(int rank);
 int init_modules(void);
 int init_modules(void);
@@ -205,4 +203,8 @@ int fixup_regex_1(void** param, int param_no);
 /* Compile regular expression in second parameter */
 /* Compile regular expression in second parameter */
 int fixup_regex_2(void** param, int param_no);
 int fixup_regex_2(void** param, int param_no);
 
 
+/* API function to get other parameters from fixup */
+action_u_t *fixup_get_param(void **cur_param, int cur_param_no, int required_param_no);
+int fixup_get_param_count(void **cur_param, int cur_param_no);
+
 #endif /* sr_module_h */
 #endif /* sr_module_h */

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません