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 178
 					ret=1;
179 179
 					break;
180 180
 				}
181
-
182 181
 				if (msg->new_uri) tmp=msg->new_uri;
183 182
 				else tmp=msg->first_line.u.request.uri;
184 183
 				if (parse_uri(tmp, strlen(tmp), &uri)<0){
... ...
@@ -264,7 +256,24 @@ int do_action(struct action* a, struct sip_msg* msg)
264 264
 				msg->new_uri=new_uri;
265 265
 				ret=1;
266 266
 				break;
267
-
267
+		case IF_T:
268
+				/* if null expr => ignore if? */
269
+				if ((a->p1_type==EXPR_ST)&&a->p1.data){
270
+					v=eval_expr((struct expr*)a->p1.data, msg);
271
+					if (v<0){
272
+						LOG(L_WARN,"WARNING: do_action:"
273
+									"error in expression\n");
274
+					}
275
+					ret=1; /* default is continue */
276
+					if (v==1){
277
+						if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
278
+							ret=run_actions((struct action*)a->p2.data, msg);
279
+						}
280
+					}else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){
281
+							ret=run_actions((struct action*)a->p3.data, msg);
282
+					}
283
+				}
284
+			break;
268 285
 		default:
269 286
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
270 287
 	}
... ...
@@ -278,7 +287,8 @@ error_uri:
278 278
 
279 279
 
280 280
 
281
-/* returns: 0 on success, -1 on error */
281
+/* returns: 0, or 1 on success, <0 on error */
282
+/* (0 if drop or break encountered, 1 if not ) */
282 283
 int run_actions(struct action* a, struct sip_msg* msg)
283 284
 {
284 285
 	struct action* t;
... ...
@@ -305,7 +315,7 @@ int run_actions(struct action* a, struct sip_msg* msg)
305 305
 	}
306 306
 	
307 307
 	rec_lev--;
308
-	return 0;
308
+	return ret;
309 309
 	
310 310
 
311 311
 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 127
 <INITIAL>{SET_USERPASS}	{ count(); yylval.strval=yytext; return SET_USERPASS; }
128 128
 <INITIAL>{SET_PORT}	{ count(); yylval.strval=yytext; return SET_PORT; }
129 129
 <INITIAL>{SET_URI}	{ count(); yylval.strval=yytext; return SET_URI; }
130
+<INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
131
+<INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
130 132
 
131 133
 <INITIAL>{METHOD}	{ count(); yylval.strval=yytext; return METHOD; }
132 134
 <INITIAL>{URI}	{ count(); yylval.strval=yytext; return URI; }
... ...
@@ -166,7 +170,7 @@ EAT_ABLE	[\ \t\b\r]
166 166
 <INITIAL>{SLASH}	{ count(); return SLASH; }
167 167
 <INITIAL>{DOT}		{ count(); return DOT; }
168 168
 <INITIAL>\\{CR}		{count(); } /* eat the escaped CR */
169
-<INITIAL>{CR}		{ count(); return CR; }
169
+<INITIAL>{CR}		{ count();/* return CR;*/ }
170 170
 
171 171
 
172 172
 <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 33
 	struct expr* expr;
34 34
 	struct action* action;
35 35
 	struct net* net;
36
-	struct route_elem* route_el;
37 36
 }
38 37
 
39 38
 /* 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 100
 
101 101
 
102 102
 /*non-terminals */
103
-%type <expr> exp, condition,  exp_elem
104
-%type <action> action, actions, cmd
103
+%type <expr> exp, exp_elem /*, condition*/
104
+%type <action> action, actions, cmd, if_cmd, stm
105 105
 %type <uval> ipv4
106 106
 %type <net> net4
107 107
 %type <strval> host
108
-%type <route_el> rules;
109
-%type <route_el> rule;
108
+/*%type <route_el> rules;
109
+  %type <route_el> rule;
110
+*/
110 111
 
111 112
 
112 113
 
