瀏覽代碼

- if () {} do not have to be followed by ';' anymore
- added switch to check the config file (-c) and display aliases and listen
interface list if the config is ok.
- changes: removed len_gt() and replaced with if (msg:len op number|max_len)
- more operators supported: != for special operations (e.g. myself or ip
comparisons), != for strings (==, !=, ~=), !=, >, <, >=, <= for numbers
(e.g msg:len >= max_len).
- updated NEWS

Andrei Pelinescu-Onciul 22 年之前
父節點
當前提交
dda578bae9
共有 10 個文件被更改,包括 293 次插入166 次删除
  1. 1 1
      Makefile.defs
  2. 29 0
      NEWS
  3. 2 2
      TODO
  4. 13 2
      cfg.lex
  5. 74 84
      cfg.y
  6. 1 0
      globals.h
  7. 12 1
      main.c
  8. 156 73
      route.c
  9. 4 2
      route_struct.h
  10. 1 1
      ser.8

+ 1 - 1
Makefile.defs

@@ -43,7 +43,7 @@ export makefile_defs
 VERSION = 0
 VERSION = 0
 PATCHLEVEL = 8
 PATCHLEVEL = 8
 SUBLEVEL =   12
 SUBLEVEL =   12
-EXTRAVERSION = dev-18-fifo
+EXTRAVERSION = dev-19
 
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")

+ 29 - 0
NEWS

@@ -7,6 +7,35 @@ $Id$
 
 
 texops:
 texops:
  - subst('s/re/repl/flags') support
  - subst('s/re/repl/flags') support
