Преглед изворни кода

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

Andrei Pelinescu-Onciul пре 24 година
родитељ
комит
7268726eee
15 измењених фајлова са 570 додато и 131 уклоњено
  1. 117 2
      action.c
  2. 30 12
      cfg.lex
  3. 103 31
      cfg.y
  4. 2 0
      config.h
  5. 20 4
      forward.c
  6. 1 1
      globals.h
  7. 20 21
      main.c
  8. 187 6
      msg_parser.c
  9. 14 0
      msg_parser.h
  10. 1 0
      receive.c
  11. 5 5
      route.c
  12. 64 44
      route_struct.c
  13. 3 2
      route_struct.h
  14. 2 2
      test/bad_via1.sip
  15. 1 1
      test/req1.sip

+ 117 - 2
action.c

@@ -12,6 +12,7 @@
 #include "forward.h"
 #include "forward.h"
 #include "udp_server.h"
 #include "udp_server.h"
 #include "route.h"
 #include "route.h"
+#include "msg_parser.h"
 
 
 #include <sys/types.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
@@ -21,14 +22,19 @@
 #include <arpa/inet.h>
 #include <arpa/inet.h>
 
 
 
 
-/* ret= 0 if action -> end of lis t(e.g DROP), >0
-   and >0 on error */
+/* ret= 0! if action -> end of list(e.g DROP), 
+      > 0 to continue processing next actions
+   and <0 on error */
 int do_action(struct action* a, struct sip_msg* msg)
 int do_action(struct action* a, struct sip_msg* msg)
 {
 {
 	int ret;
 	int ret;
 	struct sockaddr_in* to;
 	struct sockaddr_in* to;
 	struct proxy_l* p;
 	struct proxy_l* p;
 	struct route_elem* re;
 	struct route_elem* re;
+	char* tmp;
+	char *new_uri, *end, *crt;
+	int len;
+	struct sip_uri uri;
 
 
 	ret=E_BUG;
 	ret=E_BUG;
 	switch (a->type){
 	switch (a->type){
@@ -139,10 +145,119 @@ int do_action(struct action* a, struct sip_msg* msg)
 			}
 			}
 			ret=1;
 			ret=1;
 			break;
 			break;
+		case SET_HOST_T:
+		case SET_HOSTPORT_T:
+		case SET_USER_T:
+		case SET_USERPASS_T:
+		case SET_PORT_T:
+		case SET_URI_T:
+				if (a->p1_type!=STRING_ST){
+					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
+							a->p1_type);
+					ret=E_BUG;
+					break;
+				}
+				if (a->type==SET_URI_T){
+					if (msg->new_uri) free(msg->new_uri);
+					len=strlen(a->p1.string);
+					msg->new_uri=malloc(len+1);
+					if (msg->new_uri==0){
+						LOG(L_ERR, "ERROR: do_action: memory allocation failure\n");
+						ret=E_OUT_OF_MEM;
+						break;
+					}
+					memcpy(msg->new_uri, a->p1.string, len);
+					msg->new_uri[len]=0;
+					ret=1;
+					break;
+				}
+
+				if (msg->new_uri) tmp=msg->new_uri;
+				else tmp=msg->first_line.u.request.uri;
+				if (parse_uri(tmp, strlen(tmp), &uri)<0){
+					LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping packet\n", tmp);
+					ret=E_UNSPEC;
+					break;
+				}
+				
+				new_uri=malloc(MAX_URI_SIZE);
+				if (new_uri==0){
+					LOG(L_ERR, "ERROR: do_action: memory allocation failure\n");
+					ret=E_OUT_OF_MEM;
+					break;
+				}
+				end=new_uri+MAX_URI_SIZE;
+				crt=new_uri;
+				/* begin copying */
+				len=strlen("sip:"); if(crt+len>end) goto error_uri;
+				memcpy(crt,"sip:",len);crt+=len;
+				/* user */
+				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) tmp=a->p1.string;
+				else tmp=uri.user;
+				if (tmp){
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
+					memcpy(crt,tmp,len);crt+=len;
+				}
+				if (a->type==SET_USERPASS_T) tmp=0;
+				else tmp=uri.passwd;
+				/* passwd */
+				if (tmp){
+					len=strlen(":"); if(crt+len>end) goto error_uri;
+					memcpy(crt,":",len);crt+=len;
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
+					memcpy(crt,tmp,len);crt+=len;
+				}
+				/* host */
+				len=strlen("@"); if(crt+len>end) goto error_uri;
+				memcpy(crt,"@",len);crt+=len;
+				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) tmp=a->p1.string;
+				else tmp=uri.host;
+				if (tmp){
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
+					memcpy(crt,tmp,len);crt+=len;
+				}
+				/* port */
+				if (a->type==SET_HOSTPORT_T) tmp=0;
+				else if (a->type==SET_PORT_T) tmp=a->p1.string;
+				else tmp=uri.port;
+				if (tmp){
+					len=strlen(":"); if(crt+len>end) goto error_uri;
+					memcpy(crt,":",len);crt+=len;
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
+					memcpy(crt,tmp,len);crt+=len;
+				}
+				/* params */
+				tmp=uri.params;
+				if (tmp){
+					len=strlen(";"); if(crt+len>end) goto error_uri;
+					memcpy(crt,";",len);crt+=len;
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
+					memcpy(crt,tmp,len);crt+=len;
+				}
+				/* headers */
+				tmp=uri.headers;
+				if (tmp){
+					len=strlen("?"); if(crt+len>end) goto error_uri;
+					memcpy(crt,"?",len);crt+=len;
+					len=strlen(tmp); if(crt+len>end) goto error_uri;
+					memcpy(crt,tmp,len);crt+=len;
+				}
+				*crt=0; /* null terminate the thing */
+				/* copy it to the msg */
+				if (msg->new_uri) free(msg->new_uri);
+				msg->new_uri=new_uri;
+				ret=1;
+				break;
+
 		default:
 		default:
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
 	}
 	}
 	return ret;
 	return ret;
+	
+error_uri:
+	LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
+	if (new_uri) free(new_uri);
+	return E_UNSPEC;
 }
 }
 
 
 
 

+ 30 - 12
cfg.lex

