Browse code

- added rewrite support (sethost setuser, setuserpass, sethost, setport, sethostport) - allow spaces in header names (e.g: "via :") - case insensitive header name parsing - do not look anymore for the second via for requests (jiri) - fixed config match operator (was ~=, now is =~) - added config file suport for all the command line options (except -f :)) - bumped the version number

Andrei Pelinescu-Onciul authored on 25/09/2001 23:06:39
Showing 15 changed files
... ...
@@ -12,6 +12,7 @@
12 12
 #include "forward.h"
13 13
 #include "udp_server.h"
14 14
 #include "route.h"
15
+#include "msg_parser.h"
15 16
 
16 17
 #include <sys/types.h>
17 18
 #include <sys/socket.h>
... ...
@@ -21,14 +22,19 @@
21 21
 #include <arpa/inet.h>
22 22
 
23 23
 
24
-/* ret= 0 if action -> end of lis t(e.g DROP), >0
25
-   and >0 on error */
24
+/* ret= 0! if action -> end of list(e.g DROP), 
25
+      > 0 to continue processing next actions
26
+   and <0 on error */
26 27
 int do_action(struct action* a, struct sip_msg* msg)
27 28
 {
28 29
 	int ret;
29 30
 	struct sockaddr_in* to;
30 31
 	struct proxy_l* p;
31 32
 	struct route_elem* re;
33
+	char* tmp;
34
+	char *new_uri, *end, *crt;
35
+	int len;
36
+	struct sip_uri uri;
32 37
 
33 38
 	ret=E_BUG;
34 39
 	switch (a->type){
... ...
@@ -139,10 +145,119 @@ int do_action(struct action* a, struct sip_msg* msg)
139 139
 			}
140 140
 			ret=1;
141 141
 			break;
142
+		case SET_HOST_T:
143
+		case SET_HOSTPORT_T:
144
+		case SET_USER_T:
145
+		case SET_USERPASS_T:
146
+		case SET_PORT_T:
147
+		case SET_URI_T:
148
+				if (a->p1_type!=STRING_ST){
149
+					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
150
+							a->p1_type);
151
+					ret=E_BUG;
152
+					break;
153
+				}
154
+				if (a->type==SET_URI_T){
155
+					if (msg->new_uri) free(msg->new_uri);
156
+					len=strlen(a->p1.string);
157
+					msg->new_uri=malloc(len+1);
158
+					if (msg->new_uri==0){
159
+						LOG(L_ERR, "ERROR: do_action: memory allocation failure\n");
160
+						ret=E_OUT_OF_MEM;
161
+						break;
162
+					}
163
+					memcpy(msg->new_uri, a->p1.string, len);
164
+					msg->new_uri[len]=0;
165
+					ret=1;
166
+					break;
167
+				}
168
+
169
+				if (msg->new_uri) tmp=msg->new_uri;
170
+				else tmp=msg->first_line.u.request.uri;
171
+				if (parse_uri(tmp, strlen(tmp), &uri)<0){
172
+					LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping packet\n", tmp);
173
+					ret=E_UNSPEC;
174
+					break;
175
+				}
176
+				
177
+				new_uri=malloc(MAX_URI_SIZE);
178
+				if (new_uri==0){
179
+					LOG(L_ERR, "ERROR: do_action: memory allocation failure\n");
180
+					ret=E_OUT_OF_MEM;
181
+					break;
182
+				}
183
+				end=new_uri+MAX_URI_SIZE;
184
+				crt=new_uri;
185
+				/* begin copying */
186
+				len=strlen("sip:"); if(crt+len>end) goto error_uri;
187
+				memcpy(crt,"sip:",len);crt+=len;
188
+				/* user */
189
+				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) tmp=a->p1.string;
190
+				else tmp=uri.user;
191
+				if (tmp){
192
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
193
+					memcpy(crt,tmp,len);crt+=len;
194
+				}
195
+				if (a->type==SET_USERPASS_T) tmp=0;
196
+				else tmp=uri.passwd;
197
+				/* passwd */
198
+				if (tmp){
199
+					len=strlen(":"); if(crt+len>end) goto error_uri;
200
+					memcpy(crt,":",len);crt+=len;
201
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
202
+					memcpy(crt,tmp,len);crt+=len;
203
+				}
204
+				/* host */
205
+				len=strlen("@"); if(crt+len>end) goto error_uri;
206
+				memcpy(crt,"@",len);crt+=len;
207
+				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) tmp=a->p1.string;
208
+				else tmp=uri.host;
209
+				if (tmp){
210
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
211
+					memcpy(crt,tmp,len);crt+=len;
212
+				}
213
+				/* port */
214
+				if (a->type==SET_HOSTPORT_T) tmp=0;
215
+				else if (a->type==SET_PORT_T) tmp=a->p1.string;
216
+				else tmp=uri.port;
217
+				if (tmp){
218
+					len=strlen(":"); if(crt+len>end) goto error_uri;
219
+					memcpy(crt,":",len);crt+=len;
220
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
221
+					memcpy(crt,tmp,len);crt+=len;
222
+				}
223
+				/* params */
224
+				tmp=uri.params;
225
+				if (tmp){
226
+					len=strlen(";"); if(crt+len>end) goto error_uri;
227
+					memcpy(crt,";",len);crt+=len;
228
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
229
+					memcpy(crt,tmp,len);crt+=len;
230
+				}
231
+				/* headers */
232
+				tmp=uri.headers;
233
+				if (tmp){
234
+					len=strlen("?"); if(crt+len>end) goto error_uri;
235
+					memcpy(crt,"?",len);crt+=len;
236
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
237
+					memcpy(crt,tmp,len);crt+=len;
238
+				}
239
+				*crt=0; /* null terminate the thing */
240
+				/* copy it to the msg */
241
+				if (msg->new_uri) free(msg->new_uri);
242
+				msg->new_uri=new_uri;
243
+				ret=1;
244
+				break;
245
+
142 246
 		default:
143 247
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
144 248
 	}
145 249
 	return ret;
250
+	
251
+error_uri:
252
+	LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
253
+	if (new_uri) free(new_uri);
254
+	return E_UNSPEC;
146 255
 }
147 256
 
148 257
 
... ...
@@ -7,6 +7,7 @@
7 7
 