+core:
+ - added switch to check the config file (-c)
+ - changes: removed len_gt() and replaced with if (msg:len op number|max_len)
+ - multiple operator support: ==, != for special operations (e.g myself, ip)
+                              ==, !=, ~= for strings
+                              ==, !=, >, <, >=, <= for integers
+ - new config variables:
+     advertised_address= ip | string
+       address advertised in via and in the DST_* lumps (e.g RR)
+       This is the default value, if empty (default) the socket
+       address will be used.
+       WARNING: - don't set it unless you know what you are doing
+                 (e.g. nat traversal)
+               - you can set anything here, no check is made
+                (e.g. foo.bar will be accepted even if 
+                 foo.bar doesn't exist)
+    advertised_port= no
+       port advertised in via and in the DST_*lumps (e.g. RR)
+       This is the default value, if empty (default) the socket
+       port will be used.
+       Same warnings as above.
+ - new script commands:
+    set_advertised_address(ip|string)
+       same as advertised_address but it affects only the current message:
+       Message host/lump address= the set_advertised one if
+       present, else advertised_address else socket address.
+    set_advertised_port(no)
+       same as advertised_port but it affects only the current
+       message; see set_advertised_address & s/address/port/g
 
 
 
 
 
 

+ 2 - 2
TODO

@@ -8,7 +8,7 @@ x update Makefile*  from stable
 x update all package specs from stable
 x update all package specs from stable
 - add BUG checks for  fd > 0 && fd <= maxfd to all selects?
 - add BUG checks for  fd > 0 && fd <= maxfd to all selects?
 x tcp_main_loop: BUG cases should "conitnue;"
 x tcp_main_loop: BUG cases should "conitnue;"
-- change len_gt into and expr (e.g msg:len).
+x change len_gt into and expr (e.g msg:len).
 - sipit: uri == myself doesn't match tls port = 5061
 - sipit: uri == myself doesn't match tls port = 5061
 - sipit: fix check_self & *_alias to work with tcp & tls
 - sipit: fix check_self & *_alias to work with tcp & tls
 x sipit: fix ipv6 references in check_self
 x sipit: fix ipv6 references in check_self
@@ -99,7 +99,7 @@ x forward to received= if present
 x add support for -u user and -g group (not only -u uid, -g uid)
 x add support for -u user and -g group (not only -u uid, -g uid)
 - change uid/gid after opening the sockets
 - change uid/gid after opening the sockets
 - exec improvments (add format strings to it)
 - exec improvments (add format strings to it)
-- command line switch for checking the config file syntax
+x command line switch for checking the config file syntax
 - config file version (a la sendmail)
 - config file version (a la sendmail)
 0 loop detection
 0 loop detection
 - cfg. file reload
 - cfg. file reload

+ 13 - 2
cfg.lex

@@ -40,6 +40,7 @@
  *  2003-07-06  more tls config. vars added: tls_method, tls_port_no (andrei)
  *  2003-07-06  more tls config. vars added: tls_method, tls_port_no (andrei)
  *  2003-10-02  added {,set_}advertised_{address,port} (andrei)
  *  2003-10-02  added {,set_}advertised_{address,port} (andrei)
  *  2003-10-07  added hex and octal numbers support (andrei)
  *  2003-10-07  added hex and octal numbers support (andrei)
+ *  2003-10-10  replaced len_gt w/ msg:len (andrei)
  */
  */
 
 
 
 
@@ -94,7 +95,6 @@ FORCE_RPORT		"force_rport"|"add_rport"
 SETFLAG		setflag
 SETFLAG		setflag
 RESETFLAG	resetflag
 RESETFLAG	resetflag
 ISFLAGSET	isflagset
 ISFLAGSET	isflagset
-LEN_GT		len_gt
 SET_HOST		"rewritehost"|"sethost"|"seth"
 SET_HOST		"rewritehost"|"sethost"|"seth"
 SET_HOSTPORT	"rewritehostport"|"sethostport"|"sethp"
 SET_HOSTPORT	"rewritehostport"|"sethostport"|"sethp"
 SET_USER		"rewriteuser"|"setuser"|"setu"
 SET_USER		"rewriteuser"|"setuser"|"setu"
@@ -132,9 +132,15 @@ DSTPORT	dst_port
 PROTO	proto
 PROTO	proto
 AF		af
 AF		af
 MYSELF	myself
 MYSELF	myself
+MSGLEN			"msg:len"
 /* operators */
 /* operators */
 EQUAL	=
 EQUAL	=
 EQUAL_T	==
 EQUAL_T	==
+GT	>
+LT	<
+GTE	>=
+LTE	<=
+DIFF	!=
 MATCH	=~
 MATCH	=~
 NOT		!|"not"
 NOT		!|"not"
 AND		"and"|"&&"|"&"
 AND		"and"|"&&"|"&"
@@ -244,7 +250,7 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{SETFLAG}	{ count(); yylval.strval=yytext; return SETFLAG; }
 <INITIAL>{SETFLAG}	{ count(); yylval.strval=yytext; return SETFLAG; }
 <INITIAL>{RESETFLAG}	{ count(); yylval.strval=yytext; return RESETFLAG; }
 <INITIAL>{RESETFLAG}	{ count(); yylval.strval=yytext; return RESETFLAG; }
 <INITIAL>{ISFLAGSET}	{ count(); yylval.strval=yytext; return ISFLAGSET; }
 <INITIAL>{ISFLAGSET}	{ count(); yylval.strval=yytext; return ISFLAGSET; }
-<INITIAL>{LEN_GT}	{ count(); yylval.strval=yytext; return LEN_GT; }
+<INITIAL>{MSGLEN}	{ count(); yylval.strval=yytext; return MSGLEN; }
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
 <INITIAL>{ROUTE_ONREPLY}	{ count(); yylval.strval=yytext;
 <INITIAL>{ROUTE_ONREPLY}	{ count(); yylval.strval=yytext;
 								return ROUTE_ONREPLY; }
 								return ROUTE_ONREPLY; }
@@ -336,6 +342,11 @@ EAT_ABLE	[\ \t\b\r]
 
 
 <INITIAL>{EQUAL}	{ count(); return EQUAL; }
 <INITIAL>{EQUAL}	{ count(); return EQUAL; }
 <INITIAL>{EQUAL_T}	{ count(); return EQUAL_T; }
 <INITIAL>{EQUAL_T}	{ count(); return EQUAL_T; }
+<INITIAL>{GT}	{ count(); return GT; }
+<INITIAL>{LT}	{ count(); return LT; }
+<INITIAL>{GTE}	{ count(); return GTE; }
+<INITIAL>{LTE}	{ count(); return LTE; }
+<INITIAL>{DIFF}	{ count(); return DIFF; }
 <INITIAL>{MATCH}	{ count(); return MATCH; }
 <INITIAL>{MATCH}	{ count(); return MATCH; }
 <INITIAL>{NOT}		{ count(); return NOT; }
 <INITIAL>{NOT}		{ count(); return NOT; }
 <INITIAL>{AND}		{ count(); return AND; }
 <INITIAL>{AND}		{ count(); return AND; }

+ 74 - 84
cfg.y

@@ -43,6 +43,9 @@
  *              require_certificate added (andrei)
  *              require_certificate added (andrei)
  * 2003-07-06  more tls config. vars added: tls_method, tls_port_no (andrei)
  * 2003-07-06  more tls config. vars added: tls_method, tls_port_no (andrei)
  * 2003-10-02  added {,set_}advertised_{address,port} (andrei)
  * 2003-10-02  added {,set_}advertised_{address,port} (andrei)
+ * 2003-10-10  added <,>,<=,>=, != operators support
+ *             added msg:len (andrei)
+ * 2003-10-11  if(){} doesn't require a ';' after it anymore (andrei)
  */
  */
 
 
 
 
@@ -148,7 +151,6 @@ void warn(char* s);
 %token SETFLAG
 %token SETFLAG
 %token RESETFLAG
 %token RESETFLAG
 %token ISFLAGSET
 %token ISFLAGSET
-%token LEN_GT
 %token METHOD
 %token METHOD
 %token URI
 %token URI
 %token SRCIP
 %token SRCIP
@@ -158,6 +160,7 @@ void warn(char* s);
 %token PROTO
 %token PROTO
 %token AF
 %token AF
 %token MYSELF
 %token MYSELF
+%token MSGLEN 
 
 
 /* config vars. */
 /* config vars. */
 %token DEBUG
 %token DEBUG
@@ -211,6 +214,11 @@ void warn(char* s);
 /* operators */
 /* operators */
 %nonassoc EQUAL
 %nonassoc EQUAL
 %nonassoc EQUAL_T
 %nonassoc EQUAL_T
+%nonassoc GT
+%nonassoc LT
+%nonassoc GTE
+%nonassoc LTE
+%nonassoc DIFF
 %nonassoc MATCH
 %nonassoc MATCH
 %left OR
 %left OR
 %left AND
 %left AND
@@ -244,6 +252,7 @@ void warn(char* s);
 %type <strval> host
 %type <strval> host
 %type <strval> listen_id
 %type <strval> listen_id
 %type <idlst>  id_lst
 %type <idlst>  id_lst
+%type <intval> equalop strop intop
 /*%type <route_el> rules;
 /*%type <route_el> rules;
   %type <route_el> rule;
   %type <route_el> rule;
 */
 */
@@ -285,14 +294,6 @@ listen_id:	ip			{	tmp=ip_addr2a($1);
 								}
 								}
 							}
 							}
 						}
 						}
