Browse code

- new config style: if expr cmd else cmd; - expr can now contain commands (e.g: forward("proxy") && src_ip==1.2.3.4) - introduced boolean values in expr. (yes/no; true/false; on/off; 1/0) e.g.: if ( true ) log("..."); - changed name to ser, ser.cfg - bumped ver. no (0.7)

Andrei Pelinescu-Onciul authored on 11/10/2001 23:03:42
Showing 12 changed files
... ...
@@ -12,7 +12,7 @@ $(yacc_f)
12 12
 objs= $(sources:.c=.o)
13 13
 depends= $(sources:.c=.d)
14 14
 
15
-NAME=sip_router
15
+NAME=ser
16 16
 
17 17
 # compile-time options
18 18
 # NOCR disables seeking for CRs -- breaks standard but is fast
... ...
@@ -29,7 +29,7 @@ ARCH = $(shell uname -s)
29 29
 ifeq ($(ARCH), Linux)
30 30
 
31 31
 CC=gcc
32
-CFLAGS=-O2 -Wcast-align #-Wmissing-prototypes  -Wall
32
+CFLAGS=-O2 -Wcast-align #-Wmissing-prototypes 
33 33
 LEX=flex
34 34
 YACC=bison
35 35
 YACC_FLAGS=-d -b cfg
... ...
@@ -1,19 +1,21 @@
1 1
 $Id$
2 2
 
3
+( - todo, x - done)
4
+
3 5
 - better Via parsing (handle ' ' in uri, eg: foo.bar : 1234 ; received=) and
4 6
  ipv6 addresses ([fec0:aa::01]).
5 7
 
6 8
 High priority:
7
-- if () {} else {}
9
+x if () {} else {}
10
+- ipv6 support
8 11
 - reply ("response line")
9
-- default route ?
10 12
 - drop ACKs for our replies
11 13
 - icmp error handling
12
-- ipv6 support
13 14
 - add To-tag (for the replies)
14 15
 - add User-Agent (for the replies)
15 16
 
16 17
 Low priority:
18
+- command line switch for checking the config file syntax
17 19
 - config file version (a la sendmail)
18 20
 - loop detection
19 21
 - cfg. file reload
... ...
@@ -32,9 +32,9 @@
32 32
 int do_action(struct action* a, struct sip_msg* msg)
33 33
 {
34 34
 	int ret;
35
+	int v;
35 36
 	struct sockaddr_in* to;
36 37
 	struct proxy_l* p;
37
-	struct route_elem* re;
38 38
 	char* tmp;
39 39
 	char *new_uri, *end, *crt;
40 40
 	int len;
... ...
@@ -126,14 +126,7 @@ int do_action(struct action* a, struct sip_msg* msg)
126 126
 				ret=E_CFG;
127 127
 				break;
128 128
 			}
129
-			re=route_match(msg, &rlist[a->p1.number]);
130
-			if (re==0){
131
-				LOG(L_INFO, "WARNING: do_action: route(%d): no new route"
132
-						" found\n", a->p1.number);
133
-				ret=1;
134
-				break;
135
-			}
136
-			ret=((ret=run_actions(re->actions, msg))<0)?ret:1;
129
+			ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;
137 130
 			break;
138 131
 		case EXEC_T:
139 132
 			if (a->p1_type!=STRING_ST){
... ...
@@ -178,7 +171,6 @@ int do_action(struct action* a, struct sip_msg* msg)
178 171
 					ret=1;
179 172
 					break;
180 173
 				}
181
-
182 174
 				if (msg->new_uri) tmp=msg->new_uri;
183 175
 				else tmp=msg->first_line.u.request.uri;
184 176
 				if (parse_uri(tmp, strlen(tmp), &uri)<0){
... ...
@@ -264,7 +256,24 @@ int do_action(struct action* a, struct sip_msg* msg)
264 256
 				msg->new_uri=new_uri;
265 257
 				ret=1;
266 258
 				break;
267
-
259
+		case IF_T:
260
+				/* if null expr => ignore if? */
261
+				if ((a->p1_type==EXPR_ST)&&a->p1.data){
262
+					v=eval_expr((struct expr*)a->p1.data, msg);
263
+					if (v<0){
264
+						LOG(L_WARN,"WARNING: do_action:"
265
+									"error in expression\n");
266
+					}
267
+					ret=1; /* default is continue */
268
+					if (v==1){
269
+						if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
270
+							ret=run_actions((struct action*)a->p2.data, msg);
271
+						}
272
+					}else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
273
+							ret=run_actions((struct action*)a->p3.data, msg);
274
+					}
275
+				}
276
+			break;
268 277
 		default:
269 278
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
270 279
 	}
... ...
@@ -278,7 +287,8 @@ error_uri:
278 287
 
279 288
 
280 289
 
281
-/* returns: 0 on success, -1 on error */
290
+/* returns: 0, or 1 on success, <0 on error */
291
+/* (0 if drop or break encountered, 1 if not ) */
282 292
 int run_actions(struct action* a, struct sip_msg* msg)
283 293
 {
284 294
 	struct action* t;
... ...
@@ -305,7 +315,7 @@ int run_actions(struct action* a, struct sip_msg* msg)
305 315
 	}