@@ -7,6 +7,7 @@
 
 
 %{
 %{
 	#include "cfg.tab.h"
 	#include "cfg.tab.h"
+	#include "dprint.h"
 	#include <string.h>
 	#include <string.h>
 
 
 	/* states */
 	/* states */
@@ -40,6 +41,14 @@ LOG		log
 ERROR	error
 ERROR	error
 ROUTE	route
 ROUTE	route
 EXEC	exec
 EXEC	exec
+SET_HOST		"rewritehost"|"sethost"|"seth"
+SET_HOSTPORT	"rewritehostport"|"sethostport"|"sethp"
+SET_USER		"rewriteuser"|"setuser"|"setu"
+SET_USERPASS	"rewriteuserpass"|"setuserpass"|"setup"
+SET_PORT		"rewriteport"|"setport"|"setp"
+SET_URI			"rewriteuri"|"seturi"
+
+
 /* condition keywords */
 /* condition keywords */
 METHOD	method
 METHOD	method
 URI		uri
 URI		uri
@@ -48,7 +57,7 @@ DSTIP	dst_ip
 /* operators */
 /* operators */
 EQUAL	=
 EQUAL	=
 EQUAL_T	==
 EQUAL_T	==
-MATCH	~=
+MATCH	=~
 NOT		!|"not"
 NOT		!|"not"
 AND		"and"|"&&"|"&"
 AND		"and"|"&&"|"&"
 OR		"or"|"||"|"|"
 OR		"or"|"||"|"|"
@@ -60,6 +69,9 @@ LOGSTDERROR	log_stderror
 LISTEN		listen
 LISTEN		listen
 DNS		 dns
 DNS		 dns
 REV_DNS	 rev_dns
 REV_DNS	 rev_dns
+PORT	port
+CHILDREN children
+CHECK_VIA	check_via
 
 
 /* values */
 /* values */
 YES			"yes"|"true"|"on"|"enable"
 YES			"yes"|"true"|"on"|"enable"
@@ -100,10 +112,16 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{FORWARD}	{count(); yylval.strval=yytext; return FORWARD; }
 <INITIAL>{FORWARD}	{count(); yylval.strval=yytext; return FORWARD; }
 <INITIAL>{DROP}	{ count(); yylval.strval=yytext; return DROP; }
 <INITIAL>{DROP}	{ count(); yylval.strval=yytext; return DROP; }
 <INITIAL>{SEND}	{ count(); yylval.strval=yytext; return SEND; }
 <INITIAL>{SEND}	{ count(); yylval.strval=yytext; return SEND; }
-<INITIAL>{LOG}	{ count(); yylval.strval=yytext; return LOG; }
+<INITIAL>{LOG}	{ count(); yylval.strval=yytext; return LOG_TOK; }
 <INITIAL>{ERROR}	{ count(); yylval.strval=yytext; return ERROR; }
 <INITIAL>{ERROR}	{ count(); yylval.strval=yytext; return ERROR; }
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
 <INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
 <INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
+<INITIAL>{SET_HOST}	{ count(); yylval.strval=yytext; return SET_HOST; }
+<INITIAL>{SET_HOSTPORT}	{ count(); yylval.strval=yytext; return SET_HOSTPORT; }
+<INITIAL>{SET_USER}	{ count(); yylval.strval=yytext; return SET_USER; }
+<INITIAL>{SET_USERPASS}	{ count(); yylval.strval=yytext; return SET_USERPASS; }
+<INITIAL>{SET_PORT}	{ count(); yylval.strval=yytext; return SET_PORT; }
+<INITIAL>{SET_URI}	{ count(); yylval.strval=yytext; return SET_URI; }
 
 
 <INITIAL>{METHOD}	{ count(); yylval.strval=yytext; return METHOD; }
 <INITIAL>{METHOD}	{ count(); yylval.strval=yytext; return METHOD; }
 <INITIAL>{URI}	{ count(); yylval.strval=yytext; return URI; }
 <INITIAL>{URI}	{ count(); yylval.strval=yytext; return URI; }
@@ -116,6 +134,9 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{LISTEN}	{ count(); yylval.strval=yytext; return LISTEN; }
 <INITIAL>{LISTEN}	{ count(); yylval.strval=yytext; return LISTEN; }
 <INITIAL>{DNS}	{ count(); yylval.strval=yytext; return DNS; }
 <INITIAL>{DNS}	{ count(); yylval.strval=yytext; return DNS; }
 <INITIAL>{REV_DNS}	{ count(); yylval.strval=yytext; return REV_DNS; }
 <INITIAL>{REV_DNS}	{ count(); yylval.strval=yytext; return REV_DNS; }
+<INITIAL>{PORT}	{ count(); yylval.strval=yytext; return PORT; }
+<INITIAL>{CHILDREN}	{ count(); yylval.strval=yytext; return CHILDREN; }
+<INITIAL>{CHECK_VIA}	{ count(); yylval.strval=yytext; return CHECK_VIA; }
 
 
 <INITIAL>{EQUAL}	{ count(); return EQUAL; }
 <INITIAL>{EQUAL}	{ count(); return EQUAL; }
 <INITIAL>{EQUAL_T}	{ count(); return EQUAL_T; }
 <INITIAL>{EQUAL_T}	{ count(); return EQUAL_T; }
@@ -150,17 +171,11 @@ EAT_ABLE	[\ \t\b\r]
 <STRING1>{QUOTES} { count(); state=INITIAL_S; BEGIN(INITIAL); 
 <STRING1>{QUOTES} { count(); state=INITIAL_S; BEGIN(INITIAL); 
 						yytext[yyleng-1]=0; yyleng--;
 						yytext[yyleng-1]=0; yyleng--;
 						addstr(yytext, &str);
 						addstr(yytext, &str);
-						if (str){
-							printf("Found string1 <%s>\n", str);
-						}else{
-							printf("WARNING: empty string\n");
-						}
 						yylval.strval=str; str=0;
 						yylval.strval=str; str=0;
 						return STRING;
 						return STRING;
 					}
 					}
 <STRING2>{TICK}  { count(); state=INITIAL_S; BEGIN(INITIAL); 
 <STRING2>{TICK}  { count(); state=INITIAL_S; BEGIN(INITIAL); 
 						yytext[yyleng-1]=0; yyleng--;
 						yytext[yyleng-1]=0; yyleng--;
-						printf("Found string1 <%s>\n", yytext);
 						addstr(yytext, &str);
 						addstr(yytext, &str);
 						yylval.strval=str;
 						yylval.strval=str;
 						str=0;
 						str=0;
@@ -196,14 +211,17 @@ EAT_ABLE	[\ \t\b\r]
 <<EOF>>							{
 <<EOF>>							{
 									switch(state){
 									switch(state){
 										case STRING_S: 
 										case STRING_S: 
-											printf("Unexpected EOF: closed string\n");
+											LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF in"
+														" unclosed string\n");
 											if (str) {free(str); str=0;}
 											if (str) {free(str); str=0;}
 											break;
 											break;
 										case COMMENT_S:
 										case COMMENT_S:
-											printf("Unexpected EOF:%d comments open\n", comment_nest);
+											LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF:"
+														" %d comments open\n", comment_nest);
 											break;
 											break;
 										case COMMENT_LN_S:
 										case COMMENT_LN_S:
-											printf("Unexpected EOF: comment line open\n");
+											LOG(L_CRIT, "ERROR: unexpected EOF:"
+														"comment line open\n");
 											break;
 											break;
 									}
 									}
 									return 0;
 									return 0;
@@ -231,7 +249,7 @@ static char* addstr(char * src, char ** dest)
 	}
 	}
 	return *dest;
 	return *dest;
 error:
 error:
-	fprintf(stderr, "lex:addstr: memory allocation error\n");
+	LOG(L_CRIT, "ERROR:lex:addstr: memory allocation error\n");
 	return 0;
 	return 0;
 }
 }
 
 

+ 103 - 31
cfg.y

@@ -8,11 +8,16 @@
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #include "route_struct.h"
 #include "route_struct.h"
 #include "globals.h"
 #include "globals.h"
 #include "route.h"
 #include "route.h"
+#include "dprint.h"
 
 
 void yyerror(char* s);
 void yyerror(char* s);
+char* tmp;
 
 
 %}
 %}
 
 