-		 |	ID			{	$$=pkg_malloc(strlen($1)+1);
-		 					if ($$==0){
-									LOG(L_CRIT, "ERROR: cfg. parser: out of "
-											"memory.\n");
-							}else{
-									strncpy($$, $1, strlen($1)+1);
-							}
-						}
 		 |	STRING			{	$$=pkg_malloc(strlen($1)+1);
 		 |	STRING			{	$$=pkg_malloc(strlen($1)+1);
 		 					if ($$==0){
 		 					if ($$==0){
 									LOG(L_CRIT, "ERROR: cfg. parser: out of "
 									LOG(L_CRIT, "ERROR: cfg. parser: out of "
@@ -335,7 +336,7 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 		| DEBUG EQUAL error  { yyerror("number  expected"); }
 		| DEBUG EQUAL error  { yyerror("number  expected"); }
 		| FORK  EQUAL NUMBER { dont_fork= ! $3; }
 		| FORK  EQUAL NUMBER { dont_fork= ! $3; }
 		| FORK  EQUAL error  { yyerror("boolean value expected"); }
 		| FORK  EQUAL error  { yyerror("boolean value expected"); }
-		| LOGSTDERROR EQUAL NUMBER { log_stderr=$3; }
+		| LOGSTDERROR EQUAL NUMBER { if (!config_check) log_stderr=$3; }
 		| LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
 		| LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
 		| DNS EQUAL NUMBER   { received_dns|= ($3)?DO_DNS:0; }
 		| DNS EQUAL NUMBER   { received_dns|= ($3)?DO_DNS:0; }
 		| DNS EQUAL error { yyerror("boolean value expected"); }
 		| DNS EQUAL error { yyerror("boolean value expected"); }
@@ -700,117 +701,112 @@ exp:	exp AND exp 	{ $$=mk_exp(AND_OP, $1, $3); }
 	| exp_elem			{ $$=$1; }
 	| exp_elem			{ $$=$1; }
 	;
 	;
 
 
-exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST, 
+equalop:	  EQUAL_T {$$=EQUAL_OP; }
+			| DIFF	{$$=DIFF_OP; }
+		;
+		
+intop:	equalop	{$$=$1; }
+		|  GT	{$$=GT_OP; }
+		| LT	{$$=LT_OP; }
+		| GTE	{$$=GTE_OP; }
+		| LTE	{$$=LTE_OP; }
+		;
+		
+strop:	equalop	{$$=$1; }
+		| MATCH	{$$=MATCH_OP; }
+		;
+
+exp_elem:	METHOD strop STRING	{$$= mk_elem(	$2, STRING_ST, 
 													METHOD_O, $3);
 													METHOD_O, $3);
 									}
 									}
-		| METHOD EQUAL_T ID	{$$ = mk_elem(	EQUAL_OP, STRING_ST,
+		| METHOD strop  ID	{$$ = mk_elem(	$2, STRING_ST,
 											METHOD_O, $3); 
 											METHOD_O, $3); 
 				 			}
 				 			}
-		| METHOD EQUAL_T error { $$=0; yyerror("string expected"); }
-		| METHOD MATCH STRING	{$$ = mk_elem(	MATCH_OP, STRING_ST,
-												METHOD_O, $3); 
-				 				}
-		| METHOD MATCH ID	{$$ = mk_elem(	MATCH_OP, STRING_ST,
-											METHOD_O, $3); 
-				 			}
-		| METHOD MATCH error { $$=0; yyerror("string expected"); }
+		| METHOD strop error { $$=0; yyerror("string expected"); }
 		| METHOD error	{ $$=0; yyerror("invalid operator,"
 		| METHOD error	{ $$=0; yyerror("invalid operator,"
-										"== or =~ expected");
+										"== , !=, or =~ expected");
 						}
 						}
-		| URI EQUAL_T STRING 	{$$ = mk_elem(	EQUAL_OP, STRING_ST,
+		| URI strop STRING 	{$$ = mk_elem(	$2, STRING_ST,
 												URI_O, $3); 
 												URI_O, $3); 
 				 				}
 				 				}
-		| URI EQUAL_T ID 	{$$ = mk_elem(	EQUAL_OP, STRING_ST,
+		| URI strop host 	{$$ = mk_elem(	$2, STRING_ST,
 											URI_O, $3); 
 											URI_O, $3); 
 				 			}
 				 			}
-		| URI EQUAL_T MYSELF    { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
+		| URI equalop MYSELF    { $$=mk_elem(	$2, MYSELF_ST,
 												URI_O, 0);
 												URI_O, 0);
 								}
 								}
-		| URI EQUAL_T error { $$=0; yyerror("string expected"); }
-		| URI MATCH STRING	{ $$=mk_elem(	MATCH_OP, STRING_ST,
-											URI_O, $3);
-							}
-		| URI MATCH ID		{ $$=mk_elem(	MATCH_OP, STRING_ST,
-											URI_O, $3);
-							}
-		| URI MATCH error {  $$=0; yyerror("string expected"); }
+		| URI strop error { $$=0; yyerror("string or MYSELF expected"); }
 		| URI error	{ $$=0; yyerror("invalid operator,"
 		| URI error	{ $$=0; yyerror("invalid operator,"
-				  					" == or =~ expected");
+									" == , != or =~ expected");
 					}
 					}
-		| SRCPORT EQUAL_T NUMBER	{ $$=mk_elem(	EQUAL_OP, NUMBER_ST,
+		| SRCPORT intop NUMBER	{ $$=mk_elem(	$2, NUMBER_ST,
 												SRCPORT_O, (void *) $3 ); }
 												SRCPORT_O, (void *) $3 ); }
-		| SRCPORT EQUAL_T error { $$=0; yyerror("number expected"); }
-		| SRCPORT error { $$=0; yyerror("equal operator expected"); }
-		| DSTPORT EQUAL_T NUMBER	{ $$=mk_elem(	EQUAL_OP, NUMBER_ST,
+		| SRCPORT intop error { $$=0; yyerror("number expected"); }
+		| SRCPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
+		| DSTPORT intop NUMBER	{ $$=mk_elem(	$2, NUMBER_ST,
 												DSTPORT_O, (void *) $3 ); }
 												DSTPORT_O, (void *) $3 ); }
-		| DSTPORT EQUAL_T error { $$=0; yyerror("number expected"); }
-		| DSTPORT error { $$=0; yyerror("equal operator expected"); }
-		| PROTO EQUAL_T NUMBER	{ $$=mk_elem(	EQUAL_OP, NUMBER_ST,
+		| DSTPORT intop error { $$=0; yyerror("number expected"); }
+		| DSTPORT error { $$=0; yyerror("==, !=, <,>, >= or <=  expected"); }
+		| PROTO intop NUMBER	{ $$=mk_elem(	$2, NUMBER_ST,
 												PROTO_O, (void *) $3 ); }
 												PROTO_O, (void *) $3 ); }
-		| PROTO EQUAL_T error { $$=0; yyerror("number expected"); }
-		| PROTO error { $$=0; yyerror("equal operator expected"); }
-		| AF EQUAL_T NUMBER	{ $$=mk_elem(	EQUAL_OP, NUMBER_ST,
+		| PROTO intop error { $$=0; yyerror("number expected"); }
+		| PROTO error { $$=0; yyerror("equal/!= operator expected"); }
+		| AF intop NUMBER	{ $$=mk_elem(	$2, NUMBER_ST,
 												AF_O, (void *) $3 ); }
 												AF_O, (void *) $3 ); }
-		| AF EQUAL_T error { $$=0; yyerror("number expected"); }
-		| AF error { $$=0; yyerror("equal operator expected"); }
-		| SRCIP EQUAL_T ipnet	{ $$=mk_elem(	EQUAL_OP, NET_ST,
+		| AF intop error { $$=0; yyerror("number expected"); }
+		| AF error { $$=0; yyerror("equal/!= operator expected"); }
+		| MSGLEN intop NUMBER	{ $$=mk_elem(	$2, NUMBER_ST,
+												MSGLEN_O, (void *) $3 ); }
+		| MSGLEN intop MAX_LEN	{ $$=mk_elem(	$2, NUMBER_ST,
+												MSGLEN_O, (void *) BUF_SIZE); }
+		| MSGLEN intop error { $$=0; yyerror("number expected"); }
+		| MSGLEN error { $$=0; yyerror("equal/!= operator expected"); }
+		| SRCIP equalop ipnet	{ $$=mk_elem(	$2, NET_ST,
 												SRCIP_O, $3);
 												SRCIP_O, $3);
 								}
 								}
-		| SRCIP EQUAL_T STRING	{ $$=mk_elem(	EQUAL_OP, STRING_ST,
+		| SRCIP strop STRING	{ $$=mk_elem(	$2, STRING_ST,
 												SRCIP_O, $3);
 												SRCIP_O, $3);
 								}
 								}
-		| SRCIP EQUAL_T host	{ $$=mk_elem(	EQUAL_OP, STRING_ST,
+		| SRCIP strop host	{ $$=mk_elem(	$2, STRING_ST,
 												SRCIP_O, $3);
 												SRCIP_O, $3);
 								}
 								}
-		| SRCIP EQUAL_T MYSELF  { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
+		| SRCIP equalop MYSELF  { $$=mk_elem(	$2, MYSELF_ST,
 												SRCIP_O, 0);
 												SRCIP_O, 0);
 								}
 								}
-		| SRCIP EQUAL_T error { $$=0; yyerror( "ip address or hostname"
+		| SRCIP strop error { $$=0; yyerror( "ip address or hostname"
 						 "expected" ); }
 						 "expected" ); }
-		| SRCIP MATCH STRING	{ $$=mk_elem(	MATCH_OP, STRING_ST,
-												SRCIP_O, $3);
-								}
-		| SRCIP MATCH ID		{ $$=mk_elem(	MATCH_OP, STRING_ST,
-												SRCIP_O, $3);
-								}
-		| SRCIP MATCH error  { $$=0; yyerror( "hostname expected"); }
 		| SRCIP error  { $$=0; 
 		| SRCIP error  { $$=0; 
-						 yyerror("invalid operator, == or =~ expected");}
-		| DSTIP EQUAL_T ipnet	{ $$=mk_elem(	EQUAL_OP, NET_ST,
+						 yyerror("invalid operator, ==, != or =~ expected");}
+		| DSTIP equalop ipnet	{ $$=mk_elem(	$2, NET_ST,
 												DSTIP_O, $3);
 												DSTIP_O, $3);
 								}
 								}
-		| DSTIP EQUAL_T STRING	{ $$=mk_elem(	EQUAL_OP, STRING_ST,
+		| DSTIP strop STRING	{ $$=mk_elem(	$2, STRING_ST,
 												DSTIP_O, $3);
 												DSTIP_O, $3);
 								}
 								}
-		| DSTIP EQUAL_T host	{ $$=mk_elem(	EQUAL_OP, STRING_ST,
+		| DSTIP strop host	{ $$=mk_elem(	$2, STRING_ST,
 												DSTIP_O, $3);
 												DSTIP_O, $3);
 								}
 								}
-		| DSTIP EQUAL_T MYSELF  { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
+		| DSTIP equalop MYSELF  { $$=mk_elem(	$2, MYSELF_ST,
 												DSTIP_O, 0);
 												DSTIP_O, 0);
 								}
 								}
-		| DSTIP EQUAL_T error { $$=0; yyerror( "ip address or hostname"
+		| DSTIP strop error { $$=0; yyerror( "ip address or hostname"
 						 			"expected" ); }
 						 			"expected" ); }
-		| DSTIP MATCH STRING	{ $$=mk_elem(	MATCH_OP, STRING_ST,
-												DSTIP_O, $3);
-								}
-		| DSTIP MATCH ID	{ $$=mk_elem(	MATCH_OP, STRING_ST,
-											DSTIP_O, $3);
-							}
-		| DSTIP MATCH error  { $$=0; yyerror ( "hostname  expected" ); }
 		| DSTIP error { $$=0; 
 		| DSTIP error { $$=0; 
-						yyerror("invalid operator, == or =~ expected");}
-		| MYSELF EQUAL_T URI    { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
+						yyerror("invalid operator, ==, != or =~ expected");}
+		| MYSELF equalop URI    { $$=mk_elem(	$2, MYSELF_ST,
 												URI_O, 0);
 												URI_O, 0);
 								}
 								}