306 316
 	
307 317
 	rec_lev--;
308
-	return 0;
318
+	return ret;
309 319
 	
310 320
 
311 321
 error:
... ...
@@ -40,7 +40,7 @@
40 40
 
41 41
 /* action keywords */
42 42
 FORWARD	forward
43
-DROP	drop
43
+DROP	"drop"|"break"
44 44
 SEND	send
45 45
 LOG		log
46 46
 ERROR	error
... ...
@@ -52,6 +52,8 @@ SET_USER		"rewriteuser"|"setuser"|"setu"
52 52
 SET_USERPASS	"rewriteuserpass"|"setuserpass"|"setup"
53 53
 SET_PORT		"rewriteport"|"setport"|"setp"
54 54
 SET_URI			"rewriteuri"|"seturi"
55
+IF				"if"
56
+ELSE			"else"
55 57
 
56 58
 
57 59
 /* condition keywords */
... ...
@@ -127,6 +129,8 @@ EAT_ABLE	[\ \t\b\r]
127 129
 <INITIAL>{SET_USERPASS}	{ count(); yylval.strval=yytext; return SET_USERPASS; }
128 130
 <INITIAL>{SET_PORT}	{ count(); yylval.strval=yytext; return SET_PORT; }
129 131
 <INITIAL>{SET_URI}	{ count(); yylval.strval=yytext; return SET_URI; }
132
+<INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
133
+<INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
130 134
 
131 135
 <INITIAL>{METHOD}	{ count(); yylval.strval=yytext; return METHOD; }
132 136
 <INITIAL>{URI}	{ count(); yylval.strval=yytext; return URI; }
... ...
@@ -166,7 +170,7 @@ EAT_ABLE	[\ \t\b\r]
166 170
 <INITIAL>{SLASH}	{ count(); return SLASH; }
167 171
 <INITIAL>{DOT}		{ count(); return DOT; }
168 172
 <INITIAL>\\{CR}		{count(); } /* eat the escaped CR */
169
-<INITIAL>{CR}		{ count(); return CR; }
173
+<INITIAL>{CR}		{ count();/* return CR;*/ }
170 174
 
171 175
 
172 176
 <INITIAL>{QUOTES} { count(); state=STRING_S; BEGIN(STRING1); }
... ...
@@ -12,6 +12,7 @@
12 12
 #include <sys/socket.h>
13 13
 #include <netinet/in.h>
14 14
 #include <arpa/inet.h>
15
+#include <string.h>
15 16
 #include "route_struct.h"
16 17
 #include "globals.h"
17 18
 #include "route.h"
... ...
@@ -33,7 +34,6 @@ char* tmp;
33 34
 	struct expr* expr;
34 35
 	struct action* action;
35 36
 	struct net* net;
36
-	struct route_elem* route_el;
37 37
 }
38 38
 
39 39
 /* terminals */
... ...
@@ -53,6 +53,8 @@ char* tmp;
53 53
 %token SET_USERPASS
54 54
 %token SET_PORT
55 55
 %token SET_URI
56
+%token IF
57
+%token ELSE
56 58
 
57 59
 %token METHOD
58 60
 %token URI
... ...
@@ -100,13 +102,14 @@ char* tmp;
100 102
 
101 103
 
102 104
 /*non-terminals */
103
-%type <expr> exp, condition,  exp_elem
104
-%type <action> action, actions, cmd
105
+%type <expr> exp, exp_elem /*, condition*/
106
+%type <action> action, actions, cmd, if_cmd, stm
105 107
 %type <uval> ipv4
106 108
 %type <net> net4
107 109
 %type <strval> host
108
-%type <route_el> rules;
109
-%type <route_el> rule;
110
+/*%type <route_el> rules;
111
+  %type <route_el> rule;
112
+*/
110 113
 
111 114
 
112 115
 
... ...
@@ -145,43 +148,55 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
145 148
 		| LISTEN EQUAL ipv4  {
146 149
 								if (addresses_no < MAX_LISTEN){
147 150
 									tmp=inet_ntoa(*(struct in_addr*)&$3);
148
-									names[addresses_no]=(char*)malloc(strlen(tmp)+1);
151
+									names[addresses_no]=
152
+												(char*)malloc(strlen(tmp)+1);
149 153
 									if (names[addresses_no]==0){
150
-										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
154
+										LOG(L_CRIT, "ERROR: cfg. parser: "
155
+														"out of memory.\n");
151 156
 									}else{
152
-										strncpy(names[addresses_no], tmp, strlen(tmp)+1);
157
+										strncpy(names[addresses_no], tmp,
158
+												strlen(tmp)+1);
153 159
 										addresses_no++;
154 160
 									}
155 161
 								}else{
156
-									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
162
+									LOG(L_CRIT, "ERROR: cfg. parser:"
163
+												" too many listen addresses"
157 164
 												"(max. %d).\n", MAX_LISTEN);
158 165
 								}
159 166
 							  }