8 8
 %{
9 9
 	#include "cfg.tab.h"
10
+	#include "dprint.h"
10 11
 	#include <string.h>
11 12
 
12 13
 	/* states */
... ...
@@ -40,6 +41,14 @@ LOG		log
40 40
 ERROR	error
41 41
 ROUTE	route
42 42
 EXEC	exec
43
+SET_HOST		"rewritehost"|"sethost"|"seth"
44
+SET_HOSTPORT	"rewritehostport"|"sethostport"|"sethp"
45
+SET_USER		"rewriteuser"|"setuser"|"setu"
46
+SET_USERPASS	"rewriteuserpass"|"setuserpass"|"setup"
47
+SET_PORT		"rewriteport"|"setport"|"setp"
48
+SET_URI			"rewriteuri"|"seturi"
49
+
50
+
43 51
 /* condition keywords */
44 52
 METHOD	method
45 53
 URI		uri
... ...
@@ -48,7 +57,7 @@ DSTIP	dst_ip
48 48
 /* operators */
49 49
 EQUAL	=
50 50
 EQUAL_T	==
51
-MATCH	~=
51
+MATCH	=~
52 52
 NOT		!|"not"
53 53
 AND		"and"|"&&"|"&"
54 54
 OR		"or"|"||"|"|"
... ...
@@ -60,6 +69,9 @@ LOGSTDERROR	log_stderror
60 60
 LISTEN		listen
61 61
 DNS		 dns
62 62
 REV_DNS	 rev_dns
63
+PORT	port
64
+CHILDREN children
65
+CHECK_VIA	check_via
63 66
 
64 67
 /* values */
65 68
 YES			"yes"|"true"|"on"|"enable"
... ...
@@ -100,10 +112,16 @@ EAT_ABLE	[\ \t\b\r]
100 100
 <INITIAL>{FORWARD}	{count(); yylval.strval=yytext; return FORWARD; }
101 101
 <INITIAL>{DROP}	{ count(); yylval.strval=yytext; return DROP; }
102 102
 <INITIAL>{SEND}	{ count(); yylval.strval=yytext; return SEND; }
103
-<INITIAL>{LOG}	{ count(); yylval.strval=yytext; return LOG; }
103
+<INITIAL>{LOG}	{ count(); yylval.strval=yytext; return LOG_TOK; }
104 104
 <INITIAL>{ERROR}	{ count(); yylval.strval=yytext; return ERROR; }
105 105
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
106 106
 <INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
107
+<INITIAL>{SET_HOST}	{ count(); yylval.strval=yytext; return SET_HOST; }
108
+<INITIAL>{SET_HOSTPORT}	{ count(); yylval.strval=yytext; return SET_HOSTPORT; }
109
+<INITIAL>{SET_USER}	{ count(); yylval.strval=yytext; return SET_USER; }
110
+<INITIAL>{SET_USERPASS}	{ count(); yylval.strval=yytext; return SET_USERPASS; }
111
+<INITIAL>{SET_PORT}	{ count(); yylval.strval=yytext; return SET_PORT; }
112
+<INITIAL>{SET_URI}	{ count(); yylval.strval=yytext; return SET_URI; }
107 113
 
108 114
 <INITIAL>{METHOD}	{ count(); yylval.strval=yytext; return METHOD; }
109 115
 <INITIAL>{URI}	{ count(); yylval.strval=yytext; return URI; }
... ...
@@ -116,6 +134,9 @@ EAT_ABLE	[\ \t\b\r]
116 116
 <INITIAL>{LISTEN}	{ count(); yylval.strval=yytext; return LISTEN; }
117 117
 <INITIAL>{DNS}	{ count(); yylval.strval=yytext; return DNS; }
118 118
 <INITIAL>{REV_DNS}	{ count(); yylval.strval=yytext; return REV_DNS; }
119
+<INITIAL>{PORT}	{ count(); yylval.strval=yytext; return PORT; }
120
+<INITIAL>{CHILDREN}	{ count(); yylval.strval=yytext; return CHILDREN; }
121
+<INITIAL>{CHECK_VIA}	{ count(); yylval.strval=yytext; return CHECK_VIA; }
119 122
 
120 123
 <INITIAL>{EQUAL}	{ count(); return EQUAL; }
121 124
 <INITIAL>{EQUAL_T}	{ count(); return EQUAL_T; }
... ...
@@ -150,17 +171,11 @@ EAT_ABLE	[\ \t\b\r]
150 150
 <STRING1>{QUOTES} { count(); state=INITIAL_S; BEGIN(INITIAL); 
151 151
 						yytext[yyleng-1]=0; yyleng--;
152 152
 						addstr(yytext, &str);
153
-						if (str){
154
-							printf("Found string1 <%s>\n", str);
155
-						}else{
156
-							printf("WARNING: empty string\n");
157
-						}
158 153
 						yylval.strval=str; str=0;
159 154
 						return STRING;
160 155
 					}
161 156
 <STRING2>{TICK}  { count(); state=INITIAL_S; BEGIN(INITIAL); 
162 157
 						yytext[yyleng-1]=0; yyleng--;
163
-						printf("Found string1 <%s>\n", yytext);
164 158
 						addstr(yytext, &str);
165 159
 						yylval.strval=str;
166 160
 						str=0;
... ...
@@ -196,14 +211,17 @@ EAT_ABLE	[\ \t\b\r]
196 196
 <<EOF>>							{
197 197
 									switch(state){
198 198
 										case STRING_S: 
199
-											printf("Unexpected EOF: closed string\n");
199
+											LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF in"
200
+														" unclosed string\n");
200 201
 											if (str) {free(str); str=0;}
201 202
 											break;
202 203
 										case COMMENT_S:
203
-											printf("Unexpected EOF:%d comments open\n", comment_nest);
204
+											LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF:"
205
+														" %d comments open\n", comment_nest);
204 206
 											break;
205 207
 										case COMMENT_LN_S:
206
-											printf("Unexpected EOF: comment line open\n");
208
+											LOG(L_CRIT, "ERROR: unexpected EOF:"
209
+														"comment line open\n");
207 210
 											break;
208 211
 									}
209 212
 									return 0;
... ...
@@ -231,7 +249,7 @@ static char* addstr(char * src, char ** dest)
231 231
 	}
232 232
 	return *dest;
233 233
 error:
234
-	fprintf(stderr, "lex:addstr: memory allocation error\n");
234
+	LOG(L_CRIT, "ERROR:lex:addstr: memory allocation error\n");
235 235
 	return 0;
236 236
 }
237 237
 
... ...
@@ -8,11 +8,16 @@
8 8
 
9 9
 #include <stdlib.h>
10 10
 #include <stdio.h>
11
+#include <sys/socket.h>
12
+#include <netinet/in.h>
13
+#include <arpa/inet.h>
11 14
 #include "route_struct.h"
12 15
 #include "globals.h"
13 16
 #include "route.h"
17
+#include "dprint.h"
14 18
 
15 19
 void yyerror(char* s);
20
+char* tmp;
16 21
 
17 22
 %}
18 23
 
... ...
@@ -33,10 +38,16 @@ void yyerror(char* s);
33 33
 %token FORWARD
34 34
 %token SEND
35 35
 %token DROP
