Explorar o código

- made ipv4<->ipv6 possible
- added different port numbers (eg. ser -l foo -p 1234 -l bar -p 4321 )
- small signal fixes (sigterm to evrybody on exit, exit if 1 child dies a.s.o)

Andrei Pelinescu-Onciul %!s(int64=23) %!d(string=hai) anos
pai
achega
36ef03290c
Modificáronse 15 ficheiros con 334 adicións e 187 borrados
  1. 1 1
      Makefile.defs
  2. 8 2
      action.c
  3. 14 14
      cfg.lex
  4. 28 17
      cfg.y
  5. 0 1
      config.h
  6. 67 19
      forward.c
  7. 2 0
      forward.h
  8. 14 2
      globals.h
  9. 21 8
      ip_addr.h
  10. 123 90
      main.c
  11. 26 10
      msg_translator.c
  12. 3 2
      msg_translator.h
  13. 1 1
      receive.c
  14. 23 16
      udp_server.c
  15. 3 4
      udp_server.h

+ 1 - 1
Makefile.defs

@@ -8,7 +8,7 @@
 VERSION = 0
 VERSION = 0
 PATCHLEVEL = 8
 PATCHLEVEL = 8
 SUBLEVEL = 8
 SUBLEVEL = 8
-EXTRAVERSION = -1-ipv6
+EXTRAVERSION = -2-ipv6
 
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s)
 OS = $(shell uname -s)

+ 8 - 2
action.c

@@ -38,6 +38,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 	int ret;
 	int ret;
 	int v;
 	int v;
 	union sockaddr_union* to;
 	union sockaddr_union* to;
+	struct socket_info* send_sock;
 	struct proxy_l* p;
 	struct proxy_l* p;
 	char* tmp;
 	char* tmp;
 	char *new_uri, *end, *crt;
 	char *new_uri, *end, *crt;
@@ -144,8 +145,13 @@ int do_action(struct action* a, struct sip_msg* msg)
 			if (ret==0){
 			if (ret==0){
 				p->tx++;
 				p->tx++;
 				p->tx_bytes+=msg->len;
 				p->tx_bytes+=msg->len;
-				ret=udp_send(msg->orig, msg->len, to,
-								sizeof(union sockaddr_union));
+				send_sock=get_send_socket(to);
+				if (send_sock!=0){
+					ret=udp_send(send_sock, msg->orig, msg->len, to,
+									sizeof(union sockaddr_union));
+				}else{
+					ret=-1;
+				}
 			}
 			}
 			free(to);
 			free(to);
 			if (ret<0){
 			if (ret<0){

+ 14 - 14
cfg.lex

@@ -25,7 +25,7 @@
 	
 	
 	static int comment_nest=0;
 	static int comment_nest=0;
 	static int state=0;
 	static int state=0;
-	static char* str=0;
+	static char* tstr=0;
 	int line=1;
 	int line=1;
 	int column=1;
 	int column=1;
 	int startcolumn=1;
 	int startcolumn=1;
@@ -219,29 +219,29 @@ 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);
-						yylval.strval=str; str=0;
+						addstr(yytext, &tstr);
+						yylval.strval=tstr; tstr=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--;
-						addstr(yytext, &str);
-						yylval.strval=str;
-						str=0;
+						addstr(yytext, &tstr);
+						yylval.strval=tstr;
+						tstr=0;
 						return STRING;
 						return STRING;
 					}
 					}
 <STRING2>.|{EAT_ABLE}|{CR}	{ yymore(); }
 <STRING2>.|{EAT_ABLE}|{CR}	{ yymore(); }
 
 
 <STRING1>\\n		{ count(); yytext[yyleng-2]='\n';yytext[yyleng-1]=0; 
 <STRING1>\\n		{ count(); yytext[yyleng-2]='\n';yytext[yyleng-1]=0; 
-						yyleng--; addstr(yytext, &str); }
+						yyleng--; addstr(yytext, &tstr); }
 <STRING1>\\r		{ count(); yytext[yyleng-2]='\r';yytext[yyleng-1]=0; 
 <STRING1>\\r		{ count(); yytext[yyleng-2]='\r';yytext[yyleng-1]=0; 
-						yyleng--; addstr(yytext, &str); }
+						yyleng--; addstr(yytext, &tstr); }
 <STRING1>\\a		{ count(); yytext[yyleng-2]='\a';yytext[yyleng-1]=0; 
 <STRING1>\\a		{ count(); yytext[yyleng-2]='\a';yytext[yyleng-1]=0; 
-						yyleng--; addstr(yytext, &str); }
+						yyleng--; addstr(yytext, &tstr); }
 <STRING1>\\t		{ count(); yytext[yyleng-2]='\t';yytext[yyleng-1]=0; 
 <STRING1>\\t		{ count(); yytext[yyleng-2]='\t';yytext[yyleng-1]=0; 
-						yyleng--; addstr(yytext, &str); }
+						yyleng--; addstr(yytext, &tstr); }
 <STRING1>\\\\		{ count(); yytext[yyleng-2]='\\';yytext[yyleng-1]=0; 
 <STRING1>\\\\		{ count(); yytext[yyleng-2]='\\';yytext[yyleng-1]=0; 
-						yyleng--; addstr(yytext, &str); } 
+						yyleng--; addstr(yytext, &tstr); } 
 <STRING1>.|{EAT_ABLE}|{CR}	{ yymore(); }
 <STRING1>.|{EAT_ABLE}|{CR}	{ yymore(); }
 
 
 
 
@@ -257,8 +257,8 @@ EAT_ABLE	[\ \t\b\r]
 
 
 <INITIAL>{COM_LINE}.*{CR}	{ count(); } 
 <INITIAL>{COM_LINE}.*{CR}	{ count(); } 
 
 
-<INITIAL>{ID}			{ count(); addstr(yytext, &str);
-						  yylval.strval=str; str=0; return ID; }
+<INITIAL>{ID}			{ count(); addstr(yytext, &tstr);
+						  yylval.strval=tstr; tstr=0; return ID; }
 
 
 
 
 <<EOF>>							{
 <<EOF>>							{
@@ -266,7 +266,7 @@ EAT_ABLE	[\ \t\b\r]
 										case STRING_S: 
 										case STRING_S: 
 											LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF in"
 											LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF in"
 														" unclosed string\n");
 														" unclosed string\n");
-											if (str) {free(str); str=0;}
+											if (tstr) {free(tstr); tstr=0;}
 											break;
 											break;
 										case COMMENT_S:
 										case COMMENT_S:
 											LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF:"
 											LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF:"

+ 28 - 17
cfg.y

@@ -164,7 +164,10 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 		| DNS EQUAL error { yyerror("boolean value expected"); }
 		| DNS EQUAL error { yyerror("boolean value expected"); }
 		| REV_DNS EQUAL NUMBER { received_dns|= ($3)?DO_REV_DNS:0; }
 		| 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"); }
