Procházet zdrojové kódy

- changed tcp to support port aliases (major changes)
- added via alias parameter parsing
- added script var. tcp_accept_aliases= yes|no (honour or not via alias param)
- added script. cmd. force_tcp_alias( <void>|port_no)
[for more info read the NEWS file]

Andrei Pelinescu-Onciul před 22 roky
rodič
revize
59653eb856
17 změnil soubory, kde provedl 344 přidání a 66 odebrání
  1. 1 1
      Makefile.defs
  2. 26 0
      NEWS
  3. 12 9
      TODO
  4. 28 0
      action.c
  5. 7 0
      cfg.lex
  6. 44 1
      cfg.y
  7. 1 1
      forward.c
  8. 1 0
      globals.h
  9. 58 11
      parser/parse_via.c
  10. 4 2
      parser/parse_via.h
  11. 18 0
      receive.c
  12. 3 0
      route_struct.c
  13. 3 1
      route_struct.h
  14. 23 7
      tcp_conn.h
  15. 111 32
      tcp_main.c
  16. 1 1
      tcp_server.h
  17. 3 0
      test/test.cfg

+ 1 - 1
Makefile.defs

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

+ 26 - 0
NEWS

@@ -34,6 +34,14 @@ core:
        This is the default value, if empty (default) the socket
        port will be used.
        Same warnings as above.
+   tcp_accept_aliases= yes|no
+       if a message received over a tcp connection has "alias" in its via
+       a new tcp alias port will be created for the connection the message
+       came from (the alias port will be set to the via one).
+       Based on draft-ietf-sip-connect-reuse-00.txt, but using only the port
+       (host aliases are too dangerous IMHO, involve extra DNS
+        lookups and the need for them is questionable)
+       See force_tcp_alias for more details.
  - new script commands:
     set_advertised_address(ip|string)
        same as advertised_address but it affects only the current message:
@@ -42,6 +50,24 @@ core:
     set_advertised_port(no)
        same as advertised_port but it affects only the current
        message; see set_advertised_address & s/address/port/g
+   force_tcp_alias()
+   force_tcp_alias(port)
+       adds a tcp port alias for the current connection (if tcp).
+       Usefull if you want to send all the trafic to port_alias through
+       the same connection this request came from [it could help 
+       for firewall or nat traversal].
+       With no parameters adds the port from the message via as the alias.
+       When the "aliased" connection is closed (e.g. it's idle for too
+       much time), all the port aliases are removed.
+       Note: by default ser closes idle connection after 3 minutes (stable)
+       or 1 minute (unstable) so to take full advantage of tcp aliases for
+       things like firewall and nat traversal, redefine TCP_CON_*TIMEOUT
+       in tcp_conn.h and recompile. Also right now there can be maximum
+       3 port aliases to a connection (you shouldn't need more than one).
+       To change this redefine TCP_CON_MAX_ALIASES in the same file
+       (set it to you desired value + 1; 1 is needed for the real port).
+
+
 
 
 

+ 12 - 9
TODO

@@ -2,13 +2,14 @@ $Id$
 
 ( - todo, x - done)
 
-- fix aliases for tls_port (add_them?)
+- nathelper: extract_body broken-> uses content_length value form the 
+ message instead of recalculating it + duplicate code for get_body()
 - fix check_sel_op -- add proto for uri proto checks
-- add via alias for tcp port & infinite tcp conn life
+- add setting for infinite tcp conn life?
 
 - fix 2 different fixups for diff. no of parameter
- (add no of params ot struct action?) -- linked to var. no. of params
-- alias support fot tcp/tls port numbers
+ (add no of params to struct action?) -- linked to var. no. of params
+x alias support fot tcp/tls port numbers
 - warning builder set_advertised address support
 - grep parse_uri & replace with parse_sip_msg_uri (e.g do_action!)
 x update AUTHORS, debian/copyright, ser.8, ser.cfg.5 from stable
@@ -17,14 +18,16 @@ x update all package specs from stable
 - add BUG checks for  fd > 0 && fd <= maxfd to all selects?
 x tcp_main_loop: BUG cases should "conitnue;"
 x change len_gt into and expr (e.g msg:len).
-- sipit: uri == myself doesn't match tls port = 5061
-- sipit: fix check_self & *_alias to work with tcp & tls
+x sipit: uri == myself doesn't match tls port = 5061 
+  -- updated: new socket_info list code should fix it
+x sipit: fix check_self & *_alias to work with tcp & tls
+  -- updated: new socket_info list code should fix it
 x sipit: fix ipv6 references in check_self
 x regex subst on uris?
 x port receive.c pre_script_cb fix from stable
-- extend alias to include port numbers :
+x extend alias to include port numbers :
     something like alias= foo1.bar:5080 foo2.bar foo3.bar:*
-- extend listen and alias to include port numbers and protocol:
+x extend listen and alias to include port numbers and protocol:
        tcp foo.bar:5063, udp foo.bar:5062, foo2.bar
 x added set_advertised_{address,port} -- was: add force_via, force_srcip a.s.o
 (the advertised addresses should be overwritable from the script).
@@ -123,7 +126,7 @@ x man page
 - autoconf scripts
 x Debian package build files
 x the same for rpm
-- the same for FreeBSD and Slackware
+x the same for *BSD
 
 
 x jku: branch hash computation over canonical values

+ 28 - 0
action.c

@@ -35,6 +35,7 @@
  *  2003-04-12  FORCE_RPORT_T added (andrei)
  *  2003-04-22  strip_tail added (jiri)
  *  2003-10-02  added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
+ *  2003-10-29  added FORCE_TCP_ALIAS_T (andrei)
  */
 
 
@@ -629,6 +630,33 @@ int do_action(struct action* a, struct sip_msg* msg)
 			msg->set_global_port=*((str*)a->p1.data);
 			ret=1; /* continue processing */
 			break;
+#ifdef USE_TCP
+		case FORCE_TCP_ALIAS_T:
+			if ( msg->rcv.proto==PROTO_TCP
+#ifdef USE_TLS
+					|| msg->rcv.proto==PROTO_TLS
+#endif
+			   ){
+				
+				if (a->p1_type==NOSUBTYPE)	port=msg->via1->port;
+				else if (a->p1_type==NUMBER_ST) port=(int)a->p1.number;
+				else{
+					LOG(L_CRIT, "BUG: do_action: bad force_tcp_alias"
+							" port type %d\n", a->p1_type);
+					ret=E_BUG;
+					break;
+				}
+						
+				if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
+									msg->rcv.proto)!=0){
+					LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
+					ret=E_UNSPEC;
+					break;
+				}
+			}
+#endif
+			ret=1; /* continue processing */
+			break;
 		default:
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
 	}