36
-%token LOG
36
+%token LOG_TOK
37 37
 %token ERROR
38 38
 %token ROUTE
39 39
 %token EXEC
40
+%token SET_HOST
41
+%token SET_HOSTPORT
42
+%token SET_USER
43
+%token SET_USERPASS
44
+%token SET_PORT
45
+%token SET_URI
40 46
 
41 47
 %token METHOD
42 48
 %token URI
... ...
@@ -50,6 +61,10 @@ void yyerror(char* s);
50 50
 %token LISTEN
51 51
 %token DNS
52 52
 %token REV_DNS
53
+%token PORT
54
+%token CHILDREN
55
+%token CHECK_VIA
56
+
53 57
 
54 58
 
55 59
 /* operators */
... ...
@@ -101,24 +116,70 @@ statements:	statements statement {}
101 101
 		| statements error { yyerror(""); YYABORT;}
102 102
 	;
103 103
 
104
-statement:	assign_stm CR
105
-		| route_stm CR
104
+statement:	assign_stm 
105
+		| route_stm 
106 106
 		| CR	/* null statement*/
107 107
 	;
108 108
 
109
-assign_stm:	DEBUG EQUAL NUMBER 
109
+assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
110 110
 		| DEBUG EQUAL error  { yyerror("number  expected"); }
111
-		| FORK  EQUAL NUMBER
111
+		| FORK  EQUAL NUMBER { dont_fork= ! $3; }
112 112
 		| FORK  EQUAL error  { yyerror("boolean value expected"); }
113
-		| LOGSTDERROR EQUAL NUMBER 
113
+		| LOGSTDERROR EQUAL NUMBER { log_stderr=$3; }
114 114
 		| LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
115
-		| DNS EQUAL NUMBER
115
+		| DNS EQUAL NUMBER   { received_dns|= ($3)?DO_DNS:0; }
116 116
 		| DNS EQUAL error { yyerror("boolean value expected"); }
117
-		| REV_DNS EQUAL NUMBER 
117
+		| REV_DNS EQUAL NUMBER { received_dns|= ($3)?DO_REV_DNS:0; }
118 118
 		| REV_DNS EQUAL error { yyerror("boolean value expected"); }
119
-		| LISTEN EQUAL ipv4 
120
-		| LISTEN EQUAL ID 
121
-		| LISTEN EQUAL STRING
119
+		| PORT EQUAL NUMBER   { port_no=$3; }
120
+		| PORT EQUAL error    { yyerror("number expected"); } 
121
+		| CHILDREN EQUAL NUMBER { children_no=$3; }
122
+		| CHILDREN EQUAL error { yyerror("number expected"); } 
123
+		| CHECK_VIA EQUAL NUMBER { check_via=$3; }
124
+		| CHECK_VIA EQUAL error { yyerror("boolean value expected"); }
125
+		| LISTEN EQUAL ipv4  {
126
+								if (addresses_no < MAX_LISTEN){
127
+									tmp=inet_ntoa(*(struct in_addr*)&$3);
128
+									names[addresses_no]=(char*)malloc(strlen(tmp)+1);
129
+									if (names[addresses_no]==0){
130
+										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
131
+									}else{
132
+										strncpy(names[addresses_no], tmp, strlen(tmp)+1);
133
+										addresses_no++;
134
+									}
135
+								}else{
136
+									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
137
+												"(max. %d).\n", MAX_LISTEN);
138
+								}
139
+							  }
140
+		| LISTEN EQUAL ID	 {
141
+								if (addresses_no < MAX_LISTEN){
142
+									names[addresses_no]=(char*)malloc(strlen($3)+1);
143
+									if (names[addresses_no]==0){
144
+										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
145
+									}else{
146
+										strncpy(names[addresses_no], $3, strlen($3)+1);
147
+										addresses_no++;
148
+									}
149
+								}else{
150
+									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
151
+												"(max. %d).\n", MAX_LISTEN);
152
+								}
153
+							  }
154
+		| LISTEN EQUAL STRING {
155
+								if (addresses_no < MAX_LISTEN){
156
+									names[addresses_no]=(char*)malloc(strlen($3)+1);
157
+									if (names[addresses_no]==0){
158
+										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
159
+									}else{
160
+										strncpy(names[addresses_no], $3, strlen($3)+1);
161
+										addresses_no++;
162
+									}
163
+								}else{
164
+									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
165
+												"(max. %d).\n", MAX_LISTEN);
166
+								}
167
+							  }
122 168
 		| LISTEN EQUAL  error { yyerror("ip address or hostname"
123 169
 						"expected"); }
124 170
 		| error EQUAL { yyerror("unknown config variable"); }
... ...
@@ -153,26 +214,19 @@ route_stm:	ROUTE LBRACE rules RBRACE { push($3, &rlist[DEFAULT_RT]); }
153 153
 		| ROUTE error { yyerror("invalid  route  statement"); }
154 154
 	;
155 155
 
156
-rules:	rules rule { push($2, &$1); $$=$1; 
157
-						printf(": rules->rules(%x) rule(%x)\n", $1,$2);}
158
-	| rule {$$=$1; printf(": rules->rule (%x)\n",$1); }
156
+rules:	rules rule { push($2, &$1); $$=$1; }
157
+	| rule {$$=$1; }
159 158
 	| rules error { $$=0; yyerror("invalid rule"); }
160 159
 	 ;
161 160
 
162 161
 rule:	condition	actions CR {
163
-								printf("Got a new rule!\n");
164
-								printf("expr: "); print_expr($1);
165
-								printf("\n  -> actions: ");
166
-								print_action($2); printf("\n");
167
-
168 162
 								$$=0;
169 163
 								if (add_rule($1, $2, &$$)<0) {
170 164
 									yyerror("error calling add_rule");
171 165
 									YYABORT;
172 166
 								}
173
-								printf(": rule -> condition actions CR\n");
174 167
 							  }
175
-	| CR  /* null rule */		{ $$=0; printf(": rule-> CR!\n"); }
168
+	| CR  /* null rule */		{ $$=0;}
176 169
 	| condition error { $$=0; yyerror("bad actions in rule"); }
177 170
 	;
178 171
 
... ...
@@ -201,7 +255,7 @@ exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST,
201 201
 				 			}
202 202
 		| METHOD MATCH error { $$=0; yyerror("string expected"); }
203 203
 		| METHOD error	{ $$=0; yyerror("invalid operator,"
204
-										"== or ~= expected");
204
+										"== or =~ expected");
205 205
 						}
206 206
 		| URI EQUAL_T STRING 	{$$ = mk_elem(	EQUAL_OP, STRING_ST,
207 207
 												URI_O, $3); 
... ...
@@ -218,7 +272,7 @@ exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST,
218 218
 							}