@@ -33,10 +38,16 @@ void yyerror(char* s);
 %token FORWARD
 %token FORWARD
 %token SEND
 %token SEND
 %token DROP
 %token DROP
-%token LOG
+%token LOG_TOK
 %token ERROR
 %token ERROR
 %token ROUTE
 %token ROUTE
 %token EXEC
 %token EXEC
+%token SET_HOST
+%token SET_HOSTPORT
+%token SET_USER
+%token SET_USERPASS
+%token SET_PORT
+%token SET_URI
 
 
 %token METHOD
 %token METHOD
 %token URI
 %token URI
@@ -50,6 +61,10 @@ void yyerror(char* s);
 %token LISTEN
 %token LISTEN
 %token DNS
 %token DNS
 %token REV_DNS
 %token REV_DNS
+%token PORT
+%token CHILDREN
+%token CHECK_VIA
+
 
 
 
 
 /* operators */
 /* operators */
@@ -101,24 +116,70 @@ statements:	statements statement {}
 		| statements error { yyerror(""); YYABORT;}
 		| statements error { yyerror(""); YYABORT;}
 	;
 	;
 
 
-statement:	assign_stm CR
-		| route_stm CR
+statement:	assign_stm 
+		| route_stm 
 		| CR	/* null statement*/
 		| CR	/* null statement*/
 	;
 	;
 
 
-assign_stm:	DEBUG EQUAL NUMBER 
+assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 		| DEBUG EQUAL error  { yyerror("number  expected"); }
 		| DEBUG EQUAL error  { yyerror("number  expected"); }
-		| FORK  EQUAL NUMBER
+		| FORK  EQUAL NUMBER { dont_fork= ! $3; }
 		| FORK  EQUAL error  { yyerror("boolean value expected"); }
 		| FORK  EQUAL error  { yyerror("boolean value expected"); }
-		| LOGSTDERROR EQUAL NUMBER 
+		| LOGSTDERROR EQUAL NUMBER { log_stderr=$3; }
 		| LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
 		| LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
-		| DNS EQUAL NUMBER
+		| DNS EQUAL NUMBER   { received_dns|= ($3)?DO_DNS:0; }
 		| DNS EQUAL error { yyerror("boolean value expected"); }
 		| DNS EQUAL error { yyerror("boolean value expected"); }
-		| REV_DNS EQUAL NUMBER 
+		| REV_DNS EQUAL NUMBER { received_dns|= ($3)?DO_REV_DNS:0; }
 		| REV_DNS EQUAL error { yyerror("boolean value expected"); }
 		| REV_DNS EQUAL error { yyerror("boolean value expected"); }
-		| LISTEN EQUAL ipv4 
-		| LISTEN EQUAL ID 
-		| LISTEN EQUAL STRING
+		| PORT EQUAL NUMBER   { port_no=$3; }
+		| PORT EQUAL error    { yyerror("number expected"); } 
+		| CHILDREN EQUAL NUMBER { children_no=$3; }
+		| CHILDREN EQUAL error { yyerror("number expected"); } 
+		| CHECK_VIA EQUAL NUMBER { check_via=$3; }
+		| CHECK_VIA EQUAL error { yyerror("boolean value expected"); }
+		| LISTEN EQUAL ipv4  {
+								if (addresses_no < MAX_LISTEN){
+									tmp=inet_ntoa(*(struct in_addr*)&$3);
+									names[addresses_no]=(char*)malloc(strlen(tmp)+1);
+									if (names[addresses_no]==0){
+										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
+									}else{
+										strncpy(names[addresses_no], tmp, strlen(tmp)+1);
+										addresses_no++;
+									}
+								}else{
+									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
+												"(max. %d).\n", MAX_LISTEN);
+								}
+							  }
+		| LISTEN EQUAL ID	 {
+								if (addresses_no < MAX_LISTEN){
+									names[addresses_no]=(char*)malloc(strlen($3)+1);
+									if (names[addresses_no]==0){
+										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
+									}else{
+										strncpy(names[addresses_no], $3, strlen($3)+1);
+										addresses_no++;
+									}
+								}else{
+									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
+												"(max. %d).\n", MAX_LISTEN);
+								}
+							  }
+		| LISTEN EQUAL STRING {
+								if (addresses_no < MAX_LISTEN){
+									names[addresses_no]=(char*)malloc(strlen($3)+1);
+									if (names[addresses_no]==0){
+										LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
+									}else{
+										strncpy(names[addresses_no], $3, strlen($3)+1);
+										addresses_no++;
+									}
+								}else{
+									LOG(L_CRIT, "ERROR: cfg. parser: too many listen addresses"
+												"(max. %d).\n", MAX_LISTEN);
+								}
+							  }
 		| LISTEN EQUAL  error { yyerror("ip address or hostname"
 		| LISTEN EQUAL  error { yyerror("ip address or hostname"
 						"expected"); }
 						"expected"); }
 		| error EQUAL { yyerror("unknown config variable"); }
 		| error EQUAL { yyerror("unknown config variable"); }
@@ -153,26 +214,19 @@ route_stm:	ROUTE LBRACE rules RBRACE { push($3, &rlist[DEFAULT_RT]); }
 		| ROUTE error { yyerror("invalid  route  statement"); }
 		| ROUTE error { yyerror("invalid  route  statement"); }
 	;
 	;
 
 
-rules:	rules rule { push($2, &$1); $$=$1; 
-						printf(": rules->rules(%x) rule(%x)\n", $1,$2);}
-	| rule {$$=$1; printf(": rules->rule (%x)\n",$1); }
+rules:	rules rule { push($2, &$1); $$=$1; }
+	| rule {$$=$1; }
 	| rules error { $$=0; yyerror("invalid rule"); }
 	| rules error { $$=0; yyerror("invalid rule"); }
 	 ;
 	 ;
 
 
 rule:	condition	actions CR {
 rule:	condition	actions CR {
-								printf("Got a new rule!\n");
-								printf("expr: "); print_expr($1);
-								printf("\n  -> actions: ");
-								print_action($2); printf("\n");
-
 								$$=0;
 								$$=0;
 								if (add_rule($1, $2, &$$)<0) {
 								if (add_rule($1, $2, &$$)<0) {
 									yyerror("error calling add_rule");
 									yyerror("error calling add_rule");
 									YYABORT;
 									YYABORT;
 								}
 								}
-								printf(": rule -> condition actions CR\n");
 							  }
 							  }
-	| CR  /* null rule */		{ $$=0; printf(": rule-> CR!\n"); }
+	| CR  /* null rule */		{ $$=0;}
 	| condition error { $$=0; yyerror("bad actions in rule"); }
 	| condition error { $$=0; yyerror("bad actions in rule"); }
 	;
 	;
 
 
@@ -201,7 +255,7 @@ exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST,
 				 			}
 				 			}
 		| METHOD MATCH error { $$=0; yyerror("string expected"); }
 		| METHOD MATCH 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 EQUAL_T STRING 	{$$ = mk_elem(	EQUAL_OP, STRING_ST,
 												URI_O, $3); 
 												URI_O, $3); 