-		| MYSELF EQUAL_T SRCIP  { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
+		| MYSELF equalop SRCIP  { $$=mk_elem(	$2, MYSELF_ST,
 												SRCIP_O, 0);
 												SRCIP_O, 0);
 								}
 								}
-		| MYSELF EQUAL_T DSTIP  { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
+		| MYSELF equalop DSTIP  { $$=mk_elem(	$2, MYSELF_ST,
 												DSTIP_O, 0);
 												DSTIP_O, 0);
 								}
 								}
-		| MYSELF EQUAL_T error {	$$=0; 
+		| MYSELF equalop error {	$$=0; 
 									yyerror(" URI, SRCIP or DSTIP expected"); }
 									yyerror(" URI, SRCIP or DSTIP expected"); }
-		| MYSELF error	{ $$=0; yyerror ("invalid operator, == expected"); }
+		| MYSELF error	{ $$=0; 
+							yyerror ("invalid operator, == or != expected");
+						}
 		| stm				{ $$=mk_elem( NO_OP, ACTIONS_ST, ACTION_O, $1 ); }
 		| stm				{ $$=mk_elem( NO_OP, ACTIONS_ST, ACTION_O, $1 ); }
 		| NUMBER		{$$=mk_elem( NO_OP, NUMBER_ST, NUMBER_O, (void*)$1 ); }
 		| NUMBER		{$$=mk_elem( NO_OP, NUMBER_ST, NUMBER_O, (void*)$1 ); }
 	;
 	;
