Browse Source

- fixed a memroy leak (rewritehost/uri/etc.)
- added forward to uri support (forward(uri:host, uri:port) ).
- improved free_lump_list speed (could be dangerous)

Andrei Pelinescu-Onciul 24 years ago
parent
commit
5ada8f8a66
15 changed files with 203 additions and 38 deletions
  1. 6 1
      README
  2. 53 5
      action.c
  3. 8 1
      cfg.lex
  4. 25 0
      cfg.y
  5. 18 2
      data_lump.c
  6. 0 9
      forward.c
  7. 1 1
      main.c
  8. 13 10
      msg_parser.c
  9. 1 0
      msg_parser.h
  10. 45 6
      proxy.c
  11. 2 0
      proxy.h
  12. 8 2
      route.c
  13. 1 1
      route_struct.h
  14. 5 0
      test/req2.sip
  15. 17 0
      test/test3.cfg

+ 6 - 1
README

@@ -24,6 +24,7 @@ Configuration files:
 		- fork
 		- children_no
 		- log_stderror
+		- loadmodule "path/modulename"
 		...
 
 	Logical expressions [missing]
@@ -51,6 +52,10 @@ Configuration files:
 		- log
 		- exec
 		- route/goto
-		- drop
+		- drop/break
+		- if {} else{}
+	Modules:
+		- loadmodule "..."
+		- commands registered by modules
 
 

+ 53 - 5
action.c

@@ -41,6 +41,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 	int len;
 	int user;
 	struct sip_uri uri;
+	unsigned short port;
 
 	ret=E_BUG;
 	switch (a->type){
@@ -48,14 +49,54 @@ int do_action(struct action* a, struct sip_msg* msg)
 				ret=0;
 			break;
 		case FORWARD_T:
-			if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
+			if (a->p1_type==URIHOST_ST){
+				/*parse uri*/
+				tmp=(msg->new_uri)?msg->new_uri:
+						msg->first_line.u.request.uri;
+				if (parse_uri(tmp, strlen(tmp), &uri)<0){
+					LOG(L_ERR, "ERROR: do_action: forward: bad_uri <%s>,"
+								" dropping packet\n",tmp);
+					ret=E_UNSPEC;
+					break;
+				}
+				switch (a->p2_type){
+					case URIPORT_ST:
+									if (uri.port){
+										port=strtol(uri.port,&end,10);
+										if ((end)&&(*end)){
+											LOG(L_ERR, "ERROR: do_action: "
+													"forward: bad port in "
+													"uri: <%s>\n", uri.port);
+											ret=E_UNSPEC;
+											free_uri(&uri);
+											goto skip;
+										}
+									}else port=SIP_PORT;
+									break;
+					case NUMBER_ST:
+									port=a->p2.number;
+									break;
+					default:
+							LOG(L_CRIT, "BUG: do_action bad forward 2nd"
+										" param type (%d)\n", a->p2_type);
+							free_uri(&uri);
+							goto skip;
+				}
+				/* create a temporary proxy*/
+				p=mk_proxy(uri.host, port);
+				ret=forward_request(msg, p);
+				free_uri(&uri);
+				free_proxy(p); /* frees only p content, not p itself */
+				free(p);
+				if (ret>=0) ret=1;
+			}else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
+				ret=forward_request(msg,(struct proxy_l*)a->p1.data);
+				if (ret>=0) ret=1;
+			}else{
 				LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
 						a->p1_type, a->p2_type);
 				ret=E_BUG;
-				break;
 			}
-			ret=forward_request(msg, (struct proxy_l*)a->p1.data);
-			if (ret>=0) ret=1;
 			break;
 		case SEND_T:
 			to=(struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
@@ -79,6 +120,8 @@ int do_action(struct action* a, struct sip_msg* msg)
 			if (p->ok==0){
 				if (p->host.h_addr_list[p->addr_idx+1])
 					p->addr_idx++;
+				else 
+					p->addr_idx=0;
 				p->ok=1;
 			}
 			to->sin_addr.s_addr=*((long*)p->host.h_addr_list[p->addr_idx]);
@@ -186,6 +229,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 					LOG(L_ERR, "ERROR: do_action: memory allocation "
 								" failure\n");
 					ret=E_OUT_OF_MEM;
+					free_uri(&uri);
 					break;
 				}
 				end=new_uri+MAX_URI_SIZE;