219 219
 		| URI MATCH error {  $$=0; yyerror("string expected"); }
220 220
 		| URI error	{ $$=0; yyerror("invalid operator,"
221
-				  					" == or ~= expected");
221
+				  					" == or =~ expected");
222 222
 					}
223 223
 		| SRCIP EQUAL_T net4	{ $$=mk_elem(	EQUAL_OP, NET_ST,
224 224
 												SRCIP_O, $3);
... ...
@@ -239,7 +293,7 @@ exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST,
239 239
 								}
240 240
 		| SRCIP MATCH error  { $$=0; yyerror( "hostname expected"); }
241 241
 		| SRCIP error  { $$=0; 
242
-						 yyerror("invalid operator, == or ~= expected");}
242
+						 yyerror("invalid operator, == or =~ expected");}
243 243
 		| DSTIP EQUAL_T net4	{ $$=mk_elem(	EQUAL_OP, NET_ST,
244 244
 												DSTIP_O, $3);
245 245
 								}
... ...
@@ -259,7 +313,7 @@ exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST,
259 259
 							}
260 260
 		| DSTIP MATCH error  { $$=0; yyerror ( "hostname  expected" ); }
261 261
 		| DSTIP error { $$=0; 
262
-						yyerror("invalid operator, == or ~= expected");}
262
+						yyerror("invalid operator, == or =~ expected");}
263 263
 	;
264 264
 
265 265
 net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); } 
... ...
@@ -278,7 +332,7 @@ net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); }
278 278
 host:	ID				{ $$=$1; }