@@ -851,6 +847,7 @@ host:	ID				{ $$=$1; }
 
 
 
 
 stm:		cmd						{ $$=$1; }
 stm:		cmd						{ $$=$1; }
+		|	if_cmd					{ $$=$1; }
 		|	LBRACE actions RBRACE	{ $$=$2; }
 		|	LBRACE actions RBRACE	{ $$=$2; }
 	;
 	;
 
 
@@ -860,6 +857,7 @@ actions:	actions action	{$$=append_action($1, $2); }
 	;
 	;
 
 
 action:		cmd SEMICOLON {$$=$1;}
 action:		cmd SEMICOLON {$$=$1;}
+		| if_cmd {$$=$1;}
 		| SEMICOLON /* null action */ {$$=0;}
 		| SEMICOLON /* null action */ {$$=0;}
 		| cmd error { $$=0; yyerror("bad command: missing ';'?"); }
 		| cmd error { $$=0; yyerror("bad command: missing ';'?"); }
 	;
 	;
@@ -1282,13 +1280,6 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 		| SETFLAG LPAREN NUMBER RPAREN {$$=mk_action( SETFLAG_T, NUMBER_ST, 0,
 		| SETFLAG LPAREN NUMBER RPAREN {$$=mk_action( SETFLAG_T, NUMBER_ST, 0,
 													(void *)$3, 0 ); }
 													(void *)$3, 0 ); }
 		| SETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
 		| SETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
-
-		| LEN_GT LPAREN NUMBER RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
-													(void *)$3, 0 ); }
-		| LEN_GT LPAREN MAX_LEN RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
-													(void *) BUF_SIZE, 0 ); }
-		| LEN_GT error { $$=0; yyerror("missing '(' or ')'?"); }
-
 		| RESETFLAG LPAREN NUMBER RPAREN {$$=mk_action(	RESETFLAG_T, NUMBER_ST, 0,
 		| RESETFLAG LPAREN NUMBER RPAREN {$$=mk_action(	RESETFLAG_T, NUMBER_ST, 0,
 													(void *)$3, 0 ); }
 													(void *)$3, 0 ); }
 		| RESETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
 		| RESETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
@@ -1465,7 +1456,6 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 									}
 									}
 								  }
 								  }
 		| ID LPAREN error RPAREN { $$=0; yyerror("bad arguments"); }
 		| ID LPAREN error RPAREN { $$=0; yyerror("bad arguments"); }
-		| if_cmd		{ $$=$1; }
 	;
 	;
 
 
 
 

+ 1 - 0
globals.h

@@ -44,6 +44,7 @@
 
 
 
 
 extern char * cfg_file;
 extern char * cfg_file;
+extern int config_check;
 extern char *stat_file;
 extern char *stat_file;
 extern struct socket_info sock_info[]; /* all addresses we listen/send from*/
 extern struct socket_info sock_info[]; /* all addresses we listen/send from*/
 #ifdef USE_TCP
 #ifdef USE_TCP

+ 12 - 1
main.c

@@ -43,6 +43,7 @@
  *  2003-06-28  kill_all_children is now used instead of kill(0, sig)
  *  2003-06-28  kill_all_children is now used instead of kill(0, sig)
  *                see comment above it for explanations. (andrei)
  *                see comment above it for explanations. (andrei)
  *  2003-06-29  replaced port_no_str snprintf w/ int2str (andrei)
  *  2003-06-29  replaced port_no_str snprintf w/ int2str (andrei)
+ *  2003-10-10  added switch for config check (-c) (andrei)
  *
  *
  */
  */
 
 
@@ -196,6 +197,7 @@ static char help_msg[]= "\
 Usage: " NAME " -l address [-p port] [-l address [-p port]...] [options]\n\
 Usage: " NAME " -l address [-p port] [-l address [-p port]...] [options]\n\
 Options:\n\
 Options:\n\
     -f file      Configuration file (default " CFG_FILE ")\n\
     -f file      Configuration file (default " CFG_FILE ")\n\
+    -c           Check configuration file for errors\n\
     -p port      Listen on the specified port (default: 5060)\n\
     -p port      Listen on the specified port (default: 5060)\n\
                   applies to the last address in -l and to all \n\
                   applies to the last address in -l and to all \n\
                   following that do not have a corespponding -p\n\
                   following that do not have a corespponding -p\n\
@@ -289,6 +291,7 @@ int sig_flag = 0;              /* last signal received */
 int debug = L_NOTICE;
 int debug = L_NOTICE;
 int dont_fork = 0;
 int dont_fork = 0;
 int log_stderr = 0;
 int log_stderr = 0;