160 167
 		| LISTEN EQUAL ID	 {
161 168
 								if (addresses_no < MAX_LISTEN){
162
-									names[addresses_no]=(char*)malloc(strlen($3)+1);
169
+									names[addresses_no]=
170
+												(char*)malloc(strlen($3)+1);
163 171
 									if (names[addresses_no]==0){
164
-										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
172
+										LOG(L_CRIT, "ERROR: cfg. parser:"
173
+														" out of memory.\n");
165 174
 									}else{
166
-										strncpy(names[addresses_no], $3, strlen($3)+1);
175
+										strncpy(names[addresses_no], $3,
176
+													strlen($3)+1);
167 177
 										addresses_no++;
168 178
 									}
169 179
 								}else{
170
-									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
180
+									LOG(L_CRIT, "ERROR: cfg. parser: "
181
+												"too many listen addresses"
171 182
 												"(max. %d).\n", MAX_LISTEN);
172 183
 								}
173 184
 							  }
174 185
 		| LISTEN EQUAL STRING {
175 186
 								if (addresses_no < MAX_LISTEN){
176
-									names[addresses_no]=(char*)malloc(strlen($3)+1);
187
+									names[addresses_no]=
188
+										(char*)malloc(strlen($3)+1);
177 189
 									if (names[addresses_no]==0){
178
-										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
190
+										LOG(L_CRIT, "ERROR: cfg. parser:"
191
+													" out of memory.\n");
179 192
 									}else{
180
-										strncpy(names[addresses_no], $3, strlen($3)+1);
193
+										strncpy(names[addresses_no], $3,
194
+												strlen($3)+1);
181 195
 										addresses_no++;
182 196
 									}
183 197
 								}else{
184
-									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
198
+									LOG(L_CRIT, "ERROR: cfg. parser: "
199
+												"too many listen addresses"
185 200
 												"(max. %d).\n", MAX_LISTEN);
186 201
 								}
187 202
 							  }
... ...
@@ -206,9 +221,9 @@ ipv4:	NUMBER DOT NUMBER DOT NUMBER DOT NUMBER {
206 221
 												}
207 222
 	;
208 223
 
209
-route_stm:	ROUTE LBRACE rules RBRACE { push($3, &rlist[DEFAULT_RT]); }
224
+route_stm:	ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); }
210 225
 
211
-		| ROUTE LBRACK NUMBER RBRACK LBRACE rules RBRACE { 
226
+		| ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE { 
212 227
 										if (($3<RT_NO) && ($3>=0)){
213 228
 											push($6, &rlist[$3]);
214 229
 										}else{
... ...
@@ -218,7 +233,7 @@ route_stm:	ROUTE LBRACE rules RBRACE { push($3, &rlist[DEFAULT_RT]); }
218 233
 										}
219 234
 		| ROUTE error { yyerror("invalid  route  statement"); }
220 235
 	;
221
-
236
+/*
222 237
 rules:	rules rule { push($2, &$1); $$=$1; }
223 238
 	| rule {$$=$1; }
224 239
 	| rules error { $$=0; yyerror("invalid rule"); }
... ...
@@ -231,12 +246,12 @@ rule:	condition	actions CR {
231 246
 									YYABORT;
232 247
 								}
233 248
 							  }
234
-	| CR  /* null rule */		{ $$=0;}
249
+	| CR		{ $$=0;}
235 250
 	| condition error { $$=0; yyerror("bad actions in rule"); }
236 251
 	;
237 252
 
238 253
 condition:	exp {$$=$1;}
239
-	;
254
+*/
240 255
 
241 256
 exp:	exp AND exp 	{ $$=mk_exp(AND_OP, $1, $3); }
242 257
 	| exp OR  exp		{ $$=mk_exp(OR_OP, $1, $3);  }
... ...
@@ -319,6 +334,8 @@ exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST,
319 334
 		| DSTIP MATCH error  { $$=0; yyerror ( "hostname  expected" ); }
320 335
 		| DSTIP error { $$=0; 
321 336
 						yyerror("invalid operator, == or =~ expected");}
337
+		| stm				{ $$=mk_elem( NO_OP, ACTIONS_ST, ACTION_O, $1 ); }
338
+		| NUMBER		{$$=mk_elem( NO_OP, NUMBER_ST, NUMBER_O, (void*)$1 ); }
322 339
 	;
323 340
 
324 341
 net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); } 
... ...
@@ -326,7 +343,8 @@ net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); }
326 343
 								yyerror("invalid bit number in netmask");
327 344
 								$$=0;
328 345
 							}else{
329
-								$$=mk_net($1, htonl( ($3)?~( (1<<32-$3)-1 ):0 ) );
346
+								$$=mk_net($1, 
347
+										htonl( ($3)?~( (1<<(32-$3))-1 ):0 ) );
330 348
 							}
331 349
 						}
332 350
 	| ipv4				{ $$=mk_net($1, 0xffffffff); }
... ...
@@ -337,8 +355,8 @@ net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); }
337 355
 host:	ID				{ $$=$1; }