279 279
 	| host DOT ID		{ $$=(char*)malloc(strlen($1)+1+strlen($3)+1);
280 280
 						  if ($$==0){
281
-						  	fprintf(stderr, "memory allocation failure"
281
+						  	LOG(L_CRIT, "ERROR: cfg. parser: memory allocation failure"
282 282
 						 				" while parsing host\n");
283 283
 						  }else{
284 284
 						  	memcpy($$, $1, strlen($1));
... ...
@@ -382,17 +436,17 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
382 382
 													"argument"); }
383 383
 		| DROP LPAREN RPAREN	{$$=mk_action(DROP_T,0, 0, 0, 0); }
384 384
 		| DROP					{$$=mk_action(DROP_T,0, 0, 0, 0); }
385
-		| LOG LPAREN STRING RPAREN	{$$=mk_action(	LOG_T, NUMBER_ST, 
385
+		| LOG_TOK LPAREN STRING RPAREN	{$$=mk_action(	LOG_T, NUMBER_ST, 
386 386
 													STRING_ST,(void*)4,$3);
387 387
 									}
388
-		| LOG LPAREN NUMBER COMMA STRING RPAREN	{$$=mk_action(	LOG_T,
388
+		| LOG_TOK LPAREN NUMBER COMMA STRING RPAREN	{$$=mk_action(	LOG_T,
389 389
 																NUMBER_ST, 
390 390
 																STRING_ST,
391 391
 																(void*)$3,
392 392
 																$5);
393 393
 												}
394
-		| LOG error { $$=0; yyerror("missing '(' or ')' ?"); }
395
-		| LOG LPAREN error RPAREN { $$=0; yyerror("bad log"
394
+		| LOG_TOK error { $$=0; yyerror("missing '(' or ')' ?"); }
395
+		| LOG_TOK LPAREN error RPAREN { $$=0; yyerror("bad log"
396 396
 									"argument"); }
397 397
 		| ERROR LPAREN STRING COMMA STRING RPAREN {$$=mk_action(ERROR_T,
398 398
 																STRING_ST, 
... ...
@@ -413,6 +467,24 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
413 413
 		| EXEC LPAREN STRING RPAREN	{ $$=mk_action(	EXEC_T, STRING_ST, 0,
414 414
 													$3, 0);
415 415
 									}
416
+		| SET_HOST LPAREN STRING RPAREN { $$=mk_action( SET_HOST_T, STRING_ST, 0, $3, 0); }
417
+		| SET_HOST error { $$=0; yyerror("missing '(' or ')' ?"); }
418
+		| SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
419
+		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, STRING_ST, 0, $3, 0); }
420
+		| SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
421
+		| SET_HOSTPORT LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
422
+		| SET_PORT LPAREN STRING RPAREN { $$=mk_action( SET_PORT_T, STRING_ST, 0, $3, 0); }
423
+		| SET_PORT error { $$=0; yyerror("missing '(' or ')' ?"); }
424
+		| SET_PORT LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
425
+		| SET_USER LPAREN STRING RPAREN { $$=mk_action( SET_USER_T, STRING_ST, 0, $3, 0); }
426
+		| SET_USER error { $$=0; yyerror("missing '(' or ')' ?"); }
427
+		| SET_USER LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
428
+		| SET_USERPASS LPAREN STRING RPAREN { $$=mk_action( SET_USERPASS_T, STRING_ST, 0, $3, 0); }
429
+		| SET_USERPASS error { $$=0; yyerror("missing '(' or ')' ?"); }
430
+		| SET_USERPASS LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
431
+		| SET_URI LPAREN STRING RPAREN { $$=mk_action( SET_URI_T, STRING_ST, 0, $3, 0); }
432
+		| SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
433
+		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
416 434
 	;
417 435
 
418 436
 
... ...
@@ -423,7 +495,7 @@ extern int column;
423 423
 extern int startcolumn;
424 424
 void yyerror(char* s)
425 425
 {
426
-	fprintf(stderr, "parse error (%d,%d-%d): %s\n", line, startcolumn, 
426
+	LOG(L_CRIT, "parse error (%d,%d-%d): %s\n", line, startcolumn, 
427 427
 			column, s);
428 428
 	cfg_errors++;
429 429
 }
... ...
@@ -28,4 +28,6 @@
28 28
 #define ROUTE_MAX_REC_LEV 10 /* maximum number of recursive calls
29 29
 							   for route()*/
30 30
 
31
+#define MAX_URI_SIZE 1024	/* used when rewriting URIs */
32
+
31 33
 #endif
... ...
@@ -63,7 +63,7 @@ int check_address(unsigned long ip, char *name, int resolver)
63 63
 
64 64
 int forward_request( struct sip_msg* msg, struct proxy_l * p)
65 65
 {
66
-	unsigned int len, new_len, via_len, received_len;
66
+	unsigned int len, new_len, via_len, received_len, uri_len;
67 67
 	char line_buf[MAX_VIA_LINE_SIZE];
68 68
 	char received_buf[MAX_RECEIVED_SIZE];
69 69
 	char* new_buf;
... ...
@@ -96,15 +96,31 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
96 96
 	}
97 97
 	
98 98
 	new_len=len+via_len+received_len;
99
+	if (msg->new_uri){ 
100
+		uri_len=strlen(msg->new_uri); 
101
+		new_len=new_len-strlen(msg->first_line.u.request.uri)+uri_len;
102
+	}
99 103
 	new_buf=(char*)malloc(new_len+1);
100 104
 	if (new_buf==0){
101 105
 		LOG(L_ERR, "ERROR: forward_request: out of memory\n");
102 106
 		goto error;
103 107
 	}
104
-/* copy msg till first via */
108
+
105 109
 	offset=s_offset=0;
106
-	size=msg->via1.hdr-buf;
107
-	memcpy(new_buf, orig, size);
110
+	if (msg->new_uri){
111
+		/* copy message up to uri */
112
+		size=msg->first_line.u.request.uri-buf;
113
+		memcpy(new_buf, orig, size);
114
+		offset+=size;
115
+		s_offset+=size;
116
+		/* add our uri */
117
+		memcpy(new_buf+offset, msg->new_uri, uri_len);
118
+		offset+=uri_len;
119
+		s_offset+=strlen(msg->first_line.u.request.uri); /* skip original uri */
120
+	}
121
+/* copy msg till first via */
122
+	size=msg->via1.hdr-(buf+s_offset);
123
+	memcpy(new_buf+offset, orig+s_offset, size);
108 124
 	offset+=size;
109 125
 	s_offset+=size;
110 126
  /* add our via */
... ...
@@ -19,7 +19,7 @@ extern unsigned short port_no;
19 19
 extern char * names[];
20 20
 extern unsigned long addresses[];
21 21
 extern int addresses_no;
22
-extern int child_no;
22
+extern int children_no;
23 23
 extern int debug;
24 24
 extern int dont_fork;
25 25
 extern int log_stderr;
... ...
@@ -22,7 +22,7 @@
22 22
 
23 23
 
24 24
 static char id[]="@(#) $Id$";
25
-static char version[]="sip_router 0.5";
25
+static char version[]="sip_router 0.6";
26 26
 static char help_msg[]= "\
27 27
 Usage: sip_router -l address [-l address] [options]\n\
28 28
 Options:\n\
... ...
@@ -289,6 +289,25 @@ int main(int argc, char** argv)
289 289
 	
290 290
 	/* fill missing arguments with the default values*/
291 291
 	if (cfg_file==0) cfg_file=CFG_FILE;
292
+
293
+	/* load config file or die */
294
+	cfg_stream=fopen (cfg_file, "r");
295
+	if (cfg_stream==0){
296
+		fprintf(stderr, "ERROR: loading config file(%s): %s\n", cfg_file,
297
+				strerror(errno));
298
+		goto error;
299
+	}
300
+	
301
+	yyin=cfg_stream;
302
+	if ((yyparse()!=0)||(cfg_errors)){
303
+		fprintf(stderr, "ERROR: bad config file (%d errors)\n", cfg_errors);
304
+		goto error;
305
+	}
306
+	
307
+	
308
+	print_rl();
309
+
310
+	/* fix parameters */
292 311
 	if (port_no<=0) port_no=SIP_PORT;
293 312
 	if (children_no<=0) children_no=CHILD_NO;
294 313
 	if (addresses_no==0) {
... ...
@@ -320,26 +339,6 @@ int main(int argc, char** argv)
320 320
 				inet_ntoa(*(struct in_addr*)&addresses[r]),
321 321
 				(unsigned short)port_no);
322 322
 	}
323
-	
324
-	
325
-
326
-	/* load config file or die */
327
-	cfg_stream=fopen (cfg_file, "r");
328
-	if (cfg_stream==0){
329
-		fprintf(stderr, "ERROR: loading config file(%s): %s\n", cfg_file,
330
-				strerror(errno));
331
-		goto error;
332
-	}
333
-	
334
-	yyin=cfg_stream;
335
-	if ((yyparse()!=0)||(cfg_errors)){
336
-		fprintf(stderr, "ERROR: bad config file (%d errors)\n", cfg_errors);
337
-		goto error;
338
-	}
339
-	
340
-	
341
-	print_rl();
342
-
343 323
 
344 324
 	/* init_daemon? */
345 325
 	if (!dont_fork){
... ...
@@ -10,6 +10,7 @@
10 10
 
11 11
 #include "msg_parser.h"
12 12
 #include "parser_f.h"
13
+#include "error.h"
13 14
 #include "dprint.h"
14 15
 
15 16
 
... ...
@@ -118,10 +119,15 @@ error1:
118 118
 /* returns integer field name type */
119 119
 int field_name(char *s)
120 120
 {
121
-	if ((strcmp(s, "Via")==0 )||(strcmp(s,"v")==0))
121
+	int l;
122
+	l=strlen(s);
123
+	if (l<1) return HDR_OTHER;
124
+	else if ((l==1) && ((*s=='v')||(*s=='V')))
125
+		return HDR_VIA;
126
+	else if (strcasecmp(s, "Via")==0)
122 127
 		return  HDR_VIA;
123
-	if ((strcmp(s, "To")==0)||(strcmp(s,"t")==0))
124
-		return HDR_TO;
128
+/*	if ((strcmp(s, "To")==0)||(strcmp(s,"t")==0))
129
+		return HDR_TO;*/
125 130
 	return HDR_OTHER;
126 131
 }
127 132
 
... ...
@@ -137,7 +143,7 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
137 137
 	   (CRLF in the field body must be removed)
138 138
 	*/
139 139
 
140
-	char* tmp;
140
+	char* tmp, *tmp2;
141 141
 	char* nl;
142 142
 	char* body;
143 143
 	int offset;
... ...
@@ -156,11 +162,25 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
156 156
 	
157 157
 	tmp=eat_token2(buffer, len, ':');
158 158
 	if ((tmp==buffer) || (tmp-buffer==len) ||
159
-		(is_empty(buffer, tmp-buffer-1))|| (*tmp!=':')){
159
+		(is_empty(buffer, tmp-buffer))|| (*tmp!=':')){
160 160
 		hdr_f->type=HDR_ERROR;
161 161
 		goto error;
162 162
 	}
163 163
 	*tmp=0;
164
+	/* take care of possible spaces (e.g: "Via  :") */
165
+	tmp2=eat_token(buffer, tmp-buffer);
166
+	/* in the worst case tmp2=buffer+tmp-buffer=tmp */
167
+	*tmp2=0;
168
+	if (tmp2<tmp){
169
+		tmp2++;
170
+		/* catch things like: "Via foo bar:" */
171
+		tmp2=eat_space(tmp2, tmp-tmp2);
172
+		if (tmp2!=tmp){
173
+			hdr_f->type=HDR_ERROR;
174
+			goto error;
175
+		}
176
+	}
177
+
164 178
 	hdr_f->type=field_name(buffer);
165 179
 	body= ++tmp;
166 180
 	hdr_f->name=buffer;
... ...
@@ -210,6 +230,165 @@ char* parse_hostport(char* buf, char** host, short int* port)
210 210
 
211 211
 
212 212
 
213
+/* buf= pointer to begining of uri (sip:x@foo.bar:5060;a=b?h=i)
214
+   len= len of uri
215
+returns: fills uri & returns <0 on error or 0 if ok */
216
+int parse_uri(char *buf, int len, struct sip_uri* uri)
217
+{
218
+	char* next, *end;
219
+	char *user, *passwd, *host, *port, *params, *headers;
220
+	int host_len, port_len, params_len, headers_len;
221
+	int ret;
222
+	
223
+
224
+	ret=0;
225
+	end=buf+len;
226
+	memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure */
227
+	/* look for "sip:"*/;
228
+	next=memchr(buf, ':',  len);
229
+	if ((next==0)||(strncmp(buf,"sip",next-buf)!=0)){
230
+		LOG(L_DBG, "ERROR: parse_uri: bad sip uri\n");
231
+		ret=E_UNSPEC;
232
+		goto error;
233
+	}
234
+	buf=next+1; /* next char after ':' */
235
+	if (buf>end){
236
+		LOG(L_DBG, "ERROR: parse_uri: uri too short\n");
237
+		ret=E_UNSPEC;
238
+		goto error;
239
+	}
240
+	/*look for '@' */
241
+	next=memchr(buf,'@', end-buf);
242
+	if (next==0){
243
+		/* no '@' found, => no userinfo */
244
+		uri->user=0;
245
+		uri->passwd=0;
246
+		host=buf;
247
+	}else{
248
+		/* found it */
249
+		user=buf;
250
+		/* try to find passwd */
251
+		passwd=memchr(user,':', next-user);
252
+		if (passwd==0){
253
+			/* no ':' found => no password */
254
+			uri->passwd=0;
255
+			uri->user=(char*)malloc(next-user+1);
256
+			if (uri->user==0){
257
+				LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
258
+				ret=E_OUT_OF_MEM;
259
+				goto error;
260
+			}
261
+			memcpy(uri->user,user, next-user);
262
+			uri->user[next-user]=0; /* null terminate it, usefull for easy printing*/
263
+		}else{
264
+			uri->user=(char*)malloc(passwd-user+1);
265
+			if (uri->user==0){
266
+				LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
267
+				ret=E_OUT_OF_MEM;
268
+				goto error;
269
+			}
270
+			memcpy(uri->user,user, passwd-user);
271
+			uri->user[passwd-user]=0;
272
+			passwd++; /*skip ':' */
273
+			uri->passwd=(char*)malloc(next-passwd+1);
274
+			if (uri->passwd==0){
275
+				LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
276
+				ret=E_OUT_OF_MEM;
277
+				goto error;
278
+			}
279
+			memcpy(uri->passwd,passwd, next-passwd);
280
+			uri->passwd[next-passwd]=0;
281
+		}
282
+		host=next+1; /* skip '@' */
283
+	}
284
+	/* try to find the rest */
285
+	if(host>=end){
286
+		LOG(L_DBG, "ERROR: parse_uri: missing hostport\n");
287
+		ret=E_UNSPEC;
288
+		goto error;
289
+	}
290
+	headers=memchr(host,'?',end-host);
291
+	params=memchr(host,';',end-host);
292
+	port=memchr(host,':',end-host);
293
+	host_len=(port)?port-host:(params)?params-host:(headers)?headers-host:end-host;
294
+	/* get host */
295
+	uri->host=malloc(host_len+1);
296
+	if (uri->host==0){
297
+		LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
298
+		ret=E_OUT_OF_MEM;
299
+		goto error;
300
+	}
301
+	memcpy(uri->host,host, host_len);
302
+	uri->host[host_len]=0;
303
+	/* get port*/
304
+	if ((port)&&(port+1<end)){
305
+		port++;
306
+		if ( ((params) &&(params<port))||((headers) &&(headers<port)) ){
307
+			/* error -> invalid uri we found ';' or '?' before ':' */
308
+			LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n");
309
+			ret=E_UNSPEC;
310
+			goto error;
311
+		}
312
+		port_len=(params)?params-port:(headers)?headers-port:end-port;
313
+		uri->port=malloc(port_len+1);
314
+		if (uri->port==0){
315
+			LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
316
+			ret=E_OUT_OF_MEM;
317
+			goto error;
318
+		}
319
+		memcpy(uri->port, port, port_len);
320
+		uri->port[port_len]=0;
321
+	}else uri->port=0;
322
+	/* get params */
323
+	if ((params)&&(params+1<end)){
324
+		params++;
325
+		if ((headers) && (headers<params)){
326
+			/* error -> invalid uri we found '?' or '?' before ';' */
327
+			LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n");
328
+			ret=E_UNSPEC;
329
+			goto error;
330
+		}
331
+		params_len=(headers)?headers-params:end-params;
332
+		uri->params=malloc(params_len+1);
333
+		if (uri->params==0){
334
+			LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
335
+			ret=E_OUT_OF_MEM;
336
+			goto error;
337
+		}
338
+		memcpy(uri->params, params, params_len);
339
+		uri->params[params_len]=0;
340
+	}else uri->params=0;
341
+	/*get headers */
342
+	if ((headers)&&(headers+1<end)){
343
+		headers++;
344
+		headers_len=end-headers;
345
+		uri->headers=malloc(headers_len+1);
346
+		if(uri->headers==0){
347
+			LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
348
+			ret=E_OUT_OF_MEM;
349
+			goto error;
350
+		}
351
+		memcpy(uri->headers, headers, headers_len);
352
+		uri->headers[headers_len]=0;
353
+	}else uri->headers=0;
354
+	
355
+	return ret;
356
+error:
357
+	return ret;
358
+}
359
+
360
+
361
+			
362
+
363
+			
364
+			
365
+	
366
+		
367
+	
368
+	
369
+
370
+
371
+
213 372
 /* parses a via body, returns next via (for compact vias) & fills vb,
214 373
  * the buffer should be null terminated! */
215 374
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
... ...
@@ -434,9 +613,11 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
434 434
 							goto skip;
435 435
 						}else{
436 436
 						/*  add 1 (we don't see the trailing lf which
437
-						 *  was zeroed by get_hfr_field */
437
+						 *  was zeroed by get_hfr_field) */
438 438
 							vb1.size+=1;
439 439
 						}
440
+						if (fl.type!=SIP_REPLY) goto skip; /* we are interested in the 2nd via 
441
+															   only in replies */
440 442
 				}else if (second_via==0){
441 443
 							second_via=hf.body;
442 444
 							vb2.hdr=hf.name;
... ...
@@ -72,10 +72,23 @@ struct sip_msg{
72 72
 				   via, etc. point into it */
73 73
 				   
74 74
 	unsigned int len; /* message len (orig) */
75
+
76
+	/* modifications */
77
+	char* new_uri; /* changed first line uri*/
75 78
 	
76 79
 };
77 80
 
78 81
 
82
+struct sip_uri{
83
+	char* user;
84
+	char* passwd;
85
+	char* host;
86
+	char* port;
87
+	char* params;
88
+	char* headers;
89
+};
90
+
91
+
79 92
 
80 93
 char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl);
81 94
 char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f);
... ...
@@ -83,6 +96,7 @@ int field_name(char *s);
83 83
 char* parse_hostport(char* buf, char** host, short int* port);
84 84
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb);
85 85
 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
86
+int parse_uri(char *buf, int len, struct sip_uri* uri);
86 87
 
87 88
 
88 89
 
... ...
@@ -18,6 +18,7 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
18 18
 	struct sip_msg msg;
19 19
 	struct route_elem *re;
20 20
 
21
+	memset(&msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
21 22
 	/* fill in msg */
22 23
 	msg.buf=buf;
23 24
 	msg.len=len;
... ...
@@ -407,16 +407,16 @@ void print_rl()
407 407
 
408 408
 	for(j=0; j<RT_NO; j++){
409 409
 		if (rlist[j]==0){
410
-			if (j==0) printf("WARNING: the main routing table is empty\n");
410
+			if (j==0) DBG("WARNING: the main routing table is empty\n");
411 411
 			continue;
412 412
 		}
413
-		printf("routing table %d:\n",j);
413
+		DBG("routing table %d:\n",j);
414 414
 		for (t=rlist[j],i=0; t; i++, t=t->next){
415
-			printf("%2d.condition: ",i);
415
+			DBG("%2d.condition: ",i);
416 416
 			print_expr(t->condition);
417
-			printf("\n  -> ");
417
+			DBG("\n  -> ");
418 418
 			print_action(t->actions);
419
-			printf("\n    Statistics: tx=%d, errors=%d, tx_bytes=%d\n",
419
+			DBG("\n    Statistics: tx=%d, errors=%d, tx_bytes=%d\n",
420 420
 					t->tx, t->errors, t->tx_bytes);
421 421
 		}
422 422
 	}
... ...
@@ -12,6 +12,8 @@
12 12
 #include <sys/types.h>
13 13
 #include <netinet/in.h>
14 14
 
15
+#include "dprint.h"
16
+
15 17
 struct expr* mk_exp(int op, struct expr* left, struct expr* right)
16 18
 {
17 19
 	struct expr * e;
... ...
@@ -23,7 +25,7 @@ struct expr* mk_exp(int op, struct expr* left, struct expr* right)
23 23
 	e->r.expr=right;
24 24
 	return e;
25 25
 error:
26
-	fprintf(stderr, "ERROR: mk_exp: memory allocation failure\n");
26
+	LOG(L_CRIT, "ERROR: mk_exp: memory allocation failure\n");
27 27
 	return 0;
28 28
 }
29 29
 
... ...
@@ -40,7 +42,7 @@ struct expr* mk_elem(int op, int subtype, int operand, void* param)
40 40
 	e->r.param=param;
41 41
 	return e;
42 42
 error:
43
-	fprintf(stderr, "ERROR: mk_elem: memory allocation failure\n");
43
+	LOG(L_CRIT, "ERROR: mk_elem: memory allocation failure\n");
44 44
 	return 0;
45 45
 }
46 46
 
... ...
@@ -60,7 +62,7 @@ struct action* mk_action(int type, int p1_type, int p2_type, void* p1, void* p2)
60 60
 	return a;
61 61
 	
62 62
 error:
63
-	fprintf(stderr, "ERROR: mk_action: memory allocation failure\n");
63
+	LOG(L_CRIT, "ERROR: mk_action: memory allocation failure\n");
64 64
 	return 0;
65 65
 
66 66
 }
... ...
@@ -89,7 +91,7 @@ struct net* mk_net(unsigned long ip, unsigned long mask)
89 89
 	n->mask=mask;
90 90
 	return n;
91 91
 error:
92
-	fprintf(stderr, "ERROR: mk_net_mask: memory allocation failure\n");
92
+	LOG(L_CRIT, "ERROR: mk_net_mask: memory allocation failure\n");
93 93
 	return 0;
94 94
 }
95 95
 
... ...
@@ -98,7 +100,7 @@ error:
98 98
 
99 99
 void print_ip(unsigned ip)
100 100
 {
101
-	printf("%d.%d.%d.%d", ((unsigned char*)&ip)[0],
101
+	DBG("%d.%d.%d.%d", ((unsigned char*)&ip)[0],
102 102
 						  ((unsigned char*)&ip)[1],
103 103
 						  ((unsigned char*)&ip)[2],
104 104
 						  ((unsigned char*)&ip)[3]);
... ...
@@ -108,10 +110,10 @@ void print_ip(unsigned ip)
108 108
 void print_net(struct net* net)
109 109
 {
110 110
 	if (net==0){
111
-		fprintf(stderr, "ERROR: print net: null pointer\n");
111
+		LOG(L_WARN, "ERROR: print net: null pointer\n");
112 112
 		return;
113 113
 	}
114
-	print_ip(net->ip); printf("/"); print_ip(net->mask);
114
+	print_ip(net->ip); DBG("/"); print_ip(net->mask);
115 115
 }
116 116
 
117 117
 
... ...
@@ -119,42 +121,42 @@ void print_net(struct net* net)
119 119
 void print_expr(struct expr* exp)
120 120
 {
121 121
 	if (exp==0){
122
-		fprintf(stderr, "ERROR: print_expr: null expression!\n");
122
+		LOG(L_CRIT, "ERROR: print_expr: null expression!\n");
123 123
 		return;
124 124
 	}
125 125
 	if (exp->type==ELEM_T){
126 126
 		switch(exp->l.operand){
127 127
 			case METHOD_O:
128
-				printf("method");
128
+				DBG("method");
129 129
 				break;
130 130
 			case URI_O:
131
-				printf("uri");
131
+				DBG("uri");
132 132
 				break;
133 133
 			case SRCIP_O:
134
-				printf("srcip");
134
+				DBG("srcip");
135 135
 				break;
136 136
 			case DSTIP_O:
137
-				printf("dstip");
137
+				DBG("dstip");
138 138
 				break;
139 139
 			default:
140
-				printf("UNKNOWN");
140
+				DBG("UNKNOWN");
141 141
 		}
142 142
 		switch(exp->op){
143 143
 			case EQUAL_OP:
144
-				printf("==");
144
+				DBG("==");
145 145
 				break;
146 146
 			case MATCH_OP:
147
-				printf("~=");
147
+				DBG("=~");
148 148
 				break;
149 149
 			default:
150
-				printf("<UNKNOWN>");
150
+				DBG("<UNKNOWN>");
151 151
 		}
152 152
 		switch(exp->subtype){
153 153
 			case NOSUBTYPE: 
154
-					printf("N/A");
154
+					DBG("N/A");
155 155
 					break;
156 156
 			case STRING_ST:
157
-					printf("\"%s\"", (char*)exp->r.param);
157
+					DBG("\"%s\"", (char*)exp->r.param);
158 158
 					break;
159 159
 			case NET_ST:
160 160
 					print_net((struct net*)exp->r.param);
... ...
@@ -163,35 +165,35 @@ void print_expr(struct expr* exp)
163 163
 					print_ip(exp->r.intval);
164 164
 					break;
165 165
 			default:
166
-					printf("type<%d>", exp->subtype);
166
+					DBG("type<%d>", exp->subtype);
167 167
 		}
168 168
 	}else if (exp->type==EXP_T){
169 169
 		switch(exp->op){
170 170
 			case AND_OP:
171
-					printf("AND( ");
171
+					DBG("AND( ");
172 172
 					print_expr(exp->l.expr);
173
-					printf(", ");
173
+					DBG(", ");
174 174
 					print_expr(exp->r.expr);
175
-					printf(" )");
175
+					DBG(" )");
176 176
 					break;
177 177
 			case OR_OP:
178
-					printf("OR( ");
178
+					DBG("OR( ");
179 179
 					print_expr(exp->l.expr);
180
-					printf(", ");
180
+					DBG(", ");
181 181
 					print_expr(exp->r.expr);
182
-					printf(" )");
182
+					DBG(" )");
183 183
 					break;
184 184
 			case NOT_OP:	
185
-					printf("NOT( ");
185
+					DBG("NOT( ");
186 186
 					print_expr(exp->l.expr);
187
-					printf(" )");
187
+					DBG(" )");
188 188
 					break;
189 189
 			default:
190
-					printf("UNKNOWN_EXP ");
190
+					DBG("UNKNOWN_EXP ");
191 191
 		}
192 192
 					
193 193
 	}else{
194
-		printf("ERROR:print_expr: unknown type\n");
194
+		DBG("ERROR:print_expr: unknown type\n");
195 195
 	}
196 196
 }
197 197
 					
... ...
@@ -204,55 +206,73 @@ void print_action(struct action* a)
204 204
 	for(t=a; t!=0;t=t->next){
205 205
 		switch(t->type){
206 206
 			case FORWARD_T:
207
-					printf("forward(");
207
+					DBG("forward(");
208 208
 					break;
209 209
 			case SEND_T:
210
-					printf("send(");
210
+					DBG("send(");
211 211
 					break;
212 212
 			case DROP_T:
213
-					printf("drop(");
213
+					DBG("drop(");
214 214
 					break;
215 215
 			case LOG_T:
216
-					printf("log(");
216
+					DBG("log(");
217 217
 					break;
218 218
 			case ERROR_T:
219
-					printf("error(");
219
+					DBG("error(");
220 220
 					break;
221 221
 			case ROUTE_T:
222
-					printf("route(");
222
+					DBG("route(");
223 223
 					break;
224 224
 			case EXEC_T:
225
-					printf("exec(");
225
+					DBG("exec(");
226
+					break;
227
+			case SET_HOST_T:
228
+					DBG("sethost(");
229
+					break;
230
+			case SET_HOSTPORT_T:
231
+					DBG("sethostport(");
232
+					break;
233
+			case SET_USER_T:
234
+					DBG("setuser(");
235
+					break;
236
+			case SET_USERPASS_T:
237
+					DBG("setuserpass(");
238
+					break;
239
+			case SET_PORT_T:
240
+					DBG("setport(");
241
+					break;
242
+			case SET_URI_T:
243
+					DBG("seturi(");
226 244
 					break;
227 245
 			default:
228
-					printf("UNKNOWN(");
246
+					DBG("UNKNOWN(");
229 247
 		}
230 248
 		switch(t->p1_type){
231 249
 			case STRING_ST:
232
-					printf("\"%s\"", t->p1.string);
250
+					DBG("\"%s\"", t->p1.string);
233 251
 					break;
234 252
 			case NUMBER_ST:
235
-					printf("%d",t->p1.number);
253
+					DBG("%d",t->p1.number);
236 254
 					break;
237 255
 			case IP_ST:
238 256
 					print_ip(t->p1.number);
239 257
 					break;
240 258
 			default:
241
-					printf("type<%d>", t->p1_type);
259
+					DBG("type<%d>", t->p1_type);
242 260
 		}
243 261
 		switch(t->p2_type){
244 262
 			case NOSUBTYPE:
245 263
 					break;
246 264
 			case STRING_ST:
247
-					printf(", \"%s\"", t->p2.string);
265
+					DBG(", \"%s\"", t->p2.string);
248 266
 					break;
249 267
 			case NUMBER_ST:
250
-					printf(", %d",t->p2.number);
268
+					DBG(", %d",t->p2.number);
251 269
 					break;
252 270
 			default:
253
-					printf(", type<%d>", t->p2_type);
271
+					DBG(", type<%d>", t->p2_type);
254 272
 		}
255
-		printf("); ");
273
+		DBG("); ");
256 274
 	}
257 275
 }
258 276
 			
... ...
@@ -11,13 +11,14 @@ enum { AND_OP=1, OR_OP, NOT_OP };
11 11
 enum { EQUAL_OP=10, MATCH_OP };
12 12
 enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O, DEFAULT_O };
13 13
 
14
-enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T};
14
+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, 
15
+		SET_USERPASS_T, SET_PORT_T, SET_URI_T};
15 16
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST };
16 17
 
17 18
 	
18 19
 struct expr{
19 20
 	int type; /* exp, exp_elem */
20
-	int op; /* and, or, not | ==,  ~= */
21
+	int op; /* and, or, not | ==,  =~ */
21 22
 	int  subtype;
22 23
 	union {
23 24
 		struct expr* expr;
... ...
@@ -1,5 +1,5 @@
1
-INVITE sip:x@y.z SIP/2.0/UDP
2
-Via  : SIP  /   2.0
1
+INVITE sip:x@y.z SIP/2.0
2
+Via : SIP  /   2.0
3 3
  /UDP
4 4
     193.175.133.193
5 5
 
... ...
@@ -1,4 +1,4 @@
1
-INVITE sip:andrei@localhost SIP/2.0/UDP
1
+INVITE sip:andrei@localhost:5061;a=b?c=d SIP/2.0
2 2
 Via: SIP/2.0/UDP localhost
3 3
 
4 4