+int config_check = 0;
 /* check if reply first via host==us */
 /* check if reply first via host==us */
 int check_via =  0;        
 int check_via =  0;        
 /* shall use stateful synonym branches? faster but not reboot-safe */
 /* shall use stateful synonym branches? faster but not reboot-safe */
@@ -1262,13 +1265,17 @@ int main(int argc, char** argv)
 #ifdef STATS
 #ifdef STATS
 	"s:"
 	"s:"
 #endif
 #endif
-	"f:p:m:b:l:n:N:rRvdDETVhw:t:u:g:P:i:";
+	"f:cp:m:b:l:n:N:rRvdDETVhw:t:u:g:P:i:";
 	
 	
 	while((c=getopt(argc,argv,options))!=-1){
 	while((c=getopt(argc,argv,options))!=-1){
 		switch(c){
 		switch(c){
 			case 'f':
 			case 'f':
 					cfg_file=optarg;
 					cfg_file=optarg;
 					break;
 					break;
+			case 'c':
+					config_check=1;
+					log_stderr=1; /* force stderr logging */
+					break;
 			case 's':
 			case 's':
 				#ifdef STATS
 				#ifdef STATS
 					stat_file=optarg;
 					stat_file=optarg;
@@ -1710,6 +1717,10 @@ try_again:
 				(sock_no>1)?" and more than one listen address found (will"
 				(sock_no>1)?" and more than one listen address found (will"
 							" use only the the first one)":"");
 							" use only the the first one)":"");
 	}
 	}
+	if (config_check){
+		fprintf(stderr, "config file ok, exiting...\n");
+		goto error;
+	}
 	
 	
 #ifdef USE_TCP
 #ifdef USE_TCP
 	if (!tcp_disable){
 	if (!tcp_disable){

+ 156 - 73
route.c

@@ -38,6 +38,7 @@
  *  2003-04-05  s/reply_route/failure_route, onreply_route introduced (jiri)
  *  2003-04-05  s/reply_route/failure_route, onreply_route introduced (jiri)
  *  2003-05-23  comp_ip fixed, now it will resolve its operand and compare
  *  2003-05-23  comp_ip fixed, now it will resolve its operand and compare
  *              the ip with all the addresses (andrei)
  *              the ip with all the addresses (andrei)
+ *  2003-10-10  added more operators support to comp_* (<,>,<=,>=,!=) (andrei)
  */
  */
 
 
  
  
@@ -247,15 +248,28 @@ static int fix_actions(struct action* a)
 
 
 inline static int comp_no( int port, void *param, int op, int subtype )
 inline static int comp_no( int port, void *param, int op, int subtype )
 {
 {
-	if (op!=EQUAL_OP) {
-		LOG(L_CRIT, "BUG: comp_no: '=' expected: %d\n", op );
-		return E_BUG;
-	}
+	
 	if (subtype!=NUMBER_ST) {
 	if (subtype!=NUMBER_ST) {
 		LOG(L_CRIT, "BUG: comp_no: number expected: %d\n", subtype );
 		LOG(L_CRIT, "BUG: comp_no: number expected: %d\n", subtype );
 		return E_BUG;
 		return E_BUG;
 	}
 	}
-	return port==(long)param;
+	switch (op){
+		case EQUAL_OP:
+			return port==(long)param;
+		case DIFF_OP:
+			return port!=(long)param;
+		case GT_OP:
+			return port>(long)param;
+		case LT_OP:
+			return port<(long)param;
+		case GTE_OP:
+			return port>=(long)param;
+		case LTE_OP:
+			return port<=(long)param;
+		default:
+		LOG(L_CRIT, "BUG: comp_no: unknown operator: %d\n", op );
+		return E_BUG;
+	}
 }
 }
 
 
 /* eval_elem helping function, returns str op param */
 /* eval_elem helping function, returns str op param */
@@ -265,19 +279,29 @@ inline static int comp_strstr(str* str, void* param, int op, int subtype)
 	char backup;
 	char backup;
 	
 	
 	ret=-1;
 	ret=-1;
-	if (op==EQUAL_OP){
-		if (subtype!=STRING_ST){
-			LOG(L_CRIT, "BUG: comp_str: bad type %d, "
-					"string expected\n", subtype);
-			goto error;
-		}
-		ret=(strncasecmp(str->s, (char*)param, str->len)==0);
-	}else if (op==MATCH_OP){
-		if (subtype!=RE_ST){
-			LOG(L_CRIT, "BUG: comp_str: bad type %d, "
-					" RE expected\n", subtype);
-			goto error;
-		}
+	switch(op){
+		case EQUAL_OP:
+			if (subtype!=STRING_ST){
+				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
+						"string expected\n", subtype);
+				goto error;
+			}
+			ret=(strncasecmp(str->s, (char*)param, str->len)==0);
+			break;
+		case DIFF_OP:
+			if (subtype!=STRING_ST){
+				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
+						"string expected\n", subtype);
+				goto error;
+			}
+			ret=(strncasecmp(str->s, (char*)param, str->len)!=0);
+			break;
+		case MATCH_OP:
+			if (subtype!=RE_ST){
+				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
+						" RE expected\n", subtype);
+				goto error;
+			}
 		/* this is really ugly -- we put a temporary zero-terminating
 		/* this is really ugly -- we put a temporary zero-terminating
 		 * character in the original string; that's because regexps
 		 * character in the original string; that's because regexps
          * take 0-terminated strings and our messages are not
          * take 0-terminated strings and our messages are not
@@ -291,12 +315,13 @@ inline static int comp_strstr(str* str, void* param, int op, int subtype)
          * which might be too slow
          * which might be too slow
          * -jiri
          * -jiri
          */
          */
-		backup=str->s[str->len];str->s[str->len]=0;
-		ret=(regexec((regex_t*)param, str->s, 0, 0, 0)==0);
-		str->s[str->len]=backup;
-	}else{
-		LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
-		goto error;
+			backup=str->s[str->len];str->s[str->len]=0;
+			ret=(regexec((regex_t*)param, str->s, 0, 0, 0)==0);
+			str->s[str->len]=backup;
+			break;
+		default:
+			LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
+			goto error;
 	}
 	}
 	return ret;
 	return ret;
 	
 	