... ...
@@ -145,43 +148,55 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
145 145
 		| LISTEN EQUAL ipv4  {
146 146
 								if (addresses_no < MAX_LISTEN){
147 147
 									tmp=inet_ntoa(*(struct in_addr*)&$3);
148
-									names[addresses_no]=(char*)malloc(strlen(tmp)+1);
148
+									names[addresses_no]=
149
+												(char*)malloc(strlen(tmp)+1);
149 150
 									if (names[addresses_no]==0){
150
-										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
151
+										LOG(L_CRIT, "ERROR: cfg. parser: "
152
+														"out of memory.\n");
151 153
 									}else{
152
-										strncpy(names[addresses_no], tmp, strlen(tmp)+1);
154
+										strncpy(names[addresses_no], tmp,
155
+												strlen(tmp)+1);
153 156
 										addresses_no++;
154 157
 									}
155 158
 								}else{
156
-									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
159
+									LOG(L_CRIT, "ERROR: cfg. parser:"
160
+												" too many listen addresses"
157 161
 												"(max. %d).\n", MAX_LISTEN);
158 162
 								}
159 163
 							  }
160 164
 		| LISTEN EQUAL ID	 {
161 165
 								if (addresses_no < MAX_LISTEN){
162
-									names[addresses_no]=(char*)malloc(strlen($3)+1);
166
+									names[addresses_no]=
167
+												(char*)malloc(strlen($3)+1);
163 168
 									if (names[addresses_no]==0){
164
-										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
169
+										LOG(L_CRIT, "ERROR: cfg. parser:"
170
+														" out of memory.\n");
165 171
 									}else{
166
-										strncpy(names[addresses_no], $3, strlen($3)+1);
172
+										strncpy(names[addresses_no], $3,
173
+													strlen($3)+1);
167 174
 										addresses_no++;
168 175
 									}
169 176
 								}else{
170
-									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
177
+									LOG(L_CRIT, "ERROR: cfg. parser: "
178
+												"too many listen addresses"
171 179
 												"(max. %d).\n", MAX_LISTEN);
172 180
 								}
173 181
 							  }
174 182
 		| LISTEN EQUAL STRING {
175 183
 								if (addresses_no < MAX_LISTEN){
176
-									names[addresses_no]=(char*)malloc(strlen($3)+1);
184
+									names[addresses_no]=
185
+										(char*)malloc(strlen($3)+1);
177 186
 									if (names[addresses_no]==0){
178
-										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
187
+										LOG(L_CRIT, "ERROR: cfg. parser:"
188
+													" out of memory.\n");
179 189
 									}else{
180
-										strncpy(names[addresses_no], $3, strlen($3)+1);
190
+										strncpy(names[addresses_no], $3,
191
+												strlen($3)+1);
181 192
 										addresses_no++;
182 193
 									}
183 194
 								}else{
184
-									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
195
+									LOG(L_CRIT, "ERROR: cfg. parser: "
196
+												"too many listen addresses"
185 197
 												"(max. %d).\n", MAX_LISTEN);
186 198
 								}
187 199
 							  }
... ...
@@ -206,9 +221,9 @@ ipv4:	NUMBER DOT NUMBER DOT NUMBER DOT NUMBER {
206 206
 												}
207 207
 	;
208 208
 
209
-route_stm:	ROUTE LBRACE rules RBRACE { push($3, &rlist[DEFAULT_RT]); }
209
+route_stm:	ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); }
210 210
 
211
-		| ROUTE LBRACK NUMBER RBRACK LBRACE rules RBRACE { 
211
+		| ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE { 
212 212
 										if (($3<RT_NO) && ($3>=0)){
213 213
 											push($6, &rlist[$3]);
214 214
 										}else{
... ...
@@ -218,7 +233,7 @@ route_stm:	ROUTE LBRACE rules RBRACE { push($3, &rlist[DEFAULT_RT]); }
218 218
 										}
219 219
 		| ROUTE error { yyerror("invalid  route  statement"); }
220 220
 	;
221
-
221
+/*
222 222
 rules:	rules rule { push($2, &$1); $$=$1; }
223 223
 	| rule {$$=$1; }
224 224
 	| rules error { $$=0; yyerror("invalid rule"); }
... ...
@@ -231,12 +246,12 @@ rule:	condition	actions CR {
231 231
 									YYABORT;
232 232
 								}
233 233
 							  }
234
-	| CR  /* null rule */		{ $$=0;}
234
+	| CR		{ $$=0;}
235 235
 	| condition error { $$=0; yyerror("bad actions in rule"); }
236 236
 	;
237 237
 
238 238
 condition:	exp {$$=$1;}
239
-	;
239
+*/
240 240
 
241 241
 exp:	exp AND exp 	{ $$=mk_exp(AND_OP, $1, $3); }
242 242
 	| 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 319
 		| DSTIP MATCH error  { $$=0; yyerror ( "hostname  expected" ); }
320 320
 		| DSTIP error { $$=0; 
321 321
 						yyerror("invalid operator, == or =~ expected");}
322
+		| stm				{ $$=mk_elem( NO_OP, ACTIONS_ST, ACTION_O, $1 ); }
323
+		| NUMBER		{$$=mk_elem( NO_OP, NUMBER_ST, NUMBER_O, (void*)$1 ); }
322 324
 	;
323 325
 
324 326
 net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); } 