@@ -218,7 +272,7 @@ exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST,
 							}
 							}
 		| URI MATCH error {  $$=0; yyerror("string expected"); }
 		| URI MATCH error {  $$=0; yyerror("string expected"); }
 		| URI error	{ $$=0; yyerror("invalid operator,"
 		| URI error	{ $$=0; yyerror("invalid operator,"
-				  					" == or ~= expected");
+				  					" == or =~ expected");
 					}
 					}
 		| SRCIP EQUAL_T net4	{ $$=mk_elem(	EQUAL_OP, NET_ST,
 		| SRCIP EQUAL_T net4	{ $$=mk_elem(	EQUAL_OP, NET_ST,
 												SRCIP_O, $3);
 												SRCIP_O, $3);
@@ -239,7 +293,7 @@ exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST,
 								}
 								}
 		| SRCIP MATCH error  { $$=0; yyerror( "hostname expected"); }
 		| SRCIP MATCH error  { $$=0; yyerror( "hostname expected"); }
 		| SRCIP error  { $$=0; 
 		| SRCIP error  { $$=0; 
-						 yyerror("invalid operator, == or ~= expected");}
+						 yyerror("invalid operator, == or =~ expected");}
 		| DSTIP EQUAL_T net4	{ $$=mk_elem(	EQUAL_OP, NET_ST,
 		| DSTIP EQUAL_T net4	{ $$=mk_elem(	EQUAL_OP, NET_ST,
 												DSTIP_O, $3);
 												DSTIP_O, $3);
 								}
 								}
@@ -259,7 +313,7 @@ exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST,
 							}
 							}
 		| DSTIP MATCH error  { $$=0; yyerror ( "hostname  expected" ); }
 		| DSTIP MATCH error  { $$=0; yyerror ( "hostname  expected" ); }
 		| DSTIP error { $$=0; 
 		| DSTIP error { $$=0; 
-						yyerror("invalid operator, == or ~= expected");}
+						yyerror("invalid operator, == or =~ expected");}
 	;
 	;
 
 
 net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); } 
 net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); } 
@@ -278,7 +332,7 @@ net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); }
 host:	ID				{ $$=$1; }
 host:	ID				{ $$=$1; }
 	| host DOT ID		{ $$=(char*)malloc(strlen($1)+1+strlen($3)+1);
 	| host DOT ID		{ $$=(char*)malloc(strlen($1)+1+strlen($3)+1);
 						  if ($$==0){
 						  if ($$==0){
-						  	fprintf(stderr, "memory allocation failure"
+						  	LOG(L_CRIT, "ERROR: cfg. parser: memory allocation failure"
 						 				" while parsing host\n");
 						 				" while parsing host\n");
 						  }else{
 						  }else{
 						  	memcpy($$, $1, strlen($1));
 						  	memcpy($$, $1, strlen($1));
@@ -382,17 +436,17 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 													"argument"); }
 													"argument"); }
 		| DROP LPAREN RPAREN	{$$=mk_action(DROP_T,0, 0, 0, 0); }
 		| DROP LPAREN RPAREN	{$$=mk_action(DROP_T,0, 0, 0, 0); }
 		| DROP					{$$=mk_action(DROP_T,0, 0, 0, 0); }
 		| DROP					{$$=mk_action(DROP_T,0, 0, 0, 0); }
-		| LOG LPAREN STRING RPAREN	{$$=mk_action(	LOG_T, NUMBER_ST, 
+		| LOG_TOK LPAREN STRING RPAREN	{$$=mk_action(	LOG_T, NUMBER_ST, 
 													STRING_ST,(void*)4,$3);
 													STRING_ST,(void*)4,$3);
 									}
 									}
-		| LOG LPAREN NUMBER COMMA STRING RPAREN	{$$=mk_action(	LOG_T,
+		| LOG_TOK LPAREN NUMBER COMMA STRING RPAREN	{$$=mk_action(	LOG_T,
 																NUMBER_ST, 
 																NUMBER_ST, 
 																STRING_ST,
 																STRING_ST,
 																(void*)$3,
 																(void*)$3,
 																$5);
 																$5);
 												}
 												}
