- changed tcp to support port aliases (major changes)
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Wed, 29 Oct 2003 17:41:27 +0000 (17:41 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Wed, 29 Oct 2003 17:41:27 +0000 (17:41 +0000)
- 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]

17 files changed:
Makefile.defs
NEWS
TODO
action.c
cfg.lex
cfg.y
forward.c
globals.h
parser/parse_via.c
parser/parse_via.h
receive.c
route_struct.c
route_struct.h
tcp_conn.h
tcp_main.c
tcp_server.h
test/test.cfg

index c0aeb55..5ae66f4 100644 (file)
@@ -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]")
diff --git a/NEWS b/NEWS
index 8d4d529..9bc96ef 100644 (file)
--- a/NEWS
+++ b/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).
+
+
 
 
 
diff --git a/TODO b/TODO
index 5723bb2..ec1d00d 100644 (file)
--- a/TODO
+++ b/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
index 80fa80d..cd22d26 100644 (file)
--- a/action.c
+++ b/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);
        }
diff --git a/cfg.lex b/cfg.lex
index 30584ed..edb6c5f 100644 (file)
--- a/cfg.lex
+++ b/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; }
diff --git a/cfg.y b/cfg.y
index 081d395..1cf1672 100644 (file)
--- a/cfg.y
+++ b/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){
index 4d3200c..48d3013 100644 (file)
--- a/forward.c
+++ b/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)
index d3fe52b..bf5cdf8 100644 (file)
--- a/globals.h
+++ b/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;
index db0c3e3..2c69497 100644 (file)
@@ -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;
index 71ffa32..df4f5b7 100644 (file)
@@ -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 */
 };
index 6ac7b29..5ff616d 100644 (file)
--- a/receive.c
+++ b/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");
index 720304e..daa60ec 100644 (file)
@@ -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(");
                }
index 21f8ea6..70fa7bb 100644 (file)
@@ -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,
index 417b776..0261258 100644 (file)
@@ -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);
index 8af29ba..1fd8df9 100644 (file)
@@ -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);
index 2ca4300..dcb678b 100644 (file)
@@ -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);
 
 
 
index 1ff0c5f..f250653 100644 (file)
@@ -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);
 }