@@ -255,6 +299,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 				/* copy it to the msg */
 				if (msg->new_uri) free(msg->new_uri);
 				msg->new_uri=new_uri;
+				free_uri(&uri);
 				ret=1;
 				break;
 		case IF_T:
@@ -287,10 +332,12 @@ int do_action(struct action* a, struct sip_msg* msg)
 		default:
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
 	}
+skip:
 	return ret;
 	
 error_uri:
 	LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
+	free_uri(&uri);
 	if (new_uri) free(new_uri);
 	return E_UNSPEC;
 }
@@ -321,7 +368,8 @@ int run_actions(struct action* a, struct sip_msg* msg)
 	for (t=a; t!=0; t=t->next){
 		ret=do_action(t, msg);
 		if(ret==0) break;
-		else if (ret<0){ ret=-1; goto error; }
+		/* ignore errors */
+		/*else if (ret<0){ ret=-1; goto error; }*/
 	}
 	
 	rec_lev--;

+ 8 - 1
cfg.lex

@@ -55,6 +55,10 @@ SET_URI			"rewriteuri"|"seturi"
 IF				"if"
 ELSE			"else"
 
+/*ACTION LVALUES*/
+URIHOST			"uri:host"
+URIPORT			"uri:port"
+
 
 /* condition keywords */
 METHOD	method
@@ -134,6 +138,9 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
 <INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
 
+<INITIAL>{URIHOST}	{ count(); yylval.strval=yytext; return URIHOST; }
+<INITIAL>{URIPORT}	{ count(); yylval.strval=yytext; return URIPORT; }
+
 <INITIAL>{METHOD}	{ count(); yylval.strval=yytext; return METHOD; }
 <INITIAL>{URI}	{ count(); yylval.strval=yytext; return URI; }
 <INITIAL>{SRCIP}	{ count(); yylval.strval=yytext; return SRCIP; }
@@ -199,7 +206,7 @@ EAT_ABLE	[\ \t\b\r]
 						yyleng--; addstr(yytext, &str); }
 <STRING1>\\r		{ count(); yytext[yyleng-2]='\r';yytext[yyleng-1]=0; 
 						yyleng--; addstr(yytext, &str); }
-<STRING1>\\g		{ count(); yytext[yyleng-2]='\g';yytext[yyleng-1]=0; 
+<STRING1>\\a		{ count(); yytext[yyleng-2]='\a';yytext[yyleng-1]=0; 
 						yyleng--; addstr(yytext, &str); }
 <STRING1>\\t		{ count(); yytext[yyleng-2]='\t';yytext[yyleng-1]=0; 
 						yyleng--; addstr(yytext, &str); }

+ 25 - 0
cfg.y

@@ -57,6 +57,8 @@ void* f_tmp;
 %token SET_URI
 %token IF
 %token ELSE
+%token URIHOST
+%token URIPORT
 
 %token METHOD
 %token URI
@@ -449,6 +451,29 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 																 (void*)$3,
 																(void*)$5);
 												  }
+		| FORWARD LPAREN URIHOST COMMA URIPORT RPAREN {
+													$$=mk_action(FORWARD_T,
+																 URIHOST_ST,
+																 URIPORT_ST,
+																0,
+																0);
+													}
+													
+									
+		| FORWARD LPAREN URIHOST COMMA NUMBER RPAREN {
+													$$=mk_action(FORWARD_T,
+																 URIHOST_ST,
+																 NUMBER_ST,
+																0,
+																(void*)$5);
+													}
+		| FORWARD LPAREN URIHOST RPAREN {
+													$$=mk_action(FORWARD_T,
+																 URIHOST_ST,
+																 NUMBER_ST,
+																0,
+																0);
+										}
 		| FORWARD error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| FORWARD LPAREN error RPAREN { $$=0; yyerror("bad forward"
 										"argument"); }

+ 18 - 2
data_lump.c