-		| LOG error { $$=0; yyerror("missing '(' or ')' ?"); }
-		| LOG LPAREN error RPAREN { $$=0; yyerror("bad log"
+		| LOG_TOK error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| LOG_TOK LPAREN error RPAREN { $$=0; yyerror("bad log"
 									"argument"); }
 									"argument"); }
 		| ERROR LPAREN STRING COMMA STRING RPAREN {$$=mk_action(ERROR_T,
 		| ERROR LPAREN STRING COMMA STRING RPAREN {$$=mk_action(ERROR_T,
 																STRING_ST, 
 																STRING_ST, 
@@ -413,6 +467,24 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 		| EXEC LPAREN STRING RPAREN	{ $$=mk_action(	EXEC_T, STRING_ST, 0,
 		| EXEC LPAREN STRING RPAREN	{ $$=mk_action(	EXEC_T, STRING_ST, 0,
 													$3, 0);
 													$3, 0);
 									}
 									}
+		| SET_HOST LPAREN STRING RPAREN { $$=mk_action( SET_HOST_T, STRING_ST, 0, $3, 0); }
+		| SET_HOST error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
+		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, STRING_ST, 0, $3, 0); }
+		| SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| SET_HOSTPORT LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
+		| SET_PORT LPAREN STRING RPAREN { $$=mk_action( SET_PORT_T, STRING_ST, 0, $3, 0); }
+		| SET_PORT error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| SET_PORT LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
+		| SET_USER LPAREN STRING RPAREN { $$=mk_action( SET_USER_T, STRING_ST, 0, $3, 0); }
+		| SET_USER error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| SET_USER LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
+		| SET_USERPASS LPAREN STRING RPAREN { $$=mk_action( SET_USERPASS_T, STRING_ST, 0, $3, 0); }
+		| SET_USERPASS error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| SET_USERPASS LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
+		| SET_URI LPAREN STRING RPAREN { $$=mk_action( SET_URI_T, STRING_ST, 0, $3, 0); }
+		| SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
 	;
 	;
 
 
 
 
@@ -423,7 +495,7 @@ extern int column;
 extern int startcolumn;
 extern int startcolumn;
 void yyerror(char* s)
 void yyerror(char* s)
 {
 {
-	fprintf(stderr, "parse error (%d,%d-%d): %s\n", line, startcolumn, 
+	LOG(L_CRIT, "parse error (%d,%d-%d): %s\n", line, startcolumn, 
 			column, s);
 			column, s);
 	cfg_errors++;
 	cfg_errors++;
 }
 }

+ 2 - 0
config.h

@@ -28,4 +28,6 @@
 #define ROUTE_MAX_REC_LEV 10 /* maximum number of recursive calls
 #define ROUTE_MAX_REC_LEV 10 /* maximum number of recursive calls
 							   for route()*/
 							   for route()*/
 
 
+#define MAX_URI_SIZE 1024	/* used when rewriting URIs */
+
 #endif
 #endif

+ 20 - 4
forward.c

@@ -63,7 +63,7 @@ int check_address(unsigned long ip, char *name, int resolver)
 
 
 int forward_request( struct sip_msg* msg, struct proxy_l * p)
 int forward_request( struct sip_msg* msg, struct proxy_l * p)
 {
 {
-	unsigned int len, new_len, via_len, received_len;
+	unsigned int len, new_len, via_len, received_len, uri_len;
 	char line_buf[MAX_VIA_LINE_SIZE];
 	char line_buf[MAX_VIA_LINE_SIZE];
 	char received_buf[MAX_RECEIVED_SIZE];
 	char received_buf[MAX_RECEIVED_SIZE];
 	char* new_buf;
 	char* new_buf;
@@ -96,15 +96,31 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 	}
 	}
 	
 	
 	new_len=len+via_len+received_len;
 	new_len=len+via_len+received_len;
+	if (msg->new_uri){ 
+		uri_len=strlen(msg->new_uri); 
+		new_len=new_len-strlen(msg->first_line.u.request.uri)+uri_len;
+	}
 	new_buf=(char*)malloc(new_len+1);
 	new_buf=(char*)malloc(new_len+1);
 	if (new_buf==0){
 	if (new_buf==0){
 		LOG(L_ERR, "ERROR: forward_request: out of memory\n");
 		LOG(L_ERR, "ERROR: forward_request: out of memory\n");
 		goto error;
 		goto error;
 	}
 	}
-/* copy msg till first via */
+
 	offset=s_offset=0;
 	offset=s_offset=0;
-	size=msg->via1.hdr-buf;
-	memcpy(new_buf, orig, size);
+	if (msg->new_uri){
+		/* copy message up to uri */
+		size=msg->first_line.u.request.uri-buf;
+		memcpy(new_buf, orig, size);
+		offset+=size;
+		s_offset+=size;
+		/* add our uri */
+		memcpy(new_buf+offset, msg->new_uri, uri_len);
+		offset+=uri_len;
+		s_offset+=strlen(msg->first_line.u.request.uri); /* skip original uri */
+	}
+/* copy msg till first via */
+	size=msg->via1.hdr-(buf+s_offset);
+	memcpy(new_buf+offset, orig+s_offset, size);
 	offset+=size;
 	offset+=size;
 	s_offset+=size;
 	s_offset+=size;
  /* add our via */
  /* add our via */

+ 1 - 1
globals.h

@@ -19,7 +19,7 @@ extern unsigned short port_no;
 extern char * names[];
 extern char * names[];
 extern unsigned long addresses[];
 extern unsigned long addresses[];
 extern int addresses_no;
 extern int addresses_no;
-extern int child_no;
+extern int children_no;
 extern int debug;
 extern int debug;
 extern int dont_fork;
 extern int dont_fork;
 extern int log_stderr;
 extern int log_stderr;

+ 20 - 21
main.c

@@ -22,7 +22,7 @@
 
 
 
 
 static char id[]="@(#) $Id$";
 static char id[]="@(#) $Id$";
-static char version[]="sip_router 0.5";
+static char version[]="sip_router 0.6";
 static char help_msg[]= "\
 static char help_msg[]= "\
 Usage: sip_router -l address [-l address] [options]\n\
 Usage: sip_router -l address [-l address] [options]\n\
 Options:\n\
 Options:\n\
@@ -289,6 +289,25 @@ int main(int argc, char** argv)
 	
 	
 	/* fill missing arguments with the default values*/
 	/* fill missing arguments with the default values*/
 	if (cfg_file==0) cfg_file=CFG_FILE;
 	if (cfg_file==0) cfg_file=CFG_FILE;
+
+	/* load config file or die */
+	cfg_stream=fopen (cfg_file, "r");
+	if (cfg_stream==0){
+		fprintf(stderr, "ERROR: loading config file(%s): %s\n", cfg_file,
+				strerror(errno));
+		goto error;
+	}
+	
+	yyin=cfg_stream;
+	if ((yyparse()!=0)||(cfg_errors)){
+		fprintf(stderr, "ERROR: bad config file (%d errors)\n", cfg_errors);
+		goto error;
+	}
+	
+	
+	print_rl();
+
+	/* fix parameters */
 	if (port_no<=0) port_no=SIP_PORT;
 	if (port_no<=0) port_no=SIP_PORT;
 	if (children_no<=0) children_no=CHILD_NO;
 	if (children_no<=0) children_no=CHILD_NO;
 	if (addresses_no==0) {
 	if (addresses_no==0) {
@@ -320,26 +339,6 @@ int main(int argc, char** argv)
 				inet_ntoa(*(struct in_addr*)&addresses[r]),
 				inet_ntoa(*(struct in_addr*)&addresses[r]),
 				(unsigned short)port_no);
 				(unsigned short)port_no);
 	}
 	}