+ 7 - 0
cfg.lex

@@ -42,6 +42,7 @@
  *  2003-10-07  added hex and octal numbers support (andrei)
  *  2003-10-10  replaced len_gt w/ msg:len (andrei)
  *  2003-10-13  added fifo_dir (andrei)
+ *  2003-10-28  added tcp_accept_aliases (andrei)
  */
 
 
@@ -93,6 +94,7 @@ ROUTE_FAILURE failure_route
 ROUTE_ONREPLY onreply_route
 EXEC	exec
 FORCE_RPORT		"force_rport"|"add_rport"
+FORCE_TCP_ALIAS		"force_tcp_alias"|"add_tcp_alias"
 SETFLAG		setflag
 RESETFLAG	resetflag
 ISFLAGSET	isflagset
@@ -176,6 +178,7 @@ WDIR		"workdir"|"wdir"
 MHOMED		mhomed
 DISABLE_TCP		"disable_tcp"
 TCP_CHILDREN	"tcp_children"
+TCP_ACCEPT_ALIASES	"tcp_accept_aliases"
 DISABLE_TLS		"disable_tls"
 TLSLOG			"tlslog"|"tls_log"
 TLS_PORT_NO		"tls_port_no"
@@ -275,6 +278,8 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{APPEND_BRANCH}	{ count(); yylval.strval=yytext; 
 								return APPEND_BRANCH; }
 <INITIAL>{FORCE_RPORT}	{ count(); yylval.strval=yytext; return FORCE_RPORT; }
+<INITIAL>{FORCE_TCP_ALIAS}	{ count(); yylval.strval=yytext;
+								return FORCE_TCP_ALIAS; }
 	
 <INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
 <INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
@@ -321,6 +326,8 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{MHOMED}	{ count(); yylval.strval=yytext; return MHOMED; }
 <INITIAL>{DISABLE_TCP}	{ count(); yylval.strval=yytext; return DISABLE_TCP; }
 <INITIAL>{TCP_CHILDREN}	{ count(); yylval.strval=yytext; return TCP_CHILDREN; }
+<INITIAL>{TCP_ACCEPT_ALIASES}	{ count(); yylval.strval=yytext;
+									return TCP_ACCEPT_ALIASES; }
 <INITIAL>{DISABLE_TLS}	{ count(); yylval.strval=yytext; return DISABLE_TLS; }
 <INITIAL>{TLSLOG}		{ count(); yylval.strval=yytext; return TLS_PORT_NO; }
 <INITIAL>{TLS_PORT_NO}	{ count(); yylval.strval=yytext; return TLS_PORT_NO; }

+ 44 - 1
cfg.y

@@ -48,6 +48,7 @@
  * 2003-10-11  if(){} doesn't require a ';' after it anymore (andrei)
  * 2003-10-13  added FIFO_DIR & proto:host:port listen/alias support (andrei)
  * 2003-10-24  converted to the new socket_info lists (andrei)
+ * 2003-10-28  added tcp_accept_aliases (andrei)
  */
 
 
@@ -148,6 +149,7 @@ static struct id_list* mk_listen_id(char*, int, int);
 %token SET_URI
 %token REVERT_URI
 %token FORCE_RPORT