338 356
 	| host DOT ID		{ $$=(char*)malloc(strlen($1)+1+strlen($3)+1);
339 357
 						  if ($$==0){
340
-						  	LOG(L_CRIT, "ERROR: cfg. parser: memory allocation failure"
341
-						 				" while parsing host\n");
358
+						  	LOG(L_CRIT, "ERROR: cfg. parser: memory allocation"
359
+										" failure while parsing host\n");
342 360
 						  }else{
343 361
 						  	memcpy($$, $1, strlen($1));
344 362
 						  	$$[strlen($1)]='.';
... ...
@@ -351,6 +369,10 @@ host:	ID				{ $$=$1; }
351 369
 	;
352 370
 
353 371
 
372
+stm:		cmd						{ $$=$1; }
373
+		|	LBRACE actions RBRACE	{ $$=$2; }
374
+	;
375
+
354 376
 actions:	actions action	{$$=append_action($1, $2); }
355 377
 		| action			{$$=$1;}
356 378
 		| actions error { $$=0; yyerror("bad command"); }
... ...
@@ -361,6 +383,24 @@ action:		cmd SEMICOLON {$$=$1;}
361 383
 		| cmd error { $$=0; yyerror("bad command: missing ';'?"); }
362 384
 	;
363 385
 
386
+if_cmd:		IF exp stm				{ $$=mk_action3( IF_T,
387
+													 EXPR_ST,
388
+													 ACTIONS_ST,
389
+													 NOSUBTYPE,
390
+													 $2,
391
+													 $3,
392
+													 0);
393
+									}
394
+		|	IF exp stm ELSE stm		{ $$=mk_action3( IF_T,
395
+													 EXPR_ST,
396
+													 ACTIONS_ST,
397
+													 ACTIONS_ST,
398
+													 $2,
399
+													 $3,
400
+													 $5);
401
+									}
402
+	;
403
+
364 404
 cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
365 405
 														STRING_ST,
366 406
 														NUMBER_ST,
... ...
@@ -472,24 +512,37 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
472 512
 		| EXEC LPAREN STRING RPAREN	{ $$=mk_action(	EXEC_T, STRING_ST, 0,
473 513
 													$3, 0);
474 514
 									}
475
-		| SET_HOST LPAREN STRING RPAREN { $$=mk_action( SET_HOST_T, STRING_ST, 0, $3, 0); }
515
+		| SET_HOST LPAREN STRING RPAREN { $$=mk_action(SET_HOST_T, STRING_ST,
516
+														0, $3, 0); }
476 517
 		| SET_HOST error { $$=0; yyerror("missing '(' or ')' ?"); }
477
-		| SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
478
-		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, STRING_ST, 0, $3, 0); }
518
+		| SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, "
519
+														"string expected"); }
520
+		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, 
521
+														STRING_ST, 0, $3, 0); }
479 522
 		| SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
480
-		| SET_HOSTPORT LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
481
-		| SET_PORT LPAREN STRING RPAREN { $$=mk_action( SET_PORT_T, STRING_ST, 0, $3, 0); }
523
+		| SET_HOSTPORT LPAREN error RPAREN { $$=0; yyerror("bad argument,"
524
+												" string expected"); }
525
+		| SET_PORT LPAREN STRING RPAREN { $$=mk_action( SET_PORT_T, STRING_ST,
526
+														0, $3, 0); }
482 527
 		| SET_PORT error { $$=0; yyerror("missing '(' or ')' ?"); }
483
-		| SET_PORT LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
484
-		| SET_USER LPAREN STRING RPAREN { $$=mk_action( SET_USER_T, STRING_ST, 0, $3, 0); }
528
+		| SET_PORT LPAREN error RPAREN { $$=0; yyerror("bad argument, "
529
+														"string expected"); }
530
+		| SET_USER LPAREN STRING RPAREN { $$=mk_action( SET_USER_T, STRING_ST,
531
+														0, $3, 0); }
485 532
 		| SET_USER error { $$=0; yyerror("missing '(' or ')' ?"); }
486
-		| SET_USER LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
487
-		| SET_USERPASS LPAREN STRING RPAREN { $$=mk_action( SET_USERPASS_T, STRING_ST, 0, $3, 0); }
533
+		| SET_USER LPAREN error RPAREN { $$=0; yyerror("bad argument, "
534
+														"string expected"); }
535
+		| SET_USERPASS LPAREN STRING RPAREN { $$=mk_action( SET_USERPASS_T, 
536
+														STRING_ST, 0, $3, 0); }
488 537
 		| SET_USERPASS error { $$=0; yyerror("missing '(' or ')' ?"); }
489
-		| SET_USERPASS LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
490
-		| SET_URI LPAREN STRING RPAREN { $$=mk_action( SET_URI_T, STRING_ST, 0, $3, 0); }
538
+		| SET_USERPASS LPAREN error RPAREN { $$=0; yyerror("bad argument, "
539
+														"string expected"); }
540
+		| SET_URI LPAREN STRING RPAREN { $$=mk_action( SET_URI_T, STRING_ST, 
541
+														0, $3, 0); }
491 542
 		| SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
492
-		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
543
+		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, "
544
+										"string expected"); }
545
+		| if_cmd		{ $$=$1; }
493 546
 	;
494 547
 
495 548
 
... ...
@@ -10,7 +10,7 @@
10 10
 /* default sip port if none specified */
11 11
 #define SIP_PORT 5060
12 12
 
13
-#define CFG_FILE "./sip_router.cfg"
13
+#define CFG_FILE "./ser.cfg"
14 14
 