-	
-	
-
-	/* load config file or die */
-	cfg_stream=fopen (cfg_file, "r");
-	if (cfg_stream==0){
-		fprintf(stderr, "ERROR: loading config file(%s): %s\n", cfg_file,
-				strerror(errno));
-		goto error;
-	}
-	
-	yyin=cfg_stream;
-	if ((yyparse()!=0)||(cfg_errors)){
-		fprintf(stderr, "ERROR: bad config file (%d errors)\n", cfg_errors);
-		goto error;
-	}
-	
-	
-	print_rl();
-
 
 
 	/* init_daemon? */
 	/* init_daemon? */
 	if (!dont_fork){
 	if (!dont_fork){

+ 187 - 6
msg_parser.c

@@ -10,6 +10,7 @@
 
 
 #include "msg_parser.h"
 #include "msg_parser.h"
 #include "parser_f.h"
 #include "parser_f.h"
+#include "error.h"
 #include "dprint.h"
 #include "dprint.h"
 
 
 
 
@@ -118,10 +119,15 @@ error1:
 /* returns integer field name type */
 /* returns integer field name type */
 int field_name(char *s)
 int field_name(char *s)
 {
 {
-	if ((strcmp(s, "Via")==0 )||(strcmp(s,"v")==0))
+	int l;
+	l=strlen(s);
+	if (l<1) return HDR_OTHER;
+	else if ((l==1) && ((*s=='v')||(*s=='V')))
+		return HDR_VIA;
+	else if (strcasecmp(s, "Via")==0)
 		return  HDR_VIA;
 		return  HDR_VIA;
-	if ((strcmp(s, "To")==0)||(strcmp(s,"t")==0))
-		return HDR_TO;
+/*	if ((strcmp(s, "To")==0)||(strcmp(s,"t")==0))
+		return HDR_TO;*/
 	return HDR_OTHER;
 	return HDR_OTHER;
 }
 }
 
 
@@ -137,7 +143,7 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 	   (CRLF in the field body must be removed)
 	   (CRLF in the field body must be removed)
 	*/
 	*/
 
 
-	char* tmp;
+	char* tmp, *tmp2;
 	char* nl;
 	char* nl;
 	char* body;
 	char* body;
 	int offset;
 	int offset;
@@ -156,11 +162,25 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 	
 	
 	tmp=eat_token2(buffer, len, ':');
 	tmp=eat_token2(buffer, len, ':');
 	if ((tmp==buffer) || (tmp-buffer==len) ||
 	if ((tmp==buffer) || (tmp-buffer==len) ||
-		(is_empty(buffer, tmp-buffer-1))|| (*tmp!=':')){
+		(is_empty(buffer, tmp-buffer))|| (*tmp!=':')){
 		hdr_f->type=HDR_ERROR;
 		hdr_f->type=HDR_ERROR;
 		goto error;
 		goto error;
 	}
 	}
 	*tmp=0;
 	*tmp=0;
+	/* take care of possible spaces (e.g: "Via  :") */
+	tmp2=eat_token(buffer, tmp-buffer);
+	/* in the worst case tmp2=buffer+tmp-buffer=tmp */
+	*tmp2=0;
+	if (tmp2<tmp){
+		tmp2++;
+		/* catch things like: "Via foo bar:" */
+		tmp2=eat_space(tmp2, tmp-tmp2);
+		if (tmp2!=tmp){
+			hdr_f->type=HDR_ERROR;
+			goto error;
+		}
+	}
+
 	hdr_f->type=field_name(buffer);
 	hdr_f->type=field_name(buffer);
 	body= ++tmp;
 	body= ++tmp;
 	hdr_f->name=buffer;
 	hdr_f->name=buffer;
@@ -210,6 +230,165 @@ char* parse_hostport(char* buf, char** host, short int* port)
 
 
 
 
 
 
+/* buf= pointer to begining of uri (sip:[email protected]:5060;a=b?h=i)
+   len= len of uri
+returns: fills uri & returns <0 on error or 0 if ok */
+int parse_uri(char *buf, int len, struct sip_uri* uri)
+{
+	char* next, *end;
+	char *user, *passwd, *host, *port, *params, *headers;
+	int host_len, port_len, params_len, headers_len;
+	int ret;
+	
+
+	ret=0;
+	end=buf+len;
+	memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure */
+	/* look for "sip:"*/;
+	next=memchr(buf, ':',  len);
+	if ((next==0)||(strncmp(buf,"sip",next-buf)!=0)){
+		LOG(L_DBG, "ERROR: parse_uri: bad sip uri\n");
+		ret=E_UNSPEC;
+		goto error;
+	}
+	buf=next+1; /* next char after ':' */
+	if (buf>end){
+		LOG(L_DBG, "ERROR: parse_uri: uri too short\n");
+		ret=E_UNSPEC;
+		goto error;
+	}
+	/*look for '@' */
+	next=memchr(buf,'@', end-buf);
+	if (next==0){
+		/* no '@' found, => no userinfo */
+		uri->user=0;
+		uri->passwd=0;
+		host=buf;
+	}else{
+		/* found it */
+		user=buf;
+		/* try to find passwd */
+		passwd=memchr(user,':', next-user);
+		if (passwd==0){
+			/* no ':' found => no password */
+			uri->passwd=0;
+			uri->user=(char*)malloc(next-user+1);
+			if (uri->user==0){
+				LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
+				ret=E_OUT_OF_MEM;
+				goto error;
+			}
+			memcpy(uri->user,user, next-user);
+			uri->user[next-user]=0; /* null terminate it, usefull for easy printing*/
+		}else{
+			uri->user=(char*)malloc(passwd-user+1);
+			if (uri->user==0){
+				LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
+				ret=E_OUT_OF_MEM;
+				goto error;
+			}
+			memcpy(uri->user,user, passwd-user);
+			uri->user[passwd-user]=0;
+			passwd++; /*skip ':' */
+			uri->passwd=(char*)malloc(next-passwd+1);
+			if (uri->passwd==0){
+				LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
+				ret=E_OUT_OF_MEM;
+				goto error;
+			}
+			memcpy(uri->passwd,passwd, next-passwd);
+			uri->passwd[next-passwd]=0;
+		}
+		host=next+1; /* skip '@' */
+	}
+	/* try to find the rest */
+	if(host>=end){
+		LOG(L_DBG, "ERROR: parse_uri: missing hostport\n");
+		ret=E_UNSPEC;
+		goto error;
+	}
+	headers=memchr(host,'?',end-host);
+	params=memchr(host,';',end-host);
+	port=memchr(host,':',end-host);
+	host_len=(port)?port-host:(params)?params-host:(headers)?headers-host:end-host;
+	/* get host */
+	uri->host=malloc(host_len+1);
+	if (uri->host==0){
+		LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
+		ret=E_OUT_OF_MEM;
+		goto error;
+	}
+	memcpy(uri->host,host, host_len);
+	uri->host[host_len]=0;
+	/* get port*/
+	if ((port)&&(port+1<end)){
+		port++;
+		if ( ((params) &&(params<port))||((headers) &&(headers<port)) ){
+			/* error -> invalid uri we found ';' or '?' before ':' */
+			LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n");
+			ret=E_UNSPEC;
+			goto error;
+		}
+		port_len=(params)?params-port:(headers)?headers-port:end-port;
+		uri->port=malloc(port_len+1);
+		if (uri->port==0){
+			LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
+			ret=E_OUT_OF_MEM;
+			goto error;
+		}
+		memcpy(uri->port, port, port_len);
+		uri->port[port_len]=0;
+	}else uri->port=0;
+	/* get params */
+	if ((params)&&(params+1<end)){
+		params++;
+		if ((headers) && (headers<params)){
+			/* error -> invalid uri we found '?' or '?' before ';' */
+			LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n");
+			ret=E_UNSPEC;
+			goto error;
+		}
+		params_len=(headers)?headers-params:end-params;
+		uri->params=malloc(params_len+1);
+		if (uri->params==0){
+			LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
+			ret=E_OUT_OF_MEM;
+			goto error;
+		}
+		memcpy(uri->params, params, params_len);
+		uri->params[params_len]=0;
+	}else uri->params=0;
+	/*get headers */
+	if ((headers)&&(headers+1<end)){
+		headers++;
+		headers_len=end-headers;
+		uri->headers=malloc(headers_len+1);
+		if(uri->headers==0){
+			LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
+			ret=E_OUT_OF_MEM;
+			goto error;
+		}
+		memcpy(uri->headers, headers, headers_len);
+		uri->headers[headers_len]=0;
+	}else uri->headers=0;
+	
+	return ret;
+error:
+	return ret;
+}
+
+
+			
+
+			
+			
+	
+		
+	
+	
+
+
+
 /* parses a via body, returns next via (for compact vias) & fills vb,
 /* parses a via body, returns next via (for compact vias) & fills vb,
  * the buffer should be null terminated! */
  * the buffer should be null terminated! */
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
@@ -434,9 +613,11 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
 							goto skip;
 							goto skip;
 						}else{
 						}else{
 						/*  add 1 (we don't see the trailing lf which
 						/*  add 1 (we don't see the trailing lf which
-						 *  was zeroed by get_hfr_field */
+						 *  was zeroed by get_hfr_field) */
 							vb1.size+=1;
 							vb1.size+=1;
 						}
 						}
+						if (fl.type!=SIP_REPLY) goto skip; /* we are interested in the 2nd via 
+															   only in replies */
 				}else if (second_via==0){
 				}else if (second_via==0){
 							second_via=hf.body;
 							second_via=hf.body;
 							vb2.hdr=hf.name;
 							vb2.hdr=hf.name;

+ 14 - 0
msg_parser.h

@@ -72,10 +72,23 @@ struct sip_msg{
 				   via, etc. point into it */
 				   via, etc. point into it */
 				   
 				   
 	unsigned int len; /* message len (orig) */
 	unsigned int len; /* message len (orig) */
+
+	/* modifications */
+	char* new_uri; /* changed first line uri*/
 	
 	
 };
 };
 
 
 
 