+%token FORCE_TCP_ALIAS
 %token IF
 %token ELSE
 %token SET_ADV_ADDRESS
@@ -202,6 +204,7 @@ static struct id_list* mk_listen_id(char*, int, int);
 %token WDIR
 %token MHOMED
 %token DISABLE_TCP
+%token TCP_ACCEPT_ALIASES
 %token TCP_CHILDREN
 %token DISABLE_TLS
 %token TLSLOG
@@ -409,6 +412,14 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 									#endif
 									}
 		| DISABLE_TCP EQUAL error { yyerror("boolean value expected"); }
+		| TCP_ACCEPT_ALIASES EQUAL NUMBER {
+									#ifdef USE_TCP
+										tcp_accept_aliases=$3;
+									#else
+										warn("tcp support not compiled in");
+									#endif
+									}
+		| TCP_ACCEPT_ALIASES EQUAL error { yyerror("boolean value expected"); }
 		| TCP_CHILDREN EQUAL NUMBER {
 									#ifdef USE_TCP
 										tcp_children_no=$3;
@@ -1373,8 +1384,40 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 										"string expected"); }
 		| REVERT_URI LPAREN RPAREN { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
 		| REVERT_URI { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
-		| FORCE_RPORT LPAREN RPAREN	{$$=mk_action(FORCE_RPORT_T,0, 0, 0, 0); }
+		| FORCE_RPORT LPAREN RPAREN	{
+							#ifdef USE_TCP
+								$$=mk_action(FORCE_RPORT_T,0, 0, 0, 0); 
+							#else
+								yyerror("tcp support not compiled in");
+							#endif
+							}
 		| FORCE_RPORT				{$$=mk_action(FORCE_RPORT_T,0, 0, 0, 0); }
+		| FORCE_TCP_ALIAS LPAREN NUMBER RPAREN	{
+					#ifdef USE_TCP
+						$$=mk_action(FORCE_TCP_ALIAS_T,NUMBER_ST, 0,
+										(void*)$3, 0);
+					#else
+						yyerror("tcp support not compiled in");
+					#endif
+												}
+		| FORCE_TCP_ALIAS LPAREN RPAREN	{
+					#ifdef USE_TCP
+						$$=mk_action(FORCE_TCP_ALIAS_T,0, 0, 0, 0); 
+					#else
+						yyerror("tcp support not compiled in");
+					#endif
+										}
+		| FORCE_TCP_ALIAS				{
+					#ifdef USE_TCP
+						$$=mk_action(FORCE_TCP_ALIAS_T,0, 0, 0, 0);
+					#else
+						yyerror("tcp support not compiled in");
+					#endif
+										}
+		| FORCE_TCP_ALIAS LPAREN error RPAREN	{$$=0; 
+												yyerror("bad argument,"
+														" number expected");
+												}
 		| SET_ADV_ADDRESS LPAREN listen_id RPAREN {
 								$$=0;
 								if ((str_tmp=pkg_malloc(sizeof(str)))==0){

+ 1 - 1
forward.c

@@ -39,7 +39,7 @@
  *  2003-04-03  added su_setport (andrei)
  *  2003-04-04  update_sock_struct_from_via now differentiates between
  *               local replies  & "normal" replies (andrei)
- *  2003-04-12  update_sock_struct_form via uses also FL_FORCE_RPORT for
+ *  2003-04-12  update_sock_struct_from via uses also FL_FORCE_RPORT for
  *               local replies (andrei)
  *  2003-08-21  check_self properly handles ipv6 addresses & refs   (andrei)
  *  2003-10-21  check_self updated to handle proto (andrei)

+ 1 - 0
globals.h

@@ -70,6 +70,7 @@ extern int children_no;
 #ifdef USE_TCP
 extern int tcp_children_no;
 extern int tcp_disable;
+extern int tcp_accept_aliases;
 #endif
 #ifdef USE_TLS
 extern int tls_disable;

+ 58 - 11
parser/parse_via.c

@@ -44,6 +44,8 @@
  *  2003-04-26  ZSW (jiri)
  *  2003-06-23  fixed  parse_via_param [op].* param. parsing bug (andrei)
  *  2003-07-02  added support for TLS parsing in via (andrei)
+ *  2003-10-27  added support for alias via param parsing [see
+ *               draft-ietf-sip-connect-reuse-00.txt.]  (andrei)
  */
 
 
@@ -100,9 +102,10 @@ enum {
 	RECEIVED1, RECEIVED2, RECEIVED3, RECEIVED4, RECEIVED5, RECEIVED6,
 	RECEIVED7,
 	RPORT1, RPORT2, RPORT3,
+	ALIAS1, ALIAS2, ALIAS3, ALIAS4,
 	     /* fin states (227-...)*/
-	FIN_HIDDEN = 230, FIN_TTL, FIN_BRANCH, FIN_MADDR, FIN_RECEIVED,
-	FIN_RPORT, FIN_I
+	FIN_HIDDEN = 230, FIN_TTL, FIN_BRANCH,
+	FIN_MADDR, FIN_RECEIVED, FIN_RPORT, FIN_I, FIN_ALIAS
 	     /*GEN_PARAM,
 	       PARAM_ERROR*/ /* declared in msg_parser.h*/
 };
@@ -134,6 +137,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 			case '\t':
 				switch(state){
 					case FIN_HIDDEN:
+					case FIN_ALIAS:
 						param->type=state;
 						param->name.len=tmp-param->name.s;
 						state=L_PARAM;
@@ -167,6 +171,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 			case '\n':
 				switch(state){
 					case FIN_HIDDEN:
+					case FIN_ALIAS:
 						param->type=state;
 						param->name.len=tmp-param->name.s;
 						param->size=tmp-param->start; 
@@ -209,6 +214,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 			case '\r':
 				switch(state){
 					case FIN_HIDDEN:
+					case FIN_ALIAS:
 						param->type=state;
 						param->name.len=tmp-param->name.s;
 						param->size=tmp-param->start; 
@@ -260,6 +266,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						goto find_value;
 					case F_PARAM:
 					case FIN_HIDDEN:
+					case FIN_ALIAS:
 						LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
 								" state %d\n", *tmp, state);
 						goto error;
@@ -280,6 +287,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 				switch(state){
 					case FIN_HIDDEN:
 					case FIN_RPORT: /* rport can appear w/o a value */
+					case FIN_ALIAS:
 						param->type=state;
 						param->name.len=tmp-param->name.s;
 						state=F_PARAM;
@@ -309,6 +317,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 				switch(state){
 					case FIN_HIDDEN:
 					case FIN_RPORT:
+					case FIN_ALIAS:
 						param->type=state;
 						param->name.len=tmp-param->name.s;
 						state=F_VIA;
@@ -371,6 +380,9 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case RECEIVED4:
 						state=RECEIVED5;
 						break;
+					case ALIAS2:
+						state=ALIAS3;
+						break;
 					case GEN_PARAM:
 						break;
 					case F_CR:
@@ -503,6 +515,9 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case TTL2:
 						state=FIN_TTL;
 						break;
+					case ALIAS1:
+						state=ALIAS2;
+						break;
 					case GEN_PARAM:
 						break;
 					case F_CR:
@@ -536,7 +551,7 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 			case 'A':
 				switch(state){
 					case F_PARAM:
-						state=GEN_PARAM;
+						state=ALIAS1;
 						param->name.s=tmp;
 						break;
 					case MADDR1:
@@ -545,6 +560,9 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 					case BRANCH2:
 						state=BRANCH3;
 						break;
+					case ALIAS3:
+						state=ALIAS4;
+						break;
 					case GEN_PARAM:
 						break;
 					case F_CR:
@@ -684,6 +702,25 @@ static /*inline*/ char* parse_via_param(char* p, char* end,
 						state=GEN_PARAM;
 				}
 				break;
+			case 's':
+			case 'S':
+				switch(state){
+					case F_PARAM:
+						state=GEN_PARAM;
+						param->name.s=tmp;
+						break;
+					case ALIAS4:
+						state=FIN_ALIAS;
+						break;
+					case F_CR:
+					case F_LF:
+					case F_CRLF:
+						state=END_OF_HEADER;
+						goto end_via;
+					default:
+						state=GEN_PARAM;
+				}
+				break;
 			default:
 				switch(state){
 					case F_PARAM:
@@ -1814,14 +1851,24 @@ parse_again:
 						if (vb->last_param)	vb->last_param->next=param;
 						else				vb->param_lst=param;
 						vb->last_param=param;
-						if (param->type==PARAM_BRANCH)
-							vb->branch=param;
-						else if (param->type==PARAM_RECEIVED)
-							vb->received=param;
-						else if (param->type==PARAM_RPORT)
-							vb->rport=param;
-						else if (param->type==PARAM_I)
-							vb->i=param;
+						/* update param. shortcuts */
+						switch(param->type){
+							case PARAM_BRANCH:
+								vb->branch=param;
+								break;
+							case PARAM_RECEIVED:
+								vb->received=param;
+								break;
+							case PARAM_RPORT:
+								vb->rport=param;
+								break;
+							case PARAM_I:
+								vb->rport=param;
+								break;
+							case PARAM_ALIAS:
+								vb->alias=param;
+								break;
+						}
 						
 						if (state==END_OF_HEADER){
 							state=saved_state;

+ 4 - 2
parser/parse_via.h

@@ -31,6 +31,7 @@
  *  2003-01-21  added extra via param parsing code (i=...), used
  *               by tcp to identify the sending socket, by andrei
  *  2003-01-27  added a new member (start) to via_param, by andrei
+ *  2003-10-27  added alias to via && PARAM_ALIAS (andrei)
  */
 
 
@@ -45,7 +46,8 @@
  */
 enum {
 	PARAM_HIDDEN=230, PARAM_TTL, PARAM_BRANCH, 
-	PARAM_MADDR, PARAM_RECEIVED, PARAM_RPORT, PARAM_I, GEN_PARAM,
+	PARAM_MADDR, PARAM_RECEIVED, PARAM_RPORT, PARAM_I, PARAM_ALIAS,
+	GEN_PARAM,
 	PARAM_ERROR
 };
 
@@ -86,7 +88,7 @@ struct via_body {
 	struct via_param* received;
 	struct via_param* rport;
 	struct via_param* i;
-	
+	struct via_param* alias; /* alias see draft-ietf-sip-connect-reuse-00 */
 	struct via_body* next; /* pointer to next via body string if
 				  compact via or null */
 };

+ 18 - 0
receive.c

@@ -53,6 +53,8 @@
 #include "script_cb.h"
 #include "dset.h"
 
+#include "tcp_server.h" /* for tcpconn_add_alias */
+
 
 #ifdef DEBUG_DMALLOC
 #include <mem/dmalloc.h>
@@ -129,6 +131,22 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 			goto error;
 		}
 		/* check if neccesarry to add receive?->moved to forward_req */
+		/* check for the alias stuff */
+#ifdef USE_TCP
+		if (msg->via1->alias && tcp_accept_aliases && 
+				(((rcv_info->proto==PROTO_TCP) && !tcp_disable)
+#ifdef USE_TLS
+					|| ((rcv_info->proto==PROTO_TLS) && !tls_disable)
+#endif
+				)
+			){
+			if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
+									rcv_info->proto)!=0){
+				LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
+				/* continue */
+			}
+		}
+#endif
 
 		/* exec routing script */
 		DBG("preparing to run routing scripts...\n");

+ 3 - 0
route_struct.c

@@ -324,6 +324,9 @@ void print_action(struct action* a)
 			case SET_ADV_PORT_T:
 					DBG("set_advertised_port(");
 					break;
+			case FORCE_TCP_ALIAS_T:
+					DBG("force_tcp_alias(");
+					break;
 			default:
 					DBG("UNKNOWN(");
 		}

+ 3 - 1
route_struct.h

@@ -31,6 +31,7 @@
  *  2003-04-12  FORCE_RPORT_T added (andrei)
  *  2003-04-22  strip_tail added (jiri)
  *  2003-10-10  >,<,>=,<=, != and MSGLEN_O added (andrei)
+ *  2003-10-28  FORCE_TCP_ALIAS added (andrei)
  */
 
 
@@ -70,7 +71,8 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
 		SEND_TCP_T,
 		FORCE_RPORT_T,
 		SET_ADV_ADDR_T,
-		SET_ADV_PORT_T
+		SET_ADV_PORT_T,
+		FORCE_TCP_ALIAS_T
 };
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
 		EXPR_ST, ACTIONS_ST, CMDF_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST,

+ 23 - 7
tcp_conn.h

@@ -29,6 +29,7 @@
  * --------
  *  2003-01-29  tcp buffer size ++-ed to allow for 0-terminator
  *  2003-06-30  added tcp_connection flags & state (andrei) 
+ *  2003-10-27  tcp port aliases support added (andrei)
  */
 
 
@@ -40,6 +41,8 @@
 #include "locking.h"
 
 
+#define TCP_CON_MAX_ALIASES 4 /* maximum number of port aliases */
+
 #define TCP_BUF_SIZE 65535
 #define TCP_CON_TIMEOUT 60 /* in  seconds */
 #define TCP_CON_SEND_TIMEOUT 30 /* timeout after a send */
@@ -90,6 +93,18 @@ struct tcp_req{
 
 
 
+struct tcp_connection;
+
+/* tcp port alias structure */
+struct tcp_conn_alias{
+	struct tcp_connection* parent;
+	struct tcp_conn_alias* next;
+	struct tcp_conn_alias* prev;
+	unsigned short port; /* alias port */
+	unsigned short hash; /* hash index in the address hash */
+};
+
+
 
 struct tcp_connection{
 	int s; /*socket, used by "tcp main" */
@@ -105,10 +120,9 @@ struct tcp_connection{
 	enum tcp_conn_states state; /* connection state */
 	void* extra_data; /* extra data associated to the connection, 0 for tcp*/
 	int timeout; /* connection timeout, after this it will be removed*/
-	unsigned addr_hash; /* hash indexes in the 2 tables */
-	unsigned id_hash;
-	struct tcp_connection* next; /* next, prev in hash table, used by "main" */
-	struct tcp_connection* prev;
+	unsigned id_hash; /* hash index in the id_hash */
+	int aliases; /* aliases number, at least 1 */
+	struct tcp_conn_alias con_aliases[TCP_CON_MAX_ALIASES];
 	struct tcp_connection* id_next; /* next, prev in id hash table */
 	struct tcp_connection* id_prev;
 	struct tcp_connection* c_next; /* child next prev (use locally) */
@@ -118,6 +132,8 @@ struct tcp_connection{
 
 
 
+
+
 #define init_tcp_req( r) \
 	do{ \
 		memset( (r), 0, sizeof(struct tcp_req)); \
@@ -151,15 +167,15 @@ struct tcp_connection{
 #define TCPCONN_LOCK lock_get(tcpconn_lock);
 #define TCPCONN_UNLOCK lock_release(tcpconn_lock);
 
-#define TCP_ADDR_HASH_SIZE 1024
+#define TCP_ALIAS_HASH_SIZE 1024
 #define TCP_ID_HASH_SIZE 1024
 
 static inline unsigned tcp_addr_hash(struct ip_addr* ip, unsigned short port)
 {
-	if(ip->len==4) return (ip->u.addr32[0]^port)&(TCP_ADDR_HASH_SIZE-1);
+	if(ip->len==4) return (ip->u.addr32[0]^port)&(TCP_ALIAS_HASH_SIZE-1);
 	else if (ip->len==16) 
 			return (ip->u.addr32[0]^ip->u.addr32[1]^ip->u.addr32[2]^
-					ip->u.addr32[3]^port) & (TCP_ADDR_HASH_SIZE-1);
+					ip->u.addr32[3]^port) & (TCP_ALIAS_HASH_SIZE-1);
 	else{
 		LOG(L_CRIT, "tcp_addr_hash: BUG: bad len %d for an ip address\n",
 				ip->len);

+ 111 - 32
tcp_main.c

@@ -43,6 +43,7 @@
  *               handle_new_connect (andrei)
  *  2003-07-09  tls_close called before closing the tcp connection (andrei)
  *  2003-10-24  converted to the new socket_info lists (andrei)
+ *  2003-10-27  tcp port aliases support added (andrei)
  */
 
 
@@ -105,9 +106,10 @@ struct tcp_child{
 };
 
 
+int tcp_accept_aliases=0; /* by default don't accept aliases */
 
-/* connection hash table (after ip&port) */
-struct tcp_connection** tcpconn_addr_hash=0;
+/* connection hash table (after ip&port) , includes also aliases */
+struct tcp_conn_alias** tcpconn_aliases_hash=0;
 /* connection hash table (after connection id) */
 struct tcp_connection** tcpconn_id_hash=0;
 gen_lock_t* tcpconn_lock=0;
@@ -132,6 +134,7 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
 		LOG(L_ERR, "ERROR: tcpconn_new: mem. allocation failure\n");
 		goto error;
 	}
+	memset(c, 0, sizeof(struct tcp_connection)); /* zero init */
 	c->s=sock;
 	c->fd=-1; /* not initialized */
 	if (lock_init(&c->write_lock)==0){
@@ -263,14 +266,20 @@ struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
 	if (c){
 		TCPCONN_LOCK;
 		/* add it at the begining of the list*/
-		hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port);
-		c->addr_hash=hash;
-		tcpconn_listadd(tcpconn_addr_hash[hash], c, next, prev);
 		hash=tcp_id_hash(c->id);
 		c->id_hash=hash;
 		tcpconn_listadd(tcpconn_id_hash[hash], c, id_next, id_prev);
+		
+		hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port);
+		/* set the first alias */
+		c->con_aliases[0].port=c->rcv.src_port;
+		c->con_aliases[0].hash=hash;
+		c->con_aliases[0].parent=c;
+		tcpconn_listadd(tcpconn_aliases_hash[hash], &c->con_aliases[0],
+						next, prev);
+		c->aliases++;
 		TCPCONN_UNLOCK;
-		DBG("tcpconn_add: hashes: %d, %d\n", c->addr_hash, c->id_hash);
+		DBG("tcpconn_add: hashes: %d, %d\n", hash, c->id_hash);
 		return c;
 	}else{
 		LOG(L_CRIT, "tcpconn_add: BUG: null connection pointer\n");
@@ -282,8 +291,12 @@ struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
 /* unsafe tcpconn_rm version (nolocks) */
 void _tcpconn_rm(struct tcp_connection* c)
 {
-	tcpconn_listrm(tcpconn_addr_hash[c->addr_hash], c, next, prev);
+	int r;
 	tcpconn_listrm(tcpconn_id_hash[c->id_hash], c, id_next, id_prev);
+	/* remove all the aliases */
+	for (r=0; r<c->aliases; r++)
+		tcpconn_listrm(tcpconn_aliases_hash[c->con_aliases[r].hash], 
+						&c->con_aliases[r], next, prev);
 	lock_destroy(&c->write_lock);
 #ifdef USE_TLS
 	if (c->type==PROTO_TLS) tls_tcpconn_clean(c);
@@ -295,9 +308,13 @@ void _tcpconn_rm(struct tcp_connection* c)
 
 void tcpconn_rm(struct tcp_connection* c)
 {
+	int r;
 	TCPCONN_LOCK;
-	tcpconn_listrm(tcpconn_addr_hash[c->addr_hash], c, next, prev);
 	tcpconn_listrm(tcpconn_id_hash[c->id_hash], c, id_next, id_prev);
+	/* remove all the aliases */
+	for (r=0; r<c->aliases; r++)
+		tcpconn_listrm(tcpconn_aliases_hash[c->con_aliases[r].hash], 
+						&c->con_aliases[r], next, prev);
 	TCPCONN_UNLOCK;
 	lock_destroy(&c->write_lock);
 #ifdef USE_TLS
@@ -314,11 +331,12 @@ struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port)
 {
 
 	struct tcp_connection *c;
+	struct tcp_conn_alias* a;
 	unsigned hash;
 	
 #ifdef EXTRA_DEBUG
 	DBG("tcpconn_find: %d  port %d\n",id, port);
-	print_ip("tcpconn_find: ip ", ip, "\n");
+	if (ip) print_ip("tcpconn_find: ip ", ip, "\n");
 #endif
 	if (id){
 		hash=tcp_id_hash(id);
@@ -331,14 +349,15 @@ struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port)
 		}
 	}else if (ip){
 		hash=tcp_addr_hash(ip, port);
-		for (c=tcpconn_addr_hash[hash]; c; c=c->next){
+		for (a=tcpconn_aliases_hash[hash]; a; a=a->next){
 #ifdef EXTRA_DEBUG
-			DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port);
-			print_ip("ip=",&c->rcv.src_ip,"\n");
+			DBG("a=%p, c=%p, c->id=%d, alias port= %d port=%d\n", a, a->parent,
+					a->parent->id, a->port, a->parent->rcv.src_port);
+			print_ip("ip=",&a->parent->rcv.src_ip,"\n");
 #endif
-			if ( (c->state!=S_CONN_BAD) && (port==c->rcv.src_port) &&
-					(ip_addr_cmp(ip, &c->rcv.src_ip)) )
-				return c;
+			if ( (a->parent->state!=S_CONN_BAD) && (port==a->port) &&
+					(ip_addr_cmp(ip, &a->parent->rcv.src_ip)) )
+				return a->parent;
 		}
 	}
 	return 0;
@@ -363,6 +382,67 @@ struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port,
 
 
 
+/* add port as an alias for the "id" connection
+ * returns 0 on success,-1 on failure */
+int tcpconn_add_alias(int id, int port, int proto)
+{
+	struct tcp_connection* c;
+	unsigned hash;
+	struct tcp_conn_alias* a;
+	
+	a=0;
+	/* fix the port */
+	port=port?port:((proto==PROTO_TLS)?SIPS_PORT:SIP_PORT);
+	TCPCONN_LOCK;
+	/* check if alias already exists */
+	c=_tcpconn_find(id, 0, 0);
+	if (c){
+		hash=tcp_addr_hash(&c->rcv.src_ip, port);
+		/* search the aliases for an already existing one */
+		for (a=tcpconn_aliases_hash[hash]; a; a=a->next){
+			if ( (a->parent->state!=S_CONN_BAD) && (port==a->port) &&
+					(ip_addr_cmp(&c->rcv.src_ip, &a->parent->rcv.src_ip)) ){
+				/* found */
+				if (a->parent!=c) goto error_sec;
+				else goto ok;
+			}
+		}
+		if (c->aliases>=TCP_CON_MAX_ALIASES) goto error_aliases;
+		c->con_aliases[c->aliases].parent=c;
+		c->con_aliases[c->aliases].port=port;
+		c->con_aliases[c->aliases].hash=hash;
+		tcpconn_listadd(tcpconn_aliases_hash[hash], 
+								&c->con_aliases[c->aliases], next, prev);
+		c->aliases++;
+	}else goto error_not_found;
+ok:
+	TCPCONN_UNLOCK;
+#ifdef EXTRA_DEBUG
+	if (a) DBG("tcpconn_add_alias: alias already present\n");
+	else   DBG("tcpconn_add_alias: alias port %d for hash %d, id %d\n",
+			port, hash, c->id);
+#endif
+	return 0;
+error_aliases:
+	TCPCONN_UNLOCK;
+	LOG(L_ERR, "ERROR: tcpconn_add_alias: too many aliases for connection %p"
+				" (%d)\n", c, c->id);
+	return -1;
+error_not_found:
+	TCPCONN_UNLOCK;
+	LOG(L_ERR, "ERROR: tcpconn_add_alias: no connection found for id %d\n",id);
+	return -1;
+error_sec:
+	TCPCONN_UNLOCK;
+	LOG(L_ERR, "ERROR: tcpconn_add_alias: possible port hijack attemp\n");
+	LOG(L_ERR, "ERROR: tcpconn_add_alias: alias already present and points"
+			" to another connection (%d : %d and %d : %d)\n",
+			a->parent->id,  port, c->id, port);
+	return -1;
+}
+
+
+
 void tcpconn_put(struct tcp_connection* c)
 {
 	c->refcnt--; /* FIXME: atomic_dec */
@@ -516,10 +596,10 @@ void tcpconn_timeout(fd_set* set)
 	
 	ticks=get_ticks();
 	TCPCONN_LOCK; /* fixme: we can lock only on delete IMO */
-	for(h=0; h<TCP_ADDR_HASH_SIZE; h++){
-		c=tcpconn_addr_hash[h];
+	for(h=0; h<TCP_ID_HASH_SIZE; h++){
+		c=tcpconn_id_hash[h];
 		while(c){
-			next=c->next;
+			next=c->id_next;
 			if ((c->refcnt==0) && (ticks>c->timeout)) {
 				DBG("tcpconn_timeout: timeout for hash=%d - %p (%d > %d)\n",
 						h, c, ticks, c->timeout);
@@ -789,9 +869,9 @@ void tcp_main_loop()
 #endif
 		
 		/* check all the read fds (from the tcpconn_addr_hash ) */
-		for (h=0; h<TCP_ADDR_HASH_SIZE; h++){
-			for(tcpconn=tcpconn_addr_hash[h]; tcpconn && n; 
-					tcpconn=tcpconn->next){
+		for (h=0; h<TCP_ID_HASH_SIZE; h++){
+			for(tcpconn=tcpconn_id_hash[h]; tcpconn && n; 
+					tcpconn=tcpconn->id_next){
 				if ((tcpconn->refcnt==0)&&(FD_ISSET(tcpconn->s, &sel_set))){
 					/* new data available */
 					n--;
@@ -967,10 +1047,9 @@ int init_tcp()
 	}
 	*connection_id=1;
 	/* alloc hashtables*/
-	tcpconn_addr_hash=(struct tcp_connection**)shm_malloc(TCP_ADDR_HASH_SIZE*
-								sizeof(struct tcp_connection*));
-
-	if (tcpconn_addr_hash==0){
+	tcpconn_aliases_hash=(struct tcp_conn_alias**)
+			shm_malloc(TCP_ALIAS_HASH_SIZE* sizeof(struct tcp_conn_alias*));
+	if (tcpconn_aliases_hash==0){
 		LOG(L_CRIT, "ERROR: init_tcp: could not alloc address hashtable\n");
 		shm_free(connection_id);
 		connection_id=0;
@@ -986,16 +1065,16 @@ int init_tcp()
 		LOG(L_CRIT, "ERROR: init_tcp: could not alloc id hashtable\n");
 		shm_free(connection_id);
 		connection_id=0;
-		shm_free(tcpconn_addr_hash);
-		tcpconn_addr_hash=0;
+		shm_free(tcpconn_aliases_hash);
+		tcpconn_aliases_hash=0;
 		lock_destroy(tcpconn_lock);
 		lock_dealloc((void*)tcpconn_lock);
 		tcpconn_lock=0;
 		goto error;
 	}
 	/* init hashtables*/
-	memset((void*)tcpconn_addr_hash, 0, 
-			TCP_ADDR_HASH_SIZE * sizeof(struct tcp_connection*));
+	memset((void*)tcpconn_aliases_hash, 0, 
+			TCP_ALIAS_HASH_SIZE * sizeof(struct tcp_conn_alias*));
 	memset((void*)tcpconn_id_hash, 0, 
 			TCP_ID_HASH_SIZE * sizeof(struct tcp_connection*));
 	return 0;
@@ -1013,9 +1092,9 @@ void destroy_tcp()
 		lock_dealloc((void*)tcpconn_lock);
 		tcpconn_lock=0;
 	}
-	if(tcpconn_addr_hash){
-		shm_free(tcpconn_addr_hash);
-		tcpconn_addr_hash=0;
+	if(tcpconn_aliases_hash){
+		shm_free(tcpconn_aliases_hash);
+		tcpconn_aliases_hash=0;
 	}
 	if(tcpconn_id_hash){
 		shm_free(tcpconn_id_hash);

+ 1 - 1
tcp_server.h

@@ -31,7 +31,6 @@
 
 
 
-
 /* "public" functions*/
 
 struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port, 
@@ -40,6 +39,7 @@ void tcpconn_put(struct tcp_connection* c);
 int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to,
 			int id);
 
+int tcpconn_add_alias(int id, int port, int proto);
 
 
 

+ 3 - 0
test/test.cfg

@@ -28,6 +28,8 @@ alias="foo.bar"
 fifo="/tmp/ser_fifo"
 listen= tcp:10.0.0.179:5065
 alias=  tcp:all:5065
+tcp_accept_aliases=yes
+
 
 #modules
 
@@ -37,5 +39,6 @@ route{
 		log("\n\nfrom myself\n\n");
 	};
 	log(" continue \n\n");
+	#force_tcp_alias();
 	forward(uri:host, uri:port);
 }