@@ -310,23 +335,34 @@ inline static int comp_str(char* str, void* param, int op, int subtype)
 	int ret;
 	int ret;
 	
 	
 	ret=-1;
 	ret=-1;
-	if (op==EQUAL_OP){
-		if (subtype!=STRING_ST){
-			LOG(L_CRIT, "BUG: comp_str: bad type %d, "
-					"string expected\n", subtype);
-			goto error;
-		}
-		ret=(strcasecmp(str, (char*)param)==0);
-	}else if (op==MATCH_OP){
-		if (subtype!=RE_ST){
-			LOG(L_CRIT, "BUG: comp_str: bad type %d, "
-					" RE expected\n", subtype);
+	switch(op){
+		case EQUAL_OP:
+			if (subtype!=STRING_ST){
+				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
+						"string expected\n", subtype);
+				goto error;
+			}
+			ret=(strcasecmp(str, (char*)param)==0);
+			break;
+		case DIFF_OP:
+			if (subtype!=STRING_ST){
+				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
+						"string expected\n", subtype);
+				goto error;
+			}
+			ret=(strcasecmp(str, (char*)param)!=0);
+			break;
+		case MATCH_OP:
+			if (subtype!=RE_ST){
+				LOG(L_CRIT, "BUG: comp_str: bad type %d, "
+						" RE expected\n", subtype);
+				goto error;
+			}
+			ret=(regexec((regex_t*)param, str, 0, 0, 0)==0);
+			break;
+		default:
+			LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
 			goto error;
 			goto error;
-		}
-		ret=(regexec((regex_t*)param, str, 0, 0, 0)==0);
-	}else{
-		LOG(L_CRIT, "BUG: comp_str: unknown op %d\n", op);
-		goto error;
 	}
 	}
 	return ret;
 	return ret;
 	
 	
@@ -335,6 +371,25 @@ error:
 }
 }
 
 
 
 
+/* check_self wrapper -- it checks also for the op */
+inline static int check_self_op(int op, str* s, unsigned short p)
+{
+	int ret;
+	
+	ret=check_self(s, p);
+	switch(op){
+		case EQUAL_OP:
+			break;
+		case DIFF_OP:
+			if (ret>=0) ret=!ret;
+			break;
+		default:
+			LOG(L_CRIT, "BUG: check_self_op: invalid operator %d\n", op);
+			ret=-1;
+	}
+	return ret;
+}
+
 
 
 /* eval_elem helping function, returns an op param */
 /* eval_elem helping function, returns an op param */
 inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
 inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
@@ -347,45 +402,67 @@ inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
 	ret=-1;
 	ret=-1;
 	switch(subtype){
 	switch(subtype){
 		case NET_ST:
 		case NET_ST:
-			ret=matchnet(ip, (struct net*) param);
-			/*ret=(a&((struct net*)param)->mask)==((struct net*)param)->ip;*/
+			switch(op){
+				case EQUAL_OP:
+					ret=(matchnet(ip, (struct net*) param)==1);
+					break;
+				case DIFF_OP:
+					ret=(matchnet(ip, (struct net*) param)!=1);
+					break;
+				default:
+					goto error_op;
+			}
 			break;
 			break;
 		case STRING_ST:
 		case STRING_ST:
 		case RE_ST:
 		case RE_ST:
-			/* 1: compare with ip2str*/
-			ret=comp_str(ip_addr2a(ip), param, op, subtype);
-			if (ret==1) break;
-			/* 2: resolve (name) & compare w/ all the ips */
-			he=resolvehost((char*)param);
-			if (he==0){
-				DBG("comp_ip: could not resolve %s\n", (char*)param);
-			}else if (he->h_addrtype==ip->af){
-				for(h=he->h_addr_list;(ret!=1)&& (*h); h++){
-					ret=(memcmp(ip->u.addr, *h, ip->len)==0);
-				}
-				if (ret==1) break;
-			}
-			/* 3: (slow) rev dns the address
-			 * and compare with all the aliases
-			 * !!??!! review: remove this? */
-			he=rev_resolvehost(ip);
-			if (he==0){
-				print_ip( "comp_ip: could not rev_resolve ip address: ",
-							ip, "\n");
-				ret=0;
-			}else{
-				/*  compare with primary host name */
-				ret=comp_str(he->h_name, param, op, subtype);
-				/* compare with all the aliases */
-				for(h=he->h_aliases; (ret!=1) && (*h); h++){
-					ret=comp_str(*h, param, op, subtype);
-				}
+			switch(op){
+				case EQUAL_OP:
+				case MATCH_OP:
+					/* 1: compare with ip2str*/
+					ret=comp_str(ip_addr2a(ip), param, op, subtype);
+					if (ret==1) break;
+					/* 2: resolve (name) & compare w/ all the ips */
+					if (subtype==STRING_ST){
+						he=resolvehost((char*)param);
+						if (he==0){
+							DBG("comp_ip: could not resolve %s\n",
+									(char*)param);
+						}else if (he->h_addrtype==ip->af){
+							for(h=he->h_addr_list;(ret!=1)&& (*h); h++){
+								ret=(memcmp(ip->u.addr, *h, ip->len)==0);
+							}
+							if (ret==1) break;
+						}
+					}
+					/* 3: (slow) rev dns the address
+					* and compare with all the aliases
+					* !!??!! review: remove this? */
+					he=rev_resolvehost(ip);
+					if (he==0){
+						print_ip( "comp_ip: could not rev_resolve ip address:"
+									" ", ip, "\n");
+					ret=0;
+					}else{
+						/*  compare with primary host name */
+						ret=comp_str(he->h_name, param, op, subtype);
+						/* compare with all the aliases */
+						for(h=he->h_aliases; (ret!=1) && (*h); h++){
+							ret=comp_str(*h, param, op, subtype);
+						}
+					}
+					break;
+				case DIFF_OP:
+					ret=comp_ip(ip, param, EQUAL_OP, subtype);
+					if (ret>=0) ret=!ret;
+					break;
+				default:
+					goto error_op;
 			}
 			}
 			break;
 			break;
 		case MYSELF_ST: /* check if it's one of our addresses*/
 		case MYSELF_ST: /* check if it's one of our addresses*/
 			tmp.s=ip_addr2a(ip);
 			tmp.s=ip_addr2a(ip);
 			tmp.len=strlen(tmp.s);
 			tmp.len=strlen(tmp.s);
-			ret=check_self(&tmp, 0);
+			ret=check_self_op(op, &tmp, 0);
 			break;
 			break;
 		default:
 		default:
 			LOG(L_CRIT, "BUG: comp_ip: invalid type for "
 			LOG(L_CRIT, "BUG: comp_ip: invalid type for "
@@ -393,6 +470,9 @@ inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
 			ret=-1;
 			ret=-1;
 	}
 	}
 	return ret;
 	return ret;
+error_op:
+	LOG(L_CRIT, "BUG: comp_ip: invalid operator %d\n", op);
+	return -1;
 	
 	
 }
 }
 
 