... ...
@@ -326,7 +343,8 @@ net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); }
326 326
 								yyerror("invalid bit number in netmask");
327 327
 								$$=0;
328 328
 							}else{
329
-								$$=mk_net($1, htonl( ($3)?~( (1<<32-$3)-1 ):0 ) );
329
+								$$=mk_net($1, 
330
+										htonl( ($3)?~( (1<<(32-$3))-1 ):0 ) );
330 331
 							}
331 332
 						}
332 333
 	| ipv4				{ $$=mk_net($1, 0xffffffff); }
... ...
@@ -337,8 +355,8 @@ net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); }
337 337
 host:	ID				{ $$=$1; }
338 338
 	| host DOT ID		{ $$=(char*)malloc(strlen($1)+1+strlen($3)+1);
339 339
 						  if ($$==0){
340
-						  	LOG(L_CRIT, "ERROR: cfg. parser: memory allocation failure"
341
-						 				" while parsing host\n");
340
+						  	LOG(L_CRIT, "ERROR: cfg. parser: memory allocation"
341
+										" failure while parsing host\n");
342 342
 						  }else{
343 343
 						  	memcpy($$, $1, strlen($1));
344 344
 						  	$$[strlen($1)]='.';
... ...
@@ -351,6 +369,10 @@ host:	ID				{ $$=$1; }
351 351
 	;
352 352
 
353 353
 
354
+stm:		cmd						{ $$=$1; }
355
+		|	LBRACE actions RBRACE	{ $$=$2; }
356
+	;
357
+
354 358
 actions:	actions action	{$$=append_action($1, $2); }
355 359
 		| action			{$$=$1;}
356 360
 		| actions error { $$=0; yyerror("bad command"); }
... ...
@@ -361,6 +383,24 @@ action:		cmd SEMICOLON {$$=$1;}
361 361
 		| cmd error { $$=0; yyerror("bad command: missing ';'?"); }
362 362
 	;
363 363
 
364
+if_cmd:		IF exp stm				{ $$=mk_action3( IF_T,
365
+													 EXPR_ST,
366
+													 ACTIONS_ST,
367
+													 NOSUBTYPE,
368
+													 $2,
369
+													 $3,
370
+													 0);
371
+									}
372
+		|	IF exp stm ELSE stm		{ $$=mk_action3( IF_T,
373
+													 EXPR_ST,
374
+													 ACTIONS_ST,
375
+													 ACTIONS_ST,
376
+													 $2,
377
+													 $3,
378
+													 $5);
379
+									}
380
+	;
381
+
364 382
 cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
365 383
 														STRING_ST,
366 384
 														NUMBER_ST,
... ...
@@ -472,24 +512,37 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
472 472
 		| EXEC LPAREN STRING RPAREN	{ $$=mk_action(	EXEC_T, STRING_ST, 0,
473 473
 													$3, 0);
474 474
 									}
475
-		| SET_HOST LPAREN STRING RPAREN { $$=mk_action( SET_HOST_T, STRING_ST, 0, $3, 0); }
475
+		| SET_HOST LPAREN STRING RPAREN { $$=mk_action(SET_HOST_T, STRING_ST,
476
+														0, $3, 0); }
476 477
 		| 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); }
478
+		| SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, "
479
+														"string expected"); }
480
+		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, 
481
+														STRING_ST, 0, $3, 0); }
479 482
 		| 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); }
483
+		| SET_HOSTPORT LPAREN error RPAREN { $$=0; yyerror("bad argument,"
484
+												" string expected"); }
485
+		| SET_PORT LPAREN STRING RPAREN { $$=mk_action( SET_PORT_T, STRING_ST,
486
+														0, $3, 0); }
482 487
 		| 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); }