-		| PORT EQUAL NUMBER   { port_no=$3; }
+		| PORT EQUAL NUMBER   { port_no=$3; 
+								if (sock_no>0) 
+									sock_info[sock_no-1].port_no=port_no;
+							  }
 		| STAT EQUAL STRING {
 		| STAT EQUAL STRING {
 					#ifdef STATS
 					#ifdef STATS
 							stat_file=$3;
 							stat_file=$3;
@@ -180,7 +183,7 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 		| LOOP_CHECKS EQUAL NUMBER { loop_checks=$3; }
 		| LOOP_CHECKS EQUAL NUMBER { loop_checks=$3; }
 		| LOOP_CHECKS EQUAL error { yyerror("boolean value expected"); }
 		| LOOP_CHECKS EQUAL error { yyerror("boolean value expected"); }
 		| LISTEN EQUAL ip  {
 		| LISTEN EQUAL ip  {
-								if (addresses_no < MAX_LISTEN){
+								if (sock_no< MAX_LISTEN){
 									tmp=ip_addr2a($3);
 									tmp=ip_addr2a($3);
 								/*	tmp=inet_ntoa(*(struct in_addr*)&$3);*/
 								/*	tmp=inet_ntoa(*(struct in_addr*)&$3);*/
 									if (tmp==0){
 									if (tmp==0){
@@ -188,15 +191,19 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 											" bad ip address: %s\n",
 											" bad ip address: %s\n",
 											strerror(errno));
 											strerror(errno));
 									}else{
 									}else{
-										names[addresses_no]=
+										sock_info[sock_no].name.s=
 												(char*)malloc(strlen(tmp)+1);
 												(char*)malloc(strlen(tmp)+1);
-										if (names[addresses_no]==0){
+										if (sock_info[sock_no].name.s==0){
 											LOG(L_CRIT, "ERROR: cfg. parser: "
 											LOG(L_CRIT, "ERROR: cfg. parser: "
 														"out of memory.\n");
 														"out of memory.\n");
 										}else{
 										}else{
-											strncpy(names[addresses_no], tmp,
-													strlen(tmp)+1);
-											addresses_no++;
+											strncpy(sock_info[sock_no].name.s,
+													tmp, strlen(tmp)+1);
+											sock_info[sock_no].name.len=
+													strlen(tmp);
+											sock_info[sock_no].port_no=
+													port_no;
+											sock_no++;
 										}
 										}
 									}
 									}
 								}else{
 								}else{
@@ -206,16 +213,18 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 								}
 								}
 							  }
 							  }
 		| LISTEN EQUAL ID	 {
 		| LISTEN EQUAL ID	 {
-								if (addresses_no < MAX_LISTEN){
-									names[addresses_no]=
+								if (sock_no < MAX_LISTEN){
+									sock_info[sock_no].name.s=
 												(char*)malloc(strlen($3)+1);
 												(char*)malloc(strlen($3)+1);
-									if (names[addresses_no]==0){
+									if (sock_info[sock_no].name.s==0){
 										LOG(L_CRIT, "ERROR: cfg. parser:"
 										LOG(L_CRIT, "ERROR: cfg. parser:"
 														" out of memory.\n");
 														" out of memory.\n");
 									}else{
 									}else{
-										strncpy(names[addresses_no], $3,
+										strncpy(sock_info[sock_no].name.s, $3,
 													strlen($3)+1);
 													strlen($3)+1);
-										addresses_no++;
+										sock_info[sock_no].name.len=strlen($3);
+										sock_info[sock_no].port_no= port_no;
+										sock_no++;
 									}
 									}
 								}else{
 								}else{
 									LOG(L_CRIT, "ERROR: cfg. parser: "
 									LOG(L_CRIT, "ERROR: cfg. parser: "
@@ -224,16 +233,18 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 								}
 								}
 							  }
 							  }
 		| LISTEN EQUAL STRING {
 		| LISTEN EQUAL STRING {
-								if (addresses_no < MAX_LISTEN){
-									names[addresses_no]=
+								if (sock_no < MAX_LISTEN){
+									sock_info[sock_no].name.s=
 										(char*)malloc(strlen($3)+1);
 										(char*)malloc(strlen($3)+1);
-									if (names[addresses_no]==0){
+									if (sock_info[sock_no].name.s==0){
 										LOG(L_CRIT, "ERROR: cfg. parser:"
 										LOG(L_CRIT, "ERROR: cfg. parser:"
 													" out of memory.\n");
 													" out of memory.\n");
 									}else{
 									}else{
-										strncpy(names[addresses_no], $3,
+										strncpy(sock_info[sock_no].name.s, $3,
 												strlen($3)+1);
 												strlen($3)+1);
-										addresses_no++;
+										sock_info[sock_no].name.len=strlen($3);
+										sock_info[sock_no].port_no=port_no;
+										sock_no++;
 									}
 									}
 								}else{
 								}else{
 									LOG(L_CRIT, "ERROR: cfg. parser: "
 									LOG(L_CRIT, "ERROR: cfg. parser: "

+ 0 - 1
config.h

@@ -64,7 +64,6 @@
 #define SHM_MEM_SIZE 128 
 #define SHM_MEM_SIZE 128 
 
 
 #define TIMER_TICK 1
 #define TIMER_TICK 1
-#define LONG_SLEEP	3600
 
 
 /* dimensioning buckets in q_malloc */
 /* dimensioning buckets in q_malloc */
 /* size of the size2bucket table; everything beyond that asks for
 /* size of the size2bucket table; everything beyond that asks for

+ 67 - 19
forward.c

@@ -34,29 +34,50 @@
 
 
 
 
 
 
+/* returns a socket_info pointer to the sending socket or 0 on error
+ * params: destination socke_union pointer
+ */
+struct socket_info* get_send_socket(union sockaddr_union* to)
+{
+	struct socket_info* send_sock;
+	
+	send_sock=0;
+	/* check if we need to change the socket (different address families -
+	 * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
+	if (to->s.sa_family!=bind_address->address.af){
+		switch(to->s.sa_family){
+			case AF_INET:	send_sock=sendipv4;
+							break;
+#ifdef USE_IPV6
+			case AF_INET6:	send_sock=sendipv6;
+							break;
+#endif
+			default:		LOG(L_ERR, "get_send_socket: BUG: don't know how"
+									" to forward to af %d\n", to->s.sa_family);
+		}
+	}else send_sock=bind_address;
+	return send_sock;
+}
+
+
+
 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;
 	unsigned int len;
 	char* buf;
 	char* buf;
 	union sockaddr_union* to;
 	union sockaddr_union* to;
-
+	struct socket_info* send_sock;
+	
 	to=0;
 	to=0;
-	buf = build_req_buf_from_sip_req( msg, &len);
-	if (!buf){
-		LOG(L_ERR, "ERROR: forward_reply: building failed\n");
-		goto error;
-	}
-
+	buf=0;
+	
 	to=(union sockaddr_union*)malloc(sizeof(union sockaddr_union));
 	to=(union sockaddr_union*)malloc(sizeof(union sockaddr_union));
 	if (to==0){
 	if (to==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;
 	}
 	}
-
-	 /* send it! */
-	DBG("Sending:\n%s.\n", buf);
-	DBG("orig. len=%d, new_len=%d\n", msg->len, len );
-
+	
+	
 	/* if error try next ip address if possible */
 	/* if error try next ip address if possible */
 	if (p->ok==0){
 	if (p->ok==0){
 		if (p->host.h_addr_list[p->addr_idx+1])
 		if (p->host.h_addr_list[p->addr_idx+1])
@@ -64,13 +85,31 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 		else p->addr_idx=0;
 		else p->addr_idx=0;
 		p->ok=1;
 		p->ok=1;
 	}
 	}
-
+	
 	hostent2su(to, &p->host, p->addr_idx, 
 	hostent2su(to, &p->host, p->addr_idx, 
 				(p->port)?htons(p->port):htons(SIP_PORT));
 				(p->port)?htons(p->port):htons(SIP_PORT));
 	p->tx++;
 	p->tx++;
 	p->tx_bytes+=len;
 	p->tx_bytes+=len;
+	
 
 
-	if (udp_send( buf, len,  to, sizeof(union sockaddr_union))==-1){
+	send_sock=get_send_socket(to);
+	if (send_sock==0){
+		LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d "
+				"no coresponding listening socket\n", to->s.sa_family);
+		goto error;
+	}
+	
+	buf = build_req_buf_from_sip_req( msg, &len, send_sock);
+	if (!buf){
+		LOG(L_ERR, "ERROR: forward_reply: building failed\n");
+		goto error;
+	}
+	 /* send it! */
+	DBG("Sending:\n%s.\n", buf);
+	DBG("orig. len=%d, new_len=%d\n", msg->len, len );
+	
+	if (udp_send( send_sock, buf, len,  to, 
+							sizeof(union sockaddr_union))==-1){
 			p->errors++;
 			p->errors++;
 			p->ok=0;
 			p->ok=0;
 			STATS_TX_DROPS;
 			STATS_TX_DROPS;
@@ -145,6 +184,7 @@ int forward_reply(struct sip_msg* msg)
 	int  r;
 	int  r;
 	char* new_buf;
 	char* new_buf;
 	union sockaddr_union* to;
 	union sockaddr_union* to;
+	struct socket_info* send_sock;
 	unsigned int new_len;
 	unsigned int new_len;
 	struct sr_module *mod;
 	struct sr_module *mod;
 	
 	
@@ -152,11 +192,14 @@ int forward_reply(struct sip_msg* msg)
 	new_buf=0;
 	new_buf=0;
 	/*check if first via host = us */
 	/*check if first via host = us */
 	if (check_via){
 	if (check_via){
-		for (r=0; r<addresses_no; r++)
-			if(strcmp(msg->via1->host.s, names[r])==0) break;
-		if (r==addresses_no){
+		for (r=0; r<sock_no; r++)
+			if ( (msg->via1->host.len==sock_info[r].name.len) && 
+					(memcmp(msg->via1->host.s, sock_info[r].name.s, 
+										sock_info[r].name.len)==0) )
+				break;
+		if (r==sock_no){
 			LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
 			LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
-					" %s\n", msg->via1->host.s);
+					" %.*s\n", msg->via1->host.len, msg->via1->host.s);
 			/* send error msg back? */
 			/* send error msg back? */
 			goto error;
 			goto error;
 		}
 		}
@@ -192,8 +235,13 @@ int forward_reply(struct sip_msg* msg)
 	}
 	}
 
 
 	if (update_sock_struct_from_via( to, msg->via2 )==-1) goto error;
 	if (update_sock_struct_from_via( to, msg->via2 )==-1) goto error;
+	send_sock=get_send_socket(to);
+	if (send_sock==0){
+		LOG(L_ERR, "forward_reply: ERROR: no sending socket found\n");
+		goto error;
+	}
 
 
-	if (udp_send(new_buf,new_len,  to,
+	if (udp_send(send_sock, new_buf,new_len,  to,
 				sizeof(union sockaddr_union))==-1)
 				sizeof(union sockaddr_union))==-1)
 	{
 	{
 		STATS_TX_DROPS;
 		STATS_TX_DROPS;

+ 2 - 0
forward.h

@@ -9,8 +9,10 @@
 #include "parser/msg_parser.h"
 #include "parser/msg_parser.h"
 #include "route.h"
 #include "route.h"
 #include "proxy.h"
 #include "proxy.h"
+#include "ip_addr.h"
 
 
 
 
+struct socket_info* get_send_socket(union sockaddr_union* su);
 int forward_request( struct sip_msg* msg,  struct proxy_l* p);
 int forward_request( struct sip_msg* msg,  struct proxy_l* p);
 int update_sock_struct_from_via( union sockaddr_union* to,
 int update_sock_struct_from_via( union sockaddr_union* to,
 								struct via_body* via );
 								struct via_body* via );

+ 14 - 2
globals.h

@@ -11,23 +11,35 @@
 
 
 #include "types.h"
 #include "types.h"
 #include "ip_addr.h"
 #include "ip_addr.h"
+#include "str.h"
 
 
 #define NO_DNS     0
 #define NO_DNS     0
 #define DO_DNS     1
 #define DO_DNS     1
 #define DO_REV_DNS 2
 #define DO_REV_DNS 2
 
 
 
 
+
 extern char * cfg_file;
 extern char * cfg_file;
 extern char *stat_file;
 extern char *stat_file;
+extern struct socket_info sock_info[]; /* all addresses we listen/send from*/
+extern int sock_no; /* number of addresses/open sockets*/
 extern unsigned short port_no;
 extern unsigned short port_no;
+/*
 extern char port_no_str[];
 extern char port_no_str[];
 extern int port_no_str_len;
 extern int port_no_str_len;
-extern unsigned int maxbuffer;
+*/
+/*
 extern char * names[];
 extern char * names[];
 extern int names_len[];
 extern int names_len[];
 extern struct ip_addr addresses[];
 extern struct ip_addr addresses[];
 extern int addresses_no;
 extern int addresses_no;
-extern struct ip_addr* bind_address;
+*/
+extern struct socket_info* bind_address; /* pointer to the crt. proc. listening address */
+extern int bind_idx; /* same as above but index in the bound[] array */
+extern struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/
+extern struct socket_info* sendipv6; /* same as above for ipv6 */
+
+extern unsigned int maxbuffer;
 extern int children_no;
 extern int children_no;
 extern int dont_fork;
 extern int dont_fork;
 extern int check_via;
 extern int check_via;

+ 21 - 8
ip_addr.h

@@ -9,6 +9,7 @@
 #include <string.h>
 #include <string.h>
 #include <netinet/in.h>
 #include <netinet/in.h>
 #include <netdb.h>
 #include <netdb.h>
+#include "str.h"
 
 
 #ifdef USE_IPV6
 #ifdef USE_IPV6
 	#ifdef FreeBSD			/* freebsd is brain damaged and needs a different
 	#ifdef FreeBSD			/* freebsd is brain damaged and needs a different
@@ -49,6 +50,15 @@ union sockaddr_union{
 };
 };
 
 
 
 
+struct socket_info{
+	int socket;
+	str name; /* name - eg.: foo.bar or 10.0.0.1 */
+	struct ip_addr address; /* ip address */
+	str address_str;        /* ip address converted to string -- optimization*/
+	unsigned short port_no;  /* port number */
+	str port_no_str; /* port number converted to string -- optimization*/
+};
+
 
 
 
 
 /* inits an ip_addr with the addr. info from a hostent structure
 /* inits an ip_addr with the addr. info from a hostent structure
@@ -215,6 +225,7 @@ static inline char* ip_addr2a(struct ip_addr* ip)
 	register unsigned char a,b,c;
 	register unsigned char a,b,c;
 #ifdef USE_IPV6
 #ifdef USE_IPV6
 	register unsigned char d;
 	register unsigned char d;
+	register unsigned short hex4;
 #endif
 #endif
 	int r;
 	int r;
 	#define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
 	#define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
@@ -225,10 +236,11 @@ static inline char* ip_addr2a(struct ip_addr* ip)
 	#ifdef USE_IPV6
 	#ifdef USE_IPV6
 		case AF_INET6:
 		case AF_INET6:
 			for(r=0;r<7;r++){
 			for(r=0;r<7;r++){
-				a=ip->u.addr16[r]>>12;
-				b=(ip->u.addr16[r]>>8)&0xf;
-				c=(ip->u.addr16[r]>>4)&0xf;
-				d=ip->u.addr16[r]&0xf;
+				hex4=ntohs(ip->u.addr16[r]);
+				a=hex4>>12;
+				b=(hex4>>8)&0xf;
+				c=(hex4>>4)&0xf;
+				d=hex4&0xf;
 				if (a){
 				if (a){
 					buff[offset]=HEXDIG(a);
 					buff[offset]=HEXDIG(a);
 					buff[offset+1]=HEXDIG(b);
 					buff[offset+1]=HEXDIG(b);
@@ -254,10 +266,11 @@ static inline char* ip_addr2a(struct ip_addr* ip)
 				}
 				}
 			}
 			}
 			/* last int16*/
 			/* last int16*/
-			a=ip->u.addr16[r]>>12;
-			b=(ip->u.addr16[r]>>8)&0xf;
-			c=(ip->u.addr16[r]>>4)&0xf;
-			d=ip->u.addr16[r]&0xf;
+			hex4=ntohs(ip->u.addr16[r]);
+			a=hex4>>12;
+			b=(hex4>>8)&0xf;
+			c=(hex4>>4)&0xf;
+			d=hex4&0xf;
 			if (a){
 			if (a){
 				buff[offset]=HEXDIG(a);
 				buff[offset]=HEXDIG(a);
 				buff[offset+1]=HEXDIG(b);
 				buff[offset+1]=HEXDIG(b);

+ 123 - 90
main.c

@@ -122,11 +122,13 @@ static char flags[]=
 ;
 ;
 
 
 static char help_msg[]= "\
 static char help_msg[]= "\
-Usage: " NAME " -l address [-l address] [options]\n\
+Usage: " NAME " -l address [-p port] [-l address [-p port]...] [options]\n\
 Options:\n\
 Options:\n\
     -c           Perform loop checks and compute branches\n\
     -c           Perform loop checks and compute branches\n\
     -f file      Configuration file (default " CFG_FILE ")\n\
     -f file      Configuration file (default " CFG_FILE ")\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\
+                 following that do not have a corespponding -p\n\
     -l address   Listen on the specified address (multiple -l mean\n\
     -l address   Listen on the specified address (multiple -l mean\n\
                  listening on more addresses). The default behaviour\n\
                  listening on more addresses). The default behaviour\n\
                  is to listen on the addresses returned by uname(2)\n\
                  is to listen on the addresses returned by uname(2)\n\
@@ -195,9 +197,6 @@ void receive_stdin_loop()
 /* global vars */
 /* global vars */
 
 
 char* cfg_file = 0;
 char* cfg_file = 0;
-unsigned short port_no = 0; /* port on which we listen */
-char port_no_str[MAX_PORT_LEN];
-int port_no_str_len=0;
 unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do
 unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do
 												  not want to exceed durig the
 												  not want to exceed durig the
 												  auto-probing procedure; may 
 												  auto-probing procedure; may 
@@ -217,11 +216,20 @@ char* chroot_dir = 0;
 int uid = 0;
 int uid = 0;
 int gid = 0;
 int gid = 0;
 
 
+#if 0
 char* names[MAX_LISTEN];              /* our names */
 char* names[MAX_LISTEN];              /* our names */
 int names_len[MAX_LISTEN];            /* lengths of the names*/
 int names_len[MAX_LISTEN];            /* lengths of the names*/
 struct ip_addr addresses[MAX_LISTEN]; /* our ips */
 struct ip_addr addresses[MAX_LISTEN]; /* our ips */
 int addresses_no=0;                   /* number of names/ips */
 int addresses_no=0;                   /* number of names/ips */
-struct ip_addr* bind_address;        /* listen address of the crt. process */
+#endif
+struct socket_info sock_info[MAX_LISTEN]; /* all addresses we listen/send from*/
+int sock_no=0; /* number of addresses/open sockets*/
+struct socket_info* bind_address; /* pointer to the crt. proc. listening address */
+int bind_idx; /* same as above but index in the bound[] array */
+struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/
+struct socket_info* sendipv6; /* same as above for ipv6 */
+
+unsigned short port_no=0; /* default port*/
 
 
 /* ipc related globals */
 /* ipc related globals */
 int process_no = 0;
 int process_no = 0;
@@ -246,7 +254,6 @@ extern int yyparse();
 static int is_main=0; /* flag = is this the  "main" process? */
 static int is_main=0; /* flag = is this the  "main" process? */
 
 
 char* pid_file = 0; /* filename as asked by use */
 char* pid_file = 0; /* filename as asked by use */
-char *pid_fn = 0; /* and with port number appended */
 
 
 /* daemon init, return 0 on success, -1 on error */
 /* daemon init, return 0 on success, -1 on error */
 int daemonize(char*  name)
 int daemonize(char*  name)
@@ -255,7 +262,6 @@ int daemonize(char*  name)
 	pid_t pid;
 	pid_t pid;
 	int r, p;
 	int r, p;
 
 
-	int pid_fn_len;
 
 
 	p=-1;
 	p=-1;
 
 
@@ -288,8 +294,7 @@ int daemonize(char*  name)
 	if ((pid=fork())<0){
 	if ((pid=fork())<0){
 		LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
 		LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
 		goto error;
 		goto error;
-	}
-	if (pid!=0){
+	}else if (pid!=0){
 		/* parent process => exit*/
 		/* parent process => exit*/
 		exit(0);
 		exit(0);
 	}
 	}
@@ -301,49 +306,34 @@ int daemonize(char*  name)
 	if ((pid=fork())<0){
 	if ((pid=fork())<0){
 		LOG(L_CRIT, "Cannot  fork:%s\n", strerror(errno));
 		LOG(L_CRIT, "Cannot  fork:%s\n", strerror(errno));
 		goto error;
 		goto error;
-	}
-	if (pid!=0){
+	}else if (pid!=0){
 		/*parent process => exit */
 		/*parent process => exit */
 		exit(0);
 		exit(0);
 	}
 	}
 
 
 	/* added by noh: create a pid file for the main process */
 	/* added by noh: create a pid file for the main process */
 	if (pid_file!=0){
 	if (pid_file!=0){
-
-		/* added port number; -jiri */
-		pid_fn_len = strlen(pid_file) + 5 /* long port number */ 
-			+ 1 /* dot */ + 1 /* ZT */ ;
-		pid_fn = malloc( pid_fn_len );
-		if (!pid_fn) {
-			LOG(L_ERR, "ERROR: There is really no memory for ser\n");
-			goto error;
-		}
-		if (snprintf(pid_fn, pid_fn_len, "%s.%d", pid_file, port_no )==-1) {
-			LOG(L_ERR, "ERROR: pidfile printig failed -- perhaps too high port?\n");
-			goto error;
-		}
 		
 		
-			
-		if ((pid_stream=fopen(pid_fn, "r"))!=NULL){
+		if ((pid_stream=fopen(pid_file, "r"))!=NULL){
 			fscanf(pid_stream, "%d", &p);
 			fscanf(pid_stream, "%d", &p);
 			fclose(pid_stream);
 			fclose(pid_stream);
 			if (p==-1){
 			if (p==-1){
 				LOG(L_CRIT, "pid file %s exists, but doesn't contain a valid"
 				LOG(L_CRIT, "pid file %s exists, but doesn't contain a valid"
-					" pid number\n", pid_fn);
+					" pid number\n", pid_file);
 				goto error;
 				goto error;
 			}
 			}
 			if (kill((pid_t)p, 0)==0 || errno==EPERM){
 			if (kill((pid_t)p, 0)==0 || errno==EPERM){
 				LOG(L_CRIT, "running process found in the pid file %s\n",
 				LOG(L_CRIT, "running process found in the pid file %s\n",
-					pid_fn);
+					pid_file);
 				goto error;
 				goto error;
 			}else{
 			}else{
 				LOG(L_WARN, "pid file contains old pid, replacing pid\n");
 				LOG(L_WARN, "pid file contains old pid, replacing pid\n");
 			}
 			}
 		}
 		}
 		pid=getpid();
 		pid=getpid();
-		if ((pid_stream=fopen(pid_fn, "w"))==NULL){
+		if ((pid_stream=fopen(pid_file, "w"))==NULL){
 			LOG(L_WARN, "unable to create pid file %s: %s\n", 
 			LOG(L_WARN, "unable to create pid file %s: %s\n", 
-				pid_fn, strerror(errno));
+				pid_file, strerror(errno));
 			goto error;
 			goto error;
 		}else{
 		}else{
 			fprintf(pid_stream, "%i\n", (int)pid);
 			fprintf(pid_stream, "%i\n", (int)pid);
@@ -378,14 +368,19 @@ int main_loop()
 #ifdef STATS
 #ifdef STATS
 		setstats( 0 );
 		setstats( 0 );
 #endif
 #endif
-		/* only one address */
-		if (udp_init(&addresses[0],port_no)==-1) goto error;
+		/* only one address, we ignore all the others */
+		if (udp_init(&sock_info[0])==-1) goto error;
+		bind_address=&sock_info[0];
+		bind_idx=0;
+		if (sock_no>1){
+			LOG(L_WARN, "WARNING: using only the first listen address (no fork)\n");
+		}
 
 
 		/* we need another process to act as the timer*/
 		/* we need another process to act as the timer*/
 		if (timer_list){
 		if (timer_list){
 				process_no++;
 				process_no++;
 				if ((pid=fork())<0){
 				if ((pid=fork())<0){
-					LOG(L_CRIT,  "ERRROR: main_loop: Cannot fork\n");
+					LOG(L_CRIT,  "ERROR: main_loop: Cannot fork\n");
 					goto error;
 					goto error;
 				}
 				}
 				
 				
@@ -418,17 +413,28 @@ int main_loop()
 		
 		
 		return udp_rcv_loop();
 		return udp_rcv_loop();
 	}else{
 	}else{
-		for(r=0;r<addresses_no;r++){
+		for(r=0;r<sock_no;r++){
 			/* create the listening socket (for each address)*/
 			/* create the listening socket (for each address)*/
-			if (udp_init(&addresses[r], port_no)==-1) goto error;
+			if (udp_init(&sock_info[r])==-1) goto error;
+			/* get first ipv4/ipv6 socket*/
+			if ((sendipv4==0)&&(sock_info[r].address.af==AF_INET))
+				sendipv4=&sock_info[r];
+	#ifdef USE_IPV6
+			if((sendipv6==0)&&(sock_info[r].address.af==AF_INET6))
+				sendipv6=&sock_info[r];
+	#endif
+			/* all procs should have access to all the sockets (for sending)
+			 * so we open all first*/
+		}
+		for(r=0; r<sock_no;r++){
 			for(i=0;i<children_no;i++){
 			for(i=0;i<children_no;i++){
 				if ((pid=fork())<0){
 				if ((pid=fork())<0){
 					LOG(L_CRIT,  "main_loop: Cannot fork\n");
 					LOG(L_CRIT,  "main_loop: Cannot fork\n");
 					goto error;
 					goto error;
-				}
-				if (pid==0){
+				}else if (pid==0){
 					     /* child */
 					     /* child */
-
+					bind_address=&sock_info[r]; /* shortcut */
+					bind_idx=r;
 					if (init_child(i) < 0) {
 					if (init_child(i) < 0) {
 						LOG(L_ERR, "init_child failed\n");
 						LOG(L_ERR, "init_child failed\n");
 						goto error;
 						goto error;
@@ -452,6 +458,9 @@ int main_loop()
 	pids[process_no]=getpid();
 	pids[process_no]=getpid();
 	process_bit = 0;
 	process_bit = 0;
 	is_main=1;
 	is_main=1;
+	bind_address=&sock_info[0]; /* main proc -> it shoudln't send anything, if it does */
+	bind_idx=0;					/*   it will use the first address */
+
 	if (timer_list){
 	if (timer_list){
 		for(;;){
 		for(;;){
 			/* debug:  instead of doing something usefull */
 			/* debug:  instead of doing something usefull */
@@ -461,7 +470,7 @@ int main_loop()
 			timer_ticker();
 			timer_ticker();
 		}
 		}
 	}else{
 	}else{
-		for(;;) sleep(LONG_SLEEP);
+		for(;;) pause(); 
 	}
 	}
 	
 	
 	/*return 0; */
 	/*return 0; */
@@ -474,8 +483,7 @@ int main_loop()
 /* added by jku; allows for regular exit on a specific signal;
 /* added by jku; allows for regular exit on a specific signal;
    good for profiling which only works if exited regularly and
    good for profiling which only works if exited regularly and
    not by default signal handlers
    not by default signal handlers
-*/	
-
+*/
 static void sig_usr(int signo)
 static void sig_usr(int signo)
 {
 {
 	pid_t	chld;
 	pid_t	chld;
@@ -508,6 +516,8 @@ static void sig_usr(int signo)
 		}
 		}
 #endif
 #endif
 		dprint("Thank you for flying " NAME "\n");
 		dprint("Thank you for flying " NAME "\n");
+		/* kill children also*/
+		kill(0, SIGTERM);
 		exit(0);
 		exit(0);
 	} else if (signo==SIGTERM) { /* exit gracefully as daemon */
 	} else if (signo==SIGTERM) { /* exit gracefully as daemon */
 		DPrint("TERM received, program terminates\n");
 		DPrint("TERM received, program terminates\n");
@@ -515,11 +525,11 @@ static void sig_usr(int signo)
 #ifdef STATS
 #ifdef STATS
 			dump_all_statistic();
 			dump_all_statistic();
 #endif
 #endif
-			if (pid_fn) {
-				unlink(pid_fn);
-				free(pid_fn);
+			if (pid_file) {
+				unlink(pid_file);
 			}
 			}
 		}
 		}
+		kill(0, SIGTERM);
 		exit(0);
 		exit(0);
 	} else if (signo==SIGUSR1) { /* statistic */
 	} else if (signo==SIGUSR1) { /* statistic */
 #ifdef STATS
 #ifdef STATS
@@ -549,6 +559,9 @@ static void sig_usr(int signo)
 				LOG(L_INFO, "child process %d stopped by a signal %d\n",
 				LOG(L_INFO, "child process %d stopped by a signal %d\n",
 					chld, WSTOPSIG(chld_status));
 					chld, WSTOPSIG(chld_status));
 		}
 		}
+		/* exit */
+		kill(0, SIGTERM);
+		exit(0);
 	}
 	}
 }
 }
 
 
@@ -564,6 +577,8 @@ int main(int argc, char** argv)
 	char *tmp;
 	char *tmp;
 	struct utsname myname;
 	struct utsname myname;
 	char *options;
 	char *options;
+	char port_no_str[MAX_PORT_LEN];
+	int port_no_str_len=0;
 
 
 	/* added by jku: add exit handler */
 	/* added by jku: add exit handler */
 	if (signal(SIGINT, sig_usr) == SIG_ERR ) {
 	if (signal(SIGINT, sig_usr) == SIG_ERR ) {
@@ -589,9 +604,6 @@ int main(int argc, char** argv)
 		goto error;
 		goto error;
 	}
 	}
 
 
-	//memtest();
-	//hashtest();
-
 	/* process command line (get port no, cfg. file path etc) */
 	/* process command line (get port no, cfg. file path etc) */
 	opterr=0;
 	opterr=0;
 	options=
 	options=
@@ -616,34 +628,43 @@ int main(int argc, char** argv)
 						fprintf(stderr, "bad port number: -p %s\n", optarg);
 						fprintf(stderr, "bad port number: -p %s\n", optarg);
 						goto error;
 						goto error;
 					}
 					}
+					if (sock_no>0) sock_info[sock_no-1].port_no=port_no;
 					break;
 					break;
 
 
 			case 'm':
 			case 'm':
 					shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
 					shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
 					if (tmp &&(*tmp)){
 					if (tmp &&(*tmp)){
-						fprintf(stderr, "bad shmem size number: -m %s\n", optarg);
+						fprintf(stderr, "bad shmem size number: -m %s\n",
+										optarg);
 						goto error;
 						goto error;
 					};
 					};
-					LOG(L_INFO, "ser: shared memory allocated: %d MByte\n", shm_mem_size );
+					LOG(L_INFO, "ser: shared memory allocated: %d MByte\n",
+									shm_mem_size );
 					break;
 					break;
 
 
 			case 'b':
 			case 'b':
 					maxbuffer=strtol(optarg, &tmp, 10);
 					maxbuffer=strtol(optarg, &tmp, 10);
 					if (tmp &&(*tmp)){
 					if (tmp &&(*tmp)){
-                                                fprintf(stderr, "bad max buffer size number: -p %s\n", optarg);
-                                                goto error;
-                                        }
-                                        break;
+						fprintf(stderr, "bad max buffer size number: -p %s\n",
+											optarg);
+						goto error;
+					}
+					break;
 			case 'l':
 			case 'l':
 					/* add a new addr. to our address list */
 					/* add a new addr. to our address list */
-					if (addresses_no < MAX_LISTEN){
-						names[addresses_no]=(char*)malloc(strlen(optarg)+1);
-						if (names[addresses_no]==0){
+					if (sock_no < MAX_LISTEN){
+						sock_info[sock_no].name.s=
+										(char*)malloc(strlen(optarg)+1);
+						if (sock_info[sock_no].name.s==0){
 							fprintf(stderr, "Out of memory.\n");
 							fprintf(stderr, "Out of memory.\n");
 							goto error;
 							goto error;
 						}
 						}
-						strncpy(names[addresses_no], optarg, strlen(optarg)+1);
-						addresses_no++;
+						strncpy(sock_info[sock_no].name.s, optarg,
+												strlen(optarg)+1);
+						sock_info[sock_no].name.len=strlen(optarg);
+						/* set default port */
+						sock_info[sock_no].port_no=port_no;
+						sock_no++;
 					}else{
 					}else{
 						fprintf(stderr, 
 						fprintf(stderr, 
 									"Too many addresses (max. %d).\n",
 									"Too many addresses (max. %d).\n",
@@ -654,7 +675,8 @@ int main(int argc, char** argv)
 			case 'n':
 			case 'n':
 					children_no=strtol(optarg, &tmp, 10);
 					children_no=strtol(optarg, &tmp, 10);
 					if ((tmp==0) ||(*tmp)){
 					if ((tmp==0) ||(*tmp)){
-						fprintf(stderr, "bad process number: -n %s\n", optarg);
+						fprintf(stderr, "bad process number: -n %s\n",
+									optarg);
 						goto error;
 						goto error;
 					}
 					}
 					break;
 					break;
@@ -784,16 +806,6 @@ int main(int argc, char** argv)
 
 
 	/* fix parameters */
 	/* fix parameters */
 	if (port_no<=0) port_no=SIP_PORT;
 	if (port_no<=0) port_no=SIP_PORT;
-	port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d", 
-				(unsigned short) port_no);
-	if (port_no_str_len<0){
-		fprintf(stderr, "ERROR: bad port number: %d\n", port_no);
-		goto error;
-	}
-	/* on some system snprintf return really strange things if it does not 
-	   have  enough space */
-	port_no_str_len=
-				(port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN;
 
 
 	
 	
 	if (children_no<=0) children_no=CHILD_NO;
 	if (children_no<=0) children_no=CHILD_NO;
@@ -817,42 +829,63 @@ int main(int argc, char** argv)
 	}
 	}
 	memset(pids, 0, sizeof(int)*(children_no+1));
 	memset(pids, 0, sizeof(int)*(children_no+1));
 
 
-	if (addresses_no==0) {
+	if (sock_no==0) {
 		/* get our address, only the first one */
 		/* get our address, only the first one */
 		if (uname (&myname) <0){
 		if (uname (&myname) <0){
 			fprintf(stderr, "cannot determine hostname, try -l address\n");
 			fprintf(stderr, "cannot determine hostname, try -l address\n");
 			goto error;
 			goto error;
 		}
 		}
-		names[addresses_no]=(char*)malloc(strlen(myname.nodename)+1);
-		if (names[addresses_no]==0){
+		sock_info[sock_no].name.s=(char*)malloc(strlen(myname.nodename)+1);
+		if (sock_info[sock_no].name.s==0){
 			fprintf(stderr, "Out of memory.\n");
 			fprintf(stderr, "Out of memory.\n");
 			goto error;
 			goto error;
 		}
 		}
-		strncpy(names[addresses_no], myname.nodename,
+		strncpy(sock_info[sock_no].name.s, myname.nodename,
 				strlen(myname.nodename)+1);
 				strlen(myname.nodename)+1);
-		addresses_no++;
+		sock_info[sock_no].name.len=strlen(myname.nodename);
+		sock_no++;
 	}
 	}
 
 
-	/*get name lens*/
-	for(r=0; r<addresses_no; r++){
-		names_len[r]=strlen(names[r]);
-	}
-
-	
-	/* get ips */
+	/* get ips & fill the port numbers*/
 	printf("Listening on ");
 	printf("Listening on ");
-	for (r=0; r<addresses_no;r++){
-		he=resolvehost(names[r]);
+	for (r=0; r<sock_no;r++){
+		he=resolvehost(sock_info[r].name.s);
 		if (he==0){
 		if (he==0){
-			DPrint("ERROR: could not resolve %s\n", names[r]);
+			DPrint("ERROR: could not resolve %s\n", sock_info[r].name.s);
 			goto error;
 			goto error;
 		}
 		}
-		hostent2ip_addr(&addresses[r], he, 0); /*convert to ip_addr format*/
-		/*memcpy(&addresses[r], he->h_addr_list[0], sizeof(int));*/
-		/*addresses[r]=*((long*)he->h_addr_list[0]);*/
-		printf("%s [",names[r]);
-		stdout_print_ip(&addresses[r]);
-		printf("]:%d\n", (unsigned short)port_no);
+		hostent2ip_addr(&sock_info[r].address, he, 0); /*convert to ip_addr format*/
+		tmp=ip_addr2a(&sock_info[r].address);
+		sock_info[r].address_str.s=(char*)malloc(strlen(tmp)+1);
+		if (sock_info[r].address_str.s==0){
+			fprintf(stderr, "Out of memory.\n");
+			goto error;
+		}
+		strncpy(sock_info[r].address_str.s, tmp, strlen(tmp)+1);
+		sock_info[r].address_str.len=strlen(tmp);
+		
+		if (sock_info[r].port_no==0) sock_info[r].port_no=port_no;
+		port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d", 
+									(unsigned short) sock_info[r].port_no);
+		if (port_no_str_len<0){
+			fprintf(stderr, "ERROR: bad port number: %d\n", 
+						sock_info[r].port_no);
+			goto error;
+		}
+		/* on some system snprintf return really strange things if it does not 
+			have  enough space */
+		port_no_str_len=
+				(port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN;
+		sock_info[r].port_no_str.s=(char*)malloc(strlen(port_no_str)+1);
+		if (sock_info[r].port_no_str.s==0){
+			fprintf(stderr, "Out of memory.\n");
+			goto error;
+		}
+		strncpy(sock_info[r].port_no_str.s, port_no_str, strlen(port_no_str)+1);
+		sock_info[r].port_no_str.len=strlen(port_no_str);
+		
+		printf("%s [%s]:%s\n",sock_info[r].name.s, sock_info[r].address_str.s,
+				sock_info[r].port_no_str.s);
 	}
 	}
 
 
 #ifdef STATS
 #ifdef STATS

+ 26 - 10
msg_translator.c

@@ -89,30 +89,45 @@ int check_address(struct ip_addr* ip, char *name, int resolver)
 
 
 
 
 
 
-char* via_builder( struct sip_msg *msg , unsigned int *len )
+char* via_builder( struct sip_msg *msg , unsigned int *len, 
+					struct socket_info* send_sock )
 {
 {
-	unsigned int  via_len, branch_len;
+	unsigned int  via_len, branch_len, extra_len;;
 	char               *line_buf;
 	char               *line_buf;
 
 
 	line_buf=0;
 	line_buf=0;
+	extra_len=0;
 
 
 	line_buf=pkg_malloc(sizeof(char)*MAX_VIA_LINE_SIZE);
 	line_buf=pkg_malloc(sizeof(char)*MAX_VIA_LINE_SIZE);
 	if (line_buf==0){
 	if (line_buf==0){
 		LOG(L_ERR, "ERROR: via_builder: out of memory\n");
 		LOG(L_ERR, "ERROR: via_builder: out of memory\n");
 		goto error;
 		goto error;
 	}
 	}
-	via_len=MY_VIA_LEN+names_len[0]; /* space included in MY_VIA*/
+	via_len=MY_VIA_LEN+send_sock->address_str.len; /*space included in MY_VIA*/
+#ifdef USE_IPV6
+	if (send_sock->address.af==AF_INET6) via_len+=2; /* [ ]*/
+#endif
 
 
 	/* jku: if we compute branches using MD5 it will take 32 bytes */
 	/* jku: if we compute branches using MD5 it will take 32 bytes */
 	branch_len= (loop_checks ? MY_BRANCH_LEN : MY_BRANCH_LEN -1 + MD5_LEN)+
 	branch_len= (loop_checks ? MY_BRANCH_LEN : MY_BRANCH_LEN -1 + MD5_LEN)+
 					msg->add_to_branch_len;
 					msg->add_to_branch_len;
 
 
-	if ((via_len+port_no_str_len+branch_len+CRLF_LEN)<MAX_VIA_LINE_SIZE){
+	if ((via_len+send_sock->port_no_str.len+branch_len
+								+CRLF_LEN)<MAX_VIA_LINE_SIZE){
 		memcpy(line_buf, MY_VIA, MY_VIA_LEN);
 		memcpy(line_buf, MY_VIA, MY_VIA_LEN);
-		memcpy(line_buf+MY_VIA_LEN, names[0], names_len[0]);
-		if (port_no!=SIP_PORT){
-			memcpy(line_buf+via_len, port_no_str, port_no_str_len);
-			via_len+=port_no_str_len;
+#ifdef USE_IPV6
+	if (send_sock->address.af==AF_INET6) {
+		line_buf[MY_VIA_LEN]='[';
+		line_buf[MY_VIA_LEN+1+send_sock->address_str.len]=']';
+		extra_len=1;
+	}
+#endif
+		memcpy(line_buf+MY_VIA_LEN+extra_len, send_sock->address_str.s,
+									send_sock->address_str.len);
+		if (send_sock->port_no!=SIP_PORT){
+			memcpy(line_buf+via_len, send_sock->port_no_str.s,
+									 send_sock->port_no_str.len);
+			via_len+=send_sock->port_no_str.len;
 		}
 		}
 
 
 		/* jku: branch parameter */
 		/* jku: branch parameter */
@@ -222,7 +237,8 @@ done:
 
 
 
 
 char * build_req_buf_from_sip_req( struct sip_msg* msg,
 char * build_req_buf_from_sip_req( struct sip_msg* msg,
-								unsigned int *returned_len)
+								unsigned int *returned_len,
+								struct socket_info* send_sock)
 {
 {
 	unsigned int len, new_len, received_len, uri_len, via_len, extra_len;
 	unsigned int len, new_len, received_len, uri_len, via_len, extra_len;
 	char* line_buf;
 	char* line_buf;
@@ -249,7 +265,7 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
 	extra_len=0;
 	extra_len=0;
 
 
 
 
-	line_buf = via_builder( msg, &via_len );
+	line_buf = via_builder( msg, &via_len, send_sock);
 	if (!line_buf){
 	if (!line_buf){
 		LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: no via received!\n");
 		LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: no via received!\n");
 		goto error1;
 		goto error1;

+ 3 - 2
msg_translator.h

@@ -9,9 +9,10 @@
 #define MY_HF_SEP_LEN 2
 #define MY_HF_SEP_LEN 2
 
 
 #include "parser/msg_parser.h"
 #include "parser/msg_parser.h"
+#include "ip_addr.h"
 
 
 char * build_req_buf_from_sip_req (	struct sip_msg* msg, 
 char * build_req_buf_from_sip_req (	struct sip_msg* msg, 
-				unsigned int *returned_len);
+				unsigned int *returned_len, struct socket_info* send_sock);
 
 
 char * build_res_buf_from_sip_res(	struct sip_msg* msg,
 char * build_res_buf_from_sip_res(	struct sip_msg* msg,
 				unsigned int *returned_len);
 				unsigned int *returned_len);
@@ -23,7 +24,7 @@ char * build_res_buf_from_sip_req(	unsigned int code ,
 				struct sip_msg* msg,
 				struct sip_msg* msg,
 				unsigned int *returned_len);
 				unsigned int *returned_len);
 char* via_builder( 			struct sip_msg *msg ,
 char* via_builder( 			struct sip_msg *msg ,
-				unsigned int *len );
+				unsigned int *len, struct socket_info* send_sock);
 
 
 
 
 #endif
 #endif

+ 1 - 1
receive.c

@@ -43,7 +43,7 @@ int receive_msg(char* buf, unsigned int len, union sockaddr_union* src_su)
 	msg->buf=buf;
 	msg->buf=buf;
 	msg->len=len;
 	msg->len=len;
 	su2ip_addr(&msg->src_ip, src_su);
 	su2ip_addr(&msg->src_ip, src_su);
-	msg->dst_ip=*bind_address; /* won't work if listening on 0.0.0.0 */
+	msg->dst_ip=bind_address->address; /* won't work if listening on 0.0.0.0 */
 	msg->id=msg_no;
 	msg->id=msg_no;
 	/* make a copy of the message */
 	/* make a copy of the message */
 	msg->orig=(char*) pkg_malloc(len+1);
 	msg->orig=(char*) pkg_malloc(len+1);

+ 23 - 16
udp_server.c

@@ -23,7 +23,6 @@
 #include <mem/dmalloc.h>
 #include <mem/dmalloc.h>
 #endif
 #endif
 
 
-int udp_sock;
 
 
 int probe_max_receive_buffer( int udp_sock )
 int probe_max_receive_buffer( int udp_sock )
 {
 {
@@ -107,7 +106,7 @@ int probe_max_receive_buffer( int udp_sock )
 	/* EoJKU */
 	/* EoJKU */
 }
 }
 
 
-int udp_init(struct ip_addr* ip, unsigned short port)
+int udp_init(struct socket_info* sock_info)
 {
 {
 	union sockaddr_union* addr;
 	union sockaddr_union* addr;
 	int optval;
 	int optval;
@@ -119,7 +118,7 @@ int udp_init(struct ip_addr* ip, unsigned short port)
 		goto error;
 		goto error;
 	}
 	}
 	
 	
-	if (init_su(addr, ip, htons(port))<0){
+	if (init_su(addr, &sock_info->address, htons(sock_info->port_no))<0){
 		LOG(L_ERR, "ERROR: udp_init: could not init sockaddr_union\n");
 		LOG(L_ERR, "ERROR: udp_init: could not init sockaddr_union\n");
 		goto error;
 		goto error;
 	}
 	}
@@ -130,25 +129,33 @@ int udp_init(struct ip_addr* ip, unsigned short port)
 	*/
 	*/
 
 
 	
 	
-	udp_sock = socket(AF2PF(addr->s.sa_family), SOCK_DGRAM, 0);
-	if (udp_sock==-1){
+	sock_info->socket = socket(AF2PF(addr->s.sa_family), SOCK_DGRAM, 0);
+	if (sock_info->socket==-1){
 		LOG(L_ERR, "ERROR: udp_init: socket: %s\n", strerror(errno));
 		LOG(L_ERR, "ERROR: udp_init: socket: %s\n", strerror(errno));
 		goto error;
 		goto error;
 	}
 	}
 	/* set sock opts? */
 	/* set sock opts? */
 	optval=1;
 	optval=1;
-	if (setsockopt(udp_sock, SOL_SOCKET, SO_REUSEADDR ,
+	if (setsockopt(sock_info->socket, SOL_SOCKET, SO_REUSEADDR ,
 					(void*)&optval, sizeof(optval)) ==-1)
 					(void*)&optval, sizeof(optval)) ==-1)
 	{
 	{
 		LOG(L_ERR, "ERROR: udp_init: setsockopt: %s\n", strerror(errno));
 		LOG(L_ERR, "ERROR: udp_init: setsockopt: %s\n", strerror(errno));
 		goto error;
 		goto error;
 	}
 	}
 
 
-	if ( probe_max_receive_buffer(udp_sock)==-1) goto error;
-	bind_address=ip;
-
-	if (bind(udp_sock,  &addr->s, sizeof(union sockaddr_union))==-1){
-		LOG(L_ERR, "ERROR: udp_init: bind: %s\n", strerror(errno));
+	if ( probe_max_receive_buffer(sock_info->socket)==-1) goto error;
+
+	if (bind(sock_info->socket,  &addr->s, sizeof(union sockaddr_union))==-1){
+		LOG(L_ERR, "ERROR: udp_init: bind(%x, %p, %d) on %s: %s\n",
+				sock_info->socket, &addr->s, 
+				sizeof(union sockaddr_union),
+				sock_info->address_str.s,
+				strerror(errno));
+	#ifdef USE_IPV6
+		if (addr->s.sa_family==AF_INET6)
+			LOG(L_ERR, "ERROR: udp_init: might be caused by using a link "
+					" local address, try site local or global\n");
+	#endif
 		goto error;
 		goto error;
 	}
 	}
 
 
@@ -191,8 +198,8 @@ int udp_rcv_loop()
 		}
 		}
 #endif
 #endif
 		fromlen=sizeof(union sockaddr_union);
 		fromlen=sizeof(union sockaddr_union);
-		len=recvfrom(udp_sock, buf, BUF_SIZE, 0, &from->s,
-						&fromlen);
+		len=recvfrom(bind_address->socket, buf, BUF_SIZE, 0, &from->s,
+											&fromlen);
 		if (len==-1){
 		if (len==-1){
 			LOG(L_ERR, "ERROR: udp_rcv_loop:recvfrom:[%d] %s\n",
 			LOG(L_ERR, "ERROR: udp_rcv_loop:recvfrom:[%d] %s\n",
 						errno, strerror(errno));
 						errno, strerror(errno));
@@ -222,15 +229,15 @@ error:
 
 
 
 
 /* which socket to use? main socket or new one? */
 /* which socket to use? main socket or new one? */
-int udp_send(char *buf, unsigned len, union sockaddr_union*  to,
-				unsigned tolen)
+int udp_send(struct socket_info *source, char *buf, unsigned len,
+				union sockaddr_union*  to, unsigned tolen)
 {
 {
 
 
 	int n;
 	int n;
 
 
 
 
 again:
 again:
-	n=sendto(udp_sock, buf, len, 0, &to->s, tolen);
+	n=sendto(source->socket, buf, len, 0, &to->s, tolen);
 	if (n==-1){
 	if (n==-1){
 		LOG(L_ERR, "ERROR: udp_send: sendto(sock,%p,%d,0,%p,%d): %s(%d)\n",
 		LOG(L_ERR, "ERROR: udp_send: sendto(sock,%p,%d,0,%p,%d): %s(%d)\n",
 				buf,len,to,tolen,
 				buf,len,to,tolen,

+ 3 - 4
udp_server.h

@@ -12,11 +12,10 @@
 #define MAX_RECV_BUFFER_SIZE	256*1024
 #define MAX_RECV_BUFFER_SIZE	256*1024
 #define BUFFER_INCREMENT	2048
 #define BUFFER_INCREMENT	2048
 
 
-extern int udp_sock;
 
 
-int udp_init(struct ip_addr* ip, unsigned short port);
-int udp_send(char *buf, unsigned len, union sockaddr_union*  to,
-				unsigned tolen);
+int udp_init(struct socket_info* si);
+int udp_send(struct socket_info* source,char *buf, unsigned len,
+				union sockaddr_union*  to, unsigned tolen);
 int udp_rcv_loop();
 int udp_rcv_loop();