@@ -418,7 +498,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 				if(msg->new_uri.s){
 				if(msg->new_uri.s){
 					if (e->subtype==MYSELF_ST){
 					if (e->subtype==MYSELF_ST){
 						if (parse_sip_msg_uri(msg)<0) ret=-1;
 						if (parse_sip_msg_uri(msg)<0) ret=-1;
-						else	ret=check_self(&msg->parsed_uri.host,
+						else	ret=check_self_op(e->op, &msg->parsed_uri.host,
 									msg->parsed_uri.port_no?
 									msg->parsed_uri.port_no?
 									msg->parsed_uri.port_no:SIP_PORT);
 									msg->parsed_uri.port_no:SIP_PORT);
 					}else{
 					}else{
@@ -428,7 +508,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 				}else{
 				}else{
 					if (e->subtype==MYSELF_ST){
 					if (e->subtype==MYSELF_ST){
 						if (parse_sip_msg_uri(msg)<0) ret=-1;
 						if (parse_sip_msg_uri(msg)<0) ret=-1;
-						else	ret=check_self(&msg->parsed_uri.host,
+						else	ret=check_self_op(e->op, &msg->parsed_uri.host,
 									msg->parsed_uri.port_no?
 									msg->parsed_uri.port_no?
 									msg->parsed_uri.port_no:SIP_PORT);
 									msg->parsed_uri.port_no:SIP_PORT);
 					}else{
 					}else{
@@ -467,6 +547,9 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 		case AF_O:
 		case AF_O:
 				ret=comp_no(msg->rcv.src_ip.af, e->r.param, e->op, e->subtype);
 				ret=comp_no(msg->rcv.src_ip.af, e->r.param, e->op, e->subtype);
 				break;
 				break;
+		case MSGLEN_O:
+				ret=comp_no(msg->len, e->r.param, e->op, e->subtype);
+				break;
 		default:
 		default:
 				LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n",
 				LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n",
 							e->l.operand);
 							e->l.operand);

+ 4 - 2
route_struct.h

@@ -30,6 +30,7 @@
  *
  *
  *  2003-04-12  FORCE_RPORT_T added (andrei)
  *  2003-04-12  FORCE_RPORT_T added (andrei)
  *  2003-04-22  strip_tail added (jiri)
  *  2003-04-22  strip_tail added (jiri)
+ *  2003-10-10  >,<,>=,<=, != and MSGLEN_O added (andrei)
  */
  */
 
 
 
 
@@ -51,9 +52,10 @@
 
 
 enum { EXP_T=1, ELEM_T };
 enum { EXP_T=1, ELEM_T };
 enum { AND_OP=1, OR_OP, NOT_OP };
 enum { AND_OP=1, OR_OP, NOT_OP };
-enum { EQUAL_OP=10, MATCH_OP, NO_OP };
+enum { EQUAL_OP=10, MATCH_OP, GT_OP, LT_OP, GTE_OP, LTE_OP, DIFF_OP, NO_OP };
 enum { METHOD_O=1, URI_O, SRCIP_O, SRCPORT_O,
 enum { METHOD_O=1, URI_O, SRCIP_O, SRCPORT_O,
-	   DSTIP_O, DSTPORT_O, PROTO_O, AF_O, DEFAULT_O, ACTION_O, NUMBER_O};
+	   DSTIP_O, DSTPORT_O, PROTO_O, AF_O, MSGLEN_O, DEFAULT_O, ACTION_O,
+	   NUMBER_O};
 
 
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, 
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, 

+ 1 - 1
ser.8

@@ -52,7 +52,7 @@ is a very fast and configurable SIP proxy.
 Displays a short usage description, including all available options.
 Displays a short usage description, including all available options.
 .TP
 .TP
 .BI \-c
 .BI \-c
-Performs loop checks and computes branches.
+Checks the config file and displays the aliases and listen interface list.
 .TP
 .TP
 .BI \-r
 .BI \-r
 Uses dns to check if it is necessary to add a "received=" field to a via.
 Uses dns to check if it is necessary to add a "received=" field to a via.