488
+		| SET_PORT LPAREN error RPAREN { $$=0; yyerror("bad argument, "
489
+														"string expected"); }
490
+		| SET_USER LPAREN STRING RPAREN { $$=mk_action( SET_USER_T, STRING_ST,
491
+														0, $3, 0); }
485 492
 		| 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); }
493
+		| SET_USER LPAREN error RPAREN { $$=0; yyerror("bad argument, "
494
+														"string expected"); }
495
+		| SET_USERPASS LPAREN STRING RPAREN { $$=mk_action( SET_USERPASS_T, 
496
+														STRING_ST, 0, $3, 0); }
488 497
 		| 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); }
498
+		| SET_USERPASS LPAREN error RPAREN { $$=0; yyerror("bad argument, "
499
+														"string expected"); }
500
+		| SET_URI LPAREN STRING RPAREN { $$=mk_action( SET_URI_T, STRING_ST, 
501
+														0, $3, 0); }
491 502
 		| SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
492
-		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
503
+		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, "
504
+										"string expected"); }
505
+		| if_cmd		{ $$=$1; }
493 506
 	;
494 507
 
495 508
 
... ...
@@ -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 46
 		}
47 47
 		/* check if neccesarry to add receive? */
48 48
 		
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){
49
+		/* exec routing script */
50
+		if (run_actions(rlist[0], &msg)<0){
60 51
 			LOG(L_WARN, "WARNING: receive_msg: "
61
-					"error while trying actions\n");
52
+					"error while trying script\n");
62 53
 			goto error;
63 54
 		}
64 55
 	}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 99
 	regex_t* re;
100 100
 	int ret;
101 101
 	
102
+	ret=E_BUG;
102 103
 	if (exp==0){
103 104
 		LOG(L_CRIT, "BUG: fix_expr: null pointer\n");
104 105
 		return E_BUG;
... ...
@@ -143,6 +83,13 @@ static int fix_expr(struct expr* exp)
143 143
 					return E_BUG;
144 144
 				}
145 145
 			}
146
+			if (exp->l.operand==ACTION_O){
147
+				ret=fix_actions((struct action*)exp->r.param);
148
+				if (ret!=0){
149
+					LOG(L_CRIT, "ERROR: fix_expr : fix_actions error\n");
150
+					return ret;
151
+				}
152
+			}
146 153
 			ret=0;
147 154
 	}
148 155
 	return ret;
... ...
@@ -151,12 +98,18 @@ static int fix_expr(struct expr* exp)
151 151
 
152 152
 
153 153
 /* adds the proxies in the proxy list & resolves the hostnames */
154
+/* returns 0 if ok, <0 on error */
154 155
 static int fix_actions(struct action* a)
155 156
 {
156 157
 	struct action *t;
157 158
 	struct proxy_l* p;
158 159
 	char *tmp;
160
+	int ret;
159 161
 	
162
+	if (a==0){
163
+		LOG(L_CRIT,"BUG: fix_actions: null pointer\n");
164
+		return E_BUG;
165
+	}
160 166
 	for(t=a; t!=0; t=t->next){
161 167
 		switch(t->type){
162 168
 			case FORWARD_T:
... ...
@@ -187,6 +140,36 @@ static int fix_actions(struct action* a)
187 187
 							return E_BUG;
188 188
 					}
189 189
 					break;
190
+		case IF_T:
191
+				if (t->p1_type!=EXPR_ST){
192
+					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
193
+								"%d for if (should be expr)\n",
194
+								t->p1_type);
195
+					return E_BUG;
196
+				}else if( (t->p2_type!=ACTIONS_ST)&&(t->p2_type!=NOSUBTYPE) ){
197
+					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
198
+								"%d for if() {...} (should be action)\n",
199
+								t->p2_type);
200
+					return E_BUG;
201
+				}else if( (t->p3_type!=ACTIONS_ST)&&(t->p3_type!=NOSUBTYPE) ){
202
+					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
203
+								"%d for if() {} else{...}(should be action)\n",
204
+								t->p3_type);
205
+					return E_BUG;
206
+				}
207
+				if (t->p1.data){
208
+					if ((ret=fix_expr((struct expr*)t->p1.data))<0)
209
+						return ret;
210
+				}
211
+				if ( (t->p2_type==ACTIONS_ST)&&(t->p2.data) ){
212
+					if ((ret=fix_actions((struct action*)t->p2.data))<0)
213
+						return ret;
214
+				}
215
+				if ( (t->p3_type==ACTIONS_ST)&&(t->p3.data) ){
216
+						if ((ret=fix_actions((struct action*)t->p3.data))<0)
217
+						return ret;
218
+				}
219
+				break;
190 220
 		}