+struct sip_uri{
+	char* user;
+	char* passwd;
+	char* host;
+	char* port;
+	char* params;
+	char* headers;
+};
+
+
 
 
 char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl);
 char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl);
 char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f);
 char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f);
@@ -83,6 +96,7 @@ int field_name(char *s);
 char* parse_hostport(char* buf, char** host, short int* port);
 char* parse_hostport(char* buf, char** host, short int* port);
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb);
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb);
 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
+int parse_uri(char *buf, int len, struct sip_uri* uri);
 
 
 
 
 
 

+ 1 - 0
receive.c

@@ -18,6 +18,7 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 	struct sip_msg msg;
 	struct sip_msg msg;
 	struct route_elem *re;
 	struct route_elem *re;
 
 
+	memset(&msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
 	/* fill in msg */
 	/* fill in msg */
 	msg.buf=buf;
 	msg.buf=buf;
 	msg.len=len;
 	msg.len=len;

+ 5 - 5
route.c

@@ -407,16 +407,16 @@ void print_rl()
 
 
 	for(j=0; j<RT_NO; j++){
 	for(j=0; j<RT_NO; j++){
 		if (rlist[j]==0){
 		if (rlist[j]==0){
-			if (j==0) printf("WARNING: the main routing table is empty\n");
+			if (j==0) DBG("WARNING: the main routing table is empty\n");
 			continue;
 			continue;
 		}
 		}
-		printf("routing table %d:\n",j);
+		DBG("routing table %d:\n",j);
 		for (t=rlist[j],i=0; t; i++, t=t->next){
 		for (t=rlist[j],i=0; t; i++, t=t->next){
-			printf("%2d.condition: ",i);
+			DBG("%2d.condition: ",i);
 			print_expr(t->condition);
 			print_expr(t->condition);
-			printf("\n  -> ");
+			DBG("\n  -> ");
 			print_action(t->actions);
 			print_action(t->actions);
-			printf("\n    Statistics: tx=%d, errors=%d, tx_bytes=%d\n",
+			DBG("\n    Statistics: tx=%d, errors=%d, tx_bytes=%d\n",
 					t->tx, t->errors, t->tx_bytes);
 					t->tx, t->errors, t->tx_bytes);
 		}
 		}
 	}
 	}

+ 64 - 44
route_struct.c

@@ -12,6 +12,8 @@
 #include <sys/types.h>
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <netinet/in.h>
 
 
+#include "dprint.h"
+
 struct expr* mk_exp(int op, struct expr* left, struct expr* right)
 struct expr* mk_exp(int op, struct expr* left, struct expr* right)
 {
 {
 	struct expr * e;
 	struct expr * e;
@@ -23,7 +25,7 @@ struct expr* mk_exp(int op, struct expr* left, struct expr* right)
 	e->r.expr=right;
 	e->r.expr=right;
 	return e;
 	return e;
 error:
 error:
-	fprintf(stderr, "ERROR: mk_exp: memory allocation failure\n");
+	LOG(L_CRIT, "ERROR: mk_exp: memory allocation failure\n");
 	return 0;
 	return 0;
 }
 }
 
 
@@ -40,7 +42,7 @@ struct expr* mk_elem(int op, int subtype, int operand, void* param)
 	e->r.param=param;
 	e->r.param=param;
 	return e;
 	return e;
 error:
 error:
-	fprintf(stderr, "ERROR: mk_elem: memory allocation failure\n");
+	LOG(L_CRIT, "ERROR: mk_elem: memory allocation failure\n");
 	return 0;
 	return 0;
 }
 }
 
 
@@ -60,7 +62,7 @@ struct action* mk_action(int type, int p1_type, int p2_type, void* p1, void* p2)
 	return a;
 	return a;
 	
 	
 error:
 error:
-	fprintf(stderr, "ERROR: mk_action: memory allocation failure\n");
+	LOG(L_CRIT, "ERROR: mk_action: memory allocation failure\n");
 	return 0;
 	return 0;
 
 
 }
 }
@@ -89,7 +91,7 @@ struct net* mk_net(unsigned long ip, unsigned long mask)
 	n->mask=mask;
 	n->mask=mask;
 	return n;
 	return n;
 error:
 error:
-	fprintf(stderr, "ERROR: mk_net_mask: memory allocation failure\n");
+	LOG(L_CRIT, "ERROR: mk_net_mask: memory allocation failure\n");
 	return 0;
 	return 0;
 }
 }
 
 