15 15
 /* receive buffer size */
16 16
 #define BUF_SIZE 65507
... ...
@@ -30,7 +30,7 @@
30 30
 
31 31
 
32 32
 static char id[]="@(#) $Id$";
33
-static char version[]="sip_router 0.6";
33
+static char version[]="ser 0.7";
34 34
 static char flags[]="NOCR:"
35 35
 #ifdef NOCR
36 36
 "On"
... ...
@@ -46,7 +46,7 @@ static char flags[]="NOCR:"
46 46
 ;
47 47
 
48 48
 static char help_msg[]= "\
49
-Usage: sip_router -l address [-l address] [options]\n\
49
+Usage: ser -l address [-l address] [options]\n\
50 50
 Options:\n\
51 51
     -f file      Configuration file (default " CFG_FILE ")\n\
52 52
     -p port      Listen on the specified port (default: 5060)\n\
... ...
@@ -345,6 +345,12 @@ int main(int argc, char** argv)
345 345
 	
346 346
 	
347 347
 	print_rl();
348
+	/* fix routing lists */
349
+	if ( (r=fix_rls())!=0){
350
+		fprintf(stderr, "ERROR: error %x while trying to fix configuration\n",
351
+						r);
352
+		goto error;
353
+	};
348 354
 
349 355
 	/* fix parameters */
350 356
 	if (port_no<=0) port_no=SIP_PORT;
... ...
@@ -19,7 +19,6 @@
19 19
 int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
20 20
 {
21 21
 	struct sip_msg msg;
22
-	struct route_elem *re;
23 22
 
24 23
 	memset(&msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
25 24
 	/* fill in msg */
... ...
@@ -46,19 +45,10 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
46 45
 		}
47 46
 		/* check if neccesarry to add receive? */
48 47
 		
49
-		/* find route */
50
-		re=route_match( &msg, &rlist[0]);
51
-		if (re==0){
52
-			/* no route found, send back error msg? */
53
-			LOG(L_WARN, "WARNING: receive_msg: no route found!\n");
54
-			goto skip;
55
-		}
56
-		re->tx++;
57
-		/* send msg */
58
-		DBG(" found route \n");
59
-		if (run_actions(re->actions, &msg)<0){
48
+		/* exec routing script */
49
+		if (run_actions(rlist[0], &msg)<0){
60 50
 			LOG(L_WARN, "WARNING: receive_msg: "
61
-					"error while trying actions\n");
51
+					"error while trying script\n");
62 52
 			goto error;
63 53
 		}
64 54
 	}else if (msg.first_line.type==SIP_REPLY){
... ...
@@ -18,78 +18,17 @@
18 18
 #include "route.h"
19 19
 #include "dprint.h"
20 20
 #include "proxy.h"
21
+#include "action.h"
21 22
 
22 23
 #ifdef DEBUG_DMALLOC
23 24
 #include <dmalloc.h>
24 25
 #endif
25 26
 
26
-/* main routing list */
27
-struct route_elem* rlist[RT_NO];
27
+/* main routing script table  */
28
+struct action* rlist[RT_NO];
28 29
 
29 30
 
30
-
31
- void free_re(struct route_elem* r)
32
-{
33
-	/*int i;*/
34
-	if (r){
35
-		/*
36
-			regfree(&(r->method));
37
-			regfree(&(r->uri));
38
-			
39
-			if (r->host.h_name)      free(r->host.h_name);
40
-			if (r->host.h_aliases){
41
-				for (i=0; r->host.h_aliases[i]; i++)
42
-					free(r->host.h_aliases[i]);
43
-				free(r->host.h_aliases);
44
-			}
45
-			if (r->host.h_addr_list){
46
-				for (i=0; r->host.h_addr_list[i]; i++)
47
-					free(r->host.h_addr_list[i]);
48
-				free(r->host.h_addr_list);
49
-			}
50
-		*/
51
-			free(r);
52
-	}
53
-}
54
-
55
-
56
-
57
-struct route_elem* init_re()
58
-{
59
-	struct route_elem* r;
60
-	r=(struct route_elem *) malloc(sizeof(struct route_elem));
61
-	if (r==0) return 0;
62
-	memset((void*)r, 0, sizeof (struct route_elem));
63
-	return r;
64
-}
65
-
66
-
67
-/* adds re list to head; re must be null terminated (last re->next=0))*/
68
-void push(struct route_elem* re, struct route_elem** head)
69
-{
70
-	struct route_elem *t;
71
-	if (*head==0){
72
-		*head=re;
73
-		return;
74
-	}
75
-	for (t=*head; t->next;t=t->next);
76
-	t->next=re;
77
-}
78
-
79
-
80
-
81
-void clear_rlist(struct route_elem** rl)
82
-{
83
-	struct route_elem *t, *u;
84
-
85
-	if (*rl==0) return;
86
-	u=0;
87
-	for (t=*rl; t; u=t, t=t->next){
88
-		if (u) free_re(u);
89
-	}
90
-	*rl=0;
91
-}
92
-
31
+static int fix_actions(struct action* a); /*fwd declaration*/
93 32
 
94 33
 
95 34
 /* traverses an expr tree and compiles the REs where necessary) 
... ...
@@ -99,6 +38,7 @@ static int fix_expr(struct expr* exp)
99 38
 	regex_t* re;
100 39
 	int ret;
101 40
 	
41
+	ret=E_BUG;
102 42
 	if (exp==0){
103 43
 		LOG(L_CRIT, "BUG: fix_expr: null pointer\n");
104 44
 		return E_BUG;
... ...
@@ -143,6 +83,13 @@ static int fix_expr(struct expr* exp)
143 83
 					return E_BUG;
144 84
 				}
145 85
 			}
86
+			if (exp->l.operand==ACTION_O){
87
+				ret=fix_actions((struct action*)exp->r.param);
88
+				if (ret!=0){
89
+					LOG(L_CRIT, "ERROR: fix_expr : fix_actions error\n");
90
+					return ret;
91
+				}
92
+			}
146 93
 			ret=0;
147 94
 	}
148 95
 	return ret;
... ...
@@ -151,12 +98,18 @@ static int fix_expr(struct expr* exp)
151 98
 
152 99
 
153 100
 /* adds the proxies in the proxy list & resolves the hostnames */
101
+/* returns 0 if ok, <0 on error */
154 102
 static int fix_actions(struct action* a)
155 103
 {
156 104
 	struct action *t;
157 105
 	struct proxy_l* p;
158 106
 	char *tmp;
107
+	int ret;
159 108
 	
109
+	if (a==0){
110
+		LOG(L_CRIT,"BUG: fix_actions: null pointer\n");
111
+		return E_BUG;
112
+	}
160 113
 	for(t=a; t!=0; t=t->next){
161 114
 		switch(t->type){
162 115
 			case FORWARD_T:
... ...
@@ -187,6 +140,36 @@ static int fix_actions(struct action* a)
187 140
 							return E_BUG;
188 141
 					}
189 142
 					break;
143
+		case IF_T:
144
+				if (t->p1_type!=EXPR_ST){
145
+					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
146
+								"%d for if (should be expr)\n",
147
+								t->p1_type);
148
+					return E_BUG;
149
+				}else if( (t->p2_type!=ACTIONS_ST)&&(t->p2_type!=NOSUBTYPE) ){
150
+					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
151
+								"%d for if() {...} (should be action)\n",
152
+								t->p2_type);
153
+					return E_BUG;
154
+				}else if( (t->p3_type!=ACTIONS_ST)&&(t->p3_type!=NOSUBTYPE) ){
155
+					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
156
+								"%d for if() {} else{...}(should be action)\n",
157
+								t->p3_type);
158
+					return E_BUG;
159
+				}
160
+				if (t->p1.data){
161
+					if ((ret=fix_expr((struct expr*)t->p1.data))<0)
162
+						return ret;
163
+				}
164
+				if ( (t->p2_type==ACTIONS_ST)&&(t->p2.data) ){
165
+					if ((ret=fix_actions((struct action*)t->p2.data))<0)
166
+						return ret;
167
+				}
168
+				if ( (t->p3_type==ACTIONS_ST)&&(t->p3.data) ){
169
+						if ((ret=fix_actions((struct action*)t->p3.data))<0)
170
+						return ret;
171
+				}
172
+				break;
190 173
 		}