191 221
 	}
192 222
 	return 0;
... ...
@@ -277,6 +260,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
277 277
 {
278 278
 
279 279
 	int ret;
280
+	ret=E_BUG;
280 281
 	
281 282
 	if (e->type!=ELEM_T){
282 283
 		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 302
 		case DSTIP_O:
303 303
 				ret=comp_ip(msg->dst_ip, e->r.param, e->op, e->subtype);
304 304
 				break;
305
-		case DEFAULT_O:
306
-				ret=1;
305
+		case NUMBER_O:
306
+				ret=!(!e->r.intval); /* !! to transform it in {0,1} */
307
+				break;
308
+		case ACTION_O:
309
+				ret=(run_actions( (struct action*)e->r.param, msg)>=0)?1:0;
307 310
 				break;
308 311
 		default:
309 312
 				LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n",
... ...
@@ -316,7 +303,8 @@ error:
316 316
 
317 317
 
318 318
 
319
-static int eval_expr(struct expr* e, struct sip_msg* msg)
319
+/* ret= 0/1 (true/false) & -1 on error */
320
+int eval_expr(struct expr* e, struct sip_msg* msg)
320 321
 {
321 322
 	static int rec_lev=0;
322 323
 	int ret;
... ...
@@ -365,53 +353,56 @@ skip:
365 365
 }
366 366
 
367 367
 
368
+/* adds an action list to head; a must be null terminated (last a->next=0))*/
369
+void push(struct action* a, struct action** head)
370
+{
371
+	struct action *t;
372
+	if (*head==0){
373
+		*head=a;
374
+		return;
375
+	}
376
+	for (t=*head; t->next;t=t->next);
377
+	t->next=a;
378
+}
379
+
380
+
368 381
 
369 382
 
370
-int add_rule(struct expr* e, struct action* a, struct route_elem** head)
383
+int add_actions(struct action* a, struct action** head)
371 384
 {
372
-	
373
-	struct route_elem* re;
374 385
 	int ret;
375 386
 
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");
387
+	LOG(L_DBG, "add_actions: fixing actions...\n");
381 388
 	if ((ret=fix_actions(a))!=0) goto error;
382
-	re->condition=e;
383
-	re->actions=a;
384
-	
385
-	push(re,head);
389
+	push(a,head);
386 390
 	return 0;
387 391
 	
388 392
 error:
389
-	free_re(re);
390 393
 	return ret;
391 394
 }
392 395
 
393 396
 
394 397
 
395
-struct route_elem* route_match(struct sip_msg* msg, struct route_elem** rl)
398
+/* fixes all action tables */
399
+/* returns 0 if ok , <0 on error */
400
+int fix_rls()
396 401
 {
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;
402
+	int i,ret;
403
+	for(i=0;i<RT_NO;i++){
404
+		if(rlist[i]){
405
+			if ((ret=fix_actions(rlist[i]))!=0){
406
+				return ret;
407
+			}
408
+		}
404 409
 	}
405
-	/* no match :( */
406 410
 	return 0;
407 411
 }
408 412
 
409 413
 
410
-
411 414
 /* debug function, prints main routing table */
412 415
 void print_rl()
413 416
 {
414
-	struct route_elem* t;
417
+	struct action* t;
415 418
 	int i,j;
416 419
 
417 420
 	for(j=0; j<RT_NO; j++){
... ...
@@ -421,15 +412,10 @@ void print_rl()
421 421
 		}
422 422
 		DBG("routing table %d:\n",j);
423 423
 		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);
424
+			print_action(t);
430 425
 		}
426
+		DBG("\n");
431 427
 	}
432
-
433 428
 }
434 429
 
435 430
 
... ...
@@ -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 142
 			case DSTIP_O:
143 143
 				DBG("dstip");
144 144
 				break;
145
+			case NUMBER_O:
146
+				break;
147
+			case ACTION_O:
148
+				print_action((struct action*) exp->r.param);
149
+				break;
145 150
 			default:
146 151
 				DBG("UNKNOWN");
147 152
 		}
... ...
@@ -152,6 +172,8 @@ void print_expr(struct expr* exp)
152 152
 			case MATCH_OP:
153 153
 				DBG("=~");
154 154
 				break;
155
+			case NO_OP:
156
+				break;
155 157
 			default:
156 158
 				DBG("<UNKNOWN>");
157 159
 		}
... ...
@@ -168,6 +190,12 @@ void print_expr(struct expr* exp)
168 168
 			case IP_ST:
169 169
 					print_ip(exp->r.intval);
170 170
 					break;
171
+			case ACTIONS_ST:
172
+					print_action((struct action*)exp->r.param);
173
+					break;
174
+			case NUMBER_ST:
175
+					DBG("%d",exp->r.intval);
176
+					break;
171 177
 			default:
172 178
 					DBG("type<%d>", exp->subtype);
173 179
 		}
... ...
@@ -248,6 +276,9 @@ void print_action(struct action* a)
248 248
 			case SET_URI_T:
249 249
 					DBG("seturi(");
250 250
 					break;
251
+			case IF_T:
252
+					DBG("if (");
253
+					break;
251 254
 			default:
252 255
 					DBG("UNKNOWN(");
253 256
 		}
... ...
@@ -261,9 +292,16 @@ void print_action(struct action* a)
261 261
 			case IP_ST:
262 262
 					print_ip(t->p1.number);
263 263
 					break;
264
+			case EXPR_ST:
265
+					print_expr((struct expr*)t->p1.data);
266
+					break;
267
+			case ACTIONS_ST:
268
+					print_action((struct action*)t->p1.data);
269
+					break;
264 270
 			default:
265 271
 					DBG("type<%d>", t->p1_type);
266 272
 		}
273
+		if (t->type==IF_T) DBG(") {");
267 274
 		switch(t->p2_type){
268 275
 			case NOSUBTYPE:
269 276
 					break;
... ...
@@ -273,10 +311,36 @@ void print_action(struct action* a)
273 273
 			case NUMBER_ST:
274 274
 					DBG(", %d",t->p2.number);
275 275
 					break;
276
+			case EXPR_ST:
277
+					print_expr((struct expr*)t->p2.data);
278
+					break;
279
+			case ACTIONS_ST:
280
+					print_action((struct action*)t->p2.data);
281
+					break;
276 282
 			default:
277 283
 					DBG(", type<%d>", t->p2_type);
278 284
 		}
279
-		DBG("); ");
285
+		if (t->type==IF_T) DBG("} else {");
286
+		switch(t->p3_type){
287
+			case NOSUBTYPE:
288
+					break;
289
+			case STRING_ST:
290
+					DBG(", \"%s\"", t->p3.string);
291
+					break;
292
+			case NUMBER_ST:
293
+					DBG(", %d",t->p3.number);
294
+					break;
295
+			case EXPR_ST:
296
+					print_expr((struct expr*)t->p3.data);
297
+					break;
298
+			case ACTIONS_ST:
299
+					print_action((struct action*)t->p3.data);
300
+					break;
301
+			default:
302
+					DBG(", type<%d>", t->p3_type);
303
+		}
304
+		if (t->type==IF_T) DBG("}; ");
305
+		else	DBG("); ");
280 306
 	}
281 307
 }
282 308
 			
... ...
@@ -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 36
 	int type;  /* forward, drop, log, send ...*/
37 37
 	int p1_type;
38 38
 	int p2_type;
39
+	int p3_type;
39 40
 	union {
40 41
 		int number;
41 42
 		char* string;
42 43
 		void* data;
43
-	}p1, p2;
44
+	}p1, p2, p3;
44 45
 	struct action* next;
45 46
 };
46 47
 
... ...
@@ -52,7 +55,10 @@ struct net{
52 52
 
53 53
 struct expr* mk_exp(int op, struct expr* left, struct expr* right);
54 54
 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);
55
+struct action* mk_action(int type, int p1_type, int p2_type,
56
+							void* p1, void* p2);
57
+struct action* mk_action3(int type, int p1_type, int p2_type, int p3_type, 
58
+							void* p1, void* p2, void* p3);
56 59
 struct action* append_action(struct action* a, struct action* b);
57 60
 
58 61