@@ -98,7 +100,7 @@ error:
 
 
 void print_ip(unsigned ip)
 void print_ip(unsigned ip)
 {
 {
-	printf("%d.%d.%d.%d", ((unsigned char*)&ip)[0],
+	DBG("%d.%d.%d.%d", ((unsigned char*)&ip)[0],
 						  ((unsigned char*)&ip)[1],
 						  ((unsigned char*)&ip)[1],
 						  ((unsigned char*)&ip)[2],
 						  ((unsigned char*)&ip)[2],
 						  ((unsigned char*)&ip)[3]);
 						  ((unsigned char*)&ip)[3]);
@@ -108,10 +110,10 @@ void print_ip(unsigned ip)
 void print_net(struct net* net)
 void print_net(struct net* net)
 {
 {
 	if (net==0){
 	if (net==0){
-		fprintf(stderr, "ERROR: print net: null pointer\n");
+		LOG(L_WARN, "ERROR: print net: null pointer\n");
 		return;
 		return;
 	}
 	}
-	print_ip(net->ip); printf("/"); print_ip(net->mask);
+	print_ip(net->ip); DBG("/"); print_ip(net->mask);
 }
 }
 
 
 
 
@@ -119,42 +121,42 @@ void print_net(struct net* net)
 void print_expr(struct expr* exp)
 void print_expr(struct expr* exp)
 {
 {
 	if (exp==0){
 	if (exp==0){
-		fprintf(stderr, "ERROR: print_expr: null expression!\n");
+		LOG(L_CRIT, "ERROR: print_expr: null expression!\n");
 		return;
 		return;
 	}
 	}
 	if (exp->type==ELEM_T){
 	if (exp->type==ELEM_T){
 		switch(exp->l.operand){
 		switch(exp->l.operand){
 			case METHOD_O:
 			case METHOD_O:
-				printf("method");
+				DBG("method");
 				break;
 				break;
 			case URI_O:
 			case URI_O:
-				printf("uri");
+				DBG("uri");
 				break;
 				break;
 			case SRCIP_O:
 			case SRCIP_O:
-				printf("srcip");
+				DBG("srcip");
 				break;
 				break;
 			case DSTIP_O:
 			case DSTIP_O:
-				printf("dstip");
+				DBG("dstip");
 				break;
 				break;
 			default:
 			default:
-				printf("UNKNOWN");
+				DBG("UNKNOWN");
 		}
 		}
 		switch(exp->op){
 		switch(exp->op){
 			case EQUAL_OP:
 			case EQUAL_OP:
-				printf("==");
+				DBG("==");
 				break;
 				break;
 			case MATCH_OP:
 			case MATCH_OP:
-				printf("~=");
+				DBG("=~");
 				break;
 				break;
 			default:
 			default:
-				printf("<UNKNOWN>");
+				DBG("<UNKNOWN>");
 		}
 		}
 		switch(exp->subtype){
 		switch(exp->subtype){
 			case NOSUBTYPE: 
 			case NOSUBTYPE: 
-					printf("N/A");
+					DBG("N/A");
 					break;
 					break;
 			case STRING_ST:
 			case STRING_ST:
-					printf("\"%s\"", (char*)exp->r.param);
+					DBG("\"%s\"", (char*)exp->r.param);
 					break;
 					break;
 			case NET_ST:
 			case NET_ST:
 					print_net((struct net*)exp->r.param);
 					print_net((struct net*)exp->r.param);
@@ -163,35 +165,35 @@ void print_expr(struct expr* exp)
 					print_ip(exp->r.intval);
 					print_ip(exp->r.intval);
 					break;
 					break;
 			default:
 			default:
-					printf("type<%d>", exp->subtype);
+					DBG("type<%d>", exp->subtype);
 		}
 		}
 	}else if (exp->type==EXP_T){
 	}else if (exp->type==EXP_T){
 		switch(exp->op){
 		switch(exp->op){
 			case AND_OP:
 			case AND_OP:
-					printf("AND( ");
+					DBG("AND( ");
 					print_expr(exp->l.expr);
 					print_expr(exp->l.expr);
-					printf(", ");
+					DBG(", ");
 					print_expr(exp->r.expr);
 					print_expr(exp->r.expr);
-					printf(" )");
+					DBG(" )");
 					break;
 					break;
 			case OR_OP:
 			case OR_OP:
-					printf("OR( ");
+					DBG("OR( ");
 					print_expr(exp->l.expr);
 					print_expr(exp->l.expr);
-					printf(", ");
+					DBG(", ");
 					print_expr(exp->r.expr);
 					print_expr(exp->r.expr);
-					printf(" )");
+					DBG(" )");
 					break;
 					break;
 			case NOT_OP:	
 			case NOT_OP:	
-					printf("NOT( ");
+					DBG("NOT( ");
 					print_expr(exp->l.expr);
 					print_expr(exp->l.expr);
-					printf(" )");
+					DBG(" )");
 					break;
 					break;
 			default:
 			default:
-					printf("UNKNOWN_EXP ");
+					DBG("UNKNOWN_EXP ");
 		}
 		}
 					
 					
 	}else{
 	}else{
-		printf("ERROR:print_expr: unknown type\n");
+		DBG("ERROR:print_expr: unknown type\n");
 	}
 	}
 }
 }
 					
 					
@@ -204,55 +206,73 @@ void print_action(struct action* a)
 	for(t=a; t!=0;t=t->next){
 	for(t=a; t!=0;t=t->next){
 		switch(t->type){
 		switch(t->type){
 			case FORWARD_T:
 			case FORWARD_T:
-					printf("forward(");
+					DBG("forward(");
 					break;
 					break;
 			case SEND_T:
 			case SEND_T:
-					printf("send(");
+					DBG("send(");
 					break;
 					break;
 			case DROP_T:
 			case DROP_T:
-					printf("drop(");
+					DBG("drop(");
 					break;
 					break;
 			case LOG_T:
 			case LOG_T:
-					printf("log(");
+					DBG("log(");
 					break;
 					break;
 			case ERROR_T:
 			case ERROR_T:
-					printf("error(");
+					DBG("error(");
 					break;
 					break;
 			case ROUTE_T:
 			case ROUTE_T:
-					printf("route(");
+					DBG("route(");
 					break;
 					break;
 			case EXEC_T:
 			case EXEC_T:
-					printf("exec(");
+					DBG("exec(");
+					break;
+			case SET_HOST_T:
+					DBG("sethost(");
+					break;
+			case SET_HOSTPORT_T:
+					DBG("sethostport(");
+					break;
+			case SET_USER_T:
+					DBG("setuser(");
+					break;
+			case SET_USERPASS_T:
+					DBG("setuserpass(");
+					break;
+			case SET_PORT_T:
+					DBG("setport(");
+					break;
+			case SET_URI_T:
+					DBG("seturi(");
 					break;
 					break;
 			default:
 			default:
-					printf("UNKNOWN(");
+					DBG("UNKNOWN(");
 		}
 		}
 		switch(t->p1_type){
 		switch(t->p1_type){
 			case STRING_ST:
 			case STRING_ST:
-					printf("\"%s\"", t->p1.string);
+					DBG("\"%s\"", t->p1.string);
 					break;
 					break;
 			case NUMBER_ST:
 			case NUMBER_ST:
-					printf("%d",t->p1.number);
+					DBG("%d",t->p1.number);
 					break;
 					break;
 			case IP_ST:
 			case IP_ST:
 					print_ip(t->p1.number);
 					print_ip(t->p1.number);
 					break;
 					break;
 			default:
 			default:
-					printf("type<%d>", t->p1_type);
+					DBG("type<%d>", t->p1_type);
 		}
 		}
 		switch(t->p2_type){
 		switch(t->p2_type){
 			case NOSUBTYPE:
 			case NOSUBTYPE:
 					break;
 					break;
 			case STRING_ST:
 			case STRING_ST:
-					printf(", \"%s\"", t->p2.string);
+					DBG(", \"%s\"", t->p2.string);
 					break;
 					break;
 			case NUMBER_ST:
 			case NUMBER_ST:
-					printf(", %d",t->p2.number);
+					DBG(", %d",t->p2.number);
 					break;
 					break;
 			default:
 			default:
-					printf(", type<%d>", t->p2_type);
+					DBG(", type<%d>", t->p2_type);
 		}
 		}
-		printf("); ");
+		DBG("); ");
 	}
 	}
 }
 }
 			
 			

+ 3 - 2
route_struct.h

@@ -11,13 +11,14 @@ enum { AND_OP=1, OR_OP, NOT_OP };
 enum { EQUAL_OP=10, MATCH_OP };
 enum { EQUAL_OP=10, MATCH_OP };
 enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O, DEFAULT_O };
 enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O, DEFAULT_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_PORT_T, SET_URI_T};
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST };
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST };
 
 
 	
 	
 struct expr{
 struct expr{
 	int type; /* exp, exp_elem */
 	int type; /* exp, exp_elem */
-	int op; /* and, or, not | ==,  ~= */
+	int op; /* and, or, not | ==,  =~ */
 	int  subtype;
 	int  subtype;
 	union {
 	union {
 		struct expr* expr;
 		struct expr* expr;

+ 2 - 2
test/bad_via1.sip

@@ -1,5 +1,5 @@
-INVITE sip:[email protected] SIP/2.0/UDP
-Via  : SIP  /   2.0
+INVITE sip:[email protected] SIP/2.0
+Via : SIP  /   2.0
  /UDP
  /UDP
     193.175.133.193
     193.175.133.193
 
 

+ 1 - 1
test/req1.sip

@@ -1,4 +1,4 @@
-INVITE sip:andrei@localhost SIP/2.0/UDP
+INVITE sip:andrei@localhost:5061;a=b?c=d SIP/2.0
 Via: SIP/2.0/UDP localhost
 Via: SIP/2.0/UDP localhost