@@ -186,14 +186,30 @@ void free_lump(struct lump* lmp)
 
 void free_lump_list(struct lump* l)
 {
-	struct lump* t, *crt;
+	struct lump* t, *r, *foo,*crt;
 	t=l;
 	while(t){
 		crt=t;
 		t=t->next;
-		/* dangerous recursive clean*/
+	/*
+		 dangerous recursive clean
 		if (crt->before) free_lump_list(crt->before);
 		if (crt->after)  free_lump_list(crt->after);
+	*/
+		/* no more recursion, clean after and before and that's it */
+		r=crt->before;
+		while(r){
+			foo=r; r=r->before;
+			free_lump(foo);
+			free(foo);
+		}
+		r=crt->after;
+		while(r){
+			foo=r; r=r->after;
+			free_lump(foo);
+			free(foo);
+		}
+		
 		/*clean current elem*/
 		free_lump(crt);
 		free(crt);

+ 0 - 9
forward.c

@@ -142,8 +142,6 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 	new_len=len;
 	s_offset=0;
 	for(t=msg->add_rm;t;t=t->next){
-		DBG("t=%x, op=%d, offset=%x, len=%d, s_offset=%x\n",
-				t, t->op, t->u.offset, t->len, s_offset);
 		for(r=t->before;r;r=r->before){
 			switch(r->op){
 				case LUMP_ADD:
@@ -162,14 +160,11 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 			case LUMP_DEL:
 				/* fix overlapping deleted zones */
 				if (t->u.offset < s_offset){
-					DBG( "overlapping DEL offsets (%d,%d(%d)), fixing...\n",
-						 s_offset, t->u.offset, t->len);
 					/* change len */
 					if (t->len>s_offset-t->u.offset) 
 							t->len-=s_offset-t->u.offset;
 					else t->len=0;
 					t->u.offset=s_offset;
-					DBG("fixed to %d(%d)\n", t->u.offset, t->len);
 				}
 				s_offset=t->u.offset+t->len;
 				new_len-=t->len;
@@ -177,9 +172,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 			case LUMP_NOP:
 				/* fix offset if overlapping on a deleted zone */
 				if (t->u.offset < s_offset){
-					DBG("overlapping zones (%d,%d)\n", s_offset, t->u.offset);
 					t->u.offset=s_offset;
-					DBG("fixed to %d\n", t->u.offset);
 				}else
 					s_offset=t->u.offset;
 				/* do nothing */
@@ -226,8 +219,6 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 	}
 /* copy msg adding/removing lumps */
 	for (t=msg->add_rm;t;t=t->next){
-		DBG(" t=%x, op=%d, offset=%x, len=%d, s_offset=%x\n",
-				t, t->op, t->u.offset, t->len, s_offset);
 		switch(t->op){
 			case LUMP_ADD:
 				/* just add it here! */

+ 1 - 1
main.c

@@ -30,7 +30,7 @@
 
 
 static char id[]="@(#) $Id$";
-static char version[]="ser 0.8.2";
+static char version[]="ser 0.8.3";
 static char flags[]="NOCR:"
 #ifdef NOCR
 "On"

+ 13 - 10
msg_parser.c

@@ -382,16 +382,6 @@ error:
 }
 
 
-			
-
-			
-			
-	
-		
-	
-	
-
-
 
 /* parses a via body, returns next via (for compact vias) & fills vb,
  * the buffer should be null terminated! */
@@ -686,3 +676,16 @@ error:
 	return -1;
 }
 
+
+
+void free_uri(struct sip_uri* u)
+{
+	if (u){
+		if (u->user) free(u->user);
+		if (u->passwd) free(u->passwd);
+		if (u->host) free(u->host);
+		if (u->port) free(u->port);
+		if (u->params) free(u->params);
+		if (u->headers) free(u->headers);
+	}
+}

+ 1 - 0
msg_parser.h

@@ -102,6 +102,7 @@ char* parse_hostport(char* buf, char** host, short int* port);
 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_uri(char *buf, int len, struct sip_uri* uri);
+void free_uri(struct sip_uri* u);
 
 
 

+ 45 - 6
proxy.c

@@ -112,15 +112,52 @@ error:
 
 
 
+void free_hostent(struct hostent *dst)
+{
+	int r;
+	if (dst->h_name) free(dst->h_name);
+	if (dst->h_aliases){
+		for(r=0; dst->h_aliases[r]; r++)	free(dst->h_aliases[r]);
+		free(dst->h_aliases[r]);
+		free(dst->h_aliases);
+	}
+	if (dst->h_addr_list){
+		for (r=0; dst->h_addr_list[r];r++) free(dst->h_addr_list[r]);
+		free(dst->h_addr_list[r]);
+		free(dst->h_addr_list);
+	}
+}
+
+
+
+
 struct proxy_l* add_proxy(char* name, unsigned short port)
 {
 	struct proxy_l* p;
 	struct hostent* he;
 	
 	if ((p=find_proxy(name, port))!=0) return p;
+	if ((p=mk_proxy(name, port))==0) goto error;
+	/* add p to the proxy list */
+	p->next=proxies;
+	proxies=p;
+	return p;
+
+error:
+	return 0;
+}
+
+
+
+/* same as add_proxy, but it doesn't add the proxy to the list*/
+struct proxy_l* mk_proxy(char* name, unsigned short port)
+{
+	struct proxy_l* p;
+	struct hostent* he;
+	
 	p=(struct proxy_l*) malloc(sizeof(struct proxy_l));
 	if (p==0){
-		LOG(L_CRIT, "ERROR: add_proxy: memory allocation failure\n");
+		LOG(L_CRIT, "ERROR: mk_proxy: memory allocation failure\n");
 		goto error;
 	}
 	memset(p,0,sizeof(struct proxy_l));
@@ -128,7 +165,7 @@ struct proxy_l* add_proxy(char* name, unsigned short port)
 	p->port=port;
 	he=gethostbyname(name);
 	if (he==0){
-		LOG(L_CRIT, "ERROR: add_proxy: could not resolve hostname:"
+		LOG(L_CRIT, "ERROR: mk_proxy: could not resolve hostname:"
 					" \"%s\"\n", name);
 		free(p);
 		goto error;
@@ -138,12 +175,14 @@ struct proxy_l* add_proxy(char* name, unsigned short port)
 		goto error;
 	}
 	p->ok=1;
-	/* add p to the proxy list */
-	p->next=proxies;
-	proxies=p;
 	return p;
-
 error:
 	return 0;
 }
 
+
+
+void free_proxy(struct proxy_l* p)
+{
+	if (p) free_hostent(&p->host);
+}

+ 2 - 0
proxy.h

@@ -28,6 +28,8 @@ struct proxy_l{
 extern struct proxy_l* proxies;
 
 struct proxy_l* add_proxy(char* name, unsigned short port);
+struct proxy_l* mk_proxy(char* name, unsigned short port);
+void free_proxy(struct proxy_l* p);
 
 
 #endif

+ 8 - 2
route.c

@@ -135,6 +135,8 @@ static int fix_actions(struct action* a)
 							t->p1.data=p;
 							t->p1_type=PROXY_ST;
 							break;
+						case URIHOST_ST:
+							break;
 						default:
 							LOG(L_CRIT, "BUG: fix_actions: invalid type"
 									"%d (should be string or number)\n",
@@ -178,11 +180,15 @@ static int fix_actions(struct action* a)
 							mod->exports->cmd_names[r]);
 					if (mod->exports->fixup_pointers[r]){
 						if (mod->exports->param_no[r]>0){
-							ret=mod->exports->fixup_pointers[r](&t->p2.data,1);
+							ret=mod->exports->fixup_pointers[r](&t->p2.data,
+																1);
+							t->p2_type=MODFIXUP_ST;
 							if (ret<0) return ret;
 						}
 						if (mod->exports->param_no[r]>1){
-							ret=mod->exports->fixup_pointers[r](&t->p3.data,2);
+							ret=mod->exports->fixup_pointers[r](&t->p3.data,
+																2);
+							t->p3_type=MODFIXUP_ST;
 							if (ret<0) return ret;
 						}
 					}

+ 1 - 1
route_struct.h

@@ -15,7 +15,7 @@ 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, IF_T, MODULE_T };
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
-		EXPR_ST, ACTIONS_ST, CMDF_ST };
+		EXPR_ST, ACTIONS_ST, CMDF_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST };
 
 	
 struct expr{

+ 5 - 0
test/req2.sip

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

+ 17 - 0
test/test3.cfg

@@ -0,0 +1,17 @@
+debug=9          # debug level (cmd line: -dddddddddd)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=no          # (cmd. line: -D)
+log_stderror=yes # (cmd line: -E)
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+
+route{
+	#rewritehost("127.0.0.1");
+	print("trying forward to uri");
+	forward(uri:host,uri:port);
+	print("after forward");
+}