191 174
 	}
192 175
 	return 0;
... ...
@@ -277,6 +260,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
277 260
 {
278 261
 
279 262
 	int ret;
263
+	ret=E_BUG;
280 264
 	
281 265
 	if (e->type!=ELEM_T){
282 266
 		LOG(L_CRIT," BUG: eval_elem: invalid type\n");
... ...
@@ -302,8 +286,11 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
302 286
 		case DSTIP_O:
303 287
 				ret=comp_ip(msg->dst_ip, e->r.param, e->op, e->subtype);
304 288
 				break;
305
-		case DEFAULT_O:
306
-				ret=1;
289
+		case NUMBER_O:
290
+				ret=!(!e->r.intval); /* !! to transform it in {0,1} */
291
+				break;
292
+		case ACTION_O:
293
+				ret=(run_actions( (struct action*)e->r.param, msg)>=0)?1:0;
307 294
 				break;
308 295
 		default:
309 296
 				LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n",
... ...
@@ -316,7 +303,8 @@ error:
316 303
 
317 304
 
318 305
 
319
-static int eval_expr(struct expr* e, struct sip_msg* msg)
306
+/* ret= 0/1 (true/false) & -1 on error */
307
+int eval_expr(struct expr* e, struct sip_msg* msg)
320 308
 {
321 309
 	static int rec_lev=0;
322 310
 	int ret;
... ...
@@ -365,53 +353,56 @@ skip:
365 353
 }
366 354
 
367 355
 
356
+/* adds an action list to head; a must be null terminated (last a->next=0))*/
357
+void push(struct action* a, struct action** head)
358
+{
359
+	struct action *t;
360
+	if (*head==0){
361
+		*head=a;
362
+		return;
363
+	}
364
+	for (t=*head; t->next;t=t->next);
365
+	t->next=a;
366
+}
367
+
368
+
368 369
 
369 370
 
370
-int add_rule(struct expr* e, struct action* a, struct route_elem** head)
371
+int add_actions(struct action* a, struct action** head)
371 372
 {
372
-	
373
-	struct route_elem* re;
374 373
 	int ret;
375 374
 
376
-	re=init_re();
377
-	if (re==0) return E_OUT_OF_MEM;
378
-	LOG(L_DBG, "add_rule: fixing expr...\n");
379
-	if ((ret=fix_expr(e))!=0) goto error;
380
-	LOG(L_DBG, "add_rule: fixing actions...\n");
375
+	LOG(L_DBG, "add_actions: fixing actions...\n");
381 376
 	if ((ret=fix_actions(a))!=0) goto error;
382
-	re->condition=e;
383
-	re->actions=a;
384
-	
385
-	push(re,head);
377
+	push(a,head);
386 378
 	return 0;
387 379
 	
388 380
 error:
389
-	free_re(re);
390 381
 	return ret;
391 382
 }
392 383
 
393 384
 
394 385
 
395
-struct route_elem* route_match(struct sip_msg* msg, struct route_elem** rl)
386
+/* fixes all action tables */
387
+/* returns 0 if ok , <0 on error */
388
+int fix_rls()
396 389
 {
397
-	struct route_elem* t;
398
-	if (*rl==0){
399
-		LOG(L_ERR, "WARNING: route_match: empty routing table\n");
400
-		return 0;
401
-	}
402
-	for (t=*rl; t; t=t->next){
403
-		if (eval_expr(t->condition, msg)==1) return t;
390
+	int i,ret;
391
+	for(i=0;i<RT_NO;i++){
392
+		if(rlist[i]){
393
+			if ((ret=fix_actions(rlist[i]))!=0){
394
+				return ret;
395
+			}
396
+		}
404 397
 	}
405
-	/* no match :( */
406 398
 	return 0;
407 399
 }
408 400
 
409 401
 
410
-
411 402
 /* debug function, prints main routing table */
412 403
 void print_rl()
413 404
 {
414
-	struct route_elem* t;
405
+	struct action* t;
415 406
 	int i,j;
416 407
 
417 408
 	for(j=0; j<RT_NO; j++){
... ...
@@ -421,15 +412,10 @@ void print_rl()
421 412
 		}
422 413
 		DBG("routing table %d:\n",j);
423 414
 		for (t=rlist[j],i=0; t; i++, t=t->next){
424
-			DBG("%2d.condition: ",i);
425
-			print_expr(t->condition);
426
-			DBG("\n  -> ");
427
-			print_action(t->actions);
428
-			DBG("\n    Statistics: tx=%d, errors=%d, tx_bytes=%d\n",
429
-					t->tx, t->errors, t->tx_bytes);
415
+			print_action(t);
430 416
 		}
417
+		DBG("\n");
431 418
 	}
432
-
433 419
 }
434 420
 
435 421
 
... ...
@@ -17,31 +17,17 @@
17 17
 /*#include "cfg_parser.h" */
18 18
 
19 19
 
20
+/* main "script table" */
21
+extern struct action* rlist[RT_NO];
20 22
 
21
-struct route_elem{
22
-	struct route_elem* next;
23 23
 
24
-	struct expr* condition;
25
-	struct action* actions;
26
-
27
-	int ok; /* set to 0 if an error was found sendig a pkt*/
28
-	/*counters*/
29
-	int errors;
30
-	int tx;
31
-	int tx_bytes;
32
-};
33
-
34
-/* main "routing table" */
35
-extern struct route_elem* rlist[RT_NO];
24
+void push(struct action* a, struct action** head);
25
+int add_actions(struct action* a, struct action** head);
26
+void print_rl();
27
+int fix_rls();
36 28
 
29
+int eval_expr(struct expr* e, struct sip_msg* msg);
37 30
 
38
-void free_re(struct route_elem* re);
39
-struct route_elem* init_re();
40
-void push(struct route_elem* re, struct route_elem** head);
41
-void clear_rlist(struct route_elem** rl);
42
-int add_rule(struct expr* e, struct action* a, struct route_elem** head);
43
-struct route_elem* route_match(struct sip_msg* msg,struct route_elem** rl);
44
-void print_rl();
45 31
 
46 32
 
47 33
 
... ...
@@ -72,6 +72,21 @@ error:
72 72
 }
73 73
 
74 74
 
75
+struct action* mk_action3(int type, int p1_type, int p2_type, int p3_type,
76
+							void* p1, void* p2, void* p3)
77
+{
78
+	struct action* a;
79
+
80
+	a=mk_action(type, p1_type, p2_type, p1, p2);
81
+	if (a){
82
+			a->p3_type=p3_type;
83
+			a->p3.data=p3;
84
+	}
85
+	return a;
86
+}
87
+
88
+
89
+
75 90
 struct action* append_action(struct action* a, struct action* b)
76 91
 {
77 92
 	struct action *t;
... ...
@@ -142,6 +157,11 @@ void print_expr(struct expr* exp)
142 157
 			case DSTIP_O:
143 158
 				DBG("dstip");
144 159
 				break;
160
+			case NUMBER_O:
161
+				break;
162
+			case ACTION_O:
163
+				print_action((struct action*) exp->r.param);
164
+				break;
145 165
 			default:
146 166
 				DBG("UNKNOWN");
147 167
 		}
... ...
@@ -152,6 +172,8 @@ void print_expr(struct expr* exp)
152 172
 			case MATCH_OP:
153 173
 				DBG("=~");
154 174
 				break;
175
+			case NO_OP:
176
+				break;
155 177
 			default:
156 178
 				DBG("<UNKNOWN>");
157 179
 		}
... ...
@@ -168,6 +190,12 @@ void print_expr(struct expr* exp)
168 190
 			case IP_ST:
169 191
 					print_ip(exp->r.intval);
170 192
 					break;
193
+			case ACTIONS_ST:
194
+					print_action((struct action*)exp->r.param);
195
+					break;
196
+			case NUMBER_ST:
197
+					DBG("%d",exp->r.intval);
198
+					break;
171 199
 			default:
172 200
 					DBG("type<%d>", exp->subtype);
173 201
 		}
... ...
@@ -248,6 +276,9 @@ void print_action(struct action* a)
248 276
 			case SET_URI_T:
249 277
 					DBG("seturi(");
250 278
 					break;
279
+			case IF_T:
280
+					DBG("if (");
281
+					break;
251 282
 			default:
252 283
 					DBG("UNKNOWN(");
253 284
 		}
... ...
@@ -261,9 +292,16 @@ void print_action(struct action* a)
261 292
 			case IP_ST:
262 293
 					print_ip(t->p1.number);
263 294
 					break;
295
+			case EXPR_ST:
296
+					print_expr((struct expr*)t->p1.data);
297
+					break;
298
+			case ACTIONS_ST:
299
+					print_action((struct action*)t->p1.data);
300
+					break;
264 301
 			default:
265 302
 					DBG("type<%d>", t->p1_type);
266 303
 		}
304
+		if (t->type==IF_T) DBG(") {");
267 305
 		switch(t->p2_type){
268 306
 			case NOSUBTYPE:
269 307
 					break;
... ...
@@ -273,10 +311,36 @@ void print_action(struct action* a)
273 311
 			case NUMBER_ST:
274 312
 					DBG(", %d",t->p2.number);
275 313
 					break;
314
+			case EXPR_ST:
315
+					print_expr((struct expr*)t->p2.data);
316
+					break;
317
+			case ACTIONS_ST:
318
+					print_action((struct action*)t->p2.data);
319
+					break;
276 320
 			default:
277 321
 					DBG(", type<%d>", t->p2_type);
278 322
 		}
279
-		DBG("); ");
323
+		if (t->type==IF_T) DBG("} else {");
324
+		switch(t->p3_type){
325
+			case NOSUBTYPE:
326
+					break;
327
+			case STRING_ST:
328
+					DBG(", \"%s\"", t->p3.string);
329
+					break;
330
+			case NUMBER_ST:
331
+					DBG(", %d",t->p3.number);
332
+					break;
333
+			case EXPR_ST:
334
+					print_expr((struct expr*)t->p3.data);
335
+					break;
336
+			case ACTIONS_ST:
337
+					print_action((struct action*)t->p3.data);
338
+					break;
339
+			default:
340
+					DBG(", type<%d>", t->p3_type);
341
+		}
342
+		if (t->type==IF_T) DBG("}; ");
343
+		else	DBG("); ");
280 344
 	}
281 345
 }
282 346
 			
... ...
@@ -8,12 +8,14 @@
8 8
 
9 9
 enum { EXP_T=1, ELEM_T };
10 10
 enum { AND_OP=1, OR_OP, NOT_OP };
11
-enum { EQUAL_OP=10, MATCH_OP };
12
-enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O, DEFAULT_O };
11
+enum { EQUAL_OP=10, MATCH_OP, NO_OP };
12
+enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O, DEFAULT_O, ACTION_O, NUMBER_O};
13 13
 
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};
16
-enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST };
14
+enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
15
+		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, 
16
+		SET_PORT_T, SET_URI_T, IF_T };
17
+enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
18
+		EXPR_ST, ACTIONS_ST };
17 19
 
18 20
 	
19 21
 struct expr{
... ...
@@ -36,11 +38,12 @@ struct action{
36 38
 	int type;  /* forward, drop, log, send ...*/
37 39
 	int p1_type;
38 40
 	int p2_type;
41
+	int p3_type;
39 42
 	union {
40 43
 		int number;
41 44
 		char* string;
42 45
 		void* data;
43
-	}p1, p2;
46
+	}p1, p2, p3;
44 47
 	struct action* next;
45 48
 };
46 49
 
... ...
@@ -52,7 +55,10 @@ struct net{
52 55
 
53 56
 struct expr* mk_exp(int op, struct expr* left, struct expr* right);
54 57
 struct expr* mk_elem(int op, int subtype, int operand, void* param);
55
-struct action* mk_action(int type, int p1_type, int p2_type, void* p1, void* p2);
58
+struct action* mk_action(int type, int p1_type, int p2_type,
59
+							void* p1, void* p2);
60
+struct action* mk_action3(int type, int p1_type, int p2_type, int p3_type, 
61
+							void* p1, void* p2, void* p3);
56 62
 struct action* append_action(struct action* a, struct action* b);
57 63
 
58 64